mirror of
https://github.com/diced/zipline.git
synced 2026-01-25 18:54:50 -08:00
fix: #948 and tags/folders
fixes inconsistencies when editing other user's files - tags menu shows their tags - folders menu shows their folders by design, you can't and will not be able to add another user's file to your own folder. this also introduces a few wip stuff, might be buggy, please bear with me!
This commit is contained in:
@@ -103,7 +103,7 @@ export default function FileModal({
|
||||
const [editFileOpen, setEditFileOpen] = useState(false);
|
||||
|
||||
const { data: folders } = useSWR<Extract<Response['/api/user/folders'], Folder[]>>(
|
||||
'/api/user/folders?noincl=true',
|
||||
'/api/user/folders?noincl=true' + (user ? `&user=${user}` : ''),
|
||||
);
|
||||
|
||||
const folderCombobox = useCombobox();
|
||||
@@ -117,7 +117,9 @@ export default function FileModal({
|
||||
}
|
||||
};
|
||||
|
||||
const { data: tags } = useSWR<Extract<Response['/api/user/tags'], Tag[]>>('/api/user/tags');
|
||||
const { data: tags } = useSWR<Extract<Response['/api/user/tags'], Tag[]>>(
|
||||
user ? `/api/users/${user}/tags` : '/api/user/tags',
|
||||
);
|
||||
|
||||
const tagsCombobox = useCombobox();
|
||||
const [value, setValue] = useState(file?.tags?.map((x) => x.id) ?? []);
|
||||
@@ -229,7 +231,7 @@ export default function FileModal({
|
||||
)}
|
||||
</SimpleGrid>
|
||||
|
||||
{!reduce && !user && (
|
||||
{!reduce && (
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }} spacing='md' my='xs'>
|
||||
<Box>
|
||||
<Title order={4} mt='lg' mb='xs'>
|
||||
|
||||
@@ -6,12 +6,12 @@ import FileModal from './FileModal';
|
||||
|
||||
import styles from './index.module.css';
|
||||
|
||||
export default function DashboardFile({ file, reduce }: { file: File; reduce?: boolean }) {
|
||||
export default function DashboardFile({ file, reduce, id }: { file: File; reduce?: boolean; id?: string }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<FileModal open={open} setOpen={setOpen} file={file} reduce={reduce} />
|
||||
<FileModal open={open} setOpen={setOpen} file={file} reduce={reduce} user={id} />
|
||||
<Card shadow='md' radius='md' p={0} onClick={() => setOpen(true)} className={styles.file}>
|
||||
<DashboardFileType key={file.id} file={file} />
|
||||
</Card>
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function Files({ id }: { id?: string }) {
|
||||
) : (data?.page?.length ?? 0 > 0) ? (
|
||||
data?.page.map((file) => (
|
||||
<Suspense fallback={<Skeleton height={350} animate />} key={file.id}>
|
||||
<DashboardFile file={file} />
|
||||
<DashboardFile file={file} id={id} />
|
||||
</Suspense>
|
||||
))
|
||||
) : (
|
||||
|
||||
@@ -85,7 +85,7 @@ export default fastifyPlugin(
|
||||
if (req.body.tags !== undefined) {
|
||||
const tags = await prisma.tag.findMany({
|
||||
where: {
|
||||
userId: req.user.id,
|
||||
userId: req.user.id !== file.User?.id ? file.User?.id : req.user.id,
|
||||
id: {
|
||||
in: req.body.tags,
|
||||
},
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { prisma } from '@/lib/db';
|
||||
import { fileSelect } from '@/lib/db/models/file';
|
||||
import { Folder, cleanFolder } from '@/lib/db/models/folder';
|
||||
import { User } from '@/lib/db/models/user';
|
||||
import { log } from '@/lib/logger';
|
||||
import { canInteract } from '@/lib/role';
|
||||
import { userMiddleware } from '@/server/middleware/user';
|
||||
import fastifyPlugin from 'fastify-plugin';
|
||||
|
||||
@@ -20,6 +22,16 @@ type Body = {
|
||||
delete?: 'file' | 'folder';
|
||||
};
|
||||
|
||||
// TODO: need to refactor interaction checks to use this function in the future
|
||||
function checkInteraction(current?: Partial<User> | null, owner?: Partial<User> | null) {
|
||||
if (!current || !owner) return false;
|
||||
if (current.id === owner.id) return true;
|
||||
|
||||
const can = canInteract(current.role, owner.role);
|
||||
|
||||
return can;
|
||||
}
|
||||
|
||||
const logger = log('api').c('user').c('folders').c('[id]');
|
||||
|
||||
export const PATH = '/api/user/folders/:id';
|
||||
@@ -46,10 +58,11 @@ export default fastifyPlugin(
|
||||
password: true,
|
||||
},
|
||||
},
|
||||
User: true,
|
||||
},
|
||||
});
|
||||
if (!folder) return res.notFound('Folder not found');
|
||||
if (req.user.id !== folder.userId) return res.forbidden('You do not own this folder');
|
||||
if (!checkInteraction(req.user, folder.User)) return res.notFound('Folder not found');
|
||||
|
||||
if (req.method === 'PUT') {
|
||||
const { id } = req.body;
|
||||
@@ -59,9 +72,12 @@ export default fastifyPlugin(
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
User: true,
|
||||
},
|
||||
});
|
||||
if (!file) return res.notFound('File not found');
|
||||
if (file.userId !== req.user.id) return res.forbidden('You do not own this file');
|
||||
if (!checkInteraction(req.user, file.User)) return res.notFound('File not found');
|
||||
|
||||
const fileInFolder = await prisma.file.findFirst({
|
||||
where: {
|
||||
@@ -91,6 +107,7 @@ export default fastifyPlugin(
|
||||
password: true,
|
||||
},
|
||||
},
|
||||
User: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -145,6 +162,7 @@ export default fastifyPlugin(
|
||||
password: true,
|
||||
},
|
||||
},
|
||||
User: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -161,9 +179,12 @@ export default fastifyPlugin(
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
User: true,
|
||||
},
|
||||
});
|
||||
if (!file) return res.notFound('File not found');
|
||||
if (file.userId !== req.user.id) return res.forbidden('You do not own this file');
|
||||
if (!checkInteraction(req.user, file.User)) return res.notFound('File not found');
|
||||
|
||||
const fileInFolder = await prisma.file.findFirst({
|
||||
where: {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { fileSelect } from '@/lib/db/models/file';
|
||||
import { Folder, cleanFolder, cleanFolders } from '@/lib/db/models/folder';
|
||||
import { log } from '@/lib/logger';
|
||||
import { secondlyRatelimit } from '@/lib/ratelimits';
|
||||
import { canInteract } from '@/lib/role';
|
||||
import { userMiddleware } from '@/server/middleware/user';
|
||||
import fastifyPlugin from 'fastify-plugin';
|
||||
|
||||
@@ -17,6 +18,7 @@ type Body = {
|
||||
|
||||
type Query = {
|
||||
noincl?: boolean;
|
||||
user?: string;
|
||||
};
|
||||
|
||||
const logger = log('api').c('user').c('folders');
|
||||
@@ -25,11 +27,24 @@ export const PATH = '/api/user/folders';
|
||||
export default fastifyPlugin(
|
||||
(server, _, done) => {
|
||||
server.get<{ Querystring: Query }>(PATH, { preHandler: [userMiddleware] }, async (req, res) => {
|
||||
const { noincl } = req.query;
|
||||
const { noincl, user } = req.query;
|
||||
|
||||
if (user) {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
id: req.user.id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) return res.notFound();
|
||||
if (req.user.id !== user.id) {
|
||||
if (!canInteract(req.user.role, user.role)) return res.notFound();
|
||||
}
|
||||
}
|
||||
|
||||
const folders = await prisma.folder.findMany({
|
||||
where: {
|
||||
userId: req.user.id,
|
||||
userId: user || req.user.id,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
|
||||
48
src/server/routes/api/users/[id]/tags.ts
Normal file
48
src/server/routes/api/users/[id]/tags.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { prisma } from '@/lib/db';
|
||||
import { Tag, tagSelect } from '@/lib/db/models/tag';
|
||||
import { canInteract } from '@/lib/role';
|
||||
import { administratorMiddleware } from '@/server/middleware/administrator';
|
||||
import { userMiddleware } from '@/server/middleware/user';
|
||||
import fastifyPlugin from 'fastify-plugin';
|
||||
|
||||
export type ApiUsersIdTagsResponse = Tag[];
|
||||
|
||||
type Params = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
// const logger = log('api').c('user').c('id').c('tags');
|
||||
|
||||
export const PATH = '/api/users/:id/tags';
|
||||
export default fastifyPlugin(
|
||||
(server, _, done) => {
|
||||
server.get<{ Params: Params }>(
|
||||
PATH,
|
||||
{ preHandler: [userMiddleware, administratorMiddleware] },
|
||||
async (req, res) => {
|
||||
const { id } = req.params;
|
||||
|
||||
const user = await prisma.user.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) return res.notFound();
|
||||
if (!canInteract(req.user.role, user.role)) return res.notFound();
|
||||
|
||||
const tags = await prisma.tag.findMany({
|
||||
where: {
|
||||
userId: user.id,
|
||||
},
|
||||
select: tagSelect,
|
||||
});
|
||||
|
||||
return res.send(tags);
|
||||
},
|
||||
);
|
||||
|
||||
done();
|
||||
},
|
||||
{ name: PATH },
|
||||
);
|
||||
Reference in New Issue
Block a user