feat: add version to appshell

This commit is contained in:
diced 2022-08-24 20:37:57 -07:00
parent 1d42d922bd
commit 45541a3cdd
No known key found for this signature in database
GPG key ID: 370BD1BA142842D1
13 changed files with 152 additions and 156 deletions

View file

@ -25,6 +25,7 @@
- Discord embeds (OG metadata)
- Gallery viewer, and multiple file format support
- Code highlighting
- Fully customizable Discord webhook notifications
- Easy setup instructions on [docs](https://zipl.vercel.app/) (One command install `docker-compose up -d`)
# Usage

View file

@ -1,6 +1,6 @@
{
"name": "zipline",
"version": "3.5.0",
"version": "3.4.0",
"license": "MIT",
"scripts": {
"dev": "REACT_EDITOR=code NODE_ENV=development tsx src/server",
@ -15,7 +15,7 @@
"docker:build-dev": "docker-compose --file docker-compose.dev.yml up --build"
},
"dependencies": {
"@dicedtomato/mantine-data-grid": "0.0.20",
"@dicedtomato/mantine-data-grid": "0.0.21",
"@emotion/react": "^11.9.3",
"@emotion/server": "^11.4.0",
"@iarna/toml": "2.2.5",

View file

@ -1,4 +1,4 @@
import { AppShell, Box, Burger, Button, Divider, Header, MediaQuery, Navbar, NavLink, Paper, Popover, ScrollArea, Select, Stack, Text, Title, UnstyledButton, useMantineTheme, Group, Image } from '@mantine/core';
import { AppShell, Box, Burger, Button, Divider, Header, MediaQuery, Navbar, NavLink, Paper, Popover, ScrollArea, Select, Stack, Text, Title, UnstyledButton, useMantineTheme, Group, Image, Tooltip, Badge } from '@mantine/core';
import { useClipboard } from '@mantine/hooks';
import { useModals } from '@mantine/modals';
import { showNotification } from '@mantine/notifications';
@ -7,7 +7,7 @@ import { updateUser } from 'lib/redux/reducers/user';
import { useStoreDispatch } from 'lib/redux/store';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { ActivityIcon, CheckIcon, CopyIcon, CrossIcon, DeleteIcon, FileIcon, HomeIcon, LinkIcon, LogoutIcon, PencilIcon, SettingsIcon, TagIcon, TypeIcon, UploadIcon, UserIcon } from './icons';
import { friendlyThemeName, themes } from './Theming';
@ -111,10 +111,11 @@ const admin_items = [
export default function Layout({ children, user, title }) {
const [token, setToken] = useState(user?.token);
const [systemTheme, setSystemTheme] = useState(user.systemTheme ?? 'system');
const [avatar, setAvatar] = useState(user.avatar ?? null);
const [version, setVersion] = useState<{ local: string, upstream: string }>(null);
const [opened, setOpened] = useState(false); // navigation open
const [open, setOpen] = useState(false); // manage acc dropdown
const avatar = user?.avatar ?? null;
const router = useRouter();
const dispatch = useStoreDispatch();
const theme = useMantineTheme();
@ -191,6 +192,15 @@ export default function Layout({ children, user, title }) {
},
});
useEffect(() => {
(async () => {
const data = await useFetch('/api/version');
if (!data.error) {
setVersion(data);
}
})();
}, []);
return (
<AppShell
navbarOffsetBreakpoint='sm'
@ -238,6 +248,27 @@ export default function Layout({ children, user, title }) {
</NavLink>
)}
</Navbar.Section>
{version ? (
<Navbar.Section>
<Tooltip
label={
version.local !== version.upstream
? `You are running an outdated version of Zipline, refer to the docs on how to update to ${version.upstream}`
: 'You are running the latest version of Zipline'
}
>
<Badge
m='md'
radius='md'
size='lg'
variant='dot'
color={version.local !== version.upstream ? 'red' : 'primary'}
>
{version.local}
</Badge>
</Tooltip>
</Navbar.Section>
) : null}
</Navbar>
}
header={

View file

@ -116,7 +116,6 @@ export default function Dashboard() {
<Title mt='md'>Files</Title>
<MutedText size='md'>View your gallery <Link href='/dashboard/files'>here</Link>.</MutedText>
<Box>
<DataGrid
data={images}
loading={images.length ? false : true}
@ -186,7 +185,6 @@ export default function Dashboard() {
},
]}
/>
</Box>
</>
);
}

