mirror of
https://github.com/Drop-OSS/drop.git
synced 2025-11-09 20:12:10 +10:00
* chore: update prisma to 6.11 more prisma future proofing due to experimental features * chore: update dependencies twemoji - new unicode update argon2 - bux fixes vue3-carousel - improve mobile experiance vue-tsc - more stable * fix: incorrect prisma version in docker Also remove default value for BUILD_DROP_VERSION, that is now handled in nuxt config * fix: no logging in prod * chore: optimize docker builds even more * fix: revert adoption of prisma driverAdapters see: https://github.com/prisma/prisma/issues/27486 * chore: optimize dockerignore some more * Fix `pino-pretty` not being included in build (#135) * Remove `pino` from frontend * Fix for downloads and removing of library source (#136) * fix: downloads and removing library source * fix: linting * Fix max file size of 4GB (update droplet) (#137) * Fix manual metadata import (#138) * chore(deps): bump vue-i18n from 10.0.7 to 10.0.8 (#140) Bumps [vue-i18n](https://github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n) from 10.0.7 to 10.0.8. - [Release notes](https://github.com/intlify/vue-i18n/releases) - [Changelog](https://github.com/intlify/vue-i18n/blob/master/CHANGELOG.md) - [Commits](https://github.com/intlify/vue-i18n/commits/v10.0.8/packages/vue-i18n) --- updated-dependencies: - dependency-name: vue-i18n dependency-version: 10.0.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump @intlify/core from 10.0.7 to 10.0.8 (#139) --- updated-dependencies: - dependency-name: "@intlify/core" dependency-version: 10.0.8 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Small fixes (#141) * fix: save task as Json rather than string * fix: pull objects before creating game in database * fix: strips relative dirs from version information * fix: #132 * fix: lint * fix: news object ids and small tweaks * fix: notification styling errors * fix: lint * fix: build issues by regenerating lockfile --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: DecDuck <declanahofmeyr@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
238 lines
6.0 KiB
TypeScript
238 lines
6.0 KiB
TypeScript
import { APITokenMode } from "~/prisma/client/enums";
|
|
import prisma from "../db/database";
|
|
import sessionHandler from "../session";
|
|
import type { MinimumRequestObject } from "~/server/h3";
|
|
|
|
export const userACLs = [
|
|
"read",
|
|
|
|
"store:read",
|
|
|
|
"object:read",
|
|
"object:update",
|
|
"object:delete",
|
|
|
|
"notifications:read",
|
|
"notifications:mark",
|
|
"notifications:listen",
|
|
"notifications:delete",
|
|
|
|
"screenshots:new",
|
|
"screenshots:read",
|
|
"screenshots:delete",
|
|
|
|
"collections:new",
|
|
"collections:read",
|
|
"collections:delete",
|
|
"collections:add",
|
|
"collections:remove",
|
|
"library:add",
|
|
"library:remove",
|
|
|
|
"clients:read",
|
|
"clients:revoke",
|
|
|
|
"news:read",
|
|
|
|
"settings:read",
|
|
] as const;
|
|
const userACLPrefix = "user:";
|
|
|
|
export type UserACL = Array<(typeof userACLs)[number]>;
|
|
|
|
export const systemACLs = [
|
|
"auth:read",
|
|
"auth:simple:invitation:read",
|
|
"auth:simple:invitation:new",
|
|
"auth:simple:invitation:delete",
|
|
|
|
"notifications:read",
|
|
"notifications:mark",
|
|
"notifications:listen",
|
|
"notifications:delete",
|
|
|
|
"library:read",
|
|
"library:sources:read",
|
|
"library:sources:new",
|
|
"library:sources:update",
|
|
"library:sources:delete",
|
|
|
|
"game:read",
|
|
"game:update",
|
|
"game:delete",
|
|
"game:version:update",
|
|
"game:version:delete",
|
|
"game:image:new",
|
|
"game:image:delete",
|
|
|
|
"import:version:read",
|
|
"import:version:new",
|
|
|
|
"import:game:read",
|
|
"import:game:new",
|
|
|
|
"user:read",
|
|
"user:delete",
|
|
|
|
"news:read",
|
|
"news:create",
|
|
"news:delete",
|
|
|
|
"task:read",
|
|
"task:start",
|
|
|
|
"maintenance:read",
|
|
|
|
"settings:update",
|
|
] as const;
|
|
const systemACLPrefix = "system:";
|
|
|
|
export type SystemACL = Array<(typeof systemACLs)[number]>;
|
|
|
|
export type GlobalACL =
|
|
| `${typeof systemACLPrefix}${(typeof systemACLs)[number]}`
|
|
| `${typeof userACLPrefix}${(typeof userACLs)[number]}`;
|
|
|
|
class ACLManager {
|
|
private getAuthorizationToken(request: MinimumRequestObject) {
|
|
const [type, token] =
|
|
request.headers.get("Authorization")?.split(" ") ?? [];
|
|
if (!type || !token) return undefined;
|
|
if (type != "Bearer") return undefined;
|
|
return token;
|
|
}
|
|
|
|
/**
|
|
* Get userId and require one of the specified acls
|
|
* @param request
|
|
* @param acls
|
|
* @returns
|
|
*/
|
|
async getUserIdACL(request: MinimumRequestObject | undefined, acls: UserACL) {
|
|
if (!request)
|
|
throw new Error("Native web requests not available - weird deployment?");
|
|
// Sessions automatically have all ACLs
|
|
const user = await sessionHandler.getSession(request);
|
|
if (user) return user.userId;
|
|
|
|
const authorizationToken = this.getAuthorizationToken(request);
|
|
if (!authorizationToken) return undefined;
|
|
const token = await prisma.aPIToken.findUnique({
|
|
where: {
|
|
token: authorizationToken,
|
|
mode: { in: [APITokenMode.User, APITokenMode.Client] },
|
|
},
|
|
});
|
|
if (!token) return undefined;
|
|
if (!token.userId)
|
|
throw new Error(
|
|
"No userId on user or client token - is something broken?",
|
|
);
|
|
|
|
for (const acl of acls) {
|
|
const tokenACLIndex = token.acls.findIndex((e) => e == acl);
|
|
if (tokenACLIndex != -1) return token.userId;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
async getUserACL(request: MinimumRequestObject | undefined, acls: UserACL) {
|
|
if (!request)
|
|
throw new Error("Native web requests not available - weird deployment?");
|
|
const userId = await this.getUserIdACL(request, acls);
|
|
if (!userId) return undefined;
|
|
const user = await prisma.user.findUnique({ where: { id: userId } });
|
|
if (user) return user;
|
|
return undefined;
|
|
}
|
|
|
|
async allowSystemACL(
|
|
request: MinimumRequestObject | undefined,
|
|
acls: SystemACL,
|
|
) {
|
|
if (!request)
|
|
throw new Error("Native web requests not available - weird deployment?");
|
|
const userSession = await sessionHandler.getSession(request);
|
|
if (userSession) {
|
|
const user = await prisma.user.findUnique({
|
|
where: { id: userSession.userId },
|
|
});
|
|
if (!user) return false;
|
|
if (user.admin) return true;
|
|
return false;
|
|
}
|
|
|
|
const authorizationToken = this.getAuthorizationToken(request);
|
|
if (!authorizationToken) return false;
|
|
const token = await prisma.aPIToken.findUnique({
|
|
where: { token: authorizationToken },
|
|
});
|
|
if (!token) return false;
|
|
if (token.mode != APITokenMode.System) return false;
|
|
for (const acl of acls) {
|
|
const tokenACLIndex = token.acls.findIndex((e) => e == acl);
|
|
if (tokenACLIndex != -1) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
async hasACL(request: MinimumRequestObject | undefined, acls: string[]) {
|
|
for (const acl of acls) {
|
|
if (acl.startsWith(userACLPrefix)) {
|
|
const rawACL = acl.substring(userACLPrefix.length);
|
|
const userId = await this.getUserIdACL(request, [
|
|
rawACL as UserACL[number],
|
|
]);
|
|
if (!userId) return false;
|
|
}
|
|
|
|
if (acl.startsWith(systemACLPrefix)) {
|
|
const rawACL = acl.substring(systemACLPrefix.length);
|
|
const allowed = await this.allowSystemACL(request, [
|
|
rawACL as SystemACL[number],
|
|
]);
|
|
if (!allowed) return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
async fetchAllACLs(
|
|
request: MinimumRequestObject,
|
|
): Promise<GlobalACL[] | undefined> {
|
|
const userSession = await sessionHandler.getSession(request);
|
|
if (!userSession) {
|
|
const authorizationToken = this.getAuthorizationToken(request);
|
|
if (!authorizationToken) return undefined;
|
|
const token = await prisma.aPIToken.findUnique({
|
|
where: { token: authorizationToken },
|
|
});
|
|
if (!token) return undefined;
|
|
return token.acls as GlobalACL[];
|
|
}
|
|
|
|
const user = await prisma.user.findUnique({
|
|
where: { id: userSession.userId },
|
|
select: {
|
|
admin: true,
|
|
},
|
|
});
|
|
if (!user)
|
|
throw new Error("User session without user - did something break?");
|
|
|
|
const acls = userACLs.map((e) => `${userACLPrefix}${e}`);
|
|
|
|
if (user.admin) {
|
|
acls.push(...systemACLs.map((e) => `${systemACLPrefix}${e}`));
|
|
}
|
|
|
|
return acls as GlobalACL[];
|
|
}
|
|
}
|
|
|
|
export const aclManager = new ACLManager();
|
|
export default aclManager;
|