fix: do not include stats in export + other version stuff (#721)

* notFix: Removed the option to only clear db. It'd be a dangerous thing to continue allowing it.

* fix: Exclude returning user's uuid from /api/users.

* fix: Use a different method of version checking.

* fix: Upstream docker images now have an extended commit tag.

* fix: Exclude stats from the export. Has caused a lot of memory problems.
This commit is contained in:
Jay 2025-03-03 16:03:25 -08:00 committed by GitHub
parent 478baeca83
commit 61ab5a192b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 47 additions and 46 deletions

View file

@ -2,6 +2,8 @@ node_modules/
.next/ .next/
uploads/ uploads/
.git/ .git/
!.git/refs
!.git/HEAD
.yarn/* .yarn/*
!.yarn/releases !.yarn/releases
!.yarn/plugins !.yarn/plugins

View file

@ -13,7 +13,7 @@ on:
jobs: jobs:
push: push:
name: Push Image name: Push Commit Image
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out the repo - name: Check out the repo
@ -22,7 +22,7 @@ jobs:
- name: Get version - name: Get version
id: version id: version
run: | run: |
echo "zipline_version=$(jq .version package.json -r)" >> $GITHUB_OUTPUT echo "zipline_commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
- name: Setup QEMU - name: Setup QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
@ -51,8 +51,8 @@ jobs:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
tags: | tags: |
ghcr.io/diced/zipline:v3-trunk ghcr.io/diced/zipline:v3-trunk
ghcr.io/diced/zipline:v3-trunk-${{ steps.version.outputs.zipline_version }} ghcr.io/diced/zipline:v3-trunk-${{ steps.version.outputs.zipline_commit }}
${{ secrets.DOCKERHUB_USERNAME }}/zipline:v3-trunk ${{ secrets.DOCKERHUB_USERNAME }}/zipline:v3-trunk
${{ secrets.DOCKERHUB_USERNAME }}/zipline:v3-trunk-${{ steps.version.outputs.zipline_version }} ${{ secrets.DOCKERHUB_USERNAME }}/zipline:v3-trunk-${{ steps.version.outputs.zipline_commit }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max

View file

@ -53,6 +53,9 @@ ENV PRISMA_QUERY_ENGINE_BINARY=/prisma-engines/query-engine \
ZIPLINE_DOCKER_BUILD=true \ ZIPLINE_DOCKER_BUILD=true \
NEXT_TELEMETRY_DISABLED=1 NEXT_TELEMETRY_DISABLED=1
COPY .git/refs ./.git/refs
COPY .git/HEAD ./.git/HEAD
# Copy only the necessary files from the previous stage # Copy only the necessary files from the previous stage
COPY --from=builder /zipline/dist ./dist COPY --from=builder /zipline/dist ./dist

View file

@ -316,7 +316,9 @@ export default function Layout({ children, props }) {
variant='dot' variant='dot'
color={version.data.update ? 'red' : 'primary'} color={version.data.update ? 'red' : 'primary'}
> >
{version.data.versions.current} {version.data.isUpstream
? version.data.versions.current.slice(0, 7)
: version.data.versions.current}
</Badge> </Badge>
</Tooltip> </Tooltip>
</Navbar.Section> </Navbar.Section>

View file

@ -7,7 +7,7 @@ import { useState } from 'react';
export default function ClearStorage({ open, setOpen }) { export default function ClearStorage({ open, setOpen }) {
const [check, setCheck] = useState(false); const [check, setCheck] = useState(false);
const handleDelete = async (datasource: boolean, orphaned?: boolean) => { const handleDelete = async (orphaned?: boolean) => {
showNotification({ showNotification({
id: 'clear-uploads', id: 'clear-uploads',
title: 'Clearing...', title: 'Clearing...',
@ -16,7 +16,7 @@ export default function ClearStorage({ open, setOpen }) {
autoClose: false, autoClose: false,
}); });
const res = await useFetch('/api/admin/clear', 'POST', { datasource, orphaned }); const res = await useFetch('/api/admin/clear', 'POST', { orphaned });
if (res.error) { if (res.error) {
updateNotification({ updateNotification({
@ -65,21 +65,13 @@ export default function ClearStorage({ open, setOpen }) {
onClick={() => { onClick={() => {
setOpen(false); setOpen(false);
openConfirmModal({ openConfirmModal({
title: 'Do you want to clear storage too?', title: 'Are you sure?',
labels: { confirm: 'Yes', cancel: check ? 'Ok' : 'No' }, confirmProps: { color: 'red' },
children: check && ( children: <Text size='sm'>This action is destructive and irreversible.</Text>,
<Text size='sm' color='gray'> labels: { confirm: 'Yes', cancel: 'No' },
Due to clearing orphaned files, storage clearing will be unavailable.
</Text>
),
confirmProps: { disabled: check },
onConfirm: () => { onConfirm: () => {
closeAllModals(); closeAllModals();
handleDelete(true); handleDelete(check);
},
onCancel: () => {
closeAllModals();
handleDelete(false, check);
}, },
onClose: () => setCheck(false), onClose: () => setCheck(false),
}); });

View file

@ -8,21 +8,23 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) {
try { try {
const { orphaned } = req.body; const { orphaned } = req.body;
if (orphaned) { if (orphaned) {
const files = await prisma.file.findMany({
where: {
userId: null,
},
});
const { count } = await prisma.file.deleteMany({ const { count } = await prisma.file.deleteMany({
where: { where: {
userId: null, userId: null,
}, },
}); });
for (const file of files) await datasource.delete(file.name);
logger.info(`User ${user.username} (${user.id}) cleared the database of ${count} orphaned files`); logger.info(`User ${user.username} (${user.id}) cleared the database of ${count} orphaned files`);
return res.json({ message: 'cleared storage (orphaned only)' }); return res.json({ message: 'cleared storage (orphaned only)' });
} }
const { count } = await prisma.file.deleteMany({}); const { count } = await prisma.file.deleteMany({});
await datasource.clear();
logger.info(`User ${user.username} (${user.id}) cleared the database of ${count} files`); logger.info(`User ${user.username} (${user.id}) cleared the database of ${count} files`);
if (req.body.datasource) {
await datasource.clear();
logger.info(`User ${user.username} (${user.id}) cleared storage`);
}
} catch (e) { } catch (e) {
logger.error(`User ${user.username} (${user.id}) failed to clear the database or storage`); logger.error(`User ${user.username} (${user.id}) failed to clear the database or storage`);
logger.error(e); logger.error(e);

View file

@ -283,14 +283,6 @@ async function handler(req: NextApiReq, res: NextApiRes, user: UserExtended) {
}; };
} }
const stats = await prisma.stats.findMany();
for (const stat of stats) {
exportData.stats.push({
created_at: stat.createdAt.toISOString(),
data: stat.data,
});
}
exportData.request.user = exportData.user_map[user.id]; exportData.request.user = exportData.user_map[user.id];
for (const folder of folders) { for (const folder of folders) {

View file

@ -3,7 +3,10 @@ import { NextApiReq, NextApiRes, withZipline } from 'middleware/withZipline';
async function handler(_: NextApiReq, res: NextApiRes) { async function handler(_: NextApiReq, res: NextApiRes) {
const users = await prisma.user.findMany(); const users = await prisma.user.findMany();
for (let i = 0; i !== users.length; ++i) delete users[i].password; for (let i = 0; i !== users.length; ++i) {
delete users[i].password;
delete users[i].uuid;
}
return res.json(users); return res.json(users);
} }

View file

@ -5,24 +5,29 @@ import { NextApiReq, NextApiRes, withZipline } from 'middleware/withZipline';
async function handler(_: NextApiReq, res: NextApiRes) { async function handler(_: NextApiReq, res: NextApiRes) {
if (!config.website.show_version) return res.forbidden('version hidden'); if (!config.website.show_version) return res.forbidden('version hidden');
const pkg = JSON.parse(await readFile('package.json', 'utf8')); const pRev = await (async function () {
try {
return await readFile('.git/HEAD', 'utf8');
} catch (e) {
return JSON.parse(await readFile('package.json', 'utf8')).version;
}
})();
const { groups } = new RegExp(/^ref: (?<ref>(\w+\/?)*)/).exec(pRev) || { groups: null };
let rev: string;
const re = await fetch('https://zipline.diced.sh/api/version?c=' + pkg.version); if (!groups) rev = pRev;
else rev = await readFile(`.git/${groups.ref}`, 'utf8');
const re = await fetch(`https://v3.zipline.diced.sh/api/version?c=?c=${rev}`);
const json = await re.json(); const json = await re.json();
if (!re.ok) return res.badRequest(json.error);
let updateToType = 'stable'; let updateToType = 'stable';
if (json.isUpstream) updateToType = 'upstream';
if (json.isUpstream) {
updateToType = 'upstream';
if (json.update?.stable) {
updateToType = 'stable';
}
}
return res.json({ return res.json({
isUpstream: true, isUpstream: json.isUpstream,
update: json.update?.stable || json.update?.upstream, update: json.isUpstream ? json.update?.upstream : json.update?.stable,
updateToType, updateToType,
versions: { versions: {
stable: json.git.stable, stable: json.git.stable,