diff --git a/README.md b/README.md
index 1746a62482..10e187cf25 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,42 @@ dab init
DAB supports tables, views, and stored procedures. It works with SQL Server, Azure Cosmos DB, PostgreSQL, MySQL, and SQL Data Warehouse. Security is engine-level, but permissions are per entity.
+The file `dab-config.json` is automatically created through this process. These are the resulting contents:
+
+```json
+{
+ "$schema": "https://github.com/Azure/data-api-builder/releases/download/v1.5.56/dab.draft.schema.json",
+ "data-source": {
+ "database-type": "mssql",
+ "connection-string": "@env('my-connection-string')",
+ "options": {
+ "set-session-context": false
+ }
+ },
+ "runtime": {
+ "rest": {
+ "enabled": true,
+ "path": "/api",
+ "request-body-strict": true
+ },
+ "graphql": {
+ "enabled": true,
+ "path": "/graphql",
+ "allow-introspection": true
+ },
+ "host": {
+ "cors": {
+ "origins": [],
+ "allow-credentials": false
+ },
+ "authentication": {
+ "provider": "AppService"
+ },
+ "mode": "development"
+ }
+ },
+ "entities": { }
+}
```
dab add Actor
--source "dbo.Actor"
diff --git a/docs/media/dab-aifoundry-architecture.png b/docs/media/dab-aifoundry-architecture.png
new file mode 100644
index 0000000000..6823ef6418
Binary files /dev/null and b/docs/media/dab-aifoundry-architecture.png differ
diff --git a/docs/testing-guide/ai-foundry-integration.md b/docs/testing-guide/ai-foundry-integration.md
new file mode 100644
index 0000000000..0165b725f6
--- /dev/null
+++ b/docs/testing-guide/ai-foundry-integration.md
@@ -0,0 +1,275 @@
+# Deploying SQL MCP Server implemented in Data API builder and Integrating with Azure AI Foundry
+
+This document provides an end‑to‑end guide to stand up a **SQL MCP Server** with **Model Context Protocol (MCP)** tools implemented in **Data API builder (DAB)** container that also exposes **REST** and **GraphQL** endpoints, and to integrate those MCP tools with an **Azure AI Foundry Agent**.
+
+
+
+## 1. Architecture Overview
+
+**Components**
+- **Azure SQL Database** hosting domain tables and stored procedures.
+- **DAB container** (Azure Container Instances in this guide) that:
+ - reads `dab-config.json` from an **Azure Files** share at startup,
+ - exposes **REST**, **GraphQL**, and **MCP** endpoints.
+- **Azure Storage (Files)** to store and version `dab-config.json`.
+- **Azure AI Foundry Agent** configured with an **MCP tool** pointing to the SQL MCP Server endpoint.
+
+**Flow**
+1. DAB starts in ACI → reads `dab-config.json` from the mounted Azure Files share.
+2. DAB exposes `/api` (REST), `/graphql` (GraphQL), and `/mcp` (MCP).
+3. Azure AI Foundry Agent invokes MCP tools to read/update data via DAB’s surface (tables, views and stored procedures).
+
+
+## 2. Prerequisites
+- Azure Subscription with permissions for Resource Groups, Storage, ACI, and Azure SQL.
+- Azure SQL Database provisioned and reachable from ACI.
+- Azure CLI (`az`) and .NET SDK installed locally.
+- DAB CLI version **1.7.81 or later**.
+- Outbound network access from ACI to your Azure SQL server.
+
+
+## 3. Prepare the Database
+
+You need to create the necessary tables and stored procedures in your Azure SQL Database. Below is an example of how to create a simple `Products` table and a stored procedure to retrieve products by category.
+
+**Example:**
+
+1. Connect to your Azure SQL Database using Azure Data Studio, SQL Server Management Studio, or the Azure Portal's Query Editor.
+
+2. Run the following SQL script to create a sample table and stored procedure:
+
+```sql
+-- Create Products table
+CREATE TABLE Products (
+ ProductID INT IDENTITY(1,1) PRIMARY KEY,
+ Name NVARCHAR(100) NOT NULL,
+ Category NVARCHAR(50) NOT NULL,
+ Price DECIMAL(10,2) NOT NULL
+);
+
+-- Create stored procedure to get products by category
+CREATE PROCEDURE GetProductsByCategory
+ @Category NVARCHAR(50)
+AS
+BEGIN
+ SET NOCOUNT ON;
+ SELECT ProductID, Name, Category, Price
+ FROM Products
+ WHERE Category = @Category;
+END;
+```
+
+## 4. Install DAB CLI and Bootstrap Configuration
+
+```
+dotnet tool install --global Microsoft.DataApiBuilder --version 1.7.81
+export DATABASE_CONNECTION_STRING="Server=.database.windows.net;Database=;User ID=;Password=;Encrypt=True;"
+
+dab init \
+ --database-type "mssql" \
+ --connection-string "@env('DATABASE_CONNECTION_STRING')" \
+ --host-mode "Development" \
+ --rest.enabled true \
+ --graphql.enabled true \
+ --mcp.enabled true \
+ --mcp.path "/mcp"
+
+```
+
+## 5. Add all required entities (tables and stored procedures) to `dab-config.json` and enable MCP tools in the config
+
+Here is how to add a table entity and a stored procedure to your `dab-config.json`, and ensure MCP tools are enabled:
+
+1. **Open your `dab-config.json` file.**
+
+2. **Add an entity (table) definition** under the `"entities"` section. For example, to expose a `Customers` table:
+ ```
+ "entities": {
+ "Customers": {
+ "source": "Customers",
+ "rest": true,
+ "graphql": true,
+ "mcp": true,
+ "permissions": [
+ {
+ "role": "anonymous",
+ "actions": [ "read", "create", "update", "delete" ]
+ }
+ ]
+ }
+ }
+ ```
+
+3. **Add a stored procedure** under the "entities" section. For example, to expose a stored procedure called GetCustomerOrders:
+
+ ```
+ "GetCustomerOrders": {
+ "source": {
+ "object": "GetCustomerOrders",
+ "type": "stored-procedure"
+ },
+ "rest": true,
+ "graphql": true,
+ "mcp": true,
+ "permissions": [
+ {
+ "role": "anonymous",
+ "actions": [ "execute" ]
+ }
+ ]
+ }
+ ```
+
+Note: Make sure the "entities" section is a valid JSON object. If you have multiple entities, separate them with commas.
+
+4. **Ensure MCP is enabled in the "runtime" section:**
+
+```
+"runtime": {
+ "rest": { "enabled": true },
+ "graphql": { "enabled": true },
+ "mcp": {
+ "enabled": true,
+ "path": "/mcp"
+ }
+}
+```
+
+5. **Example dab-config.json structure:**
+
+```
+{
+ "data-source": {
+ "database-type": "mssql",
+ "connection-string": "@env('DATABASE_CONNECTION_STRING')"
+ },
+ "runtime": {
+ "rest": { "enabled": true },
+ "graphql": { "enabled": true },
+ "mcp": {
+ "enabled": true,
+ "path": "/mcp"
+ }
+ },
+ "entities": {
+ "Customers": {
+ "source": "Customers",
+ "rest": true,
+ "graphql": true,
+ "mcp": true,
+ "permissions": [
+ {
+ "role": "anonymous",
+ "actions": [ "read", "create", "update", "delete" ]
+ }
+ ]
+ },
+ "GetCustomerOrders": {
+ "source": {
+ "object": "GetCustomerOrders",
+ "type": "stored-procedure"
+ },
+ "rest": true,
+ "graphql": true,
+ "mcp": true,
+ "permissions": [
+ {
+ "role": "anonymous",
+ "actions": [ "execute" ]
+ }
+ ]
+ }
+ }
+}
+```
+
+6. **Save the file.**
+
+## 6. Store dab-config.json in Azure Files
+
+1. **Create a Storage Account** (if you don't have one):
+az storage account create
+--name
+--resource-group
+--location
+--sku Standard_LRS
+
+
+2. **Create a File Share**:
+az storage share create
+--name
+--account-name
+
+
+3. **Upload `dab-config.json` to the File Share**:
+az storage file upload
+--account-name
+--share-name
+--source ./dab-config.json
+--path dab-config.json
+
+
+4. **Retrieve the Storage Account key** (needed for mounting in ACI):
+az storage account keys list
+--account-name
+--resource-group
+
+Use the value of `key1` or `key2` as `` in the next step.
+
+
+## 7. Deploy DAB to Azure Container Instances
+
+```
+az container create \
+ --resource-group \
+ --name dab-mcp-demo \
+ --image mcr.microsoft.com/azure-databases/data-api-builder:1.7.81-rc \
+ --dns-name-label \
+ --ports 5000 \
+ --location \
+ --environment-variables DAB_CONFIG_PATH="/aci/dab-config.json" \
+ --azure-file-volume-share-name \
+ --azure-file-volume-account-name \
+ --azure-file-volume-account-key \
+ --azure-file-volume-mount-path "/aci" \
+ --os-type Linux \
+ --cpu 1 \
+ --memory 1.5 \
+ --command-line "dotnet Azure.DataApiBuilder.Service.dll --ConfigFileName $DAB_CONFIG_PATH --LogLevel Debug"
+```
+
+## 8. Integrate with Azure AI Foundry
+
+Follow these steps to connect your SQL MCP endpoint deployed in DAB to Azure AI Foundry and test the integration:
+
+1. **Create or Open a Project**
+ - Navigate to the [Azure AI Foundry portal](https://ai.azure.com/foundry) and sign in.
+ - On the dashboard, click **Projects** in the left navigation pane.
+ - To create a new project, click **New Project**, enter a name (e.g., `DAB-MCP-Demo`), and click **Create**.
+ - To use an existing project, select it from the list.
+
+2. **Add an Agent**
+ - Within your project, go to the **Agents** tab.
+ - Click **Add Agent**.
+ - Enter an agent name (e.g., `DAB-MCP-Agent`).
+ - (Optional) Add a description.
+ - Click **Create**.
+
+3. **Configure the MCP Tool**
+ - In the agent's configuration page, go to the **Tools** section.
+ - Click **Add Tool** and select **MCP** from the tool type dropdown.
+ - In the **MCP Endpoint URL** field, enter your SQL MCP endpoint in DAB, e.g., `http:///mcp`.
+ - (Optional) Configure authentication if your endpoint requires it.
+ - Click **Save** to add the tool.
+
+4. **Test in Playground**
+ - Go to the **Playground** tab in your project.
+ - Select the agent you created from the agent dropdown.
+ - In the input box, enter a prompt that will trigger the MCP tool, such as:
+ ```
+ Get all records from the Customers entity.
+ ```
+ - Click **Run**.
+ - The agent should invoke the MCP tool, which will call your DAB MCP endpoint and return the results.
+ - **Expected Result:** You should see the data returned from your DAB instance displayed in the Playground output panel.
+ - If there are errors, check the DAB container logs and ensure the MCP endpoint is reachable from Azure AI Foundry.
diff --git a/docs/Testing/mcp-inspector-testing.md b/docs/testing-guide/mcp-inspector-testing.md
similarity index 100%
rename from docs/Testing/mcp-inspector-testing.md
rename to docs/testing-guide/mcp-inspector-testing.md
diff --git a/schemas/dab.draft.schema.json b/schemas/dab.draft.schema.json
index 80cfd953ad..dd0bebd3cb 100644
--- a/schemas/dab.draft.schema.json
+++ b/schemas/dab.draft.schema.json
@@ -370,7 +370,7 @@
"description": "Custom authentication provider defined by the user. Use the JWT property to configure the custom provider."
}
],
- "default": "StaticWebApps"
+ "default": "AppService"
},
"jwt": {
"type": "object",
diff --git a/src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs b/src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
index cd2a7cc28b..c5b283214f 100644
--- a/src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
+++ b/src/Azure.DataApiBuilder.Mcp/BuiltInTools/DescribeEntitiesTool.cs
@@ -111,6 +111,30 @@ public Task ExecuteAsync(
}
}
+ // Get current user's role for permission filtering
+ // For discovery tools like describe_entities, we use the first valid role from the header
+ // This differs from operation-specific tools that check permissions per entity per operation
+ if (httpContext != null && authResolver.IsValidRoleContext(httpContext))
+ {
+ string roleHeader = httpContext.Request.Headers[AuthorizationResolver.CLIENT_ROLE_HEADER].ToString();
+ if (!string.IsNullOrWhiteSpace(roleHeader))
+ {
+ string[] roles = roleHeader
+ .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+
+ if (roles.Length > 1)
+ {
+ logger?.LogWarning("Multiple roles detected in request header: [{Roles}]. Using first role '{FirstRole}' for entity discovery. " +
+ "Consider using a single role for consistent permission reporting.",
+ string.Join(", ", roles), roles[0]);
+ }
+
+ // For discovery operations, take the first role from comma-separated list
+ // This provides a consistent view of available entities for the primary role
+ currentUserRole = roles.FirstOrDefault();
+ }
+ }
+
(bool nameOnly, HashSet? entityFilter) = ParseArguments(arguments, logger);
if (currentUserRole == null)
diff --git a/src/Azure.DataApiBuilder.Mcp/Core/McpProtocolDefaults.cs b/src/Azure.DataApiBuilder.Mcp/Core/McpProtocolDefaults.cs
new file mode 100644
index 0000000000..48b235f480
--- /dev/null
+++ b/src/Azure.DataApiBuilder.Mcp/Core/McpProtocolDefaults.cs
@@ -0,0 +1,39 @@
+using Azure.DataApiBuilder.Product;
+using Microsoft.Extensions.Configuration;
+
+namespace Azure.DataApiBuilder.Mcp.Core
+{
+ ///
+ /// Centralized defaults and configuration keys for MCP protocol settings.
+ ///
+ public static class McpProtocolDefaults
+ {
+ ///
+ /// Default MCP server name advertised during initialization.
+ ///
+ public const string MCP_SERVER_NAME = "SQL MCP Server";
+ ///
+ /// Default MCP server version advertised during initialization.
+ ///
+ public static readonly string MCP_SERVER_VERSION = ProductInfo.GetProductVersion();
+ ///
+ /// Default MCP protocol version advertised when no configuration override is provided.
+ ///
+ public const string DEFAULT_PROTOCOL_VERSION = "2025-06-18";
+
+ ///
+ /// Configuration key used to override the MCP protocol version.
+ ///
+ public const string PROTOCOL_VERSION_CONFIG_KEY = "MCP:ProtocolVersion";
+
+ ///
+ /// Helper to resolve the effective protocol version from configuration.
+ /// Falls back to when the key is not set.
+ ///
+ public static string ResolveProtocolVersion(IConfiguration? configuration)
+ {
+ return configuration?.GetValue(PROTOCOL_VERSION_CONFIG_KEY) ?? DEFAULT_PROTOCOL_VERSION;
+ }
+ }
+}
+
diff --git a/src/Azure.DataApiBuilder.Mcp/Core/McpServerConfiguration.cs b/src/Azure.DataApiBuilder.Mcp/Core/McpServerConfiguration.cs
index 86cccd2aaf..d76af816bd 100644
--- a/src/Azure.DataApiBuilder.Mcp/Core/McpServerConfiguration.cs
+++ b/src/Azure.DataApiBuilder.Mcp/Core/McpServerConfiguration.cs
@@ -21,7 +21,7 @@ internal static IServiceCollection ConfigureMcpServer(this IServiceCollection se
{
services.AddMcpServer(options =>
{
- options.ServerInfo = new() { Name = "Data API builder MCP Server", Version = "1.0.0" };
+ options.ServerInfo = new() { Name = McpProtocolDefaults.MCP_SERVER_NAME, Version = McpProtocolDefaults.MCP_SERVER_VERSION };
options.Capabilities = new()
{
Tools = new()
diff --git a/src/Azure.DataApiBuilder.Mcp/Core/McpStdioServer.cs b/src/Azure.DataApiBuilder.Mcp/Core/McpStdioServer.cs
new file mode 100644
index 0000000000..6584e819af
--- /dev/null
+++ b/src/Azure.DataApiBuilder.Mcp/Core/McpStdioServer.cs
@@ -0,0 +1,476 @@
+using System.Collections;
+using System.Reflection;
+using System.Security.Claims;
+using System.Text;
+using System.Text.Json;
+using Azure.DataApiBuilder.Core.AuthenticationHelpers.AuthenticationSimulator;
+using Azure.DataApiBuilder.Mcp.Model;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using ModelContextProtocol.Protocol;
+
+namespace Azure.DataApiBuilder.Mcp.Core
+{
+ ///
+ /// MCP stdio server:
+ /// - Reads JSON-RPC requests (initialize, listTools, callTool) from STDIN
+ /// - Writes ONLY MCP JSON responses to STDOUT
+ /// - Writes diagnostics to STDERR (so STDOUT remains “pure MCP”)
+ ///
+ public class McpStdioServer : IMcpStdioServer
+ {
+ private readonly McpToolRegistry _toolRegistry;
+ private readonly IServiceProvider _serviceProvider;
+ private readonly string _protocolVersion;
+
+ private const int MAX_LINE_LENGTH = 1024 * 1024; // 1 MB limit for incoming JSON-RPC requests
+
+ public McpStdioServer(McpToolRegistry toolRegistry, IServiceProvider serviceProvider)
+ {
+ _toolRegistry = toolRegistry ?? throw new ArgumentNullException(nameof(toolRegistry));
+ _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+
+ // Allow protocol version to be configured via IConfiguration, using centralized defaults.
+ IConfiguration? configuration = _serviceProvider.GetService();
+ _protocolVersion = McpProtocolDefaults.ResolveProtocolVersion(configuration);
+ }
+
+ ///
+ /// Runs the MCP stdio server loop, reading JSON-RPC requests from STDIN and writing MCP JSON responses to STDOUT.
+ ///
+ /// Token to signal cancellation of the server loop.
+ /// A task representing the asynchronous operation.
+ public async Task RunAsync(CancellationToken cancellationToken)
+ {
+ Console.Error.WriteLine("[MCP DEBUG] MCP stdio server started.");
+
+ // Use UTF-8 WITHOUT BOM
+ UTF8Encoding utf8NoBom = new(encoderShouldEmitUTF8Identifier: false);
+
+ using Stream stdin = Console.OpenStandardInput();
+ using Stream stdout = Console.OpenStandardOutput();
+ using StreamReader reader = new(stdin, utf8NoBom);
+ using StreamWriter writer = new(stdout, utf8NoBom) { AutoFlush = true };
+
+ // Redirect Console.Out to use our writer
+ Console.SetOut(writer);
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ string? line = await reader.ReadLineAsync(cancellationToken);
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ continue;
+ }
+
+ if (line.Length > MAX_LINE_LENGTH)
+ {
+ WriteError(id: null, code: McpStdioJsonRpcErrorCodes.INVALID_REQUEST, message: "Request too large");
+ continue;
+ }
+
+ JsonDocument doc;
+ try
+ {
+ doc = JsonDocument.Parse(line);
+ }
+ catch (JsonException jsonEx)
+ {
+ Console.Error.WriteLine($"[MCP DEBUG] JSON parse error: {jsonEx.Message}");
+ WriteError(id: null, code: McpStdioJsonRpcErrorCodes.PARSE_ERROR, message: "Parse error");
+ continue;
+ }
+ catch (Exception ex)
+ {
+ Console.Error.WriteLine($"[MCP DEBUG] Unexpected error parsing request: {ex.Message}");
+ WriteError(id: null, code: McpStdioJsonRpcErrorCodes.INTERNAL_ERROR, message: "Internal error");
+ continue;
+ }
+
+ using (doc)
+ {
+ JsonElement root = doc.RootElement;
+
+ JsonElement? id = null;
+ if (root.TryGetProperty("id", out JsonElement idEl))
+ {
+ id = idEl; // preserve original type (string or number)
+ }
+
+ if (!root.TryGetProperty("method", out JsonElement methodEl))
+ {
+ WriteError(id, McpStdioJsonRpcErrorCodes.INVALID_REQUEST, "Invalid Request");
+ continue;
+ }
+
+ string method = methodEl.GetString() ?? string.Empty;
+
+ try
+ {
+ switch (method)
+ {
+ case "initialize":
+ HandleInitialize(id);
+ break;
+
+ case "notifications/initialized":
+ break;
+
+ case "tools/list":
+ HandleListTools(id);
+ break;
+
+ case "tools/call":
+ await HandleCallToolAsync(id, root, cancellationToken);
+ break;
+
+ case "ping":
+ WriteResult(id, new { ok = true });
+ break;
+
+ case "shutdown":
+ WriteResult(id, new { ok = true });
+ return;
+
+ default:
+ WriteError(id, McpStdioJsonRpcErrorCodes.METHOD_NOT_FOUND, $"Method not found: {method}");
+ break;
+ }
+ }
+ catch (Exception)
+ {
+ WriteError(id, McpStdioJsonRpcErrorCodes.INTERNAL_ERROR, "Internal error");
+ }
+ }
+ }
+ }
+
+ ///
+ /// Handles the "initialize" JSON-RPC method by sending the MCP protocol version, server capabilities, and server info to the client.
+ ///
+ ///
+ /// The request identifier extracted from the incoming JSON-RPC request. Used to correlate the response with the request.
+ ///
+ ///
+ /// This method constructs and writes the MCP "initialize" response to STDOUT. It uses the protocol version defined by PROTOCOL_VERSION
+ /// and includes supported capabilities and server information. No notifications are sent here; the server waits for the client to send
+ /// "notifications/initialized" before sending any notifications.
+ ///
+ private void HandleInitialize(JsonElement? id)
+ {
+ var result = new
+ {
+ protocolVersion = _protocolVersion,
+ capabilities = new
+ {
+ tools = new { listChanged = true },
+ logging = new { }
+ },
+ serverInfo = new
+ {
+ name = McpProtocolDefaults.MCP_SERVER_NAME,
+ version = McpProtocolDefaults.MCP_SERVER_VERSION
+ }
+ };
+
+ WriteResult(id, result);
+ }
+
+ ///
+ /// Handles the "tools/list" JSON-RPC method by sending the list of available tools to the client.
+ ///
+ ///
+ /// The request identifier extracted from the incoming JSON-RPC request. Used to correlate the response with the request.
+ ///
+ private void HandleListTools(JsonElement? id)
+ {
+ List toolsWire = new();
+ int count = 0;
+
+ // Tools are expected to be registered during application startup only.
+ // If this ever changes and tools can be added/removed at runtime while
+ // requests are being handled, we may need to introduce locking here or
+ // have the registry return a thread-safe snapshot.
+ foreach (Tool tool in _toolRegistry.GetAllTools())
+ {
+ count++;
+ toolsWire.Add(new
+ {
+ name = tool.Name,
+ description = tool.Description,
+ inputSchema = tool.InputSchema
+ });
+ }
+
+ WriteResult(id, new { tools = toolsWire });
+ }
+
+ ///
+ /// Handles the "tools/call" JSON-RPC method by executing the specified tool with the provided arguments.
+ ///
+ /// The request identifier extracted from the incoming JSON-RPC request. Used to correlate the response with the request.
+ /// The root JSON element of the incoming JSON-RPC request.
+ /// Cancellation token to signal operation cancellation.
+ private async Task HandleCallToolAsync(JsonElement? id, JsonElement root, CancellationToken ct)
+ {
+ if (!root.TryGetProperty("params", out JsonElement @params) || @params.ValueKind != JsonValueKind.Object)
+ {
+ WriteError(id, McpStdioJsonRpcErrorCodes.INVALID_PARAMS, "Missing params");
+ return;
+ }
+
+ // If neither params.name (the MCP-standard field for the tool identifier)
+ // nor the legacy params.tool field is present or non-empty, we cannot tell
+ // which tool to execute. In that case we log a debug message to STDERR for
+ // diagnostics and return a JSON-RPC error (-32602 "Missing tool name") to
+ // the MCP client so it can fix the request payload.
+ string? toolName = null;
+ if (@params.TryGetProperty("name", out JsonElement nameEl) && nameEl.ValueKind == JsonValueKind.String)
+ {
+ toolName = nameEl.GetString();
+ }
+ else if (@params.TryGetProperty("tool", out JsonElement toolEl) && toolEl.ValueKind == JsonValueKind.String)
+ {
+ toolName = toolEl.GetString();
+ }
+
+ if (string.IsNullOrWhiteSpace(toolName))
+ {
+ Console.Error.WriteLine("[MCP DEBUG] callTool → missing tool name.");
+ WriteError(id, McpStdioJsonRpcErrorCodes.INVALID_PARAMS, "Missing tool name");
+ return;
+ }
+
+ if (!_toolRegistry.TryGetTool(toolName!, out IMcpTool? tool) || tool is null)
+ {
+ Console.Error.WriteLine($"[MCP DEBUG] callTool → tool not found: {toolName}");
+ WriteError(id, McpStdioJsonRpcErrorCodes.INVALID_PARAMS, $"Tool not found: {toolName}");
+ return;
+ }
+
+ JsonDocument? argsDoc = null;
+ try
+ {
+ if (@params.TryGetProperty("arguments", out JsonElement argsEl) && argsEl.ValueKind == JsonValueKind.Object)
+ {
+ string rawArgs = argsEl.GetRawText();
+ Console.Error.WriteLine($"[MCP DEBUG] callTool → tool: {toolName}, args: {rawArgs}");
+ argsDoc = JsonDocument.Parse(rawArgs);
+ }
+ else
+ {
+ Console.Error.WriteLine($"[MCP DEBUG] callTool → tool: {toolName}, args: ");
+ }
+
+ // Execute the tool.
+ // If a MCP stdio role override is set in the environment, create
+ // a request HttpContext with the X-MS-API-ROLE header so tools and authorization
+ // helpers that read IHttpContextAccessor will see the role. We also ensure the
+ // Simulator authentication handler can authenticate the user by flowing the
+ // Authorization header commonly used in tests/simulator scenarios.
+ CallToolResult callResult;
+ IConfiguration? configuration = _serviceProvider.GetService();
+ string? stdioRole = configuration?.GetValue("MCP:Role");
+ if (!string.IsNullOrWhiteSpace(stdioRole))
+ {
+ IServiceScopeFactory scopeFactory = _serviceProvider.GetRequiredService();
+ using IServiceScope scope = scopeFactory.CreateScope();
+ IServiceProvider scopedProvider = scope.ServiceProvider;
+
+ // Create a default HttpContext and set the client role header
+ DefaultHttpContext httpContext = new();
+ httpContext.Request.Headers["X-MS-API-ROLE"] = stdioRole;
+
+ // Build a simulator-style identity with the given role
+ ClaimsIdentity identity = new(
+ authenticationType: SimulatorAuthenticationDefaults.AUTHENTICATIONSCHEME);
+ identity.AddClaim(new Claim(ClaimTypes.Role, stdioRole));
+ httpContext.User = new ClaimsPrincipal(identity);
+
+ // If IHttpContextAccessor is registered, populate it for downstream code.
+ IHttpContextAccessor? httpContextAccessor = scopedProvider.GetService();
+ if (httpContextAccessor is not null)
+ {
+ httpContextAccessor.HttpContext = httpContext;
+ }
+
+ try
+ {
+ // Execute the tool with the scoped service provider so any scoped services resolve correctly.
+ callResult = await tool.ExecuteAsync(argsDoc, scopedProvider, ct);
+ }
+ finally
+ {
+ // Clear the accessor's HttpContext to avoid leaking across calls
+ if (httpContextAccessor is not null)
+ {
+ httpContextAccessor.HttpContext = null;
+ }
+ }
+ }
+ else
+ {
+ callResult = await tool.ExecuteAsync(argsDoc, _serviceProvider, ct);
+ }
+
+ // Normalize to MCP content blocks (array). We try to pass through if a 'Content' property exists,
+ // otherwise we wrap into a single text block.
+ object[] content = CoerceToMcpContentBlocks(callResult);
+
+ WriteResult(id, new { content });
+ }
+ finally
+ {
+ argsDoc?.Dispose();
+ }
+ }
+
+ ///
+ /// Coerces the call result into an array of MCP content blocks.
+ /// Tools can either return a custom object with a public "Content" property
+ /// or a raw value; this helper normalizes both patterns into the MCP wire format.
+ ///
+ /// The result object returned from a tool execution.
+ /// An array of content blocks suitable for MCP output.
+ private static object[] CoerceToMcpContentBlocks(object? callResult)
+ {
+ if (callResult is null)
+ {
+ return Array.Empty();
+ }
+
+ // Prefer a public instance "Content" property if present.
+ PropertyInfo? prop = callResult.GetType().GetProperty("Content", BindingFlags.Instance | BindingFlags.Public);
+
+ if (prop is not null)
+ {
+ object? value = prop.GetValue(callResult);
+
+ if (value is IEnumerable enumerable && value is not string)
+ {
+ List list = new();
+ foreach (object item in enumerable)
+ {
+ if (item is string s)
+ {
+ list.Add(new { type = "text", text = s });
+ }
+ else if (item is JsonElement jsonEl)
+ {
+ list.Add(new { type = "application/json", data = jsonEl });
+ }
+ else
+ {
+ list.Add(item);
+ }
+ }
+
+ return list.ToArray();
+ }
+
+ if (value is string sContent)
+ {
+ return new object[] { new { type = "text", text = sContent } };
+ }
+
+ if (value is JsonElement jsonContent)
+ {
+ return new object[] { new { type = "application/json", data = jsonContent } };
+ }
+ }
+
+ // If callResult itself is a JsonElement, treat it as application/json.
+ if (callResult is JsonElement jsonResult)
+ {
+ return new object[] { new { type = "application/json", data = jsonResult } };
+ }
+
+ // Fallback: serialize to text.
+ string text = SafeToString(callResult);
+ return new object[] { new { type = "text", text } };
+ }
+
+ ///
+ /// Safely converts an object to its string representation, preferring JSON serialization for readability.
+ ///
+ /// The object to convert to a string.
+ /// A string representation of the object.
+ private static string SafeToString(object obj)
+ {
+ try
+ {
+ // Try JSON first for readability
+ string json = JsonSerializer.Serialize(obj);
+
+ // If JSON is extremely large, truncate to avoid flooding MCP output.
+ // 32 KB is large enough to show useful JSON detail for diagnostics
+ // without flooding MCP output or impacting performance.
+ const int MAX_JSON_PREVIEW_CHARS = 32 * 1024; // 32 KB
+
+ if (json.Length > MAX_JSON_PREVIEW_CHARS)
+ {
+ return string.Concat(json.AsSpan(0, MAX_JSON_PREVIEW_CHARS), $"... [truncated, total length={json.Length} chars]");
+ }
+
+ return json;
+ }
+ catch
+ {
+ return obj.ToString() ?? string.Empty;
+ }
+ }
+
+ ///
+ /// Writes a JSON-RPC result response to the standard output.
+ ///
+ /// The request identifier extracted from the incoming JSON-RPC request. Used to correlate the response with the request.
+ /// The result object to include in the response.
+ private static void WriteResult(JsonElement? id, object resultObject)
+ {
+ var response = new
+ {
+ jsonrpc = "2.0",
+ id = id.HasValue ? GetIdValue(id.Value) : null,
+ result = resultObject
+ };
+
+ string json = JsonSerializer.Serialize(response);
+ Console.Out.WriteLine(json);
+ }
+
+ ///
+ /// Writes a JSON-RPC error response to the standard output.
+ ///
+ /// The request identifier extracted from the incoming JSON-RPC request. Used to correlate the response with the request.
+ /// The error code.
+ /// The error message.
+ private static void WriteError(JsonElement? id, int code, string message)
+ {
+ var errorObj = new
+ {
+ jsonrpc = "2.0",
+ id = id.HasValue ? GetIdValue(id.Value) : null,
+ error = new { code, message }
+ };
+
+ string json = JsonSerializer.Serialize(errorObj);
+ Console.Out.WriteLine(json);
+ }
+
+ ///
+ /// Extracts the value of a JSON-RPC request identifier.
+ ///
+ /// The JSON element representing the request identifier.
+ /// The extracted identifier value as an object, or null if the identifier is not a primitive type.
+ private static object? GetIdValue(JsonElement id)
+ {
+ return id.ValueKind switch
+ {
+ JsonValueKind.String => id.GetString(),
+ JsonValueKind.Number => id.TryGetInt64(out long l) ? l :
+ id.TryGetDouble(out double d) ? d : null,
+ _ => null
+ };
+ }
+ }
+}
diff --git a/src/Azure.DataApiBuilder.Mcp/IMcpStdioServer.cs b/src/Azure.DataApiBuilder.Mcp/IMcpStdioServer.cs
new file mode 100644
index 0000000000..033e0e3eaa
--- /dev/null
+++ b/src/Azure.DataApiBuilder.Mcp/IMcpStdioServer.cs
@@ -0,0 +1,7 @@
+namespace Azure.DataApiBuilder.Mcp.Core
+{
+ public interface IMcpStdioServer
+ {
+ Task RunAsync(CancellationToken cancellationToken);
+ }
+}
diff --git a/src/Azure.DataApiBuilder.Mcp/Model/McpStdioJsonRpcErrorCodes.cs b/src/Azure.DataApiBuilder.Mcp/Model/McpStdioJsonRpcErrorCodes.cs
new file mode 100644
index 0000000000..3bac194068
--- /dev/null
+++ b/src/Azure.DataApiBuilder.Mcp/Model/McpStdioJsonRpcErrorCodes.cs
@@ -0,0 +1,36 @@
+namespace Azure.DataApiBuilder.Mcp.Model
+{
+ ///
+ /// JSON-RPC 2.0 standard error codes used by the MCP stdio server.
+ /// These values come from the JSON-RPC 2.0 specification and are shared
+ /// so they are not hard-coded throughout the codebase.
+ ///
+ internal static class McpStdioJsonRpcErrorCodes
+ {
+ ///
+ /// Invalid JSON was received by the server.
+ /// An error occurred on the server while parsing the JSON text.
+ ///
+ public const int PARSE_ERROR = -32700;
+
+ ///
+ /// The JSON sent is not a valid Request object.
+ ///
+ public const int INVALID_REQUEST = -32600;
+
+ ///
+ /// The method does not exist / is not available.
+ ///
+ public const int METHOD_NOT_FOUND = -32601;
+
+ ///
+ /// Invalid method parameter(s).
+ ///
+ public const int INVALID_PARAMS = -32602;
+
+ ///
+ /// Internal JSON-RPC error.
+ ///
+ public const int INTERNAL_ERROR = -32603;
+ }
+}
diff --git a/src/Cli.Tests/AddOpenTelemetryTests.cs b/src/Cli.Tests/AddOpenTelemetryTests.cs
index d84473980c..b1a702d158 100644
--- a/src/Cli.Tests/AddOpenTelemetryTests.cs
+++ b/src/Cli.Tests/AddOpenTelemetryTests.cs
@@ -138,7 +138,7 @@ private static string GenerateRuntimeSection(string telemetrySection)
""allow-credentials"": false
}},
""authentication"": {{
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}}
}},
{telemetrySection}
diff --git a/src/Cli.Tests/AddTelemetryTests.cs b/src/Cli.Tests/AddTelemetryTests.cs
index ac4fe99a8f..37cd77f17d 100644
--- a/src/Cli.Tests/AddTelemetryTests.cs
+++ b/src/Cli.Tests/AddTelemetryTests.cs
@@ -140,7 +140,7 @@ private static string GenerateRuntimeSection(string telemetrySection)
""allow-credentials"": false
}},
""authentication"": {{
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}}
}},
{telemetrySection}
diff --git a/src/Cli.Tests/ConfigGeneratorTests.cs b/src/Cli.Tests/ConfigGeneratorTests.cs
index 604860eb69..59a7f7b8dd 100644
--- a/src/Cli.Tests/ConfigGeneratorTests.cs
+++ b/src/Cli.Tests/ConfigGeneratorTests.cs
@@ -139,7 +139,7 @@ public void TestSpecialCharactersInConnectionString()
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
config: TEST_RUNTIME_CONFIG_FILE);
StringBuilder expectedRuntimeConfigJson = new(
@@ -173,7 +173,7 @@ public void TestSpecialCharactersInConnectionString()
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
},
""mode"": ""production""
}
diff --git a/src/Cli.Tests/EndToEndTests.cs b/src/Cli.Tests/EndToEndTests.cs
index 5dbf97ca5e..99a9b77b6e 100644
--- a/src/Cli.Tests/EndToEndTests.cs
+++ b/src/Cli.Tests/EndToEndTests.cs
@@ -226,7 +226,7 @@ public void TestEnablingMultipleCreateOperation(CliBool isMultipleCreateEnabled,
public void TestAddEntity()
{
string[] initArgs = { "init", "-c", TEST_RUNTIME_CONFIG_FILE, "--host-mode", "development", "--database-type",
- "mssql", "--connection-string", TEST_ENV_CONN_STRING, "--auth.provider", "StaticWebApps" };
+ "mssql", "--connection-string", TEST_ENV_CONN_STRING, "--auth.provider", "AppService" };
Program.Execute(initArgs, _cliLogger!, _fileSystem!, _runtimeConfigLoader!);
Assert.IsTrue(_runtimeConfigLoader!.TryLoadConfig(TEST_RUNTIME_CONFIG_FILE, out RuntimeConfig? runtimeConfig));
diff --git a/src/Cli.Tests/InitTests.cs b/src/Cli.Tests/InitTests.cs
index 80eda44788..051bfdf7a7 100644
--- a/src/Cli.Tests/InitTests.cs
+++ b/src/Cli.Tests/InitTests.cs
@@ -49,7 +49,7 @@ public Task MsSQLDatabase()
setSessionContext: true,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "rest-api",
config: TEST_RUNTIME_CONFIG_FILE);
@@ -71,7 +71,7 @@ public Task CosmosDbPostgreSqlDatabase()
setSessionContext: false,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "/rest-endpoint",
config: TEST_RUNTIME_CONFIG_FILE);
@@ -94,7 +94,7 @@ public Task TestInitializingConfigWithoutConnectionString()
setSessionContext: false,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
config: TEST_RUNTIME_CONFIG_FILE);
return ExecuteVerifyTest(options);
@@ -118,7 +118,7 @@ public Task CosmosDbNoSqlDatabase()
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
config: TEST_RUNTIME_CONFIG_FILE);
return ExecuteVerifyTest(options);
@@ -151,7 +151,7 @@ bool expectSuccess
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restEnabled: CliBool.True,
graphqlEnabled: CliBool.True,
config: TEST_RUNTIME_CONFIG_FILE);
@@ -189,7 +189,7 @@ public void VerifyRequiredOptionsForCosmosDbNoSqlDatabase(
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
config: TEST_RUNTIME_CONFIG_FILE);
Assert.AreEqual(expectedResult, TryCreateRuntimeConfig(options, _runtimeConfigLoader!, _fileSystem!, out RuntimeConfig? _));
@@ -219,7 +219,7 @@ public void EnsureFailureWhenBothRestAndGraphQLAreDisabled(
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restEnabled: restEnabled,
graphqlEnabled: graphQLEnabled,
restDisabled: restDisabled,
@@ -245,7 +245,7 @@ public Task TestSpecialCharactersInConnectionString()
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
config: TEST_RUNTIME_CONFIG_FILE);
return ExecuteVerifyTest(options);
@@ -267,7 +267,7 @@ public void EnsureFailureOnReInitializingExistingConfig()
setSessionContext: false,
hostMode: HostMode.Development,
corsOrigin: new List() { },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
config: TEST_RUNTIME_CONFIG_FILE);
// Config generated successfully for the first time.
@@ -346,7 +346,7 @@ public void EnsureFailureReInitializingExistingConfigWithDifferentCase()
setSessionContext: true,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "rest-api",
config: TEST_RUNTIME_CONFIG_FILE);
Assert.AreEqual(true, TryGenerateConfig(initOptionsWithAllLowerCaseFileName, _runtimeConfigLoader!, _fileSystem!));
@@ -361,7 +361,7 @@ public void EnsureFailureReInitializingExistingConfigWithDifferentCase()
setSessionContext: true,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "rest-api",
config: TEST_RUNTIME_CONFIG_FILE.ToUpper());
// Platform Dependent
@@ -384,7 +384,7 @@ public Task RestPathWithoutStartingSlashWillHaveItAdded()
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "abc",
config: TEST_RUNTIME_CONFIG_FILE);
@@ -403,7 +403,7 @@ public Task GraphQLPathWithoutStartingSlashWillHaveItAdded()
setSessionContext: false,
hostMode: HostMode.Production,
corsOrigin: null,
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
graphQLPath: "abc",
config: TEST_RUNTIME_CONFIG_FILE);
@@ -466,7 +466,7 @@ public Task VerifyCorrectConfigGenerationWithMultipleMutationOptions(DatabaseTyp
setSessionContext: true,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "rest-api",
config: TEST_RUNTIME_CONFIG_FILE,
multipleCreateOperationEnabled: isMultipleCreateEnabled);
@@ -482,7 +482,7 @@ public Task VerifyCorrectConfigGenerationWithMultipleMutationOptions(DatabaseTyp
setSessionContext: true,
hostMode: HostMode.Development,
corsOrigin: new List() { "http://localhost:3000", "http://nolocalhost:80" },
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restPath: "rest-api",
config: TEST_RUNTIME_CONFIG_FILE,
multipleCreateOperationEnabled: isMultipleCreateEnabled);
diff --git a/src/Cli.Tests/ModuleInitializer.cs b/src/Cli.Tests/ModuleInitializer.cs
index e00dc00a89..a75a882968 100644
--- a/src/Cli.Tests/ModuleInitializer.cs
+++ b/src/Cli.Tests/ModuleInitializer.cs
@@ -77,6 +77,8 @@ public static void Init()
VerifierSettings.IgnoreMember(config => config.McpDmlTools);
// Ignore the IsStaticWebAppsIdentityProvider as that's unimportant from a test standpoint.
VerifierSettings.IgnoreMember(config => config.IsStaticWebAppsIdentityProvider);
+ // Ignore the IsAppServiceIdentityProvider as that's unimportant from a test standpoint.
+ VerifierSettings.IgnoreMember(config => config.IsAppServiceIdentityProvider);
// Ignore the RestPath as that's unimportant from a test standpoint.
VerifierSettings.IgnoreMember(config => config.RestPath);
// Ignore the GraphQLPath as that's unimportant from a test standpoint.
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithAnExistingNameButWithDifferentCase.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithAnExistingNameButWithDifferentCase.verified.txt
index 44fbbaa18b..12d7802079 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithAnExistingNameButWithDifferentCase.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithAnExistingNameButWithDifferentCase.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithCachingEnabled.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithCachingEnabled.verified.txt
index 6b3b5cc018..b4b428038b 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithCachingEnabled.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithCachingEnabled.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_70de36ebf1478d0d.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_70de36ebf1478d0d.verified.txt
index 7c701037fd..10324a7f50 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_70de36ebf1478d0d.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_70de36ebf1478d0d.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_9f612e68879149a3.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_9f612e68879149a3.verified.txt
index cec0a3d8ab..72d4c28329 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_9f612e68879149a3.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_9f612e68879149a3.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_bea2d26f3e5462d8.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_bea2d26f3e5462d8.verified.txt
index c318861497..d21d3b195d 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_bea2d26f3e5462d8.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddEntityWithPolicyAndFieldProperties_bea2d26f3e5462d8.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesEmpty.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesEmpty.verified.txt
index 8d8f226805..3d6deefaba 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesEmpty.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesEmpty.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesNotEmpty.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesNotEmpty.verified.txt
index 4e3184736d..d2a1b26553 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesNotEmpty.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesNotEmpty.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesWithSourceAsStoredProcedure.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesWithSourceAsStoredProcedure.verified.txt
index 21759deeed..2418bbaf9e 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesWithSourceAsStoredProcedure.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddNewEntityWhenEntitiesWithSourceAsStoredProcedure.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithBothMcpProperties.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithBothMcpProperties.verified.txt
new file mode 100644
index 0000000000..c5772388d6
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithBothMcpProperties.verified.txt
@@ -0,0 +1,61 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /api,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService
+ }
+ }
+ },
+ Entities: [
+ {
+ UpdateBook: {
+ Source: {
+ Object: dbo.UpdateBook,
+ Type: stored-procedure
+ },
+ GraphQL: {
+ Singular: UpdateBook,
+ Plural: UpdateBooks,
+ Enabled: true,
+ Operation: Mutation
+ },
+ Rest: {
+ Methods: [
+ Post
+ ],
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: Execute
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: true,
+ DmlToolEnabled: false
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithBothMcpPropertiesEnabled.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithBothMcpPropertiesEnabled.verified.txt
new file mode 100644
index 0000000000..f0c74a20b7
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithBothMcpPropertiesEnabled.verified.txt
@@ -0,0 +1,61 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /api,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService
+ }
+ }
+ },
+ Entities: [
+ {
+ GetAllBooks: {
+ Source: {
+ Object: dbo.GetAllBooks,
+ Type: stored-procedure
+ },
+ GraphQL: {
+ Singular: GetAllBooks,
+ Plural: GetAllBooks,
+ Enabled: true,
+ Operation: Mutation
+ },
+ Rest: {
+ Methods: [
+ Post
+ ],
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: Execute
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: true,
+ DmlToolEnabled: true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithMcpCustomToolEnabled.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithMcpCustomToolEnabled.verified.txt
new file mode 100644
index 0000000000..50b1b5c571
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddStoredProcedureWithMcpCustomToolEnabled.verified.txt
@@ -0,0 +1,61 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /api,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService
+ }
+ }
+ },
+ Entities: [
+ {
+ GetBookById: {
+ Source: {
+ Object: dbo.GetBookById,
+ Type: stored-procedure
+ },
+ GraphQL: {
+ Singular: GetBookById,
+ Plural: GetBookByIds,
+ Enabled: true,
+ Operation: Mutation
+ },
+ Rest: {
+ Methods: [
+ Post
+ ],
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: Execute
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: true,
+ DmlToolEnabled: true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddTableEntityWithMcpDmlTools_mcpDmlTools=false_source=authors.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddTableEntityWithMcpDmlTools_mcpDmlTools=false_source=authors.verified.txt
new file mode 100644
index 0000000000..e1ba348224
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddTableEntityWithMcpDmlTools_mcpDmlTools=false_source=authors.verified.txt
@@ -0,0 +1,57 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /api,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService
+ }
+ }
+ },
+ Entities: [
+ {
+ Author: {
+ Source: {
+ Object: authors,
+ Type: Table
+ },
+ GraphQL: {
+ Singular: Author,
+ Plural: Authors,
+ Enabled: true
+ },
+ Rest: {
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: *
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: false,
+ DmlToolEnabled: false
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.AddTableEntityWithMcpDmlTools_mcpDmlTools=true_source=books.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.AddTableEntityWithMcpDmlTools_mcpDmlTools=true_source=books.verified.txt
new file mode 100644
index 0000000000..82287b53aa
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.AddTableEntityWithMcpDmlTools_mcpDmlTools=true_source=books.verified.txt
@@ -0,0 +1,57 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /api,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService
+ }
+ }
+ },
+ Entities: [
+ {
+ Book: {
+ Source: {
+ Object: books,
+ Type: Table
+ },
+ GraphQL: {
+ Singular: Book,
+ Plural: Books,
+ Enabled: true
+ },
+ Rest: {
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: *
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: false,
+ DmlToolEnabled: true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_0c9cbb8942b4a4e5.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_0c9cbb8942b4a4e5.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_0c9cbb8942b4a4e5.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_0c9cbb8942b4a4e5.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_286d268a654ece27.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_286d268a654ece27.verified.txt
index 13beb6bc7c..99d78eaa0e 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_286d268a654ece27.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_286d268a654ece27.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3048323e01b42681.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3048323e01b42681.verified.txt
index bdd7c8f7a0..ec4549f38a 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3048323e01b42681.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3048323e01b42681.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3440d150a2282b9c.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3440d150a2282b9c.verified.txt
index 20d7bcd624..6ba80ba348 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3440d150a2282b9c.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_3440d150a2282b9c.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_381c28d25063be0c.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_381c28d25063be0c.verified.txt
index 13beb6bc7c..99d78eaa0e 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_381c28d25063be0c.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_381c28d25063be0c.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_458373311f6ed4ed.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_458373311f6ed4ed.verified.txt
index b87e804456..11d8adb815 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_458373311f6ed4ed.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_458373311f6ed4ed.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66799c963a6306ae.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66799c963a6306ae.verified.txt
index 18c5f966c5..5c6a0b7d6b 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66799c963a6306ae.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66799c963a6306ae.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66f598295b8682fd.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66f598295b8682fd.verified.txt
index 1cd138d10f..e3a6363fb1 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66f598295b8682fd.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_66f598295b8682fd.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_73f95f7e2cd3ed71.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_73f95f7e2cd3ed71.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_73f95f7e2cd3ed71.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_73f95f7e2cd3ed71.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_79d59edde7f6a272.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_79d59edde7f6a272.verified.txt
index b87e804456..11d8adb815 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_79d59edde7f6a272.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_79d59edde7f6a272.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_7ec82512a1df5293.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_7ec82512a1df5293.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_7ec82512a1df5293.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_7ec82512a1df5293.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_cbb6e5548e4d3535.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_cbb6e5548e4d3535.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_cbb6e5548e4d3535.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_cbb6e5548e4d3535.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_dc629052f38cea32.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_dc629052f38cea32.verified.txt
index 612a65c14a..aa074116d0 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_dc629052f38cea32.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_dc629052f38cea32.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_e4a97c7e3507d2c6.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_e4a97c7e3507d2c6.verified.txt
index 87b7a7697c..9b7d9f96e9 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_e4a97c7e3507d2c6.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_e4a97c7e3507d2c6.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_f8d0d0c2a38bd3b8.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_f8d0d0c2a38bd3b8.verified.txt
index 1cd138d10f..e3a6363fb1 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_f8d0d0c2a38bd3b8.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddNewSpWithDifferentRestAndGraphQLOptions_f8d0d0c2a38bd3b8.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
index 83d3882a96..11829a214c 100644
--- a/src/Cli.Tests/Snapshots/AddEntityTests.TestAddStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
+++ b/src/Cli.Tests/Snapshots/AddEntityTests.TestAddStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestAddingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestAddingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
index b072d5e5a0..3fa1fbc14e 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestAddingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestAddingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceAsStoredProcedure.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceAsStoredProcedure.verified.txt
index ca7211c485..76ea01dfca 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceAsStoredProcedure.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceAsStoredProcedure.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceWithDefaultType.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceWithDefaultType.verified.txt
index d7aadee93c..3a8c738a70 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceWithDefaultType.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithSourceWithDefaultType.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithoutIEnumerables.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithoutIEnumerables.verified.txt
index 331a040a45..df2cd4b009 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithoutIEnumerables.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestConfigGeneratedAfterAddingEntityWithoutIEnumerables.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
},
Mode: Production
}
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestInitForCosmosDBNoSql.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestInitForCosmosDBNoSql.verified.txt
index ff3f25d357..1b14a3a7f0 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestInitForCosmosDBNoSql.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestInitForCosmosDBNoSql.verified.txt
@@ -46,7 +46,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
},
Mode: Production
}
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethods.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethods.verified.txt
index a04dc2fe36..62d9e237b5 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethods.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethods.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt b/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
index cfa928a025..fa8b16e739 100644
--- a/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
+++ b/src/Cli.Tests/Snapshots/EndToEndTests.TestUpdatingStoredProcedureWithRestMethodsAndGraphQLOperations.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.CosmosDbNoSqlDatabase.verified.txt b/src/Cli.Tests/Snapshots/InitTests.CosmosDbNoSqlDatabase.verified.txt
index b9b040aa2f..9d5458c0ee 100644
--- a/src/Cli.Tests/Snapshots/InitTests.CosmosDbNoSqlDatabase.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.CosmosDbNoSqlDatabase.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
},
Mode: Production
}
diff --git a/src/Cli.Tests/Snapshots/InitTests.CosmosDbPostgreSqlDatabase.verified.txt b/src/Cli.Tests/Snapshots/InitTests.CosmosDbPostgreSqlDatabase.verified.txt
index 65b03f6293..51f6ad8d95 100644
--- a/src/Cli.Tests/Snapshots/InitTests.CosmosDbPostgreSqlDatabase.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.CosmosDbPostgreSqlDatabase.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.GraphQLPathWithoutStartingSlashWillHaveItAdded.verified.txt b/src/Cli.Tests/Snapshots/InitTests.GraphQLPathWithoutStartingSlashWillHaveItAdded.verified.txt
index bc6b6cfecb..a3a056ac0a 100644
--- a/src/Cli.Tests/Snapshots/InitTests.GraphQLPathWithoutStartingSlashWillHaveItAdded.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.GraphQLPathWithoutStartingSlashWillHaveItAdded.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
},
Mode: Production
}
diff --git a/src/Cli.Tests/Snapshots/InitTests.MsSQLDatabase.verified.txt b/src/Cli.Tests/Snapshots/InitTests.MsSQLDatabase.verified.txt
index 3078fb644f..f40350c4da 100644
--- a/src/Cli.Tests/Snapshots/InitTests.MsSQLDatabase.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.MsSQLDatabase.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.RestPathWithoutStartingSlashWillHaveItAdded.verified.txt b/src/Cli.Tests/Snapshots/InitTests.RestPathWithoutStartingSlashWillHaveItAdded.verified.txt
index c888431526..b792d41c9f 100644
--- a/src/Cli.Tests/Snapshots/InitTests.RestPathWithoutStartingSlashWillHaveItAdded.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.RestPathWithoutStartingSlashWillHaveItAdded.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
},
Mode: Production
}
diff --git a/src/Cli.Tests/Snapshots/InitTests.TestInitializingConfigWithoutConnectionString.verified.txt b/src/Cli.Tests/Snapshots/InitTests.TestInitializingConfigWithoutConnectionString.verified.txt
index 0273dcc976..173960d7b1 100644
--- a/src/Cli.Tests/Snapshots/InitTests.TestInitializingConfigWithoutConnectionString.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.TestInitializingConfigWithoutConnectionString.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.TestSpecialCharactersInConnectionString.verified.txt b/src/Cli.Tests/Snapshots/InitTests.TestSpecialCharactersInConnectionString.verified.txt
index ab71a40f03..25e3976685 100644
--- a/src/Cli.Tests/Snapshots/InitTests.TestSpecialCharactersInConnectionString.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.TestSpecialCharactersInConnectionString.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
},
Mode: Production
}
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0546bef37027a950.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0546bef37027a950.verified.txt
index 86a0716003..63f0da701c 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0546bef37027a950.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0546bef37027a950.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0ac567dd32a2e8f5.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0ac567dd32a2e8f5.verified.txt
index 3078fb644f..f40350c4da 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0ac567dd32a2e8f5.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0ac567dd32a2e8f5.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0c06949221514e77.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0c06949221514e77.verified.txt
index aac85044f9..e59070d692 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0c06949221514e77.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_0c06949221514e77.verified.txt
@@ -50,7 +50,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_18667ab7db033e9d.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_18667ab7db033e9d.verified.txt
index c7904175e0..f7de35b7ae 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_18667ab7db033e9d.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_18667ab7db033e9d.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_2f42f44c328eb020.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_2f42f44c328eb020.verified.txt
index 86a0716003..63f0da701c 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_2f42f44c328eb020.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_2f42f44c328eb020.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_3243d3f3441fdcc1.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_3243d3f3441fdcc1.verified.txt
index c7904175e0..f7de35b7ae 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_3243d3f3441fdcc1.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_3243d3f3441fdcc1.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_53350b8b47df2112.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_53350b8b47df2112.verified.txt
index d70704315e..75613db959 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_53350b8b47df2112.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_53350b8b47df2112.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_6584e0ec46b8a11d.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_6584e0ec46b8a11d.verified.txt
index ac3815f949..d93aac7dc6 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_6584e0ec46b8a11d.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_6584e0ec46b8a11d.verified.txt
@@ -46,7 +46,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_81cc88db3d4eecfb.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_81cc88db3d4eecfb.verified.txt
index fd6a494ba3..640815babb 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_81cc88db3d4eecfb.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_81cc88db3d4eecfb.verified.txt
@@ -50,7 +50,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_8ea187616dbb5577.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_8ea187616dbb5577.verified.txt
index 8044f643ac..5900015d5a 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_8ea187616dbb5577.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_8ea187616dbb5577.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_905845c29560a3ef.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_905845c29560a3ef.verified.txt
index 86a0716003..63f0da701c 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_905845c29560a3ef.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_905845c29560a3ef.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_b2fd24fab5b80917.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_b2fd24fab5b80917.verified.txt
index ac3815f949..d93aac7dc6 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_b2fd24fab5b80917.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_b2fd24fab5b80917.verified.txt
@@ -46,7 +46,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_bd7cd088755287c9.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_bd7cd088755287c9.verified.txt
index ac3815f949..d93aac7dc6 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_bd7cd088755287c9.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_bd7cd088755287c9.verified.txt
@@ -46,7 +46,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d2eccba2f836b380.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d2eccba2f836b380.verified.txt
index d70704315e..75613db959 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d2eccba2f836b380.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d2eccba2f836b380.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d463eed7fe5e4bbe.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d463eed7fe5e4bbe.verified.txt
index 8044f643ac..5900015d5a 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d463eed7fe5e4bbe.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d463eed7fe5e4bbe.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d5520dd5c33f7b8d.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d5520dd5c33f7b8d.verified.txt
index d70704315e..75613db959 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d5520dd5c33f7b8d.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_d5520dd5c33f7b8d.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_eab4a6010e602b59.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_eab4a6010e602b59.verified.txt
index c7904175e0..f7de35b7ae 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_eab4a6010e602b59.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_eab4a6010e602b59.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_ecaa688829b4030e.verified.txt b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_ecaa688829b4030e.verified.txt
index 8044f643ac..5900015d5a 100644
--- a/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_ecaa688829b4030e.verified.txt
+++ b/src/Cli.Tests/Snapshots/InitTests.VerifyCorrectConfigGenerationWithMultipleMutationOptions_ecaa688829b4030e.verified.txt
@@ -42,7 +42,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_036a859f50ce167c.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_036a859f50ce167c.verified.txt
index 260eecd0c9..003bc17a3e 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_036a859f50ce167c.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_036a859f50ce167c.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_103655d39b48d89f.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_103655d39b48d89f.verified.txt
index 80f61e17ac..29d477944f 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_103655d39b48d89f.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_103655d39b48d89f.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_442649c7ef2176bd.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_442649c7ef2176bd.verified.txt
index 260eecd0c9..003bc17a3e 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_442649c7ef2176bd.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_442649c7ef2176bd.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_7f2338fdc84aafc3.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_7f2338fdc84aafc3.verified.txt
index b6b9269e87..edfefa5bac 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_7f2338fdc84aafc3.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_7f2338fdc84aafc3.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_a70c086a74142c82.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_a70c086a74142c82.verified.txt
index 21759deeed..2418bbaf9e 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_a70c086a74142c82.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_a70c086a74142c82.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_c26902b0e44f97cd.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_c26902b0e44f97cd.verified.txt
index 2d00804545..5339d06351 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_c26902b0e44f97cd.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestConversionOfSourceObject_c26902b0e44f97cd.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByAddingNewRelationship.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByAddingNewRelationship.verified.txt
index 2789572051..ef0e2b9151 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByAddingNewRelationship.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByAddingNewRelationship.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByModifyingRelationship.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByModifyingRelationship.verified.txt
index 092dec7745..44828bd61a 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByModifyingRelationship.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityByModifyingRelationship.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityCaching.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityCaching.verified.txt
index 9ae0e33948..a3df8fd6c4 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityCaching.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityCaching.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermission.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermission.verified.txt
index 1a77d65bcd..477f15db4a 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermission.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermission.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionByAddingNewRole.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionByAddingNewRole.verified.txt
index 6775db8dde..63c4e24898 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionByAddingNewRole.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionByAddingNewRole.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionHavingWildcardAction.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionHavingWildcardAction.verified.txt
index 64517082ad..f3db383d0f 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionHavingWildcardAction.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionHavingWildcardAction.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithExistingAction.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithExistingAction.verified.txt
index 52dc99399e..c0818f3c84 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithExistingAction.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithExistingAction.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithWildcardAction.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithWildcardAction.verified.txt
index 92b5917b92..19444d8105 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithWildcardAction.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityPermissionWithWildcardAction.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithMappings.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithMappings.verified.txt
index 54d9077f1c..e6f2bec0c9 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithMappings.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithMappings.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_088d6237033e0a7c.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_088d6237033e0a7c.verified.txt
index 7c701037fd..10324a7f50 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_088d6237033e0a7c.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_088d6237033e0a7c.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_3ea32fdef7aed1b4.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_3ea32fdef7aed1b4.verified.txt
index c318861497..d21d3b195d 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_3ea32fdef7aed1b4.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_3ea32fdef7aed1b4.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_4d25c2c012107597.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_4d25c2c012107597.verified.txt
index cdf30a00c9..f44cb7a9b4 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_4d25c2c012107597.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithPolicyAndFieldProperties_4d25c2c012107597.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithSpecialCharacterInMappings.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithSpecialCharacterInMappings.verified.txt
index 1906f87425..396d09edf3 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithSpecialCharacterInMappings.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateEntityWithSpecialCharacterInMappings.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateExistingMappings.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateExistingMappings.verified.txt
index 56ce5b55c3..2884cf540b 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateExistingMappings.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateExistingMappings.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps,
+ Provider: AppService,
Jwt: {
Audience: ,
Issuer:
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdatePolicy.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdatePolicy.verified.txt
index c8002a2fbc..57c5f18284 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdatePolicy.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdatePolicy.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_10ea92e3b25ab0c9.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_10ea92e3b25ab0c9.verified.txt
index b87e804456..11d8adb815 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_10ea92e3b25ab0c9.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_10ea92e3b25ab0c9.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_127bb81593f835fe.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_127bb81593f835fe.verified.txt
index 1cd138d10f..e3a6363fb1 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_127bb81593f835fe.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_127bb81593f835fe.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_386efa1a113fac6b.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_386efa1a113fac6b.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_386efa1a113fac6b.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_386efa1a113fac6b.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_53db4712d83be8e6.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_53db4712d83be8e6.verified.txt
index 20d7bcd624..6ba80ba348 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_53db4712d83be8e6.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_53db4712d83be8e6.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_5e9ddd8c7c740efd.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_5e9ddd8c7c740efd.verified.txt
index 13beb6bc7c..99d78eaa0e 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_5e9ddd8c7c740efd.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_5e9ddd8c7c740efd.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_6c5b3bfc72e5878a.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_6c5b3bfc72e5878a.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_6c5b3bfc72e5878a.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_6c5b3bfc72e5878a.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_8398059a743d7027.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_8398059a743d7027.verified.txt
index c7cb996d03..9729cf4aae 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_8398059a743d7027.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_8398059a743d7027.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_a49380ce6d1fd8ba.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_a49380ce6d1fd8ba.verified.txt
index bdd7c8f7a0..ec4549f38a 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_a49380ce6d1fd8ba.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_a49380ce6d1fd8ba.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_c9b12fe27be53878.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_c9b12fe27be53878.verified.txt
index e8fc427339..92cb5caac0 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_c9b12fe27be53878.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_c9b12fe27be53878.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d19603117eb8b51b.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d19603117eb8b51b.verified.txt
index 13beb6bc7c..99d78eaa0e 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d19603117eb8b51b.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d19603117eb8b51b.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d770d682c5802737.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d770d682c5802737.verified.txt
index b87e804456..11d8adb815 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d770d682c5802737.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_d770d682c5802737.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_ef8cc721c9dfc7e4.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_ef8cc721c9dfc7e4.verified.txt
index 87b7a7697c..9b7d9f96e9 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_ef8cc721c9dfc7e4.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_ef8cc721c9dfc7e4.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f3897e2254996db0.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f3897e2254996db0.verified.txt
index 18c5f966c5..5c6a0b7d6b 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f3897e2254996db0.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f3897e2254996db0.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f4cadb897fc5b0fe.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f4cadb897fc5b0fe.verified.txt
index 612a65c14a..aa074116d0 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f4cadb897fc5b0fe.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f4cadb897fc5b0fe.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f59b2a65fc1e18a3.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f59b2a65fc1e18a3.verified.txt
index 1cd138d10f..e3a6363fb1 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f59b2a65fc1e18a3.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateRestAndGraphQLSettingsForStoredProcedures_f59b2a65fc1e18a3.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_574e1995f787740f.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_574e1995f787740f.verified.txt
index 260eecd0c9..003bc17a3e 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_574e1995f787740f.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_574e1995f787740f.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a13a9ca73b21f261.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a13a9ca73b21f261.verified.txt
index 80f61e17ac..29d477944f 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a13a9ca73b21f261.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a13a9ca73b21f261.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a5ce76c8bea25cc8.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a5ce76c8bea25cc8.verified.txt
index 80f61e17ac..29d477944f 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a5ce76c8bea25cc8.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_a5ce76c8bea25cc8.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_bba111332a1f973f.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_bba111332a1f973f.verified.txt
index ba28cd7509..f5dd22534c 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_bba111332a1f973f.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateSourceStringToDatabaseSourceObject_bba111332a1f973f.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithBothMcpProperties.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithBothMcpProperties.verified.txt
new file mode 100644
index 0000000000..a2aa5c0f40
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithBothMcpProperties.verified.txt
@@ -0,0 +1,64 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService,
+ Jwt: {
+ Audience: ,
+ Issuer:
+ }
+ }
+ }
+ },
+ Entities: [
+ {
+ UpdateBook: {
+ Source: {
+ Type: stored-procedure
+ },
+ GraphQL: {
+ Singular: UpdateBook,
+ Plural: UpdateBooks,
+ Enabled: true,
+ Operation: Mutation
+ },
+ Rest: {
+ Methods: [
+ Post
+ ],
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: Execute
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: true,
+ DmlToolEnabled: false
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithBothMcpPropertiesEnabled.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithBothMcpPropertiesEnabled.verified.txt
new file mode 100644
index 0000000000..6526bd5e38
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithBothMcpPropertiesEnabled.verified.txt
@@ -0,0 +1,64 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService,
+ Jwt: {
+ Audience: ,
+ Issuer:
+ }
+ }
+ }
+ },
+ Entities: [
+ {
+ GetAllBooks: {
+ Source: {
+ Type: stored-procedure
+ },
+ GraphQL: {
+ Singular: GetAllBooks,
+ Plural: GetAllBooks,
+ Enabled: true,
+ Operation: Mutation
+ },
+ Rest: {
+ Methods: [
+ Post
+ ],
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: Execute
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: true,
+ DmlToolEnabled: true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithMcpCustomToolEnabled.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithMcpCustomToolEnabled.verified.txt
new file mode 100644
index 0000000000..b74749dcf6
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateStoredProcedureWithMcpCustomToolEnabled.verified.txt
@@ -0,0 +1,64 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService,
+ Jwt: {
+ Audience: ,
+ Issuer:
+ }
+ }
+ }
+ },
+ Entities: [
+ {
+ GetBookById: {
+ Source: {
+ Type: stored-procedure
+ },
+ GraphQL: {
+ Singular: GetBookById,
+ Plural: GetBookByIds,
+ Enabled: true,
+ Operation: Mutation
+ },
+ Rest: {
+ Methods: [
+ Post
+ ],
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: Execute
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: true,
+ DmlToolEnabled: true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateTableEntityWithMcpDmlTools_newMcpDmlTools=false.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateTableEntityWithMcpDmlTools_newMcpDmlTools=false.verified.txt
new file mode 100644
index 0000000000..9efb911f99
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateTableEntityWithMcpDmlTools_newMcpDmlTools=false.verified.txt
@@ -0,0 +1,61 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService,
+ Jwt: {
+ Audience: ,
+ Issuer:
+ }
+ }
+ }
+ },
+ Entities: [
+ {
+ MyEntity: {
+ Source: {
+ Object: MyTable,
+ Type: Table
+ },
+ GraphQL: {
+ Singular: MyEntity,
+ Plural: MyEntities,
+ Enabled: true
+ },
+ Rest: {
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: *
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: false,
+ DmlToolEnabled: false
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateTableEntityWithMcpDmlTools_newMcpDmlTools=true.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateTableEntityWithMcpDmlTools_newMcpDmlTools=true.verified.txt
new file mode 100644
index 0000000000..8ffa3b4893
--- /dev/null
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.TestUpdateTableEntityWithMcpDmlTools_newMcpDmlTools=true.verified.txt
@@ -0,0 +1,61 @@
+{
+ DataSource: {
+ DatabaseType: MSSQL
+ },
+ Runtime: {
+ Rest: {
+ Enabled: true,
+ Path: /,
+ RequestBodyStrict: true
+ },
+ GraphQL: {
+ Enabled: true,
+ Path: /graphql,
+ AllowIntrospection: true
+ },
+ Host: {
+ Cors: {
+ AllowCredentials: false
+ },
+ Authentication: {
+ Provider: AppService,
+ Jwt: {
+ Audience: ,
+ Issuer:
+ }
+ }
+ }
+ },
+ Entities: [
+ {
+ MyEntity: {
+ Source: {
+ Object: MyTable,
+ Type: Table
+ },
+ GraphQL: {
+ Singular: MyEntity,
+ Plural: MyEntities,
+ Enabled: true
+ },
+ Rest: {
+ Enabled: true
+ },
+ Permissions: [
+ {
+ Role: anonymous,
+ Actions: [
+ {
+ Action: *
+ }
+ ]
+ }
+ ],
+ Mcp: {
+ CustomToolEnabled: false,
+ DmlToolEnabled: true
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceKeyFields.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceKeyFields.verified.txt
index 544a3484f9..73703220d8 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceKeyFields.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceKeyFields.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceName.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceName.verified.txt
index 1719e1ade2..50c0a1786c 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceName.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceName.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceParameters.verified.txt b/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceParameters.verified.txt
index 0cbdc4347f..a34882cefe 100644
--- a/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceParameters.verified.txt
+++ b/src/Cli.Tests/Snapshots/UpdateEntityTests.UpdateDatabaseSourceParameters.verified.txt
@@ -18,7 +18,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Cli.Tests/TestHelper.cs b/src/Cli.Tests/TestHelper.cs
index a5a0079797..8224a079d4 100644
--- a/src/Cli.Tests/TestHelper.cs
+++ b/src/Cli.Tests/TestHelper.cs
@@ -143,7 +143,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -170,7 +170,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
}";
@@ -228,7 +228,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -1003,7 +1003,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -1048,7 +1048,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -1118,7 +1118,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -1199,7 +1199,7 @@ public static Process ExecuteDabCommand(string command, string flags)
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -1298,7 +1298,7 @@ public static string GenerateConfigWithGivenDepthLimit(string? depthLimitJson =
""allow-credentials"": false
}},
""authentication"": {{
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}}
}}
}},
@@ -1323,7 +1323,7 @@ public static InitOptions CreateBasicInitOptionsForMsSqlWithConfig(string? confi
setSessionContext: true,
hostMode: HostMode.Development,
corsOrigin: new List(),
- authenticationProvider: EasyAuthType.StaticWebApps.ToString(),
+ authenticationProvider: EasyAuthType.AppService.ToString(),
restRequestBodyStrict: CliBool.True,
config: config);
}
diff --git a/src/Cli.Tests/UpdateEntityTests.cs b/src/Cli.Tests/UpdateEntityTests.cs
index 3a106c0adc..b05392aa81 100644
--- a/src/Cli.Tests/UpdateEntityTests.cs
+++ b/src/Cli.Tests/UpdateEntityTests.cs
@@ -1125,7 +1125,7 @@ private static string GetInitialConfigString()
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps"",
+ ""provider"": ""AppService"",
""jwt"": {
""audience"": """",
""issuer"": """"
diff --git a/src/Cli/Commands/ConfigureOptions.cs b/src/Cli/Commands/ConfigureOptions.cs
index 60cb12c3f8..11dca2a4eb 100644
--- a/src/Cli/Commands/ConfigureOptions.cs
+++ b/src/Cli/Commands/ConfigureOptions.cs
@@ -216,7 +216,7 @@ public ConfigureOptions(
[Option("runtime.host.cors.allow-credentials", Required = false, HelpText = "Set value for Access-Control-Allow-Credentials header in Host.Cors. Default: false (boolean).")]
public bool? RuntimeHostCorsAllowCredentials { get; }
- [Option("runtime.host.authentication.provider", Required = false, HelpText = "Configure the name of authentication provider. Default: StaticWebApps.")]
+ [Option("runtime.host.authentication.provider", Required = false, HelpText = "Configure the name of authentication provider. Default: AppService.")]
public string? RuntimeHostAuthenticationProvider { get; }
[Option("runtime.host.authentication.jwt.audience", Required = false, HelpText = "Configure the intended recipient(s) of the Jwt Token.")]
diff --git a/src/Cli/Commands/InitOptions.cs b/src/Cli/Commands/InitOptions.cs
index 91786d99ff..e01ad1b774 100644
--- a/src/Cli/Commands/InitOptions.cs
+++ b/src/Cli/Commands/InitOptions.cs
@@ -94,7 +94,7 @@ public InitOptions(
[Option("cors-origin", Separator = ',', Required = false, HelpText = "Specify the list of allowed origins.")]
public IEnumerable? CorsOrigin { get; }
- [Option("auth.provider", Default = "StaticWebApps", Required = false, HelpText = "Specify the Identity Provider.")]
+ [Option("auth.provider", Default = "AppService", Required = false, HelpText = "Specify the Identity Provider.")]
public string AuthenticationProvider { get; }
[Option("auth.audience", Required = false, HelpText = "Identifies the recipients that the JWT is intended for.")]
diff --git a/src/Cli/Commands/StartOptions.cs b/src/Cli/Commands/StartOptions.cs
index c335c6bcc5..050f410801 100644
--- a/src/Cli/Commands/StartOptions.cs
+++ b/src/Cli/Commands/StartOptions.cs
@@ -19,12 +19,14 @@ public class StartOptions : Options
{
private const string LOGLEVEL_HELPTEXT = "Specifies logging level as provided value. For possible values, see: https://go.microsoft.com/fwlink/?linkid=2263106";
- public StartOptions(bool verbose, LogLevel? logLevel, bool isHttpsRedirectionDisabled, string config)
+ public StartOptions(bool verbose, LogLevel? logLevel, bool isHttpsRedirectionDisabled, bool mcpStdio, string? mcpRole, string config)
: base(config)
{
// When verbose is true we set LogLevel to information.
LogLevel = verbose is true ? Microsoft.Extensions.Logging.LogLevel.Information : logLevel;
IsHttpsRedirectionDisabled = isHttpsRedirectionDisabled;
+ McpStdio = mcpStdio;
+ McpRole = mcpRole;
}
// SetName defines mutually exclusive sets, ie: can not have
@@ -38,6 +40,12 @@ public StartOptions(bool verbose, LogLevel? logLevel, bool isHttpsRedirectionDis
[Option("no-https-redirect", Required = false, HelpText = "Disables automatic https redirects.")]
public bool IsHttpsRedirectionDisabled { get; }
+ [Option("mcp-stdio", Required = false, HelpText = "Run Data API Builder in MCP stdio mode while starting the engine.")]
+ public bool McpStdio { get; }
+
+ [Value(0, MetaName = "role", Required = false, HelpText = "Optional MCP permissions role, e.g. role:anonymous. If omitted, defaults to anonymous.")]
+ public string? McpRole { get; }
+
public int Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSystem fileSystem)
{
logger.LogInformation("{productName} {version}", PRODUCT_NAME, ProductInfo.GetProductVersion());
@@ -45,7 +53,8 @@ public int Handler(ILogger logger, FileSystemRuntimeConfigLoader loader, IFileSy
if (!isSuccess)
{
- logger.LogError("Failed to start the engine.");
+ logger.LogError("Failed to start the engine{mode}.",
+ McpStdio ? " in MCP stdio mode" : string.Empty);
}
return isSuccess ? CliReturnCode.SUCCESS : CliReturnCode.GENERAL_ERROR;
diff --git a/src/Cli/ConfigGenerator.cs b/src/Cli/ConfigGenerator.cs
index 7c35335089..07dad2af8b 100644
--- a/src/Cli/ConfigGenerator.cs
+++ b/src/Cli/ConfigGenerator.cs
@@ -1260,7 +1260,8 @@ private static bool TryUpdateConfiguredHostValues(
string? updatedProviderValue = options?.RuntimeHostAuthenticationProvider;
if (updatedProviderValue != null)
{
- updatedValue = updatedProviderValue?.ToString() ?? nameof(EasyAuthType.StaticWebApps);
+ // Default to AppService when provider string is not provided
+ updatedValue = updatedProviderValue?.ToString() ?? nameof(EasyAuthType.AppService);
AuthenticationOptions AuthOptions;
if (updatedHostOptions?.Authentication == null)
{
@@ -2359,6 +2360,17 @@ public static bool TryStartEngineWithOptions(StartOptions options, FileSystemRun
args.Add(Startup.NO_HTTPS_REDIRECT_FLAG);
}
+ // If MCP stdio was requested, append the stdio-specific switches.
+ if (options.McpStdio)
+ {
+ string effectiveRole = string.IsNullOrWhiteSpace(options.McpRole)
+ ? "anonymous"
+ : options.McpRole;
+
+ args.Add("--mcp-stdio");
+ args.Add(effectiveRole);
+ }
+
return Azure.DataApiBuilder.Service.Program.StartEngine(args.ToArray());
}
diff --git a/src/Cli/Exporter.cs b/src/Cli/Exporter.cs
index 896b485692..e694317cd4 100644
--- a/src/Cli/Exporter.cs
+++ b/src/Cli/Exporter.cs
@@ -110,7 +110,13 @@ private static async Task ExportGraphQL(
}
else
{
- StartOptions startOptions = new(false, LogLevel.None, false, options.Config!);
+ StartOptions startOptions = new(
+ verbose: false,
+ logLevel: LogLevel.None,
+ isHttpsRedirectionDisabled: false,
+ config: options.Config!,
+ mcpStdio: false,
+ mcpRole: null);
Task dabService = Task.Run(() =>
{
diff --git a/src/Config/ObjectModel/AuthenticationOptions.cs b/src/Config/ObjectModel/AuthenticationOptions.cs
index 6750d6e807..a937168493 100644
--- a/src/Config/ObjectModel/AuthenticationOptions.cs
+++ b/src/Config/ObjectModel/AuthenticationOptions.cs
@@ -6,12 +6,12 @@ namespace Azure.DataApiBuilder.Config.ObjectModel;
///
/// Authentication configuration.
///
-/// Identity Provider. Default is StaticWebApps.
+/// Identity Provider. Default is AppService.
/// With EasyAuth and Simulator, no Audience or Issuer are expected.
///
/// Settings enabling validation of the received JWT token.
/// Required only when Provider is other than EasyAuth.
-public record AuthenticationOptions(string Provider = nameof(EasyAuthType.StaticWebApps), JwtOptions? Jwt = null)
+public record AuthenticationOptions(string Provider = nameof(EasyAuthType.AppService), JwtOptions? Jwt = null)
{
public const string SIMULATOR_AUTHENTICATION = "Simulator";
public const string CLIENT_PRINCIPAL_HEADER = "X-MS-CLIENT-PRINCIPAL";
diff --git a/src/Config/ObjectModel/RuntimeConfig.cs b/src/Config/ObjectModel/RuntimeConfig.cs
index 6896d82161..f1ab0d1f10 100644
--- a/src/Config/ObjectModel/RuntimeConfig.cs
+++ b/src/Config/ObjectModel/RuntimeConfig.cs
@@ -98,6 +98,17 @@ Runtime.Host is null ||
Runtime.Host.Authentication is null ||
EasyAuthType.StaticWebApps.ToString().Equals(Runtime.Host.Authentication.Provider, StringComparison.OrdinalIgnoreCase);
+ ///
+ /// A shorthand method to determine whether App Service is configured for the current authentication provider.
+ ///
+ /// True if the authentication provider is enabled for App Service, otherwise false.
+ [JsonIgnore]
+ public bool IsAppServiceIdentityProvider =>
+ Runtime is null ||
+ Runtime.Host is null ||
+ Runtime.Host.Authentication is null ||
+ EasyAuthType.AppService.ToString().Equals(Runtime.Host.Authentication.Provider, StringComparison.OrdinalIgnoreCase);
+
///
/// The path at which Rest APIs are available
///
diff --git a/src/Core/AuthenticationHelpers/ClientRoleHeaderAuthenticationMiddleware.cs b/src/Core/AuthenticationHelpers/ClientRoleHeaderAuthenticationMiddleware.cs
index a233355a7d..c83de9ed3a 100644
--- a/src/Core/AuthenticationHelpers/ClientRoleHeaderAuthenticationMiddleware.cs
+++ b/src/Core/AuthenticationHelpers/ClientRoleHeaderAuthenticationMiddleware.cs
@@ -62,7 +62,7 @@ public async Task InvokeAsync(HttpContext httpContext)
// Determine the authentication scheme to use based on dab-config.json.
// Compatible with both ConfigureAuthentication and ConfigureAuthenticationV2 in startup.cs.
// This means that this code is resilient to whether or not the default authentication scheme is set in startup.
- string scheme = EasyAuthAuthenticationDefaults.SWAAUTHSCHEME;
+ string scheme = EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME;
if (!_runtimeConfigProvider.IsLateConfigured)
{
AuthenticationOptions? dabAuthNOptions = _runtimeConfigProvider.GetConfig().Runtime?.Host?.Authentication;
diff --git a/src/Core/AuthenticationHelpers/EasyAuthAuthenticationBuilderExtensions.cs b/src/Core/AuthenticationHelpers/EasyAuthAuthenticationBuilderExtensions.cs
index cb1d11a149..e4edf72a7c 100644
--- a/src/Core/AuthenticationHelpers/EasyAuthAuthenticationBuilderExtensions.cs
+++ b/src/Core/AuthenticationHelpers/EasyAuthAuthenticationBuilderExtensions.cs
@@ -54,7 +54,8 @@ public static AuthenticationBuilder AddEasyAuthAuthentication(
///
/// Registers the StaticWebApps and AppService EasyAuth authentication schemes.
/// Used for ConfigureAuthenticationV2() where all EasyAuth schemes are registered.
- /// This function doesn't register EasyAuthType.AppService if the AppService environment is not detected.
+ /// AppService authentication is always registered, while StaticWebApps authentication
+ /// is also available and configured here.
///
///
public static AuthenticationBuilder AddEnvDetectedEasyAuth(this AuthenticationBuilder builder)
@@ -64,6 +65,7 @@ public static AuthenticationBuilder AddEnvDetectedEasyAuth(this AuthenticationBu
throw new ArgumentNullException(nameof(builder));
}
+ // Always register Static Web Apps authentication scheme.
builder.AddScheme(
authenticationScheme: EasyAuthAuthenticationDefaults.SWAAUTHSCHEME,
displayName: EasyAuthAuthenticationDefaults.SWAAUTHSCHEME,
@@ -72,20 +74,16 @@ public static AuthenticationBuilder AddEnvDetectedEasyAuth(this AuthenticationBu
options.EasyAuthProvider = EasyAuthType.StaticWebApps;
});
- bool appServiceEnvironmentDetected = AppServiceAuthenticationInfo.AreExpectedAppServiceEnvVarsPresent();
-
- if (appServiceEnvironmentDetected)
- {
- // Loggers not available at this point in startup.
- Console.WriteLine("AppService environment detected, configuring EasyAuth.AppService authentication scheme.");
- builder.AddScheme(
- authenticationScheme: EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME,
- displayName: EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME,
- options =>
- {
- options.EasyAuthProvider = EasyAuthType.AppService;
- });
- }
+ // Always register App Service authentication scheme as well so that
+ // AppService can be treated as the default EasyAuth provider without
+ // relying on environment variable detection.
+ builder.AddScheme(
+ authenticationScheme: EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME,
+ displayName: EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME,
+ options =>
+ {
+ options.EasyAuthProvider = EasyAuthType.AppService;
+ });
return builder;
}
diff --git a/src/Core/Configurations/RuntimeConfigValidator.cs b/src/Core/Configurations/RuntimeConfigValidator.cs
index fd8f811c9e..ec97a48e4c 100644
--- a/src/Core/Configurations/RuntimeConfigValidator.cs
+++ b/src/Core/Configurations/RuntimeConfigValidator.cs
@@ -848,6 +848,14 @@ private void ValidateAuthenticationOptions(RuntimeConfig runtimeConfig)
return;
}
+ // Warn if the configured EasyAuth provider is StaticWebApps (deprecated)
+ if (!string.IsNullOrWhiteSpace(runtimeConfig.Runtime.Host.Authentication.Provider) &&
+ Enum.TryParse(runtimeConfig.Runtime.Host.Authentication.Provider, ignoreCase: true, out EasyAuthType provider) &&
+ provider == EasyAuthType.StaticWebApps)
+ {
+ _logger.LogWarning("The 'StaticWebApps' authentication provider is deprecated.");
+ }
+
bool isAudienceSet = !string.IsNullOrEmpty(runtimeConfig.Runtime.Host.Authentication.Jwt?.Audience);
bool isIssuerSet = !string.IsNullOrEmpty(runtimeConfig.Runtime.Host.Authentication.Jwt?.Issuer);
diff --git a/src/Core/Resolvers/SqlQueryEngine.cs b/src/Core/Resolvers/SqlQueryEngine.cs
index 7b261ecb2b..6523589532 100644
--- a/src/Core/Resolvers/SqlQueryEngine.cs
+++ b/src/Core/Resolvers/SqlQueryEngine.cs
@@ -224,12 +224,18 @@ public JsonElement ResolveObject(JsonElement element, ObjectField fieldSchema, r
parentMetadata = paginationObjectMetadata;
}
- PaginationMetadata currentMetadata = parentMetadata.Subqueries[fieldSchema.Name];
- metadata = currentMetadata;
-
- if (currentMetadata.IsPaginated)
+ // In some scenarios (for example when RBAC removes a relationship
+ // or when multiple sibling nested entities are present), we may not
+ // have pagination metadata for the current field. In those cases we
+ // should simply return the element as-is instead of throwing.
+ if (parentMetadata.Subqueries.TryGetValue(fieldSchema.Name, out PaginationMetadata? currentMetadata))
{
- return SqlPaginationUtil.CreatePaginationConnectionFromJsonElement(element, currentMetadata);
+ metadata = currentMetadata;
+
+ if (currentMetadata.IsPaginated)
+ {
+ return SqlPaginationUtil.CreatePaginationConnectionFromJsonElement(element, currentMetadata);
+ }
}
}
diff --git a/src/Core/Services/ExecutionHelper.cs b/src/Core/Services/ExecutionHelper.cs
index a0a81f02cc..79bdc6af9c 100644
--- a/src/Core/Services/ExecutionHelper.cs
+++ b/src/Core/Services/ExecutionHelper.cs
@@ -4,6 +4,7 @@
using System.Diagnostics;
using System.Globalization;
using System.Net;
+using System.Text;
using System.Text.Json;
using Azure.DataApiBuilder.Config.ObjectModel;
using Azure.DataApiBuilder.Core.Configurations;
@@ -534,7 +535,24 @@ public static InputObjectType InputObjectTypeFromIInputField(IInputValueDefiniti
// /books/items/items[idx]/authors -> Depth: 3 (0-indexed) which maps to the
// pagination metadata for the "authors/items" subquery.
string paginationObjectParentName = GetMetadataKey(context.Path) + "::" + context.Path.Parent.Depth();
- return (IMetadata?)context.ContextData[paginationObjectParentName];
+
+ // For nested list fields under relationships (e.g. reviews.items, authors.items),
+ // include the relationship path suffix so we look up the same key that
+ // SetNewMetadataChildren stored ("::depth::relationshipPath").
+ string relationshipPath = GetRelationshipPathSuffix(context.Path.Parent);
+ if (!string.IsNullOrEmpty(relationshipPath))
+ {
+ paginationObjectParentName = paginationObjectParentName + "::" + relationshipPath;
+ }
+
+ if (context.ContextData.TryGetValue(key: paginationObjectParentName, out object? itemsPaginationMetadata) && itemsPaginationMetadata is not null)
+ {
+ return (IMetadata)itemsPaginationMetadata;
+ }
+
+ // If metadata is missing (e.g. Cosmos DB or pruned relationship), return an empty
+ // pagination metadata object to avoid KeyNotFoundException.
+ return PaginationMetadata.MakeEmptyPaginationMetadata();
}
// This section would be reached when processing a Cosmos query of the form:
@@ -582,7 +600,24 @@ private static IMetadata GetMetadataObjectField(IResolverContext context)
// pagination metadata from context.ContextData
// The PaginationMetadata fetched has subquery metadata for "authors" from path "/books/items/authors"
string objectParentName = GetMetadataKey(context.Path) + "::" + context.Path.Parent.Parent.Depth();
- return (IMetadata)context.ContextData[objectParentName]!;
+
+ // Include relationship path suffix (for example, "addresses" or "phoneNumbers") so
+ // we look up the same key that SetNewMetadataChildren stored
+ // ("::depth::relationshipPath").
+ string relationshipPath = GetRelationshipPathSuffix(context.Path.Parent.Parent);
+ if (!string.IsNullOrEmpty(relationshipPath))
+ {
+ objectParentName = objectParentName + "::" + relationshipPath;
+ }
+
+ if (context.ContextData.TryGetValue(objectParentName, out object? indexerMetadata) && indexerMetadata is not null)
+ {
+ return (IMetadata)indexerMetadata;
+ }
+
+ // If no metadata is present (for example, for non-paginated relationships or when
+ // RBAC prunes a branch), return an empty pagination metadata object.
+ return PaginationMetadata.MakeEmptyPaginationMetadata();
}
if (!context.Path.IsRootField() && ((NamePathSegment)context.Path.Parent).Name != PURE_RESOLVER_CONTEXT_SUFFIX)
@@ -592,12 +627,35 @@ private static IMetadata GetMetadataObjectField(IResolverContext context)
// e.g. metadata for index 4 will not exist. only 3.
// Depth: / 0 / 1 / 2 / 3 / 4
// Path: /books/items/items[0]/publishers/books
+ //
+ // To handle arbitrary nesting depths with sibling relationships, we need to include
+ // the relationship field path in the key. For example:
+ // - /entity/items[0]/rel1/nested uses key ::3::rel1
+ // - /entity/items[0]/rel2/nested uses key ::3::rel2
+ // - /entity/items[0]/rel1/nested/deeper uses key ::4::rel1::nested
+ // - /entity/items[0]/rel1/nested2/deeper uses key ::4::rel1::nested2
string objectParentName = GetMetadataKey(context.Path.Parent) + "::" + context.Path.Parent.Depth();
- return (IMetadata)context.ContextData[objectParentName]!;
+ string relationshipPath = GetRelationshipPathSuffix(context.Path.Parent);
+ if (!string.IsNullOrEmpty(relationshipPath))
+ {
+ objectParentName = objectParentName + "::" + relationshipPath;
+ }
+
+ if (context.ContextData.TryGetValue(objectParentName, out object? nestedMetadata) && nestedMetadata is not null)
+ {
+ return (IMetadata)nestedMetadata;
+ }
+
+ return PaginationMetadata.MakeEmptyPaginationMetadata();
}
string metadataKey = GetMetadataKey(context.Path) + "::" + context.Path.Depth();
- return (IMetadata)context.ContextData[metadataKey]!;
+ if (context.ContextData.TryGetValue(metadataKey, out object? rootMetadata) && rootMetadata is not null)
+ {
+ return (IMetadata)rootMetadata;
+ }
+
+ return PaginationMetadata.MakeEmptyPaginationMetadata();
}
private static string GetMetadataKey(HotChocolate.Path path)
@@ -614,6 +672,50 @@ private static string GetMetadataKey(HotChocolate.Path path)
return GetMetadataKey(path: path.Parent);
}
+ ///
+ /// Builds a suffix representing the relationship path from the IndexerPathSegment (items[n])
+ /// up to (but not including) the current path segment. This is used to create unique metadata
+ /// keys for sibling relationships at any nesting depth.
+ ///
+ /// The path to build the suffix for
+ ///
+ /// A string like "rel1" for /entity/items[0]/rel1,
+ /// or "rel1::nested" for /entity/items[0]/rel1/nested,
+ /// or empty string if no IndexerPathSegment is found in the path ancestry.
+ ///
+ private static string GetRelationshipPathSuffix(HotChocolate.Path path)
+ {
+ List pathParts = new();
+ HotChocolate.Path? current = path;
+
+ // Walk up the path collecting relationship field names until we hit an IndexerPathSegment
+ while (current is not null && !current.IsRoot)
+ {
+ if (current is IndexerPathSegment)
+ {
+ // We've reached items[n], stop here
+ break;
+ }
+
+ if (current is NamePathSegment nameSegment)
+ {
+ pathParts.Add(nameSegment.Name);
+ }
+
+ current = current.Parent;
+ }
+
+ // If we didn't find an IndexerPathSegment, return empty (this handles root-level queries)
+ if (current is not IndexerPathSegment)
+ {
+ return string.Empty;
+ }
+
+ // Reverse because we walked up the tree, but we want the path from root to leaf
+ pathParts.Reverse();
+ return string.Join("::", pathParts);
+ }
+
///
/// Resolves the name of the root object of a selection set to
/// use as the beginning of a key used to index pagination metadata in the
@@ -655,7 +757,25 @@ private static void SetNewMetadataChildren(IResolverContext context, IMetadata?
// When context.Path takes the form: "/entity/items[index]/nestedEntity" HC counts the depth as
// if the path took the form: "/entity/items/items[index]/nestedEntity" -> Depth of "nestedEntity"
// is 3 because depth is 0-indexed.
- string contextKey = GetMetadataKey(context.Path) + "::" + context.Path.Depth();
+ StringBuilder contextKeyBuilder = new();
+ contextKeyBuilder
+ .Append(GetMetadataKey(context.Path))
+ .Append("::")
+ .Append(context.Path.Depth());
+
+ // For relationship fields at any depth, include the relationship path suffix to distinguish
+ // between sibling relationships. This handles arbitrary nesting depths.
+ // e.g., "/entity/items[0]/rel1" gets key ::3::rel1
+ // e.g., "/entity/items[0]/rel1/nested" gets key ::4::rel1::nested
+ string relationshipPath = GetRelationshipPathSuffix(context.Path);
+ if (!string.IsNullOrEmpty(relationshipPath))
+ {
+ contextKeyBuilder
+ .Append("::")
+ .Append(relationshipPath);
+ }
+
+ string contextKey = contextKeyBuilder.ToString();
// It's okay to overwrite the context when we are visiting a different item in items e.g. books/items/items[1]/publishers since
// context for books/items/items[0]/publishers processing is done and that context isn't needed anymore.
diff --git a/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs b/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs
index 4ccf7945d1..644bd338e3 100644
--- a/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs
+++ b/src/Service.Tests/Authentication/Helpers/WebHostBuilderHelper.cs
@@ -75,6 +75,7 @@ public static async Task CreateWebHost(
else
{
EasyAuthType easyAuthProvider = (EasyAuthType)Enum.Parse(typeof(EasyAuthType), provider, ignoreCase: true);
+
services.AddAuthentication()
.AddEasyAuthAuthentication(easyAuthProvider);
}
diff --git a/src/Service.Tests/Caching/CachingConfigProcessingTests.cs b/src/Service.Tests/Caching/CachingConfigProcessingTests.cs
index a6daebf3e4..00729476cd 100644
--- a/src/Service.Tests/Caching/CachingConfigProcessingTests.cs
+++ b/src/Service.Tests/Caching/CachingConfigProcessingTests.cs
@@ -383,7 +383,7 @@ private static string GetRawConfigJson(string globalCacheConfig, string entityCa
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
},
""mode"": ""production""
}" + globalCacheConfig +
diff --git a/src/Service.Tests/Caching/HealthEndpointCachingTests.cs b/src/Service.Tests/Caching/HealthEndpointCachingTests.cs
index fcc3e097e5..664e6070e6 100644
--- a/src/Service.Tests/Caching/HealthEndpointCachingTests.cs
+++ b/src/Service.Tests/Caching/HealthEndpointCachingTests.cs
@@ -148,7 +148,7 @@ private static void CreateCustomConfigFile(Dictionary entityMap,
ConfigurationTests.GetConnectionStringFromEnvironmentConfig(environment: TestCategory.MSSQL),
Options: null,
Health: new(true));
- HostOptions hostOptions = new(Mode: HostMode.Development, Cors: null, Authentication: new() { Provider = nameof(EasyAuthType.StaticWebApps) });
+ HostOptions hostOptions = new(Mode: HostMode.Development, Cors: null, Authentication: new() { Provider = nameof(EasyAuthType.AppService) });
RuntimeConfig runtimeConfig = new(
Schema: string.Empty,
diff --git a/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs b/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs
index 963211ae40..846a34ebee 100644
--- a/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs
+++ b/src/Service.Tests/Configuration/AuthenticationConfigValidatorUnitTests.cs
@@ -38,7 +38,7 @@ public void TestInitialize()
public void ValidateEasyAuthConfig()
{
RuntimeConfig config =
- CreateRuntimeConfigWithOptionalAuthN(new AuthenticationOptions(EasyAuthType.StaticWebApps.ToString(), null));
+ CreateRuntimeConfigWithOptionalAuthN(new AuthenticationOptions(EasyAuthType.AppService.ToString(), null));
_mockFileSystem.AddFile(
FileSystemRuntimeConfigLoader.DEFAULT_CONFIG_FILE_NAME,
diff --git a/src/Service.Tests/Configuration/ConfigurationTests.cs b/src/Service.Tests/Configuration/ConfigurationTests.cs
index 0614e7688f..bd0ce7d1ff 100644
--- a/src/Service.Tests/Configuration/ConfigurationTests.cs
+++ b/src/Service.Tests/Configuration/ConfigurationTests.cs
@@ -50,6 +50,7 @@
using Serilog;
using VerifyMSTest;
using static Azure.DataApiBuilder.Config.FileSystemRuntimeConfigLoader;
+using static Azure.DataApiBuilder.Core.AuthenticationHelpers.AppServiceAuthentication;
using static Azure.DataApiBuilder.Service.Tests.Configuration.ConfigurationEndpoints;
using static Azure.DataApiBuilder.Service.Tests.Configuration.TestConfigFileReader;
@@ -393,7 +394,7 @@ public class ConfigurationTests
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
},
""mode"": ""development""
}
@@ -656,7 +657,7 @@ type Moon {
},
""host"": {
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -1140,10 +1141,21 @@ public async Task TestSqlSettingPostStartupConfigurations(string configurationEn
// Sends a GET request to a protected entity which requires a specific role to access.
// Authorization will pass because proper auth headers are present.
HttpRequestMessage message = new(method: HttpMethod.Get, requestUri: $"api/{POST_STARTUP_CONFIG_ENTITY}");
- string swaTokenPayload = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(
- addAuthenticated: true,
- specificRole: POST_STARTUP_CONFIG_ROLE);
- message.Headers.Add(Config.ObjectModel.AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, swaTokenPayload);
+
+ // Use an AppService EasyAuth principal carrying the required role when
+ // authentication is configured to use AppService.
+ string appServiceTokenPayload = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ roleClaimType: Config.ObjectModel.AuthenticationOptions.ROLE_CLAIM_TYPE,
+ additionalClaims:
+ [
+ new AppServiceClaim
+ {
+ Typ = Config.ObjectModel.AuthenticationOptions.ROLE_CLAIM_TYPE,
+ Val = POST_STARTUP_CONFIG_ROLE
+ }
+ ]);
+
+ message.Headers.Add(Config.ObjectModel.AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, appServiceTokenPayload);
message.Headers.Add(AuthorizationResolver.CLIENT_ROLE_HEADER, POST_STARTUP_CONFIG_ROLE);
HttpResponseMessage authorizedResponse = await httpClient.SendAsync(message);
Assert.AreEqual(expected: HttpStatusCode.OK, actual: authorizedResponse.StatusCode);
@@ -2498,7 +2510,7 @@ public async Task TestRuntimeBaseRouteInNextLinkForPaginatedRestResponse()
{
const string CUSTOM_CONFIG = "custom-config.json";
string runtimeBaseRoute = "/base-route";
- TestHelper.ConstructNewConfigWithSpecifiedHostMode(CUSTOM_CONFIG, HostMode.Production, TestCategory.MSSQL, runtimeBaseRoute: runtimeBaseRoute);
+ TestHelper.ConstructNewConfigWithSpecifiedHostMode(CUSTOM_CONFIG, HostMode.Production, TestCategory.MSSQL, runtimeBaseRoute: runtimeBaseRoute, "StaticWebApps");
string[] args = new[]
{
$"--ConfigFileName={CUSTOM_CONFIG}"
@@ -2673,12 +2685,30 @@ public async Task ValidateErrorMessageForMutationWithoutReadPermission()
$"--ConfigFileName={CUSTOM_CONFIG}"
};
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken();
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken();
using (TestServer server = new(Program.CreateWebHostBuilder(args)))
using (HttpClient client = server.CreateClient())
{
try
{
+ // Pre-clean to avoid PK violation if a previous run left the row behind.
+ string preCleanupDeleteMutation = @"
+ mutation {
+ deleteStock(categoryid: 5001, pieceid: 5001) {
+ categoryid
+ pieceid
+ }
+ }";
+
+ _ = await GraphQLRequestExecutor.PostGraphQLRequestAsync(
+ client,
+ server.Services.GetRequiredService(),
+ query: preCleanupDeleteMutation,
+ queryName: "deleteStock",
+ variables: null,
+ authToken: authToken,
+ clientRoleHeader: AuthorizationResolver.ROLE_AUTHENTICATED);
+
// A create mutation operation is executed in the context of Anonymous role. The Anonymous role has create action configured but lacks
// read action. As a result, a new record should be created in the database but the mutation operation should return an error message.
string graphQLMutation = @"
@@ -2703,7 +2733,8 @@ public async Task ValidateErrorMessageForMutationWithoutReadPermission()
query: graphQLMutation,
queryName: "createStock",
variables: null,
- clientRoleHeader: null
+ authToken: null,
+ clientRoleHeader: AuthorizationResolver.ROLE_ANONYMOUS
);
Assert.IsNotNull(mutationResponse);
@@ -3005,7 +3036,7 @@ public async Task ValidateInheritanceOfReadPermissionFromAnonymous()
query: graphQLMutation,
queryName: "createStock",
variables: null,
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(),
clientRoleHeader: AuthorizationResolver.ROLE_AUTHENTICATED
);
@@ -3572,7 +3603,7 @@ type Planet @model(name:""PlanetAlias"") {
[TestCategory(TestCategory.MSSQL)]
[DataRow(HostMode.Development, EasyAuthType.AppService, false, false, DisplayName = "AppService Dev - No EnvVars - No Error")]
[DataRow(HostMode.Development, EasyAuthType.AppService, true, false, DisplayName = "AppService Dev - EnvVars - No Error")]
- [DataRow(HostMode.Production, EasyAuthType.AppService, false, true, DisplayName = "AppService Prod - No EnvVars - Error")]
+ [DataRow(HostMode.Production, EasyAuthType.AppService, false, false, DisplayName = "AppService Prod - No EnvVars - Error")]
[DataRow(HostMode.Production, EasyAuthType.AppService, true, false, DisplayName = "AppService Prod - EnvVars - Error")]
[DataRow(HostMode.Development, EasyAuthType.StaticWebApps, false, false, DisplayName = "SWA Dev - No EnvVars - No Error")]
[DataRow(HostMode.Development, EasyAuthType.StaticWebApps, true, false, DisplayName = "SWA Dev - EnvVars - No Error")]
@@ -3606,8 +3637,10 @@ public void TestProductionModeAppServiceEnvironmentCheck(HostMode hostMode, Easy
string[] args = new[]
{
$"--ConfigFileName={CUSTOM_CONFIG}"
- };
+ };
+ // When host is in Production mode with AppService as Identity Provider and the environment variables are not set
+ // we do not throw an exception any longer(PR: 2943), instead log a warning to the user. In this case expectError is false.
// This test only checks for startup errors, so no requests are sent to the test server.
try
{
@@ -5260,10 +5293,29 @@ private static JsonContent GetPostStartupConfigParams(string environment, Runtim
/// ServiceUnavailable if service is not successfully hydrated with config
private static async Task HydratePostStartupConfiguration(HttpClient httpClient, JsonContent content, string configurationEndpoint)
{
- // Hydrate configuration post-startup
- HttpResponseMessage postResult =
- await httpClient.PostAsync(configurationEndpoint, content);
- Assert.AreEqual(HttpStatusCode.OK, postResult.StatusCode);
+ string appServiceTokenPayload = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ roleClaimType: Config.ObjectModel.AuthenticationOptions.ROLE_CLAIM_TYPE,
+ additionalClaims:
+ [
+ new AppServiceClaim
+ {
+ Typ = Config.ObjectModel.AuthenticationOptions.ROLE_CLAIM_TYPE,
+ Val = POST_STARTUP_CONFIG_ROLE
+ }
+ ]);
+
+ using HttpRequestMessage postRequest = new(HttpMethod.Post, configurationEndpoint)
+ {
+ Content = content
+ };
+
+ postRequest.Headers.Add(
+ Config.ObjectModel.AuthenticationOptions.CLIENT_PRINCIPAL_HEADER,
+ appServiceTokenPayload);
+
+ HttpResponseMessage postResult = await httpClient.SendAsync(postRequest);
+ string body = await postResult.Content.ReadAsStringAsync();
+ Assert.AreEqual(HttpStatusCode.OK, postResult.StatusCode, body);
return await GetRestResponsePostConfigHydration(httpClient);
}
@@ -5465,7 +5517,7 @@ public static RuntimeConfig InitMinimalRuntimeConfig(
);
entityMap.Add("Publisher", anotherEntity);
- Config.ObjectModel.AuthenticationOptions authenticationOptions = new(Provider: nameof(EasyAuthType.StaticWebApps), null);
+ Config.ObjectModel.AuthenticationOptions authenticationOptions = new(Provider: nameof(EasyAuthType.AppService), null);
return new(
Schema: "IntegrationTestMinimalSchema",
diff --git a/src/Service.Tests/Configuration/HealthEndpointRolesTests.cs b/src/Service.Tests/Configuration/HealthEndpointRolesTests.cs
index 9ad36bfa15..99f3284a8a 100644
--- a/src/Service.Tests/Configuration/HealthEndpointRolesTests.cs
+++ b/src/Service.Tests/Configuration/HealthEndpointRolesTests.cs
@@ -11,6 +11,7 @@
using Azure.DataApiBuilder.Core.Authorization;
using Microsoft.AspNetCore.TestHost;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using static Azure.DataApiBuilder.Core.AuthenticationHelpers.AppServiceAuthentication;
namespace Azure.DataApiBuilder.Service.Tests.Configuration
{
@@ -75,10 +76,20 @@ public async Task ComprehensiveHealthEndpoint_RolesTests(string role, HostMode h
// Sends a GET request to a protected entity which requires a specific role to access.
// Authorization checks
HttpRequestMessage message = new(method: HttpMethod.Get, requestUri: $"/health");
- string swaTokenPayload = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(
- addAuthenticated: true,
- specificRole: STARTUP_CONFIG_ROLE);
- message.Headers.Add(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, swaTokenPayload);
+ string appServiceTokenPayload = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ roleClaimType: AuthenticationOptions.ROLE_CLAIM_TYPE,
+ additionalClaims: !string.IsNullOrEmpty(STARTUP_CONFIG_ROLE)
+ ?
+ [
+ new AppServiceClaim
+ {
+ Typ = AuthenticationOptions.ROLE_CLAIM_TYPE,
+ Val = STARTUP_CONFIG_ROLE
+ }
+ ]
+ : null);
+
+ message.Headers.Add(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER, appServiceTokenPayload);
message.Headers.Add(AuthorizationResolver.CLIENT_ROLE_HEADER, STARTUP_CONFIG_ROLE);
HttpResponseMessage authorizedResponse = await client.SendAsync(message);
@@ -119,7 +130,7 @@ private static void CreateCustomConfigFile(Dictionary entityMap,
ConfigurationTests.GetConnectionStringFromEnvironmentConfig(environment: TestCategory.MSSQL),
Options: null,
Health: new(true));
- HostOptions hostOptions = new(Mode: hostMode, Cors: null, Authentication: new() { Provider = nameof(EasyAuthType.StaticWebApps) });
+ HostOptions hostOptions = new(Mode: hostMode, Cors: null, Authentication: new() { Provider = nameof(EasyAuthType.AppService) });
RuntimeConfig runtimeConfig = new(
Schema: string.Empty,
diff --git a/src/Service.Tests/Configuration/HealthEndpointTests.cs b/src/Service.Tests/Configuration/HealthEndpointTests.cs
index 1eac7416e3..7f84d4fa15 100644
--- a/src/Service.Tests/Configuration/HealthEndpointTests.cs
+++ b/src/Service.Tests/Configuration/HealthEndpointTests.cs
@@ -547,7 +547,7 @@ private static RuntimeConfig CreateRuntimeConfig(Dictionary enti
ConfigurationTests.GetConnectionStringFromEnvironmentConfig(environment: TestCategory.MSSQL),
Options: null,
Health: new(enableDatasourceHealth));
- HostOptions hostOptions = new(Mode: hostMode, Cors: null, Authentication: new() { Provider = nameof(EasyAuthType.StaticWebApps) });
+ HostOptions hostOptions = new(Mode: hostMode, Cors: null, Authentication: new() { Provider = nameof(EasyAuthType.AppService) });
RuntimeConfig runtimeConfig = new(
Schema: string.Empty,
diff --git a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs
index d2ea7708ce..0a5f460759 100644
--- a/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs
+++ b/src/Service.Tests/Configuration/HotReload/ConfigurationHotReloadTests.cs
@@ -90,7 +90,7 @@ private static void GenerateConfigFile(
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
},
""mode"": ""development""
},
diff --git a/src/Service.Tests/CosmosTests/MutationTests.cs b/src/Service.Tests/CosmosTests/MutationTests.cs
index de931dcf22..ec611da59e 100644
--- a/src/Service.Tests/CosmosTests/MutationTests.cs
+++ b/src/Service.Tests/CosmosTests/MutationTests.cs
@@ -6,6 +6,7 @@
using System.Globalization;
using System.IO;
using System.Net.Http;
+using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.DataApiBuilder.Config.NamingPolicies;
@@ -19,6 +20,7 @@
using Microsoft.Azure.Cosmos;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using static Azure.DataApiBuilder.Core.AuthenticationHelpers.AppServiceAuthentication;
namespace Azure.DataApiBuilder.Service.Tests.CosmosTests
{
@@ -278,7 +280,18 @@ public async Task CreateItemWithAuthPermissions(string roleName, string expected
name
}}
}}";
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName);
+ // For App Service, the effective role must be present as a role
+ // claim on the principal (in addition to X-MS-API-ROLE) so that
+ // DAB authZ can evaluate permissions consistently with SWA tests.
+ AppServiceClaim roleClaim = new()
+ {
+ Val = roleName,
+ Typ = ClaimTypes.Role
+ };
+
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ additionalClaims: [roleClaim]);
+
JsonElement response = await ExecuteGraphQLRequestAsync("createPlanetAgain", mutation, variables: new(), authToken: authToken, clientRoleHeader: roleName);
// Validate the result contains the GraphQL authorization error code.
@@ -317,10 +330,21 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected
name
}}
}}";
+ // For App Service, the effective role must be present as a role
+ // claim on the principal (in addition to X-MS-API-ROLE) so that
+ // DAB authZ can evaluate permissions consistently with SWA tests.
+ AppServiceClaim roleClaim = new()
+ {
+ Val = roleName,
+ Typ = ClaimTypes.Role
+ };
+
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ additionalClaims: [roleClaim]);
JsonElement createResponse = await ExecuteGraphQLRequestAsync("createPlanetAgain", createMutation,
variables: new(),
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString()),
+ authToken: authToken,
clientRoleHeader: AuthorizationType.Authenticated.ToString());
// Making sure item is created successfully
@@ -340,7 +364,6 @@ public async Task UpdateItemWithAuthPermissions(string roleName, string expected
name = "new_name"
};
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName);
JsonElement response = await ExecuteGraphQLRequestAsync(
queryName: "updatePlanetAgain",
query: mutation,
@@ -384,9 +407,21 @@ public async Task DeleteItemWithAuthPermissions(string roleName, string expected
}}
}}";
+ // For App Service, the effective role must be present as a role
+ // claim on the principal (in addition to X-MS-API-ROLE) so that
+ // DAB authZ can evaluate permissions consistently with SWA tests.
+ AppServiceClaim roleClaim = new()
+ {
+ Val = roleName,
+ Typ = ClaimTypes.Role
+ };
+
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ additionalClaims: [roleClaim]);
+
JsonElement createResponse = await ExecuteGraphQLRequestAsync("createPlanetAgain", createMutation,
variables: new(),
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString()),
+ authToken: authToken,
clientRoleHeader: AuthorizationType.Authenticated.ToString());
// Making sure item is created successfully
@@ -400,7 +435,6 @@ public async Task DeleteItemWithAuthPermissions(string roleName, string expected
name
}
}";
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName);
JsonElement response = await ExecuteGraphQLRequestAsync(
queryName: "deletePlanetAgain",
query: mutation,
@@ -563,7 +597,7 @@ type Planet @model(name:""Planet"") {
};
string id = Guid.NewGuid().ToString();
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken();
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken();
using (TestServer server = new(Program.CreateWebHostBuilder(args)))
using (HttpClient client = server.CreateClient())
{
@@ -713,7 +747,7 @@ type Planet @model(name:""Planet"") {
query: _createPlanetMutation,
queryName: "createPlanet",
variables: new() { { "item", input } },
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(),
clientRoleHeader: AuthorizationResolver.ROLE_AUTHENTICATED
);
@@ -762,6 +796,7 @@ public async Task CanPatchItemWithoutVariables()
}}
}}";
JsonElement response = await ExecuteGraphQLRequestAsync("patchPlanet", mutation, variables: new());
+
// Validate results
Assert.AreEqual(id, response.GetProperty("id").GetString());
Assert.AreEqual(newName, response.GetProperty("name").GetString());
@@ -906,7 +941,7 @@ public async Task CanPatchNestedItemWithVariables()
public async Task CanPatchMoreThan10AttributesInAnItemWithVariables()
{
string roleName = "anonymous";
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: roleName);
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken();
// Run mutation Add planet;
string id = Guid.NewGuid().ToString();
diff --git a/src/Service.Tests/CosmosTests/QueryFilterTests.cs b/src/Service.Tests/CosmosTests/QueryFilterTests.cs
index 0dac6a1c1c..187b447973 100644
--- a/src/Service.Tests/CosmosTests/QueryFilterTests.cs
+++ b/src/Service.Tests/CosmosTests/QueryFilterTests.cs
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
using System.Collections.Generic;
+using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using Azure.DataApiBuilder.Config.ObjectModel;
@@ -11,6 +12,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
+using static Azure.DataApiBuilder.Core.AuthenticationHelpers.AppServiceAuthentication;
using QueryBuilder = Azure.DataApiBuilder.Service.GraphQLBuilder.Queries.QueryBuilder;
namespace Azure.DataApiBuilder.Service.Tests.CosmosTests
@@ -280,7 +282,7 @@ public async Task TestStringMultiFiltersOnArrayTypeWithOrCondition()
private async Task ExecuteAndValidateResult(string graphQLQueryName, string gqlQuery, string dbQuery, bool ignoreBlankResults = false, Dictionary variables = null)
{
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString());
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken();
JsonElement actual = await ExecuteGraphQLRequestAsync(graphQLQueryName, query: gqlQuery, authToken: authToken, variables: variables);
JsonDocument expected = await ExecuteCosmosRequestAsync(dbQuery, _pageSize, null, _containerName);
ValidateResults(actual.GetProperty("items"), expected.RootElement, ignoreBlankResults);
@@ -918,11 +920,19 @@ public async Task TestQueryFilterFieldAuth_Only_AuthorizedArrayItem()
// Now get the item with item level permission
string clientRoleHeader = "item-level-permission-role";
- // string clientRoleHeader = "authenticated";
+
+ AppServiceClaim roleClaim = new()
+ {
+ Val = clientRoleHeader,
+ Typ = ClaimTypes.Role
+ };
+
+ // For App Service, roles must exist as claims on the principal
+ // (in addition to X-MS-API-ROLE) for DAB authZ to allow the request.
JsonElement actual = await ExecuteGraphQLRequestAsync(
queryName: _graphQLQueryName,
query: gqlQuery,
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(additionalClaims: [roleClaim]),
clientRoleHeader: clientRoleHeader);
string dbQuery = $"SELECT c.id " +
@@ -980,11 +990,22 @@ public async Task TestQueryFilterFieldAuth_UnauthorizedField()
}
}";
string clientRoleHeader = "limited-read-role";
+
+ AppServiceClaim roleClaim = new()
+ {
+ Val = clientRoleHeader,
+ Typ = ClaimTypes.Role
+ };
+
+ // For App Service, roles must exist as claims on the principal
+ // (in addition to X-MS-API-ROLE) for DAB authZ to allow the request.
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(additionalClaims: [roleClaim]);
+
JsonElement response = await ExecuteGraphQLRequestAsync(
queryName: _graphQLQueryName,
query: gqlQuery,
variables: new() { { "name", "test name" } },
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: authToken,
clientRoleHeader: clientRoleHeader);
// Validate the result contains the GraphQL authorization error code.
@@ -1012,7 +1033,7 @@ public async Task TestQueryFilterFieldAuth_AuthorizedWildCard()
queryName: "planets",
query: gqlQuery,
variables: new() { },
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(),
clientRoleHeader: clientRoleHeader);
Assert.AreEqual(response.GetProperty("items")[0].GetProperty("name").ToString(), "Earth");
@@ -1037,7 +1058,7 @@ public async Task TestQueryFilterNestedFieldAuth_AuthorizedNestedField()
}
}";
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: AuthorizationType.Authenticated.ToString());
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken();
JsonElement actual = await ExecuteGraphQLRequestAsync(_graphQLQueryName, query: gqlQuery, authToken: authToken);
Assert.AreEqual(actual.GetProperty("items")[0].GetProperty("earth").GetProperty("id").ToString(), _idList[0]);
}
@@ -1065,11 +1086,22 @@ public async Task TestQueryFilterNestedFieldAuth_UnauthorizedNestedField()
}";
string clientRoleHeader = "limited-read-role";
+
+ AppServiceClaim roleClaim = new()
+ {
+ Val = clientRoleHeader,
+ Typ = ClaimTypes.Role
+ };
+
+ // For App Service, roles must exist as claims on the principal
+ // (in addition to X-MS-API-ROLE) for DAB authZ to allow the request.
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(additionalClaims: [roleClaim]);
+
JsonElement response = await ExecuteGraphQLRequestAsync(
queryName: _graphQLQueryName,
query: gqlQuery,
variables: new() { { "name", "test name" } },
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: authToken,
clientRoleHeader: clientRoleHeader);
// Validate the result contains the GraphQL authorization error code.
@@ -1100,7 +1132,7 @@ public async Task TestQueryFilterNestedArrayFieldAuth_UnauthorizedNestedField()
JsonElement response = await ExecuteGraphQLRequestAsync(
queryName: _graphQLQueryName,
query: gqlQuery,
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(),
clientRoleHeader: clientRoleHeader);
// Validate the result contains the GraphQL authorization error code.
@@ -1131,7 +1163,17 @@ public async Task TestQueryFieldAuthConflictingWithFilterFieldAuth_Unauthorized(
}";
string clientRoleHeader = "limited-read-role";
- string authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader);
+
+ AppServiceClaim roleClaim = new()
+ {
+ Val = clientRoleHeader,
+ Typ = ClaimTypes.Role
+ };
+
+ // For App Service, roles must exist as claims on the principal
+ // (in addition to X-MS-API-ROLE) for DAB authZ to allow the request.
+ // SWA tests passed without this because SWA uses a looser, header-driven role model.
+ string authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(additionalClaims: [roleClaim]);
JsonElement response = await ExecuteGraphQLRequestAsync(_graphQLQueryName,
query: gqlQuery,
authToken: authToken,
@@ -1190,7 +1232,7 @@ public async Task TestQueryFilterFieldAuth_ExcludeTakesPredecence()
queryName: _graphQLQueryName,
query: gqlQuery,
variables: new() { { "name", "test name" } },
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(),
clientRoleHeader: clientRoleHeader);
// Validate the result contains the GraphQL authorization error code.
diff --git a/src/Service.Tests/CosmosTests/QueryTests.cs b/src/Service.Tests/CosmosTests/QueryTests.cs
index 52afa8e788..bfcdb2cf91 100644
--- a/src/Service.Tests/CosmosTests/QueryTests.cs
+++ b/src/Service.Tests/CosmosTests/QueryTests.cs
@@ -105,7 +105,7 @@ public async Task GetWithInvalidAuthorizationPolicyInSchema()
queryName: "invalidAuthModel_by_pk",
query: MoonWithInvalidAuthorizationPolicy,
variables: new() { { "id", id }, { "partitionKeyValue", id } },
- authToken: AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader),
+ authToken: AuthTestHelper.CreateAppServiceEasyAuthToken(),
clientRoleHeader: clientRoleHeader);
// Validate the result contains the GraphQL authorization error code.
diff --git a/src/Service.Tests/ModuleInitializer.cs b/src/Service.Tests/ModuleInitializer.cs
index ba0407ecd5..907c60f652 100644
--- a/src/Service.Tests/ModuleInitializer.cs
+++ b/src/Service.Tests/ModuleInitializer.cs
@@ -77,6 +77,8 @@ public static void Init()
VerifierSettings.IgnoreMember(config => config.McpDmlTools);
// Ignore the IsStaticWebAppsIdentityProvider as that's unimportant from a test standpoint.
VerifierSettings.IgnoreMember(config => config.IsStaticWebAppsIdentityProvider);
+ // Ignore the IsAppServiceIdentityProvider as that's unimportant from a test standpoint.
+ VerifierSettings.IgnoreMember(config => config.IsAppServiceIdentityProvider);
// Ignore the RestPath as that's unimportant from a test standpoint.
VerifierSettings.IgnoreMember(config => config.RestPath);
// Ignore the GraphQLPath as that's unimportant from a test standpoint.
diff --git a/src/Service.Tests/Multidab-config.MsSql.json b/src/Service.Tests/Multidab-config.MsSql.json
index a428c0a27b..b54b629023 100644
--- a/src/Service.Tests/Multidab-config.MsSql.json
+++ b/src/Service.Tests/Multidab-config.MsSql.json
@@ -30,7 +30,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service.Tests/Multidab-config.MySql.json b/src/Service.Tests/Multidab-config.MySql.json
index efd7e7c973..5a9bc4cee0 100644
--- a/src/Service.Tests/Multidab-config.MySql.json
+++ b/src/Service.Tests/Multidab-config.MySql.json
@@ -22,7 +22,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service.Tests/Multidab-config.PostgreSql.json b/src/Service.Tests/Multidab-config.PostgreSql.json
index 106e6d5ac2..0279076273 100644
--- a/src/Service.Tests/Multidab-config.PostgreSql.json
+++ b/src/Service.Tests/Multidab-config.PostgreSql.json
@@ -22,7 +22,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt
index c75d645d13..9279da9d59 100644
--- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt
+++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForCosmos.verified.txt
@@ -45,7 +45,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt
index 52f4035868..35fd562c87 100644
--- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt
+++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMsSql.verified.txt
@@ -49,7 +49,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt
index 6a3a4c226c..1490309ece 100644
--- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt
+++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForMySql.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt
index 4373b266f4..ceba40ae63 100644
--- a/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt
+++ b/src/Service.Tests/Snapshots/ConfigurationTests.TestReadingRuntimeConfigForPostgreSql.verified.txt
@@ -41,7 +41,7 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
},
diff --git a/src/Service.Tests/Snapshots/CorsUnitTests.TestCorsConfigReadCorrectly.verified.txt b/src/Service.Tests/Snapshots/CorsUnitTests.TestCorsConfigReadCorrectly.verified.txt
index d31e71399b..ce6395909b 100644
--- a/src/Service.Tests/Snapshots/CorsUnitTests.TestCorsConfigReadCorrectly.verified.txt
+++ b/src/Service.Tests/Snapshots/CorsUnitTests.TestCorsConfigReadCorrectly.verified.txt
@@ -3,6 +3,6 @@
AllowCredentials: false
},
Authentication: {
- Provider: StaticWebApps
+ Provider: AppService
}
}
\ No newline at end of file
diff --git a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs
index 00930103c7..f51dce0c24 100644
--- a/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs
+++ b/src/Service.Tests/SqlTests/GraphQLQueryTests/MsSqlGraphQLQueryTests.cs
@@ -4,7 +4,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text;
using System.Text.Json;
+using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Azure.DataApiBuilder.Config.ObjectModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -229,6 +231,199 @@ FOR JSON PATH
await InFilterOneToOneJoinQuery(msSqlQuery);
}
+ ///
+ /// Verifies that the nested reviews connection under books correctly paginates
+ /// when there are more than 100 reviews for a single book, while also
+ /// exercising sibling navigation properties (websiteplacement and authors)
+ /// under RBAC in the same request. The first page should contain 100 reviews
+ /// and the endCursor should encode the id of the last review on that page.
+ ///
+ [TestMethod]
+ public async Task NestedReviewsConnection_WithSiblings_PaginatesMoreThanHundredItems()
+ {
+ // Seed > 100 reviews for book id 1. Use a distinct id range so we can
+ // clean up without impacting existing rows used by other tests.
+ StringBuilder sb = new();
+ sb.AppendLine("SET IDENTITY_INSERT reviews ON;");
+ sb.AppendLine("INSERT INTO reviews(id, book_id, content) VALUES");
+
+ for (int id = 2000; id <= 2100; id++)
+ {
+ string line = $" ({id}, 1, 'Bulk review {id}')";
+ if (id < 2100)
+ {
+ line += ",";
+ }
+ else
+ {
+ line += ";";
+ }
+
+ sb.AppendLine(line);
+ }
+
+ sb.AppendLine("SET IDENTITY_INSERT reviews OFF;");
+ string seedReviewsSql = sb.ToString();
+
+ string cleanupReviewsSql = "DELETE FROM reviews WHERE id BETWEEN 2000 AND 2100;";
+
+ try
+ {
+ // Seed additional data for this test only.
+ await _queryExecutor.ExecuteQueryAsync(
+ seedReviewsSql,
+ dataSourceName: string.Empty,
+ parameters: null,
+ dataReaderHandler: null);
+
+ string graphQLQueryName = "books";
+ string graphQLQuery = @"query {
+ books(filter: { id: { eq: 1 } }) {
+ items {
+ id
+ title
+ websiteplacement {
+ price
+ }
+ reviews(first: 100) {
+ items {
+ id
+ }
+ endCursor
+ hasNextPage
+ }
+ authors {
+ items {
+ name
+ }
+ }
+ }
+ }
+ }";
+
+ JsonElement actual = await ExecuteGraphQLRequestAsync(
+ graphQLQuery,
+ graphQLQueryName,
+ isAuthenticated: true,
+ clientRoleHeader: "authenticated");
+
+ JsonElement book = actual.GetProperty("items")[0];
+ JsonElement websiteplacement = book.GetProperty("websiteplacement");
+ JsonElement authorsConnection = book.GetProperty("authors");
+ JsonElement reviewsConnection = book.GetProperty("reviews");
+ JsonElement reviewItems = reviewsConnection.GetProperty("items");
+
+ // First page should contain exactly 100 reviews when more than 100 exist.
+ Assert.AreEqual(100, reviewItems.GetArrayLength(), "Expected first page of reviews to contain 100 items.");
+
+ bool hasNextPage = reviewsConnection.GetProperty("hasNextPage").GetBoolean();
+ Assert.IsTrue(hasNextPage, "Expected hasNextPage to be true when more than 100 reviews exist.");
+
+ string endCursor = reviewsConnection.GetProperty("endCursor").GetString();
+ Assert.IsFalse(string.IsNullOrEmpty(endCursor), "Expected endCursor to be populated when hasNextPage is true.");
+
+ // Decode the opaque cursor and verify it encodes the id of the
+ // last review on the first page.
+ int lastReviewIdOnPage = reviewItems[reviewItems.GetArrayLength() - 1].GetProperty("id").GetInt32();
+
+ string decodedCursorJson = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(endCursor));
+ using JsonDocument cursorDoc = JsonDocument.Parse(decodedCursorJson);
+ JsonElement cursorArray = cursorDoc.RootElement;
+
+ bool foundIdFieldInCursor = false;
+ foreach (JsonElement field in cursorArray.EnumerateArray())
+ {
+ if (field.GetProperty("FieldName").GetString() == "id")
+ {
+ int cursorId = field.GetProperty("FieldValue").GetInt32();
+ Assert.AreEqual(lastReviewIdOnPage, cursorId, "endCursor should encode the id of the last review on the first page.");
+ foundIdFieldInCursor = true;
+ break;
+ }
+ }
+
+ Assert.IsTrue(foundIdFieldInCursor, "endCursor payload should include a pagination field for id.");
+
+ // Also validate that sibling navigation properties under RBAC are
+ // materialized as part of the same query and that their results
+ // match the outcome of equivalent SQL JSON queries.
+ Assert.AreEqual(JsonValueKind.Object, websiteplacement.ValueKind, "Expected websiteplacement object to be materialized.");
+
+ JsonElement authorsItems = authorsConnection.GetProperty("items");
+ Assert.IsTrue(authorsItems.GetArrayLength() > 0, "Expected authors collection to be materialized with at least one author.");
+
+ // Compare the full nested tree (id, title, websiteplacement, reviews.items, authors.items)
+ // against an equivalent SQL JSON query. Shape the SQL JSON to match the GraphQL
+ // "book" object so we can use the actual result directly for comparison.
+ string fullTreeSql = @"
+ SELECT
+ [b].[id] AS [id],
+ [b].[title] AS [title],
+ JSON_QUERY((
+ SELECT TOP 1 [wp].[price] AS [price]
+ FROM [dbo].[book_website_placements] AS [wp]
+ WHERE [wp].[book_id] = [b].[id]
+ ORDER BY [wp].[id] ASC
+ FOR JSON PATH, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER
+ )) AS [websiteplacement],
+ JSON_QUERY((
+ SELECT
+ JSON_QUERY((
+ SELECT TOP 100 [r].[id] AS [id]
+ FROM [dbo].[reviews] AS [r]
+ WHERE [r].[book_id] = [b].[id]
+ ORDER BY [r].[id] ASC
+ FOR JSON PATH, INCLUDE_NULL_VALUES
+ )) AS [items]
+ FOR JSON PATH, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER
+ )) AS [reviews],
+ JSON_QUERY((
+ SELECT
+ JSON_QUERY((
+ SELECT [a].[name] AS [name]
+ FROM [dbo].[authors] AS [a]
+ INNER JOIN [dbo].[book_author_link] AS [bal]
+ ON [bal].[author_id] = [a].[id]
+ WHERE [bal].[book_id] = [b].[id]
+ ORDER BY [a].[id] ASC
+ FOR JSON PATH, INCLUDE_NULL_VALUES
+ )) AS [items]
+ FOR JSON PATH, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER
+ )) AS [authors]
+ FROM [dbo].[books] AS [b]
+ WHERE [b].[id] = 1
+ FOR JSON PATH, INCLUDE_NULL_VALUES, WITHOUT_ARRAY_WRAPPER";
+
+ string expectedFullTreeJson = await GetDatabaseResultAsync(fullTreeSql);
+
+ // Use the actual GraphQL "book" object for comparison, trimming pagination metadata
+ // (endCursor, hasNextPage) that cannot be reproduced via SQL.
+ JsonNode actualBookNode = JsonNode.Parse(book.ToString());
+ if (actualBookNode is JsonObject bookObject &&
+ bookObject["reviews"] is JsonObject reviewsObject)
+ {
+ reviewsObject.Remove("endCursor");
+ reviewsObject.Remove("hasNextPage");
+ }
+
+ string actualComparableJson = actualBookNode.ToJsonString();
+
+ SqlTestHelper.PerformTestEqualJsonStrings(
+ expectedFullTreeJson,
+ actualComparableJson);
+ }
+ finally
+ {
+ // Clean up the seeded reviews so other tests relying on the base
+ // fixture data remain unaffected.
+ await _queryExecutor.ExecuteQueryAsync(
+ cleanupReviewsSql,
+ dataSourceName: string.Empty,
+ parameters: null,
+ dataReaderHandler: null);
+ }
+ }
+
///
/// Test query on One-To-One relationship when the fields defining
/// the relationship in the entity include fields that are mapped in
diff --git a/src/Service.Tests/SqlTests/SqlTestBase.cs b/src/Service.Tests/SqlTests/SqlTestBase.cs
index bb8ed0628d..16e804f117 100644
--- a/src/Service.Tests/SqlTests/SqlTestBase.cs
+++ b/src/Service.Tests/SqlTests/SqlTestBase.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
@@ -36,6 +37,7 @@
using MySqlConnector;
using Npgsql;
using ZiggyCreatures.Caching.Fusion;
+using static Azure.DataApiBuilder.Core.AuthenticationHelpers.AppServiceAuthentication;
namespace Azure.DataApiBuilder.Service.Tests.SqlTests
{
@@ -84,6 +86,7 @@ protected async static Task InitializeTestFixture(
bool isRestBodyStrict = true)
{
TestHelper.SetupDatabaseEnvironment(DatabaseEngine);
+
// Get the base config file from disk
RuntimeConfig runtimeConfig = SqlTestHelper.SetupRuntimeConfig();
@@ -508,9 +511,37 @@ protected static async Task SetupAndRunRestApiTest(
if (clientRoleHeader is not null)
{
- request.Headers.Add(AuthorizationResolver.CLIENT_ROLE_HEADER, clientRoleHeader.ToString());
- request.Headers.Add(AuthenticationOptions.CLIENT_PRINCIPAL_HEADER,
- AuthTestHelper.CreateStaticWebAppsEasyAuthToken(addAuthenticated: true, specificRole: clientRoleHeader));
+ request.Headers.Add(AuthorizationResolver.CLIENT_ROLE_HEADER, clientRoleHeader);
+
+ // Detect runtime auth provider once per call
+ RuntimeConfigProvider configProvider = _application.Services.GetRequiredService();
+ string provider = configProvider.GetConfig().Runtime.Host.Authentication.Provider;
+
+ if (string.Equals(provider, nameof(EasyAuthType.AppService), StringComparison.OrdinalIgnoreCase))
+ {
+ // AppService EasyAuth principal with this role
+ request.Headers.Add(
+ AuthenticationOptions.CLIENT_PRINCIPAL_HEADER,
+ AuthTestHelper.CreateAppServiceEasyAuthToken(
+ roleClaimType: AuthenticationOptions.ROLE_CLAIM_TYPE,
+ additionalClaims:
+ [
+ new AppServiceClaim
+ {
+ Typ = AuthenticationOptions.ROLE_CLAIM_TYPE,
+ Val = clientRoleHeader
+ }
+ ]));
+ }
+ else
+ {
+ // Static Web Apps principal as before
+ request.Headers.Add(
+ AuthenticationOptions.CLIENT_PRINCIPAL_HEADER,
+ AuthTestHelper.CreateStaticWebAppsEasyAuthToken(
+ addAuthenticated: true,
+ specificRole: clientRoleHeader));
+ }
}
// Send request to the engine.
@@ -614,13 +645,43 @@ protected virtual async Task ExecuteGraphQLRequestAsync(
bool expectsError = false)
{
RuntimeConfigProvider configProvider = _application.Services.GetService();
+
+ string authToken = null;
+
+ if (isAuthenticated)
+ {
+ string provider = configProvider.GetConfig().Runtime.Host.Authentication.Provider;
+
+ if (string.Equals(provider, nameof(EasyAuthType.AppService), StringComparison.OrdinalIgnoreCase))
+ {
+ authToken = AuthTestHelper.CreateAppServiceEasyAuthToken(
+ roleClaimType: AuthenticationOptions.ROLE_CLAIM_TYPE,
+ additionalClaims: !string.IsNullOrEmpty(clientRoleHeader)
+ ?
+ [
+ new AppServiceClaim
+ {
+ Typ = AuthenticationOptions.ROLE_CLAIM_TYPE,
+ Val = clientRoleHeader
+ }
+ ]
+ : null);
+ }
+ else
+ {
+ authToken = AuthTestHelper.CreateStaticWebAppsEasyAuthToken(
+ addAuthenticated: true,
+ specificRole: clientRoleHeader);
+ }
+ }
+
return await GraphQLRequestExecutor.PostGraphQLRequestAsync(
HttpClient,
configProvider,
queryName,
query,
variables,
- isAuthenticated ? AuthTestHelper.CreateStaticWebAppsEasyAuthToken(specificRole: clientRoleHeader) : null,
+ authToken,
clientRoleHeader: clientRoleHeader);
}
diff --git a/src/Service.Tests/SqlTests/SqlTestHelper.cs b/src/Service.Tests/SqlTests/SqlTestHelper.cs
index e739f6cc8c..cf65c9a9f5 100644
--- a/src/Service.Tests/SqlTests/SqlTestHelper.cs
+++ b/src/Service.Tests/SqlTests/SqlTestHelper.cs
@@ -381,7 +381,7 @@ public static RuntimeConfig InitBasicRuntimeConfigWithNoEntity(
string testCategory = TestCategory.MSSQL)
{
DataSource dataSource = new(dbType, GetConnectionStringFromEnvironmentConfig(environment: testCategory), new());
- Config.ObjectModel.AuthenticationOptions authenticationOptions = new(Provider: nameof(EasyAuthType.StaticWebApps), null);
+ Config.ObjectModel.AuthenticationOptions authenticationOptions = new(Provider: nameof(EasyAuthType.AppService), null);
RuntimeConfig runtimeConfig = new(
Schema: "IntegrationTestMinimalSchema",
diff --git a/src/Service.Tests/TestHelper.cs b/src/Service.Tests/TestHelper.cs
index b94470b96b..035ee3e6ee 100644
--- a/src/Service.Tests/TestHelper.cs
+++ b/src/Service.Tests/TestHelper.cs
@@ -185,7 +185,7 @@ public static string GenerateInvalidSchema()
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -217,7 +217,7 @@ public static string GenerateInvalidSchema()
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
},
@@ -259,7 +259,7 @@ public static string GenerateInvalidSchema()
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
}
}
}" + "," +
@@ -330,27 +330,39 @@ public static RuntimeConfigProvider GenerateInMemoryRuntimeConfigProvider(Runtim
/// HostMode for the engine
/// Database type
/// Base route for API requests.
- public static void ConstructNewConfigWithSpecifiedHostMode(string configFileName, HostMode hostModeType, string databaseType, string runtimeBaseRoute = "/")
+ /// Provider for authentication
+ public static void ConstructNewConfigWithSpecifiedHostMode(
+ string configFileName,
+ HostMode hostModeType,
+ string databaseType,
+ string runtimeBaseRoute = "/",
+ string provider = "AppService")
{
SetupDatabaseEnvironment(databaseType);
RuntimeConfigProvider configProvider = GetRuntimeConfigProvider(GetRuntimeConfigLoader());
RuntimeConfig config = configProvider.GetConfig();
+ AuthenticationOptions auth = config.Runtime?.Host?.Authentication with { Provider = provider };
+
+ bool isStaticWebApps = string.Equals(provider, "StaticWebApps", StringComparison.OrdinalIgnoreCase);
+
RuntimeConfig configWithCustomHostMode =
- config
- with
+ config with
{
- Runtime = config.Runtime
- with
+ Runtime = config.Runtime with
{
- Host = config.Runtime?.Host
- with
- { Mode = hostModeType },
- BaseRoute = runtimeBaseRoute
+ Host = config.Runtime?.Host with
+ {
+ Mode = hostModeType,
+ // For tests that explicitly set SWA, we’ll keep BaseRoute.
+ // For others (AppService), BaseRoute will be null.
+ Authentication = auth
+ },
+ BaseRoute = isStaticWebApps ? runtimeBaseRoute : null
}
};
- File.WriteAllText(configFileName, configWithCustomHostMode.ToJson());
+ File.WriteAllText(configFileName, configWithCustomHostMode.ToJson());
}
///
diff --git a/src/Service.Tests/UnitTests/ConfigFileWatcherUnitTests.cs b/src/Service.Tests/UnitTests/ConfigFileWatcherUnitTests.cs
index 4807fcfe6f..b0ae580828 100644
--- a/src/Service.Tests/UnitTests/ConfigFileWatcherUnitTests.cs
+++ b/src/Service.Tests/UnitTests/ConfigFileWatcherUnitTests.cs
@@ -54,7 +54,7 @@ HostMode mode
""allow-credentials"": false
},
""authentication"": {
- ""provider"": ""StaticWebApps""
+ ""provider"": ""AppService""
},
""mode"": """ + mode + @"""
}
diff --git a/src/Service.Tests/UnitTests/RuntimeConfigLoaderJsonDeserializerTests.cs b/src/Service.Tests/UnitTests/RuntimeConfigLoaderJsonDeserializerTests.cs
index 8329dc2134..3f56b85901 100644
--- a/src/Service.Tests/UnitTests/RuntimeConfigLoaderJsonDeserializerTests.cs
+++ b/src/Service.Tests/UnitTests/RuntimeConfigLoaderJsonDeserializerTests.cs
@@ -656,7 +656,7 @@ private static bool TryParseAndAssertOnDefaults(string json, out RuntimeConfig p
Assert.AreEqual(McpRuntimeOptions.DEFAULT_PATH, parsedConfig.McpPath);
Assert.IsTrue(parsedConfig.AllowIntrospection);
Assert.IsFalse(parsedConfig.IsDevelopmentMode());
- Assert.IsTrue(parsedConfig.IsStaticWebAppsIdentityProvider);
+ Assert.IsTrue(parsedConfig.IsAppServiceIdentityProvider);
Assert.IsTrue(parsedConfig.IsRequestBodyStrict);
Assert.IsTrue(parsedConfig.IsLogLevelNull());
Assert.IsTrue(parsedConfig.Runtime?.Telemetry?.ApplicationInsights is null
diff --git a/src/Service.Tests/dab-config.CosmosDb_NoSql.json b/src/Service.Tests/dab-config.CosmosDb_NoSql.json
index 5704dc19be..26f2e3fc3c 100644
--- a/src/Service.Tests/dab-config.CosmosDb_NoSql.json
+++ b/src/Service.Tests/dab-config.CosmosDb_NoSql.json
@@ -28,7 +28,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
},
diff --git a/src/Service.Tests/dab-config.DwSql.json b/src/Service.Tests/dab-config.DwSql.json
index 78f9e91480..bb0d6a5893 100644
--- a/src/Service.Tests/dab-config.DwSql.json
+++ b/src/Service.Tests/dab-config.DwSql.json
@@ -26,7 +26,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service.Tests/dab-config.MsSql.json b/src/Service.Tests/dab-config.MsSql.json
index d5e903d4f3..e7f73702ba 100644
--- a/src/Service.Tests/dab-config.MsSql.json
+++ b/src/Service.Tests/dab-config.MsSql.json
@@ -36,7 +36,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service.Tests/dab-config.MySql.json b/src/Service.Tests/dab-config.MySql.json
index a0b36b0388..c08069a5c8 100644
--- a/src/Service.Tests/dab-config.MySql.json
+++ b/src/Service.Tests/dab-config.MySql.json
@@ -24,7 +24,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service.Tests/dab-config.PostgreSql.json b/src/Service.Tests/dab-config.PostgreSql.json
index e9a8ddf5ab..48f9700754 100644
--- a/src/Service.Tests/dab-config.PostgreSql.json
+++ b/src/Service.Tests/dab-config.PostgreSql.json
@@ -24,7 +24,7 @@
"allow-credentials": false
},
"authentication": {
- "provider": "StaticWebApps"
+ "provider": "AppService"
},
"mode": "development"
}
diff --git a/src/Service/Program.cs b/src/Service/Program.cs
index 1059fd52ff..e23fb98cd9 100644
--- a/src/Service/Program.cs
+++ b/src/Service/Program.cs
@@ -5,16 +5,19 @@
using System.CommandLine;
using System.CommandLine.Parsing;
using System.Runtime.InteropServices;
+using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Azure.DataApiBuilder.Config;
using Azure.DataApiBuilder.Service.Exceptions;
using Azure.DataApiBuilder.Service.Telemetry;
+using Azure.DataApiBuilder.Service.Utilities;
using Microsoft.ApplicationInsights;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.ApplicationInsights;
@@ -33,6 +36,14 @@ public class Program
public static void Main(string[] args)
{
+ bool runMcpStdio = McpStdioHelper.ShouldRunMcpStdio(args, out string? mcpRole);
+
+ if (runMcpStdio)
+ {
+ Console.OutputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
+ Console.InputEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
+ }
+
if (!ValidateAspNetCoreUrls())
{
Console.Error.WriteLine("Invalid ASPNETCORE_URLS format. e.g.: ASPNETCORE_URLS=\"http://localhost:5000;https://localhost:5001\"");
@@ -40,20 +51,26 @@ public static void Main(string[] args)
return;
}
- if (!StartEngine(args))
+ if (!StartEngine(args, runMcpStdio, mcpRole))
{
Environment.ExitCode = -1;
}
}
- public static bool StartEngine(string[] args)
+ public static bool StartEngine(string[] args, bool runMcpStdio, string? mcpRole)
{
- // Unable to use ILogger because this code is invoked before LoggerFactory
- // is instantiated.
Console.WriteLine("Starting the runtime engine...");
try
{
- CreateHostBuilder(args).Build().Run();
+ IHost host = CreateHostBuilder(args, runMcpStdio, mcpRole).Build();
+
+ if (runMcpStdio)
+ {
+ return McpStdioHelper.RunMcpStdioHost(host);
+ }
+
+ // Normal web mode
+ host.Run();
return true;
}
// Catch exception raised by explicit call to IHostApplicationLifetime.StopApplication()
@@ -72,17 +89,28 @@ public static bool StartEngine(string[] args)
}
}
- public static IHostBuilder CreateHostBuilder(string[] args)
+ // Compatibility overload used by external callers that do not pass the runMcpStdio flag.
+ public static bool StartEngine(string[] args)
+ {
+ bool runMcpStdio = McpStdioHelper.ShouldRunMcpStdio(args, out string? mcpRole);
+ return StartEngine(args, runMcpStdio, mcpRole: mcpRole);
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args, bool runMcpStdio, string? mcpRole)
{
return Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder =>
{
AddConfigurationProviders(builder, args);
+ if (runMcpStdio)
+ {
+ McpStdioHelper.ConfigureMcpStdio(builder, mcpRole);
+ }
})
.ConfigureWebHostDefaults(webBuilder =>
{
Startup.MinimumLogLevel = GetLogLevelFromCommandLineArgs(args, out Startup.IsLogLevelOverriddenByCli);
- ILoggerFactory loggerFactory = GetLoggerFactoryForLogLevel(Startup.MinimumLogLevel);
+ ILoggerFactory loggerFactory = GetLoggerFactoryForLogLevel(Startup.MinimumLogLevel, stdio: runMcpStdio);
ILogger startupLogger = loggerFactory.CreateLogger();
DisableHttpsRedirectionIfNeeded(args);
webBuilder.UseStartup(builder => new Startup(builder.Configuration, startupLogger));
@@ -140,7 +168,14 @@ private static ParseResult GetParseResult(Command cmd, string[] args)
/// Telemetry client
/// Hot-reloadable log level
/// Core Serilog logging pipeline
- public static ILoggerFactory GetLoggerFactoryForLogLevel(LogLevel logLevel, TelemetryClient? appTelemetryClient = null, LogLevelInitializer? logLevelInitializer = null, Logger? serilogLogger = null)
+ /// Whether the logger is for stdio mode
+ /// ILoggerFactory
+ public static ILoggerFactory GetLoggerFactoryForLogLevel(
+ LogLevel logLevel,
+ TelemetryClient? appTelemetryClient = null,
+ LogLevelInitializer? logLevelInitializer = null,
+ Logger? serilogLogger = null,
+ bool stdio = false)
{
return LoggerFactory
.Create(builder =>
@@ -229,7 +264,19 @@ public static ILoggerFactory GetLoggerFactoryForLogLevel(LogLevel logLevel, Tele
}
}
- builder.AddConsole();
+ // In stdio mode, route console logs to STDERR to keep STDOUT clean for MCP JSON
+ if (stdio)
+ {
+ builder.ClearProviders();
+ builder.AddConsole(options =>
+ {
+ options.LogToStandardErrorThreshold = LogLevel.Trace;
+ });
+ }
+ else
+ {
+ builder.AddConsole();
+ }
});
}
diff --git a/src/Service/Startup.cs b/src/Service/Startup.cs
index 48a39d31d0..333bf57234 100644
--- a/src/Service/Startup.cs
+++ b/src/Service/Startup.cs
@@ -348,7 +348,16 @@ public void ConfigureServices(IServiceCollection services)
return handler;
});
- if (runtimeConfig is not null && runtimeConfig.Runtime?.Host?.Mode is HostMode.Development)
+ bool isMcpStdio = Configuration.GetValue("MCP:StdioMode");
+
+ if (isMcpStdio)
+ {
+ // Explicitly force Simulator when running in MCP stdio mode.
+ services.AddAuthentication(
+ defaultScheme: SimulatorAuthenticationDefaults.AUTHENTICATIONSCHEME)
+ .AddSimulatorAuthentication();
+ }
+ else if (runtimeConfig is not null && runtimeConfig.Runtime?.Host?.Mode is HostMode.Development)
{
// Development mode implies support for "Hot Reload". The V2 authentication function
// wires up all DAB supported authentication providers (schemes) so that at request time,
@@ -456,6 +465,8 @@ public void ConfigureServices(IServiceCollection services)
services.AddDabMcpServer(configProvider);
+ services.AddSingleton();
+
services.AddControllers();
}
@@ -785,21 +796,18 @@ private void ConfigureAuthentication(IServiceCollection services, RuntimeConfigP
if (easyAuthType == EasyAuthType.AppService && !appServiceEnvironmentDetected)
{
- if (isProductionMode)
- {
- throw new DataApiBuilderException(
- message: AppServiceAuthenticationInfo.APPSERVICE_PROD_MISSING_ENV_CONFIG,
- statusCode: System.Net.HttpStatusCode.ServiceUnavailable,
- subStatusCode: DataApiBuilderException.SubStatusCodes.ErrorInInitialization);
- }
- else
- {
- _logger.LogWarning(AppServiceAuthenticationInfo.APPSERVICE_DEV_MISSING_ENV_CONFIG);
- }
+ _logger.LogWarning(AppServiceAuthenticationInfo.APPSERVICE_DEV_MISSING_ENV_CONFIG);
}
- services.AddAuthentication(EasyAuthAuthenticationDefaults.AUTHENTICATIONSCHEME)
- .AddEasyAuthAuthentication(easyAuthAuthenticationProvider: easyAuthType);
+ string defaultScheme = easyAuthType == EasyAuthType.AppService
+ ? EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME
+ : EasyAuthAuthenticationDefaults.SWAAUTHSCHEME;
+
+ services.AddAuthentication(defaultScheme)
+ .AddEnvDetectedEasyAuth();
+
+ _logger.LogInformation("Registered EasyAuth scheme: {Scheme}", defaultScheme);
+
}
else if (mode == HostMode.Development && authOptions.IsAuthenticationSimulatorEnabled())
{
@@ -820,7 +828,7 @@ private void ConfigureAuthentication(IServiceCollection services, RuntimeConfigP
{
// Sets EasyAuth as the default authentication scheme when runtime configuration
// is not present.
- SetStaticWebAppsAuthentication(services);
+ SetAppServiceAuthentication(services);
}
}
@@ -1012,13 +1020,13 @@ private void ConfigureFileSink(IApplicationBuilder app, RuntimeConfig runtimeCon
}
///
- /// Sets Static Web Apps EasyAuth as the authentication scheme for the engine.
+ /// Sets App Service EasyAuth as the authentication scheme for the engine.
///
/// The service collection where authentication services are added.
- private static void SetStaticWebAppsAuthentication(IServiceCollection services)
+ private static void SetAppServiceAuthentication(IServiceCollection services)
{
- services.AddAuthentication(EasyAuthAuthenticationDefaults.AUTHENTICATIONSCHEME)
- .AddEasyAuthAuthentication(EasyAuthType.StaticWebApps);
+ services.AddAuthentication(EasyAuthAuthenticationDefaults.APPSERVICEAUTHSCHEME)
+ .AddEnvDetectedEasyAuth();
}
///
diff --git a/src/Service/Utilities/McpStdioHelper.cs b/src/Service/Utilities/McpStdioHelper.cs
new file mode 100644
index 0000000000..043e9dd85d
--- /dev/null
+++ b/src/Service/Utilities/McpStdioHelper.cs
@@ -0,0 +1,102 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace Azure.DataApiBuilder.Service.Utilities
+{
+ ///
+ /// Helper methods for configuring and running MCP in stdio mode.
+ ///
+ internal static class McpStdioHelper
+ {
+ ///
+ /// Determines if MCP stdio mode should be run based on command line arguments.
+ ///
+ /// The command line arguments.
+ /// The role for MCP stdio mode. When this method returns true, the role defaults to anonymous.
+ /// True when MCP stdio mode should be enabled; otherwise false.
+ public static bool ShouldRunMcpStdio(string[] args, [NotNullWhen(true)] out string? mcpRole)
+ {
+ mcpRole = null;
+
+ bool runMcpStdio = Array.Exists(
+ args,
+ a => string.Equals(a, "--mcp-stdio", StringComparison.OrdinalIgnoreCase));
+
+ if (!runMcpStdio)
+ {
+ return false;
+ }
+
+ string? roleArg = Array.Find(
+ args,
+ a => a != null && a.StartsWith("role:", StringComparison.OrdinalIgnoreCase));
+
+ if (!string.IsNullOrEmpty(roleArg))
+ {
+ string roleValue = roleArg[(roleArg.IndexOf(':') + 1)..];
+ if (!string.IsNullOrWhiteSpace(roleValue))
+ {
+ mcpRole = roleValue;
+ }
+ }
+
+ // Ensure that when MCP stdio is enabled, mcpRole is always non-null.
+ // This matches the NotNullWhen(true) contract and avoids nullable warnings
+ // for callers while still allowing an implicit default when no role is provided.
+ mcpRole ??= "anonymous";
+
+ return true;
+ }
+
+ ///
+ /// Configures the IConfigurationBuilder for MCP stdio mode.
+ ///
+ ///
+ ///
+ public static void ConfigureMcpStdio(IConfigurationBuilder builder, string? mcpRole)
+ {
+ builder.AddInMemoryCollection(new Dictionary
+ {
+ ["MCP:StdioMode"] = "true",
+ ["MCP:Role"] = mcpRole ?? "anonymous",
+ ["Runtime:Host:Authentication:Provider"] = "Simulator"
+ });
+ }
+
+ ///
+ /// Runs the MCP stdio host.
+ ///
+ /// The host to run.
+ public static bool RunMcpStdioHost(IHost host)
+ {
+ host.Start();
+
+ Mcp.Core.McpToolRegistry registry =
+ host.Services.GetRequiredService();
+ IEnumerable tools =
+ host.Services.GetServices();
+
+ foreach (Mcp.Model.IMcpTool tool in tools)
+ {
+ registry.RegisterTool(tool);
+ }
+
+ IHostApplicationLifetime lifetime =
+ host.Services.GetRequiredService();
+ Mcp.Core.IMcpStdioServer stdio =
+ host.Services.GetRequiredService();
+
+ stdio.RunAsync(lifetime.ApplicationStopping).GetAwaiter().GetResult();
+ host.StopAsync().GetAwaiter().GetResult();
+
+ return true;
+ }
+ }
+}