Finish preliminary CRUD ops for service token v3, ServiceTokenV3Key structure

This commit is contained in:
Tuan Dang
2023-09-21 15:15:22 +01:00
parent efb14ca267
commit 84d094b4d8
16 changed files with 668 additions and 171 deletions
@@ -1,51 +1,99 @@
import { Request, Response } from "express";
import { Types } from "mongoose";
import { ServiceTokenDataV3 } from "../../models";
import {
ServiceTokenDataV3,
ServiceTokenDataV3Key
} from "../../models";
import { validateRequest } from "../../helpers/validation";
import * as reqValidator from "../../validation/serviceTokenV3";
import { createToken } from "../../helpers/auth";
/**
* Create service token data
* @param req
* @param res
* @returns
*/
export const createServiceTokenData = async (req: Request, res: Response) => {
const {
body: { name, workspaceId, publicKey }
body: {
name,
workspaceId,
publicKey,
scopes,
expiresIn,
encryptedKey, // for ServiceTokenDataV3Key
nonce // for ServiceTokenDataV3Key
}
} = await validateRequest(reqValidator.CreateServiceTokenV3, req);
let expiresAt;
if (expiresIn) {
expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
}
const serviceTokenData = await new ServiceTokenDataV3({
name,
workspace: new Types.ObjectId(workspaceId),
publicKey,
isActive: false
scopes,
isActive: false,
expiresAt
}).save();
await new ServiceTokenDataV3Key({
encryptedKey,
nonce,
sender: req.user._id,
serviceTokenData: serviceTokenData._id,
workspace: new Types.ObjectId(workspaceId)
}).save();
console.log("the newly created serviceTokenDataV3: ", serviceTokenData);
const token = createToken({
payload: {
_id: serviceTokenData._id.toString()
},
expiresIn: "5d",
expiresIn,
secret: "hello" // TODO: replace with real secret
});
console.log("jwt token: ", token);
return res.status(200).send({
serviceTokenData,
serviceToken: `proj_token.${token}`
});
}
/**
* Update service token data with id [serviceTokenDataId]
* @param req
* @param res
* @returns
*/
export const updateServiceTokenData = async (req: Request, res: Response) => {
const {
params: { serviceTokenDataId },
body: { name, isActive }
body: {
name,
isActive,
scopes,
expiresIn
}
} = await validateRequest(reqValidator.UpdateServiceTokenV3, req);
let expiresAt;
if (expiresIn) {
expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn);
}
const serviceTokenData = await ServiceTokenDataV3.findByIdAndUpdate(
serviceTokenDataId,
{
name,
isActive
isActive,
scopes,
expiresAt
},
{
new: true
@@ -57,12 +105,24 @@ export const updateServiceTokenData = async (req: Request, res: Response) => {
});
}
/**
* Delete service token data with id [serviceTokenDataId]
* @param req
* @param res
* @returns
*/
export const deleteServiceTokenData = async (req: Request, res: Response) => {
const {
params: { serviceTokenDataId }
} = await validateRequest(reqValidator.DeleteServiceTokenV3, req);
const serviceTokenData = await ServiceTokenDataV3.findByIdAndDelete(serviceTokenDataId);
if (serviceTokenData) {
await ServiceTokenDataV3Key.findOneAndDelete({
serviceTokenData: serviceTokenData._id
});
}
return res.status(200).send({
serviceTokenData
+6 -2
View File
@@ -382,11 +382,15 @@ export const createToken = ({
secret,
}: {
payload: any;
expiresIn: string | number;
expiresIn?: string | number;
secret: string;
}) => {
return jwt.sign(payload, secret, {
expiresIn,
...(
(expiresIn !== undefined && expiresIn !== null)
? { expiresIn }
: {}
)
});
};
+2 -1
View File
@@ -28,4 +28,5 @@ export * from "./apiKeyData";
export * from "./loginSRPDetail";
export * from "./tokenVersion";
export * from "./webhooks";
export * from "./serviceTokenDataV3";
export * from "./serviceTokenDataV3";
export * from "./serviceTokenDataV3Key";
+1
View File
@@ -1,3 +1,4 @@
// TODO: deprecate
import { Schema, Types, model } from "mongoose";
export interface IServiceToken {
_id: Types.ObjectId;
+1
View File
@@ -1,3 +1,4 @@
// TODO: deprecate
import { Document, Schema, Types, model } from "mongoose";
export interface IServiceTokenData extends Document {
+38
View File
@@ -1,5 +1,16 @@
import { Document, Schema, Types, model } from "mongoose";
enum Permission {
READ = "read",
READ_WRITE = "readWrite"
}
interface Scope {
environment: string;
secretPath: string;
permission: Permission;
}
export interface IServiceTokenDataV3 extends Document {
_id: Types.ObjectId;
name: string;
@@ -7,6 +18,7 @@ export interface IServiceTokenDataV3 extends Document {
publicKey: string;
isActive: boolean;
lastUsed: Date;
scopes: Array<Scope>;
}
const serviceTokenDataV3Schema = new Schema(
@@ -31,6 +43,32 @@ const serviceTokenDataV3Schema = new Schema(
lastUsed: {
type: Date,
required: false
},
expiresAt: {
type: Date,
required: false,
expires: 0
},
scopes: {
type: [
{
environment: {
type: String,
required: true
},
secretPath: {
type: String,
default: "/",
required: true
},
permission: {
type: String,
enum: [Permission.READ, Permission.READ_WRITE],
required: true
}
}
],
required: true
}
},
{
@@ -0,0 +1,43 @@
import { Document, Schema, Types, model } from "mongoose";
export interface IServiceTokenDataV3Key extends Document {
_id: Types.ObjectId;
encryptedKey: string;
nonce: string;
sender: Types.ObjectId;
serviceTokenData: Types.ObjectId;
workspace: Types.ObjectId;
}
const serviceTokenDataV3KeySchema = new Schema(
{
encryptedKey: {
type: String,
required: true
},
nonce: {
type: String,
required: true
},
sender: {
type: Schema.Types.ObjectId,
ref: "User",
required: true
},
serviceTokenData: {
type: Schema.Types.ObjectId,
ref: "ServiceTokenDataV3",
required: true,
},
workspace: {
type: Schema.Types.ObjectId,
ref: "Workspace",
required: true,
}
},
{
timestamps: true
}
);
export const ServiceTokenDataV3Key = model<IServiceTokenDataV3Key>("ServiceTokenDataV3Key", serviceTokenDataV3KeySchema);
+23 -2
View File
@@ -5,6 +5,17 @@ export const CreateServiceTokenV3 = z.object({
name: z.string().trim(),
workspaceId: z.string().trim(),
publicKey: z.string().trim(),
scopes: z
.object({
permission: z.enum(["read", "readWrite"]),
environment: z.string().trim(),
secretPath: z.string().trim()
})
.array()
.min(1),
expiresIn: z.number().optional(),
encryptedKey: z.string().trim(),
nonce: z.string().trim()
})
});
@@ -14,8 +25,18 @@ export const UpdateServiceTokenV3 = z.object({
}),
body: z.object({
name: z.string().trim().optional(),
isActive: z.boolean().optional()
})
isActive: z.boolean().optional(),
scopes: z
.object({
permission: z.enum(["read", "readWrite"]),
environment: z.string().trim(),
secretPath: z.string().trim()
})
.array()
.min(1)
.optional(),
expiresIn: z.number().optional()
}),
});
export const DeleteServiceTokenV3 = z.object({