Merge pull request #91 from MAGICGrants/user-update-fix

fix: properly make keycloak user updates
This commit is contained in:
Artur
2024-11-26 14:50:13 -03:00
committed by GitHub
4 changed files with 85 additions and 23 deletions

View File

@@ -28,7 +28,16 @@ import Spinner from './Spinner'
const schema = z
.object({
name: z.string().min(1),
firstName: z
.string()
.trim()
.min(1)
.regex(/^[A-Za-záéíóúÁÉÍÓÚñÑçÇ]+$/, 'Use alphabetic characters only.'),
lastName: z
.string()
.trim()
.min(1)
.regex(/^[A-Za-záéíóúÁÉÍÓÚñÑçÇ]+$/, 'Use alphabetic characters only.'),
email: z.string().email(),
password: z.string().min(8),
confirmPassword: z.string().min(8),
@@ -82,19 +91,35 @@ function RegisterFormModal({ close, openLoginModal }: Props) {
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col space-y-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormControl>
<Input placeholder="John Doe" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="w-full space-y-4 sm:space-x-2 sm:space-y-0 flex flex-col sm:flex-row">
<FormField
control={form.control}
name="firstName"
render={({ field }) => (
<FormItem className="grow">
<FormLabel>First name</FormLabel>
<FormControl>
<Input placeholder="John" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="lastName"
render={({ field }) => (
<FormItem className="grow">
<FormLabel>Last name</FormLabel>
<FormControl>
<Input placeholder="Doe" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}

View File

@@ -51,9 +51,18 @@ export const accountRouter = router({
await authenticateKeycloakClient()
const user = await keycloak.users.findOne({ id: userId })
if (!user || !user.id)
throw new TRPCError({
code: 'NOT_FOUND',
message: 'USER_NOT_FOUND',
})
await keycloak.users.update(
{ id: userId },
{
...user,
email,
credentials: [{ type: 'password', value: input.newPassword, temporary: false }],
}
@@ -88,7 +97,7 @@ export const accountRouter = router({
if (!emailVerifyTokenVersion) {
await keycloak.users.update(
{ id: userId },
{ email: user.email, attributes: { emailVerifyTokenVersion: 1 } }
{ ...user, attributes: { ...user.attributes, emailVerifyTokenVersion: 1 } }
)
emailVerifyTokenVersion = 1
}

View File

@@ -13,7 +13,16 @@ export const authRouter = router({
register: publicProcedure
.input(
z.object({
name: z.string().trim().min(1),
firstName: z
.string()
.trim()
.min(1)
.regex(/^[A-Za-záéíóúÁÉÍÓÚñÑçÇ]+$/, 'Use alphabetic characters only.'),
lastName: z
.string()
.trim()
.min(1)
.regex(/^[A-Za-záéíóúÁÉÍÓÚñÑçÇ]+$/, 'Use alphabetic characters only.'),
email: z.string().email(),
password: z.string(),
fundSlug: z.enum(fundSlugs),
@@ -31,7 +40,7 @@ export const authRouter = router({
credentials: [{ type: 'password', value: input.password, temporary: false }],
requiredActions: ['VERIFY_EMAIL'],
attributes: {
name: input.name,
name: `${input.firstName} ${input.lastName}`,
passwordResetTokenVersion: 1,
emailVerifyTokenVersion: 1,
},
@@ -107,10 +116,12 @@ export const authRouter = router({
await keycloak.users.update(
{ id: decoded.userId },
{
...user,
email: decoded.email,
emailVerified: true,
requiredActions: [],
attributes: {
...user.attributes,
emailVerifyTokenVersion: (emailVerifyTokenVersion + 1).toString(),
},
}
@@ -140,7 +151,11 @@ export const authRouter = router({
if (!passwordResetTokenVersion) {
await keycloak.users.update(
{ id: user.id },
{ email: input.email, attributes: { passwordResetTokenVersion: 1 } }
{
...user,
email: input.email,
attributes: { ...user.attributes, passwordResetTokenVersion: 1 },
}
)
passwordResetTokenVersion = 1
@@ -202,7 +217,7 @@ export const authRouter = router({
if (!passwordResetTokenVersion) {
await keycloak.users.update(
{ id: user.id },
{ email: user.email, attributes: { passwordResetTokenVersion: 1 } }
{ ...user, attributes: { ...user.attributes, passwordResetTokenVersion: 1 } }
)
passwordResetTokenVersion = 1
@@ -217,9 +232,11 @@ export const authRouter = router({
await keycloak.users.update(
{ id: decoded.userId },
{
...user,
email: decoded.email,
credentials: [{ type: 'password', value: input.password, temporary: false }],
attributes: {
...user.attributes,
passwordResetTokenVersion: (passwordResetTokenVersion + 1).toString(),
},
}

View File

@@ -2,6 +2,7 @@ import { Stripe } from 'stripe'
import { TRPCError } from '@trpc/server'
import { Donation } from '@prisma/client'
import { z } from 'zod'
import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation'
import { protectedProcedure, publicProcedure, router } from '../trpc'
import { CURRENCY, MAX_AMOUNT, MEMBERSHIP_PRICE, MIN_AMOUNT } from '../../config'
@@ -30,10 +31,11 @@ export const donationRouter = router({
let email = input.email
let name = input.name
let stripeCustomerId: string | null = null
let user: UserRepresentation | null = null
if (userId) {
await authenticateKeycloakClient()
const user = await keycloak.users.findOne({ id: userId })!
user = (await keycloak.users.findOne({ id: userId })!) || null
email = user?.email!
name = user?.attributes?.name?.[0]
stripeCustomerId = user?.attributes?.[fundSlugToCustomerIdAttr[input.fundSlug]]?.[0] || null
@@ -41,7 +43,7 @@ export const donationRouter = router({
const stripe = _stripe[input.fundSlug]
if (!stripeCustomerId && userId && email && name) {
if (!stripeCustomerId && userId && user && email && name) {
const customer = await stripe.customers.create({
email,
name,
@@ -51,7 +53,7 @@ export const donationRouter = router({
await keycloak.users.update(
{ id: userId },
{ email: email, attributes: { stripeCustomerId } }
{ ...user, attributes: { ...user.attributes, stripeCustomerId } }
)
}
@@ -181,6 +183,12 @@ export const donationRouter = router({
const email = user?.email!
const name = user?.attributes?.name?.[0]!
if (!user || !user.id)
throw new TRPCError({
code: 'NOT_FOUND',
message: 'USER_NOT_FOUND',
})
let stripeCustomerId =
user?.attributes?.[fundSlugToCustomerIdAttr[input.fundSlug]]?.[0] || null
@@ -189,7 +197,10 @@ export const donationRouter = router({
stripeCustomerId = customer.id
await keycloak.users.update({ id: userId }, { email, attributes: { stripeCustomerId } })
await keycloak.users.update(
{ id: userId },
{ ...user, attributes: { ...user.attributes, stripeCustomerId } }
)
}
const metadata: DonationMetadata = {