Skip to content

Robel-Manoa/my-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Internal Company Portal Prototype

Functional prototype for an internal company portal using Node.js, TypeScript, Express, Zod, React Admin, Vite, and Docker Compose.

Architecture

The backend follows Hexagonal Architecture:

  • back/src/domain: entities, invariants, lifecycle rules, domain exceptions
  • back/src/application: use cases, authorization policy, Zod API contracts
  • back/src/ports: repository ports
  • back/src/adapters: HTTP routes and PostgreSQL repository adapters
  • back/src/infrastructure: config, middleware, database bootstrap/migrations

Repositories are backed by PostgreSQL, included in Compose with a persistent volume. The database starts empty on a fresh environment — see back/README.md for how to create the first account.

Services

  • postgres: PostgreSQL 15 with persistent pgdata
  • backend: Express API on http://localhost:3001/api
  • frontend-admin: React Admin on http://localhost:3000
  • frontend-employee: Vite employee self-service on http://localhost:3002

Startup

docker-compose up --build

Then open:

  • Admin/HR interface: http://localhost:3000
  • Employee interface: http://localhost:3002
  • API health: http://localhost:3001/api/health

First Account

There is no seed data — the database starts empty. Register an account from the employee interface (it is always created with the EMPLOYEE role), then promote it to HR_ADMIN directly in the database:

UPDATE users SET role = 'HR_ADMIN' WHERE email = 'you@example.com';

See back/README.md for details.

Implemented Rules

  • Department code uniqueness and assignment checks
  • Employee department assignment, valid email, and self-manager prevention
  • Announcement lifecycle: DRAFT -> PUBLISHED -> ARCHIVED
  • Feedback workflow: SUBMITTED -> REVIEWED -> CLOSED
  • RBAC:
    • HR Admin can manage departments, all employees, announcements, and feedback
    • Department Admin can manage rows for their own department
    • Employee can view published announcements and manage only their own feedback
  • Field-level simulation: salary band is hidden from non-HR employee listings

Environment Files

Examples are provided in:

  • back/.env.example
  • frontend-admin/.env.example
  • frontend-employee/.env.example

For local non-Docker development, set VITE_API_URL=http://localhost:3001/api for both frontends.

Rapport de conformité — Internal Company Portal

Comparaison entre l'implémentation actuelle (branche dev) et le document Domain Model Specification (Nexus Advisory Group, v1, 12 Jun 2026).

1. Nettoyage effectué dans cette session

  • Directus : aucune référence trouvée dans tout le dépôt (code, config, docs). Rien à supprimer.
  • Azure AD : entièrement retiré du backend, qui était le seul endroit où il restait des traces (le fournisseur d'authentification Azure lui-même avait déjà été supprimé lors d'une session précédente ; il ne restait que des champs et de la logique morte) :
    • User (entité domaine) : suppression du champ azureId.
    • UserRepository (port) : suppression de la méthode optionnelle findByAzureId.
    • PostgresAuthUserRepository : suppression de la colonne azure_id dans les requêtes SQL et de la méthode findByAzureId.
    • schema.ts : suppression de la colonne azure_id TEXT UNIQUE de la table users.
    • RegisterUseCase : suppression de la génération d'un faux azureId (azure-${Date.now()}) et de la vérification d'unicité associée — ce mécanisme ne servait plus à rien depuis le retrait du vrai fournisseur Azure AD.
    • PortalUseCases : suppression de la méthode login(email), du code mort qui simulait un « Mock Azure AD user » (jamais appelée par aucune route — le vrai login passe par LoginUseCase + AuthController).
    • Tests unitaires associés mis à jour en conséquence (RegisterUseCase.test.ts, LoginUseCase.test.ts, ChangePasswordUseCase.test.ts, PostgresAuthUserRepository.test.ts, PortalUseCases.test.ts).
    • README.md (racine) : la section « Demo Accounts » qui renvoyait vers un « mock Azure AD login » et des comptes de démonstration qui n'existent plus a été remplacée par une section « First Account » décrivant la vraie procédure (inscription + promotion SQL). La description de l'architecture a aussi été corrigée (elle décrivait encore des dépôts « in-memory », alors que tout est sur PostgreSQL depuis la session précédente).
    • Résultat vérifié : tsc --noEmit propre, suite de tests backend complète toujours au vert (220/220 tests, 22 suites, couverture ~90%).

Note : la colonne azure_id a été retirée du fichier schema.ts, mais celui-ci utilise CREATE TABLE IF NOT EXISTS (pas de vrai système de migration). Sur une base déjà existante et déployée, la colonne resterait physiquement présente (juste inutilisée) tant qu'un ALTER TABLE users DROP COLUMN azure_id; n'est pas exécuté manuellement. Sans incidence sur un environnement neuf.

2. Méthode de comparaison

