Add Swagger integration and console logging for debugging
Integrated Swagger module in the backend for API documentation. Added console logs for better traceability and debugging in service and controller methods.
This commit is contained in:
parent
6f0f209e00
commit
ff649ebdbf
@ -1,14 +1,14 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Patch,
|
||||
Post,
|
||||
UnauthorizedException,
|
||||
UseGuards,
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Patch,
|
||||
Post,
|
||||
UnauthorizedException,
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto";
|
||||
import { AuthService } from "apps/backend/src/app/auth/auth.service";
|
||||
@ -16,52 +16,50 @@ import { UserGuard } from "./auth.guard";
|
||||
|
||||
@Controller("auth")
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
constructor(private readonly authService: AuthService) { }
|
||||
|
||||
//TODO Initial account validation for admin privileges
|
||||
//POST signup
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@Post("signup")
|
||||
async signUp(@Body() dto: SignUpDto) {
|
||||
console.log(dto);
|
||||
return this.authService.doRegister(dto);
|
||||
}
|
||||
//TODO Initial account validation for admin privileges
|
||||
//POST signup
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@Post("signup")
|
||||
async signUp(@Body() dto: SignUpDto) {
|
||||
return this.authService.doRegister(dto);
|
||||
}
|
||||
|
||||
//POST signin
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post("signin")
|
||||
async signIn(@Body() dto: SignInDto) {
|
||||
console.log(dto);
|
||||
return this.authService.doLogin(dto);
|
||||
}
|
||||
//GET me -- Get current user data via jwt
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Get("me")
|
||||
@UseGuards(UserGuard)
|
||||
async getMe(@Body() body: object) {
|
||||
// @ts-ignore
|
||||
const targetId = body.sourceUserId;
|
||||
const userData = await this.authService.fetchUserById(targetId);
|
||||
if (!userData) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
return userData;
|
||||
}
|
||||
//DELETE me
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Delete("me")
|
||||
@UseGuards(UserGuard)
|
||||
async deleteMe(@Body() body: object) {
|
||||
// @ts-ignore
|
||||
const targetId = body.sourceUserId;
|
||||
try {
|
||||
await this.authService.deleteUser(targetId);
|
||||
} catch (err) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
//POST signin
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post("signin")
|
||||
async signIn(@Body() dto: SignInDto) {
|
||||
return this.authService.doLogin(dto);
|
||||
}
|
||||
//GET me -- Get current user data via jwt
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Get("me")
|
||||
@UseGuards(UserGuard)
|
||||
async getMe(@Body() body: object) {
|
||||
// @ts-ignore
|
||||
const targetId = body.sourceUserId;
|
||||
const userData = await this.authService.fetchUserById(targetId);
|
||||
if (!userData) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
return userData;
|
||||
}
|
||||
//DELETE me
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Delete("me")
|
||||
@UseGuards(UserGuard)
|
||||
async deleteMe(@Body() body: object) {
|
||||
// @ts-ignore
|
||||
const targetId = body.sourceUserId;
|
||||
try {
|
||||
await this.authService.deleteUser(targetId);
|
||||
} catch (err) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
//PATCH me
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Patch("me")
|
||||
|
@ -31,7 +31,6 @@ export class SignUpDto {
|
||||
@IsNotEmpty()
|
||||
@IsStrongPassword({
|
||||
minLength: 6,
|
||||
minSymbols: 1,
|
||||
})
|
||||
password: string;
|
||||
}
|
||||
@ -46,7 +45,6 @@ export class SignInDto {
|
||||
@IsNotEmpty()
|
||||
@IsStrongPassword({
|
||||
minLength: 6,
|
||||
minSymbols: 1,
|
||||
})
|
||||
password: string;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {
|
||||
Injectable,
|
||||
OnModuleInit,
|
||||
UnauthorizedException,
|
||||
Injectable,
|
||||
OnModuleInit,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { SignInDto, SignUpDto } from "apps/backend/src/app/auth/auth.dto";
|
||||
import { CredentialsService } from "apps/backend/src/app/credentials/credentials.service";
|
||||
@ -11,103 +11,102 @@ import { eq } from "drizzle-orm";
|
||||
|
||||
@Injectable()
|
||||
export class AuthService implements OnModuleInit {
|
||||
constructor(
|
||||
private db: DbService,
|
||||
private credentials: CredentialsService,
|
||||
) {}
|
||||
constructor(
|
||||
private db: DbService,
|
||||
private credentials: CredentialsService,
|
||||
) { }
|
||||
|
||||
//TODO Initial account validation for admin privileges
|
||||
async doRegister(data: SignUpDto) {
|
||||
console.log(data);
|
||||
const existingUser = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.email, data.email))
|
||||
.prepare("userByEmail")
|
||||
.execute();
|
||||
if (existingUser.length !== 0)
|
||||
throw new UnauthorizedException("Already exist");
|
||||
const query = await this.db
|
||||
.use()
|
||||
.insert(UsersTable)
|
||||
.values({
|
||||
//firstName: data.firstName,
|
||||
//lastName: data.lastName,
|
||||
email: data.email,
|
||||
hash: await this.credentials.hash(data.password),
|
||||
})
|
||||
.returning()
|
||||
.prepare("insertUser")
|
||||
.execute()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw new UnauthorizedException(
|
||||
"Error occurred while inserting user",
|
||||
err,
|
||||
);
|
||||
});
|
||||
return {
|
||||
message: "User created, check your email for validation.",
|
||||
token: await this.credentials.signAuthToken({ sub: query[0].uuid }),
|
||||
};
|
||||
}
|
||||
//TODO Initial account validation for admin privileges
|
||||
async doRegister(data: SignUpDto) {
|
||||
const existingUser = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.email, data.email))
|
||||
.prepare("userByEmail")
|
||||
.execute();
|
||||
if (existingUser.length !== 0)
|
||||
throw new UnauthorizedException("Already exist");
|
||||
const query = await this.db
|
||||
.use()
|
||||
.insert(UsersTable)
|
||||
.values({
|
||||
//firstName: data.firstName,
|
||||
//lastName: data.lastName,
|
||||
email: data.email,
|
||||
hash: await this.credentials.hash(data.password),
|
||||
})
|
||||
.returning()
|
||||
.prepare("insertUser")
|
||||
.execute()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw new UnauthorizedException(
|
||||
"Error occurred while inserting user",
|
||||
err,
|
||||
);
|
||||
});
|
||||
return {
|
||||
message: "User created, check your email for validation.",
|
||||
token: await this.credentials.signAuthToken({ sub: query[0].uuid }),
|
||||
};
|
||||
}
|
||||
|
||||
async doLogin(data: SignInDto) {
|
||||
const user = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.email, data.email))
|
||||
.prepare("userByEmail")
|
||||
.execute();
|
||||
if (user.length !== 1)
|
||||
throw new UnauthorizedException("Invalid credentials");
|
||||
const passwordMatch = await this.credentials.check(
|
||||
data.password,
|
||||
user[0].hash,
|
||||
);
|
||||
if (!passwordMatch) throw new UnauthorizedException("Invalid credentials");
|
||||
const token = await this.credentials.signAuthToken({ sub: user[0].uuid });
|
||||
return {
|
||||
message: "Login successful",
|
||||
token: token,
|
||||
};
|
||||
}
|
||||
async doLogin(data: SignInDto) {
|
||||
const user = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.email, data.email))
|
||||
.prepare("userByEmail")
|
||||
.execute();
|
||||
if (user.length !== 1)
|
||||
throw new UnauthorizedException("Invalid credentials");
|
||||
const passwordMatch = await this.credentials.check(
|
||||
data.password,
|
||||
user[0].hash,
|
||||
);
|
||||
if (!passwordMatch) throw new UnauthorizedException("Invalid credentials");
|
||||
const token = await this.credentials.signAuthToken({ sub: user[0].uuid });
|
||||
return {
|
||||
message: "Login successful",
|
||||
token: token,
|
||||
};
|
||||
}
|
||||
|
||||
async fetchUserById(userId: string) {
|
||||
const user = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.uuid, userId))
|
||||
.prepare("userById")
|
||||
.execute();
|
||||
if (user.length !== 1) {
|
||||
throw new UnauthorizedException("User not found");
|
||||
}
|
||||
delete user[0].hash;
|
||||
//delete user[0].emailCode;
|
||||
return user[0];
|
||||
}
|
||||
async fetchUserById(userId: string) {
|
||||
const user = await this.db
|
||||
.use()
|
||||
.select()
|
||||
.from(UsersTable)
|
||||
.where(eq(UsersTable.uuid, userId))
|
||||
.prepare("userById")
|
||||
.execute();
|
||||
if (user.length !== 1) {
|
||||
throw new UnauthorizedException("User not found");
|
||||
}
|
||||
delete user[0].hash;
|
||||
//delete user[0].emailCode;
|
||||
return user[0];
|
||||
}
|
||||
|
||||
async fetchUsers() {
|
||||
//TODO Pagination
|
||||
const usersInDb = await this.db.use().select().from(UsersTable);
|
||||
const result = {
|
||||
total: usersInDb.length,
|
||||
users: usersInDb.map((user) => {
|
||||
delete user.hash;
|
||||
return {
|
||||
...user,
|
||||
};
|
||||
}),
|
||||
};
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
async fetchUsers() {
|
||||
//TODO Pagination
|
||||
const usersInDb = await this.db.use().select().from(UsersTable);
|
||||
const result = {
|
||||
total: usersInDb.length,
|
||||
users: usersInDb.map((user) => {
|
||||
delete user.hash;
|
||||
return {
|
||||
...user,
|
||||
};
|
||||
}),
|
||||
};
|
||||
console.log(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
async updateUser(targetId: string, userData: IUserUpdateData) {
|
||||
const validationResult = UserUpdateSchema.safeParse(userData);
|
||||
if (!validationResult.success) {
|
||||
@ -133,26 +132,26 @@ export class AuthService implements OnModuleInit {
|
||||
}
|
||||
*/
|
||||
|
||||
async deleteUser(targetId: string) {
|
||||
await this.db
|
||||
.use()
|
||||
.delete(UsersTable)
|
||||
.where(eq(UsersTable.uuid, targetId))
|
||||
.prepare("deleteUserById")
|
||||
.execute()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw new UnauthorizedException(
|
||||
"Error occurred while deleting user",
|
||||
err,
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
async deleteUser(targetId: string) {
|
||||
await this.db
|
||||
.use()
|
||||
.delete(UsersTable)
|
||||
.where(eq(UsersTable.uuid, targetId))
|
||||
.prepare("deleteUserById")
|
||||
.execute()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw new UnauthorizedException(
|
||||
"Error occurred while deleting user",
|
||||
err,
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
setTimeout(() => {
|
||||
this.fetchUsers();
|
||||
}, 2000);
|
||||
}
|
||||
async onModuleInit() {
|
||||
setTimeout(() => {
|
||||
this.fetchUsers();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
@ -6,52 +6,51 @@ import { JWTPayload, generateSecret } from "jose";
|
||||
|
||||
@Injectable()
|
||||
export class CredentialsService {
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
constructor(private readonly configService: ConfigService) { }
|
||||
|
||||
async hash(plaintextPassword: string) {
|
||||
console.log(plaintextPassword);
|
||||
if (plaintextPassword.length < 6)
|
||||
throw new BadRequestException("Password is not strong enough !");
|
||||
return argon.hash(plaintextPassword, {
|
||||
secret: Buffer.from(this.configService.get("APP_HASH_SECRET")),
|
||||
});
|
||||
}
|
||||
async hash(plaintextPassword: string) {
|
||||
if (plaintextPassword.length < 6)
|
||||
throw new BadRequestException("Password is not strong enough !");
|
||||
return argon.hash(plaintextPassword, {
|
||||
secret: Buffer.from(this.configService.get("APP_HASH_SECRET")),
|
||||
});
|
||||
}
|
||||
|
||||
async check(plaintextPassword: string, hashedPassword: string) {
|
||||
return argon.verify(hashedPassword, plaintextPassword, {
|
||||
secret: Buffer.from(this.configService.get("APP_HASH_SECRET")),
|
||||
});
|
||||
}
|
||||
async check(plaintextPassword: string, hashedPassword: string) {
|
||||
return argon.verify(hashedPassword, plaintextPassword, {
|
||||
secret: Buffer.from(this.configService.get("APP_HASH_SECRET")),
|
||||
});
|
||||
}
|
||||
|
||||
async verifyAuthToken(token: string) {
|
||||
try {
|
||||
const result = await jose.jwtVerify(
|
||||
token,
|
||||
Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")),
|
||||
{
|
||||
audience: "auth:user",
|
||||
issuer: "FabLab",
|
||||
},
|
||||
);
|
||||
console.log(result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new BadRequestException("Invalid token");
|
||||
}
|
||||
}
|
||||
async verifyAuthToken(token: string) {
|
||||
try {
|
||||
const result = await jose.jwtVerify(
|
||||
token,
|
||||
Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")),
|
||||
{
|
||||
audience: "auth:user",
|
||||
issuer: "FabLab",
|
||||
},
|
||||
);
|
||||
console.log(result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new BadRequestException("Invalid token");
|
||||
}
|
||||
}
|
||||
|
||||
async signAuthToken(payload: JWTPayload) {
|
||||
console.log(this.configService.get("APP_TOKEN_SECRET"));
|
||||
const token = new jose.SignJWT(payload)
|
||||
.setProtectedHeader({ alg: "HS512", enc: "A128CBC-HS512" })
|
||||
.setIssuedAt()
|
||||
.setExpirationTime("5 day")
|
||||
.setIssuer("FabLab")
|
||||
.setAudience("auth:user");
|
||||
console.log(token);
|
||||
return await token.sign(
|
||||
Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")),
|
||||
);
|
||||
}
|
||||
async signAuthToken(payload: JWTPayload) {
|
||||
console.log(this.configService.get("APP_TOKEN_SECRET"));
|
||||
const token = new jose.SignJWT(payload)
|
||||
.setProtectedHeader({ alg: "HS512", enc: "A128CBC-HS512" })
|
||||
.setIssuedAt()
|
||||
.setExpirationTime("5 day")
|
||||
.setIssuer("FabLab")
|
||||
.setAudience("auth:user");
|
||||
console.log(token);
|
||||
return await token.sign(
|
||||
Uint8Array.from(this.configService.get("APP_TOKEN_SECRET")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,24 @@
|
||||
import { IncomingMessage } from "node:http";
|
||||
import {
|
||||
BadRequestException,
|
||||
Body,
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
ParseUUIDPipe,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
Request,
|
||||
Res,
|
||||
Response,
|
||||
StreamableFile,
|
||||
UseGuards,
|
||||
BadRequestException,
|
||||
Body,
|
||||
Controller,
|
||||
DefaultValuePipe,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
HttpStatus,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
ParseUUIDPipe,
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
Request,
|
||||
Res,
|
||||
Response,
|
||||
StreamableFile,
|
||||
UseGuards,
|
||||
} from "@nestjs/common";
|
||||
import { CreateFileTypeDto } from "apps/backend/src/app/files/files.dto";
|
||||
import { AdminGuard, InsertAdminState } from "../auth/auth.guard";
|
||||
@ -26,130 +26,132 @@ import { FilesService } from "./files.service";
|
||||
|
||||
@Controller("files")
|
||||
export class FilesController {
|
||||
constructor(private readonly filesService: FilesService) {}
|
||||
constructor(private readonly filesService: FilesService) { }
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(InsertAdminState)
|
||||
@Post("new")
|
||||
async saveFile(@Req() req: IncomingMessage, @Res() res: Response) {
|
||||
let fileBuffer: Buffer = Buffer.from([]);
|
||||
req.on("data", (chunk: Buffer) => {
|
||||
fileBuffer = Buffer.concat([fileBuffer, chunk]);
|
||||
});
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(InsertAdminState)
|
||||
@Post("new")
|
||||
async saveFile(@Req() req: IncomingMessage, @Res() res: Response) {
|
||||
let fileBuffer: Buffer = Buffer.from([]);
|
||||
req.on("data", (chunk: Buffer) => {
|
||||
fileBuffer = Buffer.concat([fileBuffer, chunk]);
|
||||
});
|
||||
|
||||
req.on("end", async () => {
|
||||
try {
|
||||
console.log(fileBuffer);
|
||||
const _fileName = req.headers["file_name"] as string;
|
||||
const _groupId = req.headers["group_id"] as string;
|
||||
const _uploadedBy = req.headers["uploaded_by"] as string;
|
||||
const _machineId = req.headers["machine_id"];
|
||||
const _isDocumentation = req.headers["is_documentation"] as string;
|
||||
const _isRestricted = req.headers["is_restricted"] as string;
|
||||
const _isAdmin = Boolean(req.headers["is_admin"] as string | boolean);
|
||||
console.log(
|
||||
_fileName,
|
||||
_groupId,
|
||||
_uploadedBy,
|
||||
_machineId,
|
||||
_isDocumentation,
|
||||
_isRestricted,
|
||||
_isAdmin,
|
||||
);
|
||||
req.on("end", async () => {
|
||||
try {
|
||||
console.log(fileBuffer);
|
||||
const _fileName = req.headers["file_name"] as string;
|
||||
const _groupId = req.headers["group_id"] as string;
|
||||
const _uploadedBy = req.headers["uploaded_by"] as string;
|
||||
const _machineId = req.headers["machine_id"];
|
||||
const _isDocumentation = req.headers["is_documentation"] as string;
|
||||
const _isRestricted = req.headers["is_restricted"] as string;
|
||||
const _isAdmin = Boolean(req.headers["is_admin"] as string | boolean);
|
||||
console.log(
|
||||
_fileName,
|
||||
_groupId,
|
||||
_uploadedBy,
|
||||
_machineId,
|
||||
_isDocumentation,
|
||||
_isRestricted,
|
||||
_isAdmin,
|
||||
);
|
||||
|
||||
// Vérifier que les en-têtes nécessaires sont présents
|
||||
if (!_fileName || !_machineId) {
|
||||
throw new BadRequestException("Header(s) manquant(s)");
|
||||
}
|
||||
console.log("Header found !");
|
||||
const machineId = Array(_machineId);
|
||||
// Vérifier que les en-têtes nécessaires sont présents
|
||||
if (!_fileName || !_machineId) {
|
||||
throw new BadRequestException("Header(s) manquant(s)");
|
||||
}
|
||||
console.log("Header found !");
|
||||
const machineId = Array(_machineId);
|
||||
|
||||
const Params = new Map()
|
||||
.set("fileName", _fileName.toString())
|
||||
.set("groupId", _groupId.toString() || null)
|
||||
.set("uploadedBy", _uploadedBy.toString())
|
||||
.set("machineId", Array(JSON.parse(machineId.toString())))
|
||||
.set("isDocumentation", false)
|
||||
.set("isRestricted", false);
|
||||
const Params = new Map()
|
||||
.set("fileName", _fileName.toString())
|
||||
.set("groupId", _groupId.toString() || null)
|
||||
.set("uploadedBy", _uploadedBy.toString())
|
||||
.set("machineId", Array(JSON.parse(machineId.toString())))
|
||||
.set("isDocumentation", false)
|
||||
.set("isRestricted", false);
|
||||
|
||||
console.log("Current params :\n", Params);
|
||||
console.log("Current params :\n", Params);
|
||||
|
||||
//TODO Integrate a verification if the source is an admin, if that the case then it can define isDocumentation and isRestricted else throw in case of presence of those parameters.
|
||||
if (_isAdmin) {
|
||||
Params.set("isDocumentation", Boolean(_isDocumentation));
|
||||
Params.set("isRestricted", Boolean(_isRestricted));
|
||||
}
|
||||
//TODO Integrate a verification if the source is an admin, if that the case then it can define isDocumentation and isRestricted else throw in case of presence of those parameters.
|
||||
if (_isAdmin) {
|
||||
Params.set("isDocumentation", Boolean(_isDocumentation));
|
||||
Params.set("isRestricted", Boolean(_isRestricted));
|
||||
}
|
||||
|
||||
console.log("Executing save procedure...");
|
||||
return (
|
||||
res
|
||||
// @ts-ignore
|
||||
.status(HttpStatus.CREATED)
|
||||
.send(await this.filesService.save(fileBuffer, Params))
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return (
|
||||
res
|
||||
// @ts-ignore
|
||||
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.send(err)
|
||||
);
|
||||
}
|
||||
});
|
||||
console.log("Executing save procedure...");
|
||||
return (
|
||||
res
|
||||
// @ts-ignore
|
||||
.status(HttpStatus.CREATED)
|
||||
.send(await this.filesService.save(fileBuffer, Params))
|
||||
);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return (
|
||||
res
|
||||
// @ts-ignore
|
||||
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.send(err)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
req.on("error", (err) => {
|
||||
return (
|
||||
res
|
||||
// @ts-ignore
|
||||
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.send(err)
|
||||
);
|
||||
});
|
||||
req.on("error", (err) => {
|
||||
return (
|
||||
res
|
||||
// @ts-ignore
|
||||
.status(err.status || HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.send(err)
|
||||
);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Get("find")
|
||||
async findMany(
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
) {
|
||||
return this.filesService.search(limit, offset, search);
|
||||
}
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Get("find")
|
||||
async findMany(
|
||||
@Query("limit", new DefaultValuePipe(20), ParseIntPipe) limit: number,
|
||||
@Query("offset", new DefaultValuePipe(0), ParseIntPipe) offset: number,
|
||||
@Query("search", new DefaultValuePipe("")) search: string,
|
||||
) {
|
||||
return this.filesService.search(limit, offset, search);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Get(":fileId")
|
||||
async getFile(@Param("fileId") fileId: string) {
|
||||
return await this.filesService.get(fileId);
|
||||
}
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Get("types")
|
||||
async getTypes() {
|
||||
console.log("Performing request")
|
||||
return await this.filesService.getAllFilesTypes();
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(AdminGuard)
|
||||
@Delete(":fileId")
|
||||
async deleteFile(@Param("fileId", ParseUUIDPipe) fileId: string) {
|
||||
return await this.filesService.deleteFile(fileId);
|
||||
}
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@UseGuards(AdminGuard)
|
||||
@Post("types/new")
|
||||
async newType(@Body() body: CreateFileTypeDto) {
|
||||
return await this.filesService.createFileType(body.name, body.mime);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Get("types")
|
||||
async getTypes() {
|
||||
return await this.filesService.getAllFilesTypes();
|
||||
}
|
||||
@HttpCode(HttpStatus.ACCEPTED)
|
||||
@UseGuards(AdminGuard)
|
||||
@Delete("types/:typeId")
|
||||
async delType(@Param(":typeId", ParseUUIDPipe) typeId: string) {
|
||||
return await this.filesService.removeFileType(typeId)
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.CREATED)
|
||||
@UseGuards(AdminGuard)
|
||||
@Post("types/new")
|
||||
async newType(@Body() body: CreateFileTypeDto) {
|
||||
return await this.filesService.createFileType(body.name, body.mime);
|
||||
}
|
||||
@HttpCode(HttpStatus.FOUND)
|
||||
@Get(":fileId")
|
||||
async getFile(@Param("fileId") fileId: string) {
|
||||
return await this.filesService.get(fileId);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(AdminGuard)
|
||||
@Delete(":fileId")
|
||||
async deleteFile(@Param("fileId", ParseUUIDPipe) fileId: string) {
|
||||
return await this.filesService.deleteFile(fileId);
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.ACCEPTED)
|
||||
@UseGuards(AdminGuard)
|
||||
@Delete("types/:typeId")
|
||||
async delType(@Param(":typeId", ParseUUIDPipe) typeId: string) {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
@ -293,12 +293,14 @@ export class FilesService {
|
||||
* @return {Promise<Array>} Promise that resolves to an array of file types.
|
||||
*/
|
||||
public async getAllFilesTypes(): Promise<Array<object>> {
|
||||
return await this.database
|
||||
const result = await this.database
|
||||
.use()
|
||||
.select()
|
||||
.from(FilesTypesTable)
|
||||
.prepare("getAllFilesTypes")
|
||||
.execute();
|
||||
console.log(result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,20 +1,28 @@
|
||||
/**
|
||||
* This is not a production server yet!
|
||||
* This is only a minimal backend to get started.
|
||||
*/
|
||||
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { NestFactory } from "@nestjs/core";
|
||||
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
||||
|
||||
|
||||
import helmet from "helmet";
|
||||
import { AppModule } from "./app/app.module";
|
||||
|
||||
async function bootstrap() {
|
||||
|
||||
const config = new DocumentBuilder()
|
||||
.setTitle('Fab Explorer')
|
||||
.setDescription("Définition de l'api du FabLab Explorer")
|
||||
.setVersion('1.0')
|
||||
.build();
|
||||
|
||||
const app = await NestFactory.create(AppModule);
|
||||
const globalPrefix = "api";
|
||||
app.setGlobalPrefix(globalPrefix);
|
||||
app.use(helmet());
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const document = SwaggerModule.createDocument(app, config);
|
||||
SwaggerModule.setup('api', app, document);
|
||||
|
||||
await app.listen(port);
|
||||
Logger.log(
|
||||
`🚀 Application is running on: http://localhost:${port}/${globalPrefix}`,
|
||||
|
@ -17,6 +17,7 @@
|
||||
"@nestjs/core": "^10.4.4",
|
||||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/platform-express": "^10.4.4",
|
||||
"@nestjs/swagger": "^7.4.2",
|
||||
"@nestjs/throttler": "^6.2.1",
|
||||
"@radix-ui/react-accordion": "^1.2.1",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.2",
|
||||
|
45
pnpm-lock.yaml
generated
45
pnpm-lock.yaml
generated
@ -26,6 +26,9 @@ importers:
|
||||
'@nestjs/platform-express':
|
||||
specifier: ^10.4.4
|
||||
version: 10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)
|
||||
'@nestjs/swagger':
|
||||
specifier: ^7.4.2
|
||||
version: 7.4.2(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)
|
||||
'@nestjs/throttler':
|
||||
specifier: ^6.2.1
|
||||
version: 6.2.1(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14)
|
||||
@ -1582,6 +1585,9 @@ packages:
|
||||
resolution: {integrity: sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
'@microsoft/tsdoc@0.15.0':
|
||||
resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==}
|
||||
|
||||
'@module-federation/bridge-react-webpack-plugin@0.2.8':
|
||||
resolution: {integrity: sha512-6G1qTo1HWvRcN5fzE+SZgvgzSPoq5YqNx8hFL8BttJmnd3wj4SUOFiikAsXhdVrzSK+Zuzg6pipkiLH1m+pbtw==}
|
||||
|
||||
@ -1712,6 +1718,23 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=4.3.5'
|
||||
|
||||
'@nestjs/swagger@7.4.2':
|
||||
resolution: {integrity: sha512-Mu6TEn1M/owIvAx2B4DUQObQXqo2028R2s9rSZ/hJEgBK95+doTwS0DjmVA2wTeZTyVtXOoN7CsoM5pONBzvKQ==}
|
||||
peerDependencies:
|
||||
'@fastify/static': ^6.0.0 || ^7.0.0
|
||||
'@nestjs/common': ^9.0.0 || ^10.0.0
|
||||
'@nestjs/core': ^9.0.0 || ^10.0.0
|
||||
class-transformer: '*'
|
||||
class-validator: '*'
|
||||
reflect-metadata: ^0.1.12 || ^0.2.0
|
||||
peerDependenciesMeta:
|
||||
'@fastify/static':
|
||||
optional: true
|
||||
class-transformer:
|
||||
optional: true
|
||||
class-validator:
|
||||
optional: true
|
||||
|
||||
'@nestjs/testing@10.4.4':
|
||||
resolution: {integrity: sha512-qRGFj51A5RM7JqA8pcyEwSLA3Y0dle/PAZ8oxP0suimoCusRY3Tk7wYqutZdCNj1ATb678SDaUZDHk2pwSv9/g==}
|
||||
peerDependencies:
|
||||
@ -7894,6 +7917,9 @@ packages:
|
||||
engines: {node: '>=14.0.0'}
|
||||
hasBin: true
|
||||
|
||||
swagger-ui-dist@5.17.14:
|
||||
resolution: {integrity: sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==}
|
||||
|
||||
symbol-tree@3.2.4:
|
||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||
|
||||
@ -9971,6 +9997,8 @@ snapshots:
|
||||
|
||||
'@lukeed/csprng@1.1.0': {}
|
||||
|
||||
'@microsoft/tsdoc@0.15.0': {}
|
||||
|
||||
'@module-federation/bridge-react-webpack-plugin@0.2.8':
|
||||
dependencies:
|
||||
'@module-federation/sdk': 0.2.8
|
||||
@ -10171,6 +10199,21 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- chokidar
|
||||
|
||||
'@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)':
|
||||
dependencies:
|
||||
'@microsoft/tsdoc': 0.15.0
|
||||
'@nestjs/common': 10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1)
|
||||
'@nestjs/core': 10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1)
|
||||
'@nestjs/mapped-types': 2.0.5(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)
|
||||
js-yaml: 4.1.0
|
||||
lodash: 4.17.21
|
||||
path-to-regexp: 3.3.0
|
||||
reflect-metadata: 0.1.14
|
||||
swagger-ui-dist: 5.17.14
|
||||
optionalDependencies:
|
||||
class-transformer: 0.5.1
|
||||
class-validator: 0.14.1
|
||||
|
||||
'@nestjs/testing@10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4))':
|
||||
dependencies:
|
||||
'@nestjs/common': 10.4.4(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.1.14)(rxjs@7.8.1)
|
||||
@ -17863,6 +17906,8 @@ snapshots:
|
||||
csso: 5.0.5
|
||||
picocolors: 1.0.1
|
||||
|
||||
swagger-ui-dist@5.17.14: {}
|
||||
|
||||
symbol-tree@3.2.4: {}
|
||||
|
||||
tailwind-merge@2.5.3: {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user