diff --git a/sdk/synapse/synapse-access-control-rest/package.json b/sdk/synapse/synapse-access-control-rest/package.json index 2fa2553f2bfb..69b659f2dcef 100644 --- a/sdk/synapse/synapse-access-control-rest/package.json +++ b/sdk/synapse/synapse-access-control-rest/package.json @@ -9,7 +9,6 @@ "dependencies": { "@azure-rest/core-client": "^2.3.1", "@azure/core-auth": "^1.9.0", - "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.18.0", "tslib": "^2.8.1" }, @@ -38,6 +37,7 @@ "module": "./dist/esm/index.js", "types": "./dist/commonjs/index.d.ts", "devDependencies": { + "@azure/logger": "^1.0.0", "@azure-tools/test-credential": "^2.0.0", "@azure-tools/test-recorder": "^4.1.0", "@azure-tools/test-utils-vitest": "^1.0.0", diff --git a/sdk/synapse/synapse-access-control-rest/review/synapse-access-control.api.md b/sdk/synapse/synapse-access-control-rest/review/synapse-access-control.api.md index 690e64f72c3d..1933dd4d539e 100644 --- a/sdk/synapse/synapse-access-control-rest/review/synapse-access-control.api.md +++ b/sdk/synapse/synapse-access-control-rest/review/synapse-access-control.api.md @@ -7,7 +7,6 @@ import type { Client } from '@azure-rest/core-client'; import type { ClientOptions } from '@azure-rest/core-client'; import type { HttpResponse } from '@azure-rest/core-client'; -import type { PagedAsyncIterableIterator } from '@azure/core-paging'; import type { PathUncheckedResponse } from '@azure-rest/core-client'; import type { RawHttpHeaders } from '@azure/core-rest-pipeline'; import type { RawHttpHeadersInput } from '@azure/core-rest-pipeline'; @@ -20,81 +19,98 @@ export type AccessControlRestClient = Client & { path: Routes; }; -// @public (undocumented) +// @public +export interface AccessControlRestClientOptions extends ClientOptions { + apiVersion?: string; +} + +// @public export interface CheckAccessDecisionOutput { accessDecision?: string; actionId?: string; roleAssignment?: RoleAssignmentDetailsOutput; } -// @public (undocumented) +// @public export interface CheckPrincipalAccessRequest { actions: Array; scope: string; subject: SubjectInfo; } -// @public (undocumented) +// @public export interface CheckPrincipalAccessResponseOutput { AccessDecisions?: Array; } -// @public (undocumented) -function createClient(endpoint: string, credentials: TokenCredential, options?: ClientOptions): AccessControlRestClient; +// @public +function createClient(endpoint: string, credentials: TokenCredential, { apiVersion, ...options }?: AccessControlRestClientOptions): AccessControlRestClient; export default createClient; -// @public (undocumented) +// @public export interface ErrorAdditionalInfoOutput { - info?: Record; - type?: string; + readonly info?: Record; + readonly type?: string; } -// @public (undocumented) +// @public export interface ErrorContractOutput { error?: ErrorResponseOutput; } -// @public (undocumented) +// @public export interface ErrorResponseOutput { - additionalInfo?: Array; - code?: string; - details?: Array; - message?: string; - target?: string; + readonly additionalInfo?: Array; + readonly code?: string; + readonly details?: Array; + readonly message?: string; + readonly target?: string; } // @public export type GetArrayType = T extends Array ? TData : never; // @public -export type GetPage = (pageLink: string, maxPageSize?: number) => Promise<{ +export type GetPage = (pageLink: string) => Promise<{ page: TPage; nextPageLink?: string; }>; // @public (undocumented) -export function isUnexpected(response: RoleAssignmentsCheckPrincipalAccess200Response | RoleAssignmentsCheckPrincipalAccessdefaultResponse): response is RoleAssignmentsCheckPrincipalAccessdefaultResponse; +export function isUnexpected(response: RoleAssignmentsCheckPrincipalAccess200Response | RoleAssignmentsCheckPrincipalAccessDefaultResponse): response is RoleAssignmentsCheckPrincipalAccessDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleAssignmentsListRoleAssignments200Response | RoleAssignmentsListRoleAssignmentsdefaultResponse): response is RoleAssignmentsListRoleAssignmentsdefaultResponse; +export function isUnexpected(response: RoleAssignmentsListRoleAssignments200Response | RoleAssignmentsListRoleAssignmentsDefaultResponse): response is RoleAssignmentsListRoleAssignmentsDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleAssignmentsCreateRoleAssignment200Response | RoleAssignmentsCreateRoleAssignmentdefaultResponse): response is RoleAssignmentsCreateRoleAssignmentdefaultResponse; +export function isUnexpected(response: RoleAssignmentsCreateRoleAssignment200Response | RoleAssignmentsCreateRoleAssignmentDefaultResponse): response is RoleAssignmentsCreateRoleAssignmentDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleAssignmentsGetRoleAssignmentById200Response | RoleAssignmentsGetRoleAssignmentByIddefaultResponse): response is RoleAssignmentsGetRoleAssignmentByIddefaultResponse; +export function isUnexpected(response: RoleAssignmentsGetRoleAssignmentById200Response | RoleAssignmentsGetRoleAssignmentByIdDefaultResponse): response is RoleAssignmentsGetRoleAssignmentByIdDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleAssignmentsDeleteRoleAssignmentById200Response | RoleAssignmentsDeleteRoleAssignmentById204Response | RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse): response is RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse; +export function isUnexpected(response: RoleAssignmentsDeleteRoleAssignmentById200Response | RoleAssignmentsDeleteRoleAssignmentById204Response | RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse): response is RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleDefinitionsListRoleDefinitions200Response | RoleDefinitionsListRoleDefinitionsdefaultResponse): response is RoleDefinitionsListRoleDefinitionsdefaultResponse; +export function isUnexpected(response: RoleDefinitionsListRoleDefinitions200Response | RoleDefinitionsListRoleDefinitionsDefaultResponse): response is RoleDefinitionsListRoleDefinitionsDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleDefinitionsGetRoleDefinitionById200Response | RoleDefinitionsGetRoleDefinitionByIddefaultResponse): response is RoleDefinitionsGetRoleDefinitionByIddefaultResponse; +export function isUnexpected(response: RoleDefinitionsGetRoleDefinitionById200Response | RoleDefinitionsGetRoleDefinitionByIdDefaultResponse): response is RoleDefinitionsGetRoleDefinitionByIdDefaultResponse; // @public (undocumented) -export function isUnexpected(response: RoleDefinitionsListScopes200Response | RoleDefinitionsListScopesdefaultResponse): response is RoleDefinitionsListScopesdefaultResponse; +export function isUnexpected(response: RoleDefinitionsListScopes200Response | RoleDefinitionsListScopesDefaultResponse): response is RoleDefinitionsListScopesDefaultResponse; + +// @public +export interface PagedAsyncIterableIterator { + [Symbol.asyncIterator](): PagedAsyncIterableIterator; + byPage: (settings?: TPageSettings) => AsyncIterableIterator; + next(): Promise>; +} + +// @public +export interface PageSettings { + continuationToken?: string; +} // @public export function paginate(client: Client, initialResponse: TResponse, options?: PagingOptions): PagedAsyncIterableIterator>; @@ -111,19 +127,19 @@ export interface PagingOptions { customGetPage?: GetPage[]>; } -// @public (undocumented) +// @public export interface RequiredAction { id: string; isDataAction: boolean; } -// @public (undocumented) +// @public export interface RoleAssignmentDetailsListOutput { count?: number; value?: Array; } -// @public (undocumented) +// @public export interface RoleAssignmentDetailsOutput { id?: string; principalId?: string; @@ -132,7 +148,7 @@ export interface RoleAssignmentDetailsOutput { scope?: string; } -// @public (undocumented) +// @public export interface RoleAssignmentRequest { principalId: string; principalType?: string; @@ -142,7 +158,7 @@ export interface RoleAssignmentRequest { // @public (undocumented) export interface RoleAssignmentsCheckPrincipalAccess { - post(options: RoleAssignmentsCheckPrincipalAccessParameters): StreamableMethod; + post(options: RoleAssignmentsCheckPrincipalAccessParameters): StreamableMethod; } // @public @@ -159,7 +175,7 @@ export interface RoleAssignmentsCheckPrincipalAccessBodyParam { } // @public -export interface RoleAssignmentsCheckPrincipalAccessdefaultResponse extends HttpResponse { +export interface RoleAssignmentsCheckPrincipalAccessDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -176,9 +192,9 @@ export type RoleAssignmentsCheckPrincipalAccessParameters = RoleAssignmentsCheck // @public (undocumented) export interface RoleAssignmentsCreateRoleAssignment { - delete(options?: RoleAssignmentsDeleteRoleAssignmentByIdParameters): StreamableMethod; - get(options?: RoleAssignmentsGetRoleAssignmentByIdParameters): StreamableMethod; - put(options: RoleAssignmentsCreateRoleAssignmentParameters): StreamableMethod; + delete(options?: RoleAssignmentsDeleteRoleAssignmentByIdParameters): StreamableMethod; + get(options?: RoleAssignmentsGetRoleAssignmentByIdParameters): StreamableMethod; + put(options: RoleAssignmentsCreateRoleAssignmentParameters): StreamableMethod; } // @public @@ -195,7 +211,7 @@ export interface RoleAssignmentsCreateRoleAssignmentBodyParam { } // @public -export interface RoleAssignmentsCreateRoleAssignmentdefaultResponse extends HttpResponse { +export interface RoleAssignmentsCreateRoleAssignmentDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -212,22 +228,18 @@ export type RoleAssignmentsCreateRoleAssignmentParameters = RoleAssignmentsCreat // @public export interface RoleAssignmentsDeleteRoleAssignmentById200Response extends HttpResponse { - // (undocumented) - body: Record; // (undocumented) status: "200"; } // @public export interface RoleAssignmentsDeleteRoleAssignmentById204Response extends HttpResponse { - // (undocumented) - body: Record; // (undocumented) status: "204"; } // @public -export interface RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse extends HttpResponse { +export interface RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -257,7 +269,7 @@ export interface RoleAssignmentsGetRoleAssignmentById200Response extends HttpRes } // @public -export interface RoleAssignmentsGetRoleAssignmentByIddefaultResponse extends HttpResponse { +export interface RoleAssignmentsGetRoleAssignmentByIdDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -269,7 +281,7 @@ export type RoleAssignmentsGetRoleAssignmentByIdParameters = RequestParameters; // @public (undocumented) export interface RoleAssignmentsListRoleAssignments { - get(options?: RoleAssignmentsListRoleAssignmentsParameters): StreamableMethod; + get(options?: RoleAssignmentsListRoleAssignmentsParameters): StreamableMethod; } // @public (undocumented) @@ -288,7 +300,7 @@ export interface RoleAssignmentsListRoleAssignments200Response extends HttpRespo } // @public -export interface RoleAssignmentsListRoleAssignmentsdefaultResponse extends HttpResponse { +export interface RoleAssignmentsListRoleAssignmentsDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -298,7 +310,7 @@ export interface RoleAssignmentsListRoleAssignmentsdefaultResponse extends HttpR // @public (undocumented) export interface RoleAssignmentsListRoleAssignmentsHeaderParam { // (undocumented) - headers: RawHttpHeadersInput & RoleAssignmentsListRoleAssignmentsHeaders; + headers?: RawHttpHeadersInput & RoleAssignmentsListRoleAssignmentsHeaders; } // @public (undocumented) @@ -324,7 +336,7 @@ export interface RoleAssignmentsListRoleAssignmentsQueryParamProperties { // @public (undocumented) export interface RoleDefinitionsGetRoleDefinitionById { - get(options?: RoleDefinitionsGetRoleDefinitionByIdParameters): StreamableMethod; + get(options?: RoleDefinitionsGetRoleDefinitionByIdParameters): StreamableMethod; } // @public @@ -336,7 +348,7 @@ export interface RoleDefinitionsGetRoleDefinitionById200Response extends HttpRes } // @public -export interface RoleDefinitionsGetRoleDefinitionByIddefaultResponse extends HttpResponse { +export interface RoleDefinitionsGetRoleDefinitionByIdDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -348,7 +360,7 @@ export type RoleDefinitionsGetRoleDefinitionByIdParameters = RequestParameters; // @public (undocumented) export interface RoleDefinitionsListRoleDefinitions { - get(options?: RoleDefinitionsListRoleDefinitionsParameters): StreamableMethod; + get(options?: RoleDefinitionsListRoleDefinitionsParameters): StreamableMethod; } // @public @@ -360,7 +372,7 @@ export interface RoleDefinitionsListRoleDefinitions200Response extends HttpRespo } // @public -export interface RoleDefinitionsListRoleDefinitionsdefaultResponse extends HttpResponse { +export interface RoleDefinitionsListRoleDefinitionsDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -384,7 +396,7 @@ export interface RoleDefinitionsListRoleDefinitionsQueryParamProperties { // @public (undocumented) export interface RoleDefinitionsListScopes { - get(options?: RoleDefinitionsListScopesParameters): StreamableMethod; + get(options?: RoleDefinitionsListScopesParameters): StreamableMethod; } // @public @@ -396,7 +408,7 @@ export interface RoleDefinitionsListScopes200Response extends HttpResponse { } // @public -export interface RoleDefinitionsListScopesdefaultResponse extends HttpResponse { +export interface RoleDefinitionsListScopesDefaultResponse extends HttpResponse { // (undocumented) body: ErrorContractOutput; // (undocumented) @@ -416,13 +428,13 @@ export interface Routes { (path: "/rbacScopes"): RoleDefinitionsListScopes; } -// @public (undocumented) +// @public export interface SubjectInfo { groupIds?: Array; principalId: string; } -// @public (undocumented) +// @public export interface SynapseRbacPermissionOutput { actions?: Array; dataActions?: Array; @@ -430,7 +442,7 @@ export interface SynapseRbacPermissionOutput { notDataActions?: Array; } -// @public (undocumented) +// @public export interface SynapseRoleDefinitionOutput { availabilityStatus?: string; description?: string; diff --git a/sdk/synapse/synapse-access-control-rest/src/accessControlRestClient.ts b/sdk/synapse/synapse-access-control-rest/src/accessControlRestClient.ts index f8fa6dd1a298..37282528d509 100644 --- a/sdk/synapse/synapse-access-control-rest/src/accessControlRestClient.ts +++ b/sdk/synapse/synapse-access-control-rest/src/accessControlRestClient.ts @@ -3,23 +3,28 @@ import type { ClientOptions } from "@azure-rest/core-client"; import { getClient } from "@azure-rest/core-client"; +import { logger } from "./logger.js"; import type { TokenCredential } from "@azure/core-auth"; import type { AccessControlRestClient } from "./clientDefinitions.js"; +/** The optional parameters for the client */ +export interface AccessControlRestClientOptions extends ClientOptions { + /** The api version option of the client */ + apiVersion?: string; +} + +/** + * Initialize a new instance of `AccessControlRestClient` + * @param endpoint - The workspace development endpoint, for example `https://myworkspace.dev.azuresynapse.net`. + * @param credentials - uniquely identify client credential + * @param options - the parameter for all optional parameters + */ export default function createClient( endpoint: string, credentials: TokenCredential, - options: ClientOptions = {}, + { apiVersion = "2020-12-01", ...options }: AccessControlRestClientOptions = {}, ): AccessControlRestClient { - const baseUrl = options.baseUrl ?? `${endpoint}`; - options.apiVersion = options.apiVersion ?? "2020-12-01"; - options = { - ...options, - credentials: { - scopes: ["https://dev.azuresynapse.net/.default"], - }, - }; - + const endpointUrl = options.endpoint ?? options.baseUrl ?? `${endpoint}`; const userAgentInfo = `azsdk-js-synapse-access-control-rest/1.0.0-beta.1`; const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix @@ -30,9 +35,31 @@ export default function createClient( userAgentOptions: { userAgentPrefix, }, + loggingOptions: { + logger: options.loggingOptions?.logger ?? logger.info, + }, + credentials: { + scopes: options.credentials?.scopes ?? ["https://dev.azuresynapse.net/.default"], + }, }; + const client = getClient(endpointUrl, credentials, options) as AccessControlRestClient; + + client.pipeline.removePolicy({ name: "ApiVersionPolicy" }); + client.pipeline.addPolicy({ + name: "ClientApiVersionPolicy", + sendRequest: (req, next) => { + // Use the apiVersion defined in request url directly + // Append one if there is no apiVersion and we have one at client options + const url = new URL(req.url); + if (!url.searchParams.get("api-version") && apiVersion) { + req.url = `${req.url}${ + Array.from(url.searchParams.keys()).length > 0 ? "&" : "?" + }api-version=${apiVersion}`; + } - const client = getClient(baseUrl, credentials, options) as AccessControlRestClient; + return next(req); + }, + }); return client; } diff --git a/sdk/synapse/synapse-access-control-rest/src/clientDefinitions.ts b/sdk/synapse/synapse-access-control-rest/src/clientDefinitions.ts index 38f1a15c0cc1..e985ef7d4be6 100644 --- a/sdk/synapse/synapse-access-control-rest/src/clientDefinitions.ts +++ b/sdk/synapse/synapse-access-control-rest/src/clientDefinitions.ts @@ -13,22 +13,22 @@ import type { } from "./parameters.js"; import type { RoleAssignmentsCheckPrincipalAccess200Response, - RoleAssignmentsCheckPrincipalAccessdefaultResponse, + RoleAssignmentsCheckPrincipalAccessDefaultResponse, RoleAssignmentsListRoleAssignments200Response, - RoleAssignmentsListRoleAssignmentsdefaultResponse, + RoleAssignmentsListRoleAssignmentsDefaultResponse, RoleAssignmentsCreateRoleAssignment200Response, - RoleAssignmentsCreateRoleAssignmentdefaultResponse, + RoleAssignmentsCreateRoleAssignmentDefaultResponse, RoleAssignmentsGetRoleAssignmentById200Response, - RoleAssignmentsGetRoleAssignmentByIddefaultResponse, + RoleAssignmentsGetRoleAssignmentByIdDefaultResponse, RoleAssignmentsDeleteRoleAssignmentById200Response, RoleAssignmentsDeleteRoleAssignmentById204Response, - RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse, + RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse, RoleDefinitionsListRoleDefinitions200Response, - RoleDefinitionsListRoleDefinitionsdefaultResponse, + RoleDefinitionsListRoleDefinitionsDefaultResponse, RoleDefinitionsGetRoleDefinitionById200Response, - RoleDefinitionsGetRoleDefinitionByIddefaultResponse, + RoleDefinitionsGetRoleDefinitionByIdDefaultResponse, RoleDefinitionsListScopes200Response, - RoleDefinitionsListScopesdefaultResponse, + RoleDefinitionsListScopesDefaultResponse, } from "./responses.js"; import type { Client, StreamableMethod } from "@azure-rest/core-client"; @@ -38,7 +38,7 @@ export interface RoleAssignmentsCheckPrincipalAccess { options: RoleAssignmentsCheckPrincipalAccessParameters, ): StreamableMethod< | RoleAssignmentsCheckPrincipalAccess200Response - | RoleAssignmentsCheckPrincipalAccessdefaultResponse + | RoleAssignmentsCheckPrincipalAccessDefaultResponse >; } @@ -48,7 +48,7 @@ export interface RoleAssignmentsListRoleAssignments { options?: RoleAssignmentsListRoleAssignmentsParameters, ): StreamableMethod< | RoleAssignmentsListRoleAssignments200Response - | RoleAssignmentsListRoleAssignmentsdefaultResponse + | RoleAssignmentsListRoleAssignmentsDefaultResponse >; } @@ -58,14 +58,14 @@ export interface RoleAssignmentsCreateRoleAssignment { options: RoleAssignmentsCreateRoleAssignmentParameters, ): StreamableMethod< | RoleAssignmentsCreateRoleAssignment200Response - | RoleAssignmentsCreateRoleAssignmentdefaultResponse + | RoleAssignmentsCreateRoleAssignmentDefaultResponse >; /** Get role assignment by role assignment Id. */ get( options?: RoleAssignmentsGetRoleAssignmentByIdParameters, ): StreamableMethod< | RoleAssignmentsGetRoleAssignmentById200Response - | RoleAssignmentsGetRoleAssignmentByIddefaultResponse + | RoleAssignmentsGetRoleAssignmentByIdDefaultResponse >; /** Delete role assignment by role assignment Id. */ delete( @@ -73,7 +73,7 @@ export interface RoleAssignmentsCreateRoleAssignment { ): StreamableMethod< | RoleAssignmentsDeleteRoleAssignmentById200Response | RoleAssignmentsDeleteRoleAssignmentById204Response - | RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse + | RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse >; } @@ -83,7 +83,7 @@ export interface RoleDefinitionsListRoleDefinitions { options?: RoleDefinitionsListRoleDefinitionsParameters, ): StreamableMethod< | RoleDefinitionsListRoleDefinitions200Response - | RoleDefinitionsListRoleDefinitionsdefaultResponse + | RoleDefinitionsListRoleDefinitionsDefaultResponse >; } @@ -93,7 +93,7 @@ export interface RoleDefinitionsGetRoleDefinitionById { options?: RoleDefinitionsGetRoleDefinitionByIdParameters, ): StreamableMethod< | RoleDefinitionsGetRoleDefinitionById200Response - | RoleDefinitionsGetRoleDefinitionByIddefaultResponse + | RoleDefinitionsGetRoleDefinitionByIdDefaultResponse >; } @@ -102,7 +102,7 @@ export interface RoleDefinitionsListScopes { get( options?: RoleDefinitionsListScopesParameters, ): StreamableMethod< - RoleDefinitionsListScopes200Response | RoleDefinitionsListScopesdefaultResponse + RoleDefinitionsListScopes200Response | RoleDefinitionsListScopesDefaultResponse >; } diff --git a/sdk/synapse/synapse-access-control-rest/src/isUnexpected.ts b/sdk/synapse/synapse-access-control-rest/src/isUnexpected.ts index 66f2af8faba0..7ee00ecd446a 100644 --- a/sdk/synapse/synapse-access-control-rest/src/isUnexpected.ts +++ b/sdk/synapse/synapse-access-control-rest/src/isUnexpected.ts @@ -3,22 +3,22 @@ import type { RoleAssignmentsCheckPrincipalAccess200Response, - RoleAssignmentsCheckPrincipalAccessdefaultResponse, + RoleAssignmentsCheckPrincipalAccessDefaultResponse, RoleAssignmentsListRoleAssignments200Response, - RoleAssignmentsListRoleAssignmentsdefaultResponse, + RoleAssignmentsListRoleAssignmentsDefaultResponse, RoleAssignmentsCreateRoleAssignment200Response, - RoleAssignmentsCreateRoleAssignmentdefaultResponse, + RoleAssignmentsCreateRoleAssignmentDefaultResponse, RoleAssignmentsGetRoleAssignmentById200Response, - RoleAssignmentsGetRoleAssignmentByIddefaultResponse, + RoleAssignmentsGetRoleAssignmentByIdDefaultResponse, RoleAssignmentsDeleteRoleAssignmentById200Response, RoleAssignmentsDeleteRoleAssignmentById204Response, - RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse, + RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse, RoleDefinitionsListRoleDefinitions200Response, - RoleDefinitionsListRoleDefinitionsdefaultResponse, + RoleDefinitionsListRoleDefinitionsDefaultResponse, RoleDefinitionsGetRoleDefinitionById200Response, - RoleDefinitionsGetRoleDefinitionByIddefaultResponse, + RoleDefinitionsGetRoleDefinitionByIdDefaultResponse, RoleDefinitionsListScopes200Response, - RoleDefinitionsListScopesdefaultResponse, + RoleDefinitionsListScopesDefaultResponse, } from "./responses.js"; const responseMap: Record = { @@ -35,128 +35,139 @@ const responseMap: Record = { export function isUnexpected( response: | RoleAssignmentsCheckPrincipalAccess200Response - | RoleAssignmentsCheckPrincipalAccessdefaultResponse, -): response is RoleAssignmentsCheckPrincipalAccessdefaultResponse; + | RoleAssignmentsCheckPrincipalAccessDefaultResponse, +): response is RoleAssignmentsCheckPrincipalAccessDefaultResponse; export function isUnexpected( response: | RoleAssignmentsListRoleAssignments200Response - | RoleAssignmentsListRoleAssignmentsdefaultResponse, -): response is RoleAssignmentsListRoleAssignmentsdefaultResponse; + | RoleAssignmentsListRoleAssignmentsDefaultResponse, +): response is RoleAssignmentsListRoleAssignmentsDefaultResponse; export function isUnexpected( response: | RoleAssignmentsCreateRoleAssignment200Response - | RoleAssignmentsCreateRoleAssignmentdefaultResponse, -): response is RoleAssignmentsCreateRoleAssignmentdefaultResponse; + | RoleAssignmentsCreateRoleAssignmentDefaultResponse, +): response is RoleAssignmentsCreateRoleAssignmentDefaultResponse; export function isUnexpected( response: | RoleAssignmentsGetRoleAssignmentById200Response - | RoleAssignmentsGetRoleAssignmentByIddefaultResponse, -): response is RoleAssignmentsGetRoleAssignmentByIddefaultResponse; + | RoleAssignmentsGetRoleAssignmentByIdDefaultResponse, +): response is RoleAssignmentsGetRoleAssignmentByIdDefaultResponse; export function isUnexpected( response: | RoleAssignmentsDeleteRoleAssignmentById200Response | RoleAssignmentsDeleteRoleAssignmentById204Response - | RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse, -): response is RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse; + | RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse, +): response is RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse; export function isUnexpected( response: | RoleDefinitionsListRoleDefinitions200Response - | RoleDefinitionsListRoleDefinitionsdefaultResponse, -): response is RoleDefinitionsListRoleDefinitionsdefaultResponse; + | RoleDefinitionsListRoleDefinitionsDefaultResponse, +): response is RoleDefinitionsListRoleDefinitionsDefaultResponse; export function isUnexpected( response: | RoleDefinitionsGetRoleDefinitionById200Response - | RoleDefinitionsGetRoleDefinitionByIddefaultResponse, -): response is RoleDefinitionsGetRoleDefinitionByIddefaultResponse; + | RoleDefinitionsGetRoleDefinitionByIdDefaultResponse, +): response is RoleDefinitionsGetRoleDefinitionByIdDefaultResponse; export function isUnexpected( - response: RoleDefinitionsListScopes200Response | RoleDefinitionsListScopesdefaultResponse, -): response is RoleDefinitionsListScopesdefaultResponse; + response: RoleDefinitionsListScopes200Response | RoleDefinitionsListScopesDefaultResponse, +): response is RoleDefinitionsListScopesDefaultResponse; export function isUnexpected( response: | RoleAssignmentsCheckPrincipalAccess200Response - | RoleAssignmentsCheckPrincipalAccessdefaultResponse + | RoleAssignmentsCheckPrincipalAccessDefaultResponse | RoleAssignmentsListRoleAssignments200Response - | RoleAssignmentsListRoleAssignmentsdefaultResponse + | RoleAssignmentsListRoleAssignmentsDefaultResponse | RoleAssignmentsCreateRoleAssignment200Response - | RoleAssignmentsCreateRoleAssignmentdefaultResponse + | RoleAssignmentsCreateRoleAssignmentDefaultResponse | RoleAssignmentsGetRoleAssignmentById200Response - | RoleAssignmentsGetRoleAssignmentByIddefaultResponse + | RoleAssignmentsGetRoleAssignmentByIdDefaultResponse | RoleAssignmentsDeleteRoleAssignmentById200Response | RoleAssignmentsDeleteRoleAssignmentById204Response - | RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse + | RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse | RoleDefinitionsListRoleDefinitions200Response - | RoleDefinitionsListRoleDefinitionsdefaultResponse + | RoleDefinitionsListRoleDefinitionsDefaultResponse | RoleDefinitionsGetRoleDefinitionById200Response - | RoleDefinitionsGetRoleDefinitionByIddefaultResponse + | RoleDefinitionsGetRoleDefinitionByIdDefaultResponse | RoleDefinitionsListScopes200Response - | RoleDefinitionsListScopesdefaultResponse, + | RoleDefinitionsListScopesDefaultResponse, ): response is - | RoleAssignmentsCheckPrincipalAccessdefaultResponse - | RoleAssignmentsListRoleAssignmentsdefaultResponse - | RoleAssignmentsCreateRoleAssignmentdefaultResponse - | RoleAssignmentsGetRoleAssignmentByIddefaultResponse - | RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse - | RoleDefinitionsListRoleDefinitionsdefaultResponse - | RoleDefinitionsGetRoleDefinitionByIddefaultResponse - | RoleDefinitionsListScopesdefaultResponse { + | RoleAssignmentsCheckPrincipalAccessDefaultResponse + | RoleAssignmentsListRoleAssignmentsDefaultResponse + | RoleAssignmentsCreateRoleAssignmentDefaultResponse + | RoleAssignmentsGetRoleAssignmentByIdDefaultResponse + | RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse + | RoleDefinitionsListRoleDefinitionsDefaultResponse + | RoleDefinitionsGetRoleDefinitionByIdDefaultResponse + | RoleDefinitionsListScopesDefaultResponse { const lroOriginal = response.headers["x-ms-original-url"]; const url = new URL(lroOriginal ?? response.request.url); const method = response.request.method; let pathDetails = responseMap[`${method} ${url.pathname}`]; if (!pathDetails) { - pathDetails = geParametrizedPathSuccess(url.pathname); + pathDetails = getParametrizedPathSuccess(method, url.pathname); } return !pathDetails.includes(response.status); } -function geParametrizedPathSuccess(path: string): string[] { +function getParametrizedPathSuccess(method: string, path: string): string[] { const pathParts = path.split("/"); + // Traverse list to match the longest candidate + // matchedLen: the length of candidate path + // matchedValue: the matched status code array + let matchedLen = -1, + matchedValue: string[] = []; + // Iterate the responseMap to find a match for (const [key, value] of Object.entries(responseMap)) { // Extracting the path from the map key which is in format // GET /path/foo + if (!key.startsWith(method)) { + continue; + } const candidatePath = getPathFromMapKey(key); // Get each part of the url path const candidateParts = candidatePath.split("/"); - // If the candidate and actual paths don't match in size - // we move on to the next candidate path - if (candidateParts.length === pathParts.length && hasParametrizedPath(key)) { - // track if we have found a match to return the values found. - let found = true; - for (let i = 0; i < candidateParts.length; i++) { - if (candidateParts[i].startsWith("{") && candidateParts[i].endsWith("}")) { - // If the current part of the candidate is a "template" part - // it is a match with the actual path part on hand - // skip as the parameterized part can match anything - continue; - } + // track if we have found a match to return the values found. + let found = true; + for (let i = candidateParts.length - 1, j = pathParts.length - 1; i >= 1 && j >= 1; i--, j--) { + if (candidateParts[i]?.startsWith("{") && candidateParts[i]?.indexOf("}") !== -1) { + const start = candidateParts[i]!.indexOf("}") + 1, + end = candidateParts[i]?.length; + // If the current part of the candidate is a "template" part + // Try to use the suffix of pattern to match the path + // {guid} ==> $ + // {guid}:export ==> :export$ + const isMatched = new RegExp(`${candidateParts[i]?.slice(start, end)}`).test( + pathParts[j] || "", + ); - // If the candidate part is not a template and - // the parts don't match mark the candidate as not found - // to move on with the next candidate path. - if (candidateParts[i] !== pathParts[i]) { + if (!isMatched) { found = false; break; } + continue; } - // We finished evaluating the current candidate parts - // if all parts matched we return the success values form - // the path mapping. - if (found) { - return value; + // If the candidate part is not a template and + // the parts don't match mark the candidate as not found + // to move on with the next candidate path. + if (candidateParts[i] !== pathParts[j]) { + found = false; + break; } } - } - // No match was found, return an empty array. - return []; -} + // We finished evaluating the current candidate parts + // Update the matched value if and only if we found the longer pattern + if (found && candidatePath.length > matchedLen) { + matchedLen = candidatePath.length; + matchedValue = value; + } + } -function hasParametrizedPath(path: string): boolean { - return path.includes("/{"); + return matchedValue; } function getPathFromMapKey(mapKey: string): string { diff --git a/sdk/synapse/synapse-access-control-rest/src/logger.ts b/sdk/synapse/synapse-access-control-rest/src/logger.ts new file mode 100644 index 000000000000..5c572f53d29d --- /dev/null +++ b/sdk/synapse/synapse-access-control-rest/src/logger.ts @@ -0,0 +1,5 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { createClientLogger } from "@azure/logger"; +export const logger = createClientLogger("synapse-access-control"); diff --git a/sdk/synapse/synapse-access-control-rest/src/models.ts b/sdk/synapse/synapse-access-control-rest/src/models.ts index 45913da2f0ad..a4c5f4c77803 100644 --- a/sdk/synapse/synapse-access-control-rest/src/models.ts +++ b/sdk/synapse/synapse-access-control-rest/src/models.ts @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +/** Check access request details */ export interface CheckPrincipalAccessRequest { /** Subject details */ subject: SubjectInfo; @@ -10,6 +11,7 @@ export interface CheckPrincipalAccessRequest { scope: string; } +/** Subject details */ export interface SubjectInfo { /** * Principal Id @@ -21,6 +23,7 @@ export interface SubjectInfo { groupIds?: Array; } +/** Action Info */ export interface RequiredAction { /** Action Id. */ id: string; @@ -28,6 +31,7 @@ export interface RequiredAction { isDataAction: boolean; } +/** Role Assignment request details */ export interface RoleAssignmentRequest { /** * Role ID of the Synapse Built-In Role diff --git a/sdk/synapse/synapse-access-control-rest/src/outputModels.ts b/sdk/synapse/synapse-access-control-rest/src/outputModels.ts index 9487b94ed1f7..954a7e97a5e0 100644 --- a/sdk/synapse/synapse-access-control-rest/src/outputModels.ts +++ b/sdk/synapse/synapse-access-control-rest/src/outputModels.ts @@ -1,11 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +/** Check access response details */ export interface CheckPrincipalAccessResponseOutput { /** To check if the current user, group, or service principal has permission to read artifacts in the specified workspace. */ AccessDecisions?: Array; } +/** Check access response details */ export interface CheckAccessDecisionOutput { /** Access Decision. */ accessDecision?: string; @@ -15,6 +17,7 @@ export interface CheckAccessDecisionOutput { roleAssignment?: RoleAssignmentDetailsOutput; } +/** Role Assignment response details */ export interface RoleAssignmentDetailsOutput { /** Role Assignment ID */ id?: string; @@ -36,31 +39,35 @@ export interface RoleAssignmentDetailsOutput { principalType?: string; } +/** Contains details when the response code indicates an error. */ export interface ErrorContractOutput { /** The error details. */ error?: ErrorResponseOutput; } +/** Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.) */ export interface ErrorResponseOutput { /** The error code. */ - code?: string; + readonly code?: string; /** The error message. */ - message?: string; + readonly message?: string; /** The error target. */ - target?: string; + readonly target?: string; /** The error details. */ - details?: Array; + readonly details?: Array; /** The error additional info. */ - additionalInfo?: Array; + readonly additionalInfo?: Array; } +/** The resource management error additional info. */ export interface ErrorAdditionalInfoOutput { /** The additional info type. */ - type?: string; + readonly type?: string; /** The additional info. */ - info?: Record; + readonly info?: Record; } +/** Role Assignment response details */ export interface RoleAssignmentDetailsListOutput { /** Number of role assignments */ count?: number; @@ -68,6 +75,7 @@ export interface RoleAssignmentDetailsListOutput { value?: Array; } +/** Synapse role definition details */ export interface SynapseRoleDefinitionOutput { /** * Role Definition ID @@ -89,6 +97,7 @@ export interface SynapseRoleDefinitionOutput { availabilityStatus?: string; } +/** Synapse role definition details */ export interface SynapseRbacPermissionOutput { /** List of actions */ actions?: Array; diff --git a/sdk/synapse/synapse-access-control-rest/src/paginateHelper.ts b/sdk/synapse/synapse-access-control-rest/src/paginateHelper.ts index 5d541b4e406d..9ea946d9d6c5 100644 --- a/sdk/synapse/synapse-access-control-rest/src/paginateHelper.ts +++ b/sdk/synapse/synapse-access-control-rest/src/paginateHelper.ts @@ -1,11 +1,148 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import type { PagedAsyncIterableIterator, PagedResult } from "@azure/core-paging"; -import { getPagedAsyncIterator } from "@azure/core-paging"; import type { Client, PathUncheckedResponse } from "@azure-rest/core-client"; import { createRestError } from "@azure-rest/core-client"; +/** + * returns an async iterator that iterates over results. It also has a `byPage` + * method that returns pages of items at once. + * + * @param pagedResult - an object that specifies how to get pages. + * @returns a paged async iterator that iterates over results. + */ +function getPagedAsyncIterator< + TElement, + TPage = TElement[], + TPageSettings = PageSettings, + TLink = string, +>( + pagedResult: PagedResult, +): PagedAsyncIterableIterator { + const iter = getItemAsyncIterator(pagedResult); + return { + next() { + return iter.next(); + }, + [Symbol.asyncIterator]() { + return this; + }, + byPage: + pagedResult?.byPage ?? + (((settings?: PageSettings) => { + const { continuationToken } = settings ?? {}; + return getPageAsyncIterator(pagedResult, { + pageLink: continuationToken as unknown as TLink | undefined, + }); + }) as unknown as (settings?: TPageSettings) => AsyncIterableIterator), + }; +} + +async function* getItemAsyncIterator( + pagedResult: PagedResult, +): AsyncIterableIterator { + const pages = getPageAsyncIterator(pagedResult); + const firstVal = await pages.next(); + // if the result does not have an array shape, i.e. TPage = TElement, then we return it as is + if (!Array.isArray(firstVal.value)) { + // can extract elements from this page + const { toElements } = pagedResult; + if (toElements) { + yield* toElements(firstVal.value) as TElement[]; + for await (const page of pages) { + yield* toElements(page) as TElement[]; + } + } else { + yield firstVal.value; + // `pages` is of type `AsyncIterableIterator` but TPage = TElement in this case + yield* pages as unknown as AsyncIterableIterator; + } + } else { + yield* firstVal.value; + for await (const page of pages) { + // pages is of type `AsyncIterableIterator` so `page` is of type `TPage`. In this branch, + // it must be the case that `TPage = TElement[]` + yield* page as unknown as TElement[]; + } + } +} + +async function* getPageAsyncIterator( + pagedResult: PagedResult, + options: { + pageLink?: TLink; + } = {}, +): AsyncIterableIterator { + const { pageLink } = options; + let response = await pagedResult.getPage(pageLink ?? pagedResult.firstPageLink); + if (!response) { + return; + } + yield response.page; + while (response.nextPageLink) { + response = await pagedResult.getPage(response.nextPageLink); + if (!response) { + return; + } + yield response.page; + } +} + +/** + * An interface that tracks the settings for paged iteration + */ +export interface PageSettings { + /** + * The token that keeps track of where to continue the iterator + */ + continuationToken?: string; +} + +/** + * An interface that allows async iterable iteration both to completion and by page. + */ +export interface PagedAsyncIterableIterator< + TElement, + TPage = TElement[], + TPageSettings = PageSettings, +> { + /** + * The next method, part of the iteration protocol + */ + next(): Promise>; + /** + * The connection to the async iterator, part of the iteration protocol + */ + [Symbol.asyncIterator](): PagedAsyncIterableIterator; + /** + * Return an AsyncIterableIterator that works a page at a time + */ + byPage: (settings?: TPageSettings) => AsyncIterableIterator; +} + +/** + * An interface that describes how to communicate with the service. + */ +interface PagedResult { + /** + * Link to the first page of results. + */ + firstPageLink: TLink; + /** + * A method that returns a page of results. + */ + getPage: (pageLink: TLink) => Promise<{ page: TPage; nextPageLink?: TLink } | undefined>; + /** + * a function to implement the `byPage` method on the paged async iterator. + */ + byPage?: (settings?: TPageSettings) => AsyncIterableIterator; + + /** + * A function to extract elements from a page. + */ + toElements?: (page: TPage) => unknown[]; +} + /** * Helper type to extract the type of an array */ @@ -14,10 +151,7 @@ export type GetArrayType = T extends Array ? TData : never; /** * The type of a custom function that defines how to get a page and a link to the next one if any. */ -export type GetPage = ( - pageLink: string, - maxPageSize?: number, -) => Promise<{ +export type GetPage = (pageLink: string) => Promise<{ page: TPage; nextPageLink?: string; }>; diff --git a/sdk/synapse/synapse-access-control-rest/src/parameters.ts b/sdk/synapse/synapse-access-control-rest/src/parameters.ts index 7f30b1cadc57..9adf277b7364 100644 --- a/sdk/synapse/synapse-access-control-rest/src/parameters.ts +++ b/sdk/synapse/synapse-access-control-rest/src/parameters.ts @@ -39,7 +39,7 @@ export interface RoleAssignmentsListRoleAssignmentsQueryParam { } export interface RoleAssignmentsListRoleAssignmentsHeaderParam { - headers: RawHttpHeadersInput & RoleAssignmentsListRoleAssignmentsHeaders; + headers?: RawHttpHeadersInput & RoleAssignmentsListRoleAssignmentsHeaders; } export type RoleAssignmentsListRoleAssignmentsParameters = diff --git a/sdk/synapse/synapse-access-control-rest/src/responses.ts b/sdk/synapse/synapse-access-control-rest/src/responses.ts index f680b135933d..f206577d545f 100644 --- a/sdk/synapse/synapse-access-control-rest/src/responses.ts +++ b/sdk/synapse/synapse-access-control-rest/src/responses.ts @@ -18,7 +18,7 @@ export interface RoleAssignmentsCheckPrincipalAccess200Response extends HttpResp } /** Check if the given principalId has access to perform list of actions at a given scope. */ -export interface RoleAssignmentsCheckPrincipalAccessdefaultResponse extends HttpResponse { +export interface RoleAssignmentsCheckPrincipalAccessDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -36,7 +36,7 @@ export interface RoleAssignmentsListRoleAssignments200Response extends HttpRespo } /** List role assignments. */ -export interface RoleAssignmentsListRoleAssignmentsdefaultResponse extends HttpResponse { +export interface RoleAssignmentsListRoleAssignmentsDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -48,7 +48,7 @@ export interface RoleAssignmentsCreateRoleAssignment200Response extends HttpResp } /** Create role assignment. */ -export interface RoleAssignmentsCreateRoleAssignmentdefaultResponse extends HttpResponse { +export interface RoleAssignmentsCreateRoleAssignmentDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -60,7 +60,7 @@ export interface RoleAssignmentsGetRoleAssignmentById200Response extends HttpRes } /** Get role assignment by role assignment Id. */ -export interface RoleAssignmentsGetRoleAssignmentByIddefaultResponse extends HttpResponse { +export interface RoleAssignmentsGetRoleAssignmentByIdDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -68,17 +68,15 @@ export interface RoleAssignmentsGetRoleAssignmentByIddefaultResponse extends Htt /** Delete role assignment by role assignment Id. */ export interface RoleAssignmentsDeleteRoleAssignmentById200Response extends HttpResponse { status: "200"; - body: Record; } /** Delete role assignment by role assignment Id. */ export interface RoleAssignmentsDeleteRoleAssignmentById204Response extends HttpResponse { status: "204"; - body: Record; } /** Delete role assignment by role assignment Id. */ -export interface RoleAssignmentsDeleteRoleAssignmentByIddefaultResponse extends HttpResponse { +export interface RoleAssignmentsDeleteRoleAssignmentByIdDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -90,7 +88,7 @@ export interface RoleDefinitionsListRoleDefinitions200Response extends HttpRespo } /** List role definitions. */ -export interface RoleDefinitionsListRoleDefinitionsdefaultResponse extends HttpResponse { +export interface RoleDefinitionsListRoleDefinitionsDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -102,7 +100,7 @@ export interface RoleDefinitionsGetRoleDefinitionById200Response extends HttpRes } /** Get role definition by role definition Id. */ -export interface RoleDefinitionsGetRoleDefinitionByIddefaultResponse extends HttpResponse { +export interface RoleDefinitionsGetRoleDefinitionByIdDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } @@ -114,7 +112,7 @@ export interface RoleDefinitionsListScopes200Response extends HttpResponse { } /** List rbac scopes. */ -export interface RoleDefinitionsListScopesdefaultResponse extends HttpResponse { +export interface RoleDefinitionsListScopesDefaultResponse extends HttpResponse { status: string; body: ErrorContractOutput; } diff --git a/sdk/synapse/synapse-access-control-rest/swagger/README.md b/sdk/synapse/synapse-access-control-rest/swagger/README.md index 3509b04d66a6..0470af3060a0 100644 --- a/sdk/synapse/synapse-access-control-rest/swagger/README.md +++ b/sdk/synapse/synapse-access-control-rest/swagger/README.md @@ -5,6 +5,8 @@ ## Configuration ```yaml +flavor: azure +openapi-type: data-plane tag: package-access-control-2020-12-01 package-name: "@azure-rest/synapse-access-control" package-version: "1.0.0-beta.1"