fix(tenant): reuse existing Logto users and clean up on delete
All checks were successful
CI / build (push) Successful in 2m14s
CI / docker (push) Successful in 1m10s

Create: if admin email matches an existing Logto user, add them to the
tenant org instead of creating a duplicate account. Only creates a new
user when no match is found and a password is provided.

Delete: before deleting the Logto org, list its members. After org
deletion, delete tenant-only users (those with no remaining org
memberships). Users who belong to other orgs are preserved.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-28 20:25:21 +02:00
parent 029f2ef0de
commit df25dcf81a

View File

@@ -104,18 +104,34 @@ public class VendorTenantService {
if (tenant.getLogtoOrgId() != null && logtoClient.isAvailable()) { if (tenant.getLogtoOrgId() != null && logtoClient.isAvailable()) {
String ownerRoleId = logtoClient.findOrgRoleIdByName("owner"); String ownerRoleId = logtoClient.findOrgRoleIdByName("owner");
// Create tenant admin (email is the primary identity) // Create or find tenant admin (email is the primary identity)
if (request.adminEmail() != null && request.adminPassword() != null) { if (request.adminEmail() != null) {
try { try {
String email = request.adminEmail(); String email = request.adminEmail();
String username = request.adminUsername(); // Check if user already exists in Logto (e.g., platform admin or self-registered user)
if (username == null || username.isBlank()) { var existingUser = logtoClient.findUserByEmail(email);
username = email.substring(0, email.indexOf('@')); String userId;
if (existingUser != null) {
userId = String.valueOf(existingUser.get("id"));
log.info("User '{}' already exists ({}), adding to tenant org", email, userId);
} else if (request.adminPassword() != null) {
String username = request.adminUsername();
if (username == null || username.isBlank()) {
username = email.substring(0, email.indexOf('@'));
}
userId = logtoClient.createUserWithPassword(
username, request.adminPassword(),
null, null);
logtoClient.updateUserProfile(userId, Map.of("primaryEmail", email));
} else {
userId = null;
}
if (userId != null) {
logtoClient.addUserToOrganization(tenant.getLogtoOrgId(), userId);
if (ownerRoleId != null) {
logtoClient.assignOrganizationRole(tenant.getLogtoOrgId(), userId, ownerRoleId);
}
} }
String userId = logtoClient.createUserWithPassword(
username, request.adminPassword(),
tenant.getLogtoOrgId(), ownerRoleId);
logtoClient.updateUserProfile(userId, Map.of("primaryEmail", email));
} catch (Exception e) { } catch (Exception e) {
log.warn("Failed to create admin user for tenant {}: {}", tenant.getSlug(), e.getMessage()); log.warn("Failed to create admin user for tenant {}: {}", tenant.getSlug(), e.getMessage());
} }
@@ -364,10 +380,26 @@ public class VendorTenantService {
// Revoke license // Revoke license
licenseService.revokeLicense(tenantId, actorId); licenseService.revokeLicense(tenantId, actorId);
// Delete Logto org // Delete Logto org and clean up tenant-only users
if (logtoClient.isAvailable() && tenant.getLogtoOrgId() != null) { if (logtoClient.isAvailable() && tenant.getLogtoOrgId() != null) {
try { try {
// List org members before deleting the org
var members = logtoClient.listOrganizationMembers(tenant.getLogtoOrgId());
logtoClient.deleteOrganization(tenant.getLogtoOrgId()); logtoClient.deleteOrganization(tenant.getLogtoOrgId());
// Delete users that have no other org memberships (tenant-only users)
for (var member : members) {
String userId = String.valueOf(member.get("id"));
try {
var orgs = logtoClient.getUserOrganizations(userId);
if (orgs.isEmpty()) {
logtoClient.deleteUser(userId);
log.info("Deleted tenant-only Logto user {} for tenant {}", userId, tenant.getSlug());
}
} catch (Exception e) {
log.warn("Failed to clean up Logto user {} for tenant {}: {}", userId, tenant.getSlug(), e.getMessage());
}
}
} catch (Exception e) { } catch (Exception e) {
log.warn("Failed to delete Logto org for tenant {}: {}", tenant.getSlug(), e.getMessage()); log.warn("Failed to delete Logto org for tenant {}: {}", tenant.getSlug(), e.getMessage());
} }