Skip to content

Commit

Permalink
feat: 🔥 support cli backend without auth
Browse files Browse the repository at this point in the history
support cli backend without auth
  • Loading branch information
Tal Rofe committed Jun 20, 2022
1 parent 952eb63 commit 075cb4d
Show file tree
Hide file tree
Showing 54 changed files with 6,651 additions and 15,151 deletions.
3 changes: 2 additions & 1 deletion .depcheckrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"prettier",
"@commitlint/cli",
"@types/node",
"stylelint"
"stylelint",
"@prisma/client"
]
}
2 changes: 1 addition & 1 deletion .github/workflows/integrate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
run: pnpm --filter frontend stylelint

- name: Check Prisma Schema
run: pnpm --filter backend prisma-format
run: pnpm prisma-format

- name: Check build command
run: pnpm -r --parallel build
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,7 @@ When you want look at the backend documentation

When you want look at the backend OpenAPI (Swagger), you need to run the application in development mode.
Then, you can browse to `http://localhost:3000/api` (replace the port if you use other port)

## Improvements

- Need to have a common application (shared folder for `backend` and `cli-backend`)
1 change: 0 additions & 1 deletion apps/backend/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
node_modules
dist
tsconfig.tsbuildinfo
.env
.env.production
documentation
11 changes: 4 additions & 7 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@
"scripts": {
"postinstall": "pnpm prisma-gen",
"build": "nest build",
"start": "dotenv -e ./envs/.env.production -e ./prisma/.env.production nest start",
"start:dev": "dotenv -e ./envs/.env.development -e ./prisma/.env.development nest start --watch",
"start:prod": "dotenv -e ./envs/.env.production -e ./prisma/.env.production node dist/main",
"prisma-format": "prisma format",
"prisma-gen": "prisma generate --schema ./prisma/schema.prisma",
"prisma-push:dev": "dotenv -e ./prisma/.env.development prisma db push --schema ./prisma/schema.prisma",
"prisma-push:prod": "dotenv -e ./prisma/.env.production prisma db push --schema ./prisma/schema.prisma",
"start": "dotenv -e ./envs/.env.production -e ../../prisma/.env.production nest start",
"start:dev": "dotenv -e ./envs/.env.development -e ../../prisma/.env.development nest start --watch",
"start:prod": "dotenv -e ./envs/.env.production -e ../../prisma/.env.production node dist/main",
"prisma-gen": "prisma generate --schema ../../prisma/schema.prisma",
"compodoc": "compodoc && open-cli ./documentation/index.html",
"lint": "eslint -c ./.eslintrc.cjs --ignore-path ./.eslintignore \"./**/*.ts\"",
"type-check": "tsc --project ./tsconfig.json",
Expand Down
1 change: 0 additions & 1 deletion apps/backend/src/strategies/access-token.strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';

import { IEnvironment } from '../config/env.interface';

import { IJwtTokenPayload } from '../interfaces/jwt-token';

@Injectable()
Expand Down
6 changes: 6 additions & 0 deletions apps/cli-backend/.compodocrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "./node_modules/@compodoc/compodoc/src/config/schema.json",
"tsconfig": "./tsconfig.doc.json",
"silent": true,
"serve": false
}
17 changes: 17 additions & 0 deletions apps/cli-backend/.depcheckrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"ignores": [
"rimraf",
"@nestjs/schematics",
"ts-loader",

"@nestjs/jwt",
"@octokit/oauth-app",
"googleapis",
"passport-github2",
"passport-google-oauth20",
"passport-local",
"@types/passport-github2",
"@types/passport-google-oauth20",
"@types/passport-local"
]
}
2 changes: 2 additions & 0 deletions apps/cli-backend/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist
.eslintrc.cjs
17 changes: 17 additions & 0 deletions apps/cli-backend/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
root: true,
extends: ['../../.eslintrc.cjs'],
parserOptions: {
ecmaVersion: 12,
project: './tsconfig.eslint.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
extraFileExtensions: ['.cjs'],
},
plugins: ['node'],
rules: {
'max-lines': ['error', { max: 150, skipBlankLines: true, skipComments: true }],

'node/no-sync': 'error',
},
};
5 changes: 5 additions & 0 deletions apps/cli-backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
tsconfig.tsbuildinfo
.env.production
documentation
17 changes: 17 additions & 0 deletions apps/cli-backend/@types/global/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production';
readonly PORT: string;
readonly JWT_KEY: string;
readonly GOOGLE_OAUTH_CLIENT_ID: string;
readonly GOOGLE_OAUTH_CLIENT_SECRET: string;
readonly GOOGLE_OAUTH_REDIRECT_URI: string;
readonly GITHUB_OAUTH_CLIENT_ID: string;
readonly GITHUB_OAUTH_CLIENT_SECRET: string;
readonly GITHUB_OAUTH_REDIRECT_URI: string;
}
}
}

