use session storage for client secret during onboarding (fix #14)
This commit is contained in:
@@ -1,12 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { ButtonContainer } from '@/components/button-container';
|
import { ButtonContainer } from '@/components/button-container';
|
||||||
import { InputWithLabel } from '@/components/forms/input-with-label';
|
import { InputWithLabel } from '@/components/forms/input-with-label';
|
||||||
import { Alert } from '@/components/ui/alert';
|
|
||||||
import { LinkButton } from '@/components/ui/button';
|
import { LinkButton } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { useClientSecret } from '@/hooks/useClientSecret';
|
||||||
import { KeyIcon, LockIcon } from 'lucide-react';
|
import { LockIcon } from 'lucide-react';
|
||||||
|
|
||||||
import type { IServiceProjectWithClients } from '@openpanel/db';
|
import type { IServiceProjectWithClients } from '@openpanel/db';
|
||||||
|
|
||||||
@@ -23,6 +21,7 @@ type Props = {
|
|||||||
|
|
||||||
const Connect = ({ project }: Props) => {
|
const Connect = ({ project }: Props) => {
|
||||||
const client = project.clients[0];
|
const client = project.clients[0];
|
||||||
|
const [secret] = useClientSecret();
|
||||||
|
|
||||||
if (!client) {
|
if (!client) {
|
||||||
return <div>Hmm, something fishy is going on. Please reload the page.</div>;
|
return <div>Hmm, something fishy is going on. Please reload the page.</div>;
|
||||||
@@ -43,11 +42,7 @@ const Connect = ({ project }: Props) => {
|
|||||||
Credentials
|
Credentials
|
||||||
</div>
|
</div>
|
||||||
<InputWithLabel label="Client ID" disabled value={client.id} />
|
<InputWithLabel label="Client ID" disabled value={client.id} />
|
||||||
<InputWithLabel
|
<InputWithLabel label="Client Secret" disabled value={secret} />
|
||||||
label="Client Secret"
|
|
||||||
disabled
|
|
||||||
value={client.secret ?? 'unknown'}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
{project.types.map((type) => {
|
{project.types.map((type) => {
|
||||||
const Component = {
|
const Component = {
|
||||||
@@ -56,7 +51,7 @@ const Connect = ({ project }: Props) => {
|
|||||||
backend: ConnectBackend,
|
backend: ConnectBackend,
|
||||||
}[type];
|
}[type];
|
||||||
|
|
||||||
return <Component key={type} client={client} />;
|
return <Component key={type} client={{ ...client, secret }} />;
|
||||||
})}
|
})}
|
||||||
<ButtonContainer>
|
<ButtonContainer>
|
||||||
<div />
|
<div />
|
||||||
|
|||||||
@@ -17,17 +17,11 @@ const Connect = async ({ params: { projectId } }: Props) => {
|
|||||||
throw new Error('No organization found');
|
throw new Error('No organization found');
|
||||||
}
|
}
|
||||||
const project = await getProjectWithClients(projectId);
|
const project = await getProjectWithClients(projectId);
|
||||||
const clientSecret = cookies().get('onboarding_client_secret')?.value ?? null;
|
|
||||||
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
return <div>Hmm, something fishy is going on. Please reload the page.</div>;
|
return <div>Hmm, something fishy is going on. Please reload the page.</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set visible client secret from cookie
|
|
||||||
if (clientSecret && project.clients[0]) {
|
|
||||||
project.clients[0].secret = clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <OnboardingConnect project={project} />;
|
return <OnboardingConnect project={project} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,17 +27,11 @@ const Verify = async ({ params: { projectId } }: Props) => {
|
|||||||
`SELECT * FROM events WHERE project_id = ${escape(projectId)} LIMIT 100`
|
`SELECT * FROM events WHERE project_id = ${escape(projectId)} LIMIT 100`
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
const clientSecret = cookies().get('onboarding_client_secret')?.value ?? null;
|
|
||||||
|
|
||||||
if (!project) {
|
if (!project) {
|
||||||
return <div>Hmm, something fishy is going on. Please reload the page.</div>;
|
return <div>Hmm, something fishy is going on. Please reload the page.</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set visible client secret from cookie
|
|
||||||
if (clientSecret && project.clients[0]) {
|
|
||||||
project.clients[0].secret = clientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <OnboardingVerify project={project} events={events} />;
|
return <OnboardingVerify project={project} events={events} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { InputWithLabel } from '@/components/forms/input-with-label';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Combobox } from '@/components/ui/combobox';
|
import { Combobox } from '@/components/ui/combobox';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
|
import { useClientSecret } from '@/hooks/useClientSecret';
|
||||||
import { api, handleError } from '@/trpc/client';
|
import { api, handleError } from '@/trpc/client';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import {
|
import {
|
||||||
@@ -33,10 +34,12 @@ const Tracking = ({
|
|||||||
}: {
|
}: {
|
||||||
organizations: IServiceOrganization[];
|
organizations: IServiceOrganization[];
|
||||||
}) => {
|
}) => {
|
||||||
|
const [, setSecret] = useClientSecret();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const mutation = api.onboarding.project.useMutation({
|
const mutation = api.onboarding.project.useMutation({
|
||||||
onError: handleError,
|
onError: handleError,
|
||||||
onSuccess(res) {
|
onSuccess(res) {
|
||||||
|
setSecret(res.secret);
|
||||||
router.push(`/onboarding/${res.projectId}/connect`);
|
router.push(`/onboarding/${res.projectId}/connect`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
23
apps/dashboard/src/hooks/useClientSecret.ts
Normal file
23
apps/dashboard/src/hooks/useClientSecret.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export const ONBOARDING_SECRET_KEY = 'onboarding.clientSecret';
|
||||||
|
const DEFAULT_SECRET = '[CLIENT_SECRET]';
|
||||||
|
|
||||||
|
export function useClientSecret() {
|
||||||
|
const [clientSecret, setClientSecret] = useState<string>(DEFAULT_SECRET);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (clientSecret && DEFAULT_SECRET !== clientSecret) {
|
||||||
|
sessionStorage.setItem(ONBOARDING_SECRET_KEY, clientSecret);
|
||||||
|
}
|
||||||
|
}, [clientSecret]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const clientSecret = sessionStorage.getItem(ONBOARDING_SECRET_KEY);
|
||||||
|
if (clientSecret) {
|
||||||
|
setClientSecret(clientSecret);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return [clientSecret, setClientSecret] as const;
|
||||||
|
}
|
||||||
@@ -69,11 +69,6 @@ export const onboardingRouter = createTRPCRouter({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.setCookie('onboarding_client_secret', secret, {
|
|
||||||
maxAge: 60 * 60, // 1 hour
|
|
||||||
path: '/',
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...client,
|
...client,
|
||||||
secret,
|
secret,
|
||||||
|
|||||||
Reference in New Issue
Block a user