diff --git a/src/lib/components/organizationUsageLimits.svelte b/src/lib/components/organizationUsageLimits.svelte
index 39ae9a1ea..8373b17b3 100644
--- a/src/lib/components/organizationUsageLimits.svelte
+++ b/src/lib/components/organizationUsageLimits.svelte
@@ -90,10 +90,14 @@
}
if (selectedProjectsToDelete?.length) {
- const projectsDeletionPromises = selectedProjectsToDelete.map((projectId) => ({
- projectId,
- promise: sdk.forConsole.projects.delete({ projectId })
- }));
+ const projectsDeletionPromises = selectedProjectsToDelete.map((projectId) => {
+ const projectToDelete = projects.find((project) => project.$id === projectId);
+
+ return {
+ projectId,
+ promise: sdk.forProject(projectToDelete.region, projectId).project.delete()
+ };
+ });
try {
const results = await Promise.allSettled(
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
index be661eefb..d917925ae 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -112,8 +112,8 @@ export const defaultScopes: string[] = [
'projects.write',
'locale.read',
'avatars.read',
- 'execution.read',
- 'execution.write',
+ 'executions.read',
+ 'executions.write',
'targets.read',
'targets.write',
'subscribers.write',
@@ -339,17 +339,31 @@ export const scopes: ScopeDefinition[] = [
icon: 'lightning-bolt'
},
{
- scope: 'execution.read',
+ scope: 'executions.read',
description: "Access to read your project's execution logs",
category: 'Functions',
icon: 'lightning-bolt'
},
{
- scope: 'execution.write',
+ scope: 'executions.write',
description: "Access to execute your project's functions",
category: 'Functions',
icon: 'lightning-bolt'
},
+ {
+ scope: 'execution.read',
+ description: "Access to read your project's execution logs",
+ category: 'Functions',
+ icon: 'lightning-bolt',
+ deprecated: true
+ },
+ {
+ scope: 'execution.write',
+ description: "Access to execute your project's functions",
+ category: 'Functions',
+ icon: 'lightning-bolt',
+ deprecated: true
+ },
{
scope: 'targets.read',
description: "Access to read your project's messaging targets",
diff --git a/src/lib/stores/oauth-providers.ts b/src/lib/stores/oauth-providers.ts
index 11191dbaf..1a2143a17 100644
--- a/src/lib/stores/oauth-providers.ts
+++ b/src/lib/stores/oauth-providers.ts
@@ -1,13 +1,5 @@
import type { Component } from 'svelte';
-import Apple from '$routes/(console)/project-[region]-[project]/auth/(providers)/appleOAuth.svelte';
-import Auth0 from '$routes/(console)/project-[region]-[project]/auth/(providers)/auth0OAuth.svelte';
-import Authentik from '$routes/(console)/project-[region]-[project]/auth/(providers)/authentikOAuth.svelte';
-import GitLab from '$routes/(console)/project-[region]-[project]/auth/(providers)/gitlabOAuth.svelte';
-import Google from '$routes/(console)/project-[region]-[project]/auth/(providers)/googleOAuth.svelte';
import Main from '$routes/(console)/project-[region]-[project]/auth/(providers)/mainOAuth.svelte';
-import Microsoft from '$routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte';
-import Oidc from '$routes/(console)/project-[region]-[project]/auth/(providers)/oidcOAuth.svelte';
-import Okta from '$routes/(console)/project-[region]-[project]/auth/(providers)/oktaOAuth.svelte';
export type Provider = {
name: string;
@@ -28,19 +20,19 @@ export const oAuthProviders: Record = {
name: 'Apple',
icon: 'apple',
docs: 'https://developer.apple.com/sign-in-with-apple/',
- component: Apple
+ component: Main
},
auth0: {
name: 'Auth0',
icon: 'auth0',
docs: 'https://auth0.com/developers',
- component: Auth0
+ component: Main
},
authentik: {
name: 'Authentik',
icon: 'authentik',
docs: 'https://goauthentik.io/integrations/sources/oauth/',
- component: Authentik
+ component: Main
},
autodesk: {
name: 'Autodesk',
@@ -108,6 +100,12 @@ export const oAuthProviders: Record = {
docs: 'https://www.figma.com/developers/api#access-tokens',
component: Main
},
+ fusionauth: {
+ name: 'FusionAuth',
+ icon: 'fusionauth',
+ docs: 'https://fusionauth.io/docs/apis/identity-providers/oauth2',
+ component: Main
+ },
github: {
name: 'GitHub',
icon: 'github',
@@ -125,21 +123,33 @@ export const oAuthProviders: Record = {
name: 'GitLab',
icon: 'gitlab',
docs: 'https://docs.gitlab.com/ee/api/',
- component: GitLab
+ component: Main
},
google: {
name: 'Google',
icon: 'google',
docs: 'https://support.google.com/googleapi/answer/6158849',
- component: Google
+ component: Main
},
googleImagine: {
name: 'Google',
icon: 'google',
docs: 'https://support.google.com/googleapi/answer/6158849',
- component: Google,
+ component: Main,
internal: true
},
+ keycloak: {
+ name: 'Keycloak',
+ icon: 'keycloak',
+ docs: 'https://www.keycloak.org/securing-apps/oidc-layers',
+ component: Main
+ },
+ kick: {
+ name: 'Kick',
+ icon: 'kick',
+ docs: 'https://docs.kick.com/getting-started/using-the-api',
+ component: Main
+ },
linkedin: {
name: 'LinkedIn',
icon: 'linkedin',
@@ -150,7 +160,7 @@ export const oAuthProviders: Record = {
name: 'Microsoft',
icon: 'microsoft',
docs: 'https://developer.microsoft.com/en-us/',
- component: Microsoft
+ component: Main
},
notion: {
name: 'Notion',
@@ -162,13 +172,13 @@ export const oAuthProviders: Record = {
name: 'OIDC',
icon: 'oidc',
docs: 'https://openid.net/connect/faq/',
- component: Oidc
+ component: Main
},
okta: {
name: 'Okta',
icon: 'okta',
docs: 'https://developer.okta.com',
- component: Okta
+ component: Main
},
paypal: {
name: 'Paypal',
@@ -176,7 +186,7 @@ export const oAuthProviders: Record = {
docs: 'https://developer.paypal.com/docs/api/overview/',
component: Main
},
- paypalsandbox: {
+ paypalSandbox: {
name: 'Paypal Sandbox',
icon: 'paypal',
docs: 'https://developer.paypal.com/docs/api/overview/',
@@ -248,12 +258,6 @@ export const oAuthProviders: Record = {
docs: 'https://developer.yahoo.com/oauth2/guide/flows_authcode/',
component: Main
},
- yammer: {
- name: 'Yammer',
- icon: 'yammer',
- docs: 'https://developer.yammer.com/docs/oauth-2',
- component: Main
- },
yandex: {
name: 'Yandex',
icon: 'yandex',
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index 987d1bca6..d8e9d5be8 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -148,6 +148,52 @@
];
}
+ function createBandwidthProgressData(
+ totalBytes: number,
+ realtimeBytes: number,
+ maxGB: number
+ ): Array<{ size: number; color: string; tooltip?: { title: string; label: string } }> {
+ if (maxGB <= 0) return [];
+
+ const maxBytes = maxGB * 1000 * 1000 * 1000;
+ const percentage = Math.min((totalBytes / maxBytes) * 100, 100);
+ const showRealtimeSegment = realtimeBytes > 0 && realtimeBytes <= totalBytes;
+ const realtimePortion = showRealtimeSegment ? realtimeBytes : 0;
+ const regularPortion = Math.max(0, totalBytes - realtimePortion);
+ const regularSize = humanFileSize(regularPortion);
+ const realtimeSize = humanFileSize(realtimePortion);
+
+ const segments: Array<{
+ size: number;
+ color: string;
+ tooltip?: { title: string; label: string };
+ }> = [];
+
+ if (regularPortion > 0) {
+ segments.push({
+ size: regularPortion,
+ color: 'var(--bgcolor-neutral-invert)',
+ tooltip: {
+ title: `${percentage.toFixed(0)}% used`,
+ label: `Bandwidth: ${regularSize.value} ${regularSize.unit}`
+ }
+ });
+ }
+
+ if (realtimePortion > 0) {
+ segments.push({
+ size: realtimePortion,
+ color: 'var(--bgcolor-neutral-invert-weak)',
+ tooltip: {
+ title: 'Realtime bandwidth',
+ label: `${realtimeSize.value} ${realtimeSize.unit}`
+ }
+ });
+ }
+
+ return segments;
+ }
+
function getResource(resources: Array | undefined, resourceId: string) {
return resources?.find((resource) => resource.resourceId === resourceId);
}
@@ -278,9 +324,13 @@
const projects = (currentAggregation?.breakdown || []).map((projectData) => {
const resources = projectData.resources || [];
const bandwidth = getResource(resources, 'bandwidth');
+ const realtimeBandwidth = getResource(resources, 'realtimeBandwidth');
const storage = getResource(resources, 'storage');
const authPhone = getResource(resources, 'authPhone');
+ const bandwidthValue = bandwidth?.value || 0;
+ const realtimeBandwidthValue = realtimeBandwidth?.value || 0;
+
return {
id: `project-${projectData.$id}`,
expandable: true,
@@ -305,10 +355,31 @@
),
priceFormatter: ({ amount }) => formatCurrency(amount),
progressFactory: ({ value, planLimit, hasLimit }) =>
- hasLimit ? createStorageProgressData(value, planLimit || 0) : [],
+ hasLimit
+ ? createBandwidthProgressData(
+ value,
+ realtimeBandwidthValue,
+ planLimit || 0
+ )
+ : [],
maxFactory: ({ planLimit, hasLimit }) =>
hasLimit ? (planLimit || 0) * 1000 * 1000 * 1000 : null
}),
+ ...(realtimeBandwidthValue > bandwidthValue
+ ? [
+ createRow({
+ id: 'realtime-bandwidth',
+ label: 'Realtime bandwidth',
+ resource: realtimeBandwidth,
+ usageFormatter: ({ value }) => {
+ const size = humanFileSize(value);
+ return `${size.value} ${size.unit}`;
+ },
+ priceFormatter: ({ amount }) => formatCurrency(amount),
+ includeProgress: false
+ })
+ ]
+ : []),
// standard resources (numeric)
createResourceRow(
'users',
@@ -379,15 +450,6 @@
getResource(resources, 'realtimeMessages'),
currentPlan?.realtimeMessages
),
- createRow({
- id: 'realtime-bandwidth',
- label: 'Realtime bandwidth',
- resource: getResource(resources, 'realtimeBandwidth'),
- usageFormatter: ({ value }) =>
- humanFileSize(value).value + humanFileSize(value).unit,
- priceFormatter: ({ amount }) => formatCurrency(amount),
- includeProgress: false
- }),
createRow({
id: 'sms',
label: 'Phone OTP',
diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte
index 4a743e4e7..874cc23ec 100644
--- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.svelte
@@ -584,7 +584,7 @@
color: '#68A3FE',
tooltip: {
title: 'Backups storage',
- label: `${Math.round(bytesToSize(data.organizationUsage.backupsStorageTotal, 'GB') * 100) / 100}MB`
+ label: `${Math.round(bytesToSize(data.organizationUsage.backupsStorageTotal, 'GB') * 100) / 100}GB`
}
},
{
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/appleOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/appleOAuth.svelte
deleted file mode 100644
index 0554e9598..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/appleOAuth.svelte
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
-
- visit the docs.
-
-
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/auth0OAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/auth0OAuth.svelte
deleted file mode 100644
index 9b114e740..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/auth0OAuth.svelte
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
- visit the docs.
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/authentikOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/authentikOAuth.svelte
deleted file mode 100644
index 19a3b40c6..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/authentikOAuth.svelte
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
- visit the docs.
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/gitlabOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/gitlabOAuth.svelte
deleted file mode 100644
index fc46679bd..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/gitlabOAuth.svelte
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
- visit the docs.
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/googleOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/googleOAuth.svelte
deleted file mode 100644
index d5457b28b..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/googleOAuth.svelte
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
- {provider.name} OAuth2 settings
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
- visit the docs.
-
-
-
-
-
- To complete the setup, create an OAuth2 client ID with "Web application" as the application
- type, then add this redirect URI to your {provider.name} configuration.
-
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/mainOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/mainOAuth.svelte
index 365782e6b..acc3a90c5 100644
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/mainOAuth.svelte
+++ b/src/routes/(console)/project-[region]-[project]/auth/(providers)/mainOAuth.svelte
@@ -1,35 +1,204 @@
@@ -49,21 +220,157 @@
target="_blank"
rel="noopener noreferrer">visit the docs.
+
-
-
+
+ {#if appIdParam}
+
+ {/if}
+
+ {#each basicDetailParams as param}
+
+ {/each}
+
+ {#if advancedDetailParams.length > 0}
+
+
+ {#each advancedDetailParams as param}
+
+ {/each}
+
+
+ {/if}
+
+ {#if secretParams.length > 0}
+ {#if !showSecretInput}
+
+ (showSecretInput = true)}>
+ Update {secretCardTitle}
+
+
+ {:else}
+
+
+
+
+ {secretCardTitle}
+
+
+
+
+
+ {#if secretParams.length === 1}
+ This field is write-only. Enter a new value to update it.
+ {:else}
+ These fields are write-only. Enter new values to update them.
+ {/if}
+
+
+
+
+
+
+ {#each secretParams as param}
+ {#if isP8Param(param.$id)}
+
+
+ {#if p8PasteMode[param.$id]}
+
+ {:else}
+
+ {#if fieldValues[param.$id]}
+
+ File loaded — click to replace
+ {
+ event.preventDefault();
+ event.stopPropagation();
+ fieldValues[param.$id] = null;
+ }}>
+
+
+ {:else}
+
+ Click to upload .p8 file
+ {/if}
+
+
+ handleP8FileUpload(param.$id, event)} />
+ {/if}
+
+ {:else}
+
+ {/if}
+ {/each}
+
+
+
+ {/if}
+ {/if}
+
To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
@@ -72,12 +379,52 @@
value={`${getApiEndpoint(page.params.region)}/account/sessions/oauth2/callback/${provider.key}/${projectId}`} />
(provider = null)}>Cancel
- Update
+ Update
+
+
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte
deleted file mode 100644
index e6679ab2e..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
-
- visit the docs.
-
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/oidcOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/oidcOAuth.svelte
deleted file mode 100644
index 1360c4b72..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/oidcOAuth.svelte
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
- visit the docs.
-
-
-
-
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/oktaOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/oktaOAuth.svelte
deleted file mode 100644
index 57f5c9e2c..000000000
--- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/oktaOAuth.svelte
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
-
- To use {provider.name} authentication in your application, first fill in this form. For more info
- you can
- visit the docs.
-
-
-
-
-
-
-
-
- To complete set up, add this OAuth2 redirect URI to your {provider.name} app configuration.
-
-
-
- (provider = null)}>Cancel
- Update
-
-
diff --git a/src/routes/(console)/project-[region]-[project]/auth/settings/+page.svelte b/src/routes/(console)/project-[region]-[project]/auth/settings/+page.svelte
index c086f5b55..3596e8d7e 100644
--- a/src/routes/(console)/project-[region]-[project]/auth/settings/+page.svelte
+++ b/src/routes/(console)/project-[region]-[project]/auth/settings/+page.svelte
@@ -30,6 +30,8 @@
let { data }: PageProps = $props();
/** Must stay derived from `data` so OAuth/auth toggles reflect `invalidate(Dependencies.PROJECT)` without a full reload. */
const project = $derived(data.project);
+ const resolvedOAuthProviders = $derived(data.oauthProviders);
+ const consoleParamsMap = $derived(data.consoleParamsMap);
let showProvider = $state(false);
let selectedProvider: Models.AuthProvider | null = $state(null);
@@ -152,7 +154,11 @@
Enable the authentication methods you wish to use.
-
+
{
@@ -172,10 +178,10 @@
disabled={shouldDisableDisableAllButton}>Disable all
-
-
+
+
{#each $authMethods.list as box}
-
+
{/if}
-
+
{/each}
-
+
@@ -200,8 +206,8 @@
OAuth2 Providers
- {#each project.oAuthProviders
- .filter((p) => p.name !== 'Mock')
+ {#each resolvedOAuthProviders
+ .filter((p) => p.key !== 'mock' && p.name !== 'Mock')
.sort( (a, b) => (a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1) ) as provider}
{@const oAuthProvider = oAuthProviders[provider.key]}
{#if oAuthProvider && !oAuthProvider.internal}
@@ -248,6 +254,7 @@
{
selectedProvider = null;
showProvider = false;
@@ -271,3 +278,22 @@
+
+
diff --git a/src/routes/(console)/project-[region]-[project]/auth/settings/+page.ts b/src/routes/(console)/project-[region]-[project]/auth/settings/+page.ts
new file mode 100644
index 000000000..0aa058f7e
--- /dev/null
+++ b/src/routes/(console)/project-[region]-[project]/auth/settings/+page.ts
@@ -0,0 +1,52 @@
+import { Dependencies } from '$lib/constants';
+import { oAuthProviders } from '$lib/stores/oauth-providers';
+import { sdk } from '$lib/stores/sdk';
+import type { Models, Models as ConsoleModels } from '@appwrite.io/console';
+import type { PageLoad } from './$types';
+
+/** Extract the appId equivalent from a typed OAuth2 provider model. */
+function extractAppId(p: Record): string {
+ return (p['clientId'] ??
+ p['appId'] ??
+ p['oauthClientId'] ??
+ p['oauth2ClientId'] ??
+ p['applicationId'] ??
+ p['serviceId'] ??
+ p['apiKey'] ??
+ p['publicKey'] ??
+ p['appKey'] ??
+ p['keyString'] ??
+ p['customerKey'] ??
+ p['key'] ??
+ '') as string;
+}
+
+export const load: PageLoad = async ({ depends, params }) => {
+ depends(Dependencies.PROJECT);
+
+ const [providerList, consoleProviderList] = await Promise.all([
+ sdk.forProject(params.region, params.project).project.listOAuth2Providers(),
+ sdk.forConsole.console.listOAuth2Providers()
+ ]);
+
+ const consoleParamsMap = new Map();
+ for (const cp of consoleProviderList.oAuth2Providers) {
+ consoleParamsMap.set(cp.$id, cp.parameters ?? []);
+ }
+
+ const oauthProviders: Models.AuthProvider[] = providerList.providers
+ .filter((p) => p.$id !== 'mock')
+ .map((p) => {
+ const raw = p as unknown as Record;
+ return {
+ ...raw,
+ key: p.$id,
+ name: oAuthProviders[p.$id]?.name ?? p.$id,
+ appId: extractAppId(raw),
+ secret: '',
+ enabled: p.enabled
+ };
+ });
+
+ return { oauthProviders, consoleParamsMap };
+};
diff --git a/src/routes/(console)/project-[region]-[project]/auth/updateOAuth.ts b/src/routes/(console)/project-[region]-[project]/auth/updateOAuth.ts
index 6249ef31e..0c2195502 100644
--- a/src/routes/(console)/project-[region]-[project]/auth/updateOAuth.ts
+++ b/src/routes/(console)/project-[region]-[project]/auth/updateOAuth.ts
@@ -7,10 +7,12 @@ import { sdk } from '$lib/stores/sdk';
import { OAuthProvider, type Models } from '@appwrite.io/console';
type Args = {
+ region: string;
projectId: string;
provider: Models.AuthProvider;
- appId: string;
+ appId: string | null;
secret: string;
+ details: Record;
enabled: boolean;
};
@@ -19,11 +21,323 @@ type Return = {
message?: string;
};
-export async function updateOAuth({
+function parseSecret(secret: string) {
+ if (!secret) return {};
+
+ try {
+ return JSON.parse(secret);
+ } catch {
+ return {};
+ }
+}
+
+async function updateProjectOAuth({
+ region,
projectId,
provider,
appId,
secret,
+ details,
+ enabled
+}: Args) {
+ const projectSdk = sdk.forProject(region, projectId).project;
+ const parsedSecret = parseSecret(secret);
+
+ const getAppId = (): string => appId ?? '';
+ const getDetail = (key: string): string => details[key] ?? '';
+ const getSecret = (key?: string): string | undefined => {
+ if (key) {
+ const value = parsedSecret[key];
+ return typeof value === 'string' && value !== '' ? value : undefined;
+ }
+
+ const firstValue = Object.values(parsedSecret).find(
+ (value): value is string => typeof value === 'string' && value !== ''
+ );
+
+ return firstValue;
+ };
+
+ switch (provider.key) {
+ case OAuthProvider.Amazon:
+ return projectSdk.updateOAuth2Amazon({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Apple:
+ return projectSdk.updateOAuth2Apple({
+ serviceId: getAppId(),
+ keyId: getDetail('keyId'),
+ teamId: getDetail('teamId'),
+ p8File: getSecret('p8File'),
+ enabled
+ });
+ case OAuthProvider.Auth0:
+ return projectSdk.updateOAuth2Auth0({
+ clientId: getAppId(),
+ clientSecret: getSecret('clientSecret'),
+ endpoint: getDetail('endpoint'),
+ enabled
+ });
+ case OAuthProvider.Authentik:
+ return projectSdk.updateOAuth2Authentik({
+ endpoint: getDetail('endpoint'),
+ clientId: getAppId(),
+ clientSecret: getSecret('clientSecret'),
+ enabled
+ });
+ case OAuthProvider.Autodesk:
+ return projectSdk.updateOAuth2Autodesk({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Bitbucket:
+ return projectSdk.updateOAuth2Bitbucket({
+ key: getAppId(),
+ secret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Bitly:
+ return projectSdk.updateOAuth2Bitly({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Box:
+ return projectSdk.updateOAuth2Box({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Dailymotion:
+ return projectSdk.updateOAuth2Dailymotion({
+ apiKey: getAppId(),
+ apiSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Discord:
+ return projectSdk.updateOAuth2Discord({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Disqus:
+ return projectSdk.updateOAuth2Disqus({
+ publicKey: getAppId(),
+ secretKey: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Dropbox:
+ return projectSdk.updateOAuth2Dropbox({
+ appKey: getAppId(),
+ appSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Etsy:
+ return projectSdk.updateOAuth2Etsy({
+ keyString: getAppId(),
+ sharedSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Facebook:
+ return projectSdk.updateOAuth2Facebook({
+ appId: getAppId(),
+ appSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Figma:
+ return projectSdk.updateOAuth2Figma({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Fusionauth:
+ return projectSdk.updateOAuth2FusionAuth({
+ endpoint: getDetail('endpoint'),
+ clientId: getAppId(),
+ clientSecret: getSecret('clientSecret'),
+ enabled
+ });
+ case OAuthProvider.Github:
+ return projectSdk.updateOAuth2GitHub({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Gitlab:
+ return projectSdk.updateOAuth2Gitlab({
+ applicationId: getAppId(),
+ secret: getSecret('secret'),
+ endpoint: getDetail('endpoint'),
+ enabled
+ });
+ case OAuthProvider.Google:
+ return projectSdk.updateOAuth2Google({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Keycloak:
+ return projectSdk.updateOAuth2Keycloak({
+ endpoint: getDetail('endpoint'),
+ realmName: getDetail('realmName'),
+ clientId: getAppId(),
+ clientSecret: getSecret('clientSecret'),
+ enabled
+ });
+ case OAuthProvider.Kick:
+ return projectSdk.updateOAuth2Kick({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Linkedin:
+ return projectSdk.updateOAuth2Linkedin({
+ clientId: getAppId(),
+ primaryClientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Microsoft:
+ return projectSdk.updateOAuth2Microsoft({
+ tenant: getDetail('tenant'),
+ applicationId: getAppId(),
+ applicationSecret: getSecret('applicationSecret'),
+ enabled
+ });
+ case OAuthProvider.Notion:
+ return projectSdk.updateOAuth2Notion({
+ oauthClientId: getAppId(),
+ oauthClientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Oidc:
+ return projectSdk.updateOAuth2Oidc({
+ clientId: getAppId(),
+ clientSecret: getSecret('clientSecret'),
+ wellKnownURL: getDetail('wellKnownURL'),
+ authorizationURL: getDetail('authorizationURL'),
+ tokenUrl: getDetail('tokenUrl'),
+ userInfoUrl: getDetail('userInfoUrl'),
+ enabled
+ });
+ case OAuthProvider.Okta:
+ return projectSdk.updateOAuth2Okta({
+ clientId: getAppId(),
+ clientSecret: getSecret('clientSecret'),
+ domain: getDetail('domain'),
+ authorizationServerId: getDetail('authorizationServerId'),
+ enabled
+ });
+ case OAuthProvider.Paypal:
+ return projectSdk.updateOAuth2Paypal({
+ clientId: getAppId(),
+ secretKey: getSecret(),
+ enabled
+ });
+ case OAuthProvider.PaypalSandbox:
+ return projectSdk.updateOAuth2PaypalSandbox({
+ clientId: getAppId(),
+ secretKey: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Podio:
+ return projectSdk.updateOAuth2Podio({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Salesforce:
+ return projectSdk.updateOAuth2Salesforce({
+ customerKey: getAppId(),
+ customerSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Slack:
+ return projectSdk.updateOAuth2Slack({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Spotify:
+ return projectSdk.updateOAuth2Spotify({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Stripe:
+ return projectSdk.updateOAuth2Stripe({
+ clientId: getAppId(),
+ apiSecretKey: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Tradeshift:
+ return projectSdk.updateOAuth2Tradeshift({
+ oauth2ClientId: getAppId(),
+ oauth2ClientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.TradeshiftBox:
+ return projectSdk.updateOAuth2TradeshiftSandbox({
+ oauth2ClientId: getAppId(),
+ oauth2ClientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Twitch:
+ return projectSdk.updateOAuth2Twitch({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Wordpress:
+ return projectSdk.updateOAuth2WordPress({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.X:
+ return projectSdk.updateOAuth2X({
+ customerKey: getAppId(),
+ secretKey: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Yahoo:
+ return projectSdk.updateOAuth2Yahoo({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Yandex:
+ return projectSdk.updateOAuth2Yandex({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Zoho:
+ return projectSdk.updateOAuth2Zoho({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ case OAuthProvider.Zoom:
+ return projectSdk.updateOAuth2Zoom({
+ clientId: getAppId(),
+ clientSecret: getSecret(),
+ enabled
+ });
+ default:
+ throw new Error(`Unsupported OAuth2 provider: ${provider.key}`);
+ }
+}
+
+export async function updateOAuth({
+ region,
+ projectId,
+ provider,
+ appId,
+ secret,
+ details,
enabled
}: Args): Promise {
try {
@@ -31,13 +345,7 @@ export async function updateOAuth({
throw new Error(`Invalid OAuth2 provider: ${provider.key}`);
}
- await sdk.forConsole.projects.updateOAuth2({
- projectId,
- provider: provider.key,
- appId: appId || undefined,
- secret: secret || undefined,
- enabled
- });
+ await updateProjectOAuth({ region, projectId, provider, appId, secret, details, enabled });
await invalidate(Dependencies.PROJECT);
addNotification({
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/error.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/errorSonner.svelte
similarity index 100%
rename from src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/error.svelte
rename to src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/errorSonner.svelte
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/index.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/index.ts
index cc1daf60a..f5afd0bc5 100644
--- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/index.ts
+++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/collection-[collection]/(components)/sonners/index.ts
@@ -1,3 +1,3 @@
export { default as Save } from './save.svelte';
-export { default as Error } from './error.svelte';
+export { default as Error } from './errorSonner.svelte';
export { default as Suggestions } from './suggestions.svelte';
diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createGit.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createGit.svelte
index 1ea7fffbd..e9ee60e75 100644
--- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createGit.svelte
+++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/(modals)/createGit.svelte
@@ -90,7 +90,10 @@
scopes: ($func.scopes as Scopes[]) || undefined,
installationId: $installation.$id || undefined,
providerRepositoryId: selectedRepository || undefined,
- providerBranch: branch || undefined
+ providerBranch: branch || undefined,
+ providerSilentMode: $func.providerSilentMode ?? undefined,
+ providerRootDirectory: $func.providerRootDirectory ?? undefined,
+ buildSpecification: $func.buildSpecification || undefined
});
}
if (commit) {
diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/disconnectRepo.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/disconnectRepo.svelte
index 9ba31a85a..fc27ddfe9 100644
--- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/disconnectRepo.svelte
+++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/disconnectRepo.svelte
@@ -40,7 +40,8 @@
providerRepositoryId: '',
providerBranch: '',
providerSilentMode: true,
- providerRootDirectory: ''
+ providerRootDirectory: '',
+ buildSpecification: $func.buildSpecification || undefined
});
await invalidate(Dependencies.FUNCTION);
dispatch('success');
diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateRepository.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateRepository.svelte
index 1a2412dfe..c091ffe53 100644
--- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateRepository.svelte
+++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/settings/updateRepository.svelte
@@ -91,7 +91,8 @@
providerRepositoryId: func.providerRepositoryId || undefined,
providerBranch: selectedBranch,
providerSilentMode: silentMode,
- providerRootDirectory: selectedDir
+ providerRootDirectory: selectedDir,
+ buildSpecification: func.buildSpecification || undefined
});
await invalidate(Dependencies.FUNCTION);
addNotification({
@@ -129,7 +130,21 @@
selectedDir !== func?.providerRootDirectory;
async function connect(selectedInstallationId: string, selectedRepository: string) {
+ let nextBranch = func?.providerBranch ?? 'main';
try {
+ const branchList = await sdk
+ .forProject(page.params.region, page.params.project)
+ .vcs.listRepositoryBranches({
+ installationId: selectedInstallationId,
+ providerRepositoryId: selectedRepository
+ });
+ const sorted = sortBranches(branchList.branches);
+ nextBranch =
+ sorted.find((branch) => branch.name === func?.providerBranch)?.name ??
+ sorted.find((branch) => branch.name === 'main' || branch.name === 'master')?.name ??
+ sorted[0]?.name ??
+ nextBranch;
+
if (!isValueOfStringEnum(Runtime, func.runtime)) {
throw new Error(`Invalid runtime: ${func.runtime}`);
}
@@ -148,7 +163,10 @@
scopes: (func.scopes as Scopes[]) || undefined,
installationId: selectedInstallationId,
providerRepositoryId: selectedRepository,
- providerBranch: 'main'
+ providerBranch: nextBranch,
+ providerSilentMode: func.providerSilentMode ?? undefined,
+ providerRootDirectory: func.providerRootDirectory ?? undefined,
+ buildSpecification: func.buildSpecification || undefined
});
await invalidate(Dependencies.FUNCTION);
} catch {
@@ -275,7 +293,7 @@
{#if showSelectRoot}
{/if}
diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
index 70608e2f0..7309623b5 100644
--- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
+++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
@@ -1,8 +1,9 @@
-
+ {#if loadError}
+ {loadError}
+ {/if}
Select all
@@ -158,7 +224,7 @@
{@const checked = categoryState(category, scopes)}
{@const isLastItem = index === categories.length - 1}
{@const scopesLength = filteredScopes.filter(
- (n) => n.category === category && scopes.includes(n.scope as Scopes)
+ (n) => n.category === category && effectiveScopes.includes(n.scope)
).length}
{
try {
// send the project to correct region pool for deletion!
- await sdk.forConsoleIn($project.region).projects.delete({
- projectId: $project.$id
- });
+ await sdk.forProject($project.region, $project.$id).project.delete();
await finishAndRedirect();
} catch (e) {
error = e.message;
diff --git a/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte
index 7bed364e6..fc54b8ba6 100644
--- a/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte
+++ b/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte
@@ -105,7 +105,7 @@
Scopes.FilesRead,
Scopes.BucketsRead,
Scopes.FunctionsRead,
- Scopes.ExecutionRead,
+ Scopes.ExecutionsRead,
Scopes.LocaleRead,
Scopes.AvatarsRead,
Scopes.HealthRead
diff --git a/src/routes/(console)/project-[region]-[project]/settings/migrations/exportModal.svelte b/src/routes/(console)/project-[region]-[project]/settings/migrations/exportModal.svelte
index d2e717718..e70702127 100644
--- a/src/routes/(console)/project-[region]-[project]/settings/migrations/exportModal.svelte
+++ b/src/routes/(console)/project-[region]-[project]/settings/migrations/exportModal.svelte
@@ -107,7 +107,7 @@
Scopes.FilesRead,
Scopes.BucketsRead,
Scopes.FunctionsRead,
- Scopes.ExecutionRead,
+ Scopes.ExecutionsRead,
Scopes.SitesRead,
Scopes.ProvidersRead,
Scopes.TopicsRead,
diff --git a/static/icons/dark/color/fusionauth.svg b/static/icons/dark/color/fusionauth.svg
new file mode 100644
index 000000000..00303a443
--- /dev/null
+++ b/static/icons/dark/color/fusionauth.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/static/icons/dark/color/keycloak.svg b/static/icons/dark/color/keycloak.svg
new file mode 100644
index 000000000..62219d304
--- /dev/null
+++ b/static/icons/dark/color/keycloak.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/static/icons/dark/color/kick.svg b/static/icons/dark/color/kick.svg
new file mode 100644
index 000000000..7bd713230
--- /dev/null
+++ b/static/icons/dark/color/kick.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/static/icons/dark/color/oidc.svg b/static/icons/dark/color/oidc.svg
index 3e45a505d..69ba83b7c 100644
--- a/static/icons/dark/color/oidc.svg
+++ b/static/icons/dark/color/oidc.svg
@@ -1,3 +1,5 @@
-
-
+
+
+
+
diff --git a/static/icons/dark/color/yammer.svg b/static/icons/dark/color/yammer.svg
deleted file mode 100644
index 2d1083bd9..000000000
--- a/static/icons/dark/color/yammer.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/static/icons/dark/grayscale/yammer.svg b/static/icons/dark/grayscale/yammer.svg
deleted file mode 100644
index cbb07a3c2..000000000
--- a/static/icons/dark/grayscale/yammer.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/static/icons/light/color/fusionauth.svg b/static/icons/light/color/fusionauth.svg
new file mode 100644
index 000000000..00303a443
--- /dev/null
+++ b/static/icons/light/color/fusionauth.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/static/icons/light/color/keycloak.svg b/static/icons/light/color/keycloak.svg
new file mode 100644
index 000000000..264768ec4
--- /dev/null
+++ b/static/icons/light/color/keycloak.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/static/icons/light/color/kick.svg b/static/icons/light/color/kick.svg
new file mode 100644
index 000000000..7bd713230
--- /dev/null
+++ b/static/icons/light/color/kick.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/static/icons/light/color/oidc.svg b/static/icons/light/color/oidc.svg
index 3e45a505d..69ba83b7c 100644
--- a/static/icons/light/color/oidc.svg
+++ b/static/icons/light/color/oidc.svg
@@ -1,3 +1,5 @@
-
-
+
+
+
+
diff --git a/static/icons/light/color/yammer.svg b/static/icons/light/color/yammer.svg
deleted file mode 100644
index e6d34f1e9..000000000
--- a/static/icons/light/color/yammer.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/static/icons/light/grayscale/yammer.svg b/static/icons/light/grayscale/yammer.svg
deleted file mode 100644
index 66e6ba653..000000000
--- a/static/icons/light/grayscale/yammer.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-