Skip to content

Commit

Permalink
add user in entities
Browse files Browse the repository at this point in the history
  • Loading branch information
BenoitSerrano committed Dec 10, 2024
1 parent 98e71e0 commit 3c284e9
Show file tree
Hide file tree
Showing 15 changed files with 351 additions and 3 deletions.
109 changes: 109 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@
"@types/cors": "^2.8.17",
"@types/express": "^4.17.13",
"@types/jest": "^29.5.2",
"@types/jsonwebtoken": "^9.0.7",
"@types/node": "^20.3.1",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.21.2",
"http-status": "^1.6.2",
"joi": "^17.9.2",
"jsonwebtoken": "^9.0.2",
"path": "^0.12.7",
"pg": "^8.8.0",
"pg-connection-string": "^2.6.0",
Expand Down
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ if (process.env.DATABASE_URL) {
const config = {
PORT: process.env.PORT || 3000,
HOST_URL: process.env.HOST_URL || '',
JWT_TOKEN_SECRET: process.env.JWT_TOKEN_SECRET || '',
HASH_SECRET: process.env.HASH_SECRET || '',
DATABASE_HOST: process.env.DATABASE_HOST || '',
DATABASE_PASSWORD: process.env.DATABASE_PASSWORD || '',
DATABASE_USER: process.env.DATABASE_USER || '',
Expand Down
3 changes: 2 additions & 1 deletion src/dataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { SystemPulse } from './modules/systemPulse';
import { Event } from './modules/event';
import { Monitor } from './modules/monitor';
import { MonitorEvent } from './modules/monitorEvent';
import { User } from './modules/user';

const dataSource = new DataSource({
type: 'postgres',
Expand All @@ -15,7 +16,7 @@ const dataSource = new DataSource({
database: config.DATABASE_NAME,
logging: ['warn', 'error'],
connectTimeoutMS: 20000,
entities: [SystemPulse, Event, Monitor, MonitorEvent],
entities: [SystemPulse, Event, Monitor, MonitorEvent, User],
subscribers: [],
migrations: ['**/migrations/*.js'],
});
Expand Down
26 changes: 26 additions & 0 deletions src/lib/hasher.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { hasher } from './hasher';

describe('hasher', () => {
it('should hash the value', () => {
const value1 = 'Une valeur spécifique';
const value2 = 'Une autre valeur moins spécifique';

const hash1 = hasher.hash(value1);
const hash2 = hasher.hash(value2);

expect(hash1.length).toBe(64);
expect(hash2.length).toBe(64);
expect(hash1).not.toBe(hash2);
});

it('should verify if the hashed value matches', () => {
const value = 'Une valeur spécifique';

const result = hasher.verify(
value,
'af85257f2800d6dfc7ed65d5566d7a159408e27080e5c81e491eb86783daac63',
);

expect(result).toBe(true);
});
});
15 changes: 15 additions & 0 deletions src/lib/hasher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import crypto from 'crypto';
import { config } from '../config';

const hasher = { hash, verify };

function hash(value: string) {
const hashedValue = crypto.createHmac('sha256', config.HASH_SECRET).update(value).digest('hex');
return hashedValue;
}

function verify(value: string, hashedValue: string) {
return hash(value) === hashedValue;
}

export { hasher };
25 changes: 25 additions & 0 deletions src/lib/signer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { signer } from './signer';

describe('signer', () => {
describe('sign', () => {
it('should create a token', () => {
const payload = { foo: 'bar' };

const token = signer.sign(payload);
const [header, body, _] = token.split('.');
const value = JSON.parse(atob(body))['foo'];

expect(header).toBe('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9');
expect(value).toBe('bar');
});

it('should verify a token', () => {
const payload = { foo: 'bar' };

const token = signer.sign(payload);
const value = (signer.verify(token) as Record<string, any>)['foo'];

expect(value).toBe('bar');
});
});
});
22 changes: 22 additions & 0 deletions src/lib/signer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import jwt from 'jsonwebtoken';
import { config } from '../config';

const SIX_MONTHS = 60 * 60 * 24 * 30 * 6;
const ALGORITHM = 'HS256' as const;

function sign(payload: Object) {
const token = jwt.sign(payload, config.JWT_TOKEN_SECRET, {
algorithm: ALGORITHM,
expiresIn: SIX_MONTHS,
});

return token;
}

function verify(token: string) {
return jwt.verify(token, config.JWT_TOKEN_SECRET, { algorithms: [ALGORITHM] });
}

const signer = { sign, verify };

export { signer };
38 changes: 38 additions & 0 deletions src/migrations/1733847009730-add-user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddUser1733847009730 implements MigrationInterface {
name = 'AddUser1733847009730';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TABLE "user" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "email" character varying NOT NULL, "hashedPassword" character varying NOT NULL, CONSTRAINT "UQ_e12875dfb3b1d92d7d7c5377e22" UNIQUE ("email"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`,
);
const [insertedUser] = await queryRunner.query(
`INSERT INTO "user" ("email", "hashedPassword") VALUES ('[email protected]', '7b155b65c3ecb88501347988ab889b021c4c891e547976b27e2419734117240b') RETURNING id`,
);
const userId = insertedUser.id;
await queryRunner.query(`ALTER TABLE "system_pulse" ADD "userId" uuid`);
await queryRunner.query(`ALTER TABLE "monitor" ADD "userId" uuid`);
await queryRunner.query(
`ALTER TABLE "system_pulse" ADD CONSTRAINT "FK_9c9997d98ccc4e43157c9803b0a" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
await queryRunner.query(
`ALTER TABLE "monitor" ADD CONSTRAINT "FK_17b6081f05eee538f7db3de2f9c" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);

await queryRunner.query(`UPDATE "system_pulse" SET "userId"='${userId}'`);
await queryRunner.query(`UPDATE "monitor" SET "userId"='${userId}'`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "monitor" DROP CONSTRAINT "FK_17b6081f05eee538f7db3de2f9c"`,
);
await queryRunner.query(
`ALTER TABLE "system_pulse" DROP CONSTRAINT "FK_9c9997d98ccc4e43157c9803b0a"`,
);
await queryRunner.query(`ALTER TABLE "monitor" DROP COLUMN "userId"`);
await queryRunner.query(`ALTER TABLE "system_pulse" DROP COLUMN "userId"`);
await queryRunner.query(`DROP TABLE "user"`);
}
}
6 changes: 5 additions & 1 deletion src/modules/monitor/Monitor.entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { User } from '../user';

@Entity()
export class Monitor {
Expand All @@ -22,4 +23,7 @@ export class Monitor {

@Column({ type: 'timestamp', nullable: true })
lastCall: string | null;

@ManyToOne(() => User, { onDelete: 'CASCADE', nullable: true })
user: User;
}
6 changes: 5 additions & 1 deletion src/modules/systemPulse/SystemPulse.entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { User } from '../user';

@Entity()
export class SystemPulse {
Expand All @@ -16,4 +17,7 @@ export class SystemPulse {

@Column({ type: 'timestamp', nullable: true })
lastPingedAt: string | null;

@ManyToOne(() => User, { onDelete: 'CASCADE', nullable: true })
user: User;
}
13 changes: 13 additions & 0 deletions src/modules/user/User.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;

@Column({ unique: true })
email: string;

@Column()
hashedPassword: string;
}
4 changes: 4 additions & 0 deletions src/modules/user/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { User } from './User.entity';
import { buildUserController } from './user.controller';

export { User, buildUserController };
Loading

0 comments on commit 3c284e9

Please sign in to comment.