Skip to content

fix: resolve invitation select synchronization and error handling - #5502

Open
rubenspezzoli-pz wants to merge 1 commit into
Dokploy:canaryfrom
rubenspezzoli-pz:fix-invitation-select
Open

rubenspezzoli-pz wants to merge 1 commit into
Dokploy:canaryfrom
rubenspezzoli-pz:fix-invitation-select

Conversation

@rubenspezzoli-pz

@rubenspezzoli-pz rubenspezzoli-pz commented Sep 21, 2026

Copy link
Copy Markdown

What is this PR about?

Please describe in a short paragraph what this PR is about.

Checklist

Before submitting this PR, please make sure that:

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file https://github.com/Dokploy/dokploy/blob/canary/CONTRIBUTING.md#pull-request
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting. This helps avoid wasting maintainers' time reviewing code that has not been verified by you.

Issues related (if applicable)

closes #5497

Screenshots (if applicable)

RetriggerConfidence Score: 2/5

This PR is not safe to merge because the rewritten invitation component does not type-check against its callers or the organization router and also removes supported administrative workflows.

Summary

This PR rewrites the invitation dialog in an attempt to synchronize its role select and revise error handling, but the replacement is incompatible with the existing component and API contracts.

  • Introduces required props and tRPC procedure names that existing callers and routers do not provide.
  • Changes role handling in ways that reject valid custom/default-role behavior and expose an always-invalid owner option.
  • Removes self-hosted credentials provisioning and email-provider invitation capabilities.
  • Leaves failed mutations as rejected submit promises and introduces Italian copy into an English settings surface.

Reviews (1) · Last reviewed commit: "fix: resolve invitation select synchroni..."

Comment on lines +41 to +62
interface AddInvitationProps {
organizationId: string
onSuccess?: () => void
}

export function AddInvitation({ organizationId, onSuccess }: AddInvitationProps) {
const [isOpen, setIsOpen] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const utils = api.useUtils()

const form = useForm<AddInvitationValues>({
resolver: zodResolver(addInvitationSchema),
defaultValues: {
email: "",
role: "member",
},
})

const { mutateAsync: createInvitation } = api.organization.createInvitation.useMutation({
onSuccess: () => {
toast.success("Invito inviato con successo")
utils.organization.getInvitations.invalidate()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Component Contract Is Broken

The rewritten component requires an organizationId, but both existing call sites render <AddInvitation /> without it. It also calls api.organization.createInvitation and invalidates utils.organization.getInvitations, while the organization router exposes inviteMember and allInvitations instead. These mismatches prevent the dashboard from type-checking and building.

Knowledge Base Used: Web control plane

Comment on lines +34 to +37
const addInvitationSchema = z.object({
email: z.string().email("Email non valida"),
role: z.enum(["owner", "admin", "member"]),
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Role Choices Break Invitations

This allowlist offers owner, even though the server always rejects owner invitations as non-delegable. It also excludes the custom roles supported by the server and ignores the organization's configured default role. As a result, users can select an invitation that is guaranteed to fail, while enterprise organizations can no longer invite members with their intended roles.

Knowledge Base Used:

Comment on lines +34 to +46
const addInvitationSchema = z.object({
email: z.string().email("Email non valida"),
role: z.enum(["owner", "admin", "member"]),
})

type AddInvitationValues = z.infer<typeof addInvitationSchema>

interface AddInvitationProps {
organizationId: string
onSuccess?: () => void
}

export function AddInvitation({ organizationId, onSuccess }: AddInvitationProps) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Supported Workflows Were Removed

The replacement schema models only an email and role, removing the self-hosted initial-credentials flow and the email-provider invitation flow that this dialog previously exposed. Administrators can therefore no longer provision a user with a password or select a configured provider from the users screen, even though the corresponding backend capabilities remain available.

Knowledge Base Used: Web control plane

Comment on lines +72 to +83
async function onSubmit(values: AddInvitationValues) {
try {
setIsLoading(true)
await createInvitation({
organizationId,
email: values.email,
role: values.role,
})
} finally {
setIsLoading(false)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Mutation Rejection Escapes

mutateAsync still rejects after its onError callback runs, but this submit handler uses only try/finally. When an invitation fails, the toast appears and the rejected promise then escapes through handleSubmit, producing an unhandled submit-handler rejection. Catch the error after displaying it or otherwise handle the rejection in onSubmit.

Comment on lines +88 to +94
<Button>Invita membro</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Invita un nuovo utente</DialogTitle>
<DialogDescription>
Inserisci l'indirizzo email e seleziona il ruolo per l'invito.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Dialog Language Is Inconsistent

This rewrite changes the dialog's labels, validation messages, and notifications to Italian while the surrounding users interface remains English. That makes the actions and errors difficult to understand for users relying on the application's established language. Keep the existing English copy or route these strings through the application's localization system.

Knowledge Base Used: Web control plane

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@imrja8

imrja8 commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

PR #5498 already solves issue #5497 with a clean solution and was opened ~6 hours before this PR.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: add-invitation form resets state on API error but leaves Select component visually out of sync

2 participants