diff --git a/apps/basic-auth-provider-admin/src/App.tsx b/apps/basic-auth-provider-admin/src/App.tsx index 7139684..f3f6d87 100644 --- a/apps/basic-auth-provider-admin/src/App.tsx +++ b/apps/basic-auth-provider-admin/src/App.tsx @@ -129,7 +129,7 @@ import { UserList } from "./user/UserList"; import { UserCreate } from "./user/UserCreate"; import { UserEdit } from "./user/UserEdit"; import { UserShow } from "./user/UserShow"; -import { jwtAuthProvider } from "./auth-provider/ra-auth-jwt"; +import { httpAuthProvider } from "./auth-provider/ra-auth-http"; const App = (): React.ReactElement => { const [dataProvider, setDataProvider] = useState(null); @@ -150,7 +150,7 @@ const App = (): React.ReactElement => { { + console.error(error); + process.exit(1); + }); } -async function seed() { +async function seed(bcryptSalt: Salt) { console.info("Seeding database..."); const client = new PrismaClient(); + + const data = { + username: "admin", + password: await hash("admin", bcryptSalt), + roles: ["user"], + }; + + await client.user.upsert({ + where: { + username: data.username, + }, + + update: {}, + create: data, + }); + void client.$disconnect(); console.info("Seeding database with custom seed..."); diff --git a/apps/basic-auth-provider/src/account/account.controller.ts b/apps/basic-auth-provider/src/account/account.controller.ts index eb68f76..a539f90 100644 --- a/apps/basic-auth-provider/src/account/account.controller.ts +++ b/apps/basic-auth-provider/src/account/account.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { AccountService } from "./account.service"; import { AccountControllerBase } from "./base/account.controller.base"; @swagger.ApiTags("accounts") @common.Controller("accounts") export class AccountController extends AccountControllerBase { - constructor(protected readonly service: AccountService) { - super(service); + constructor( + protected readonly service: AccountService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/account/account.module.ts b/apps/basic-auth-provider/src/account/account.module.ts index bc6b28a..2a839c7 100644 --- a/apps/basic-auth-provider/src/account/account.module.ts +++ b/apps/basic-auth-provider/src/account/account.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { AccountModuleBase } from "./base/account.module.base"; import { AccountService } from "./account.service"; import { AccountController } from "./account.controller"; import { AccountResolver } from "./account.resolver"; @Module({ - imports: [AccountModuleBase], + imports: [AccountModuleBase, forwardRef(() => AuthModule)], controllers: [AccountController], providers: [AccountService, AccountResolver], exports: [AccountService], diff --git a/apps/basic-auth-provider/src/account/account.resolver.ts b/apps/basic-auth-provider/src/account/account.resolver.ts index c6a50f6..06ceeae 100644 --- a/apps/basic-auth-provider/src/account/account.resolver.ts +++ b/apps/basic-auth-provider/src/account/account.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { AccountResolverBase } from "./base/account.resolver.base"; import { Account } from "./base/Account"; import { AccountService } from "./account.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Account) export class AccountResolver extends AccountResolverBase { - constructor(protected readonly service: AccountService) { - super(service); + constructor( + protected readonly service: AccountService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/account/base/account.controller.base.ts b/apps/basic-auth-provider/src/account/base/account.controller.base.ts index 7e8b5e8..726c111 100644 --- a/apps/basic-auth-provider/src/account/base/account.controller.base.ts +++ b/apps/basic-auth-provider/src/account/base/account.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { AccountService } from "../account.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { AccountCreateInput } from "./AccountCreateInput"; import { Account } from "./Account"; import { AccountFindManyArgs } from "./AccountFindManyArgs"; import { AccountWhereUniqueInput } from "./AccountWhereUniqueInput"; import { AccountUpdateInput } from "./AccountUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class AccountControllerBase { - constructor(protected readonly service: AccountService) {} + constructor( + protected readonly service: AccountService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Account }) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createAccount( @common.Body() data: AccountCreateInput ): Promise { @@ -62,9 +80,18 @@ export class AccountControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Account] }) @ApiNestedQuery(AccountFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async accounts(@common.Req() request: Request): Promise { const args = plainToClass(AccountFindManyArgs, request.query); return this.service.accounts({ @@ -91,9 +118,18 @@ export class AccountControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Account }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async account( @common.Param() params: AccountWhereUniqueInput ): Promise { @@ -127,9 +163,18 @@ export class AccountControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Account }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateAccount( @common.Param() params: AccountWhereUniqueInput, @common.Body() data: AccountUpdateInput @@ -179,6 +224,14 @@ export class AccountControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Account }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteAccount( @common.Param() params: AccountWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/account/base/account.module.base.ts b/apps/basic-auth-provider/src/account/base/account.module.base.ts index 39ee020..e96ccd4 100644 --- a/apps/basic-auth-provider/src/account/base/account.module.base.ts +++ b/apps/basic-auth-provider/src/account/base/account.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class AccountModuleBase {} diff --git a/apps/basic-auth-provider/src/account/base/account.resolver.base.ts b/apps/basic-auth-provider/src/account/base/account.resolver.base.ts index 18b5901..71bbb69 100644 --- a/apps/basic-auth-provider/src/account/base/account.resolver.base.ts +++ b/apps/basic-auth-provider/src/account/base/account.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Account } from "./Account"; import { AccountCountArgs } from "./AccountCountArgs"; import { AccountFindManyArgs } from "./AccountFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateAccountArgs } from "./UpdateAccountArgs"; import { DeleteAccountArgs } from "./DeleteAccountArgs"; import { OrigUser } from "../../origUser/base/OrigUser"; import { AccountService } from "../account.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Account) export class AccountResolverBase { - constructor(protected readonly service: AccountService) {} + constructor( + protected readonly service: AccountService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "any", + }) async _accountsMeta( @graphql.Args() args: AccountCountArgs ): Promise { @@ -35,14 +51,26 @@ export class AccountResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Account]) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "any", + }) async accounts( @graphql.Args() args: AccountFindManyArgs ): Promise { return this.service.accounts(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Account, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "own", + }) async account( @graphql.Args() args: AccountFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class AccountResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Account) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "create", + possession: "any", + }) async createAccount( @graphql.Args() args: CreateAccountArgs ): Promise { @@ -71,7 +105,13 @@ export class AccountResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Account) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "update", + possession: "any", + }) async updateAccount( @graphql.Args() args: UpdateAccountArgs ): Promise { @@ -99,6 +139,11 @@ export class AccountResolverBase { } @graphql.Mutation(() => Account) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "delete", + possession: "any", + }) async deleteAccount( @graphql.Args() args: DeleteAccountArgs ): Promise { @@ -114,10 +159,16 @@ export class AccountResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Account): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/apiKey/apiKey.controller.ts b/apps/basic-auth-provider/src/apiKey/apiKey.controller.ts index 06122a6..bddb950 100644 --- a/apps/basic-auth-provider/src/apiKey/apiKey.controller.ts +++ b/apps/basic-auth-provider/src/apiKey/apiKey.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { ApiKeyService } from "./apiKey.service"; import { ApiKeyControllerBase } from "./base/apiKey.controller.base"; @swagger.ApiTags("apiKeys") @common.Controller("apiKeys") export class ApiKeyController extends ApiKeyControllerBase { - constructor(protected readonly service: ApiKeyService) { - super(service); + constructor( + protected readonly service: ApiKeyService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/apiKey/apiKey.module.ts b/apps/basic-auth-provider/src/apiKey/apiKey.module.ts index f536303..84e7314 100644 --- a/apps/basic-auth-provider/src/apiKey/apiKey.module.ts +++ b/apps/basic-auth-provider/src/apiKey/apiKey.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { ApiKeyModuleBase } from "./base/apiKey.module.base"; import { ApiKeyService } from "./apiKey.service"; import { ApiKeyController } from "./apiKey.controller"; import { ApiKeyResolver } from "./apiKey.resolver"; @Module({ - imports: [ApiKeyModuleBase], + imports: [ApiKeyModuleBase, forwardRef(() => AuthModule)], controllers: [ApiKeyController], providers: [ApiKeyService, ApiKeyResolver], exports: [ApiKeyService], diff --git a/apps/basic-auth-provider/src/apiKey/apiKey.resolver.ts b/apps/basic-auth-provider/src/apiKey/apiKey.resolver.ts index 555ce79..995caed 100644 --- a/apps/basic-auth-provider/src/apiKey/apiKey.resolver.ts +++ b/apps/basic-auth-provider/src/apiKey/apiKey.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { ApiKeyResolverBase } from "./base/apiKey.resolver.base"; import { ApiKey } from "./base/ApiKey"; import { ApiKeyService } from "./apiKey.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => ApiKey) export class ApiKeyResolver extends ApiKeyResolverBase { - constructor(protected readonly service: ApiKeyService) { - super(service); + constructor( + protected readonly service: ApiKeyService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/apiKey/base/apiKey.controller.base.ts b/apps/basic-auth-provider/src/apiKey/base/apiKey.controller.base.ts index bbac6e2..de73e76 100644 --- a/apps/basic-auth-provider/src/apiKey/base/apiKey.controller.base.ts +++ b/apps/basic-auth-provider/src/apiKey/base/apiKey.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { ApiKeyService } from "../apiKey.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { ApiKeyCreateInput } from "./ApiKeyCreateInput"; import { ApiKey } from "./ApiKey"; import { ApiKeyFindManyArgs } from "./ApiKeyFindManyArgs"; import { ApiKeyWhereUniqueInput } from "./ApiKeyWhereUniqueInput"; import { ApiKeyUpdateInput } from "./ApiKeyUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class ApiKeyControllerBase { - constructor(protected readonly service: ApiKeyService) {} + constructor( + protected readonly service: ApiKeyService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: ApiKey }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createApiKey(@common.Body() data: ApiKeyCreateInput): Promise { return await this.service.createApiKey({ data: { @@ -67,9 +85,18 @@ export class ApiKeyControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [ApiKey] }) @ApiNestedQuery(ApiKeyFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async apiKeys(@common.Req() request: Request): Promise { const args = plainToClass(ApiKeyFindManyArgs, request.query); return this.service.apiKeys({ @@ -97,9 +124,18 @@ export class ApiKeyControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: ApiKey }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async apiKey( @common.Param() params: ApiKeyWhereUniqueInput ): Promise { @@ -134,9 +170,18 @@ export class ApiKeyControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: ApiKey }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateApiKey( @common.Param() params: ApiKeyWhereUniqueInput, @common.Body() data: ApiKeyUpdateInput @@ -193,6 +238,14 @@ export class ApiKeyControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: ApiKey }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteApiKey( @common.Param() params: ApiKeyWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/apiKey/base/apiKey.module.base.ts b/apps/basic-auth-provider/src/apiKey/base/apiKey.module.base.ts index 857051d..bc47bea 100644 --- a/apps/basic-auth-provider/src/apiKey/base/apiKey.module.base.ts +++ b/apps/basic-auth-provider/src/apiKey/base/apiKey.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class ApiKeyModuleBase {} diff --git a/apps/basic-auth-provider/src/apiKey/base/apiKey.resolver.base.ts b/apps/basic-auth-provider/src/apiKey/base/apiKey.resolver.base.ts index 99c0b06..34add1e 100644 --- a/apps/basic-auth-provider/src/apiKey/base/apiKey.resolver.base.ts +++ b/apps/basic-auth-provider/src/apiKey/base/apiKey.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { ApiKey } from "./ApiKey"; import { ApiKeyCountArgs } from "./ApiKeyCountArgs"; import { ApiKeyFindManyArgs } from "./ApiKeyFindManyArgs"; @@ -23,10 +29,20 @@ import { DeleteApiKeyArgs } from "./DeleteApiKeyArgs"; import { AppModel } from "../../appModel/base/AppModel"; import { OrigUser } from "../../origUser/base/OrigUser"; import { ApiKeyService } from "../apiKey.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => ApiKey) export class ApiKeyResolverBase { - constructor(protected readonly service: ApiKeyService) {} - + constructor( + protected readonly service: ApiKeyService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) async _apiKeysMeta( @graphql.Args() args: ApiKeyCountArgs ): Promise { @@ -36,12 +52,24 @@ export class ApiKeyResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [ApiKey]) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) async apiKeys(@graphql.Args() args: ApiKeyFindManyArgs): Promise { return this.service.apiKeys(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => ApiKey, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "own", + }) async apiKey( @graphql.Args() args: ApiKeyFindUniqueArgs ): Promise { @@ -52,7 +80,13 @@ export class ApiKeyResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => ApiKey) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "create", + possession: "any", + }) async createApiKey(@graphql.Args() args: CreateApiKeyArgs): Promise { return await this.service.createApiKey({ ...args, @@ -74,7 +108,13 @@ export class ApiKeyResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => ApiKey) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "update", + possession: "any", + }) async updateApiKey( @graphql.Args() args: UpdateApiKeyArgs ): Promise { @@ -108,6 +148,11 @@ export class ApiKeyResolverBase { } @graphql.Mutation(() => ApiKey) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "delete", + possession: "any", + }) async deleteApiKey( @graphql.Args() args: DeleteApiKeyArgs ): Promise { @@ -123,10 +168,16 @@ export class ApiKeyResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => AppModel, { nullable: true, name: "appField", }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "any", + }) async getAppField( @graphql.Parent() parent: ApiKey ): Promise { @@ -138,10 +189,16 @@ export class ApiKeyResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: ApiKey): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/app.module.ts b/apps/basic-auth-provider/src/app.module.ts index c5b6972..9d590e4 100644 --- a/apps/basic-auth-provider/src/app.module.ts +++ b/apps/basic-auth-provider/src/app.module.ts @@ -39,9 +39,14 @@ import { ConfigModule, ConfigService } from "@nestjs/config"; import { GraphQLModule } from "@nestjs/graphql"; import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo"; +import { ACLModule } from "./auth/acl.module"; +import { AuthModule } from "./auth/auth.module"; + @Module({ controllers: [], imports: [ + ACLModule, + AuthModule, EventTypeModule, CredentialModule, DestinationCalendarModule, diff --git a/apps/basic-auth-provider/src/appModel/appModel.controller.ts b/apps/basic-auth-provider/src/appModel/appModel.controller.ts index eaa447e..0b1d402 100644 --- a/apps/basic-auth-provider/src/appModel/appModel.controller.ts +++ b/apps/basic-auth-provider/src/appModel/appModel.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { AppModelService } from "./appModel.service"; import { AppModelControllerBase } from "./base/appModel.controller.base"; @swagger.ApiTags("appModels") @common.Controller("appModels") export class AppModelController extends AppModelControllerBase { - constructor(protected readonly service: AppModelService) { - super(service); + constructor( + protected readonly service: AppModelService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/appModel/appModel.module.ts b/apps/basic-auth-provider/src/appModel/appModel.module.ts index 14c5f07..6fc6a90 100644 --- a/apps/basic-auth-provider/src/appModel/appModel.module.ts +++ b/apps/basic-auth-provider/src/appModel/appModel.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { AppModelModuleBase } from "./base/appModel.module.base"; import { AppModelService } from "./appModel.service"; import { AppModelController } from "./appModel.controller"; import { AppModelResolver } from "./appModel.resolver"; @Module({ - imports: [AppModelModuleBase], + imports: [AppModelModuleBase, forwardRef(() => AuthModule)], controllers: [AppModelController], providers: [AppModelService, AppModelResolver], exports: [AppModelService], diff --git a/apps/basic-auth-provider/src/appModel/appModel.resolver.ts b/apps/basic-auth-provider/src/appModel/appModel.resolver.ts index b7bd12f..d60b177 100644 --- a/apps/basic-auth-provider/src/appModel/appModel.resolver.ts +++ b/apps/basic-auth-provider/src/appModel/appModel.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { AppModelResolverBase } from "./base/appModel.resolver.base"; import { AppModel } from "./base/AppModel"; import { AppModelService } from "./appModel.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => AppModel) export class AppModelResolver extends AppModelResolverBase { - constructor(protected readonly service: AppModelService) { - super(service); + constructor( + protected readonly service: AppModelService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/appModel/base/appModel.controller.base.ts b/apps/basic-auth-provider/src/appModel/base/appModel.controller.base.ts index 3c83cb7..8b55c74 100644 --- a/apps/basic-auth-provider/src/appModel/base/appModel.controller.base.ts +++ b/apps/basic-auth-provider/src/appModel/base/appModel.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { AppModelService } from "../appModel.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { AppModelCreateInput } from "./AppModelCreateInput"; import { AppModel } from "./AppModel"; import { AppModelFindManyArgs } from "./AppModelFindManyArgs"; @@ -32,10 +36,24 @@ import { WebhookFindManyArgs } from "../../webhook/base/WebhookFindManyArgs"; import { Webhook } from "../../webhook/base/Webhook"; import { WebhookWhereUniqueInput } from "../../webhook/base/WebhookWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class AppModelControllerBase { - constructor(protected readonly service: AppModelService) {} + constructor( + protected readonly service: AppModelService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: AppModel }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createAppModel( @common.Body() data: AppModelCreateInput ): Promise { @@ -52,9 +70,18 @@ export class AppModelControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [AppModel] }) @ApiNestedQuery(AppModelFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async appModels(@common.Req() request: Request): Promise { const args = plainToClass(AppModelFindManyArgs, request.query); return this.service.appModels({ @@ -70,9 +97,18 @@ export class AppModelControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: AppModel }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async appModel( @common.Param() params: AppModelWhereUniqueInput ): Promise { @@ -95,9 +131,18 @@ export class AppModelControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: AppModel }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateAppModel( @common.Param() params: AppModelWhereUniqueInput, @common.Body() data: AppModelUpdateInput @@ -128,6 +173,14 @@ export class AppModelControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: AppModel }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteAppModel( @common.Param() params: AppModelWhereUniqueInput ): Promise { @@ -153,8 +206,14 @@ export class AppModelControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/apiKey") @ApiNestedQuery(ApiKeyFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) async findApiKey( @common.Req() request: Request, @common.Param() params: AppModelWhereUniqueInput @@ -192,6 +251,11 @@ export class AppModelControllerBase { } @common.Post("/:id/apiKey") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async connectApiKey( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: ApiKeyWhereUniqueInput[] @@ -209,6 +273,11 @@ export class AppModelControllerBase { } @common.Patch("/:id/apiKey") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async updateApiKey( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: ApiKeyWhereUniqueInput[] @@ -226,6 +295,11 @@ export class AppModelControllerBase { } @common.Delete("/:id/apiKey") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async disconnectApiKey( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: ApiKeyWhereUniqueInput[] @@ -242,8 +316,14 @@ export class AppModelControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/credentials") @ApiNestedQuery(CredentialFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async findCredentials( @common.Req() request: Request, @common.Param() params: AppModelWhereUniqueInput @@ -278,6 +358,11 @@ export class AppModelControllerBase { } @common.Post("/:id/credentials") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async connectCredentials( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: CredentialWhereUniqueInput[] @@ -295,6 +380,11 @@ export class AppModelControllerBase { } @common.Patch("/:id/credentials") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async updateCredentials( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: CredentialWhereUniqueInput[] @@ -312,6 +402,11 @@ export class AppModelControllerBase { } @common.Delete("/:id/credentials") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async disconnectCredentials( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: CredentialWhereUniqueInput[] @@ -328,8 +423,14 @@ export class AppModelControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/webhook") @ApiNestedQuery(WebhookFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async findWebhook( @common.Req() request: Request, @common.Param() params: AppModelWhereUniqueInput @@ -376,6 +477,11 @@ export class AppModelControllerBase { } @common.Post("/:id/webhook") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async connectWebhook( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -393,6 +499,11 @@ export class AppModelControllerBase { } @common.Patch("/:id/webhook") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async updateWebhook( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -410,6 +521,11 @@ export class AppModelControllerBase { } @common.Delete("/:id/webhook") + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async disconnectWebhook( @common.Param() params: AppModelWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/appModel/base/appModel.module.base.ts b/apps/basic-auth-provider/src/appModel/base/appModel.module.base.ts index ce11dc5..957051d 100644 --- a/apps/basic-auth-provider/src/appModel/base/appModel.module.base.ts +++ b/apps/basic-auth-provider/src/appModel/base/appModel.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class AppModelModuleBase {} diff --git a/apps/basic-auth-provider/src/appModel/base/appModel.resolver.base.ts b/apps/basic-auth-provider/src/appModel/base/appModel.resolver.base.ts index 61ed59d..251d864 100644 --- a/apps/basic-auth-provider/src/appModel/base/appModel.resolver.base.ts +++ b/apps/basic-auth-provider/src/appModel/base/appModel.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { AppModel } from "./AppModel"; import { AppModelCountArgs } from "./AppModelCountArgs"; import { AppModelFindManyArgs } from "./AppModelFindManyArgs"; @@ -27,10 +33,20 @@ import { Credential } from "../../credential/base/Credential"; import { WebhookFindManyArgs } from "../../webhook/base/WebhookFindManyArgs"; import { Webhook } from "../../webhook/base/Webhook"; import { AppModelService } from "../appModel.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => AppModel) export class AppModelResolverBase { - constructor(protected readonly service: AppModelService) {} - + constructor( + protected readonly service: AppModelService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "any", + }) async _appModelsMeta( @graphql.Args() args: AppModelCountArgs ): Promise { @@ -40,14 +56,26 @@ export class AppModelResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [AppModel]) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "any", + }) async appModels( @graphql.Args() args: AppModelFindManyArgs ): Promise { return this.service.appModels(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => AppModel, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "own", + }) async appModel( @graphql.Args() args: AppModelFindUniqueArgs ): Promise { @@ -58,7 +86,13 @@ export class AppModelResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => AppModel) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "create", + possession: "any", + }) async createAppModel( @graphql.Args() args: CreateAppModelArgs ): Promise { @@ -68,7 +102,13 @@ export class AppModelResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => AppModel) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "update", + possession: "any", + }) async updateAppModel( @graphql.Args() args: UpdateAppModelArgs ): Promise { @@ -88,6 +128,11 @@ export class AppModelResolverBase { } @graphql.Mutation(() => AppModel) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "delete", + possession: "any", + }) async deleteAppModel( @graphql.Args() args: DeleteAppModelArgs ): Promise { @@ -103,7 +148,13 @@ export class AppModelResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [ApiKey], { name: "apiKey" }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) async findApiKey( @graphql.Parent() parent: AppModel, @graphql.Args() args: ApiKeyFindManyArgs @@ -117,7 +168,13 @@ export class AppModelResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Credential], { name: "credentials" }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async findCredentials( @graphql.Parent() parent: AppModel, @graphql.Args() args: CredentialFindManyArgs @@ -131,7 +188,13 @@ export class AppModelResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Webhook], { name: "webhook" }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async findWebhook( @graphql.Parent() parent: AppModel, @graphql.Args() args: WebhookFindManyArgs diff --git a/apps/basic-auth-provider/src/attendee/attendee.controller.ts b/apps/basic-auth-provider/src/attendee/attendee.controller.ts index 3a99c1a..b68086c 100644 --- a/apps/basic-auth-provider/src/attendee/attendee.controller.ts +++ b/apps/basic-auth-provider/src/attendee/attendee.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { AttendeeService } from "./attendee.service"; import { AttendeeControllerBase } from "./base/attendee.controller.base"; @swagger.ApiTags("attendees") @common.Controller("attendees") export class AttendeeController extends AttendeeControllerBase { - constructor(protected readonly service: AttendeeService) { - super(service); + constructor( + protected readonly service: AttendeeService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/attendee/attendee.module.ts b/apps/basic-auth-provider/src/attendee/attendee.module.ts index e74a5c6..3c0d9b0 100644 --- a/apps/basic-auth-provider/src/attendee/attendee.module.ts +++ b/apps/basic-auth-provider/src/attendee/attendee.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { AttendeeModuleBase } from "./base/attendee.module.base"; import { AttendeeService } from "./attendee.service"; import { AttendeeController } from "./attendee.controller"; import { AttendeeResolver } from "./attendee.resolver"; @Module({ - imports: [AttendeeModuleBase], + imports: [AttendeeModuleBase, forwardRef(() => AuthModule)], controllers: [AttendeeController], providers: [AttendeeService, AttendeeResolver], exports: [AttendeeService], diff --git a/apps/basic-auth-provider/src/attendee/attendee.resolver.ts b/apps/basic-auth-provider/src/attendee/attendee.resolver.ts index 43ecdac..c506599 100644 --- a/apps/basic-auth-provider/src/attendee/attendee.resolver.ts +++ b/apps/basic-auth-provider/src/attendee/attendee.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { AttendeeResolverBase } from "./base/attendee.resolver.base"; import { Attendee } from "./base/Attendee"; import { AttendeeService } from "./attendee.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Attendee) export class AttendeeResolver extends AttendeeResolverBase { - constructor(protected readonly service: AttendeeService) { - super(service); + constructor( + protected readonly service: AttendeeService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/attendee/base/attendee.controller.base.ts b/apps/basic-auth-provider/src/attendee/base/attendee.controller.base.ts index 0a7c04d..450a0b4 100644 --- a/apps/basic-auth-provider/src/attendee/base/attendee.controller.base.ts +++ b/apps/basic-auth-provider/src/attendee/base/attendee.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { AttendeeService } from "../attendee.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { AttendeeCreateInput } from "./AttendeeCreateInput"; import { Attendee } from "./Attendee"; import { AttendeeFindManyArgs } from "./AttendeeFindManyArgs"; import { AttendeeWhereUniqueInput } from "./AttendeeWhereUniqueInput"; import { AttendeeUpdateInput } from "./AttendeeUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class AttendeeControllerBase { - constructor(protected readonly service: AttendeeService) {} + constructor( + protected readonly service: AttendeeService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Attendee }) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createAttendee( @common.Body() data: AttendeeCreateInput ): Promise { @@ -56,9 +74,18 @@ export class AttendeeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Attendee] }) @ApiNestedQuery(AttendeeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async attendees(@common.Req() request: Request): Promise { const args = plainToClass(AttendeeFindManyArgs, request.query); return this.service.attendees({ @@ -79,9 +106,18 @@ export class AttendeeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Attendee }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async attendee( @common.Param() params: AttendeeWhereUniqueInput ): Promise { @@ -109,9 +145,18 @@ export class AttendeeControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Attendee }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateAttendee( @common.Param() params: AttendeeWhereUniqueInput, @common.Body() data: AttendeeUpdateInput @@ -155,6 +200,14 @@ export class AttendeeControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Attendee }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteAttendee( @common.Param() params: AttendeeWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/attendee/base/attendee.module.base.ts b/apps/basic-auth-provider/src/attendee/base/attendee.module.base.ts index 3000fd5..2bbc6ae 100644 --- a/apps/basic-auth-provider/src/attendee/base/attendee.module.base.ts +++ b/apps/basic-auth-provider/src/attendee/base/attendee.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class AttendeeModuleBase {} diff --git a/apps/basic-auth-provider/src/attendee/base/attendee.resolver.base.ts b/apps/basic-auth-provider/src/attendee/base/attendee.resolver.base.ts index 9d6977d..8c17fd4 100644 --- a/apps/basic-auth-provider/src/attendee/base/attendee.resolver.base.ts +++ b/apps/basic-auth-provider/src/attendee/base/attendee.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Attendee } from "./Attendee"; import { AttendeeCountArgs } from "./AttendeeCountArgs"; import { AttendeeFindManyArgs } from "./AttendeeFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateAttendeeArgs } from "./UpdateAttendeeArgs"; import { DeleteAttendeeArgs } from "./DeleteAttendeeArgs"; import { Booking } from "../../booking/base/Booking"; import { AttendeeService } from "../attendee.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Attendee) export class AttendeeResolverBase { - constructor(protected readonly service: AttendeeService) {} + constructor( + protected readonly service: AttendeeService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "any", + }) async _attendeesMeta( @graphql.Args() args: AttendeeCountArgs ): Promise { @@ -35,14 +51,26 @@ export class AttendeeResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Attendee]) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "any", + }) async attendees( @graphql.Args() args: AttendeeFindManyArgs ): Promise { return this.service.attendees(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Attendee, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "own", + }) async attendee( @graphql.Args() args: AttendeeFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class AttendeeResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Attendee) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "create", + possession: "any", + }) async createAttendee( @graphql.Args() args: CreateAttendeeArgs ): Promise { @@ -71,7 +105,13 @@ export class AttendeeResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Attendee) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "update", + possession: "any", + }) async updateAttendee( @graphql.Args() args: UpdateAttendeeArgs ): Promise { @@ -99,6 +139,11 @@ export class AttendeeResolverBase { } @graphql.Mutation(() => Attendee) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "delete", + possession: "any", + }) async deleteAttendee( @graphql.Args() args: DeleteAttendeeArgs ): Promise { @@ -114,10 +159,16 @@ export class AttendeeResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Booking, { nullable: true, name: "booking", }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async getBooking( @graphql.Parent() parent: Attendee ): Promise { diff --git a/apps/basic-auth-provider/src/auth/Credentials.ts b/apps/basic-auth-provider/src/auth/Credentials.ts new file mode 100644 index 0000000..9ac6798 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/Credentials.ts @@ -0,0 +1,21 @@ +import { ApiProperty } from "@nestjs/swagger"; +import { InputType, Field } from "@nestjs/graphql"; +import { IsString } from "class-validator"; + +@InputType() +export class Credentials { + @ApiProperty({ + required: true, + type: String, + }) + @IsString() + @Field(() => String, { nullable: false }) + username!: string; + @ApiProperty({ + required: true, + type: String, + }) + @IsString() + @Field(() => String, { nullable: false }) + password!: string; +} diff --git a/apps/basic-auth-provider/src/auth/IAuthStrategy.ts b/apps/basic-auth-provider/src/auth/IAuthStrategy.ts new file mode 100644 index 0000000..7406267 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/IAuthStrategy.ts @@ -0,0 +1,6 @@ +import { UserInfo } from "./UserInfo"; + +export interface IAuthStrategy { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + validate: (...any: any) => Promise; +} diff --git a/apps/basic-auth-provider/src/auth/ITokenService.ts b/apps/basic-auth-provider/src/auth/ITokenService.ts new file mode 100644 index 0000000..7983189 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/ITokenService.ts @@ -0,0 +1,9 @@ +export interface ITokenPayload { + id: string; + username: string; + password: string; +} + +export interface ITokenService { + createToken: ({ id, username, password }: ITokenPayload) => Promise; +} diff --git a/apps/basic-auth-provider/src/auth/LoginArgs.ts b/apps/basic-auth-provider/src/auth/LoginArgs.ts new file mode 100644 index 0000000..66a0b2f --- /dev/null +++ b/apps/basic-auth-provider/src/auth/LoginArgs.ts @@ -0,0 +1,12 @@ +import { ArgsType, Field } from "@nestjs/graphql"; +import { ValidateNested } from "class-validator"; +import { Type } from "class-transformer"; +import { Credentials } from "./Credentials"; + +@ArgsType() +export class LoginArgs { + @Field(() => Credentials, { nullable: false }) + @Type(() => Credentials) + @ValidateNested() + credentials!: Credentials; +} diff --git a/apps/basic-auth-provider/src/auth/UserInfo.ts b/apps/basic-auth-provider/src/auth/UserInfo.ts new file mode 100644 index 0000000..ef61dc4 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/UserInfo.ts @@ -0,0 +1,14 @@ +import { Field, ObjectType } from "@nestjs/graphql"; +import { User } from "../user/base/User"; + +@ObjectType() +export class UserInfo implements Partial { + @Field(() => String) + id!: string; + @Field(() => String) + username!: string; + @Field(() => [String]) + roles!: string[]; + @Field(() => String, { nullable: true }) + accessToken?: string; +} diff --git a/apps/basic-auth-provider/src/auth/abac.util.ts b/apps/basic-auth-provider/src/auth/abac.util.ts new file mode 100644 index 0000000..2f0dcab --- /dev/null +++ b/apps/basic-auth-provider/src/auth/abac.util.ts @@ -0,0 +1,19 @@ +import { Permission } from "accesscontrol"; + +/** + * @returns attributes not allowed to appear on given data according to given + * attributeMatchers + */ +export function getInvalidAttributes( + permission: Permission, + // eslint-disable-next-line @typescript-eslint/ban-types + data: Object +): string[] { + // The structuredClone call is necessary because the + // `Permission.filter` function doesn't consider objects + // with null prototypes. And in graphql requests, the + // object passed here by the request interceptor is an object + // with a null prototype. + const filteredData = permission.filter(structuredClone(data)); + return Object.keys(data).filter((key) => !(key in filteredData)); +} diff --git a/apps/basic-auth-provider/src/auth/acl.module.ts b/apps/basic-auth-provider/src/auth/acl.module.ts new file mode 100644 index 0000000..040e7e5 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/acl.module.ts @@ -0,0 +1,6 @@ +import { AccessControlModule, RolesBuilder } from "nest-access-control"; + +import grants from "../grants.json"; + +// eslint-disable-next-line @typescript-eslint/naming-convention +export const ACLModule = AccessControlModule.forRoles(new RolesBuilder(grants)); diff --git a/apps/basic-auth-provider/src/auth/auth.controller.ts b/apps/basic-auth-provider/src/auth/auth.controller.ts new file mode 100644 index 0000000..7ae732f --- /dev/null +++ b/apps/basic-auth-provider/src/auth/auth.controller.ts @@ -0,0 +1,15 @@ +import { Body, Controller, Post } from "@nestjs/common"; +import { ApiTags } from "@nestjs/swagger"; +import { AuthService } from "./auth.service"; +import { Credentials } from "../auth/Credentials"; +import { UserInfo } from "./UserInfo"; + +@ApiTags("auth") +@Controller() +export class AuthController { + constructor(private readonly authService: AuthService) {} + @Post("login") + async login(@Body() body: Credentials): Promise { + return this.authService.login(body); + } +} diff --git a/apps/basic-auth-provider/src/auth/auth.module.ts b/apps/basic-auth-provider/src/auth/auth.module.ts new file mode 100644 index 0000000..c533753 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/auth.module.ts @@ -0,0 +1,25 @@ +import { forwardRef, Module } from "@nestjs/common"; +import { PassportModule } from "@nestjs/passport"; +import { SecretsManagerModule } from "../providers/secrets/secretsManager.module"; +import { SecretsManagerService } from "../providers/secrets/secretsManager.service"; +import { AuthController } from "./auth.controller"; +import { AuthResolver } from "./auth.resolver"; +import { AuthService } from "./auth.service"; +import { BasicStrategy } from "./basic/basic.strategy"; +import { PasswordService } from "./password.service"; +import { TokenService } from "./token.service"; +import { UserModule } from "../user/user.module"; + +@Module({ + imports: [forwardRef(() => UserModule), PassportModule, SecretsManagerModule], + providers: [ + AuthService, + BasicStrategy, + PasswordService, + AuthResolver, + TokenService, + ], + controllers: [AuthController], + exports: [AuthService, PasswordService], +}) +export class AuthModule {} diff --git a/apps/basic-auth-provider/src/auth/auth.resolver.ts b/apps/basic-auth-provider/src/auth/auth.resolver.ts new file mode 100644 index 0000000..c186f41 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/auth.resolver.ts @@ -0,0 +1,23 @@ +import * as common from "@nestjs/common"; +import { Args, Mutation, Query, Resolver } from "@nestjs/graphql"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { AuthService } from "./auth.service"; +import { GqlDefaultAuthGuard } from "./gqlDefaultAuth.guard"; +import { UserData } from "./userData.decorator"; +import { LoginArgs } from "./LoginArgs"; +import { UserInfo } from "./UserInfo"; + +@Resolver(UserInfo) +export class AuthResolver { + constructor(private readonly authService: AuthService) {} + @Mutation(() => UserInfo) + async login(@Args() args: LoginArgs): Promise { + return this.authService.login(args.credentials); + } + + @Query(() => UserInfo) + @common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) + async userInfo(@UserData() entityInfo: UserInfo): Promise { + return entityInfo; + } +} diff --git a/apps/basic-auth-provider/src/auth/auth.service.spec.ts b/apps/basic-auth-provider/src/auth/auth.service.spec.ts new file mode 100644 index 0000000..90b04f4 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/auth.service.spec.ts @@ -0,0 +1,114 @@ +import { Test, TestingModule } from "@nestjs/testing"; +import { AuthService } from "./auth.service"; +import { Credentials } from "./Credentials"; +import { PasswordService } from "./password.service"; +import { TokenService } from "./token.service"; +import { VALID_ID } from "../tests/auth/constants"; +import { UserService } from "../user/user.service"; + +const VALID_CREDENTIALS: Credentials = { + username: "Valid User", + password: "Valid User Password", +}; +const INVALID_CREDENTIALS: Credentials = { + username: "Invalid User", + password: "Invalid User Password", +}; +const USER: any = { + ...VALID_CREDENTIALS, + createdAt: new Date(), + firstName: "ofek", + id: VALID_ID, + lastName: "gabay", + roles: ["admin"], + updatedAt: new Date(), +}; + +const SIGN_TOKEN = "SIGN_TOKEN"; + +const authEntityService = { + user(args: { where: { username: string } }): any | null { + if (args.where.username === VALID_CREDENTIALS.username) { + return USER; + } + return null; + }, +}; + +const passwordService = { + compare(password: string, encrypted: string) { + return true; + }, +}; + +const tokenService = { + createToken(username: string, password: string) { + return SIGN_TOKEN; + }, +}; + +describe("AuthService", () => { + //ARRANGE + let service: AuthService; + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + { + provide: UserService, + useValue: authEntityService, + }, + { + provide: PasswordService, + useValue: passwordService, + }, + { + provide: TokenService, + useValue: tokenService, + }, + AuthService, + ], + }).compile(); + + service = module.get(AuthService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); + + describe("Testing the authService.validateUser()", () => { + it("should validate a valid user", async () => { + await expect( + service.validateUser( + VALID_CREDENTIALS.username, + VALID_CREDENTIALS.password + ) + ).resolves.toEqual({ + username: USER.username, + roles: USER.roles, + id: USER.id, + }); + }); + + it("should not validate a invalid user", async () => { + await expect( + service.validateUser( + INVALID_CREDENTIALS.username, + INVALID_CREDENTIALS.password + ) + ).resolves.toBe(null); + }); + }); + + describe("Testing the authService.login()", () => { + it("should return userInfo object for correct username and password", async () => { + const loginResult = await service.login(VALID_CREDENTIALS); + expect(loginResult).toEqual({ + username: USER.username, + roles: USER.roles, + accessToken: SIGN_TOKEN, + id: USER.id, + }); + }); + }); +}); diff --git a/apps/basic-auth-provider/src/auth/auth.service.ts b/apps/basic-auth-provider/src/auth/auth.service.ts new file mode 100644 index 0000000..9f6add2 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/auth.service.ts @@ -0,0 +1,49 @@ +import { Injectable, UnauthorizedException } from "@nestjs/common"; +import { Credentials } from "./Credentials"; +import { PasswordService } from "./password.service"; +import { TokenService } from "./token.service"; +import { UserInfo } from "./UserInfo"; +import { UserService } from "../user/user.service"; + +@Injectable() +export class AuthService { + constructor( + private readonly passwordService: PasswordService, + private readonly tokenService: TokenService, + private readonly userService: UserService + ) {} + + async validateUser( + username: string, + password: string + ): Promise { + const user = await this.userService.user({ + where: { username }, + }); + if (user && (await this.passwordService.compare(password, user.password))) { + const { id, roles } = user; + const roleList = roles as string[]; + return { id, username, roles: roleList }; + } + return null; + } + async login(credentials: Credentials): Promise { + const { username, password } = credentials; + const user = await this.validateUser( + credentials.username, + credentials.password + ); + if (!user) { + throw new UnauthorizedException("The passed credentials are incorrect"); + } + const accessToken = await this.tokenService.createToken({ + id: user.id, + username, + password, + }); + return { + accessToken, + ...user, + }; + } +} diff --git a/apps/basic-auth-provider/src/auth/base/token.service.base.ts b/apps/basic-auth-provider/src/auth/base/token.service.base.ts new file mode 100644 index 0000000..f2a64fe --- /dev/null +++ b/apps/basic-auth-provider/src/auth/base/token.service.base.ts @@ -0,0 +1,21 @@ +import { Injectable } from "@nestjs/common"; +import { INVALID_PASSWORD_ERROR, INVALID_USERNAME_ERROR } from "../constants"; +import { ITokenService, ITokenPayload } from "../ITokenService"; +/** + * TokenServiceBase is a basic http implementation of ITokenService + */ +@Injectable() +export class TokenServiceBase implements ITokenService { + /** + * + * @object { username: String, password: String } + * @returns a base64 string of the username and password + */ + createToken({ username, password }: ITokenPayload): Promise { + if (!username) return Promise.reject(INVALID_USERNAME_ERROR); + if (!password) return Promise.reject(INVALID_PASSWORD_ERROR); + return Promise.resolve( + Buffer.from(`${username}:${password}`).toString("base64") + ); + } +} diff --git a/apps/basic-auth-provider/src/auth/basic/base/basic.strategy.base.ts b/apps/basic-auth-provider/src/auth/basic/base/basic.strategy.base.ts new file mode 100644 index 0000000..e138356 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/basic/base/basic.strategy.base.ts @@ -0,0 +1,23 @@ +import { UnauthorizedException } from "@nestjs/common"; +import { PassportStrategy } from "@nestjs/passport"; +import { BasicStrategy as Strategy } from "passport-http"; +import { AuthService } from "../../auth.service"; +import { IAuthStrategy } from "../../IAuthStrategy"; +import { UserInfo } from "../../UserInfo"; + +export class BasicStrategyBase + extends PassportStrategy(Strategy) + implements IAuthStrategy +{ + constructor(protected readonly authService: AuthService) { + super(); + } + + async validate(username: string, password: string): Promise { + const user = await this.authService.validateUser(username, password); + if (!user) { + throw new UnauthorizedException(); + } + return user; + } +} diff --git a/apps/basic-auth-provider/src/auth/basic/basic.strategy.ts b/apps/basic-auth-provider/src/auth/basic/basic.strategy.ts new file mode 100644 index 0000000..f087795 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/basic/basic.strategy.ts @@ -0,0 +1,10 @@ +import { Injectable } from "@nestjs/common"; +import { AuthService } from "../auth.service"; +import { BasicStrategyBase } from "./base/basic.strategy.base"; + +@Injectable() +export class BasicStrategy extends BasicStrategyBase { + constructor(protected readonly authService: AuthService) { + super(authService); + } +} diff --git a/apps/basic-auth-provider/src/auth/basic/basicAuth.guard.ts b/apps/basic-auth-provider/src/auth/basic/basicAuth.guard.ts new file mode 100644 index 0000000..9c92fdd --- /dev/null +++ b/apps/basic-auth-provider/src/auth/basic/basicAuth.guard.ts @@ -0,0 +1,3 @@ +import { AuthGuard } from "@nestjs/passport"; + +export class BasicAuthGuard extends AuthGuard("basic") {} diff --git a/apps/basic-auth-provider/src/auth/constants.ts b/apps/basic-auth-provider/src/auth/constants.ts new file mode 100644 index 0000000..59f9f7d --- /dev/null +++ b/apps/basic-auth-provider/src/auth/constants.ts @@ -0,0 +1,2 @@ +export const INVALID_USERNAME_ERROR = "Invalid username"; +export const INVALID_PASSWORD_ERROR = "Invalid password"; diff --git a/apps/basic-auth-provider/src/auth/defaultAuth.guard.ts b/apps/basic-auth-provider/src/auth/defaultAuth.guard.ts new file mode 100644 index 0000000..d1ec3db --- /dev/null +++ b/apps/basic-auth-provider/src/auth/defaultAuth.guard.ts @@ -0,0 +1,27 @@ +import { Observable } from "rxjs"; +import { ExecutionContext, Injectable } from "@nestjs/common"; +import { Reflector } from "@nestjs/core"; +import { IS_PUBLIC_KEY } from "../decorators/public.decorator"; +import { BasicAuthGuard } from "./basic/basicAuth.guard"; + +@Injectable() +export class DefaultAuthGuard extends BasicAuthGuard { + constructor(private readonly reflector: Reflector) { + super(); + } + + canActivate( + context: ExecutionContext + ): boolean | Promise | Observable { + const isPublic = this.reflector.get( + IS_PUBLIC_KEY, + context.getHandler() + ); + + if (isPublic) { + return true; + } + + return super.canActivate(context); + } +} diff --git a/apps/basic-auth-provider/src/auth/gqlAC.guard.ts b/apps/basic-auth-provider/src/auth/gqlAC.guard.ts new file mode 100644 index 0000000..dacac55 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/gqlAC.guard.ts @@ -0,0 +1,11 @@ +import { ExecutionContext } from "@nestjs/common"; +import { GqlExecutionContext } from "@nestjs/graphql"; +import { ACGuard } from "nest-access-control"; + +export class GqlACGuard extends ACGuard { + async getUser(context: ExecutionContext): Promise { + const ctx = GqlExecutionContext.create(context); + const request = ctx.getContext<{ req: { user: User } }>().req; + return request.user; + } +} diff --git a/apps/basic-auth-provider/src/auth/gqlDefaultAuth.guard.ts b/apps/basic-auth-provider/src/auth/gqlDefaultAuth.guard.ts new file mode 100644 index 0000000..abebd93 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/gqlDefaultAuth.guard.ts @@ -0,0 +1,12 @@ +import { ExecutionContext } from "@nestjs/common"; +import { GqlExecutionContext } from "@nestjs/graphql"; +import type { Request } from "express"; +import { DefaultAuthGuard } from "./defaultAuth.guard"; + +export class GqlDefaultAuthGuard extends DefaultAuthGuard { + // This method is required for the interface - do not delete it. + getRequest(context: ExecutionContext): Request { + const ctx = GqlExecutionContext.create(context); + return ctx.getContext<{ req: Request }>().req; + } +} diff --git a/apps/basic-auth-provider/src/auth/gqlUserRoles.decorator.ts b/apps/basic-auth-provider/src/auth/gqlUserRoles.decorator.ts new file mode 100644 index 0000000..5ea256b --- /dev/null +++ b/apps/basic-auth-provider/src/auth/gqlUserRoles.decorator.ts @@ -0,0 +1,19 @@ +import { createParamDecorator, ExecutionContext } from "@nestjs/common"; +import { GqlExecutionContext } from "@nestjs/graphql"; + +/** + * Access the user roles from the request object i.e `req.user.roles`. + * + * You can pass an optional property key to the decorator to get it from the user object + * e.g `@UserRoles('permissions')` will return the `req.user.permissions` instead. + */ +export const UserRoles = createParamDecorator( + (data: string, context: ExecutionContext) => { + const ctx = GqlExecutionContext.create(context); + const request = ctx.getContext<{ req: { user: any } }>().req; + if (!request.user) { + return null; + } + return data ? request.user[data] : request.user.roles; + } +); diff --git a/apps/basic-auth-provider/src/auth/password.service.spec.ts b/apps/basic-auth-provider/src/auth/password.service.spec.ts new file mode 100644 index 0000000..309c8c0 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/password.service.spec.ts @@ -0,0 +1,69 @@ +import { ConfigService } from "@nestjs/config"; +import { Test, TestingModule } from "@nestjs/testing"; +import { PasswordService } from "./password.service"; + +const EXAMPLE_PASSWORD = "examplePassword"; +const EXAMPLE_HASHED_PASSWORD = "exampleHashedPassword"; + +const EXAMPLE_SALT_OR_ROUNDS = 1; + +const configServiceGetMock = jest.fn(() => { + return EXAMPLE_SALT_OR_ROUNDS; +}); + +jest.mock("bcrypt", () => ({ + hash: jest.fn(), + compare: jest.fn(), +})); + +const { hash, compare } = jest.requireMock("bcrypt"); + +hash.mockImplementation(async () => EXAMPLE_HASHED_PASSWORD); + +compare.mockImplementation(async () => true); + +describe("PasswordService", () => { + let service: PasswordService; + + beforeEach(async () => { + jest.clearAllMocks(); + const module: TestingModule = await Test.createTestingModule({ + providers: [ + PasswordService, + { + provide: ConfigService, + useClass: jest.fn(() => ({ + get: configServiceGetMock, + })), + }, + ], + imports: [], + }).compile(); + + service = module.get(PasswordService); + }); + + it("should be defined", () => { + expect(service).toBeDefined(); + }); + + it("should have salt defined", () => { + expect(service.salt).toEqual(EXAMPLE_SALT_OR_ROUNDS); + }); + + it("should compare a password", async () => { + const args = { + password: EXAMPLE_PASSWORD, + hashedPassword: EXAMPLE_HASHED_PASSWORD, + }; + await expect( + service.compare(args.password, args.hashedPassword) + ).resolves.toEqual(true); + }); + + it("should hash a password", async () => { + await expect(service.hash(EXAMPLE_PASSWORD)).resolves.toEqual( + EXAMPLE_HASHED_PASSWORD + ); + }); +}); diff --git a/apps/basic-auth-provider/src/auth/password.service.ts b/apps/basic-auth-provider/src/auth/password.service.ts new file mode 100644 index 0000000..377b64b --- /dev/null +++ b/apps/basic-auth-provider/src/auth/password.service.ts @@ -0,0 +1,64 @@ +import { Injectable } from "@nestjs/common"; +import { hash, compare } from "bcrypt"; +import { ConfigService } from "@nestjs/config"; + +/** Salt or number of rounds to generate a salt */ +export type Salt = string | number; + +const BCRYPT_SALT_VAR = "BCRYPT_SALT"; +const UNDEFINED_SALT_OR_ROUNDS_ERROR = `${BCRYPT_SALT_VAR} is not defined`; +const SALT_OR_ROUNDS_TYPE_ERROR = `${BCRYPT_SALT_VAR} must be a positive integer or text`; + +@Injectable() +export class PasswordService { + /** + * the salt to be used to hash the password. if specified as a number then a + * salt will be generated with the specified number of rounds and used + */ + salt: Salt; + + constructor(private configService: ConfigService) { + const saltOrRounds = this.configService.get(BCRYPT_SALT_VAR); + this.salt = parseSalt(saltOrRounds); + } + + /** + * + * @param password the password to be encrypted. + * @param encrypted the encrypted password to be compared against. + * @returns whether the password match the encrypted password + */ + compare(password: string, encrypted: string): Promise { + return compare(password, encrypted); + } + + /** + * @param password the password to be encrypted + * @return encrypted password + */ + hash(password: string): Promise { + return hash(password, this.salt); + } +} + +/** + * Parses a salt environment variable value. + * If a number string value is given tries to parse it as a number of rounds to generate a salt + * @param value salt environment variable value + * @returns salt or number of rounds to generate a salt + */ +export function parseSalt(value: string | undefined): Salt { + if (value === undefined) { + throw new Error(UNDEFINED_SALT_OR_ROUNDS_ERROR); + } + + const rounds = Number(value); + + if (Number.isNaN(rounds)) { + return value; + } + if (!Number.isInteger(rounds) || rounds < 0) { + throw new Error(SALT_OR_ROUNDS_TYPE_ERROR); + } + return rounds; +} diff --git a/apps/basic-auth-provider/src/auth/token.service.ts b/apps/basic-auth-provider/src/auth/token.service.ts new file mode 100644 index 0000000..2ee079c --- /dev/null +++ b/apps/basic-auth-provider/src/auth/token.service.ts @@ -0,0 +1,5 @@ +import { ITokenService } from "./ITokenService"; + +import { TokenServiceBase } from "./base/token.service.base"; + +export class TokenService extends TokenServiceBase implements ITokenService {} diff --git a/apps/basic-auth-provider/src/auth/userData.decorator.ts b/apps/basic-auth-provider/src/auth/userData.decorator.ts new file mode 100644 index 0000000..6a40ad1 --- /dev/null +++ b/apps/basic-auth-provider/src/auth/userData.decorator.ts @@ -0,0 +1,30 @@ +import { createParamDecorator, ExecutionContext } from "@nestjs/common"; +import { GqlContextType, GqlExecutionContext } from "@nestjs/graphql"; +import { User } from "@prisma/client"; + +/** + * Access the user data from the request object i.e `req.user`. + */ +function userFactory(ctx: ExecutionContext): User { + const contextType = ctx.getType(); + if (contextType === "http") { + // do something that is only important in the context of regular HTTP requests (REST) + const { user } = ctx.switchToHttp().getRequest(); + return user; + } else if (contextType === "rpc") { + // do something that is only important in the context of Microservice requests + throw new Error("Rpc context is not implemented yet"); + } else if (contextType === "ws") { + // do something that is only important in the context of Websockets requests + throw new Error("Websockets context is not implemented yet"); + } else if (ctx.getType() === "graphql") { + // do something that is only important in the context of GraphQL requests + const gqlExecutionContext = GqlExecutionContext.create(ctx); + return gqlExecutionContext.getContext().req.user; + } + throw new Error("Invalid context"); +} + +export const UserData = createParamDecorator( + (data, ctx: ExecutionContext) => userFactory(ctx) +); diff --git a/apps/basic-auth-provider/src/availability/availability.controller.ts b/apps/basic-auth-provider/src/availability/availability.controller.ts index a7efd5f..c9e80c9 100644 --- a/apps/basic-auth-provider/src/availability/availability.controller.ts +++ b/apps/basic-auth-provider/src/availability/availability.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { AvailabilityService } from "./availability.service"; import { AvailabilityControllerBase } from "./base/availability.controller.base"; @swagger.ApiTags("availabilities") @common.Controller("availabilities") export class AvailabilityController extends AvailabilityControllerBase { - constructor(protected readonly service: AvailabilityService) { - super(service); + constructor( + protected readonly service: AvailabilityService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/availability/availability.module.ts b/apps/basic-auth-provider/src/availability/availability.module.ts index c21340d..1344c3e 100644 --- a/apps/basic-auth-provider/src/availability/availability.module.ts +++ b/apps/basic-auth-provider/src/availability/availability.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { AvailabilityModuleBase } from "./base/availability.module.base"; import { AvailabilityService } from "./availability.service"; import { AvailabilityController } from "./availability.controller"; import { AvailabilityResolver } from "./availability.resolver"; @Module({ - imports: [AvailabilityModuleBase], + imports: [AvailabilityModuleBase, forwardRef(() => AuthModule)], controllers: [AvailabilityController], providers: [AvailabilityService, AvailabilityResolver], exports: [AvailabilityService], diff --git a/apps/basic-auth-provider/src/availability/availability.resolver.ts b/apps/basic-auth-provider/src/availability/availability.resolver.ts index 3d4a089..713795b 100644 --- a/apps/basic-auth-provider/src/availability/availability.resolver.ts +++ b/apps/basic-auth-provider/src/availability/availability.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { AvailabilityResolverBase } from "./base/availability.resolver.base"; import { Availability } from "./base/Availability"; import { AvailabilityService } from "./availability.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Availability) export class AvailabilityResolver extends AvailabilityResolverBase { - constructor(protected readonly service: AvailabilityService) { - super(service); + constructor( + protected readonly service: AvailabilityService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/availability/base/availability.controller.base.ts b/apps/basic-auth-provider/src/availability/base/availability.controller.base.ts index 7cb5cdb..7ab04dd 100644 --- a/apps/basic-auth-provider/src/availability/base/availability.controller.base.ts +++ b/apps/basic-auth-provider/src/availability/base/availability.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { AvailabilityService } from "../availability.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { AvailabilityCreateInput } from "./AvailabilityCreateInput"; import { Availability } from "./Availability"; import { AvailabilityFindManyArgs } from "./AvailabilityFindManyArgs"; import { AvailabilityWhereUniqueInput } from "./AvailabilityWhereUniqueInput"; import { AvailabilityUpdateInput } from "./AvailabilityUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class AvailabilityControllerBase { - constructor(protected readonly service: AvailabilityService) {} + constructor( + protected readonly service: AvailabilityService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Availability }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createAvailability( @common.Body() data: AvailabilityCreateInput ): Promise { @@ -82,9 +100,18 @@ export class AvailabilityControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Availability] }) @ApiNestedQuery(AvailabilityFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async availabilities( @common.Req() request: Request ): Promise { @@ -121,9 +148,18 @@ export class AvailabilityControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Availability }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async availability( @common.Param() params: AvailabilityWhereUniqueInput ): Promise { @@ -165,9 +201,18 @@ export class AvailabilityControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Availability }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateAvailability( @common.Param() params: AvailabilityWhereUniqueInput, @common.Body() data: AvailabilityUpdateInput @@ -237,6 +282,14 @@ export class AvailabilityControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Availability }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteAvailability( @common.Param() params: AvailabilityWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/availability/base/availability.module.base.ts b/apps/basic-auth-provider/src/availability/base/availability.module.base.ts index 31f1d1b..9507cd9 100644 --- a/apps/basic-auth-provider/src/availability/base/availability.module.base.ts +++ b/apps/basic-auth-provider/src/availability/base/availability.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class AvailabilityModuleBase {} diff --git a/apps/basic-auth-provider/src/availability/base/availability.resolver.base.ts b/apps/basic-auth-provider/src/availability/base/availability.resolver.base.ts index 5337a38..68b8a49 100644 --- a/apps/basic-auth-provider/src/availability/base/availability.resolver.base.ts +++ b/apps/basic-auth-provider/src/availability/base/availability.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Availability } from "./Availability"; import { AvailabilityCountArgs } from "./AvailabilityCountArgs"; import { AvailabilityFindManyArgs } from "./AvailabilityFindManyArgs"; @@ -24,10 +30,20 @@ import { EventType } from "../../eventType/base/EventType"; import { Schedule } from "../../schedule/base/Schedule"; import { OrigUser } from "../../origUser/base/OrigUser"; import { AvailabilityService } from "../availability.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Availability) export class AvailabilityResolverBase { - constructor(protected readonly service: AvailabilityService) {} - + constructor( + protected readonly service: AvailabilityService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async _availabilitiesMeta( @graphql.Args() args: AvailabilityCountArgs ): Promise { @@ -37,14 +53,26 @@ export class AvailabilityResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Availability]) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async availabilities( @graphql.Args() args: AvailabilityFindManyArgs ): Promise { return this.service.availabilities(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Availability, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "own", + }) async availability( @graphql.Args() args: AvailabilityFindUniqueArgs ): Promise { @@ -55,7 +83,13 @@ export class AvailabilityResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Availability) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "create", + possession: "any", + }) async createAvailability( @graphql.Args() args: CreateAvailabilityArgs ): Promise { @@ -85,7 +119,13 @@ export class AvailabilityResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Availability) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "update", + possession: "any", + }) async updateAvailability( @graphql.Args() args: UpdateAvailabilityArgs ): Promise { @@ -125,6 +165,11 @@ export class AvailabilityResolverBase { } @graphql.Mutation(() => Availability) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "delete", + possession: "any", + }) async deleteAvailability( @graphql.Args() args: DeleteAvailabilityArgs ): Promise { @@ -140,10 +185,16 @@ export class AvailabilityResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: Availability ): Promise { @@ -155,10 +206,16 @@ export class AvailabilityResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Schedule, { nullable: true, name: "schedule", }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) async getSchedule( @graphql.Parent() parent: Availability ): Promise { @@ -170,10 +227,16 @@ export class AvailabilityResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser( @graphql.Parent() parent: Availability ): Promise { diff --git a/apps/basic-auth-provider/src/booking/base/booking.controller.base.ts b/apps/basic-auth-provider/src/booking/base/booking.controller.base.ts index 7d87ca4..1e78cce 100644 --- a/apps/basic-auth-provider/src/booking/base/booking.controller.base.ts +++ b/apps/basic-auth-provider/src/booking/base/booking.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { BookingService } from "../booking.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { BookingCreateInput } from "./BookingCreateInput"; import { Booking } from "./Booking"; import { BookingFindManyArgs } from "./BookingFindManyArgs"; @@ -35,10 +39,24 @@ import { WorkflowReminderFindManyArgs } from "../../workflowReminder/base/Workfl import { WorkflowReminder } from "../../workflowReminder/base/WorkflowReminder"; import { WorkflowReminderWhereUniqueInput } from "../../workflowReminder/base/WorkflowReminderWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class BookingControllerBase { - constructor(protected readonly service: BookingService) {} + constructor( + protected readonly service: BookingService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Booking }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createBooking( @common.Body() data: BookingCreateInput ): Promise { @@ -122,9 +140,18 @@ export class BookingControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Booking] }) @ApiNestedQuery(BookingFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async bookings(@common.Req() request: Request): Promise { const args = plainToClass(BookingFindManyArgs, request.query); return this.service.bookings({ @@ -181,9 +208,18 @@ export class BookingControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Booking }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async booking( @common.Param() params: BookingWhereUniqueInput ): Promise { @@ -247,9 +283,18 @@ export class BookingControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Booking }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateBooking( @common.Param() params: BookingWhereUniqueInput, @common.Body() data: BookingUpdateInput @@ -347,6 +392,14 @@ export class BookingControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Booking }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteBooking( @common.Param() params: BookingWhereUniqueInput ): Promise { @@ -413,8 +466,14 @@ export class BookingControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/attendees") @ApiNestedQuery(AttendeeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "any", + }) async findAttendees( @common.Req() request: Request, @common.Param() params: BookingWhereUniqueInput @@ -445,6 +504,11 @@ export class BookingControllerBase { } @common.Post("/:id/attendees") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async connectAttendees( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: AttendeeWhereUniqueInput[] @@ -462,6 +526,11 @@ export class BookingControllerBase { } @common.Patch("/:id/attendees") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async updateAttendees( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: AttendeeWhereUniqueInput[] @@ -479,6 +548,11 @@ export class BookingControllerBase { } @common.Delete("/:id/attendees") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async disconnectAttendees( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: AttendeeWhereUniqueInput[] @@ -495,8 +569,14 @@ export class BookingControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/payment") @ApiNestedQuery(PaymentFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "any", + }) async findPayment( @common.Req() request: Request, @common.Param() params: BookingWhereUniqueInput @@ -533,6 +613,11 @@ export class BookingControllerBase { } @common.Post("/:id/payment") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async connectPayment( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: PaymentWhereUniqueInput[] @@ -550,6 +635,11 @@ export class BookingControllerBase { } @common.Patch("/:id/payment") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async updatePayment( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: PaymentWhereUniqueInput[] @@ -567,6 +657,11 @@ export class BookingControllerBase { } @common.Delete("/:id/payment") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async disconnectPayment( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: PaymentWhereUniqueInput[] @@ -583,8 +678,14 @@ export class BookingControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/references") @ApiNestedQuery(BookingReferenceFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "any", + }) async findReferences( @common.Req() request: Request, @common.Param() params: BookingWhereUniqueInput @@ -618,6 +719,11 @@ export class BookingControllerBase { } @common.Post("/:id/references") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async connectReferences( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: BookingReferenceWhereUniqueInput[] @@ -635,6 +741,11 @@ export class BookingControllerBase { } @common.Patch("/:id/references") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async updateReferences( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: BookingReferenceWhereUniqueInput[] @@ -652,6 +763,11 @@ export class BookingControllerBase { } @common.Delete("/:id/references") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async disconnectReferences( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: BookingReferenceWhereUniqueInput[] @@ -668,8 +784,14 @@ export class BookingControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/workflowReminders") @ApiNestedQuery(WorkflowReminderFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) async findWorkflowReminders( @common.Req() request: Request, @common.Param() params: BookingWhereUniqueInput @@ -706,6 +828,11 @@ export class BookingControllerBase { } @common.Post("/:id/workflowReminders") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async connectWorkflowReminders( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: WorkflowReminderWhereUniqueInput[] @@ -723,6 +850,11 @@ export class BookingControllerBase { } @common.Patch("/:id/workflowReminders") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async updateWorkflowReminders( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: WorkflowReminderWhereUniqueInput[] @@ -740,6 +872,11 @@ export class BookingControllerBase { } @common.Delete("/:id/workflowReminders") + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async disconnectWorkflowReminders( @common.Param() params: BookingWhereUniqueInput, @common.Body() body: WorkflowReminderWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/booking/base/booking.module.base.ts b/apps/basic-auth-provider/src/booking/base/booking.module.base.ts index fba8710..381bc81 100644 --- a/apps/basic-auth-provider/src/booking/base/booking.module.base.ts +++ b/apps/basic-auth-provider/src/booking/base/booking.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class BookingModuleBase {} diff --git a/apps/basic-auth-provider/src/booking/base/booking.resolver.base.ts b/apps/basic-auth-provider/src/booking/base/booking.resolver.base.ts index d8c2cac..cfc4e64 100644 --- a/apps/basic-auth-provider/src/booking/base/booking.resolver.base.ts +++ b/apps/basic-auth-provider/src/booking/base/booking.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Booking } from "./Booking"; import { BookingCountArgs } from "./BookingCountArgs"; import { BookingFindManyArgs } from "./BookingFindManyArgs"; @@ -33,10 +39,20 @@ import { DestinationCalendar } from "../../destinationCalendar/base/DestinationC import { EventType } from "../../eventType/base/EventType"; import { OrigUser } from "../../origUser/base/OrigUser"; import { BookingService } from "../booking.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Booking) export class BookingResolverBase { - constructor(protected readonly service: BookingService) {} - + constructor( + protected readonly service: BookingService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async _bookingsMeta( @graphql.Args() args: BookingCountArgs ): Promise { @@ -46,14 +62,26 @@ export class BookingResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Booking]) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async bookings( @graphql.Args() args: BookingFindManyArgs ): Promise { return this.service.bookings(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Booking, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "own", + }) async booking( @graphql.Args() args: BookingFindUniqueArgs ): Promise { @@ -64,7 +92,13 @@ export class BookingResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Booking) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "create", + possession: "any", + }) async createBooking( @graphql.Args() args: CreateBookingArgs ): Promise { @@ -100,7 +134,13 @@ export class BookingResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Booking) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "update", + possession: "any", + }) async updateBooking( @graphql.Args() args: UpdateBookingArgs ): Promise { @@ -146,6 +186,11 @@ export class BookingResolverBase { } @graphql.Mutation(() => Booking) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "delete", + possession: "any", + }) async deleteBooking( @graphql.Args() args: DeleteBookingArgs ): Promise { @@ -161,7 +206,13 @@ export class BookingResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Attendee], { name: "attendees" }) + @nestAccessControl.UseRoles({ + resource: "Attendee", + action: "read", + possession: "any", + }) async findAttendees( @graphql.Parent() parent: Booking, @graphql.Args() args: AttendeeFindManyArgs @@ -175,7 +226,13 @@ export class BookingResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Payment], { name: "payment" }) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "any", + }) async findPayment( @graphql.Parent() parent: Booking, @graphql.Args() args: PaymentFindManyArgs @@ -189,7 +246,13 @@ export class BookingResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [BookingReference], { name: "references" }) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "any", + }) async findReferences( @graphql.Parent() parent: Booking, @graphql.Args() args: BookingReferenceFindManyArgs @@ -203,7 +266,13 @@ export class BookingResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [WorkflowReminder], { name: "workflowReminders" }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) async findWorkflowReminders( @graphql.Parent() parent: Booking, @graphql.Args() args: WorkflowReminderFindManyArgs @@ -217,10 +286,16 @@ export class BookingResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => DailyEventReference, { nullable: true, name: "dailyRef", }) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "read", + possession: "any", + }) async getDailyRef( @graphql.Parent() parent: Booking ): Promise { @@ -232,10 +307,16 @@ export class BookingResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => DestinationCalendar, { nullable: true, name: "destinationCalendar", }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async getDestinationCalendar( @graphql.Parent() parent: Booking ): Promise { @@ -247,10 +328,16 @@ export class BookingResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: Booking ): Promise { @@ -262,10 +349,16 @@ export class BookingResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Booking): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/booking/booking.controller.ts b/apps/basic-auth-provider/src/booking/booking.controller.ts index 32c7da8..7c80d4f 100644 --- a/apps/basic-auth-provider/src/booking/booking.controller.ts +++ b/apps/basic-auth-provider/src/booking/booking.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { BookingService } from "./booking.service"; import { BookingControllerBase } from "./base/booking.controller.base"; @swagger.ApiTags("bookings") @common.Controller("bookings") export class BookingController extends BookingControllerBase { - constructor(protected readonly service: BookingService) { - super(service); + constructor( + protected readonly service: BookingService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/booking/booking.module.ts b/apps/basic-auth-provider/src/booking/booking.module.ts index 9ba2abf..a0a3023 100644 --- a/apps/basic-auth-provider/src/booking/booking.module.ts +++ b/apps/basic-auth-provider/src/booking/booking.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { BookingModuleBase } from "./base/booking.module.base"; import { BookingService } from "./booking.service"; import { BookingController } from "./booking.controller"; import { BookingResolver } from "./booking.resolver"; @Module({ - imports: [BookingModuleBase], + imports: [BookingModuleBase, forwardRef(() => AuthModule)], controllers: [BookingController], providers: [BookingService, BookingResolver], exports: [BookingService], diff --git a/apps/basic-auth-provider/src/booking/booking.resolver.ts b/apps/basic-auth-provider/src/booking/booking.resolver.ts index c77f4c3..85fe656 100644 --- a/apps/basic-auth-provider/src/booking/booking.resolver.ts +++ b/apps/basic-auth-provider/src/booking/booking.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { BookingResolverBase } from "./base/booking.resolver.base"; import { Booking } from "./base/Booking"; import { BookingService } from "./booking.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Booking) export class BookingResolver extends BookingResolverBase { - constructor(protected readonly service: BookingService) { - super(service); + constructor( + protected readonly service: BookingService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/bookingReference/base/bookingReference.controller.base.ts b/apps/basic-auth-provider/src/bookingReference/base/bookingReference.controller.base.ts index 2588a32..9786e37 100644 --- a/apps/basic-auth-provider/src/bookingReference/base/bookingReference.controller.base.ts +++ b/apps/basic-auth-provider/src/bookingReference/base/bookingReference.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { BookingReferenceService } from "../bookingReference.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { BookingReferenceCreateInput } from "./BookingReferenceCreateInput"; import { BookingReference } from "./BookingReference"; import { BookingReferenceFindManyArgs } from "./BookingReferenceFindManyArgs"; import { BookingReferenceWhereUniqueInput } from "./BookingReferenceWhereUniqueInput"; import { BookingReferenceUpdateInput } from "./BookingReferenceUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class BookingReferenceControllerBase { - constructor(protected readonly service: BookingReferenceService) {} + constructor( + protected readonly service: BookingReferenceService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: BookingReference }) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createBookingReference( @common.Body() data: BookingReferenceCreateInput ): Promise { @@ -59,9 +77,18 @@ export class BookingReferenceControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [BookingReference] }) @ApiNestedQuery(BookingReferenceFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async bookingReferences( @common.Req() request: Request ): Promise { @@ -87,9 +114,18 @@ export class BookingReferenceControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: BookingReference }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async bookingReference( @common.Param() params: BookingReferenceWhereUniqueInput ): Promise { @@ -120,9 +156,18 @@ export class BookingReferenceControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: BookingReference }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateBookingReference( @common.Param() params: BookingReferenceWhereUniqueInput, @common.Body() data: BookingReferenceUpdateInput @@ -169,6 +214,14 @@ export class BookingReferenceControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: BookingReference }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteBookingReference( @common.Param() params: BookingReferenceWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/bookingReference/base/bookingReference.module.base.ts b/apps/basic-auth-provider/src/bookingReference/base/bookingReference.module.base.ts index c48226d..a137810 100644 --- a/apps/basic-auth-provider/src/bookingReference/base/bookingReference.module.base.ts +++ b/apps/basic-auth-provider/src/bookingReference/base/bookingReference.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class BookingReferenceModuleBase {} diff --git a/apps/basic-auth-provider/src/bookingReference/base/bookingReference.resolver.base.ts b/apps/basic-auth-provider/src/bookingReference/base/bookingReference.resolver.base.ts index 96b16ad..76dbfd1 100644 --- a/apps/basic-auth-provider/src/bookingReference/base/bookingReference.resolver.base.ts +++ b/apps/basic-auth-provider/src/bookingReference/base/bookingReference.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { BookingReference } from "./BookingReference"; import { BookingReferenceCountArgs } from "./BookingReferenceCountArgs"; import { BookingReferenceFindManyArgs } from "./BookingReferenceFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateBookingReferenceArgs } from "./UpdateBookingReferenceArgs"; import { DeleteBookingReferenceArgs } from "./DeleteBookingReferenceArgs"; import { Booking } from "../../booking/base/Booking"; import { BookingReferenceService } from "../bookingReference.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => BookingReference) export class BookingReferenceResolverBase { - constructor(protected readonly service: BookingReferenceService) {} + constructor( + protected readonly service: BookingReferenceService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "any", + }) async _bookingReferencesMeta( @graphql.Args() args: BookingReferenceCountArgs ): Promise { @@ -35,14 +51,26 @@ export class BookingReferenceResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [BookingReference]) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "any", + }) async bookingReferences( @graphql.Args() args: BookingReferenceFindManyArgs ): Promise { return this.service.bookingReferences(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => BookingReference, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "read", + possession: "own", + }) async bookingReference( @graphql.Args() args: BookingReferenceFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class BookingReferenceResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => BookingReference) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "create", + possession: "any", + }) async createBookingReference( @graphql.Args() args: CreateBookingReferenceArgs ): Promise { @@ -71,7 +105,13 @@ export class BookingReferenceResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => BookingReference) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "update", + possession: "any", + }) async updateBookingReference( @graphql.Args() args: UpdateBookingReferenceArgs ): Promise { @@ -99,6 +139,11 @@ export class BookingReferenceResolverBase { } @graphql.Mutation(() => BookingReference) + @nestAccessControl.UseRoles({ + resource: "BookingReference", + action: "delete", + possession: "any", + }) async deleteBookingReference( @graphql.Args() args: DeleteBookingReferenceArgs ): Promise { @@ -114,10 +159,16 @@ export class BookingReferenceResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Booking, { nullable: true, name: "booking", }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async getBooking( @graphql.Parent() parent: BookingReference ): Promise { diff --git a/apps/basic-auth-provider/src/bookingReference/bookingReference.controller.ts b/apps/basic-auth-provider/src/bookingReference/bookingReference.controller.ts index 4763970..3bdef52 100644 --- a/apps/basic-auth-provider/src/bookingReference/bookingReference.controller.ts +++ b/apps/basic-auth-provider/src/bookingReference/bookingReference.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { BookingReferenceService } from "./bookingReference.service"; import { BookingReferenceControllerBase } from "./base/bookingReference.controller.base"; @swagger.ApiTags("bookingReferences") @common.Controller("bookingReferences") export class BookingReferenceController extends BookingReferenceControllerBase { - constructor(protected readonly service: BookingReferenceService) { - super(service); + constructor( + protected readonly service: BookingReferenceService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/bookingReference/bookingReference.module.ts b/apps/basic-auth-provider/src/bookingReference/bookingReference.module.ts index 85f0bbf..a402797 100644 --- a/apps/basic-auth-provider/src/bookingReference/bookingReference.module.ts +++ b/apps/basic-auth-provider/src/bookingReference/bookingReference.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { BookingReferenceModuleBase } from "./base/bookingReference.module.base"; import { BookingReferenceService } from "./bookingReference.service"; import { BookingReferenceController } from "./bookingReference.controller"; import { BookingReferenceResolver } from "./bookingReference.resolver"; @Module({ - imports: [BookingReferenceModuleBase], + imports: [BookingReferenceModuleBase, forwardRef(() => AuthModule)], controllers: [BookingReferenceController], providers: [BookingReferenceService, BookingReferenceResolver], exports: [BookingReferenceService], diff --git a/apps/basic-auth-provider/src/bookingReference/bookingReference.resolver.ts b/apps/basic-auth-provider/src/bookingReference/bookingReference.resolver.ts index 8d64178..bc4661a 100644 --- a/apps/basic-auth-provider/src/bookingReference/bookingReference.resolver.ts +++ b/apps/basic-auth-provider/src/bookingReference/bookingReference.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { BookingReferenceResolverBase } from "./base/bookingReference.resolver.base"; import { BookingReference } from "./base/BookingReference"; import { BookingReferenceService } from "./bookingReference.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => BookingReference) export class BookingReferenceResolver extends BookingReferenceResolverBase { - constructor(protected readonly service: BookingReferenceService) { - super(service); + constructor( + protected readonly service: BookingReferenceService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/credential/base/credential.controller.base.ts b/apps/basic-auth-provider/src/credential/base/credential.controller.base.ts index 55344a4..7f6d515 100644 --- a/apps/basic-auth-provider/src/credential/base/credential.controller.base.ts +++ b/apps/basic-auth-provider/src/credential/base/credential.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { CredentialService } from "../credential.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { CredentialCreateInput } from "./CredentialCreateInput"; import { Credential } from "./Credential"; import { CredentialFindManyArgs } from "./CredentialFindManyArgs"; @@ -26,10 +30,24 @@ import { DestinationCalendarFindManyArgs } from "../../destinationCalendar/base/ import { DestinationCalendar } from "../../destinationCalendar/base/DestinationCalendar"; import { DestinationCalendarWhereUniqueInput } from "../../destinationCalendar/base/DestinationCalendarWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class CredentialControllerBase { - constructor(protected readonly service: CredentialService) {} + constructor( + protected readonly service: CredentialService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Credential }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createCredential( @common.Body() data: CredentialCreateInput ): Promise { @@ -69,9 +87,18 @@ export class CredentialControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Credential] }) @ApiNestedQuery(CredentialFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async credentials(@common.Req() request: Request): Promise { const args = plainToClass(CredentialFindManyArgs, request.query); return this.service.credentials({ @@ -96,9 +123,18 @@ export class CredentialControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Credential }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async credential( @common.Param() params: CredentialWhereUniqueInput ): Promise { @@ -130,9 +166,18 @@ export class CredentialControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Credential }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateCredential( @common.Param() params: CredentialWhereUniqueInput, @common.Body() data: CredentialUpdateInput @@ -186,6 +231,14 @@ export class CredentialControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Credential }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteCredential( @common.Param() params: CredentialWhereUniqueInput ): Promise { @@ -220,8 +273,14 @@ export class CredentialControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/destinationCalendars") @ApiNestedQuery(DestinationCalendarFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async findDestinationCalendars( @common.Req() request: Request, @common.Param() params: CredentialWhereUniqueInput @@ -268,6 +327,11 @@ export class CredentialControllerBase { } @common.Post("/:id/destinationCalendars") + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "update", + possession: "any", + }) async connectDestinationCalendars( @common.Param() params: CredentialWhereUniqueInput, @common.Body() body: DestinationCalendarWhereUniqueInput[] @@ -285,6 +349,11 @@ export class CredentialControllerBase { } @common.Patch("/:id/destinationCalendars") + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "update", + possession: "any", + }) async updateDestinationCalendars( @common.Param() params: CredentialWhereUniqueInput, @common.Body() body: DestinationCalendarWhereUniqueInput[] @@ -302,6 +371,11 @@ export class CredentialControllerBase { } @common.Delete("/:id/destinationCalendars") + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "update", + possession: "any", + }) async disconnectDestinationCalendars( @common.Param() params: CredentialWhereUniqueInput, @common.Body() body: DestinationCalendarWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/credential/base/credential.module.base.ts b/apps/basic-auth-provider/src/credential/base/credential.module.base.ts index 5676762..5561c34 100644 --- a/apps/basic-auth-provider/src/credential/base/credential.module.base.ts +++ b/apps/basic-auth-provider/src/credential/base/credential.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class CredentialModuleBase {} diff --git a/apps/basic-auth-provider/src/credential/base/credential.resolver.base.ts b/apps/basic-auth-provider/src/credential/base/credential.resolver.base.ts index 16c63e7..db5222f 100644 --- a/apps/basic-auth-provider/src/credential/base/credential.resolver.base.ts +++ b/apps/basic-auth-provider/src/credential/base/credential.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Credential } from "./Credential"; import { CredentialCountArgs } from "./CredentialCountArgs"; import { CredentialFindManyArgs } from "./CredentialFindManyArgs"; @@ -25,10 +31,20 @@ import { DestinationCalendar } from "../../destinationCalendar/base/DestinationC import { AppModel } from "../../appModel/base/AppModel"; import { OrigUser } from "../../origUser/base/OrigUser"; import { CredentialService } from "../credential.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Credential) export class CredentialResolverBase { - constructor(protected readonly service: CredentialService) {} - + constructor( + protected readonly service: CredentialService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async _credentialsMeta( @graphql.Args() args: CredentialCountArgs ): Promise { @@ -38,14 +54,26 @@ export class CredentialResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Credential]) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async credentials( @graphql.Args() args: CredentialFindManyArgs ): Promise { return this.service.credentials(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Credential, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "own", + }) async credential( @graphql.Args() args: CredentialFindUniqueArgs ): Promise { @@ -56,7 +84,13 @@ export class CredentialResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Credential) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "create", + possession: "any", + }) async createCredential( @graphql.Args() args: CreateCredentialArgs ): Promise { @@ -80,7 +114,13 @@ export class CredentialResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Credential) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "update", + possession: "any", + }) async updateCredential( @graphql.Args() args: UpdateCredentialArgs ): Promise { @@ -114,6 +154,11 @@ export class CredentialResolverBase { } @graphql.Mutation(() => Credential) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "delete", + possession: "any", + }) async deleteCredential( @graphql.Args() args: DeleteCredentialArgs ): Promise { @@ -129,9 +174,15 @@ export class CredentialResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [DestinationCalendar], { name: "destinationCalendars", }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async findDestinationCalendars( @graphql.Parent() parent: Credential, @graphql.Args() args: DestinationCalendarFindManyArgs @@ -148,10 +199,16 @@ export class CredentialResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => AppModel, { nullable: true, name: "appField", }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "any", + }) async getAppField( @graphql.Parent() parent: Credential ): Promise { @@ -163,10 +220,16 @@ export class CredentialResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser( @graphql.Parent() parent: Credential ): Promise { diff --git a/apps/basic-auth-provider/src/credential/credential.controller.ts b/apps/basic-auth-provider/src/credential/credential.controller.ts index 5a108e1..7df000e 100644 --- a/apps/basic-auth-provider/src/credential/credential.controller.ts +++ b/apps/basic-auth-provider/src/credential/credential.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { CredentialService } from "./credential.service"; import { CredentialControllerBase } from "./base/credential.controller.base"; @swagger.ApiTags("credentials") @common.Controller("credentials") export class CredentialController extends CredentialControllerBase { - constructor(protected readonly service: CredentialService) { - super(service); + constructor( + protected readonly service: CredentialService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/credential/credential.module.ts b/apps/basic-auth-provider/src/credential/credential.module.ts index 01e2a08..c525453 100644 --- a/apps/basic-auth-provider/src/credential/credential.module.ts +++ b/apps/basic-auth-provider/src/credential/credential.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { CredentialModuleBase } from "./base/credential.module.base"; import { CredentialService } from "./credential.service"; import { CredentialController } from "./credential.controller"; import { CredentialResolver } from "./credential.resolver"; @Module({ - imports: [CredentialModuleBase], + imports: [CredentialModuleBase, forwardRef(() => AuthModule)], controllers: [CredentialController], providers: [CredentialService, CredentialResolver], exports: [CredentialService], diff --git a/apps/basic-auth-provider/src/credential/credential.resolver.ts b/apps/basic-auth-provider/src/credential/credential.resolver.ts index a812954..0072bf5 100644 --- a/apps/basic-auth-provider/src/credential/credential.resolver.ts +++ b/apps/basic-auth-provider/src/credential/credential.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { CredentialResolverBase } from "./base/credential.resolver.base"; import { Credential } from "./base/Credential"; import { CredentialService } from "./credential.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Credential) export class CredentialResolver extends CredentialResolverBase { - constructor(protected readonly service: CredentialService) { - super(service); + constructor( + protected readonly service: CredentialService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.controller.base.ts b/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.controller.base.ts index d6fa0a8..e36809b 100644 --- a/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.controller.base.ts +++ b/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { DailyEventReferenceService } from "../dailyEventReference.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { DailyEventReferenceCreateInput } from "./DailyEventReferenceCreateInput"; import { DailyEventReference } from "./DailyEventReference"; import { DailyEventReferenceFindManyArgs } from "./DailyEventReferenceFindManyArgs"; import { DailyEventReferenceWhereUniqueInput } from "./DailyEventReferenceWhereUniqueInput"; import { DailyEventReferenceUpdateInput } from "./DailyEventReferenceUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class DailyEventReferenceControllerBase { - constructor(protected readonly service: DailyEventReferenceService) {} + constructor( + protected readonly service: DailyEventReferenceService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: DailyEventReference }) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createDailyEventReference( @common.Body() data: DailyEventReferenceCreateInput ): Promise { @@ -54,9 +72,18 @@ export class DailyEventReferenceControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [DailyEventReference] }) @ApiNestedQuery(DailyEventReferenceFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async dailyEventReferences( @common.Req() request: Request ): Promise { @@ -77,9 +104,18 @@ export class DailyEventReferenceControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: DailyEventReference }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async dailyEventReference( @common.Param() params: DailyEventReferenceWhereUniqueInput ): Promise { @@ -105,9 +141,18 @@ export class DailyEventReferenceControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: DailyEventReference }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateDailyEventReference( @common.Param() params: DailyEventReferenceWhereUniqueInput, @common.Body() data: DailyEventReferenceUpdateInput @@ -149,6 +194,14 @@ export class DailyEventReferenceControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: DailyEventReference }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteDailyEventReference( @common.Param() params: DailyEventReferenceWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.module.base.ts b/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.module.base.ts index b28a1aa..438bd37 100644 --- a/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.module.base.ts +++ b/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class DailyEventReferenceModuleBase {} diff --git a/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.resolver.base.ts b/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.resolver.base.ts index 04d25fe..d96791a 100644 --- a/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.resolver.base.ts +++ b/apps/basic-auth-provider/src/dailyEventReference/base/dailyEventReference.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { DailyEventReference } from "./DailyEventReference"; import { DailyEventReferenceCountArgs } from "./DailyEventReferenceCountArgs"; import { DailyEventReferenceFindManyArgs } from "./DailyEventReferenceFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateDailyEventReferenceArgs } from "./UpdateDailyEventReferenceArgs"; import { DeleteDailyEventReferenceArgs } from "./DeleteDailyEventReferenceArgs"; import { Booking } from "../../booking/base/Booking"; import { DailyEventReferenceService } from "../dailyEventReference.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => DailyEventReference) export class DailyEventReferenceResolverBase { - constructor(protected readonly service: DailyEventReferenceService) {} + constructor( + protected readonly service: DailyEventReferenceService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "read", + possession: "any", + }) async _dailyEventReferencesMeta( @graphql.Args() args: DailyEventReferenceCountArgs ): Promise { @@ -35,14 +51,26 @@ export class DailyEventReferenceResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [DailyEventReference]) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "read", + possession: "any", + }) async dailyEventReferences( @graphql.Args() args: DailyEventReferenceFindManyArgs ): Promise { return this.service.dailyEventReferences(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => DailyEventReference, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "read", + possession: "own", + }) async dailyEventReference( @graphql.Args() args: DailyEventReferenceFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class DailyEventReferenceResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => DailyEventReference) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "create", + possession: "any", + }) async createDailyEventReference( @graphql.Args() args: CreateDailyEventReferenceArgs ): Promise { @@ -71,7 +105,13 @@ export class DailyEventReferenceResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => DailyEventReference) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "update", + possession: "any", + }) async updateDailyEventReference( @graphql.Args() args: UpdateDailyEventReferenceArgs ): Promise { @@ -99,6 +139,11 @@ export class DailyEventReferenceResolverBase { } @graphql.Mutation(() => DailyEventReference) + @nestAccessControl.UseRoles({ + resource: "DailyEventReference", + action: "delete", + possession: "any", + }) async deleteDailyEventReference( @graphql.Args() args: DeleteDailyEventReferenceArgs ): Promise { @@ -114,10 +159,16 @@ export class DailyEventReferenceResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Booking, { nullable: true, name: "booking", }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async getBooking( @graphql.Parent() parent: DailyEventReference ): Promise { diff --git a/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.controller.ts b/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.controller.ts index 70a3e8b..28438f7 100644 --- a/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.controller.ts +++ b/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { DailyEventReferenceService } from "./dailyEventReference.service"; import { DailyEventReferenceControllerBase } from "./base/dailyEventReference.controller.base"; @swagger.ApiTags("dailyEventReferences") @common.Controller("dailyEventReferences") export class DailyEventReferenceController extends DailyEventReferenceControllerBase { - constructor(protected readonly service: DailyEventReferenceService) { - super(service); + constructor( + protected readonly service: DailyEventReferenceService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.module.ts b/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.module.ts index 4ca3135..48bb5eb 100644 --- a/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.module.ts +++ b/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { DailyEventReferenceModuleBase } from "./base/dailyEventReference.module.base"; import { DailyEventReferenceService } from "./dailyEventReference.service"; import { DailyEventReferenceController } from "./dailyEventReference.controller"; import { DailyEventReferenceResolver } from "./dailyEventReference.resolver"; @Module({ - imports: [DailyEventReferenceModuleBase], + imports: [DailyEventReferenceModuleBase, forwardRef(() => AuthModule)], controllers: [DailyEventReferenceController], providers: [DailyEventReferenceService, DailyEventReferenceResolver], exports: [DailyEventReferenceService], diff --git a/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.resolver.ts b/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.resolver.ts index d75e8e3..6925878 100644 --- a/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.resolver.ts +++ b/apps/basic-auth-provider/src/dailyEventReference/dailyEventReference.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { DailyEventReferenceResolverBase } from "./base/dailyEventReference.resolver.base"; import { DailyEventReference } from "./base/DailyEventReference"; import { DailyEventReferenceService } from "./dailyEventReference.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => DailyEventReference) export class DailyEventReferenceResolver extends DailyEventReferenceResolverBase { - constructor(protected readonly service: DailyEventReferenceService) { - super(service); + constructor( + protected readonly service: DailyEventReferenceService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.controller.base.ts b/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.controller.base.ts index 8d8a584..74dc5bd 100644 --- a/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.controller.base.ts +++ b/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { DestinationCalendarService } from "../destinationCalendar.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { DestinationCalendarCreateInput } from "./DestinationCalendarCreateInput"; import { DestinationCalendar } from "./DestinationCalendar"; import { DestinationCalendarFindManyArgs } from "./DestinationCalendarFindManyArgs"; import { DestinationCalendarWhereUniqueInput } from "./DestinationCalendarWhereUniqueInput"; import { DestinationCalendarUpdateInput } from "./DestinationCalendarUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class DestinationCalendarControllerBase { - constructor(protected readonly service: DestinationCalendarService) {} + constructor( + protected readonly service: DestinationCalendarService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: DestinationCalendar }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createDestinationCalendar( @common.Body() data: DestinationCalendarCreateInput ): Promise { @@ -90,9 +108,18 @@ export class DestinationCalendarControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [DestinationCalendar] }) @ApiNestedQuery(DestinationCalendarFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async destinationCalendars( @common.Req() request: Request ): Promise { @@ -131,9 +158,18 @@ export class DestinationCalendarControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: DestinationCalendar }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async destinationCalendar( @common.Param() params: DestinationCalendarWhereUniqueInput ): Promise { @@ -177,9 +213,18 @@ export class DestinationCalendarControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: DestinationCalendar }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateDestinationCalendar( @common.Param() params: DestinationCalendarWhereUniqueInput, @common.Body() data: DestinationCalendarUpdateInput @@ -257,6 +302,14 @@ export class DestinationCalendarControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: DestinationCalendar }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteDestinationCalendar( @common.Param() params: DestinationCalendarWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.module.base.ts b/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.module.base.ts index beb9734..80db1f7 100644 --- a/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.module.base.ts +++ b/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class DestinationCalendarModuleBase {} diff --git a/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.resolver.base.ts b/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.resolver.base.ts index 55a6686..c3eb7f1 100644 --- a/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.resolver.base.ts +++ b/apps/basic-auth-provider/src/destinationCalendar/base/destinationCalendar.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { DestinationCalendar } from "./DestinationCalendar"; import { DestinationCalendarCountArgs } from "./DestinationCalendarCountArgs"; import { DestinationCalendarFindManyArgs } from "./DestinationCalendarFindManyArgs"; @@ -25,10 +31,20 @@ import { Credential } from "../../credential/base/Credential"; import { EventType } from "../../eventType/base/EventType"; import { OrigUser } from "../../origUser/base/OrigUser"; import { DestinationCalendarService } from "../destinationCalendar.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => DestinationCalendar) export class DestinationCalendarResolverBase { - constructor(protected readonly service: DestinationCalendarService) {} + constructor( + protected readonly service: DestinationCalendarService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async _destinationCalendarsMeta( @graphql.Args() args: DestinationCalendarCountArgs ): Promise { @@ -38,14 +54,26 @@ export class DestinationCalendarResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [DestinationCalendar]) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async destinationCalendars( @graphql.Args() args: DestinationCalendarFindManyArgs ): Promise { return this.service.destinationCalendars(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => DestinationCalendar, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "own", + }) async destinationCalendar( @graphql.Args() args: DestinationCalendarFindUniqueArgs ): Promise { @@ -56,7 +84,13 @@ export class DestinationCalendarResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => DestinationCalendar) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "create", + possession: "any", + }) async createDestinationCalendar( @graphql.Args() args: CreateDestinationCalendarArgs ): Promise { @@ -92,7 +126,13 @@ export class DestinationCalendarResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => DestinationCalendar) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "update", + possession: "any", + }) async updateDestinationCalendar( @graphql.Args() args: UpdateDestinationCalendarArgs ): Promise { @@ -138,6 +178,11 @@ export class DestinationCalendarResolverBase { } @graphql.Mutation(() => DestinationCalendar) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "delete", + possession: "any", + }) async deleteDestinationCalendar( @graphql.Args() args: DeleteDestinationCalendarArgs ): Promise { @@ -153,10 +198,16 @@ export class DestinationCalendarResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Booking, { nullable: true, name: "booking", }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async getBooking( @graphql.Parent() parent: DestinationCalendar ): Promise { @@ -168,10 +219,16 @@ export class DestinationCalendarResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Credential, { nullable: true, name: "credential", }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async getCredential( @graphql.Parent() parent: DestinationCalendar ): Promise { @@ -183,10 +240,16 @@ export class DestinationCalendarResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: DestinationCalendar ): Promise { @@ -198,10 +261,16 @@ export class DestinationCalendarResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser( @graphql.Parent() parent: DestinationCalendar ): Promise { diff --git a/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.controller.ts b/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.controller.ts index 2cc35ad..a4db55d 100644 --- a/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.controller.ts +++ b/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { DestinationCalendarService } from "./destinationCalendar.service"; import { DestinationCalendarControllerBase } from "./base/destinationCalendar.controller.base"; @swagger.ApiTags("destinationCalendars") @common.Controller("destinationCalendars") export class DestinationCalendarController extends DestinationCalendarControllerBase { - constructor(protected readonly service: DestinationCalendarService) { - super(service); + constructor( + protected readonly service: DestinationCalendarService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.module.ts b/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.module.ts index 3afa296..961406b 100644 --- a/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.module.ts +++ b/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { DestinationCalendarModuleBase } from "./base/destinationCalendar.module.base"; import { DestinationCalendarService } from "./destinationCalendar.service"; import { DestinationCalendarController } from "./destinationCalendar.controller"; import { DestinationCalendarResolver } from "./destinationCalendar.resolver"; @Module({ - imports: [DestinationCalendarModuleBase], + imports: [DestinationCalendarModuleBase, forwardRef(() => AuthModule)], controllers: [DestinationCalendarController], providers: [DestinationCalendarService, DestinationCalendarResolver], exports: [DestinationCalendarService], diff --git a/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.resolver.ts b/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.resolver.ts index 33e00fe..b688af0 100644 --- a/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.resolver.ts +++ b/apps/basic-auth-provider/src/destinationCalendar/destinationCalendar.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { DestinationCalendarResolverBase } from "./base/destinationCalendar.resolver.base"; import { DestinationCalendar } from "./base/DestinationCalendar"; import { DestinationCalendarService } from "./destinationCalendar.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => DestinationCalendar) export class DestinationCalendarResolver extends DestinationCalendarResolverBase { - constructor(protected readonly service: DestinationCalendarService) { - super(service); + constructor( + protected readonly service: DestinationCalendarService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/eventType/base/eventType.controller.base.ts b/apps/basic-auth-provider/src/eventType/base/eventType.controller.base.ts index e750264..cd0f34a 100644 --- a/apps/basic-auth-provider/src/eventType/base/eventType.controller.base.ts +++ b/apps/basic-auth-provider/src/eventType/base/eventType.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { EventTypeService } from "../eventType.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { EventTypeCreateInput } from "./EventTypeCreateInput"; import { EventType } from "./EventType"; import { EventTypeFindManyArgs } from "./EventTypeFindManyArgs"; @@ -41,10 +45,24 @@ import { WorkflowsOnEventTypeFindManyArgs } from "../../workflowsOnEventType/bas import { WorkflowsOnEventType } from "../../workflowsOnEventType/base/WorkflowsOnEventType"; import { WorkflowsOnEventTypeWhereUniqueInput } from "../../workflowsOnEventType/base/WorkflowsOnEventTypeWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class EventTypeControllerBase { - constructor(protected readonly service: EventTypeService) {} + constructor( + protected readonly service: EventTypeService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: EventType }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createEventType( @common.Body() data: EventTypeCreateInput ): Promise { @@ -139,9 +157,18 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [EventType] }) @ApiNestedQuery(EventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async eventTypes(@common.Req() request: Request): Promise { const args = plainToClass(EventTypeFindManyArgs, request.query); return this.service.eventTypes({ @@ -209,9 +236,18 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: EventType }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async eventType( @common.Param() params: EventTypeWhereUniqueInput ): Promise { @@ -286,9 +322,18 @@ export class EventTypeControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: EventType }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateEventType( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() data: EventTypeUpdateInput @@ -397,6 +442,14 @@ export class EventTypeControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: EventType }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteEventType( @common.Param() params: EventTypeWhereUniqueInput ): Promise { @@ -474,8 +527,14 @@ export class EventTypeControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/availability") @ApiNestedQuery(AvailabilityFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async findAvailability( @common.Req() request: Request, @common.Param() params: EventTypeWhereUniqueInput @@ -520,6 +579,11 @@ export class EventTypeControllerBase { } @common.Post("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async connectAvailability( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -537,6 +601,11 @@ export class EventTypeControllerBase { } @common.Patch("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateAvailability( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -554,6 +623,11 @@ export class EventTypeControllerBase { } @common.Delete("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async disconnectAvailability( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -570,8 +644,14 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/bookings") @ApiNestedQuery(BookingFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async findBookings( @common.Req() request: Request, @common.Param() params: EventTypeWhereUniqueInput @@ -638,6 +718,11 @@ export class EventTypeControllerBase { } @common.Post("/:id/bookings") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async connectBookings( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: BookingWhereUniqueInput[] @@ -655,6 +740,11 @@ export class EventTypeControllerBase { } @common.Patch("/:id/bookings") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateBookings( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: BookingWhereUniqueInput[] @@ -672,6 +762,11 @@ export class EventTypeControllerBase { } @common.Delete("/:id/bookings") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async disconnectBookings( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: BookingWhereUniqueInput[] @@ -688,8 +783,14 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/customInputs") @ApiNestedQuery(EventTypeCustomInputFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "any", + }) async findCustomInputs( @common.Req() request: Request, @common.Param() params: EventTypeWhereUniqueInput @@ -720,6 +821,11 @@ export class EventTypeControllerBase { } @common.Post("/:id/customInputs") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async connectCustomInputs( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: EventTypeCustomInputWhereUniqueInput[] @@ -737,6 +843,11 @@ export class EventTypeControllerBase { } @common.Patch("/:id/customInputs") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateCustomInputs( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: EventTypeCustomInputWhereUniqueInput[] @@ -754,6 +865,11 @@ export class EventTypeControllerBase { } @common.Delete("/:id/customInputs") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async disconnectCustomInputs( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: EventTypeCustomInputWhereUniqueInput[] @@ -770,8 +886,14 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/users") @ApiNestedQuery(OrigUserFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async findUsers( @common.Req() request: Request, @common.Param() params: EventTypeWhereUniqueInput @@ -833,6 +955,11 @@ export class EventTypeControllerBase { } @common.Post("/:id/users") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async connectUsers( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: OrigUserWhereUniqueInput[] @@ -850,6 +977,11 @@ export class EventTypeControllerBase { } @common.Patch("/:id/users") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateUsers( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: OrigUserWhereUniqueInput[] @@ -867,6 +999,11 @@ export class EventTypeControllerBase { } @common.Delete("/:id/users") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async disconnectUsers( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: OrigUserWhereUniqueInput[] @@ -883,8 +1020,14 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/webhooks") @ApiNestedQuery(WebhookFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async findWebhooks( @common.Req() request: Request, @common.Param() params: EventTypeWhereUniqueInput @@ -931,6 +1074,11 @@ export class EventTypeControllerBase { } @common.Post("/:id/webhooks") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async connectWebhooks( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -948,6 +1096,11 @@ export class EventTypeControllerBase { } @common.Patch("/:id/webhooks") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateWebhooks( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -965,6 +1118,11 @@ export class EventTypeControllerBase { } @common.Delete("/:id/webhooks") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async disconnectWebhooks( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -981,8 +1139,14 @@ export class EventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/workflows") @ApiNestedQuery(WorkflowsOnEventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) async findWorkflows( @common.Req() request: Request, @common.Param() params: EventTypeWhereUniqueInput @@ -1015,6 +1179,11 @@ export class EventTypeControllerBase { } @common.Post("/:id/workflows") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async connectWorkflows( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: WorkflowsOnEventTypeWhereUniqueInput[] @@ -1032,6 +1201,11 @@ export class EventTypeControllerBase { } @common.Patch("/:id/workflows") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateWorkflows( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: WorkflowsOnEventTypeWhereUniqueInput[] @@ -1049,6 +1223,11 @@ export class EventTypeControllerBase { } @common.Delete("/:id/workflows") + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async disconnectWorkflows( @common.Param() params: EventTypeWhereUniqueInput, @common.Body() body: WorkflowsOnEventTypeWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/eventType/base/eventType.module.base.ts b/apps/basic-auth-provider/src/eventType/base/eventType.module.base.ts index 4d2e373..32312d1 100644 --- a/apps/basic-auth-provider/src/eventType/base/eventType.module.base.ts +++ b/apps/basic-auth-provider/src/eventType/base/eventType.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class EventTypeModuleBase {} diff --git a/apps/basic-auth-provider/src/eventType/base/eventType.resolver.base.ts b/apps/basic-auth-provider/src/eventType/base/eventType.resolver.base.ts index 873c17e..66576b2 100644 --- a/apps/basic-auth-provider/src/eventType/base/eventType.resolver.base.ts +++ b/apps/basic-auth-provider/src/eventType/base/eventType.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { EventType } from "./EventType"; import { EventTypeCountArgs } from "./EventTypeCountArgs"; import { EventTypeFindManyArgs } from "./EventTypeFindManyArgs"; @@ -37,10 +43,20 @@ import { HashedLink } from "../../hashedLink/base/HashedLink"; import { Schedule } from "../../schedule/base/Schedule"; import { Team } from "../../team/base/Team"; import { EventTypeService } from "../eventType.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => EventType) export class EventTypeResolverBase { - constructor(protected readonly service: EventTypeService) {} - + constructor( + protected readonly service: EventTypeService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async _eventTypesMeta( @graphql.Args() args: EventTypeCountArgs ): Promise { @@ -50,14 +66,26 @@ export class EventTypeResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [EventType]) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async eventTypes( @graphql.Args() args: EventTypeFindManyArgs ): Promise { return this.service.eventTypes(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => EventType, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "own", + }) async eventType( @graphql.Args() args: EventTypeFindUniqueArgs ): Promise { @@ -68,7 +96,13 @@ export class EventTypeResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => EventType) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "create", + possession: "any", + }) async createEventType( @graphql.Args() args: CreateEventTypeArgs ): Promise { @@ -104,7 +138,13 @@ export class EventTypeResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => EventType) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "update", + possession: "any", + }) async updateEventType( @graphql.Args() args: UpdateEventTypeArgs ): Promise { @@ -150,6 +190,11 @@ export class EventTypeResolverBase { } @graphql.Mutation(() => EventType) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "delete", + possession: "any", + }) async deleteEventType( @graphql.Args() args: DeleteEventTypeArgs ): Promise { @@ -165,7 +210,13 @@ export class EventTypeResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Availability], { name: "availability" }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async findAvailability( @graphql.Parent() parent: EventType, @graphql.Args() args: AvailabilityFindManyArgs @@ -179,7 +230,13 @@ export class EventTypeResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Booking], { name: "bookings" }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async findBookings( @graphql.Parent() parent: EventType, @graphql.Args() args: BookingFindManyArgs @@ -193,7 +250,13 @@ export class EventTypeResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [EventTypeCustomInput], { name: "customInputs" }) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "any", + }) async findCustomInputs( @graphql.Parent() parent: EventType, @graphql.Args() args: EventTypeCustomInputFindManyArgs @@ -207,7 +270,13 @@ export class EventTypeResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [OrigUser], { name: "users" }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async findUsers( @graphql.Parent() parent: EventType, @graphql.Args() args: OrigUserFindManyArgs @@ -221,7 +290,13 @@ export class EventTypeResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Webhook], { name: "webhooks" }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async findWebhooks( @graphql.Parent() parent: EventType, @graphql.Args() args: WebhookFindManyArgs @@ -235,7 +310,13 @@ export class EventTypeResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [WorkflowsOnEventType], { name: "workflows" }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) async findWorkflows( @graphql.Parent() parent: EventType, @graphql.Args() args: WorkflowsOnEventTypeFindManyArgs @@ -249,10 +330,16 @@ export class EventTypeResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => DestinationCalendar, { nullable: true, name: "destinationCalendar", }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async getDestinationCalendar( @graphql.Parent() parent: EventType ): Promise { @@ -264,10 +351,16 @@ export class EventTypeResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => HashedLink, { nullable: true, name: "hashedLink", }) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "read", + possession: "any", + }) async getHashedLink( @graphql.Parent() parent: EventType ): Promise { @@ -279,10 +372,16 @@ export class EventTypeResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Schedule, { nullable: true, name: "schedule", }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) async getSchedule( @graphql.Parent() parent: EventType ): Promise { @@ -294,10 +393,16 @@ export class EventTypeResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Team, { nullable: true, name: "team", }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "any", + }) async getTeam(@graphql.Parent() parent: EventType): Promise { const result = await this.service.getTeam(parent.id); diff --git a/apps/basic-auth-provider/src/eventType/eventType.controller.ts b/apps/basic-auth-provider/src/eventType/eventType.controller.ts index 0e64c3a..e475c37 100644 --- a/apps/basic-auth-provider/src/eventType/eventType.controller.ts +++ b/apps/basic-auth-provider/src/eventType/eventType.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { EventTypeService } from "./eventType.service"; import { EventTypeControllerBase } from "./base/eventType.controller.base"; @swagger.ApiTags("eventTypes") @common.Controller("eventTypes") export class EventTypeController extends EventTypeControllerBase { - constructor(protected readonly service: EventTypeService) { - super(service); + constructor( + protected readonly service: EventTypeService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/eventType/eventType.module.ts b/apps/basic-auth-provider/src/eventType/eventType.module.ts index 9d6a47c..0493b5f 100644 --- a/apps/basic-auth-provider/src/eventType/eventType.module.ts +++ b/apps/basic-auth-provider/src/eventType/eventType.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { EventTypeModuleBase } from "./base/eventType.module.base"; import { EventTypeService } from "./eventType.service"; import { EventTypeController } from "./eventType.controller"; import { EventTypeResolver } from "./eventType.resolver"; @Module({ - imports: [EventTypeModuleBase], + imports: [EventTypeModuleBase, forwardRef(() => AuthModule)], controllers: [EventTypeController], providers: [EventTypeService, EventTypeResolver], exports: [EventTypeService], diff --git a/apps/basic-auth-provider/src/eventType/eventType.resolver.ts b/apps/basic-auth-provider/src/eventType/eventType.resolver.ts index 652074d..5d5a1f8 100644 --- a/apps/basic-auth-provider/src/eventType/eventType.resolver.ts +++ b/apps/basic-auth-provider/src/eventType/eventType.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { EventTypeResolverBase } from "./base/eventType.resolver.base"; import { EventType } from "./base/EventType"; import { EventTypeService } from "./eventType.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => EventType) export class EventTypeResolver extends EventTypeResolverBase { - constructor(protected readonly service: EventTypeService) { - super(service); + constructor( + protected readonly service: EventTypeService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.controller.base.ts b/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.controller.base.ts index 67cb58f..9e95597 100644 --- a/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.controller.base.ts +++ b/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { EventTypeCustomInputService } from "../eventTypeCustomInput.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { EventTypeCustomInputCreateInput } from "./EventTypeCustomInputCreateInput"; import { EventTypeCustomInput } from "./EventTypeCustomInput"; import { EventTypeCustomInputFindManyArgs } from "./EventTypeCustomInputFindManyArgs"; import { EventTypeCustomInputWhereUniqueInput } from "./EventTypeCustomInputWhereUniqueInput"; import { EventTypeCustomInputUpdateInput } from "./EventTypeCustomInputUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class EventTypeCustomInputControllerBase { - constructor(protected readonly service: EventTypeCustomInputService) {} + constructor( + protected readonly service: EventTypeCustomInputService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: EventTypeCustomInput }) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createEventTypeCustomInput( @common.Body() data: EventTypeCustomInputCreateInput ): Promise { @@ -54,9 +72,18 @@ export class EventTypeCustomInputControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [EventTypeCustomInput] }) @ApiNestedQuery(EventTypeCustomInputFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async eventTypeCustomInputs( @common.Req() request: Request ): Promise { @@ -79,9 +106,18 @@ export class EventTypeCustomInputControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: EventTypeCustomInput }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async eventTypeCustomInput( @common.Param() params: EventTypeCustomInputWhereUniqueInput ): Promise { @@ -109,9 +145,18 @@ export class EventTypeCustomInputControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: EventTypeCustomInput }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateEventTypeCustomInput( @common.Param() params: EventTypeCustomInputWhereUniqueInput, @common.Body() data: EventTypeCustomInputUpdateInput @@ -153,6 +198,14 @@ export class EventTypeCustomInputControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: EventTypeCustomInput }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteEventTypeCustomInput( @common.Param() params: EventTypeCustomInputWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.module.base.ts b/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.module.base.ts index 1346a4d..c6d6650 100644 --- a/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.module.base.ts +++ b/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class EventTypeCustomInputModuleBase {} diff --git a/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.resolver.base.ts b/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.resolver.base.ts index 29da814..ab2e58b 100644 --- a/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.resolver.base.ts +++ b/apps/basic-auth-provider/src/eventTypeCustomInput/base/eventTypeCustomInput.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { EventTypeCustomInput } from "./EventTypeCustomInput"; import { EventTypeCustomInputCountArgs } from "./EventTypeCustomInputCountArgs"; import { EventTypeCustomInputFindManyArgs } from "./EventTypeCustomInputFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateEventTypeCustomInputArgs } from "./UpdateEventTypeCustomInputArgs import { DeleteEventTypeCustomInputArgs } from "./DeleteEventTypeCustomInputArgs"; import { EventType } from "../../eventType/base/EventType"; import { EventTypeCustomInputService } from "../eventTypeCustomInput.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => EventTypeCustomInput) export class EventTypeCustomInputResolverBase { - constructor(protected readonly service: EventTypeCustomInputService) {} + constructor( + protected readonly service: EventTypeCustomInputService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "any", + }) async _eventTypeCustomInputsMeta( @graphql.Args() args: EventTypeCustomInputCountArgs ): Promise { @@ -35,14 +51,26 @@ export class EventTypeCustomInputResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [EventTypeCustomInput]) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "any", + }) async eventTypeCustomInputs( @graphql.Args() args: EventTypeCustomInputFindManyArgs ): Promise { return this.service.eventTypeCustomInputs(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => EventTypeCustomInput, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "read", + possession: "own", + }) async eventTypeCustomInput( @graphql.Args() args: EventTypeCustomInputFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class EventTypeCustomInputResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => EventTypeCustomInput) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "create", + possession: "any", + }) async createEventTypeCustomInput( @graphql.Args() args: CreateEventTypeCustomInputArgs ): Promise { @@ -69,7 +103,13 @@ export class EventTypeCustomInputResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => EventTypeCustomInput) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "update", + possession: "any", + }) async updateEventTypeCustomInput( @graphql.Args() args: UpdateEventTypeCustomInputArgs ): Promise { @@ -95,6 +135,11 @@ export class EventTypeCustomInputResolverBase { } @graphql.Mutation(() => EventTypeCustomInput) + @nestAccessControl.UseRoles({ + resource: "EventTypeCustomInput", + action: "delete", + possession: "any", + }) async deleteEventTypeCustomInput( @graphql.Args() args: DeleteEventTypeCustomInputArgs ): Promise { @@ -110,10 +155,16 @@ export class EventTypeCustomInputResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: EventTypeCustomInput ): Promise { diff --git a/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.controller.ts b/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.controller.ts index f4bdc77..33a5527 100644 --- a/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.controller.ts +++ b/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { EventTypeCustomInputService } from "./eventTypeCustomInput.service"; import { EventTypeCustomInputControllerBase } from "./base/eventTypeCustomInput.controller.base"; @swagger.ApiTags("eventTypeCustomInputs") @common.Controller("eventTypeCustomInputs") export class EventTypeCustomInputController extends EventTypeCustomInputControllerBase { - constructor(protected readonly service: EventTypeCustomInputService) { - super(service); + constructor( + protected readonly service: EventTypeCustomInputService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.module.ts b/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.module.ts index 98f0e16..60c4864 100644 --- a/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.module.ts +++ b/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { EventTypeCustomInputModuleBase } from "./base/eventTypeCustomInput.module.base"; import { EventTypeCustomInputService } from "./eventTypeCustomInput.service"; import { EventTypeCustomInputController } from "./eventTypeCustomInput.controller"; import { EventTypeCustomInputResolver } from "./eventTypeCustomInput.resolver"; @Module({ - imports: [EventTypeCustomInputModuleBase], + imports: [EventTypeCustomInputModuleBase, forwardRef(() => AuthModule)], controllers: [EventTypeCustomInputController], providers: [EventTypeCustomInputService, EventTypeCustomInputResolver], exports: [EventTypeCustomInputService], diff --git a/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.resolver.ts b/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.resolver.ts index 6fae146..4fd9cc3 100644 --- a/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.resolver.ts +++ b/apps/basic-auth-provider/src/eventTypeCustomInput/eventTypeCustomInput.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { EventTypeCustomInputResolverBase } from "./base/eventTypeCustomInput.resolver.base"; import { EventTypeCustomInput } from "./base/EventTypeCustomInput"; import { EventTypeCustomInputService } from "./eventTypeCustomInput.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => EventTypeCustomInput) export class EventTypeCustomInputResolver extends EventTypeCustomInputResolverBase { - constructor(protected readonly service: EventTypeCustomInputService) { - super(service); + constructor( + protected readonly service: EventTypeCustomInputService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/feedback/base/feedback.controller.base.ts b/apps/basic-auth-provider/src/feedback/base/feedback.controller.base.ts index 3683ad9..1a73754 100644 --- a/apps/basic-auth-provider/src/feedback/base/feedback.controller.base.ts +++ b/apps/basic-auth-provider/src/feedback/base/feedback.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { FeedbackService } from "../feedback.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { FeedbackCreateInput } from "./FeedbackCreateInput"; import { Feedback } from "./Feedback"; import { FeedbackFindManyArgs } from "./FeedbackFindManyArgs"; import { FeedbackWhereUniqueInput } from "./FeedbackWhereUniqueInput"; import { FeedbackUpdateInput } from "./FeedbackUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class FeedbackControllerBase { - constructor(protected readonly service: FeedbackService) {} + constructor( + protected readonly service: FeedbackService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Feedback }) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createFeedback( @common.Body() data: FeedbackCreateInput ): Promise { @@ -53,9 +71,18 @@ export class FeedbackControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Feedback] }) @ApiNestedQuery(FeedbackFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async feedbacks(@common.Req() request: Request): Promise { const args = plainToClass(FeedbackFindManyArgs, request.query); return this.service.feedbacks({ @@ -75,9 +102,18 @@ export class FeedbackControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Feedback }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async feedback( @common.Param() params: FeedbackWhereUniqueInput ): Promise { @@ -104,9 +140,18 @@ export class FeedbackControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Feedback }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateFeedback( @common.Param() params: FeedbackWhereUniqueInput, @common.Body() data: FeedbackUpdateInput @@ -147,6 +192,14 @@ export class FeedbackControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Feedback }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteFeedback( @common.Param() params: FeedbackWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/feedback/base/feedback.module.base.ts b/apps/basic-auth-provider/src/feedback/base/feedback.module.base.ts index d0705e2..cfb8c48 100644 --- a/apps/basic-auth-provider/src/feedback/base/feedback.module.base.ts +++ b/apps/basic-auth-provider/src/feedback/base/feedback.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class FeedbackModuleBase {} diff --git a/apps/basic-auth-provider/src/feedback/base/feedback.resolver.base.ts b/apps/basic-auth-provider/src/feedback/base/feedback.resolver.base.ts index 5b65646..b8e59c9 100644 --- a/apps/basic-auth-provider/src/feedback/base/feedback.resolver.base.ts +++ b/apps/basic-auth-provider/src/feedback/base/feedback.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Feedback } from "./Feedback"; import { FeedbackCountArgs } from "./FeedbackCountArgs"; import { FeedbackFindManyArgs } from "./FeedbackFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateFeedbackArgs } from "./UpdateFeedbackArgs"; import { DeleteFeedbackArgs } from "./DeleteFeedbackArgs"; import { OrigUser } from "../../origUser/base/OrigUser"; import { FeedbackService } from "../feedback.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Feedback) export class FeedbackResolverBase { - constructor(protected readonly service: FeedbackService) {} + constructor( + protected readonly service: FeedbackService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "any", + }) async _feedbacksMeta( @graphql.Args() args: FeedbackCountArgs ): Promise { @@ -35,14 +51,26 @@ export class FeedbackResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Feedback]) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "any", + }) async feedbacks( @graphql.Args() args: FeedbackFindManyArgs ): Promise { return this.service.feedbacks(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Feedback, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "own", + }) async feedback( @graphql.Args() args: FeedbackFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class FeedbackResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Feedback) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "create", + possession: "any", + }) async createFeedback( @graphql.Args() args: CreateFeedbackArgs ): Promise { @@ -69,7 +103,13 @@ export class FeedbackResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Feedback) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "update", + possession: "any", + }) async updateFeedback( @graphql.Args() args: UpdateFeedbackArgs ): Promise { @@ -95,6 +135,11 @@ export class FeedbackResolverBase { } @graphql.Mutation(() => Feedback) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "delete", + possession: "any", + }) async deleteFeedback( @graphql.Args() args: DeleteFeedbackArgs ): Promise { @@ -110,10 +155,16 @@ export class FeedbackResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Feedback): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/feedback/feedback.controller.ts b/apps/basic-auth-provider/src/feedback/feedback.controller.ts index 06a848e..fb73341 100644 --- a/apps/basic-auth-provider/src/feedback/feedback.controller.ts +++ b/apps/basic-auth-provider/src/feedback/feedback.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { FeedbackService } from "./feedback.service"; import { FeedbackControllerBase } from "./base/feedback.controller.base"; @swagger.ApiTags("feedbacks") @common.Controller("feedbacks") export class FeedbackController extends FeedbackControllerBase { - constructor(protected readonly service: FeedbackService) { - super(service); + constructor( + protected readonly service: FeedbackService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/feedback/feedback.module.ts b/apps/basic-auth-provider/src/feedback/feedback.module.ts index 43a9a09..ea4c8e6 100644 --- a/apps/basic-auth-provider/src/feedback/feedback.module.ts +++ b/apps/basic-auth-provider/src/feedback/feedback.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { FeedbackModuleBase } from "./base/feedback.module.base"; import { FeedbackService } from "./feedback.service"; import { FeedbackController } from "./feedback.controller"; import { FeedbackResolver } from "./feedback.resolver"; @Module({ - imports: [FeedbackModuleBase], + imports: [FeedbackModuleBase, forwardRef(() => AuthModule)], controllers: [FeedbackController], providers: [FeedbackService, FeedbackResolver], exports: [FeedbackService], diff --git a/apps/basic-auth-provider/src/feedback/feedback.resolver.ts b/apps/basic-auth-provider/src/feedback/feedback.resolver.ts index 593181c..2cccf90 100644 --- a/apps/basic-auth-provider/src/feedback/feedback.resolver.ts +++ b/apps/basic-auth-provider/src/feedback/feedback.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { FeedbackResolverBase } from "./base/feedback.resolver.base"; import { Feedback } from "./base/Feedback"; import { FeedbackService } from "./feedback.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Feedback) export class FeedbackResolver extends FeedbackResolverBase { - constructor(protected readonly service: FeedbackService) { - super(service); + constructor( + protected readonly service: FeedbackService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/grants.json b/apps/basic-auth-provider/src/grants.json new file mode 100644 index 0000000..fc4effa --- /dev/null +++ b/apps/basic-auth-provider/src/grants.json @@ -0,0 +1,932 @@ +[ + { + "role": "user", + "resource": "EventType", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventType", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventType", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventType", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventType", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Credential", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Credential", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Credential", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Credential", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Credential", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DestinationCalendar", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "DestinationCalendar", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DestinationCalendar", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DestinationCalendar", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DestinationCalendar", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "OrigUser", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "OrigUser", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "OrigUser", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "OrigUser", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "OrigUser", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Team", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Team", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Team", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Team", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Team", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Membership", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Membership", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Membership", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Membership", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Membership", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "VerificationToken", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "VerificationToken", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "VerificationToken", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "VerificationToken", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "VerificationToken", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "BookingReference", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "BookingReference", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "BookingReference", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "BookingReference", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "BookingReference", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Attendee", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Attendee", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Attendee", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Attendee", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Attendee", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DailyEventReference", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "DailyEventReference", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DailyEventReference", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DailyEventReference", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "DailyEventReference", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Booking", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Booking", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Booking", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Booking", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Booking", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Schedule", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Schedule", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Schedule", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Schedule", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Schedule", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Availability", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Availability", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Availability", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Availability", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Availability", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "SelectedCalendar", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "SelectedCalendar", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "SelectedCalendar", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "SelectedCalendar", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "SelectedCalendar", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventTypeCustomInput", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventTypeCustomInput", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventTypeCustomInput", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventTypeCustomInput", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "EventTypeCustomInput", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ResetPasswordRequest", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "ResetPasswordRequest", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ResetPasswordRequest", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ResetPasswordRequest", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ResetPasswordRequest", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ReminderMail", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "ReminderMail", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ReminderMail", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ReminderMail", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ReminderMail", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Payment", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Payment", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Payment", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Payment", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Payment", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Webhook", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Webhook", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Webhook", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Webhook", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Webhook", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Impersonation", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Impersonation", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Impersonation", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Impersonation", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Impersonation", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ApiKey", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "ApiKey", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ApiKey", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ApiKey", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "ApiKey", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "HashedLink", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "HashedLink", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "HashedLink", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "HashedLink", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "HashedLink", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Account", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Account", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Account", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Account", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Account", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Session", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Session", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Session", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Session", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Session", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "AppModel", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "AppModel", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "AppModel", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "AppModel", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "AppModel", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Feedback", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Feedback", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Feedback", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Feedback", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Feedback", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowStep", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowStep", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowStep", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowStep", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowStep", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Workflow", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "Workflow", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Workflow", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Workflow", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "Workflow", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowsOnEventType", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowsOnEventType", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowsOnEventType", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowsOnEventType", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowsOnEventType", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowReminder", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowReminder", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowReminder", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowReminder", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "WorkflowReminder", + "action": "read:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "User", + "action": "read:own", + "attributes": "*" + }, + { + "role": "user", + "resource": "User", + "action": "create:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "User", + "action": "update:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "User", + "action": "delete:any", + "attributes": "*" + }, + { + "role": "user", + "resource": "User", + "action": "read:any", + "attributes": "*" + } +] diff --git a/apps/basic-auth-provider/src/hashedLink/base/hashedLink.controller.base.ts b/apps/basic-auth-provider/src/hashedLink/base/hashedLink.controller.base.ts index fc339cc..8bf4de5 100644 --- a/apps/basic-auth-provider/src/hashedLink/base/hashedLink.controller.base.ts +++ b/apps/basic-auth-provider/src/hashedLink/base/hashedLink.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { HashedLinkService } from "../hashedLink.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { HashedLinkCreateInput } from "./HashedLinkCreateInput"; import { HashedLink } from "./HashedLink"; import { HashedLinkFindManyArgs } from "./HashedLinkFindManyArgs"; import { HashedLinkWhereUniqueInput } from "./HashedLinkWhereUniqueInput"; import { HashedLinkUpdateInput } from "./HashedLinkUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class HashedLinkControllerBase { - constructor(protected readonly service: HashedLinkService) {} + constructor( + protected readonly service: HashedLinkService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: HashedLink }) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createHashedLink( @common.Body() data: HashedLinkCreateInput ): Promise { @@ -51,9 +69,18 @@ export class HashedLinkControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [HashedLink] }) @ApiNestedQuery(HashedLinkFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async hashedLinks(@common.Req() request: Request): Promise { const args = plainToClass(HashedLinkFindManyArgs, request.query); return this.service.hashedLinks({ @@ -71,9 +98,18 @@ export class HashedLinkControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: HashedLink }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async hashedLink( @common.Param() params: HashedLinkWhereUniqueInput ): Promise { @@ -98,9 +134,18 @@ export class HashedLinkControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: HashedLink }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateHashedLink( @common.Param() params: HashedLinkWhereUniqueInput, @common.Body() data: HashedLinkUpdateInput @@ -139,6 +184,14 @@ export class HashedLinkControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: HashedLink }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteHashedLink( @common.Param() params: HashedLinkWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/hashedLink/base/hashedLink.module.base.ts b/apps/basic-auth-provider/src/hashedLink/base/hashedLink.module.base.ts index 4e4780b..3ae804e 100644 --- a/apps/basic-auth-provider/src/hashedLink/base/hashedLink.module.base.ts +++ b/apps/basic-auth-provider/src/hashedLink/base/hashedLink.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class HashedLinkModuleBase {} diff --git a/apps/basic-auth-provider/src/hashedLink/base/hashedLink.resolver.base.ts b/apps/basic-auth-provider/src/hashedLink/base/hashedLink.resolver.base.ts index fa60bbe..04a3adc 100644 --- a/apps/basic-auth-provider/src/hashedLink/base/hashedLink.resolver.base.ts +++ b/apps/basic-auth-provider/src/hashedLink/base/hashedLink.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { HashedLink } from "./HashedLink"; import { HashedLinkCountArgs } from "./HashedLinkCountArgs"; import { HashedLinkFindManyArgs } from "./HashedLinkFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateHashedLinkArgs } from "./UpdateHashedLinkArgs"; import { DeleteHashedLinkArgs } from "./DeleteHashedLinkArgs"; import { EventType } from "../../eventType/base/EventType"; import { HashedLinkService } from "../hashedLink.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => HashedLink) export class HashedLinkResolverBase { - constructor(protected readonly service: HashedLinkService) {} + constructor( + protected readonly service: HashedLinkService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "read", + possession: "any", + }) async _hashedLinksMeta( @graphql.Args() args: HashedLinkCountArgs ): Promise { @@ -35,14 +51,26 @@ export class HashedLinkResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [HashedLink]) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "read", + possession: "any", + }) async hashedLinks( @graphql.Args() args: HashedLinkFindManyArgs ): Promise { return this.service.hashedLinks(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => HashedLink, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "read", + possession: "own", + }) async hashedLink( @graphql.Args() args: HashedLinkFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class HashedLinkResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => HashedLink) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "create", + possession: "any", + }) async createHashedLink( @graphql.Args() args: CreateHashedLinkArgs ): Promise { @@ -69,7 +103,13 @@ export class HashedLinkResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => HashedLink) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "update", + possession: "any", + }) async updateHashedLink( @graphql.Args() args: UpdateHashedLinkArgs ): Promise { @@ -95,6 +135,11 @@ export class HashedLinkResolverBase { } @graphql.Mutation(() => HashedLink) + @nestAccessControl.UseRoles({ + resource: "HashedLink", + action: "delete", + possession: "any", + }) async deleteHashedLink( @graphql.Args() args: DeleteHashedLinkArgs ): Promise { @@ -110,10 +155,16 @@ export class HashedLinkResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: HashedLink ): Promise { diff --git a/apps/basic-auth-provider/src/hashedLink/hashedLink.controller.ts b/apps/basic-auth-provider/src/hashedLink/hashedLink.controller.ts index 6e26b78..49a0f17 100644 --- a/apps/basic-auth-provider/src/hashedLink/hashedLink.controller.ts +++ b/apps/basic-auth-provider/src/hashedLink/hashedLink.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { HashedLinkService } from "./hashedLink.service"; import { HashedLinkControllerBase } from "./base/hashedLink.controller.base"; @swagger.ApiTags("hashedLinks") @common.Controller("hashedLinks") export class HashedLinkController extends HashedLinkControllerBase { - constructor(protected readonly service: HashedLinkService) { - super(service); + constructor( + protected readonly service: HashedLinkService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/hashedLink/hashedLink.module.ts b/apps/basic-auth-provider/src/hashedLink/hashedLink.module.ts index 300ca21..fa71d2f 100644 --- a/apps/basic-auth-provider/src/hashedLink/hashedLink.module.ts +++ b/apps/basic-auth-provider/src/hashedLink/hashedLink.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { HashedLinkModuleBase } from "./base/hashedLink.module.base"; import { HashedLinkService } from "./hashedLink.service"; import { HashedLinkController } from "./hashedLink.controller"; import { HashedLinkResolver } from "./hashedLink.resolver"; @Module({ - imports: [HashedLinkModuleBase], + imports: [HashedLinkModuleBase, forwardRef(() => AuthModule)], controllers: [HashedLinkController], providers: [HashedLinkService, HashedLinkResolver], exports: [HashedLinkService], diff --git a/apps/basic-auth-provider/src/hashedLink/hashedLink.resolver.ts b/apps/basic-auth-provider/src/hashedLink/hashedLink.resolver.ts index ac4bc02..502739f 100644 --- a/apps/basic-auth-provider/src/hashedLink/hashedLink.resolver.ts +++ b/apps/basic-auth-provider/src/hashedLink/hashedLink.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { HashedLinkResolverBase } from "./base/hashedLink.resolver.base"; import { HashedLink } from "./base/HashedLink"; import { HashedLinkService } from "./hashedLink.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => HashedLink) export class HashedLinkResolver extends HashedLinkResolverBase { - constructor(protected readonly service: HashedLinkService) { - super(service); + constructor( + protected readonly service: HashedLinkService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/impersonation/base/impersonation.controller.base.ts b/apps/basic-auth-provider/src/impersonation/base/impersonation.controller.base.ts index 9e35d7d..a78809b 100644 --- a/apps/basic-auth-provider/src/impersonation/base/impersonation.controller.base.ts +++ b/apps/basic-auth-provider/src/impersonation/base/impersonation.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { ImpersonationService } from "../impersonation.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { ImpersonationCreateInput } from "./ImpersonationCreateInput"; import { Impersonation } from "./Impersonation"; import { ImpersonationFindManyArgs } from "./ImpersonationFindManyArgs"; import { ImpersonationWhereUniqueInput } from "./ImpersonationWhereUniqueInput"; import { ImpersonationUpdateInput } from "./ImpersonationUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class ImpersonationControllerBase { - constructor(protected readonly service: ImpersonationService) {} + constructor( + protected readonly service: ImpersonationService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Impersonation }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createImpersonation( @common.Body() data: ImpersonationCreateInput ): Promise { @@ -61,9 +79,18 @@ export class ImpersonationControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Impersonation] }) @ApiNestedQuery(ImpersonationFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async impersonations( @common.Req() request: Request ): Promise { @@ -89,9 +116,18 @@ export class ImpersonationControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Impersonation }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async impersonation( @common.Param() params: ImpersonationWhereUniqueInput ): Promise { @@ -122,9 +158,18 @@ export class ImpersonationControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Impersonation }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateImpersonation( @common.Param() params: ImpersonationWhereUniqueInput, @common.Body() data: ImpersonationUpdateInput @@ -173,6 +218,14 @@ export class ImpersonationControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Impersonation }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteImpersonation( @common.Param() params: ImpersonationWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/impersonation/base/impersonation.module.base.ts b/apps/basic-auth-provider/src/impersonation/base/impersonation.module.base.ts index 15e43dc..736dfd9 100644 --- a/apps/basic-auth-provider/src/impersonation/base/impersonation.module.base.ts +++ b/apps/basic-auth-provider/src/impersonation/base/impersonation.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class ImpersonationModuleBase {} diff --git a/apps/basic-auth-provider/src/impersonation/base/impersonation.resolver.base.ts b/apps/basic-auth-provider/src/impersonation/base/impersonation.resolver.base.ts index 75951a4..dd11cd6 100644 --- a/apps/basic-auth-provider/src/impersonation/base/impersonation.resolver.base.ts +++ b/apps/basic-auth-provider/src/impersonation/base/impersonation.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Impersonation } from "./Impersonation"; import { ImpersonationCountArgs } from "./ImpersonationCountArgs"; import { ImpersonationFindManyArgs } from "./ImpersonationFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateImpersonationArgs } from "./UpdateImpersonationArgs"; import { DeleteImpersonationArgs } from "./DeleteImpersonationArgs"; import { OrigUser } from "../../origUser/base/OrigUser"; import { ImpersonationService } from "../impersonation.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Impersonation) export class ImpersonationResolverBase { - constructor(protected readonly service: ImpersonationService) {} - + constructor( + protected readonly service: ImpersonationService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) async _impersonationsMeta( @graphql.Args() args: ImpersonationCountArgs ): Promise { @@ -35,14 +51,26 @@ export class ImpersonationResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Impersonation]) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) async impersonations( @graphql.Args() args: ImpersonationFindManyArgs ): Promise { return this.service.impersonations(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Impersonation, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "own", + }) async impersonation( @graphql.Args() args: ImpersonationFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class ImpersonationResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Impersonation) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "create", + possession: "any", + }) async createImpersonation( @graphql.Args() args: CreateImpersonationArgs ): Promise { @@ -73,7 +107,13 @@ export class ImpersonationResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Impersonation) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "update", + possession: "any", + }) async updateImpersonation( @graphql.Args() args: UpdateImpersonationArgs ): Promise { @@ -103,6 +143,11 @@ export class ImpersonationResolverBase { } @graphql.Mutation(() => Impersonation) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "delete", + possession: "any", + }) async deleteImpersonation( @graphql.Args() args: DeleteImpersonationArgs ): Promise { @@ -118,10 +163,16 @@ export class ImpersonationResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "impersonatedBy", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getImpersonatedBy( @graphql.Parent() parent: Impersonation ): Promise { @@ -133,10 +184,16 @@ export class ImpersonationResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "impersonatedUser", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getImpersonatedUser( @graphql.Parent() parent: Impersonation ): Promise { diff --git a/apps/basic-auth-provider/src/impersonation/impersonation.controller.ts b/apps/basic-auth-provider/src/impersonation/impersonation.controller.ts index 5d5f537..ebea442 100644 --- a/apps/basic-auth-provider/src/impersonation/impersonation.controller.ts +++ b/apps/basic-auth-provider/src/impersonation/impersonation.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { ImpersonationService } from "./impersonation.service"; import { ImpersonationControllerBase } from "./base/impersonation.controller.base"; @swagger.ApiTags("impersonations") @common.Controller("impersonations") export class ImpersonationController extends ImpersonationControllerBase { - constructor(protected readonly service: ImpersonationService) { - super(service); + constructor( + protected readonly service: ImpersonationService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/impersonation/impersonation.module.ts b/apps/basic-auth-provider/src/impersonation/impersonation.module.ts index a2252f2..aff28c5 100644 --- a/apps/basic-auth-provider/src/impersonation/impersonation.module.ts +++ b/apps/basic-auth-provider/src/impersonation/impersonation.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { ImpersonationModuleBase } from "./base/impersonation.module.base"; import { ImpersonationService } from "./impersonation.service"; import { ImpersonationController } from "./impersonation.controller"; import { ImpersonationResolver } from "./impersonation.resolver"; @Module({ - imports: [ImpersonationModuleBase], + imports: [ImpersonationModuleBase, forwardRef(() => AuthModule)], controllers: [ImpersonationController], providers: [ImpersonationService, ImpersonationResolver], exports: [ImpersonationService], diff --git a/apps/basic-auth-provider/src/impersonation/impersonation.resolver.ts b/apps/basic-auth-provider/src/impersonation/impersonation.resolver.ts index 833d4b3..bb36bd3 100644 --- a/apps/basic-auth-provider/src/impersonation/impersonation.resolver.ts +++ b/apps/basic-auth-provider/src/impersonation/impersonation.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { ImpersonationResolverBase } from "./base/impersonation.resolver.base"; import { Impersonation } from "./base/Impersonation"; import { ImpersonationService } from "./impersonation.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Impersonation) export class ImpersonationResolver extends ImpersonationResolverBase { - constructor(protected readonly service: ImpersonationService) { - super(service); + constructor( + protected readonly service: ImpersonationService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/interceptors/aclFilterResponse.interceptor.ts b/apps/basic-auth-provider/src/interceptors/aclFilterResponse.interceptor.ts new file mode 100644 index 0000000..5eeba18 --- /dev/null +++ b/apps/basic-auth-provider/src/interceptors/aclFilterResponse.interceptor.ts @@ -0,0 +1,42 @@ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from "@nestjs/common"; +import { Observable } from "rxjs"; +import { map } from "rxjs/operators"; +import { InjectRolesBuilder, RolesBuilder } from "nest-access-control"; +import { Reflector } from "@nestjs/core"; + +@Injectable() +export class AclFilterResponseInterceptor implements NestInterceptor { + constructor( + @InjectRolesBuilder() private readonly rolesBuilder: RolesBuilder, + private readonly reflector: Reflector + ) {} + + intercept(context: ExecutionContext, next: CallHandler): Observable { + const [permissionsRoles]: any = this.reflector.getAllAndMerge( + "roles", + [context.getHandler(), context.getClass()] + ); + + const permission = this.rolesBuilder.permission({ + role: permissionsRoles.role, + action: permissionsRoles.action, + possession: permissionsRoles.possession, + resource: permissionsRoles.resource, + }); + + return next.handle().pipe( + map((data) => { + if (Array.isArray(data)) { + return data.map((results: any) => permission.filter(results)); + } else { + return permission.filter(data); + } + }) + ); + } +} diff --git a/apps/basic-auth-provider/src/interceptors/aclValidateRequest.interceptor.ts b/apps/basic-auth-provider/src/interceptors/aclValidateRequest.interceptor.ts new file mode 100644 index 0000000..6d30246 --- /dev/null +++ b/apps/basic-auth-provider/src/interceptors/aclValidateRequest.interceptor.ts @@ -0,0 +1,53 @@ +import { + CallHandler, + ExecutionContext, + Injectable, + NestInterceptor, +} from "@nestjs/common"; +import { Observable } from "rxjs"; +import { InjectRolesBuilder, RolesBuilder } from "nest-access-control"; +import { Reflector } from "@nestjs/core"; +import * as abacUtil from "../auth/abac.util"; +import { ForbiddenException } from "../errors"; + +@Injectable() +export class AclValidateRequestInterceptor implements NestInterceptor { + constructor( + @InjectRolesBuilder() private readonly rolesBuilder: RolesBuilder, + private readonly reflector: Reflector + ) {} + + intercept(context: ExecutionContext, next: CallHandler): Observable { + const [permissionsRoles]: any = this.reflector.getAllAndMerge( + "roles", + [context.getHandler(), context.getClass()] + ); + + const type = context.getType(); + + const inputDataToValidate = + type === "http" + ? context.switchToHttp().getRequest().body + : context.getArgByIndex(1).data; + + const permission = this.rolesBuilder.permission({ + role: permissionsRoles.role, + action: permissionsRoles.action, + possession: permissionsRoles.possession, + resource: permissionsRoles.resource, + }); + + const invalidAttributes = abacUtil.getInvalidAttributes( + permission, + inputDataToValidate + ); + + if (invalidAttributes.length) { + throw new ForbiddenException( + "Insufficient privileges to complete the operation" + ); + } + + return next.handle(); + } +} diff --git a/apps/basic-auth-provider/src/membership/base/membership.controller.base.ts b/apps/basic-auth-provider/src/membership/base/membership.controller.base.ts index ca0645f..46baf66 100644 --- a/apps/basic-auth-provider/src/membership/base/membership.controller.base.ts +++ b/apps/basic-auth-provider/src/membership/base/membership.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { MembershipService } from "../membership.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { MembershipCreateInput } from "./MembershipCreateInput"; import { Membership } from "./Membership"; import { MembershipFindManyArgs } from "./MembershipFindManyArgs"; import { MembershipWhereUniqueInput } from "./MembershipWhereUniqueInput"; import { MembershipUpdateInput } from "./MembershipUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class MembershipControllerBase { - constructor(protected readonly service: MembershipService) {} + constructor( + protected readonly service: MembershipService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Membership }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createMembership( @common.Body() data: MembershipCreateInput ): Promise { @@ -62,9 +80,18 @@ export class MembershipControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Membership] }) @ApiNestedQuery(MembershipFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async memberships(@common.Req() request: Request): Promise { const args = plainToClass(MembershipFindManyArgs, request.query); return this.service.memberships({ @@ -89,9 +116,18 @@ export class MembershipControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Membership }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async membership( @common.Param() params: MembershipWhereUniqueInput ): Promise { @@ -123,9 +159,18 @@ export class MembershipControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Membership }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateMembership( @common.Param() params: MembershipWhereUniqueInput, @common.Body() data: MembershipUpdateInput @@ -175,6 +220,14 @@ export class MembershipControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Membership }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteMembership( @common.Param() params: MembershipWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/membership/base/membership.module.base.ts b/apps/basic-auth-provider/src/membership/base/membership.module.base.ts index 39efc03..704652a 100644 --- a/apps/basic-auth-provider/src/membership/base/membership.module.base.ts +++ b/apps/basic-auth-provider/src/membership/base/membership.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class MembershipModuleBase {} diff --git a/apps/basic-auth-provider/src/membership/base/membership.resolver.base.ts b/apps/basic-auth-provider/src/membership/base/membership.resolver.base.ts index ffa39eb..465afa7 100644 --- a/apps/basic-auth-provider/src/membership/base/membership.resolver.base.ts +++ b/apps/basic-auth-provider/src/membership/base/membership.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Membership } from "./Membership"; import { MembershipCountArgs } from "./MembershipCountArgs"; import { MembershipFindManyArgs } from "./MembershipFindManyArgs"; @@ -23,10 +29,20 @@ import { DeleteMembershipArgs } from "./DeleteMembershipArgs"; import { Team } from "../../team/base/Team"; import { OrigUser } from "../../origUser/base/OrigUser"; import { MembershipService } from "../membership.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Membership) export class MembershipResolverBase { - constructor(protected readonly service: MembershipService) {} - + constructor( + protected readonly service: MembershipService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) async _membershipsMeta( @graphql.Args() args: MembershipCountArgs ): Promise { @@ -36,14 +52,26 @@ export class MembershipResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Membership]) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) async memberships( @graphql.Args() args: MembershipFindManyArgs ): Promise { return this.service.memberships(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Membership, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "own", + }) async membership( @graphql.Args() args: MembershipFindUniqueArgs ): Promise { @@ -54,7 +82,13 @@ export class MembershipResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Membership) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "create", + possession: "any", + }) async createMembership( @graphql.Args() args: CreateMembershipArgs ): Promise { @@ -74,7 +108,13 @@ export class MembershipResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Membership) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "update", + possession: "any", + }) async updateMembership( @graphql.Args() args: UpdateMembershipArgs ): Promise { @@ -104,6 +144,11 @@ export class MembershipResolverBase { } @graphql.Mutation(() => Membership) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "delete", + possession: "any", + }) async deleteMembership( @graphql.Args() args: DeleteMembershipArgs ): Promise { @@ -119,10 +164,16 @@ export class MembershipResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Team, { nullable: true, name: "team", }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "any", + }) async getTeam(@graphql.Parent() parent: Membership): Promise { const result = await this.service.getTeam(parent.id); @@ -132,10 +183,16 @@ export class MembershipResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser( @graphql.Parent() parent: Membership ): Promise { diff --git a/apps/basic-auth-provider/src/membership/membership.controller.ts b/apps/basic-auth-provider/src/membership/membership.controller.ts index 285142a..013bf9d 100644 --- a/apps/basic-auth-provider/src/membership/membership.controller.ts +++ b/apps/basic-auth-provider/src/membership/membership.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { MembershipService } from "./membership.service"; import { MembershipControllerBase } from "./base/membership.controller.base"; @swagger.ApiTags("memberships") @common.Controller("memberships") export class MembershipController extends MembershipControllerBase { - constructor(protected readonly service: MembershipService) { - super(service); + constructor( + protected readonly service: MembershipService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/membership/membership.module.ts b/apps/basic-auth-provider/src/membership/membership.module.ts index 1cba28c..c2a92dc 100644 --- a/apps/basic-auth-provider/src/membership/membership.module.ts +++ b/apps/basic-auth-provider/src/membership/membership.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { MembershipModuleBase } from "./base/membership.module.base"; import { MembershipService } from "./membership.service"; import { MembershipController } from "./membership.controller"; import { MembershipResolver } from "./membership.resolver"; @Module({ - imports: [MembershipModuleBase], + imports: [MembershipModuleBase, forwardRef(() => AuthModule)], controllers: [MembershipController], providers: [MembershipService, MembershipResolver], exports: [MembershipService], diff --git a/apps/basic-auth-provider/src/membership/membership.resolver.ts b/apps/basic-auth-provider/src/membership/membership.resolver.ts index 7163597..08c591f 100644 --- a/apps/basic-auth-provider/src/membership/membership.resolver.ts +++ b/apps/basic-auth-provider/src/membership/membership.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { MembershipResolverBase } from "./base/membership.resolver.base"; import { Membership } from "./base/Membership"; import { MembershipService } from "./membership.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Membership) export class MembershipResolver extends MembershipResolverBase { - constructor(protected readonly service: MembershipService) { - super(service); + constructor( + protected readonly service: MembershipService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/origUser/base/origUser.controller.base.ts b/apps/basic-auth-provider/src/origUser/base/origUser.controller.base.ts index 3199a7b..89dcd66 100644 --- a/apps/basic-auth-provider/src/origUser/base/origUser.controller.base.ts +++ b/apps/basic-auth-provider/src/origUser/base/origUser.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { OrigUserService } from "../origUser.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { OrigUserCreateInput } from "./OrigUserCreateInput"; import { OrigUser } from "./OrigUser"; import { OrigUserFindManyArgs } from "./OrigUserFindManyArgs"; @@ -65,10 +69,24 @@ import { WorkflowFindManyArgs } from "../../workflow/base/WorkflowFindManyArgs"; import { Workflow } from "../../workflow/base/Workflow"; import { WorkflowWhereUniqueInput } from "../../workflow/base/WorkflowWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class OrigUserControllerBase { - constructor(protected readonly service: OrigUserService) {} + constructor( + protected readonly service: OrigUserService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: OrigUser }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createOrigUser( @common.Body() data: OrigUserCreateInput ): Promise { @@ -129,9 +147,18 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [OrigUser] }) @ApiNestedQuery(OrigUserFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async origUsers(@common.Req() request: Request): Promise { const args = plainToClass(OrigUserFindManyArgs, request.query); return this.service.origUsers({ @@ -183,9 +210,18 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: OrigUser }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async origUser( @common.Param() params: OrigUserWhereUniqueInput ): Promise { @@ -244,9 +280,18 @@ export class OrigUserControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: OrigUser }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateOrigUser( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() data: OrigUserUpdateInput @@ -321,6 +366,14 @@ export class OrigUserControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: OrigUser }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteOrigUser( @common.Param() params: OrigUserWhereUniqueInput ): Promise { @@ -382,8 +435,14 @@ export class OrigUserControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/accounts") @ApiNestedQuery(AccountFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "any", + }) async findAccounts( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -420,6 +479,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/accounts") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectAccounts( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: AccountWhereUniqueInput[] @@ -437,6 +501,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/accounts") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateAccounts( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: AccountWhereUniqueInput[] @@ -454,6 +523,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/accounts") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectAccounts( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: AccountWhereUniqueInput[] @@ -470,8 +544,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/apiKeys") @ApiNestedQuery(ApiKeyFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) async findApiKeys( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -509,6 +589,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/apiKeys") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectApiKeys( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ApiKeyWhereUniqueInput[] @@ -526,6 +611,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/apiKeys") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateApiKeys( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ApiKeyWhereUniqueInput[] @@ -543,6 +633,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/apiKeys") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectApiKeys( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ApiKeyWhereUniqueInput[] @@ -559,8 +654,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/availability") @ApiNestedQuery(AvailabilityFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async findAvailability( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -605,6 +706,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectAvailability( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -622,6 +728,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateAvailability( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -639,6 +750,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectAvailability( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -655,8 +771,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/bookings") @ApiNestedQuery(BookingFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async findBookings( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -723,6 +845,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/bookings") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectBookings( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: BookingWhereUniqueInput[] @@ -740,6 +867,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/bookings") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateBookings( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: BookingWhereUniqueInput[] @@ -757,6 +889,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/bookings") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectBookings( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: BookingWhereUniqueInput[] @@ -773,8 +910,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/credentials") @ApiNestedQuery(CredentialFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async findCredentials( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -809,6 +952,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/credentials") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectCredentials( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: CredentialWhereUniqueInput[] @@ -826,6 +974,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/credentials") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateCredentials( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: CredentialWhereUniqueInput[] @@ -843,6 +996,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/credentials") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectCredentials( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: CredentialWhereUniqueInput[] @@ -859,8 +1017,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/eventTypes") @ApiNestedQuery(EventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async findEventTypes( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -938,6 +1102,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/eventTypes") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectEventTypes( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -955,6 +1124,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/eventTypes") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateEventTypes( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -972,6 +1146,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/eventTypes") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectEventTypes( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -988,8 +1167,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/feedback") @ApiNestedQuery(FeedbackFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "any", + }) async findFeedback( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1019,6 +1204,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/feedback") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectFeedback( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: FeedbackWhereUniqueInput[] @@ -1036,6 +1226,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/feedback") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateFeedback( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: FeedbackWhereUniqueInput[] @@ -1053,6 +1248,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/feedback") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectFeedback( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: FeedbackWhereUniqueInput[] @@ -1069,8 +1269,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/impersonatedBy") @ApiNestedQuery(ImpersonationFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) async findImpersonatedBy( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1104,6 +1310,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/impersonatedBy") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectImpersonatedBy( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ImpersonationWhereUniqueInput[] @@ -1121,6 +1332,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/impersonatedBy") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateImpersonatedBy( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ImpersonationWhereUniqueInput[] @@ -1138,6 +1354,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/impersonatedBy") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectImpersonatedBy( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ImpersonationWhereUniqueInput[] @@ -1154,8 +1375,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/impersonatedUsers") @ApiNestedQuery(ImpersonationFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) async findImpersonatedUsers( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1189,6 +1416,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/impersonatedUsers") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectImpersonatedUsers( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ImpersonationWhereUniqueInput[] @@ -1206,6 +1438,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/impersonatedUsers") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateImpersonatedUsers( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ImpersonationWhereUniqueInput[] @@ -1223,6 +1460,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/impersonatedUsers") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectImpersonatedUsers( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ImpersonationWhereUniqueInput[] @@ -1239,8 +1481,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/schedules") @ApiNestedQuery(ScheduleFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) async findSchedules( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1269,6 +1517,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/schedules") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectSchedules( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ScheduleWhereUniqueInput[] @@ -1286,6 +1539,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/schedules") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateSchedules( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ScheduleWhereUniqueInput[] @@ -1303,6 +1561,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/schedules") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectSchedules( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: ScheduleWhereUniqueInput[] @@ -1319,8 +1582,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/selectedCalendars") @ApiNestedQuery(SelectedCalendarFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "any", + }) async findSelectedCalendars( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1349,6 +1618,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/selectedCalendars") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectSelectedCalendars( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: SelectedCalendarWhereUniqueInput[] @@ -1366,6 +1640,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/selectedCalendars") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateSelectedCalendars( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: SelectedCalendarWhereUniqueInput[] @@ -1383,6 +1662,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/selectedCalendars") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectSelectedCalendars( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: SelectedCalendarWhereUniqueInput[] @@ -1399,8 +1683,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/sessions") @ApiNestedQuery(SessionFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "any", + }) async findSessions( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1429,6 +1719,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/sessions") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectSessions( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: SessionWhereUniqueInput[] @@ -1446,6 +1741,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/sessions") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateSessions( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: SessionWhereUniqueInput[] @@ -1463,6 +1763,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/sessions") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectSessions( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: SessionWhereUniqueInput[] @@ -1479,8 +1784,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/teams") @ApiNestedQuery(MembershipFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) async findTeams( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1515,6 +1826,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/teams") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectTeams( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: MembershipWhereUniqueInput[] @@ -1532,6 +1848,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/teams") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateTeams( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: MembershipWhereUniqueInput[] @@ -1549,6 +1870,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/teams") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectTeams( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: MembershipWhereUniqueInput[] @@ -1565,8 +1891,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/webhooks") @ApiNestedQuery(WebhookFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async findWebhooks( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1613,6 +1945,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/webhooks") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectWebhooks( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -1630,6 +1967,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/webhooks") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateWebhooks( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -1647,6 +1989,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/webhooks") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectWebhooks( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: WebhookWhereUniqueInput[] @@ -1663,8 +2010,14 @@ export class OrigUserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/workflows") @ApiNestedQuery(WorkflowFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) async findWorkflows( @common.Req() request: Request, @common.Param() params: OrigUserWhereUniqueInput @@ -1695,6 +2048,11 @@ export class OrigUserControllerBase { } @common.Post("/:id/workflows") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async connectWorkflows( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: WorkflowWhereUniqueInput[] @@ -1712,6 +2070,11 @@ export class OrigUserControllerBase { } @common.Patch("/:id/workflows") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateWorkflows( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: WorkflowWhereUniqueInput[] @@ -1729,6 +2092,11 @@ export class OrigUserControllerBase { } @common.Delete("/:id/workflows") + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async disconnectWorkflows( @common.Param() params: OrigUserWhereUniqueInput, @common.Body() body: WorkflowWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/origUser/base/origUser.module.base.ts b/apps/basic-auth-provider/src/origUser/base/origUser.module.base.ts index 1d8d095..e19d47f 100644 --- a/apps/basic-auth-provider/src/origUser/base/origUser.module.base.ts +++ b/apps/basic-auth-provider/src/origUser/base/origUser.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class OrigUserModuleBase {} diff --git a/apps/basic-auth-provider/src/origUser/base/origUser.resolver.base.ts b/apps/basic-auth-provider/src/origUser/base/origUser.resolver.base.ts index deca7c5..5794fa0 100644 --- a/apps/basic-auth-provider/src/origUser/base/origUser.resolver.base.ts +++ b/apps/basic-auth-provider/src/origUser/base/origUser.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { OrigUser } from "./OrigUser"; import { OrigUserCountArgs } from "./OrigUserCountArgs"; import { OrigUserFindManyArgs } from "./OrigUserFindManyArgs"; @@ -50,10 +56,20 @@ import { WorkflowFindManyArgs } from "../../workflow/base/WorkflowFindManyArgs"; import { Workflow } from "../../workflow/base/Workflow"; import { DestinationCalendar } from "../../destinationCalendar/base/DestinationCalendar"; import { OrigUserService } from "../origUser.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => OrigUser) export class OrigUserResolverBase { - constructor(protected readonly service: OrigUserService) {} - + constructor( + protected readonly service: OrigUserService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async _origUsersMeta( @graphql.Args() args: OrigUserCountArgs ): Promise { @@ -63,14 +79,26 @@ export class OrigUserResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [OrigUser]) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async origUsers( @graphql.Args() args: OrigUserFindManyArgs ): Promise { return this.service.origUsers(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => OrigUser, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "own", + }) async origUser( @graphql.Args() args: OrigUserFindUniqueArgs ): Promise { @@ -81,7 +109,13 @@ export class OrigUserResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => OrigUser) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "create", + possession: "any", + }) async createOrigUser( @graphql.Args() args: CreateOrigUserArgs ): Promise { @@ -99,7 +133,13 @@ export class OrigUserResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => OrigUser) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "update", + possession: "any", + }) async updateOrigUser( @graphql.Args() args: UpdateOrigUserArgs ): Promise { @@ -127,6 +167,11 @@ export class OrigUserResolverBase { } @graphql.Mutation(() => OrigUser) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "delete", + possession: "any", + }) async deleteOrigUser( @graphql.Args() args: DeleteOrigUserArgs ): Promise { @@ -142,7 +187,13 @@ export class OrigUserResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Account], { name: "accounts" }) + @nestAccessControl.UseRoles({ + resource: "Account", + action: "read", + possession: "any", + }) async findAccounts( @graphql.Parent() parent: OrigUser, @graphql.Args() args: AccountFindManyArgs @@ -156,7 +207,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [ApiKey], { name: "apiKeys" }) + @nestAccessControl.UseRoles({ + resource: "ApiKey", + action: "read", + possession: "any", + }) async findApiKeys( @graphql.Parent() parent: OrigUser, @graphql.Args() args: ApiKeyFindManyArgs @@ -170,7 +227,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Availability], { name: "availability" }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async findAvailability( @graphql.Parent() parent: OrigUser, @graphql.Args() args: AvailabilityFindManyArgs @@ -184,7 +247,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Booking], { name: "bookings" }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async findBookings( @graphql.Parent() parent: OrigUser, @graphql.Args() args: BookingFindManyArgs @@ -198,7 +267,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Credential], { name: "credentials" }) + @nestAccessControl.UseRoles({ + resource: "Credential", + action: "read", + possession: "any", + }) async findCredentials( @graphql.Parent() parent: OrigUser, @graphql.Args() args: CredentialFindManyArgs @@ -212,7 +287,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [EventType], { name: "eventTypes" }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async findEventTypes( @graphql.Parent() parent: OrigUser, @graphql.Args() args: EventTypeFindManyArgs @@ -226,7 +307,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Feedback], { name: "feedback" }) + @nestAccessControl.UseRoles({ + resource: "Feedback", + action: "read", + possession: "any", + }) async findFeedback( @graphql.Parent() parent: OrigUser, @graphql.Args() args: FeedbackFindManyArgs @@ -240,7 +327,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Impersonation], { name: "impersonatedBy" }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) async findImpersonatedBy( @graphql.Parent() parent: OrigUser, @graphql.Args() args: ImpersonationFindManyArgs @@ -254,7 +347,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Impersonation], { name: "impersonatedUsers" }) + @nestAccessControl.UseRoles({ + resource: "Impersonation", + action: "read", + possession: "any", + }) async findImpersonatedUsers( @graphql.Parent() parent: OrigUser, @graphql.Args() args: ImpersonationFindManyArgs @@ -268,7 +367,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Schedule], { name: "schedules" }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) async findSchedules( @graphql.Parent() parent: OrigUser, @graphql.Args() args: ScheduleFindManyArgs @@ -282,7 +387,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [SelectedCalendar], { name: "selectedCalendars" }) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "any", + }) async findSelectedCalendars( @graphql.Parent() parent: OrigUser, @graphql.Args() args: SelectedCalendarFindManyArgs @@ -296,7 +407,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Session], { name: "sessions" }) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "any", + }) async findSessions( @graphql.Parent() parent: OrigUser, @graphql.Args() args: SessionFindManyArgs @@ -310,7 +427,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Membership], { name: "teams" }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) async findTeams( @graphql.Parent() parent: OrigUser, @graphql.Args() args: MembershipFindManyArgs @@ -324,7 +447,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Webhook], { name: "webhooks" }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async findWebhooks( @graphql.Parent() parent: OrigUser, @graphql.Args() args: WebhookFindManyArgs @@ -338,7 +467,13 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Workflow], { name: "workflows" }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) async findWorkflows( @graphql.Parent() parent: OrigUser, @graphql.Args() args: WorkflowFindManyArgs @@ -352,10 +487,16 @@ export class OrigUserResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => DestinationCalendar, { nullable: true, name: "destinationCalendar", }) + @nestAccessControl.UseRoles({ + resource: "DestinationCalendar", + action: "read", + possession: "any", + }) async getDestinationCalendar( @graphql.Parent() parent: OrigUser ): Promise { diff --git a/apps/basic-auth-provider/src/origUser/origUser.controller.ts b/apps/basic-auth-provider/src/origUser/origUser.controller.ts index adf80ea..ca02d70 100644 --- a/apps/basic-auth-provider/src/origUser/origUser.controller.ts +++ b/apps/basic-auth-provider/src/origUser/origUser.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { OrigUserService } from "./origUser.service"; import { OrigUserControllerBase } from "./base/origUser.controller.base"; @swagger.ApiTags("origUsers") @common.Controller("origUsers") export class OrigUserController extends OrigUserControllerBase { - constructor(protected readonly service: OrigUserService) { - super(service); + constructor( + protected readonly service: OrigUserService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/origUser/origUser.module.ts b/apps/basic-auth-provider/src/origUser/origUser.module.ts index 9da53be..91b51ef 100644 --- a/apps/basic-auth-provider/src/origUser/origUser.module.ts +++ b/apps/basic-auth-provider/src/origUser/origUser.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { OrigUserModuleBase } from "./base/origUser.module.base"; import { OrigUserService } from "./origUser.service"; import { OrigUserController } from "./origUser.controller"; import { OrigUserResolver } from "./origUser.resolver"; @Module({ - imports: [OrigUserModuleBase], + imports: [OrigUserModuleBase, forwardRef(() => AuthModule)], controllers: [OrigUserController], providers: [OrigUserService, OrigUserResolver], exports: [OrigUserService], diff --git a/apps/basic-auth-provider/src/origUser/origUser.resolver.ts b/apps/basic-auth-provider/src/origUser/origUser.resolver.ts index 8ba6826..85fcefb 100644 --- a/apps/basic-auth-provider/src/origUser/origUser.resolver.ts +++ b/apps/basic-auth-provider/src/origUser/origUser.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { OrigUserResolverBase } from "./base/origUser.resolver.base"; import { OrigUser } from "./base/OrigUser"; import { OrigUserService } from "./origUser.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => OrigUser) export class OrigUserResolver extends OrigUserResolverBase { - constructor(protected readonly service: OrigUserService) { - super(service); + constructor( + protected readonly service: OrigUserService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/payment/base/payment.controller.base.ts b/apps/basic-auth-provider/src/payment/base/payment.controller.base.ts index 20282a3..3395b8e 100644 --- a/apps/basic-auth-provider/src/payment/base/payment.controller.base.ts +++ b/apps/basic-auth-provider/src/payment/base/payment.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { PaymentService } from "../payment.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { PaymentCreateInput } from "./PaymentCreateInput"; import { Payment } from "./Payment"; import { PaymentFindManyArgs } from "./PaymentFindManyArgs"; import { PaymentWhereUniqueInput } from "./PaymentWhereUniqueInput"; import { PaymentUpdateInput } from "./PaymentUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class PaymentControllerBase { - constructor(protected readonly service: PaymentService) {} + constructor( + protected readonly service: PaymentService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Payment }) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createPayment( @common.Body() data: PaymentCreateInput ): Promise { @@ -62,9 +80,18 @@ export class PaymentControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Payment] }) @ApiNestedQuery(PaymentFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async payments(@common.Req() request: Request): Promise { const args = plainToClass(PaymentFindManyArgs, request.query); return this.service.payments({ @@ -91,9 +118,18 @@ export class PaymentControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Payment }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async payment( @common.Param() params: PaymentWhereUniqueInput ): Promise { @@ -127,9 +163,18 @@ export class PaymentControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Payment }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updatePayment( @common.Param() params: PaymentWhereUniqueInput, @common.Body() data: PaymentUpdateInput @@ -179,6 +224,14 @@ export class PaymentControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Payment }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deletePayment( @common.Param() params: PaymentWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/payment/base/payment.module.base.ts b/apps/basic-auth-provider/src/payment/base/payment.module.base.ts index bd786e5..ddc72b1 100644 --- a/apps/basic-auth-provider/src/payment/base/payment.module.base.ts +++ b/apps/basic-auth-provider/src/payment/base/payment.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class PaymentModuleBase {} diff --git a/apps/basic-auth-provider/src/payment/base/payment.resolver.base.ts b/apps/basic-auth-provider/src/payment/base/payment.resolver.base.ts index 27ad43e..d03c782 100644 --- a/apps/basic-auth-provider/src/payment/base/payment.resolver.base.ts +++ b/apps/basic-auth-provider/src/payment/base/payment.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Payment } from "./Payment"; import { PaymentCountArgs } from "./PaymentCountArgs"; import { PaymentFindManyArgs } from "./PaymentFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdatePaymentArgs } from "./UpdatePaymentArgs"; import { DeletePaymentArgs } from "./DeletePaymentArgs"; import { Booking } from "../../booking/base/Booking"; import { PaymentService } from "../payment.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Payment) export class PaymentResolverBase { - constructor(protected readonly service: PaymentService) {} + constructor( + protected readonly service: PaymentService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "any", + }) async _paymentsMeta( @graphql.Args() args: PaymentCountArgs ): Promise { @@ -35,14 +51,26 @@ export class PaymentResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Payment]) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "any", + }) async payments( @graphql.Args() args: PaymentFindManyArgs ): Promise { return this.service.payments(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Payment, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "read", + possession: "own", + }) async payment( @graphql.Args() args: PaymentFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class PaymentResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Payment) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "create", + possession: "any", + }) async createPayment( @graphql.Args() args: CreatePaymentArgs ): Promise { @@ -71,7 +105,13 @@ export class PaymentResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Payment) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "update", + possession: "any", + }) async updatePayment( @graphql.Args() args: UpdatePaymentArgs ): Promise { @@ -99,6 +139,11 @@ export class PaymentResolverBase { } @graphql.Mutation(() => Payment) + @nestAccessControl.UseRoles({ + resource: "Payment", + action: "delete", + possession: "any", + }) async deletePayment( @graphql.Args() args: DeletePaymentArgs ): Promise { @@ -114,10 +159,16 @@ export class PaymentResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Booking, { nullable: true, name: "booking", }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async getBooking(@graphql.Parent() parent: Payment): Promise { const result = await this.service.getBooking(parent.id); diff --git a/apps/basic-auth-provider/src/payment/payment.controller.ts b/apps/basic-auth-provider/src/payment/payment.controller.ts index 7c02bc3..7f49163 100644 --- a/apps/basic-auth-provider/src/payment/payment.controller.ts +++ b/apps/basic-auth-provider/src/payment/payment.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { PaymentService } from "./payment.service"; import { PaymentControllerBase } from "./base/payment.controller.base"; @swagger.ApiTags("payments") @common.Controller("payments") export class PaymentController extends PaymentControllerBase { - constructor(protected readonly service: PaymentService) { - super(service); + constructor( + protected readonly service: PaymentService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/payment/payment.module.ts b/apps/basic-auth-provider/src/payment/payment.module.ts index 8779d63..31c634b 100644 --- a/apps/basic-auth-provider/src/payment/payment.module.ts +++ b/apps/basic-auth-provider/src/payment/payment.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { PaymentModuleBase } from "./base/payment.module.base"; import { PaymentService } from "./payment.service"; import { PaymentController } from "./payment.controller"; import { PaymentResolver } from "./payment.resolver"; @Module({ - imports: [PaymentModuleBase], + imports: [PaymentModuleBase, forwardRef(() => AuthModule)], controllers: [PaymentController], providers: [PaymentService, PaymentResolver], exports: [PaymentService], diff --git a/apps/basic-auth-provider/src/payment/payment.resolver.ts b/apps/basic-auth-provider/src/payment/payment.resolver.ts index 6df076d..0c5ac5a 100644 --- a/apps/basic-auth-provider/src/payment/payment.resolver.ts +++ b/apps/basic-auth-provider/src/payment/payment.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { PaymentResolverBase } from "./base/payment.resolver.base"; import { Payment } from "./base/Payment"; import { PaymentService } from "./payment.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Payment) export class PaymentResolver extends PaymentResolverBase { - constructor(protected readonly service: PaymentService) { - super(service); + constructor( + protected readonly service: PaymentService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/reminderMail/base/reminderMail.controller.base.ts b/apps/basic-auth-provider/src/reminderMail/base/reminderMail.controller.base.ts index ace7843..04fb26a 100644 --- a/apps/basic-auth-provider/src/reminderMail/base/reminderMail.controller.base.ts +++ b/apps/basic-auth-provider/src/reminderMail/base/reminderMail.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { ReminderMailService } from "../reminderMail.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { ReminderMailCreateInput } from "./ReminderMailCreateInput"; import { ReminderMail } from "./ReminderMail"; import { ReminderMailFindManyArgs } from "./ReminderMailFindManyArgs"; import { ReminderMailWhereUniqueInput } from "./ReminderMailWhereUniqueInput"; import { ReminderMailUpdateInput } from "./ReminderMailUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class ReminderMailControllerBase { - constructor(protected readonly service: ReminderMailService) {} + constructor( + protected readonly service: ReminderMailService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: ReminderMail }) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createReminderMail( @common.Body() data: ReminderMailCreateInput ): Promise { @@ -42,9 +60,18 @@ export class ReminderMailControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [ReminderMail] }) @ApiNestedQuery(ReminderMailFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async reminderMails(@common.Req() request: Request): Promise { const args = plainToClass(ReminderMailFindManyArgs, request.query); return this.service.reminderMails({ @@ -59,9 +86,18 @@ export class ReminderMailControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: ReminderMail }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async reminderMail( @common.Param() params: ReminderMailWhereUniqueInput ): Promise { @@ -83,9 +119,18 @@ export class ReminderMailControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: ReminderMail }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateReminderMail( @common.Param() params: ReminderMailWhereUniqueInput, @common.Body() data: ReminderMailUpdateInput @@ -115,6 +160,14 @@ export class ReminderMailControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: ReminderMail }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteReminderMail( @common.Param() params: ReminderMailWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/reminderMail/base/reminderMail.module.base.ts b/apps/basic-auth-provider/src/reminderMail/base/reminderMail.module.base.ts index 98113e5..bc52481 100644 --- a/apps/basic-auth-provider/src/reminderMail/base/reminderMail.module.base.ts +++ b/apps/basic-auth-provider/src/reminderMail/base/reminderMail.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class ReminderMailModuleBase {} diff --git a/apps/basic-auth-provider/src/reminderMail/base/reminderMail.resolver.base.ts b/apps/basic-auth-provider/src/reminderMail/base/reminderMail.resolver.base.ts index c79070f..91981c5 100644 --- a/apps/basic-auth-provider/src/reminderMail/base/reminderMail.resolver.base.ts +++ b/apps/basic-auth-provider/src/reminderMail/base/reminderMail.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { ReminderMail } from "./ReminderMail"; import { ReminderMailCountArgs } from "./ReminderMailCountArgs"; import { ReminderMailFindManyArgs } from "./ReminderMailFindManyArgs"; @@ -21,10 +27,20 @@ import { CreateReminderMailArgs } from "./CreateReminderMailArgs"; import { UpdateReminderMailArgs } from "./UpdateReminderMailArgs"; import { DeleteReminderMailArgs } from "./DeleteReminderMailArgs"; import { ReminderMailService } from "../reminderMail.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => ReminderMail) export class ReminderMailResolverBase { - constructor(protected readonly service: ReminderMailService) {} + constructor( + protected readonly service: ReminderMailService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "read", + possession: "any", + }) async _reminderMailsMeta( @graphql.Args() args: ReminderMailCountArgs ): Promise { @@ -34,14 +50,26 @@ export class ReminderMailResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [ReminderMail]) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "read", + possession: "any", + }) async reminderMails( @graphql.Args() args: ReminderMailFindManyArgs ): Promise { return this.service.reminderMails(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => ReminderMail, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "read", + possession: "own", + }) async reminderMail( @graphql.Args() args: ReminderMailFindUniqueArgs ): Promise { @@ -52,7 +80,13 @@ export class ReminderMailResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => ReminderMail) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "create", + possession: "any", + }) async createReminderMail( @graphql.Args() args: CreateReminderMailArgs ): Promise { @@ -62,7 +96,13 @@ export class ReminderMailResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => ReminderMail) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "update", + possession: "any", + }) async updateReminderMail( @graphql.Args() args: UpdateReminderMailArgs ): Promise { @@ -82,6 +122,11 @@ export class ReminderMailResolverBase { } @graphql.Mutation(() => ReminderMail) + @nestAccessControl.UseRoles({ + resource: "ReminderMail", + action: "delete", + possession: "any", + }) async deleteReminderMail( @graphql.Args() args: DeleteReminderMailArgs ): Promise { diff --git a/apps/basic-auth-provider/src/reminderMail/reminderMail.controller.ts b/apps/basic-auth-provider/src/reminderMail/reminderMail.controller.ts index cd4caac..f22d0b2 100644 --- a/apps/basic-auth-provider/src/reminderMail/reminderMail.controller.ts +++ b/apps/basic-auth-provider/src/reminderMail/reminderMail.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { ReminderMailService } from "./reminderMail.service"; import { ReminderMailControllerBase } from "./base/reminderMail.controller.base"; @swagger.ApiTags("reminderMails") @common.Controller("reminderMails") export class ReminderMailController extends ReminderMailControllerBase { - constructor(protected readonly service: ReminderMailService) { - super(service); + constructor( + protected readonly service: ReminderMailService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/reminderMail/reminderMail.module.ts b/apps/basic-auth-provider/src/reminderMail/reminderMail.module.ts index a6ca772..e369a04 100644 --- a/apps/basic-auth-provider/src/reminderMail/reminderMail.module.ts +++ b/apps/basic-auth-provider/src/reminderMail/reminderMail.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { ReminderMailModuleBase } from "./base/reminderMail.module.base"; import { ReminderMailService } from "./reminderMail.service"; import { ReminderMailController } from "./reminderMail.controller"; import { ReminderMailResolver } from "./reminderMail.resolver"; @Module({ - imports: [ReminderMailModuleBase], + imports: [ReminderMailModuleBase, forwardRef(() => AuthModule)], controllers: [ReminderMailController], providers: [ReminderMailService, ReminderMailResolver], exports: [ReminderMailService], diff --git a/apps/basic-auth-provider/src/reminderMail/reminderMail.resolver.ts b/apps/basic-auth-provider/src/reminderMail/reminderMail.resolver.ts index 758184b..ca96d38 100644 --- a/apps/basic-auth-provider/src/reminderMail/reminderMail.resolver.ts +++ b/apps/basic-auth-provider/src/reminderMail/reminderMail.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { ReminderMailResolverBase } from "./base/reminderMail.resolver.base"; import { ReminderMail } from "./base/ReminderMail"; import { ReminderMailService } from "./reminderMail.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => ReminderMail) export class ReminderMailResolver extends ReminderMailResolverBase { - constructor(protected readonly service: ReminderMailService) { - super(service); + constructor( + protected readonly service: ReminderMailService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.controller.base.ts b/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.controller.base.ts index 1ddca06..416a96c 100644 --- a/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.controller.base.ts +++ b/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { ResetPasswordRequestService } from "../resetPasswordRequest.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { ResetPasswordRequestCreateInput } from "./ResetPasswordRequestCreateInput"; import { ResetPasswordRequest } from "./ResetPasswordRequest"; import { ResetPasswordRequestFindManyArgs } from "./ResetPasswordRequestFindManyArgs"; import { ResetPasswordRequestWhereUniqueInput } from "./ResetPasswordRequestWhereUniqueInput"; import { ResetPasswordRequestUpdateInput } from "./ResetPasswordRequestUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class ResetPasswordRequestControllerBase { - constructor(protected readonly service: ResetPasswordRequestService) {} + constructor( + protected readonly service: ResetPasswordRequestService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: ResetPasswordRequest }) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createResetPasswordRequest( @common.Body() data: ResetPasswordRequestCreateInput ): Promise { @@ -42,9 +60,18 @@ export class ResetPasswordRequestControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [ResetPasswordRequest] }) @ApiNestedQuery(ResetPasswordRequestFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async resetPasswordRequests( @common.Req() request: Request ): Promise { @@ -61,9 +88,18 @@ export class ResetPasswordRequestControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: ResetPasswordRequest }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async resetPasswordRequest( @common.Param() params: ResetPasswordRequestWhereUniqueInput ): Promise { @@ -85,9 +121,18 @@ export class ResetPasswordRequestControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: ResetPasswordRequest }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateResetPasswordRequest( @common.Param() params: ResetPasswordRequestWhereUniqueInput, @common.Body() data: ResetPasswordRequestUpdateInput @@ -117,6 +162,14 @@ export class ResetPasswordRequestControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: ResetPasswordRequest }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteResetPasswordRequest( @common.Param() params: ResetPasswordRequestWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.module.base.ts b/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.module.base.ts index f8e9874..a16b894 100644 --- a/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.module.base.ts +++ b/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class ResetPasswordRequestModuleBase {} diff --git a/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.resolver.base.ts b/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.resolver.base.ts index 2a5da6a..2ec7d5b 100644 --- a/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.resolver.base.ts +++ b/apps/basic-auth-provider/src/resetPasswordRequest/base/resetPasswordRequest.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { ResetPasswordRequest } from "./ResetPasswordRequest"; import { ResetPasswordRequestCountArgs } from "./ResetPasswordRequestCountArgs"; import { ResetPasswordRequestFindManyArgs } from "./ResetPasswordRequestFindManyArgs"; @@ -21,10 +27,20 @@ import { CreateResetPasswordRequestArgs } from "./CreateResetPasswordRequestArgs import { UpdateResetPasswordRequestArgs } from "./UpdateResetPasswordRequestArgs"; import { DeleteResetPasswordRequestArgs } from "./DeleteResetPasswordRequestArgs"; import { ResetPasswordRequestService } from "../resetPasswordRequest.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => ResetPasswordRequest) export class ResetPasswordRequestResolverBase { - constructor(protected readonly service: ResetPasswordRequestService) {} + constructor( + protected readonly service: ResetPasswordRequestService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "read", + possession: "any", + }) async _resetPasswordRequestsMeta( @graphql.Args() args: ResetPasswordRequestCountArgs ): Promise { @@ -34,14 +50,26 @@ export class ResetPasswordRequestResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [ResetPasswordRequest]) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "read", + possession: "any", + }) async resetPasswordRequests( @graphql.Args() args: ResetPasswordRequestFindManyArgs ): Promise { return this.service.resetPasswordRequests(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => ResetPasswordRequest, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "read", + possession: "own", + }) async resetPasswordRequest( @graphql.Args() args: ResetPasswordRequestFindUniqueArgs ): Promise { @@ -52,7 +80,13 @@ export class ResetPasswordRequestResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => ResetPasswordRequest) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "create", + possession: "any", + }) async createResetPasswordRequest( @graphql.Args() args: CreateResetPasswordRequestArgs ): Promise { @@ -62,7 +96,13 @@ export class ResetPasswordRequestResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => ResetPasswordRequest) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "update", + possession: "any", + }) async updateResetPasswordRequest( @graphql.Args() args: UpdateResetPasswordRequestArgs ): Promise { @@ -82,6 +122,11 @@ export class ResetPasswordRequestResolverBase { } @graphql.Mutation(() => ResetPasswordRequest) + @nestAccessControl.UseRoles({ + resource: "ResetPasswordRequest", + action: "delete", + possession: "any", + }) async deleteResetPasswordRequest( @graphql.Args() args: DeleteResetPasswordRequestArgs ): Promise { diff --git a/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.controller.ts b/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.controller.ts index 1702b02..4d79339 100644 --- a/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.controller.ts +++ b/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { ResetPasswordRequestService } from "./resetPasswordRequest.service"; import { ResetPasswordRequestControllerBase } from "./base/resetPasswordRequest.controller.base"; @swagger.ApiTags("resetPasswordRequests") @common.Controller("resetPasswordRequests") export class ResetPasswordRequestController extends ResetPasswordRequestControllerBase { - constructor(protected readonly service: ResetPasswordRequestService) { - super(service); + constructor( + protected readonly service: ResetPasswordRequestService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.module.ts b/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.module.ts index 3bd885d..0c3ff1c 100644 --- a/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.module.ts +++ b/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { ResetPasswordRequestModuleBase } from "./base/resetPasswordRequest.module.base"; import { ResetPasswordRequestService } from "./resetPasswordRequest.service"; import { ResetPasswordRequestController } from "./resetPasswordRequest.controller"; import { ResetPasswordRequestResolver } from "./resetPasswordRequest.resolver"; @Module({ - imports: [ResetPasswordRequestModuleBase], + imports: [ResetPasswordRequestModuleBase, forwardRef(() => AuthModule)], controllers: [ResetPasswordRequestController], providers: [ResetPasswordRequestService, ResetPasswordRequestResolver], exports: [ResetPasswordRequestService], diff --git a/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.resolver.ts b/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.resolver.ts index 2740896..0105fd6 100644 --- a/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.resolver.ts +++ b/apps/basic-auth-provider/src/resetPasswordRequest/resetPasswordRequest.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { ResetPasswordRequestResolverBase } from "./base/resetPasswordRequest.resolver.base"; import { ResetPasswordRequest } from "./base/ResetPasswordRequest"; import { ResetPasswordRequestService } from "./resetPasswordRequest.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => ResetPasswordRequest) export class ResetPasswordRequestResolver extends ResetPasswordRequestResolverBase { - constructor(protected readonly service: ResetPasswordRequestService) { - super(service); + constructor( + protected readonly service: ResetPasswordRequestService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/schedule/base/schedule.controller.base.ts b/apps/basic-auth-provider/src/schedule/base/schedule.controller.base.ts index 806bb72..919f79e 100644 --- a/apps/basic-auth-provider/src/schedule/base/schedule.controller.base.ts +++ b/apps/basic-auth-provider/src/schedule/base/schedule.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { ScheduleService } from "../schedule.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { ScheduleCreateInput } from "./ScheduleCreateInput"; import { Schedule } from "./Schedule"; import { ScheduleFindManyArgs } from "./ScheduleFindManyArgs"; @@ -29,10 +33,24 @@ import { EventTypeFindManyArgs } from "../../eventType/base/EventTypeFindManyArg import { EventType } from "../../eventType/base/EventType"; import { EventTypeWhereUniqueInput } from "../../eventType/base/EventTypeWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class ScheduleControllerBase { - constructor(protected readonly service: ScheduleService) {} + constructor( + protected readonly service: ScheduleService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Schedule }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createSchedule( @common.Body() data: ScheduleCreateInput ): Promise { @@ -58,9 +76,18 @@ export class ScheduleControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Schedule] }) @ApiNestedQuery(ScheduleFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async schedules(@common.Req() request: Request): Promise { const args = plainToClass(ScheduleFindManyArgs, request.query); return this.service.schedules({ @@ -79,9 +106,18 @@ export class ScheduleControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Schedule }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async schedule( @common.Param() params: ScheduleWhereUniqueInput ): Promise { @@ -107,9 +143,18 @@ export class ScheduleControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Schedule }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateSchedule( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() data: ScheduleUpdateInput @@ -149,6 +194,14 @@ export class ScheduleControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Schedule }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteSchedule( @common.Param() params: ScheduleWhereUniqueInput ): Promise { @@ -177,8 +230,14 @@ export class ScheduleControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/availability") @ApiNestedQuery(AvailabilityFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async findAvailability( @common.Req() request: Request, @common.Param() params: ScheduleWhereUniqueInput @@ -223,6 +282,11 @@ export class ScheduleControllerBase { } @common.Post("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async connectAvailability( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -240,6 +304,11 @@ export class ScheduleControllerBase { } @common.Patch("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async updateAvailability( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -257,6 +326,11 @@ export class ScheduleControllerBase { } @common.Delete("/:id/availability") + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async disconnectAvailability( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() body: AvailabilityWhereUniqueInput[] @@ -273,8 +347,14 @@ export class ScheduleControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/eventType") @ApiNestedQuery(EventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async findEventType( @common.Req() request: Request, @common.Param() params: ScheduleWhereUniqueInput @@ -352,6 +432,11 @@ export class ScheduleControllerBase { } @common.Post("/:id/eventType") + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async connectEventType( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -369,6 +454,11 @@ export class ScheduleControllerBase { } @common.Patch("/:id/eventType") + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async updateEventType( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -386,6 +476,11 @@ export class ScheduleControllerBase { } @common.Delete("/:id/eventType") + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async disconnectEventType( @common.Param() params: ScheduleWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/schedule/base/schedule.module.base.ts b/apps/basic-auth-provider/src/schedule/base/schedule.module.base.ts index 2976749..af359b8 100644 --- a/apps/basic-auth-provider/src/schedule/base/schedule.module.base.ts +++ b/apps/basic-auth-provider/src/schedule/base/schedule.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class ScheduleModuleBase {} diff --git a/apps/basic-auth-provider/src/schedule/base/schedule.resolver.base.ts b/apps/basic-auth-provider/src/schedule/base/schedule.resolver.base.ts index c4e3df5..dace300 100644 --- a/apps/basic-auth-provider/src/schedule/base/schedule.resolver.base.ts +++ b/apps/basic-auth-provider/src/schedule/base/schedule.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Schedule } from "./Schedule"; import { ScheduleCountArgs } from "./ScheduleCountArgs"; import { ScheduleFindManyArgs } from "./ScheduleFindManyArgs"; @@ -26,10 +32,20 @@ import { EventTypeFindManyArgs } from "../../eventType/base/EventTypeFindManyArg import { EventType } from "../../eventType/base/EventType"; import { OrigUser } from "../../origUser/base/OrigUser"; import { ScheduleService } from "../schedule.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Schedule) export class ScheduleResolverBase { - constructor(protected readonly service: ScheduleService) {} - + constructor( + protected readonly service: ScheduleService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) async _schedulesMeta( @graphql.Args() args: ScheduleCountArgs ): Promise { @@ -39,14 +55,26 @@ export class ScheduleResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Schedule]) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "any", + }) async schedules( @graphql.Args() args: ScheduleFindManyArgs ): Promise { return this.service.schedules(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Schedule, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "read", + possession: "own", + }) async schedule( @graphql.Args() args: ScheduleFindUniqueArgs ): Promise { @@ -57,7 +85,13 @@ export class ScheduleResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Schedule) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "create", + possession: "any", + }) async createSchedule( @graphql.Args() args: CreateScheduleArgs ): Promise { @@ -73,7 +107,13 @@ export class ScheduleResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Schedule) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "update", + possession: "any", + }) async updateSchedule( @graphql.Args() args: UpdateScheduleArgs ): Promise { @@ -99,6 +139,11 @@ export class ScheduleResolverBase { } @graphql.Mutation(() => Schedule) + @nestAccessControl.UseRoles({ + resource: "Schedule", + action: "delete", + possession: "any", + }) async deleteSchedule( @graphql.Args() args: DeleteScheduleArgs ): Promise { @@ -114,7 +159,13 @@ export class ScheduleResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Availability], { name: "availability" }) + @nestAccessControl.UseRoles({ + resource: "Availability", + action: "read", + possession: "any", + }) async findAvailability( @graphql.Parent() parent: Schedule, @graphql.Args() args: AvailabilityFindManyArgs @@ -128,7 +179,13 @@ export class ScheduleResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [EventType], { name: "eventType" }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async findEventType( @graphql.Parent() parent: Schedule, @graphql.Args() args: EventTypeFindManyArgs @@ -142,10 +199,16 @@ export class ScheduleResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Schedule): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/schedule/schedule.controller.ts b/apps/basic-auth-provider/src/schedule/schedule.controller.ts index daf7f6e..f25aac4 100644 --- a/apps/basic-auth-provider/src/schedule/schedule.controller.ts +++ b/apps/basic-auth-provider/src/schedule/schedule.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { ScheduleService } from "./schedule.service"; import { ScheduleControllerBase } from "./base/schedule.controller.base"; @swagger.ApiTags("schedules") @common.Controller("schedules") export class ScheduleController extends ScheduleControllerBase { - constructor(protected readonly service: ScheduleService) { - super(service); + constructor( + protected readonly service: ScheduleService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/schedule/schedule.module.ts b/apps/basic-auth-provider/src/schedule/schedule.module.ts index 771e6d7..fae23a8 100644 --- a/apps/basic-auth-provider/src/schedule/schedule.module.ts +++ b/apps/basic-auth-provider/src/schedule/schedule.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { ScheduleModuleBase } from "./base/schedule.module.base"; import { ScheduleService } from "./schedule.service"; import { ScheduleController } from "./schedule.controller"; import { ScheduleResolver } from "./schedule.resolver"; @Module({ - imports: [ScheduleModuleBase], + imports: [ScheduleModuleBase, forwardRef(() => AuthModule)], controllers: [ScheduleController], providers: [ScheduleService, ScheduleResolver], exports: [ScheduleService], diff --git a/apps/basic-auth-provider/src/schedule/schedule.resolver.ts b/apps/basic-auth-provider/src/schedule/schedule.resolver.ts index a277b31..0e09f22 100644 --- a/apps/basic-auth-provider/src/schedule/schedule.resolver.ts +++ b/apps/basic-auth-provider/src/schedule/schedule.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { ScheduleResolverBase } from "./base/schedule.resolver.base"; import { Schedule } from "./base/Schedule"; import { ScheduleService } from "./schedule.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Schedule) export class ScheduleResolver extends ScheduleResolverBase { - constructor(protected readonly service: ScheduleService) { - super(service); + constructor( + protected readonly service: ScheduleService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.controller.base.ts b/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.controller.base.ts index 84d53b4..27cc208 100644 --- a/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.controller.base.ts +++ b/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { SelectedCalendarService } from "../selectedCalendar.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { SelectedCalendarCreateInput } from "./SelectedCalendarCreateInput"; import { SelectedCalendar } from "./SelectedCalendar"; import { SelectedCalendarFindManyArgs } from "./SelectedCalendarFindManyArgs"; import { SelectedCalendarWhereUniqueInput } from "./SelectedCalendarWhereUniqueInput"; import { SelectedCalendarUpdateInput } from "./SelectedCalendarUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class SelectedCalendarControllerBase { - constructor(protected readonly service: SelectedCalendarService) {} + constructor( + protected readonly service: SelectedCalendarService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: SelectedCalendar }) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createSelectedCalendar( @common.Body() data: SelectedCalendarCreateInput ): Promise { @@ -52,9 +70,18 @@ export class SelectedCalendarControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [SelectedCalendar] }) @ApiNestedQuery(SelectedCalendarFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async selectedCalendars( @common.Req() request: Request ): Promise { @@ -75,9 +102,18 @@ export class SelectedCalendarControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: SelectedCalendar }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async selectedCalendar( @common.Param() params: SelectedCalendarWhereUniqueInput ): Promise { @@ -103,9 +139,18 @@ export class SelectedCalendarControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: SelectedCalendar }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateSelectedCalendar( @common.Param() params: SelectedCalendarWhereUniqueInput, @common.Body() data: SelectedCalendarUpdateInput @@ -145,6 +190,14 @@ export class SelectedCalendarControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: SelectedCalendar }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteSelectedCalendar( @common.Param() params: SelectedCalendarWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.module.base.ts b/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.module.base.ts index 9717b79..d798c62 100644 --- a/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.module.base.ts +++ b/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class SelectedCalendarModuleBase {} diff --git a/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.resolver.base.ts b/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.resolver.base.ts index 0f15318..4b4f0db 100644 --- a/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.resolver.base.ts +++ b/apps/basic-auth-provider/src/selectedCalendar/base/selectedCalendar.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { SelectedCalendar } from "./SelectedCalendar"; import { SelectedCalendarCountArgs } from "./SelectedCalendarCountArgs"; import { SelectedCalendarFindManyArgs } from "./SelectedCalendarFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateSelectedCalendarArgs } from "./UpdateSelectedCalendarArgs"; import { DeleteSelectedCalendarArgs } from "./DeleteSelectedCalendarArgs"; import { OrigUser } from "../../origUser/base/OrigUser"; import { SelectedCalendarService } from "../selectedCalendar.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => SelectedCalendar) export class SelectedCalendarResolverBase { - constructor(protected readonly service: SelectedCalendarService) {} + constructor( + protected readonly service: SelectedCalendarService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "any", + }) async _selectedCalendarsMeta( @graphql.Args() args: SelectedCalendarCountArgs ): Promise { @@ -35,14 +51,26 @@ export class SelectedCalendarResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [SelectedCalendar]) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "any", + }) async selectedCalendars( @graphql.Args() args: SelectedCalendarFindManyArgs ): Promise { return this.service.selectedCalendars(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => SelectedCalendar, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "read", + possession: "own", + }) async selectedCalendar( @graphql.Args() args: SelectedCalendarFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class SelectedCalendarResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => SelectedCalendar) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "create", + possession: "any", + }) async createSelectedCalendar( @graphql.Args() args: CreateSelectedCalendarArgs ): Promise { @@ -69,7 +103,13 @@ export class SelectedCalendarResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => SelectedCalendar) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "update", + possession: "any", + }) async updateSelectedCalendar( @graphql.Args() args: UpdateSelectedCalendarArgs ): Promise { @@ -95,6 +135,11 @@ export class SelectedCalendarResolverBase { } @graphql.Mutation(() => SelectedCalendar) + @nestAccessControl.UseRoles({ + resource: "SelectedCalendar", + action: "delete", + possession: "any", + }) async deleteSelectedCalendar( @graphql.Args() args: DeleteSelectedCalendarArgs ): Promise { @@ -110,10 +155,16 @@ export class SelectedCalendarResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser( @graphql.Parent() parent: SelectedCalendar ): Promise { diff --git a/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.controller.ts b/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.controller.ts index ff741e7..e44d146 100644 --- a/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.controller.ts +++ b/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { SelectedCalendarService } from "./selectedCalendar.service"; import { SelectedCalendarControllerBase } from "./base/selectedCalendar.controller.base"; @swagger.ApiTags("selectedCalendars") @common.Controller("selectedCalendars") export class SelectedCalendarController extends SelectedCalendarControllerBase { - constructor(protected readonly service: SelectedCalendarService) { - super(service); + constructor( + protected readonly service: SelectedCalendarService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.module.ts b/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.module.ts index aa990df..f815c9e 100644 --- a/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.module.ts +++ b/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { SelectedCalendarModuleBase } from "./base/selectedCalendar.module.base"; import { SelectedCalendarService } from "./selectedCalendar.service"; import { SelectedCalendarController } from "./selectedCalendar.controller"; import { SelectedCalendarResolver } from "./selectedCalendar.resolver"; @Module({ - imports: [SelectedCalendarModuleBase], + imports: [SelectedCalendarModuleBase, forwardRef(() => AuthModule)], controllers: [SelectedCalendarController], providers: [SelectedCalendarService, SelectedCalendarResolver], exports: [SelectedCalendarService], diff --git a/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.resolver.ts b/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.resolver.ts index 9cdb292..a886d93 100644 --- a/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.resolver.ts +++ b/apps/basic-auth-provider/src/selectedCalendar/selectedCalendar.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { SelectedCalendarResolverBase } from "./base/selectedCalendar.resolver.base"; import { SelectedCalendar } from "./base/SelectedCalendar"; import { SelectedCalendarService } from "./selectedCalendar.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => SelectedCalendar) export class SelectedCalendarResolver extends SelectedCalendarResolverBase { - constructor(protected readonly service: SelectedCalendarService) { - super(service); + constructor( + protected readonly service: SelectedCalendarService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/session/base/session.controller.base.ts b/apps/basic-auth-provider/src/session/base/session.controller.base.ts index d2ae626..3445195 100644 --- a/apps/basic-auth-provider/src/session/base/session.controller.base.ts +++ b/apps/basic-auth-provider/src/session/base/session.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { SessionService } from "../session.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { SessionCreateInput } from "./SessionCreateInput"; import { Session } from "./Session"; import { SessionFindManyArgs } from "./SessionFindManyArgs"; import { SessionWhereUniqueInput } from "./SessionWhereUniqueInput"; import { SessionUpdateInput } from "./SessionUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class SessionControllerBase { - constructor(protected readonly service: SessionService) {} + constructor( + protected readonly service: SessionService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Session }) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createSession( @common.Body() data: SessionCreateInput ): Promise { @@ -54,9 +72,18 @@ export class SessionControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Session] }) @ApiNestedQuery(SessionFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async sessions(@common.Req() request: Request): Promise { const args = plainToClass(SessionFindManyArgs, request.query); return this.service.sessions({ @@ -75,9 +102,18 @@ export class SessionControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Session }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async session( @common.Param() params: SessionWhereUniqueInput ): Promise { @@ -103,9 +139,18 @@ export class SessionControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Session }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateSession( @common.Param() params: SessionWhereUniqueInput, @common.Body() data: SessionUpdateInput @@ -147,6 +192,14 @@ export class SessionControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Session }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteSession( @common.Param() params: SessionWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/session/base/session.module.base.ts b/apps/basic-auth-provider/src/session/base/session.module.base.ts index 1801ea5..08e9a09 100644 --- a/apps/basic-auth-provider/src/session/base/session.module.base.ts +++ b/apps/basic-auth-provider/src/session/base/session.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class SessionModuleBase {} diff --git a/apps/basic-auth-provider/src/session/base/session.resolver.base.ts b/apps/basic-auth-provider/src/session/base/session.resolver.base.ts index 929c5fd..d629a35 100644 --- a/apps/basic-auth-provider/src/session/base/session.resolver.base.ts +++ b/apps/basic-auth-provider/src/session/base/session.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Session } from "./Session"; import { SessionCountArgs } from "./SessionCountArgs"; import { SessionFindManyArgs } from "./SessionFindManyArgs"; @@ -22,10 +28,20 @@ import { UpdateSessionArgs } from "./UpdateSessionArgs"; import { DeleteSessionArgs } from "./DeleteSessionArgs"; import { OrigUser } from "../../origUser/base/OrigUser"; import { SessionService } from "../session.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Session) export class SessionResolverBase { - constructor(protected readonly service: SessionService) {} + constructor( + protected readonly service: SessionService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "any", + }) async _sessionsMeta( @graphql.Args() args: SessionCountArgs ): Promise { @@ -35,14 +51,26 @@ export class SessionResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Session]) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "any", + }) async sessions( @graphql.Args() args: SessionFindManyArgs ): Promise { return this.service.sessions(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Session, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "read", + possession: "own", + }) async session( @graphql.Args() args: SessionFindUniqueArgs ): Promise { @@ -53,7 +81,13 @@ export class SessionResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Session) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "create", + possession: "any", + }) async createSession( @graphql.Args() args: CreateSessionArgs ): Promise { @@ -71,7 +105,13 @@ export class SessionResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Session) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "update", + possession: "any", + }) async updateSession( @graphql.Args() args: UpdateSessionArgs ): Promise { @@ -99,6 +139,11 @@ export class SessionResolverBase { } @graphql.Mutation(() => Session) + @nestAccessControl.UseRoles({ + resource: "Session", + action: "delete", + possession: "any", + }) async deleteSession( @graphql.Args() args: DeleteSessionArgs ): Promise { @@ -114,10 +159,16 @@ export class SessionResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Session): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/session/session.controller.ts b/apps/basic-auth-provider/src/session/session.controller.ts index 83ffd9f..8a1ef65 100644 --- a/apps/basic-auth-provider/src/session/session.controller.ts +++ b/apps/basic-auth-provider/src/session/session.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { SessionService } from "./session.service"; import { SessionControllerBase } from "./base/session.controller.base"; @swagger.ApiTags("sessions") @common.Controller("sessions") export class SessionController extends SessionControllerBase { - constructor(protected readonly service: SessionService) { - super(service); + constructor( + protected readonly service: SessionService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/session/session.module.ts b/apps/basic-auth-provider/src/session/session.module.ts index 27828de..e9c434b 100644 --- a/apps/basic-auth-provider/src/session/session.module.ts +++ b/apps/basic-auth-provider/src/session/session.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { SessionModuleBase } from "./base/session.module.base"; import { SessionService } from "./session.service"; import { SessionController } from "./session.controller"; import { SessionResolver } from "./session.resolver"; @Module({ - imports: [SessionModuleBase], + imports: [SessionModuleBase, forwardRef(() => AuthModule)], controllers: [SessionController], providers: [SessionService, SessionResolver], exports: [SessionService], diff --git a/apps/basic-auth-provider/src/session/session.resolver.ts b/apps/basic-auth-provider/src/session/session.resolver.ts index 8d37df5..a19a2d7 100644 --- a/apps/basic-auth-provider/src/session/session.resolver.ts +++ b/apps/basic-auth-provider/src/session/session.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { SessionResolverBase } from "./base/session.resolver.base"; import { Session } from "./base/Session"; import { SessionService } from "./session.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Session) export class SessionResolver extends SessionResolverBase { - constructor(protected readonly service: SessionService) { - super(service); + constructor( + protected readonly service: SessionService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/team/base/team.controller.base.ts b/apps/basic-auth-provider/src/team/base/team.controller.base.ts index dba4e2d..88416bd 100644 --- a/apps/basic-auth-provider/src/team/base/team.controller.base.ts +++ b/apps/basic-auth-provider/src/team/base/team.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { TeamService } from "../team.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { TeamCreateInput } from "./TeamCreateInput"; import { Team } from "./Team"; import { TeamFindManyArgs } from "./TeamFindManyArgs"; @@ -29,10 +33,24 @@ import { MembershipFindManyArgs } from "../../membership/base/MembershipFindMany import { Membership } from "../../membership/base/Membership"; import { MembershipWhereUniqueInput } from "../../membership/base/MembershipWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class TeamControllerBase { - constructor(protected readonly service: TeamService) {} + constructor( + protected readonly service: TeamService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Team }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createTeam(@common.Body() data: TeamCreateInput): Promise { return await this.service.createTeam({ data: data, @@ -47,9 +65,18 @@ export class TeamControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Team] }) @ApiNestedQuery(TeamFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async teams(@common.Req() request: Request): Promise { const args = plainToClass(TeamFindManyArgs, request.query); return this.service.teams({ @@ -65,9 +92,18 @@ export class TeamControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Team }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async team( @common.Param() params: TeamWhereUniqueInput ): Promise { @@ -90,9 +126,18 @@ export class TeamControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Team }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateTeam( @common.Param() params: TeamWhereUniqueInput, @common.Body() data: TeamUpdateInput @@ -123,6 +168,14 @@ export class TeamControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Team }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteTeam( @common.Param() params: TeamWhereUniqueInput ): Promise { @@ -148,8 +201,14 @@ export class TeamControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/eventTypes") @ApiNestedQuery(EventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async findEventTypes( @common.Req() request: Request, @common.Param() params: TeamWhereUniqueInput @@ -227,6 +286,11 @@ export class TeamControllerBase { } @common.Post("/:id/eventTypes") + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async connectEventTypes( @common.Param() params: TeamWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -244,6 +308,11 @@ export class TeamControllerBase { } @common.Patch("/:id/eventTypes") + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async updateEventTypes( @common.Param() params: TeamWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -261,6 +330,11 @@ export class TeamControllerBase { } @common.Delete("/:id/eventTypes") + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async disconnectEventTypes( @common.Param() params: TeamWhereUniqueInput, @common.Body() body: EventTypeWhereUniqueInput[] @@ -277,8 +351,14 @@ export class TeamControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/members") @ApiNestedQuery(MembershipFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) async findMembers( @common.Req() request: Request, @common.Param() params: TeamWhereUniqueInput @@ -313,6 +393,11 @@ export class TeamControllerBase { } @common.Post("/:id/members") + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async connectMembers( @common.Param() params: TeamWhereUniqueInput, @common.Body() body: MembershipWhereUniqueInput[] @@ -330,6 +415,11 @@ export class TeamControllerBase { } @common.Patch("/:id/members") + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async updateMembers( @common.Param() params: TeamWhereUniqueInput, @common.Body() body: MembershipWhereUniqueInput[] @@ -347,6 +437,11 @@ export class TeamControllerBase { } @common.Delete("/:id/members") + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async disconnectMembers( @common.Param() params: TeamWhereUniqueInput, @common.Body() body: MembershipWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/team/base/team.module.base.ts b/apps/basic-auth-provider/src/team/base/team.module.base.ts index a35c690..cd54a2b 100644 --- a/apps/basic-auth-provider/src/team/base/team.module.base.ts +++ b/apps/basic-auth-provider/src/team/base/team.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class TeamModuleBase {} diff --git a/apps/basic-auth-provider/src/team/base/team.resolver.base.ts b/apps/basic-auth-provider/src/team/base/team.resolver.base.ts index 2a682d4..a3a5714 100644 --- a/apps/basic-auth-provider/src/team/base/team.resolver.base.ts +++ b/apps/basic-auth-provider/src/team/base/team.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Team } from "./Team"; import { TeamCountArgs } from "./TeamCountArgs"; import { TeamFindManyArgs } from "./TeamFindManyArgs"; @@ -25,10 +31,20 @@ import { EventType } from "../../eventType/base/EventType"; import { MembershipFindManyArgs } from "../../membership/base/MembershipFindManyArgs"; import { Membership } from "../../membership/base/Membership"; import { TeamService } from "../team.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Team) export class TeamResolverBase { - constructor(protected readonly service: TeamService) {} + constructor( + protected readonly service: TeamService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "any", + }) async _teamsMeta( @graphql.Args() args: TeamCountArgs ): Promise { @@ -38,12 +54,24 @@ export class TeamResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Team]) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "any", + }) async teams(@graphql.Args() args: TeamFindManyArgs): Promise { return this.service.teams(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Team, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "read", + possession: "own", + }) async team(@graphql.Args() args: TeamFindUniqueArgs): Promise { const result = await this.service.team(args); if (result === null) { @@ -52,7 +80,13 @@ export class TeamResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Team) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "create", + possession: "any", + }) async createTeam(@graphql.Args() args: CreateTeamArgs): Promise { return await this.service.createTeam({ ...args, @@ -60,7 +94,13 @@ export class TeamResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Team) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "update", + possession: "any", + }) async updateTeam(@graphql.Args() args: UpdateTeamArgs): Promise { try { return await this.service.updateTeam({ @@ -78,6 +118,11 @@ export class TeamResolverBase { } @graphql.Mutation(() => Team) + @nestAccessControl.UseRoles({ + resource: "Team", + action: "delete", + possession: "any", + }) async deleteTeam(@graphql.Args() args: DeleteTeamArgs): Promise { try { return await this.service.deleteTeam(args); @@ -91,7 +136,13 @@ export class TeamResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [EventType], { name: "eventTypes" }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async findEventTypes( @graphql.Parent() parent: Team, @graphql.Args() args: EventTypeFindManyArgs @@ -105,7 +156,13 @@ export class TeamResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [Membership], { name: "members" }) + @nestAccessControl.UseRoles({ + resource: "Membership", + action: "read", + possession: "any", + }) async findMembers( @graphql.Parent() parent: Team, @graphql.Args() args: MembershipFindManyArgs diff --git a/apps/basic-auth-provider/src/team/team.controller.ts b/apps/basic-auth-provider/src/team/team.controller.ts index 2c4f84f..dc037fa 100644 --- a/apps/basic-auth-provider/src/team/team.controller.ts +++ b/apps/basic-auth-provider/src/team/team.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { TeamService } from "./team.service"; import { TeamControllerBase } from "./base/team.controller.base"; @swagger.ApiTags("teams") @common.Controller("teams") export class TeamController extends TeamControllerBase { - constructor(protected readonly service: TeamService) { - super(service); + constructor( + protected readonly service: TeamService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/team/team.module.ts b/apps/basic-auth-provider/src/team/team.module.ts index bff75c3..99e6e9d 100644 --- a/apps/basic-auth-provider/src/team/team.module.ts +++ b/apps/basic-auth-provider/src/team/team.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { TeamModuleBase } from "./base/team.module.base"; import { TeamService } from "./team.service"; import { TeamController } from "./team.controller"; import { TeamResolver } from "./team.resolver"; @Module({ - imports: [TeamModuleBase], + imports: [TeamModuleBase, forwardRef(() => AuthModule)], controllers: [TeamController], providers: [TeamService, TeamResolver], exports: [TeamService], diff --git a/apps/basic-auth-provider/src/team/team.resolver.ts b/apps/basic-auth-provider/src/team/team.resolver.ts index aa3445d..d37f8c5 100644 --- a/apps/basic-auth-provider/src/team/team.resolver.ts +++ b/apps/basic-auth-provider/src/team/team.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { TeamResolverBase } from "./base/team.resolver.base"; import { Team } from "./base/Team"; import { TeamService } from "./team.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Team) export class TeamResolver extends TeamResolverBase { - constructor(protected readonly service: TeamService) { - super(service); + constructor( + protected readonly service: TeamService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/tests/auth/basic/basic.strategy.spec.ts b/apps/basic-auth-provider/src/tests/auth/basic/basic.strategy.spec.ts new file mode 100644 index 0000000..29ae042 --- /dev/null +++ b/apps/basic-auth-provider/src/tests/auth/basic/basic.strategy.spec.ts @@ -0,0 +1,37 @@ +import { UnauthorizedException } from "@nestjs/common"; +import { mock } from "jest-mock-extended"; +import { AuthService } from "../../../auth/auth.service"; +import { BasicStrategyBase } from "../../../auth/basic/base/basic.strategy.base"; +import { TEST_USER } from "../constants"; + +describe("Testing the basicStrategyBase.validate()", () => { + const TEST_PASSWORD = "gabay"; + const authService = mock(); + const basicStrategy = new BasicStrategyBase(authService); + beforeEach(() => { + authService.validateUser.mockClear(); + }); + beforeAll(() => { + //ARRANGE + authService.validateUser + .calledWith(TEST_USER.username, TEST_PASSWORD) + .mockReturnValue(Promise.resolve(TEST_USER)); + }); + it("should return the user", async () => { + //ACT + const result = await basicStrategy.validate( + TEST_USER.username, + TEST_PASSWORD + ); + //ASSERT + expect(result).toBe(TEST_USER); + }); + it("should throw error if there is not valid user", async () => { + //ARRANGE + authService.validateUser.mockReturnValue(Promise.resolve(null)); + //ACT + const result = basicStrategy.validate("noUsername", TEST_PASSWORD); + //ASSERT + return expect(result).rejects.toThrowError(UnauthorizedException); + }); +}); diff --git a/apps/basic-auth-provider/src/tests/auth/constants.ts b/apps/basic-auth-provider/src/tests/auth/constants.ts new file mode 100644 index 0000000..98e4887 --- /dev/null +++ b/apps/basic-auth-provider/src/tests/auth/constants.ts @@ -0,0 +1,19 @@ +import { Credentials } from "../../auth/Credentials"; +import { UserInfo } from "../../auth/UserInfo"; + +export const VALID_ID = "1"; + +export const TEST_USER: UserInfo = { + id: "cl7qmjh4h0000tothyjqapgj5", + roles: ["User"], + username: "ofek", +}; +export const SIGN_TOKEN = "SIGN_TOKEN"; +export const VALID_CREDENTIALS: Credentials = { + username: "Valid User", + password: "Valid User Password", +}; +export const INVALID_CREDENTIALS: Credentials = { + username: "Invalid User", + password: "Invalid User Password", +}; diff --git a/apps/basic-auth-provider/src/tests/auth/token.service.spec.ts b/apps/basic-auth-provider/src/tests/auth/token.service.spec.ts new file mode 100644 index 0000000..5768a23 --- /dev/null +++ b/apps/basic-auth-provider/src/tests/auth/token.service.spec.ts @@ -0,0 +1,42 @@ +import { TokenServiceBase } from "../../auth/base/token.service.base"; +import { + INVALID_USERNAME_ERROR, + INVALID_PASSWORD_ERROR, +} from "../../auth/constants"; +import { SIGN_TOKEN, VALID_CREDENTIALS, VALID_ID } from "./constants"; + +describe("Testing the TokenServiceBase", () => { + let tokenServiceBase: TokenServiceBase; + beforeEach(() => { + tokenServiceBase = new TokenServiceBase(); + }); + describe("Testing the BasicTokenService.createToken()", () => { + it("should create valid token for given username and password", async () => { + expect( + await tokenServiceBase.createToken({ + id: VALID_ID, + username: "admin", + password: "admin", + }) + ).toBe("YWRtaW46YWRtaW4="); + }); + it("should reject when username missing", () => { + const result = tokenServiceBase.createToken({ + id: VALID_ID, + //@ts-ignore + username: null, + password: VALID_CREDENTIALS.password, + }); + return expect(result).rejects.toBe(INVALID_USERNAME_ERROR); + }); + it("should reject when password missing", () => { + const result = tokenServiceBase.createToken({ + id: VALID_ID, + username: VALID_CREDENTIALS.username, + //@ts-ignore + password: null, + }); + return expect(result).rejects.toBe(INVALID_PASSWORD_ERROR); + }); + }); +}); diff --git a/apps/basic-auth-provider/src/user/base/user.controller.base.ts b/apps/basic-auth-provider/src/user/base/user.controller.base.ts index d4f1fda..9dbb8c4 100644 --- a/apps/basic-auth-provider/src/user/base/user.controller.base.ts +++ b/apps/basic-auth-provider/src/user/base/user.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { UserService } from "../user.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { UserCreateInput } from "./UserCreateInput"; import { User } from "./User"; import { UserFindManyArgs } from "./UserFindManyArgs"; import { UserWhereUniqueInput } from "./UserWhereUniqueInput"; import { UserUpdateInput } from "./UserUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class UserControllerBase { - constructor(protected readonly service: UserService) {} + constructor( + protected readonly service: UserService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: User }) + @nestAccessControl.UseRoles({ + resource: "User", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createUser(@common.Body() data: UserCreateInput): Promise { return await this.service.createUser({ data: data, @@ -43,9 +61,18 @@ export class UserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [User] }) @ApiNestedQuery(UserFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "User", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async users(@common.Req() request: Request): Promise { const args = plainToClass(UserFindManyArgs, request.query); return this.service.users({ @@ -63,9 +90,18 @@ export class UserControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: User }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "User", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async user( @common.Param() params: UserWhereUniqueInput ): Promise { @@ -90,9 +126,18 @@ export class UserControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: User }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "User", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateUser( @common.Param() params: UserWhereUniqueInput, @common.Body() data: UserUpdateInput @@ -125,6 +170,14 @@ export class UserControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: User }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "User", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteUser( @common.Param() params: UserWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/user/base/user.module.base.ts b/apps/basic-auth-provider/src/user/base/user.module.base.ts index 87dbcf8..a8b6c68 100644 --- a/apps/basic-auth-provider/src/user/base/user.module.base.ts +++ b/apps/basic-auth-provider/src/user/base/user.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class UserModuleBase {} diff --git a/apps/basic-auth-provider/src/user/base/user.resolver.base.ts b/apps/basic-auth-provider/src/user/base/user.resolver.base.ts index 364d7ee..0c60d95 100644 --- a/apps/basic-auth-provider/src/user/base/user.resolver.base.ts +++ b/apps/basic-auth-provider/src/user/base/user.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { User } from "./User"; import { UserCountArgs } from "./UserCountArgs"; import { UserFindManyArgs } from "./UserFindManyArgs"; @@ -21,10 +27,20 @@ import { CreateUserArgs } from "./CreateUserArgs"; import { UpdateUserArgs } from "./UpdateUserArgs"; import { DeleteUserArgs } from "./DeleteUserArgs"; import { UserService } from "../user.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => User) export class UserResolverBase { - constructor(protected readonly service: UserService) {} + constructor( + protected readonly service: UserService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "User", + action: "read", + possession: "any", + }) async _usersMeta( @graphql.Args() args: UserCountArgs ): Promise { @@ -34,12 +50,24 @@ export class UserResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [User]) + @nestAccessControl.UseRoles({ + resource: "User", + action: "read", + possession: "any", + }) async users(@graphql.Args() args: UserFindManyArgs): Promise { return this.service.users(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => User, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "User", + action: "read", + possession: "own", + }) async user(@graphql.Args() args: UserFindUniqueArgs): Promise { const result = await this.service.user(args); if (result === null) { @@ -48,7 +76,13 @@ export class UserResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => User) + @nestAccessControl.UseRoles({ + resource: "User", + action: "create", + possession: "any", + }) async createUser(@graphql.Args() args: CreateUserArgs): Promise { return await this.service.createUser({ ...args, @@ -56,7 +90,13 @@ export class UserResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => User) + @nestAccessControl.UseRoles({ + resource: "User", + action: "update", + possession: "any", + }) async updateUser(@graphql.Args() args: UpdateUserArgs): Promise { try { return await this.service.updateUser({ @@ -74,6 +114,11 @@ export class UserResolverBase { } @graphql.Mutation(() => User) + @nestAccessControl.UseRoles({ + resource: "User", + action: "delete", + possession: "any", + }) async deleteUser(@graphql.Args() args: DeleteUserArgs): Promise { try { return await this.service.deleteUser(args); diff --git a/apps/basic-auth-provider/src/user/base/user.service.base.ts b/apps/basic-auth-provider/src/user/base/user.service.base.ts index 904537c..6a749c5 100644 --- a/apps/basic-auth-provider/src/user/base/user.service.base.ts +++ b/apps/basic-auth-provider/src/user/base/user.service.base.ts @@ -11,9 +11,14 @@ https://docs.amplication.com/how-to/custom-code */ import { PrismaService } from "../../prisma/prisma.service"; import { Prisma, User as PrismaUser } from "@prisma/client"; +import { PasswordService } from "../../auth/password.service"; +import { transformStringFieldUpdateInput } from "../../prisma.util"; export class UserServiceBase { - constructor(protected readonly prisma: PrismaService) {} + constructor( + protected readonly prisma: PrismaService, + protected readonly passwordService: PasswordService + ) {} async count(args: Omit): Promise { return this.prisma.user.count(args); @@ -26,10 +31,30 @@ export class UserServiceBase { return this.prisma.user.findUnique(args); } async createUser(args: Prisma.UserCreateArgs): Promise { - return this.prisma.user.create(args); + return this.prisma.user.create({ + ...args, + + data: { + ...args.data, + password: await this.passwordService.hash(args.data.password), + }, + }); } async updateUser(args: Prisma.UserUpdateArgs): Promise { - return this.prisma.user.update(args); + return this.prisma.user.update({ + ...args, + + data: { + ...args.data, + + password: + args.data.password && + (await transformStringFieldUpdateInput( + args.data.password, + (password) => this.passwordService.hash(password) + )), + }, + }); } async deleteUser(args: Prisma.UserDeleteArgs): Promise { return this.prisma.user.delete(args); diff --git a/apps/basic-auth-provider/src/user/user.controller.ts b/apps/basic-auth-provider/src/user/user.controller.ts index b783f3c..21d9583 100644 --- a/apps/basic-auth-provider/src/user/user.controller.ts +++ b/apps/basic-auth-provider/src/user/user.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { UserService } from "./user.service"; import { UserControllerBase } from "./base/user.controller.base"; @swagger.ApiTags("users") @common.Controller("users") export class UserController extends UserControllerBase { - constructor(protected readonly service: UserService) { - super(service); + constructor( + protected readonly service: UserService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/user/user.module.ts b/apps/basic-auth-provider/src/user/user.module.ts index 6fb3d60..2d6dd05 100644 --- a/apps/basic-auth-provider/src/user/user.module.ts +++ b/apps/basic-auth-provider/src/user/user.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { UserModuleBase } from "./base/user.module.base"; import { UserService } from "./user.service"; import { UserController } from "./user.controller"; import { UserResolver } from "./user.resolver"; @Module({ - imports: [UserModuleBase], + imports: [UserModuleBase, forwardRef(() => AuthModule)], controllers: [UserController], providers: [UserService, UserResolver], exports: [UserService], diff --git a/apps/basic-auth-provider/src/user/user.resolver.ts b/apps/basic-auth-provider/src/user/user.resolver.ts index 9997b13..bc3a79b 100644 --- a/apps/basic-auth-provider/src/user/user.resolver.ts +++ b/apps/basic-auth-provider/src/user/user.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { UserResolverBase } from "./base/user.resolver.base"; import { User } from "./base/User"; import { UserService } from "./user.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => User) export class UserResolver extends UserResolverBase { - constructor(protected readonly service: UserService) { - super(service); + constructor( + protected readonly service: UserService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/user/user.service.ts b/apps/basic-auth-provider/src/user/user.service.ts index cae0388..a8e4508 100644 --- a/apps/basic-auth-provider/src/user/user.service.ts +++ b/apps/basic-auth-provider/src/user/user.service.ts @@ -1,10 +1,14 @@ import { Injectable } from "@nestjs/common"; import { PrismaService } from "../prisma/prisma.service"; +import { PasswordService } from "../auth/password.service"; import { UserServiceBase } from "./base/user.service.base"; @Injectable() export class UserService extends UserServiceBase { - constructor(protected readonly prisma: PrismaService) { - super(prisma); + constructor( + protected readonly prisma: PrismaService, + protected readonly passwordService: PasswordService + ) { + super(prisma, passwordService); } } diff --git a/apps/basic-auth-provider/src/verificationToken/base/verificationToken.controller.base.ts b/apps/basic-auth-provider/src/verificationToken/base/verificationToken.controller.base.ts index 1b0b8f9..86ae0b9 100644 --- a/apps/basic-auth-provider/src/verificationToken/base/verificationToken.controller.base.ts +++ b/apps/basic-auth-provider/src/verificationToken/base/verificationToken.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { VerificationTokenService } from "../verificationToken.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { VerificationTokenCreateInput } from "./VerificationTokenCreateInput"; import { VerificationToken } from "./VerificationToken"; import { VerificationTokenFindManyArgs } from "./VerificationTokenFindManyArgs"; import { VerificationTokenWhereUniqueInput } from "./VerificationTokenWhereUniqueInput"; import { VerificationTokenUpdateInput } from "./VerificationTokenUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class VerificationTokenControllerBase { - constructor(protected readonly service: VerificationTokenService) {} + constructor( + protected readonly service: VerificationTokenService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: VerificationToken }) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createVerificationToken( @common.Body() data: VerificationTokenCreateInput ): Promise { @@ -43,9 +61,18 @@ export class VerificationTokenControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [VerificationToken] }) @ApiNestedQuery(VerificationTokenFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async verificationTokens( @common.Req() request: Request ): Promise { @@ -63,9 +90,18 @@ export class VerificationTokenControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: VerificationToken }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async verificationToken( @common.Param() params: VerificationTokenWhereUniqueInput ): Promise { @@ -88,9 +124,18 @@ export class VerificationTokenControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: VerificationToken }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateVerificationToken( @common.Param() params: VerificationTokenWhereUniqueInput, @common.Body() data: VerificationTokenUpdateInput @@ -121,6 +166,14 @@ export class VerificationTokenControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: VerificationToken }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteVerificationToken( @common.Param() params: VerificationTokenWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/verificationToken/base/verificationToken.module.base.ts b/apps/basic-auth-provider/src/verificationToken/base/verificationToken.module.base.ts index 0abd237..8f76f67 100644 --- a/apps/basic-auth-provider/src/verificationToken/base/verificationToken.module.base.ts +++ b/apps/basic-auth-provider/src/verificationToken/base/verificationToken.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class VerificationTokenModuleBase {} diff --git a/apps/basic-auth-provider/src/verificationToken/base/verificationToken.resolver.base.ts b/apps/basic-auth-provider/src/verificationToken/base/verificationToken.resolver.base.ts index 2811b61..c783708 100644 --- a/apps/basic-auth-provider/src/verificationToken/base/verificationToken.resolver.base.ts +++ b/apps/basic-auth-provider/src/verificationToken/base/verificationToken.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { VerificationToken } from "./VerificationToken"; import { VerificationTokenCountArgs } from "./VerificationTokenCountArgs"; import { VerificationTokenFindManyArgs } from "./VerificationTokenFindManyArgs"; @@ -21,10 +27,20 @@ import { CreateVerificationTokenArgs } from "./CreateVerificationTokenArgs"; import { UpdateVerificationTokenArgs } from "./UpdateVerificationTokenArgs"; import { DeleteVerificationTokenArgs } from "./DeleteVerificationTokenArgs"; import { VerificationTokenService } from "../verificationToken.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => VerificationToken) export class VerificationTokenResolverBase { - constructor(protected readonly service: VerificationTokenService) {} + constructor( + protected readonly service: VerificationTokenService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "read", + possession: "any", + }) async _verificationTokensMeta( @graphql.Args() args: VerificationTokenCountArgs ): Promise { @@ -34,14 +50,26 @@ export class VerificationTokenResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [VerificationToken]) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "read", + possession: "any", + }) async verificationTokens( @graphql.Args() args: VerificationTokenFindManyArgs ): Promise { return this.service.verificationTokens(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => VerificationToken, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "read", + possession: "own", + }) async verificationToken( @graphql.Args() args: VerificationTokenFindUniqueArgs ): Promise { @@ -52,7 +80,13 @@ export class VerificationTokenResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => VerificationToken) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "create", + possession: "any", + }) async createVerificationToken( @graphql.Args() args: CreateVerificationTokenArgs ): Promise { @@ -62,7 +96,13 @@ export class VerificationTokenResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => VerificationToken) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "update", + possession: "any", + }) async updateVerificationToken( @graphql.Args() args: UpdateVerificationTokenArgs ): Promise { @@ -82,6 +122,11 @@ export class VerificationTokenResolverBase { } @graphql.Mutation(() => VerificationToken) + @nestAccessControl.UseRoles({ + resource: "VerificationToken", + action: "delete", + possession: "any", + }) async deleteVerificationToken( @graphql.Args() args: DeleteVerificationTokenArgs ): Promise { diff --git a/apps/basic-auth-provider/src/verificationToken/verificationToken.controller.ts b/apps/basic-auth-provider/src/verificationToken/verificationToken.controller.ts index a6eecd0..c39947c 100644 --- a/apps/basic-auth-provider/src/verificationToken/verificationToken.controller.ts +++ b/apps/basic-auth-provider/src/verificationToken/verificationToken.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { VerificationTokenService } from "./verificationToken.service"; import { VerificationTokenControllerBase } from "./base/verificationToken.controller.base"; @swagger.ApiTags("verificationTokens") @common.Controller("verificationTokens") export class VerificationTokenController extends VerificationTokenControllerBase { - constructor(protected readonly service: VerificationTokenService) { - super(service); + constructor( + protected readonly service: VerificationTokenService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/verificationToken/verificationToken.module.ts b/apps/basic-auth-provider/src/verificationToken/verificationToken.module.ts index 15a0f36..82ffdc7 100644 --- a/apps/basic-auth-provider/src/verificationToken/verificationToken.module.ts +++ b/apps/basic-auth-provider/src/verificationToken/verificationToken.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { VerificationTokenModuleBase } from "./base/verificationToken.module.base"; import { VerificationTokenService } from "./verificationToken.service"; import { VerificationTokenController } from "./verificationToken.controller"; import { VerificationTokenResolver } from "./verificationToken.resolver"; @Module({ - imports: [VerificationTokenModuleBase], + imports: [VerificationTokenModuleBase, forwardRef(() => AuthModule)], controllers: [VerificationTokenController], providers: [VerificationTokenService, VerificationTokenResolver], exports: [VerificationTokenService], diff --git a/apps/basic-auth-provider/src/verificationToken/verificationToken.resolver.ts b/apps/basic-auth-provider/src/verificationToken/verificationToken.resolver.ts index 31d93fb..1ee95ca 100644 --- a/apps/basic-auth-provider/src/verificationToken/verificationToken.resolver.ts +++ b/apps/basic-auth-provider/src/verificationToken/verificationToken.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { VerificationTokenResolverBase } from "./base/verificationToken.resolver.base"; import { VerificationToken } from "./base/VerificationToken"; import { VerificationTokenService } from "./verificationToken.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => VerificationToken) export class VerificationTokenResolver extends VerificationTokenResolverBase { - constructor(protected readonly service: VerificationTokenService) { - super(service); + constructor( + protected readonly service: VerificationTokenService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/webhook/base/webhook.controller.base.ts b/apps/basic-auth-provider/src/webhook/base/webhook.controller.base.ts index 3efc703..ca02efe 100644 --- a/apps/basic-auth-provider/src/webhook/base/webhook.controller.base.ts +++ b/apps/basic-auth-provider/src/webhook/base/webhook.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { WebhookService } from "../webhook.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { WebhookCreateInput } from "./WebhookCreateInput"; import { Webhook } from "./Webhook"; import { WebhookFindManyArgs } from "./WebhookFindManyArgs"; import { WebhookWhereUniqueInput } from "./WebhookWhereUniqueInput"; import { WebhookUpdateInput } from "./WebhookUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class WebhookControllerBase { - constructor(protected readonly service: WebhookService) {} + constructor( + protected readonly service: WebhookService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Webhook }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createWebhook( @common.Body() data: WebhookCreateInput ): Promise { @@ -84,9 +102,18 @@ export class WebhookControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Webhook] }) @ApiNestedQuery(WebhookFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async webhooks(@common.Req() request: Request): Promise { const args = plainToClass(WebhookFindManyArgs, request.query); return this.service.webhooks({ @@ -123,9 +150,18 @@ export class WebhookControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Webhook }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async webhook( @common.Param() params: WebhookWhereUniqueInput ): Promise { @@ -169,9 +205,18 @@ export class WebhookControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Webhook }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateWebhook( @common.Param() params: WebhookWhereUniqueInput, @common.Body() data: WebhookUpdateInput @@ -243,6 +288,14 @@ export class WebhookControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Webhook }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteWebhook( @common.Param() params: WebhookWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/webhook/base/webhook.module.base.ts b/apps/basic-auth-provider/src/webhook/base/webhook.module.base.ts index d987dfb..1b1b7c6 100644 --- a/apps/basic-auth-provider/src/webhook/base/webhook.module.base.ts +++ b/apps/basic-auth-provider/src/webhook/base/webhook.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class WebhookModuleBase {} diff --git a/apps/basic-auth-provider/src/webhook/base/webhook.resolver.base.ts b/apps/basic-auth-provider/src/webhook/base/webhook.resolver.base.ts index 8c1db99..107cb42 100644 --- a/apps/basic-auth-provider/src/webhook/base/webhook.resolver.base.ts +++ b/apps/basic-auth-provider/src/webhook/base/webhook.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Webhook } from "./Webhook"; import { WebhookCountArgs } from "./WebhookCountArgs"; import { WebhookFindManyArgs } from "./WebhookFindManyArgs"; @@ -24,10 +30,20 @@ import { AppModel } from "../../appModel/base/AppModel"; import { EventType } from "../../eventType/base/EventType"; import { OrigUser } from "../../origUser/base/OrigUser"; import { WebhookService } from "../webhook.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Webhook) export class WebhookResolverBase { - constructor(protected readonly service: WebhookService) {} - + constructor( + protected readonly service: WebhookService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async _webhooksMeta( @graphql.Args() args: WebhookCountArgs ): Promise { @@ -37,14 +53,26 @@ export class WebhookResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Webhook]) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "any", + }) async webhooks( @graphql.Args() args: WebhookFindManyArgs ): Promise { return this.service.webhooks(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Webhook, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "read", + possession: "own", + }) async webhook( @graphql.Args() args: WebhookFindUniqueArgs ): Promise { @@ -55,7 +83,13 @@ export class WebhookResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Webhook) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "create", + possession: "any", + }) async createWebhook( @graphql.Args() args: CreateWebhookArgs ): Promise { @@ -85,7 +119,13 @@ export class WebhookResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Webhook) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "update", + possession: "any", + }) async updateWebhook( @graphql.Args() args: UpdateWebhookArgs ): Promise { @@ -125,6 +165,11 @@ export class WebhookResolverBase { } @graphql.Mutation(() => Webhook) + @nestAccessControl.UseRoles({ + resource: "Webhook", + action: "delete", + possession: "any", + }) async deleteWebhook( @graphql.Args() args: DeleteWebhookArgs ): Promise { @@ -140,10 +185,16 @@ export class WebhookResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => AppModel, { nullable: true, name: "appField", }) + @nestAccessControl.UseRoles({ + resource: "AppModel", + action: "read", + possession: "any", + }) async getAppField( @graphql.Parent() parent: Webhook ): Promise { @@ -155,10 +206,16 @@ export class WebhookResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: Webhook ): Promise { @@ -170,10 +227,16 @@ export class WebhookResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Webhook): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/webhook/webhook.controller.ts b/apps/basic-auth-provider/src/webhook/webhook.controller.ts index 3ba0214..b621f6e 100644 --- a/apps/basic-auth-provider/src/webhook/webhook.controller.ts +++ b/apps/basic-auth-provider/src/webhook/webhook.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { WebhookService } from "./webhook.service"; import { WebhookControllerBase } from "./base/webhook.controller.base"; @swagger.ApiTags("webhooks") @common.Controller("webhooks") export class WebhookController extends WebhookControllerBase { - constructor(protected readonly service: WebhookService) { - super(service); + constructor( + protected readonly service: WebhookService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/webhook/webhook.module.ts b/apps/basic-auth-provider/src/webhook/webhook.module.ts index 659384e..a7cd15f 100644 --- a/apps/basic-auth-provider/src/webhook/webhook.module.ts +++ b/apps/basic-auth-provider/src/webhook/webhook.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { WebhookModuleBase } from "./base/webhook.module.base"; import { WebhookService } from "./webhook.service"; import { WebhookController } from "./webhook.controller"; import { WebhookResolver } from "./webhook.resolver"; @Module({ - imports: [WebhookModuleBase], + imports: [WebhookModuleBase, forwardRef(() => AuthModule)], controllers: [WebhookController], providers: [WebhookService, WebhookResolver], exports: [WebhookService], diff --git a/apps/basic-auth-provider/src/webhook/webhook.resolver.ts b/apps/basic-auth-provider/src/webhook/webhook.resolver.ts index b32c62b..e8c8603 100644 --- a/apps/basic-auth-provider/src/webhook/webhook.resolver.ts +++ b/apps/basic-auth-provider/src/webhook/webhook.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { WebhookResolverBase } from "./base/webhook.resolver.base"; import { Webhook } from "./base/Webhook"; import { WebhookService } from "./webhook.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Webhook) export class WebhookResolver extends WebhookResolverBase { - constructor(protected readonly service: WebhookService) { - super(service); + constructor( + protected readonly service: WebhookService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflow/base/workflow.controller.base.ts b/apps/basic-auth-provider/src/workflow/base/workflow.controller.base.ts index e2ad5a5..e110c63 100644 --- a/apps/basic-auth-provider/src/workflow/base/workflow.controller.base.ts +++ b/apps/basic-auth-provider/src/workflow/base/workflow.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { WorkflowService } from "../workflow.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { WorkflowCreateInput } from "./WorkflowCreateInput"; import { Workflow } from "./Workflow"; import { WorkflowFindManyArgs } from "./WorkflowFindManyArgs"; @@ -29,10 +33,24 @@ import { WorkflowStepFindManyArgs } from "../../workflowStep/base/WorkflowStepFi import { WorkflowStep } from "../../workflowStep/base/WorkflowStep"; import { WorkflowStepWhereUniqueInput } from "../../workflowStep/base/WorkflowStepWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class WorkflowControllerBase { - constructor(protected readonly service: WorkflowService) {} + constructor( + protected readonly service: WorkflowService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: Workflow }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createWorkflow( @common.Body() data: WorkflowCreateInput ): Promise { @@ -60,9 +78,18 @@ export class WorkflowControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [Workflow] }) @ApiNestedQuery(WorkflowFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflows(@common.Req() request: Request): Promise { const args = plainToClass(WorkflowFindManyArgs, request.query); return this.service.workflows({ @@ -83,9 +110,18 @@ export class WorkflowControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: Workflow }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflow( @common.Param() params: WorkflowWhereUniqueInput ): Promise { @@ -113,9 +149,18 @@ export class WorkflowControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: Workflow }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateWorkflow( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() data: WorkflowUpdateInput @@ -157,6 +202,14 @@ export class WorkflowControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: Workflow }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteWorkflow( @common.Param() params: WorkflowWhereUniqueInput ): Promise { @@ -187,8 +240,14 @@ export class WorkflowControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/activeOn") @ApiNestedQuery(WorkflowsOnEventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) async findActiveOn( @common.Req() request: Request, @common.Param() params: WorkflowWhereUniqueInput @@ -221,6 +280,11 @@ export class WorkflowControllerBase { } @common.Post("/:id/activeOn") + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async connectActiveOn( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() body: WorkflowsOnEventTypeWhereUniqueInput[] @@ -238,6 +302,11 @@ export class WorkflowControllerBase { } @common.Patch("/:id/activeOn") + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async updateActiveOn( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() body: WorkflowsOnEventTypeWhereUniqueInput[] @@ -255,6 +324,11 @@ export class WorkflowControllerBase { } @common.Delete("/:id/activeOn") + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async disconnectActiveOn( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() body: WorkflowsOnEventTypeWhereUniqueInput[] @@ -271,8 +345,14 @@ export class WorkflowControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/steps") @ApiNestedQuery(WorkflowStepFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "any", + }) async findSteps( @common.Req() request: Request, @common.Param() params: WorkflowWhereUniqueInput @@ -305,6 +385,11 @@ export class WorkflowControllerBase { } @common.Post("/:id/steps") + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async connectSteps( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() body: WorkflowStepWhereUniqueInput[] @@ -322,6 +407,11 @@ export class WorkflowControllerBase { } @common.Patch("/:id/steps") + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async updateSteps( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() body: WorkflowStepWhereUniqueInput[] @@ -339,6 +429,11 @@ export class WorkflowControllerBase { } @common.Delete("/:id/steps") + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async disconnectSteps( @common.Param() params: WorkflowWhereUniqueInput, @common.Body() body: WorkflowStepWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/workflow/base/workflow.module.base.ts b/apps/basic-auth-provider/src/workflow/base/workflow.module.base.ts index 34e4af3..99273de 100644 --- a/apps/basic-auth-provider/src/workflow/base/workflow.module.base.ts +++ b/apps/basic-auth-provider/src/workflow/base/workflow.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class WorkflowModuleBase {} diff --git a/apps/basic-auth-provider/src/workflow/base/workflow.resolver.base.ts b/apps/basic-auth-provider/src/workflow/base/workflow.resolver.base.ts index ca9647e..d814855 100644 --- a/apps/basic-auth-provider/src/workflow/base/workflow.resolver.base.ts +++ b/apps/basic-auth-provider/src/workflow/base/workflow.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { Workflow } from "./Workflow"; import { WorkflowCountArgs } from "./WorkflowCountArgs"; import { WorkflowFindManyArgs } from "./WorkflowFindManyArgs"; @@ -26,10 +32,20 @@ import { WorkflowStepFindManyArgs } from "../../workflowStep/base/WorkflowStepFi import { WorkflowStep } from "../../workflowStep/base/WorkflowStep"; import { OrigUser } from "../../origUser/base/OrigUser"; import { WorkflowService } from "../workflow.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Workflow) export class WorkflowResolverBase { - constructor(protected readonly service: WorkflowService) {} - + constructor( + protected readonly service: WorkflowService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) async _workflowsMeta( @graphql.Args() args: WorkflowCountArgs ): Promise { @@ -39,14 +55,26 @@ export class WorkflowResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [Workflow]) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) async workflows( @graphql.Args() args: WorkflowFindManyArgs ): Promise { return this.service.workflows(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => Workflow, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "own", + }) async workflow( @graphql.Args() args: WorkflowFindUniqueArgs ): Promise { @@ -57,7 +85,13 @@ export class WorkflowResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Workflow) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "create", + possession: "any", + }) async createWorkflow( @graphql.Args() args: CreateWorkflowArgs ): Promise { @@ -73,7 +107,13 @@ export class WorkflowResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => Workflow) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "update", + possession: "any", + }) async updateWorkflow( @graphql.Args() args: UpdateWorkflowArgs ): Promise { @@ -99,6 +139,11 @@ export class WorkflowResolverBase { } @graphql.Mutation(() => Workflow) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "delete", + possession: "any", + }) async deleteWorkflow( @graphql.Args() args: DeleteWorkflowArgs ): Promise { @@ -114,7 +159,13 @@ export class WorkflowResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [WorkflowsOnEventType], { name: "activeOn" }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) async findActiveOn( @graphql.Parent() parent: Workflow, @graphql.Args() args: WorkflowsOnEventTypeFindManyArgs @@ -128,7 +179,13 @@ export class WorkflowResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [WorkflowStep], { name: "steps" }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "any", + }) async findSteps( @graphql.Parent() parent: Workflow, @graphql.Args() args: WorkflowStepFindManyArgs @@ -142,10 +199,16 @@ export class WorkflowResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => OrigUser, { nullable: true, name: "user", }) + @nestAccessControl.UseRoles({ + resource: "OrigUser", + action: "read", + possession: "any", + }) async getUser(@graphql.Parent() parent: Workflow): Promise { const result = await this.service.getUser(parent.id); diff --git a/apps/basic-auth-provider/src/workflow/workflow.controller.ts b/apps/basic-auth-provider/src/workflow/workflow.controller.ts index 52b5699..7705386 100644 --- a/apps/basic-auth-provider/src/workflow/workflow.controller.ts +++ b/apps/basic-auth-provider/src/workflow/workflow.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { WorkflowService } from "./workflow.service"; import { WorkflowControllerBase } from "./base/workflow.controller.base"; @swagger.ApiTags("workflows") @common.Controller("workflows") export class WorkflowController extends WorkflowControllerBase { - constructor(protected readonly service: WorkflowService) { - super(service); + constructor( + protected readonly service: WorkflowService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflow/workflow.module.ts b/apps/basic-auth-provider/src/workflow/workflow.module.ts index bcee4da..331772d 100644 --- a/apps/basic-auth-provider/src/workflow/workflow.module.ts +++ b/apps/basic-auth-provider/src/workflow/workflow.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { WorkflowModuleBase } from "./base/workflow.module.base"; import { WorkflowService } from "./workflow.service"; import { WorkflowController } from "./workflow.controller"; import { WorkflowResolver } from "./workflow.resolver"; @Module({ - imports: [WorkflowModuleBase], + imports: [WorkflowModuleBase, forwardRef(() => AuthModule)], controllers: [WorkflowController], providers: [WorkflowService, WorkflowResolver], exports: [WorkflowService], diff --git a/apps/basic-auth-provider/src/workflow/workflow.resolver.ts b/apps/basic-auth-provider/src/workflow/workflow.resolver.ts index d9593c9..76a3f10 100644 --- a/apps/basic-auth-provider/src/workflow/workflow.resolver.ts +++ b/apps/basic-auth-provider/src/workflow/workflow.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { WorkflowResolverBase } from "./base/workflow.resolver.base"; import { Workflow } from "./base/Workflow"; import { WorkflowService } from "./workflow.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => Workflow) export class WorkflowResolver extends WorkflowResolverBase { - constructor(protected readonly service: WorkflowService) { - super(service); + constructor( + protected readonly service: WorkflowService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.controller.base.ts b/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.controller.base.ts index 90682b7..16a67fc 100644 --- a/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.controller.base.ts +++ b/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { WorkflowReminderService } from "../workflowReminder.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { WorkflowReminderCreateInput } from "./WorkflowReminderCreateInput"; import { WorkflowReminder } from "./WorkflowReminder"; import { WorkflowReminderFindManyArgs } from "./WorkflowReminderFindManyArgs"; import { WorkflowReminderWhereUniqueInput } from "./WorkflowReminderWhereUniqueInput"; import { WorkflowReminderUpdateInput } from "./WorkflowReminderUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class WorkflowReminderControllerBase { - constructor(protected readonly service: WorkflowReminderService) {} + constructor( + protected readonly service: WorkflowReminderService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: WorkflowReminder }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createWorkflowReminder( @common.Body() data: WorkflowReminderCreateInput ): Promise { @@ -66,9 +84,18 @@ export class WorkflowReminderControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [WorkflowReminder] }) @ApiNestedQuery(WorkflowReminderFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflowReminders( @common.Req() request: Request ): Promise { @@ -97,9 +124,18 @@ export class WorkflowReminderControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: WorkflowReminder }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflowReminder( @common.Param() params: WorkflowReminderWhereUniqueInput ): Promise { @@ -133,9 +169,18 @@ export class WorkflowReminderControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: WorkflowReminder }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateWorkflowReminder( @common.Param() params: WorkflowReminderWhereUniqueInput, @common.Body() data: WorkflowReminderUpdateInput @@ -189,6 +234,14 @@ export class WorkflowReminderControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: WorkflowReminder }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteWorkflowReminder( @common.Param() params: WorkflowReminderWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.module.base.ts b/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.module.base.ts index a5bf7f6..4757a6c 100644 --- a/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.module.base.ts +++ b/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class WorkflowReminderModuleBase {} diff --git a/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.resolver.base.ts b/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.resolver.base.ts index 2aef60f..166b171 100644 --- a/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.resolver.base.ts +++ b/apps/basic-auth-provider/src/workflowReminder/base/workflowReminder.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { WorkflowReminder } from "./WorkflowReminder"; import { WorkflowReminderCountArgs } from "./WorkflowReminderCountArgs"; import { WorkflowReminderFindManyArgs } from "./WorkflowReminderFindManyArgs"; @@ -23,10 +29,20 @@ import { DeleteWorkflowReminderArgs } from "./DeleteWorkflowReminderArgs"; import { Booking } from "../../booking/base/Booking"; import { WorkflowStep } from "../../workflowStep/base/WorkflowStep"; import { WorkflowReminderService } from "../workflowReminder.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => WorkflowReminder) export class WorkflowReminderResolverBase { - constructor(protected readonly service: WorkflowReminderService) {} - + constructor( + protected readonly service: WorkflowReminderService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) async _workflowRemindersMeta( @graphql.Args() args: WorkflowReminderCountArgs ): Promise { @@ -36,14 +52,26 @@ export class WorkflowReminderResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [WorkflowReminder]) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) async workflowReminders( @graphql.Args() args: WorkflowReminderFindManyArgs ): Promise { return this.service.workflowReminders(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => WorkflowReminder, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "own", + }) async workflowReminder( @graphql.Args() args: WorkflowReminderFindUniqueArgs ): Promise { @@ -54,7 +82,13 @@ export class WorkflowReminderResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => WorkflowReminder) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "create", + possession: "any", + }) async createWorkflowReminder( @graphql.Args() args: CreateWorkflowReminderArgs ): Promise { @@ -76,7 +110,13 @@ export class WorkflowReminderResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => WorkflowReminder) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "update", + possession: "any", + }) async updateWorkflowReminder( @graphql.Args() args: UpdateWorkflowReminderArgs ): Promise { @@ -108,6 +148,11 @@ export class WorkflowReminderResolverBase { } @graphql.Mutation(() => WorkflowReminder) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "delete", + possession: "any", + }) async deleteWorkflowReminder( @graphql.Args() args: DeleteWorkflowReminderArgs ): Promise { @@ -123,10 +168,16 @@ export class WorkflowReminderResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Booking, { nullable: true, name: "booking", }) + @nestAccessControl.UseRoles({ + resource: "Booking", + action: "read", + possession: "any", + }) async getBooking( @graphql.Parent() parent: WorkflowReminder ): Promise { @@ -138,10 +189,16 @@ export class WorkflowReminderResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => WorkflowStep, { nullable: true, name: "workflowStep", }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "any", + }) async getWorkflowStep( @graphql.Parent() parent: WorkflowReminder ): Promise { diff --git a/apps/basic-auth-provider/src/workflowReminder/workflowReminder.controller.ts b/apps/basic-auth-provider/src/workflowReminder/workflowReminder.controller.ts index 6bb3138..881503a 100644 --- a/apps/basic-auth-provider/src/workflowReminder/workflowReminder.controller.ts +++ b/apps/basic-auth-provider/src/workflowReminder/workflowReminder.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { WorkflowReminderService } from "./workflowReminder.service"; import { WorkflowReminderControllerBase } from "./base/workflowReminder.controller.base"; @swagger.ApiTags("workflowReminders") @common.Controller("workflowReminders") export class WorkflowReminderController extends WorkflowReminderControllerBase { - constructor(protected readonly service: WorkflowReminderService) { - super(service); + constructor( + protected readonly service: WorkflowReminderService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflowReminder/workflowReminder.module.ts b/apps/basic-auth-provider/src/workflowReminder/workflowReminder.module.ts index abae12e..a584da1 100644 --- a/apps/basic-auth-provider/src/workflowReminder/workflowReminder.module.ts +++ b/apps/basic-auth-provider/src/workflowReminder/workflowReminder.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { WorkflowReminderModuleBase } from "./base/workflowReminder.module.base"; import { WorkflowReminderService } from "./workflowReminder.service"; import { WorkflowReminderController } from "./workflowReminder.controller"; import { WorkflowReminderResolver } from "./workflowReminder.resolver"; @Module({ - imports: [WorkflowReminderModuleBase], + imports: [WorkflowReminderModuleBase, forwardRef(() => AuthModule)], controllers: [WorkflowReminderController], providers: [WorkflowReminderService, WorkflowReminderResolver], exports: [WorkflowReminderService], diff --git a/apps/basic-auth-provider/src/workflowReminder/workflowReminder.resolver.ts b/apps/basic-auth-provider/src/workflowReminder/workflowReminder.resolver.ts index aba5763..60c3d56 100644 --- a/apps/basic-auth-provider/src/workflowReminder/workflowReminder.resolver.ts +++ b/apps/basic-auth-provider/src/workflowReminder/workflowReminder.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { WorkflowReminderResolverBase } from "./base/workflowReminder.resolver.base"; import { WorkflowReminder } from "./base/WorkflowReminder"; import { WorkflowReminderService } from "./workflowReminder.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => WorkflowReminder) export class WorkflowReminderResolver extends WorkflowReminderResolverBase { - constructor(protected readonly service: WorkflowReminderService) { - super(service); + constructor( + protected readonly service: WorkflowReminderService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflowStep/base/workflowStep.controller.base.ts b/apps/basic-auth-provider/src/workflowStep/base/workflowStep.controller.base.ts index 564cf45..16f9ea6 100644 --- a/apps/basic-auth-provider/src/workflowStep/base/workflowStep.controller.base.ts +++ b/apps/basic-auth-provider/src/workflowStep/base/workflowStep.controller.base.ts @@ -16,7 +16,11 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { WorkflowStepService } from "../workflowStep.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { WorkflowStepCreateInput } from "./WorkflowStepCreateInput"; import { WorkflowStep } from "./WorkflowStep"; import { WorkflowStepFindManyArgs } from "./WorkflowStepFindManyArgs"; @@ -26,10 +30,24 @@ import { WorkflowReminderFindManyArgs } from "../../workflowReminder/base/Workfl import { WorkflowReminder } from "../../workflowReminder/base/WorkflowReminder"; import { WorkflowReminderWhereUniqueInput } from "../../workflowReminder/base/WorkflowReminderWhereUniqueInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class WorkflowStepControllerBase { - constructor(protected readonly service: WorkflowStepService) {} + constructor( + protected readonly service: WorkflowStepService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: WorkflowStep }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createWorkflowStep( @common.Body() data: WorkflowStepCreateInput ): Promise { @@ -59,9 +77,18 @@ export class WorkflowStepControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [WorkflowStep] }) @ApiNestedQuery(WorkflowStepFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflowSteps(@common.Req() request: Request): Promise { const args = plainToClass(WorkflowStepFindManyArgs, request.query); return this.service.workflowSteps({ @@ -84,9 +111,18 @@ export class WorkflowStepControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: WorkflowStep }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflowStep( @common.Param() params: WorkflowStepWhereUniqueInput ): Promise { @@ -116,9 +152,18 @@ export class WorkflowStepControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: WorkflowStep }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateWorkflowStep( @common.Param() params: WorkflowStepWhereUniqueInput, @common.Body() data: WorkflowStepUpdateInput @@ -162,6 +207,14 @@ export class WorkflowStepControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: WorkflowStep }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteWorkflowStep( @common.Param() params: WorkflowStepWhereUniqueInput ): Promise { @@ -194,8 +247,14 @@ export class WorkflowStepControllerBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id/workflowReminders") @ApiNestedQuery(WorkflowReminderFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) async findWorkflowReminders( @common.Req() request: Request, @common.Param() params: WorkflowStepWhereUniqueInput @@ -232,6 +291,11 @@ export class WorkflowStepControllerBase { } @common.Post("/:id/workflowReminders") + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "update", + possession: "any", + }) async connectWorkflowReminders( @common.Param() params: WorkflowStepWhereUniqueInput, @common.Body() body: WorkflowReminderWhereUniqueInput[] @@ -249,6 +313,11 @@ export class WorkflowStepControllerBase { } @common.Patch("/:id/workflowReminders") + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "update", + possession: "any", + }) async updateWorkflowReminders( @common.Param() params: WorkflowStepWhereUniqueInput, @common.Body() body: WorkflowReminderWhereUniqueInput[] @@ -266,6 +335,11 @@ export class WorkflowStepControllerBase { } @common.Delete("/:id/workflowReminders") + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "update", + possession: "any", + }) async disconnectWorkflowReminders( @common.Param() params: WorkflowStepWhereUniqueInput, @common.Body() body: WorkflowReminderWhereUniqueInput[] diff --git a/apps/basic-auth-provider/src/workflowStep/base/workflowStep.module.base.ts b/apps/basic-auth-provider/src/workflowStep/base/workflowStep.module.base.ts index 435ee2d..c812c92 100644 --- a/apps/basic-auth-provider/src/workflowStep/base/workflowStep.module.base.ts +++ b/apps/basic-auth-provider/src/workflowStep/base/workflowStep.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class WorkflowStepModuleBase {} diff --git a/apps/basic-auth-provider/src/workflowStep/base/workflowStep.resolver.base.ts b/apps/basic-auth-provider/src/workflowStep/base/workflowStep.resolver.base.ts index d1df62b..1305b1d 100644 --- a/apps/basic-auth-provider/src/workflowStep/base/workflowStep.resolver.base.ts +++ b/apps/basic-auth-provider/src/workflowStep/base/workflowStep.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { WorkflowStep } from "./WorkflowStep"; import { WorkflowStepCountArgs } from "./WorkflowStepCountArgs"; import { WorkflowStepFindManyArgs } from "./WorkflowStepFindManyArgs"; @@ -24,10 +30,20 @@ import { WorkflowReminderFindManyArgs } from "../../workflowReminder/base/Workfl import { WorkflowReminder } from "../../workflowReminder/base/WorkflowReminder"; import { Workflow } from "../../workflow/base/Workflow"; import { WorkflowStepService } from "../workflowStep.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => WorkflowStep) export class WorkflowStepResolverBase { - constructor(protected readonly service: WorkflowStepService) {} + constructor( + protected readonly service: WorkflowStepService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "any", + }) async _workflowStepsMeta( @graphql.Args() args: WorkflowStepCountArgs ): Promise { @@ -37,14 +53,26 @@ export class WorkflowStepResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [WorkflowStep]) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "any", + }) async workflowSteps( @graphql.Args() args: WorkflowStepFindManyArgs ): Promise { return this.service.workflowSteps(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => WorkflowStep, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "read", + possession: "own", + }) async workflowStep( @graphql.Args() args: WorkflowStepFindUniqueArgs ): Promise { @@ -55,7 +83,13 @@ export class WorkflowStepResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => WorkflowStep) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "create", + possession: "any", + }) async createWorkflowStep( @graphql.Args() args: CreateWorkflowStepArgs ): Promise { @@ -71,7 +105,13 @@ export class WorkflowStepResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => WorkflowStep) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "update", + possession: "any", + }) async updateWorkflowStep( @graphql.Args() args: UpdateWorkflowStepArgs ): Promise { @@ -97,6 +137,11 @@ export class WorkflowStepResolverBase { } @graphql.Mutation(() => WorkflowStep) + @nestAccessControl.UseRoles({ + resource: "WorkflowStep", + action: "delete", + possession: "any", + }) async deleteWorkflowStep( @graphql.Args() args: DeleteWorkflowStepArgs ): Promise { @@ -112,7 +157,13 @@ export class WorkflowStepResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => [WorkflowReminder], { name: "workflowReminders" }) + @nestAccessControl.UseRoles({ + resource: "WorkflowReminder", + action: "read", + possession: "any", + }) async findWorkflowReminders( @graphql.Parent() parent: WorkflowStep, @graphql.Args() args: WorkflowReminderFindManyArgs @@ -126,10 +177,16 @@ export class WorkflowStepResolverBase { return results; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Workflow, { nullable: true, name: "workflow", }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) async getWorkflow( @graphql.Parent() parent: WorkflowStep ): Promise { diff --git a/apps/basic-auth-provider/src/workflowStep/workflowStep.controller.ts b/apps/basic-auth-provider/src/workflowStep/workflowStep.controller.ts index 06db7eb..f6e7980 100644 --- a/apps/basic-auth-provider/src/workflowStep/workflowStep.controller.ts +++ b/apps/basic-auth-provider/src/workflowStep/workflowStep.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { WorkflowStepService } from "./workflowStep.service"; import { WorkflowStepControllerBase } from "./base/workflowStep.controller.base"; @swagger.ApiTags("workflowSteps") @common.Controller("workflowSteps") export class WorkflowStepController extends WorkflowStepControllerBase { - constructor(protected readonly service: WorkflowStepService) { - super(service); + constructor( + protected readonly service: WorkflowStepService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflowStep/workflowStep.module.ts b/apps/basic-auth-provider/src/workflowStep/workflowStep.module.ts index f5d30a7..29d6799 100644 --- a/apps/basic-auth-provider/src/workflowStep/workflowStep.module.ts +++ b/apps/basic-auth-provider/src/workflowStep/workflowStep.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { WorkflowStepModuleBase } from "./base/workflowStep.module.base"; import { WorkflowStepService } from "./workflowStep.service"; import { WorkflowStepController } from "./workflowStep.controller"; import { WorkflowStepResolver } from "./workflowStep.resolver"; @Module({ - imports: [WorkflowStepModuleBase], + imports: [WorkflowStepModuleBase, forwardRef(() => AuthModule)], controllers: [WorkflowStepController], providers: [WorkflowStepService, WorkflowStepResolver], exports: [WorkflowStepService], diff --git a/apps/basic-auth-provider/src/workflowStep/workflowStep.resolver.ts b/apps/basic-auth-provider/src/workflowStep/workflowStep.resolver.ts index 10600b1..782edc2 100644 --- a/apps/basic-auth-provider/src/workflowStep/workflowStep.resolver.ts +++ b/apps/basic-auth-provider/src/workflowStep/workflowStep.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { WorkflowStepResolverBase } from "./base/workflowStep.resolver.base"; import { WorkflowStep } from "./base/WorkflowStep"; import { WorkflowStepService } from "./workflowStep.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => WorkflowStep) export class WorkflowStepResolver extends WorkflowStepResolverBase { - constructor(protected readonly service: WorkflowStepService) { - super(service); + constructor( + protected readonly service: WorkflowStepService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.controller.base.ts b/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.controller.base.ts index 68f8f71..04f0bd0 100644 --- a/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.controller.base.ts +++ b/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.controller.base.ts @@ -16,17 +16,35 @@ import * as errors from "../../errors"; import { Request } from "express"; import { plainToClass } from "class-transformer"; import { ApiNestedQuery } from "../../decorators/api-nested-query.decorator"; +import * as nestAccessControl from "nest-access-control"; +import * as defaultAuthGuard from "../../auth/defaultAuth.guard"; import { WorkflowsOnEventTypeService } from "../workflowsOnEventType.service"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; import { WorkflowsOnEventTypeCreateInput } from "./WorkflowsOnEventTypeCreateInput"; import { WorkflowsOnEventType } from "./WorkflowsOnEventType"; import { WorkflowsOnEventTypeFindManyArgs } from "./WorkflowsOnEventTypeFindManyArgs"; import { WorkflowsOnEventTypeWhereUniqueInput } from "./WorkflowsOnEventTypeWhereUniqueInput"; import { WorkflowsOnEventTypeUpdateInput } from "./WorkflowsOnEventTypeUpdateInput"; +@swagger.ApiBearerAuth() +@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard) export class WorkflowsOnEventTypeControllerBase { - constructor(protected readonly service: WorkflowsOnEventTypeService) {} + constructor( + protected readonly service: WorkflowsOnEventTypeService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Post() @swagger.ApiCreatedResponse({ type: WorkflowsOnEventType }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "create", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async createWorkflowsOnEventType( @common.Body() data: WorkflowsOnEventTypeCreateInput ): Promise { @@ -60,9 +78,18 @@ export class WorkflowsOnEventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get() @swagger.ApiOkResponse({ type: [WorkflowsOnEventType] }) @ApiNestedQuery(WorkflowsOnEventTypeFindManyArgs) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflowsOnEventTypes( @common.Req() request: Request ): Promise { @@ -87,9 +114,18 @@ export class WorkflowsOnEventTypeControllerBase { }); } + @common.UseInterceptors(AclFilterResponseInterceptor) @common.Get("/:id") @swagger.ApiOkResponse({ type: WorkflowsOnEventType }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "own", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async workflowsOnEventType( @common.Param() params: WorkflowsOnEventTypeWhereUniqueInput ): Promise { @@ -119,9 +155,18 @@ export class WorkflowsOnEventTypeControllerBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @common.Patch("/:id") @swagger.ApiOkResponse({ type: WorkflowsOnEventType }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "update", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async updateWorkflowsOnEventType( @common.Param() params: WorkflowsOnEventTypeWhereUniqueInput, @common.Body() data: WorkflowsOnEventTypeUpdateInput @@ -169,6 +214,14 @@ export class WorkflowsOnEventTypeControllerBase { @common.Delete("/:id") @swagger.ApiOkResponse({ type: WorkflowsOnEventType }) @swagger.ApiNotFoundResponse({ type: errors.NotFoundException }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "delete", + possession: "any", + }) + @swagger.ApiForbiddenResponse({ + type: errors.ForbiddenException, + }) async deleteWorkflowsOnEventType( @common.Param() params: WorkflowsOnEventTypeWhereUniqueInput ): Promise { diff --git a/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.module.base.ts b/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.module.base.ts index 8c22b63..e4932fd 100644 --- a/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.module.base.ts +++ b/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.module.base.ts @@ -10,9 +10,9 @@ https://docs.amplication.com/how-to/custom-code ------------------------------------------------------------------------------ */ import { Module } from "@nestjs/common"; - +import { ACLModule } from "../../auth/acl.module"; @Module({ - imports: [], - exports: [], + imports: [ACLModule], + exports: [ACLModule], }) export class WorkflowsOnEventTypeModuleBase {} diff --git a/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.resolver.base.ts b/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.resolver.base.ts index 84306cb..9e516d2 100644 --- a/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.resolver.base.ts +++ b/apps/basic-auth-provider/src/workflowsOnEventType/base/workflowsOnEventType.resolver.base.ts @@ -13,6 +13,12 @@ import * as graphql from "@nestjs/graphql"; import { GraphQLError } from "graphql"; import { isRecordNotFoundError } from "../../prisma.util"; import { MetaQueryPayload } from "../../util/MetaQueryPayload"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; +import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor"; +import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor"; import { WorkflowsOnEventType } from "./WorkflowsOnEventType"; import { WorkflowsOnEventTypeCountArgs } from "./WorkflowsOnEventTypeCountArgs"; import { WorkflowsOnEventTypeFindManyArgs } from "./WorkflowsOnEventTypeFindManyArgs"; @@ -23,10 +29,20 @@ import { DeleteWorkflowsOnEventTypeArgs } from "./DeleteWorkflowsOnEventTypeArgs import { EventType } from "../../eventType/base/EventType"; import { Workflow } from "../../workflow/base/Workflow"; import { WorkflowsOnEventTypeService } from "../workflowsOnEventType.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => WorkflowsOnEventType) export class WorkflowsOnEventTypeResolverBase { - constructor(protected readonly service: WorkflowsOnEventTypeService) {} - + constructor( + protected readonly service: WorkflowsOnEventTypeService, + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) {} + + @graphql.Query(() => MetaQueryPayload) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) async _workflowsOnEventTypesMeta( @graphql.Args() args: WorkflowsOnEventTypeCountArgs ): Promise { @@ -36,14 +52,26 @@ export class WorkflowsOnEventTypeResolverBase { }; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => [WorkflowsOnEventType]) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "any", + }) async workflowsOnEventTypes( @graphql.Args() args: WorkflowsOnEventTypeFindManyArgs ): Promise { return this.service.workflowsOnEventTypes(args); } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.Query(() => WorkflowsOnEventType, { nullable: true }) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "read", + possession: "own", + }) async workflowsOnEventType( @graphql.Args() args: WorkflowsOnEventTypeFindUniqueArgs ): Promise { @@ -54,7 +82,13 @@ export class WorkflowsOnEventTypeResolverBase { return result; } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => WorkflowsOnEventType) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "create", + possession: "any", + }) async createWorkflowsOnEventType( @graphql.Args() args: CreateWorkflowsOnEventTypeArgs ): Promise { @@ -74,7 +108,13 @@ export class WorkflowsOnEventTypeResolverBase { }); } + @common.UseInterceptors(AclValidateRequestInterceptor) @graphql.Mutation(() => WorkflowsOnEventType) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "update", + possession: "any", + }) async updateWorkflowsOnEventType( @graphql.Args() args: UpdateWorkflowsOnEventTypeArgs ): Promise { @@ -104,6 +144,11 @@ export class WorkflowsOnEventTypeResolverBase { } @graphql.Mutation(() => WorkflowsOnEventType) + @nestAccessControl.UseRoles({ + resource: "WorkflowsOnEventType", + action: "delete", + possession: "any", + }) async deleteWorkflowsOnEventType( @graphql.Args() args: DeleteWorkflowsOnEventTypeArgs ): Promise { @@ -119,10 +164,16 @@ export class WorkflowsOnEventTypeResolverBase { } } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => EventType, { nullable: true, name: "eventType", }) + @nestAccessControl.UseRoles({ + resource: "EventType", + action: "read", + possession: "any", + }) async getEventType( @graphql.Parent() parent: WorkflowsOnEventType ): Promise { @@ -134,10 +185,16 @@ export class WorkflowsOnEventTypeResolverBase { return result; } + @common.UseInterceptors(AclFilterResponseInterceptor) @graphql.ResolveField(() => Workflow, { nullable: true, name: "workflow", }) + @nestAccessControl.UseRoles({ + resource: "Workflow", + action: "read", + possession: "any", + }) async getWorkflow( @graphql.Parent() parent: WorkflowsOnEventType ): Promise { diff --git a/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.controller.ts b/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.controller.ts index b327fcd..513aa0e 100644 --- a/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.controller.ts +++ b/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.controller.ts @@ -1,12 +1,17 @@ import * as common from "@nestjs/common"; import * as swagger from "@nestjs/swagger"; +import * as nestAccessControl from "nest-access-control"; import { WorkflowsOnEventTypeService } from "./workflowsOnEventType.service"; import { WorkflowsOnEventTypeControllerBase } from "./base/workflowsOnEventType.controller.base"; @swagger.ApiTags("workflowsOnEventTypes") @common.Controller("workflowsOnEventTypes") export class WorkflowsOnEventTypeController extends WorkflowsOnEventTypeControllerBase { - constructor(protected readonly service: WorkflowsOnEventTypeService) { - super(service); + constructor( + protected readonly service: WorkflowsOnEventTypeService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } } diff --git a/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.module.ts b/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.module.ts index e1de1ff..1626a8b 100644 --- a/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.module.ts +++ b/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.module.ts @@ -1,11 +1,12 @@ -import { Module } from "@nestjs/common"; +import { Module, forwardRef } from "@nestjs/common"; +import { AuthModule } from "../auth/auth.module"; import { WorkflowsOnEventTypeModuleBase } from "./base/workflowsOnEventType.module.base"; import { WorkflowsOnEventTypeService } from "./workflowsOnEventType.service"; import { WorkflowsOnEventTypeController } from "./workflowsOnEventType.controller"; import { WorkflowsOnEventTypeResolver } from "./workflowsOnEventType.resolver"; @Module({ - imports: [WorkflowsOnEventTypeModuleBase], + imports: [WorkflowsOnEventTypeModuleBase, forwardRef(() => AuthModule)], controllers: [WorkflowsOnEventTypeController], providers: [WorkflowsOnEventTypeService, WorkflowsOnEventTypeResolver], exports: [WorkflowsOnEventTypeService], diff --git a/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.resolver.ts b/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.resolver.ts index 7637108..c9236a6 100644 --- a/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.resolver.ts +++ b/apps/basic-auth-provider/src/workflowsOnEventType/workflowsOnEventType.resolver.ts @@ -1,11 +1,20 @@ import * as graphql from "@nestjs/graphql"; +import * as nestAccessControl from "nest-access-control"; +import * as gqlACGuard from "../auth/gqlAC.guard"; +import { GqlDefaultAuthGuard } from "../auth/gqlDefaultAuth.guard"; +import * as common from "@nestjs/common"; import { WorkflowsOnEventTypeResolverBase } from "./base/workflowsOnEventType.resolver.base"; import { WorkflowsOnEventType } from "./base/WorkflowsOnEventType"; import { WorkflowsOnEventTypeService } from "./workflowsOnEventType.service"; +@common.UseGuards(GqlDefaultAuthGuard, gqlACGuard.GqlACGuard) @graphql.Resolver(() => WorkflowsOnEventType) export class WorkflowsOnEventTypeResolver extends WorkflowsOnEventTypeResolverBase { - constructor(protected readonly service: WorkflowsOnEventTypeService) { - super(service); + constructor( + protected readonly service: WorkflowsOnEventTypeService, + @nestAccessControl.InjectRolesBuilder() + protected readonly rolesBuilder: nestAccessControl.RolesBuilder + ) { + super(service, rolesBuilder); } }