Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
comment(
`Authorization rule${fieldMention}: { allow: ${rule.allow}, groupsField: "${groupsAttribute}", groupClaim: "${groupClaimAttribute}"}`
),
// Add the new auth expression and values
this.setUserGroups(rule.groupClaim),
forEach(ref('userGroup'), ref('userGroups'), [
raw(`$util.qr($groupAuthExpressions.add("contains(#${groupsAttributeName}, :${groupName}$foreach.count)"))`),
raw(`$util.qr($groupAuthExpressionValues.put(":${groupName}$foreach.count", { "S": $userGroup }))`),
]),
iff(raw('$userGroups.size() > 0'), raw(`$util.qr($groupAuthExpressionNames.put("#${groupsAttributeName}", "${groupsAttribute}"))`))
);
ruleNumber++;
}
// check for groupclaim here
return block('Dynamic group authorization checks', [
set(ref('groupAuthExpressions'), list([])),
set(ref('groupAuthExpressionValues'), obj({})),
set(ref('groupAuthExpressionNames'), obj({})),
...groupAuthorizationExpressions,
]);
}
public staticGroupAuthorizationExpression(rules: AuthRule[], field?: FieldDefinitionNode): Expression {
if (!rules || rules.length === 0) {
return comment(`No Static Group Authorization Rules`);
}
const variableToSet = this.getStaticAuthorizationVariable(field);
let groupAuthorizationExpressions = [];
for (const rule of rules) {
const groups = rule.groups;
const groupClaimAttribute = rule.groupClaim || DEFAULT_GROUP_CLAIM;
if (groups) {
groupAuthorizationExpressions = groupAuthorizationExpressions.concat(
comment(`Authorization rule: { allow: groups, groups: ${JSON.stringify(groups)}, groupClaim: "${groupClaimAttribute}" }`),
this.setUserGroups(rule.groupClaim),
set(ref('allowedGroups'), list(groups.map(s => str(s)))),
forEach(ref('userGroup'), ref('userGroups'), [
iff(raw(`$allowedGroups.contains($userGroup)`), compoundExpression([set(ref(variableToSet), raw('true')), raw('#break')])),
])
);
}
}
const staticGroupAuthorizedVariable = this.getStaticAuthorizationVariable(field);
// tslint:disable-next-line
return block('Static Group Authorization Checks', [
raw(`#set($${staticGroupAuthorizedVariable} = $util.defaultIfNull(
$${staticGroupAuthorizedVariable}, false))`),
...groupAuthorizationExpressions,
]);
}
private makeListRelationalResolver(type: string, queryTypeName: string = 'Query') {
const fieldName = graphqlName('list' + plurality(toUpper(type)));
const sql = `SELECT * FROM ${type}`;
const reqFileName = `${queryTypeName}.${fieldName}.req.vtl`;
const resFileName = `${queryTypeName}.${fieldName}.res.vtl`;
const reqTemplate = print(
RelationalDBMappingTemplate.rdsQuery({
statements: list([str(sql)]),
})
);
const resTemplate = print(ref('utils.toJson($utils.rds.toJsonObject($ctx.result)[0])'));
fs.writeFileSync(`${this.resolverFilePath}/${reqFileName}`, reqTemplate, 'utf8');
fs.writeFileSync(`${this.resolverFilePath}/${resFileName}`, resTemplate, 'utf8');
let resolver = new AppSync.Resolver({
ApiId: Fn.Ref(ResourceConstants.PARAMETERS.AppSyncApiId),
DataSourceName: Fn.GetAtt(ResourceConstants.RESOURCES.RelationalDatabaseDataSource, 'Name'),
TypeName: queryTypeName,
FieldName: fieldName,
RequestMappingTemplateS3Location: Fn.Sub(s3BaseUrl, {
[ResourceConstants.PARAMETERS.S3DeploymentBucket]: Fn.Ref(ResourceConstants.PARAMETERS.S3DeploymentBucket),
[ResourceConstants.PARAMETERS.S3DeploymentRootKey]: Fn.Ref(ResourceConstants.PARAMETERS.S3DeploymentRootKey),
[resolverFileName]: reqFileName,
iff(raw('!$util.isNullOrEmpty($context.args.sort.field) && !$util.isNullOrEmpty($context.args.sort.direction)'),
obj({
"$context.args.sort.field": obj({
"order": str('$context.args.sort.direction')
})
})
),
str('_doc')
]),
list([]))
})
])
),
ResponseMappingTemplate: print(
compoundExpression([
set(ref('items'), list([])),
forEach(
ref('entry'),
ref('context.result.hits.hits'),
[
iff(
raw('!$foreach.hasNext'),
set(ref('nextToken'), str('$entry.sort.get(0)'))
),
qref('$items.add($entry.get("_source"))')
]
),
toJson(obj({
"items": ref('items'),
"total": ref('ctx.result.hits.total'),
"nextToken": ref('nextToken')
}))
selectSql = `SELECT * FROM ${type} WHERE ${this.typePrimaryKeyMap.get(type)}=$ctx.args.update${toUpper(
type
)}Input.${this.typePrimaryKeyMap.get(type)}`;
}
const reqFileName = `${mutationTypeName}.${fieldName}.req.vtl`;
const resFileName = `${mutationTypeName}.${fieldName}.res.vtl`;
const reqTemplate = print(
compoundExpression([
set(ref('updateList'), obj({})),
forEach(ref('entry'), ref(`ctx.args.update${toUpper(type)}Input.keySet()`), [
set(ref('discard'), ref(`updateList.put($entry, "'$ctx.args.update${toUpper(type)}Input[$entry]'")`)),
]),
set(ref('update'), ref(`updateList.toString().replace("{","").replace("}","")`)),
RelationalDBMappingTemplate.rdsQuery({
statements: list([str(updateSql), str(selectSql)]),
}),
])
);
const resTemplate = print(ref('utils.toJson($utils.parseJson($utils.rds.toJsonString($ctx.result))[1][0])'));
fs.writeFileSync(`${this.resolverFilePath}/${reqFileName}`, reqTemplate, 'utf8');
fs.writeFileSync(`${this.resolverFilePath}/${resFileName}`, resTemplate, 'utf8');
let resolver = new AppSync.Resolver({
ApiId: Fn.Ref(ResourceConstants.PARAMETERS.AppSyncApiId),
DataSourceName: Fn.GetAtt(ResourceConstants.RESOURCES.RelationalDatabaseDataSource, 'Name'),
TypeName: mutationTypeName,
FieldName: fieldName,
RequestMappingTemplateS3Location: Fn.Sub(s3BaseUrl, {
[ResourceConstants.PARAMETERS.S3DeploymentBucket]: Fn.Ref(ResourceConstants.PARAMETERS.S3DeploymentBucket),
set(ref('sortDirection'), raw('$util.defaultIfNull($context.args.sort.direction, "desc")')),
set(ref('sortField'), raw(`$util.defaultIfNull($context.args.sort.field, "${primaryKey}")`)),
])
),
ElasticsearchMappingTemplate.searchItem({
path: str('$indexPath'),
size: ifElse(ref('context.args.limit'), ref('context.args.limit'), int(10), true),
search_after: list([str('$context.args.nextToken')]),
query: ifElse(
ref('context.args.filter'),
ref('util.transform.toElasticsearchQueryDSL($ctx.args.filter)'),
obj({
match_all: obj({}),
})
),
sort: list([
raw(
'{ #if($nonKeywordFields.contains($sortField))\
"$sortField" #else "${sortField}.keyword" #end : {\
"order" : "$sortDirection"\
} }'
),
]),
}),
])
),
ResponseMappingTemplate: print(
compoundExpression([
set(ref('es_items'), list([])),
forEach(ref('entry'), ref('context.result.hits.hits'), [
iff(raw('!$foreach.hasNext'), set(ref('nextToken'), ref('entry.sort.get(0)'))),
qref('$es_items.add($entry.get("_source"))'),
RequestMappingTemplate: print(
compoundExpression([
set(ref('indexPath'), str(`/${type.toLowerCase()}/doc/_search`)),
set(ref('nonKeywordFields'), list(nonKeywordFields)),
ifElse(
ref('util.isNullOrEmpty($context.args.sort)'),
compoundExpression([set(ref('sortDirection'), str('desc')), set(ref('sortField'), str(primaryKey))]),
compoundExpression([
set(ref('sortDirection'), raw('$util.defaultIfNull($context.args.sort.direction, "desc")')),
set(ref('sortField'), raw(`$util.defaultIfNull($context.args.sort.field, "${primaryKey}")`)),
])
),
ElasticsearchMappingTemplate.searchItem({
path: str('$indexPath'),
size: ifElse(ref('context.args.limit'), ref('context.args.limit'), int(10), true),
search_after: list([str('$context.args.nextToken')]),
query: ifElse(
ref('context.args.filter'),
ref('util.transform.toElasticsearchQueryDSL($ctx.args.filter)'),
obj({
match_all: obj({}),
})
),
sort: list([
raw(
'{ #if($nonKeywordFields.contains($sortField))\
"$sortField" #else "${sortField}.keyword" #end : {\
"order" : "$sortDirection"\
} }'
),
]),
}),
private makeDeleteRelationalResolver(type: string, mutationTypeName: string = 'Mutation') {
const fieldName = graphqlName('delete' + toUpper(type));
let selectSql;
if (this.typePrimaryKeyTypeMap.get(type).includes('String')) {
selectSql = `SELECT * FROM ${type} WHERE ${this.typePrimaryKeyMap.get(type)}=\'$ctx.args.${this.typePrimaryKeyMap.get(type)}\'`;
} else {
selectSql = `SELECT * FROM ${type} WHERE ${this.typePrimaryKeyMap.get(type)}=$ctx.args.${this.typePrimaryKeyMap.get(type)}`;
}
const deleteSql = `DELETE FROM ${type} WHERE ${this.typePrimaryKeyMap.get(type)}=$ctx.args.${this.typePrimaryKeyMap.get(type)}`;
const reqFileName = `${mutationTypeName}.${fieldName}.req.vtl`;
const resFileName = `${mutationTypeName}.${fieldName}.res.vtl`;
const reqTemplate = print(
compoundExpression([
RelationalDBMappingTemplate.rdsQuery({
statements: list([str(selectSql), str(deleteSql)]),
}),
])
);
const resTemplate = print(ref('utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])'));
fs.writeFileSync(`${this.resolverFilePath}/${reqFileName}`, reqTemplate, 'utf8');
fs.writeFileSync(`${this.resolverFilePath}/${resFileName}`, resTemplate, 'utf8');
let resolver = new AppSync.Resolver({
ApiId: Fn.Ref(ResourceConstants.PARAMETERS.AppSyncApiId),
DataSourceName: Fn.GetAtt(ResourceConstants.RESOURCES.RelationalDatabaseDataSource, 'Name'),
TypeName: mutationTypeName,
FieldName: fieldName,
RequestMappingTemplateS3Location: Fn.Sub(s3BaseUrl, {
[ResourceConstants.PARAMETERS.S3DeploymentBucket]: Fn.Ref(ResourceConstants.PARAMETERS.S3DeploymentBucket),
[ResourceConstants.PARAMETERS.S3DeploymentRootKey]: Fn.Ref(ResourceConstants.PARAMETERS.S3DeploymentRootKey),
private validateKeyUpdateArgumentsSnippet = (directive: DirectiveNode): string => {
const directiveArgs: KeyArguments = getDirectiveArguments(directive);
if (!this.isPrimaryKey(directive) && directiveArgs.fields.length > 2) {
const sortKeyFields = directiveArgs.fields.slice(1);
return printBlock(`Validate update mutation for @key '${directiveArgs.name}'`)(compoundExpression([
set(ref('hasSeenSomeKeyArg'), bool(false)),
set(ref('keyFieldNames'), list(sortKeyFields.map(f => str(f)))),
forEach(ref('keyFieldName'), ref('keyFieldNames'), [
iff(
raw(`$ctx.args.input.containsKey("$keyFieldName")`),
set(ref('hasSeenSomeKeyArg'), bool(true)),
true
)
]),
forEach(ref('keyFieldName'), ref('keyFieldNames'), [
iff(
raw(`$hasSeenSomeKeyArg && !$ctx.args.input.containsKey("$keyFieldName")`),
raw(`$util.error("When updating any part of the composite sort key for @key '${directiveArgs.name}',` +
` you must provide all fields for the key. Missing key: '$keyFieldName'.")`)
)
])
]));
}
})
),
sort: list([
raw(
'{ #if($nonKeywordFields.contains($sortField))\
"$sortField" #else "${sortField}.keyword" #end : {\
"order" : "$sortDirection"\
} }'
),
]),
}),
])
),
ResponseMappingTemplate: print(
compoundExpression([
set(ref('es_items'), list([])),
forEach(ref('entry'), ref('context.result.hits.hits'), [
iff(raw('!$foreach.hasNext'), set(ref('nextToken'), ref('entry.sort.get(0)'))),
qref('$es_items.add($entry.get("_source"))'),
]),
toJson(
obj({
items: ref('es_items'),
total: ref('ctx.result.hits.total'),
nextToken: ref('nextToken'),
})
),
])
),
}).dependsOn([ResourceConstants.RESOURCES.ElasticsearchDataSourceLogicalID]);
}