amplify-category-api icon indicating copy to clipboard operation
amplify-category-api copied to clipboard

Enable storing of often reused data authorization rules in variables

Open JonasRothSwinx opened this issue 1 year ago • 2 comments

Environment information

System:
  OS: Windows 10 10.0.19045
  CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
  Memory: 8.67 GB / 31.92 GB
Binaries:
  Node: 20.11.0 - C:\Program Files\nodejs\node.EXE
  Yarn: 3.3.1 - C:\Program Files\nodejs\yarn.CMD
  npm: 10.7.0 - D:\DocumentsWin\Arbeit\Software\swinx-web\node_modules\.bin\npm.CMD
  pnpm: 8.15.4 - C:\Program Files\nodejs\pnpm.CMD
NPM Packages:
  @aws-amplify/backend: 1.0.1
  @aws-amplify/backend-cli: 1.0.2
  aws-amplify: 6.3.0
  aws-cdk: Not Found
  aws-cdk-lib: Not Found
  typescript: 5.4.5
AWS environment variables:
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_PROFILE = my_default_profile_name
  AWS_SDK_LOAD_CONFIG = 1
  AWS_STS_REGIONAL_ENDPOINTS = regional
No CDK environment variables

Description

I used to save commonly used auth configurations in variables like this:

const adminsAndManagers = a.allow.specificGroups(["admin", "projektmanager"], "userPools");
const publicRead = a.allow.public().to(["read"]);

It would be great if we could still do this with the new way of defining rules with the allow-functions? Fully writing this gets very wordy, especially when doing field level auth rules.

Example of how i did it before:

const adminsAndManagers = a.allow.specificGroups(["admin", "projektmanager"], "userPools");
const publicRead = a.allow.public().to(["read"]);
InfluencerAssignment: a
    .model({
        budget: a.integer(),
        isPlaceholder: a.boolean().required(),
        placeholderName: a.string().authorization([adminsAndManagers]),
         //##########################
        //### Relations ############
        influencerId: a.id().authorization([adminsAndManagers]),
        influencer: a
            .belongsTo("Influencer", "influencerId")
            .authorization([adminsAndManagers]),

        timelineEvents: a.hasMany("EventAssignment", "assignmentId"),
        campaignId: a.id().required(),
        campaign: a.belongsTo("Campaign", "campaignId"),

        candidates: a
            .hasMany("InfluencerCandidate", "candidateAssignmentId")
            .authorization([adminsAndManagers]),
        //##########################
    })
    .authorization([publicRead, adminsAndManagers]),

This is the same model in the newer version:

   InfluencerAssignment: a
        .model({
            budget: a.integer(),
            isPlaceholder: a.boolean().required(),
            placeholderName: a.string().authorization((allow) => [allow.groups(["admin", "projektmanager"])]),

            //##########################
            //### Relations ############
            influencerId: a.id().authorization((allow) => [allow.groups(["admin", "projektmanager"])]),
            influencer: a
                .belongsTo("Influencer", "influencerId")
                .authorization((allow) => [allow.groups(["admin", "projektmanager"])]),

            timelineEvents: a.hasMany("EventAssignment", "assignmentId"),

            campaignId: a.id().required(),
            campaign: a.belongsTo("Campaign", "campaignId"),

            candidates: a
                .hasMany("InfluencerCandidate", "candidateAssignmentId")
                .authorization((allow) => [allow.groups(["admin", "projektmanager"])]),
            //##########################
        })
        .authorization((allow) => [allow.publicApiKey().to(["read"]), allow.groups(["admin", "projektmanager"])]),

JonasRothSwinx avatar May 13 '24 17:05 JonasRothSwinx

Hi @JonasRothSwinx, you should be able to do something like this:

const publicReadAndAdminsAndManagers = allow => [allow.publicApiKey(), allow.groups(["admin", "projectManager"])]

//... schema
Todo: a
    .model({
      id: [a.id](http://a.id/)().required(),
      name: a.string().required(),
      description: a.string(),
      completed: a.boolean().required(),
    })
    .authorization(publicReadAndAdminsAndManagers),

Unfortunately, you can't really separate the auth rules like you did before because the authorization modifier accepts a callback function that returns an array of auth rules now rather than an array directly.

We can mark this as a feature request to review with the team on potential DX improvements

chrisbonifacio avatar May 13 '24 19:05 chrisbonifacio

What would be the correct way to type the allow? My IDE is not happy with the implicit any type

JonasRothSwinx avatar May 14 '24 10:05 JonasRothSwinx