diff --git a/next.config.ts b/next.config.ts
index 40c94fa2b..eac6f327a 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -5,7 +5,7 @@ const TRACKER_SCRIPT = '/script.js';
const basePath = process.env.BASE_PATH;
const collectApiEndpoint = process.env.COLLECT_API_ENDPOINT;
-const cloudUrl = process.env.CLOUD_URL;
+const cloudMode = !!process.env.CLOUD_MODE;
const corsMaxAge = process.env.CORS_MAX_AGE;
const defaultLocale = process.env.DEFAULT_LOCALE;
const forceSSL = process.env.FORCE_SSL;
@@ -157,20 +157,12 @@ if (trackerScriptName) {
}
}
-if (cloudUrl) {
- redirects.push({
- source: '/login',
- destination: cloudUrl,
- permanent: false,
- });
-}
-
/** @type {import('next').NextConfig} */
export default {
reactStrictMode: false,
env: {
basePath,
- cloudUrl,
+ cloudMode,
currentVersion: pkg.version,
defaultLocale,
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6c035c862..865d02cf1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -364,6 +364,8 @@ importers:
specifier: ^5.9.2
version: 5.9.2
+ dist: {}
+
packages:
'@ampproject/remapping@2.3.0':
diff --git a/src/app/(collect)/p/[slug]/route.ts b/src/app/(collect)/p/[slug]/route.ts
index 97d9a3f2a..23ac03cc1 100644
--- a/src/app/(collect)/p/[slug]/route.ts
+++ b/src/app/(collect)/p/[slug]/route.ts
@@ -29,7 +29,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
const req = new Request(request.url, {
method: 'POST',
- headers: { 'Content-Type': 'application/json' },
+ headers: request.headers,
body: JSON.stringify(payload),
});
diff --git a/src/app/(collect)/q/[slug]/route.ts b/src/app/(collect)/q/[slug]/route.ts
index 4c0f683c3..3a6806565 100644
--- a/src/app/(collect)/q/[slug]/route.ts
+++ b/src/app/(collect)/q/[slug]/route.ts
@@ -27,7 +27,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
const req = new Request(request.url, {
method: 'POST',
- headers: { 'Content-Type': 'application/json' },
+ headers: request.headers,
body: JSON.stringify(payload),
});
diff --git a/src/app/(main)/UpdateNotice.tsx b/src/app/(main)/UpdateNotice.tsx
index c971d4038..357287912 100644
--- a/src/app/(main)/UpdateNotice.tsx
+++ b/src/app/(main)/UpdateNotice.tsx
@@ -18,7 +18,7 @@ export function UpdateNotice({ user, config }) {
!config?.updatesDisabled &&
!config?.privateMode &&
!pathname.includes('/share/') &&
- !process.env.cloudUrl &&
+ !process.env.cloudMode &&
!dismissed;
const updateCheck = useCallback(() => {
diff --git a/src/app/(main)/admin/AdminLayout.tsx b/src/app/(main)/admin/AdminLayout.tsx
index eb4c2ffa5..8b1387854 100644
--- a/src/app/(main)/admin/AdminLayout.tsx
+++ b/src/app/(main)/admin/AdminLayout.tsx
@@ -11,7 +11,7 @@ export function AdminLayout({ children }: { children: ReactNode }) {
const { formatMessage, labels } = useMessages();
const { pathname } = useNavigation();
- if (!user.isAdmin || process.env.cloudUrl) {
+ if (!user.isAdmin || process.env.cloudMode) {
return null;
}
diff --git a/src/app/(main)/admin/layout.tsx b/src/app/(main)/admin/layout.tsx
index 3dea41422..634fc6588 100644
--- a/src/app/(main)/admin/layout.tsx
+++ b/src/app/(main)/admin/layout.tsx
@@ -2,7 +2,7 @@ import { Metadata } from 'next';
import { AdminLayout } from './AdminLayout';
export default function ({ children }) {
- if (process.env.cloudUrl) {
+ if (process.env.cloudMode) {
return null;
}
diff --git a/src/app/(main)/links/LinkAddButton.tsx b/src/app/(main)/links/LinkAddButton.tsx
index dc819ef38..4ad81a46f 100644
--- a/src/app/(main)/links/LinkAddButton.tsx
+++ b/src/app/(main)/links/LinkAddButton.tsx
@@ -1,17 +1,10 @@
-import { useMessages, useModified } from '@/components/hooks';
-import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
+import { useMessages } from '@/components/hooks';
+import { Button, Icon, Modal, Dialog, DialogTrigger, Text } from '@umami/react-zen';
import { Plus } from '@/components/icons';
import { LinkEditForm } from './LinkEditForm';
export function LinkAddButton({ teamId }: { teamId?: string }) {
- const { formatMessage, labels, messages } = useMessages();
- const { toast } = useToast();
- const { touch } = useModified();
-
- const handleSave = async () => {
- toast(formatMessage(messages.saved));
- touch('links');
- };
+ const { formatMessage, labels } = useMessages();
return (
@@ -23,7 +16,7 @@ export function LinkAddButton({ teamId }: { teamId?: string }) {
diff --git a/src/app/(main)/links/LinkEditForm.tsx b/src/app/(main)/links/LinkEditForm.tsx
index 16c65aecb..23aaab1e6 100644
--- a/src/app/(main)/links/LinkEditForm.tsx
+++ b/src/app/(main)/links/LinkEditForm.tsx
@@ -139,7 +139,9 @@ export function LinkEditForm({
{formatMessage(labels.cancel)}
)}
- {formatMessage(labels.save)}
+
+ {formatMessage(labels.save)}
+
>
);
diff --git a/src/app/(main)/pixels/PixelAddButton.tsx b/src/app/(main)/pixels/PixelAddButton.tsx
index 0958ff0e6..9c60db8c6 100644
--- a/src/app/(main)/pixels/PixelAddButton.tsx
+++ b/src/app/(main)/pixels/PixelAddButton.tsx
@@ -1,17 +1,10 @@
-import { useMessages, useModified } from '@/components/hooks';
-import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
+import { useMessages } from '@/components/hooks';
+import { Button, Icon, Modal, Dialog, DialogTrigger, Text } from '@umami/react-zen';
import { Plus } from '@/components/icons';
import { PixelEditForm } from './PixelEditForm';
export function PixelAddButton({ teamId }: { teamId?: string }) {
- const { formatMessage, labels, messages } = useMessages();
- const { toast } = useToast();
- const { touch } = useModified();
-
- const handleSave = async () => {
- toast(formatMessage(messages.saved));
- touch('pixels');
- };
+ const { formatMessage, labels } = useMessages();
return (
@@ -23,7 +16,7 @@ export function PixelAddButton({ teamId }: { teamId?: string }) {
diff --git a/src/app/(main)/settings/layout.tsx b/src/app/(main)/settings/layout.tsx
index 6f409e483..fcc7392ad 100644
--- a/src/app/(main)/settings/layout.tsx
+++ b/src/app/(main)/settings/layout.tsx
@@ -2,7 +2,7 @@ import { Metadata } from 'next';
import { SettingsLayout } from './SettingsLayout';
export default function ({ children }) {
- if (process.env.cloudUrl) {
+ if (process.env.cloudMode) {
return null;
}
diff --git a/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx b/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx
index cfe552300..c02d85c9a 100644
--- a/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx
+++ b/src/app/(main)/websites/[websiteId]/cohorts/CohortEditForm.tsx
@@ -114,10 +114,7 @@ export function CohortEditForm({
-
+
diff --git a/src/app/api/config/route.ts b/src/app/api/config/route.ts
index 7fa9ce8e2..4e40caa4b 100644
--- a/src/app/api/config/route.ts
+++ b/src/app/api/config/route.ts
@@ -9,8 +9,7 @@ export async function GET(request: Request) {
}
return json({
- cloudMode: !!process.env.CLOUD_URL,
- cloudUrl: process.env.CLOUD_URL,
+ cloudMode: !!process.env.CLOUD_MODE,
faviconUrl: process.env.FAVICON_URL,
linksUrl: process.env.LINKS_URL,
pixelsUrl: process.env.PIXELS_URL,
diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx
index 4c8d80446..8abf7a4e0 100644
--- a/src/app/login/page.tsx
+++ b/src/app/login/page.tsx
@@ -2,7 +2,7 @@ import { Metadata } from 'next';
import { LoginPage } from './LoginPage';
export default async function () {
- if (process.env.DISABLE_LOGIN) {
+ if (process.env.DISABLE_LOGIN || process.env.CLOUD_MODE) {
return null;
}
diff --git a/src/app/logout/page.tsx b/src/app/logout/page.tsx
index 7b56ea679..0617c2e2d 100644
--- a/src/app/logout/page.tsx
+++ b/src/app/logout/page.tsx
@@ -1,8 +1,8 @@
-import { LogoutPage } from './LogoutPage';
import { Metadata } from 'next';
+import { LogoutPage } from './LogoutPage';
export default function () {
- if (process.env.DISABLE_LOGIN) {
+ if (process.env.DISABLE_LOGIN || process.env.CLOUD_MODE) {
return null;
}
diff --git a/src/components/hooks/useConfig.ts b/src/components/hooks/useConfig.ts
index 170136437..643b9cbc7 100644
--- a/src/components/hooks/useConfig.ts
+++ b/src/components/hooks/useConfig.ts
@@ -4,7 +4,6 @@ import { useApi } from '@/components/hooks/useApi';
export type Config = {
cloudMode: boolean;
- cloudUrl?: string;
faviconUrl?: string;
linksUrl?: string;
pixelsUrl?: string;
diff --git a/src/components/input/ProfileButton.tsx b/src/components/input/ProfileButton.tsx
index 017ea8319..03f14d071 100644
--- a/src/components/input/ProfileButton.tsx
+++ b/src/components/input/ProfileButton.tsx
@@ -11,14 +11,13 @@ import {
Text,
Row,
} from '@umami/react-zen';
-import { useMessages, useLoginQuery, useNavigation, useConfig } from '@/components/hooks';
+import { useMessages, useLoginQuery, useNavigation } from '@/components/hooks';
import { LogOut, UserCircle, LockKeyhole } from '@/components/icons';
export function ProfileButton() {
const { formatMessage, labels } = useMessages();
const { user } = useLoginQuery();
const { renderUrl } = useNavigation();
- const { cloudUrl } = useConfig();
const items = [
{
@@ -28,7 +27,7 @@ export function ProfileButton() {
icon: ,
},
user.isAdmin &&
- !cloudUrl && {
+ !process.env.cloudMode && {
id: 'admin',
label: formatMessage(labels.admin),
path: '/admin',
diff --git a/src/components/input/SettingsButton.tsx b/src/components/input/SettingsButton.tsx
index 7e5ac4852..68fd2cdc3 100644
--- a/src/components/input/SettingsButton.tsx
+++ b/src/components/input/SettingsButton.tsx
@@ -16,12 +16,12 @@ export function SettingsButton() {
const { formatMessage, labels } = useMessages();
const { user } = useLoginQuery();
const { router, renderUrl } = useNavigation();
- const { cloudMode, cloudUrl } = useConfig();
+ const { cloudMode } = useConfig();
const handleAction = (id: Key) => {
if (id === 'settings') {
if (cloudMode) {
- window.location.href = `${cloudUrl}/settings`;
+ window.location.href = `/settings`;
return;
}
}
diff --git a/src/components/messages.ts b/src/components/messages.ts
index ebd8c7651..1abe98f28 100644
--- a/src/components/messages.ts
+++ b/src/components/messages.ts
@@ -359,7 +359,7 @@ export const labels = defineMessages({
invalidUrl: { id: 'label.invalid-url', defaultMessage: 'Invalid URL' },
environment: { id: 'label.environment', defaultMessage: 'Environment' },
criteria: { id: 'label.criteria', defaultMessage: 'Criteria' },
- share: { defaultMessage: 'label.share', id: 'Share' },
+ share: { id: 'label.share', defaultMessage: 'Share' },
});
export const messages = defineMessages({
diff --git a/src/lib/auth.ts b/src/lib/auth.ts
index 46af18b8a..890e535f4 100644
--- a/src/lib/auth.ts
+++ b/src/lib/auth.ts
@@ -18,10 +18,10 @@ export function getBearerToken(request: Request) {
export async function checkAuth(request: Request) {
const token = getBearerToken(request);
const payload = parseSecureToken(token, secret());
- const shareToken = await parseShareToken(request.headers);
+ const shareToken = await parseShareToken(request);
let user = null;
- const { userId, authKey, grant } = payload || {};
+ const { userId, authKey } = payload || {};
if (userId) {
user = await getUser(userId);
@@ -33,7 +33,7 @@ export async function checkAuth(request: Request) {
}
}
- log({ token, shareToken, payload, user, grant });
+ log({ token, payload, authKey, shareToken, user });
if (!user?.id && !shareToken) {
log('User not authorized');
@@ -45,11 +45,10 @@ export async function checkAuth(request: Request) {
}
return {
- user,
- grant,
token,
- shareToken,
authKey,
+ shareToken,
+ user,
};
}
@@ -71,9 +70,9 @@ export async function hasPermission(role: string, permission: string | string[])
return ensureArray(permission).some(e => ROLE_PERMISSIONS[role]?.includes(e));
}
-export function parseShareToken(headers: Headers) {
+export function parseShareToken(request: Request) {
try {
- return parseToken(headers.get(SHARE_TOKEN_HEADER), secret());
+ return parseToken(request.headers.get(SHARE_TOKEN_HEADER), secret());
} catch (e) {
log(e);
return null;
diff --git a/src/lib/types.ts b/src/lib/types.ts
index c70490598..1237f5199 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -1,5 +1,5 @@
import { UseQueryOptions } from '@tanstack/react-query';
-import { DATA_TYPE, PERMISSIONS, ROLES, OPERATORS } from './constants';
+import { DATA_TYPE, ROLES, OPERATORS } from './constants';
import { TIME_UNIT } from './date';
export type ObjectValues = T[keyof T];
@@ -7,7 +7,6 @@ export type ObjectValues = T[keyof T];
export type ReactQueryOptions = Omit, 'queryKey' | 'queryFn'>;
export type TimeUnit = ObjectValues;
-export type Permission = ObjectValues;
export type Role = ObjectValues;
export type DynamicDataType = ObjectValues;
export type Operator = (typeof OPERATORS)[keyof typeof OPERATORS];
@@ -19,7 +18,6 @@ export interface Auth {
role: string;
isAdmin: boolean;
};
- grant?: Permission[];
shareToken?: {
websiteId: string;
};
diff --git a/src/permissions/team.ts b/src/permissions/team.ts
index 3273c8192..77e42b1bd 100644
--- a/src/permissions/team.ts
+++ b/src/permissions/team.ts
@@ -3,8 +3,6 @@ import { PERMISSIONS } from '@/lib/constants';
import { getTeamUser } from '@/queries';
import { hasPermission } from '@/lib/auth';
-const cloudMode = !!process.env.CLOUD_URL;
-
export async function canViewTeam({ user }: Auth, teamId: string) {
if (user.isAdmin) {
return true;
@@ -13,11 +11,7 @@ export async function canViewTeam({ user }: Auth, teamId: string) {
return getTeamUser(teamId, user.id);
}
-export async function canCreateTeam({ user, grant }: Auth) {
- if (cloudMode) {
- return !!grant?.find(a => a === PERMISSIONS.teamCreate);
- }
-
+export async function canCreateTeam({ user }: Auth) {
if (user.isAdmin) {
return true;
}
@@ -25,15 +19,11 @@ export async function canCreateTeam({ user, grant }: Auth) {
return !!user;
}
-export async function canUpdateTeam({ user, grant }: Auth, teamId: string) {
+export async function canUpdateTeam({ user }: Auth, teamId: string) {
if (user.isAdmin) {
return true;
}
- if (cloudMode) {
- return !!grant?.find(a => a === PERMISSIONS.teamUpdate);
- }
-
const teamUser = await getTeamUser(teamId, user.id);
return teamUser && hasPermission(teamUser.role, PERMISSIONS.teamUpdate);
@@ -49,11 +39,7 @@ export async function canDeleteTeam({ user }: Auth, teamId: string) {
return teamUser && hasPermission(teamUser.role, PERMISSIONS.teamDelete);
}
-export async function canAddUserToTeam({ user, grant }: Auth) {
- if (cloudMode) {
- return !!grant?.find(a => a === PERMISSIONS.teamUpdate);
- }
-
+export async function canAddUserToTeam({ user }: Auth) {
return user.isAdmin;
}
diff --git a/src/permissions/website.ts b/src/permissions/website.ts
index 63ae5c903..11e8dc650 100644
--- a/src/permissions/website.ts
+++ b/src/permissions/website.ts
@@ -3,8 +3,6 @@ import { PERMISSIONS } from '@/lib/constants';
import { hasPermission } from '@/lib/auth';
import { getTeamUser, getWebsite } from '@/queries';
-const cloudMode = !!process.env.CLOUD_URL;
-
export async function canViewWebsite({ user, shareToken }: Auth, websiteId: string) {
if (user?.isAdmin) {
return true;
@@ -33,11 +31,7 @@ export async function canViewAllWebsites({ user }: Auth) {
return user.isAdmin;
}
-export async function canCreateWebsite({ user, grant }: Auth) {
- if (cloudMode) {
- return !!grant?.find(a => a === PERMISSIONS.websiteCreate);
- }
-
+export async function canCreateWebsite({ user }: Auth) {
if (user.isAdmin) {
return true;
}