export {};
9 changes: 9 additions & 0 deletions apps/cli-backend/envs/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
NODE_ENV="development"
PORT="5000"
JWT_KEY="JWT"
GOOGLE_OAUTH_CLIENT_ID="DUMMY"
GOOGLE_OAUTH_CLIENT_SECRET="DUMMY"
GOOGLE_OAUTH_REDIRECT_URI="http://localhost:5000/user/auth/google-redirect"
GITHUB_OAUTH_CLIENT_ID="DUMMY"
GITHUB_OAUTH_CLIENT_SECRET="DUMMY"
GITHUB_OAUTH_REDIRECT_URI="http://localhost:5000/user/auth/github-redirect"
9 changes: 9 additions & 0 deletions apps/cli-backend/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"webpack": true,
"webpackConfigPath": "./webpack.config.ts"
}
}
68 changes: 68 additions & 0 deletions apps/cli-backend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "@exlint-dashboard/cli-backend",
"version": "1.0.0",
"private": true,
"description": "CLI Backend package",
"author": "Exlint <dev@exlint.io> (https://www.exlint.io)",
"license": "UNLICENSED",
"scripts": {
"postinstall": "pnpm prisma-gen",
"build": "nest build",
"start": "dotenv -e ./envs/.env.production -e ../../prisma/.env.production nest start",
"start:dev": "dotenv -e ./envs/.env.development -e ../../prisma/.env.development nest start --watch",
"start:prod": "dotenv -e ./envs/.env.production -e ../../prisma/.env.production node dist/main",
"prisma-gen": "prisma generate --schema ../../prisma/schema.prisma",
"compodoc": "compodoc && open-cli ./documentation/index.html",
"lint": "eslint -c ./.eslintrc.cjs --ignore-path ./.eslintignore \"./**/*.ts\"",
"type-check": "tsc --project ./tsconfig.json",
"depcheck": "depcheck --config ./.depcheckrc.json"
},
"dependencies": {
"@nestjs/common": "8.4.6",
"@nestjs/config": "2.1.0",
"@nestjs/core": "8.4.6",
"@nestjs/cqrs": "8.0.4",
"@nestjs/jwt": "8.0.1",
"@nestjs/passport": "8.2.1",
"@nestjs/platform-express": "8.4.6",
"@octokit/oauth-app": "3.6.2",
"@prisma/client": "3.15.1",
"class-transformer": "0.5.1",
"class-validator": "0.13.2",
"googleapis": "101.0.0",
"passport": "0.6.0",
"passport-github2": "0.1.12",
"passport-google-oauth20": "2.0.0",
"passport-jwt": "4.0.0",
"passport-local": "1.0.0",
"reflect-metadata": "0.1.13",
"rxjs": "7.5.5"
},
"devDependencies": {
"@compodoc/compodoc": "1.1.19",
"@nestjs/cli": "8.2.6",
"@nestjs/schematics": "8.0.11",
"@nestjs/swagger": "5.2.1",
"@types/passport-github2": "1.2.5",
"@types/passport-google-oauth20": "2.0.11",
"@types/passport-jwt": "3.0.6",
"@types/passport-local": "1.0.34",
"@typescript-eslint/eslint-plugin": "5.27.1",
"@typescript-eslint/parser": "5.27.1",
"depcheck": "1.4.3",
"dotenv-cli": "5.1.0",
"eslint": "8.17.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-unused-imports": "2.0.0",
"open-cli": "7.0.1",
"rimraf": "3.0.2",
"prisma": "3.15.1",
"swagger-ui-express": "4.4.0",
"ts-loader": "9.3.0",
"typescript": "4.7.3",
"webpack": "5.73.0",
"webpack-shell-plugin-next": "2.2.2"
}
}
37 changes: 37 additions & 0 deletions apps/cli-backend/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { APP_GUARD, RouterModule } from '@nestjs/core';

import { appRoutes } from './app.routes';
import EnvConfiguration from './config/configuration';
import { validate } from './config/env.validation';
import { TokenGuard } from './guards/token.guard';
import { DatabaseModule } from './modules/database/database.module';
import { UserModule } from './modules/user/user.module';
import { TokenStrategy } from './strategies/token.strategy';