Le document fourni décrit un modèle métier « cible » (entités, invariants, cas d'usage). Le tableau ci-dessous confronte chaque élément du document à ce qui existe réellement dans back/src. Les écarts sont classés par sévérité :

  • 🔴 Écart réel : la règle métier du document n'est pas respectée par le code (bug potentiel ou fonctionnalité manquante).
  • 🟡 Écart mineur / nommage : le comportement est équivalent, seule la terminologie diffère.
  • Conforme.

3. Entités

User

Attendu (spec) Présent dans le code Statut
id, email, firstName, lastName, role, isActive Présents, mais répartis sur deux classes différentes : User (identifiants de connexion : email/mot de passe/prénom/nom) et UserAccount (vue métier : displayName fusionné, departmentId, employeeId, active) 🟡 Le modèle cible prévoit un seul agrégat User. Le code actuel duplique la notion en deux représentations qui doivent rester synchronisées manuellement (voir updateOwnProfile, qui met à jour les deux). Fonctionnellement correct mais plus fragile que prévu par le modèle.
createdAt, updatedAt Colonnes présentes en base (users.created_at/updated_at) mais jamais exposées par les entités User/UserAccount 🔴 Écart réel — l'invariant « toute modification auditable doit enregistrer l'utilisateur responsable » n'est pas vérifiable côté domaine puisqu'aucune entité ne porte ces champs.
azureId Supprimé dans cette session ℹ️ Écart voulu — le document mentionne Azure AD mais le système utilise désormais une authentification email/mot de passe locale. À mettre à jour dans une prochaine révision du document si Azure AD est officiellement abandonné.
Invariant : « un utilisateur ne peut pas changer son propre rôle » updateOwnProfile ne touche jamais role

Employee

Attendu (spec) Présent dans le code Statut
employeeNumber (unique) Absent 🔴 Champ requis par le document, jamais implémenté (ni dans l'entité, ni dans le schéma SQL).
joinDate Absent 🔴 Champ requis par le document, jamais implémenté.
phone (optionnel) Absent 🔴 Champ requis par le document, jamais implémenté.
position Présent sous le nom jobTitle 🟡 Nommage différent, même rôle.
status (ACTIVE/INACTIVE/ON_LEAVE) Présent (ACTIVE/ON_LEAVE/INACTIVE)
userId (référence 1-1 vers User) Présent, mais généré artificiellement (user-${uuid()}) sans jamais créer la ligne User correspondante (voir §5) 🔴 Écart réel — le lien Employee → User existe en apparence mais ne correspond à aucun compte utilisable.
Champs supplémentaires non prévus par le document : firstName, lastName, email dupliqués depuis User, managerId, salaryBand 🟡 Le document ne prévoit pas de duplication d'identité sur Employee (l'identité devrait vivre uniquement sur User) ni de hiérarchie manager. Ce sont des ajouts fonctionnels raisonnables mais non documentés dans la spec fournie.

Department

Attendu (spec) Présent dans le code Statut
name, code (uniques) Présents, unicité vérifiée dans PortalUseCases
headOfDepartmentId Absent 🔴 Le concept de « Head of Department » (attribut, invariant « au plus un par département », cas d'usage « Assign Head of Department ») n'existe nulle part dans le code : ni schéma, ni entité, ni cas d'usage.
Seuls les HR Admins créent/modifient createDepartment/updateDepartment/deleteDepartment protégés par requireHr

Announcement

Attendu (spec) Présent dans le code Statut
title, content, status, departmentId (optionnel), createdBy, publishedAt, archivedAt Tous présents (contentbody, createdByauthorId) 🟡 Uniquement du nommage, aucun écart fonctionnel.
« Après publication, seul HR Admin peut modifier » updateDraft() refuse toute modification dès que le statut n'est plus DRAFT, y compris pour un HR Admin 🔴 Écart réel — le document autorise HR Admin à modifier une annonce publiée ; le code interdit cette modification à tout le monde une fois publiée.
« Delete Announcement » (HR Admin, cas exceptionnel) Aucune route ni cas d'usage de suppression n'existe pour les annonces 🔴 Fonctionnalité du document totalement absente.
Cycle de vie DRAFT → PUBLISHED → ARCHIVED, jamais de retour arrière Respecté (publish() exige DRAFT, archive() exige PUBLISHED, aucune méthode de retour)

Feedback

Attendu (spec) Présent dans le code Statut
title (optionnel), message (requis) Le code n'a pas de title distinct ; subject (obligatoire) en tient lieu 🟡 Nommage/obligation différents mais couvre le besoin.
employeeId et createdBy (deux attributs distincts) Un seul champ employeeId ; pour les acteurs sans profil employé, le code fabrique un identifiant de secours (employee-${actor.id}) 🔴 Conséquence directe de l'absence du champ createdBy prévu par le document — la modélisation ne distingue pas « qui a soumis » de « quel profil employé est concerné ».
Statuts : PENDING → REVIEWED → RESOLVED / CLOSED (4 états) Le code n'a que 3 états : SUBMITTED → REVIEWED → CLOSEDRESOLVED n'existe pas 🔴 Écart réel sur la machine à états.
« Employés et Department Admins peuvent soumettre un feedback » submitFeedback rejette explicitement tout acteur qui n'est pas EMPLOYEE (ForbiddenError) 🔴 Contradiction directe avec le document — les Department Admins ne peuvent pas soumettre de feedback dans le code actuel, alors que la spec le demande explicitement (résumé des règles métier + tableau des cas d'usage 4.2).
« Review Feedback » réservé au HR Admin reviewFeedback utilise requireHrOrDepartmentAdmin — un Department Admin peut aussi review 🔴 Écart (le code est plus permissif que la spec).
« Delete Feedback » : le propriétaire ou un HR Admin deleteFeedback n'autorise que le propriétaire (role === EMPLOYEE + vérification d'appartenance) ; un HR Admin ne peut jamais supprimer un feedback 🔴 Fonctionnalité du document absente pour la partie HR Admin.

