Expanded edit fields. Added revision history to scene and user pages.
This commit is contained in:
@@ -218,7 +218,11 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
||||
}
|
||||
|
||||
if (filters.query) {
|
||||
builder.whereRaw('match(\'@name :query:\', actors)', { query: escape(filters.query) });
|
||||
if (filters.query.charAt(0) === '#') {
|
||||
builder.where('id', Number(escape(filters.query.slice(1))));
|
||||
} else {
|
||||
builder.whereRaw('match(\'@name :query:\', actors)', { query: escape(filters.query) });
|
||||
}
|
||||
}
|
||||
|
||||
// attribute filters
|
||||
|
||||
@@ -59,6 +59,7 @@ export async function login(credentials, userIp) {
|
||||
|
||||
await knex('users')
|
||||
.update('last_login', 'NOW()')
|
||||
.update('last_ip', userIp)
|
||||
.where('id', user.id);
|
||||
|
||||
logger.verbose(`Login from '${user.username}' (${user.id}, ${userIp})`);
|
||||
|
||||
242
src/scenes.js
242
src/scenes.js
@@ -1,11 +1,13 @@
|
||||
import config from 'config';
|
||||
import util from 'util'; /* eslint-disable-line no-unused-vars */
|
||||
import { MerkleJson } from 'merkle-json';
|
||||
|
||||
import { knexQuery as knex, knexOwner, knexManticore } from './knex.js';
|
||||
import { utilsApi } from './manticore.js';
|
||||
import { HttpError } from './errors.js';
|
||||
import { fetchActorsById, curateActor, sortActorsByGender } from './actors.js';
|
||||
import { fetchTagsById } from './tags.js';
|
||||
import { fetchMoviesById } from './movies.js';
|
||||
import { fetchEntitiesById } from './entities.js';
|
||||
import { curateStash } from './stashes.js';
|
||||
import { curateMedia } from './media.js';
|
||||
@@ -14,6 +16,7 @@ import promiseProps from '../utils/promise-props.js';
|
||||
import initLogger from './logger.js';
|
||||
|
||||
const logger = initLogger();
|
||||
const mj = new MerkleJson();
|
||||
|
||||
function getWatchUrl(scene) {
|
||||
if (scene.url) {
|
||||
@@ -600,59 +603,169 @@ export async function fetchScenes(filters, rawOptions, reqUser) {
|
||||
};
|
||||
}
|
||||
|
||||
async function applySceneValueDelta(sceneId, delta, trx) {
|
||||
console.log('value delta', delta);
|
||||
function curateRevision(revision) {
|
||||
return {
|
||||
id: revision.id,
|
||||
sceneId: revision.scene_id,
|
||||
base: revision.base,
|
||||
deltas: revision.deltas,
|
||||
hash: revision.hash,
|
||||
comment: revision.comment,
|
||||
user: revision.user_id && {
|
||||
id: revision.user_id,
|
||||
username: revision.username,
|
||||
},
|
||||
review: typeof revision.approved === 'boolean' ? {
|
||||
isApproved: revision.approved,
|
||||
userId: revision.reviewed_by,
|
||||
username: revision.reviewer_username,
|
||||
reviewedAt: revision.reviewed_at,
|
||||
} : null,
|
||||
appliedAt: revision.applied_at,
|
||||
failed: revision.failed,
|
||||
createdAt: revision.created_at,
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchSceneRevisions(revisionId, filters = {}, reqUser) {
|
||||
const limit = filters.limit || 50;
|
||||
const page = filters.page || 1;
|
||||
|
||||
const revisions = await knexOwner('scenes_revisions')
|
||||
.select(
|
||||
'scenes_revisions.*',
|
||||
'users.username as username',
|
||||
'reviewers.username as reviewer_username',
|
||||
)
|
||||
.leftJoin('users', 'users.id', 'scenes_revisions.user_id')
|
||||
.leftJoin('users as reviewers', 'reviewers.id', 'scenes_revisions.reviewed_by')
|
||||
.modify((builder) => {
|
||||
if (reqUser?.role !== 'admin' && !filters.userId && !filters.sceneId) {
|
||||
builder.where('user_id', reqUser.id);
|
||||
}
|
||||
|
||||
if (filters.userId) {
|
||||
if (reqUser?.role !== 'admin' && filters.userId !== reqUser.id) {
|
||||
throw new HttpError('You are not permitted to view revisions from other users.', 403);
|
||||
}
|
||||
|
||||
builder.where('scenes_revisions.user_id', filters.userId);
|
||||
}
|
||||
|
||||
if (revisionId) {
|
||||
builder.where('scenes_revisions.id', revisionId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (filters.sceneId) {
|
||||
builder.where('scenes_revisions.scene_id', filters.sceneId);
|
||||
}
|
||||
|
||||
console.log(filters);
|
||||
|
||||
if (filters.isFinalized === false) {
|
||||
builder.whereNull('approved');
|
||||
}
|
||||
|
||||
if (filters.isFinalized === true) {
|
||||
builder.whereNotNull('approved');
|
||||
}
|
||||
})
|
||||
.orderBy('created_at', 'desc')
|
||||
.limit(limit)
|
||||
.offset((page - 1) * limit);
|
||||
|
||||
const actorIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.actors, ...(revision.deltas.find((delta) => delta.key === 'actors')?.value || [])])));
|
||||
const tagIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.tags, ...(revision.deltas.find((delta) => delta.key === 'tags')?.value || [])])));
|
||||
const movieIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.movies, ...(revision.deltas.find((delta) => delta.key === 'movies')?.value || [])])));
|
||||
|
||||
const [actors, tags, movies] = await Promise.all([
|
||||
fetchActorsById(actorIds),
|
||||
fetchTagsById(tagIds),
|
||||
fetchMoviesById(movieIds),
|
||||
]);
|
||||
|
||||
const curatedRevisions = revisions.map((revision) => curateRevision(revision));
|
||||
|
||||
return {
|
||||
revisions: curatedRevisions,
|
||||
revision: revisionId && curatedRevisions.find((revision) => revision.id === revisionId),
|
||||
actors,
|
||||
tags,
|
||||
movies,
|
||||
};
|
||||
}
|
||||
|
||||
const keyMap = {
|
||||
productionDate: 'production_date',
|
||||
};
|
||||
|
||||
async function applySceneValueDelta(sceneId, delta, trx) {
|
||||
return knexOwner('releases')
|
||||
.where('id', sceneId)
|
||||
.update(delta.key, delta.value)
|
||||
.update(keyMap[delta.key] || delta.key, delta.value)
|
||||
.transacting(trx);
|
||||
}
|
||||
|
||||
async function applySceneActorsDelta(sceneId, delta, trx) {
|
||||
console.log('actors delta', delta);
|
||||
|
||||
await knexOwner('releases_actors')
|
||||
.where('release_id', sceneId)
|
||||
.delete()
|
||||
.transacting(trx);
|
||||
|
||||
await knexOwner('releases_actors')
|
||||
.insert(delta.value.map((actorId) => ({
|
||||
release_id: sceneId,
|
||||
actor_id: actorId,
|
||||
})))
|
||||
.transacting(trx);
|
||||
if (delta.value.length > 0) {
|
||||
await knexOwner('releases_actors')
|
||||
.insert(delta.value.map((actorId) => ({
|
||||
release_id: sceneId,
|
||||
actor_id: actorId,
|
||||
})))
|
||||
.transacting(trx);
|
||||
}
|
||||
}
|
||||
|
||||
async function applySceneTagsDelta(sceneId, delta, trx) {
|
||||
console.log('tags delta', delta);
|
||||
|
||||
// don't remove unidentified tags
|
||||
await knexOwner('releases_tags')
|
||||
.where('release_id', sceneId)
|
||||
.whereNotNull('tag_id')
|
||||
.delete()
|
||||
.transacting(trx);
|
||||
|
||||
await knexOwner('releases_tags')
|
||||
.insert(delta.value.map((tagId) => ({
|
||||
release_id: sceneId,
|
||||
tag_id: tagId,
|
||||
source: 'editor',
|
||||
})))
|
||||
.transacting(trx);
|
||||
if (delta.value.length > 0) {
|
||||
await knexOwner('releases_tags')
|
||||
.insert(delta.value.map((tagId) => ({
|
||||
release_id: sceneId,
|
||||
tag_id: tagId,
|
||||
source: 'editor',
|
||||
})))
|
||||
.transacting(trx);
|
||||
}
|
||||
}
|
||||
|
||||
async function applySceneRevision(sceneIds) {
|
||||
async function applySceneMoviesDelta(sceneId, delta, trx) {
|
||||
await knexOwner('movies_scenes')
|
||||
.where('scene_id', sceneId)
|
||||
.delete()
|
||||
.transacting(trx);
|
||||
|
||||
if (delta.value.length > 0) {
|
||||
await knexOwner('movies_scenes')
|
||||
.insert(delta.value.map((movieId) => ({
|
||||
scene_id: sceneId,
|
||||
movie_id: movieId,
|
||||
})))
|
||||
.transacting(trx);
|
||||
}
|
||||
}
|
||||
|
||||
async function applySceneRevision(revisionIds) {
|
||||
const revisions = await knexOwner('scenes_revisions')
|
||||
.whereIn('scene_id', sceneIds)
|
||||
.whereNull('applied_at');
|
||||
.whereIn('id', revisionIds)
|
||||
.whereNull('applied_at'); // should not re-apply revision that was already applied
|
||||
|
||||
await revisions.reduce(async (chain, revision) => {
|
||||
await chain;
|
||||
|
||||
console.log('revision', revision);
|
||||
|
||||
await knexOwner.transaction(async (trx) => {
|
||||
await revision.deltas.map(async (delta) => {
|
||||
if ([
|
||||
@@ -660,10 +773,10 @@ async function applySceneRevision(sceneIds) {
|
||||
'description',
|
||||
'date',
|
||||
'duration',
|
||||
'production_date',
|
||||
'production_location',
|
||||
'production_city',
|
||||
'production_state',
|
||||
'productionDate',
|
||||
'productionLocation',
|
||||
'productionCity',
|
||||
'productionState',
|
||||
].includes(delta.key)) {
|
||||
return applySceneValueDelta(revision.scene_id, delta, trx);
|
||||
}
|
||||
@@ -676,6 +789,10 @@ async function applySceneRevision(sceneIds) {
|
||||
return applySceneTagsDelta(revision.scene_id, delta, trx);
|
||||
}
|
||||
|
||||
if (delta.key === 'movies') {
|
||||
return applySceneMoviesDelta(revision.scene_id, delta, trx);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -690,20 +807,44 @@ async function applySceneRevision(sceneIds) {
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
const keyMap = {
|
||||
productionDate: 'production_date',
|
||||
};
|
||||
export async function reviewSceneRevision(revisionId, isApproved, { feedback }, reqUser) {
|
||||
if (!reqUser || reqUser.role === 'user') {
|
||||
throw new HttpError('You are not permitted to approve revisions', 403);
|
||||
}
|
||||
|
||||
export async function createSceneRevision(sceneId, { edits, comment }, reqUser) {
|
||||
if (typeof isApproved !== 'boolean') {
|
||||
throw new HttpError('You must either approve or reject the revision', 400);
|
||||
}
|
||||
|
||||
await knexOwner('scenes_revisions')
|
||||
.where('id', revisionId)
|
||||
.whereRaw('approved is not true') // don't rerun approved and applied revision, must be forked into new revision instead
|
||||
.whereNull('applied_at')
|
||||
.update({
|
||||
approved: isApproved,
|
||||
reviewed_at: knex.fn.now(),
|
||||
reviewed_by: reqUser.id,
|
||||
feedback,
|
||||
});
|
||||
|
||||
if (isApproved) {
|
||||
await applySceneRevision([revisionId]);
|
||||
}
|
||||
}
|
||||
|
||||
export async function createSceneRevision(sceneId, { edits, comment, apply }, reqUser) {
|
||||
const [
|
||||
[scene],
|
||||
openRevisions,
|
||||
] = await Promise.all([
|
||||
fetchScenesById([sceneId], { reqUser, includeAssets: true }),
|
||||
fetchScenesById([sceneId], {
|
||||
reqUser,
|
||||
includeAssets: true,
|
||||
includePartOf: true,
|
||||
}),
|
||||
knexOwner('scenes_revisions')
|
||||
.where('user_id', reqUser.id)
|
||||
.whereNull('approved_by')
|
||||
.whereNot('failed', true),
|
||||
.whereNull('approved'),
|
||||
]);
|
||||
|
||||
if (!scene) {
|
||||
@@ -754,25 +895,28 @@ export async function createSceneRevision(sceneId, { edits, comment }, reqUser)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
key: keyMap[key] || key,
|
||||
value,
|
||||
};
|
||||
return { key, value };
|
||||
}).filter(Boolean);
|
||||
|
||||
if (deltas.length === 0) {
|
||||
throw new HttpError('No effective changes provided', 400);
|
||||
}
|
||||
|
||||
await knexOwner('scenes_revisions').insert({
|
||||
user_id: reqUser.id,
|
||||
scene_id: scene.id,
|
||||
base: JSON.stringify(baseScene),
|
||||
deltas: JSON.stringify(deltas),
|
||||
comment,
|
||||
});
|
||||
const [revisionEntry] = await knexOwner('scenes_revisions')
|
||||
.insert({
|
||||
user_id: reqUser.id,
|
||||
scene_id: scene.id,
|
||||
base: JSON.stringify(baseScene),
|
||||
deltas: JSON.stringify(deltas),
|
||||
hash: mj.hash({
|
||||
base: baseScene,
|
||||
deltas,
|
||||
}),
|
||||
comment,
|
||||
})
|
||||
.returning('id');
|
||||
|
||||
if (['admin', 'editor'].includes(reqUser.role)) {
|
||||
await applySceneRevision([scene.id]);
|
||||
if (['admin', 'editor'].includes(reqUser.role) && apply) {
|
||||
await reviewSceneRevision(revisionEntry.id, true, {}, reqUser);
|
||||
}
|
||||
}
|
||||
|
||||
20
src/users.js
20
src/users.js
@@ -1,3 +1,4 @@
|
||||
import config from 'config';
|
||||
import { parse } from 'yaml';
|
||||
|
||||
import { knexOwner as knex } from './knex.js';
|
||||
@@ -128,3 +129,22 @@ export async function removeTemplate(templateId, reqUser) {
|
||||
.where('user_id', reqUser.id)
|
||||
.delete();
|
||||
}
|
||||
|
||||
export async function createBan(ban, reqUser) {
|
||||
console.log(ban);
|
||||
|
||||
if (reqUser.role !== 'admin') {
|
||||
throw new HttpError('You do not have sufficient privileges to set a ban', 403);
|
||||
}
|
||||
|
||||
const targetUser = ban.userId && await knex('users').where('id', ban.userId).first();
|
||||
|
||||
const curatedBan = {
|
||||
user_id: ban.userId,
|
||||
username: ban.username,
|
||||
ip: ban.banIp && targetUser.last_ip,
|
||||
expires_at: knex.raw('now() + make_interval(mins => :minutes)', { minutes: config.bans.defaultExpiry }),
|
||||
};
|
||||
|
||||
await knex('bans').insert(curatedBan);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,11 @@ function getIp(req) {
|
||||
? ip.slice(ip.lastIndexOf(':') + 1)
|
||||
: ip;
|
||||
|
||||
if (!unmappedIp) {
|
||||
console.log('failed unmapped ip', ip, unmappedIp);
|
||||
return null;
|
||||
}
|
||||
|
||||
// ensure IP is in expanded notation for consistency and matching
|
||||
const expandedIp = unmappedIp.includes(':')
|
||||
? new IPCIDR(`${ip}/128`) // IPv6
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import Router from 'express-promise-router';
|
||||
import { stringify } from '@brillout/json-serializer/stringify'; /* eslint-disable-line import/extensions */
|
||||
|
||||
import {
|
||||
fetchScenes,
|
||||
fetchScenesById,
|
||||
fetchSceneRevisions,
|
||||
createSceneRevision,
|
||||
reviewSceneRevision,
|
||||
} from '../scenes.js';
|
||||
|
||||
import { parseActorIdentifier } from '../query.js';
|
||||
@@ -48,7 +51,7 @@ export async function curateScenesQuery(query) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchScenesApi(req, res) {
|
||||
async function fetchScenesApi(req, res) {
|
||||
const {
|
||||
scenes,
|
||||
aggYears,
|
||||
@@ -203,11 +206,9 @@ export async function fetchScenesGraphql(query, req) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchSceneApi(req, res) {
|
||||
async function fetchSceneApi(req, res) {
|
||||
const [scene] = await fetchScenesById([Number(req.params.sceneId)], { reqUser: req.user });
|
||||
|
||||
console.log(req.params.sceneId, scene);
|
||||
|
||||
if (!scene) {
|
||||
throw new HttpError(`No scene with ID ${req.params.sceneId} found`, 404);
|
||||
}
|
||||
@@ -228,8 +229,30 @@ export async function fetchScenesByIdGraphql(query, req) {
|
||||
return scenes[0];
|
||||
}
|
||||
|
||||
export async function createSceneRevisionApi(req, res) {
|
||||
await createSceneRevision(Number(req.params.sceneId), req.body, req.user);
|
||||
async function fetchSceneRevisionsApi(req, res) {
|
||||
const revisions = await fetchSceneRevisions(Number(req.params.revisionId) || null, req.query, req.user);
|
||||
|
||||
res.send(revisions);
|
||||
}
|
||||
|
||||
async function createSceneRevisionApi(req, res) {
|
||||
await createSceneRevision(Number(req.body.sceneId), req.body, req.user);
|
||||
|
||||
res.status(204).send();
|
||||
}
|
||||
|
||||
async function reviewSceneRevisionApi(req, res) {
|
||||
await reviewSceneRevision(Number(req.params.revisionId), req.body.isApproved, req.body, req.user);
|
||||
|
||||
res.status(204).send();
|
||||
}
|
||||
|
||||
export const scenesRouter = Router();
|
||||
|
||||
scenesRouter.get('/api/scenes', fetchScenesApi);
|
||||
scenesRouter.get('/api/scenes/:sceneId', fetchSceneApi);
|
||||
|
||||
scenesRouter.get('/api/revisions', fetchSceneRevisionsApi);
|
||||
scenesRouter.get('/api/revisions/:revisionId', fetchSceneRevisionsApi);
|
||||
scenesRouter.post('/api/revisions', createSceneRevisionApi);
|
||||
scenesRouter.post('/api/revisions/:revisionId/reviews', reviewSceneRevisionApi);
|
||||
|
||||
@@ -13,11 +13,7 @@ import redis from '../redis.js';
|
||||
import errorHandler from './error.js';
|
||||
import consentHandler from './consent.js';
|
||||
|
||||
import {
|
||||
fetchScenesApi,
|
||||
fetchSceneApi,
|
||||
createSceneRevisionApi,
|
||||
} from './scenes.js';
|
||||
import { scenesRouter } from './scenes.js';
|
||||
|
||||
import { fetchActorsApi } from './actors.js';
|
||||
import { fetchMoviesApi } from './movies.js';
|
||||
@@ -39,25 +35,8 @@ import {
|
||||
flushUserKeysApi,
|
||||
} from './auth.js';
|
||||
|
||||
import {
|
||||
fetchUserApi,
|
||||
fetchUserTemplatesApi,
|
||||
createTemplateApi,
|
||||
removeTemplateApi,
|
||||
} from './users.js';
|
||||
|
||||
import {
|
||||
fetchUserStashesApi,
|
||||
createStashApi,
|
||||
removeStashApi,
|
||||
stashActorApi,
|
||||
stashSceneApi,
|
||||
stashMovieApi,
|
||||
unstashActorApi,
|
||||
unstashSceneApi,
|
||||
unstashMovieApi,
|
||||
updateStashApi,
|
||||
} from './stashes.js';
|
||||
import { router as userRouter } from './users.js';
|
||||
import { router as stashesRouter } from './stashes.js';
|
||||
|
||||
import {
|
||||
fetchAlertsApi,
|
||||
@@ -145,32 +124,12 @@ export default async function initServer() {
|
||||
router.delete('/api/session', logoutApi);
|
||||
|
||||
// USERS
|
||||
router.get('/api/users/:userId', fetchUserApi);
|
||||
router.post('/api/users', signupApi);
|
||||
|
||||
router.get('/api/users/:userId/notifications', fetchNotificationsApi);
|
||||
router.patch('/api/users/:userId/notifications', updateNotificationsApi);
|
||||
router.patch('/api/users/:userId/notifications/:notificationId', updateNotificationApi);
|
||||
|
||||
// STASHES
|
||||
router.get('/api/users/:userId/stashes', fetchUserStashesApi);
|
||||
router.post('/api/stashes', createStashApi);
|
||||
router.patch('/api/stashes/:stashId', updateStashApi);
|
||||
router.delete('/api/stashes/:stashId', removeStashApi);
|
||||
|
||||
router.post('/api/stashes/:stashId/actors', stashActorApi);
|
||||
router.post('/api/stashes/:stashId/scenes', stashSceneApi);
|
||||
router.post('/api/stashes/:stashId/movies', stashMovieApi);
|
||||
|
||||
router.delete('/api/stashes/:stashId/actors/:actorId', unstashActorApi);
|
||||
router.delete('/api/stashes/:stashId/scenes/:sceneId', unstashSceneApi);
|
||||
router.delete('/api/stashes/:stashId/movies/:movieId', unstashMovieApi);
|
||||
|
||||
// SUMMARY TEMPLATES
|
||||
router.get('/api/users/:userId/templates', fetchUserTemplatesApi);
|
||||
router.post('/api/templates', createTemplateApi);
|
||||
router.delete('/api/templates/:templateId', removeTemplateApi);
|
||||
|
||||
// API KEYS
|
||||
router.get('/api/me/keys', fetchUserKeysApi);
|
||||
router.post('/api/keys', createKeyApi);
|
||||
@@ -182,10 +141,9 @@ export default async function initServer() {
|
||||
router.post('/api/alerts', createAlertApi);
|
||||
router.delete('/api/alerts/:alertId', removeAlertApi);
|
||||
|
||||
// SCENES
|
||||
router.get('/api/scenes', fetchScenesApi);
|
||||
router.get('/api/scenes/:sceneId', fetchSceneApi);
|
||||
router.patch('/api/scenes/:sceneId', createSceneRevisionApi);
|
||||
router.use(userRouter);
|
||||
router.use(stashesRouter);
|
||||
router.use(scenesRouter);
|
||||
|
||||
// ACTORS
|
||||
router.get('/api/actors', fetchActorsApi);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Router from 'express-promise-router';
|
||||
|
||||
import {
|
||||
fetchUserStashes,
|
||||
createStash,
|
||||
@@ -70,3 +72,18 @@ export async function unstashMovieApi(req, res) {
|
||||
|
||||
res.send(stashes);
|
||||
}
|
||||
|
||||
export const router = Router();
|
||||
|
||||
router.get('/api/users/:userId/stashes', fetchUserStashesApi);
|
||||
router.post('/api/stashes', createStashApi);
|
||||
router.patch('/api/stashes/:stashId', updateStashApi);
|
||||
router.delete('/api/stashes/:stashId', removeStashApi);
|
||||
|
||||
router.post('/api/stashes/:stashId/actors', stashActorApi);
|
||||
router.post('/api/stashes/:stashId/scenes', stashSceneApi);
|
||||
router.post('/api/stashes/:stashId/movies', stashMovieApi);
|
||||
|
||||
router.delete('/api/stashes/:stashId/actors/:actorId', unstashActorApi);
|
||||
router.delete('/api/stashes/:stashId/scenes/:sceneId', unstashSceneApi);
|
||||
router.delete('/api/stashes/:stashId/movies/:movieId', unstashMovieApi);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Router from 'express-promise-router';
|
||||
import { stringify } from '@brillout/json-serializer/stringify'; /* eslint-disable-line import/extensions */
|
||||
|
||||
import {
|
||||
@@ -5,28 +6,45 @@ import {
|
||||
fetchUserTemplates,
|
||||
createTemplate,
|
||||
removeTemplate,
|
||||
createBan,
|
||||
} from '../users.js';
|
||||
|
||||
export async function fetchUserApi(req, res) {
|
||||
async function fetchUserApi(req, res) {
|
||||
const user = await fetchUser(req.params.userId, {}, req.user);
|
||||
|
||||
res.send(stringify(user));
|
||||
}
|
||||
|
||||
export async function fetchUserTemplatesApi(req, res) {
|
||||
async function fetchUserTemplatesApi(req, res) {
|
||||
const templates = await fetchUserTemplates(req.user);
|
||||
|
||||
res.send(templates);
|
||||
}
|
||||
|
||||
export async function createTemplateApi(req, res) {
|
||||
async function createTemplateApi(req, res) {
|
||||
const template = await createTemplate(req.body, req.user);
|
||||
|
||||
res.send(stringify(template));
|
||||
}
|
||||
|
||||
export async function removeTemplateApi(req, res) {
|
||||
async function removeTemplateApi(req, res) {
|
||||
await removeTemplate(req.params.templateId, req.user);
|
||||
|
||||
res.status(204).send();
|
||||
}
|
||||
|
||||
async function createBanApi(req, res) {
|
||||
await createBan(req.body, req.user);
|
||||
|
||||
res.status(204).send();
|
||||
}
|
||||
|
||||
export const router = Router();
|
||||
|
||||
router.get('/api/users/:userId', fetchUserApi);
|
||||
router.get('/api/users/:userId/templates', fetchUserTemplatesApi);
|
||||
|
||||
router.post('/api/templates', createTemplateApi);
|
||||
router.delete('/api/templates/:templateId', removeTemplateApi);
|
||||
|
||||
router.post('/api/bans', createBanApi);
|
||||
|
||||
Reference in New Issue
Block a user