1
1
mirror of https://github.com/Burn-E99/TheArtificer.git synced 2026-06-04 09:03:50 -04:00

Cleaned up API responses to make them more standard and easier to customize

This commit is contained in:
Ean Milligan (Bastion)
2022-06-21 21:33:24 -04:00
parent 0cabfe0c99
commit d45cc89eec
12 changed files with 103 additions and 130 deletions

View File

@@ -8,11 +8,9 @@ import {
nanoid,
// Discordeno deps
sendMessage,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import { generateApiDeleteEmail } from '../../commandUtils.ts';
import stdResp from '../stdResponses.ts';
export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, apiUserEmail: string, apiUserDelCode: string) => {
if (query.has('user') && ((query.get('user') || '').length > 0) && query.has('email') && ((query.get('email') || '').length > 0)) {
@@ -24,7 +22,7 @@ export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<s
await dbClient.execute('DELETE FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-6`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
if (erroredOut) {
@@ -33,19 +31,19 @@ export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<s
await dbClient.execute('DELETE FROM all_keys WHERE userid = ?', [apiUserid]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-7`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
if (erroredOut) {
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.OK), { status: Status.OK }));
// Send OK as response to indicate key deletion was successful
requestEvent.respondWith(stdResp.OK(''));
return;
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// User does not have their delete code yet, so we need to generate one and email it to them
@@ -56,7 +54,7 @@ export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<s
// Execute the DB modification
await dbClient.execute('UPDATE all_keys SET deleteCode = ? WHERE userid = ?', [deleteCode, apiUserid]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-8`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
if (erroredOut) {
@@ -65,23 +63,23 @@ export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<s
// "Send" the email
await sendMessage(config.api.email, generateApiDeleteEmail(apiUserEmail, deleteCode)).catch(() => {
requestEvent.respondWith(new Response('Message 30 failed to send.', { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
erroredOut = true;
});
if (erroredOut) {
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.FailedDependency), { status: Status.FailedDependency }));
requestEvent.respondWith(stdResp.FailedDependency('Please look for an email containing a Delete Key and run this query again with said key.'));
return;
}
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -3,10 +3,8 @@ import {
// Log4Deno deps
log,
LT,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import stdResp from '../stdResponses.ts';
export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
if (query.has('user') && ((query.get('user') || '').length > 0)) {
@@ -17,7 +15,7 @@ export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<str
// Get all channels userid has authorized
const dbAllowedChannelQuery = await dbClient.query('SELECT * FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-1`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
@@ -26,16 +24,16 @@ export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<str
} else {
// Customized strinification to handle BigInts correctly
const returnChannels = JSON.stringify(dbAllowedChannelQuery, (_key, value) => (typeof value === 'bigint' ? value.toString() : value));
// Send API key as response
requestEvent.respondWith(new Response(returnChannels, { status: Status.OK }));
// Send channel list as response
requestEvent.respondWith(stdResp.OK(returnChannels));
return;
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -8,11 +8,9 @@ import {
nanoid,
// Discordeno deps
sendMessage,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import { generateApiKeyEmail } from '../../commandUtils.ts';
import stdResp from '../stdResponses.ts';
export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string, string>) => {
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('email') && ((query.get('email') || '').length > 0))) {
@@ -26,7 +24,7 @@ export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string,
await dbClient.execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()]).catch(
(e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-9`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
},
);
@@ -38,19 +36,19 @@ export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string,
// "Send" the email
await sendMessage(config.api.email, generateApiKeyEmail(query.get('email') || 'no email', newKey)).catch(() => {
requestEvent.respondWith(new Response('Message 31 failed to send.', { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
erroredOut = true;
});
if (erroredOut) {
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.OK), { status: Status.OK }));
// Send basic OK to indicate key has been sent
requestEvent.respondWith(stdResp.OK(''));
return;
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -6,10 +6,8 @@ import {
LT,
// nanoid deps
nanoid,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import stdResp from '../stdResponses.ts';
export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('a') && ((query.get('a') || '').length > 0))) {
@@ -23,7 +21,7 @@ export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<st
// Insert new key/user pair into the db
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [apiUserid, newKey]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-0`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
@@ -32,15 +30,15 @@ export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<st
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(JSON.stringify({ 'key': newKey, 'userid': query.get('user') }), { status: Status.OK }));
requestEvent.respondWith(stdResp.OK(JSON.stringify({ 'key': newKey, 'userid': query.get('user') })));
return;
}
} else {
// Only allow the db admin to use this API
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -6,12 +6,10 @@ import {
// Log4Deno deps
log,
LT,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import { QueuedRoll, RollModifiers } from '../../mod.d.ts';
import { queueRoll } from '../../solver/rollQueue.ts';
import stdResp from '../stdResponses.ts';
const apiWarning = `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>`;
@@ -23,7 +21,7 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
) {
if (query.has('n') && query.has('m')) {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
return;
}
@@ -59,7 +57,7 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
if (rollCmd.length === 0) {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
// Always log API rolls for abuse detection
dbClient.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null]).catch((e) => {
@@ -70,7 +68,7 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
if (query.has('o') && (query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a')) {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
// Always log API rolls for abuse detection
dbClient.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null]).catch((e) => {
@@ -109,19 +107,18 @@ export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string
} catch (err) {
// Handle any errors we missed
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`);
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.InternalServerError), { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(
new Response(
stdResp.Forbidden(
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`,
{ status: Status.Forbidden, statusText: STATUS_TEXT.get(Status.Forbidden) },
),
);
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -3,10 +3,8 @@ import {
// Log4Deno deps
log,
LT,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import stdResp from '../stdResponses.ts';
export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0))) {
@@ -17,7 +15,7 @@ export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<
// Insert new user/channel pair into the db
await dbClient.execute('INSERT INTO allowed_channels(userid,channelid) values(?,?)', [apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-2`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
@@ -25,16 +23,16 @@ export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<
if (erroredOut) {
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.OK), { status: Status.OK }));
// Send OK to indicate modification was successful
requestEvent.respondWith(stdResp.OK(''));
return;
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -3,10 +3,8 @@ import {
// Log4Deno deps
log,
LT,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import stdResp from '../stdResponses.ts';
export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if ((query.has('channel') && ((query.get('channel') || '').length > 0)) && (query.has('user') && ((query.get('user') || '').length > 0))) {
@@ -24,7 +22,7 @@ export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, qu
// Update the requested entry
await dbClient.execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-5`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
@@ -33,15 +31,15 @@ export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, qu
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.OK), { status: Status.OK }));
requestEvent.respondWith(stdResp.OK(''));
return;
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -4,10 +4,8 @@ import {
// Log4Deno deps
log,
LT,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import stdResp from '../stdResponses.ts';
export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if (
@@ -28,7 +26,7 @@ export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query
// Execute the DB modification
await dbClient.execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-4`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
@@ -36,16 +34,16 @@ export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query
if (erroredOut) {
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.OK), { status: Status.OK }));
// Send OK to indicate modification was successful
requestEvent.respondWith(stdResp.OK(''));
return;
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -4,10 +4,8 @@ import {
// Log4Deno deps
log,
LT,
// httpd deps
Status,
STATUS_TEXT,
} from '../../../deps.ts';
import stdResp from '../stdResponses.ts';
export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
if ((query.has('a') && ((query.get('a') || '').length > 0)) && (query.has('user') && ((query.get('user') || '').length > 0))) {
@@ -32,7 +30,7 @@ export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<s
// Execute the DB modification
await dbClient.execute('UPDATE all_keys SET ?? = ? WHERE userid = ?', [key, value, apiUserid]).catch((e) => {
log(LT.ERROR, `Failed to insert into database: ${JSON.stringify(e)}`);
requestEvent.respondWith(new Response(`${STATUS_TEXT.get(Status.InternalServerError)}-3`, { status: Status.InternalServerError }));
requestEvent.respondWith(stdResp.InternalServerError(''));
erroredOut = true;
});
@@ -40,16 +38,16 @@ export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<s
if (erroredOut) {
return;
} else {
// Send API key as response
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.OK), { status: Status.OK }));
// Send OK as response to indicate modification was successful
requestEvent.respondWith(stdResp.OK(''));
return;
}
} else {
// Alert API user that they shouldn't be doing this
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.Forbidden), { status: Status.Forbidden }));
requestEvent.respondWith(stdResp.Forbidden(''));
}
} else {
// Alert API user that they messed up
requestEvent.respondWith(new Response(STATUS_TEXT.get(Status.BadRequest), { status: Status.BadRequest }));
requestEvent.respondWith(stdResp.BadRequest(''));
}
};

View File

@@ -0,0 +1,19 @@
import {
// httpd deps
Status,
STATUS_TEXT,
} from '../../deps.ts';
const genericResponse = (customText: string, status: Status) => new Response(customText || STATUS_TEXT.get(status), { status: status, statusText: STATUS_TEXT.get(status) });
export default {
BadRequest: (customText: string) => genericResponse(customText, Status.BadRequest),
FailedDependency: (customText: string) => genericResponse(customText, Status.FailedDependency),
InternalServerError: (customText: string) => genericResponse(customText, Status.InternalServerError),
Forbidden: (customText: string) => genericResponse(customText, Status.Forbidden),
MethodNotAllowed: (customText: string) => genericResponse(customText, Status.MethodNotAllowed),
NotFound: (customText: string) => genericResponse(customText, Status.NotFound),
OK: (customText: string) => genericResponse(customText, Status.OK),
RequestTimeout: (customText: string) => genericResponse(customText, Status.RequestTimeout),
TooManyRequests: (customText: string) => genericResponse(customText, Status.TooManyRequests),
};