diff --git a/packages/arcade/.env b/packages/arcade/.env
index ee618c2..6611a85 100644
--- a/packages/arcade/.env
+++ b/packages/arcade/.env
@@ -1,13 +1,14 @@
BCRYPT_SALT=10
COMPOSE_PROJECT_NAME=amp_clc6ep483045sou01045ac971
-JWT_SECRET_KEY=Change_ME!!!
-JWT_EXPIRATION=2d
PORT=3000
KAFKA_BROKERS=localhost:9092
KAFKA_ENABLE_SSL=false
KAFKA_CLIENT_ID=arcade-service
KAFKA_GROUP_ID=arcade-service
-DB_USER=postgres
-DB_PASSWORD=postgres
+JWT_SECRET_KEY=Change_ME!!!
+JWT_EXPIRATION=2d
+DB_URL=postgres://admin:admin@localhost:5432/my-db
+DB_USER=admin
+DB_PASSWORD=admin
DB_PORT=5432
-DB_URL=postgres://postgres:postgres@localhost:5432/postgres
\ No newline at end of file
+DB_NAME=my-db
\ No newline at end of file
diff --git a/packages/arcade/.gitignore b/packages/arcade/.gitignore
index b65b772..08c9980 100644
--- a/packages/arcade/.gitignore
+++ b/packages/arcade/.gitignore
@@ -1,6 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-
-
+
/node_modules
/dist
-.DS_Store
\ No newline at end of file
+.DS_Store
diff --git a/packages/arcade/Dockerfile b/packages/arcade/Dockerfile
index 586f38c..0a20053 100644
--- a/packages/arcade/Dockerfile
+++ b/packages/arcade/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:19.1 AS base
+FROM node:18.12.1 AS base
WORKDIR /app
@@ -14,7 +14,7 @@ COPY . .
RUN npm run build
-FROM node:19.1 AS prod
+FROM node:18.12.1 AS prod
WORKDIR /app
diff --git a/packages/arcade/README.md b/packages/arcade/README.md
new file mode 100644
index 0000000..9de25c0
--- /dev/null
+++ b/packages/arcade/README.md
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+# Introduction
+
+This service was generated with Amplication. The server-side of the generated project. This component provides the different backend services - i.e., REST API, GraphQL API, authentication, authorization, logging, data validation and the connection to the database. Additional information about the server component and the architecture around it, can be found on the [documentation](https://docs.amplication.com/guides/getting-started) site.
+
+# Getting started
+
+## Step 1: Configuration
+
+Configuration for the server component can be provided through the use of environment variables. These can be passed to the application via the use of the `.env` file in the base directory of the generated service. Below a table can be found which show the different variables that can be passed - these are the variables which exist by default, through the use of plugins additional integrations could require additional values. These values are provided default values after generation, change them to the desired values.
+
+| Variable | Description | Value |
+| -------------------- | -------------------------------------------- | ------------------------------------------------------------------- |
+| BCRYPT_SALT | the string used for hashing | [random-string] |
+| COMPOSE_PROJECT_NAME | the identifier of the service plus prefix | amp_[service-identifier] |
+| PORT | the port on which to run the server | 3000 |
+| DB_URL | the connection url for the database | [db-provider]://[username]:[password]@localhost:[db-port]/[db-name] |
+| DB_PORT | the port used by the database instance | [db-provider-port] |
+| DB_USER | the username used to connect to the database | [username] |
+| DB_PASSWORD | the password used to connect to the database | [password] |
+| DB_NAME | the name of the database | [service-name] / [project-name] |
+| JWT_SECRET_KEY | the secret used to sign the json-web token | [secret] |
+| JWT_EXPIRATION | the expiration time for the json-web token | 2d |
+
+> **Note**
+> Amplication generates default values and stores them under the .env file. It is advised to use some form of secrets manager/vault solution when using in production.
+
+## Step 2.1: Scripts - pre-requisites
+
+After configuration of the server the next step would be to run the application. Before running the server side of the component, make sure that the different pre-requisites are met - i.e., node.js [^16.x], npm, docker. After the setup of the pre-requisites the server component can be started.
+
+```sh
+# installation of the dependencies
+$ npm install
+```
+```sh
+# generate the prisma client
+$ npm run prisma:generate
+```
+```sh
+# start the database where the server component will connect to
+$ npm run docker:db
+```
+```sh
+# initialize the database
+$ npm run db:init
+```
+
+## Step 2.2: Scripts - local development
+
+```shell
+# start the server component
+$ npm run install
+```
+
+## Step 2.2: Scripts - container based development
+
+```shell
+# start the server component as a docker container
+$ npm run compose:up
+```
diff --git a/packages/arcade/docker-compose.yml b/packages/arcade/docker-compose.yml
index b69f003..5aba9fb 100644
--- a/packages/arcade/docker-compose.yml
+++ b/packages/arcade/docker-compose.yml
@@ -11,7 +11,7 @@ services:
BCRYPT_SALT: ${BCRYPT_SALT}
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
JWT_EXPIRATION: ${JWT_EXPIRATION}
- DB_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5433
+ DB_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
depends_on:
- migrate
migrate:
@@ -23,7 +23,7 @@ services:
working_dir: /app/server
environment:
BCRYPT_SALT: ${BCRYPT_SALT}
- DB_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5432
+ DB_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
depends_on:
db:
condition: service_healthy
@@ -61,17 +61,13 @@ services:
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
+ POSTGRES_DB: ${DB_NAME}
volumes:
- postgres:/var/lib/postgresql/data
healthcheck:
test:
- - CMD
- - pg_isready
- - -q
- - -d
- - ${DB_DB_NAME}
- - -U
- - ${DB_USER}
+ - CMD-SHELL
+ - pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
timeout: 45s
interval: 10s
retries: 10
diff --git a/packages/arcade/package.json b/packages/arcade/package.json
index 5ee3636..b7b4ff0 100644
--- a/packages/arcade/package.json
+++ b/packages/arcade/package.json
@@ -23,8 +23,6 @@
"@nestjs/config": "1.1.5",
"@nestjs/core": "8.4.7",
"@nestjs/graphql": "9.1.2",
- "@nestjs/jwt": "8.0.0",
- "@nestjs/passport": "8.2.2",
"@nestjs/platform-express": "8.4.7",
"@nestjs/serve-static": "2.2.2",
"@nestjs/swagger": "5.1.5",
@@ -39,14 +37,17 @@
"nest-morgan": "1.0.1",
"nestjs-prisma": "0.19.0",
"npm-run-all": "4.1.5",
- "passport": "0.6.0",
- "passport-http": "0.3.0",
- "passport-jwt": "4.0.0",
"reflect-metadata": "0.1.13",
"swagger-ui-express": "4.3.0",
- "ts-node": "9.1.1",
+ "ts-node": "10.9.1",
+ "validator": "^13.9.0",
"@nestjs/microservices": "8.2.3",
- "kafkajs": "2.2.0"
+ "kafkajs": "2.2.0",
+ "@nestjs/jwt": "^10.0.2",
+ "@nestjs/passport": "^9.0.0",
+ "passport": "0.6.0",
+ "passport-http": "0.3.0",
+ "passport-jwt": "4.0.1"
},
"devDependencies": {
"@nestjs/cli": "8.2.5",
@@ -56,16 +57,17 @@
"@types/graphql-type-json": "0.3.2",
"@types/jest": "26.0.19",
"@types/normalize-path": "3.0.0",
- "@types/passport-http": "0.3.9",
- "@types/passport-jwt": "3.0.6",
"@types/supertest": "2.0.11",
+ "@types/validator": "^13.7.15",
"jest": "27.0.6",
"jest-mock-extended": "^2.0.4",
"prisma": "4.6.1",
"supertest": "4.0.2",
"ts-jest": "27.0.3",
"type-fest": "0.11.0",
- "typescript": "4.2.3"
+ "typescript": "4.2.3",
+ "@types/passport-http": "0.3.9",
+ "@types/passport-jwt": "3.0.8"
},
"jest": {
"preset": "ts-jest",
diff --git a/packages/arcade/scripts/seed.ts b/packages/arcade/scripts/seed.ts
index 3bb4d3a..272dddd 100644
--- a/packages/arcade/scripts/seed.ts
+++ b/packages/arcade/scripts/seed.ts
@@ -1,8 +1,8 @@
import * as dotenv from "dotenv";
import { PrismaClient } from "@prisma/client";
+import { customSeed } from "./customSeed";
import { Salt, parseSalt } from "../src/auth/password.service";
import { hash } from "bcrypt";
-import { customSeed } from "./customSeed";
if (require.main === module) {
dotenv.config();
@@ -12,7 +12,6 @@ if (require.main === module) {
if (!BCRYPT_SALT) {
throw new Error("BCRYPT_SALT environment variable must be defined");
}
-
const salt = parseSalt(BCRYPT_SALT);
seed(salt).catch((error) => {
@@ -25,16 +24,22 @@ 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 },
+ where: {
+ username: data.username,
+ },
+
update: {},
create: data,
});
+
void client.$disconnect();
console.info("Seeding database with custom seed...");
diff --git a/packages/arcade/src/app.module.ts b/packages/arcade/src/app.module.ts
index ef31ca0..1cae661 100644
--- a/packages/arcade/src/app.module.ts
+++ b/packages/arcade/src/app.module.ts
@@ -4,9 +4,8 @@ import { MorganInterceptor, MorganModule } from "nest-morgan";
import { UserModule } from "./user/user.module";
import { GameModule } from "./game/game.module";
import { SessionModule } from "./session/session.module";
-import { ACLModule } from "./auth/acl.module";
-import { AuthModule } from "./auth/auth.module";
import { HealthModule } from "./health/health.module";
+import { PrismaModule } from "./prisma/prisma.module";
import { SecretsManagerModule } from "./providers/secrets/secretsManager.module";
import { KafkaModule } from "./kafka/kafka.module";
import { ConfigModule, ConfigService } from "@nestjs/config";
@@ -14,17 +13,20 @@ import { ServeStaticModule } from "@nestjs/serve-static";
import { ServeStaticOptionsService } from "./serveStaticOptions.service";
import { GraphQLModule } from "@nestjs/graphql";
+import { ACLModule } from "./auth/acl.module";
+import { AuthModule } from "./auth/auth.module";
+
@Module({
controllers: [],
imports: [
+ ACLModule,
+ AuthModule,
UserModule,
GameModule,
SessionModule,
- ACLModule,
- AuthModule,
HealthModule,
+ PrismaModule,
SecretsManagerModule,
- KafkaModule,
MorganModule,
ConfigModule.forRoot({ isGlobal: true }),
ServeStaticModule.forRootAsync({
diff --git a/packages/arcade/src/auth/UserInfo.ts b/packages/arcade/src/auth/UserInfo.ts
index f1b1d3c..ef61dc4 100644
--- a/packages/arcade/src/auth/UserInfo.ts
+++ b/packages/arcade/src/auth/UserInfo.ts
@@ -1,5 +1,5 @@
import { Field, ObjectType } from "@nestjs/graphql";
-import { User } from "../user/base/user";
+import { User } from "../user/base/User";
@ObjectType()
export class UserInfo implements Partial {
diff --git a/packages/arcade/src/auth/auth.service.spec.ts b/packages/arcade/src/auth/auth.service.spec.ts
new file mode 100644
index 0000000..aaa68e4
--- /dev/null
+++ b/packages/arcade/src/auth/auth.service.spec.ts
@@ -0,0 +1,118 @@
+import { Test, TestingModule } from "@nestjs/testing";
+// @ts-ignore
+// eslint-disable-next-line
+import { UserService } from "../user/user.service";
+import { AuthService } from "./auth.service";
+import { Credentials } from "./Credentials";
+import { PasswordService } from "./password.service";
+// @ts-ignore
+// eslint-disable-next-line
+import { TokenService } from "./token.service";
+import { VALID_ID } from "../tests/auth/constants";
+
+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 userService = {
+ findOne(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: userService,
+ },
+ {
+ 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/packages/arcade/src/auth/basic/base/basic.strategy.base.ts b/packages/arcade/src/auth/basic/base/basic.strategy.base.ts
deleted file mode 100644
index e138356..0000000
--- a/packages/arcade/src/auth/basic/base/basic.strategy.base.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-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/packages/arcade/src/auth/basic/basic.strategy.ts b/packages/arcade/src/auth/basic/basic.strategy.ts
deleted file mode 100644
index f087795..0000000
--- a/packages/arcade/src/auth/basic/basic.strategy.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-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/packages/arcade/src/auth/basic/basicAuth.guard.ts b/packages/arcade/src/auth/basic/basicAuth.guard.ts
deleted file mode 100644
index 9c92fdd..0000000
--- a/packages/arcade/src/auth/basic/basicAuth.guard.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { AuthGuard } from "@nestjs/passport";
-
-export class BasicAuthGuard extends AuthGuard("basic") {}
diff --git a/packages/arcade/src/auth/jwt/jwt.strategy.ts b/packages/arcade/src/auth/jwt/jwt.strategy.ts
index 0de5def..0794650 100644
--- a/packages/arcade/src/auth/jwt/jwt.strategy.ts
+++ b/packages/arcade/src/auth/jwt/jwt.strategy.ts
@@ -2,6 +2,7 @@ import { Inject, Injectable } from "@nestjs/common";
import { JWT_SECRET_KEY } from "../../constants";
import { UserService } from "../../user/user.service";
import { JwtStrategyBase } from "./base/jwt.strategy.base";
+
@Injectable()
export class JwtStrategy extends JwtStrategyBase {
constructor(
diff --git a/packages/arcade/src/auth/password.service.spec.ts b/packages/arcade/src/auth/password.service.spec.ts
new file mode 100644
index 0000000..309c8c0
--- /dev/null
+++ b/packages/arcade/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/packages/arcade/src/auth/userData.decorator.ts b/packages/arcade/src/auth/userData.decorator.ts
index 240c7d9..6a40ad1 100644
--- a/packages/arcade/src/auth/userData.decorator.ts
+++ b/packages/arcade/src/auth/userData.decorator.ts
@@ -1,6 +1,5 @@
import { createParamDecorator, ExecutionContext } from "@nestjs/common";
import { GqlContextType, GqlExecutionContext } from "@nestjs/graphql";
-//@ts-ignore
import { User } from "@prisma/client";
/**
diff --git a/packages/arcade/src/game/base/CreateGameArgs.ts b/packages/arcade/src/game/base/CreateGameArgs.ts
index 0a6dcdc..7f813c8 100644
--- a/packages/arcade/src/game/base/CreateGameArgs.ts
+++ b/packages/arcade/src/game/base/CreateGameArgs.ts
@@ -18,4 +18,4 @@ class CreateGameArgs {
data!: GameCreateInput;
}
-export { CreateGameArgs };
+export { CreateGameArgs as CreateGameArgs };
diff --git a/packages/arcade/src/game/base/DeleteGameArgs.ts b/packages/arcade/src/game/base/DeleteGameArgs.ts
index dd749cf..cfcd055 100644
--- a/packages/arcade/src/game/base/DeleteGameArgs.ts
+++ b/packages/arcade/src/game/base/DeleteGameArgs.ts
@@ -18,4 +18,4 @@ class DeleteGameArgs {
where!: GameWhereUniqueInput;
}
-export { DeleteGameArgs };
+export { DeleteGameArgs as DeleteGameArgs };
diff --git a/packages/arcade/src/game/base/Game.ts b/packages/arcade/src/game/base/Game.ts
index 8fa9766..c6ea580 100644
--- a/packages/arcade/src/game/base/Game.ts
+++ b/packages/arcade/src/game/base/Game.ts
@@ -22,6 +22,7 @@ import { Type } from "class-transformer";
import { EnumGameGameType } from "./EnumGameGameType";
import { Session } from "../../session/base/Session";
import { User } from "../../user/base/User";
+
@ObjectType()
class Game {
@ApiProperty({
@@ -99,4 +100,5 @@ class Game {
@IsOptional()
users?: Array;
}
-export { Game };
+
+export { Game as Game };
diff --git a/packages/arcade/src/game/base/GameCreateInput.ts b/packages/arcade/src/game/base/GameCreateInput.ts
index d16be0c..56fa1f1 100644
--- a/packages/arcade/src/game/base/GameCreateInput.ts
+++ b/packages/arcade/src/game/base/GameCreateInput.ts
@@ -16,6 +16,7 @@ import { IsEnum, IsOptional, IsString, ValidateNested } from "class-validator";
import { SessionCreateNestedManyWithoutGamesInput } from "./SessionCreateNestedManyWithoutGamesInput";
import { Type } from "class-transformer";
import { UserCreateNestedManyWithoutGamesInput } from "./UserCreateNestedManyWithoutGamesInput";
+
@InputType()
class GameCreateInput {
@ApiProperty({
@@ -75,4 +76,5 @@ class GameCreateInput {
})
users?: UserCreateNestedManyWithoutGamesInput;
}
-export { GameCreateInput };
+
+export { GameCreateInput as GameCreateInput };
diff --git a/packages/arcade/src/game/base/GameFindManyArgs.ts b/packages/arcade/src/game/base/GameFindManyArgs.ts
index 99e838d..519c933 100644
--- a/packages/arcade/src/game/base/GameFindManyArgs.ts
+++ b/packages/arcade/src/game/base/GameFindManyArgs.ts
@@ -50,4 +50,4 @@ class GameFindManyArgs {
take?: number;
}
-export { GameFindManyArgs };
+export { GameFindManyArgs as GameFindManyArgs };
diff --git a/packages/arcade/src/game/base/GameFindUniqueArgs.ts b/packages/arcade/src/game/base/GameFindUniqueArgs.ts
index 49a62df..71823b3 100644
--- a/packages/arcade/src/game/base/GameFindUniqueArgs.ts
+++ b/packages/arcade/src/game/base/GameFindUniqueArgs.ts
@@ -18,4 +18,4 @@ class GameFindUniqueArgs {
where!: GameWhereUniqueInput;
}
-export { GameFindUniqueArgs };
+export { GameFindUniqueArgs as GameFindUniqueArgs };
diff --git a/packages/arcade/src/game/base/GameListRelationFilter.ts b/packages/arcade/src/game/base/GameListRelationFilter.ts
index 2f6282d..44cc653 100644
--- a/packages/arcade/src/game/base/GameListRelationFilter.ts
+++ b/packages/arcade/src/game/base/GameListRelationFilter.ts
@@ -53,4 +53,4 @@ class GameListRelationFilter {
})
none?: GameWhereInput;
}
-export { GameListRelationFilter };
+export { GameListRelationFilter as GameListRelationFilter };
diff --git a/packages/arcade/src/game/base/GameOrderByInput.ts b/packages/arcade/src/game/base/GameOrderByInput.ts
index 6f79d89..13a7bdd 100644
--- a/packages/arcade/src/game/base/GameOrderByInput.ts
+++ b/packages/arcade/src/game/base/GameOrderByInput.ts
@@ -73,4 +73,4 @@ class GameOrderByInput {
updatedAt?: SortOrder;
}
-export { GameOrderByInput };
+export { GameOrderByInput as GameOrderByInput };
diff --git a/packages/arcade/src/game/base/GameUpdateInput.ts b/packages/arcade/src/game/base/GameUpdateInput.ts
index dc1c8a7..10fe65d 100644
--- a/packages/arcade/src/game/base/GameUpdateInput.ts
+++ b/packages/arcade/src/game/base/GameUpdateInput.ts
@@ -16,6 +16,7 @@ import { IsEnum, IsOptional, IsString, ValidateNested } from "class-validator";
import { SessionUpdateManyWithoutGamesInput } from "./SessionUpdateManyWithoutGamesInput";
import { Type } from "class-transformer";
import { UserUpdateManyWithoutGamesInput } from "./UserUpdateManyWithoutGamesInput";
+
@InputType()
class GameUpdateInput {
@ApiProperty({
@@ -75,4 +76,5 @@ class GameUpdateInput {
})
users?: UserUpdateManyWithoutGamesInput;
}
-export { GameUpdateInput };
+
+export { GameUpdateInput as GameUpdateInput };
diff --git a/packages/arcade/src/game/base/GameWhereInput.ts b/packages/arcade/src/game/base/GameWhereInput.ts
index 871263c..b3b810d 100644
--- a/packages/arcade/src/game/base/GameWhereInput.ts
+++ b/packages/arcade/src/game/base/GameWhereInput.ts
@@ -18,6 +18,7 @@ import { Type } from "class-transformer";
import { StringNullableFilter } from "../../util/StringNullableFilter";
import { SessionListRelationFilter } from "../../session/base/SessionListRelationFilter";
import { UserListRelationFilter } from "../../user/base/UserListRelationFilter";
+
@InputType()
class GameWhereInput {
@ApiProperty({
@@ -88,4 +89,5 @@ class GameWhereInput {
})
users?: UserListRelationFilter;
}
-export { GameWhereInput };
+
+export { GameWhereInput as GameWhereInput };
diff --git a/packages/arcade/src/game/base/GameWhereUniqueInput.ts b/packages/arcade/src/game/base/GameWhereUniqueInput.ts
index 7fb7233..e3f8554 100644
--- a/packages/arcade/src/game/base/GameWhereUniqueInput.ts
+++ b/packages/arcade/src/game/base/GameWhereUniqueInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
import { IsString } from "class-validator";
+
@InputType()
class GameWhereUniqueInput {
@ApiProperty({
@@ -22,4 +23,5 @@ class GameWhereUniqueInput {
@Field(() => String)
id!: string;
}
-export { GameWhereUniqueInput };
+
+export { GameWhereUniqueInput as GameWhereUniqueInput };
diff --git a/packages/arcade/src/game/base/SessionCreateNestedManyWithoutGamesInput.ts b/packages/arcade/src/game/base/SessionCreateNestedManyWithoutGamesInput.ts
index adf8384..a991f08 100644
--- a/packages/arcade/src/game/base/SessionCreateNestedManyWithoutGamesInput.ts
+++ b/packages/arcade/src/game/base/SessionCreateNestedManyWithoutGamesInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { SessionWhereUniqueInput } from "../../session/base/SessionWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class SessionCreateNestedManyWithoutGamesInput {
@Field(() => [SessionWhereUniqueInput], {
@@ -23,4 +24,5 @@ class SessionCreateNestedManyWithoutGamesInput {
})
connect?: Array;
}
-export { SessionCreateNestedManyWithoutGamesInput };
+
+export { SessionCreateNestedManyWithoutGamesInput as SessionCreateNestedManyWithoutGamesInput };
diff --git a/packages/arcade/src/game/base/SessionUpdateManyWithoutGamesInput.ts b/packages/arcade/src/game/base/SessionUpdateManyWithoutGamesInput.ts
index 3f7ab8f..d509b9b 100644
--- a/packages/arcade/src/game/base/SessionUpdateManyWithoutGamesInput.ts
+++ b/packages/arcade/src/game/base/SessionUpdateManyWithoutGamesInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { SessionWhereUniqueInput } from "../../session/base/SessionWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class SessionUpdateManyWithoutGamesInput {
@Field(() => [SessionWhereUniqueInput], {
@@ -41,4 +42,5 @@ class SessionUpdateManyWithoutGamesInput {
})
set?: Array;
}
-export { SessionUpdateManyWithoutGamesInput };
+
+export { SessionUpdateManyWithoutGamesInput as SessionUpdateManyWithoutGamesInput };
diff --git a/packages/arcade/src/game/base/UpdateGameArgs.ts b/packages/arcade/src/game/base/UpdateGameArgs.ts
index a9cbae7..039d303 100644
--- a/packages/arcade/src/game/base/UpdateGameArgs.ts
+++ b/packages/arcade/src/game/base/UpdateGameArgs.ts
@@ -21,4 +21,4 @@ class UpdateGameArgs {
data!: GameUpdateInput;
}
-export { UpdateGameArgs };
+export { UpdateGameArgs as UpdateGameArgs };
diff --git a/packages/arcade/src/game/base/UserCreateNestedManyWithoutGamesInput.ts b/packages/arcade/src/game/base/UserCreateNestedManyWithoutGamesInput.ts
index fb820c0..653e6f1 100644
--- a/packages/arcade/src/game/base/UserCreateNestedManyWithoutGamesInput.ts
+++ b/packages/arcade/src/game/base/UserCreateNestedManyWithoutGamesInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { UserWhereUniqueInput } from "../../user/base/UserWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class UserCreateNestedManyWithoutGamesInput {
@Field(() => [UserWhereUniqueInput], {
@@ -23,4 +24,5 @@ class UserCreateNestedManyWithoutGamesInput {
})
connect?: Array;
}
-export { UserCreateNestedManyWithoutGamesInput };
+
+export { UserCreateNestedManyWithoutGamesInput as UserCreateNestedManyWithoutGamesInput };
diff --git a/packages/arcade/src/game/base/UserUpdateManyWithoutGamesInput.ts b/packages/arcade/src/game/base/UserUpdateManyWithoutGamesInput.ts
index d04498b..e1c7f2f 100644
--- a/packages/arcade/src/game/base/UserUpdateManyWithoutGamesInput.ts
+++ b/packages/arcade/src/game/base/UserUpdateManyWithoutGamesInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { UserWhereUniqueInput } from "../../user/base/UserWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class UserUpdateManyWithoutGamesInput {
@Field(() => [UserWhereUniqueInput], {
@@ -41,4 +42,5 @@ class UserUpdateManyWithoutGamesInput {
})
set?: Array;
}
-export { UserUpdateManyWithoutGamesInput };
+
+export { UserUpdateManyWithoutGamesInput as UserUpdateManyWithoutGamesInput };
diff --git a/packages/arcade/src/game/base/game.controller.base.ts b/packages/arcade/src/game/base/game.controller.base.ts
index 0f5e21b..708d7fe 100644
--- a/packages/arcade/src/game/base/game.controller.base.ts
+++ b/packages/arcade/src/game/base/game.controller.base.ts
@@ -11,13 +11,13 @@ https://docs.amplication.com/how-to/custom-code
*/
import * as common from "@nestjs/common";
import * as swagger from "@nestjs/swagger";
-import * as nestAccessControl from "nest-access-control";
-import * as defaultAuthGuard from "../../auth/defaultAuth.guard";
import { isRecordNotFoundError } from "../../prisma.util";
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 { GameService } from "../game.service";
import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor";
import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor";
@@ -33,6 +33,7 @@ import { SessionWhereUniqueInput } from "../../session/base/SessionWhereUniqueIn
import { UserFindManyArgs } from "../../user/base/UserFindManyArgs";
import { User } from "../../user/base/User";
import { UserWhereUniqueInput } from "../../user/base/UserWhereUniqueInput";
+
@swagger.ApiBearerAuth()
@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard)
export class GameControllerBase {
@@ -40,16 +41,17 @@ export class GameControllerBase {
protected readonly service: GameService,
protected readonly rolesBuilder: nestAccessControl.RolesBuilder
) {}
-
@common.UseInterceptors(AclValidateRequestInterceptor)
+ @common.Post()
+ @swagger.ApiCreatedResponse({ type: Game })
@nestAccessControl.UseRoles({
resource: "Game",
action: "create",
possession: "any",
})
- @common.Post()
- @swagger.ApiCreatedResponse({ type: Game })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async create(@common.Body() data: GameCreateInput): Promise {
return await this.service.create({
data: data,
@@ -65,15 +67,17 @@ export class GameControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get()
+ @swagger.ApiOkResponse({ type: [Game] })
+ @ApiNestedQuery(GameFindManyArgs)
@nestAccessControl.UseRoles({
resource: "Game",
action: "read",
possession: "any",
})
- @common.Get()
- @swagger.ApiOkResponse({ type: [Game] })
- @swagger.ApiForbiddenResponse()
- @ApiNestedQuery(GameFindManyArgs)
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async findMany(@common.Req() request: Request): Promise {
const args = plainToClass(GameFindManyArgs, request.query);
return this.service.findMany({
@@ -90,15 +94,17 @@ export class GameControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get("/:id")
+ @swagger.ApiOkResponse({ type: Game })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "Game",
action: "read",
possession: "own",
})
- @common.Get("/:id")
- @swagger.ApiOkResponse({ type: Game })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async findOne(
@common.Param() params: GameWhereUniqueInput
): Promise {
@@ -122,15 +128,17 @@ export class GameControllerBase {
}
@common.UseInterceptors(AclValidateRequestInterceptor)
+ @common.Patch("/:id")
+ @swagger.ApiOkResponse({ type: Game })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Patch("/:id")
- @swagger.ApiOkResponse({ type: Game })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async update(
@common.Param() params: GameWhereUniqueInput,
@common.Body() data: GameUpdateInput
@@ -158,15 +166,17 @@ export class GameControllerBase {
}
}
+ @common.Delete("/:id")
+ @swagger.ApiOkResponse({ type: Game })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "Game",
action: "delete",
possession: "any",
})
- @common.Delete("/:id")
- @swagger.ApiOkResponse({ type: Game })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async delete(
@common.Param() params: GameWhereUniqueInput
): Promise {
@@ -193,13 +203,13 @@ export class GameControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get("/:id/sessions")
+ @ApiNestedQuery(SessionFindManyArgs)
@nestAccessControl.UseRoles({
resource: "Session",
action: "read",
possession: "any",
})
- @common.Get("/:id/sessions")
- @ApiNestedQuery(SessionFindManyArgs)
async findManySessions(
@common.Req() request: Request,
@common.Param() params: GameWhereUniqueInput
@@ -235,12 +245,12 @@ export class GameControllerBase {
return results;
}
+ @common.Post("/:id/sessions")
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Post("/:id/sessions")
async connectSessions(
@common.Param() params: GameWhereUniqueInput,
@common.Body() body: SessionWhereUniqueInput[]
@@ -257,12 +267,12 @@ export class GameControllerBase {
});
}
+ @common.Patch("/:id/sessions")
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Patch("/:id/sessions")
async updateSessions(
@common.Param() params: GameWhereUniqueInput,
@common.Body() body: SessionWhereUniqueInput[]
@@ -279,12 +289,12 @@ export class GameControllerBase {
});
}
+ @common.Delete("/:id/sessions")
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Delete("/:id/sessions")
async disconnectSessions(
@common.Param() params: GameWhereUniqueInput,
@common.Body() body: SessionWhereUniqueInput[]
@@ -302,13 +312,13 @@ export class GameControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get("/:id/users")
+ @ApiNestedQuery(UserFindManyArgs)
@nestAccessControl.UseRoles({
resource: "User",
action: "read",
possession: "any",
})
- @common.Get("/:id/users")
- @ApiNestedQuery(UserFindManyArgs)
async findManyUsers(
@common.Req() request: Request,
@common.Param() params: GameWhereUniqueInput
@@ -334,12 +344,12 @@ export class GameControllerBase {
return results;
}
+ @common.Post("/:id/users")
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Post("/:id/users")
async connectUsers(
@common.Param() params: GameWhereUniqueInput,
@common.Body() body: UserWhereUniqueInput[]
@@ -356,12 +366,12 @@ export class GameControllerBase {
});
}
+ @common.Patch("/:id/users")
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Patch("/:id/users")
async updateUsers(
@common.Param() params: GameWhereUniqueInput,
@common.Body() body: UserWhereUniqueInput[]
@@ -378,12 +388,12 @@ export class GameControllerBase {
});
}
+ @common.Delete("/:id/users")
@nestAccessControl.UseRoles({
resource: "Game",
action: "update",
possession: "any",
})
- @common.Delete("/:id/users")
async disconnectUsers(
@common.Param() params: GameWhereUniqueInput,
@common.Body() body: UserWhereUniqueInput[]
diff --git a/packages/arcade/src/game/base/game.module.base.ts b/packages/arcade/src/game/base/game.module.base.ts
index a16ee0c..2736c2f 100644
--- a/packages/arcade/src/game/base/game.module.base.ts
+++ b/packages/arcade/src/game/base/game.module.base.ts
@@ -11,18 +11,10 @@ https://docs.amplication.com/how-to/custom-code
*/
import { Module, forwardRef } from "@nestjs/common";
import { MorganModule } from "nest-morgan";
-import { PrismaModule } from "nestjs-prisma";
import { ACLModule } from "../../auth/acl.module";
import { AuthModule } from "../../auth/auth.module";
-
@Module({
- imports: [
- ACLModule,
- forwardRef(() => AuthModule),
- MorganModule,
- PrismaModule,
- ],
-
- exports: [ACLModule, AuthModule, MorganModule, PrismaModule],
+ imports: [ACLModule, forwardRef(() => AuthModule), MorganModule],
+ exports: [ACLModule, AuthModule, MorganModule],
})
export class GameModuleBase {}
diff --git a/packages/arcade/src/game/base/game.service.base.ts b/packages/arcade/src/game/base/game.service.base.ts
index 99c4f95..97c9f21 100644
--- a/packages/arcade/src/game/base/game.service.base.ts
+++ b/packages/arcade/src/game/base/game.service.base.ts
@@ -9,7 +9,7 @@ https://docs.amplication.com/how-to/custom-code
------------------------------------------------------------------------------
*/
-import { PrismaService } from "nestjs-prisma";
+import { PrismaService } from "../../prisma/prisma.service";
import { Prisma, Game, Session, User } from "@prisma/client";
export class GameServiceBase {
diff --git a/packages/arcade/src/grants.json b/packages/arcade/src/grants.json
index 3dc6d14..fbec5e5 100644
--- a/packages/arcade/src/grants.json
+++ b/packages/arcade/src/grants.json
@@ -89,4 +89,4 @@
"action": "read:any",
"attributes": "*"
}
-]
\ No newline at end of file
+]
diff --git a/packages/arcade/src/health/base/health.service.base.ts b/packages/arcade/src/health/base/health.service.base.ts
index 0db85da..49a93a5 100644
--- a/packages/arcade/src/health/base/health.service.base.ts
+++ b/packages/arcade/src/health/base/health.service.base.ts
@@ -1,5 +1,5 @@
import { Injectable } from "@nestjs/common";
-import { PrismaService } from "nestjs-prisma";
+import { PrismaService } from "../../prisma/prisma.service";
@Injectable()
export class HealthServiceBase {
diff --git a/packages/arcade/src/prisma.util.spec.ts b/packages/arcade/src/prisma.util.spec.ts
new file mode 100644
index 0000000..0aa308e
--- /dev/null
+++ b/packages/arcade/src/prisma.util.spec.ts
@@ -0,0 +1,23 @@
+import {
+ isRecordNotFoundError,
+ PRISMA_QUERY_INTERPRETATION_ERROR,
+} from "./prisma.util";
+
+describe("isRecordNotFoundError", () => {
+ test("returns true for record not found error", () => {
+ expect(
+ isRecordNotFoundError(
+ Object.assign(
+ new Error(`Error occurred during query execution:
+ InterpretationError("Error for binding '0': RecordNotFound("Record to update not found.")")`),
+ {
+ code: PRISMA_QUERY_INTERPRETATION_ERROR,
+ }
+ )
+ )
+ ).toBe(true);
+ });
+ test("returns false for any other error", () => {
+ expect(isRecordNotFoundError(new Error())).toBe(false);
+ });
+});
diff --git a/packages/arcade/src/prisma/prisma.module.ts b/packages/arcade/src/prisma/prisma.module.ts
new file mode 100644
index 0000000..1edbf95
--- /dev/null
+++ b/packages/arcade/src/prisma/prisma.module.ts
@@ -0,0 +1,9 @@
+import { Global, Module } from "@nestjs/common";
+import { PrismaService } from "./prisma.service";
+
+@Global()
+@Module({
+ providers: [PrismaService],
+ exports: [PrismaService],
+})
+export class PrismaModule {}
diff --git a/packages/arcade/src/prisma/prisma.service.ts b/packages/arcade/src/prisma/prisma.service.ts
new file mode 100644
index 0000000..3fb4081
--- /dev/null
+++ b/packages/arcade/src/prisma/prisma.service.ts
@@ -0,0 +1,15 @@
+import { Injectable, OnModuleInit, INestApplication } from "@nestjs/common";
+import { PrismaClient } from "@prisma/client";
+
+@Injectable()
+export class PrismaService extends PrismaClient implements OnModuleInit {
+ async onModuleInit() {
+ await this.$connect();
+ }
+
+ async enableShutdownHooks(app: INestApplication) {
+ this.$on("beforeExit", async () => {
+ await app.close();
+ });
+ }
+}
diff --git a/packages/arcade/src/providers/secrets/base/secretsManager.service.base.spec.ts b/packages/arcade/src/providers/secrets/base/secretsManager.service.base.spec.ts
new file mode 100644
index 0000000..0b5a709
--- /dev/null
+++ b/packages/arcade/src/providers/secrets/base/secretsManager.service.base.spec.ts
@@ -0,0 +1,39 @@
+import { ConfigService } from "@nestjs/config";
+import { mock } from "jest-mock-extended";
+import { SecretsManagerServiceBase } from "./secretsManager.service.base";
+
+describe("Testing the secrets manager base class", () => {
+ const SECRET_KEY = "SECRET_KEY";
+ const SECRET_VALUE = "SECRET_VALUE";
+ const configService = mock();
+ const secretsManagerServiceBase = new SecretsManagerServiceBase(
+ configService
+ );
+ beforeEach(() => {
+ configService.get.mockClear();
+ });
+ it("should return value from env", async () => {
+ //ARRANGE
+ configService.get.mockReturnValue(SECRET_VALUE);
+ //ACT
+ const result = await secretsManagerServiceBase.getSecret(SECRET_KEY);
+ //ASSERT
+ expect(result).toBe(SECRET_VALUE);
+ });
+ it("should return null for unknown keys", async () => {
+ //ARRANGE
+ configService.get.mockReturnValue(undefined);
+ //ACT
+ const result = await secretsManagerServiceBase.getSecret(SECRET_KEY);
+ //ASSERT
+ expect(result).toBeNull();
+ });
+ it("should throw error if dont get key", () => {
+ //@ts-ignore
+ return expect(secretsManagerServiceBase.getSecret()).rejects.toThrow();
+ });
+ it("should throw an exeption if getting null key", () => {
+ //@ts-ignore
+ return expect(secretsManagerServiceBase.getSecret(null)).rejects.toThrow();
+ });
+});
diff --git a/packages/arcade/src/session/base/CreateSessionArgs.ts b/packages/arcade/src/session/base/CreateSessionArgs.ts
index 0b5e4aa..c665905 100644
--- a/packages/arcade/src/session/base/CreateSessionArgs.ts
+++ b/packages/arcade/src/session/base/CreateSessionArgs.ts
@@ -18,4 +18,4 @@ class CreateSessionArgs {
data!: SessionCreateInput;
}
-export { CreateSessionArgs };
+export { CreateSessionArgs as CreateSessionArgs };
diff --git a/packages/arcade/src/session/base/DeleteSessionArgs.ts b/packages/arcade/src/session/base/DeleteSessionArgs.ts
index 5274fe8..309e7bd 100644
--- a/packages/arcade/src/session/base/DeleteSessionArgs.ts
+++ b/packages/arcade/src/session/base/DeleteSessionArgs.ts
@@ -18,4 +18,4 @@ class DeleteSessionArgs {
where!: SessionWhereUniqueInput;
}
-export { DeleteSessionArgs };
+export { DeleteSessionArgs as DeleteSessionArgs };
diff --git a/packages/arcade/src/session/base/Session.ts b/packages/arcade/src/session/base/Session.ts
index 595130c..1dff541 100644
--- a/packages/arcade/src/session/base/Session.ts
+++ b/packages/arcade/src/session/base/Session.ts
@@ -15,6 +15,7 @@ import { IsDate, IsOptional, ValidateNested, IsString } from "class-validator";
import { Type } from "class-transformer";
import { Game } from "../../game/base/Game";
import { User } from "../../user/base/User";
+
@ObjectType()
class Session {
@ApiProperty({
@@ -70,4 +71,5 @@ class Session {
@IsOptional()
user?: User | null;
}
-export { Session };
+
+export { Session as Session };
diff --git a/packages/arcade/src/session/base/SessionCreateInput.ts b/packages/arcade/src/session/base/SessionCreateInput.ts
index b2cf08a..fde834e 100644
--- a/packages/arcade/src/session/base/SessionCreateInput.ts
+++ b/packages/arcade/src/session/base/SessionCreateInput.ts
@@ -15,6 +15,7 @@ import { IsDate, IsOptional, ValidateNested } from "class-validator";
import { Type } from "class-transformer";
import { GameWhereUniqueInput } from "../../game/base/GameWhereUniqueInput";
import { UserWhereUniqueInput } from "../../user/base/UserWhereUniqueInput";
+
@InputType()
class SessionCreateInput {
@ApiProperty({
@@ -52,4 +53,5 @@ class SessionCreateInput {
})
user?: UserWhereUniqueInput | null;
}
-export { SessionCreateInput };
+
+export { SessionCreateInput as SessionCreateInput };
diff --git a/packages/arcade/src/session/base/SessionFindManyArgs.ts b/packages/arcade/src/session/base/SessionFindManyArgs.ts
index e295d56..a0e26ef 100644
--- a/packages/arcade/src/session/base/SessionFindManyArgs.ts
+++ b/packages/arcade/src/session/base/SessionFindManyArgs.ts
@@ -50,4 +50,4 @@ class SessionFindManyArgs {
take?: number;
}
-export { SessionFindManyArgs };
+export { SessionFindManyArgs as SessionFindManyArgs };
diff --git a/packages/arcade/src/session/base/SessionFindUniqueArgs.ts b/packages/arcade/src/session/base/SessionFindUniqueArgs.ts
index b616f8b..577b58f 100644
--- a/packages/arcade/src/session/base/SessionFindUniqueArgs.ts
+++ b/packages/arcade/src/session/base/SessionFindUniqueArgs.ts
@@ -18,4 +18,4 @@ class SessionFindUniqueArgs {
where!: SessionWhereUniqueInput;
}
-export { SessionFindUniqueArgs };
+export { SessionFindUniqueArgs as SessionFindUniqueArgs };
diff --git a/packages/arcade/src/session/base/SessionListRelationFilter.ts b/packages/arcade/src/session/base/SessionListRelationFilter.ts
index be24231..64dbed8 100644
--- a/packages/arcade/src/session/base/SessionListRelationFilter.ts
+++ b/packages/arcade/src/session/base/SessionListRelationFilter.ts
@@ -53,4 +53,4 @@ class SessionListRelationFilter {
})
none?: SessionWhereInput;
}
-export { SessionListRelationFilter };
+export { SessionListRelationFilter as SessionListRelationFilter };
diff --git a/packages/arcade/src/session/base/SessionOrderByInput.ts b/packages/arcade/src/session/base/SessionOrderByInput.ts
index 4a5a339..7ee9345 100644
--- a/packages/arcade/src/session/base/SessionOrderByInput.ts
+++ b/packages/arcade/src/session/base/SessionOrderByInput.ts
@@ -73,4 +73,4 @@ class SessionOrderByInput {
userId?: SortOrder;
}
-export { SessionOrderByInput };
+export { SessionOrderByInput as SessionOrderByInput };
diff --git a/packages/arcade/src/session/base/SessionUpdateInput.ts b/packages/arcade/src/session/base/SessionUpdateInput.ts
index b7122bd..2d342b5 100644
--- a/packages/arcade/src/session/base/SessionUpdateInput.ts
+++ b/packages/arcade/src/session/base/SessionUpdateInput.ts
@@ -15,6 +15,7 @@ import { IsDate, IsOptional, ValidateNested } from "class-validator";
import { Type } from "class-transformer";
import { GameWhereUniqueInput } from "../../game/base/GameWhereUniqueInput";
import { UserWhereUniqueInput } from "../../user/base/UserWhereUniqueInput";
+
@InputType()
class SessionUpdateInput {
@ApiProperty({
@@ -52,4 +53,5 @@ class SessionUpdateInput {
})
user?: UserWhereUniqueInput | null;
}
-export { SessionUpdateInput };
+
+export { SessionUpdateInput as SessionUpdateInput };
diff --git a/packages/arcade/src/session/base/SessionWhereInput.ts b/packages/arcade/src/session/base/SessionWhereInput.ts
index e54da3b..f097f4f 100644
--- a/packages/arcade/src/session/base/SessionWhereInput.ts
+++ b/packages/arcade/src/session/base/SessionWhereInput.ts
@@ -17,6 +17,7 @@ import { IsOptional, ValidateNested } from "class-validator";
import { GameWhereUniqueInput } from "../../game/base/GameWhereUniqueInput";
import { StringFilter } from "../../util/StringFilter";
import { UserWhereUniqueInput } from "../../user/base/UserWhereUniqueInput";
+
@InputType()
class SessionWhereInput {
@ApiProperty({
@@ -65,4 +66,5 @@ class SessionWhereInput {
})
user?: UserWhereUniqueInput;
}
-export { SessionWhereInput };
+
+export { SessionWhereInput as SessionWhereInput };
diff --git a/packages/arcade/src/session/base/SessionWhereUniqueInput.ts b/packages/arcade/src/session/base/SessionWhereUniqueInput.ts
index cd0d90c..b462221 100644
--- a/packages/arcade/src/session/base/SessionWhereUniqueInput.ts
+++ b/packages/arcade/src/session/base/SessionWhereUniqueInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
import { IsString } from "class-validator";
+
@InputType()
class SessionWhereUniqueInput {
@ApiProperty({
@@ -22,4 +23,5 @@ class SessionWhereUniqueInput {
@Field(() => String)
id!: string;
}
-export { SessionWhereUniqueInput };
+
+export { SessionWhereUniqueInput as SessionWhereUniqueInput };
diff --git a/packages/arcade/src/session/base/UpdateSessionArgs.ts b/packages/arcade/src/session/base/UpdateSessionArgs.ts
index a949e95..c9222cf 100644
--- a/packages/arcade/src/session/base/UpdateSessionArgs.ts
+++ b/packages/arcade/src/session/base/UpdateSessionArgs.ts
@@ -21,4 +21,4 @@ class UpdateSessionArgs {
data!: SessionUpdateInput;
}
-export { UpdateSessionArgs };
+export { UpdateSessionArgs as UpdateSessionArgs };
diff --git a/packages/arcade/src/session/base/session.controller.base.ts b/packages/arcade/src/session/base/session.controller.base.ts
index 978dee3..7d0181a 100644
--- a/packages/arcade/src/session/base/session.controller.base.ts
+++ b/packages/arcade/src/session/base/session.controller.base.ts
@@ -11,13 +11,13 @@ https://docs.amplication.com/how-to/custom-code
*/
import * as common from "@nestjs/common";
import * as swagger from "@nestjs/swagger";
-import * as nestAccessControl from "nest-access-control";
-import * as defaultAuthGuard from "../../auth/defaultAuth.guard";
import { isRecordNotFoundError } from "../../prisma.util";
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";
@@ -27,6 +27,7 @@ import { SessionWhereUniqueInput } from "./SessionWhereUniqueInput";
import { SessionFindManyArgs } from "./SessionFindManyArgs";
import { SessionUpdateInput } from "./SessionUpdateInput";
import { Session } from "./Session";
+
@swagger.ApiBearerAuth()
@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard)
export class SessionControllerBase {
@@ -34,16 +35,17 @@ export class SessionControllerBase {
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",
})
- @common.Post()
- @swagger.ApiCreatedResponse({ type: Session })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async create(@common.Body() data: SessionCreateInput): Promise {
return await this.service.create({
data: {
@@ -84,15 +86,17 @@ export class SessionControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get()
+ @swagger.ApiOkResponse({ type: [Session] })
+ @ApiNestedQuery(SessionFindManyArgs)
@nestAccessControl.UseRoles({
resource: "Session",
action: "read",
possession: "any",
})
- @common.Get()
- @swagger.ApiOkResponse({ type: [Session] })
- @swagger.ApiForbiddenResponse()
- @ApiNestedQuery(SessionFindManyArgs)
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async findMany(@common.Req() request: Request): Promise {
const args = plainToClass(SessionFindManyArgs, request.query);
return this.service.findMany({
@@ -120,15 +124,17 @@ 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",
})
- @common.Get("/:id")
- @swagger.ApiOkResponse({ type: Session })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async findOne(
@common.Param() params: SessionWhereUniqueInput
): Promise {
@@ -163,15 +169,17 @@ export class SessionControllerBase {
}
@common.UseInterceptors(AclValidateRequestInterceptor)
+ @common.Patch("/:id")
+ @swagger.ApiOkResponse({ type: Session })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "Session",
action: "update",
possession: "any",
})
- @common.Patch("/:id")
- @swagger.ApiOkResponse({ type: Session })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async update(
@common.Param() params: SessionWhereUniqueInput,
@common.Body() data: SessionUpdateInput
@@ -224,15 +232,17 @@ export class SessionControllerBase {
}
}
+ @common.Delete("/:id")
+ @swagger.ApiOkResponse({ type: Session })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "Session",
action: "delete",
possession: "any",
})
- @common.Delete("/:id")
- @swagger.ApiOkResponse({ type: Session })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async delete(
@common.Param() params: SessionWhereUniqueInput
): Promise {
diff --git a/packages/arcade/src/session/base/session.module.base.ts b/packages/arcade/src/session/base/session.module.base.ts
index dc82208..3047b58 100644
--- a/packages/arcade/src/session/base/session.module.base.ts
+++ b/packages/arcade/src/session/base/session.module.base.ts
@@ -11,18 +11,10 @@ https://docs.amplication.com/how-to/custom-code
*/
import { Module, forwardRef } from "@nestjs/common";
import { MorganModule } from "nest-morgan";
-import { PrismaModule } from "nestjs-prisma";
import { ACLModule } from "../../auth/acl.module";
import { AuthModule } from "../../auth/auth.module";
-
@Module({
- imports: [
- ACLModule,
- forwardRef(() => AuthModule),
- MorganModule,
- PrismaModule,
- ],
-
- exports: [ACLModule, AuthModule, MorganModule, PrismaModule],
+ imports: [ACLModule, forwardRef(() => AuthModule), MorganModule],
+ exports: [ACLModule, AuthModule, MorganModule],
})
export class SessionModuleBase {}
diff --git a/packages/arcade/src/session/base/session.service.base.ts b/packages/arcade/src/session/base/session.service.base.ts
index 4e67a00..b04a282 100644
--- a/packages/arcade/src/session/base/session.service.base.ts
+++ b/packages/arcade/src/session/base/session.service.base.ts
@@ -9,7 +9,7 @@ https://docs.amplication.com/how-to/custom-code
------------------------------------------------------------------------------
*/
-import { PrismaService } from "nestjs-prisma";
+import { PrismaService } from "../../prisma/prisma.service";
import { Prisma, Session, Game, User } from "@prisma/client";
export class SessionServiceBase {
diff --git a/packages/arcade/src/swagger.ts b/packages/arcade/src/swagger.ts
index db3199c..e1ced32 100644
--- a/packages/arcade/src/swagger.ts
+++ b/packages/arcade/src/swagger.ts
@@ -7,7 +7,7 @@ export const swaggerDocumentOptions = new DocumentBuilder()
.setDescription(
'\n\n## Congratulations! Your service resource is ready.\n \nPlease note that all endpoints are secured with JWT Bearer authentication.\nBy default, your service resource comes with one user with the username "admin" and password "admin".\nLearn more in [our docs](https://docs.amplication.com)'
)
- .setVersion("jro00nvp")
+ .setVersion("5gsfs2xq")
.addBearerAuth()
.build();
diff --git a/packages/arcade/src/tests/health/health.service.spec.ts b/packages/arcade/src/tests/health/health.service.spec.ts
new file mode 100644
index 0000000..f7cd00b
--- /dev/null
+++ b/packages/arcade/src/tests/health/health.service.spec.ts
@@ -0,0 +1,36 @@
+import { mock } from "jest-mock-extended";
+import { PrismaService } from "nestjs-prisma";
+import { HealthServiceBase } from "../../health/base/health.service.base";
+
+describe("Testing the HealthServiceBase", () => {
+ //ARRANGE
+ let prismaService: PrismaService;
+ let healthServiceBase: HealthServiceBase;
+
+ describe("Testing the isDbReady function in HealthServiceBase class", () => {
+ beforeEach(() => {
+ prismaService = mock();
+ healthServiceBase = new HealthServiceBase(prismaService);
+ });
+ it("should return true if allow connection to db", async () => {
+ //ARRANGE
+ prismaService.$queryRaw
+ //@ts-ignore
+ .mockReturnValue(Promise.resolve(true));
+ //ACT
+ const response = await healthServiceBase.isDbReady();
+ //ASSERT
+ expect(response).toBe(true);
+ });
+ it("should return false if db is not available", async () => {
+ //ARRANGE
+ prismaService.$queryRaw
+ //@ts-ignore
+ .mockReturnValue(Promise.reject(false));
+ //ACT
+ const response = await healthServiceBase.isDbReady();
+ //ASSERT
+ expect(response).toBe(false);
+ });
+ });
+});
diff --git a/packages/arcade/src/types.ts b/packages/arcade/src/types.ts
index 16a8bd9..f762a5d 100644
--- a/packages/arcade/src/types.ts
+++ b/packages/arcade/src/types.ts
@@ -1,3 +1,3 @@
-import { JsonValue } from "type-fest";
+import type { JsonValue } from "type-fest";
export type InputJsonValue = Omit;
diff --git a/packages/arcade/src/user/base/CreateUserArgs.ts b/packages/arcade/src/user/base/CreateUserArgs.ts
index 4a1e644..24817ac 100644
--- a/packages/arcade/src/user/base/CreateUserArgs.ts
+++ b/packages/arcade/src/user/base/CreateUserArgs.ts
@@ -18,4 +18,4 @@ class CreateUserArgs {
data!: UserCreateInput;
}
-export { CreateUserArgs };
+export { CreateUserArgs as CreateUserArgs };
diff --git a/packages/arcade/src/user/base/DeleteUserArgs.ts b/packages/arcade/src/user/base/DeleteUserArgs.ts
index ec845b0..3649def 100644
--- a/packages/arcade/src/user/base/DeleteUserArgs.ts
+++ b/packages/arcade/src/user/base/DeleteUserArgs.ts
@@ -18,4 +18,4 @@ class DeleteUserArgs {
where!: UserWhereUniqueInput;
}
-export { DeleteUserArgs };
+export { DeleteUserArgs as DeleteUserArgs };
diff --git a/packages/arcade/src/user/base/GameCreateNestedManyWithoutUsersInput.ts b/packages/arcade/src/user/base/GameCreateNestedManyWithoutUsersInput.ts
index b41d71e..aea3f7b 100644
--- a/packages/arcade/src/user/base/GameCreateNestedManyWithoutUsersInput.ts
+++ b/packages/arcade/src/user/base/GameCreateNestedManyWithoutUsersInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { GameWhereUniqueInput } from "../../game/base/GameWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class GameCreateNestedManyWithoutUsersInput {
@Field(() => [GameWhereUniqueInput], {
@@ -23,4 +24,5 @@ class GameCreateNestedManyWithoutUsersInput {
})
connect?: Array;
}
-export { GameCreateNestedManyWithoutUsersInput };
+
+export { GameCreateNestedManyWithoutUsersInput as GameCreateNestedManyWithoutUsersInput };
diff --git a/packages/arcade/src/user/base/GameUpdateManyWithoutUsersInput.ts b/packages/arcade/src/user/base/GameUpdateManyWithoutUsersInput.ts
index 498d06a..726b39d 100644
--- a/packages/arcade/src/user/base/GameUpdateManyWithoutUsersInput.ts
+++ b/packages/arcade/src/user/base/GameUpdateManyWithoutUsersInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { GameWhereUniqueInput } from "../../game/base/GameWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class GameUpdateManyWithoutUsersInput {
@Field(() => [GameWhereUniqueInput], {
@@ -41,4 +42,5 @@ class GameUpdateManyWithoutUsersInput {
})
set?: Array;
}
-export { GameUpdateManyWithoutUsersInput };
+
+export { GameUpdateManyWithoutUsersInput as GameUpdateManyWithoutUsersInput };
diff --git a/packages/arcade/src/user/base/SessionCreateNestedManyWithoutUsersInput.ts b/packages/arcade/src/user/base/SessionCreateNestedManyWithoutUsersInput.ts
index 1a5adec..140201a 100644
--- a/packages/arcade/src/user/base/SessionCreateNestedManyWithoutUsersInput.ts
+++ b/packages/arcade/src/user/base/SessionCreateNestedManyWithoutUsersInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { SessionWhereUniqueInput } from "../../session/base/SessionWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class SessionCreateNestedManyWithoutUsersInput {
@Field(() => [SessionWhereUniqueInput], {
@@ -23,4 +24,5 @@ class SessionCreateNestedManyWithoutUsersInput {
})
connect?: Array;
}
-export { SessionCreateNestedManyWithoutUsersInput };
+
+export { SessionCreateNestedManyWithoutUsersInput as SessionCreateNestedManyWithoutUsersInput };
diff --git a/packages/arcade/src/user/base/SessionUpdateManyWithoutUsersInput.ts b/packages/arcade/src/user/base/SessionUpdateManyWithoutUsersInput.ts
index a3da5f5..afbe78c 100644
--- a/packages/arcade/src/user/base/SessionUpdateManyWithoutUsersInput.ts
+++ b/packages/arcade/src/user/base/SessionUpdateManyWithoutUsersInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { SessionWhereUniqueInput } from "../../session/base/SessionWhereUniqueInput";
import { ApiProperty } from "@nestjs/swagger";
+
@InputType()
class SessionUpdateManyWithoutUsersInput {
@Field(() => [SessionWhereUniqueInput], {
@@ -41,4 +42,5 @@ class SessionUpdateManyWithoutUsersInput {
})
set?: Array;
}
-export { SessionUpdateManyWithoutUsersInput };
+
+export { SessionUpdateManyWithoutUsersInput as SessionUpdateManyWithoutUsersInput };
diff --git a/packages/arcade/src/user/base/UpdateUserArgs.ts b/packages/arcade/src/user/base/UpdateUserArgs.ts
index d2f133f..342f128 100644
--- a/packages/arcade/src/user/base/UpdateUserArgs.ts
+++ b/packages/arcade/src/user/base/UpdateUserArgs.ts
@@ -21,4 +21,4 @@ class UpdateUserArgs {
data!: UserUpdateInput;
}
-export { UpdateUserArgs };
+export { UpdateUserArgs as UpdateUserArgs };
diff --git a/packages/arcade/src/user/base/User.ts b/packages/arcade/src/user/base/User.ts
index ac6151c..bd7a42c 100644
--- a/packages/arcade/src/user/base/User.ts
+++ b/packages/arcade/src/user/base/User.ts
@@ -11,18 +11,14 @@ https://docs.amplication.com/how-to/custom-code
*/
import { ObjectType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
-import {
- IsDate,
- IsString,
- IsOptional,
- ValidateNested,
- IsJSON,
-} from "class-validator";
+import { IsDate, IsString, IsOptional, ValidateNested } from "class-validator";
import { Type } from "class-transformer";
import { Game } from "../../game/base/Game";
+import { IsJSONValue } from "@app/custom-validators";
import { GraphQLJSON } from "graphql-type-json";
import { JsonValue } from "type-fest";
import { Session } from "../../session/base/Session";
+
@ObjectType()
class User {
@ApiProperty({
@@ -75,7 +71,7 @@ class User {
@ApiProperty({
required: true,
})
- @IsJSON()
+ @IsJSONValue()
@Field(() => GraphQLJSON)
roles!: JsonValue;
@@ -104,4 +100,5 @@ class User {
@Field(() => String)
username!: string;
}
-export { User };
+
+export { User as User };
diff --git a/packages/arcade/src/user/base/UserCreateInput.ts b/packages/arcade/src/user/base/UserCreateInput.ts
index f825699..4401024 100644
--- a/packages/arcade/src/user/base/UserCreateInput.ts
+++ b/packages/arcade/src/user/base/UserCreateInput.ts
@@ -11,12 +11,14 @@ https://docs.amplication.com/how-to/custom-code
*/
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
-import { IsString, IsOptional, ValidateNested, IsJSON } from "class-validator";
+import { IsString, IsOptional, ValidateNested } from "class-validator";
import { GameCreateNestedManyWithoutUsersInput } from "./GameCreateNestedManyWithoutUsersInput";
import { Type } from "class-transformer";
+import { IsJSONValue } from "@app/custom-validators";
import { GraphQLJSON } from "graphql-type-json";
import { InputJsonValue } from "../../types";
import { SessionCreateNestedManyWithoutUsersInput } from "./SessionCreateNestedManyWithoutUsersInput";
+
@InputType()
class UserCreateInput {
@ApiProperty({
@@ -64,7 +66,7 @@ class UserCreateInput {
@ApiProperty({
required: true,
})
- @IsJSON()
+ @IsJSONValue()
@Field(() => GraphQLJSON)
roles!: InputJsonValue;
@@ -88,4 +90,5 @@ class UserCreateInput {
@Field(() => String)
username!: string;
}
-export { UserCreateInput };
+
+export { UserCreateInput as UserCreateInput };
diff --git a/packages/arcade/src/user/base/UserFindManyArgs.ts b/packages/arcade/src/user/base/UserFindManyArgs.ts
index 07ffdab..11525da 100644
--- a/packages/arcade/src/user/base/UserFindManyArgs.ts
+++ b/packages/arcade/src/user/base/UserFindManyArgs.ts
@@ -50,4 +50,4 @@ class UserFindManyArgs {
take?: number;
}
-export { UserFindManyArgs };
+export { UserFindManyArgs as UserFindManyArgs };
diff --git a/packages/arcade/src/user/base/UserFindUniqueArgs.ts b/packages/arcade/src/user/base/UserFindUniqueArgs.ts
index 3767539..b7810d2 100644
--- a/packages/arcade/src/user/base/UserFindUniqueArgs.ts
+++ b/packages/arcade/src/user/base/UserFindUniqueArgs.ts
@@ -18,4 +18,4 @@ class UserFindUniqueArgs {
where!: UserWhereUniqueInput;
}
-export { UserFindUniqueArgs };
+export { UserFindUniqueArgs as UserFindUniqueArgs };
diff --git a/packages/arcade/src/user/base/UserListRelationFilter.ts b/packages/arcade/src/user/base/UserListRelationFilter.ts
index 4c57721..0ff7d94 100644
--- a/packages/arcade/src/user/base/UserListRelationFilter.ts
+++ b/packages/arcade/src/user/base/UserListRelationFilter.ts
@@ -53,4 +53,4 @@ class UserListRelationFilter {
})
none?: UserWhereInput;
}
-export { UserListRelationFilter };
+export { UserListRelationFilter as UserListRelationFilter };
diff --git a/packages/arcade/src/user/base/UserOrderByInput.ts b/packages/arcade/src/user/base/UserOrderByInput.ts
index 07baa8d..849a0c3 100644
--- a/packages/arcade/src/user/base/UserOrderByInput.ts
+++ b/packages/arcade/src/user/base/UserOrderByInput.ts
@@ -91,4 +91,4 @@ class UserOrderByInput {
username?: SortOrder;
}
-export { UserOrderByInput };
+export { UserOrderByInput as UserOrderByInput };
diff --git a/packages/arcade/src/user/base/UserUpdateInput.ts b/packages/arcade/src/user/base/UserUpdateInput.ts
index 48c82b6..38ff4f9 100644
--- a/packages/arcade/src/user/base/UserUpdateInput.ts
+++ b/packages/arcade/src/user/base/UserUpdateInput.ts
@@ -11,12 +11,14 @@ https://docs.amplication.com/how-to/custom-code
*/
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
-import { IsString, IsOptional, ValidateNested, IsJSON } from "class-validator";
+import { IsString, IsOptional, ValidateNested } from "class-validator";
import { GameUpdateManyWithoutUsersInput } from "./GameUpdateManyWithoutUsersInput";
import { Type } from "class-transformer";
+import { IsJSONValue } from "@app/custom-validators";
import { GraphQLJSON } from "graphql-type-json";
import { InputJsonValue } from "../../types";
import { SessionUpdateManyWithoutUsersInput } from "./SessionUpdateManyWithoutUsersInput";
+
@InputType()
class UserUpdateInput {
@ApiProperty({
@@ -67,7 +69,7 @@ class UserUpdateInput {
@ApiProperty({
required: false,
})
- @IsJSON()
+ @IsJSONValue()
@IsOptional()
@Field(() => GraphQLJSON, {
nullable: true,
@@ -97,4 +99,5 @@ class UserUpdateInput {
})
username?: string;
}
-export { UserUpdateInput };
+
+export { UserUpdateInput as UserUpdateInput };
diff --git a/packages/arcade/src/user/base/UserWhereInput.ts b/packages/arcade/src/user/base/UserWhereInput.ts
index 538ee42..a4e3cc5 100644
--- a/packages/arcade/src/user/base/UserWhereInput.ts
+++ b/packages/arcade/src/user/base/UserWhereInput.ts
@@ -17,6 +17,7 @@ import { IsOptional, ValidateNested } from "class-validator";
import { GameListRelationFilter } from "../../game/base/GameListRelationFilter";
import { StringFilter } from "../../util/StringFilter";
import { SessionListRelationFilter } from "../../session/base/SessionListRelationFilter";
+
@InputType()
class UserWhereInput {
@ApiProperty({
@@ -87,4 +88,5 @@ class UserWhereInput {
})
username?: StringFilter;
}
-export { UserWhereInput };
+
+export { UserWhereInput as UserWhereInput };
diff --git a/packages/arcade/src/user/base/UserWhereUniqueInput.ts b/packages/arcade/src/user/base/UserWhereUniqueInput.ts
index 648452d..0bcea12 100644
--- a/packages/arcade/src/user/base/UserWhereUniqueInput.ts
+++ b/packages/arcade/src/user/base/UserWhereUniqueInput.ts
@@ -12,6 +12,7 @@ https://docs.amplication.com/how-to/custom-code
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
import { IsString } from "class-validator";
+
@InputType()
class UserWhereUniqueInput {
@ApiProperty({
@@ -22,4 +23,5 @@ class UserWhereUniqueInput {
@Field(() => String)
id!: string;
}
-export { UserWhereUniqueInput };
+
+export { UserWhereUniqueInput as UserWhereUniqueInput };
diff --git a/packages/arcade/src/user/base/user.controller.base.ts b/packages/arcade/src/user/base/user.controller.base.ts
index 632717f..77e8b3d 100644
--- a/packages/arcade/src/user/base/user.controller.base.ts
+++ b/packages/arcade/src/user/base/user.controller.base.ts
@@ -11,13 +11,13 @@ https://docs.amplication.com/how-to/custom-code
*/
import * as common from "@nestjs/common";
import * as swagger from "@nestjs/swagger";
-import * as nestAccessControl from "nest-access-control";
-import * as defaultAuthGuard from "../../auth/defaultAuth.guard";
import { isRecordNotFoundError } from "../../prisma.util";
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";
@@ -33,6 +33,7 @@ import { GameWhereUniqueInput } from "../../game/base/GameWhereUniqueInput";
import { SessionFindManyArgs } from "../../session/base/SessionFindManyArgs";
import { Session } from "../../session/base/Session";
import { SessionWhereUniqueInput } from "../../session/base/SessionWhereUniqueInput";
+
@swagger.ApiBearerAuth()
@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard)
export class UserControllerBase {
@@ -40,16 +41,17 @@ export class UserControllerBase {
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",
})
- @common.Post()
- @swagger.ApiCreatedResponse({ type: User })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async create(@common.Body() data: UserCreateInput): Promise {
return await this.service.create({
data: data,
@@ -66,15 +68,17 @@ export class UserControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get()
+ @swagger.ApiOkResponse({ type: [User] })
+ @ApiNestedQuery(UserFindManyArgs)
@nestAccessControl.UseRoles({
resource: "User",
action: "read",
possession: "any",
})
- @common.Get()
- @swagger.ApiOkResponse({ type: [User] })
- @swagger.ApiForbiddenResponse()
- @ApiNestedQuery(UserFindManyArgs)
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async findMany(@common.Req() request: Request): Promise {
const args = plainToClass(UserFindManyArgs, request.query);
return this.service.findMany({
@@ -92,15 +96,17 @@ 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",
})
- @common.Get("/:id")
- @swagger.ApiOkResponse({ type: User })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async findOne(
@common.Param() params: UserWhereUniqueInput
): Promise {
@@ -125,15 +131,17 @@ export class UserControllerBase {
}
@common.UseInterceptors(AclValidateRequestInterceptor)
+ @common.Patch("/:id")
+ @swagger.ApiOkResponse({ type: User })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Patch("/:id")
- @swagger.ApiOkResponse({ type: User })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async update(
@common.Param() params: UserWhereUniqueInput,
@common.Body() data: UserUpdateInput
@@ -162,15 +170,17 @@ export class UserControllerBase {
}
}
+ @common.Delete("/:id")
+ @swagger.ApiOkResponse({ type: User })
+ @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
@nestAccessControl.UseRoles({
resource: "User",
action: "delete",
possession: "any",
})
- @common.Delete("/:id")
- @swagger.ApiOkResponse({ type: User })
- @swagger.ApiNotFoundResponse({ type: errors.NotFoundException })
- @swagger.ApiForbiddenResponse({ type: errors.ForbiddenException })
+ @swagger.ApiForbiddenResponse({
+ type: errors.ForbiddenException,
+ })
async delete(
@common.Param() params: UserWhereUniqueInput
): Promise {
@@ -198,13 +208,13 @@ export class UserControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get("/:id/game")
+ @ApiNestedQuery(GameFindManyArgs)
@nestAccessControl.UseRoles({
resource: "Game",
action: "read",
possession: "any",
})
- @common.Get("/:id/game")
- @ApiNestedQuery(GameFindManyArgs)
async findManyGame(
@common.Req() request: Request,
@common.Param() params: UserWhereUniqueInput
@@ -229,12 +239,12 @@ export class UserControllerBase {
return results;
}
+ @common.Post("/:id/game")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Post("/:id/game")
async connectGame(
@common.Param() params: UserWhereUniqueInput,
@common.Body() body: GameWhereUniqueInput[]
@@ -251,12 +261,12 @@ export class UserControllerBase {
});
}
+ @common.Patch("/:id/game")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Patch("/:id/game")
async updateGame(
@common.Param() params: UserWhereUniqueInput,
@common.Body() body: GameWhereUniqueInput[]
@@ -273,12 +283,12 @@ export class UserControllerBase {
});
}
+ @common.Delete("/:id/game")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Delete("/:id/game")
async disconnectGame(
@common.Param() params: UserWhereUniqueInput,
@common.Body() body: GameWhereUniqueInput[]
@@ -296,13 +306,13 @@ export class UserControllerBase {
}
@common.UseInterceptors(AclFilterResponseInterceptor)
+ @common.Get("/:id/sessions")
+ @ApiNestedQuery(SessionFindManyArgs)
@nestAccessControl.UseRoles({
resource: "Session",
action: "read",
possession: "any",
})
- @common.Get("/:id/sessions")
- @ApiNestedQuery(SessionFindManyArgs)
async findManySessions(
@common.Req() request: Request,
@common.Param() params: UserWhereUniqueInput
@@ -338,12 +348,12 @@ export class UserControllerBase {
return results;
}
+ @common.Post("/:id/sessions")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Post("/:id/sessions")
async connectSessions(
@common.Param() params: UserWhereUniqueInput,
@common.Body() body: SessionWhereUniqueInput[]
@@ -360,12 +370,12 @@ export class UserControllerBase {
});
}
+ @common.Patch("/:id/sessions")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Patch("/:id/sessions")
async updateSessions(
@common.Param() params: UserWhereUniqueInput,
@common.Body() body: SessionWhereUniqueInput[]
@@ -382,12 +392,12 @@ export class UserControllerBase {
});
}
+ @common.Delete("/:id/sessions")
@nestAccessControl.UseRoles({
resource: "User",
action: "update",
possession: "any",
})
- @common.Delete("/:id/sessions")
async disconnectSessions(
@common.Param() params: UserWhereUniqueInput,
@common.Body() body: SessionWhereUniqueInput[]
diff --git a/packages/arcade/src/user/base/user.module.base.ts b/packages/arcade/src/user/base/user.module.base.ts
index 6dc8244..76d29fe 100644
--- a/packages/arcade/src/user/base/user.module.base.ts
+++ b/packages/arcade/src/user/base/user.module.base.ts
@@ -11,18 +11,10 @@ https://docs.amplication.com/how-to/custom-code
*/
import { Module, forwardRef } from "@nestjs/common";
import { MorganModule } from "nest-morgan";
-import { PrismaModule } from "nestjs-prisma";
import { ACLModule } from "../../auth/acl.module";
import { AuthModule } from "../../auth/auth.module";
-
@Module({
- imports: [
- ACLModule,
- forwardRef(() => AuthModule),
- MorganModule,
- PrismaModule,
- ],
-
- exports: [ACLModule, AuthModule, MorganModule, PrismaModule],
+ imports: [ACLModule, forwardRef(() => AuthModule), MorganModule],
+ exports: [ACLModule, AuthModule, MorganModule],
})
export class UserModuleBase {}
diff --git a/packages/arcade/src/user/base/user.service.base.ts b/packages/arcade/src/user/base/user.service.base.ts
index 02a32f8..3baee31 100644
--- a/packages/arcade/src/user/base/user.service.base.ts
+++ b/packages/arcade/src/user/base/user.service.base.ts
@@ -9,7 +9,7 @@ https://docs.amplication.com/how-to/custom-code
------------------------------------------------------------------------------
*/
-import { PrismaService } from "nestjs-prisma";
+import { PrismaService } from "../../prisma/prisma.service";
import { Prisma, User, Game, Session } from "@prisma/client";
import { PasswordService } from "../../auth/password.service";
import { transformStringFieldUpdateInput } from "../../prisma.util";
diff --git a/packages/arcade/src/util/JsonNullableFilter.ts b/packages/arcade/src/util/JsonNullableFilter.ts
index 2750eaf..3381d52 100644
--- a/packages/arcade/src/util/JsonNullableFilter.ts
+++ b/packages/arcade/src/util/JsonNullableFilter.ts
@@ -1,4 +1,4 @@
-import { JsonValue } from "type-fest";
+import type { JsonValue } from "type-fest";
import { Field, InputType } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
import { IsOptional } from "class-validator";
diff --git a/packages/arcade/src/validators/index.ts b/packages/arcade/src/validators/index.ts
new file mode 100644
index 0000000..7f62d84
--- /dev/null
+++ b/packages/arcade/src/validators/index.ts
@@ -0,0 +1 @@
+export * from "./is-json-value-validator";
diff --git a/packages/arcade/src/validators/is-json-value-validator.spec.ts b/packages/arcade/src/validators/is-json-value-validator.spec.ts
new file mode 100644
index 0000000..5a77824
--- /dev/null
+++ b/packages/arcade/src/validators/is-json-value-validator.spec.ts
@@ -0,0 +1,44 @@
+import { validate, ValidationError } from "class-validator";
+import { IsJSONValue } from "./is-json-value-validator";
+
+class TestClass {
+ @IsJSONValue()
+ jsonProperty: unknown;
+}
+
+describe("IsJSONValue", () => {
+ it("should validate a valid JSON string", async () => {
+ const testObj = new TestClass();
+ testObj.jsonProperty = '{"name": "John", "age": 30}';
+ const errors: ValidationError[] = await validate(testObj);
+ expect(errors.length).toBe(0);
+ });
+
+ it("should not validate an invalid JSON string", async () => {
+ const testObj = new TestClass();
+ testObj.jsonProperty = '{name: "John", age: 30}';
+ const errors: ValidationError[] = await validate(testObj);
+ expect(errors.length).toBe(1);
+ });
+
+ it("should not validate an invalid JSON string", async () => {
+ const testObj = new TestClass();
+ testObj.jsonProperty = "John";
+ const errors: ValidationError[] = await validate(testObj);
+ expect(errors.length).toBe(1);
+ });
+
+ it("should validate a valid JSON object", async () => {
+ const testObj = new TestClass();
+ testObj.jsonProperty = { name: "John", age: 30 };
+ const errors: ValidationError[] = await validate(testObj);
+ expect(errors.length).toBe(0);
+ });
+
+ it("should validate a valid JSON array", async () => {
+ const testObj = new TestClass();
+ testObj.jsonProperty = ["John", "30"];
+ const errors: ValidationError[] = await validate(testObj);
+ expect(errors.length).toBe(0);
+ });
+});
diff --git a/packages/arcade/src/validators/is-json-value-validator.ts b/packages/arcade/src/validators/is-json-value-validator.ts
new file mode 100644
index 0000000..7b96b4a
--- /dev/null
+++ b/packages/arcade/src/validators/is-json-value-validator.ts
@@ -0,0 +1,29 @@
+import {
+ ValidationArguments,
+ registerDecorator,
+ ValidationOptions,
+} from "class-validator";
+import isJSONValidator from "validator/lib/isJSON";
+
+export function IsJSONValue(validationOptions?: ValidationOptions) {
+ return function (object: Object, propertyName: string) {
+ registerDecorator({
+ name: "IsJSONValue",
+ target: object.constructor,
+ propertyName: propertyName,
+ options: validationOptions,
+ validator: {
+ validate(value: any, args: ValidationArguments) {
+ if (typeof value === "string") {
+ return isJSONValidator(value);
+ }
+
+ return isJSONValidator(JSON.stringify(value));
+ },
+ defaultMessage(args: ValidationArguments): string {
+ return `${args.property} must be a valid json`;
+ },
+ },
+ });
+ };
+}
diff --git a/packages/arcade/tsconfig.json b/packages/arcade/tsconfig.json
index ff90c46..f084cf7 100644
--- a/packages/arcade/tsconfig.json
+++ b/packages/arcade/tsconfig.json
@@ -1,5 +1,6 @@
{
"compilerOptions": {
+ "baseUrl": "./",
"module": "commonjs",
"declaration": false,
"removeComments": true,
@@ -14,7 +15,10 @@
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"skipLibCheck": true,
- "strict": true
+ "strict": true,
+ "paths": {
+ "@app/custom-validators": ["src/validators"]
+ }
},
"include": ["src"]
}