Merge pull request #8 from jgillich/master

Update db schema, fix broken /stats route
This commit is contained in:
Mazo 2020-08-26 23:33:52 +01:00 committed by GitHub
commit 10b075ed78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 164 additions and 138 deletions

View file

@ -31,7 +31,7 @@ export const SQL_ORDER = Object.freeze({
});
export const ACCOUNT = Object.freeze({
THIS: Symbol("accounts"),
THIS: Symbol("account"),
ID: Symbol("id"),
USER: Symbol("username"),
PASSWORD: Symbol("passhash"),
@ -45,7 +45,7 @@ export const ACCOUNT = Object.freeze({
});
export const CHARACTER = Object.freeze({
THIS: Symbol("characters"),
THIS: Symbol("avatar"),
ID: Symbol("id"),
NAME: Symbol("name"),
ACCOUNT_ID: Symbol("account_id"),
@ -60,7 +60,7 @@ export const CHARACTER = Object.freeze({
});
export const LOGIN = Object.freeze({
THIS: Symbol("logins"),
THIS: Symbol("login"),
ID: Symbol("id"),
ACCOUNT_ID: Symbol("account_id"),
});
@ -180,7 +180,7 @@ export async function connect_to_db() {
export async function get_account_by_id(id) {
try {
const account = await pool.query('SELECT * FROM accounts WHERE id=$1', [id]);
const account = await pool.query('SELECT * FROM account WHERE id=$1', [id]);
if (account.rows.length == 0) {
return undefined;
@ -201,7 +201,7 @@ export async function get_accounts(pagination, sort, order) {
try {
const account_count = await get_row_count(ACCOUNT.THIS);
const accounts = await pool.query(`SELECT id, username, created, last_modified, gm, inactive FROM accounts ORDER BY ${to_sql(sort)} ${to_sql(order)} OFFSET $1 LIMIT $2`, values);
const accounts = await pool.query(`SELECT id, username, created, last_modified, gm, inactive FROM account ORDER BY ${to_sql(sort)} ${to_sql(order)} OFFSET $1 LIMIT $2`, values);
pagination.item_count = account_count;
pagination.page_count = Math.ceil(pagination.item_count / pagination.items_per_page);
@ -233,13 +233,13 @@ export async function get_accounts_login_info(pagination, sort, filter) {
// this was a really hard query to get right...
// https://www.gab.lc/articles/better_faster_subqueries_postgresql/
const accounts = await pool.query(
'SELECT accounts.*, COALESCE(l.lastLogin, TIMESTAMP \'epoch\') as last_login, l2.ip_address, l2.canonical_hostname FROM accounts' +
'SELECT account.*, COALESCE(l.lastLogin, TIMESTAMP \'epoch\') as last_login, l2.ip_address, l2.canonical_hostname FROM account' +
' LEFT OUTER JOIN (' +
' SELECT MAX(id) as loginId, account_id, MAX(login_time) as lastLogin' +
' FROM logins' +
' FROM login' +
' GROUP BY account_id' +
' ) l ON l.account_id = accounts.id' +
' LEFT OUTER JOIN logins l2' +
' ) l ON l.account_id = account.id' +
' LEFT OUTER JOIN login l2' +
' ON l2.id = l.loginId' +
` ${to_sql(where.sql)}` +
` ${to_sql(order)}` +
@ -282,7 +282,7 @@ export async function get_characters(pagination, sort, order) {
try {
const char_count = await get_row_count(CHARACTER.THIS);
const chars = await pool.query(`SELECT id, account_id, name, faction_id, created, last_login FROM characters ORDER BY ${to_sql(sort)} ${to_sql(order)} OFFSET $1 LIMIT $2`, values);
const chars = await pool.query(`SELECT id, account_id, name, faction_id, created, last_login FROM avatar ORDER BY ${to_sql(sort)} ${to_sql(order)} OFFSET $1 LIMIT $2`, values);
pagination.item_count = char_count;
pagination.page_count = Math.ceil(pagination.item_count / pagination.items_per_page);
@ -297,7 +297,7 @@ export async function get_characters(pagination, sort, order) {
export async function get_characters_by_account(account_id) {
try {
const characters = await pool.query('SELECT * FROM characters WHERE account_id=$1 AND deleted=false', [account_id])
const characters = await pool.query('SELECT * FROM avatar WHERE account_id=$1 AND deleted=false', [account_id])
return characters.rows;
} catch (e) {
if (e.code)
@ -308,7 +308,7 @@ export async function get_characters_by_account(account_id) {
export async function get_account_by_name(name) {
try {
const account = await pool.query('SELECT * FROM accounts WHERE username=$1', [name]);
const account = await pool.query('SELECT * FROM account WHERE username=$1', [name]);
return account.rows[0];
} catch (e) {
if (e.code)
@ -319,7 +319,7 @@ export async function get_account_by_name(name) {
export async function get_character_by_name(name) {
try {
const account = await pool.query('SELECT id, account_id, name, faction_id, created, last_login FROM characters WHERE name=$1 AND deleted=false', [name]);
const account = await pool.query('SELECT id, account_id, name, faction_id, created, last_login FROM avatar WHERE name=$1 AND deleted=false', [name]);
return account.rows[0];
} catch (e) {
if (e.code)
@ -331,7 +331,7 @@ export async function get_character_by_name(name) {
export async function create_account(username, password) {
try {
const passhash = await bcrypt.hash(password, BCRYPT_ROUNDS);
const account_id = await pool.query('INSERT INTO accounts(username, passhash) VALUES($1, $2) RETURNING id', [username, passhash]);
const account_id = await pool.query('INSERT INTO account(username, passhash) VALUES($1, $2) RETURNING id', [username, passhash]);
return account_id.rows[0].id;
} catch (e) {
if (e.code)
@ -349,7 +349,7 @@ export async function update_account(account_id, fields) {
set.values.push(account_id)
try {
const update_result = await pool.query(`UPDATE accounts ${to_sql(set.sql)} WHERE id=$${set.next_idx}`, set.values);
const update_result = await pool.query(`UPDATE account ${to_sql(set.sql)} WHERE id=$${set.next_idx}`, set.values);
return update_result.rowCount;
} catch (e) {
if (e.code)
@ -360,7 +360,7 @@ export async function update_account(account_id, fields) {
export async function get_empire_stats() {
try {
const query = await pool.query('SELECT faction_id, COUNT(*) FROM characters GROUP BY faction_id');
const query = await pool.query('SELECT faction_id, COUNT(*) FROM avatar GROUP BY faction_id');
const empires = {};
query.rows.forEach((r) => {
@ -380,7 +380,7 @@ export async function get_stats() {
try {
const account_count = await get_row_count(ACCOUNT.THIS);
const character_count = await get_row_count(CHARACTER.THIS);
const last_character = await pool.query('SELECT id, account_id, name, faction_id, created FROM characters ORDER BY id DESC LIMIT 1');
const last_character = await pool.query('SELECT id, account_id, name, faction_id, created FROM avatar ORDER BY id DESC LIMIT 1');
const stats = {}
@ -407,7 +407,7 @@ export async function get_account_logins(account_id, pagination) {
[LOGIN.ACCOUNT_ID]: account_id,
}
});
const logins = await pool.query('SELECT * FROM logins WHERE account_id=$1 ORDER by login_time DESC ' + ` OFFSET $2 LIMIT $3`, values);
const logins = await pool.query('SELECT * FROM login WHERE account_id=$1 ORDER by login_time DESC ' + ` OFFSET $2 LIMIT $3`, values);
pagination.item_count = login_count;
pagination.page_count = Math.ceil(pagination.item_count / pagination.items_per_page);
@ -432,10 +432,10 @@ export async function search(term, pagination) {
const values = ['%' + term.toUpperCase() + '%', start_id, pagination.items_per_page];
try {
const accounts = await pool.query('SELECT id, username, gm, inactive FROM accounts ' +
const accounts = await pool.query('SELECT id, username, gm, inactive FROM account ' +
'WHERE upper(username) LIKE $1 ' +
` ORDER BY username OFFSET $2 LIMIT $3`, values);
const characters = await pool.query('SELECT id, name, account_id, faction_id FROM characters ' +
const characters = await pool.query('SELECT id, name, account_id, faction_id FROM avatar ' +
'WHERE upper(name) LIKE $1 ' +
` ORDER BY name OFFSET $2 LIMIT $3`, values);
@ -484,7 +484,7 @@ export async function search(term, pagination) {
export async function validate_account(username, password) {
try {
const data = await pool.query('SELECT id, passhash FROM accounts WHERE username=$1 and gm=true', [username]);
const data = await pool.query('SELECT id, passhash FROM account WHERE username=$1', [username]);
if (data.rows.length === 0) {
return undefined;

View file

@ -15,13 +15,13 @@ api.get('/stats', async (req, res, next) => {
let players = info.players;
for (let i = 0; i < players.length; i++) {
const char = await db.get_character_by_name(players[i]);
const char = await db.get_character_by_name(players[i].name);
if (char) {
player_info = player_info.concat(char)
stats.empires[db.FACTION_MAP[char.faction_id][1]] += 1
} else {
console.log("WARNING: cannot find player info '" + players[i] + "' (are you sure PSAdmin is configured right?)")
console.log("WARNING: cannot find player info '" + players[i].name + "' (are you sure PSAdmin is configured right?)")
}
}

View file

@ -32,7 +32,7 @@ api.get('/user/:user/profile', NEED_SESSION, async (req, res, next) => {
id: account.id,
name: account.username,
//email : account.email, // TODO
email : "bademail@email.com",
email: "N/A",
account_created: account.created,
admin: account.gm,
inactive: account.inactive,

View file

@ -8,18 +8,7 @@ import api from './api/index.js'
import { start_server_polling } from './api/psadmin.js'
import * as db from './api/db.js'
const envresult = dotenv.config();
if (envresult.error) {
const err = envresult.error;
if (err.code == 'ENOENT') {
console.log("FATAL: your .env file is missing!")
process.exit(1);
} else {
throw envresult.error;
}
}
dotenv.config();
const PORT = process.env.PORT || 8080;
const MODE = process.env.NODE_ENV || 'development';

63
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "psfportal",
"version": "1.0.0",
"version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1484,6 +1484,28 @@
"integrity": "sha512-pWRuser61Opj/LtzrkuRkmBcCYY1dvZ7jLu83rR7vIsTzFpmQoe1KcmMalwlN3rCq1VVHssGjY42SCSe2vEizQ==",
"requires": {
"pg": "^7.4.3"
},
"dependencies": {
"pg": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz",
"integrity": "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==",
"requires": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
"pg-connection-string": "0.1.3",
"pg-packet-stream": "^1.1.0",
"pg-pool": "^2.0.10",
"pg-types": "^2.1.0",
"pgpass": "1.x",
"semver": "4.3.2"
}
},
"semver": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
"integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
}
}
},
"console-browserify": {
@ -5227,20 +5249,30 @@
}
},
"pg": {
"version": "7.17.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-7.17.0.tgz",
"integrity": "sha512-70Q4ZzIdPgwMPb3zUIzAUwigNJ4v5vsWdMED6OzXMfOECeYTvTm7iSC3FpKizu/R1BHL8Do3bLs6ltGfOTAnqg==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.2.0.tgz",
"integrity": "sha512-EQeWKZv7qBTQZQa7EraR61AOi0bpizvlZLvrPdgAGaraX4YI+y40iQnL39XjPMXVnHOOG3jV6kAGtc0WSJn/+A==",
"requires": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
"pg-connection-string": "0.1.3",
"pg-packet-stream": "^1.1.0",
"pg-pool": "^2.0.9",
"pg-connection-string": "^2.2.2",
"pg-pool": "^3.2.0",
"pg-protocol": "^1.2.3",
"pg-types": "^2.1.0",
"pgpass": "1.x",
"semver": "4.3.2"
},
"dependencies": {
"pg-connection-string": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.2.2.tgz",
"integrity": "sha512-+hel4DGuSZCjCZwglAuyi+XlodHnKmrbyTw0hVWlmGN2o4AfJDkDo5obAFzblS5M5PFBMx0uDt5Y1QjlNC+tqg=="
},
"pg-pool": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.0.tgz",
"integrity": "sha512-7BLwDNDEfPFjE9vmZLcJPLFwuDAVGZ5lIZo2MeQfwYG7EPGfdNVis/dz6obI/yKqvQIx2sf6QBKXMLB+y/ftgA=="
},
"semver": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
@ -5269,9 +5301,14 @@
"integrity": "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg=="
},
"pg-pool": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.9.tgz",
"integrity": "sha512-gNiuIEKNCT3OnudQM2kvgSnXsLkSpd6mS/fRnqs6ANtrke6j8OY5l9mnAryf1kgwJMWLg0C1N1cYTZG1xmEYHQ=="
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz",
"integrity": "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg=="
},
"pg-protocol": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.3.tgz",
"integrity": "sha512-erHFURS0mPmTbq18cn/zNL3Y4IzNCrU4sgCim0qy7zAPe3Vc0rvK5cImJR6lDvIaz3fJU2R1R9FNOlnUtyF10Q=="
},
"pg-types": {
"version": "2.2.0",
@ -6048,9 +6085,9 @@
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
},
"postgres-date": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.4.tgz",
"integrity": "sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA=="
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz",
"integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA=="
},
"postgres-interval": {
"version": "1.2.0",

View file

@ -31,7 +31,7 @@
"express-session": "^1.17.0",
"morgan": "^1.9.1",
"page": "^1.11.5",
"pg": "^7.15.1",
"pg": "^8.2.0",
"pg-error-constants": "^1.0.0"
},
"devDependencies": {