Endpoints only retrieve / modify objects related to the active user.

pull/31/head
Sander Vocke 5 years ago
parent 04a025f850
commit 45a31d1c05
  1. 21
      client/src/components/windows/login/LoginWindow.tsx
  2. 2
      server/app.ts
  3. 4
      server/endpoints/AlbumDetails.ts
  4. 3
      server/endpoints/ArtistDetails.ts
  5. 6
      server/endpoints/CreateAlbum.ts
  6. 7
      server/endpoints/CreateArtist.ts
  7. 7
      server/endpoints/CreateSong.ts
  8. 7
      server/endpoints/CreateTag.ts
  9. 14
      server/endpoints/DeleteTag.ts
  10. 7
      server/endpoints/MergeTag.ts
  11. 5
      server/endpoints/ModifyAlbum.ts
  12. 6
      server/endpoints/ModifyArtist.ts
  13. 5
      server/endpoints/ModifySong.ts
  14. 6
      server/endpoints/ModifyTag.ts
  15. 25
      server/endpoints/Query.ts
  16. 3
      server/endpoints/SongDetails.ts
  17. 3
      server/endpoints/TagDetails.ts
  18. 54
      server/migrations/20201110170100_add_users.ts

@ -3,14 +3,23 @@ import { WindowState } from "../Windows";
import { Box, Paper, Typography, TextField, Button } from "@material-ui/core";
import { useHistory, useLocation } from 'react-router';
import { useAuth, Auth } from '../../../lib/useAuth';
import Alert from '@material-ui/lab/Alert';
export enum LoginStatus {
NoneSubmitted = 0,
Unsuccessful,
// Note: no "successful" status because that would lead to a redirect.
}
export interface LoginWindowState extends WindowState {
email: string,
password: string,
status: LoginStatus,
}
export enum LoginWindowStateActions {
SetEmail = "SetEmail",
SetPassword = "SetPassword",
SetStatus = "SetStatus",
}
export function LoginWindowReducer(state: LoginWindowState, action: any) {
switch (action.type) {
@ -18,6 +27,8 @@ export function LoginWindowReducer(state: LoginWindowState, action: any) {
return { ...state, email: action.value }
case LoginWindowStateActions.SetPassword:
return { ...state, password: action.value }
case LoginWindowStateActions.SetStatus:
return { ...state, status: action.value }
default:
throw new Error("Unimplemented LoginWindow state update.")
}
@ -27,6 +38,7 @@ export default function LoginWindow(props: {}) {
const [state, dispatch] = useReducer(LoginWindowReducer, {
email: "",
password: "",
status: LoginStatus.NoneSubmitted,
});
return <LoginWindowControlled state={state} dispatch={dispatch} />
@ -46,6 +58,11 @@ export function LoginWindowControlled(props: {
auth.signin(props.state.email, props.state.password)
.then(() => {
history.replace(from);
}).catch((e: any) => {
props.dispatch({
type: LoginWindowStateActions.SetStatus,
value: LoginStatus.Unsuccessful,
})
})
}
@ -86,6 +103,10 @@ export function LoginWindowControlled(props: {
value: e.target.value
})}
/>
{props.state.status === LoginStatus.Unsuccessful && <Alert severity="error">
Login failed - Please check your credentials.
</Alert>
}
<Button
type="submit"
fullWidth

@ -76,7 +76,7 @@ const SetupApp = (app: any, knex: Knex, apiBaseUrl: string) => {
})();
});
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
app.use(require('express-session')({ secret: 'EA9q5cukt7UFhN', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());

@ -12,6 +12,8 @@ export const AlbumDetailsEndpointHandler: EndpointHandler = async (req: any, res
throw e;
}
const { id: userId } = req.user;
try {
// Start transfers for songs, tags and artists.
// Also request the album itself.
@ -35,6 +37,7 @@ export const AlbumDetailsEndpointHandler: EndpointHandler = async (req: any, res
});
const albumPromise = knex.select('name', 'storeLinks')
.from('albums')
.where({ 'user': userId })
.where({ id: req.params.id })
.then((albums: any) => albums[0]);
@ -43,7 +46,6 @@ export const AlbumDetailsEndpointHandler: EndpointHandler = async (req: any, res
await Promise.all([albumPromise, tagIdsPromise, songIdsPromise, artistIdsPromise]);
// Respond to the request.
console.log("ALBUM: ", album);
const response: api.AlbumDetailsResponse = {
name: album['name'],
artistIds: artists,

@ -12,6 +12,8 @@ export const ArtistDetailsEndpointHandler: EndpointHandler = async (req: any, re
throw e;
}
const { id: userId } = req.user;
try {
const tagIds = Array.from(new Set((await knex.select('tagId')
.from('artists_tags')
@ -20,6 +22,7 @@ export const ArtistDetailsEndpointHandler: EndpointHandler = async (req: any, re
const results = await knex.select(['id', 'name', 'storeLinks'])
.from('artists')
.where({ 'user': userId })
.where({ 'id': req.params.id });
const response: api.ArtistDetailsResponse = {

@ -11,8 +11,9 @@ export const CreateAlbumEndpointHandler: EndpointHandler = async (req: any, res:
throw e;
}
const reqObject: api.CreateAlbumRequest = req.body;
const { id: userId } = req.user;
console.log("Create Album:", reqObject);
console.log("User ", userId, ": Create Album ", reqObject);
await knex.transaction(async (trx) => {
try {
@ -20,6 +21,7 @@ export const CreateAlbumEndpointHandler: EndpointHandler = async (req: any, res:
const artistIdsPromise = reqObject.artistIds ?
trx.select('id')
.from('artists')
.where({ 'user': userId })
.whereIn('id', reqObject.artistIds)
.then((as: any) => as.map((a: any) => a['id'])) :
(async () => { return [] })();
@ -28,6 +30,7 @@ export const CreateAlbumEndpointHandler: EndpointHandler = async (req: any, res:
const tagIdsPromise = reqObject.tagIds ?
trx.select('id')
.from('tags')
.where({ 'user': userId })
.whereIn('id', reqObject.tagIds)
.then((as: any) => as.map((a: any) => a['id'])) :
(async () => { return [] })();
@ -50,6 +53,7 @@ export const CreateAlbumEndpointHandler: EndpointHandler = async (req: any, res:
.insert({
name: reqObject.name,
storeLinks: JSON.stringify(reqObject.storeLinks || []),
user: userId,
})
.returning('id') // Needed for Postgres
)[0];

@ -11,8 +11,9 @@ export const CreateArtistEndpointHandler: EndpointHandler = async (req: any, res
throw e;
}
const reqObject: api.CreateArtistRequest = req.body;
const { id: userId } = req.user;
console.log("Create artist:", reqObject)
console.log("User ", userId, ": Create artist ", reqObject)
await knex.transaction(async (trx) => {
try {
@ -20,13 +21,12 @@ export const CreateArtistEndpointHandler: EndpointHandler = async (req: any, res
const tags: number[] = reqObject.tagIds ?
Array.from(new Set(
(await trx.select('id').from('tags')
.where({ 'user': userId })
.whereIn('id', reqObject.tagIds))
.map((tag: any) => tag['id'])
))
: [];
console.log("Found artist tags:", tags)
if (reqObject.tagIds && tags && tags.length !== reqObject.tagIds.length) {
const e: EndpointError = {
internalMessage: 'Not all tags exist for CreateArtist request: ' + JSON.stringify(req.body),
@ -40,6 +40,7 @@ export const CreateArtistEndpointHandler: EndpointHandler = async (req: any, res
.insert({
name: reqObject.name,
storeLinks: JSON.stringify(reqObject.storeLinks || []),
user: userId,
})
.returning('id') // Needed for Postgres
)[0];

@ -11,8 +11,9 @@ export const CreateSongEndpointHandler: EndpointHandler = async (req: any, res:
throw e;
}
const reqObject: api.CreateSongRequest = req.body;
const { id: userId } = req.user;
console.log("Create Song:", reqObject);
console.log("User ", userId, ": Create Song ", reqObject);
await knex.transaction(async (trx) => {
try {
@ -20,6 +21,7 @@ export const CreateSongEndpointHandler: EndpointHandler = async (req: any, res:
const artistIdsPromise = reqObject.artistIds ?
trx.select('id')
.from('artists')
.where({ 'user': userId })
.whereIn('id', reqObject.artistIds)
.then((as: any) => as.map((a: any) => a['id'])) :
(async () => { return [] })();
@ -28,6 +30,7 @@ export const CreateSongEndpointHandler: EndpointHandler = async (req: any, res:
const tagIdsPromise = reqObject.tagIds ?
trx.select('id')
.from('tags')
.where({ 'user': userId })
.whereIn('id', reqObject.tagIds)
.then((as: any) => as.map((a: any) => a['id'])) :
(async () => { return [] })();
@ -36,6 +39,7 @@ export const CreateSongEndpointHandler: EndpointHandler = async (req: any, res:
const albumIdsPromise = reqObject.albumIds ?
trx.select('id')
.from('albums')
.where({ 'user': userId })
.whereIn('id', reqObject.albumIds)
.then((as: any) => as.map((a: any) => a['id'])) :
(async () => { return [] })();
@ -59,6 +63,7 @@ export const CreateSongEndpointHandler: EndpointHandler = async (req: any, res:
.insert({
title: reqObject.title,
storeLinks: JSON.stringify(reqObject.storeLinks || []),
user: userId,
})
.returning('id') // Needed for Postgres
)[0];

@ -11,8 +11,9 @@ export const CreateTagEndpointHandler: EndpointHandler = async (req: any, res: a
throw e;
}
const reqObject: api.CreateTagRequest = req.body;
const { id: userId } = req.user;
console.log("Create Tag: ", reqObject);
console.log("User ", userId, ": Create Tag ", reqObject);
await knex.transaction(async (trx) => {
try {
@ -21,6 +22,7 @@ export const CreateTagEndpointHandler: EndpointHandler = async (req: any, res: a
reqObject.parentId ?
(await trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ 'id': reqObject.parentId }))[0]['id'] :
undefined;
@ -35,7 +37,8 @@ export const CreateTagEndpointHandler: EndpointHandler = async (req: any, res: a
// Create the new tag.
var tag: any = {
name: reqObject.name
name: reqObject.name,
user: userId,
};
if (maybeParent) {
tag['parentId'] = maybeParent;

@ -2,13 +2,14 @@ import * as api from '../../client/src/api';
import { EndpointError, EndpointHandler, catchUnhandledErrors } from './types';
import Knex from 'knex';
async function getChildrenRecursive(id: number, trx: any) {
async function getChildrenRecursive(id: number, userId: number, trx: any) {
const directChildren = (await trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ 'parentId': id })).map((r: any) => r.id);
const indirectChildrenPromises = directChildren.map(
(child: number) => getChildrenRecursive(child, trx)
(child: number) => getChildrenRecursive(child, userId, trx)
);
const indirectChildrenNested = await Promise.all(indirectChildrenPromises);
const indirectChildren = indirectChildrenNested.flat();
@ -28,19 +29,20 @@ export const DeleteTagEndpointHandler: EndpointHandler = async (req: any, res: a
throw e;
}
const reqObject: api.DeleteTagRequest = req.body;
const { id: userId } = req.user;
console.log("Delete Tag:", reqObject);
console.log("User ", userId, ": Delete Tag ", reqObject);
await knex.transaction(async (trx) => {
try {
// Start retrieving any child tags.
const childTagsPromise =
getChildrenRecursive(req.params.id, trx);
getChildrenRecursive(req.params.id, userId, trx);
// Start retrieving the tag itself.
const tagPromise = trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ id: req.params.id })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined)
@ -49,7 +51,6 @@ export const DeleteTagEndpointHandler: EndpointHandler = async (req: any, res: a
// Merge all IDs.
const toDelete = [ tag, ...children ];
console.log ("deleting tags: ", toDelete);
// Check that we found all objects we need.
if (!tag) {
@ -62,6 +63,7 @@ export const DeleteTagEndpointHandler: EndpointHandler = async (req: any, res: a
// Delete the tag and its children.
await trx('tags')
.where({ 'user': userId })
.whereIn('id', toDelete)
.del();

@ -11,8 +11,9 @@ export const MergeTagEndpointHandler: EndpointHandler = async (req: any, res: an
throw e;
}
const reqObject: api.DeleteTagRequest = req.body;
const { id: userId } = req.user;
console.log("Merge Tag:", reqObject);
console.log("User ", userId, ": Merge Tag ", reqObject);
const fromId = req.params.id;
const toId = req.params.toId;
@ -21,12 +22,14 @@ export const MergeTagEndpointHandler: EndpointHandler = async (req: any, res: an
// Start retrieving the "from" tag.
const fromTagPromise = trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ id: fromId })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined)
// Start retrieving the "to" tag.
const toTagPromise = trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ id: toId })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined)
@ -44,6 +47,7 @@ export const MergeTagEndpointHandler: EndpointHandler = async (req: any, res: an
// Assign new tag ID to any objects referencing the to-be-merged tag.
const cPromise = trx('tags')
.where({ 'user': userId })
.where({ 'parentId': fromId })
.update({ 'parentId': toId });
const sPromise = trx('songs_tags')
@ -59,6 +63,7 @@ export const MergeTagEndpointHandler: EndpointHandler = async (req: any, res: an
// Delete the original tag.
await trx('tags')
.where({ 'user': userId })
.where({ 'id': fromId })
.del();

@ -11,8 +11,9 @@ export const ModifyAlbumEndpointHandler: EndpointHandler = async (req: any, res:
throw e;
}
const reqObject: api.ModifyAlbumRequest = req.body;
const { id: userId } = req.user;
console.log("Modify Album:", reqObject);
console.log("User ", userId, ": Modify Album ", reqObject);
await knex.transaction(async (trx) => {
try {
@ -20,6 +21,7 @@ export const ModifyAlbumEndpointHandler: EndpointHandler = async (req: any, res:
// Start retrieving the album itself.
const albumPromise = trx.select('id')
.from('albums')
.where({ 'user': userId })
.where({ id: req.params.id })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined);
@ -58,6 +60,7 @@ export const ModifyAlbumEndpointHandler: EndpointHandler = async (req: any, res:
if ("name" in reqObject) { update["name"] = reqObject.name; }
if ("storeLinks" in reqObject) { update["storeLinks"] = JSON.stringify(reqObject.storeLinks || []); }
const modifyAlbumPromise = trx('albums')
.where({ 'user': userId })
.where({ 'id': req.params.id })
.update(update)

@ -11,7 +11,9 @@ export const ModifyArtistEndpointHandler: EndpointHandler = async (req: any, res
throw e;
}
const reqObject: api.ModifyArtistRequest = req.body;
console.log("Modify Artist:", reqObject);
const { id: userId } = req.user;
console.log("User ", userId, ": Modify Artist ", reqObject);
await knex.transaction(async (trx) => {
try {
@ -20,6 +22,7 @@ export const ModifyArtistEndpointHandler: EndpointHandler = async (req: any, res
// Start retrieving the artist itself.
const artistPromise = trx.select('id')
.from('artists')
.where({ 'user': userId })
.where({ id: artistId })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined)
@ -49,6 +52,7 @@ export const ModifyArtistEndpointHandler: EndpointHandler = async (req: any, res
if ("name" in reqObject) { update["name"] = reqObject.name; }
if ("storeLinks" in reqObject) { update["storeLinks"] = JSON.stringify(reqObject.storeLinks || []); }
const modifyArtistPromise = trx('artists')
.where({ 'user': userId })
.where({ 'id': artistId })
.update(update)

@ -11,14 +11,16 @@ export const ModifySongEndpointHandler: EndpointHandler = async (req: any, res:
throw e;
}
const reqObject: api.ModifySongRequest = req.body;
const { id: userId } = req.user;
console.log("Modify Song:", reqObject);
console.log("User ", userId, ": Modify Song ", reqObject);
await knex.transaction(async (trx) => {
try {
// Retrieve the song to be modified itself.
const songPromise = trx.select('id')
.from('songs')
.where({ 'user': userId })
.where({ id: req.params.id })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined)
@ -67,6 +69,7 @@ export const ModifySongEndpointHandler: EndpointHandler = async (req: any, res:
if ("title" in reqObject) { update["title"] = reqObject.title; }
if ("storeLinks" in reqObject) { update["storeLinks"] = JSON.stringify(reqObject.storeLinks || []); }
const modifySongPromise = trx('songs')
.where({ 'user': userId })
.where({ 'id': req.params.id })
.update(update)

@ -11,8 +11,9 @@ export const ModifyTagEndpointHandler: EndpointHandler = async (req: any, res: a
throw e;
}
const reqObject: api.ModifyTagRequest = req.body;
const { id: userId } = req.user;
console.log("Modify Tag:", reqObject);
console.log("User ", userId, ": Modify Tag ", reqObject);
await knex.transaction(async (trx) => {
try {
@ -20,6 +21,7 @@ export const ModifyTagEndpointHandler: EndpointHandler = async (req: any, res: a
const parentTagPromise = reqObject.parentId ?
trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ 'id': reqObject.parentId })
.then((ts: any) => ts.map((t: any) => t['tagId'])) :
(async () => { return [] })();
@ -27,6 +29,7 @@ export const ModifyTagEndpointHandler: EndpointHandler = async (req: any, res: a
// Start retrieving the tag itself.
const tagPromise = trx.select('id')
.from('tags')
.where({ 'user': userId })
.where({ id: req.params.id })
.then((r: any) => (r && r[0]) ? r[0]['id'] : undefined)
@ -45,6 +48,7 @@ export const ModifyTagEndpointHandler: EndpointHandler = async (req: any, res: a
// Modify the tag.
await trx('tags')
.where({ 'user': userId })
.where({ 'id': req.params.id })
.update({
name: reqObject.name,

@ -178,7 +178,7 @@ const objectColumns = {
[ObjectType.Tag]: ['tags.id as tags.id', 'tags.name as tags.name', 'tags.parentId as tags.parentId']
};
function constructQuery(knex: Knex, queryFor: ObjectType, queryElem: api.QueryElem, ordering: api.Ordering,
function constructQuery(knex: Knex, userId: number, queryFor: ObjectType, queryElem: api.QueryElem, ordering: api.Ordering,
offset: number, limit: number | null) {
const joinObjects = getRequiredDatabaseObjects(queryElem);
joinObjects.delete(queryFor); // We are already querying this object in the base query.
@ -194,6 +194,7 @@ function constructQuery(knex: Knex, queryFor: ObjectType, queryElem: api.QueryEl
// First, we create a base query for the type of object we need to yield.
var q = knex.select(columns)
.where({ [objectTables[queryFor] + '.user']: userId })
.groupBy(objectTables[queryFor] + '.' + 'id')
.from(objectTables[queryFor]);
@ -223,7 +224,7 @@ function constructQuery(knex: Knex, queryFor: ObjectType, queryElem: api.QueryEl
return q;
}
async function getLinkedObjects(knex: Knex, base: ObjectType, linked: ObjectType, baseIds: number[]) {
async function getLinkedObjects(knex: Knex, userId: number, base: ObjectType, linked: ObjectType, baseIds: number[]) {
var result: Record<number, any[]> = {};
const otherTable = objectTables[linked];
const linkingTable = getLinkingTable(base, linked);
@ -232,6 +233,7 @@ async function getLinkedObjects(knex: Knex, base: ObjectType, linked: ObjectType
await Promise.all(baseIds.map((baseId: number) => {
return knex.select(columns).groupBy(otherTable + '.id').from(otherTable)
.join(linkingTable, { [linkingTable + '.' + linkingTableIdNames[linked]]: otherTable + '.id' })
.where({ [otherTable + '.user']: userId })
.where({ [linkingTable + '.' + linkingTableIdNames[base]]: baseId })
.then((others: any) => { result[baseId] = others; })
}))
@ -241,11 +243,12 @@ async function getLinkedObjects(knex: Knex, base: ObjectType, linked: ObjectType
}
// Resolve a tag into the full nested structure of its ancestors.
async function getFullTag(knex: Knex, tag: any): Promise<any> {
async function getFullTag(knex: Knex, userId: number, tag: any): Promise<any> {
const resolveTag = async (t: any) => {
if (t['tags.parentId']) {
const parent = (await knex.select(objectColumns[ObjectType.Tag])
.from('tags')
.where({ 'user': userId })
.where({ [objectTables[ObjectType.Tag] + '.id']: t['tags.parentId'] }))[0];
t.parent = await resolveTag(parent);
}
@ -264,7 +267,9 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
throw e;
}
const reqObject: api.QueryRequest = req.body;
console.log("Query: ", reqObject);
const { id: userId } = req.user;
console.log("User ", userId, ": Query ", reqObject);
try {
const songLimit = reqObject.offsetsLimits.songLimit;
@ -278,6 +283,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
const artistsPromise: Promise<any> = (artistLimit && artistLimit !== 0) ?
constructQuery(knex,
userId,
ObjectType.Artist,
reqObject.query,
reqObject.ordering,
@ -288,6 +294,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
const albumsPromise: Promise<any> = (albumLimit && albumLimit !== 0) ?
constructQuery(knex,
userId,
ObjectType.Album,
reqObject.query,
reqObject.ordering,
@ -298,6 +305,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
const songsPromise: Promise<any> = (songLimit && songLimit !== 0) ?
constructQuery(knex,
userId,
ObjectType.Song,
reqObject.query,
reqObject.ordering,
@ -308,6 +316,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
const tagsPromise: Promise<any> = (tagLimit && tagLimit !== 0) ?
constructQuery(knex,
userId,
ObjectType.Tag,
reqObject.query,
reqObject.ordering,
@ -325,18 +334,18 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
})();
const songsArtistsPromise: Promise<Record<number, any[]>> = (songLimit && songLimit !== 0) ?
(async () => {
return await getLinkedObjects(knex, ObjectType.Song, ObjectType.Artist, await songIdsPromise);
return await getLinkedObjects(knex, userId, ObjectType.Song, ObjectType.Artist, await songIdsPromise);
})() :
(async () => { return {}; })();
const songsTagsPromise: Promise<Record<number, any[]>> = (songLimit && songLimit !== 0) ?
(async () => {
const tagsPerSong: Record<number, any> = await getLinkedObjects(knex, ObjectType.Song, ObjectType.Tag, await songIdsPromise);
const tagsPerSong: Record<number, any> = await getLinkedObjects(knex, userId, ObjectType.Song, ObjectType.Tag, await songIdsPromise);
var result: Record<number, any> = {};
for (var key in tagsPerSong) {
const tags = tagsPerSong[key];
var fullTags: any[] = [];
for (var idx in tags) {
fullTags.push(await getFullTag(knex, tags[idx]));
fullTags.push(await getFullTag(knex, userId, tags[idx]));
}
result[key] = fullTags;
}
@ -345,7 +354,7 @@ export const QueryEndpointHandler: EndpointHandler = async (req: any, res: any,
(async () => { return {}; })();
const songsAlbumsPromise: Promise<Record<number, any[]>> = (songLimit && songLimit !== 0) ?
(async () => {
return await getLinkedObjects(knex, ObjectType.Song, ObjectType.Album, await songIdsPromise);
return await getLinkedObjects(knex, userId, ObjectType.Song, ObjectType.Album, await songIdsPromise);
})() :
(async () => { return {}; })();

@ -12,6 +12,8 @@ export const SongDetailsEndpointHandler: EndpointHandler = async (req: any, res:
throw e;
}
const { id: userId } = req.user;
try {
const tagIdsPromise: Promise<number[]> = knex.select('tagId')
.from('songs_tags')
@ -41,6 +43,7 @@ export const SongDetailsEndpointHandler: EndpointHandler = async (req: any, res:
})
const songPromise = await knex.select(['id', 'title', 'storeLinks'])
.from('songs')
.where({ 'user': userId })
.where({ 'id': req.params.id })
.then((ss: any) => ss[0])

@ -11,9 +11,12 @@ export const TagDetailsEndpointHandler: EndpointHandler = async (req: any, res:
throw e;
}
const { id: userId } = req.user;
try {
const results = await knex.select(['id', 'name', 'parentId'])
.from('tags')
.where({ 'user': userId })
.where({ 'id': req.params.id });
const response: api.TagDetailsResponse = {

@ -1,4 +1,5 @@
import * as Knex from "knex";
import { sha512 } from "js-sha512";
export async function up(knex: Knex): Promise<void> {
@ -11,10 +12,63 @@ export async function up(knex: Knex): Promise<void> {
table.string('passwordHash')
}
)
// Add user column to other object tables.
// FIXME: figure out what happens in practice with pre-existing objects.
await knex.schema.alterTable(
'songs',
(table: any) => {
table.integer('user').unsigned().notNullable().defaultTo(1);
}
)
await knex.schema.alterTable(
'albums',
(table: any) => {
table.integer('user').unsigned().notNullable().defaultTo(1);
}
)
await knex.schema.alterTable(
'tags',
(table: any) => {
table.integer('user').unsigned().notNullable().defaultTo(1);
}
)
await knex.schema.alterTable(
'artists',
(table: any) => {
table.integer('user').unsigned().notNullable().defaultTo(1);
}
)
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.dropTable('users');
// Remove the user column
await knex.schema.alterTable(
'songs',
(table: any) => {
table.dropColumn('user');
}
)
await knex.schema.alterTable(
'albums',
(table: any) => {
table.dropColumn('user');
}
)
await knex.schema.alterTable(
'tags',
(table: any) => {
table.dropColumn('user');
}
)
await knex.schema.alterTable(
'artists',
(table: any) => {
table.dropColumn('user');
}
)
}

Loading…
Cancel
Save