@aws-amplify/data-schema 0.13.10 → 0.13.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import type { UnionToIntersection } from '@aws-amplify/data-schema-types';
1
+ import type { UnionToIntersection, FunctionSchemaAccess } from '@aws-amplify/data-schema-types';
2
2
  declare const __data: unique symbol;
3
3
  /**
4
4
  * All possible providers.
@@ -41,6 +41,24 @@ export type Strategy = (typeof Strategies)[number];
41
41
  */
42
42
  export declare const Operations: readonly ["create", "update", "delete", "read", "get", "list", "sync", "listen", "search"];
43
43
  export type Operation = (typeof Operations)[number];
44
+ /**
45
+ * The operations that can be performed against an API by a Lambda function.
46
+ */
47
+ export declare const ResourceOperations: readonly ["query", "mutate", "listen"];
48
+ export type ResourceOperation = (typeof ResourceOperations)[number];
49
+ /**
50
+ * Super-set of regular auth type; includes schema-level resource access configuration
51
+ */
52
+ export type SchemaAuthorization<AuthStrategy extends Strategy, AuthField extends string | undefined, AuthFieldPlurality extends boolean> = Authorization<AuthStrategy, AuthField, AuthFieldPlurality> | ResourceAuthorization;
53
+ export type ResourceAuthorization = {
54
+ [__data]: ResourceAuthorizationData;
55
+ };
56
+ type DefineFunction = FunctionSchemaAccess['resourceProvider'];
57
+ export type ResourceAuthorizationData = {
58
+ strategy: 'resource';
59
+ resource: DefineFunction;
60
+ operations?: ResourceOperation[];
61
+ };
44
62
  export type Authorization<AuthStrategy extends Strategy, AuthField extends string | undefined, AuthFieldPlurality extends boolean> = {
45
63
  [__data]: {
46
64
  strategy?: AuthStrategy;
@@ -200,7 +218,11 @@ export declare const allow: {
200
218
  readonly custom: (provider?: CustomProvider) => Authorization<"custom", undefined, false> & {
201
219
  to: typeof to;
202
220
  };
221
+ readonly resource: (fn: DefineFunction) => ResourceAuthorization & {
222
+ to: typeof resourceTo;
223
+ };
203
224
  };
225
+ declare function resourceTo<SELF extends ResourceAuthorization>(this: SELF, operations: ResourceOperation[]): Omit<SELF, "to">;
204
226
  /**
205
227
  * Turns the type from a list of `Authorization` rules like this:
206
228
  *
@@ -261,4 +283,5 @@ export declare const accessData: <T extends Authorization<any, any, any>>(author
261
283
  identityClaim?: string | undefined;
262
284
  groupClaim?: string | undefined;
263
285
  };
286
+ export declare const accessSchemaData: <T extends SchemaAuthorization<any, any, any>>(authorization: T) => T[typeof __data];
264
287
  export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.accessData = exports.allow = exports.Operations = exports.Strategies = exports.CustomProviders = exports.GroupProviders = exports.OwnerProviders = exports.PrivateProviders = exports.PublicProviders = exports.Providers = void 0;
3
+ exports.accessSchemaData = exports.accessData = exports.allow = exports.ResourceOperations = exports.Operations = exports.Strategies = exports.CustomProviders = exports.GroupProviders = exports.OwnerProviders = exports.PrivateProviders = exports.PublicProviders = exports.Providers = void 0;
4
4
  const __data = Symbol('data');
5
5
  /**
6
6
  * All possible providers.
@@ -57,6 +57,10 @@ exports.Operations = [
57
57
  'listen',
58
58
  'search',
59
59
  ];
60
+ /**
61
+ * The operations that can be performed against an API by a Lambda function.
62
+ */
63
+ exports.ResourceOperations = ['query', 'mutate', 'listen'];
60
64
  /**
61
65
  * Creates a shallow copy of an object with an individual field pruned away.
62
66
  *
@@ -302,6 +306,27 @@ exports.allow = {
302
306
  to,
303
307
  });
304
308
  },
309
+ resource(fn) {
310
+ return resourceAuthData(fn, {
311
+ to: resourceTo,
312
+ });
313
+ },
305
314
  };
315
+ function resourceTo(operations) {
316
+ this[__data].operations = operations;
317
+ return omit(this, 'to');
318
+ }
319
+ function resourceAuthData(resource, builderMethods) {
320
+ return {
321
+ [__data]: {
322
+ strategy: 'resource',
323
+ resource,
324
+ },
325
+ ...builderMethods,
326
+ };
327
+ }
306
328
  const accessData = (authorization) => authorization[__data];
307
329
  exports.accessData = accessData;
330
+ // TODO: delete when we make resource auth available at each level in the schema (model, field)
331
+ const accessSchemaData = (authorization) => authorization[__data];
332
+ exports.accessSchemaData = accessSchemaData;
@@ -3,7 +3,7 @@ import { type ModelType, type ModelTypeParamShape, type InternalModel, SchemaMod
3
3
  import type { EnumType, EnumTypeParamShape } from './EnumType';
4
4
  import type { CustomType, CustomTypeParamShape } from './CustomType';
5
5
  import type { CustomOperation, CustomOperationParamShape, InternalCustom, MutationCustomOperation, QueryCustomOperation, SubscriptionCustomOperation } from './CustomOperation';
6
- import { Authorization } from './Authorization';
6
+ import { SchemaAuthorization } from './Authorization';
7
7
  type SchemaContent = ModelType<ModelTypeParamShape, any> | CustomType<CustomTypeParamShape> | EnumType<EnumTypeParamShape> | CustomOperation<CustomOperationParamShape, any>;
8
8
  type ModelSchemaContents = Record<string, SchemaContent>;
9
9
  type InternalSchemaModels = Record<string, InternalModel | EnumType<any> | CustomType<any> | InternalCustom>;
@@ -35,7 +35,7 @@ export type SchemaConfig<DE extends DatasourceEngine, DC extends DatasourceConfi
35
35
  };
36
36
  export type ModelSchemaParamShape = {
37
37
  types: ModelSchemaContents;
38
- authorization: Authorization<any, any, any>[];
38
+ authorization: SchemaAuthorization<any, any, any>[];
39
39
  configuration: SchemaConfig<any, any>;
40
40
  };
41
41
  export type SQLModelSchemaParamShape = ModelSchemaParamShape & {
@@ -44,11 +44,11 @@ export type SQLModelSchemaParamShape = ModelSchemaParamShape & {
44
44
  export type InternalSchema = {
45
45
  data: {
46
46
  types: InternalSchemaModels;
47
- authorization: Authorization<any, any, any>[];
47
+ authorization: SchemaAuthorization<any, any, any>[];
48
48
  };
49
49
  };
50
50
  export type ModelSchema<T extends ModelSchemaParamShape, UsedMethods extends 'authorization' = never> = Omit<{
51
- authorization: <AuthRules extends Authorization<any, any, any>>(auth: AuthRules[]) => ModelSchema<SetTypeSubArg<T, 'authorization', AuthRules[]>, UsedMethods | 'authorization'>;
51
+ authorization: <AuthRules extends SchemaAuthorization<any, any, any>>(auth: AuthRules[]) => ModelSchema<SetTypeSubArg<T, 'authorization', AuthRules[]>, UsedMethods | 'authorization'>;
52
52
  }, UsedMethods> & {
53
53
  data: T;
54
54
  models: {
@@ -243,6 +243,18 @@ function mergeFieldObjects(...fieldsObjects) {
243
243
  }
244
244
  return result;
245
245
  }
246
+ /**
247
+ * Throws if resource/lambda auth is configured at the model or field level
248
+ *
249
+ * @param authorization A list of authorization rules.
250
+ */
251
+ function validateAuth(authorization = []) {
252
+ for (const entry of authorization) {
253
+ if (ruleIsResourceAuth(entry)) {
254
+ throw new Error('Lambda resource authorization is only confiugrable at the schema level');
255
+ }
256
+ }
257
+ }
246
258
  /**
247
259
  * Given a list of authorization rules, produces a set of the implied owner and/or
248
260
  * group fields, along with the associated graphql `@auth` string directive.
@@ -530,7 +542,9 @@ const idFields = (model) => {
530
542
  function processFieldLevelAuthRules(fields, authFields) {
531
543
  const fieldLevelAuthRules = {};
532
544
  for (const [fieldName, fieldDef] of Object.entries(fields)) {
533
- const { authString, authFields: fieldAuthField } = calculateAuth(fieldDef?.data?.authorization || []);
545
+ const fieldAuth = fieldDef?.data?.authorization || [];
546
+ validateAuth(fieldAuth);
547
+ const { authString, authFields: fieldAuthField } = calculateAuth(fieldAuth);
534
548
  if (authString)
535
549
  fieldLevelAuthRules[fieldName] = authString;
536
550
  if (fieldAuthField) {
@@ -621,6 +635,38 @@ const transformedSecondaryIndexesForModel = (secondaryIndexes) => {
621
635
  return acc;
622
636
  }, {});
623
637
  };
638
+ const ruleIsResourceAuth = (authRule) => {
639
+ const data = (0, Authorization_1.accessSchemaData)(authRule);
640
+ return data.strategy === 'resource';
641
+ };
642
+ /**
643
+ * Separates out lambda resource auth rules from remaining schema rules.
644
+ *
645
+ * @param authRules schema auth rules
646
+ */
647
+ const extractFunctionSchemaAccess = (authRules) => {
648
+ const schemaAuth = [];
649
+ const functionSchemaAccess = [];
650
+ const defaultActions = [
651
+ 'query',
652
+ 'mutate',
653
+ 'listen',
654
+ ];
655
+ for (const rule of authRules) {
656
+ if (ruleIsResourceAuth(rule)) {
657
+ const ruleData = (0, Authorization_1.accessSchemaData)(rule);
658
+ const fnAccess = {
659
+ resourceProvider: ruleData.resource,
660
+ actions: ruleData.operations || defaultActions,
661
+ };
662
+ functionSchemaAccess.push(fnAccess);
663
+ }
664
+ else {
665
+ schemaAuth.push(rule);
666
+ }
667
+ }
668
+ return { schemaAuth, functionSchemaAccess };
669
+ };
624
670
  const schemaPreprocessor = (schema) => {
625
671
  const gqlModels = [];
626
672
  const customQueries = [];
@@ -629,10 +675,12 @@ const schemaPreprocessor = (schema) => {
629
675
  const jsFunctions = [];
630
676
  const fkFields = allImpliedFKs(schema);
631
677
  const topLevelTypes = Object.entries(schema.data.types);
678
+ const { schemaAuth, functionSchemaAccess } = extractFunctionSchemaAccess(schema.data.authorization);
632
679
  for (const [typeName, typeDef] of topLevelTypes) {
680
+ validateAuth(typeDef.data?.authorization);
633
681
  const mostRelevantAuthRules = typeDef.data?.authorization?.length > 0
634
682
  ? typeDef.data.authorization
635
- : schema.data.authorization;
683
+ : schemaAuth;
636
684
  if (!isInternalModel(typeDef)) {
637
685
  if (isEnumType(typeDef)) {
638
686
  if (typeDef.values.some((value) => /\s/.test(value))) {
@@ -706,7 +754,7 @@ const schemaPreprocessor = (schema) => {
706
754
  };
707
755
  gqlModels.push(...generateCustomOperationTypes(customOperations));
708
756
  const processedSchema = gqlModels.join('\n\n');
709
- return { schema: processedSchema, jsFunctions };
757
+ return { schema: processedSchema, jsFunctions, functionSchemaAccess };
710
758
  };
711
759
  function validateCustomOperations(typeDef, typeName, authRules) {
712
760
  const { functionRef, handlers } = typeDef.data;
@@ -819,7 +867,7 @@ function generateCustomOperationTypes({ queries, mutations, subscriptions, }) {
819
867
  * @returns DerivedApiDefinition that conforms to IAmplifyGraphqlDefinition
820
868
  */
821
869
  function processSchema(arg) {
822
- const { schema, jsFunctions } = schemaPreprocessor(arg.schema);
823
- return { schema, functionSlots: [], jsFunctions };
870
+ const { schema, jsFunctions, functionSchemaAccess } = schemaPreprocessor(arg.schema);
871
+ return { schema, functionSlots: [], jsFunctions, functionSchemaAccess };
824
872
  }
825
873
  exports.processSchema = processSchema;