Skip to content

Commit

Permalink
Major Refactor: migrate to React-Query and Axios. Uplaodd avatar afte…
Browse files Browse the repository at this point in the history
…r registration but before activation
  • Loading branch information
azeddine-hmd committed Dec 15, 2023
1 parent db73020 commit 6d69502
Show file tree
Hide file tree
Showing 35 changed files with 1,664 additions and 311 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ docker compose up --build
* Nextjs 13
* Server/Client component
* Tailwindcss
* Framer-Motion (animation)

## Example :
Check hosted webserver on: [Chichat | talk and hang out with friends](https://chichat.azeddine.xyz)
19 changes: 14 additions & 5 deletions backend/src/api/auth/auth-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,24 @@ import * as authService from './auth-service';
import { VerifyEmailDto } from './dto/verify-email';
import { LoginDto } from './dto/login-dto';
import { defaultCookieOptions } from '../../config';
import * as profileService from '../users/services/profile-service';

export async function register(req: Request, res: Response) {
const registerDto = plainToClass(RegisterDto, req.body);
const validationError = await validate(registerDto);
if (validationError.length > 0) return res.status(400).json(validationError);
const user = await authService.registerUser(registerDto);
res.status(201).send();
}

export async function uploadAvatar(req: Request, res: Response) {
const user = await authService.getUser(req.body.email, req.body.password);
const avatar = await profileService.uploadAvatar(
user,
req.files['avatar'][0]
);
await authService.sendEmailVerification(user);
res.status(201).send({
id: user.id,
username: user.username,
email: user.email,
});
res.status(201).send({ url: avatar.url });
}

export async function login(req: Request, res: Response) {
Expand All @@ -34,6 +40,9 @@ export async function verifyEmail(req: Request, res: Response) {
const validationError = await validate(verifyEmailDto);
if (validationError.length > 0) return res.status(400).json(validationError);
const user = await authService.verifyEmail(verifyEmailDto.code);
res.status(200).send();
return;

const { token } = await authService.login(user.email);
res.cookie(`${process.env.JWT_COOKIE_NAME}`, token, defaultCookieOptions);
res.status(200).send();
Expand Down
10 changes: 10 additions & 0 deletions backend/src/api/auth/auth-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ export async function registerUser(registerDto: RegisterDto): Promise<User> {
return user;
}

export async function getUser(email: string, password: string) {
const user = await prisma.user.findFirst({
where: { email: email },
});
if (!(await comparePassword(password, user.password)))
throw new HttpError(400, 'no such user with email and password');
return user;
}

export async function sendEmailVerification(user: User) {
if (process.env.NODE_ENV === 'test') return;
const emailSecret = randomUUID();
Expand Down Expand Up @@ -82,6 +91,7 @@ export async function login(email: string, password?: string) {
password: true,
username: true,
active: true,
avatar: true,
},
});
if (!user || (password && !comparePassword(password, user.password)))
Expand Down
21 changes: 20 additions & 1 deletion backend/src/api/auth/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Router } from 'express';
import * as authController from './auth-controller';
import passport from 'passport';
import { upload } from '../../config';

const prefix = '/auth';

Expand All @@ -13,5 +14,23 @@ authRouter.get(
);

authRouter.post(prefix + '/register', authController.register);
authRouter.post(prefix + '/email-verify', authController.verifyEmail);
authRouter.post(
prefix + '/upload/avatar',
upload.fields([
{
name: 'email',
},
{
name: 'password',
},
{
name: 'avatar',
},
]),
authController.uploadAvatar
);
authRouter.post(
prefix + '/email-verify',
authController.verifyEmail
);
authRouter.post(prefix + '/login', authController.login);
11 changes: 5 additions & 6 deletions backend/src/api/users/controllers/profile-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,18 @@ function mapToProfileResponse(user: User, avatar?: File) {
}

export async function myProfile(req: Request, res: Response) {
const { user, avatar } = await profileService.getProfile(req.user.id);
res.status(200).send(mapToProfileResponse(user, avatar));
const { profile, avatar } = await profileService.getProfile(req.user.id);
res.status(200).send(mapToProfileResponse(profile, avatar));
}

export async function otherProfile(req: Request, res: Response) {
const id = parseInt(req.params.id);
if (!id) throw new HttpError(400, 'Invalid id');
const { user, avatar } = await profileService.getProfile(id);
res.status(200).send(mapToProfileResponse(user, avatar));
const { profile, avatar } = await profileService.getProfile(id);
res.status(200).send(mapToProfileResponse(profile, avatar));
}

export async function uploadAvatar(req: Request, res: Response) {
console.log('Uploaded file: ', req.file);
const avatar = await profileService.uploadFile(req.user, req.file);
const avatar = await profileService.uploadAvatar(req.user, req.file);
res.status(201).send({ url: avatar.url });
}
12 changes: 7 additions & 5 deletions backend/src/api/users/services/profile-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ export async function getProfile(id: number) {
const user = await prisma.user.findUnique({
where: { id: id },
include: {
files: true,
avatar: true,
},
});
const avatar = user.files.find((file) => file['fieldname'] === 'avatar');
return {
user: user,
avatar: avatar,
profile: user,
avatar: user.avatar,
};
}

export async function uploadFile(me: Express.User, file: Express.Multer.File) {
export async function uploadAvatar(
me: Express.User,
file: Express.Multer.File
) {
try {
const avatar = await prisma.file.create({
data: {
Expand Down
2 changes: 0 additions & 2 deletions backend/src/config/pg.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Pool } from 'pg';

console.log('loading pg.ts file');

export const pool = new Pool({
user: process.env.POSTGRES_USER,
host: process.env.POSTGRES_HOST,
Expand Down
8 changes: 4 additions & 4 deletions frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "next/core-web-vitals"
// "rules": {
// "max-len": ["error", {"code": 120}]
// }
"extends": [
"next/core-web-vitals",
"plugin:@tanstack/eslint-plugin-query/recommended"
]
}
7 changes: 2 additions & 5 deletions frontend/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import FormField from "@/components/molecules/form-field";
import PrimaryDotLoadingButton from "@/components/molecules/primary-dot-loading-button";
import { loginUser } from "@/network/login";
import { delay } from "@/utils/delay";
import { strongEmail } from "@/utils/yup-extra";
import { delay } from "@/lib/delay";
import { strongEmail } from "@/lib/yup-extra";
import { Formik } from "formik";
import { motion } from "framer-motion";
import Link from "next/link";
Expand Down Expand Up @@ -41,9 +41,6 @@ export default function Login() {
} else {
setLoadingState(false);
setError(error.message);
// setTimeout(() => {
// setError(null);
// }, 10_000);
}
})();
}
Expand Down
Loading

0 comments on commit 6d69502

Please sign in to comment.