diff --git a/apps/temporary-admin/Dockerfile b/apps/temporary-admin/Dockerfile
index 9c43e40..0911e21 100644
--- a/apps/temporary-admin/Dockerfile
+++ b/apps/temporary-admin/Dockerfile
@@ -44,7 +44,7 @@ RUN chown -R nginx:nginx /var/run/nginx.pid \
USER nginx
# expose a specific port on the docker container
-ENV PORT=80
+ENV PORT=3001
EXPOSE ${PORT}
# start the server using the previously build application
diff --git a/apps/temporary-admin/README.md b/apps/temporary-admin/README.md
index 715d898..cc7c387 100644
--- a/apps/temporary-admin/README.md
+++ b/apps/temporary-admin/README.md
@@ -1,12 +1,12 @@
-
+
# Introduction
-This service was generated with Amplication. It serves as the client-side for the generated server component. The client-side consist of a React application with ready-made forms for creating and editing the different data models of the application. It is pre-conffigured to work with the server and comes with the boilerplate and foundation for the client - i.e., routing, navigation, authentication, premissions, menu, breadcrumbs, error handling and much more. Additional information about the admin component and the architecture around it, can be found on the [documentation](https://docs.amplication.com/guides/getting-started) site. This side of the generated project was bootstrapped with [create-react-app](https://github.com/facebook/create-react-app) and built with [react-admin](https://marmelab.com/react-admin/).
+This service was generated with Amplication. It serves as the client-side for the generated server component. The client-side consist of a React application with ready-made forms for creating and editing the different data models of the application. It is pre-conffigured to work with the server and comes with the boilerplate and foundation for the client - i.e., routing, navigation, authentication, permissions, menu, breadcrumbs, error handling and much more. Additional information about the admin component and the architecture around it, can be found on the [documentation](https://docs.amplication.com/guides/getting-started) site. This side of the generated project was bootstrapped with [create-react-app](https://github.com/facebook/create-react-app) and built with [react-admin](https://marmelab.com/react-admin/).
diff --git a/apps/temporary-admin/configuration/nginx.conf b/apps/temporary-admin/configuration/nginx.conf
index 88dad6e..c907b5c 100644
--- a/apps/temporary-admin/configuration/nginx.conf
+++ b/apps/temporary-admin/configuration/nginx.conf
@@ -1,7 +1,7 @@
server_tokens off;
server {
- listen 8080;
+ listen 3001;
server_name localhost;
location / {
root /usr/share/nginx/html;
diff --git a/apps/temporary-admin/src/index.tsx b/apps/temporary-admin/src/index.tsx
index 5e2de69..2da129c 100644
--- a/apps/temporary-admin/src/index.tsx
+++ b/apps/temporary-admin/src/index.tsx
@@ -1,8 +1,7 @@
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
-// @ts-ignore
-// eslint-disable-next-line import/no-unresolved
+
import App from "./App";
import reportWebVitals from "./reportWebVitals";
diff --git a/apps/temporary-admin/src/user/RolesOptions.ts b/apps/temporary-admin/src/user/RolesOptions.ts
index 2f12fcf..5e30fe9 100644
--- a/apps/temporary-admin/src/user/RolesOptions.ts
+++ b/apps/temporary-admin/src/user/RolesOptions.ts
@@ -1,4 +1,3 @@
-//@ts-ignore
import { ROLES } from "./roles";
declare interface Role {
diff --git a/apps/temporary/.env b/apps/temporary/.env
index 04605cd..f7678fa 100644
--- a/apps/temporary/.env
+++ b/apps/temporary/.env
@@ -1,10 +1,10 @@
BCRYPT_SALT=10
COMPOSE_PROJECT_NAME=amp_clmypp40t05ojm801iwsykclg
-PORT=3000
-DB_URL=postgres://admin:admin@localhost:5432/my-db
-DB_USER=admin
+DB_NAME=my-db
DB_PASSWORD=admin
DB_PORT=5432
-DB_NAME=my-db
+DB_URL=postgres://admin:admin@localhost:5432/my-db
+DB_USER=admin
+JWT_EXPIRATION=2d
JWT_SECRET_KEY=Change_ME!!!
-JWT_EXPIRATION=2d
\ No newline at end of file
+PORT=3000
\ No newline at end of file
diff --git a/apps/temporary/README.md b/apps/temporary/README.md
index 6db8e75..bca0445 100644
--- a/apps/temporary/README.md
+++ b/apps/temporary/README.md
@@ -1,6 +1,6 @@
-
+
diff --git a/apps/temporary/docker-compose.yml b/apps/temporary/docker-compose.yml
index 6b231f2..2a466f3 100644
--- a/apps/temporary/docker-compose.yml
+++ b/apps/temporary/docker-compose.yml
@@ -14,6 +14,7 @@ services:
DB_URL: postgres://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
depends_on:
- migrate
+ restart: on-failure
migrate:
build:
context: .
diff --git a/apps/temporary/nest-cli.json b/apps/temporary/nest-cli.json
index fe51713..b7b60ae 100644
--- a/apps/temporary/nest-cli.json
+++ b/apps/temporary/nest-cli.json
@@ -1,6 +1,10 @@
{
"sourceRoot": "src",
"compilerOptions": {
- "assets": ["swagger"]
+ "assets": [
+ {
+ "include": "swagger/**/*"
+ }
+ ]
}
}
diff --git a/apps/temporary/package.json b/apps/temporary/package.json
index 5d54604..e768e95 100644
--- a/apps/temporary/package.json
+++ b/apps/temporary/package.json
@@ -10,7 +10,7 @@
"seed": "ts-node scripts/seed.ts",
"db:migrate-save": "prisma migrate dev",
"db:migrate-up": "prisma migrate deploy",
- "db:clean": "ts-node scripts/clean.ts",
+ "db:clean": "prisma migrate reset",
"db:init": "run-s \"db:migrate-save -- --name 'initial version'\" db:migrate-up seed",
"prisma:generate": "prisma generate",
"docker:dev": "docker-compose -f docker-compose.dev.yml up -d",
@@ -19,57 +19,59 @@
"compose:down": "docker-compose down --volumes"
},
"dependencies": {
- "@nestjs/common": "8.4.7",
- "@nestjs/config": "1.1.5",
- "@nestjs/core": "8.4.7",
- "@nestjs/graphql": "9.1.2",
- "@nestjs/platform-express": "8.4.7",
- "@nestjs/serve-static": "2.2.2",
- "@nestjs/swagger": "5.1.5",
+ "@apollo/server": "^4.9.4",
+ "@nestjs/apollo": "12.0.9",
+ "@nestjs/common": "10.2.7",
+ "@nestjs/config": "3.1.1",
+ "@nestjs/core": "10.2.7",
+ "@nestjs/graphql": "12.0.9",
+ "@nestjs/jwt": "^10.1.1",
+ "@nestjs/passport": "^10.0.2",
+ "@nestjs/platform-express": "10.2.7",
+ "@nestjs/serve-static": "4.0.0",
+ "@nestjs/swagger": "7.1.13",
+ "@prisma/client": "^5.4.2",
"@types/bcrypt": "5.0.0",
- "@prisma/client": "4.6.1",
- "apollo-server-express": "3.6.1",
- "bcrypt": "5.0.1",
+ "bcrypt": "5.1.1",
"class-transformer": "0.5.1",
"class-validator": "0.14.0",
- "dotenv": "^16.1.4",
- "graphql": "15.7.2",
+ "dotenv": "16.3.1",
+ "graphql": "^16.8.1",
"graphql-type-json": "0.3.2",
- "nest-access-control": "2.0.3",
- "nest-morgan": "1.0.1",
+ "nest-access-control": "^3.1.0",
"npm-run-all": "4.1.5",
- "reflect-metadata": "0.1.13",
- "swagger-ui-express": "4.3.0",
- "ts-node": "10.9.1",
- "type-fest": "0.13.1",
- "validator": "^13.9.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"
+ "passport-jwt": "4.0.1",
+ "reflect-metadata": "0.1.13",
+ "ts-node": "10.9.2",
+ "type-fest": "2.19.0",
+ "validator": "13.11.0"
},
"devDependencies": {
- "@nestjs/cli": "8.2.5",
- "@nestjs/testing": "8.4.7",
- "@types/express": "4.17.9",
- "@types/graphql-type-json": "0.3.2",
- "@types/jest": "26.0.19",
+ "@nestjs/cli": "^10.1.18",
+ "@nestjs/testing": "^10.2.7",
+ "@types/express": "^4.17.19",
+ "@types/graphql-type-json": "0.3.3",
+ "@types/jest": "^29.5.5",
"@types/normalize-path": "3.0.0",
- "@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",
- "typescript": "4.3.5",
"@types/passport-http": "0.3.9",
- "@types/passport-jwt": "3.0.8"
+ "@types/passport-jwt": "3.0.10",
+ "@types/supertest": "^2.0.14",
+ "@types/validator": "^13.11.2",
+ "jest": "^29.7.0",
+ "jest-mock-extended": "^3.0.5",
+ "prisma": "^5.4.2",
+ "supertest": "^6.3.3",
+ "ts-jest": "^29.1.1",
+ "typescript": "^5.4.3"
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
+ "moduleNameMapper": {
+ "@app/custom-validators": "/src/validators"
+ },
"modulePathIgnorePatterns": ["/dist/"]
}
}
diff --git a/apps/temporary/scripts/clean.ts b/apps/temporary/scripts/clean.ts
deleted file mode 100644
index a3887c8..0000000
--- a/apps/temporary/scripts/clean.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * Clean all the tables and types created by Prisma in the database
- */
-
-import { PrismaClient } from "@prisma/client";
-
-if (require.main === module) {
- clean().catch((error) => {
- console.error(error);
- process.exit(1);
- });
-}
-
-async function clean() {
- console.info("Dropping all tables in the database...");
- const prisma = new PrismaClient();
- const tables = await getTables(prisma);
- const types = await getTypes(prisma);
- await dropTables(prisma, tables);
- await dropTypes(prisma, types);
- console.info("Cleaned database successfully");
- await prisma.$disconnect();
-}
-
-async function dropTables(
- prisma: PrismaClient,
- tables: string[]
-): Promise {
- for (const table of tables) {
- await prisma.$executeRawUnsafe(`DROP TABLE public."${table}" CASCADE;`);
- }
-}
-
-async function dropTypes(prisma: PrismaClient, types: string[]) {
- for (const type of types) {
- await prisma.$executeRawUnsafe(`DROP TYPE IF EXISTS "${type}" CASCADE;`);
- }
-}
-
-async function getTables(prisma: PrismaClient): Promise {
- const results: Array<{
- tablename: string;
- }> =
- await prisma.$queryRaw`SELECT tablename from pg_tables where schemaname = 'public';`;
- return results.map((result) => result.tablename);
-}
-
-async function getTypes(prisma: PrismaClient): Promise {
- const results: Array<{
- typname: string;
- }> = await prisma.$queryRaw`
- SELECT t.typname
- FROM pg_type t
- JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
- WHERE n.nspname = 'public';
- `;
- return results.map((result) => result.typname);
-}
diff --git a/apps/temporary/src/app.module.ts b/apps/temporary/src/app.module.ts
index e33968e..2fcb3b5 100644
--- a/apps/temporary/src/app.module.ts
+++ b/apps/temporary/src/app.module.ts
@@ -1,6 +1,4 @@
-import { Module, Scope } from "@nestjs/common";
-import { APP_INTERCEPTOR } from "@nestjs/core";
-import { MorganInterceptor, MorganModule } from "nest-morgan";
+import { Module } from "@nestjs/common";
import { UserModule } from "./user/user.module";
import { HealthModule } from "./health/health.module";
import { PrismaModule } from "./prisma/prisma.module";
@@ -9,6 +7,7 @@ import { ServeStaticModule } from "@nestjs/serve-static";
import { ServeStaticOptionsService } from "./serveStaticOptions.service";
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";
@@ -22,13 +21,13 @@ import { AuthModule } from "./auth/auth.module";
HealthModule,
PrismaModule,
SecretsManagerModule,
- MorganModule,
ConfigModule.forRoot({ isGlobal: true }),
ServeStaticModule.forRootAsync({
useClass: ServeStaticOptionsService,
}),
- GraphQLModule.forRootAsync({
- useFactory: (configService) => {
+ GraphQLModule.forRootAsync({
+ driver: ApolloDriver,
+ useFactory: (configService: ConfigService) => {
const playground = configService.get("GRAPHQL_PLAYGROUND");
const introspection = configService.get("GRAPHQL_INTROSPECTION");
return {
@@ -42,12 +41,6 @@ import { AuthModule } from "./auth/auth.module";
imports: [ConfigModule],
}),
],
- providers: [
- {
- provide: APP_INTERCEPTOR,
- scope: Scope.REQUEST,
- useClass: MorganInterceptor("combined"),
- },
- ],
+ providers: [],
})
export class AppModule {}
diff --git a/apps/temporary/src/auth/IAuthStrategy.ts b/apps/temporary/src/auth/IAuthStrategy.ts
index 5db10cf..7406267 100644
--- a/apps/temporary/src/auth/IAuthStrategy.ts
+++ b/apps/temporary/src/auth/IAuthStrategy.ts
@@ -1,5 +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/temporary/src/auth/abac.util.ts b/apps/temporary/src/auth/abac.util.ts
index 7047513..2f0dcab 100644
--- a/apps/temporary/src/auth/abac.util.ts
+++ b/apps/temporary/src/auth/abac.util.ts
@@ -9,6 +9,11 @@ export function getInvalidAttributes(
// eslint-disable-next-line @typescript-eslint/ban-types
data: Object
): string[] {
- const filteredData = permission.filter(data);
+ // 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/temporary/src/auth/acl.module.ts b/apps/temporary/src/auth/acl.module.ts
index eb90005..040e7e5 100644
--- a/apps/temporary/src/auth/acl.module.ts
+++ b/apps/temporary/src/auth/acl.module.ts
@@ -1,6 +1,5 @@
import { AccessControlModule, RolesBuilder } from "nest-access-control";
-// @ts-ignore
-// eslint-disable-next-line import/no-unresolved
+
import grants from "../grants.json";
// eslint-disable-next-line @typescript-eslint/naming-convention
diff --git a/apps/temporary/src/auth/auth.module.ts b/apps/temporary/src/auth/auth.module.ts
index 73c8725..d69fd95 100644
--- a/apps/temporary/src/auth/auth.module.ts
+++ b/apps/temporary/src/auth/auth.module.ts
@@ -2,9 +2,10 @@ import { forwardRef, Module } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { JwtModule } from "@nestjs/jwt";
import { PassportModule } from "@nestjs/passport";
-import { JWT_EXPIRATION, JWT_SECRET_KEY } from "../constants";
+import { JWT_EXPIRATION } from "../constants";
import { SecretsManagerModule } from "../providers/secrets/secretsManager.module";
import { SecretsManagerService } from "../providers/secrets/secretsManager.service";
+import { EnumSecretsNameKey } from "../providers/secrets/secretsNameKey.enum";
import { AuthController } from "./auth.controller";
import { AuthResolver } from "./auth.resolver";
import { AuthService } from "./auth.service";
@@ -25,7 +26,9 @@ import { UserModule } from "../user/user.module";
secretsService: SecretsManagerService,
configService: ConfigService
) => {
- const secret = await secretsService.getSecret(JWT_SECRET_KEY);
+ const secret = await secretsService.getSecret(
+ EnumSecretsNameKey.JwtSecretKey
+ );
const expiresIn = configService.get(JWT_EXPIRATION);
if (!secret) {
throw new Error("Didn't get a valid jwt secret");
diff --git a/apps/temporary/src/auth/auth.service.spec.ts b/apps/temporary/src/auth/auth.service.spec.ts
index 72fd2d3..90b04f4 100644
--- a/apps/temporary/src/auth/auth.service.spec.ts
+++ b/apps/temporary/src/auth/auth.service.spec.ts
@@ -27,7 +27,7 @@ const USER: any = {
const SIGN_TOKEN = "SIGN_TOKEN";
const authEntityService = {
- findOne(args: { where: { username: string } }): any | null {
+ user(args: { where: { username: string } }): any | null {
if (args.where.username === VALID_CREDENTIALS.username) {
return USER;
}
diff --git a/apps/temporary/src/auth/auth.service.ts b/apps/temporary/src/auth/auth.service.ts
index f5a74ba..9f6add2 100644
--- a/apps/temporary/src/auth/auth.service.ts
+++ b/apps/temporary/src/auth/auth.service.ts
@@ -17,7 +17,7 @@ export class AuthService {
username: string,
password: string
): Promise {
- const user = await this.userService.findOne({
+ const user = await this.userService.user({
where: { username },
});
if (user && (await this.passwordService.compare(password, user.password))) {
diff --git a/apps/temporary/src/auth/gqlDefaultAuth.guard.ts b/apps/temporary/src/auth/gqlDefaultAuth.guard.ts
index 17143e1..abebd93 100644
--- a/apps/temporary/src/auth/gqlDefaultAuth.guard.ts
+++ b/apps/temporary/src/auth/gqlDefaultAuth.guard.ts
@@ -1,13 +1,11 @@
import { ExecutionContext } from "@nestjs/common";
import { GqlExecutionContext } from "@nestjs/graphql";
import type { Request } from "express";
-// @ts-ignore
-// eslint-disable-next-line
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 {
+ getRequest(context: ExecutionContext): Request {
const ctx = GqlExecutionContext.create(context);
return ctx.getContext<{ req: Request }>().req;
}
diff --git a/apps/temporary/src/auth/jwt/base/jwt.strategy.base.ts b/apps/temporary/src/auth/jwt/base/jwt.strategy.base.ts
index 3bbc919..26da6a7 100644
--- a/apps/temporary/src/auth/jwt/base/jwt.strategy.base.ts
+++ b/apps/temporary/src/auth/jwt/base/jwt.strategy.base.ts
@@ -22,7 +22,7 @@ export class JwtStrategyBase
async validate(payload: UserInfo): Promise {
const { username } = payload;
- const user = await this.userService.findOne({
+ const user = await this.userService.user({
where: { username },
});
if (!user) {
diff --git a/apps/temporary/src/auth/jwt/jwt.strategy.ts b/apps/temporary/src/auth/jwt/jwt.strategy.ts
index 9e75f4c..13395e5 100644
--- a/apps/temporary/src/auth/jwt/jwt.strategy.ts
+++ b/apps/temporary/src/auth/jwt/jwt.strategy.ts
@@ -1,12 +1,12 @@
import { Inject, Injectable } from "@nestjs/common";
-import { JWT_SECRET_KEY } from "../../constants";
+import { JWT_SECRET_KEY_PROVIDER_NAME } from "../../constants";
import { JwtStrategyBase } from "./base/jwt.strategy.base";
import { UserService } from "../../user/user.service";
@Injectable()
export class JwtStrategy extends JwtStrategyBase {
constructor(
- @Inject(JWT_SECRET_KEY) secretOrKey: string,
+ @Inject(JWT_SECRET_KEY_PROVIDER_NAME) secretOrKey: string,
protected readonly userService: UserService
) {
super(secretOrKey, userService);
diff --git a/apps/temporary/src/auth/jwt/jwtSecretFactory.ts b/apps/temporary/src/auth/jwt/jwtSecretFactory.ts
index 151e793..8ca4d74 100644
--- a/apps/temporary/src/auth/jwt/jwtSecretFactory.ts
+++ b/apps/temporary/src/auth/jwt/jwtSecretFactory.ts
@@ -1,12 +1,15 @@
-import { JWT_SECRET_KEY } from "../../constants";
+import { JWT_SECRET_KEY_PROVIDER_NAME } from "../../constants";
import { SecretsManagerService } from "../../providers/secrets/secretsManager.service";
+import { EnumSecretsNameKey } from "../../providers/secrets/secretsNameKey.enum";
export const jwtSecretFactory = {
- provide: JWT_SECRET_KEY,
+ provide: JWT_SECRET_KEY_PROVIDER_NAME,
useFactory: async (
secretsService: SecretsManagerService
): Promise => {
- const secret = await secretsService.getSecret(JWT_SECRET_KEY);
+ const secret = await secretsService.getSecret(
+ EnumSecretsNameKey.JwtSecretKey
+ );
if (secret) {
return secret;
}
diff --git a/apps/temporary/src/auth/token.service.ts b/apps/temporary/src/auth/token.service.ts
index b102b72..2ee079c 100644
--- a/apps/temporary/src/auth/token.service.ts
+++ b/apps/temporary/src/auth/token.service.ts
@@ -1,7 +1,5 @@
-//@ts-ignore
import { ITokenService } from "./ITokenService";
-// eslint-disable-next-line import/no-unresolved
-//@ts-ignore
+
import { TokenServiceBase } from "./base/token.service.base";
export class TokenService extends TokenServiceBase implements ITokenService {}
diff --git a/apps/temporary/src/constants.ts b/apps/temporary/src/constants.ts
index 08f98bf..e131049 100644
--- a/apps/temporary/src/constants.ts
+++ b/apps/temporary/src/constants.ts
@@ -1,2 +1,2 @@
-export const JWT_SECRET_KEY = "JWT_SECRET_KEY";
+export const JWT_SECRET_KEY_PROVIDER_NAME = "JWT_SECRET_KEY";
export const JWT_EXPIRATION = "JWT_EXPIRATION";
diff --git a/apps/temporary/src/prisma.util.ts b/apps/temporary/src/prisma.util.ts
index 8e0779c..029b98a 100644
--- a/apps/temporary/src/prisma.util.ts
+++ b/apps/temporary/src/prisma.util.ts
@@ -1,10 +1,9 @@
export const PRISMA_QUERY_INTERPRETATION_ERROR = "P2016";
export const PRISMA_RECORD_NOT_FOUND = "RecordNotFound";
-export function isRecordNotFoundError(
- error: Error & { code?: string }
-): boolean {
+export function isRecordNotFoundError(error: any): boolean {
return (
+ error instanceof Error &&
"code" in error &&
error.code === PRISMA_QUERY_INTERPRETATION_ERROR &&
error.message.includes(PRISMA_RECORD_NOT_FOUND)
diff --git a/apps/temporary/src/prisma/prisma.service.ts b/apps/temporary/src/prisma/prisma.service.ts
index 3fb4081..79ea4fa 100644
--- a/apps/temporary/src/prisma/prisma.service.ts
+++ b/apps/temporary/src/prisma/prisma.service.ts
@@ -6,10 +6,4 @@ 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/apps/temporary/src/providers/secrets/base/secretsManager.service.base.spec.ts b/apps/temporary/src/providers/secrets/base/secretsManager.service.base.spec.ts
index eb4dfb1..f161172 100644
--- a/apps/temporary/src/providers/secrets/base/secretsManager.service.base.spec.ts
+++ b/apps/temporary/src/providers/secrets/base/secretsManager.service.base.spec.ts
@@ -1,6 +1,7 @@
import { ConfigService } from "@nestjs/config";
import { mock } from "jest-mock-extended";
import { SecretsManagerServiceBase } from "./secretsManager.service.base";
+import { EnumSecretsNameKey } from "../secretsNameKey.enum";
describe("Testing the secrets manager base class", () => {
const SECRET_KEY = "SECRET_KEY";
@@ -16,7 +17,9 @@ describe("Testing the secrets manager base class", () => {
//ARRANGE
configService.get.mockReturnValue(SECRET_VALUE);
//ACT
- const result = await secretsManagerServiceBase.getSecret(SECRET_KEY);
+ const result = await secretsManagerServiceBase.getSecret(
+ SECRET_KEY as unknown as EnumSecretsNameKey
+ );
//ASSERT
expect(result).toBe(SECRET_VALUE);
});
@@ -24,16 +27,15 @@ describe("Testing the secrets manager base class", () => {
//ARRANGE
configService.get.mockReturnValue(undefined);
//ACT
- const result = await secretsManagerServiceBase.getSecret(SECRET_KEY);
+ const result = await secretsManagerServiceBase.getSecret(
+ SECRET_KEY as unknown as EnumSecretsNameKey
+ );
//ASSERT
expect(result).toBeNull();
});
- it("should throw error if dont get key", () => {
- return expect(secretsManagerServiceBase.getSecret("")).rejects.toThrow();
- });
- it("should throw an exeption if getting null key", () => {
+ it("should throw an exception if getting null key", () => {
return expect(
- secretsManagerServiceBase.getSecret(null as unknown as string)
+ secretsManagerServiceBase.getSecret(null as unknown as EnumSecretsNameKey)
).rejects.toThrow();
});
});
diff --git a/apps/temporary/src/providers/secrets/base/secretsManager.service.base.ts b/apps/temporary/src/providers/secrets/base/secretsManager.service.base.ts
index 18a340b..340818c 100644
--- a/apps/temporary/src/providers/secrets/base/secretsManager.service.base.ts
+++ b/apps/temporary/src/providers/secrets/base/secretsManager.service.base.ts
@@ -1,16 +1,14 @@
import { ConfigService } from "@nestjs/config";
+import { EnumSecretsNameKey } from "../secretsNameKey.enum";
export interface ISecretsManager {
- getSecret: (key: string) => Promise;
+ getSecret: (key: EnumSecretsNameKey) => Promise;
}
export class SecretsManagerServiceBase implements ISecretsManager {
constructor(protected readonly configService: ConfigService) {}
- async getSecret(key: string): Promise {
- if (!key) {
- throw new Error("Didn't got the key");
- }
- const value = this.configService.get(key);
+ async getSecret(key: EnumSecretsNameKey): Promise {
+ const value = this.configService.get(key.toString());
if (value) {
return value;
}
diff --git a/apps/temporary/src/providers/secrets/secretsNameKey.enum.ts b/apps/temporary/src/providers/secrets/secretsNameKey.enum.ts
new file mode 100644
index 0000000..52c18af
--- /dev/null
+++ b/apps/temporary/src/providers/secrets/secretsNameKey.enum.ts
@@ -0,0 +1,3 @@
+export enum EnumSecretsNameKey {
+ JwtSecretKey = "JWT_SECRET_KEY"
+}
\ No newline at end of file
diff --git a/apps/temporary/src/tests/auth/jwt/jwt.strategy.spec.ts b/apps/temporary/src/tests/auth/jwt/jwt.strategy.spec.ts
index 2463c9b..36bbb24 100644
--- a/apps/temporary/src/tests/auth/jwt/jwt.strategy.spec.ts
+++ b/apps/temporary/src/tests/auth/jwt/jwt.strategy.spec.ts
@@ -5,14 +5,16 @@ import { TEST_USER } from "../constants";
import { UserService } from "../../../user/user.service";
describe("Testing the jwtStrategyBase.validate()", () => {
const userService = mock();
- const jwtStrategy = new JwtStrategyBase(userService, "Secrete");
+ const jwtStrategy = new JwtStrategyBase("Secrete", userService);
beforeEach(() => {
- userService.findOne.mockClear();
+ userService.user.mockClear();
});
it("should throw UnauthorizedException where there is no user", async () => {
//ARRANGE
- userService.findOne
- .calledWith({ where: { username: TEST_USER.username } })
+ userService.user
+ .calledWith({
+ where: { username: TEST_USER.username },
+ })
.mockReturnValue(Promise.resolve(null));
//ACT
const result = jwtStrategy.validate({
diff --git a/apps/temporary/src/user/base/User.ts b/apps/temporary/src/user/base/User.ts
index 45adebe..348fd32 100644
--- a/apps/temporary/src/user/base/User.ts
+++ b/apps/temporary/src/user/base/User.ts
@@ -11,9 +11,9 @@ https://docs.amplication.com/how-to/custom-code
*/
import { ObjectType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
-import { IsDate, IsString, IsOptional } from "class-validator";
+import { IsDate, IsString, MaxLength, IsOptional } from "class-validator";
import { Type } from "class-transformer";
-import { IsJSONValue } from "@app/custom-validators";
+import { IsJSONValue } from "../../validators";
import { GraphQLJSON } from "graphql-type-json";
import { JsonValue } from "type-fest";
@@ -32,6 +32,7 @@ class User {
type: String,
})
@IsString()
+ @MaxLength(256)
@IsOptional()
@Field(() => String, {
nullable: true,
@@ -51,6 +52,7 @@ class User {
type: String,
})
@IsString()
+ @MaxLength(256)
@IsOptional()
@Field(() => String, {
nullable: true,
diff --git a/apps/temporary/src/user/base/UserCreateInput.ts b/apps/temporary/src/user/base/UserCreateInput.ts
index 6896f2a..a98430e 100644
--- a/apps/temporary/src/user/base/UserCreateInput.ts
+++ b/apps/temporary/src/user/base/UserCreateInput.ts
@@ -11,8 +11,8 @@ https://docs.amplication.com/how-to/custom-code
*/
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
-import { IsString, IsOptional } from "class-validator";
-import { IsJSONValue } from "@app/custom-validators";
+import { IsString, MaxLength, IsOptional } from "class-validator";
+import { IsJSONValue } from "../../validators";
import { GraphQLJSON } from "graphql-type-json";
import { InputJsonValue } from "../../types";
@@ -23,6 +23,7 @@ class UserCreateInput {
type: String,
})
@IsString()
+ @MaxLength(256)
@IsOptional()
@Field(() => String, {
nullable: true,
@@ -34,6 +35,7 @@ class UserCreateInput {
type: String,
})
@IsString()
+ @MaxLength(256)
@IsOptional()
@Field(() => String, {
nullable: true,
diff --git a/apps/temporary/src/user/base/UserUpdateInput.ts b/apps/temporary/src/user/base/UserUpdateInput.ts
index b6e0e21..aefeb3f 100644
--- a/apps/temporary/src/user/base/UserUpdateInput.ts
+++ b/apps/temporary/src/user/base/UserUpdateInput.ts
@@ -11,8 +11,8 @@ https://docs.amplication.com/how-to/custom-code
*/
import { InputType, Field } from "@nestjs/graphql";
import { ApiProperty } from "@nestjs/swagger";
-import { IsString, IsOptional } from "class-validator";
-import { IsJSONValue } from "@app/custom-validators";
+import { IsString, MaxLength, IsOptional } from "class-validator";
+import { IsJSONValue } from "../../validators";
import { GraphQLJSON } from "graphql-type-json";
import { InputJsonValue } from "../../types";
@@ -23,6 +23,7 @@ class UserUpdateInput {
type: String,
})
@IsString()
+ @MaxLength(256)
@IsOptional()
@Field(() => String, {
nullable: true,
@@ -34,6 +35,7 @@ class UserUpdateInput {
type: String,
})
@IsString()
+ @MaxLength(256)
@IsOptional()
@Field(() => String, {
nullable: true,
diff --git a/apps/temporary/src/user/base/user.controller.base.spec.ts b/apps/temporary/src/user/base/user.controller.base.spec.ts
index 63b8914..fb15280 100644
--- a/apps/temporary/src/user/base/user.controller.base.spec.ts
+++ b/apps/temporary/src/user/base/user.controller.base.spec.ts
@@ -6,7 +6,6 @@ import {
CallHandler,
} from "@nestjs/common";
import request from "supertest";
-import { MorganModule } from "nest-morgan";
import { ACGuard } from "nest-access-control";
import { DefaultAuthGuard } from "../../auth/defaultAuth.guard";
import { ACLModule } from "../../auth/acl.module";
@@ -58,11 +57,11 @@ const FIND_ONE_RESULT = {
};
const service = {
- create() {
+ createUser() {
return CREATE_RESULT;
},
- findMany: () => FIND_MANY_RESULT,
- findOne: ({ where }: { where: { id: string } }) => {
+ users: () => FIND_MANY_RESULT,
+ user: ({ where }: { where: { id: string } }) => {
switch (where.id) {
case existingId:
return FIND_ONE_RESULT;
@@ -116,7 +115,7 @@ describe("User", () => {
},
],
controllers: [UserController],
- imports: [MorganModule.forRoot(), ACLModule],
+ imports: [ACLModule],
})
.overrideGuard(DefaultAuthGuard)
.useValue(basicAuthGuard)
diff --git a/apps/temporary/src/user/base/user.controller.base.ts b/apps/temporary/src/user/base/user.controller.base.ts
index 0a05e44..57e9815 100644
--- a/apps/temporary/src/user/base/user.controller.base.ts
+++ b/apps/temporary/src/user/base/user.controller.base.ts
@@ -22,11 +22,10 @@ import { UserService } from "../user.service";
import { AclValidateRequestInterceptor } from "../../interceptors/aclValidateRequest.interceptor";
import { AclFilterResponseInterceptor } from "../../interceptors/aclFilterResponse.interceptor";
import { UserCreateInput } from "./UserCreateInput";
-import { UserWhereInput } from "./UserWhereInput";
-import { UserWhereUniqueInput } from "./UserWhereUniqueInput";
+import { User } from "./User";
import { UserFindManyArgs } from "./UserFindManyArgs";
+import { UserWhereUniqueInput } from "./UserWhereUniqueInput";
import { UserUpdateInput } from "./UserUpdateInput";
-import { User } from "./User";
@swagger.ApiBearerAuth()
@common.UseGuards(defaultAuthGuard.DefaultAuthGuard, nestAccessControl.ACGuard)
@@ -46,8 +45,8 @@ export class UserControllerBase {
@swagger.ApiForbiddenResponse({
type: errors.ForbiddenException,
})
- async create(@common.Body() data: UserCreateInput): Promise {
- return await this.service.create({
+ async createUser(@common.Body() data: UserCreateInput): Promise {
+ return await this.service.createUser({
data: data,
select: {
createdAt: true,
@@ -73,9 +72,9 @@ export class UserControllerBase {
@swagger.ApiForbiddenResponse({
type: errors.ForbiddenException,
})
- async findMany(@common.Req() request: Request): Promise {
+ async users(@common.Req() request: Request): Promise {
const args = plainToClass(UserFindManyArgs, request.query);
- return this.service.findMany({
+ return this.service.users({
...args,
select: {
createdAt: true,
@@ -101,10 +100,10 @@ export class UserControllerBase {
@swagger.ApiForbiddenResponse({
type: errors.ForbiddenException,
})
- async findOne(
+ async user(
@common.Param() params: UserWhereUniqueInput
): Promise {
- const result = await this.service.findOne({
+ const result = await this.service.user({
where: params,
select: {
createdAt: true,
@@ -136,12 +135,12 @@ export class UserControllerBase {
@swagger.ApiForbiddenResponse({
type: errors.ForbiddenException,
})
- async update(
+ async updateUser(
@common.Param() params: UserWhereUniqueInput,
@common.Body() data: UserUpdateInput
): Promise {
try {
- return await this.service.update({
+ return await this.service.updateUser({
where: params,
data: data,
select: {
@@ -175,11 +174,11 @@ export class UserControllerBase {
@swagger.ApiForbiddenResponse({
type: errors.ForbiddenException,
})
- async delete(
+ async deleteUser(
@common.Param() params: UserWhereUniqueInput
): Promise {
try {
- return await this.service.delete({
+ return await this.service.deleteUser({
where: params,
select: {
createdAt: true,
diff --git a/apps/temporary/src/user/base/user.module.base.ts b/apps/temporary/src/user/base/user.module.base.ts
index 078e0b5..a8b6c68 100644
--- a/apps/temporary/src/user/base/user.module.base.ts
+++ b/apps/temporary/src/user/base/user.module.base.ts
@@ -10,10 +10,9 @@ https://docs.amplication.com/how-to/custom-code
------------------------------------------------------------------------------
*/
import { Module } from "@nestjs/common";
-import { MorganModule } from "nest-morgan";
import { ACLModule } from "../../auth/acl.module";
@Module({
- imports: [ACLModule, MorganModule],
- exports: [ACLModule, MorganModule],
+ imports: [ACLModule],
+ exports: [ACLModule],
})
export class UserModuleBase {}
diff --git a/apps/temporary/src/user/base/user.resolver.base.ts b/apps/temporary/src/user/base/user.resolver.base.ts
index ad9e01a..0c60d95 100644
--- a/apps/temporary/src/user/base/user.resolver.base.ts
+++ b/apps/temporary/src/user/base/user.resolver.base.ts
@@ -10,7 +10,7 @@ https://docs.amplication.com/how-to/custom-code
------------------------------------------------------------------------------
*/
import * as graphql from "@nestjs/graphql";
-import * as apollo from "apollo-server-express";
+import { GraphQLError } from "graphql";
import { isRecordNotFoundError } from "../../prisma.util";
import { MetaQueryPayload } from "../../util/MetaQueryPayload";
import * as nestAccessControl from "nest-access-control";
@@ -19,13 +19,13 @@ 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 { CreateUserArgs } from "./CreateUserArgs";
-import { UpdateUserArgs } from "./UpdateUserArgs";
-import { DeleteUserArgs } from "./DeleteUserArgs";
+import { User } from "./User";
import { UserCountArgs } from "./UserCountArgs";
import { UserFindManyArgs } from "./UserFindManyArgs";
import { UserFindUniqueArgs } from "./UserFindUniqueArgs";
-import { User } from "./User";
+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)
@@ -58,7 +58,7 @@ export class UserResolverBase {
possession: "any",
})
async users(@graphql.Args() args: UserFindManyArgs): Promise {
- return this.service.findMany(args);
+ return this.service.users(args);
}
@common.UseInterceptors(AclFilterResponseInterceptor)
@@ -69,7 +69,7 @@ export class UserResolverBase {
possession: "own",
})
async user(@graphql.Args() args: UserFindUniqueArgs): Promise {
- const result = await this.service.findOne(args);
+ const result = await this.service.user(args);
if (result === null) {
return null;
}
@@ -84,7 +84,7 @@ export class UserResolverBase {
possession: "any",
})
async createUser(@graphql.Args() args: CreateUserArgs): Promise {
- return await this.service.create({
+ return await this.service.createUser({
...args,
data: args.data,
});
@@ -99,13 +99,13 @@ export class UserResolverBase {
})
async updateUser(@graphql.Args() args: UpdateUserArgs): Promise {
try {
- return await this.service.update({
+ return await this.service.updateUser({
...args,
data: args.data,
});
} catch (error) {
if (isRecordNotFoundError(error)) {
- throw new apollo.ApolloError(
+ throw new GraphQLError(
`No resource was found for ${JSON.stringify(args.where)}`
);
}
@@ -121,10 +121,10 @@ export class UserResolverBase {
})
async deleteUser(@graphql.Args() args: DeleteUserArgs): Promise {
try {
- return await this.service.delete(args);
+ return await this.service.deleteUser(args);
} catch (error) {
if (isRecordNotFoundError(error)) {
- throw new apollo.ApolloError(
+ throw new GraphQLError(
`No resource was found for ${JSON.stringify(args.where)}`
);
}
diff --git a/apps/temporary/src/user/base/user.service.base.ts b/apps/temporary/src/user/base/user.service.base.ts
index 3c9de61..6a749c5 100644
--- a/apps/temporary/src/user/base/user.service.base.ts
+++ b/apps/temporary/src/user/base/user.service.base.ts
@@ -10,7 +10,7 @@ https://docs.amplication.com/how-to/custom-code
------------------------------------------------------------------------------
*/
import { PrismaService } from "../../prisma/prisma.service";
-import { Prisma, User } from "@prisma/client";
+import { Prisma, User as PrismaUser } from "@prisma/client";
import { PasswordService } from "../../auth/password.service";
import { transformStringFieldUpdateInput } from "../../prisma.util";
@@ -20,26 +20,18 @@ export class UserServiceBase {
protected readonly passwordService: PasswordService
) {}
- async count(
- args: Prisma.SelectSubset
- ): Promise {
+ async count(args: Omit): Promise {
return this.prisma.user.count(args);
}
- async findMany(
- args: Prisma.SelectSubset
- ): Promise {
+ async users(args: Prisma.UserFindManyArgs): Promise {
return this.prisma.user.findMany(args);
}
- async findOne(
- args: Prisma.SelectSubset
- ): Promise {
+ async user(args: Prisma.UserFindUniqueArgs): Promise {
return this.prisma.user.findUnique(args);
}
- async create(
- args: Prisma.SelectSubset
- ): Promise {
- return this.prisma.user.create({
+ async createUser(args: Prisma.UserCreateArgs): Promise {
+ return this.prisma.user.create({
...args,
data: {
@@ -48,10 +40,8 @@ export class UserServiceBase {
},
});
}
- async update(
- args: Prisma.SelectSubset
- ): Promise {
- return this.prisma.user.update({
+ async updateUser(args: Prisma.UserUpdateArgs): Promise {
+ return this.prisma.user.update({
...args,
data: {
@@ -66,9 +56,7 @@ export class UserServiceBase {
},
});
}
- async delete(
- args: Prisma.SelectSubset
- ): Promise {
+ async deleteUser(args: Prisma.UserDeleteArgs): Promise {
return this.prisma.user.delete(args);
}
}
diff --git a/apps/temporary/tsconfig.json b/apps/temporary/tsconfig.json
index f084cf7..707e8cd 100644
--- a/apps/temporary/tsconfig.json
+++ b/apps/temporary/tsconfig.json
@@ -6,8 +6,8 @@
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
- "target": "es2017",
- "lib": ["ES2020"],
+ "target": "es2022",
+ "lib": ["es2023"],
"sourceMap": true,
"outDir": "./dist",
"incremental": true,
@@ -15,10 +15,7 @@
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"skipLibCheck": true,
- "strict": true,
- "paths": {
- "@app/custom-validators": ["src/validators"]
- }
+ "strict": true
},
"include": ["src"]
}
diff --git a/helm/flights/templates/deployment.yaml b/helm/flights/templates/deployment.yaml
index 4e87585..ff02491 100644
--- a/helm/flights/templates/deployment.yaml
+++ b/helm/flights/templates/deployment.yaml
@@ -30,6 +30,21 @@ spec:
serviceAccountName: {{ include "flights.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
+ {{- if or .Values.variables.configmap.DB_URL .Values.variables.secret.DB_URL }}
+ initContainers:
+ - name: {{ .Chart.Name }}-prisma-migrate
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ command: ["sh", "-c", "npx prisma migrate deploy; exit 0"]
+ {{- if .Values.variables.configmap.DB_URL }}
+ env:
+ - name: DATABASE_URL
+ value: {{ required ".Values.variables.configmap.DB_URL is required" .Values.variables.configmap.DB_URL }}
+ {{- else if .Values.variables.secret.DB_URL }}
+ env:
+ - name: DATABASE_URL
+ value: {{ required ".Values.variables.configmap.DB_URL is required" .Values.variables.configmap.DB_URL }}
+ {{- end }}
+ {{- end }}
containers:
- name: {{ .Chart.Name }}
securityContext:
diff --git a/helm/flights/templates/hpa.yaml b/helm/flights/templates/hpa.yaml
index e256d88..1c56f9b 100644
--- a/helm/flights/templates/hpa.yaml
+++ b/helm/flights/templates/hpa.yaml
@@ -1,5 +1,5 @@
{{- if .Values.autoscaling.enabled }}
-apiVersion: autoscaling/v2beta1
+apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "flights.fullname" . }}
@@ -17,12 +17,16 @@ spec:
- type: Resource
resource:
name: cpu
- targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ target:
+ type: Utilization
+ averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
- targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ target:
+ type: Utilization
+ averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}
diff --git a/helm/flights/values.yaml b/helm/flights/values.yaml
index b7e4238..38a9e30 100644
--- a/helm/flights/values.yaml
+++ b/helm/flights/values.yaml
@@ -10,16 +10,16 @@ image:
variables:
configmap:
- BCRYPT_SALT: 10
- COMPOSE_PROJECT_NAME: amp_${resourceId}
- PORT: 3000
- DB_URL: postgres://admin:admin@localhost:5432/my-db
- DB_USER: admin
- DB_PASSWORD: admin
- DB_PORT: 5432
- DB_NAME: my-db
- JWT_SECRET_KEY: Change_ME!!!
- JWT_EXPIRATION: 2d
+ BCRYPT_SALT: "10"
+ COMPOSE_PROJECT_NAME: "amp_${resourceId}"
+ PORT: "3000"
+ 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_NAME: "my-db"
secret: {}
imagePullSecrets: []