Added stash GraphQL mutations. Added movies to GraphQL queries. Moved key management to profile page, only for approved users.
This commit is contained in:
295
src/stashes.js
295
src/stashes.js
@@ -40,6 +40,21 @@ export function curateStash(stash, assets = {}) {
|
||||
return curatedStash;
|
||||
}
|
||||
|
||||
function curateStashed(stashed) {
|
||||
if (!stashed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const curatedStashed = {
|
||||
id: stashed.id,
|
||||
stashId: stashed.stash_id,
|
||||
actorId: stashed.actor_id,
|
||||
createdAt: stashed.created_at,
|
||||
};
|
||||
|
||||
return curatedStashed;
|
||||
}
|
||||
|
||||
function curateStashEntry(stash, user) {
|
||||
const curatedStashEntry = {
|
||||
user_id: user?.id || undefined,
|
||||
@@ -57,9 +72,17 @@ function verifyStashAccess(stash, sessionUser) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchStashById(stashId, sessionUser) {
|
||||
export async function fetchStashById(stashIdOrSlug, sessionUser) {
|
||||
const stash = await knex('stashes')
|
||||
.where('id', stashId)
|
||||
.where((builder) => {
|
||||
if (typeof stashIdOrSlug === 'number') {
|
||||
builder.where('id', stashIdOrSlug);
|
||||
} else {
|
||||
builder
|
||||
.where('slug', stashIdOrSlug)
|
||||
.where('user_id', sessionUser.id);
|
||||
}
|
||||
})
|
||||
.first();
|
||||
|
||||
verifyStashAccess(stash, sessionUser);
|
||||
@@ -67,8 +90,16 @@ export async function fetchStashById(stashId, sessionUser) {
|
||||
return curateStash(stash);
|
||||
}
|
||||
|
||||
export async function fetchStashByUsernameAndSlug(username, stashSlug, sessionUser) {
|
||||
const user = await knex('users').where('username', username).first();
|
||||
export async function fetchStashByUsernameAndSlug(usernameOrId, stashSlug, sessionUser) {
|
||||
const user = await knex('users')
|
||||
.where((builder) => {
|
||||
if (typeof usernameOrId === 'number') {
|
||||
builder.where('id', usernameOrId);
|
||||
} else {
|
||||
builder.where('username', usernameOrId);
|
||||
}
|
||||
})
|
||||
.first();
|
||||
|
||||
if (!user) {
|
||||
throw new HttpError('This user does not exist.', 404);
|
||||
@@ -86,10 +117,22 @@ export async function fetchStashByUsernameAndSlug(username, stashSlug, sessionUs
|
||||
return curateStash(stash, { user });
|
||||
}
|
||||
|
||||
export async function fetchUserStashes(userId, reqUser) {
|
||||
export async function fetchUserStashes(usernameOrId, reqUser) {
|
||||
const userId = typeof usernameOrId === 'number'
|
||||
? usernameOrId
|
||||
: await knex('users')
|
||||
.where('username', usernameOrId)
|
||||
.first()
|
||||
.then((user) => user?.id);
|
||||
|
||||
if (!userId) {
|
||||
throw new HttpError(`Could not find user '${usernameOrId}'`);
|
||||
}
|
||||
|
||||
const stashes = await knex('stashes')
|
||||
.select('stashes.*', 'stashes_meta.*')
|
||||
.leftJoin('stashes_meta', 'stashes_meta.stash_id', 'stashes.id')
|
||||
.leftJoin('users', 'users.id', 'stashes.user_id')
|
||||
.where('user_id', userId)
|
||||
.modify((builder) => {
|
||||
if (userId !== reqUser?.id) {
|
||||
@@ -172,7 +215,7 @@ export async function createStash(newStash, sessionUser) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateStash(stashId, updatedStash, sessionUser) {
|
||||
export async function updateStash(stashIdOrSlug, updatedStash, sessionUser) {
|
||||
if (!sessionUser) {
|
||||
throw new HttpError('You are not authenthicated', 401);
|
||||
}
|
||||
@@ -182,11 +225,15 @@ export async function updateStash(stashId, updatedStash, sessionUser) {
|
||||
}
|
||||
|
||||
try {
|
||||
const stash = await knex('stashes')
|
||||
.where({
|
||||
id: stashId,
|
||||
user_id: sessionUser.id,
|
||||
const [stash] = await knex('stashes')
|
||||
.where((builder) => {
|
||||
if (typeof stashIdOrSlug === 'number') {
|
||||
builder.where('id', stashIdOrSlug);
|
||||
} else {
|
||||
builder.where('slug', stashIdOrSlug);
|
||||
}
|
||||
})
|
||||
.where('user_id', sessionUser.id)
|
||||
.update(curateStashEntry(updatedStash))
|
||||
.returning('*');
|
||||
|
||||
@@ -209,57 +256,86 @@ export async function removeStash(stashId, sessionUser) {
|
||||
throw new HttpError('You are not authenthicated', 401);
|
||||
}
|
||||
|
||||
const removed = await knex('stashes')
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
const [removed] = await knex('stashes')
|
||||
.where({
|
||||
id: stashId,
|
||||
id: stash.id,
|
||||
user_id: sessionUser.id,
|
||||
primary: false,
|
||||
})
|
||||
.delete();
|
||||
.delete()
|
||||
.returning('*');
|
||||
|
||||
if (removed === 0) {
|
||||
throw new HttpError('Unable to remove this stash', 400);
|
||||
}
|
||||
|
||||
return curateStash(stash);
|
||||
}
|
||||
|
||||
export async function stashActor(actorId, stashId, sessionUser) {
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
const [stashed] = await knex('stashes_actors')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
actor_id: actorId,
|
||||
})
|
||||
.returning(['id', 'created_at']);
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
await indexApi.replace({
|
||||
index: 'actors_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
actor_id: actorId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stashId,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
try {
|
||||
const [stashed] = await knex('stashes_actors')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
actor_id: actorId,
|
||||
})
|
||||
.returning('*');
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed actor ${actorId} to stash ${stash.id} (${stash.name})`);
|
||||
await indexApi.replace({
|
||||
index: 'actors_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
actor_id: actorId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stash.id,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
|
||||
refreshView('actors');
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed actor ${actorId} to stash ${stash.id} (${stash.name})`);
|
||||
|
||||
return fetchDomainStashes('actor', actorId, sessionUser);
|
||||
refreshView('actors');
|
||||
|
||||
// return fetchDomainStashes('actor', actorId, sessionUser);
|
||||
return curateStashed(stashed);
|
||||
} catch (error) {
|
||||
if (error.routine === '_bt_check_unique') {
|
||||
throw new HttpError(`Actor ${actorId} is already stashed in '${stash.name}'`, 409);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function unstashActor(actorId, stashId, sessionUser) {
|
||||
await knex
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
const [unstashed] = await knex
|
||||
.from('stashes_actors AS deletable')
|
||||
.where('deletable.actor_id', actorId)
|
||||
.where('deletable.stash_id', stashId)
|
||||
.where('deletable.stash_id', stash.id)
|
||||
.whereExists(knex('stashes_actors') // verify user owns this stash, complimentary to row-level security
|
||||
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id')
|
||||
.where('stashes_actors.stash_id', knex.raw('deletable.stash_id'))
|
||||
.where('stashes.user_id', sessionUser.id))
|
||||
.delete();
|
||||
.delete()
|
||||
.returning('*');
|
||||
|
||||
try {
|
||||
await indexApi.callDelete({
|
||||
@@ -268,7 +344,7 @@ export async function unstashActor(actorId, stashId, sessionUser) {
|
||||
bool: {
|
||||
must: [
|
||||
{ equals: { actor_id: actorId } },
|
||||
{ equals: { stash_id: stashId } },
|
||||
{ equals: { stash_id: stash.id } },
|
||||
{ equals: { user_id: sessionUser.id } },
|
||||
],
|
||||
},
|
||||
@@ -278,52 +354,73 @@ export async function unstashActor(actorId, stashId, sessionUser) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed actor ${actorId} from stash ${stashId}`);
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed actor ${actorId} from stash ${stashId} (${stash.name})`);
|
||||
|
||||
refreshView('actors');
|
||||
|
||||
return fetchDomainStashes('actor', actorId, sessionUser);
|
||||
// return fetchDomainStashes('actor', actorId, sessionUser);
|
||||
return curateStashed(unstashed);
|
||||
}
|
||||
|
||||
export async function stashScene(sceneId, stashId, sessionUser) {
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
const [stashed] = await knex('stashes_scenes')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
scene_id: sceneId,
|
||||
})
|
||||
.returning(['id', 'created_at']);
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
await indexApi.replace({
|
||||
index: 'scenes_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
// ...doc.replace.doc,
|
||||
scene_id: sceneId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stashId,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
try {
|
||||
const [stashed] = await knex('stashes_scenes')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
scene_id: sceneId,
|
||||
})
|
||||
.returning('*');
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed scene ${sceneId} to stash ${stash.id} (${stash.name})`);
|
||||
await indexApi.replace({
|
||||
index: 'scenes_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
// ...doc.replace.doc,
|
||||
scene_id: sceneId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stash.id,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
|
||||
refreshView('scenes');
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed scene ${sceneId} to stash ${stash.id} (${stash.name})`);
|
||||
|
||||
return fetchDomainStashes('scene', sceneId, sessionUser);
|
||||
refreshView('scenes');
|
||||
|
||||
// return fetchDomainStashes('scene', sceneId, sessionUser);
|
||||
return curateStashed(stashed);
|
||||
} catch (error) {
|
||||
if (error.routine === '_bt_check_unique') {
|
||||
throw new HttpError(`Scene ${sceneId} is already stashed in '${stash.name}'`, 409);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function unstashScene(sceneId, stashId, sessionUser) {
|
||||
await knex
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
const [unstashed] = await knex
|
||||
.from('stashes_scenes AS deletable')
|
||||
.where('deletable.scene_id', sceneId)
|
||||
.where('deletable.stash_id', stashId)
|
||||
.where('deletable.stash_id', stash.id)
|
||||
.whereExists(knex('stashes_scenes') // verify user owns this stash, complimentary to row-level security
|
||||
.leftJoin('stashes', 'stashes.id', 'stashes_scenes.stash_id')
|
||||
.where('stashes_scenes.stash_id', knex.raw('deletable.stash_id'))
|
||||
.where('stashes.user_id', sessionUser.id))
|
||||
.delete();
|
||||
.delete()
|
||||
.returning('*');
|
||||
|
||||
await indexApi.callDelete({
|
||||
index: 'scenes_stashed',
|
||||
@@ -331,57 +428,78 @@ export async function unstashScene(sceneId, stashId, sessionUser) {
|
||||
bool: {
|
||||
must: [
|
||||
{ equals: { scene_id: sceneId } },
|
||||
{ equals: { stash_id: stashId } },
|
||||
{ equals: { stash_id: stash.id } },
|
||||
{ equals: { user_id: sessionUser.id } },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed scene ${sceneId} from stash ${stashId}`);
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed scene ${sceneId} from stash ${stash.id} (${stash.name})`);
|
||||
|
||||
refreshView('scenes');
|
||||
|
||||
return fetchDomainStashes('scene', sceneId, sessionUser);
|
||||
// return fetchDomainStashes('scene', sceneId, sessionUser);
|
||||
return curateStashed(unstashed);
|
||||
}
|
||||
|
||||
export async function stashMovie(movieId, stashId, sessionUser) {
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
const [stashed] = await knex('stashes_movies')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
movie_id: movieId,
|
||||
})
|
||||
.returning(['id', 'created_at']);
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
await indexApi.replace({
|
||||
index: 'movies_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
movie_id: movieId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stashId,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
try {
|
||||
const [stashed] = await knex('stashes_movies')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
movie_id: movieId,
|
||||
})
|
||||
.returning('*');
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed movie ${movieId} to stash ${stash.id} (${stash.name})`);
|
||||
await indexApi.replace({
|
||||
index: 'movies_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
movie_id: movieId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stash.id,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
|
||||
refreshView('movies');
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed movie ${movieId} to stash ${stash.id} (${stash.name})`);
|
||||
|
||||
return fetchDomainStashes('movie', movieId, sessionUser);
|
||||
refreshView('movies');
|
||||
|
||||
// return fetchDomainStashes('movie', movieId, sessionUser);
|
||||
return curateStashed(stashed);
|
||||
} catch (error) {
|
||||
if (error.routine === '_bt_check_unique') {
|
||||
throw new HttpError(`Movie ${movieId} is already stashed in '${stash.name}'`, 409);
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function unstashMovie(movieId, stashId, sessionUser) {
|
||||
await knex
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
if (!stash) {
|
||||
throw new HttpError(`Could not find stash '${stashId}'`, 404);
|
||||
}
|
||||
|
||||
const [unstashed] = await knex
|
||||
.from('stashes_movies AS deletable')
|
||||
.where('deletable.movie_id', movieId)
|
||||
.where('deletable.stash_id', stashId)
|
||||
.where('deletable.stash_id', stash.id)
|
||||
.whereExists(knex('stashes_movies') // verify user owns this stash, complimentary to row-level security
|
||||
.leftJoin('stashes', 'stashes.id', 'stashes_movies.stash_id')
|
||||
.where('stashes_movies.stash_id', knex.raw('deletable.stash_id'))
|
||||
.where('stashes.user_id', sessionUser.id))
|
||||
.returning('*')
|
||||
.delete();
|
||||
|
||||
await indexApi.callDelete({
|
||||
@@ -390,18 +508,19 @@ export async function unstashMovie(movieId, stashId, sessionUser) {
|
||||
bool: {
|
||||
must: [
|
||||
{ equals: { movie_id: movieId } },
|
||||
{ equals: { stash_id: stashId } },
|
||||
{ equals: { stash_id: stash.id } },
|
||||
{ equals: { user_id: sessionUser.id } },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed movie ${movieId} from stash ${stashId}`);
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed movie ${movieId} from stash ${stash.id} (${stash.name})`);
|
||||
|
||||
refreshView('movies');
|
||||
|
||||
return fetchDomainStashes('movie', movieId, sessionUser);
|
||||
// return fetchDomainStashes('movie', movieId, sessionUser);
|
||||
return curateStashed(unstashed);
|
||||
}
|
||||
|
||||
CronJob.from({
|
||||
|
||||
Reference in New Issue
Block a user