Skip to content

Commit

Permalink
feat: new permission model
Browse files Browse the repository at this point in the history
  • Loading branch information
lucsoft committed Apr 16, 2023
1 parent 14c2c47 commit ea1ddb5
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 62 deletions.
50 changes: 16 additions & 34 deletions components/nav.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import bbnLogo from '../assets/img/bbnBig.svg';
import bbnMusicLogo from '../assets/img/bbnMusicBig.svg';
import bbnHostingLogo from '../assets/img/bbnHosting.svg';
import bbnAdminLogo from '../assets/img/bbnAdmin.svg';

import '../assets/css/components/nav.css';
import { Box, Button, ButtonStyle, CenterV, Color, Component, createElement, Custom, Horizontal, Icon, img, MaterialIcons, PlainText, Spacer, Vertical } from "webgen/mod.ts";
import { IsLoggedIn, stringToColour } from "../pages/manager/helper.ts";
import { Box, Button, ButtonStyle, CenterV, Color, Component, createElement, Custom, Horizontal, Icon, img, MaterialIcons, PlainText, Reactive, Spacer, Vertical } from "webgen/mod.ts";
import { activeUser, IsLoggedIn, permCheck, stringToColour } from "../pages/manager/helper.ts";
import { delay } from "https://deno.land/std@0.167.0/async/delay.ts";
import { API } from "../pages/manager/RESTSpec.ts";
import { activeLogo, pages } from "./pages.ts";
new MaterialIcons();
const Nav = (component: Component) => {
const nav = createElement("nav");
Expand All @@ -30,34 +26,28 @@ function ProfilePicture(component: Component, name: string) {
ele.style.backgroundColor = stringToColour(name);
return Custom(ele).addClass("profile-picture");
}
const dropOver = Box(Vertical(

const dropOver = Reactive(activeUser, "permission", () => Vertical(
PlainText("SWITCH TO").addClass("title"),
Horizontal(
Custom(img(bbnLogo)),
pages.map(([ logo, permission, route ]) => permCheck(...permission) ? Horizontal(
Custom(img(logo)),
Spacer(),
Icon("arrow_forward_ios")
).addClass("small-entry")
.onClick(() => location.href = "/"),
Horizontal(
Custom(img(bbnMusicLogo)),
Spacer(),
Icon("arrow_forward_ios")
).addClass("small-entry")
.onClick(() => location.href = "/music"),
(API.permission.isReviewer(IsLoggedIn()) ? Horizontal(
Custom(img(bbnAdminLogo)),
Spacer(),
Icon("arrow_forward_ios")
).addClass("small-entry")
.onClick(() => location.href = "/admin") : null),
)
.addClass("small-entry")
.onClick(() => location.href = route) : null
),
Horizontal(
PlainText("Go to Settings"),
Spacer(),
Icon("arrow_forward_ios")
).addClass("small-entry", "settings")
.onClick(() => location.href = "/settings")
)
).addClass("drop-over").setId("drop-over").draw();
)
.addClass("drop-over")
.setId("drop-over")
.draw();

dropOver.onblur = () => dropOver.classList.remove("open");
dropOver.tabIndex = 0;
Expand All @@ -82,15 +72,7 @@ export function DynaNavigation(type: "Home" | "Music" | "Settings" | "Hosting" |
Icon("apps"),
Vertical(
Custom(img(
(() => {
if (type == "Music")
return bbnMusicLogo;
if (type == "Hosting")
return bbnHostingLogo;
if (type == "Admin")
return bbnAdminLogo;
return bbnLogo;
})()
activeLogo(type)
)),
),
)
Expand Down
27 changes: 27 additions & 0 deletions components/pages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// @deno-types="https://raw.githubusercontent.com/lucsoft-DevTeam/lucsoft.de/master/custom.d.ts"
import bbnHolding from '../assets/img/bbnHolding.svg';
// @deno-types="https://raw.githubusercontent.com/lucsoft-DevTeam/lucsoft.de/master/custom.d.ts"
import bbnMusicLogo from '../assets/img/bbnMusic.svg';
// @deno-types="https://raw.githubusercontent.com/lucsoft-DevTeam/lucsoft.de/master/custom.d.ts"
import bbnHostingLogo from '../assets/img/bbnHosting.svg';
// @deno-types="https://raw.githubusercontent.com/lucsoft-DevTeam/lucsoft.de/master/custom.d.ts"
import bbnAdminLogo from '../assets/img/bbnAdmin.svg';

import { Permission } from "../pages/manager/RESTSpec.ts";

export const pages: [ logo: any, perm: Permission[], route: string ][] = [
[ bbnHolding, [], "/" ],
[ bbnMusicLogo, [], "/music" ],
[ bbnHostingLogo, [ "/bbn/beta-hosting" ], "/hosting" ],
[ bbnAdminLogo, [ "/bbn/manage", "/hmsys/user" ], "/admin" ],
];

export function activeLogo(type: string) {
if (type == "Music")
return bbnMusicLogo;
if (type == "Hosting")
return bbnHostingLogo;
if (type == "Admin")
return bbnAdminLogo;
return bbnHolding;
}
18 changes: 10 additions & 8 deletions pages/admin/admin.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { WebGen, MaterialIcons, Box, Custom, Vertical, View, ViewClass, loadingWheel, PlainText } from "webgen/mod.ts";
import { IsLoggedIn, Redirect, RegisterAuthRefresh, activeUser, renewAccessTokenIfNeeded } from "../manager/helper.ts";
import { WebGen, MaterialIcons, Box, Custom, Vertical, View, ViewClass, loadingWheel } from "webgen/mod.ts";
import { Redirect, RegisterAuthRefresh, activeUser, permCheck, renewAccessTokenIfNeeded } from "../manager/helper.ts";
import { changeThemeColor } from "../manager/misc/common.ts";
import { DynaNavigation } from "../../components/nav.ts";
import { API } from "../manager/RESTSpec.ts";
import { ActionBar } from "../manager/misc/actionbar.ts";
import { ViewState } from "../admin/types.ts";
import { ReviewPanel } from "./reviews.ts";
Expand All @@ -16,7 +15,10 @@ import { OverviewPanel } from "./overview.ts";
Redirect();
await RegisterAuthRefresh();

if (!API.permission.isReviewer(IsLoggedIn())) {
if (!permCheck(
"/hmsys/user/manage",
"/bbn/manage"
)) {
location.href = "/";
}

Expand Down Expand Up @@ -57,11 +59,11 @@ const view: ViewClass<ViewState> = View<ViewState>(({ state, update }) => Vertic
return ReviewPanel(() => view, state);
if (state.users && state.users.length != 0 && state.type == "users")
return UserPanel(state);
if (state.type == "payouts")
return PayoutPanel(state)
if (state.type == "payouts")
return PayoutPanel(state);
if (state.type == "overview")
return OverviewPanel(state)
return Custom(loadingWheel() as Element as HTMLElement)
return OverviewPanel(state);
return Custom(loadingWheel() as Element as HTMLElement);
})()).addClass("loading"),
))
.change(({ update }) => {
Expand Down
8 changes: 4 additions & 4 deletions pages/admin/helper.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { ViewClass, Component, Custom, PlainText, ReCache, Image, Box } from "webgen/mod.ts";
import { API } from "../manager/RESTSpec.ts";
import { IsLoggedIn, ProfileData, stringToColour } from "../manager/helper.ts";
import { ProfileData, permCheck, stringToColour } from "../manager/helper.ts";
import { ViewState } from "./types.ts";

export async function loadReviews(view: ViewClass<ViewState>) {
if (API.permission.isReviewer(IsLoggedIn())) {
if (permCheck("/bbn/manage/drops/review")) {
const list = await API.music(API.getToken()).reviews.get();
view.viewOptions().update({ reviews: list });
}
}

export async function loadUsers(view: ViewClass<ViewState>) {
if (API.permission.isAdmin(IsLoggedIn())) {
if (permCheck("/hmsys/user")) {
const list = await API.user(API.getToken()).list.get();
view.viewOptions().update({ users: list });
}
}

export async function loadPayouts(view: ViewClass<ViewState>) {
if (API.permission.isAdmin(IsLoggedIn())) {
if (permCheck("/bbn/manage/drops/review")) {
const list = await API.music(API.getToken()).payouts.get();
view.viewOptions().update({ payouts: list });
}
Expand Down
2 changes: 2 additions & 0 deletions pages/index/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { renderFooter } from "../../components/footer.ts";
import { asset } from "../../assets/img/subsidiaries/index.ts";
import '../../assets/css/components/subsidiaries.css';
import services from "../../data/services.json" assert { type: "json" };
import { RegisterAuthRefresh } from "../manager/helper.ts";

WebGen({ icon: new MaterialIcons() });
await RegisterAuthRefresh();

function inlineSVG(data: string) {
const ele = createElement("div");
Expand Down
43 changes: 34 additions & 9 deletions pages/manager/RESTSpec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// deno-lint-ignore-file no-unused-vars
import { assert } from "https://deno.land/std@0.167.0/testing/asserts.ts";
import "https://unpkg.com/construct-style-sheets-polyfill@3.1.0/dist/adoptedStyleSheets.js";
import { Drop, DropType, Payout } from "../../spec/music.ts";
import { ProfileData } from "./helper.ts";

export type ErrorObject = {
error: true,
Expand All @@ -12,18 +10,45 @@ export type ErrorObject = {
// Only visable when running in verbose
stack?: string;
};
export const Permissions = [
"/hmsys",
"/hmsys/user",
"/hmsys/user/manage",

"/bbn",
"/bbn/beta-hosting",
"/bbn/manage",
"/bbn/manage/drops",
"/bbn/manage/drops/review",
"/bbn/manage/payouts",
] as const;

export type Permission = typeof Permissions[ number ];

export const API = {
getToken: () => localStorage[ "access-token" ],
BASE_URL: location.hostname == "bbn.one" ? "https://bbn.one/api/@bbn/" : "http://localhost:8443/api/@bbn/",
// deno-lint-ignore no-explicit-any
isError: (data: any): data is ErrorObject => typeof data === "object" && data.error,
permission: {
consts: {
admin: "6293b146d55350d24e6da542",
reviewer: "6293bb4fd55350d24e6da550",
},
isReviewer: (x: ProfileData | null) => (x?.groups ?? []).find(x => API.permission.consts.admin == x || API.permission.consts.reviewer == x),
isAdmin: (x: ProfileData | null) => (x?.groups ?? []).find(x => API.permission.consts.admin == x),
permission: Permissions,
_legacyPermissionFromGroups: (group: string) => {
const admin = "6293b146d55350d24e6da542";
const reviewer = "6293bb4fd55350d24e6da550";
if (group === reviewer)
return [
"/bbn/payouts"
];

if (group === admin)
// Always highest permissions
return [
"/bbn",
"/hmsys"
];
return [];
},
isPermited: (requiredPermissions: Permission[], userPermission: Permission[]) => {
return requiredPermissions.every(required => userPermission.find(user => required.startsWith(user)));
},
user: (token: string) => ({
mail: {
Expand Down
26 changes: 22 additions & 4 deletions pages/manager/helper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This code Will be ported to webgen

import { Box, Button, ColumEntry, Component, Custom, Dialog, DropDownInput, Horizontal, Image, Page, PlainText, Reactive, ReCache, Spacer, State, StateHandler, Table, TextInput, Vertical, ViewClass } from "webgen/mod.ts";
import { API } from "./RESTSpec.ts";
import { API, Permission } from "./RESTSpec.ts";
import artwork from "../../assets/img/template-artwork.png";
import { Artist, ArtistTypes, Drop } from "../../spec/music.ts";
import { ViewState } from "./types.ts";
Expand Down Expand Up @@ -58,19 +58,35 @@ function rawAccessToken() {
return JSON.parse(b64DecodeUnicode(localStorage[ "access-token" ].split(".")[ 1 ]));
}


export const activeUser = State({
email: <string | undefined>"--",
username: <string | undefined>"--",
avatar: <string | undefined>undefined
avatar: <string | undefined>undefined,
permission: <Permission[]>[]
});

export function permCheck(...per: Permission[]) {
console.log("permitted", API.isPermited(per, activeUser.permission), "req", per, "has", [ ...activeUser.permission ]);
return API.isPermited(per, activeUser.permission);
}

export function updateActiveUserData() {
try {
if (!localStorage.getItem("access-token")) return;
const user = JSON.parse(b64DecodeUnicode(localStorage[ "access-token" ].split(".")[ 1 ])).user as ProfileData;
console.log(activeUser.permission);
const user = IsLoggedIn();
if (!user) return;
activeUser.username = user.profile.username;
activeUser.email = user.profile.email;
activeUser.avatar = user.profile.avatar;

// Convert id based system to new hmsys permission system.
activeUser.permission = State([
...activeUser.permission,
...new Set(user.groups.map(x => API._legacyPermissionFromGroups(x)).flat())
]);

console.log(activeUser.permission);
} catch (_) {
// Session should be invalid
logOut();
Expand Down Expand Up @@ -119,6 +135,8 @@ function isExpired(exp: number) {

export async function RegisterAuthRefresh() {
try {
if (!IsLoggedIn()) return;

updateActiveUserData();
checkIfRefreshTokenIsValid();
await renewAccessTokenIfNeeded();
Expand Down
4 changes: 2 additions & 2 deletions pages/manager/music/changeMain.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Grid, Horizontal, Page, PlainText, Spacer, Vertical, Wizard } from "webgen/mod.ts";
import { Drop, DropType } from "../../../spec/music.ts";
import { IsLoggedIn, showPreviewImage } from "../helper.ts";
import { permCheck, showPreviewImage } from "../helper.ts";
import { ActionBar } from "../misc/actionbar.ts";
import { changePage } from "../misc/common.ts";
import { DownloadDrop } from "../misc/drop.ts";
Expand Down Expand Up @@ -63,6 +63,6 @@ export function ChangeMain(data: Drop, update: (data: Partial<EditViewState>) =>
const Permissions = {
canTakedown: (drop: Drop) => drop.type == "PUBLISHED",
canSubmit: (drop: Drop) => (<Drop[ "type" ][]>[ "UNSUBMITTED", "PRIVATE" ]).includes(drop.type),
canEdit: (drop: Drop) => (drop.type == "PRIVATE" || drop.type == "UNSUBMITTED") || API.permission.isReviewer(IsLoggedIn()),
canEdit: (drop: Drop) => (drop.type == "PRIVATE" || drop.type == "UNSUBMITTED") || permCheck("/bbn/manage/drops"),
canCancelReview: (drop: Drop) => drop.type == "UNDER_REVIEW"
};
3 changes: 2 additions & 1 deletion serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ serve({
"admin": "./pages/admin/admin.ts",
},
poylfills: [
"https://unpkg.com/construct-style-sheets-polyfill@3.1.0"
"https://unpkg.com/construct-style-sheets-polyfill@3.1.0",
"https://unpkg.com/urlpattern-polyfill@7.0.0"
]
});

0 comments on commit ea1ddb5

Please sign in to comment.