Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 67 additions & 37 deletions backend/src/api/public/v1/members/identities/createMemberIdentity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { ConflictError, NotFoundError } from '@crowd/common'
import {
MemberField,
findMemberById,
findMemberIdentitiesByValue,
createMemberIdentity as insertMemberIdentity,
optionsQx,
touchMemberUpdatedAt,
updateMemberIdentity,
} from '@crowd/data-access-layer'
import { IMemberIdentity, MemberIdentityType } from '@crowd/types'

import { created } from '@/utils/api'
import { created, ok } from '@/utils/api'
import { validateOrThrow } from '@/utils/validation'

const paramsSchema = z.object({
Expand Down Expand Up @@ -45,60 +47,82 @@ export async function createMemberIdentity(req: Request, res: Response): Promise
}

let result!: IMemberIdentity
let alreadyExisted = false

await captureApiChange(
req,
memberEditIdentitiesAction(memberId, async (captureOldState, captureNewState) => {
captureOldState({})

await qx.tx(async (tx) => {
try {
result = await insertMemberIdentity(
tx,
{
memberId,
platform: data.platform,
value: data.value,
type: data.type,
source: data.source,
verified: data.verified,
verifiedBy: data.verifiedBy,
},
true,
true,
)
} catch (error) {
const constraint =
error.constraint ?? error.original?.constraint ?? error.parent?.constraint

if (constraint === 'uix_memberIdentities_memberId_platform_value_type') {
throw new ConflictError('Identity already exists on this member', {
platform: data.platform,
value: data.value,
type: data.type,
})
const existing = await findMemberIdentitiesByValue(tx, memberId, data.value, {
type: data.type,
})

const exactMatch = existing.find((i) => i.platform === data.platform)
Comment thread
skwowet marked this conversation as resolved.
Outdated

if (exactMatch) {
alreadyExisted = true
result = exactMatch
} else {
try {
result = await insertMemberIdentity(
tx,
{
memberId,
platform: data.platform,
value: data.value,
type: data.type,
source: data.source,
verified: data.verified,
verifiedBy: data.verifiedBy,
},
true,
true,
)
} catch (error) {
const constraint =
error.constraint ?? error.original?.constraint ?? error.parent?.constraint

if (constraint === 'uix_memberIdentities_platform_value_type_verified') {
throw new ConflictError('Identity already verified on another member', {
platform: data.platform,
value: data.value,
type: data.type,
})
}

throw error
}
}

if (constraint === 'uix_memberIdentities_platform_value_type_verified') {
throw new ConflictError('Identity already verified on another member', {
platform: data.platform,
value: data.value,
type: data.type,
})
}
if (data.verified && existing.length > 0) {
await Promise.all(
existing.map((i) =>
updateMemberIdentity(tx, memberId, i.id, {
verified: true,
verifiedBy: data.verifiedBy,
}),
),
)
Comment thread
cursor[bot] marked this conversation as resolved.
Outdated

throw error
if (alreadyExisted) {
result = {
...exactMatch,
verified: true,
verifiedBy: data.verifiedBy,
}
}
Comment thread
cursor[bot] marked this conversation as resolved.
}

// touch member updated at to trigger merge suggestion
await touchMemberUpdatedAt(tx, memberId)
})

captureNewState(result)
}),
)

created(res, {
const response = {
id: result.id,
value: result.value,
platform: result.platform,
Expand All @@ -108,5 +132,11 @@ export async function createMemberIdentity(req: Request, res: Response): Promise
source: result.source ?? null,
createdAt: result.createdAt,
updatedAt: result.updatedAt,
})
}

if (alreadyExisted) {
ok(res, response)
} else {
created(res, response)
}
}
7 changes: 6 additions & 1 deletion backend/src/api/public/v1/members/resolveMember.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ export async function resolveMemberByIdentities(req: Request, res: Response): Pr
platform: PlatformType.LFID,
type: MemberIdentityType.USERNAME,
value: lfid,
verified: true,
})),
...(emails?.map((email) => ({ type: MemberIdentityType.EMAIL, value: email })) ?? []),
...(emails?.map((email) => ({
type: MemberIdentityType.EMAIL,
value: email,
verified: true,
})) ?? []),
]

const memberIds = await findMemberIdsByIdentities(qx, identities)
Expand Down
2 changes: 1 addition & 1 deletion services/libs/data-access-layer/src/members/identities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export async function findMemberIdentitiesByValue(
): Promise<IMemberIdentity[]> {
return qx.select(
`
SELECT id, platform, "sourceId", type, value, verified
SELECT *
Comment thread
skwowet marked this conversation as resolved.
Comment thread
joanagmaia marked this conversation as resolved.
FROM "memberIdentities"
WHERE value = $(value)
AND "memberId" = $(memberId)
Expand Down
Loading