Added token authentication, organization module. Moved server bootstrapping code to server.ts file

This commit is contained in:
2024-12-19 21:49:54 +05:30
parent 970a972b11
commit 4b49c43a0c
16 changed files with 652 additions and 22 deletions

View File

@@ -0,0 +1,33 @@
import { FastifyReply, FastifyRequest } from "fastify";
import { CreateTokenInput } from "./token.schema";
import { createToken, getToken } from "./token.service";
export async function createTokenHandler(
req: FastifyRequest<{ Body: CreateTokenInput }>,
res: FastifyReply
) {
const input = req.body;
try {
const result = await createToken(input);
return res.code(201).send(result);
} catch (err) {
return err;
}
}
export async function getTokenHandler(
req: FastifyRequest<{ Params: { tokenId: string } }>,
res: FastifyReply
) {
const { tokenId } = req.params;
try {
const token = await getToken(tokenId);
if (token === null) return res.code(404).send();
return res.code(200).send(token);
} catch (err) {
return err;
}
}

24
src/tokens/token.route.ts Normal file
View File

@@ -0,0 +1,24 @@
import { FastifyInstance } from "fastify";
import { createTokenHandler, getTokenHandler } from "./token.controller";
import { $token } from "./token.schema";
export async function tokenRoutes(fastify: FastifyInstance) {
fastify.post(
"/",
{
schema: {
body: $token("createTokenInput"),
response: {
201: $token("createTokenResponse"),
},
},
},
createTokenHandler
);
fastify.get(
"/:tokenId",
{ schema: { response: { 200: $token("getTokenResponse") } } },
getTokenHandler
);
}

View File

@@ -0,0 +1,52 @@
import { buildJsonSchemas } from "fastify-zod";
import mongoose from "mongoose";
import { z } from "zod";
import { Claim } from "../utils/claims";
export const tokenModel = mongoose.model(
"token",
new mongoose.Schema({
tenantId: String,
pid: {
type: String,
unique: true,
},
name: String,
claims: [],
userId: mongoose.Types.ObjectId,
hash: { type: String, required: true },
createdAt: Date,
})
);
const tokenCore = {
name: z.string().max(30),
claims: z.array(z.string()).nonempty(),
};
const createTokenInput = z.object({
...tokenCore,
});
const createTokenResponse = z.object({
pid: z.string(),
token: z.string(),
...tokenCore,
});
const getTokenResponse = z.object({
pid: z.string(),
name: z.string(),
createdAt: z.string(),
});
export type CreateTokenInput = z.infer<typeof createTokenInput>;
export const { schemas: tokenSchemas, $ref: $token } = buildJsonSchemas(
{
createTokenInput,
createTokenResponse,
getTokenResponse,
},
{ $id: "token" }
);

View File

@@ -0,0 +1,27 @@
import bcrypt from "bcrypt";
import { generateId, generateToken } from "../utils/id";
import { CreateTokenInput, tokenModel } from "./token.schema";
export async function createToken(input: CreateTokenInput) {
const tokenId = generateId();
const newToken = await generateToken();
const tokenHash = await bcrypt.hash(newToken, 10);
const tokenInDb = await tokenModel.create({
pid: tokenId,
hash: tokenHash,
createdAt: new Date(),
...input,
});
return {
pid: tokenInDb.pid,
name: tokenInDb.name,
claims: tokenInDb.claims,
token: `${tokenInDb.pid}.${newToken}`,
};
}
export async function getToken(tokenId: string) {
return await tokenModel.findOne({ pid: tokenId });
}