Skip to content

Commit

Permalink
feat: gestion d'utilisateur (#16)
Browse files Browse the repository at this point in the history
* feat: user management base

* refactor: review

* feat: command to create user

* fix: test

* chore: talisman exclude test and key

* chore: wip broken [skip ci]

* refactor: simplify file structure

* chore(server): authorization bearer, schema headers, find options

* fix: tests

---------

Co-authored-by: David Dela Cruz <david.dela.cruz@beta.gouv.fr>
Co-authored-by: Antoine Bigard <bigard.antoine@gmail.com>
  • Loading branch information
3 people authored Mar 30, 2023
1 parent d0bbbcc commit 4c61b19
Show file tree
Hide file tree
Showing 23 changed files with 431 additions and 190 deletions.
99 changes: 57 additions & 42 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,46 +1,61 @@
fileignoreconfig:
- filename: .github/workflows/_deploy.yml
checksum: 937b3c6985c909437e9a4362eea76eccd3a946ead5bea27f24f9b0ced02df128
- filename: .github/workflows/publish.yml
checksum: cf87922f9cd1d8f4bb965920800187860609408c64406991a6dfad0ab79cc6aa
- filename: .github/workflows/release.yml
checksum: 96cdfb3f17eb6f7be3852f165c6587659570a814f879705348b7abaffc29742a
- filename: .infra/README.md
checksum: 46ff20cd40c93c0580c896707afadccc37486909997213c452393d8179d12a3d
- filename: .infra/ansible/roles/setup/files/app/.overrides/common/docker-compose.common.yml
checksum: c2a10f20a22c2df9c97be935509f0119799be6467fe797399bd589fae2d10388
- filename: .infra/ansible/roles/setup/files/app/.overrides/production/docker-compose.env.yml
checksum: a0e0aee8350df735bf9e13b4d19a3ec0b2a11c742e3ed4681d2d2cc5d672994f
- filename: .infra/ansible/roles/setup/files/app/mongodb/docker-entrypoint-initdb.d/01_create_users.js
checksum: f8af7aa98f4242b1c472c53f85f3d62a14a1239e7259ec0fec837ee09c7df989
- filename: .infra/ansible/roles/setup/files/app/tools/metabase/backup-metabase.sh
checksum: 4243b31cd3918b3d7c739fb7469ed7c1177826648c5b8f54e821df8f749be52e
- filename: .infra/ansible/roles/setup/tasks/configure-backup.yml
checksum: aa93a5ec0e3365d21334481c5f816d3f42775ab08512cf7276b66b28f8df8f86
- filename: .infra/ansible/roles/setup/tasks/install-app.yml
checksum: 2c7d8cdb7af638f1f5588ac9969128dddccc0a0650a5b70af5be7711d8dfbbe7
- filename: .infra/ansible/roles/setup/vars/main/vault.yml
checksum: e40d1cfbe320ad9152ae23f552f16a1cf01451725292112f539285fa455f78fd
- filename: .infra/docker-compose.production.yml
checksum: 88f2901eb4b3b71b55fd9b7031d02a2c9064fa55b065bfb70c80730fee206cf9
- filename: .infra/env.ini
checksum: 2d1ab129d6f39a2c634312ab647a13e2cc0036fa237f0497575890ec04cd87a6
- filename: .infra/scripts/deploy-app.sh
checksum: efeabc0bb607aa1ed68ed076f197461735cf2c21a09ed369965ec713d369e56c
- filename: .infra/scripts/ovh/create-backup-partition.sh
checksum: 4ab5023a5bfef64b0db52158d42fd7635f2754eb3596ac5b53e085815977f1aa
- filename: .infra/scripts/vault/generate-vault-password.sh
checksum: 86baa73f9c5559afc69f12d124d9895a104869cfb8fe396568f88954351a38b5
- filename: .infra/scripts/vault/get-vault-password-client.sh
checksum: 4ac0001fb9e12df75becb3eec2cc41431bc036b293cdcfee3b769daf8649e5e8
- filename: .infra/scripts/vault/renew-vault.sh
checksum: 86ee05100090183153d43671fd74bddf0552793dfe0f2a9a01c137d3cb248487
- filename: git-hooks/prepare-release.sh
checksum: 451afde847ac06703ffa04ea37b058d8522b60b94c891bf0979158dac5bc3610
- filename: server/.env.test
checksum: c0ef2f69099b6b85e1ee02f31ead22e9b7385bbb213d610fb953c0fc976709ac
- filename: .github/workflows/_deploy.yml
checksum: 937b3c6985c909437e9a4362eea76eccd3a946ead5bea27f24f9b0ced02df128
- filename: .github/workflows/publish.yml
checksum: cf87922f9cd1d8f4bb965920800187860609408c64406991a6dfad0ab79cc6aa
- filename: .github/workflows/release.yml
checksum: 96cdfb3f17eb6f7be3852f165c6587659570a814f879705348b7abaffc29742a
- filename: .infra/README.md
checksum: 46ff20cd40c93c0580c896707afadccc37486909997213c452393d8179d12a3d
- filename: .infra/ansible/roles/setup/files/app/.overrides/common/docker-compose.common.yml
checksum: c2a10f20a22c2df9c97be935509f0119799be6467fe797399bd589fae2d10388
- filename: .infra/ansible/roles/setup/files/app/.overrides/production/docker-compose.env.yml
checksum: a0e0aee8350df735bf9e13b4d19a3ec0b2a11c742e3ed4681d2d2cc5d672994f
- filename: .infra/ansible/roles/setup/files/app/mongodb/docker-entrypoint-initdb.d/01_create_users.js
checksum: f8af7aa98f4242b1c472c53f85f3d62a14a1239e7259ec0fec837ee09c7df989
- filename: .infra/ansible/roles/setup/files/app/tools/metabase/backup-metabase.sh
checksum: 4243b31cd3918b3d7c739fb7469ed7c1177826648c5b8f54e821df8f749be52e
- filename: .infra/ansible/roles/setup/tasks/configure-backup.yml
checksum: aa93a5ec0e3365d21334481c5f816d3f42775ab08512cf7276b66b28f8df8f86
- filename: .infra/ansible/roles/setup/tasks/install-app.yml
checksum: 2c7d8cdb7af638f1f5588ac9969128dddccc0a0650a5b70af5be7711d8dfbbe7
- filename: .infra/ansible/roles/setup/vars/main/vault.yml
checksum: e40d1cfbe320ad9152ae23f552f16a1cf01451725292112f539285fa455f78fd
- filename: .infra/docker-compose.production.yml
checksum: 88f2901eb4b3b71b55fd9b7031d02a2c9064fa55b065bfb70c80730fee206cf9
- filename: .infra/env.ini
checksum: 2d1ab129d6f39a2c634312ab647a13e2cc0036fa237f0497575890ec04cd87a6
- filename: .infra/scripts/deploy-app.sh
checksum: efeabc0bb607aa1ed68ed076f197461735cf2c21a09ed369965ec713d369e56c
- filename: .infra/scripts/ovh/create-backup-partition.sh
checksum: 4ab5023a5bfef64b0db52158d42fd7635f2754eb3596ac5b53e085815977f1aa
- filename: .infra/scripts/vault/generate-vault-password.sh
checksum: 86baa73f9c5559afc69f12d124d9895a104869cfb8fe396568f88954351a38b5
- filename: .infra/scripts/vault/get-vault-password-client.sh
checksum: 4ac0001fb9e12df75becb3eec2cc41431bc036b293cdcfee3b769daf8649e5e8
- filename: .infra/scripts/vault/renew-vault.sh
checksum: 86ee05100090183153d43671fd74bddf0552793dfe0f2a9a01c137d3cb248487
- filename: git-hooks/prepare-release.sh
checksum: 451afde847ac06703ffa04ea37b058d8522b60b94c891bf0979158dac5bc3610
- filename: server/.env.test
checksum: 3273a6b258bcaca7bf4e13099590cbe65a303aaa0a26709fa9dd24be46c872f4
- filename: "*.route.test.ts"
checksum: f0902a33ec3d28bad8dd85fcfff1bc5277c65d29798ea04c353b221c82a85df5
- filename: "*.test.ts"
checksum: a25b36c117e32dc0806d2d15104cbf66e2dd0b85e89a544df22ca0adb857005b
- filename: server/config/config.ts
checksum: 5b97c2c58ef9eb12063becfe44194016fd09c25ac29617de9ceba2201f2b849b
- filename: server/src/app.ts
checksum: 87ab06269a50c3cbca6370691e77fcf30b4863b2ad66a6a50d74e10e1ee95271
- filename: server/src/modules/server/index.ts
checksum: e9d1bc8dfc528ec8786f21af1d8ec5ecb290bb5f8b6b63275f744dc5b27673e3
- filename: server/src/utils/jwtUtils.ts
checksum: 071d8aa92d917d9224e77393463a2af00a65d381637b08140d52d11571dab51c
scopeconfig:
- scope: node
- scope: node
custom_patterns:
- (?s)[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}
- (?s)[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}
allowed_patterns:
- key
- secret
version: "1.0"
3 changes: 3 additions & 0 deletions server/.env.test
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
APP_NAME=BAL
MNA_BAL_ENV=test
MNA_BAL_PUBLIC_URL=http://localhost
MNA_BAL_AUTH_USER_JWT_SECRET=jwtsecret
MNA_BAL_AUTH_ACTIVATION_JWT_SECRET=jwtsecret
MNA_BAL_AUTH_PASSWORD_JWT_SECRET=jwtsecret

