a lot of things

This commit is contained in:
2026-02-20 11:46:30 -06:00
parent 987a1c8a6a
commit 70284bc14e
37 changed files with 1080 additions and 79 deletions
+3 -1
View File
@@ -80,7 +80,9 @@ export class CompanyController {
city: this.cw_Data?.city,
state: this.cw_Data?.state,
zip: this.cw_Data?.zip,
country: this.cw_Data?.country.name,
country: this.cw_Data?.country
? this.cw_Data.country.name
: "United States",
},
},
};
+17 -6
View File
@@ -10,6 +10,7 @@ import { fieldValidator } from "../modules/credentials/fieldValidator";
import {
CredentialField,
CredentialTypeField,
ValueType,
} from "../modules/credentials/credentialTypeDefs";
import { generateSecureValue } from "../modules/credentials/generateSecureValue";
import { readSecureValue } from "../modules/credentials/readSecureValue";
@@ -24,6 +25,7 @@ import GenericError from "../Errors/GenericError";
export class CredentialController {
public readonly id: string;
public name: string;
public notes: string | null;
public readonly typeId: string;
public readonly companyId: string;
public fields: any;
@@ -44,6 +46,7 @@ export class CredentialController {
) {
this.id = credentialData.id;
this.name = credentialData.name;
this.notes = credentialData.notes;
this.typeId = credentialData.typeId;
this.companyId = credentialData.companyId;
this._type = credentialData.type;
@@ -52,14 +55,21 @@ export class CredentialController {
this.fields = (() => {
let fields = credentialData.fields as Record<string, any>;
this._secureValues.forEach((sv) => (fields[sv.name] = `secure-${sv.id}`));
return (this._type.fields! as any).map((f: any) => ({
id: f.id,
name: f.name,
secure: f.secure,
required: f.required,
valueType: f.valueType as ValueType,
value: f.secure
? `secure-${this._secureValues.find((sv) => sv.name === f.id)?.id}`
: fields[f.id],
}));
return fields;
})();
this.createdAt = credentialData.createdAt;
this.updatedAt = credentialData.updatedAt;
console.log(credentialData);
}
/**
@@ -72,6 +82,7 @@ export class CredentialController {
*/
private _updateInternalValues(credentialData: Credential) {
this.name = credentialData.name;
this.notes = credentialData.notes;
this.fields = credentialData.fields;
this.updatedAt = credentialData.updatedAt;
}
@@ -174,7 +185,6 @@ export class CredentialController {
const nonSecureFields = this.fields as Record<string, any>;
Object.entries(nonSecureFields || {}).forEach(([fieldId, value]) => {
fields.push({
id: `${this.id}-${fieldId}`, // Generate a consistent ID
fieldId,
value: value as string,
});
@@ -183,7 +193,6 @@ export class CredentialController {
// Add secure fields from SecureValue table (encrypted)
this._secureValues.forEach((secureValue) => {
fields.push({
id: secureValue.id,
fieldId: secureValue.name,
value: secureValue.content, // Encrypted value
});
@@ -253,11 +262,12 @@ export class CredentialController {
* @returns {Promise<CredentialController>} - The updated credential controller
*/
async update(
data: Partial<Pick<Credential, "name">>,
data: Partial<Pick<Credential, "name" | "notes">>,
): Promise<CredentialController> {
const pData = z
.object({
name: z.string().optional(),
notes: z.string().nullable().optional(),
})
.strict()
.parse(data);
@@ -307,6 +317,7 @@ export class CredentialController {
return {
id: this.id,
name: this.name,
notes: this.notes,
typeId: this.typeId,
companyId: this.companyId,
fields: this.fields,
+92 -12
View File
@@ -1,5 +1,4 @@
import { Collection } from "@discordjs/collection";
import { z } from "zod";
import { Role } from "../../generated/prisma/client";
import { User } from "../../generated/prisma/browser";
import { SessionTokensObject } from "./SessionController";
@@ -9,6 +8,10 @@ import { prisma } from "../constants";
import { events } from "../modules/globalEvents";
import { RoleController } from "./RoleController";
import { roles } from "../managers/roles";
import { signPermissions } from "../modules/permission-utils/signPermissions";
import { DecodedPermissionsBlock } from "../types/PermissionTypes";
import jwt from "jsonwebtoken";
import { permissionsPrivateKey } from "../constants";
export default class UserController {
public id: string;
@@ -18,6 +21,7 @@ export default class UserController {
public image: string | null;
private _roles: Collection<string, Role>;
private _permissions: string | null;
public createdAt: Date;
public updatedAt: Date;
@@ -29,6 +33,7 @@ export default class UserController {
this.image = userdata.image;
this.updatedAt = userdata.updatedAt;
this.createdAt = userdata.createdAt;
this._permissions = userdata.permissions ?? null;
this._roles = (() => {
let collection = new Collection<string, Role>();
@@ -77,22 +82,13 @@ export default class UserController {
* @param data - A partial of the user data
* @returns {Promise<UserController>} - The updated user controller
*/
public async update(data: Partial<User>) {
// Parsed Data With Schema
const pData = z
.object({
name: z.string().optional(),
image: z.string().optional(),
})
.strict()
.parse(data);
public async update(data: Partial<Pick<User, "name" | "image">>) {
if (Object.keys(data).length == 0)
throw new BodyError("Body cannot be empty.");
const updatedUser = await prisma.user.update({
where: { id: this.id },
data: pData,
data,
});
this._updateInternalValues(updatedUser);
@@ -101,6 +97,87 @@ export default class UserController {
return this;
}
/**
* Set Roles
*
* Replace the user's roles with the provided array of role identifiers (id or moniker).
* Validates that each role exists before assigning.
*
* @param roleIdentifiers - Array of role ids or monikers to assign
* @returns {Promise<UserController>} - The updated user controller
*/
public async setRoles(roleIdentifiers: string[]): Promise<UserController> {
const resolvedRoles = await Promise.all(
roleIdentifiers.map((identifier) => roles.fetch(identifier)),
);
const updatedUser = await prisma.user.update({
where: { id: this.id },
data: {
roles: {
set: resolvedRoles.map((r) => ({ id: r.id })),
},
},
include: { roles: true },
});
this._updateInternalValues(updatedUser);
this._roles = new Collection<string, Role>();
updatedUser.roles.map((v: any) => this._roles.set(v.id, v));
for (const role of resolvedRoles) {
events.emit("user:role:assigned", { user: this, role });
}
return this;
}
/**
* Set Permissions
*
* Replace the user's direct permissions with the provided array of permission strings.
* Signs the permissions with the user issuer before storing.
*
* @param permissions - Array of permission node strings to assign
* @returns {Promise<UserController>} - The updated user controller
*/
public async setPermissions(permissions: string[]): Promise<UserController> {
const signed = signPermissions({
issuer: "user",
subject: this.id,
permissions,
});
const updatedUser = await prisma.user.update({
where: { id: this.id },
data: { permissions: signed },
});
this._updateInternalValues(updatedUser);
return this;
}
/**
* Read Permissions
*
* Verifies and decodes the user's direct permissions JWT and returns the array of
* permission node strings. Returns an empty array if the user has no direct permissions.
*
* @returns {string[]} The user's direct permission nodes
*/
public readPermissions(): string[] {
if (!this._permissions) return [];
const decoded = jwt.verify(this._permissions, permissionsPrivateKey, {
algorithms: ["RS256"],
issuer: "user",
subject: this.id,
}) as DecodedPermissionsBlock;
return decoded.permissions;
}
/**
* Fetch Roles
*
@@ -185,9 +262,12 @@ export default class UserController {
: this._roles.size > 0
? this._roles.map((v) => v.moniker)
: undefined,
permissions: opts?.safeReturn ? undefined : this.readPermissions(),
login: opts?.safeReturn ? undefined : this.login,
email: opts?.safeReturn ? undefined : this.email,
image: this.image,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
};
}
}