add BadgeEditor user role
This commit is contained in:
parent
23a206ce99
commit
ee9f50c87f
6 changed files with 46 additions and 23 deletions
|
@ -105,7 +105,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
|||
return this.redirectToAction("parties");
|
||||
}
|
||||
|
||||
public async Badges_Get() {
|
||||
public async Badges_Get_Auth$BadgeEditor() {
|
||||
const adminBadgesViewModel: AdminBadgesViewModel = {
|
||||
badges: await BadgeService.LoadAll()
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
|||
return this.view(adminBadgesViewModel);
|
||||
}
|
||||
|
||||
public async Badge_Get(adminBadgeViewModel: AdminBadgeViewModel) {
|
||||
public async Badge_Get_Auth$BadgeEditor(adminBadgeViewModel: AdminBadgeViewModel) {
|
||||
const badge = adminBadgeViewModel.id ? await BadgeService.LoadBadge(parseInt(adminBadgeViewModel.id)) : null;
|
||||
if (typeof(adminBadgeViewModel.id) !== "undefined" && badge) {
|
||||
adminBadgeViewModel.name = badge.Name;
|
||||
|
@ -130,7 +130,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
|||
return this.view(adminBadgeViewModel);
|
||||
}
|
||||
|
||||
public async Badge_Post(adminBadgeViewModel: AdminBadgeViewModel) {
|
||||
public async Badge_Post_Auth$BadgeEditor(adminBadgeViewModel: AdminBadgeViewModel) {
|
||||
if (typeof(adminBadgeViewModel.id) === "undefined") {
|
||||
return this.badRequest();
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ export default class AdminController_Auth$Admin extends Controller {
|
|||
return this.redirectToAction("badges");
|
||||
}
|
||||
|
||||
public async DeleteBadge_Get(adminDeleteBadgeModel: AdminDeleteBadgeModel) {
|
||||
public async DeleteBadge_Get_Auth$BadgeEditor(adminDeleteBadgeModel: AdminDeleteBadgeModel) {
|
||||
if (typeof(adminDeleteBadgeModel.id) === "undefined" || typeof(adminDeleteBadgeModel.id) !== "string") {
|
||||
return this.badRequest();
|
||||
}
|
||||
|
|
|
@ -15,13 +15,14 @@ export default abstract class Controller {
|
|||
const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(this));
|
||||
const rawControllerParts = this.constructor.name.split("_");
|
||||
const controllerName = rawControllerParts.splice(0, 1)[0].replace("Controller", "").toLowerCase();
|
||||
let controllerAuthLevel: UserLevel | undefined;
|
||||
const controllerAuthLevels: Array<UserLevel> = [];
|
||||
const actionAuthLevels: { [ key : string ]: Array<UserLevel> } = {};
|
||||
|
||||
for (const prop of rawControllerParts) {
|
||||
if (prop.startsWith("Auth")) {
|
||||
const userLevel = prop.split("$")[1];
|
||||
// @ts-ignore
|
||||
controllerAuthLevel = UserLevel[userLevel];
|
||||
controllerAuthLevels.push(UserLevel[userLevel]);
|
||||
Console.printInfo(`Set Auth level requirement for ${this.constructor.name} to ${userLevel}`);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +33,7 @@ export default abstract class Controller {
|
|||
}
|
||||
|
||||
const params = method.split("_");
|
||||
const methodNameRaw = params.splice(0, 1)[0]
|
||||
const methodNameRaw = params.splice(0, 1)[0];
|
||||
const methodName = methodNameRaw.toLowerCase();
|
||||
const doAuth = !params.includes("AllowAnonymous");
|
||||
|
||||
|
@ -44,8 +45,25 @@ export default abstract class Controller {
|
|||
if (doAuth && session === undefined) {
|
||||
return res.redirect(`/account/login?returnTo=${encodeURIComponent(req.url)}`);
|
||||
}
|
||||
if (session !== undefined && controllerAuthLevel !== undefined && controllerAuthLevel !== session.userLevel) {
|
||||
return res.status(403).send("Forbidden");
|
||||
const methodAuthCheck = actionAuthLevels[`${controllerName}_${methodName}_${req.method.toLowerCase()}`];
|
||||
let wasMethodMatch = false;
|
||||
if (methodAuthCheck && session !== undefined) {
|
||||
for (const auth of methodAuthCheck) {
|
||||
if (auth === session.userLevel) {
|
||||
wasMethodMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wasMethodMatch && session !== undefined && controllerAuthLevels.length > 0) {
|
||||
let hasLevelMatch = false;
|
||||
for (const level of controllerAuthLevels) {
|
||||
if (level === session.userLevel) {
|
||||
hasLevelMatch = true;
|
||||
}
|
||||
}
|
||||
if (!hasLevelMatch) {
|
||||
return res.status(403).send("Forbidden");
|
||||
}
|
||||
}
|
||||
|
||||
const requestCtx = new RequestCtx(req, res, controllerName, methodName, session);
|
||||
|
@ -53,9 +71,12 @@ export default abstract class Controller {
|
|||
}
|
||||
|
||||
let funcMethods:Array<string> = [];
|
||||
let thisMethodHttpMethod = "";
|
||||
for (const param of params) {
|
||||
//console.log(param);
|
||||
if (param === "Get" || param === "Post" || param === "Put") {
|
||||
funcMethods.push(param);
|
||||
thisMethodHttpMethod = param.toLowerCase();
|
||||
// @ts-ignore
|
||||
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}/${methodName === "index" ? "" : methodName}`, requestHandler);
|
||||
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}/${methodName === "index" ? "" : methodName}" as ${param}`);
|
||||
|
@ -67,6 +88,15 @@ export default abstract class Controller {
|
|||
Controller.FastifyInstance[param.toLowerCase()](`/${controllerName}`, requestHandler);
|
||||
Console.printInfo(`Registered ${this.constructor.name}.${method} to "/${controllerName}" as ${param}`);
|
||||
}
|
||||
} else if (param.startsWith("Auth")) {
|
||||
const nameWithMethod = `${controllerName}_${methodName}_${thisMethodHttpMethod}`;
|
||||
const userLevel = param.split("$")[1];
|
||||
if (!(nameWithMethod in actionAuthLevels)) {
|
||||
actionAuthLevels[nameWithMethod] = [];
|
||||
}
|
||||
// @ts-ignore
|
||||
actionAuthLevels[nameWithMethod].push(UserLevel[userLevel]);
|
||||
Console.printInfo(`Set Auth level requirement for ${this.constructor.name}.${method} to ${userLevel}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export enum UserLevel {
|
||||
Unknown = 0,
|
||||
User = 10,
|
||||
BadgeEditor = 20,
|
||||
Admin = 999
|
||||
}
|
|
@ -124,7 +124,6 @@ export default class UserService {
|
|||
await UserPartyRepo.insertUpdate(userParty);
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
console.log(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +133,6 @@ export default class UserService {
|
|||
await UserPartyRepo.deactivateAll(currentUserId);
|
||||
} catch (e) {
|
||||
Console.printError(`MultiProbe server service error:\n${e}`);
|
||||
console.log(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
<select class="form-select" name="userLevel" required>
|
||||
<option value="" disabled <%= userLevel === "0" ? "selected" : "" %>>Please select...</option>
|
||||
<option value="10" <%= userLevel === "10" ? "selected" : "" %>>User</option>
|
||||
<option value="20" <%= userLevel === "20" ? "selected" : "" %>>Badge Editor</option>
|
||||
<option value="999" <%= userLevel === "999" ? "selected" : "" %>>Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -50,16 +51,4 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
const imageImg = document.querySelector("#imageImg");
|
||||
const imageUrl = document.querySelector("#imageUrl");
|
||||
imageUrl.addEventListener("change", () => {
|
||||
if (imageUrl.value.trim() === ""){
|
||||
imageImg.src = "/img/missing.png";
|
||||
} else {
|
||||
imageImg.src = imageUrl.value;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<%- include("../base/footer") %>
|
|
@ -12,6 +12,11 @@
|
|||
<a class="btn btn-primary btn-lg me-2" href="/party/create">Create Party</a>
|
||||
<a class="btn btn-primary btn-lg" href="/party/join">Join Party</a>
|
||||
</div>
|
||||
<% if (user.UserLevel === UserLevel.BadgeEditor) { %>
|
||||
<div class="mt-3">
|
||||
<a class="btn btn-primary btn-lg" href="/admin/badges">Badge Management</a>
|
||||
</div>
|
||||
<% } %>
|
||||
<% if (user.UserLevel === UserLevel.Admin) { %>
|
||||
<div class="mt-3">
|
||||
<a class="btn btn-primary btn-lg" href="/admin">Admin Dashboard</a>
|
||||
|
|
Loading…
Reference in a new issue