Removed web project (galvanic authentication support in IL2CPP universal patch)
Moved instance ID to header User instances for profile management .. other stuff
This commit is contained in:
128
src/data/profiles.ts
Normal file
128
src/data/profiles.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { Redis } from "../db.ts";
|
||||
import Dictionary from "./usernames.ts";
|
||||
import { Config } from "../config.ts";
|
||||
import { AuthType } from "./users.ts";
|
||||
import * as JsonWebToken from "@gz/jwt";
|
||||
|
||||
const config = Config.getConfig();
|
||||
|
||||
interface ProfileInitOptions {
|
||||
username: string
|
||||
}
|
||||
interface AccountExport {
|
||||
accountId: number,
|
||||
profileImage: string,
|
||||
isJunior: boolean,
|
||||
platforms: number,
|
||||
username: string,
|
||||
displayName: string
|
||||
}
|
||||
export type ProfileTokenFormat = {
|
||||
iss: string;
|
||||
sub: number;
|
||||
nbf: number;
|
||||
iat: number;
|
||||
exp: number;
|
||||
typ: AuthType;
|
||||
}
|
||||
|
||||
class Profile {
|
||||
|
||||
static async getUniqueId() {
|
||||
let id = Math.round(Math.random() * Math.pow(2, 31));
|
||||
while ((await Redis.Database.exists(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.Username))) >= 1)
|
||||
id = await this.getUniqueId();
|
||||
return id;
|
||||
}
|
||||
|
||||
static async byName(name: string) {
|
||||
const id = await Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profile_Usernames, name));
|
||||
if (id == null) return null;
|
||||
else return new Profile(parseInt(id, 10));
|
||||
}
|
||||
|
||||
static async getUniqueUsername() {
|
||||
let username = `${Dictionary.Adjectives[Math.floor(Math.random() * Dictionary.Adjectives.length)]}${Dictionary.Nouns[Math.floor(Math.random() * Dictionary.Nouns.length)]}${Math.round(Math.random() * 10000)}`
|
||||
while ((await Profile.byName(username)) !== null) username = await this.getUniqueUsername();
|
||||
return username;
|
||||
}
|
||||
|
||||
static async init(options?: ProfileInitOptions) {
|
||||
|
||||
const optionsSpecified = typeof options !== 'undefined';
|
||||
|
||||
const newId = await this.getUniqueId();
|
||||
const newUsername = optionsSpecified ? options.username : await this.getUniqueUsername();
|
||||
|
||||
await Redis.Database.set(Redis.buildKey(Redis.KeyGroups.Profile_Usernames, newUsername), newId);
|
||||
await Redis.Database.set(Redis.buildKey(Redis.KeyGroups.Profiles.Root, newId.toString(), Redis.KeyGroups.Profiles.Username), newUsername);
|
||||
|
||||
return new Profile(newId);
|
||||
|
||||
}
|
||||
|
||||
// surely this can be written better
|
||||
static getExportAccount(id: number): Promise<AccountExport | null> {
|
||||
return new Promise((resolve, _reject) => {
|
||||
Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.Username)).then(val => {
|
||||
if (val == null) resolve(null);
|
||||
else {
|
||||
const promises = {
|
||||
profileImage: Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.ProfileImage)),
|
||||
isJunior: Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.Junior)),
|
||||
platforms: Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.Platforms)),
|
||||
displayName: Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.DisplayName)),
|
||||
username: Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Profiles.Root, id.toString(), Redis.KeyGroups.Profiles.Username)),
|
||||
}
|
||||
|
||||
Promise.all(Object.values(promises)).then((values) => {
|
||||
resolve({
|
||||
accountId: id,
|
||||
profileImage: values[0] == null ? "DefaultProfileImage" : values[0],
|
||||
isJunior: values[1] == null ? false : JSON.parse(values[1]),
|
||||
platforms: values[2] == null ? 1 : JSON.parse(values[2]),
|
||||
displayName: values[3] == null ? (values[4] == null ? "DATABASEERROR" : values[4]) : values[3],
|
||||
username: values[4] == null ? "DATABASEERROR" : values[4],
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static async getExportAccountsBulk(ids: number[]) {
|
||||
|
||||
const accs = await Promise.all(ids.map(val => this.getExportAccount(val)));
|
||||
return accs.filter(val => val !== null);
|
||||
|
||||
}
|
||||
|
||||
#id: number;
|
||||
|
||||
constructor(id: number) {
|
||||
this.#id = id;
|
||||
}
|
||||
|
||||
getId() {
|
||||
return this.#id;
|
||||
}
|
||||
|
||||
async export() {
|
||||
return await Profile.getExportAccount(this.#id);
|
||||
}
|
||||
|
||||
async getToken() {
|
||||
const payload: ProfileTokenFormat = {
|
||||
iss: config.web.publichost,
|
||||
sub: this.#id,
|
||||
nbf: Math.round(Date.now() / 1000) - 200,
|
||||
iat: Math.round(Date.now() / 1000),
|
||||
exp: Math.round(Date.now() / 1000) + (config.auth.timeout * 60 * 60),
|
||||
typ: AuthType.Web
|
||||
};
|
||||
return await JsonWebToken.encode(payload, config.auth.secret, { algorithm: "HS512" });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Profile;
|
||||
Reference in New Issue
Block a user