feat: updated more types to avoid infer

This commit is contained in:
=
2025-06-13 23:52:40 +05:30
parent 5311daed64
commit 7a00ade119
125 changed files with 1974 additions and 571 deletions
@@ -6,16 +6,312 @@ import {
OrgMembershipRole,
OrgMembershipsSchema,
TableName,
TIdentityOrgMemberships,
TProjectRoles,
TProjects
} from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
export type TPermissionDALFactory = ReturnType<typeof permissionDALFactory>;
export interface TPermissionDALFactory {
getOrgPermission: (
userId: string,
orgId: string
) => Promise<
{
status: string;
orgId: string;
id: string;
createdAt: Date;
updatedAt: Date;
role: string;
isActive: boolean;
shouldUseNewPrivilegeSystem: boolean;
bypassOrgAuthEnabled: boolean;
permissions?: unknown;
userId?: string | null | undefined;
roleId?: string | null | undefined;
inviteEmail?: string | null | undefined;
projectFavorites?: string[] | null | undefined;
customRoleSlug?: string | null | undefined;
orgAuthEnforced?: boolean | null | undefined;
} & {
groups: {
id: string;
updatedAt: Date;
createdAt: Date;
role: string;
roleId: string | null | undefined;
customRolePermission: unknown;
name: string;
slug: string;
orgId: string;
}[];
}
>;
getOrgIdentityPermission: (
identityId: string,
orgId: string
) => Promise<
| (TIdentityOrgMemberships & {
orgAuthEnforced: boolean | null | undefined;
shouldUseNewPrivilegeSystem: boolean;
permissions?: unknown;
})
| undefined
>;
getProjectPermission: (
userId: string,
projectId: string
) => Promise<
| {
roles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
additionalPrivileges: {
id: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
orgId: string;
orgAuthEnforced: boolean | null | undefined;
orgRole: OrgMembershipRole;
userId: string;
projectId: string;
username: string;
projectType: string;
id: string;
createdAt: Date;
updatedAt: Date;
shouldUseNewPrivilegeSystem: boolean;
bypassOrgAuthEnabled: boolean;
metadata: {
id: string;
key: string;
value: string;
}[];
userGroupRoles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
projecMembershiptRoles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
}
| undefined
>;
getProjectIdentityPermission: (
identityId: string,
projectId: string
) => Promise<
| {
roles: {
id: string;
createdAt: Date;
updatedAt: Date;
isTemporary: boolean;
role: string;
projectMembershipId: string;
temporaryRange?: string | null | undefined;
permissions?: unknown;
customRoleId?: string | null | undefined;
temporaryMode?: string | null | undefined;
temporaryAccessStartTime?: Date | null | undefined;
temporaryAccessEndTime?: Date | null | undefined;
customRoleSlug?: string | null | undefined;
}[];
additionalPrivileges: {
id: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
isTemporary: boolean;
}[];
id: string;
identityId: string;
username: string;
projectId: string;
createdAt: Date;
updatedAt: Date;
orgId: string;
projectType: string;
shouldUseNewPrivilegeSystem: boolean;
orgAuthEnforced: boolean;
metadata: {
id: string;
key: string;
value: string;
}[];
}
| undefined
>;
getProjectUserPermissions: (projectId: string) => Promise<
{
roles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
additionalPrivileges: {
id: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
orgId: string;
orgAuthEnforced: boolean | null | undefined;
userId: string;
projectId: string;
username: string;
projectType: string;
id: string;
createdAt: Date;
updatedAt: Date;
metadata: {
id: string;
key: string;
value: string;
}[];
userGroupRoles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
projectMembershipRoles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
}[]
>;
getProjectIdentityPermissions: (projectId: string) => Promise<
{
roles: {
id: string;
createdAt: Date;
updatedAt: Date;
isTemporary: boolean;
role: string;
projectMembershipId: string;
temporaryRange?: string | null | undefined;
permissions?: unknown;
customRoleId?: string | null | undefined;
temporaryMode?: string | null | undefined;
temporaryAccessStartTime?: Date | null | undefined;
temporaryAccessEndTime?: Date | null | undefined;
customRoleSlug?: string | null | undefined;
}[];
additionalPrivileges: {
id: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
isTemporary: boolean;
}[];
id: string;
identityId: string;
username: string;
projectId: string;
createdAt: Date;
updatedAt: Date;
orgId: string;
projectType: string;
orgAuthEnforced: boolean;
metadata: {
id: string;
key: string;
value: string;
}[];
}[]
>;
getProjectGroupPermissions: (
projectId: string,
filterGroupId?: string
) => Promise<
{
roles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
groupId: string;
username: string;
id: string;
groupRoles: {
id: string;
role: string;
customRoleSlug: string;
permissions: unknown;
temporaryRange: string | null | undefined;
temporaryMode: string | null | undefined;
temporaryAccessStartTime: Date | null | undefined;
temporaryAccessEndTime: Date | null | undefined;
isTemporary: boolean;
}[];
}[]
>;
}
export const permissionDALFactory = (db: TDbClient) => {
const getOrgPermission = async (userId: string, orgId: string) => {
export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => {
const getOrgPermission: TPermissionDALFactory["getOrgPermission"] = async (userId: string, orgId: string) => {
try {
const groupSubQuery = db(TableName.Groups)
.where(`${TableName.Groups}.orgId`, orgId)
@@ -112,7 +408,10 @@ export const permissionDALFactory = (db: TDbClient) => {
}
};
const getOrgIdentityPermission = async (identityId: string, orgId: string) => {
const getOrgIdentityPermission: TPermissionDALFactory["getOrgIdentityPermission"] = async (
identityId: string,
orgId: string
) => {
try {
const membership = await db
.replicaNode()(TableName.IdentityOrgMembership)
@@ -132,7 +431,10 @@ export const permissionDALFactory = (db: TDbClient) => {
}
};
const getProjectGroupPermissions = async (projectId: string, filterGroupId?: string) => {
const getProjectGroupPermissions: TPermissionDALFactory["getProjectGroupPermissions"] = async (
projectId: string,
filterGroupId?: string
) => {
try {
const docs = await db
.replicaNode()(TableName.GroupProjectMembership)
@@ -245,7 +547,7 @@ export const permissionDALFactory = (db: TDbClient) => {
}
};
const getProjectUserPermissions = async (projectId: string) => {
const getProjectUserPermissions: TPermissionDALFactory["getProjectUserPermissions"] = async (projectId: string) => {
try {
const docs = await db
.replicaNode()(TableName.Users)
@@ -535,7 +837,10 @@ export const permissionDALFactory = (db: TDbClient) => {
}
};
const getProjectPermission = async (userId: string, projectId: string) => {
const getProjectPermission: TPermissionDALFactory["getProjectPermission"] = async (
userId: string,
projectId: string
) => {
try {
const subQueryUserGroups = db(TableName.UserGroupMembership).where("userId", userId).select("groupId");
const docs = await db
@@ -838,7 +1143,9 @@ export const permissionDALFactory = (db: TDbClient) => {
}
};
const getProjectIdentityPermissions = async (projectId: string) => {
const getProjectIdentityPermissions: TPermissionDALFactory["getProjectIdentityPermissions"] = async (
projectId: string
) => {
try {
const docs = await db
.replicaNode()(TableName.IdentityProjectMembership)
@@ -995,7 +1302,10 @@ export const permissionDALFactory = (db: TDbClient) => {
}
};
const getProjectIdentityPermission = async (identityId: string, projectId: string) => {
const getProjectIdentityPermission: TPermissionDALFactory["getProjectIdentityPermission"] = async (
identityId,
projectId
) => {
try {
const docs = await db
.replicaNode()(TableName.IdentityProjectMembership)
@@ -1,6 +1,12 @@
import { MongoAbility, RawRuleOf } from "@casl/ability";
import { MongoQuery } from "@ucast/mongo2js";
import { ActionProjectType } from "@app/db/schemas";
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
import { OrgPermissionSet } from "./org-permission";
import { ProjectPermissionSet } from "./project-permission";
export type TBuildProjectPermissionDTO = {
permissions?: unknown;
role: string;
@@ -41,3 +47,240 @@ export type TGetProjectPermissionArg = {
actorOrgId?: string;
actionProjectType: ActionProjectType;
};
export type TPermissionServiceFactory = {
getUserOrgPermission: (
userId: string,
orgId: string,
authMethod: ActorAuthMethod,
userOrgId?: string
) => Promise<{
permission: MongoAbility<OrgPermissionSet, MongoQuery>;
membership: {
status: string;
orgId: string;
id: string;
createdAt: Date;
updatedAt: Date;
role: string;
isActive: boolean;
shouldUseNewPrivilegeSystem: boolean;
bypassOrgAuthEnabled: boolean;
permissions?: unknown;
userId?: string | null | undefined;
roleId?: string | null | undefined;
inviteEmail?: string | null | undefined;
projectFavorites?: string[] | null | undefined;
customRoleSlug?: string | null | undefined;
orgAuthEnforced?: boolean | null | undefined;
} & {
groups: {
id: string;
updatedAt: Date;
createdAt: Date;
role: string;
roleId: string | null | undefined;
customRolePermission: unknown;
name: string;
slug: string;
orgId: string;
}[];
};
}>;
getOrgPermission: (
type: ActorType,
id: string,
orgId: string,
authMethod: ActorAuthMethod,
actorOrgId: string | undefined
) => Promise<
| {
permission: MongoAbility<OrgPermissionSet, MongoQuery>;
membership: {
status: string;
orgId: string;
id: string;
createdAt: Date;
updatedAt: Date;
role: string;
isActive: boolean;
shouldUseNewPrivilegeSystem: boolean;
bypassOrgAuthEnabled: boolean;
permissions?: unknown;
userId?: string | null | undefined;
roleId?: string | null | undefined;
inviteEmail?: string | null | undefined;
projectFavorites?: string[] | null | undefined;
customRoleSlug?: string | null | undefined;
orgAuthEnforced?: boolean | null | undefined;
} & {
groups: {
id: string;
updatedAt: Date;
createdAt: Date;
role: string;
roleId: string | null | undefined;
customRolePermission: unknown;
name: string;
slug: string;
orgId: string;
}[];
};
}
| {
permission: MongoAbility<OrgPermissionSet, MongoQuery>;
membership: {
id: string;
role: string;
createdAt: Date;
updatedAt: Date;
orgId: string;
roleId?: string | null | undefined;
permissions?: unknown;
identityId: string;
orgAuthEnforced: boolean | null | undefined;
shouldUseNewPrivilegeSystem: boolean;
};
}
>;
getUserProjectPermission: ({
userId,
projectId,
authMethod,
userOrgId,
actionProjectType
}: TGetUserProjectPermissionArg) => Promise<{
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: {
id: string;
createdAt: Date;
updatedAt: Date;
userId: string;
projectId: string;
} & {
orgAuthEnforced: boolean | null | undefined;
orgId: string;
roles: Array<{
role: string;
}>;
shouldUseNewPrivilegeSystem: boolean;
};
hasRole: (role: string) => boolean;
}>;
getProjectPermission: <T extends ActorType>(
arg: TGetProjectPermissionArg
) => Promise<
T extends ActorType.SERVICE
? {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: {
shouldUseNewPrivilegeSystem: boolean;
};
hasRole: (arg: string) => boolean;
}
: {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: (T extends ActorType.USER
? {
id: string;
createdAt: Date;
updatedAt: Date;
userId: string;
projectId: string;
}
: {
id: string;
createdAt: Date;
updatedAt: Date;
projectId: string;
identityId: string;
}) & {
orgAuthEnforced: boolean | null | undefined;
orgId: string;
roles: Array<{
role: string;
}>;
shouldUseNewPrivilegeSystem: boolean;
};
hasRole: (role: string) => boolean;
}
>;
getProjectPermissions: (projectId: string) => Promise<{
userPermissions: {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
id: string;
name: string;
membershipId: string;
}[];
identityPermissions: {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
id: string;
name: string;
membershipId: string;
}[];
groupPermissions: {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
id: string;
name: string;
membershipId: string;
}[];
}>;
getOrgPermissionByRole: (
role: string,
orgId: string
) => Promise<
| {
permission: MongoAbility<OrgPermissionSet, MongoQuery>;
role: {
name: string;
orgId: string;
id: string;
createdAt: Date;
updatedAt: Date;
slug: string;
permissions?: unknown;
description?: string | null | undefined;
};
}
| {
permission: MongoAbility<OrgPermissionSet, MongoQuery>;
role?: undefined;
}
>;
getProjectPermissionByRole: (
role: string,
projectId: string
) => Promise<
| {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
role: {
name: string;
version: number;
id: string;
createdAt: Date;
updatedAt: Date;
projectId: string;
slug: string;
permissions?: unknown;
description?: string | null | undefined;
};
}
| {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
role?: undefined;
}
>;
buildOrgPermission: (orgUserRoles: TBuildOrgPermissionDTO) => MongoAbility<OrgPermissionSet, MongoQuery>;
buildProjectPermissionRules: (
projectUserRoles: TBuildProjectPermissionDTO
) => RawRuleOf<MongoAbility<ProjectPermissionSet>>[];
checkGroupProjectPermission: ({
groupId,
projectId,
checkPermissions
}: {
groupId: string;
projectId: string;
checkPermissions: ProjectPermissionSet;
}) => Promise<boolean>;
};
@@ -23,7 +23,7 @@ import {
import { conditionsMatcher } from "@app/lib/casl";
import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
import { objectify } from "@app/lib/fn";
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
import { ActorType } from "@app/services/auth/auth-type";
import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal";
@@ -38,7 +38,8 @@ import {
TGetIdentityProjectPermissionArg,
TGetProjectPermissionArg,
TGetServiceTokenProjectPermissionArg,
TGetUserProjectPermissionArg
TGetUserProjectPermissionArg,
TPermissionServiceFactory
} from "./permission-service-types";
import { buildServiceTokenProjectPermission, ProjectPermissionSet } from "./project-permission";
@@ -50,15 +51,13 @@ type TPermissionServiceFactoryDep = {
permissionDAL: TPermissionDALFactory;
};
export type TPermissionServiceFactory = ReturnType<typeof permissionServiceFactory>;
export const permissionServiceFactory = ({
permissionDAL,
orgRoleDAL,
projectRoleDAL,
serviceTokenDAL,
projectDAL
}: TPermissionServiceFactoryDep) => {
}: TPermissionServiceFactoryDep): TPermissionServiceFactory => {
const buildOrgPermission = (orgUserRoles: TBuildOrgPermissionDTO) => {
const rules = orgUserRoles
.map(({ role, permissions }) => {
@@ -120,11 +119,11 @@ export const permissionServiceFactory = ({
/*
* Get user permission in an organization
*/
const getUserOrgPermission = async (
userId: string,
orgId: string,
authMethod: ActorAuthMethod,
userOrgId?: string
const getUserOrgPermission: TPermissionServiceFactory["getUserOrgPermission"] = async (
userId,
orgId,
authMethod,
userOrgId
) => {
// when token is scoped, ensure the passed org id is same as user org id
if (userOrgId && userOrgId !== orgId)
@@ -172,12 +171,12 @@ export const permissionServiceFactory = ({
};
};
const getOrgPermission = async (
type: ActorType,
id: string,
orgId: string,
authMethod: ActorAuthMethod,
actorOrgId: string | undefined
const getOrgPermission: TPermissionServiceFactory["getOrgPermission"] = async (
type,
id,
orgId,
authMethod,
actorOrgId
) => {
switch (type) {
case ActorType.USER:
@@ -194,7 +193,7 @@ export const permissionServiceFactory = ({
// instead of actor type this will fetch by role slug. meaning it can be the pre defined slugs like
// admin member or user defined ones like biller etc
const getOrgPermissionByRole = async (role: string, orgId: string) => {
const getOrgPermissionByRole: TPermissionServiceFactory["getOrgPermissionByRole"] = async (role, orgId) => {
const isCustomRole = !Object.values(OrgMembershipRole).includes(role as OrgMembershipRole);
if (isCustomRole) {
const orgRole = await orgRoleDAL.findOne({ slug: role, orgId });
@@ -437,7 +436,7 @@ export const permissionServiceFactory = ({
hasRole: (role: string) => boolean;
};
const getProjectPermissions = async (projectId: string) => {
const getProjectPermissions: TPermissionServiceFactory["getProjectPermissions"] = async (projectId) => {
// fetch user permissions
const rawUserProjectPermissions = await permissionDAL.getProjectUserPermissions(projectId);
const userPermissions = rawUserProjectPermissions.map((userProjectPermission) => {
@@ -607,7 +606,10 @@ export const permissionServiceFactory = ({
}
};
const getProjectPermissionByRole = async (role: string, projectId: string) => {
const getProjectPermissionByRole: TPermissionServiceFactory["getProjectPermissionByRole"] = async (
role,
projectId
) => {
const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole);
if (isCustomRole) {
const projectRole = await projectRoleDAL.findOne({ slug: role, projectId });
@@ -630,14 +632,10 @@ export const permissionServiceFactory = ({
return { permission };
};
const checkGroupProjectPermission = async ({
const checkGroupProjectPermission: TPermissionServiceFactory["checkGroupProjectPermission"] = async ({
groupId,
projectId,
checkPermissions
}: {
groupId: string;
projectId: string;
checkPermissions: ProjectPermissionSet;
}) => {
const rawGroupProjectPermissions = await permissionDAL.getProjectGroupPermissions(projectId, groupId);
const groupPermissions = rawGroupProjectPermissions.map((groupProjectPermission) => {