Skip to content

Commit

Permalink
fix: fix null check for implied owner check (aws-amplify#8586)
Browse files Browse the repository at this point in the history
  • Loading branch information
SwaySway authored and AmmarKarachi committed Nov 3, 2021
1 parent 4ed3fc3 commit c6c0640
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ownerfield where the field is a list 1`] = `
"## [Start] Authorization Steps. **
$util.qr($ctx.stash.put(\\"hasAuth\\", true))
#set( $inputFields = $util.parseJson($util.toJson($ctx.args.input.keySet())) )
#set( $isAuthorized = false )
#set( $allowedFields = [] )
#if( $util.authType() == \\"User Pool Authorization\\" )
#if( !$isAuthorized )
#set( $ownerEntity0 = $util.defaultIfNull($ctx.args.input.editors, null) )
#set( $ownerClaim0 = $util.defaultIfNull($ctx.identity.claims.get(\\"username\\"), $util.defaultIfNull($ctx.identity.claims.get(\\"cognito:username\\"), \\"___xamznone____\\")) )
#set( $ownerAllowedFields0 = [] )
#foreach( $allowedOwner in $ownerEntity0 )
#if( $allowedOwner == $ownerClaim0 )
#if( !$ownerAllowedFields0.isEmpty() )
$util.qr($allowedFields.addAll($ownerAllowedFields0))
#else
#set( $isAuthorized = true )
#break
#end
#end
#end
#if( $util.isNull($ownerEntity0) && !$ctx.args.input.containsKey(\\"editors\\") )
$util.qr($ctx.args.input.put(\\"editors\\", [$ownerClaim0]))
#if( !$ownerAllowedFields0.isEmpty() )
$util.qr($allowedFields.addAll($ownerAllowedFields0))
#else
#set( $isAuthorized = true )
#end
#end
#end
#end
#if( !$isAuthorized && $allowedFields.isEmpty() )
$util.unauthorized()
#end
#if( !$isAuthorized )
#set( $deniedFields = $util.list.copyAndRemoveAll($inputFields, $allowedFields) )
#if( $deniedFields.size() > 0 )
$util.error(\\"Unauthorized on \${deniedFields}\\", \\"Unauthorized\\")
#end
#end
$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}})
## [End] Authorization Steps. **"
`;

exports[`ownerfield where the field is a list 2`] = `
"## [Start] Get Request template. **
#set( $GetRequest = {
\\"version\\": \\"2018-05-29\\",
\\"operation\\": \\"GetItem\\"
} )
#if( $ctx.stash.metadata.modelObjectKey )
#set( $key = $ctx.stash.metadata.modelObjectKey )
#else
#set( $key = {
\\"id\\": $util.dynamodb.toDynamoDB($ctx.args.input.id)
} )
#end
$util.qr($GetRequest.put(\\"key\\", $key))
$util.toJson($GetRequest)
## [End] Get Request template. **"
`;

exports[`ownerfield where the field is a list 3`] = `
"## [Start] Get Request template. **
#set( $GetRequest = {
\\"version\\": \\"2018-05-29\\",
\\"operation\\": \\"GetItem\\"
} )
#if( $ctx.stash.metadata.modelObjectKey )
#set( $key = $ctx.stash.metadata.modelObjectKey )
#else
#set( $key = {
\\"id\\": $util.dynamodb.toDynamoDB($ctx.args.input.id)
} )
#end
$util.qr($GetRequest.put(\\"key\\", $key))
$util.toJson($GetRequest)
## [End] Get Request template. **"
`;

exports[`ownerfield where the field is a list 4`] = `
"## [Start] Authorization Steps. **
$util.qr($ctx.stash.put(\\"hasAuth\\", true))
#set( $isAuthorized = false )
#set( $primaryFieldMap = {} )
#if( $util.authType() == \\"User Pool Authorization\\" )
#if( !$isAuthorized )
#set( $authFilter = [{
\\"editors\\": {
\\"contains\\": $util.defaultIfNull($ctx.identity.claims.get(\\"username\\"), $util.defaultIfNull($ctx.identity.claims.get(\\"cognito:username\\"), \\"___xamznone____\\"))
}
}] )
$util.qr($ctx.stash.put(\\"authFilter\\", { \\"or\\": $authFilter }))
#end
#end
#if( !$isAuthorized && $util.isNull($ctx.stash.authFilter) && $primaryFieldMap.isEmpty() )
$util.unauthorized()
#end
$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}})
## [End] Authorization Steps. **"
`;

exports[`ownerfield where the field is a list 5`] = `
"## [Start] Authorization Steps. **
$util.qr($ctx.stash.put(\\"hasAuth\\", true))
#set( $isAuthorized = false )
#set( $primaryFieldMap = {} )
#if( $util.authType() == \\"User Pool Authorization\\" )
#if( !$isAuthorized )
#set( $authFilter = [{
\\"editors\\": {
\\"contains\\": $util.defaultIfNull($ctx.identity.claims.get(\\"username\\"), $util.defaultIfNull($ctx.identity.claims.get(\\"cognito:username\\"), \\"___xamznone____\\"))
}
}] )
$util.qr($ctx.stash.put(\\"authFilter\\", { \\"or\\": $authFilter }))
#end
#end
#if( !$isAuthorized && $util.isNull($ctx.stash.authFilter) && $primaryFieldMap.isEmpty() )
$util.unauthorized()
#end
$util.toJson({\\"version\\":\\"2018-05-29\\",\\"payload\\":{}})
## [End] Authorization Steps. **"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,37 @@ test('auth transformer validation happy case', () => {
);
});

