mirror of
https://github.com/fosrl/pangolin.git
synced 2025-08-30 06:29:23 +02:00
Add member portal functionality - extracted from feature/member-landing-page
This commit is contained in:
parent
5c929badeb
commit
bcc2c59f08
6 changed files with 938 additions and 26 deletions
|
@ -233,6 +233,12 @@ authenticated.get(
|
|||
resource.listResources
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
"/org/:orgId/user-resources",
|
||||
verifyOrgAccess,
|
||||
resource.getUserResources
|
||||
);
|
||||
|
||||
authenticated.get(
|
||||
"/org/:orgId/domains",
|
||||
verifyOrgAccess,
|
||||
|
|
168
server/routers/resource/getUserResources.ts
Normal file
168
server/routers/resource/getUserResources.ts
Normal file
|
@ -0,0 +1,168 @@
|
|||
import { Request, Response, NextFunction } from "express";
|
||||
import { db } from "@server/db";
|
||||
import { and, eq, or, inArray } from "drizzle-orm";
|
||||
import {
|
||||
resources,
|
||||
userResources,
|
||||
roleResources,
|
||||
userOrgs,
|
||||
roles,
|
||||
resourcePassword,
|
||||
resourcePincode,
|
||||
resourceWhitelist,
|
||||
sites
|
||||
} from "@server/db";
|
||||
import createHttpError from "http-errors";
|
||||
import HttpCode from "@server/types/HttpCode";
|
||||
import { response } from "@server/lib/response";
|
||||
|
||||
export async function getUserResources(
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
): Promise<any> {
|
||||
try {
|
||||
const { orgId } = req.params;
|
||||
const userId = req.user?.userId;
|
||||
|
||||
if (!userId) {
|
||||
return next(
|
||||
createHttpError(HttpCode.UNAUTHORIZED, "User not authenticated")
|
||||
);
|
||||
}
|
||||
|
||||
// First get the user's role in the organization
|
||||
const userOrgResult = await db
|
||||
.select({
|
||||
roleId: userOrgs.roleId
|
||||
})
|
||||
.from(userOrgs)
|
||||
.where(
|
||||
and(
|
||||
eq(userOrgs.userId, userId),
|
||||
eq(userOrgs.orgId, orgId)
|
||||
)
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (userOrgResult.length === 0) {
|
||||
return next(
|
||||
createHttpError(HttpCode.FORBIDDEN, "User not in organization")
|
||||
);
|
||||
}
|
||||
|
||||
const userRoleId = userOrgResult[0].roleId;
|
||||
|
||||
// Get resources accessible through direct assignment or role assignment
|
||||
const directResourcesQuery = db
|
||||
.select({ resourceId: userResources.resourceId })
|
||||
.from(userResources)
|
||||
.where(eq(userResources.userId, userId));
|
||||
|
||||
const roleResourcesQuery = db
|
||||
.select({ resourceId: roleResources.resourceId })
|
||||
.from(roleResources)
|
||||
.where(eq(roleResources.roleId, userRoleId));
|
||||
|
||||
const [directResources, roleResourceResults] = await Promise.all([
|
||||
directResourcesQuery,
|
||||
roleResourcesQuery
|
||||
]);
|
||||
|
||||
// Combine all accessible resource IDs
|
||||
const accessibleResourceIds = [
|
||||
...directResources.map(r => r.resourceId),
|
||||
...roleResourceResults.map(r => r.resourceId)
|
||||
];
|
||||
|
||||
if (accessibleResourceIds.length === 0) {
|
||||
return response(res, {
|
||||
data: { resources: [] },
|
||||
success: true,
|
||||
error: false,
|
||||
message: "No resources found",
|
||||
status: HttpCode.OK
|
||||
});
|
||||
}
|
||||
|
||||
// Get resource details for accessible resources
|
||||
const resourcesData = await db
|
||||
.select({
|
||||
resourceId: resources.resourceId,
|
||||
name: resources.name,
|
||||
fullDomain: resources.fullDomain,
|
||||
ssl: resources.ssl,
|
||||
enabled: resources.enabled,
|
||||
sso: resources.sso,
|
||||
protocol: resources.protocol,
|
||||
emailWhitelistEnabled: resources.emailWhitelistEnabled,
|
||||
siteName: sites.name
|
||||
})
|
||||
.from(resources)
|
||||
.leftJoin(sites, eq(sites.siteId, resources.siteId))
|
||||
.where(
|
||||
and(
|
||||
inArray(resources.resourceId, accessibleResourceIds),
|
||||
eq(resources.orgId, orgId),
|
||||
eq(resources.enabled, true)
|
||||
)
|
||||
);
|
||||
|
||||
// Check for password, pincode, and whitelist protection for each resource
|
||||
const resourcesWithAuth = await Promise.all(
|
||||
resourcesData.map(async (resource) => {
|
||||
const [passwordCheck, pincodeCheck, whitelistCheck] = await Promise.all([
|
||||
db.select().from(resourcePassword).where(eq(resourcePassword.resourceId, resource.resourceId)).limit(1),
|
||||
db.select().from(resourcePincode).where(eq(resourcePincode.resourceId, resource.resourceId)).limit(1),
|
||||
db.select().from(resourceWhitelist).where(eq(resourceWhitelist.resourceId, resource.resourceId)).limit(1)
|
||||
]);
|
||||
|
||||
const hasPassword = passwordCheck.length > 0;
|
||||
const hasPincode = pincodeCheck.length > 0;
|
||||
const hasWhitelist = whitelistCheck.length > 0 || resource.emailWhitelistEnabled;
|
||||
|
||||
return {
|
||||
resourceId: resource.resourceId,
|
||||
name: resource.name,
|
||||
domain: `${resource.ssl ? "https://" : "http://"}${resource.fullDomain}`,
|
||||
enabled: resource.enabled,
|
||||
protected: !!(resource.sso || hasPassword || hasPincode || hasWhitelist),
|
||||
protocol: resource.protocol,
|
||||
sso: resource.sso,
|
||||
password: hasPassword,
|
||||
pincode: hasPincode,
|
||||
whitelist: hasWhitelist,
|
||||
siteName: resource.siteName
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return response(res, {
|
||||
data: { resources: resourcesWithAuth },
|
||||
success: true,
|
||||
error: false,
|
||||
message: "User resources retrieved successfully",
|
||||
status: HttpCode.OK
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error fetching user resources:", error);
|
||||
return next(
|
||||
createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "Internal server error")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export type GetUserResourcesResponse = {
|
||||
success: boolean;
|
||||
data: {
|
||||
resources: Array<{
|
||||
resourceId: number;
|
||||
name: string;
|
||||
domain: string;
|
||||
enabled: boolean;
|
||||
protected: boolean;
|
||||
protocol: string;
|
||||
}>;
|
||||
};
|
||||
};
|
|
@ -21,4 +21,5 @@ export * from "./getExchangeToken";
|
|||
export * from "./createResourceRule";
|
||||
export * from "./deleteResourceRule";
|
||||
export * from "./listResourceRules";
|
||||
export * from "./updateResourceRule";
|
||||
export * from "./updateResourceRule";
|
||||
export * from "./getUserResources";
|
Loading…
Add table
Add a link
Reference in a new issue