UNPKG

dimensions-ai

Version:

A generalized AI Competition framework that allows you to create any competition you want in any language you want with no hassle.

268 lines 10.2 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { Database } from '../../Plugin/Database'; import { Player } from '../../Tournament'; import { verify, generateToken } from '../../Plugin/Database/utils'; import { Plugin } from '../../Plugin'; import bcrypt from 'bcryptjs'; import { Datastore } from '@google-cloud/datastore'; import { pickMatch } from '../../Station/routes/api/dimensions/match'; import { deepMerge } from '../../utils/DeepMerge'; import { deepCopy } from '../../utils/DeepCopy'; import { stripFunctions } from '../../utils'; // eslint-disable-next-line @typescript-eslint/no-var-requires require('dotenv').config(); const salt = bcrypt.genSaltSync(); export class GCloudDataStore extends Database { constructor(gcpConfigs, configs = {}) { super(configs); this.name = 'GCloud Data Store'; this.type = Plugin.Type.DATABASE; this.datastore = new Datastore({ keyFile: gcpConfigs.keyFile }); } initialize() { return __awaiter(this, void 0, void 0, function* () { const existingUser = yield this.getUser('admin'); if (!existingUser) { yield this.registerUser('admin', process.env.ADMIN_PASSWORD); } return; }); } storeMatch(match, governID) { return __awaiter(this, void 0, void 0, function* () { const data = Object.assign(Object.assign({}, pickMatch(match)), { governID: governID }); // store all relevant data and strip functions const strippedData = stripFunctions(deepCopy(data)); const key = this.getMatchDatastoreKey(match.id); return this.datastore.save({ key: key, data: strippedData, }); }); } getMatch(id) { return __awaiter(this, void 0, void 0, function* () { const key = this.getMatchDatastoreKey(id); return (yield this.datastore.get(key))[0]; }); } getPlayerMatches(playerID, governID, offset = 0, limit = 10, order = -1) { return __awaiter(this, void 0, void 0, function* () { const query = this.datastore .createQuery(GCloudDataStore.Kinds.MATCHES) .filter('agents.tournamentID.id', '=', playerID) .filter('governID', '=', governID) .offset(offset) .limit(limit) .order('creationDate', { descending: order === -1 }); return (yield this.datastore.runQuery(query))[0]; }); } registerUser(username, password, // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types userData) { return __awaiter(this, void 0, void 0, function* () { const hash = bcrypt.hashSync(password, salt); const playerID = Player.generatePlayerID(); // const key = this.getUserDatastoreKey(username); const playerIDkey = this.datastore.key([ GCloudDataStore.Kinds.USERS, username, GCloudDataStore.Kinds.PLAYER_IDS, playerID, ]); const userKey = this.getUserDatastoreKey(username); const user = { username, passwordHash: hash, statistics: { test: { nested: 'abc', }, }, playerID: playerID, meta: Object.assign({}, userData), }; yield this.datastore.insert({ key: userKey, data: user, excludeFromIndexes: ['passwordHash'], }); yield this.datastore.insert({ key: playerIDkey, data: {}, }); }); } getUserDatastoreKey(username) { return this.datastore.key([GCloudDataStore.Kinds.USERS, username]); } getMatchDatastoreKey(matchID) { return this.datastore.key([GCloudDataStore.Kinds.MATCHES, matchID]); } getTournamentConfigsDatastoreKey(tournamentID) { return this.datastore.key([ GCloudDataStore.Kinds.TOURNAMENT_CONFIGS, tournamentID, ]); } /** * Gets user information. If public is false, will retrieve all information other than password * @param usernameOrID */ getUser(usernameOrID, publicView = true) { return __awaiter(this, void 0, void 0, function* () { let user; // query by playerID first, then by username const q = this.datastore .createQuery(GCloudDataStore.Kinds.USERS) .filter('playerID', '=', usernameOrID); const res = yield this.datastore.runQuery(q); user = res[0][0]; // there should only be one user with this playerID if (!user) { const key = this.getUserDatastoreKey(usernameOrID); user = (yield this.datastore.get(key))[0]; } if (publicView && user) { delete user.passwordHash; } return user; }); } loginUser(username, password) { return __awaiter(this, void 0, void 0, function* () { const userKey = this.getUserDatastoreKey(username); const user = (yield this.datastore.get(userKey))[0]; if (user) { if (bcrypt.compareSync(password, user.passwordHash)) { return generateToken(user); } else { throw new Error('Invalid password'); } } else { throw new Error('Not a valid user'); } }); } updateUser(usernameOrID, update) { return __awaiter(this, void 0, void 0, function* () { let user = yield this.getUser(usernameOrID); const userKey = this.getUserDatastoreKey(user.username); user = deepMerge(user, update); yield this.datastore.update({ key: userKey, data: user, }); }); } deleteUser(usernameOrID) { return __awaiter(this, void 0, void 0, function* () { const user = yield this.getUser(usernameOrID); const userKey = this.getUserDatastoreKey(user.username); yield this.datastore.delete({ key: userKey, }); }); } verifyToken(jwt) { return __awaiter(this, void 0, void 0, function* () { return verify(jwt); }); } isAdmin(user) { if (user.username === 'admin') return true; return false; } getUsersInTournament(tournamentKey, offset = 0, limit = -1) { return __awaiter(this, void 0, void 0, function* () { const key = `statistics.${tournamentKey}`; if (limit == -1) { limit = 0; } else if (limit == 0) { return []; } const q = this.datastore .createQuery(GCloudDataStore.Kinds.USERS) .filter(`${key}.matchesPlayed`, '>=', 0) .offset(offset); return (yield this.datastore.runQuery(q))[0]; }); } manipulate(dimension) { return __awaiter(this, void 0, void 0, function* () { dimension.configs.backingDatabase = this.name; return; }); } storeTournamentConfigs(tournamentID, tournamentConfigs, status) { return __awaiter(this, void 0, void 0, function* () { const key = this.getTournamentConfigsDatastoreKey(tournamentID); yield this.datastore.upsert({ key: key, data: { configs: stripFunctions(deepCopy(tournamentConfigs)), id: tournamentID, status: status, modificationDate: new Date(), }, }); }); } getTournamentConfigsModificationDate(tournamentID) { return __awaiter(this, void 0, void 0, function* () { const key = this.getTournamentConfigsDatastoreKey(tournamentID); const data = (yield this.datastore.get(key))[0]; if (data) { return new Date(data.modificationDate); } return null; }); } getTournamentConfigs(tournamentID) { return __awaiter(this, void 0, void 0, function* () { const key = this.getTournamentConfigsDatastoreKey(tournamentID); const data = (yield this.datastore.get(key))[0]; if (data) { return { configs: data.configs, status: data.status }; } return null; }); } } (function (GCloudDataStore) { /** * The kind of various groupings in the datastore */ let Kinds; (function (Kinds) { /** * For all user data */ Kinds["USERS"] = "users"; /** * Player ID data for uniqueness */ Kinds["PLAYER_IDS"] = "playerIds"; /** * For all tournament configuration data */ Kinds["TOURNAMENT_CONFIGS"] = "tournamentConfigs"; /** * For all match data */ Kinds["MATCHES"] = "matches"; })(Kinds = GCloudDataStore.Kinds || (GCloudDataStore.Kinds = {})); })(GCloudDataStore || (GCloudDataStore = {})); //# sourceMappingURL=index.js.map