Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e811f67c07 | |||
| 08aade7dcd | |||
| f04f01a39c | |||
| 5322aefcdb | |||
| 53bd76c78d |
@@ -122,3 +122,8 @@ export class LineasInvestigacion{
|
|||||||
@Length(0,300)
|
@Length(0,300)
|
||||||
lineas_inv_html: string;
|
lineas_inv_html: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UpdateProfesorImageDto {
|
||||||
|
@IsString()
|
||||||
|
fotografia: string;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
Controller,
|
Controller,
|
||||||
Delete,
|
Delete,
|
||||||
Get,
|
Get,
|
||||||
|
HttpException,
|
||||||
Logger,
|
Logger,
|
||||||
Param,
|
Param,
|
||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
@@ -12,10 +13,11 @@ import {
|
|||||||
UseGuards
|
UseGuards
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import { ProfesorService } from "./profesor.service";
|
import { ProfesorService } from "./profesor.service";
|
||||||
import { profesorDto } from "./dto/profesorDto.dto";
|
import { profesorDto, UpdateProfesorImageDto } from "./dto/profesorDto.dto";
|
||||||
import { Roles } from "../permissions/roles.decorator";
|
import { Roles } from "../permissions/roles.decorator";
|
||||||
import { RolesGuard } from "../permissions/roles.guard";
|
import { RolesGuard } from "../permissions/roles.guard";
|
||||||
import { Role } from "../permissions/role.enum";
|
import { Role } from "../permissions/role.enum";
|
||||||
|
import { Profesor } from "./entities/profesor.entity";
|
||||||
|
|
||||||
@Controller("profesor")
|
@Controller("profesor")
|
||||||
@UseGuards(RolesGuard)
|
@UseGuards(RolesGuard)
|
||||||
@@ -30,6 +32,24 @@ export class ProfesorController {
|
|||||||
return this.profesorService.register(data);
|
return this.profesorService.register(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Put(':id_profesor/image')
|
||||||
|
async updateImage(
|
||||||
|
@Param('id_profesor') id_profesor: number,
|
||||||
|
@Body() updateProfesorImageDto: UpdateProfesorImageDto,
|
||||||
|
): Promise<Profesor> {
|
||||||
|
const { fotografia } = updateProfesorImageDto;
|
||||||
|
|
||||||
|
const profesor = await this.profesorService.findOne(id_profesor);
|
||||||
|
|
||||||
|
if (!profesor) {
|
||||||
|
throw new HttpException('Profesor not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
profesor.fotografia = fotografia;
|
||||||
|
|
||||||
|
return this.profesorService.update(profesor);
|
||||||
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll() {
|
findAll() {
|
||||||
Logger.debug("findAllProfesors");
|
Logger.debug("findAllProfesors");
|
||||||
@@ -37,11 +57,11 @@ export class ProfesorController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get("page")
|
@Get("page")
|
||||||
findAllPaginated(@Query("page") page: number = 1, @Query("limit") limit: number = 10, @Query() filters: any) {
|
findAllPaginated(@Query("page") page: number = 1, @Query("limit") limit: number = 12, @Query() filters: any) {
|
||||||
try {
|
try {
|
||||||
Logger.debug("Page Profesors");
|
Logger.debug("Page Profesors");
|
||||||
page = page < 1 ? 1 : page;
|
page = page < 1 ? 1 : page;
|
||||||
limit = limit > 10 || limit < 1 ? 10 : limit;
|
limit = limit > 12 || limit < 1 ? 12 : limit;
|
||||||
return this.profesorService.findAllPaginated(page, limit, filters);
|
return this.profesorService.findAllPaginated(page, limit, filters);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error("profesor controller ", err.error);
|
Logger.error("profesor controller ", err.error);
|
||||||
|
|||||||
@@ -10,12 +10,7 @@ import { ProyectosAcademicos } from 'src/proyectos_academicos/entities/proyectos
|
|||||||
import { DatosAcademicos } from 'src/datos_academicos/entities/datos_academicos.entity'
|
import { DatosAcademicos } from 'src/datos_academicos/entities/datos_academicos.entity'
|
||||||
import { LineasInvestigacion } from 'src/lineas_investigacion/entities/lineas_investigacion.entity'
|
import { LineasInvestigacion } from 'src/lineas_investigacion/entities/lineas_investigacion.entity'
|
||||||
|
|
||||||
import { ProyectosAcademicosService } from 'src/proyectos_academicos/proyectos_academicos.service';
|
|
||||||
import { DatosAcademicosService } from 'src/datos_academicos/datos_academicos.service';
|
|
||||||
import { LineasInvestigacionService } from 'src/lineas_investigacion/lineas_investigacion.service';
|
|
||||||
|
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
import { RolesGuard } from '../permissions/roles.guard';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
|||||||
@@ -27,6 +27,14 @@ export class ProfesorService {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findOne(id_profesor: number): Promise<Profesor | undefined> {
|
||||||
|
return this.profesorRepository.findOne({ where: { id_profesor } });
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(profesor: Profesor): Promise<Profesor> {
|
||||||
|
return this.profesorRepository.save(profesor);
|
||||||
|
}
|
||||||
|
|
||||||
private async findAvailableId(): Promise<number> {
|
private async findAvailableId(): Promise<number> {
|
||||||
let id = 1;
|
let id = 1;
|
||||||
let exists = true;
|
let exists = true;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export class AdscripcionService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findAll(): Promise<Adscripcion[]> {
|
async findAll(): Promise<Adscripcion[]> {
|
||||||
return this.adscripcionRepository.find();
|
return this.adscripcionRepository.find({
|
||||||
|
order: { adscripcion: 'ASC' }, // Change 'adscripcion' to your desired column for ordering
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
ParseIntPipe,
|
ParseIntPipe,
|
||||||
Query,
|
Query,
|
||||||
Logger,
|
Logger,
|
||||||
|
Req,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { AuthGuard } from './auth.guard';
|
import { AuthGuard } from './auth.guard';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
@@ -36,7 +37,7 @@ export class AuthController {
|
|||||||
|
|
||||||
//@UseGuards()
|
//@UseGuards()
|
||||||
@Post('register')
|
@Post('register')
|
||||||
//@Roles(Role.Admin)
|
@Roles(Role.Admin)
|
||||||
async register(@Body() data: registerDto) {
|
async register(@Body() data: registerDto) {
|
||||||
Logger.debug('register user');
|
Logger.debug('register user');
|
||||||
return this.authService.register(data);
|
return this.authService.register(data);
|
||||||
@@ -73,9 +74,12 @@ export class AuthController {
|
|||||||
async update(
|
async update(
|
||||||
@Param('id_usuario') id_usuario: number,
|
@Param('id_usuario') id_usuario: number,
|
||||||
@Body() data: registerDto,
|
@Body() data: registerDto,
|
||||||
|
@Req() req: any
|
||||||
) {
|
) {
|
||||||
Logger.debug('update user');
|
const authHeader = req.headers['authorization'];
|
||||||
return this.authService.update(id_usuario, data);
|
const [, token] = authHeader.split(' ');
|
||||||
|
|
||||||
|
return this.authService.update(id_usuario, data, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
//@UseGuards(AuthGuard)
|
//@UseGuards(AuthGuard)
|
||||||
|
|||||||
+37
-12
@@ -26,7 +26,7 @@ export class AuthService {
|
|||||||
|
|
||||||
//register users
|
//register users
|
||||||
async register(data: registerDto) {
|
async register(data: registerDto) {
|
||||||
const { usuario, contraseña} = data;
|
const { usuario, contraseña } = data;
|
||||||
|
|
||||||
if (await this.usersService.findOne(usuario)) {
|
if (await this.usersService.findOne(usuario)) {
|
||||||
throw new HttpException('User already exist', 403);
|
throw new HttpException('User already exist', 403);
|
||||||
@@ -74,17 +74,29 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//update user
|
//update user
|
||||||
async update(id_usuario: number, data: registerDto) {
|
async update(
|
||||||
const { contraseña } = data;
|
id_usuario: number,
|
||||||
|
data: registerDto,
|
||||||
|
token: string,
|
||||||
|
): Promise<any> {
|
||||||
|
const { contraseña, id_tipo_usuario } = data;
|
||||||
|
|
||||||
|
const tokenUserId = this.getTokenUserId(token);
|
||||||
|
|
||||||
|
if (tokenUserId == id_usuario && id_tipo_usuario !== undefined) {
|
||||||
|
Logger.debug('Cannot modify id_tipo_usuario')
|
||||||
|
delete data.id_tipo_usuario;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await this.userRepository.findOne({ where: { id_usuario } });
|
||||||
|
if (!user) {
|
||||||
|
throw new HttpException('User not found', 404);
|
||||||
|
}
|
||||||
|
|
||||||
if (contraseña) {
|
if (contraseña) {
|
||||||
const hashedpassword = await hash(contraseña, 10);
|
const hashedpassword = await hash(contraseña, 10);
|
||||||
data = { ...data, contraseña: hashedpassword };
|
data = { ...data, contraseña: hashedpassword };
|
||||||
} else {
|
} else {
|
||||||
const user = await this.userRepository.findOne({ where: { id_usuario } });
|
|
||||||
if (!user) {
|
|
||||||
throw new HttpException('User not found', 404);
|
|
||||||
}
|
|
||||||
data = { ...data, contraseña: user.contraseña };
|
data = { ...data, contraseña: user.contraseña };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +126,7 @@ export class AuthService {
|
|||||||
throw new UnauthorizedException('Token has expired');
|
throw new UnauthorizedException('Token has expired');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ;
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new UnauthorizedException('validation token failed');
|
throw new UnauthorizedException('validation token failed');
|
||||||
}
|
}
|
||||||
@@ -127,18 +139,22 @@ export class AuthService {
|
|||||||
async findAllPaginated(
|
async findAllPaginated(
|
||||||
page: number,
|
page: number,
|
||||||
limit: number,
|
limit: number,
|
||||||
filters: any
|
filters: any,
|
||||||
): Promise<{ usuarios: User[], total: number, totalPages: number }> {
|
): Promise<{ usuarios: User[]; total: number; totalPages: number }> {
|
||||||
const query = this.userRepository.createQueryBuilder('usuario');
|
const query = this.userRepository.createQueryBuilder('usuario');
|
||||||
|
|
||||||
if (filters.nombre) {
|
if (filters.nombre) {
|
||||||
Logger.debug('fiter by name user');
|
Logger.debug('fiter by name user');
|
||||||
query.andWhere('usuario.nombre LIKE :nombre', { nombre: `%${filters.nombre}%` });
|
query.andWhere('usuario.nombre LIKE :nombre', {
|
||||||
|
nombre: `%${filters.nombre}%`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters.id_tipo_usuario) {
|
if (filters.id_tipo_usuario) {
|
||||||
Logger.debug('fiter by id user');
|
Logger.debug('fiter by id user');
|
||||||
query.andWhere('usuario.id_tipo_usuario = :id_tipo_usuario', { id_tipo_usuario: filters.id_tipo_usuario });
|
query.andWhere('usuario.id_tipo_usuario = :id_tipo_usuario', {
|
||||||
|
id_tipo_usuario: filters.id_tipo_usuario,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const [usuarios, total] = await query
|
const [usuarios, total] = await query
|
||||||
@@ -164,4 +180,13 @@ export class AuthService {
|
|||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTokenUserId(token: string): number {
|
||||||
|
try {
|
||||||
|
const decoded = this.jwtService.verify(token);
|
||||||
|
return decoded['id_usuario'];
|
||||||
|
} catch (error) {
|
||||||
|
throw new UnauthorizedException('Invalid token');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ export class CategoriaService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findAll(): Promise<Categoria[]> {
|
async findAll(): Promise<Categoria[]> {
|
||||||
return this.categoriaRepository.find();
|
return this.categoriaRepository.find({ order: { categoria: 'ASC' } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export class EdificioService {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findAll(): Promise<Edificio[]> {
|
async findAll(): Promise<Edificio[]> {
|
||||||
return this.categoriaRepository.find();
|
return this.categoriaRepository.find({
|
||||||
|
order: { edificio: 'ASC' }, // Change 'edificio' to your desired column for ordering
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { Injectable, BadRequestException, NotFoundException, Logger } from '@nestjs/common';
|
import { Injectable, BadRequestException, Logger } from '@nestjs/common';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as sharp from 'sharp';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ImagenService {
|
export class ImagenService {
|
||||||
async saveImage(fotografia: string, nombre: string): Promise<string> {
|
async saveImage(fotografia: string, id: string): Promise<string> {
|
||||||
if (!fotografia) {
|
if (!fotografia) {
|
||||||
throw new BadRequestException('No image provided');
|
throw new BadRequestException('No image provided');
|
||||||
}
|
}
|
||||||
@@ -19,8 +18,7 @@ export class ImagenService {
|
|||||||
|
|
||||||
// Decode base64 string and save the image
|
// Decode base64 string and save the image
|
||||||
const buffer = Buffer.from(fotografia.split(',')[1], 'base64');
|
const buffer = Buffer.from(fotografia.split(',')[1], 'base64');
|
||||||
const sanitizedFileName = nombre.replace(/\s+/g, '_').toLowerCase();
|
const imageName = `${id}.${ext}`;
|
||||||
const imageName = `${sanitizedFileName}.${ext}`;
|
|
||||||
|
|
||||||
// Save image to the 'imagenes' directory in the root of the project
|
// Save image to the 'imagenes' directory in the root of the project
|
||||||
const imagePath = path.join(process.cwd(), 'imagenes', imageName);
|
const imagePath = path.join(process.cwd(), 'imagenes', imageName);
|
||||||
@@ -31,16 +29,15 @@ export class ImagenService {
|
|||||||
fs.mkdirSync(dirPath, { recursive: true });
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
await sharp(buffer).toFile(imagePath);
|
fs.writeFileSync(imagePath, buffer);
|
||||||
|
|
||||||
return `/imagenes/${imageName}`;
|
return imageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteImage(nombre: string): Promise<void> {
|
async deleteImage(id: string): Promise<void> {
|
||||||
Logger.debug('delete image');
|
Logger.debug('delete image');
|
||||||
const sanitizedFileName = nombre.replace(/\s+/g, '_').toLowerCase();
|
|
||||||
const imageDir = path.join(process.cwd(), 'imagenes');
|
const imageDir = path.join(process.cwd(), 'imagenes');
|
||||||
const imagePath = path.join(imageDir, sanitizedFileName);
|
const imagePath = path.join(imageDir, id);
|
||||||
|
|
||||||
const extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'avif'];
|
const extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'avif'];
|
||||||
|
|
||||||
@@ -56,16 +53,15 @@ export class ImagenService {
|
|||||||
|
|
||||||
if (!fileFound) {
|
if (!fileFound) {
|
||||||
console.log('Image not found, but continuing to save the new image.');
|
console.log('Image not found, but continuing to save the new image.');
|
||||||
// No se lanza excepción
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async modify(fotografia: string, nombre: string): Promise<string> {
|
async modify(fotografia: string, id: string): Promise<string> {
|
||||||
if (!fotografia) {
|
if (!fotografia) {
|
||||||
throw new BadRequestException('No image provided');
|
throw new BadRequestException('No image provided');
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.deleteImage(nombre);
|
await this.deleteImage(id);
|
||||||
|
|
||||||
// Extract the image extension
|
// Extract the image extension
|
||||||
const matches = fotografia.match(/^data:image\/([a-zA-Z]+);base64,/);
|
const matches = fotografia.match(/^data:image\/([a-zA-Z]+);base64,/);
|
||||||
@@ -76,8 +72,7 @@ export class ImagenService {
|
|||||||
|
|
||||||
// Decode base64 string and save the image
|
// Decode base64 string and save the image
|
||||||
const buffer = Buffer.from(fotografia.split(',')[1], 'base64');
|
const buffer = Buffer.from(fotografia.split(',')[1], 'base64');
|
||||||
const sanitizedFileName = nombre.replace(/\s+/g, '_').toLowerCase();
|
const imageName = `${id}.${ext}`;
|
||||||
const imageName = `${sanitizedFileName}.${ext}`;
|
|
||||||
|
|
||||||
// Save image to the 'imagenes' directory in the root of the project
|
// Save image to the 'imagenes' directory in the root of the project
|
||||||
const imagePath = path.join(process.cwd(), 'imagenes', imageName);
|
const imagePath = path.join(process.cwd(), 'imagenes', imageName);
|
||||||
@@ -88,8 +83,8 @@ export class ImagenService {
|
|||||||
fs.mkdirSync(dirPath, { recursive: true });
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
await sharp(buffer).toFile(imagePath);
|
fs.writeFileSync(imagePath, buffer);
|
||||||
|
|
||||||
return `/imagenes/${imageName}`;
|
return imageName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,19 @@ import { NestFactory } from '@nestjs/core';
|
|||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import { NestExpressApplication } from '@nestjs/platform-express';
|
import { NestExpressApplication } from '@nestjs/platform-express';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import * as bodyParser from 'body-parser';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
||||||
app.enableCors();
|
app.enableCors();
|
||||||
|
|
||||||
|
app.use(bodyParser.json({ limit: '1mb' }));
|
||||||
|
app.use(bodyParser.urlencoded({ limit: '1mb', extended: true }));
|
||||||
|
|
||||||
app.useStaticAssets(path.join(__dirname, '..', 'imagenes'), {
|
app.useStaticAssets(path.join(__dirname, '..', 'imagenes'), {
|
||||||
prefix: '/imagenes/',
|
prefix: '/imagenes/',
|
||||||
});
|
});
|
||||||
|
|
||||||
await app.listen(3000);
|
await app.listen(3000);
|
||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user