Compare commits
2 Commits
18a5999334
...
ff649ebdbf
| Author | SHA1 | Date | |
|---|---|---|---|
|
ff649ebdbf
|
|||
|
6f0f209e00
|
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,13 @@ export class FilesService {
|
||||
}
|
||||
if (sameFileInStorage.length === 1) {
|
||||
//if there is one only entry then remove the file from the storage and the database.
|
||||
await this.database
|
||||
.use()
|
||||
.delete(FilesForMachinesTable)
|
||||
.where(eq(FilesForMachinesTable.fileId, fileId))
|
||||
.prepare("deleteFileAssociationFromMachine")
|
||||
.execute();
|
||||
|
||||
await this.database
|
||||
.use()
|
||||
.delete(FilesTable)
|
||||
@@ -286,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: {}
|
||||
|
||||
Reference in New Issue
Block a user