test('ownerfield where the field is a list', () => {
const authConfig: AppSyncAuthConfiguration = {
defaultAuthentication: {
authenticationType: 'AMAZON_COGNITO_USER_POOLS',
},
additionalAuthenticationProviders: [],
};
const validSchema = `
type Post @model @auth(rules: [{allow: owner, ownerField: "editors" }]) {
id: ID!
title: String!
editors: [String]
createdAt: String
updatedAt: String
}`;
const transformer = new GraphQLTransform({
authConfig,
transformers: [new ModelTransformer(), new AuthTransformer()],
});
const out = transformer.transform(validSchema);
expect(out).toBeDefined();
expect(out.rootStack.Resources[ResourceConstants.RESOURCES.GraphQLAPILogicalID].Properties.AuthenticationType).toEqual(
'AMAZON_COGNITO_USER_POOLS',
);
expect(out.pipelineFunctions['Mutation.createPost.auth.1.req.vtl']).toMatchSnapshot();
expect(out.pipelineFunctions['Mutation.updatePost.auth.1.req.vtl']).toMatchSnapshot();
expect(out.pipelineFunctions['Mutation.deletePost.auth.1.req.vtl']).toMatchSnapshot();
expect(out.pipelineFunctions['Query.getPost.auth.1.req.vtl']).toMatchSnapshot();
expect(out.pipelineFunctions['Query.listPosts.auth.1.req.vtl']).toMatchSnapshot();
});

test('ownerfield with subscriptions', () => {
const authConfig: AppSyncAuthConfiguration = {
defaultAuthentication: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
raw,
iff,
and,
isNullOrEmpty,
not,
methodCall,
qref,
Expand Down Expand Up @@ -152,7 +151,7 @@ const generateStaticRoleExpression = (roles: Array<RoleDefinition>): Array<Expre
return staticRoleExpression;
};

const dynamicGroupRoleExpression = (roles: Array<RoleDefinition>, fields: ReadonlyArray<FieldDefinitionNode>): Array<Expression> => {
const dynamicRoleExpression = (roles: Array<RoleDefinition>, fields: ReadonlyArray<FieldDefinitionNode>): Array<Expression> => {
const ownerExpression = new Array<Expression>();
const dynamicGroupExpression = new Array<Expression>();
roles.forEach((role, idx) => {
Expand All @@ -162,10 +161,7 @@ const dynamicGroupRoleExpression = (roles: Array<RoleDefinition>, fields: Readon
iff(
not(ref(IS_AUTHORIZED_FLAG)),
compoundExpression([
set(
ref(`ownerEntity${idx}`),
methodCall(ref('util.defaultIfNull'), ref(`ctx.args.input.${role.entity!}`), entityIsList ? list([]) : nul()),
),
set(ref(`ownerEntity${idx}`), methodCall(ref('util.defaultIfNull'), ref(`ctx.args.input.${role.entity!}`), nul())),
set(ref(`ownerClaim${idx}`), getOwnerClaim(role.claim!)),
set(ref(`ownerAllowedFields${idx}`), raw(JSON.stringify(role.allowedFields))),
...(entityIsList
Expand All @@ -176,7 +172,7 @@ const dynamicGroupRoleExpression = (roles: Array<RoleDefinition>, fields: Readon
]
: [iff(equals(ref(`ownerClaim${idx}`), ref(`ownerEntity${idx}`)), addAllowedFieldsIfElse(`ownerAllowedFields${idx}`))]),
iff(
and([isNullOrEmpty(ref(`ownerEntity${idx}`)), not(methodCall(ref('ctx.args.input.containsKey'), str(role.entity!)))]),
and([ref(`util.isNull($ownerEntity${idx})`), not(methodCall(ref('ctx.args.input.containsKey'), str(role.entity!)))]),
compoundExpression([
qref(
methodCall(
Expand Down Expand Up @@ -264,7 +260,7 @@ export const generateAuthExpressionForCreate = (
equals(ref('util.authType()'), str(COGNITO_AUTH_TYPE)),
compoundExpression([
...generateStaticRoleExpression(cognitoStaticGroupRoles),
...dynamicGroupRoleExpression(cognitoDynamicRoles, fields),
...dynamicRoleExpression(cognitoDynamicRoles, fields),
]),
),
);
Expand All @@ -273,10 +269,7 @@ export const generateAuthExpressionForCreate = (
totalAuthExpressions.push(
iff(
equals(ref('util.authType()'), str(OIDC_AUTH_TYPE)),
compoundExpression([
...generateStaticRoleExpression(oidcStaticGroupRoles),
...dynamicGroupRoleExpression(oidcDynamicRoles, fields),
]),
compoundExpression([...generateStaticRoleExpression(oidcStaticGroupRoles), ...dynamicRoleExpression(oidcDynamicRoles, fields)]),
),
);
}
Expand Down

0 comments on commit c6c0640

Please sign in to comment.