This is a standalone API application that allows you to manage the organizational structure of any educational institution. I am creating this mostly to get familiar with my new team's tech stack, and as a practical project for my thesis.
I am not planning on expanding this project with any frontend implementations. It is supposed to be open for adaptation of users.
Function | Framework |
---|---|
GQL engine | Mercurius |
HTTP server | Fastify |
Authentication | JWT |
Runtime Environment | NodeJS |
Language | TypeScript |
Database | MongoDB |
Using PNPM is recommended with this project. Make sure you edit the .env
file, especially the session secret, and that you have a MongoDB instance you can connect to.
pnpm i
pnpm start
The start
script runs the TypeScript compiler and then runs the project with NodeJS. I do not run this project using ts-node
.
To create a standalone container for the API service, use this command
docker build -t uni-mgr-api .
docker run -p 8001:8001 -d uni-mgr-api
Alternatively, create a stack with docker-compose
docker compose up
As of right now, the image ignores the pnpm-lock.yaml
and uses npm
instead of pnpm
. This will get changed in the future.
As usual, querying GraphQL is possible at /graphql
. To try and design queries and mutations, /graphiql
is also enabled by default.
The GQL schema is located in ./schema/
directory.
Registering accounts which are able to receive JWT tokens from the API is done within the GQL paradigm. Account
s are able to be created only for UUID
s which already have a Person
. Check out ./schema/accounts.gql
for more detail.
The expected course of behavior is to create Person
objects for each new student/professor/hire and then issue accounts to them by the administrator.
Person
objects contain personal and organizational data on persons (students, professors, employees etc.) while Account
contains the shared UUID
, passwordHash
which only appears on root document in Mongo but cannot be returned by GQL, and later will contain access groups and other authorization data (when authorization is implemented).
Authenticating and obtaining the JWT is possible via login
query. The user provides the Credentials
input object as a parameter, and is returned LoginStatus
which either consists of an error string, or a Token
which is structured exactly like the expected idiomatic authorization header.
It is up to the client to store the token, and add it to the headers
of subsequent GQL requests. The structure of the TokenHeader
makes it easy to retrieve and inject the header if authentication was successful;
export type TokenHeader = {
Authorization: `Bearer ${string}`;
};
export type LoginStatus = { token: TokenHeader } | { error: string };