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
JavaScript
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