MNA_BAL_MONGODB_URI=mongodb://[user]:[password]@mongodb:27017/[db]?retryWrites=true&w=majority
14 changes: 14 additions & 0 deletions server/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,18 @@ export const config = {
type: env.get("MNA_BAL_LOG_TYPE").default("console").asString(),
level: env.get("MNA_BAL_LOG_LEVEL").default("info").asString(),
},
auth: {
user: {
jwtSecret: env.get("MNA_BAL_AUTH_USER_JWT_SECRET").required().asString(),
expiresIn: "7d",
},
activation: {
jwtSecret: env.get("MNA_BAL_AUTH_ACTIVATION_JWT_SECRET").required().asString(),
expiresIn: "96h",
},
resetPasswordToken: {
jwtSecret: env.get("MNA_BAL_AUTH_PASSWORD_JWT_SECRET").required().asString(),
expiresIn: "1h",
},
},
};
6 changes: 4 additions & 2 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
"migration:create": "migrate-mongo create",
"migration:up": "migrate-mongo up",
"migration:down": "migrate-mongo down",
"cli": "ts-node -T src/modules/data/cli.ts ",
"cli": "ts-node -T src/modules/data/cli.ts",
"cli-docker": "docker exec -it bal_server yarn cli",
"test": "yarn test:cmd 'tests/**/*.test.ts'",
"test:coverage": "c8 --reporter lcov --reporter text yarn test",
"test:cmd": "cross-env NODE_ENV=test DOTENV_CONFIG_PATH=.env.test ts-mocha -n loader=ts-node/esm"
},
"dependencies": {
"@fastify/auth": "^4.2.0",
"@fastify/cors": "^8.2.0",
"@fastify/type-provider-json-schema-to-ts": "^2.2.2",
"axios": "0.24.0",
Expand All @@ -37,7 +38,7 @@
"env-var": "7.1.1",
"fastify": "^4.12.0",
"json-schema-to-ts": "^2.7.2",
"jsonwebtoken": "8.5.1",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
"luxon": "2.3.0",
"migrate-mongo": "9.0.0",
Expand All @@ -55,6 +56,7 @@
"devDependencies": {
"@types/bunyan": "^1.8.8",
"@types/bunyan-prettystream": "^0.1.32",
"@types/jsonwebtoken": "^9.0.1",
"@types/lodash": "^4.14.191",
"@types/luxon": "^3.2.0",
"@types/mocha": "^10.0.1",
Expand Down
18 changes: 0 additions & 18 deletions server/src/app.ts

This file was deleted.

File renamed without changes.
6 changes: 3 additions & 3 deletions server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { config } from "config/config";

import { configureDbSchemaValidation, connectToMongodb } from "./db/mongodb";
import { modelDescriptors } from "./models/collections";
import { server } from "./server";
import { modelDescriptors } from "./db/models";
import { server } from "./modules/server";
import { configureDbSchemaValidation, connectToMongodb } from "./utils/mongodb";

(async function () {
try {
Expand Down
30 changes: 30 additions & 0 deletions server/src/modules/actions/users.actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Filter, FindOptions, ObjectId } from "mongodb";
import { IUser } from "shared/models/user.model";
import { IReqPostUser } from "shared/routes/user.routes";

import { createUserToken } from "../../utils/jwtUtils";
import { getDbCollection } from "../../utils/mongodb";

export const createUser = async (data: IReqPostUser) => {
const _id = new ObjectId();
const token = createUserToken({ ...data, _id: _id.toString() });

const { insertedId: userId } = await getDbCollection("users").insertOne({
...data,
_id,
token,
});

const user = await findUser({ _id: userId });

return user;
};

export const findUser = async (
filter: Filter<IUser>,
options?: FindOptions
) => {
const user = await getDbCollection("users").findOne<IUser>(filter, options);

return user;
};
8 changes: 0 additions & 8 deletions server/src/modules/core/index.ts

This file was deleted.

39 changes: 0 additions & 39 deletions server/src/modules/core/routes/user.routes.ts

This file was deleted.

38 changes: 38 additions & 0 deletions server/src/modules/data/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Command } from "commander";

import { config } from "../../../config/config";
import { modelDescriptors } from "../../db/models";
import {
configureDbSchemaValidation,
connectToMongodb,
} from "../../utils/mongodb";
import { createUser } from "../actions/users.actions";
const program = new Command();

type IJob = () => Promise<void>;

export const runScript = async (job: IJob) => {
await connectToMongodb(config.mongodb.uri);
await configureDbSchemaValidation(modelDescriptors);

await job();
};

program
.command("users:create")
.description("Créer un utilisateur")
.option("-e, --email <string>", "Email de l'utilisateur")
.action(async ({ email }) =>
runScript(async () => {
try {
const user = await createUser({ email });
console.log(user);
process.exit(0);
} catch (error) {
console.error(error);
process.exit(1);
}
})
);

program.parse(process.argv);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { salut } from "shared";

import { Server } from "../../../server";
import { Server } from ".";

export const coreRoutes = ({ server }: { server: Server }) => {
server.get("/", async (request, response) => {
Expand Down
46 changes: 46 additions & 0 deletions server/src/modules/server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import fastifyAuth, { FastifyAuthFunction } from "@fastify/auth";
import fastifyCors from "@fastify/cors";
import { JsonSchemaToTsProvider } from "@fastify/type-provider-json-schema-to-ts";
import fastify, { FastifyServerOptions } from "fastify";

import { coreRoutes } from "./core.routes";
import { userRoutes } from "./user.routes";

type FastifyServer = typeof server;
export interface Server extends FastifyServer {
validateJWT: FastifyAuthFunction;
}

import { authValidateJWT } from "./utils/auth.strategies";

export function build(opts: FastifyServerOptions = {}) {
const app = fastify(opts);

app.decorate("validateJWT", authValidateJWT);

app.register(fastifyAuth);
app.register(fastifyCors, {});
app.register(
async (instance) => {
registerRoutes({ server: instance as Server });
},
{ prefix: "/api" }
);

return app;
}

export const server = build({
logger: true,
ajv: {
customOptions: {
strict: "log",
keywords: ["kind", "modifier"],
},
},
}).withTypeProvider<JsonSchemaToTsProvider>();

export const registerRoutes = ({ server }: { server: Server }) => {
coreRoutes({ server });
userRoutes({ server });
};
Loading

0 comments on commit 4c61b19

Please sign in to comment.