Skip to content

Commit

Permalink
feat(2915): fix update. field validation for email.
Browse files Browse the repository at this point in the history
  • Loading branch information
koekiebox committed Feb 12, 2025
1 parent e718b64 commit f90efd0
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 70 deletions.
1 change: 0 additions & 1 deletion packages/frontend/app/routes/peers.$peerId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
}

const peer = await getPeer(request, { id: result.data })

if (!peer) {
throw json(null, { status: 400, statusText: 'Peer not found.' })
}
Expand Down
128 changes: 60 additions & 68 deletions packages/frontend/app/routes/tenants.$tenantId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
} from '~/components/ConfirmationDialog'
import { updateTenant, deleteTenant, whoAmI } from '~/lib/api/tenant.server'
import { messageStorage, setMessageAndRedirect } from '~/lib/message.server'
import { updateTenantSchema, uuidSchema } from '~/lib/validate.server'
import { createTenantSchema, updateTenantSchema, uuidSchema } from '~/lib/validate.server'
import type { ZodFieldErrors } from '~/shared/types'
import { checkAuthAndRedirect } from '../lib/kratos_checks.server'
import { getTenantInfo } from '~/lib/api/tenant.server'
Expand Down Expand Up @@ -62,9 +62,7 @@ export default function ViewTenantPage() {
}

const onConfirm = () => {
if (formData) {
submit(formData, { method: 'post' })
}
if (formData) submit(formData, { method: 'post' })
}

