diff --git a/.env b/.env
deleted file mode 100644
index ee7ba66..0000000
--- a/.env
+++ /dev/null
@@ -1,8 +0,0 @@
-#Common
-BACKEND_PORT=3300
-# Database
-POSTGRES_USER=postgres
-POSTGRES_PASSWORD=postgres
-POSTGRES_DB=schbody
-POSTGRES_PORT=5432
-DATABASE_URL=postgresql://postgres:postgres@localhost:5432/schbody?schema=public
diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml
new file mode 100644
index 0000000..541945b
--- /dev/null
+++ b/.idea/jsLinters/eslint.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts
index 3713aaa..c7e8200 100644
--- a/apps/backend/src/app.module.ts
+++ b/apps/backend/src/app.module.ts
@@ -3,9 +3,10 @@ import { PrismaModule } from 'nestjs-prisma';
import { AppController } from './app.controller';
import { AppService } from './app.service';
+import { UsersModule } from './users/users.module';
@Module({
- imports: [PrismaModule.forRoot({ isGlobal: true })],
+ imports: [PrismaModule.forRoot({ isGlobal: true }), UsersModule],
controllers: [AppController],
providers: [AppService],
})
diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts
index bd4dd77..0ecd081 100644
--- a/apps/backend/src/main.ts
+++ b/apps/backend/src/main.ts
@@ -1,9 +1,15 @@
+import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
+ app.useGlobalPipes(
+ new ValidationPipe({
+ whitelist: true,
+ })
+ );
await app.listen(3001);
}
bootstrap();
diff --git a/apps/backend/src/users/dto/create-user.dto.ts b/apps/backend/src/users/dto/create-user.dto.ts
new file mode 100644
index 0000000..b5ec2c1
--- /dev/null
+++ b/apps/backend/src/users/dto/create-user.dto.ts
@@ -0,0 +1,5 @@
+import { OmitType } from '@nestjs/swagger';
+
+import { User } from '../entities/user.entity';
+
+export class CreateUserDto extends OmitType(User, ['id']) {}
diff --git a/apps/backend/src/users/dto/update-user.dto.ts b/apps/backend/src/users/dto/update-user.dto.ts
new file mode 100644
index 0000000..deaf4b4
--- /dev/null
+++ b/apps/backend/src/users/dto/update-user.dto.ts
@@ -0,0 +1,5 @@
+import { PartialType } from '@nestjs/mapped-types';
+
+import { CreateUserDto } from './create-user.dto';
+
+export class UpdateUserDto extends PartialType(CreateUserDto) {}
diff --git a/apps/backend/src/users/entities/user.entity.ts b/apps/backend/src/users/entities/user.entity.ts
new file mode 100644
index 0000000..d7f9113
--- /dev/null
+++ b/apps/backend/src/users/entities/user.entity.ts
@@ -0,0 +1,29 @@
+import { Role } from '@prisma/client';
+import { IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsOptional, IsPositive, IsString } from 'class-validator';
+
+export class User {
+ @IsNumber()
+ @IsPositive()
+ id: number;
+
+ @IsString()
+ @IsNotEmpty()
+ name: string;
+
+ @IsEmail()
+ email: string;
+
+ @IsString()
+ @IsOptional()
+ phone: string;
+
+ @IsBoolean()
+ isDormResident: boolean;
+
+ @IsString()
+ @IsOptional()
+ roomNumber: string;
+
+ @IsEnum(Role)
+ role: Role;
+}
diff --git a/apps/backend/src/users/users.controller.ts b/apps/backend/src/users/users.controller.ts
new file mode 100644
index 0000000..198bb74
--- /dev/null
+++ b/apps/backend/src/users/users.controller.ts
@@ -0,0 +1,30 @@
+import { Body, Controller, Get, Param, ParseIntPipe, Patch } from '@nestjs/common';
+import { User } from '@prisma/client';
+
+import { UpdateUserDto } from './dto/update-user.dto';
+import { UsersService } from './users.service';
+
+@Controller('users')
+export class UsersController {
+ constructor(private readonly usersService: UsersService) {}
+
+ @Get()
+ async findAll() {
+ return this.usersService.findAll();
+ }
+
+ @Get('me')
+ async getCurrentUser(user: User) {
+ return this.usersService.findOne(user.id);
+ }
+
+ @Get(':id')
+ async findOne(@Param('id', ParseIntPipe) id: number) {
+ return this.usersService.findOne(id);
+ }
+
+ @Patch(':id')
+ update(@Param('id', ParseIntPipe) id: number, @Body() updateUserDto: UpdateUserDto) {
+ return this.usersService.update(id, updateUserDto);
+ }
+}
diff --git a/apps/backend/src/users/users.module.ts b/apps/backend/src/users/users.module.ts
new file mode 100644
index 0000000..f57cea5
--- /dev/null
+++ b/apps/backend/src/users/users.module.ts
@@ -0,0 +1,10 @@
+import { Module } from '@nestjs/common';
+
+import { UsersController } from './users.controller';
+import { UsersService } from './users.service';
+
+@Module({
+ controllers: [UsersController],
+ providers: [UsersService],
+})
+export class UsersModule {}
diff --git a/apps/backend/src/users/users.service.ts b/apps/backend/src/users/users.service.ts
new file mode 100644
index 0000000..ba4c204
--- /dev/null
+++ b/apps/backend/src/users/users.service.ts
@@ -0,0 +1,47 @@
+import { Injectable, NotFoundException } from '@nestjs/common';
+import { Prisma, User } from '@prisma/client';
+import { PrismaService } from 'nestjs-prisma';
+
+import { UpdateUserDto } from './dto/update-user.dto';
+
+@Injectable()
+export class UsersService {
+ constructor(private readonly prisma: PrismaService) {}
+
+ async findAll(): Promise<{ users: User[] }> {
+ const users = await this.prisma.user.findMany();
+ return { users };
+ }
+
+ async findOne(id: number): Promise {
+ const user = await this.prisma.user.findUnique({
+ where: {
+ id,
+ },
+ });
+
+ if (!user) {
+ throw new NotFoundException(`User with id ${id} not found`);
+ }
+
+ return user;
+ }
+
+ async update(id: number, updateUserDto: UpdateUserDto) {
+ try {
+ return this.prisma.user.update({
+ where: {
+ id,
+ },
+ data: updateUserDto,
+ });
+ } catch (e) {
+ if (e instanceof Prisma.PrismaClientKnownRequestError) {
+ if (e.code === 'P2025') {
+ throw new NotFoundException(`User with id ${id} not found`);
+ }
+ }
+ throw e;
+ }
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 0fb07e9..7428f19 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1037,11 +1037,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
-ansi-styles@^6.1.0:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
- integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
-
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
@@ -1737,11 +1732,6 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
-eastasianwidth@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
- integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
-
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -4232,7 +4222,7 @@ streamsearch@^1.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
-string-width@^4.1.0:
+string-width@4.1.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, string-width@^5.1.2:
version "4.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.1.0.tgz#ba846d1daa97c3c596155308063e075ed1c99aff"
integrity sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==
@@ -4241,24 +4231,6 @@ string-width@^4.1.0:
is-fullwidth-code-point "^3.0.0"
strip-ansi "^5.2.0"
-string-width@^4.2.0, string-width@^4.2.3:
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^5.0.1, string-width@^5.1.2:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
- integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
- dependencies:
- eastasianwidth "^0.2.0"
- emoji-regex "^9.2.2"
- strip-ansi "^7.0.1"
-
string.prototype.matchall@^4.0.10:
version "4.0.11"
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a"
@@ -4908,24 +4880,15 @@ which@^2.0.1:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^6.0.1, wrap-ansi@^6.2.0:
- version "6.2.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
- integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+wrap-ansi@7.0.0, wrap-ansi@^6.0.1, wrap-ansi@^6.2.0, wrap-ansi@^8.1.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^8.1.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
- integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
- dependencies:
- ansi-styles "^6.1.0"
- string-width "^5.0.1"
- strip-ansi "^7.0.1"
-
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"