Skip to content

Commit 11d2a8c

Browse files
committed
add rights and a few menus to go along with that
1 parent b944be9 commit 11d2a8c

File tree

7 files changed

+339
-9
lines changed

7 files changed

+339
-9
lines changed

src/webpage/localuser.ts

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {Emoji} from "./emoji.js";
2929
import {Play} from "./audio/play.js";
3030
import {Message} from "./message.js";
3131
import {badgeArr} from "./Dbadges.js";
32+
import {Rights} from "./rights.js";
3233

3334
const wsCodesRetry = new Set([4000, 4001, 4002, 4003, 4005, 4007, 4008, 4009]);
3435

@@ -79,18 +80,22 @@ class Localuser {
7980
this.play = _;
8081
});
8182
if (userinfo === -1) {
83+
this.rights = new Rights("");
8284
return;
8385
}
8486
this.token = userinfo.token;
8587
this.userinfo = userinfo;
8688
this.perminfo.guilds ??= {};
89+
this.perminfo.user ??= {};
8790
this.serverurls = this.userinfo.serverurls;
8891
this.initialized = false;
8992
this.info = this.serverurls;
9093
this.headers = {
9194
"Content-type": "application/json; charset=UTF-8",
9295
Authorization: this.userinfo.token,
9396
};
97+
const rights = this.perminfo.user.rights || "875069521787904";
98+
this.rights = new Rights(rights);
9499
}
95100
async gottenReady(ready: readyjson): Promise<void> {
96101
await I18n.done;
@@ -406,6 +411,11 @@ class Localuser {
406411
await promise;
407412
}
408413
relationshipsUpdate = () => {};
414+
rights: Rights;
415+
updateRights(rights: string | number) {
416+
this.rights.update(rights);
417+
this.perminfo.user.rights = rights;
418+
}
409419
async handleEvent(temp: wsjson) {
410420
console.debug(temp);
411421
if (temp.s) this.lastSequence = temp.s;
@@ -1776,6 +1786,135 @@ class Localuser {
17761786
}
17771787
});
17781788
}
1789+
if (
1790+
this.rights.hasPermission("OPERATOR") ||
1791+
this.rights.hasPermission("CREATE_REGISTRATION_TOKENS")
1792+
) {
1793+
const manageInstance = settings.addButton(I18n.localuser.manageInstance());
1794+
if (this.rights.hasPermission("OPERATOR")) {
1795+
manageInstance.addButtonInput("", I18n.manageInstance.stop(), () => {
1796+
const menu = new Dialog("");
1797+
const options = menu.float.options;
1798+
options.addTitle(I18n.manageInstance.AreYouSureStop());
1799+
const yesno = options.addOptions("", {ltr: true});
1800+
yesno.addButtonInput("", I18n.yes(), () => {
1801+
fetch(this.info.api + "/stop", {headers: this.headers, method: "POST"});
1802+
menu.hide();
1803+
});
1804+
yesno.addButtonInput("", I18n.no(), () => {
1805+
menu.hide();
1806+
});
1807+
menu.show();
1808+
});
1809+
}
1810+
if (this.rights.hasPermission("CREATE_REGISTRATION_TOKENS")) {
1811+
manageInstance.addButtonInput("", I18n.manageInstance.createTokens(), () => {
1812+
const tokens = manageInstance.addSubOptions(I18n.manageInstance.createTokens(), {
1813+
noSubmit: true,
1814+
});
1815+
const count = tokens.addTextInput(I18n.manageInstance.count(), () => {}, {
1816+
initText: "1",
1817+
});
1818+
const length = tokens.addTextInput(I18n.manageInstance.length(), () => {}, {
1819+
initText: "32",
1820+
});
1821+
const format = tokens.addSelect(
1822+
I18n.manageInstance.format(),
1823+
() => {},
1824+
[
1825+
I18n.manageInstance.TokenFormats.JSON(),
1826+
I18n.manageInstance.TokenFormats.plain(),
1827+
I18n.manageInstance.TokenFormats.URLs(),
1828+
],
1829+
{
1830+
defaultIndex: 2,
1831+
},
1832+
);
1833+
format.watchForChange((e) => {
1834+
if (e !== 2) {
1835+
urlOption.removeAll();
1836+
} else {
1837+
makeURLMenu();
1838+
}
1839+
});
1840+
const urlOption = tokens.addOptions("");
1841+
const urlOptionsJSON = {
1842+
url: window.location.origin,
1843+
type: "Jank",
1844+
};
1845+
function makeURLMenu() {
1846+
urlOption
1847+
.addTextInput(I18n.manageInstance.clientURL(), () => {}, {
1848+
initText: urlOptionsJSON.url,
1849+
})
1850+
.watchForChange((str) => {
1851+
urlOptionsJSON.url = str;
1852+
});
1853+
urlOption
1854+
.addSelect(
1855+
I18n.manageInstance.regType(),
1856+
() => {},
1857+
["Jank", I18n.manageInstance.genericType()],
1858+
{
1859+
defaultIndex: ["Jank", "generic"].indexOf(urlOptionsJSON.type),
1860+
},
1861+
)
1862+
.watchForChange((i) => {
1863+
urlOptionsJSON.type = ["Jank", "generic"][i];
1864+
});
1865+
}
1866+
makeURLMenu();
1867+
tokens.addButtonInput("", I18n.manageInstance.create(), async () => {
1868+
const params = new URLSearchParams();
1869+
params.set("count", count.value);
1870+
params.set("length", length.value);
1871+
const json = (await (
1872+
await fetch(
1873+
this.info.api + "/auth/generate-registration-tokens?" + params.toString(),
1874+
{
1875+
headers: this.headers,
1876+
},
1877+
)
1878+
).json()) as {tokens: string[]};
1879+
if (format.index === 0) {
1880+
pre.textContent = JSON.stringify(json.tokens);
1881+
} else if (format.index === 1) {
1882+
pre.textContent = json.tokens.join("\n");
1883+
} else if (format.index === 2) {
1884+
if (urlOptionsJSON.type === "Jank") {
1885+
const options = new URLSearchParams();
1886+
options.set("instance", this.info.wellknown);
1887+
pre.textContent = json.tokens
1888+
.map((token) => {
1889+
options.set("token", token);
1890+
return `${urlOptionsJSON.url}/register?` + options.toString();
1891+
})
1892+
.join("\n");
1893+
} else {
1894+
const options = new URLSearchParams();
1895+
pre.textContent = json.tokens
1896+
.map((token) => {
1897+
options.set("token", token);
1898+
return `${urlOptionsJSON.url}/register?` + options.toString();
1899+
})
1900+
.join("\n");
1901+
}
1902+
}
1903+
});
1904+
tokens.addButtonInput("", I18n.manageInstance.copy(), async () => {
1905+
try {
1906+
if (pre.textContent) {
1907+
await navigator.clipboard.writeText(pre.textContent);
1908+
}
1909+
} catch (err) {
1910+
console.error(err);
1911+
}
1912+
});
1913+
const pre = document.createElement("pre");
1914+
tokens.addHTMLArea(pre);
1915+
});
1916+
}
1917+
}
17791918
settings.show();
17801919
}
17811920
readonly botTokens: Map<string, string> = new Map();

