From 73379a8d4085ad32d72dc14c6fbcbdc0bf2847b1 Mon Sep 17 00:00:00 2001 From: Yoni FIRROLONI Date: Wed, 23 Feb 2022 01:26:23 +0100 Subject: [PATCH 1/2] add deployments --- Dockerfile => Dockerfile.dev | 2 +- deployments/api/deployment.yml | 24 ++++++++++++++++++++++++ deployments/mongo/deployment.yml | 22 ++++++++++++++++++++++ deployments/mongo/pvc.yml | 11 +++++++++++ deployments/mongo/service.yml | 10 ++++++++++ docker-compose.yml | 2 +- 6 files changed, 69 insertions(+), 2 deletions(-) rename Dockerfile => Dockerfile.dev (91%) create mode 100644 deployments/api/deployment.yml create mode 100644 deployments/mongo/deployment.yml create mode 100644 deployments/mongo/pvc.yml create mode 100644 deployments/mongo/service.yml diff --git a/Dockerfile b/Dockerfile.dev similarity index 91% rename from Dockerfile rename to Dockerfile.dev index 3cc3495..917fecc 100644 --- a/Dockerfile +++ b/Dockerfile.dev @@ -5,6 +5,6 @@ WORKDIR /usr/src/app # Copy package.json and package-lock.json COPY ./package*.json ./ -RUN npm install +RUN npm ci # Copy source code COPY . . \ No newline at end of file diff --git a/deployments/api/deployment.yml b/deployments/api/deployment.yml new file mode 100644 index 0000000..98b1807 --- /dev/null +++ b/deployments/api/deployment.yml @@ -0,0 +1,24 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: uni-verse-api +spec: + selector: + matchLabels: + app: uni-verse-api + template: + metadata: + labels: + app: uni-verse-api + spec: + imagePullSecrets: + - name: regcred + containers: + - name: uni-verse-api + image: registry.qtmsheep.com/vagahbond/uni-verse/api + resources: + limits: + memory: "128Mi" + cpu: "500m" + ports: + - containerPort: 3000 diff --git a/deployments/mongo/deployment.yml b/deployments/mongo/deployment.yml new file mode 100644 index 0000000..cc53a7b --- /dev/null +++ b/deployments/mongo/deployment.yml @@ -0,0 +1,22 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: uni-verse-database +spec: + selector: + matchLabels: + app: uni-verse-database + template: + metadata: + labels: + app: uni-verse-database + spec: + containers: + - name: uni-verse-database + image: mongo:latest + resources: + limits: + memory: "128Mi" + cpu: "500m" + ports: + - containerPort: 27017 diff --git a/deployments/mongo/pvc.yml b/deployments/mongo/pvc.yml new file mode 100644 index 0000000..43e2416 --- /dev/null +++ b/deployments/mongo/pvc.yml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: uni-verse-database-pvc +spec: + resources: + requests: + storage: 100Mi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce diff --git a/deployments/mongo/service.yml b/deployments/mongo/service.yml new file mode 100644 index 0000000..1032112 --- /dev/null +++ b/deployments/mongo/service.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: uni-verse-database-service +spec: + selector: + app: uni-verse-database + ports: + - port: 27017 + targetPort: 27017 diff --git a/docker-compose.yml b/docker-compose.yml index 55193ff..e4185ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: container_name: uni_verse_api_dev build: context: . - dockerfile: ./Dockerfile + dockerfile: ./Dockerfile.dev command: npm run start:dev ports: - 3000:3000 From 3af223386d09c89088f221b72f64afbc42ea917e Mon Sep 17 00:00:00 2001 From: Yoni FIRROLONI Date: Wed, 23 Feb 2022 02:15:34 +0100 Subject: [PATCH 2/2] add cd-ci --- .github/workflows/build.yml | 24 +++ .github/workflows/ci.yml | 23 +++ .github/workflows/release.yml | 35 ++++ Dockerfile | 24 +++ package-lock.json | 3 +- package.json | 2 +- src/app.module.ts | 5 +- src/auth/auth.service.ts | 12 +- src/auth/constants.ts | 4 +- src/auth/decorators/public.decorator.ts | 2 +- src/auth/guards/jwt-auth.guard.ts | 32 ++-- src/auth/strategies/jwt.strategy.ts | 2 +- src/database/database.module.ts | 6 +- src/database/database.provider.ts | 16 +- src/main.ts | 2 +- src/playlists/playlists.controller.ts | 15 +- src/playlists/playlists.module.ts | 2 +- src/playlists/playlists.service.ts | 2 + src/releases/releases.controller.ts | 10 +- src/releases/releases.module.ts | 2 +- src/releases/releases.service.ts | 2 + .../resource-packs.controller.ts | 15 +- src/resource-packs/resource-packs.module.ts | 2 +- src/resource-packs/resource-packs.service.ts | 2 + src/users/dto/create-user.dto.ts | 40 ++-- src/users/dto/login-user.dto.ts | 33 ++-- src/users/interfaces/user.interface.ts | 2 +- src/users/providers/users.providers.ts | 5 +- src/users/schemas/user.schema.ts | 65 +++---- src/users/users.controller.ts | 11 +- src/users/users.module.ts | 16 +- src/users/users.service.ts | 174 +++++++++--------- 32 files changed, 378 insertions(+), 212 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 Dockerfile diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..71e7f53 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,24 @@ +name: build + +on: + pull_request: + push: + branches: + - 'main' +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Prepare buildx + uses: docker/setup-buildx-action@v1 + id: buildx + with: + install: true + + - name: Build + run: | + docker build . # will run buildx \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..5428134 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,23 @@ +name: ci + +on: + pull_request: +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v2 + + - name: deps + run: npm ci + + - name: tests + run: npm run test + + - name: eslint + run: npm run lint + + - name: prettier + run: npm run format diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b60c665 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,35 @@ +name: release + +on: + release: + types: [created] +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to registry + uses: docker/login-action@v1 + with: + registry: ${{ secrets.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_REGISTRY_USER }} + password: ${{ secrets.DOCKER_REGISTRY_PASS }} + + - name: Tag name + id: tag_name + run: echo ::set-output name=TAG_NAME::${GITHUB_REF/refs\/tags\//} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + push: true + tags: | + ${{ secrets.DOCKER_REGISTRY }}/vagahbond/uni-verse/api + ${{ secrets.DOCKER_REGISTRY }}/vagahbond/uni-verse/api:${{ steps.tag_name.outputs.TAG_NAME }} + - name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..743370c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM node:16-alpine as builder + +WORKDIR /usr/src/app + +COPY ./package*.json ./ +RUN npm ci + +COPY . . + +RUN npm run prebuild +RUN npm run build + +RUN npm prune --production + +FROM node:16-alpine + +WORKDIR /usr/src/app + +COPY --from=builder /usr/src/app/package*.json ./ +COPY --from=builder /usr/src/app/node_modules ./node_modules +COPY --from=builder /usr/src/app/dist ./dist + + +CMD ["npm", "run", "start:prod"] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0c9b3c5..716fe29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "uni-verse-api", "version": "0.0.1", "license": "UNLICENSED", "dependencies": { @@ -48,7 +49,7 @@ "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", - "eslint": "^8.0.1", + "eslint": "^8.9.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^27.2.5", diff --git a/package.json b/package.json index da190e0..23a17d4 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", - "eslint": "^8.0.1", + "eslint": "^8.9.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^27.2.5", diff --git a/src/app.module.ts b/src/app.module.ts index 4af7dcc..c3d7d59 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,5 +1,4 @@ import { Module } from '@nestjs/common'; -import { MongooseModule } from '@nestjs/mongoose'; import { AuthModule } from './auth/auth.module'; import { UsersModule } from './users/users.module'; import { Database } from './database'; @@ -9,12 +8,12 @@ import { ResourcePacksModule } from './resource-packs/resource-packs.module'; import { PlaylistsModule } from './playlists/playlists.module'; @Module({ imports: [ - AuthModule, + AuthModule, UsersModule, ReleasesModule, ResourcePacksModule, PlaylistsModule, - DatabaseModule + DatabaseModule, ], controllers: [], providers: [Database], diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 057f0fc..991baf4 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -3,12 +3,10 @@ import { JwtService } from '@nestjs/jwt'; @Injectable() export class AuthService { - constructor( - private jwtService: JwtService - ) {} + constructor(private jwtService: JwtService) {} - async login(userId: string) { - const payload = { userId }; - return this.jwtService.sign(payload) - } + async login(userId: string) { + const payload = { userId }; + return this.jwtService.sign(payload); + } } diff --git a/src/auth/constants.ts b/src/auth/constants.ts index 6b03df6..8b22f8b 100644 --- a/src/auth/constants.ts +++ b/src/auth/constants.ts @@ -1,3 +1,3 @@ export const jwtConstants = { - secret: 'secretKey', -}; \ No newline at end of file + secret: 'secretKey', +}; diff --git a/src/auth/decorators/public.decorator.ts b/src/auth/decorators/public.decorator.ts index fcdbe9f..466abc7 100644 --- a/src/auth/decorators/public.decorator.ts +++ b/src/auth/decorators/public.decorator.ts @@ -1,2 +1,2 @@ import { SetMetadata } from '@nestjs/common'; -export const Public = () => SetMetadata('isPublic', true); \ No newline at end of file +export const Public = () => SetMetadata('isPublic', true); diff --git a/src/auth/guards/jwt-auth.guard.ts b/src/auth/guards/jwt-auth.guard.ts index 6cd2c9a..2086fac 100644 --- a/src/auth/guards/jwt-auth.guard.ts +++ b/src/auth/guards/jwt-auth.guard.ts @@ -4,20 +4,20 @@ import { AuthGuard } from '@nestjs/passport'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { - constructor(private readonly reflector: Reflector) { - super(); - } - - canActivate(context: ExecutionContext) { - const isPublic = this.reflector.get( - 'isPublic', - context.getHandler() - ); - - if (isPublic) { - return true; - } - - return super.canActivate(context); - } + constructor(private readonly reflector: Reflector) { + super(); + } + + canActivate(context: ExecutionContext) { + const isPublic = this.reflector.get( + 'isPublic', + context.getHandler(), + ); + + if (isPublic) { + return true; + } + + return super.canActivate(context); + } } diff --git a/src/auth/strategies/jwt.strategy.ts b/src/auth/strategies/jwt.strategy.ts index bb2bc22..43a1778 100644 --- a/src/auth/strategies/jwt.strategy.ts +++ b/src/auth/strategies/jwt.strategy.ts @@ -16,4 +16,4 @@ export class JwtStrategy extends PassportStrategy(Strategy) { async validate(payload: any) { return { userId: payload.sub, username: payload.username }; } -} \ No newline at end of file +} diff --git a/src/database/database.module.ts b/src/database/database.module.ts index 9f7adf0..fa9bb84 100644 --- a/src/database/database.module.ts +++ b/src/database/database.module.ts @@ -2,7 +2,7 @@ import { Module } from '@nestjs/common'; import { databaseProviders } from './database.provider'; @Module({ - providers: [...databaseProviders], - exports: [...databaseProviders], + providers: [...databaseProviders], + exports: [...databaseProviders], }) -export class DatabaseModule { } +export class DatabaseModule {} diff --git a/src/database/database.provider.ts b/src/database/database.provider.ts index 2f2890e..9a7f472 100644 --- a/src/database/database.provider.ts +++ b/src/database/database.provider.ts @@ -1,4 +1,4 @@ -import mongoose from "mongoose"; +import mongoose from 'mongoose'; const mongoHostName = process.env.MONGO_HOSNAME || 'localhost'; const mongoUsername = process.env.MONGO_USER; @@ -6,9 +6,11 @@ const mongoPassword = process.env.MONGO_PASSWORD; const mongoPort = process.env.MONGO_PORT || 27017; export const databaseProviders = [ - { - provide: 'DATABASE_CONNECTION', - useFactory: (): Promise => - mongoose.connect(`mongodb://${mongoUsername}:${mongoPassword}@${mongoHostName}:${mongoPort}`), - }, -]; \ No newline at end of file + { + provide: 'DATABASE_CONNECTION', + useFactory: (): Promise => + mongoose.connect( + `mongodb://${mongoUsername}:${mongoPassword}@${mongoHostName}:${mongoPort}`, + ), + }, +]; diff --git a/src/main.ts b/src/main.ts index 281630a..0ded931 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,7 +3,7 @@ import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { AppModule } from './app.module'; import { JwtAuthGuard } from './auth/guards/jwt-auth.guard'; -const API_VERSION = 2 +const API_VERSION = 2; async function bootstrap() { const app = await NestFactory.create(AppModule); diff --git a/src/playlists/playlists.controller.ts b/src/playlists/playlists.controller.ts index 09185a5..6672f5b 100644 --- a/src/playlists/playlists.controller.ts +++ b/src/playlists/playlists.controller.ts @@ -1,4 +1,12 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from '@nestjs/common'; import { PlaylistsService } from './playlists.service'; import { CreatePlaylistDto } from './dto/create-playlist.dto'; import { UpdatePlaylistDto } from './dto/update-playlist.dto'; @@ -23,7 +31,10 @@ export class PlaylistsController { } @Patch(':id') - update(@Param('id') id: string, @Body() updatePlaylistDto: UpdatePlaylistDto) { + update( + @Param('id') id: string, + @Body() updatePlaylistDto: UpdatePlaylistDto, + ) { return this.playlistsService.update(+id, updatePlaylistDto); } diff --git a/src/playlists/playlists.module.ts b/src/playlists/playlists.module.ts index 8293543..1a62a70 100644 --- a/src/playlists/playlists.module.ts +++ b/src/playlists/playlists.module.ts @@ -4,6 +4,6 @@ import { PlaylistsController } from './playlists.controller'; @Module({ controllers: [PlaylistsController], - providers: [PlaylistsService] + providers: [PlaylistsService], }) export class PlaylistsModule {} diff --git a/src/playlists/playlists.service.ts b/src/playlists/playlists.service.ts index 2286313..3910886 100644 --- a/src/playlists/playlists.service.ts +++ b/src/playlists/playlists.service.ts @@ -4,6 +4,7 @@ import { UpdatePlaylistDto } from './dto/update-playlist.dto'; @Injectable() export class PlaylistsService { + // eslint-disable-next-line @typescript-eslint/no-unused-vars create(createPlaylistDto: CreatePlaylistDto) { return 'This action adds a new playlist'; } @@ -16,6 +17,7 @@ export class PlaylistsService { return `This action returns a #${id} playlist`; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars update(id: number, updatePlaylistDto: UpdatePlaylistDto) { return `This action updates a #${id} playlist`; } diff --git a/src/releases/releases.controller.ts b/src/releases/releases.controller.ts index ea805a8..e34b833 100644 --- a/src/releases/releases.controller.ts +++ b/src/releases/releases.controller.ts @@ -1,4 +1,12 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from '@nestjs/common'; import { ReleasesService } from './releases.service'; import { CreateReleaseDto } from './dto/create-release.dto'; import { UpdateReleaseDto } from './dto/update-release.dto'; diff --git a/src/releases/releases.module.ts b/src/releases/releases.module.ts index 57d24d3..dcc7935 100644 --- a/src/releases/releases.module.ts +++ b/src/releases/releases.module.ts @@ -4,6 +4,6 @@ import { ReleasesController } from './releases.controller'; @Module({ controllers: [ReleasesController], - providers: [ReleasesService] + providers: [ReleasesService], }) export class ReleasesModule {} diff --git a/src/releases/releases.service.ts b/src/releases/releases.service.ts index 4c51aa8..44f92b5 100644 --- a/src/releases/releases.service.ts +++ b/src/releases/releases.service.ts @@ -4,6 +4,7 @@ import { UpdateReleaseDto } from './dto/update-release.dto'; @Injectable() export class ReleasesService { + // eslint-disable-next-line @typescript-eslint/no-unused-vars create(createReleaseDto: CreateReleaseDto) { return 'This action adds a new release'; } @@ -16,6 +17,7 @@ export class ReleasesService { return `This action returns a #${id} release`; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars update(id: number, updateReleaseDto: UpdateReleaseDto) { return `This action updates a #${id} release`; } diff --git a/src/resource-packs/resource-packs.controller.ts b/src/resource-packs/resource-packs.controller.ts index 61d7afe..c255102 100644 --- a/src/resource-packs/resource-packs.controller.ts +++ b/src/resource-packs/resource-packs.controller.ts @@ -1,4 +1,12 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Patch, + Param, + Delete, +} from '@nestjs/common'; import { ResourcePacksService } from './resource-packs.service'; import { CreateResourcePackDto } from './dto/create-resource-pack.dto'; import { UpdateResourcePackDto } from './dto/update-resource-pack.dto'; @@ -23,7 +31,10 @@ export class ResourcePacksController { } @Patch(':id') - update(@Param('id') id: string, @Body() updateResourcePackDto: UpdateResourcePackDto) { + update( + @Param('id') id: string, + @Body() updateResourcePackDto: UpdateResourcePackDto, + ) { return this.resourcePacksService.update(+id, updateResourcePackDto); } diff --git a/src/resource-packs/resource-packs.module.ts b/src/resource-packs/resource-packs.module.ts index e2b7230..22a9452 100644 --- a/src/resource-packs/resource-packs.module.ts +++ b/src/resource-packs/resource-packs.module.ts @@ -4,6 +4,6 @@ import { ResourcePacksController } from './resource-packs.controller'; @Module({ controllers: [ResourcePacksController], - providers: [ResourcePacksService] + providers: [ResourcePacksService], }) export class ResourcePacksModule {} diff --git a/src/resource-packs/resource-packs.service.ts b/src/resource-packs/resource-packs.service.ts index b8bfb99..e5280ef 100644 --- a/src/resource-packs/resource-packs.service.ts +++ b/src/resource-packs/resource-packs.service.ts @@ -4,6 +4,7 @@ import { UpdateResourcePackDto } from './dto/update-resource-pack.dto'; @Injectable() export class ResourcePacksService { + // eslint-disable-next-line @typescript-eslint/no-unused-vars create(createResourcePackDto: CreateResourcePackDto) { return 'This action adds a new resourcePack'; } @@ -16,6 +17,7 @@ export class ResourcePacksService { return `This action returns a #${id} resourcePack`; } + // eslint-disable-next-line @typescript-eslint/no-unused-vars update(id: number, updateResourcePackDto: UpdateResourcePackDto) { return `This action updates a #${id} resourcePack`; } diff --git a/src/users/dto/create-user.dto.ts b/src/users/dto/create-user.dto.ts index 054c579..9964ec4 100644 --- a/src/users/dto/create-user.dto.ts +++ b/src/users/dto/create-user.dto.ts @@ -1,22 +1,28 @@ -import { IsNotEmpty, MinLength, MaxLength, IsEmail, IsString } from 'class-validator'; +import { + IsNotEmpty, + MinLength, + MaxLength, + IsEmail, + IsString, +} from 'class-validator'; export class CreateUserDto { - @IsNotEmpty() - @IsString() - @MinLength(5) - @MaxLength(255) - readonly username: string; + @IsNotEmpty() + @IsString() + @MinLength(5) + @MaxLength(255) + readonly username: string; - @IsNotEmpty() - @IsString() - @MinLength(5) - @MaxLength(255) - @IsEmail() - readonly email: string; + @IsNotEmpty() + @IsString() + @MinLength(5) + @MaxLength(255) + @IsEmail() + readonly email: string; - @IsNotEmpty() - @IsString() - @MinLength(5) - @MaxLength(1024) - readonly password: string; + @IsNotEmpty() + @IsString() + @MinLength(5) + @MaxLength(1024) + readonly password: string; } diff --git a/src/users/dto/login-user.dto.ts b/src/users/dto/login-user.dto.ts index 795f445..c774e09 100644 --- a/src/users/dto/login-user.dto.ts +++ b/src/users/dto/login-user.dto.ts @@ -1,17 +1,22 @@ -import { IsNotEmpty, MinLength, MaxLength, IsEmail, IsString } from 'class-validator'; +import { + IsNotEmpty, + MinLength, + MaxLength, + IsEmail, + IsString, +} from 'class-validator'; export class LoginUserDto { - - @IsNotEmpty() - @IsString() - @MinLength(5) - @MaxLength(255) - @IsEmail() - readonly email: string; + @IsNotEmpty() + @IsString() + @MinLength(5) + @MaxLength(255) + @IsEmail() + readonly email: string; - @IsNotEmpty() - @IsString() - @MinLength(5) - @MaxLength(1024) - readonly password: string; -} \ No newline at end of file + @IsNotEmpty() + @IsString() + @MinLength(5) + @MaxLength(1024) + readonly password: string; +} diff --git a/src/users/interfaces/user.interface.ts b/src/users/interfaces/user.interface.ts index 0302218..61635aa 100644 --- a/src/users/interfaces/user.interface.ts +++ b/src/users/interfaces/user.interface.ts @@ -4,4 +4,4 @@ export interface User extends Document { readonly username: string; readonly email: string; readonly password: string; -} \ No newline at end of file +} diff --git a/src/users/providers/users.providers.ts b/src/users/providers/users.providers.ts index 3950224..1de7e2c 100644 --- a/src/users/providers/users.providers.ts +++ b/src/users/providers/users.providers.ts @@ -4,7 +4,8 @@ import { UserSchema } from '../schemas/user.schema'; export const usersProviders = [ { provide: 'USER_MODEL', - useFactory: (connection: Connection) => connection.model('User', UserSchema), + useFactory: (connection: Connection) => + connection.model('User', UserSchema), inject: ['DATABASE_CONNECTION'], }, -]; \ No newline at end of file +]; diff --git a/src/users/schemas/user.schema.ts b/src/users/schemas/user.schema.ts index 596ad68..f4381bc 100644 --- a/src/users/schemas/user.schema.ts +++ b/src/users/schemas/user.schema.ts @@ -2,46 +2,49 @@ import * as mongoose from 'mongoose'; import validator from 'validator'; import * as bcrypt from 'bcrypt'; -export const UserSchema = new mongoose.Schema({ +export const UserSchema = new mongoose.Schema( + { username: { - type: String, - minlength: 6, - maxlength: 255, - required: [true, 'USERNAME_IS_BLANK'], + type: String, + minlength: 6, + maxlength: 255, + required: [true, 'USERNAME_IS_BLANK'], }, email: { - type: String, - lowercase: true, - validate: validator.isEmail, - maxlength: 255, - minlength: 6, - required: [true, 'EMAIL_IS_BLANK'], + type: String, + lowercase: true, + validate: validator.isEmail, + maxlength: 255, + minlength: 6, + required: [true, 'EMAIL_IS_BLANK'], }, password: { - type: String, - minlength: 5, - maxlength: 1024, - required: [true, 'PASSWORD_IS_BLANK'], + type: String, + minlength: 5, + maxlength: 1024, + required: [true, 'PASSWORD_IS_BLANK'], }, -}, { + }, + { versionKey: false, timestamps: true, -}); + }, +); -UserSchema.pre('save', async function(next) { - try { - if (!this.isModified('password')) { - return next(); - } +UserSchema.pre('save', async function (next) { + try { + if (!this.isModified('password')) { + return next(); + } - console.log(bcrypt.genSalt()) + console.log(bcrypt.genSalt()); - const hashed = await bcrypt.hash(this['password'], 10); + const hashed = await bcrypt.hash(this['password'], 10); - this['password'] = hashed; - - return next(); - } catch (err) { - return next(err); - } - }); \ No newline at end of file + this['password'] = hashed; + + return next(); + } catch (err) { + return next(err); + } +}); diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index a4a7b2f..25b8f0f 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -1,4 +1,13 @@ -import { Controller, Get, Post, Body, Patch, Param, Delete, UseGuards, Query } from '@nestjs/common'; +import { + Controller, + Get, + Post, + Body, + Param, + Delete, + UseGuards, + Query, +} from '@nestjs/common'; import { UsersService } from './users.service'; import { CreateUserDto } from './dto/create-user.dto'; import { LoginUserDto } from './dto/login-user.dto'; diff --git a/src/users/users.module.ts b/src/users/users.module.ts index d9e2b04..02ad00c 100644 --- a/src/users/users.module.ts +++ b/src/users/users.module.ts @@ -6,15 +6,9 @@ import { UsersController } from './users.controller'; import { UsersService } from './users.service'; @Module({ - imports: [ - DatabaseModule, - AuthModule - ], - controllers: [UsersController], - providers: [ - UsersService, - ...usersProviders - ], - exports: [UsersService], + imports: [DatabaseModule, AuthModule], + controllers: [UsersController], + providers: [UsersService, ...usersProviders], + exports: [UsersService], }) -export class UsersModule { } +export class UsersModule {} diff --git a/src/users/users.service.ts b/src/users/users.service.ts index f53d99a..33b677c 100644 --- a/src/users/users.service.ts +++ b/src/users/users.service.ts @@ -1,4 +1,9 @@ -import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; +import { + BadRequestException, + Inject, + Injectable, + NotFoundException, +} from '@nestjs/common'; import { Model } from 'mongoose'; import { CreateUserDto } from './dto/create-user.dto'; import { LoginUserDto } from './dto/login-user.dto'; @@ -8,98 +13,99 @@ import { AuthService } from 'src/auth/auth.service'; @Injectable() export class UsersService { + constructor( + private authService: AuthService, + @Inject('USER_MODEL') + private userModel: Model, + ) {} - constructor( - private authService: AuthService, - @Inject('USER_MODEL') - private userModel: Model, - ) { } + async create(createUserDto: CreateUserDto): Promise { + const user = new this.userModel(createUserDto); + await this.isEmailUnique(user.email); + await this.isUsernameUnique(user.username); + await user.save(); + return this.buildRegistrationInfo(user); + } - async create(createUserDto: CreateUserDto): Promise { - const user = new this.userModel(createUserDto); - await this.isEmailUnique(user.email); - await this.isUsernameUnique(user.username); - await user.save(); - return this.buildRegistrationInfo(user); - } + async login(loginUserDto: LoginUserDto) { + const user = await await this.userModel.findOne({ + email: loginUserDto.email, + }); + await this.checkPassword(loginUserDto.password, user); + return { + username: user.username, + email: user.email, + jwt: await this.authService.login(user._id), + }; + } - async login(loginUserDto: LoginUserDto) { - const user = await await this.userModel.findOne({'email': loginUserDto.email}); - await this.checkPassword(loginUserDto.password, user); - return { - username: user.username, - email: user.email, - jwt: await this.authService.login(user._id), - }; - } - - async findAll() { - const users = await this.userModel.find() - return { - ...users - } - } + async findAll() { + const users = await this.userModel.find(); + return { + ...users, + }; + } - async remove(username: string) { - const user = await this.findUserByUsername(username); - await this.userModel.remove(user) - return { - email: user.email, - msg: "user deleted", - } - } + async remove(username: string) { + const user = await this.findUserByUsername(username); + await this.userModel.remove(user); + return { + email: user.email, + msg: 'user deleted', + }; + } - private async checkPassword(password: string, user: User) { - const match = await bcrypt.compare(password, user.password); - if (!match) { - throw new NotFoundException('Wrong email or password.'); - } - return match; - } + private async checkPassword(password: string, user: User) { + const match = await bcrypt.compare(password, user.password); + if (!match) { + throw new NotFoundException('Wrong email or password.'); + } + return match; + } - private buildRegistrationInfo(user): any { - const userRegistrationInfo = { - username: user.username, - email: user.email, - }; - return userRegistrationInfo; - } + private buildRegistrationInfo(user): any { + const userRegistrationInfo = { + username: user.username, + email: user.email, + }; + return userRegistrationInfo; + } - private async isUsernameUnique(username: string) { - const user = await this.userModel.findOne({ 'username': username }); - if (user) { - throw new BadRequestException('Username must be unique.'); - } - } + private async isUsernameUnique(username: string) { + const user = await this.userModel.findOne({ username: username }); + if (user) { + throw new BadRequestException('Username must be unique.'); + } + } - private async isEmailUnique(email: string) { - const user = await this.userModel.findOne({ 'email': email }); - if (user) { - throw new BadRequestException('Email must be unique.'); - } - } + private async isEmailUnique(email: string) { + const user = await this.userModel.findOne({ email: email }); + if (user) { + throw new BadRequestException('Email must be unique.'); + } + } - async findUserByUsername(username: string): Promise { - const user = await this.userModel.findOne({ username }); - if (!user) { - throw new BadRequestException("This user doesn't exist"); - } - return this.buildUserInfo(user); - } + async findUserByUsername(username: string): Promise { + const user = await this.userModel.findOne({ username }); + if (!user) { + throw new BadRequestException("This user doesn't exist"); + } + return this.buildUserInfo(user); + } - async findUserByEmail(email: string): Promise { - const user = await this.userModel.findOne({ email }); - if (!user) { - throw new BadRequestException("This user doesn't exist"); - } - return this.buildUserInfo(user); - } + async findUserByEmail(email: string): Promise { + const user = await this.userModel.findOne({ email }); + if (!user) { + throw new BadRequestException("This user doesn't exist"); + } + return this.buildUserInfo(user); + } - private buildUserInfo(user): any { - const userUserInfo = { - username: user.username, - email: user.email, - }; - return userUserInfo; - } + private buildUserInfo(user): any { + const userUserInfo = { + username: user.username, + email: user.email, + }; + return userUserInfo; + } }