Skip to content

Commit

Permalink
Redirect if user not logged in when trying to claim ticket (#2192)
Browse files Browse the repository at this point in the history
If the user is not logged in when trying to claim a ticket, redirect
them to the login/register screen, and redirect them back to the claim
after they sign in.

Also added the claim link to the Podbox UI, to make it easier for Podbox
admins to find claim links.
  • Loading branch information
robknight authored Jan 16, 2025
1 parent 157a4ed commit e8553f2
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ExternalLinkIcon } from "@chakra-ui/icons";
import {
Accordion,
AccordionButton,
Expand Down Expand Up @@ -80,24 +79,40 @@ export function PipelineDetailSection({
{pipelineInfo.feeds &&
pipelineInfo.feeds.map((feed, i) => (
<Box key={feed.url} mb={i === 0 ? 0 : 2}>
<PodLink
hideIcon
isExternal
to={`${
process.env.PASSPORT_CLIENT_URL
}/#/add-subscription?url=${encodeURIComponent(feed.url)}`}
>
<Button colorScheme="green">
<Box mr={2}>{feed.name} Feed for Zupass</Box>{" "}
<ExternalLinkIcon mx="2px" />
</Button>
</PodLink>
<Box ml={4} display="inline-block"></Box>
{isAdminView && (
<PodLink to={feed.url} isExternal={true}>
Feed Link
</PodLink>
)}
<UnorderedList spacing={1}>
<ListItem>
<PodLink
hideIcon
isExternal
to={`${
process.env.PASSPORT_CLIENT_URL
}/#/add-subscription?url=${encodeURIComponent(
feed.url
)}`}
>
Subscribe to Feed in Zupass
</PodLink>
</ListItem>
<ListItem>
<PodLink
to={`${
process.env.PASSPORT_CLIENT_URL
}/#/claim?type=ticket&feedUrl=${encodeURIComponent(
feed.url
)}`}
isExternal={true}
>
Claim Single Ticket in Zupass
</PodLink>
</ListItem>
{isAdminView && (
<ListItem>
<PodLink to={feed.url} isExternal={true}>
Direct Feed Link
</PodLink>
</ListItem>
)}
</UnorderedList>
</Box>
))}
</SectionContainer>
Expand Down
15 changes: 14 additions & 1 deletion apps/passport-client/components/screens/ClaimScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ import { NewModals } from "../../new-components/shared/Modals/NewModals";
import { NewLoader } from "../../new-components/shared/NewLoader";
import { Typography } from "../../new-components/shared/Typography";
import { appConfig } from "../../src/appConfig";
import { useCredentialManager, useDispatch, useSelf } from "../../src/appHooks";
import {
useCredentialManager,
useDispatch,
useLoginIfNoSelf,
useSelf
} from "../../src/appHooks";
import { pendingRequestKeys } from "../../src/sessionStorage";
import { Spacer } from "../core";
import { PCDCard } from "../shared/PCDCard";

Expand All @@ -37,6 +43,8 @@ const ClaimRequestSchema = v.object({
type: v.literal("ticket")
});

export type ClaimRequest = v.InferOutput<typeof ClaimRequestSchema>;

function validateRequest(
params: URLSearchParams
): v.SafeParseResult<typeof ClaimRequestSchema> {
Expand All @@ -53,6 +61,11 @@ export function ClaimScreen(): JSX.Element | null {
const request = validateRequest(params);
const queryClient = new QueryClient();

useLoginIfNoSelf(
pendingRequestKeys.claimTicket,
request.success ? request.output : undefined
);

return (
<div>
{request.success &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { assertUnreachable } from "@pcd/util";
import { useLayoutEffect } from "react";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
Expand Down Expand Up @@ -91,7 +92,17 @@ export function NewLoginInterstitialScreen(): JSX.Element {
});
break;
}
case "claimTicket": {
console.log("Redirecting to claim ticket screen");
const encReq = new URLSearchParams(
JSON.parse(pendingRequest.value)
).toString();
clearAllPendingRequests();
navigate(`/claim?${encReq}`, { replace: true });
break;
}
default:
assertUnreachable(pendingRequest.key);
window.location.hash = "#/";
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
pendingRequestKeys,
setPendingAddRequest,
setPendingAddSubscriptionRequest,
setPendingClaimTicketRequest,
setPendingGenericIssuanceCheckinRequest,
setPendingGetWithoutProvingRequest,
setPendingProofRequest,
Expand Down Expand Up @@ -55,6 +56,8 @@ export const NewLoginScreen = (): JSX.Element => {
const pendingGenericIssuanceCheckinRequest = query?.get(
pendingRequestKeys.genericIssuanceCheckin
);
const pendingClaimTicketRequest = query?.get(pendingRequestKeys.claimTicket);

useEffect(() => {
let pendingRequestForLogging: string | undefined = undefined;

Expand All @@ -81,6 +84,9 @@ export const NewLoginScreen = (): JSX.Element => {
pendingGenericIssuanceCheckinRequest
);
pendingRequestForLogging = pendingRequestKeys.genericIssuanceCheckin;
} else if (pendingClaimTicketRequest) {
setPendingClaimTicketRequest(pendingClaimTicketRequest);
pendingRequestForLogging = pendingRequestKeys.claimTicket;
}

if (pendingRequestForLogging) {
Expand All @@ -95,7 +101,8 @@ export const NewLoginScreen = (): JSX.Element => {
pendingViewSubscriptionsRequest,
pendingAddSubscriptionRequest,
pendingViewFrogCryptoRequest,
pendingGenericIssuanceCheckinRequest
pendingGenericIssuanceCheckinRequest,
pendingClaimTicketRequest
]);

const suggestedEmail = query?.get("email");
Expand Down
3 changes: 2 additions & 1 deletion apps/passport-client/src/appHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { SemaphoreIdentityPCD } from "@pcd/semaphore-identity-pcd";
import { Identity } from "@semaphore-protocol/identity";
import { useContext, useEffect, useMemo, useRef, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { ClaimRequest } from "../components/screens/ClaimScreen";
import {
Dispatcher,
StateContext,
Expand Down Expand Up @@ -337,7 +338,7 @@ export function useLaserScannerKeystrokeInput(): string {

export function useLoginIfNoSelf(
key: string,
request?: PCDRequest | string
request?: PCDRequest | string | ClaimRequest
): void {
const self = useSelf();
const userForcedToLogout = useUserForcedToLogout();
Expand Down
25 changes: 20 additions & 5 deletions apps/passport-client/src/sessionStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export function clearAllPendingRequests(): void {
clearPendingAddSubscriptionRequest();
clearPendingGenericIssuanceCheckinRequest();
clearPendingAuthenticateIFrameRequest();
clearPendingClaimTicketRequest();
}

export function hasPendingRequest(): boolean {
Expand All @@ -19,11 +20,12 @@ export function hasPendingRequest(): boolean {
getPendingAddSubscriptionPageRequest() ||
getPendingViewFrogCryptoPageRequest() ||
getPendingGenericIssuanceCheckinRequest() ||
getPendingAuthenticateIFrameRequest()
getPendingAuthenticateIFrameRequest() ||
getPendingClaimTicketRequest()
);
}

export const pendingRequestKeys: Record<string, string> = {
export const pendingRequestKeys = {
getWithoutProving: "getWithoutProvingRequest",
add: "pendingAddRequest",
halo: "pendingHaloRequest",
Expand All @@ -32,7 +34,8 @@ export const pendingRequestKeys: Record<string, string> = {
addSubscription: "pendingAddSubscription",
viewFrogCrypto: "pendingViewFrogCrypto",
genericIssuanceCheckin: "pendingGenericIssuanceCheckin",
authenticateIFrame: "pendingAuthenticateIFrame"
authenticateIFrame: "pendingAuthenticateIFrame",
claimTicket: "pendingClaimTicket"
} as const;

export function setPendingGetWithoutProvingRequest(request: string): void {
Expand Down Expand Up @@ -154,14 +157,26 @@ export function getPendingAuthenticateIFrameRequest(): string | undefined {
return value ?? undefined;
}

export function setPendingClaimTicketRequest(request: string): void {
sessionStorage.setItem(pendingRequestKeys.claimTicket, request);
}

export function clearPendingClaimTicketRequest(): void {
sessionStorage.removeItem(pendingRequestKeys.claimTicket);
}

export function getPendingClaimTicketRequest(): string | undefined {
const value = sessionStorage.getItem(pendingRequestKeys.claimTicket);
return value ?? undefined;
}

/**
* Gets any pending request, if any. Returns undefined if none.
*/
export function getPendingRequest():
| { key: keyof typeof pendingRequestKeys; value: string }
| undefined {
for (const key in pendingRequestKeys) {
const sessionStorageKey = pendingRequestKeys[key];
for (const [key, sessionStorageKey] of Object.entries(pendingRequestKeys)) {
const item = sessionStorage.getItem(sessionStorageKey);
if (item) {
return {
Expand Down

0 comments on commit e8553f2

Please sign in to comment.