mirror of
https://github.com/fergalmoran/snapp.git
synced 2025-12-22 09:41:45 +00:00
added unsecure http option
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
- Minor cleaning here and there
|
||||
- 0.6.1
|
||||
- Added export to CSV for operating user, other users and all snapps on db.
|
||||
- Cleaned README and CHANGELOG
|
||||
- Cleaned README and CHANGELOG
|
||||
- 0.6.2
|
||||
- minor clean up of changelog
|
||||
- minor clean up of csv auth needed
|
||||
@@ -69,3 +69,7 @@
|
||||
- Provided placeholder default for better understanding of missing languages file
|
||||
- Corrected README unnecessarely mounting translation folder
|
||||
- Fixed overlay on Single Snapp dashboard
|
||||
- 0.7.2
|
||||
- Fixed typo
|
||||
- Fix on custom theme
|
||||
|
||||
@@ -16,6 +16,7 @@ COPY . /app
|
||||
ENV SNAPP_VERSION=0.7.1
|
||||
|
||||
ENV AUTH_SECRET=lFNiU7T98/44Qlqb4hMUkVcLOpijEI7z722Kxhv4O2Y=
|
||||
ENV ALLOW_UNSECURE_HTTP=false
|
||||
ENV DB_HOST=100.64.0.21
|
||||
ENV DB_PASS=
|
||||
ENV DB_PORT=6379
|
||||
|
||||
@@ -25,7 +25,7 @@ html.dark body {
|
||||
select,
|
||||
input,
|
||||
button {
|
||||
@apply outline-0 ring-0 border-none ;
|
||||
@apply outline-0 ring-0 border-none;
|
||||
}
|
||||
|
||||
.link {
|
||||
|
||||
@@ -115,6 +115,7 @@ async function initializeDBIndexes() {
|
||||
await check_and_set('settings:app:smtp:port', env.SMTP_PORT?.toString()?.toLowerCase());
|
||||
await check_and_set('settings:app:smtp:user', env.SMTP_USER?.toString()?.toLowerCase());
|
||||
await check_and_set('settings:app:smtp:from', env.SMTP_FROM?.toString()?.toLowerCase());
|
||||
await check_and_set('settings:app:allow:unsecure:http', env.ALLOW_UNSECURE_HTTP?.toString()?.toLowerCase());
|
||||
await check_and_set('settings:api:key:vt', env.VIRUSTOTAL_API_KEY?.toString()?.toLowerCase());
|
||||
await check_and_set(
|
||||
'settings:api:key:umami:website:id',
|
||||
|
||||
@@ -30,6 +30,9 @@ export default async function shorten(
|
||||
|
||||
const roles = user.roles;
|
||||
|
||||
const allow_unsecure_http =
|
||||
(await this.getSetting('settings:app:allow:unsecure:http'))?.toString().toLocaleLowerCase() ===
|
||||
'true';
|
||||
const global_max_urls = await this.getSetting('settings:app:limits:max:urls');
|
||||
const max_urls = user?.settings?.max?.urls ?? global_max_urls;
|
||||
const urls = await this.snapps.search().where('user_id').equals(user_id).returnCount();
|
||||
@@ -37,13 +40,13 @@ export default async function shorten(
|
||||
if (urls > max_urls && (!roles.includes('admin') || !roles.includes('superadmin')))
|
||||
return new SnappError(400, { message: 'snapps:max:urls:reached' });
|
||||
|
||||
const regex = new RegExp(/^https:\/\/[^\s/$.?#].[^\s]*$/);
|
||||
const httpRegexp = new RegExp(/^https:\/\/[^\s/$.?#].[^\s]*$/);
|
||||
|
||||
if (!original_url || typeof original_url !== 'string' || original_url.trim() === '')
|
||||
return new SnappError(400, { message: 'snapps:original:url:unset' });
|
||||
|
||||
if (original_url) {
|
||||
if (regex.test(original_url) === false)
|
||||
if (allow_unsecure_http === false && httpRegexp.test(original_url) === false)
|
||||
return new SnappError(400, { message: 'snapps:original:url:invalid' });
|
||||
snapp.original_url = original_url;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ services:
|
||||
image: redis/redis-stack:latest
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /home/snapp/redis/data:rw
|
||||
- /home/snapp/redis:/data:rw
|
||||
networks:
|
||||
- snapp-stack
|
||||
environment:
|
||||
|
||||
@@ -66,7 +66,10 @@ export async function load({ locals, depends, fetch }) {
|
||||
},
|
||||
whitelists: {
|
||||
emails: (await db.redis.zCard(whiteEmailZList)) + (await db.redis.zCard(whiteProviderZList))
|
||||
}
|
||||
},
|
||||
allow_unsecure_http: await db
|
||||
.getSetting('settings:app:allow:unsecure:http')
|
||||
.then((res) => res?.toString().toLowerCase() === 'true')
|
||||
},
|
||||
active_smtp,
|
||||
vtapikey: vtapikey !== undefined && vtapikey !== null
|
||||
@@ -118,6 +121,7 @@ export const actions = {
|
||||
const signup = form.get('signup')?.toString();
|
||||
const home = form.get('home')?.toString();
|
||||
const limits = form.get('limits')?.toString();
|
||||
const allow_unsecure_http = form.get('allowUnsecureHttp')?.toString();
|
||||
|
||||
if (!home || (home !== 'enabled' && home !== 'disabled'))
|
||||
throw error(404, { message: 'settings:not:found' });
|
||||
@@ -125,6 +129,11 @@ export const actions = {
|
||||
throw error(404, { message: 'settings:not:found' });
|
||||
if (!limits || (limits !== 'enabled' && limits !== 'disabled'))
|
||||
throw error(404, { message: 'settings:not:found' });
|
||||
if (
|
||||
!allow_unsecure_http ||
|
||||
(allow_unsecure_http !== 'enabled' && allow_unsecure_http !== 'disabled')
|
||||
)
|
||||
throw error(404, { message: 'settings:not:found' });
|
||||
|
||||
switch (signup) {
|
||||
case 'enabled':
|
||||
@@ -151,6 +160,14 @@ export const actions = {
|
||||
await db.setSetting('settings:app:home:enabled', 'false');
|
||||
break;
|
||||
}
|
||||
switch (allow_unsecure_http) {
|
||||
case 'enabled':
|
||||
await db.setSetting('settings:app:allow:unsecure:http', 'true');
|
||||
break;
|
||||
case 'disabled':
|
||||
await db.setSetting('settings:app:allow:unsecure:http', 'false');
|
||||
break;
|
||||
}
|
||||
|
||||
return { status: 200, success: true, message: 'settings:app:wise:saved' };
|
||||
},
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import Extralarge from '../../../../../lib/ui/typography/extralarge.svelte';
|
||||
import { invalidate, invalidateAll } from '$app/navigation';
|
||||
import CustomToast from '$lib/ui/toaster/customToast.svelte';
|
||||
import { toast } from 'svelte-sonner';
|
||||
@@ -23,12 +22,13 @@
|
||||
import { SlideToggle, getModalStore, type ModalSettings } from '@skeletonlabs/skeleton';
|
||||
import Breadcrumbs from '$lib/ui/crumbs/breadcrumbs.svelte';
|
||||
import { getLocale } from '$lib/i18n';
|
||||
import { H3, ExtraLarge, Lead, Paragraph, Small, Large } from '$lib/ui/typography';
|
||||
import { H3, Lead, Paragraph, Small, Large } from '$lib/ui/typography';
|
||||
import type { SubmitFunction } from './$types.js';
|
||||
const { t } = getLocale();
|
||||
|
||||
export let data, form;
|
||||
let is_saving = false;
|
||||
let allow_unsecure_http = data.app_settings.allow_unsecure_http;
|
||||
let enable_signup = data.app_settings.signup.enabled;
|
||||
let enable_limits = data.app_settings.limits.enabled;
|
||||
let disable_home = !data.app_settings.home.enabled;
|
||||
@@ -95,6 +95,7 @@
|
||||
formData.set('home', disable_home === true ? 'disabled' : 'enabled');
|
||||
formData.set('signup', enable_signup === true ? 'enabled' : 'disabled');
|
||||
formData.set('limits', enable_limits === true ? 'enabled' : 'disabled');
|
||||
formData.set('allowUnsecureHttp', allow_unsecure_http === true ? 'enabled' : 'disabled');
|
||||
|
||||
return async function ({ result }) {
|
||||
await applyAction(result);
|
||||
@@ -181,6 +182,12 @@
|
||||
is_saving = true;
|
||||
document.forms.namedItem('settings')?.requestSubmit();
|
||||
}
|
||||
|
||||
function handle_allow_unsecure_http() {
|
||||
is_saving = true;
|
||||
document.forms.namedItem('settings')?.requestSubmit();
|
||||
}
|
||||
|
||||
function handle_enable_limits() {
|
||||
is_saving = true;
|
||||
document.forms.namedItem('settings')?.requestSubmit();
|
||||
@@ -234,7 +241,7 @@
|
||||
>{$t('settings:app:wise')}
|
||||
{$t('settings:app:switch')}
|
||||
</Paragraph>
|
||||
<label for="enable-signup" class="flex flex-col gap-1 mt-4 mb-2">
|
||||
<label for="enable-signup" class="flex flex-col gap-1 mb-2">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<Paragraph class="font-semibold flex gap-2 items-center">
|
||||
<UsersIcon class="w-4 h-4" />
|
||||
@@ -255,7 +262,7 @@
|
||||
</div>
|
||||
<Small>{$t('settings:app:sign:up:description')}</Small>
|
||||
</label>
|
||||
<label for="enable-homepage" class="flex flex-col gap-1 mt-4 mb-2">
|
||||
<label for="enable-homepage" class="flex flex-col gap-1 mb-2">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<Paragraph class="font-semibold flex gap-2 items-center">
|
||||
<HomeIcon class="w-4 h-4" />
|
||||
@@ -274,7 +281,28 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Small>{$t('settings:app:home:description')}</Small>
|
||||
<Small>{@html $t('settings:app:home:description')}</Small>
|
||||
</label>
|
||||
<label for="allow-unsecure-http" class="flex flex-col gap-1 mb-2">
|
||||
<div class="flex w-full justify-between items-center">
|
||||
<Paragraph class="font-semibold flex gap-2 items-center">
|
||||
<HomeIcon class="w-4 h-4" />
|
||||
{$t('settings:app:allow:unsecure:http')}
|
||||
</Paragraph>
|
||||
<div class="flex items-center justify-end scale-[.8]">
|
||||
<SlideToggle
|
||||
size="sm"
|
||||
id="allow-unsecure-http"
|
||||
name="allow_unsecure_http"
|
||||
background="bg-surface-300-600-token"
|
||||
active="bg-success-300-600-token"
|
||||
disabled={is_saving}
|
||||
bind:checked={allow_unsecure_http}
|
||||
on:change={handle_allow_unsecure_http}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Small>{@html $t('settings:app:allow:unsecure:http:description')}</Small>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,9 +13,13 @@ export async function load({ locals, parent }) {
|
||||
|
||||
const isAdmin = await db.admin(session.user.id);
|
||||
|
||||
const ALLOW_UNSECURE_HTTP =
|
||||
(await db.getSetting('settings:app:allow:unsecure:http'))?.toString()?.toLowerCase() === 'true';
|
||||
console.log(ALLOW_UNSECURE_HTTP)
|
||||
return {
|
||||
max_urls: user.settings?.max?.urls ?? data.max_urls ?? 0,
|
||||
existing: await db.snapps.search().where('user_id').equal(session.user.id).returnCount(),
|
||||
allow_unsecure_http: ALLOW_UNSECURE_HTTP,
|
||||
isAdmin: (typeof isAdmin === 'boolean' && isAdmin) || false
|
||||
};
|
||||
}
|
||||
@@ -43,7 +47,7 @@ export const actions: Actions = {
|
||||
let expiration: number | undefined;
|
||||
|
||||
if (_expires) expiration = _expires === '-1' ? -1 : Math.ceil(Number(_expires) / 1000);
|
||||
|
||||
|
||||
let newSnapp: Partial<DBSnapp> = {
|
||||
id: randomUUID(),
|
||||
original_url,
|
||||
@@ -53,7 +57,7 @@ export const actions: Actions = {
|
||||
notes,
|
||||
user_id: session.user.id
|
||||
};
|
||||
|
||||
|
||||
const result = await db.shorten(newSnapp, fetch, expiration);
|
||||
|
||||
if (result.status !== 200) {
|
||||
|
||||
@@ -83,6 +83,11 @@
|
||||
is_invalid_url = false;
|
||||
is_valid_url = false;
|
||||
} else {
|
||||
if (data.allow_unsecure_http) {
|
||||
is_valid_url = true;
|
||||
is_invalid_url = false;
|
||||
return;
|
||||
}
|
||||
is_valid_url = httpsRegexp.test(original_url);
|
||||
is_invalid_url = !is_valid_url;
|
||||
}
|
||||
@@ -157,7 +162,7 @@
|
||||
<label for="original_url" class="flex flex-col gap-1">
|
||||
<Paragraph class="font-semibold">{$t('snapps:original:url:label')}</Paragraph>
|
||||
<div
|
||||
class="input-group max-w-sm input-group-divider grid-cols-[auto_1fr_auto]"
|
||||
class="input-group input-group-divider grid-cols-[auto_1fr_auto]"
|
||||
class:variant-glass-success={is_valid_url}
|
||||
class:variant-glass-error={is_invalid_url}
|
||||
>
|
||||
@@ -177,11 +182,13 @@
|
||||
bind:value={original_url}
|
||||
/>
|
||||
</div>
|
||||
<Small class="mt-1">{@html $t('snapps:original:url:helper')}</Small>
|
||||
<Small class="mt-1"
|
||||
>{#if data.allow_unsecure_http}{@html $t('snapps:original:url:helper')}{/if}</Small
|
||||
>
|
||||
</label>
|
||||
<label for="shortcode" class="flex flex-col gap-1">
|
||||
<Paragraph class="font-semibold">{$t('snapps:shortcode:label')}</Paragraph>
|
||||
<div class="input-group max-w-sm input-group-divider grid-cols-[auto_1fr_auto]">
|
||||
<div class="input-group input-group-divider grid-cols-[auto_1fr_auto]">
|
||||
<div class="flex items-center w-10" style:padding="0" style:justify-content="center">
|
||||
<LinkIcon strokeWidth="1.5" class="w-5 h-5" />
|
||||
</div>
|
||||
@@ -319,7 +326,7 @@
|
||||
>{@html $t('snapps:sections:advanced:secret:description')}</Paragraph
|
||||
>
|
||||
<div
|
||||
class="input-group max-w-sm h-10 mt-2 flex-grow-0input-group-divider grid-cols-[auto_1fr_auto]"
|
||||
class="input-group h-10 mt-2 flex-grow-0input-group-divider grid-cols-[auto_1fr_auto]"
|
||||
>
|
||||
<div class="flex items-center w-10" style:padding="0" style:justify-content="center">
|
||||
<KeyIcon strokeWidth="1.5" class="w-5 h-5" />
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/* :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;
|
||||
} */
|
||||
@@ -209,7 +209,9 @@
|
||||
"settings:app:exports:all": "Export all",
|
||||
"settings:app:exports:confirm:message": "This will exports all snapps in the database, and may require some time depending on the size of the database. Do you want to continue?",
|
||||
"settings:app:exports:helper": "If you want to leave Snapp you can export a CSV with all your shortened-url.",
|
||||
"settings:app:home:description": "Redirect users to login or dashboard instead..",
|
||||
"settings:app:home:description": "Redirect users to login or dashboard instead.",
|
||||
"settings:app:allow:unsecure:http": "Allow Unsecure HTTP",
|
||||
"settings:app:allow:unsecure:http:description": "Allow the use of <b class='text-error-500'>unsecure HTTP</b> target website during creation of snapps.",
|
||||
"settings:app:home:label": "Disable homepage",
|
||||
"settings:app:private:saved": "Preferences updated",
|
||||
"settings:app:sign:up:description": "Allow external signups to this app.",
|
||||
|
||||
Reference in New Issue
Block a user