View file

@ -1,63 +1,32 @@
export interface ConfigCore {
// Whether to return http or https links
https: boolean;
// Used for signing of cookies and other stuff
secret: string;
// The host Zipline will run on
host: string;
// The port Zipline will run on
port: number;
// The PostgreSQL database url
database_url: string;
// Whether or not to log stuff
logger: boolean;
// The interval to store stats
stats_interval: number;
invites_interval: number;
}
export interface ConfigDatasource {
// The type of datasource
type: 'local' | 's3' | 'swift';
// The local datasource, the default
local: ConfigLocalDatasource;
// The s3 datasource
s3?: ConfigS3Datasource;
// The Swift datasource
swift?: ConfigSwiftDatasource;
}
export interface ConfigLocalDatasource {
// The directory to store files in
directory: string;
}
export interface ConfigS3Datasource {
// The access key id for the s3 bucket
access_key_id: string;
// The secret access key for the s3 bucket
secret_access_key: string;
// Not required, but if using a non-aws S3 service you can specify the endpoint
endpoint?: string;
// The S3 bucket to store files in
bucket: string;
// If true Zipline will attempt to connect to the bucket via the url "https://s3.amazonaws.com/{bucket}/stuff"
// If false Zipline will attempt to connect to the bucket via the url "http://{bucket}.s3.amazonaws.com/stuff"
force_s3_path: boolean;
// Region
// aws region, default will be us-east-1 (if using a non-aws S3 service this might work for you)
region?: string;
}
@ -72,44 +41,27 @@ export interface ConfigSwiftDatasource {
}
export interface ConfigUploader {
// The route uploads will be served on
route: string;
// Length of random chars to generate for file names
length: number;
// Admin file upload limit
admin_limit: number;
// User file upload limit
user_limit: number;
// Disabled extensions to block from uploading
disabled_extensions: string[];
}
export interface ConfigUrls {
// The route urls will be served on
route: string;
// Length of random chars to generate for urls
length: number;
}
// Ratelimiting for users/admins, setting them to 0 disables ratelimiting
export interface ConfigRatelimit {
// Ratelimit for users
user: number;
// Ratelimit for admins
admin: number;
}
export interface ConfigWebsite {
// Change the title from Zipline to something else
title: string;
// If zipline should show files per user in the stats page
show_files_per_user: boolean;
show_version: boolean;
}
export interface ConfigDiscord {

View file

@ -49,6 +49,7 @@ export default function readConfig() {
map('CORE_DATABASE_URL', 'string', 'core.database_url'),
map('CORE_LOGGER', 'boolean', 'core.logger'),
map('CORE_STATS_INTERVAL', 'number', 'core.stats_interval'),
map('CORE_INVITES_INTERVAL', 'number', 'core.invites_interval'),
map('DATASOURCE_TYPE', 'string', 'datasource.type'),
@ -83,6 +84,7 @@ export default function readConfig() {
map('WEBSITE_TITLE', 'string', 'website.title'),
map('WEBSITE_SHOW_FILES_PER_USER', 'boolean', 'website.show_files_per_user'),
map('WEBSITE_SHOW_VERSION', 'boolean', 'website.show_version'),
map('DISCORD_URL', 'string', 'discord.url'),
map('DISCORD_USERNAME', 'string', 'discord.username'),

View file

@ -23,6 +23,7 @@ const validator = object({
database_url: string().required(),
logger: boolean().default(false),
stats_interval: number().default(1800),
invites_interval: number().default(1800),
}).required(),
datasource: object({
type: string().oneOf(['local', 's3', 'swift']).default('local'),
@ -66,6 +67,7 @@ const validator = object({
website: object({
title: string().default('Zipline'),
show_files_per_user: boolean().default(true),
show_version: boolean().default(true),
}),
discord: object({
url: string(),
@ -110,8 +112,6 @@ export default function validate(config): Config {
}
}
console.log(validated);
return validated as unknown as Config;
} catch (e) {
if (process.env.ZIPLINE_DOCKER_BUILD) return null;

View file

@ -114,8 +114,6 @@ export async function sendShorten(user: User, url: Url, host: string) {
}] : null,
};
console.log(body);
const res = await fetch(config.discord.url, {
method: 'POST',
body: JSON.stringify(body),

View file

@ -1,8 +1,14 @@
import { readFile } from 'fs/promises';
import config from 'lib/config';
import { NextApiReq, NextApiRes, withZipline } from 'middleware/withZipline';
async function handler(req: NextApiReq, res: NextApiRes) {
const user = await req.user();
if (!user) return res.forbid('not logged in');
if (!config.website.show_version) return res.bad('version hidden');
const pkg = JSON.parse(await readFile('package.json', 'utf8'));
const re = await fetch('https://raw.githubusercontent.com/diced/zipline/trunk/package.json');

View file

@ -142,15 +142,7 @@ export const getServerSideProps: GetServerSideProps = async context => {
if (!invite) return { notFound: true };
if (invite.used) return { notFound: true };
if (invite.expires_at && invite.expires_at < new Date()) {
await prisma.invite.delete({
where: {
code,
},
});
return { notFound: true };
};
if (invite.expires_at && invite.expires_at < new Date()) return { notFound: true };
return {
props: {

View file

@ -115,6 +115,16 @@ async function start() {
logger.info(`started ${dev ? 'development' : 'production'} zipline@${version} server`);
stats(prisma);
setInterval(async () => {
await prisma.invite.deleteMany({
where: {
used: true,
},
});
if (config.core.logger) logger.info('invites cleaned');
}, config.core.invites_interval * 1000);
}
async function rawFile(

View file

@ -5,6 +5,7 @@ import { Datasource } from 'lib/datasources';
import { PrismaClient } from '@prisma/client';
export async function migrations() {
try {
const migrate = new Migrate('./prisma/schema.prisma');
await ensureDatabaseExists('apply', true, './prisma/schema.prisma');
@ -23,6 +24,11 @@ export async function migrations() {
} else {
migrate.stop();
}
} catch (error) {
Logger.get('database').error('Failed to migrate database... exiting...');
Logger.get('database').error(error);
process.exit(1);
}
}
export function log(url: string) {

View file

@ -301,9 +301,9 @@ __metadata:
languageName: node
linkType: hard
"@dicedtomato/mantine-data-grid@npm:0.0.20":
version: 0.0.20
resolution: "@dicedtomato/mantine-data-grid@npm:0.0.20"
"@dicedtomato/mantine-data-grid@npm:0.0.21":
version: 0.0.21
resolution: "@dicedtomato/mantine-data-grid@npm:0.0.21"
dependencies:
"@emotion/react": ^11.9.3
"@mantine/core": ^5.0.0
@ -324,7 +324,7 @@ __metadata:
peerDependenciesMeta:
dayjs:
optional: true
checksum: 6d23048cc4d0dba093c8bbbaa70f7f7b8539834bcf11f070669b54a643b8def70c21a3a3ed7e807220e2c9928239c658b0a8f717a466cbfd4e8933576a2762a2
checksum: bca215db4cc2fbf776a30c2fe9fbb2e95649d9adfd8b014c04ae6a8dff00a726c6042546d79144f11323e2895539cc5d83686d9e5c6bc7a2e9f1a48cb2831b87
languageName: node
linkType: hard
@ -8867,7 +8867,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "zipline@workspace:."
dependencies:
"@dicedtomato/mantine-data-grid": 0.0.20
"@dicedtomato/mantine-data-grid": 0.0.21
"@emotion/react": ^11.9.3
"@emotion/server": ^11.4.0
"@iarna/toml": 2.2.5