diff --git a/README.md b/README.md index e029757..811c60c 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,22 @@ ### `.env Example` ```env -# SQL Server Configuration -SQL_SERVER=localhost -SQL_DATABASE=ExampleDatabase +SQL_SERVER=sqlserver +SQL_DATABASE=ExampleDB SQL_USER_ID=admin -SQL_PASSWORD=ExamplePassword123! +SQL_PASSWORD=SuperSecure(!)Pass123 -# Auth0 Configuration -AUTH0_SECRET=0000000000000000000000000000000000000000000000000000000000000000 -AUTH0_ISSUER_BASE_URL=https://auth.example.com -AUTH0_CLIENT_ID=EXAMPLE_CLIENT_ID_12345 -AUTH0_CLIENT_SECRET=EXAMPLE_CLIENT_SECRET_ABCDE12345 -AUTH0_AUDIENCE=https://api.example.com +AUTH0_SECRET=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd +AUTH0_ISSUER_BASE_URL=auth.example.com +AUTH0_CLIENT_ID=abcDEF123456xyz7890 +AUTH0_CLIENT_SECRET=SecretClientKeyHereThatLooksRealButIsFake1234567890 +AUTH0_AUDIENCE=https://example.com AUTH0_SCOPE=openid profile email -AUTH0_DOMAIN=https://example.auth0.com/ +AUTH0_DOMAIN=https://dev-12345678.us.auth0.com/ AUTH0_AUTHORITY=https://auth.example.com/ -# App Configuration APP_BASE_URL=https://example.com -# ASP.NET Core Configuration ASPNETCORE_ENVIRONMENT=Development ASPNETCORE_HTTP_PORTS=8080 ASPNETCORE_APPLY_MIGRATIONS_AT_STARTUP=true @@ -30,12 +26,15 @@ ASPNETCORE_LOGGING_LEVEL=Information ASPNETCORE_LOGGING_LEVEL_EFCORE=Information ASPNETCORE_LOGGING_LEVEL_APP=Information -# Seq UI URL SEQ_BASE_URI=https://example.com/seq -# Node.js / Next.js Configuration +ZIPLINE_SECRET=somefakesecretkey123 +ZIPLINE_URL=https://example.com/res +ZIPLINE_ROUTE=/res + NODE_ENV=development COOKIE_DOMAIN=.example.com NEXT_PUBLIC_API_URL=https://example.com/api NEXT_PUBLIC_AUTH0_DOMAIN=auth.example.com -NEXT_PUBLIC_AUTH0_CLIENT_ID=EXAMPLE_PUBLIC_CLIENT_ID +NEXT_PUBLIC_AUTH0_CLIENT_ID=abcDEF123456xyz7890 +``` diff --git a/docker-compose.yml b/docker-compose.yml index 873aa04..f658388 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -97,6 +97,38 @@ services: networks: - app-network + zipline: + image: ghcr.io/diced/zipline:latest + expose: + - "3000" + environment: + - CORE_RETURN_HTTPS=true + - CORE_SECRET=${ZIPLINE_SECRET} + - CORE_HOST=0.0.0.0 + - CORE_PORT=3000 + - CORE_DATABASE_URL=file:./zipline.db + - CORE_LOGGER=true + - URLS_ROUTE=${ZIPLINE_ROUTE} + - URLS_LENGTH=6 + - UPLOADER_DEFAULT_FORMAT=RANDOM + - UPLOADER_DISABLED_EXTENSIONS= + - UPLOADER_FORMAT_DATE=%Y-%m-%d_%H-%M-%S + - FEATURES_INVITES=false + - FEATURES_REGISTRATION=false + - FEATURES_HEADLESS=true + - FEATURES_USER_REGISTRATION=false + - FEATURES_OAUTH_REGISTRATION=false + - FEATURES_ANONYMOUS_UPLOAD=true + - WEBSITE_TITLE=File Upload + - WEBSITE_EXTERNAL_LINKS=${ZIPLINE_URL} + volumes: + - zipline_data:/zipline/uploads + - zipline_public:/zipline/public + - zipline_db:/zipline + restart: unless-stopped + networks: + - app-network + networks: app-network: driver: bridge \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf index f8b7a8b..8d2dbb1 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -21,6 +21,10 @@ http { server seq:80; } + upstream zipline { + server zipline:3000; + } + server { listen 80; server_name impr.ink; @@ -81,6 +85,25 @@ http { rewrite ^/seq/(.*)$ /$1 break; } + location /res { + proxy_pass http://zipline; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Prefix /res; + + proxy_request_buffering off; + proxy_buffering off; + proxy_read_timeout 300s; + proxy_send_timeout 300s; + + rewrite ^/res/(.*)$ /$1 break; + rewrite ^/res$ / break; + } + location / { proxy_pass http://webui/; proxy_http_version 1.1; diff --git a/webui/package-lock.json b/webui/package-lock.json index 034abd1..5742bc1 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -12,7 +12,11 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^7.1.1", + "@mui/material": "^7.1.1", + "@mui/x-data-grid": "^8.5.2", + "@mui/x-date-pickers": "^8.5.2", "axios": "^1.9.0", + "lucide-react": "^0.516.0", "next": "15.3.3", "react": "^19.0.0", "react-dom": "^19.0.0" @@ -824,7 +828,6 @@ "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz", "integrity": "sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" @@ -861,7 +864,6 @@ "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.1.1.tgz", "integrity": "sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.1", "@mui/core-downloads-tracker": "^7.1.1", @@ -911,7 +913,6 @@ "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.1.1.tgz", "integrity": "sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.1", "@mui/utils": "^7.1.1", @@ -939,7 +940,6 @@ "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.1.1.tgz", "integrity": "sha512-R2wpzmSN127j26HrCPYVQ53vvMcT5DaKLoWkrfwUYq3cYytL6TQrCH8JBH3z79B6g4nMZZVoaXrxO757AlShaw==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.1", "@emotion/cache": "^11.13.5", @@ -974,7 +974,6 @@ "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.1.1.tgz", "integrity": "sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.1", "@mui/private-theming": "^7.1.1", @@ -1015,7 +1014,6 @@ "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.3.tgz", "integrity": "sha512-2UCEiK29vtiZTeLdS2d4GndBKacVyxGvReznGXGr+CzW/YhjIX+OHUdCIczZjzcRAgKBGmE9zCIgoV9FleuyRQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.1" }, @@ -1033,7 +1031,6 @@ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.1.1.tgz", "integrity": "sha512-BkOt2q7MBYl7pweY2JWwfrlahhp+uGLR8S+EhiyRaofeRYUWL2YKbSGQvN4hgSN1i8poN0PaUiii1kEMrchvzg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.27.1", "@mui/types": "^7.4.3", @@ -1059,6 +1056,131 @@ } } }, + "node_modules/@mui/x-data-grid": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-8.5.2.tgz", + "integrity": "sha512-4KzawLZqRKp3KcGKsTDVz7zkEjACllQD5Zb8ds1QKlA6C3/oIoSU7PsemFLj+RL3rT5aORsLMBl97/egQ5tUhA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "@mui/utils": "^7.1.1", + "@mui/x-internals": "8.5.2", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/x-date-pickers": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-8.5.2.tgz", + "integrity": "sha512-KN0GK5aVetGFB3n4W7XsUI79uTSxftTEhHtDCdQjOOeri2lZSY55MVn/CeYZdpuWlBOD1eTLPtCFzueeUp3m6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "@mui/utils": "^7.1.1", + "@mui/x-internals": "8.5.2", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0", + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", + "date-fns": "^2.25.0 || ^3.2.0 || ^4.0.0", + "date-fns-jalali": "^2.13.0-0 || ^3.2.0-0 || ^4.0.0-0", + "dayjs": "^1.10.7", + "luxon": "^3.0.2", + "moment": "^2.29.4", + "moment-hijri": "^2.1.2 || ^3.0.0", + "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "date-fns": { + "optional": true + }, + "date-fns-jalali": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + }, + "moment-hijri": { + "optional": true + }, + "moment-jalaali": { + "optional": true + } + } + }, + "node_modules/@mui/x-internals": { + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@mui/x-internals/-/x-internals-8.5.2.tgz", + "integrity": "sha512-5YhB2AekK7G8d0YrAjg3WNf0uy3V73JD98WNxJhbIlCraQgl8QOQzr2zNO7MAf/X7mZQtjpjuAsiG3+gI2NVyg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "@mui/utils": "^7.1.1", + "reselect": "^5.1.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/system": "^5.15.14 || ^6.0.0 || ^7.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@next/env": { "version": "15.3.3", "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.3.tgz", @@ -1207,7 +1329,6 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", - "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -1514,8 +1635,7 @@ "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/react": { "version": "19.1.7", @@ -1532,7 +1652,6 @@ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "*" } @@ -1643,7 +1762,6 @@ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", - "peer": true, "engines": { "node": ">=6" } @@ -1783,7 +1901,6 @@ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" @@ -2390,7 +2507,6 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", - "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -2398,6 +2514,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lucide-react": { + "version": "0.516.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.516.0.tgz", + "integrity": "sha512-aybBJzLHcw1CIn3rUcRkztB37dsJATtpffLNX+0/w+ws2p21nYIlOwX/B5fqxq8F/BjqVemnJX8chKwRidvROg==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -2597,7 +2722,6 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2687,7 +2811,6 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -2698,8 +2821,7 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/proxy-from-env": { "version": "1.1.0", @@ -2732,15 +2854,13 @@ "version": "19.1.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "license": "BSD-3-Clause", - "peer": true, "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -2752,6 +2872,12 @@ "react-dom": ">=16.6.0" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", diff --git a/webui/package.json b/webui/package.json index 9b6d4f3..e5cffc8 100644 --- a/webui/package.json +++ b/webui/package.json @@ -13,7 +13,11 @@ "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@mui/icons-material": "^7.1.1", + "@mui/material": "^7.1.1", + "@mui/x-data-grid": "^8.5.2", + "@mui/x-date-pickers": "^8.5.2", "axios": "^1.9.0", + "lucide-react": "^0.516.0", "next": "15.3.3", "react": "^19.0.0", "react-dom": "^19.0.0" diff --git a/webui/src/app/favicon.ico b/webui/src/app/favicon.ico index 718d6fe..b0ae2d4 100644 Binary files a/webui/src/app/favicon.ico and b/webui/src/app/favicon.ico differ diff --git a/webui/src/app/globals.css b/webui/src/app/globals.css deleted file mode 100644 index a2dc41e..0000000 --- a/webui/src/app/globals.css +++ /dev/null @@ -1,26 +0,0 @@ -@import "tailwindcss"; - -:root { - --background: #ffffff; - --foreground: #171717; -} - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; -} diff --git a/webui/src/app/layout.js b/webui/src/app/layout.js index 7bf337d..c649f58 100644 --- a/webui/src/app/layout.js +++ b/webui/src/app/layout.js @@ -1,28 +1,25 @@ -import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; +'use client' -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], +import { CssBaseline } from '@mui/material'; +import { ThemeProvider, createTheme } from '@mui/material/styles'; + +const theme = createTheme({ + palette: { + mode: 'light', + primary: { + main: '#1976d2', + }, + }, }); -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); - -export const metadata = { - title: "Create Next App", - description: "Generated by create next app", -}; - export default function RootLayout({ children }) { return ( -
- {children} + +
- {JSON.stringify(user, null, 2)}
-
-