src/webpage/login.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ if (instancein) {
8888
}
8989
timeout = setTimeout(() => checkInstance((instancein as HTMLInputElement).value), 1000);
9090
});
91-
if (localStorage.getItem("instanceinfo")) {
91+
if (
92+
localStorage.getItem("instanceinfo") &&
93+
!new URLSearchParams(window.location.search).get("instance")
94+
) {
9295
const json = JSON.parse(localStorage.getItem("instanceinfo")!);
9396
if (json.value) {
9497
(instancein as HTMLInputElement).value = json.value;

src/webpage/register.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,13 @@ async function registertry(e: Event) {
4242

4343
const instanceInfo = JSON.parse(localStorage.getItem("instanceinfo") ?? "{}");
4444
const apiurl = new URL(instanceInfo.api);
45-
45+
let add = "";
46+
const token = new URLSearchParams(window.location.search).get("token");
47+
if (token) {
48+
add = "?" + new URLSearchParams([["token", token]]).toString();
49+
}
4650
try {
47-
const response = await fetch(apiurl + "/auth/register", {
51+
const response = await fetch(apiurl + "/auth/register" + add, {
4852
body: JSON.stringify({
4953
date_of_birth: dateofbirth,
5054
email,

src/webpage/rights.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import {I18n} from "./i18n.js";
2+
3+
class Rights {
4+
allow!: bigint;
5+
constructor(allow: string | number) {
6+
this.update(allow);
7+
}
8+
update(allow: string | number) {
9+
try {
10+
this.allow = BigInt(allow);
11+
} catch {
12+
this.allow = 875069521787904n;
13+
console.error(
14+
`Something really stupid happened with a permission with allow being ${allow}, execution will still happen, but something really stupid happened, please report if you know what caused this.`,
15+
);
16+
}
17+
}
18+
getPermissionbit(b: number, big: bigint): boolean {
19+
return Boolean((big >> BigInt(b)) & 1n);
20+
}
21+
setPermissionbit(b: number, state: boolean, big: bigint): bigint {
22+
const bit = 1n << BigInt(b);
23+
return (big & ~bit) | (BigInt(state) << BigInt(b)); //thanks to geotale for this code :3
24+
}
25+
static *info(): Generator<{name: string; readableName: string; description: string}> {
26+
throw new Error("Isn't implemented");
27+
for (const thing of this.permisions) {
28+
yield {
29+
name: thing,
30+
readableName: I18n.getTranslation("permissions.readableNames." + thing),
31+
description: I18n.getTranslation("permissions.descriptions." + thing),
32+
};
33+
}
34+
}
35+
static readonly permisions = [
36+
"OPERATOR",
37+
"MANAGE_APPLICATIONS",
38+
"MANAGE_GUILDS",
39+
"MANAGE_MESSAGES",
40+
"MANAGE_RATE_LIMITS",
41+
"MANAGE_ROUTING",
42+
"MANAGE_TICKETS",
43+
"MANAGE_USERS",
44+
"ADD_MEMBERS",
45+
"BYPASS_RATE_LIMITS",
46+
"CREATE_APPLICATIONS",
47+
"CREATE_CHANNELS",
48+
"CREATE_DMS",
49+
"CREATE_DM_GROUPS",
50+
"CREATE_GUILDS",
51+
"CREATE_INVITES",
52+
"CREATE_ROLES",
53+
"CREATE_TEMPLATES",
54+
"CREATE_WEBHOOKS",
55+
"JOIN_GUILDS",
56+
"PIN_MESSAGES",
57+
"SELF_ADD_REACTIONS",
58+
"SELF_DELETE_MESSAGES",
59+
"SELF_EDIT_MESSAGES",
60+
"SELF_EDIT_NAME",
61+
"SEND_MESSAGES",
62+
"USE_ACTIVITIES",
63+
"USE_VIDEO",
64+
"USE_VOICE",
65+
"INVITE_USERS",
66+
"SELF_DELETE_DISABLE",
67+
"DEBTABLE",
68+
"CREDITABLE",
69+
"KICK_BAN_MEMBERS",
70+
"SELF_LEAVE_GROUPS",
71+
"PRESENCE",
72+
"SELF_ADD_DISCOVERABLE",
73+
"MANAGE_GUILD_DIRECTORY",
74+
"POGGERS",
75+
"USE_ACHIEVEMENTS",
76+
"INITIATE_INTERACTIONS",
77+
"RESPOND_TO_INTERACTIONS",
78+
"SEND_BACKDATED_EVENTS",
79+
"USE_MASS_INVITES",
80+
"ACCEPT_INVITES",
81+
"SELF_EDIT_FLAGS",
82+
"EDIT_FLAGS",
83+
"MANAGE_GROUPS",
84+
"VIEW_SERVER_STATS",
85+
"RESEND_VERIFICATION_EMAIL",
86+
"CREATE_REGISTRATION_TOKENS",
87+
];
88+
getPermission(name: string): boolean {
89+
if (undefined === Rights.permisions.indexOf(name)) {
90+
console.error(name + " is not found in map", Rights.permisions);
91+
}
92+
return this.getPermissionbit(Rights.permisions.indexOf(name), this.allow);
93+
}
94+
hasPermission(name: string, adminOverride = true): boolean {
95+
if (this.getPermissionbit(Rights.permisions.indexOf(name), this.allow)) return true;
96+
if (name !== "OPERATOR" && adminOverride) return this.hasPermission("OPERATOR");
97+
return false;
98+
}
99+
setPermission(name: string, setto: number): void {
100+
const bit = Rights.permisions.indexOf(name);
101+
if (bit === undefined) {
102+
return console.error(
103+
"Tried to set permission to " + setto + " for " + name + " but it doesn't exist",
104+
);
105+
}
106+
107+
if (setto === 0) {
108+
this.allow = this.setPermissionbit(bit, false, this.allow);
109+
} else if (setto === 1) {
110+
this.allow = this.setPermissionbit(bit, true, this.allow);
111+
} else {
112+
console.error("invalid number entered:" + setto);
113+
}
114+
}
115+
}
116+
export {Rights};

src/webpage/role.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import {Guild} from "./guild.js";
44
import {SnowFlake} from "./snowflake.js";
55
import {rolesjson} from "./jsontypes.js";
66
import {Search} from "./search.js";
7+
import {OptionsElement, Buttons} from "./settings.js";
8+
import {Contextmenu} from "./contextmenu.js";
9+
import {Channel} from "./channel.js";
10+
import {I18n} from "./i18n.js";
11+
712
class Role extends SnowFlake {
813
permissions: Permissions;
914
owner: Guild;
@@ -135,10 +140,7 @@ class PermissionToggle implements OptionsElement<number> {
135140
}
136141
submit() {}
137142
}
138-
import {OptionsElement, Buttons} from "./settings.js";
139-
import {Contextmenu} from "./contextmenu.js";
140-
import {Channel} from "./channel.js";
141-
import {I18n} from "./i18n.js";
143+
142144
class RoleList extends Buttons {
143145
permissions: [Role, Permissions][];
144146
permission: Permissions;

0 commit comments

Comments
 (0)