Skip to content

Commit

Permalink
fix: campaign checks (#614)
Browse files Browse the repository at this point in the history
Signed-off-by: Urban Vidovič <urbanfoundit@gmail.com>
Co-authored-by: Urban <urbanfoundit@gmail.com>
  • Loading branch information
tadejpodrekar and pseudobun authored Mar 30, 2024
1 parent 5cb712a commit fc1f796
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 48 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-pandas-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@blockchain-lab-um/dapp": patch
---

Adds campaign issue checks.
103 changes: 61 additions & 42 deletions packages/dapp/src/app/api/campaigns/issue/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,35 +76,74 @@ export async function POST(request: NextRequest) {
});
}

if (campaign.total && campaign.claimed >= campaign.total) {
return new NextResponse('Campaign is already fully claimed', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}
const { data: completedRequirements, error: completedRequirementsError } =
await supabase.rpc('get_num_of_users_requirements_by_campaign', {
campaign_id: campaignId,
user_id: user.sub,
});
const { data: claim, error: claimError } = await supabase
.from('claims')
.select('*')
.eq('campaign_id', campaignId)
.eq('user_id', user.sub);

if (completedRequirementsError) {
if (claimError) {
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}
if (completedRequirements !== campaign.requirements.length) {
return new NextResponse('User has not completed all requirements', {
status: 400,
headers: {
...CORS_HEADERS,
},
});

let claimDate = new Date().toISOString();
let alreadyClaimed = false;
if (claim.length > 0) {
claimDate = claim[0].claimed_at;
alreadyClaimed = true;
}

if (!alreadyClaimed) {
const now = new Date();
const startDateValid =
campaign.start_date && new Date(campaign.start_date) > now;
const endDateValid =
campaign.end_date && new Date(campaign.end_date) < now;
const isCampaignInactive = startDateValid || endDateValid;
const isCampaignFullyClaimed =
campaign.total && campaign.claimed >= campaign.total;

if (isCampaignInactive) {
return new NextResponse('Campaign is not active', {
status: 400,
headers: { ...CORS_HEADERS },
});
}

if (isCampaignFullyClaimed) {
return new NextResponse('Campaign is already fully claimed', {
status: 400,
headers: { ...CORS_HEADERS },
});
}

const { data: completedRequirements, error: completedRequirementsError } =
await supabase.rpc('get_num_of_users_requirements_by_campaign', {
campaign_id: campaignId,
user_id: user.sub,
});

if (completedRequirementsError) {
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}
if (completedRequirements !== campaign.requirements.length) {
return new NextResponse('User has not completed all requirements', {
status: 400,
headers: {
...CORS_HEADERS,
},
});
}
}

const agent = await getAgent();
Expand Down Expand Up @@ -135,21 +174,6 @@ export async function POST(request: NextRequest) {
});
}

const { data: claim, error: claimError } = await supabase
.from('claims')
.select('*')
.eq('campaign_id', campaignId)
.eq('user_id', user.sub);

if (claimError) {
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
...CORS_HEADERS,
},
});
}

const controllerKeyId = 'key-1';

const issuerDid = await agent.didManagerImport({
Expand All @@ -166,12 +190,8 @@ export async function POST(request: NextRequest) {
],
});

let claimDate = new Date().toISOString();
if (claim.length > 0) {
claimDate = claim[0].claimed_at;
}
let credentialId = claim[0]?.credential_id;
if (claim.length === 0) {
if (!alreadyClaimed) {
const { data: insertedClaimData, error: updatedClaimError } =
await supabase
.from('claims')
Expand All @@ -194,7 +214,6 @@ export async function POST(request: NextRequest) {
});
}

console.error('Error updating claim', updatedClaimError);
return new NextResponse('Internal Server Error', {
status: 500,
headers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,15 @@ export async function POST(
let credentials: VerifiableCredential[];

try {
credentials = presentation.verifiableCredential.map((credential) =>
normalizeCredential(credential)
credentials = presentation.verifiableCredential.reduce(
(result, credential) => {
const normalized = normalizeCredential(credential);
if (normalized?.credentialSubject?.id === did) {
result.push(normalized);
}
return result;
},
[] as VerifiableCredential[]
);
} catch (error) {
console.error('Error decoding credentials', error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { useSwitchChain, useVerifyRequirement } from '@/hooks';
import { useAuthStore, useMascaStore, useToastStore } from '@/stores';
import { isError } from '@blockchain-lab-um/masca-connector';
import { shallow } from 'zustand/shallow';
import { VerifiableCredential } from 'did-jwt-vc';
import type { W3CVerifiableCredential } from '@veramo/core';

type RequirementProps = {
requirement: Tables<'requirements'>;
Expand All @@ -24,7 +26,14 @@ export const RequirementDisplay = ({
}: RequirementProps) => {
const t = useTranslations('RequirementDisplay');

const token = useAuthStore((state) => state.token);
const { token, isSignedIn, changeIsSignInModalOpen } = useAuthStore(
(state) => ({
token: state.token,
isSignedIn: state.isSignedIn,
changeIsSignInModalOpen: state.changeIsSignInModalOpen,
}),
shallow
);

const { api, did, didMethod, changeDID, changeCurrDIDMethod } = useMascaStore(
(state) => ({
Expand Down Expand Up @@ -80,9 +89,18 @@ export const RequirementDisplay = ({
return;
}

// Create a presentation from all the user's credentials
// Create a presentation from all the user's credentials except the polygonid ones
const createPresentationResult = await api.createPresentation({
vcs: queryCredentialsResult.data.map((queryResult) => queryResult.data),
vcs: queryCredentialsResult.data.reduce((acc, queryResult) => {
const credential = queryResult.data;
if (
!credential.issuer.includes('did:poylgonid') &&
!credential.issuer.includes('did:iden3')
) {
acc.push(credential);
}
return acc;
}, [] as W3CVerifiableCredential[]),
proofFormat: 'EthereumEip712Signature2021',
});

Expand All @@ -91,6 +109,7 @@ export const RequirementDisplay = ({
return;
}
setStartedVerifying(false);

await verifyRequirement({
did: currentDid,
presentation: createPresentationResult.data,
Expand Down Expand Up @@ -120,7 +139,9 @@ export const RequirementDisplay = ({
<Button
variant="primary"
size="xs"
onClick={handleVerify}
onClick={() =>
isSignedIn ? handleVerify() : changeIsSignInModalOpen(true)
}
loading={startedVerifying || isVerifying}
disabled={!did || startedVerifying || isVerifying}
>
Expand Down

0 comments on commit fc1f796

Please sign in to comment.