-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding the users' crud endpoints #19
Changes from 7 commits
af0dd01
1711849
864ff0d
42d8a96
c48317f
0473fab
5e6ae3e
57bbb36
49546da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
-- CreateEnum | ||
CREATE TYPE "Role" AS ENUM ('BODY_ADMIN', 'BODY_MEMBER', 'USER'); | ||
|
||
-- CreateEnum | ||
CREATE TYPE "ApplicationStatus" AS ENUM ('SUBMITTED', 'ACCEPTED', 'REJECTED', 'NEEDS_REVIEW', 'FINISHED'); | ||
|
||
-- CreateTable | ||
CREATE TABLE "User" ( | ||
"authSchId" TEXT NOT NULL, | ||
"fullName" TEXT NOT NULL, | ||
"nickName" TEXT NOT NULL, | ||
"role" "Role" NOT NULL DEFAULT 'USER', | ||
"neptun" TEXT, | ||
"email" TEXT, | ||
"isSchResident" BOOLEAN NOT NULL, | ||
"isActiveVikStudent" BOOLEAN NOT NULL, | ||
"roomNumber" INTEGER, | ||
"profileImage" BYTEA, | ||
"canHelpNoobs" BOOLEAN NOT NULL DEFAULT false, | ||
"publicDesc" TEXT, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
"profileSeenAt" TIMESTAMP(3), | ||
|
||
CONSTRAINT "User_pkey" PRIMARY KEY ("authSchId") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "ApplicationPeriod" ( | ||
"id" SERIAL NOT NULL, | ||
"name" TEXT NOT NULL, | ||
"applicationPeriodStartAt" TIMESTAMP(3) NOT NULL, | ||
"applicationPeriodEndAt" TIMESTAMP(3) NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
"ticketsAreValid" BOOLEAN NOT NULL DEFAULT false, | ||
"authorId" TEXT NOT NULL, | ||
|
||
CONSTRAINT "ApplicationPeriod_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Application" ( | ||
"id" SERIAL NOT NULL, | ||
"userId" TEXT NOT NULL, | ||
"applicationPeriodId" INTEGER NOT NULL, | ||
"status" "ApplicationStatus" NOT NULL DEFAULT 'SUBMITTED', | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "Application_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateTable | ||
CREATE TABLE "Post" ( | ||
"id" SERIAL NOT NULL, | ||
"title" TEXT NOT NULL, | ||
"content" TEXT NOT NULL, | ||
"preview" TEXT NOT NULL, | ||
"visible" BOOLEAN NOT NULL DEFAULT true, | ||
"authorId" TEXT NOT NULL, | ||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"updatedAt" TIMESTAMP(3) NOT NULL, | ||
|
||
CONSTRAINT "Post_pkey" PRIMARY KEY ("id") | ||
); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "User_neptun_key" ON "User"("neptun"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "ApplicationPeriod_authorId_idx" ON "ApplicationPeriod"("authorId"); | ||
|
||
-- CreateIndex | ||
CREATE UNIQUE INDEX "Application_userId_applicationPeriodId_key" ON "Application"("userId", "applicationPeriodId"); | ||
|
||
-- CreateIndex | ||
CREATE INDEX "Post_authorId_idx" ON "Post"("authorId"); | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "ApplicationPeriod" ADD CONSTRAINT "ApplicationPeriod_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("authSchId") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Application" ADD CONSTRAINT "Application_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("authSchId") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Application" ADD CONSTRAINT "Application_applicationPeriodId_fkey" FOREIGN KEY ("applicationPeriodId") REFERENCES "ApplicationPeriod"("id") ON DELETE RESTRICT ON UPDATE CASCADE; | ||
|
||
-- AddForeignKey | ||
ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("authSchId") ON DELETE RESTRICT ON UPDATE CASCADE; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Please do not edit this file manually | ||
# It should be added in your version-control system (i.e. Git) | ||
provider = "postgresql" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { IsBoolean, IsEmail, IsNumber, IsOptional, IsString } from 'class-validator'; | ||
|
||
export class UpdateUserAdminDto { | ||
@IsString() | ||
@IsOptional() | ||
nickName: string; | ||
|
||
@IsBoolean() | ||
@IsOptional() | ||
isSchResident: boolean; | ||
|
||
@IsNumber() | ||
@IsOptional() | ||
roomNumber: number; | ||
|
||
@IsEmail() | ||
@IsOptional() | ||
email: string; | ||
|
||
@IsBoolean() | ||
@IsOptional() | ||
canHelpNoobs: boolean; | ||
|
||
@IsString() | ||
@IsOptional() | ||
publicDesc: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { IsBoolean, IsEmail, IsNumber, IsOptional, IsString } from 'class-validator'; | ||
|
||
export class UpdateUserDto { | ||
@IsString() | ||
@IsOptional() | ||
nickName: string; | ||
|
||
@IsBoolean() | ||
@IsOptional() | ||
isSchResident: boolean; | ||
|
||
@IsNumber() | ||
@IsOptional() | ||
roomNumber: number; | ||
|
||
@IsEmail() | ||
@IsOptional() | ||
email: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { Role } from '@prisma/client'; | ||
|
||
export class UserEntity { | ||
authSchId: string; | ||
fullName: string; | ||
nickName: string; | ||
role: Role; | ||
neptun?: string; | ||
email?: string; | ||
isSchResident: boolean; | ||
isActiveVikStudent: boolean; | ||
roomNumber?: number; | ||
profileImage?: Buffer; | ||
canHelpNoobs: boolean; | ||
publicDesc?: string; | ||
createdAt: Date; | ||
updatedAt: Date; | ||
profileSeenAt?: Date; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,49 @@ | ||
import { Controller } from '@nestjs/common'; | ||
import { CurrentUser } from '@kir-dev/passport-authsch'; | ||
import { Body, Controller, Get, Param, ParseIntPipe, Patch, Query, UseGuards } from '@nestjs/common'; | ||
import { AuthGuard } from '@nestjs/passport'; | ||
import { Role } from '@prisma/client'; | ||
|
||
import { Roles } from '../auth/decorators/Roles.decorator'; | ||
import { RolesGuard } from '../auth/roles.guard'; | ||
import { UpdateUserDto } from './dto/update-user.dto'; | ||
import { UserEntity } from './entities/user.entity'; | ||
import { UserService } from './user.service'; | ||
|
||
@Controller('user') | ||
@Controller('users') | ||
export class UserController { | ||
constructor(private readonly userService: UserService) {} | ||
|
||
@Get() | ||
@UseGuards(AuthGuard('jwt'), RolesGuard) | ||
@Roles(Role.BODY_ADMIN, Role.BODY_MEMBER) | ||
async findAll(@Query('page', ParseIntPipe) page: number = 1, @Query('pageSize', ParseIntPipe) pageSize: number = 10) { | ||
return this.userService.findMany(page, pageSize); | ||
} | ||
|
||
@Get('me') | ||
@UseGuards(AuthGuard('jwt')) | ||
async getCurrentUser(@CurrentUser() user: UserEntity) { | ||
return user; | ||
} | ||
|
||
@Patch('me') | ||
@UseGuards(AuthGuard('jwt')) | ||
@Roles(Role.BODY_ADMIN, Role.BODY_MEMBER, Role.USER) | ||
async updateCurrentUser(@Body() updateUserDto: UpdateUserDto, @CurrentUser() user: UserEntity) { | ||
return this.userService.update(user.authSchId, updateUserDto); | ||
} | ||
|
||
@Get(':id') | ||
@UseGuards(AuthGuard('jwt'), RolesGuard) | ||
@Roles(Role.BODY_ADMIN, Role.BODY_MEMBER) | ||
async findOne(@Param('id') id: string) { | ||
return this.userService.findOne(id); | ||
} | ||
|
||
@Patch(':id') | ||
@UseGuards(AuthGuard('jwt'), RolesGuard) | ||
@Roles(Role.BODY_ADMIN, Role.BODY_MEMBER) | ||
async update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we need to add the option for the user to update their own profile also. For eg nickname or profile description should be for sure editable. But on the other hand, schresident and vik student should be managed by admins. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But these are only for schbody members, right? No point in regular users having nicknames and stuff There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ohh, that is fair. I forgot about that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so @Dkrisztan I think body members should be able to edit their own nickname and description There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first part makes sense, the second not really 😅 . So body members can edit nickname desc and resident and vikstudent fields as well? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we are not able to check who lives in the dorm and who does not, we agreed on all users will be able to edit their email, sch-status (room number also) as some kind of a self-declaration. Or at least, it is what I remember. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope. makes sense I just didn't understand the difference between the admin and member role, regarding this update. This fix will be up later this day. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see the point of a nickname and description for regular users, their profile won't even be public, right? or are we planning on turning this app into a workout social network? xd makes sense that the user can set their schStatus and roomNumber, but then the body members should be able to edit another flag that the sch residency was approved during the belepoosztas. Or I guess that could be unnecessary, they just simply don't give them their pass if it wasn't approved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes |
||
return this.userService.update(id, updateUserDto); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,63 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; | ||
import { PrismaService } from 'nestjs-prisma'; | ||
|
||
import { UpdateUserDto } from './dto/update-user.dto'; | ||
import { UserEntity } from './entities/user.entity'; | ||
|
||
@Injectable() | ||
export class UserService {} | ||
export class UserService { | ||
constructor(private readonly prisma: PrismaService) {} | ||
|
||
async findOne(id: string): Promise<UserEntity> { | ||
const user = this.prisma.user.findUnique({ | ||
where: { authSchId: id }, | ||
}); | ||
|
||
if (user === null) { | ||
throw new NotFoundException(`User with id ${id} not found`); | ||
} | ||
|
||
return user; | ||
} | ||
|
||
async findMany( | ||
page: number, | ||
pageSize: number | ||
): Promise<{ users: UserEntity[]; pageNumber: number; totalUsers: number }> { | ||
const [totalUsers, users] = await Promise.all([ | ||
this.prisma.user.count(), | ||
this.prisma.user.findMany({ | ||
orderBy: { fullName: 'asc' }, | ||
skip: (page - 1) * pageSize, | ||
take: pageSize, | ||
}), | ||
]); | ||
|
||
return { | ||
users, | ||
pageNumber: page, | ||
totalUsers, | ||
}; | ||
} | ||
|
||
async update(id: string, updateUserDto: UpdateUserDto): Promise<UserEntity> { | ||
const user = await this.prisma.user.findUnique({ where: { authSchId: id } }); | ||
|
||
if (user === null) { | ||
throw new NotFoundException(`User with id ${id} not found`); | ||
} else if (user.isSchResident === false && updateUserDto.roomNumber) { | ||
throw new BadRequestException('Non-resident users cannot have a room number'); | ||
} | ||
|
||
return this.prisma.user.update({ where: { authSchId: id }, data: updateUserDto }); | ||
} | ||
|
||
// TODO maybe remove it? currently not used (could be useful later) | ||
async delete(id: string): Promise<UserEntity> { | ||
try { | ||
return this.prisma.user.delete({ where: { authSchId: id } }); | ||
} catch (error) { | ||
throw new NotFoundException(`User with id ${id} not found`); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lmao why was this missing