return (
Expand All @@ -81,13 +79,14 @@ export default function ViewTenantPage() {
<p className='text-sm'>
Created at {new Date(tenant.createdAt).toLocaleString()}
</p>
<ErrorPanel errors={response?.errors.general.message} />
<ErrorPanel errors={response?.errors?.message} />
</div>
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
<Form method='post' replace preventScrollReset>
<fieldset disabled={isSubmitting}>
<div className='w-full p-4 space-y-3'>
<Input type='hidden' name='id' value={tenant.id} />
<Input type='hidden' name='apiSecret' value={tenant.apiSecret} />
<Input
label='Tenant ID'
name='tenantId'
Expand All @@ -99,13 +98,13 @@ export default function ViewTenantPage() {
label='Public Name'
name='publicName'
defaultValue={tenant.publicName ?? undefined}
error={response?.errors.general.fieldErrors.publicName}
error={response?.errors?.fieldErrors.publicName}
/>
<Input
label='Email'
name='email'
defaultValue={tenant.email ?? undefined}
error={response?.errors.general.fieldErrors.email}
error={response?.errors?.fieldErrors.email}
/>
</div>
<div className='flex justify-end p-4'>
Expand All @@ -122,62 +121,31 @@ export default function ViewTenantPage() {
</Form>
</div>
</div>
{/* Sensitive Info */}
<div className='grid grid-cols-1 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
<div className='col-span-1 pt-3'>
<h3 className='text-lg font-medium'>Sensitive Information</h3>
<ErrorPanel errors={response?.errors.general.message} />
</div>
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
<Form method='post' replace preventScrollReset>
<fieldset disabled={isSubmitting}>
<div className='w-full p-4 space-y-3'>
<Input type='hidden' name='id' value={tenant.id} />
<PasswordInput
name='apiSecret'
label='API Secret'
defaultValue={tenant.apiSecret ?? undefined}
required
disabled
/>
</div>
<div className='flex justify-end p-4'>
<Button
aria-label='save sensitive information'
type='submit'
name='intent'
value='sensitive'
>
{isSubmitting ? 'Saving ...' : 'Save'}
</Button>
</div>
</fieldset>
</Form>
</div>
</div>
{/* Sensitive - END */}
{/* Identity Provider Information */}
<div className='grid grid-cols-1 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
<div className='col-span-1 pt-3'>
<h3 className='text-lg font-medium'>
Identity Provider Information
</h3>
<ErrorPanel errors={response?.errors.general.message} />
<ErrorPanel errors={response?.errors?.message} />
</div>
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
<Form method='post' replace preventScrollReset>
<fieldset disabled={isSubmitting}>
<div className='w-full p-4 space-y-3'>
<Input type='hidden' name='id' value={tenant.id} />
<Input type='hidden' name='apiSecret' value={tenant.apiSecret} />
<Input
name='idpConsentUrl'
label='Consent URL'
defaultValue={tenant.idpConsentUrl ?? undefined}
error={response?.errors?.fieldErrors.idpConsentUrl}
/>
<PasswordInput
name='idpSecret'
label='Secret'
defaultValue={tenant.idpSecret ?? undefined}
error={response?.errors?.fieldErrors.idpSecret}
/>
</div>
<div className='flex justify-end p-4'>
Expand All @@ -195,7 +163,30 @@ export default function ViewTenantPage() {
</div>
</div>
{/* Identity Provider Information - END */}

{/* Sensitive Info */}
<div className='grid grid-cols-1 py-3 gap-6 md:grid-cols-3 border-b border-pearl'>
<div className='col-span-1 pt-3'>
<h3 className='text-lg font-medium'>Sensitive Information</h3>
<ErrorPanel errors={response?.errors.message} />
</div>
<div className='md:col-span-2 bg-white rounded-md shadow-md'>
<Form method='post' replace preventScrollReset>
<fieldset disabled={isSubmitting}>
<div className='w-full p-4 space-y-3'>
<Input type='hidden' name='id' value={tenant.id} />
<PasswordInput
name='apiSecret'
label='API Secret'
value={tenant.apiSecret}
required
disabled
/>
</div>
</fieldset>
</Form>
</div>
</div>
{/* Sensitive - END */}
{/* DELETE TENANT - Danger zone */}
{me.isOperator && me.id !== tenant.id && (
<DangerZone title='Delete Tenant'>
Expand All @@ -208,34 +199,26 @@ export default function ViewTenantPage() {
</Form>
</DangerZone>
)}
<ConfirmationDialog
ref={dialogRef}
onConfirm={onConfirm}
title={`Delete Tenant ${tenant.publicName}`}
keyword={'delete tenant'}
confirmButtonText='Delete this tenant'
/>
</div>
<ConfirmationDialog
ref={dialogRef}
onConfirm={onConfirm}
title={`Delete Tenant ${tenant.publicName}`}
keyword={'delete tenant'}
confirmButtonText='Delete this tenant'
/>
<Outlet />
</div>
)
}

export async function action({ request }: ActionFunctionArgs) {
const actionResponse: {
errors: {
general: {
fieldErrors: ZodFieldErrors<typeof updateTenantSchema>
message: string[]
}
}
const errors: {
fieldErrors: ZodFieldErrors<typeof createTenantSchema>
message: string[]
} = {
errors: {
general: {
fieldErrors: {},
message: []
}
}
fieldErrors: {},
message: []
}

const session = await messageStorage.getSession(request.headers.get('cookie'))
Expand All @@ -250,20 +233,29 @@ export async function action({ request }: ActionFunctionArgs) {
const formEntries = Object.fromEntries(formData)
const result = updateTenantSchema.safeParse(formEntries)
if (!result.success) {
actionResponse.errors.general.fieldErrors =
result.error.flatten().fieldErrors
return json({ ...actionResponse }, { status: 400 })
errors.fieldErrors = result.error.flatten().fieldErrors
return json({ ...errors }, { status: 400 })
}
if (
result.data.email &&
result.data.email.trim().length > 0 &&
!new RegExp(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/).test(
result.data.email
)
) {
errors.fieldErrors.email = ['Email is invalid.']
return json({ errors }, { status: 400 })
}

const response = await updateTenant(request, {
...result.data
})

if (!response?.tenant) {
actionResponse.errors.general.message = [
errors.message = [
'Could not update tenant. Please try again!'
]
return json({ ...actionResponse }, { status: 400 })
return json({ ...errors }, { status: 400 })
}

const me = await whoAmI(request)
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/app/routes/tenants.create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export async function action({ request }: ActionFunctionArgs) {
result.data.email
)
) {
errors.message = ['Email is invalid.']
errors.fieldErrors.email = ['Email is invalid.']
return json({ errors }, { status: 400 })
}

Expand Down

0 comments on commit f90efd0

Please sign in to comment.