Hangar/frontend/utils/perms.ts

99 lines
3.5 KiB
TypeScript
Raw Normal View History

2021-02-05 08:22:22 +08:00
import { Context, Middleware } from '@nuxt/types';
import { PermissionCheck } from 'hangar-api';
import { NamedPermission, PermissionType } from '~/types/enums';
import { AuthState } from '~/store/auth';
2021-03-13 18:10:56 +08:00
const loggedInMiddleware = (code: number, msg?: string): Middleware => ({ store, error }: Context) => {
2021-02-05 08:22:22 +08:00
if (!store.state.auth.authenticated) {
error({
2021-03-13 18:10:56 +08:00
message: msg,
statusCode: code,
2021-02-05 08:22:22 +08:00
});
}
};
2021-04-04 14:20:20 +08:00
export function NotLoggedIn(constructor: Function) {
addMiddleware(constructor, ({ store, redirect }) => {
if (store.state.auth.authenticated) {
redirect('/');
}
});
}
2021-02-05 08:22:22 +08:00
export function LoggedIn(constructor: Function) {
2021-03-13 18:10:56 +08:00
addMiddleware(constructor, loggedInMiddleware(401, 'You must be logged in to perform this action'));
2021-02-05 08:22:22 +08:00
}
2021-04-06 16:41:02 +08:00
export function CurrentUser(constructor: Function) {
addMiddleware(constructor, loggedInMiddleware(403), ({ params, store, $perms, error }) => {
if (!$perms.canEditAllUserSettings) {
if (!params.user) {
throw new TypeError("Must have 'user' as a route param to use CurrentUser");
}
if (params.user !== (store.state.auth as AuthState).user!.name) {
error({
statusCode: 403,
});
}
}
});
}
2021-02-05 08:22:22 +08:00
// TODO this maybe should use the global permissions store in the JWT to reduce db lookups?
export function GlobalPermission(...permissions: NamedPermission[]) {
2021-04-03 14:56:55 +08:00
const middleware: Middleware = ({ error, $api, $util }: Context) => {
2021-02-05 08:22:22 +08:00
return $api
.request<PermissionCheck>('permissions/hasAll', true, 'get', {
permissions,
})
.then((check) => {
if (check.type !== PermissionType.GLOBAL || !check.result) {
error({
message: 'Not Found',
statusCode: 404,
});
}
})
2021-04-03 14:56:55 +08:00
.catch($util.handlePageRequestError);
2021-02-05 08:22:22 +08:00
};
return function (constructor: Function) {
2021-03-13 18:10:56 +08:00
addMiddleware(constructor, loggedInMiddleware(404), middleware);
2021-02-05 08:22:22 +08:00
};
}
export function ProjectPermission(...permissions: NamedPermission[]) {
const middleware: Middleware = ({ store, route, $util, error }: Context) => {
if (!route.params.author || !route.params.slug) {
throw new Error("Can't use this decorator on a route without `author` and `slug` path params");
}
if (!(store.state.auth as AuthState).routePermissions) {
error({
statusCode: 404,
});
2021-02-07 13:44:53 +08:00
return;
2021-02-05 08:22:22 +08:00
}
2021-02-07 11:22:37 +08:00
if (!$util.hasPerms(...permissions)) {
2021-02-05 08:22:22 +08:00
error({
statusCode: 404,
});
}
};
return function (constructor: Function) {
2021-03-13 18:10:56 +08:00
addMiddleware(constructor, loggedInMiddleware(404), middleware);
2021-02-05 08:22:22 +08:00
};
}
function addMiddleware(constructor: Function, ...middleware: Middleware[]): void {
if (!constructor.prototype.middleware) {
constructor.prototype.middleware = [...middleware];
} else if (typeof constructor.prototype.middleware === 'string') {
constructor.prototype.middleware = [constructor.prototype.middleware, ...middleware];
} else if (Array.isArray(constructor.prototype.middleware)) {
constructor.prototype.middleware = [...constructor.prototype.middleware, ...middleware];
} else {
throw new TypeError('Unable to add permissions middleware');
}
}