Added various tag photos and descriptions.
|
@ -55,14 +55,14 @@
|
||||||
v-show="me && isStashed"
|
v-show="me && isStashed"
|
||||||
icon="heart7"
|
icon="heart7"
|
||||||
class="stash stashed noselect"
|
class="stash stashed noselect"
|
||||||
@click="unstashScene"
|
@click="unstashRelease"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
v-show="me && !isStashed"
|
v-show="me && !isStashed"
|
||||||
icon="heart8"
|
icon="heart8"
|
||||||
class="stash unstashed noselect"
|
class="stash unstashed noselect"
|
||||||
@click="stashScene"
|
@click="stashRelease"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -251,18 +251,20 @@ async function fetchRelease(scroll = true) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function stashScene() {
|
async function stashRelease() {
|
||||||
this.$store.dispatch('stashScene', {
|
this.$store.dispatch(this.$route.name === 'movie' ? 'stashMovie' : 'stashRelease', {
|
||||||
sceneId: this.release.id,
|
sceneId: this.release.id,
|
||||||
|
movieId: this.release.id,
|
||||||
stashId: this.$store.getters.favorites.id,
|
stashId: this.$store.getters.favorites.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.fetchRelease(false);
|
this.fetchRelease(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unstashScene() {
|
async function unstashRelease() {
|
||||||
this.$store.dispatch('unstashScene', {
|
this.$store.dispatch(this.$route.name === 'movie' ? 'unstashMovie' : 'unstashRelease', {
|
||||||
sceneId: this.release.id,
|
sceneId: this.release.id,
|
||||||
|
movieId: this.release.id,
|
||||||
stashId: this.$store.getters.favorites.id,
|
stashId: this.$store.getters.favorites.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -321,8 +323,8 @@ export default {
|
||||||
mounted: fetchRelease,
|
mounted: fetchRelease,
|
||||||
methods: {
|
methods: {
|
||||||
fetchRelease,
|
fetchRelease,
|
||||||
stashScene,
|
stashRelease,
|
||||||
unstashScene,
|
unstashRelease,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -138,7 +138,11 @@ function initReleasesActions(store, router) {
|
||||||
// const release = await get(`/releases/${releaseId}`);
|
// const release = await get(`/releases/${releaseId}`);
|
||||||
|
|
||||||
const { movie } = await graphql(`
|
const { movie } = await graphql(`
|
||||||
query Movie($movieId: Int!) {
|
query Movie(
|
||||||
|
$movieId: Int!
|
||||||
|
$hasAuth: Boolean!
|
||||||
|
$userId: Int
|
||||||
|
) {
|
||||||
movie(id: $movieId) {
|
movie(id: $movieId) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
@ -232,10 +236,27 @@ function initReleasesActions(store, router) {
|
||||||
hasLogo
|
hasLogo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stashes: stashesMovies(
|
||||||
|
filter: {
|
||||||
|
stash: {
|
||||||
|
userId: {
|
||||||
|
equalTo: $userId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) @include(if: $hasAuth) {
|
||||||
|
stash {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`, {
|
`, {
|
||||||
movieId: Number(movieId),
|
movieId: Number(movieId),
|
||||||
|
hasAuth: !!store.state.auth.user,
|
||||||
|
userId: store.state.auth.user?.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!movie) {
|
if (!movie) {
|
||||||
|
|
|
@ -17,11 +17,21 @@ function initStashesActions(_store, _router) {
|
||||||
await del(`/stashes/${stashId}/scenes/${sceneId}`);
|
await del(`/stashes/${stashId}/scenes/${sceneId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function stashMovie(context, { movieId, stashId }) {
|
||||||
|
await post(`/stashes/${stashId}/movies`, { movieId });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unstashMovie(context, { movieId, stashId }) {
|
||||||
|
await del(`/stashes/${stashId}/movies/${movieId}`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
stashActor,
|
stashActor,
|
||||||
stashScene,
|
stashScene,
|
||||||
|
stashMovie,
|
||||||
unstashActor,
|
unstashActor,
|
||||||
unstashScene,
|
unstashScene,
|
||||||
|
unstashMovie,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1054,7 +1054,8 @@ exports.up = knex => Promise.resolve()
|
||||||
|
|
||||||
table.integer('user_id')
|
table.integer('user_id')
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('users');
|
.inTable('users')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
table.string('name')
|
table.string('name')
|
||||||
.notNullable();
|
.notNullable();
|
||||||
|
@ -1074,27 +1075,48 @@ exports.up = knex => Promise.resolve()
|
||||||
table.integer('stash_id')
|
table.integer('stash_id')
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('stashes');
|
.inTable('stashes')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
table.integer('scene_id')
|
table.integer('scene_id')
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('releases');
|
.inTable('releases')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
table.unique(['stash_id', 'scene_id']);
|
table.unique(['stash_id', 'scene_id']);
|
||||||
|
|
||||||
table.string('comment');
|
table.string('comment');
|
||||||
}))
|
}))
|
||||||
|
.then(() => knex.schema.createTable('stashes_movies', (table) => {
|
||||||
|
table.integer('stash_id')
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('stashes')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
|
table.integer('movie_id')
|
||||||
|
.notNullable()
|
||||||
|
.references('id')
|
||||||
|
.inTable('movies')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
|
table.unique(['stash_id', 'movie_id']);
|
||||||
|
|
||||||
|
table.string('comment');
|
||||||
|
}))
|
||||||
.then(() => knex.schema.createTable('stashes_actors', (table) => {
|
.then(() => knex.schema.createTable('stashes_actors', (table) => {
|
||||||
table.integer('stash_id')
|
table.integer('stash_id')
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('stashes');
|
.inTable('stashes')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
table.integer('actor_id')
|
table.integer('actor_id')
|
||||||
.notNullable()
|
.notNullable()
|
||||||
.references('id')
|
.references('id')
|
||||||
.inTable('actors');
|
.inTable('actors')
|
||||||
|
.onDelete('cascade');
|
||||||
|
|
||||||
table.unique(['stash_id', 'actor_id']);
|
table.unique(['stash_id', 'actor_id']);
|
||||||
|
|
||||||
|
@ -1304,6 +1326,7 @@ exports.up = knex => Promise.resolve()
|
||||||
|
|
||||||
ALTER TABLE stashes ENABLE ROW LEVEL SECURITY;
|
ALTER TABLE stashes ENABLE ROW LEVEL SECURITY;
|
||||||
ALTER TABLE stashes_scenes ENABLE ROW LEVEL SECURITY;
|
ALTER TABLE stashes_scenes ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE stashes_movies ENABLE ROW LEVEL SECURITY;
|
||||||
ALTER TABLE stashes_actors ENABLE ROW LEVEL SECURITY;
|
ALTER TABLE stashes_actors ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
CREATE POLICY stashes_policy_select ON stashes FOR SELECT USING (stashes.public OR stashes.user_id = current_user_id());
|
CREATE POLICY stashes_policy_select ON stashes FOR SELECT USING (stashes.public OR stashes.user_id = current_user_id());
|
||||||
|
@ -1319,6 +1342,14 @@ exports.up = knex => Promise.resolve()
|
||||||
AND (stashes.user_id = current_user_id() OR stashes.public)
|
AND (stashes.user_id = current_user_id() OR stashes.public)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
CREATE POLICY stashes_policy ON stashes_movies
|
||||||
|
USING (EXISTS (
|
||||||
|
SELECT *
|
||||||
|
FROM stashes
|
||||||
|
WHERE stashes.id = stashes_movies.stash_id
|
||||||
|
AND (stashes.user_id = current_user_id() OR stashes.public)
|
||||||
|
));
|
||||||
|
|
||||||
CREATE POLICY stashes_policy ON stashes_actors
|
CREATE POLICY stashes_policy ON stashes_actors
|
||||||
USING (EXISTS (
|
USING (EXISTS (
|
||||||
SELECT *
|
SELECT *
|
||||||
|
@ -1416,6 +1447,7 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
|
||||||
DROP TABLE IF EXISTS entities CASCADE;
|
DROP TABLE IF EXISTS entities CASCADE;
|
||||||
|
|
||||||
DROP TABLE IF EXISTS stashes_scenes CASCADE;
|
DROP TABLE IF EXISTS stashes_scenes CASCADE;
|
||||||
|
DROP TABLE IF EXISTS stashes_movies CASCADE;
|
||||||
DROP TABLE IF EXISTS stashes_actors CASCADE;
|
DROP TABLE IF EXISTS stashes_actors CASCADE;
|
||||||
DROP TABLE IF EXISTS stashes CASCADE;
|
DROP TABLE IF EXISTS stashes CASCADE;
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 3.0 MiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 3.2 MiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 2.5 MiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 2.5 MiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 2.8 MiB After Width: | Height: | Size: 3.1 MiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 2.7 MiB |
After Width: | Height: | Size: 3.4 MiB |
After Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 495 KiB After Width: | Height: | Size: 495 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 35 KiB |
|
@ -98,7 +98,7 @@ const tags = [
|
||||||
{
|
{
|
||||||
name: 'airtight',
|
name: 'airtight',
|
||||||
slug: 'airtight',
|
slug: 'airtight',
|
||||||
description: 'Stuffing one cock in her ass, one in her pussy, and one in her mouth, filling all of her penetrable holes and sealing her airtight like a figurative balloon. In other words, simultaneously getting [double penetrated](/tag/dp), and giving a [blowjob](/tag/blowjob) or getting [facefucked](/tag/facefuck). Being airtight implies being [gangbanged](/tag/gangbang).', /* eslint-disable-line max-len */
|
description: 'Stuffing one cock in your ass, one in your pussy, and one in your mouth, filling up all of your penetrable holes and getting sealed airtight like a figurative balloon. In other words, simultaneously getting [double penetrated](/tag/dp), and giving a [blowjob](/tag/blowjob) or getting [facefucked](/tag/facefucking). Being airtight implies being [gangbanged](/tag/gangbang).', /* eslint-disable-line max-len */
|
||||||
priority: 9,
|
priority: 9,
|
||||||
group: 'penetration',
|
group: 'penetration',
|
||||||
},
|
},
|
||||||
|
@ -242,13 +242,14 @@ const tags = [
|
||||||
name: 'blowjob',
|
name: 'blowjob',
|
||||||
slug: 'blowjob',
|
slug: 'blowjob',
|
||||||
priority: 5,
|
priority: 5,
|
||||||
|
description: 'Taking a dick in your mouth, sucking, licking and kissing it, often while giving a [handjob](/tag/handjob). You may slide it all the way [down your throat](/tag/deepthroat), or let them [fuck your face](/tag/facefucking).',
|
||||||
group: 'oral',
|
group: 'oral',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'blowbang',
|
name: 'blowbang',
|
||||||
slug: 'blowbang',
|
slug: 'blowbang',
|
||||||
priority: 9,
|
priority: 9,
|
||||||
description: 'Pleasuring a gang of three or more cocks by sucking and jerking off as many cocks as they can, often getting [facefucked](/tag/facefuck), groped and rubbed out, and followed by a [bukkake](/tag/bukkake). If they are getting fucked, it is a [gangbang](/tag/gangbang).',
|
description: 'Pleasuring a gang of three or more cocks by sucking and jerking off as many cocks as you can, often getting [facefucked](/tag/facefucking), groped and rubbed out, and followed by a [bukkake](/tag/bukkake). If you are also getting fucked, it is a [gangbang](/tag/gangbang).',
|
||||||
group: 'group',
|
group: 'group',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -388,13 +389,14 @@ const tags = [
|
||||||
name: 'deepthroat',
|
name: 'deepthroat',
|
||||||
slug: 'deepthroat',
|
slug: 'deepthroat',
|
||||||
priority: 6,
|
priority: 6,
|
||||||
|
description: 'Shoving a cock down your throat during a [blowjob](/tag/blowjob) or [facefuck](/tag/facefucking), giving them a tight sensation while showing off your skills. Without practice, their cock hitting the back of your mouth may make you [gag](/tag/gagging).',
|
||||||
group: 'oral',
|
group: 'oral',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'double penetration',
|
name: 'double penetration',
|
||||||
slug: 'dp',
|
slug: 'dp',
|
||||||
priority: 9,
|
priority: 9,
|
||||||
description: 'Fucking two cocks at once, with one in her ass, and one in her pussy. If she has another cock in her mouth, she is [airtight](/tag/airtight).',
|
description: 'Getting your [ass](/tag/anal) and pussy fucked at the same time. If you take another cock in your mouth, you are [airtight](/tag/airtight).',
|
||||||
group: 'penetration',
|
group: 'penetration',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -450,6 +452,7 @@ const tags = [
|
||||||
name: 'facefucking',
|
name: 'facefucking',
|
||||||
slug: 'facefucking',
|
slug: 'facefucking',
|
||||||
priority: 7,
|
priority: 7,
|
||||||
|
description: 'A [blowjob](/tag/blowjob) where you give up control, and let them fuck your mouth and [throat](/tag/deepthroat) as if it\'s your pussy.',
|
||||||
group: 'oral',
|
group: 'oral',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -487,6 +490,10 @@ const tags = [
|
||||||
name: 'fisting DP',
|
name: 'fisting DP',
|
||||||
slug: 'fisting-dp',
|
slug: 'fisting-dp',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'flexible',
|
||||||
|
slug: 'flexible',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'MFF threesome',
|
name: 'MFF threesome',
|
||||||
slug: 'mff',
|
slug: 'mff',
|
||||||
|
|
|
@ -650,9 +650,10 @@ const tagMedia = [
|
||||||
['blowbang', 1, 'Nicole Black in GIO1680', 'legalporno'],
|
['blowbang', 1, 'Nicole Black in GIO1680', 'legalporno'],
|
||||||
['blowjob', 1, 'Kylie Page in "Stepsis Gives Soapy Handjob In Shower"', 'spyfam'],
|
['blowjob', 1, 'Kylie Page in "Stepsis Gives Soapy Handjob In Shower"', 'spyfam'],
|
||||||
['blowjob', 4, 'Chloe Cherry in "Chloe\'s Big Anal"', 'darkx'],
|
['blowjob', 4, 'Chloe Cherry in "Chloe\'s Big Anal"', 'darkx'],
|
||||||
|
['blowjob', 'cecilia_lion_wefuckblackgirls', 'Cecilia Lion in "Cecilia Lion\'s Second Appearance"', 'wefuckblackgirls'],
|
||||||
|
['blowjob', 0, 'Adriana Chechik in "The Dinner Party"', 'realwifestories'],
|
||||||
['blowjob', 5, 'Kaylynn', 'mommyblowsbest'],
|
['blowjob', 5, 'Kaylynn', 'mommyblowsbest'],
|
||||||
['blowjob', 'azul_hermosa_realitykings', 'Azul Hermosa and Scott Nails in "Diva For A Day"', 'brazzers'],
|
['blowjob', 'azul_hermosa_realitykings', 'Azul Hermosa and Scott Nails in "Diva For A Day"', 'brazzers'],
|
||||||
['blowjob', 0, 'Adriana Chechik in "The Dinner Party"', 'realwifestories'],
|
|
||||||
['blowjob', 3, 'Rose Valie', 'handsonhardcore'],
|
['blowjob', 3, 'Rose Valie', 'handsonhardcore'],
|
||||||
['blowjob', 2, 'Luna Kitsuen in "Gag Reflex"', 'evilangel'],
|
['blowjob', 2, 'Luna Kitsuen in "Gag Reflex"', 'evilangel'],
|
||||||
['bondage', 0, 'Veronica Leal', 'herlimit'],
|
['bondage', 0, 'Veronica Leal', 'herlimit'],
|
||||||
|
@ -675,6 +676,7 @@ const tagMedia = [
|
||||||
['cum-in-mouth', 5, 'Emma Hix in "A Big Dick"', 'darkx'],
|
['cum-in-mouth', 5, 'Emma Hix in "A Big Dick"', 'darkx'],
|
||||||
['cum-in-mouth', 4, 'Vanna Bardot and Isiah Maxwell in "Vanna Craves Isiah\'s Cock!"', 'darkx'],
|
['cum-in-mouth', 4, 'Vanna Bardot and Isiah Maxwell in "Vanna Craves Isiah\'s Cock!"', 'darkx'],
|
||||||
['cum-in-mouth', 2, 'Jaye Summers in "Double The Cum"', 'hardx'],
|
['cum-in-mouth', 2, 'Jaye Summers in "Double The Cum"', 'hardx'],
|
||||||
|
['cum-in-mouth', 'lara_frost_legalporno', 'Lara Frost in NRX059', 'legalporno'],
|
||||||
['cum-in-mouth', 0, 'Vina Sky and Avi Love', 'hardx'],
|
['cum-in-mouth', 0, 'Vina Sky and Avi Love', 'hardx'],
|
||||||
['cum-on-boobs', 1, 'Kylie Page in "Melt In Your Mouth"', 'twistyshard'],
|
['cum-on-boobs', 1, 'Kylie Page in "Melt In Your Mouth"', 'twistyshard'],
|
||||||
['cum-on-boobs', 0, 'Alessandra Jane', 'private'],
|
['cum-on-boobs', 0, 'Alessandra Jane', 'private'],
|
||||||
|
@ -746,6 +748,7 @@ const tagMedia = [
|
||||||
['dp', 3, 'Hime Marie in AA047', 'legalporno'],
|
['dp', 3, 'Hime Marie in AA047', 'legalporno'],
|
||||||
['dp', 2, 'Megan Rain in "DP Masters 4"', 'julesjordan'],
|
['dp', 2, 'Megan Rain in "DP Masters 4"', 'julesjordan'],
|
||||||
['dp', 6, 'Kira Noir', 'hardx'],
|
['dp', 6, 'Kira Noir', 'hardx'],
|
||||||
|
['dp', 'lara_frost_legalporno', 'Lara Frost in NRX070', 'legalporno'],
|
||||||
['dp', 5, 'Lana Rhoades in "Gangbang Me 3"', 'hardx'],
|
['dp', 5, 'Lana Rhoades in "Gangbang Me 3"', 'hardx'],
|
||||||
['dp', 'zaawaadi_roccosiffredi', 'Zaawaadi in "My Name Is Zaawaadi"', 'roccosiffredi'],
|
['dp', 'zaawaadi_roccosiffredi', 'Zaawaadi in "My Name Is Zaawaadi"', 'roccosiffredi'],
|
||||||
['dp', 7, 'Chloe Lamour in "DP Masters 7"', 'julesjordan'],
|
['dp', 7, 'Chloe Lamour in "DP Masters 7"', 'julesjordan'],
|
||||||
|
@ -771,6 +774,7 @@ const tagMedia = [
|
||||||
['facial', 'hope_howell_manojob', 'Hope Howell in "Super Slutty Step-Daugher"', 'manojob'],
|
['facial', 'hope_howell_manojob', 'Hope Howell in "Super Slutty Step-Daugher"', 'manojob'],
|
||||||
['facial', 2, 'Ashly Anderson', 'hookuphotshot'],
|
['facial', 2, 'Ashly Anderson', 'hookuphotshot'],
|
||||||
['facial', 4, 'Kendra Heart', 'facialsforever'],
|
['facial', 4, 'Kendra Heart', 'facialsforever'],
|
||||||
|
['flexible', 'lara_frost_legalporno', 'Lara Frost in NRX059', 'legalporno'],
|
||||||
['enhanced-boobs', 7, 'Charley Atwell', 'icandigirls'],
|
['enhanced-boobs', 7, 'Charley Atwell', 'icandigirls'],
|
||||||
['enhanced-boobs', 14, 'Rikki Six', 'dreamdolls'],
|
['enhanced-boobs', 14, 'Rikki Six', 'dreamdolls'],
|
||||||
['enhanced-boobs', 2, 'Gia Milana in "Hot Anal Latina"', 'hardx'],
|
['enhanced-boobs', 2, 'Gia Milana in "Hot Anal Latina"', 'hardx'],
|
||||||
|
@ -787,7 +791,8 @@ const tagMedia = [
|
||||||
['enhanced-boobs', '23d', 'Lulu Sex Bomb in "Tropical Touch"'],
|
['enhanced-boobs', '23d', 'Lulu Sex Bomb in "Tropical Touch"'],
|
||||||
['enhanced-boobs', 22, 'Sakura Sena'],
|
['enhanced-boobs', 22, 'Sakura Sena'],
|
||||||
['enhanced-boobs', 'mareeva_trudy_photodromm_1', 'Mareeva and Trudy', 'photodromm'],
|
['enhanced-boobs', 'mareeva_trudy_photodromm_1', 'Mareeva and Trudy', 'photodromm'],
|
||||||
['enhanced-boobs', 'shawna_lenee_inthecrack_1', 'Shawna Lenee', 'inthecrack'],
|
['enhanced-boobs', 'lara_frost_legalporno', 'Lara Frost in NRX059', 'legalporno'],
|
||||||
|
['enhanced-boobs', 'shawna_lenee_inthecrack_3', 'Shawna Lenee', 'inthecrack'],
|
||||||
['enhanced-boobs', 16, 'Marsha May in "Once You Go Black 7"', 'julesjordan'],
|
['enhanced-boobs', 16, 'Marsha May in "Once You Go Black 7"', 'julesjordan'],
|
||||||
['enhanced-boobs', 'azul_hermosa_pornstarslikeitbig', 'Azul Hermosa in "She Likes Rough Quickies"', 'pornstarslikeitbig'],
|
['enhanced-boobs', 'azul_hermosa_pornstarslikeitbig', 'Azul Hermosa in "She Likes Rough Quickies"', 'pornstarslikeitbig'],
|
||||||
['enhanced-boobs', 21, 'Emelie Ekström'],
|
['enhanced-boobs', 21, 'Emelie Ekström'],
|
||||||
|
@ -814,10 +819,10 @@ const tagMedia = [
|
||||||
['fisting', 0, 'Abella Danger and Karma Rx in "Neon Dreaming"', 'brazzers'],
|
['fisting', 0, 'Abella Danger and Karma Rx in "Neon Dreaming"', 'brazzers'],
|
||||||
['fisting-dp', 0, 'Janice Griffith and Veronica Avluv in "The Nymphomaniac\'s Apprentice', 'theupperfloor'],
|
['fisting-dp', 0, 'Janice Griffith and Veronica Avluv in "The Nymphomaniac\'s Apprentice', 'theupperfloor'],
|
||||||
['gangbang', 5, 'Carter Cruise\'s first gangbang in "Slut Puppies 9"', 'julesjordan'],
|
['gangbang', 5, 'Carter Cruise\'s first gangbang in "Slut Puppies 9"', 'julesjordan'],
|
||||||
['gangbang', 'poster', 'Kristen Scott in "Interracial Gangbang!"', 'julesjordan'],
|
['gangbang', 'kristen_scott_julesjordan', 'Kristen Scott in "Interracial Gangbang!"', 'julesjordan'],
|
||||||
['gangbang', 7, 'Alexa Flexy in GL376'],
|
['gangbang', 'lara_frost_legalporno_1', 'Lara Frost in NRX070', 'legalporno'],
|
||||||
|
['gangbang', 7, 'Alexa Flexy in GL376', 'legalporno'],
|
||||||
['gangbang', 0, '"4 On 1 Gangbangs"', 'doghousedigital'],
|
['gangbang', 0, '"4 On 1 Gangbangs"', 'doghousedigital'],
|
||||||
['gangbang', 6, 'Silvia Soprano in GIO1580', 'legalporno'],
|
|
||||||
['gangbang', 4, 'Marley Brinx in "The Gangbang of Marley Brinx"', 'julesjordan'],
|
['gangbang', 4, 'Marley Brinx in "The Gangbang of Marley Brinx"', 'julesjordan'],
|
||||||
['gangbang', 1, 'Ginger Lynn in "Gangbang Mystique", a photoset shot by Suze Randall, 1984. Depicting a woman \'airtight\' pushed the boundaries of pornography at the time.'],
|
['gangbang', 1, 'Ginger Lynn in "Gangbang Mystique", a photoset shot by Suze Randall, 1984. Depicting a woman \'airtight\' pushed the boundaries of pornography at the time.'],
|
||||||
['gaping', 1, 'Vina Sky in "Vina Sky Does Anal"', 'hardx'],
|
['gaping', 1, 'Vina Sky in "Vina Sky Does Anal"', 'hardx'],
|
||||||
|
@ -914,8 +919,9 @@ const tagMedia = [
|
||||||
['titty-fucking', 4, 'Set 5532', 'tugjobs'],
|
['titty-fucking', 4, 'Set 5532', 'tugjobs'],
|
||||||
['titty-fucking', 3, 'Anna Bell Peaks in "Ringing Her Bell"', 'milfvr'],
|
['titty-fucking', 3, 'Anna Bell Peaks in "Ringing Her Bell"', 'milfvr'],
|
||||||
['titty-fucking', 1, 'Chloe Lamour', 'ddfbusty'],
|
['titty-fucking', 1, 'Chloe Lamour', 'ddfbusty'],
|
||||||
['toy-anal', 1, 'Nina North and Cassidy Klein in "Nina\'s First Lesbian Anal"', 'lesbianx'],
|
|
||||||
['toy-anal', 3, 'Kelly and Leona in "Sleeping Over"', 'lezcuties'],
|
['toy-anal', 3, 'Kelly and Leona in "Sleeping Over"', 'lezcuties'],
|
||||||
|
['toy-anal', 'ember_snow_jane_wilde_lesbianx', 'Ember Snow and Jane Wilde in "Ember\'s Wilde Ride"', 'lesbianx'],
|
||||||
|
['toy-anal', 1, 'Nina North and Cassidy Klein in "Nina\'s First Lesbian Anal"', 'lesbianx'],
|
||||||
['toy-anal', 2, 'Denise, Irina and Laki in "Sexy Slumber"', 'lezcuties'],
|
['toy-anal', 2, 'Denise, Irina and Laki in "Sexy Slumber"', 'lezcuties'],
|
||||||
['toy-anal', 0, 'Kira Noir in 1225', 'inthecrack'],
|
['toy-anal', 0, 'Kira Noir in 1225', 'inthecrack'],
|
||||||
['toy-dp', 1, 'Krissy Lynn and London River in "Lesbian DP Workout"', 'lesbianx'],
|
['toy-dp', 1, 'Krissy Lynn and London River in "Lesbian DP Workout"', 'lesbianx'],
|
||||||
|
|
|
@ -67,7 +67,7 @@ async function signup(credentials) {
|
||||||
const hashedPassword = (await scrypt(credentials.password, salt, 64)).toString('hex');
|
const hashedPassword = (await scrypt(credentials.password, salt, 64)).toString('hex');
|
||||||
const storedPassword = `${salt}/${hashedPassword}`;
|
const storedPassword = `${salt}/${hashedPassword}`;
|
||||||
|
|
||||||
const [user] = await knex('users')
|
const [userId] = await knex('users')
|
||||||
.insert({
|
.insert({
|
||||||
username: credentials.username,
|
username: credentials.username,
|
||||||
email: credentials.email,
|
email: credentials.email,
|
||||||
|
@ -76,13 +76,13 @@ async function signup(credentials) {
|
||||||
.returning('id');
|
.returning('id');
|
||||||
|
|
||||||
await knex('stashes').insert({
|
await knex('stashes').insert({
|
||||||
user_id: user.id,
|
user_id: userId,
|
||||||
name: 'Favorites',
|
name: 'Favorites',
|
||||||
slug: 'favorites',
|
slug: 'favorites',
|
||||||
public: false,
|
public: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
return fetchUser(user.id);
|
return fetchUser(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -4,6 +4,10 @@ const knex = require('./knex');
|
||||||
const { HttpError } = require('./errors');
|
const { HttpError } = require('./errors');
|
||||||
|
|
||||||
function curateStash(stash) {
|
function curateStash(stash) {
|
||||||
|
if (!stash) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const curatedStash = {
|
const curatedStash = {
|
||||||
id: stash.id,
|
id: stash.id,
|
||||||
name: stash.name,
|
name: stash.name,
|
||||||
|
@ -52,12 +56,22 @@ async function stashScene(sceneId, stashId, sessionUser) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function stashMovie(movieId, stashId, sessionUser) {
|
||||||
|
const stash = await fetchStash(stashId, sessionUser);
|
||||||
|
|
||||||
|
await knex('stashes_movies')
|
||||||
|
.insert({
|
||||||
|
stash_id: stash.id,
|
||||||
|
movie_id: movieId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function unstashActor(actorId, stashId, sessionUser) {
|
async function unstashActor(actorId, stashId, sessionUser) {
|
||||||
await knex
|
await knex
|
||||||
.from('stashes_actors AS deletable')
|
.from('stashes_actors AS deletable')
|
||||||
.where('deletable.actor_id', actorId)
|
.where('deletable.actor_id', actorId)
|
||||||
.where('deletable.stash_id', stashId)
|
.where('deletable.stash_id', stashId)
|
||||||
.whereExists(knex('stashes_actors') // verify user owns this stash
|
.whereExists(knex('stashes_actors') // verify user owns this stash, complimentary to row-level security
|
||||||
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id')
|
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id')
|
||||||
.where('stashes_actors.stash_id', knex.raw('deletable.stash_id'))
|
.where('stashes_actors.stash_id', knex.raw('deletable.stash_id'))
|
||||||
.where('stashes.user_id', sessionUser.id))
|
.where('stashes.user_id', sessionUser.id))
|
||||||
|
@ -69,17 +83,31 @@ async function unstashScene(sceneId, stashId, sessionUser) {
|
||||||
.from('stashes_scenes AS deletable')
|
.from('stashes_scenes AS deletable')
|
||||||
.where('deletable.scene_id', sceneId)
|
.where('deletable.scene_id', sceneId)
|
||||||
.where('deletable.stash_id', stashId)
|
.where('deletable.stash_id', stashId)
|
||||||
.whereExists(knex('stashes_scenes') // verify user owns this stash
|
.whereExists(knex('stashes_scenes') // verify user owns this stash, complimentary to row-level security
|
||||||
.leftJoin('stashes', 'stashes.id', 'stashes_scenes.stash_id')
|
.leftJoin('stashes', 'stashes.id', 'stashes_scenes.stash_id')
|
||||||
.where('stashes_scenes.stash_id', knex.raw('deletable.stash_id'))
|
.where('stashes_scenes.stash_id', knex.raw('deletable.stash_id'))
|
||||||
.where('stashes.user_id', sessionUser.id))
|
.where('stashes.user_id', sessionUser.id))
|
||||||
.delete();
|
.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function unstashMovie(movieId, stashId, sessionUser) {
|
||||||
|
await knex
|
||||||
|
.from('stashes_movies AS deletable')
|
||||||
|
.where('deletable.movie_id', movieId)
|
||||||
|
.where('deletable.stash_id', stashId)
|
||||||
|
.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))
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
curateStash,
|
curateStash,
|
||||||
stashActor,
|
stashActor,
|
||||||
stashScene,
|
stashScene,
|
||||||
|
stashMovie,
|
||||||
unstashScene,
|
unstashScene,
|
||||||
unstashActor,
|
unstashActor,
|
||||||
|
unstashMovie,
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,7 +18,7 @@ function curateUser(user) {
|
||||||
identityVerified: user.identity_verified,
|
identityVerified: user.identity_verified,
|
||||||
ability,
|
ability,
|
||||||
createdAt: user.created_at,
|
createdAt: user.created_at,
|
||||||
stashes: user.stashes?.map(stash => curateStash(stash)) || [],
|
stashes: user.stashes?.filter(Boolean).map(stash => curateStash(stash)) || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
return curatedUser;
|
return curatedUser;
|
||||||
|
@ -26,7 +26,7 @@ function curateUser(user) {
|
||||||
|
|
||||||
async function fetchUser(userId, raw) {
|
async function fetchUser(userId, raw) {
|
||||||
const user = await knex('users')
|
const user = await knex('users')
|
||||||
.select(knex.raw('users.*, users_roles.abilities as role_abilities, json_agg(stashes) as stashes'))
|
.select(knex.raw('users.*, users_roles.abilities as role_abilities, COALESCE(json_agg(stashes) FILTER (WHERE stashes.id IS NOT NULL), \'[]\') as stashes'))
|
||||||
.modify((builder) => {
|
.modify((builder) => {
|
||||||
if (typeof userId === 'number') {
|
if (typeof userId === 'number') {
|
||||||
builder.where('users.id', userId);
|
builder.where('users.id', userId);
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const argv = require('../argv');
|
||||||
const logger = require('../logger')(__filename);
|
const logger = require('../logger')(__filename);
|
||||||
|
|
||||||
function errorHandler(error, req, res, _next) {
|
function errorHandler(error, req, res, _next) {
|
||||||
logger.warn(`Failed to fulfill request to ${req.path}: ${error.message}`);
|
logger.warn(`Failed to fulfill request to ${req.path}: ${error.message}`);
|
||||||
|
|
||||||
|
if (argv.debug) {
|
||||||
|
logger.error(error);
|
||||||
|
}
|
||||||
|
|
||||||
if (error.httpCode) {
|
if (error.httpCode) {
|
||||||
res.status(error.httpCode).send(error.message);
|
res.status(error.httpCode).send(error.message);
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,10 @@ const {
|
||||||
const {
|
const {
|
||||||
stashActor,
|
stashActor,
|
||||||
stashScene,
|
stashScene,
|
||||||
|
stashMovie,
|
||||||
unstashActor,
|
unstashActor,
|
||||||
unstashScene,
|
unstashScene,
|
||||||
|
unstashMovie,
|
||||||
} = require('./stashes');
|
} = require('./stashes');
|
||||||
|
|
||||||
async function initServer() {
|
async function initServer() {
|
||||||
|
@ -83,9 +85,11 @@ async function initServer() {
|
||||||
|
|
||||||
router.post('/api/stashes/:stashId/actors', stashActor);
|
router.post('/api/stashes/:stashId/actors', stashActor);
|
||||||
router.post('/api/stashes/:stashId/scenes', stashScene);
|
router.post('/api/stashes/:stashId/scenes', stashScene);
|
||||||
|
router.post('/api/stashes/:stashId/movies', stashMovie);
|
||||||
|
|
||||||
router.delete('/api/stashes/:stashId/actors/:actorId', unstashActor);
|
router.delete('/api/stashes/:stashId/actors/:actorId', unstashActor);
|
||||||
router.delete('/api/stashes/:stashId/scenes/:sceneId', unstashScene);
|
router.delete('/api/stashes/:stashId/scenes/:sceneId', unstashScene);
|
||||||
|
router.delete('/api/stashes/:stashId/movies/:movieId', unstashMovie);
|
||||||
|
|
||||||
router.get('/api/scenes', fetchScenes);
|
router.get('/api/scenes', fetchScenes);
|
||||||
router.get('/api/scenes/:releaseId', fetchScene);
|
router.get('/api/scenes/:releaseId', fetchScene);
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { stashActor, stashScene, unstashActor, unstashScene } = require('../stashes');
|
const {
|
||||||
|
stashActor,
|
||||||
|
stashScene,
|
||||||
|
stashMovie,
|
||||||
|
unstashActor,
|
||||||
|
unstashScene,
|
||||||
|
unstashMovie,
|
||||||
|
} = require('../stashes');
|
||||||
|
|
||||||
async function stashActorApi(req, res) {
|
async function stashActorApi(req, res) {
|
||||||
await stashActor(req.body.actorId, req.params.stashId, req.session.user);
|
await stashActor(req.body.actorId, req.params.stashId, req.session.user);
|
||||||
|
@ -14,6 +21,12 @@ async function stashSceneApi(req, res) {
|
||||||
res.status(201).send();
|
res.status(201).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function stashMovieApi(req, res) {
|
||||||
|
await stashMovie(req.body.movieId, req.params.stashId, req.session.user);
|
||||||
|
|
||||||
|
res.status(201).send();
|
||||||
|
}
|
||||||
|
|
||||||
async function unstashActorApi(req, res) {
|
async function unstashActorApi(req, res) {
|
||||||
await unstashActor(req.params.actorId, req.params.stashId, req.session.user);
|
await unstashActor(req.params.actorId, req.params.stashId, req.session.user);
|
||||||
|
|
||||||
|
@ -26,9 +39,17 @@ async function unstashSceneApi(req, res) {
|
||||||
res.status(204).send();
|
res.status(204).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function unstashMovieApi(req, res) {
|
||||||
|
await unstashMovie(req.params.movieId, req.params.stashId, req.session.user);
|
||||||
|
|
||||||
|
res.status(204).send();
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
stashActor: stashActorApi,
|
stashActor: stashActorApi,
|
||||||
stashScene: stashSceneApi,
|
stashScene: stashSceneApi,
|
||||||
|
stashMovie: stashMovieApi,
|
||||||
unstashActor: unstashActorApi,
|
unstashActor: unstashActorApi,
|
||||||
unstashScene: unstashSceneApi,
|
unstashScene: unstashSceneApi,
|
||||||
|
unstashMovie: unstashMovieApi,
|
||||||
};
|
};
|
||||||
|
|