diff --git a/README.md b/README.md index d5323ab..a11db5b 100644 --- a/README.md +++ b/README.md @@ -72,40 +72,57 @@ Read more and have docker compose in [announcement discussion](https://github.co ```yml version: "3" services: - redis-stack: + redis: image: redis/redis-stack:latest - ports: - - 6379:6379/tcp - - 8001:8001 + # ports: # you can specify LOCAL_IP OR VPN_IP to make db or redis insight available privately + # - (LOCAL_IP or VPN_IP):6379:6379/tcp + # - (LOCAL_IP or VPN_IP):8001:8001 volumes: - - /home/snapp/redis/test:/data:rw + - /home/snapp/redis/test:/data:rw + # this make sure to enable persistance through docker restarts + # and shutdowns or updates -- change it to a folder of your choise - /etc/localtime:/etc/localtime:ro + networks: + - snapp-stack environment: - REDIS_ARGS: "--save 60 1 --appendonly yes" + REDIS_ARGS: "--save 60 1 --appendonly yes" # Optional: `--requirepass mypassword` + snapp: image: uraniadev/snapp:0.7.test ports: - 3000:3000 + volumes: + - /home/snapp/app/translations:/app/translations:ro + # - /home/snapp/redis/theme/theme.css:/app/static/custom-theme.css + # See (Discussion about theming)[https://github.com/urania-dev/snapp/discussions/18] + networks: + - snapp-stack environment: - AUTH_SECRET: - DB_HOST: - DB_PASS: - DB_PORT: 6379 - DB_IDX: 0 - ENABLE_LIMITS: false - ENABLE_SIGNUP: true - ENABLE_HOME: false - DEFAULT_THEME: dark - DEFAULT_LANG: en - LOCALIZATION_FOLDER: /app/translations - MAX_SHORT_URL: 10 - MAX_USAGES: 0 - MAX_RPM: 0 - MAX_RPD: 0 - VIRUSTOTAL_API_KEY: - PUBLIC_URL: https://example.com - ORIGIN: https://example.com + AUTH_SECRET: very-secure-and-long-pass-words # random string, generate it with bash: openssl rand -base64 32 + DB_HOST: redis + # DB_PASS: # Optional: Requires `--requirepass mypassword` in REDIS_ARGS + # DB_PORT: 6379 + # DB_IDX: 0 + # ENABLE_LIMITS: false + # ENABLE_SIGNUP: true + # ENABLE_HOME: false + # DEFAULT_THEME: dark + # DEFAULT_LANG: en + # LOCALIZATION_FOLDER: /app/translations + # MAX_SHORT_URL: 10 + # MAX_USAGES: 0 + # MAX_RPM: 0 + # MAX_RPD: 0 + # UMAMI_WEBSITE_ID: + # UMAMI_URL: + # VIRUSTOTAL_API_KEY: + # PUBLIC_URL: http://host:5173 + # ORIGIN: http://host:5173 + ## all commented vars are optional. Note that omitting PUBLIC_URL and ORIGIN it expects to be used from http://localhost:3000 +networks: + snapp-stack: # Snapp Network so Snapp and redis can communicate but redis is isolated from the wan + external: false ``` ## Migration diff --git a/src/lib/db/index.ts b/src/lib/db/index.ts index 59360e7..8a6923f 100644 --- a/src/lib/db/index.ts +++ b/src/lib/db/index.ts @@ -27,6 +27,7 @@ import isBlackListedEmail from './users/isEmailBlackListed'; import trackMaxURLs from './settings/trackMaxURLs'; import trackRPDandRPM from './settings/trackRPDandRPM'; import hasWhiteList from './snapps/has_whitelist'; +import checkRepoInfo from './repoInfo'; export const domainZList = 'settings:app:banlists:website' as const; export const usernameZList = 'settings:app:banlists:username' as const; @@ -47,32 +48,53 @@ export class Database { this.snapps = new Repository(snappsSchema, redis); this.apikeys = new Repository(apiKeysSchema, redis); this.usages = new Repository(usagesSchema, redis); + signinUser.bind(this); + signupUser.bind(this); + updateUser.bind(this); + deleteUser.bind(this); + admin.bind(this); + shortenSnapp.bind(this); + editSnapp.bind(this); + authorship.bind(this); + getSetting.bind(this); + setSetting.bind(this); + checkRPMLimit.bind(this); + checkRPDLimit.bind(this); + trackMaxURLs.bind(this); + trackRPDandRPM.bind(this); + isWhiteListed.bind(this); + isBlackListed.bind(this); + isBlackListedEmail.bind(this); + hasWhiteList.bind(this); + checkRepoInfo.bind(this); } - signinUser = signinUser.bind(this); - signupUser = signupUser.bind(this); - updateUser = updateUser.bind(this); - deleteUser = deleteUser.bind(this); - admin = admin.bind(this); + signinUser = signinUser; + signupUser = signupUser; + updateUser = updateUser; + deleteUser = deleteUser; + admin = admin; - shorten = shortenSnapp.bind(this); - edit = editSnapp.bind(this); - authorship = authorship.bind(this); + shorten = shortenSnapp; + edit = editSnapp; + authorship = authorship; - getSetting = getSetting.bind(this); - setSetting = setSetting.bind(this); + getSetting = getSetting; + setSetting = setSetting; - rpm = checkRPMLimit.bind(this); - rpd = checkRPDLimit.bind(this); + rpm = checkRPMLimit; + rpd = checkRPDLimit; - trackMaxURLs = trackMaxURLs.bind(this); - trackRPDandRPM = trackRPDandRPM.bind(this); + trackMaxURLs = trackMaxURLs; + trackRPDandRPM = trackRPDandRPM; - whitelisted = isWhiteListed.bind(this); - blacklisted = isBlackListed.bind(this); - blacklistedEmail = isBlackListedEmail.bind(this); + whitelisted = isWhiteListed; + blacklisted = isBlackListed; + blacklistedEmail = isBlackListedEmail; - hasWhiteList = hasWhiteList.bind(this); + hasWhiteList = hasWhiteList; + + repoInfo = checkRepoInfo; } let password = env.DB_PASS ?? ''; @@ -89,7 +111,7 @@ async function getClient() { console.log(err); }) .connect(); - else throw new Error('This version of Snapps requires REDIS STACK, please read documentation') + else throw new Error('This version of Snapps requires REDIS STACK, please read documentation'); } const client = await getClient(); diff --git a/src/lib/db/repoInfo/index.ts b/src/lib/db/repoInfo/index.ts new file mode 100644 index 0000000..2f9de00 --- /dev/null +++ b/src/lib/db/repoInfo/index.ts @@ -0,0 +1,20 @@ +import type { Database } from '..'; + +export default async function checkRepoInfo( + this: Database, + fetch: (input: string | URL | Request, init?: RequestInit | undefined) => Promise +) { + const key = `settings:repo:info`; + + const stored = await this.redis.get(key); + + if (stored) { + return JSON.parse(stored); + } else { + const repoInfo = await (await fetch('https://api.github.com/repos/urania-dev/snapp')).json(); + await this.redis.set(key, JSON.stringify(repoInfo)); + await this.redis.expire(key, 60 * 60 * 24); + + return repoInfo; + } +} diff --git a/src/lib/db/settings/trackMaxURLs.ts b/src/lib/db/settings/trackMaxURLs.ts index 0b47b02..0c5b41e 100644 --- a/src/lib/db/settings/trackMaxURLs.ts +++ b/src/lib/db/settings/trackMaxURLs.ts @@ -1,6 +1,4 @@ -import getLanguage from '$lib/api/utils/getLanguage'; import parseNumber from '$lib/utils/parseNumber'; -import { error } from '@sveltejs/kit'; import type { Database } from '..'; export default async function trackMaxURLs(this: Database, apiKey: DBAPIKey, _EN?: Translation) { @@ -11,8 +9,6 @@ export default async function trackMaxURLs(this: Database, apiKey: DBAPIKey, _EN ); if (!is_limited) return false; - const EN = _EN ? _EN : await getLanguage(); - const global_limit_urls = await parseNumber(this.getSetting('settings:app:limits:max:urls')); const user_limit = ( diff --git a/src/lib/db/settings/trackRPDandRPM.ts b/src/lib/db/settings/trackRPDandRPM.ts index 71bf62e..db136dd 100644 --- a/src/lib/db/settings/trackRPDandRPM.ts +++ b/src/lib/db/settings/trackRPDandRPM.ts @@ -1,6 +1,4 @@ -import getLanguage from '$lib/api/utils/getLanguage'; import parseNumber from '$lib/utils/parseNumber'; -import { error } from 'console'; import type { Database } from '..'; export default async function trackRPDandRPM(this: Database, apiKey: DBAPIKey, _EN?: Translation) { diff --git a/src/routes/(frontend)/+page.server.ts b/src/routes/(frontend)/+page.server.ts index 5f84e90..d99d12e 100644 --- a/src/routes/(frontend)/+page.server.ts +++ b/src/routes/(frontend)/+page.server.ts @@ -2,13 +2,15 @@ import { dev } from '$app/environment'; import { db } from '$lib/db/index.js'; import { redirect } from '@sveltejs/kit'; -export async function load({ locals }) { - const session = await locals.getSession(); +export async function load({ fetch }) { + const repoInfo = await db.repoInfo(fetch); const disabled_home = await db .getSetting('settings:app:home:enabled') .then((res) => res === 'false'); if (disabled_home === true) throw redirect(302, '/dashboard'); + + return { repoInfo }; } export const actions = { @@ -27,7 +29,11 @@ export const actions = { if (!session) return { success: true, theme: theme ?? 'dark' }; else { if (session.user.id === undefined) return; - const user = await db.users.search().where('id').equalTo(session.user.id).first() as DBUser | null; + const user = (await db.users + .search() + .where('id') + .equalTo(session.user.id) + .first()) as DBUser | null; if (user) await db.updateUser({ ...user, settings: { ...user.settings, theme: theme ?? 'dark' } }); return { success: true, mode: theme ?? 'dark' }; diff --git a/src/routes/(frontend)/+page.svelte b/src/routes/(frontend)/+page.svelte index bb0ecc2..8131547 100644 --- a/src/routes/(frontend)/+page.svelte +++ b/src/routes/(frontend)/+page.svelte @@ -10,11 +10,14 @@ import AuthJSLogo from '$lib/logo/authjs.svg?raw'; import RedisLogo from '$lib/logo/redis.svg?raw'; + import GitHubIcon from '$lib/logo/github.svg?raw'; + import DockerHubIcon from '$lib/logo/docker.svg?raw'; + + import StarIcon from 'lucide-svelte/icons/star'; import StackIcon from 'lucide-svelte/icons/layers'; import FeaturesIcon from 'lucide-svelte/icons/award'; import CloneIcon from 'lucide-svelte/icons/copy-check'; import ContainerIcon from 'lucide-svelte/icons/container'; - import CorsIcon from 'lucide-svelte/icons/shield-alert'; import DownloadIcon from 'lucide-svelte/icons/hard-drive-download'; import DevIcon from 'lucide-svelte/icons/keyboard'; import BuildIcon from 'lucide-svelte/icons/server-cog'; @@ -27,17 +30,44 @@ import { CodeBlock } from '@skeletonlabs/skeleton'; const { t } = getLocale(); const APPNAME = $t('global:appname'); + + export let data; {$t('global:appname')} -
-

-

+
{$t('home:intro', { appname: APPNAME })}
@@ -132,129 +162,142 @@
-
-
- {@html $t('home:manual:install')} -
-
- -
- -
- {@html $t('home:manual:install:steps')} -
- -
- -
- {@html $t('home:manual:install:redis')} -
- -
- -
- - {@html $t('home:manual:install:clone:0')} - {@html $t('home:manual:install:clone:1')} - -
- -
- -
- - {@html $t('home:manual:install:download:0')}
- {@html $t('home:manual:install:download:1')} -
-
- -
- -
- - {@html $t('home:manual:install:env:0')} - {@html $t('home:manual:install:env:1')} - -
- -
- -
- - - {@html $t('home:manual:install:dev:0')}
- {@html $t('home:manual:install:dev:1')} -
-
- -
- -
- - {@html $t('home:manual:install:build:0')}
- {@html $t('home:manual:install:build:1')} -
-
- -
- -
- - {@html $t('home:manual:install:run:0')}
- {@html $t('home:manual:install:run:1')} -
-
-
-
- {@html $t('home:docker')} + {@html $t('home:manual:install')}
-
- +
+
- + +
+ {@html $t('home:manual:install:steps')} +
+ +
+ +
+ {@html $t('home:manual:install:redis')} +
+ +
+ +
+ + {@html $t('home:manual:install:clone:0')} + {@html $t('home:manual:install:clone:1')} + +
+ +
+ +
+ + {@html $t('home:manual:install:download:0')}
+ {@html $t('home:manual:install:download:1')} +
+
+ +
+ +
+ + {@html $t('home:manual:install:env:0')} + {@html $t('home:manual:install:env:1')} + +
+ +
+
-
- {$t('home:docker:description')} - + + {@html $t('home:manual:install:dev:0')}
+ {@html $t('home:manual:install:dev:1')} +
+ + +
+
+ + {@html $t('home:manual:install:build:0')}
+ {@html $t('home:manual:install:build:1')} +
- -
- -
- - {@html $t('home:docker:run:cors')} - - +
+ + {@html $t('home:manual:install:run:0')}
+ {@html $t('home:manual:install:run:1')} +
-
+
{$t('home:migration')}
- + {$t('home:migration:description')}
+ +
+
+ {@html $t('home:docker')} +
+
+ +
+
+ +
+ + {$t('home:docker:description')} +
+ +
+ + {@html $t('home:docker:better', { url: 'https://github.com/urania-dev/snapp' })} + +
+

diff --git a/static/custom-theme.css b/static/custom-theme.css index 0612f38..4829ba5 100644 --- a/static/custom-theme.css +++ b/static/custom-theme.css @@ -1,3 +1,94 @@ -:root{ - --color-surface-950: "30 42 52", -} \ No newline at end of file +/* :root [data-theme="snappTheme"] { + --theme-font-family-base: `system-ui`; + --theme-font-family-heading: `system-ui`; + --theme-font-color-base: 0 0 0; + --theme-font-color-dark: 255 255 255; + --theme-rounded-base: 0px; + --theme-rounded-container: 0px; + --theme-border-base: 1px; + + --on-primary: 0 0 0; + --on-secondary: 255 255 255; + --on-tertiary: 255 255 255; + --on-success: 0 0 0; + --on-warning: 0 0 0; + --on-error: 255 255 255; + --on-surface: 255 255 255; + + --color-primary-50: 249 243 225; + --color-primary-100: 246 239 215; + --color-primary-200: 244 235 205; + --color-primary-300: 238 223 175; + --color-primary-400: 225 199 115; + --color-primary-500: 212 175 55; + --color-primary-600: 191 158 50; + --color-primary-700: 159 131 41; + --color-primary-800: 127 105 33; + --color-primary-900: 104 86 27; + + --color-secondary-50: 238 231 236; + --color-secondary-100: 233 222 229; + --color-secondary-200: 227 214 223; + --color-secondary-300: 210 190 203; + --color-secondary-400: 177 141 164; + --color-secondary-500: 143 92 125; + --color-secondary-600: 129 83 113; + --color-secondary-700: 107 69 94; + --color-secondary-800: 86 55 75; + --color-secondary-900: 70 45 61; + + --color-tertiary-50: 222 228 233; + --color-tertiary-100: 211 218 225; + --color-tertiary-200: 201 209 218; + --color-tertiary-300: 168 182 196; + --color-tertiary-400: 102 127 151; + --color-tertiary-500: 37 72 107; + --color-tertiary-600: 33 65 96; + --color-tertiary-700: 28 54 80; + --color-tertiary-800: 22 43 64; + --color-tertiary-900: 18 35 52; + + --color-success-50: 242 247 220; + --color-success-100: 238 245 208; + --color-success-200: 233 242 197; + --color-success-300: 220 235 161; + --color-success-400: 194 219 91; + --color-success-500: 168 204 21; + --color-success-600: 151 184 19; + --color-success-700: 126 153 16; + --color-success-800: 101 122 13; + --color-success-900: 82 100 10; + + --color-warning-50: 248 230 222; + --color-warning-100: 245 221 211; + --color-warning-200: 243 213 200; + --color-warning-300: 236 188 167; + --color-warning-400: 221 137 101; + --color-warning-500: 207 87 35; + --color-warning-600: 186 78 32; + --color-warning-700: 155 65 26; + --color-warning-800: 124 52 21; + --color-warning-900: 101 43 17; + + --color-error-50: 249 221 234; + --color-error-100: 246 209 228; + --color-error-200: 244 198 221; + --color-error-300: 238 163 200; + --color-error-400: 225 94 159; + --color-error-500: 212 25 118; + --color-error-600: 191 23 106; + --color-error-700: 159 19 89; + --color-error-800: 127 15 71; + --color-error-900: 104 12 58; + + --color-surface-50: 224 225 226; + --color-surface-100: 214 215 216; + --color-surface-200: 204 206 206; + --color-surface-300: 173 176 177; + --color-surface-400: 112 116 119; + --color-surface-500: 51 57 60; + --color-surface-600: 46 51 54; + --color-surface-700: 38 43 45; + --color-surface-800: 31 34 36; + --color-surface-900: 25 28 29; +} */ diff --git a/translations/en.json b/translations/en.json index ebdca14..4aa192d 100644 --- a/translations/en.json +++ b/translations/en.json @@ -342,7 +342,7 @@ "snapps:import": "Import Snapps", "snapps:import:sqlite:button": "Upgrade Database", "snapps:import:sqlite:modal:label": "Upgrade Database", - "snapps:import:sqlite:modal:helper":"A SQLITE file from a previous version has been detected. Do you want to try importing the previous Snapp? This operation may take a long time for large databases.", + "snapps:import:sqlite:modal:helper": "A SQLITE file from a previous version has been detected. Do you want to try importing the previous Snapp? This operation may take a long time for large databases.", "snapps:import:helper": "Import CSV File from previous version of Snapp", "snapps:import:label": "Upload a CSV File", "snapps:import:label:assign": "Assign snapps to users", @@ -424,10 +424,8 @@ "home:manual:install:run:0": "Run and enjoy!", "home:manual:install:run:1": "node -r dotenv/config build", "home:docker": "Using Docker Container", - "home:docker:description": "Simply type in your terminal", - "home:docker:run": "docker run -p 3000:3000 uraniadev/snapp:latest", - "home:docker:run:cors": "If you run into CORS errors, remember to set PUBLIC_URL and ORIGIN env variables", - "home:docker:run:origin": "docker run -p 3000:3000 \n -e ORIGIN=https://example.com \n -e PUBLIC_URL=https://example.com \n uraniadev/snapp:latest", + "home:docker:description": "Use this docker-compose.yml to run your Snapp", + "home:docker:better": "You can find a better docker compose on our Github Repository.", "home:migration": "Migration", "home:migration:description": "Latest versions of Snapp included CSV Export in order to facilitate migration. Simply login and import your urls from dashboard, and continue from where you left.", diff --git a/translations/it.json b/translations/it.json index 8f3fe4d..3e1148d 100644 --- a/translations/it.json +++ b/translations/it.json @@ -343,8 +343,8 @@ "snapps:import": "Importa Snapps", "snapps:import:sqlite:button": "Aggiorna Database", - "snapps:import:sqlite:modal:label":"Aggiorna Database", - "snapps:import:sqlite:modal:helper":"Un file SQLITE di una precedente versione è stato rilevato. Vuoi provare l'importazione dei precedenti Snapp? Questa operazione potrebbe richiedere molto tempo in caso di database corposi", + "snapps:import:sqlite:modal:label": "Aggiorna Database", + "snapps:import:sqlite:modal:helper": "Un file SQLITE di una precedente versione è stato rilevato. Vuoi provare l'importazione dei precedenti Snapp? Questa operazione potrebbe richiedere molto tempo in caso di database corposi", "snapps:import:helper": "Importa il CSV di una versione precedente di Snapp", "snapps:import:label": "Carica un CSV", "snapps:import:label:assign": "Assegna snapps agli utenti", @@ -425,10 +425,8 @@ "home:manual:install:run:0": "Esegui e goditi!", "home:manual:install:run:1": "node -r dotenv/config build", "home:docker": "Utilizzo del container Docker", - "home:docker:description": "Scrivi semplicemente nel tuo terminale", - "home:docker:run": "docker run -p 3000:3000 uraniadev/snapp:latest", - "home:docker:run:cors": "Se incontri errori di CORS, ricorda di impostare le variabili d'ambiente PUBLIC_URL e ORIGIN", - "home:docker:run:origin": "docker run -p 3000:3000 \n -e ORIGIN=https://example.com \n -e PUBLIC_URL=https://example.com \n uraniadev/snapp:latest", + "home:docker:description": "Usa questo docker-compose.yml per far partire il tuo Snapp", + "home:docker:better": "Puoi trovare un docker compose migliore sul nostro Github Repository.", "home:migration": "Migrazione", "home:migration:description": "Le ultime versioni di Snapp includono l'esportazione CSV per facilitare la migrazione. Effettua semplicemente il login e importa i tuoi URL dal dashboard e continua da dove hai lasciato.",