Add get profile route that supports gravatar
This commit is contained in:
@@ -44,16 +44,16 @@ export class AuthController {
|
|||||||
private settingsService: SettingsService,
|
private settingsService: SettingsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get("login/google")
|
@Get('login/google')
|
||||||
@UseGuards(AuthGuard('google'))
|
@UseGuards(AuthGuard('google'))
|
||||||
googleLogin() { }
|
googleLogin() {}
|
||||||
|
|
||||||
@Get("logged/google")
|
@Get('logged/google')
|
||||||
@UseGuards(AuthGuard('google'))
|
@UseGuards(AuthGuard('google'))
|
||||||
async googleLoginCallbakc(@Req() req: any) {
|
async googleLoginCallbakc(@Req() req: any) {
|
||||||
let user = await this.usersService.user({googleID: req.user.googleID});
|
let user = await this.usersService.user({ googleID: req.user.googleID });
|
||||||
if (!user) {
|
if (!user) {
|
||||||
user = await this.usersService.createUser(req.user)
|
user = await this.usersService.createUser(req.user);
|
||||||
await this.settingsService.createUserSetting(user.id);
|
await this.settingsService.createUserSetting(user.id);
|
||||||
}
|
}
|
||||||
return this.authService.login(user);
|
return this.authService.login(user);
|
||||||
@@ -62,9 +62,9 @@ export class AuthController {
|
|||||||
@Post('register')
|
@Post('register')
|
||||||
async register(@Body() registerDto: RegisterDto): Promise<void> {
|
async register(@Body() registerDto: RegisterDto): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const user = await this.usersService.createUser(registerDto)
|
const user = await this.usersService.createUser(registerDto);
|
||||||
await this.settingsService.createUserSetting(user.id);
|
await this.settingsService.createUserSetting(user.id);
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
throw new BadRequestException();
|
throw new BadRequestException();
|
||||||
}
|
}
|
||||||
@@ -86,6 +86,15 @@ export class AuthController {
|
|||||||
return this.authService.login(user);
|
return this.authService.login(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(JwtAuthGuard)
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@ApiOkResponse({ description: 'The user profile picture' })
|
||||||
|
@ApiUnauthorizedResponse({ description: 'Invalid token' })
|
||||||
|
@Get('me/picture')
|
||||||
|
async getProfilePicture(@Request() req: any) {
|
||||||
|
return await this.usersService.getProfilePicture(req.user.id);
|
||||||
|
}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@ApiOkResponse({ description: 'Successfully logged in', type: User })
|
@ApiOkResponse({ description: 'Successfully logged in', type: User })
|
||||||
@@ -133,25 +142,28 @@ export class AuthController {
|
|||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@ApiOkResponse({description: 'Successfully edited settings', type: Setting})
|
@ApiOkResponse({ description: 'Successfully edited settings', type: Setting })
|
||||||
@ApiUnauthorizedResponse({description: 'Invalid token'})
|
@ApiUnauthorizedResponse({ description: 'Invalid token' })
|
||||||
@Patch('me/settings')
|
@Patch('me/settings')
|
||||||
udpateSettings(
|
udpateSettings(
|
||||||
@Request() req: any,
|
@Request() req: any,
|
||||||
@Body() settingUserDto: UpdateSettingDto): Promise<Setting> {
|
@Body() settingUserDto: UpdateSettingDto,
|
||||||
|
): Promise<Setting> {
|
||||||
return this.settingsService.updateUserSettings({
|
return this.settingsService.updateUserSettings({
|
||||||
where: { userId: +req.user.id},
|
where: { userId: +req.user.id },
|
||||||
data: settingUserDto,
|
data: settingUserDto,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@ApiOkResponse({description: 'Successfully edited settings', type: Setting})
|
@ApiOkResponse({ description: 'Successfully edited settings', type: Setting })
|
||||||
@ApiUnauthorizedResponse({description: 'Invalid token'})
|
@ApiUnauthorizedResponse({ description: 'Invalid token' })
|
||||||
@Get('me/settings')
|
@Get('me/settings')
|
||||||
async getSettings(@Request() req: any): Promise<Setting> {
|
async getSettings(@Request() req: any): Promise<Setting> {
|
||||||
const result = await this.settingsService.getUserSetting({ userId: +req.user.id });
|
const result = await this.settingsService.getUserSetting({
|
||||||
|
userId: +req.user.id,
|
||||||
|
});
|
||||||
if (!result) throw new NotFoundException();
|
if (!result) throw new NotFoundException();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,9 @@ export class UsersController {
|
|||||||
if (!ret) throw new NotFoundException();
|
if (!ret) throw new NotFoundException();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get(':id/picture')
|
||||||
|
async getPicture(@Param('id') id: number) {
|
||||||
|
return await this.usersService.getProfilePicture(+id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import {
|
||||||
|
Injectable,
|
||||||
|
InternalServerErrorException,
|
||||||
|
NotFoundException,
|
||||||
|
StreamableFile,
|
||||||
|
} from '@nestjs/common';
|
||||||
import { User, Prisma } from '@prisma/client';
|
import { User, Prisma } from '@prisma/client';
|
||||||
import { PrismaService } from 'src/prisma/prisma.service';
|
import { PrismaService } from 'src/prisma/prisma.service';
|
||||||
import * as bcrypt from 'bcryptjs';
|
import * as bcrypt from 'bcryptjs';
|
||||||
import { randomUUID } from 'crypto';
|
import { createHash, randomUUID } from 'crypto';
|
||||||
|
import { createReadStream, existsSync } from 'fs';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UsersService {
|
export class UsersService {
|
||||||
@@ -34,8 +40,7 @@ export class UsersService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async createUser(data: Prisma.UserCreateInput): Promise<User> {
|
async createUser(data: Prisma.UserCreateInput): Promise<User> {
|
||||||
if (data.password)
|
if (data.password) data.password = await bcrypt.hash(data.password, 8);
|
||||||
data.password = await bcrypt.hash(data.password, 8);
|
|
||||||
return this.prisma.user.create({
|
return this.prisma.user.create({
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
@@ -73,4 +78,23 @@ export class UsersService {
|
|||||||
where,
|
where,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getProfilePicture(userId: number) {
|
||||||
|
const path = `/data/${userId}.png`;
|
||||||
|
if (existsSync(path)) {
|
||||||
|
const file = createReadStream(path);
|
||||||
|
return new StreamableFile(file);
|
||||||
|
}
|
||||||
|
// We could not find a profile icon locally, using gravatar instead.
|
||||||
|
const user = await this.user({ id: userId });
|
||||||
|
if (!user) throw new InternalServerErrorException();
|
||||||
|
const hash = createHash('md5')
|
||||||
|
.update(user.email.trim().toLowerCase())
|
||||||
|
.digest('hex');
|
||||||
|
const resp = await fetch(
|
||||||
|
`https://www.gravatar.com/avatar/${hash}.jpg?d=404`,
|
||||||
|
);
|
||||||
|
if (!resp.ok) throw new NotFoundException('No image found for user');
|
||||||
|
return resp.arrayBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./back:/app
|
- ./back:/app
|
||||||
- ./assets:/assets
|
- ./assets:/assets
|
||||||
|
- data:/data
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -54,3 +55,6 @@ services:
|
|||||||
- "back"
|
- "back"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ services:
|
|||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./assets:/assets
|
- ./assets:/assets
|
||||||
|
- data:/data
|
||||||
scorometer:
|
scorometer:
|
||||||
image: ghcr.io/chroma-case/scorometer:main
|
image: ghcr.io/chroma-case/scorometer:main
|
||||||
ports:
|
ports:
|
||||||
@@ -43,3 +44,6 @@ services:
|
|||||||
- "back"
|
- "back"
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ services:
|
|||||||
- .env
|
- .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./assets:/assets
|
- ./assets:/assets
|
||||||
|
- data:/data
|
||||||
scorometer:
|
scorometer:
|
||||||
build: ./scorometer
|
build: ./scorometer
|
||||||
ports:
|
ports:
|
||||||
@@ -52,3 +53,4 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db:
|
db:
|
||||||
|
data:
|
||||||
|
|||||||
Reference in New Issue
Block a user