fix: hook.ts - relogin needed

updated packages
fix: Lots of typescript thingy
fix: ssl request flow
fix: proxy cleanup flow
This commit is contained in:
Andras Bacsai
2022-02-18 13:59:23 +01:00
parent 4d8bf57135
commit 2ce64ac213
33 changed files with 243 additions and 247 deletions

View File

@@ -1,74 +1,25 @@
/// <reference types="@sveltejs/kit" />
interface Cookies {
teamId?: string;
gitlabToken?: string;
'kit.session'?: string;
}
interface Locals {
gitlabToken?: string;
user: {
teamId: string;
permission: string;
isAdmin: boolean;
};
session: {
data: {
uid?: string;
teams?: string[];
expires?: string;
};
};
declare namespace App {
interface Locals {
session: import('svelte-kit-cookie-session').Session<SessionData>;
cookies: Record<string, string>;
}
interface Platform {}
interface Session extends SessionData {}
interface Stuff {}
}
type Applications = {
name: string;
domain: string;
};
interface Hash {
iv: string;
content: string;
interface SessionData {
version?: string;
userId?: string | null;
teamId?: string | null;
permission?: string;
isAdmin?: boolean;
expires?: string | null;
gitlabToken?: string | null;
}
interface BuildPack {
name: string;
}
// TODO: Not used, not working what?!
enum GitSource {
Github = 'github',
Gitlab = 'gitlab',
Bitbucket = 'bitbucket'
}
type RawHaproxyConfiguration = {
_version: number;
data: string;
};
type NewTransaction = {
_version: number;
id: string;
status: string;
};
type HttpRequestRuleForceSSL = {
return_hdrs: null;
cond: string;
cond_test: string;
index: number;
redir_code: number;
redir_type: string;
redir_value: string;
type: string;
};
// TODO: No any please
type HttpRequestRule = {
_version: number;
data: Array<any>;
};
type DateTimeFormatOptions = {
localeMatcher?: 'lookup' | 'best fit';
weekday?: 'long' | 'short' | 'narrow';
@@ -84,3 +35,24 @@ type DateTimeFormatOptions = {
hour12?: boolean;
timeZone?: string;
};
interface Hash {
iv: string;
content: string;
}
type RawHaproxyConfiguration = {
_version: number;
data: string;
};
type NewTransaction = {
_version: number;
id: string;
status: string;
};
type Application = {
name: string;
domain: string;
};

View File

@@ -2,7 +2,7 @@ import dotEnvExtended from 'dotenv-extended';
dotEnvExtended.load();
import type { GetSession } from '@sveltejs/kit';
import { handleSession } from 'svelte-kit-cookie-session';
import { getUserDetails, isTeamIdTokenAvailable, sentry } from '$lib/common';
import { getUserDetails, sentry } from '$lib/common';
import { version } from '$lib/common';
import cookie from 'cookie';
import { dev } from '$app/env';
@@ -16,22 +16,29 @@ export const handle = handleSession(
async function ({ event, resolve }) {
let response;
try {
const cookies: Cookies = cookie.parse(event.request.headers.get('cookie') || '');
if (cookies['kit.session']) {
const { permission, teamId } = await getUserDetails(event, false);
event.locals.user = {
let gitlabToken = event.locals.cookies.gitlabToken;
if (event.locals.cookies['kit.session']) {
const { permission, teamId, userId } = await getUserDetails(event, false);
const newSession = {
userId,
teamId,
permission,
isAdmin: permission === 'admin' || permission === 'owner'
isAdmin: permission === 'admin' || permission === 'owner',
expires: event.locals.session.data.expires,
gitlabToken: gitlabToken
};
if (JSON.stringify(event.locals.session.data) !== JSON.stringify(newSession)) {
event.locals.session.data = { ...newSession };
}
}
if (cookies.gitlabToken) {
event.locals.gitlabToken = cookies.gitlabToken;
}
response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/webhooks/success')
});
} catch (error) {
console.log(error);
response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/webhooks/success')
});
@@ -62,17 +69,13 @@ export const handle = handleSession(
}
);
export const getSession: GetSession = function (request) {
export const getSession: GetSession = function ({ locals }) {
return {
version,
gitlabToken: request.locals?.gitlabToken || null,
uid: request.locals.session.data?.uid || null,
teamId: request.locals.user?.teamId || null,
permission: request.locals.user?.permission,
isAdmin: request.locals.user?.isAdmin || false
...locals.session.data
};
};
export async function handleError({ error, event }) {
if (!dev) sentry.captureException(error, { event });
if (!dev) sentry.captureException(error, event);
}

View File

@@ -67,7 +67,7 @@ export const isTeamIdTokenAvailable = (request) => {
};
export const getTeam = (event) => {
const cookies: Cookies = Cookie.parse(event.request.headers.get('cookie'));
const cookies = Cookie.parse(event.request.headers.get('cookie'));
if (cookies.teamId) {
return cookies.teamId;
} else if (event.locals.session.data.teamId) {
@@ -78,7 +78,7 @@ export const getTeam = (event) => {
export const getUserDetails = async (event, isAdminRequired = true) => {
const teamId = getTeam(event);
const userId = event.locals.session.data.uid || null;
const userId = event.locals.session.data.userId || null;
const { permission = 'read' } = await db.prisma.permission.findFirst({
where: { teamId, userId },
select: { permission: true },

View File

@@ -6,6 +6,7 @@
export let description;
export let isCenter = true;
export let disabled = false;
export let dataTooltip = null;
</script>
<div class="flex items-center py-4 pr-8">
@@ -14,7 +15,7 @@
<Explainer text={description} />
</div>
</div>
<div class:text-center={isCenter}>
<div class:tooltip={dataTooltip} class:text-center={isCenter} data-tooltip={dataTooltip}>
<div
type="button"
on:click

View File

@@ -1,5 +1,5 @@
import { decrypt, encrypt } from '$lib/crypto';
import { removeProxyConfiguration, removeWwwRedirection } from '$lib/haproxy';
import { removeProxyConfiguration } from '$lib/haproxy';
import { asyncExecShell, getEngine } from '$lib/common';
import { getDomain, removeDestinationDocker } from '$lib/common';

View File

@@ -2,6 +2,7 @@ import { dev } from '$app/env';
import { sentry } from '$lib/common';
import * as Prisma from '@prisma/client';
import { default as ProdPrisma } from '@prisma/client';
import type { PrismaClientOptions } from '@prisma/client/runtime';
import generator from 'generate-password';
import forge from 'node-forge';
@@ -19,28 +20,20 @@ if (!dev) {
PrismaClient = ProdPrisma.PrismaClient;
P = ProdPrisma.Prisma;
}
let prismaOptions = {
export const prisma = new PrismaClient({
errorFormat: 'pretty',
rejectOnNotFound: false
};
if (dev) {
prismaOptions = {
errorFormat: 'pretty',
rejectOnNotFound: false,
log: [
{
emit: 'event',
level: 'query'
}
]
};
}
export const prisma = new PrismaClient(prismaOptions);
});
export function ErrorHandler(e) {
if (e! instanceof Error) {
e = new Error(e.toString());
}
let truncatedError = e;
if (e.stdout) {
truncatedError = e.stdout;
}
if (e.message?.includes('docker run')) {
let truncatedArray = [];
truncatedArray = truncatedError.message.split('-').filter((line) => {

View File

@@ -12,13 +12,16 @@ export async function login({ email, password }) {
const users = await prisma.user.count();
const userFound = await prisma.user.findUnique({
where: { email },
include: { teams: true },
include: { teams: true, permission: true },
rejectOnNotFound: false
});
console.log(userFound);
// Registration disabled if database is not seeded properly
const { isRegistrationEnabled, id } = await db.listSettings();
let uid = cuid();
let permission = 'read';
let isAdmin = false;
// Disable registration if we are registering the first user.
if (users === 0) {
await prisma.setting.update({ where: { id }, data: { isRegistrationEnabled: false } });
@@ -50,6 +53,8 @@ export async function login({ email, password }) {
};
}
uid = userFound.id;
// permission = userFound.permission;
isAdmin = true;
}
} else {
// If registration disabled, return 403
@@ -61,6 +66,8 @@ export async function login({ email, password }) {
const hashedPassword = await bcrypt.hash(password, saltRounds);
if (users === 0) {
permission = 'owner';
isAdmin = true;
await prisma.user.create({
data: {
id: uid,
@@ -103,8 +110,10 @@ export async function login({ email, password }) {
'Set-Cookie': `teamId=${uid}; HttpOnly; Path=/; Max-Age=15778800;`
},
body: {
uid,
teamId: uid
userId: uid,
teamId: uid,
permission,
isAdmin
}
};
}

View File

@@ -48,7 +48,8 @@ export async function completeTransaction(transactionId) {
return await haproxy.put(`v2/services/haproxy/transactions/${transactionId}`);
}
export async function removeProxyConfiguration({ domain }) {
export async function removeProxyConfiguration(fqdn) {
const domain = getDomain(fqdn);
const haproxy = await haproxyInstance();
const backendFound = await haproxy
.get(`v2/services/haproxy/configuration/backends/${domain}`)
@@ -64,10 +65,10 @@ export async function removeProxyConfiguration({ domain }) {
.json();
await completeTransaction(transactionId);
}
await forceSSLOffApplication({ domain });
await removeWwwRedirection(domain);
await forceSSLOffApplication(domain);
await removeWwwRedirection(fqdn);
}
export async function forceSSLOffApplication({ domain }) {
export async function forceSSLOffApplication(domain) {
const haproxy = await haproxyInstance();
await checkHAProxy(haproxy);
let transactionId;
@@ -104,7 +105,7 @@ export async function forceSSLOffApplication({ domain }) {
if (transactionId) await completeTransaction(transactionId);
}
}
export async function forceSSLOnApplication({ domain }) {
export async function forceSSLOnApplication(domain) {
const haproxy = await haproxyInstance();
await checkHAProxy(haproxy);
let transactionId;
@@ -283,7 +284,7 @@ export async function configureCoolifyProxyOff(fqdn) {
})
.json();
await completeTransaction(transactionId);
if (isHttps) await forceSSLOffApplication({ domain });
if (isHttps) await forceSSLOffApplication(domain);
await removeWwwRedirection(fqdn);
} catch (error) {
throw error?.response?.body || error;
@@ -558,7 +559,8 @@ export async function configureSimpleServiceProxyOn({ id, domain, port }) {
await completeTransaction(transactionId);
}
export async function configureSimpleServiceProxyOff({ domain }) {
export async function configureSimpleServiceProxyOff(fqdn) {
const domain = getDomain(fqdn);
const haproxy = await haproxyInstance();
await checkHAProxy(haproxy);
try {
@@ -573,12 +575,16 @@ export async function configureSimpleServiceProxyOff({ domain }) {
.json();
await completeTransaction(transactionId);
} catch (error) {}
await forceSSLOffApplication({ domain });
await removeWwwRedirection(domain);
await forceSSLOffApplication(domain);
await removeWwwRedirection(fqdn);
return;
}
export async function removeWwwRedirection(domain) {
export async function removeWwwRedirection(fqdn) {
const domain = getDomain(fqdn);
const isHttps = fqdn.startsWith('https://');
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
const haproxy = await haproxyInstance();
await checkHAProxy();
const rules: any = await haproxy
@@ -590,9 +596,7 @@ export async function removeWwwRedirection(domain) {
})
.json();
if (rules.data.length > 0) {
const rule = rules.data.find((rule) =>
rule.redir_value.includes(`${domain}%[capture.req.uri]`)
);
const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue));
if (rule) {
const transactionId = await getNextTransactionId();
await haproxy
@@ -617,6 +621,7 @@ export async function setWwwRedirection(fqdn) {
const domain = getDomain(fqdn);
const isHttps = fqdn.startsWith('https://');
const isWWW = fqdn.includes('www.');
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
const contTest = `{ req.hdr(host) -i ${isWWW ? domain.replace('www.', '') : `www.${domain}`} }`;
const rules: any = await haproxy
.get(`v2/services/haproxy/configuration/http_request_rules`, {
@@ -628,13 +633,11 @@ export async function setWwwRedirection(fqdn) {
.json();
let nextRule = 0;
if (rules.data.length > 0) {
const rule = rules.data.find((rule) =>
rule.redir_value.includes(`${domain}%[capture.req.uri]`)
);
const rule = rules.data.find((rule) => rule.redir_value.includes(redirectValue));
if (rule) return;
nextRule = rules.data[rules.data.length - 1].index + 1;
}
const redirectValue = `${isHttps ? 'https://' : 'http://'}${domain}%[capture.req.uri]`;
transactionId = await getNextTransactionId();
await haproxy
.post(`v2/services/haproxy/configuration/http_request_rules`, {

View File

@@ -46,35 +46,33 @@ export async function letsEncrypt({ domain, isCoolify = false, id = null }) {
}
}
}
await forceSSLOffApplication({ domain });
await forceSSLOffApplication(domain);
if (dualCerts) {
const error = await asyncExecShell(
await asyncExecShell(
`DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p ${randomPort}:${randomPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${randomPort} -d ${nakedDomain} -d ${wwwDomain} --expand --agree-tos --non-interactive --register-unsafely-without-email ${
dev ? '--test-cert' : ''
}`
);
if (error.stderr) throw error;
const sslCopyError = await asyncExecShell(
await asyncExecShell(
`DOCKER_HOST=${host} docker run --rm -v "coolify-letsencrypt:/etc/letsencrypt" -v "coolify-ssl-certs:/app/ssl" alpine:latest sh -c "test -d /etc/letsencrypt/live/${nakedDomain}/ && cat /etc/letsencrypt/live/${nakedDomain}/fullchain.pem /etc/letsencrypt/live/${nakedDomain}/privkey.pem > /app/ssl/${nakedDomain}.pem || cat /etc/letsencrypt/live/${wwwDomain}/fullchain.pem /etc/letsencrypt/live/${wwwDomain}/privkey.pem > /app/ssl/${wwwDomain}.pem"`
);
if (sslCopyError.stderr) throw sslCopyError;
} else {
const sslGenerateError = await asyncExecShell(
await asyncExecShell(
`DOCKER_HOST=${host} docker run --rm --name certbot-${randomCuid} -p ${randomPort}:${randomPort} -v "coolify-letsencrypt:/etc/letsencrypt" certbot/certbot --logs-dir /etc/letsencrypt/logs certonly --standalone --preferred-challenges http --http-01-address 0.0.0.0 --http-01-port ${randomPort} -d ${domain} --expand --agree-tos --non-interactive --register-unsafely-without-email ${
dev ? '--test-cert' : ''
}`
);
if (sslGenerateError.stderr) throw sslGenerateError;
const sslCopyError = await asyncExecShell(
await asyncExecShell(
`DOCKER_HOST=${host} docker run --rm -v "coolify-letsencrypt:/etc/letsencrypt" -v "coolify-ssl-certs:/app/ssl" alpine:latest sh -c "cat /etc/letsencrypt/live/${domain}/fullchain.pem /etc/letsencrypt/live/${domain}/privkey.pem > /app/ssl/${domain}.pem"`
);
if (sslCopyError.stderr) throw sslCopyError;
}
} catch (error) {
throw error;
if (error.code !== 0) {
throw error;
}
} finally {
if (!isCoolify) {
await forceSSLOnApplication({ domain });
await forceSSLOnApplication(domain);
}
}
}

View File

@@ -48,7 +48,7 @@ export default async function () {
port
});
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
if (isHttps) await forceSSLOnApplication(domain);
await setWwwRedirection(fqdn);
}
}
@@ -98,7 +98,7 @@ export default async function () {
await configureCoolifyProxyOn(fqdn);
await setWwwRedirection(fqdn);
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
if (isHttps) await forceSSLOnApplication(domain);
}
} catch (error) {
console.log(error);

View File

@@ -3,13 +3,13 @@
import { publicPaths } from '$lib/settings';
export const load: Load = async ({ fetch, url, params, session }) => {
if (!session.uid && !publicPaths.includes(url.pathname)) {
if (!session.userId && !publicPaths.includes(url.pathname)) {
return {
status: 302,
redirect: '/login'
};
}
if (!session.uid) {
if (!session.userId) {
return {};
}
const endpoint = `/teams.json`;
@@ -49,7 +49,7 @@
};
let latestVersion = 'latest';
onMount(async () => {
if ($session.uid) {
if ($session.userId) {
const overrideVersion = browser && window.localStorage.getItem('latestVersion');
try {
await get(`/login.json`);
@@ -84,7 +84,7 @@
}
async function switchTeam() {
try {
await post(`/index.json?from=${$page.url.pathname}`, {
await post(`/dashboard.json?from=${$page.url.pathname}`, {
cookie: 'teamId',
value: selectedTeamId
});
@@ -129,7 +129,7 @@
<title>Coolify</title>
</svelte:head>
<SvelteToast options={{ intro: { y: -64 }, duration: 3000, pausable: true }} />
{#if $session.uid}
{#if $session.userId}
<nav class="nav-main">
<div class="flex h-screen w-full flex-col items-center transition-all duration-100">
<div class="my-4 h-10 w-10"><img src="/favicon.png" alt="coolLabs logo" /></div>

View File

@@ -8,7 +8,6 @@
import cuid from 'cuid';
import { goto } from '$app/navigation';
import { del, get, post, put } from '$lib/api';
const { id } = $page.params;
const from = $page.url.searchParams.get('from');

View File

@@ -276,11 +276,13 @@
</div>
<div class="grid grid-cols-2 items-center pb-8">
<Setting
dataTooltip="Must be stopped to modify."
disabled={isRunning}
isCenter={false}
bind:setting={dualCerts}
title="Generate SSL for www and non-www?"
description="It will generate certificates for both www and non-www. <br>You need to have <span class='font-bold text-green-500'>both DNS entries</span> set in advance.<br><br>Useful if you expect to have visitors on both.<br>Application must be redeployed."
on:click={() => changeSettings('dualCerts')}
description="It will generate certificates for both www and non-www. <br>You need to have <span class='font-bold text-green-500'>both DNS entries</span> set in advance.<br><br>Useful if you expect to have visitors on both."
on:click={() => !isRunning && changeSettings('dualCerts')}
/>
</div>
{#if !staticDeployments.includes(application.buildPack)}

View File

@@ -16,12 +16,11 @@ export const post: RequestHandler = async (event) => {
id,
teamId
});
const domain = getDomain(fqdn);
if (destinationDockerId) {
const docker = dockerInstance({ destinationDocker });
await docker.engine.getContainer(id).stop();
}
await removeProxyConfiguration({ domain });
await removeProxyConfiguration(fqdn);
return {
status: 200
};

View File

@@ -20,7 +20,7 @@
</script>
<script lang="ts">
export let applications: Array<Applications>;
export let applications: Array<Application>;
import { session } from '$app/stores';
import Application from './_Application.svelte';
</script>

View File

@@ -24,7 +24,7 @@ export const post: RequestHandler = async (event) => {
await configureCoolifyProxyOn(fqdn);
await setWwwRedirection(fqdn);
const isHttps = fqdn.startsWith('https://');
if (isHttps) await forceSSLOnApplication({ domain });
if (isHttps) await forceSSLOnApplication(domain);
return {
status: 200
};

View File

@@ -1,7 +1,7 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ fetch, session }) => {
const url = `/index.json`;
const url = `/dashboard.json`;
const res = await fetch(url);
if (res.ok) {

View File

@@ -9,7 +9,7 @@
let emailEl;
let email, password;
if (browser && $session.uid) {
if (browser && $session.userId) {
goto('/');
}
onMount(() => {
@@ -34,7 +34,7 @@
</script>
<div class="flex h-screen flex-col items-center justify-center">
{#if $session.uid}
{#if $session.userId}
<div class="flex justify-center px-4 text-xl font-bold">Already logged in...</div>
{:else}
<div class="flex justify-center px-4">

View File

@@ -129,10 +129,12 @@
</div>
<div class="grid grid-cols-2 items-center px-10">
<Setting
disabled={isRunning}
dataTooltip="Must be stopped to modify."
bind:setting={dualCerts}
title="Generate SSL for www and non-www?"
description="It will generate certificates for both www and non-www. <br>You need to have <span class='font-bold text-pink-600'>both DNS entries</span> set in advance.<br><br>Service needs to be restarted."
on:click={() => changeSettings('dualCerts')}
on:click={() => !isRunning && changeSettings('dualCerts')}
/>
</div>
{#if service.type === 'plausibleanalytics'}

View File

@@ -35,7 +35,7 @@ export const post: RequestHandler = async (event) => {
}
try {
await stopTcpHttpProxy(destinationDocker, publicPort);
await configureSimpleServiceProxyOff({ domain });
await configureSimpleServiceProxyOff(fqdn);
} catch (error) {
console.log(error);
}

View File

@@ -28,7 +28,7 @@ export const post: RequestHandler = async (event) => {
console.error(error);
}
try {
await configureSimpleServiceProxyOff({ domain });
await configureSimpleServiceProxyOff(fqdn);
} catch (error) {
console.log(error);
}

View File

@@ -38,7 +38,7 @@ export const post: RequestHandler = async (event) => {
}
try {
await configureSimpleServiceProxyOff({ domain });
await configureSimpleServiceProxyOff(fqdn);
} catch (error) {
console.log(error);
}

View File

@@ -28,7 +28,7 @@ export const post: RequestHandler = async (event) => {
console.error(error);
}
try {
await configureSimpleServiceProxyOff({ domain });
await configureSimpleServiceProxyOff(fqdn);
} catch (error) {
console.log(error);
}

View File

@@ -28,7 +28,7 @@ export const post: RequestHandler = async (event) => {
console.error(error);
}
try {
await configureSimpleServiceProxyOff({ domain });
await configureSimpleServiceProxyOff(fqdn);
} catch (error) {
console.log(error);
}

View File

@@ -31,7 +31,7 @@ export const post: RequestHandler = async (event) => {
console.error(error);
}
try {
await configureSimpleServiceProxyOff({ domain });
await configureSimpleServiceProxyOff(fqdn);
} catch (error) {
console.log(error);
}

View File

@@ -101,7 +101,7 @@ export const post: RequestHandler = async (event) => {
await setWwwRedirection(fqdn);
if (isHttps) {
await letsEncrypt({ domain, isCoolify: true });
await forceSSLOnApplication({ domain });
await forceSSLOnApplication(domain);
await reloadHaproxy('/var/run/docker.sock');
}
}

View File

@@ -131,6 +131,7 @@
</div>
<div class="grid grid-cols-2 items-center">
<Setting
dataTooltip="Must remove the domain before you can change this setting."
disabled={isFqdnSet}
bind:setting={dualCerts}
title="Generate SSL for www and non-www?"

View File

@@ -22,21 +22,20 @@
<script lang="ts">
export let permissions;
export let team;
export let invitations;
export let invitations: any[];
import { page, session } from '$app/stores';
import Explainer from '$lib/components/Explainer.svelte';
import { errorNotification } from '$lib/form';
import { post } from '$lib/api';
const { id } = $page.params;
let invitation = {
teamName: team.name,
email: null,
permission: 'read'
};
let myPermission = permissions.find((u) => u.user.id === $session.uid).permission;
function isAdmin(permission = myPermission) {
if (myPermission === 'admin' || myPermission === 'owner') {
// let myPermission = permissions.find((u) => u.user.id === $session.userId).permission;
function isAdmin(permission: string) {
if (permission === 'admin' || permission === 'owner') {
return true;
}
@@ -56,7 +55,7 @@
return errorNotification(error);
}
}
async function revokeInvitation(id) {
async function revokeInvitation(id: string) {
try {
await post(`/teams/${id}/invitation/revoke.json`, { id });
return window.location.reload();
@@ -64,7 +63,7 @@
return errorNotification(error);
}
}
async function removeFromTeam(uid) {
async function removeFromTeam(uid: string) {
try {
await post(`/teams/${id}/remove/user.json`, { teamId: team.id, uid });
return window.location.reload();
@@ -72,7 +71,7 @@
return errorNotification(error);
}
}
async function changePermission(userId, permissionId, currentPermission) {
async function changePermission(userId: string, permissionId: string, currentPermission: string) {
let newPermission = 'read';
if (currentPermission === 'read') {
newPermission = 'admin';
@@ -136,10 +135,11 @@
<tr class="text-xs">
<td class="py-4"
>{permission.user.email}
<span class="font-bold">{permission.user.id === $session.uid ? '(You)' : ''}</span></td
<span class="font-bold">{permission.user.id === $session.userId ? '(You)' : ''}</span
></td
>
<td class="py-4">{permission.permission}</td>
{#if $session.isAdmin && permission.user.id !== $session.uid && permission.permission !== 'owner'}
{#if $session.isAdmin && permission.user.id !== $session.userId && permission.permission !== 'owner'}
<td class="flex flex-col items-center justify-center space-y-2 py-4 text-center">
<button
class="w-52 bg-red-600 hover:bg-red-500"

View File

@@ -144,10 +144,17 @@ export const post: RequestHandler = async (event) => {
} else if (pullmergeRequestAction === 'closed') {
if (applicationFound.destinationDockerId) {
const domain = getDomain(applicationFound.fqdn);
const isHttps = applicationFound.fqdn.startsWith('https://');
const isWWW = applicationFound.fqdn.includes('www.');
const fqdn = `${isHttps ? 'https://' : 'http://'}${
isWWW ? 'www.' : ''
}${pullmergeRequestId}.${domain}`;
const id = `${applicationFound.id}-${pullmergeRequestId}`;
const engine = applicationFound.destinationDocker.engine;
await removeDestinationDocker({ id, engine });
await removeProxyConfiguration({ domain: `${pullmergeRequestId}.${domain}` });
await removeProxyConfiguration(fqdn);
}
return {
status: 200,

View File

@@ -141,10 +141,17 @@ export const post: RequestHandler = async (event) => {
} else if (action === 'close') {
if (applicationFound.destinationDockerId) {
const domain = getDomain(applicationFound.fqdn);
const isHttps = applicationFound.fqdn.startsWith('https://');
const isWWW = applicationFound.fqdn.includes('www.');
const fqdn = `${isHttps ? 'https://' : 'http://'}${
isWWW ? 'www.' : ''
}${pullmergeRequestId}.${domain}`;
const id = `${applicationFound.id}-${pullmergeRequestId}`;
const engine = applicationFound.destinationDocker.engine;
await removeProxyConfiguration({ domain: `${pullmergeRequestId}.${domain}` });
await removeDestinationDocker({ id, engine });
await removeProxyConfiguration(fqdn);
}
return {