Skip to content

Commit

Permalink
feat(signature-collection): user not found handling (#16431)
Browse files Browse the repository at this point in the history
* feat(signature=collection): user not found handling

* fix: text update

* chore: nx format:write update dirty files

---------

Co-authored-by: andes-it <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 16, 2024
1 parent d25d4e9 commit 8b46f97
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
Injectable,
NotFoundException,
UnauthorizedException,
} from '@nestjs/common'
import { Injectable, NotFoundException } from '@nestjs/common'
import { SignatureCollectionSuccess } from './models/success.model'
import { SignatureCollection } from './models/collection.model'
import {
Expand All @@ -19,11 +15,8 @@ import { User } from '@island.is/auth-nest-tools'
import { SignatureCollectionCancelListsInput } from './dto/cencelLists.input'
import { SignatureCollectionIdInput } from './dto/collectionId.input'
import { SignatureCollectionAddListsInput } from './dto/addLists.input'
import { SignatureCollectionOwnerInput } from './dto/owner.input'
import { SignatureCollectionListBulkUploadInput } from './dto/bulkUpload.input'
import { SignatureCollectionUploadPaperSignatureInput } from './dto/uploadPaperSignature.input'
import { SignatureCollectionCanSignFromPaperInput } from './dto/canSignFromPaper.input'
import { SignatureCollectionCandidateIdInput } from './dto/candidateId.input'
import { SignatureCollectionCollector } from './models/collector.model'

@Injectable()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,41 @@ export class ParliamentaryListSigningService extends BaseTemplateApiService {
}

async canSign({ auth }: TemplateApiModuleActionProps) {
const signee = await this.signatureCollectionClientService.getSignee(auth)
const { canSign, canSignInfo } = signee
if (canSign) {
return signee
}
if (!canSignInfo) {
// canCreateInfo will always be defined if canCreate is false but we need to check for typescript
try {
const signee = await this.signatureCollectionClientService.getSignee(auth)
const { canSign, canSignInfo } = signee
if (canSign) {
return signee
}
if (!canSignInfo) {
// canCreateInfo will always be defined if canCreate is false but we need to check for typescript
throw new TemplateApiError(errorMessages.deniedByService, 400)
}
const errors: ProviderErrorReason[] = canSignInfo?.map((key) => {
switch (key) {
case ReasonKey.UnderAge:
return errorMessages.age
case ReasonKey.NoCitizenship:
return errorMessages.citizenship
case ReasonKey.NotISResidency:
return errorMessages.residency
case ReasonKey.CollectionNotOpen:
return errorMessages.active
case ReasonKey.AlreadySigned:
return errorMessages.signer
case ReasonKey.noInvalidSignature:
return errorMessages.invalidSignature
default:
return errorMessages.deniedByService
}
})
throw new TemplateApiError(errors, 405)
} catch (error) {
if (error.status === 404) {
throw new TemplateApiError(errorMessages.singeeNotFound, 404)
}
throw new TemplateApiError(errorMessages.deniedByService, 400)
}
const errors: ProviderErrorReason[] = canSignInfo?.map((key) => {
switch (key) {
case ReasonKey.UnderAge:
return errorMessages.age
case ReasonKey.NoCitizenship:
return errorMessages.citizenship
case ReasonKey.NotISResidency:
return errorMessages.residency
case ReasonKey.CollectionNotOpen:
return errorMessages.active
case ReasonKey.AlreadySigned:
return errorMessages.signer
case ReasonKey.noInvalidSignature:
return errorMessages.invalidSignature
default:
return errorMessages.deniedByService
}
})
throw new TemplateApiError(errors, 405)
}

async getList({ auth, application }: TemplateApiModuleActionProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const errorMessages = {
active: defineMessages({
title: {
id: 'pls.application:error.active.title',
defaultMessage: 'Ekki er hægt að mæla með framboði.',
defaultMessage: 'Ekki er hægt að mæla með framboði',
description: '',
},
summary: {
Expand Down Expand Up @@ -101,7 +101,7 @@ export const errorMessages = {
maxReached: defineMessages({
title: {
id: 'pls.application:error.maxReached.title',
defaultMessage: 'Framboð hefur náð hámarksfjölda meðmæla.',
defaultMessage: 'Framboð hefur náð hámarksfjölda meðmæla',
description: '',
},
summary: {
Expand All @@ -122,4 +122,18 @@ export const errorMessages = {
description: '',
},
}),
singeeNotFound: defineMessages({
title: {
id: 'pls.application:error.singeeNotFound.title',
defaultMessage:
'Notandi uppfyllir ekki skilyrði til að framkvæma þessa aðgerð',
description: '',
},
summary: {
id: 'pls.application:error.singeeNotFound.summary',
defaultMessage:
'Hægt er að hafa samband við Þjóðskrá fyrir nánari upplýsingar.',
description: '',
},
}),
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common'
import { Injectable, NotFoundException } from '@nestjs/common'
import {
FrambodApi,
FrambodDTO,
Expand All @@ -10,19 +10,12 @@ import {
GetListInput,
CreateListInput,
ReasonKey,
CanCreateInput,
CanSignInput,
CreateParliamentaryCandidacyInput,
AddListsInput,
} from './signature-collection.types'
import { Collection } from './types/collection.dto'
import {
List,
SignedList,
getSlug,
mapList,
mapListBase,
} from './types/list.dto'
import { List, SignedList, getSlug, mapListBase } from './types/list.dto'
import { Signature, mapSignature } from './types/signature.dto'
import { Signee } from './types/user.dto'
import { Success, mapReasons } from './types/success.dto'
Expand Down Expand Up @@ -432,62 +425,68 @@ export class SignatureCollectionClientService {
async getSignee(auth: User, nationalId?: string): Promise<Signee> {
const collection = await this.currentCollection()
const { id, isPresidential, isActive, areas } = collection
const user = await this.getApiWithAuth(
this.collectionsApi,
auth,
).medmaelasofnunIDEinsInfoKennitalaGet({
kennitala: nationalId ?? auth.nationalId,
iD: parseInt(id),
})

const candidate = user.frambod ? mapCandidate(user.frambod) : undefined
const activeSignature = user.medmaeli?.find((signature) => signature.valid)
const signatures = user.medmaeli?.map((signature) =>
mapSignature(signature),
)
const ownedLists =
user.medmaelalistar && candidate
? user.medmaelalistar?.map((list) => mapListBase(list))
: []

const { success: canCreate, reasons: canCreateInfo } =
await this.sharedService.canCreate({
requirementsMet: user.maFrambod,
canCreateInfo: user.maFrambodInfo,
ownedLists,
isPresidential,
isActive,
areas,
try {
const user = await this.getApiWithAuth(
this.collectionsApi,
auth,
).medmaelasofnunIDEinsInfoKennitalaGet({
kennitala: nationalId ?? auth.nationalId,
iD: parseInt(id),
})

const { success: canSign, reasons: canSignInfo } = await this.canSign({
requirementsMet: user.maKjosa,
canSignInfo: user.maKjosaInfo,
activeSignature,
signatures,
})
const candidate = user.frambod ? mapCandidate(user.frambod) : undefined
const activeSignature = user.medmaeli?.find(
(signature) => signature.valid,
)
const signatures = user.medmaeli?.map((signature) =>
mapSignature(signature),
)
const ownedLists =
user.medmaelalistar && candidate
? user.medmaelalistar?.map((list) => mapListBase(list))
: []

const { success: canCreate, reasons: canCreateInfo } =
await this.sharedService.canCreate({
requirementsMet: user.maFrambod,
canCreateInfo: user.maFrambodInfo,
ownedLists,
isPresidential,
isActive,
areas,
})

const { success: canSign, reasons: canSignInfo } = await this.canSign({
requirementsMet: user.maKjosa,
canSignInfo: user.maKjosaInfo,
activeSignature,
signatures,
})

return {
nationalId: user.kennitala ?? '',
name: user.nafn ?? '',
electionName: user.kosningNafn ?? '',
canSign,
canSignInfo,
canCreate,
canCreateInfo,
area: user.svaedi && {
id: user.svaedi?.id?.toString() ?? '',
name: user.svaedi?.nafn?.toString() ?? '',
},
signatures,
ownedLists,
isOwner: user.medmaelalistar ? user.medmaelalistar?.length > 0 : false,
candidate,
hasPartyBallotLetter: !!user.maFrambodInfo?.medListabokstaf,
partyBallotLetterInfo: {
letter: user.listabokstafur?.stafur ?? '',
name: user.listabokstafur?.frambodNafn ?? '',
},
return {
nationalId: user.kennitala ?? '',
name: user.nafn ?? '',
electionName: user.kosningNafn ?? '',
canSign,
canSignInfo,
canCreate,
canCreateInfo,
area: user.svaedi && {
id: user.svaedi?.id?.toString() ?? '',
name: user.svaedi?.nafn?.toString() ?? '',
},
signatures,
ownedLists,
isOwner: user.medmaelalistar ? user.medmaelalistar?.length > 0 : false,
candidate,
hasPartyBallotLetter: !!user.maFrambodInfo?.medListabokstaf,
partyBallotLetterInfo: {
letter: user.listabokstafur?.stafur ?? '',
name: user.listabokstafur?.frambodNafn ?? '',
},
}
} catch (e) {
throw new NotFoundException('User not found')
}
}

Expand Down
8 changes: 7 additions & 1 deletion libs/service-portal/signature-collection/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const useGetListsForUser = (collectionId?: string) => {
data: getListsForUser,
loading: loadingUserLists,
refetch: refetchListsForUser,
error: getListsForUserError,
} = useQuery<{
signatureCollectionListsForUser?: SignatureCollectionListBase[]
}>(GetListsForUser, {
Expand All @@ -93,7 +94,12 @@ export const useGetListsForUser = (collectionId?: string) => {
const listsForUser =
(getListsForUser?.signatureCollectionListsForUser as SignatureCollectionListBase[]) ??
[]
return { listsForUser, loadingUserLists, refetchListsForUser }
return {
listsForUser,
loadingUserLists,
refetchListsForUser,
getListsForUserError,
}
}

export const useGetListsForOwner = (collectionId: string) => {
Expand Down
12 changes: 12 additions & 0 deletions libs/service-portal/signature-collection/src/lib/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ export const m = defineMessages({
},

/* Signee View */
noUserFound: {
id: 'sp.signatureCollection:noUserFound',
defaultMessage:
'Þú uppfyllir ekki skilyrði til að taka þátt í meðmælasöfnunum',
description: '',
},
noUserFoundDescription: {
id: 'sp.signatureCollection:noUserFoundDescription#markdown',
defaultMessage:
'Ef þú telur þessar upplýsingar rangar, vinsamlegast hafðu samband við Þjóðskrá Íslands.',
description: '',
},
noCollectionIsActive: {
id: 'sp.signatureCollection:noCollectionIsActive',
defaultMessage: 'Engin söfnun í gangi',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,38 @@ const SigneeView = ({
const { userInfo: user } = useAuth()
const { formatMessage } = useLocale()
const { signedLists, loadingSignedLists } = useGetSignedList()
const { listsForUser, loadingUserLists } = useGetListsForUser(
currentCollection?.id,
)
const { listsForUser, loadingUserLists, getListsForUserError } =
useGetListsForUser(currentCollection?.id)

if (getListsForUserError !== undefined) {
return (
<EmptyState
title={m.noUserFound}
description={m.noUserFoundDescription}
/>
)
}

return (
<Box>
{!user?.profile.actor && !loadingSignedLists && !loadingUserLists ? (
<Box>
{listsForUser.length === 0 && signedLists.length === 0 && (
{listsForUser?.length === 0 && signedLists?.length === 0 && (
<Box marginTop={10}>
<EmptyState
title={m.noCollectionIsActive}
description={m.noCollectionIsActiveDescription}
/>
</Box>
)}

<Box marginTop={[2, 7]}>
{/* Signed list */}
<SignedList currentCollection={currentCollection} />

{/* Other available lists */}
<Box marginTop={[5, 10]}>
{listsForUser.length > 0 && (
{listsForUser?.length > 0 && (
<Text marginBottom={2} variant="h4">
{formatMessage(m.mySigneeListsByAreaHeader)}
</Text>
Expand Down

0 comments on commit 8b46f97

Please sign in to comment.