feat: create initial admin user + add vendor to new tenant orgs
All checks were successful
CI / build (push) Successful in 50s
CI / docker (push) Successful in 41s

When creating a tenant, the vendor can specify adminUsername +
adminPassword. The backend creates the user in Logto and assigns them
the owner org role. The vendor user is also auto-added to every new
org for support access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-10 07:35:17 +02:00
parent b7a0530466
commit 2dc75c4361
10 changed files with 114 additions and 22 deletions

View File

@@ -15,6 +15,8 @@ export function CreateTenantPage() {
const [slug, setSlug] = useState('');
const [slugTouched, setSlugTouched] = useState(false);
const [tier, setTier] = useState('LOW');
const [adminUsername, setAdminUsername] = useState('');
const [adminPassword, setAdminPassword] = useState('');
useEffect(() => {
if (!slugTouched) {
@@ -25,7 +27,11 @@ export function CreateTenantPage() {
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
try {
const result = await createTenant.mutateAsync({ name, slug, tier });
const result = await createTenant.mutateAsync({
name, slug, tier,
adminUsername: adminUsername || undefined,
adminPassword: adminPassword || undefined,
});
toast({ title: 'Tenant created', variant: 'success' });
navigate(`/vendor/tenants/${result.id}`);
} catch (err) {
@@ -85,6 +91,25 @@ export function CreateTenantPage() {
</select>
</FormField>
<FormField label="Admin Username" htmlFor="admin-user" hint="Initial tenant admin (owner role)">
<Input
id="admin-user"
value={adminUsername}
onChange={(e) => setAdminUsername(e.target.value)}
placeholder="admin"
/>
</FormField>
<FormField label="Admin Password" htmlFor="admin-pass">
<Input
id="admin-pass"
type="password"
value={adminPassword}
onChange={(e) => setAdminPassword(e.target.value)}
placeholder="••••••••"
/>
</FormField>
<div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', paddingTop: 8 }}>
<Button
type="button"

View File

@@ -55,6 +55,8 @@ export interface CreateTenantRequest {
name: string;
slug: string;
tier?: string;
adminUsername?: string;
adminPassword?: string;
}
// Tenant portal API types