Skip to content

Feature/login formular #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 39 commits into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
d1018ab
composant login, composant logo et page login faites(mobile)
sadjoaldi Mar 28, 2025
87d41d0
page login, signup, forgotten password done
sadjoaldi Mar 31, 2025
9d5224c
bug build
sadjoaldi Apr 1, 2025
4282fa1
bug build
sadjoaldi Apr 1, 2025
97024fe
bug build
sadjoaldi Apr 1, 2025
26faf67
merge develop
sadjoaldi Apr 1, 2025
9151867
pull develop
sadjoaldi Apr 1, 2025
ba2db5d
ajustement style
sadjoaldi Apr 2, 2025
92a6377
register&login back ok, login front ok
sadjoaldi Apr 9, 2025
a5c3381
renommage de fichiers, register et login ok front et back
sadjoaldi Apr 9, 2025
940e59d
cheik error
sadjoaldi Apr 9, 2025
14b1fcb
cheik error
sadjoaldi Apr 9, 2025
626410c
cheik error
sadjoaldi Apr 9, 2025
ffb02e8
correction
sadjoaldi Apr 10, 2025
c30c060
register, login, logout good
sadjoaldi Apr 17, 2025
8d9f34e
register, login, logout ok
sadjoaldi Apr 22, 2025
b1ae9eb
Merge branch 'develop' into feature/login-formular
sadjoaldi Apr 22, 2025
dada3ee
register,login, logout
sadjoaldi Apr 22, 2025
fe40730
register,login, logout
sadjoaldi Apr 22, 2025
d19dfe1
corrections
sadjoaldi Apr 23, 2025
07d13d2
regis, log, cook
sadjoaldi Apr 24, 2025
c68a1c0
pull
sadjoaldi Apr 24, 2025
143c9e8
Merge branch 'develop' into feature/login-formular
sadjoaldi Apr 24, 2025
7b4c593
pull
sadjoaldi Apr 24, 2025
0251665
pull
sadjoaldi Apr 24, 2025
bb00354
pull
sadjoaldi Apr 24, 2025
2a47c44
corrections
sadjoaldi Apr 24, 2025
8561465
correct
sadjoaldi Apr 25, 2025
c2bcfdd
Delete .vscode/settings.json
TeddyAgt Apr 25, 2025
f0d6d56
recup user
sadjoaldi Apr 25, 2025
99e8a66
correction pr
sadjoaldi Apr 28, 2025
ff834c6
correction pr
sadjoaldi Apr 28, 2025
3498528
Delete .vscode/settings.json
TeddyAgt Apr 28, 2025
a7fa47a
correction authentification
sadjoaldi Apr 29, 2025
1966e25
correction
sadjoaldi Apr 29, 2025
0e6997d
correction authmiddl
sadjoaldi Apr 29, 2025
e2079ea
rename newAccessToken à accessToken ligne 55 et 66 de authmiddleware
sadjoaldi Apr 29, 2025
04d5919
creation fichier cookie-router, ajout dans authrouter, ajout de type …
sadjoaldi Apr 29, 2025
f3b8a0b
vscode settings
sadjoaldi Apr 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,5 @@ web-build/
*-mock.*
deployment/db/
*-mock.*
test.js
test.js
**/*.tsbuildinfo
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ packages/frontend/mobile/ios
packages/frontend/mobile/android
deployment/mysql/data
**/types/database.ts
**/*.tsbuildinfo
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Devdb.colorTheme": "dark"
}
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default typescriptPlugin.config([
'packages/frontend/mobile/ios',
'packages/frontend/mobile/android',
'deployment/mysql/data',
'**/*.tsbuildinfo',
],
},
{
Expand Down
864 changes: 480 additions & 384 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/backend/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@
"dependencies": {
"@app/backend-shared": "*",
"@app/shared": "*",
"argon2": "^0.41.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"express": "^4.21.2",
"jose": "^6.0.10",
"kysely": "^0.27.6"
},
"devDependencies": {
"@types/cookie-parser": "^1.4.8",
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
"@types/react": "^19.0.12",
Expand Down
11 changes: 11 additions & 0 deletions packages/backend/api/src/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// import express from 'express';

// import postLoginRouter from './post.login';
// import postRegisterRouter from './post.register';

// const authRouter = express.Router();

// authRouter.use(postLoginRouter);
// authRouter.use(postRegisterRouter);

// export default authRouter;
57 changes: 57 additions & 0 deletions packages/backend/api/src/auth/post.login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import argon2 from 'argon2';
import express from 'express';
import * as jose from 'jose';
import { sql } from 'kysely';

import { db } from '@app/backend-shared';

const loginRouter = express.Router();

const FRONTEND_HOST = process.env.FRONTEND_HOST ?? '';

loginRouter.post('/login', async (req, res) => {
try {
const { email, password } = req.body;

if (!email || !password) {

Check warning on line 16 in packages/backend/api/src/auth/post.login.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected any value in conditional. An explicit comparison or type conversion is required

Check warning on line 16 in packages/backend/api/src/auth/post.login.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected any value in conditional. An explicit comparison or type conversion is required
return res.status(400).json({ error: 'email and password required' });
}

const result = await sql`
SELECT * FROM user WHERE user.email = ${email}
`.execute(db);

const user = result.rows[0];

if (!user) {

Check warning on line 26 in packages/backend/api/src/auth/post.login.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected any value in conditional. An explicit comparison or type conversion is required
res.json({ message: 'user or password incorrect' });
return;
}

const isPasswordValide = await argon2.verify(user.password, password);

if (!isPasswordValide) {
res.json({ message: 'user or password incorrect' });
return;
}

new jose.SignJWT({
sub: email,
})
.setProtectedHeader({
alg: 'HS256',
})
.setIssuedAt()
.setIssuer(FRONTEND_HOST)
.setAudience(FRONTEND_HOST);

res.json({
message: 'User logged in',
});
} catch (error) {
console.log(error);

Check warning on line 52 in packages/backend/api/src/auth/post.login.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected console statement. Only these console methods are allowed: error
res.status(400);
}
});

export default loginRouter;
36 changes: 36 additions & 0 deletions packages/backend/api/src/auth/post.register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import argon2 from 'argon2';
import express from 'express';
import { sql } from 'kysely';

import { db } from '@app/backend-shared';

const postRegisterRouter = express.Router();

postRegisterRouter.post('/register', async (req, res) => {
try {
const { email, username, password } = req.body;

if (!email || !username || !password) {

Check warning on line 13 in packages/backend/api/src/auth/post.register.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected any value in conditional. An explicit comparison or type conversion is required

Check warning on line 13 in packages/backend/api/src/auth/post.register.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected any value in conditional. An explicit comparison or type conversion is required

Check warning on line 13 in packages/backend/api/src/auth/post.register.ts

View workflow job for this annotation

GitHub Actions / check-pr

Unexpected any value in conditional. An explicit comparison or type conversion is required
return res.status(400).json({ error: 'All fields are required' });
}

const hashedPassword = await argon2.hash(password);

await sql`
INSERT INTO user(email, username, password) VALUES(${email}, ${username}, ${hashedPassword})
`.execute(db);

res.status(201).json({ message: 'user successfully created' });
} catch (error) {
console.error('not user created', error);
res.status(500).json({ error: 'internal server error' });
}
});

export default postRegisterRouter;

// {
// "email":"[email protected]",
// "username":"amingo",
// "password":"amingo"
// }
12 changes: 11 additions & 1 deletion packages/backend/api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import cookieParser from 'cookie-parser';
import cors from 'cors';
import express from 'express';
import path from 'path';
Expand All @@ -14,8 +15,17 @@ const app = express();
const HOST = process.env.BACKEND_HOST ?? 'localhost';
const PORT = process.env.BACKEND_PORT ?? 3000;

const COOKIE_SECRET = process.env.COOKIE_SECRET ?? 'secret';

app.use(cookieParser(COOKIE_SECRET));

app.use(express.json());
app.use(cors());
app.use(
cors({
origin: `http://${process.env.FRONTEND_HOST}:${process.env.FRONTEND_PORT}`,
credentials: true,
}),
);
app.use(
'/cdn',
express.static(
Expand Down
11 changes: 11 additions & 0 deletions packages/backend/api/src/models/cookie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { db } from '@app/backend-shared';

export default {
userCookie() {
return db
.selectFrom('user')
.select(['user.id', 'user.email'])
.where('user.id', '=', 1)
.executeTakeFirstOrThrow();
},
};
28 changes: 28 additions & 0 deletions packages/backend/api/src/models/user-login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import argon2 from 'argon2';

import { db } from '@app/backend-shared';

export async function userLogin(email: string, password: string) {
try {
const user = await db
.selectFrom('user')
.selectAll()
.where('user.email', '=', email || 'user.username')
.executeTakeFirst();

if (!user) {
return { error: 'Invalid email or password' };
}

const isPasswordValid = await argon2.verify(user.password, password);

if (!isPasswordValid) {
return { error: 'Invalid email or password' };
}

return { message: 'Login successful' };
} catch (error) {
console.error('Error logging in:', error);
throw new Error('Internal server error');
}
}
25 changes: 25 additions & 0 deletions packages/backend/api/src/models/user-register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import argon2 from 'argon2';

import { db } from '@app/backend-shared';

export async function userRegister(
email: string,
username: string,
password: string,
) {
const hashPassword = await argon2.hash(password, {
memoryCost: 19456,
timeCost: 2,
parallelism: 1,
});

return db
.insertInto('user')
.values({ email, username, password: hashPassword })
.executeTakeFirst()
.then(() => ({ message: 'User created successfully' }))
.catch((error: unknown) => {
console.error('Error creating user:', error);
throw new Error('Failed to create user');
});
}
8 changes: 8 additions & 0 deletions packages/backend/api/src/router.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import express from 'express';

import {
default as cookkieRouterGet,
default as userLoginRouter,
} from './subrouters/login-router';
import postsRouter from './subrouters/posts-router';
import tagsRouter from './subrouters/tags-router';
import usersRouter from './subrouters/users-router';
Expand All @@ -10,6 +14,10 @@ router.use('/posts', postsRouter);
router.use('/users', usersRouter);
router.use('/tags', tagsRouter);

router.use('/login', userLoginRouter);
router.use('/register', usersRouter);
router.use('/cookie', cookkieRouterGet);

router.get('*', function (req, res) {
res.status(404).send(`ressource ${req.path} not found`);
});
Expand Down
93 changes: 93 additions & 0 deletions packages/backend/api/src/subrouters/login-router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import express from 'express';
import * as jose from 'jose';

import { env } from '@app/shared';

import { userLogin } from '@/models/user-login';

env();

const userLoginRouter = express.Router();

const cookkieRouterGet = express.Router();

const FRONTEND_HOST = process.env.FRONTEND_HOST ?? '';

const JWT_SECRET = process.env.JWT_SECRET;

const secret = new TextEncoder().encode(JWT_SECRET);

// POST LOGIN**************************************************

userLoginRouter.post('/', async function (req, res) {
try {
const { email, password } = req.body;

const userAccess = await userLogin(email, password);

const token = await new jose.SignJWT({ sub: email })
.setProtectedHeader({ alg: 'HS256' })
.setIssuedAt()
.setIssuer(FRONTEND_HOST)
.setAudience(FRONTEND_HOST)
.setExpirationTime('2h')
.sign(secret);

res.cookie('token', token, {
httpOnly: true,
signed: true,
// secure: true,
// sameSite: 'strict',
});

res.json(userAccess);
} catch (error) {
if (
error instanceof Error &&
error.message === 'Invalid email or password'
) {
res.status(401).json({ message: error.message });
} else {
console.error('Error during login:', error);
res.status(500).json({ message: 'Internal login server error' });
}
}
});

// GET COOKIES **************************************************

cookkieRouterGet.get('/', async function (req, res) {
const token = req.signedCookies.token;

try {
const { payload } = await jose.jwtVerify(token, secret, {
audience: FRONTEND_HOST,
issuer: FRONTEND_HOST,
});

res.json(payload);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'wrong' });
}
});

// GET **************************************************

userLoginRouter.get('/:id', function (req, res) {
res.send('login get');
});

// UPDATE **************************************************

userLoginRouter.put('/', function (req, res) {
res.send('login put');
});

// DELETE **************************************************

userLoginRouter.delete('/:id', function (req, res) {
res.send('login delete');
});

export default userLoginRouter;
14 changes: 13 additions & 1 deletion packages/backend/api/src/subrouters/users-router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import express from 'express';

import postModel from '@/models/post-model';
import { userRegister } from '@/models/user-register';

const usersRouter = express.Router();

Expand All @@ -19,6 +19,18 @@ usersRouter.get('/tag/:tag', function () {

// POST **************************************************

usersRouter.post('/', async function (req, res) {
try {
const { email, username, password } = req.body;

const result = await userRegister(email, username, password);

res.json(result);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Internal register server error' });
}
});
// UPDATE **************************************************

// DELETE **************************************************
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"vite": "^6.2.0"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "^4.38.0",
"@rollup/rollup-win32-x64-msvc": "^4.37.0",
"@tailwindcss/oxide-win32-x64-msvc": "^4.0.17"
}
Expand Down
Loading
Loading