4. Cas d'usage — Identity & Access (section 4.3)

Cas d'usage (spec) Statut réel
Create User (HR Admin crée un compte) 🔴 Non implémenté. Le seul moyen de créer un compte est l'auto-inscription (/auth/register, toujours EMPLOYEE) ; un HR Admin n'a aucun moyen de provisionner un compte pour un tiers.
Assign Role 🔴 Non implémenté en tant que fonctionnalité applicative — la seule voie actuelle est une commande SQL manuelle documentée dans back/README.md (décision assumée de cette session, mais ne répond pas formellement au cas d'usage attendu).
Deactivate User 🔴 Non implémenté — aucune route ne permet de désactiver un compte.
Reactivate User 🔴 Non implémenté, même constat.

5. Invariants métier — points de vigilance

  • « Chaque Employee est lié à exactement un User » : en pratique, createEmployee génère un userId fictif mais ne crée jamais la ligne User correspondante. L'invariant est donc cassé silencieusement : un Employee créé par RH n'a pas de compte utilisable pour se connecter. Combiné au point précédent (pas de « Create User »), il n'existe aujourd'hui aucun parcours pour qu'un HR Admin fasse à la fois exister un Employee et un compte de connexion associé — seule l'auto-inscription de l'employé lui-même (sans lien vers un profil Employee) fonctionne de bout en bout.
  • « Seuls les HR Admins créent/modifient les Employee » : contredit par le code, qui autorise aussi les Department Admins (dans leur propre département) via createEmployee/updateEmployee. Probablement un choix produit délibéré et raisonnable, mais à faire valider/documenter puisqu'il contredit le texte de la spec telle quelle.
  • Traçabilité (createdBy/updatedBy) : partiellement assurée (Announcement a authorId, Feedback a reviewerId), mais Employee et Department n'ont ni l'un ni l'autre — seulement des timestamps.

6. Ce qui est conforme et solide

  • Le cycle de vie des Announcements (DRAFT/PUBLISHED/ARCHIVED, transitions à sens unique, contenu minimum requis) est fidèle à la spec, à l'exception du point sur l'édition post-publication par HR Admin et de la suppression absente.
  • Le scoping par département (Department Admin ne voit/gère que son département) est cohérent et appliqué systématiquement via AuthorizationService, aussi bien pour les employés, les annonces que le feedback.
  • Les invariants d'unicité de département (nom/code) et d'auto-management interdit (INVALID_MANAGER) sont bien couverts.
  • La règle « un utilisateur ne peut pas changer son propre rôle » et « utilisateur inactif ne peut rien faire » sont correctement appliquées à l'exécution.
  • La couverture de tests est solide sur tout ce qui existe (~90% backend, 220 tests après le nettoyage Azure AD), ce qui limite le risque de régression lors des corrections des écarts listés ci-dessus.

7. Synthèse des écarts par sévérité

Fonctionnalités du document totalement absentes du code :

  1. Head of Department (attribut, invariant, cas d'usage).
  2. Delete Announcement.
  3. Delete Feedback par un HR Admin.
  4. Create User / Assign Role / Deactivate User / Reactivate User (gestion des comptes par un HR Admin).
  5. Champs Employee : employeeNumber, joinDate, phone.
  6. Statut Feedback RESOLVED.
  7. Champ Feedback createdBy distinct d'employeeId.

Contradictions directes avec une règle métier explicite du document :

  1. Les Department Admins ne peuvent pas soumettre de feedback (la spec dit qu'ils le peuvent).
  2. Une annonce publiée ne peut plus être modifiée par personne, y compris HR Admin (la spec dit que HR Admin le peut).
  3. Le lien Employee ↔ User n'est pas réellement établi à la création d'un Employee.

Le code est plus permissif que la spec (à valider si voulu) :

  1. Les Department Admins peuvent modifier des Employee (spec réserve ça à HR Admin).
  2. Les Department Admins peuvent review un Feedback (spec réserve ça à HR Admin).

8. Recommandation

Aucune de ces actions n'a été effectuée automatiquement — ce rapport est une base de décision. Les points de la section « Contradictions directes » sont les plus importants à trancher rapidement, car ce sont des règles métier écrites noir sur blanc qui ne sont pas respectées (en particulier : Department Admin qui ne peut pas soumettre de feedback, et l'absence de compte utilisateur réel derrière chaque Employee créé par RH). Les autres points sont des fonctionnalités manquantes qu'il faut simplement prioriser selon les besoins réels du produit.

About

Frontend Part with React Js

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors