forked from engineering/cloudservices
fixes
parent
7d5b56d8cc
commit
8c12ad4086
|
@ -57,6 +57,8 @@ export default class Root extends Route {
|
||||||
try {
|
try {
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
const token = <any> jwt.verify(req.query.t.toString(), this.server.client.config.keyPair.privateKey);
|
const token = <any> jwt.verify(req.query.t.toString(), this.server.client.config.keyPair.privateKey);
|
||||||
|
const check = await this.server.storage.get<boolean>(token);
|
||||||
|
if (!check) return res.sendStatus(401);
|
||||||
const embed = new RichEmbed();
|
const embed = new RichEmbed();
|
||||||
embed.setTitle('Referral Authorization');
|
embed.setTitle('Referral Authorization');
|
||||||
embed.addField('Referred User', token.referredUserAndDiscrim, true);
|
embed.addField('Referred User', token.referredUserAndDiscrim, true);
|
||||||
|
@ -64,6 +66,7 @@ export default class Root extends Route {
|
||||||
embed.addField('Referral Code', token.referralCode, true);
|
embed.addField('Referral Code', token.referralCode, true);
|
||||||
const channel = <TextChannel> this.server.client.guilds.get('446067825673633794').channels.get('580950455581147146');
|
const channel = <TextChannel> this.server.client.guilds.get('446067825673633794').channels.get('580950455581147146');
|
||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
|
await this.server.storage.set(token, true);
|
||||||
return channel.createMessage({ content: `<@${token.staffUserID}>`, embed });
|
return channel.createMessage({ content: `<@${token.staffUserID}>`, embed });
|
||||||
} catch {
|
} catch {
|
||||||
return res.sendStatus(401);
|
return res.sendStatus(401);
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
if (response.status === 200) return alert('Request authorized. You may now close this tab.');
|
if (response.status === 200) return alert('Request authorized. You may now close this tab.');
|
||||||
if (response.status === 401) return alert('Authorization Token incorrect, try again.');
|
if (response.status === 401) return alert('Authorization Token incorrect, try again.');
|
||||||
if (response.status >= 500) return alert('INTERNAL SERVER ERROR');
|
if (response.status >= 500) return alert('INTERNAL SERVER ERROR');
|
||||||
alert('Authentication Complete.');
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err);
|
alert(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
/* eslint-disable no-constant-condition */
|
||||||
|
import { promises as fs, accessSync, constants, writeFileSync } from 'fs';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
import { gzip, gzipSync, unzip } from 'zlib';
|
||||||
|
|
||||||
|
type JSONData = [{key: string, value: any}?];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistant local JSON-based storage.
|
||||||
|
* - auto-locking system to prevent corrupted data
|
||||||
|
* - uses gzip compression to keep DB storage space utilization low
|
||||||
|
* @author Matthew <matthew@staff.libraryofcode.org>
|
||||||
|
*/
|
||||||
|
export default class LocalStorage {
|
||||||
|
protected readonly storagePath: string;
|
||||||
|
|
||||||
|
protected locked: boolean = false;
|
||||||
|
|
||||||
|
constructor(dbName: string, dir = `${__dirname}/../../localstorage`) {
|
||||||
|
this.storagePath = `${dir}/${dbName}.json.gz`;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private init() {
|
||||||
|
try {
|
||||||
|
accessSync(this.storagePath, constants.F_OK);
|
||||||
|
} catch {
|
||||||
|
const setup = [];
|
||||||
|
const data = gzipSync(JSON.stringify(setup));
|
||||||
|
writeFileSync(this.storagePath, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compresses data using gzip.
|
||||||
|
* @param data The data to be compressed.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.compress('hello!');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
static async compress(data: string): Promise<Buffer> {
|
||||||
|
const func = promisify(gzip);
|
||||||
|
const comp = <Buffer> await func(data);
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decompresses data using gzip.
|
||||||
|
* @param data The data to be decompressed.
|
||||||
|
* ```ts
|
||||||
|
* const compressed = await LocalStorage.compress('data');
|
||||||
|
* const decompressed = await LocalStorage.decompress(compressed);
|
||||||
|
* console.log(decompressed); // logs 'data';
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
static async decompress(data: Buffer): Promise<string> {
|
||||||
|
const func = promisify(unzip);
|
||||||
|
const uncomp = <Buffer> await func(data);
|
||||||
|
return uncomp.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves one data from the store.
|
||||||
|
* If the store has multiple entries for the same key, this function will only return the first entry.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.get<type>('data-key');
|
||||||
|
* ```
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
*/
|
||||||
|
public async get<T>(key: string): Promise<T> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(this.storagePath);
|
||||||
|
const uncomp = await LocalStorage.decompress(file);
|
||||||
|
this.locked = false;
|
||||||
|
const json: JSONData = JSON.parse(uncomp);
|
||||||
|
const result = json.filter((data) => data.key === key);
|
||||||
|
if (!result[0]) return null;
|
||||||
|
return result[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves multiple data keys/values from the store.
|
||||||
|
* This function will return all of the values matching the key you provided exactly. Use `LocalStorage.get();` if possible.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.get<type>('data-key');
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
*/
|
||||||
|
public async getMany<T>(key: string): Promise<{key: string, value: T}[]> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(this.storagePath);
|
||||||
|
const uncomp = await LocalStorage.decompress(file);
|
||||||
|
this.locked = false;
|
||||||
|
const json: JSONData = JSON.parse(uncomp);
|
||||||
|
const result = json.filter((data) => data.key === key);
|
||||||
|
if (result.length < 1) return null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a key/value pair and creates a new data entry.
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
* @param value The value for the data entry, can be anything that is valid JSON.
|
||||||
|
* @param options.override [DEPRECATED] By default, this function will error if the key you're trying to set already exists. Set this option to true to override that setting.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.set('data-key', 'test');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
public async set(key: string, value: any): Promise<void> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(this.storagePath);
|
||||||
|
const uncomp = await LocalStorage.decompress(file);
|
||||||
|
const json: JSONData = JSON.parse(uncomp);
|
||||||
|
json.push({ key, value });
|
||||||
|
const comp = await LocalStorage.compress(JSON.stringify(json));
|
||||||
|
await fs.writeFile(this.storagePath, comp);
|
||||||
|
this.locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the data for the specified key.
|
||||||
|
* **Warning:** This function will delete ALL matching entries.
|
||||||
|
* ```ts
|
||||||
|
* await LocalStorage.del('data-key');
|
||||||
|
* ```
|
||||||
|
* @param key The key for the data entry.
|
||||||
|
*/
|
||||||
|
public async del(key: string): Promise<void> {
|
||||||
|
while (true) {
|
||||||
|
if (!this.locked) break;
|
||||||
|
}
|
||||||
|
this.locked = true;
|
||||||
|
|
||||||
|
const file = await fs.readFile(this.storagePath);
|
||||||
|
const uncomp = await LocalStorage.decompress(file);
|
||||||
|
const json: JSONData = JSON.parse(uncomp);
|
||||||
|
const filtered = json.filter((data) => data.key !== key);
|
||||||
|
const comp = await LocalStorage.compress(JSON.stringify(filtered));
|
||||||
|
await fs.writeFile(this.storagePath, comp);
|
||||||
|
this.locked = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ import express from 'express';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
import helmet from 'helmet';
|
import helmet from 'helmet';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import { Client, Collection, Route } from '.';
|
import { Client, Collection, LocalStorage, Route } from '.';
|
||||||
import { Security } from '../api';
|
import { Security } from '../api';
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +16,8 @@ export default class Server {
|
||||||
|
|
||||||
public app: express.Express;
|
public app: express.Express;
|
||||||
|
|
||||||
|
public storage: LocalStorage;
|
||||||
|
|
||||||
public options: { port: number }
|
public options: { port: number }
|
||||||
|
|
||||||
constructor(client: Client, options?: { port: number }) {
|
constructor(client: Client, options?: { port: number }) {
|
||||||
|
@ -24,6 +26,7 @@ export default class Server {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.security = new Security(this.client);
|
this.security = new Security(this.client);
|
||||||
this.app = express();
|
this.app = express();
|
||||||
|
this.storage = new LocalStorage('usedra', '/opt/CloudServices/localstorage');
|
||||||
this.connect();
|
this.connect();
|
||||||
this.loadRoutes();
|
this.loadRoutes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ export { default as Client } from './Client';
|
||||||
export { default as Collection } from './Collection';
|
export { default as Collection } from './Collection';
|
||||||
export { default as Command } from './Command';
|
export { default as Command } from './Command';
|
||||||
export { default as Event } from './Event';
|
export { default as Event } from './Event';
|
||||||
|
export { default as LocalStorage } from './LocalStorage';
|
||||||
export { default as RichEmbed } from './RichEmbed';
|
export { default as RichEmbed } from './RichEmbed';
|
||||||
export { default as Route } from './Route';
|
export { default as Route } from './Route';
|
||||||
export { default as Security } from './Security';
|
export { default as Security } from './Security';
|
||||||
|
|
Loading…
Reference in New Issue