diff --git a/package-lock.json b/package-lock.json index f4cf9c2..e542fdb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1270,6 +1270,15 @@ "tslib": "2.3.0" } }, + "@nestjs/schedule": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/schedule/-/schedule-1.0.1.tgz", + "integrity": "sha512-EU2tB4rxuEgum8JlorAFvXkU982EYZm/IBa7n6kgkyps5BbxQSFf7iR1CLkP9zODO9ApZTWk5z3q9L3O7vrkoQ==", + "requires": { + "cron": "1.7.2", + "uuid": "8.3.2" + } + }, "@nestjs/schematics": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-8.0.2.tgz", @@ -3050,6 +3059,14 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, + "cron": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/cron/-/cron-1.7.2.tgz", + "integrity": "sha512-+SaJ2OfeRvfQqwXQ2kgr0Y5pzBR/lijf5OpnnaruwWnmI799JfWr2jN2ItOV9s3A/+TFOt6mxvKzQq5F0Jp6VQ==", + "requires": { + "moment-timezone": "^0.5.x" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6931,6 +6948,19 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.33", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", + "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "requires": { + "moment": ">= 2.9.0" + } + }, "moo": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", @@ -7006,6 +7036,14 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" }, + "node-cron": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz", + "integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==", + "requires": { + "moment-timezone": "^0.5.31" + } + }, "node-emoji": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", diff --git a/package.json b/package.json index 991b25f..85b979a 100644 --- a/package.json +++ b/package.json @@ -25,12 +25,14 @@ "@nestjs/common": "^8.0.0", "@nestjs/core": "^8.0.0", "@nestjs/platform-express": "^8.0.0", + "@nestjs/schedule": "^1.0.1", "bcrypt": "^5.0.1", "class-validator": "^0.13.1", "dotenv": "^10.0.0", "express": "^4.17.1", "handlebars": "^4.7.7", "jsonwebtoken": "^8.5.1", + "node-cron": "^3.0.0", "nodemailer": "^6.6.3", "pg": "^8.7.1", "pg-promise": "^10.11.0", diff --git a/src/app.controller.spec.ts b/src/app.controller.spec.ts deleted file mode 100644 index d22f389..0000000 --- a/src/app.controller.spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { AppController } from './app.controller'; -import { AppService } from './app.service'; - -describe('AppController', () => { - let appController: AppController; - - beforeEach(async () => { - const app: TestingModule = await Test.createTestingModule({ - controllers: [AppController], - providers: [AppService], - }).compile(); - - appController = app.get(AppController); - }); - - describe('root', () => { - it('should return "Hello World!"', () => { - expect(appController.getHello()).toBe('Hello World!'); - }); - }); -}); diff --git a/src/app.module.ts b/src/app.module.ts index 0cc2d2d..53d2db9 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,11 +1,20 @@ import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { UserAuthModule } from './user-auth/user-auth.module'; +import { UserAuthModule } from './userAuth/userAuth.module'; import { PasswordModule } from './password/password.module'; +import { UserGroupModule } from './user-group/user-group.module'; +import { CronModule } from './schedule/schedule.module'; +import { ScheduleModule } from '@nestjs/schedule'; @Module({ - imports: [UserAuthModule, PasswordModule], + imports: [ + UserAuthModule, + PasswordModule, + UserGroupModule, + CronModule, + ScheduleModule.forRoot(), + ], controllers: [AppController], providers: [AppService], }) diff --git a/src/database/database.module.ts b/src/modules/database/database.module.ts similarity index 100% rename from src/database/database.module.ts rename to src/modules/database/database.module.ts diff --git a/src/password/dto/changePassword.dto.ts b/src/modules/password/dto/changePassword.dto.ts similarity index 100% rename from src/password/dto/changePassword.dto.ts rename to src/modules/password/dto/changePassword.dto.ts diff --git a/src/password/dto/forgotPassword.dto.ts b/src/modules/password/dto/forgotPassword.dto.ts similarity index 100% rename from src/password/dto/forgotPassword.dto.ts rename to src/modules/password/dto/forgotPassword.dto.ts diff --git a/src/password/password.controller.ts b/src/modules/password/password.controller.ts similarity index 73% rename from src/password/password.controller.ts rename to src/modules/password/password.controller.ts index b507c80..2555703 100644 --- a/src/password/password.controller.ts +++ b/src/modules/password/password.controller.ts @@ -1,5 +1,5 @@ import { Body, Controller, Post, Req } from '@nestjs/common'; -import { ChangePasswordDto } from 'src/password/dto/changePassword.dto'; +import { ChangePasswordDto } from '../password/dto/changePassword.dto'; import { Request } from 'express'; import { PasswordService } from './password.service'; @@ -16,11 +16,8 @@ export class PasswordController { } @Post('sendmail') - async forgotPassword( - @Body() password: ChangePasswordDto, - @Req() req: Request, - ) { - return await this.passwordService.forgotPassword(password, req); + async forgotPassword(@Req() req: Request) { + return await this.passwordService.forgotPassword(req); } @Post('forgotpassword') diff --git a/src/password/password.module.ts b/src/modules/password/password.module.ts similarity index 100% rename from src/password/password.module.ts rename to src/modules/password/password.module.ts diff --git a/src/password/password.service.ts b/src/modules/password/password.service.ts similarity index 79% rename from src/password/password.service.ts rename to src/modules/password/password.service.ts index a257ba2..70f6165 100644 --- a/src/password/password.service.ts +++ b/src/modules/password/password.service.ts @@ -1,10 +1,9 @@ -import { Body, Injectable, Req } from '@nestjs/common'; +import { Body, Injectable } from '@nestjs/common'; import * as jwt from 'jsonwebtoken'; import * as nodemailer from 'nodemailer'; -import { Request } from 'express'; -import { ChangePasswordDto } from 'src/password/dto/changePassword.dto'; -import { client } from 'src/database/database.module'; -import { resMessage } from 'src/user-auth/helper/resMessage'; +import { ChangePasswordDto } from '../password/dto/changePassword.dto'; +import { client } from 'src/modules/database/database.module'; +import { resMessage } from '../userAuth/helper/resMessage'; @Injectable() export class PasswordService { @@ -13,7 +12,7 @@ export class PasswordService { * @param password oldPassword and NewPassword * @returns Password Status */ - async changePassword(password: ChangePasswordDto, @Req() req: Request) { + async changePassword(password: ChangePasswordDto, req) { const oldPassword = password.oldpassword; const newPassword = password.newpassword; @@ -34,7 +33,7 @@ export class PasswordService { } } - async forgotPassword(password: ChangePasswordDto, @Req() req: Request) { + async forgotPassword(req) { const email = req.body.email; if (email) { const transporter = nodemailer.createTransport({ @@ -68,8 +67,8 @@ export class PasswordService { } } - async setPassword(@Body() password: ChangePasswordDto, @Req() req: Request) { - const newPassword = req.body.newpassword; + async setPassword(@Body() password: ChangePasswordDto, req) { + const newPassword = password.newpassword; const bearerHeader = req.headers.authorization.replace('Bearer ', ''); const jwtData = jwt.verify(bearerHeader, process.env.ACCESS_TOKEN); diff --git a/src/modules/schedule/schedule.module.ts b/src/modules/schedule/schedule.module.ts new file mode 100644 index 0000000..2215a39 --- /dev/null +++ b/src/modules/schedule/schedule.module.ts @@ -0,0 +1,7 @@ +import { Module } from '@nestjs/common'; +import { ScheduleService } from './schedule.service'; + +@Module({ + providers: [ScheduleService], +}) +export class CronModule {} diff --git a/src/modules/schedule/schedule.service.ts b/src/modules/schedule/schedule.service.ts new file mode 100644 index 0000000..91a4d25 --- /dev/null +++ b/src/modules/schedule/schedule.service.ts @@ -0,0 +1,17 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { Cron, CronExpression } from '@nestjs/schedule'; + +@Injectable() +export class ScheduleService { + private readonly logger = new Logger(ScheduleService.name); + + @Cron(CronExpression.EVERY_DAY_AT_10AM) + handleCron() { + this.logger.debug("Let's go for Coffee"); + } + + @Cron(CronExpression.EVERY_DAY_AT_9AM) + handleNewCron() { + console.log('Good Morning !'); + } +} diff --git a/src/modules/user-group/dto/createGroup.dto.ts b/src/modules/user-group/dto/createGroup.dto.ts new file mode 100644 index 0000000..91fbd8c --- /dev/null +++ b/src/modules/user-group/dto/createGroup.dto.ts @@ -0,0 +1,11 @@ +import { IsNotEmpty, IsOptional, IsString } from 'class-validator'; + +export class CreateGroupDto { + @IsNotEmpty() + @IsString() + groupName: string; + + @IsString() + @IsNotEmpty() + member1: string; +} diff --git a/src/modules/user-group/dto/groupMember.dto.ts b/src/modules/user-group/dto/groupMember.dto.ts new file mode 100644 index 0000000..352bb38 --- /dev/null +++ b/src/modules/user-group/dto/groupMember.dto.ts @@ -0,0 +1,25 @@ +import { IsBoolean, IsNotEmpty, IsString } from 'class-validator'; + +export class GroupMemberDto { + @IsString() + @IsNotEmpty() + id: string; + + @IsString() + @IsNotEmpty() + member_id: string; + + @IsString() + @IsNotEmpty() + group_id: string; + + @IsString() + @IsBoolean() + @IsNotEmpty() + is_admin: boolean; + + @IsString() + @IsBoolean() + @IsNotEmpty() + is_super_admin: boolean; +} diff --git a/src/modules/user-group/user-group.controller.ts b/src/modules/user-group/user-group.controller.ts new file mode 100644 index 0000000..a90fdc7 --- /dev/null +++ b/src/modules/user-group/user-group.controller.ts @@ -0,0 +1,29 @@ +import { Controller, Delete, Post, Put, Req } from '@nestjs/common'; +import { Request } from 'express'; +import { CreateGroupDto } from './dto/createGroup.dto'; +import { UserGroupService } from './user-group.service'; + +@Controller('api') +export class UserGroupController { + constructor(private userGroupService: UserGroupService) {} + + @Post('create-group') + async createGroup(createGroup: CreateGroupDto, @Req() req: Request) { + return await this.userGroupService.createGroup(createGroup, req); + } + + @Post('add-members') + async addMembers(@Req() req: Request) { + return await this.userGroupService.addMember(req); + } + + @Put('make-admin') + async makeAdmin(@Req() req: Request) { + return await this.userGroupService.makeAdmin(req); + } + + @Delete('remove-member') + async removeMember(@Req() req: Request) { + return await this.userGroupService.removeMember(req); + } +} diff --git a/src/modules/user-group/user-group.module.ts b/src/modules/user-group/user-group.module.ts new file mode 100644 index 0000000..689cc25 --- /dev/null +++ b/src/modules/user-group/user-group.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { UserGroupController } from './user-group.controller'; +import { UserGroupService } from './user-group.service'; + +@Module({ + controllers: [UserGroupController], + providers: [UserGroupService], +}) +export class UserGroupModule {} diff --git a/src/modules/user-group/user-group.service.ts b/src/modules/user-group/user-group.service.ts new file mode 100644 index 0000000..3fe6386 --- /dev/null +++ b/src/modules/user-group/user-group.service.ts @@ -0,0 +1,82 @@ +import { Injectable, Req } from '@nestjs/common'; +import * as jwt from 'jsonwebtoken'; +import { client } from 'src/modules/database/database.module'; +import { v4 as uuidv4 } from 'uuid'; +import { CreateGroupDto } from './dto/createGroup.dto'; + +@Injectable() +export class UserGroupService { + async createGroup(createGroup: CreateGroupDto, req) { + const groupName = createGroup.groupName; + + try { + const groupDetails = await client.query( + `INSERT INTO group_info (group_id, group_name) VALUES ('${uuidv4()}', '${groupName}')`, + ); + } catch { + return { message: 'GroupName Already Exists' }; + } + + const groupid = await client.query( + `SELECT group_id FROM group_info WHERE group_name='${groupName}'`, + ); + + const bearerHeader = req.headers.authorization.replace('Bearer ', ''); + const jwtData = jwt.verify(bearerHeader, process.env.ACCESS_TOKEN); + + const user_id = await client.query( + `SELECT id FROM userdata WHERE email='${jwtData['email']}'`, + ); + + const groupAdminDetails = await client.query( + `INSERT INTO group_member (id, member_id, group_id, is_admin, is_super_admin) VALUES ('${uuidv4()}', '${ + user_id.rows[0]['id'] + }', '${groupid.rows[0]['group_id']}', true, true)`, + ); + return { message: 'Group Created' }; + } + + async addMember(req) { + const groupMember = req.body.member; + const groupName = req.body.groupname; + const groupMemberAdmin = req.body.isadmin; + + const groupid = await client.query( + `SELECT group_id FROM group_info WHERE group_name='${groupName}'`, + ); + + try { + const existGroupId = await client.query( + `SELECT group_id FROM group_member WHERE member_id='${groupMemberAdmin}'`, + ); + } catch { + return { message: 'User Already in Group' }; + } + + const groupMemberDetails = await client.query( + `INSERT INTO group_member (id, member_id, group_id, is_admin, is_super_admin) VALUES ('${uuidv4()}', '${groupMember}', '${ + groupid.rows[0]['group_id'] + }', '${groupMemberAdmin}', false)`, + ); + return { message: 'Member Added' }; + } + + async makeAdmin(req) { + const groupMember = req.body.member; + const groupMemberAdmin = req.body.isadmin; + + const makeAdmin = await client.query( + `UPDATE group_member SET is_admin='${groupMemberAdmin}' WHERE member_id='${groupMember}'`, + ); + return { message: 'Admin Added' }; + } + + async removeMember(req) { + const groupMember = req.body.member; + + const removeMember = await client.query( + `DELETE FROM group_member WHERE member_id='${groupMember}'`, + ); + return { message: 'Removed Successfully' }; + } +} diff --git a/src/user-auth/dto/user.dto.ts b/src/modules/userAuth/dto/user.dto.ts similarity index 100% rename from src/user-auth/dto/user.dto.ts rename to src/modules/userAuth/dto/user.dto.ts diff --git a/src/user-auth/helper/resMessage.ts b/src/modules/userAuth/helper/resMessage.ts similarity index 100% rename from src/user-auth/helper/resMessage.ts rename to src/modules/userAuth/helper/resMessage.ts diff --git a/src/user-auth/user-auth.controller.ts b/src/modules/userAuth/userAuth.controller.ts similarity index 50% rename from src/user-auth/user-auth.controller.ts rename to src/modules/userAuth/userAuth.controller.ts index d9eebba..0854fe8 100644 --- a/src/user-auth/user-auth.controller.ts +++ b/src/modules/userAuth/userAuth.controller.ts @@ -1,6 +1,6 @@ -import { Body, Controller, Post, Req } from '@nestjs/common'; +import { Body, Controller, Post } from '@nestjs/common'; import { UserDto } from './dto/user.dto'; -import { UserAuthService } from './user-auth.service'; +import { UserAuthService } from './userAuth.service'; @Controller('api') export class UserAuthController { @@ -8,11 +8,13 @@ export class UserAuthController { @Post('signup') async signup(@Body() user: UserDto) { - return await this.userAuthsService.signup(user); + const signupData = await this.userAuthsService.signup(user); + return signupData; } @Post('login') async login(@Body() user: UserDto) { - return await this.userAuthsService.login(user); + const loginData = await this.userAuthsService.login(user); + return loginData; } } diff --git a/src/user-auth/user-auth.module.ts b/src/modules/userAuth/userAuth.module.ts similarity index 57% rename from src/user-auth/user-auth.module.ts rename to src/modules/userAuth/userAuth.module.ts index 2adee2f..8adec3b 100644 --- a/src/user-auth/user-auth.module.ts +++ b/src/modules/userAuth/userAuth.module.ts @@ -1,6 +1,6 @@ import { Module } from '@nestjs/common'; -import { UserAuthController } from './user-auth.controller'; -import { UserAuthService } from './user-auth.service'; +import { UserAuthController } from './userAuth.controller'; +import { UserAuthService } from './userAuth.service'; @Module({ controllers: [UserAuthController], diff --git a/src/user-auth/user-auth.service.ts b/src/modules/userAuth/userAuth.service.ts similarity index 89% rename from src/user-auth/user-auth.service.ts rename to src/modules/userAuth/userAuth.service.ts index 9a00394..7fad67c 100644 --- a/src/user-auth/user-auth.service.ts +++ b/src/modules/userAuth/userAuth.service.ts @@ -1,10 +1,10 @@ -import { Body, Injectable } from '@nestjs/common'; +import { BadRequestException, Body, Injectable } from '@nestjs/common'; import { UserDto } from './dto/user.dto'; import { resMessage } from './helper/resMessage'; import * as jwt from 'jsonwebtoken'; import * as bcrypt from 'bcrypt'; import { v4 as uuidv4 } from 'uuid'; -import { client } from 'src/database/database.module'; +import { client } from 'src/modules/database/database.module'; @Injectable() export class UserAuthService { @@ -52,7 +52,9 @@ export class UserAuthService { const userToken = await this.generateAccessToken(email); return { Token: userToken }; } else { - return { message: resMessage.messages.InvalidLoginData }; + throw new BadRequestException( + 'Your login information was incorrect. Please check and try again.', + ); } } else { return { message: resMessage.messages.UserNotExists }; diff --git a/src/password/password.controller.spec.ts b/src/password/password.controller.spec.ts deleted file mode 100644 index 7b581c5..0000000 --- a/src/password/password.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PasswordController } from './password.controller'; - -describe('PasswordController', () => { - let controller: PasswordController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [PasswordController], - }).compile(); - - controller = module.get(PasswordController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/password/password.service.spec.ts b/src/password/password.service.spec.ts deleted file mode 100644 index 730923b..0000000 --- a/src/password/password.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { PasswordService } from './password.service'; - -describe('PasswordService', () => { - let service: PasswordService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [PasswordService], - }).compile(); - - service = module.get(PasswordService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/src/user-auth/user-auth.controller.spec.ts b/src/user-auth/user-auth.controller.spec.ts deleted file mode 100644 index e975969..0000000 --- a/src/user-auth/user-auth.controller.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UserAuthController } from './user-auth.controller'; - -describe('UserAuthController', () => { - let controller: UserAuthController; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [UserAuthController], - }).compile(); - - controller = module.get(UserAuthController); - }); - - it('should be defined', () => { - expect(controller).toBeDefined(); - }); -}); diff --git a/src/user-auth/user-auth.service.spec.ts b/src/user-auth/user-auth.service.spec.ts deleted file mode 100644 index 3fda1c5..0000000 --- a/src/user-auth/user-auth.service.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { UserAuthService } from './user-auth.service'; - -describe('UserAuthService', () => { - let service: UserAuthService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [UserAuthService], - }).compile(); - - service = module.get(UserAuthService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -});