Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(signature-collection): Support adding constituancies for parliamentary collection #16056

Merged
merged 8 commits into from
Sep 18, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IsArray, IsString } from 'class-validator'
import { Field, InputType } from '@nestjs/graphql'
import { SignatureCollectionIdInput } from './collectionId.input'

@InputType()
export class SignatureCollectionAddListsInput extends SignatureCollectionIdInput {
@Field()
@IsString()
candidateId!: string

@Field(() => [String], { nullable: true, defaultValue: [] })
@IsArray()
areaIds?: string[]
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
UserAccess,
} from '../decorators/acessRequirement.decorator'
import { SignatureCollectionService } from '../signatureCollection.service'
import { AuthDelegationType } from '@island.is/shared/types'

@Injectable()
export class UserAccessGuard implements CanActivate {
Expand Down Expand Up @@ -34,6 +35,9 @@ export class UserAccessGuard implements CanActivate {
return false
}
const isDelegatedUser = !!user?.actor?.nationalId
const isProcurationHolder = user?.delegationType?.some(
(delegation) => delegation === AuthDelegationType.ProcurationHolder,
)
// IsOwner needs signee
const signee = await this.signatureCollectionService.signee(user)
request.body = { ...request.body, signee }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { CurrentSignee } from './decorators/signee.decorator'
import { ApiScope } from '@island.is/auth/scopes'
import { SignatureCollectionCancelListsInput } from './dto/cencelLists.input'
import { SignatureCollectionIdInput } from './dto/collectionId.input'
import { SignatureCollectionAddListsInput } from './dto/addLists.input'
@UseGuards(IdsUserGuard, ScopesGuard, UserAccessGuard)
@Resolver()
@Audit({ namespace: '@island.is/api/signature-collection' })
Expand Down Expand Up @@ -146,4 +147,15 @@ export class SignatureCollectionResolver {
): Promise<SignatureCollectionSuccess> {
return this.signatureCollectionService.cancel(input, user)
}

@Scopes(ApiScope.signatureCollection)
@AccessRequirement(OwnerAccess.RestrictActor)
@Mutation(() => SignatureCollectionSuccess)
@Audit()
async signatureCollectionAddAreas(
@CurrentUser() user: User,
@Args('input') input: SignatureCollectionAddListsInput,
): Promise<SignatureCollectionSuccess> {
return this.signatureCollectionService.add(input, user)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
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'

@Injectable()
export class SignatureCollectionService {
Expand Down Expand Up @@ -118,4 +120,14 @@ export class SignatureCollectionService {
): Promise<SignatureCollectionSuccess> {
return await this.signatureCollectionClientService.removeLists(input, user)
}

async add(
input: SignatureCollectionAddListsInput,
user: User,
): Promise<SignatureCollectionSuccess> {
return await this.signatureCollectionClientService.createParliamentaryLists(
{ ...input, areas: input.areaIds?.map((area) => ({ areaId: area })) },
user,
)
}
}
29 changes: 25 additions & 4 deletions libs/clients/signature-collection/src/clientConfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@
"/Frambod/{ID}/RemoveFrambodUser": {
"post": {
"tags": ["Frambod"],
"summary": "GAMALT. Nota DELETE /Frambod/{ID}.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -522,6 +523,7 @@
"/Frambod/{ID}/RemoveFrambodAdmin": {
"post": {
"tags": ["Frambod"],
"summary": "GAMALT. Nota DELETE /Admin/Frambod/{ID}.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -551,6 +553,7 @@
"/Frambod/{ID}/AddUmbod": {
"post": {
"tags": ["Frambod"],
"summary": "Ath. þarfnast skoðunar",
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -587,6 +590,7 @@
"/Frambod/{ID}/RemoveUmbod/{Kennitala}": {
"get": {
"tags": ["Frambod"],
"summary": "Ath. þarfnast skoðunar",
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -800,7 +804,10 @@
"description": "OK",
"content": {
"application/json": {
"schema": { "$ref": "#/components/schemas/MedmaelalistiDTO" }
"schema": {
"type": "array",
"items": { "$ref": "#/components/schemas/MedmaelalistiDTO" }
}
}
}
},
Expand All @@ -816,6 +823,7 @@
"/Medmaelalistar/AddListar": {
"post": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Nota POST /Frambod til að stofna framboð.\r\nNota POST /Medmaelalistar til að bæta listum við þegar stofnað framboð.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"requestBody": {
"content": {
"application/json": {
Expand Down Expand Up @@ -849,6 +857,7 @@
"/Medmaelalistar/AddListarAdmin": {
"post": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Nota POST /Admin/Frambod til að stofna framboð.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"requestBody": {
"content": {
"application/json": {
Expand Down Expand Up @@ -1033,6 +1042,7 @@
"/Medmaelalistar/{ID}/AddMedmaeli": {
"post": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Nota POST /Medmaelalistar/{ID}/Medmaeli til að bæta við meðmæli.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1063,6 +1073,7 @@
"/Medmaelalistar/{ID}/AddMedmaeliBulk": {
"post": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Fyrir framboð: Nota POST /Medmaelalistar/{ID}/Medmaeli/Bulk til að bæta við skriflegum meðmælum.\r\nFyrir admin: Nota POST /Admin/Medmaelalistar/{ID}/Medmaeli/Bulk til að bæta við skriflegum meðmælum.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1103,6 +1114,7 @@
"/Medmaelalistar/{ID}/ExtendTime": {
"patch": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Nota PATCH /Admin/Medmaelalistar/{ID}/ExtendTime til að framlengja meðmælalista.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1140,6 +1152,7 @@
"/Medmaelalistar/{ID}/ToggleList": {
"patch": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Nota PATCH /Admin/Medmaelalistar/{ID}/ToggleList.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1172,6 +1185,7 @@
"/Medmaelalistar/{ID}/Compare": {
"post": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Nota POST /Admin/Medmaelalistar/{ID}/Compare.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1212,6 +1226,7 @@
"/Medmaelalistar/{ID}/RemoveMedmaelalistiUser": {
"post": {
"tags": ["Medmaelalistar"],
"summary": "GAMALT. Fyrir framboð: Nota DELETE /Medmaelalistar/{ID}.\r\nFyrir admin: Nota DELETE /Admin/Medmaelalistar/{ID}.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1474,6 +1489,7 @@
"/Medmaelasofnun/{ID}/EinsInfoAdmin/{Kennitala}": {
"get": {
"tags": ["Medmaelasofnun"],
"summary": "GAMALT. Nota GET /Admin/Medmaelasofnun/{ID}/EinsInfo/{Kennitala}.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1511,6 +1527,7 @@
"/Medmaelasofnun/{ID}/ToggleSofnun": {
"post": {
"tags": ["Medmaelasofnun"],
"summary": "GAMALT. Nota PATCH /Admin/Medmaelasofnun/{ID}/ToggleSofnun.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1541,6 +1558,7 @@
"/Medmaelasofnun/{ID}/Compare": {
"post": {
"tags": ["Medmaelasofnun"],
"summary": "GAMALT. Nota POST /Admin/Medmaelasofnun/{ID}/Compare.",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1618,6 +1636,7 @@
"/Medmaeli/{ID}/RemoveMedmaeliUser": {
"post": {
"tags": ["Medmaeli"],
"summary": "GAMALT. Nota DELETE /Medmaeli/{ID}",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1647,6 +1666,7 @@
"/Medmaeli/{ID}/RemoveMedmaeliAdmin": {
"post": {
"tags": ["Medmaeli"],
"summary": "GAMALT. Nota DELETE Admin/Medmaeli/{ID}",
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
"parameters": [
{
"name": "ID",
Expand Down Expand Up @@ -1960,8 +1980,9 @@
"type": "object",
"properties": {
"frambodID": { "type": "integer", "format": "int32" },
"medmaelalisti": {
"$ref": "#/components/schemas/FrambodListarRequestDTO"
"medmaelalistar": {
"type": "array",
"items": { "$ref": "#/components/schemas/FrambodListarRequestDTO" }
}
},
"additionalProperties": false
Expand Down Expand Up @@ -2095,7 +2116,7 @@
"$ref": "#/components/schemas/MedmaelasofnunExtendedDTO"
}
},
"sveitastjornakosningar": {
"sveitarstjornarkosningar": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MedmaelasofnunExtendedDTO"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ import {
CanCreateInput,
CanSignInput,
CreateParliamentaryCandidacyInput,
AddListsInput,
} from './signature-collection.types'
import { Collection } from './types/collection.dto'
import { List, SignedList, mapList, mapListBase } from './types/list.dto'
import {
List,
SignedList,
getSlug,
mapList,
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 @@ -179,7 +186,68 @@ export class SignatureCollectionClientService {
})),
},
})
return { slug: 'frambodWowee' }
return {
slug: getSlug(
candidacy.id ?? '',
candidacy.medmaelasofnun?.kosningTegund ?? '',
),
}
albinagu marked this conversation as resolved.
Show resolved Hide resolved
}

async createParliamentaryLists(
{ collectionId, candidateId, areas }: AddListsInput,
auth: User,
albinagu marked this conversation as resolved.
Show resolved Hide resolved
): Promise<Success> {
const {
id,
isActive,
isPresidential,
areas: collectionAreas,
} = await this.currentCollection()

// check if collectionId is current collection and current collection is open
if (collectionId !== id.toString() || !isActive) {
throw new Error('Collection is not open')
}
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
// check if user is already owner of lists

const { canCreate, canCreateInfo, name } = await this.getSignee(auth)
if (!canCreate) {
// allow parliamentary owners to add more areas to their collection
if (
!isPresidential &&
!(
canCreateInfo?.length === 1 &&
canCreateInfo[0] === ReasonKey.AlreadyOwner
)
) {
return { success: false, reasons: canCreateInfo }
}
}
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved

const filteredAreas = areas
? collectionAreas.filter((area) =>
areas.flatMap((a) => a.areaId).includes(area.id),
)
: collectionAreas
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved

const lists = await this.getApiWithAuth(
this.listsApi,
auth,
).medmaelalistarPost({
medmaelalistarRequestDTO: {
frambodID: parseInt(candidateId),
medmaelalistar: filteredAreas.map((area) => ({
svaediID: parseInt(area.id),
listiNafn: `${name} - ${area.name}`,
})),
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved
},
})
juni-haukur marked this conversation as resolved.
Show resolved Hide resolved

if (filteredAreas.length !== lists.length) {
throw new Error('Not all lists created')
}
return { success: true }
}

async signList(listId: string, auth: User): Promise<Signature> {
Expand Down Expand Up @@ -250,14 +318,12 @@ export class SignatureCollectionClientService {
return { success: false, reasons: [ReasonKey.NoListToRemove] }
}

listsToRemove.map(
async (list) =>
await this.getApiWithAuth(
this.listsApi,
auth,
).medmaelalistarIDRemoveMedmaelalistiUserPost({
await Promise.all(
listsToRemove.map((list) =>
this.getApiWithAuth(this.listsApi, auth).medmaelalistarIDDelete({
iD: parseInt(list.id),
}),
),
)
return { success: true }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ export interface CreateListInput {
owner: OwnerInput
areas?: AreaInput[]
}

// Should replace CreateListInput once refactored to new ÞÍ endpoints
export interface AddListsInput {
collectionId: string
candidateId: string
areas?: AreaInput[]
}

export interface CreateParliamentaryCandidacyInput extends CreateListInput {
agents: AgentInput[]
}
Expand Down
Loading