@Module({
imports: [
DatabaseModule,
UserModule,
RouterModule.register(appRoutes),
ConfigModule.forRoot({
load: [EnvConfiguration],
isGlobal: true,
cache: true,
validate,
validationOptions: {
allowUnknown: false,
abortEarly: true,
},
}),
],
providers: [
{
provide: APP_GUARD,
useClass: TokenGuard,
},
TokenStrategy,
],
})
export class AppModule {}
12 changes: 12 additions & 0 deletions apps/cli-backend/src/app.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Routes } from '@nestjs/core';

import { UserModule } from './modules/user/user.module';
import { userRoutes } from './modules/user/user.routes';

export const appRoutes: Routes = [
{
path: 'user',
module: UserModule,
children: userRoutes,
},
];
15 changes: 15 additions & 0 deletions apps/cli-backend/src/config/configuration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IEnvironment } from './env.interface';

const EnvConfiguration = (): IEnvironment => ({
nodeEnv: process.env.NODE_ENV,
port: process.env.PORT,
jwtKey: process.env.JWT_KEY,
googleOAuthClientId: process.env.GOOGLE_OAUTH_CLIENT_ID,
googleOAuthClientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET,
googleOAuthRedirectUri: process.env.GOOGLE_OAUTH_REDIRECT_URI,
githubOAuthClientId: process.env.GITHUB_OAUTH_CLIENT_ID,
githubOAuthClientSecret: process.env.GITHUB_OAUTH_CLIENT_SECRET,
githubOAuthRedirectUri: process.env.GITHUB_OAUTH_REDIRECT_URI,
});

export default EnvConfiguration;
11 changes: 11 additions & 0 deletions apps/cli-backend/src/config/env.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface IEnvironment {
readonly nodeEnv: 'development' | 'production';
readonly port: string;
readonly jwtKey: string;
readonly googleOAuthClientId: string;
readonly googleOAuthClientSecret: string;
readonly googleOAuthRedirectUri: string;
readonly githubOAuthClientId: string;
readonly githubOAuthClientSecret: string;
readonly githubOAuthRedirectUri: string;
}
48 changes: 48 additions & 0 deletions apps/cli-backend/src/config/env.validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { plainToClass } from 'class-transformer';
import { IsEnum, IsPositive, IsInt, IsString, validateSync } from 'class-validator';

enum Environment {
Development = 'development',
Production = 'production',
}

class EnvironmentVariables {
@IsEnum(Environment)
public NODE_ENV!: Environment;

@IsInt()
@IsPositive()
public PORT!: number;

@IsString()
public JWT_KEY!: string;

@IsString()
public GOOGLE_OAUTH_CLIENT_ID!: string;

@IsString()
public GOOGLE_OAUTH_CLIENT_SECRET!: string;

@IsString()
public GOOGLE_OAUTH_REDIRECT_URI!: string;

@IsString()
public GITHUB_OAUTH_CLIENT_ID!: string;

@IsString()
public GITHUB_OAUTH_CLIENT_SECRET!: string;

@IsString()
public GITHUB_OAUTH_REDIRECT_URI!: string;
}

export const validate = (config: Record<string, unknown>) => {
const validatedConfig = plainToClass(EnvironmentVariables, config, { enableImplicitConversion: true });
const errors = validateSync(validatedConfig, { skipMissingProperties: false });

if (errors.length > 0) {
throw new Error(errors.toString());
}

return validatedConfig;
};
10 changes: 10 additions & 0 deletions apps/cli-backend/src/decorators/current-user-id.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

import { IJwtTokenPayload } from '@/interfaces/jwt-token';

export const CurrentUserId = createParamDecorator((_: undefined, context: ExecutionContext) => {
const request = context.switchToHttp().getRequest();
const user = request.user as IJwtTokenPayload;

return user.sub;
});
3 changes: 3 additions & 0 deletions apps/cli-backend/src/decorators/public.decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { SetMetadata } from '@nestjs/common';

export const Public = () => SetMetadata('isPublic', true);
23 changes: 23 additions & 0 deletions apps/cli-backend/src/guards/token.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class TokenGuard extends AuthGuard('token') {
constructor(private reflector: Reflector) {
super();
}

public override canActivate(context: ExecutionContext) {
const isPublic = this.reflector.getAllAndOverride('isPublic', [
context.getHandler(),
context.getClass(),
]);

if (isPublic) {
return true;
}

return super.canActivate(context);
}
}
Loading

0 comments on commit 075cb4d

Please sign in to comment.