Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/de/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -612,8 +612,12 @@ export default {
oidc: 'OIDC',
enableThisProvider: 'Diesen Anbieter aktivieren',
enableThisProviderDesc: 'Benutzer können sich mit diesem SSO-Anbieter anmelden',
autoProvisionUsers: 'Benutzer automatisch erstellen',
autoProvisionUsersDesc: 'Benutzerkonten automatisch bei erster SSO-Anmeldung erstellen',
autoProvisionUsers: 'Kontoerstellung erlauben',
autoProvisionUsersDesc: 'Interne Benutzerkonten bei der ersten Anmeldung erstellen. Wenn deaktiviert, können sich nur bestehende Konten anmelden.',
customerAccountCreationHelp: 'Reine Portalkundenkonten bei der ersten Anmeldung erstellen. Wenn deaktiviert, können sich nur bestehende Kunden anmelden.',
customerOrganisationOptional: 'Kundenorganisation (optional)',
noCustomerOrganisation: 'Keine Organisation',
customerOrganisationHelp: 'Optional neue Kunden dieser Organisation zuweisen und die Zugehörigkeit bestehender Kunden verlangen. Leer lassen, um keine Organisationseinschränkung anzuwenden. Gewährt niemals Backend-Zugriff. Kontotyp und Organisationszuweisung können nach Erstellung des Anbieters nicht geändert werden.',
manualUserCreationOnly: 'Nur manuelle Benutzererstellung',
trustIdpEmailVerification: 'Konten auch ohne IdP-E-Mail-Verifizierung verknüpfen',
trustIdpEmailVerificationDesc: 'Wenn aktiviert, werden Identitäten dieses Anbieters auch dann per E-Mail mit bestehenden Windshift-Konten verknüpft, wenn der Anbieter die Adresse nicht verifiziert. Wenn deaktiviert, erfordert die Verknüpfung eine vom Anbieter verifizierte E-Mail.',
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/en/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -653,8 +653,12 @@ export default {
oidc: 'OIDC',
enableThisProvider: 'Enable this provider',
enableThisProviderDesc: 'Users can sign in using this SSO provider',
autoProvisionUsers: 'Auto-provision users',
autoProvisionUsersDesc: 'Automatically create user accounts on first SSO login',
autoProvisionUsers: 'Allow account creation',
autoProvisionUsersDesc: 'Create internal user accounts on first sign-in. When off, only existing accounts can sign in.',
customerAccountCreationHelp: 'Create portal-only customer accounts on first sign-in. When off, only existing customers can sign in.',
customerOrganisationOptional: 'Customer organisation (optional)',
noCustomerOrganisation: 'No organisation',
customerOrganisationHelp: 'Optionally assign new customers to this organisation and require existing customers to belong to it. Leave empty to allow customers without an organisation restriction. Never grants backend access. Account type and organisation assignment cannot be changed after provider creation.',
manualUserCreationOnly: 'Manual user creation only',
trustIdpEmailVerification: 'Link accounts without IdP email verification',
trustIdpEmailVerificationDesc:
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/fa/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,12 @@ export default {
"oidc": "OIDC",
"enableThisProvider": "این ارائه دهنده را فعال کنید",
"enableThisProviderDesc": "کاربران می توانند با استفاده از این ارائه دهنده SSO وارد سیستم شوند",
"autoProvisionUsers": "ارائه خودکار کاربران",
"autoProvisionUsersDesc": "در اولین ورود SSO به طور خودکار حساب های کاربری ایجاد کنید",
"autoProvisionUsers": "اجازه ایجاد حساب",
"autoProvisionUsersDesc": "در اولین ورود، حساب کاربر داخلی ایجاد شود. در صورت غیرفعال بودن، فقط حساب‌های موجود می‌توانند وارد شوند.",
"customerAccountCreationHelp": "در اولین ورود، حساب مشتری با دسترسی فقط به پورتال ایجاد شود. در صورت غیرفعال بودن، فقط مشتریان موجود می‌توانند وارد شوند.",
"customerOrganisationOptional": "سازمان مشتری (اختیاری)",
"noCustomerOrganisation": "بدون سازمان",
"customerOrganisationHelp": "در صورت انتخاب، مشتریان جدید به این سازمان اختصاص می‌یابند و مشتریان موجود باید عضو آن باشند. برای ورود بدون محدودیت سازمانی، خالی بگذارید. هرگز دسترسی به بخش داخلی نمی‌دهد. نوع حساب و تخصیص سازمان پس از ایجاد ارائه‌دهنده قابل تغییر نیست.",
"manualUserCreationOnly": "فقط ایجاد کاربر دستی",
"trustIdpEmailVerification": "پیوند حساب ها بدون تأیید ایمیل IdP",
"trustIdpEmailVerificationDesc": "وقتی فعال باشد، هویت‌های این ارائه‌دهنده از طریق ایمیل به حساب‌های موجود Windshift مرتبط می‌شود، حتی زمانی که ارائه‌دهنده آدرس را تأیید نمی‌کند. وقتی غیرفعال است، پیوند حساب به یک ادعای ایمیل تأیید شده از ارائه‌دهنده نیاز دارد.",
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/fr/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,12 @@ export default {
oidc: 'OIDC',
enableThisProvider: 'Activer ce fournisseur',
enableThisProviderDesc: 'Les utilisateurs peuvent se connecter via ce fournisseur SSO',
autoProvisionUsers: 'Création automatique de comptes',
autoProvisionUsersDesc: 'Créer automatiquement les comptes lors de la première connexion SSO',
autoProvisionUsers: 'Autoriser la création de comptes',
autoProvisionUsersDesc: 'Créer des comptes utilisateurs internes à la première connexion. Si désactivé, seuls les comptes existants peuvent se connecter.',
customerAccountCreationHelp: 'Créer des comptes clients limités au portail à la première connexion. Si désactivé, seuls les clients existants peuvent se connecter.',
customerOrganisationOptional: 'Organisation cliente (facultatif)',
noCustomerOrganisation: 'Aucune organisation',
customerOrganisationHelp: 'Attribuez éventuellement les nouveaux clients à cette organisation et exigez que les clients existants en soient membres. Laissez vide pour ne pas restreindre la connexion par organisation. Ne donne jamais accès au back-office. Le type de compte et l’organisation ne peuvent plus être modifiés après la création du fournisseur.',
manualUserCreationOnly: 'Création manuelle d\'utilisateurs uniquement',
trustIdpEmailVerification: 'Faire confiance aux e-mails vérifiés du fournisseur',
trustIdpEmailVerificationDesc:
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/pl/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -653,8 +653,12 @@ export default {
oidc: 'OIDC',
enableThisProvider: 'Włącz tego dostawcę',
enableThisProviderDesc: 'Użytkownicy mogą logować się za pomocą tego dostawcy SSO',
autoProvisionUsers: 'Automatyczne tworzenie użytkowników',
autoProvisionUsersDesc: 'Automatycznie twórz konta użytkowników przy pierwszym logowaniu SSO',
autoProvisionUsers: 'Zezwalaj na tworzenie kont',
autoProvisionUsersDesc: 'Twórz konta użytkowników wewnętrznych przy pierwszym logowaniu. Po wyłączeniu mogą się logować tylko istniejące konta.',
customerAccountCreationHelp: 'Twórz konta klientów z dostępem tylko do portalu przy pierwszym logowaniu. Po wyłączeniu mogą się logować tylko istniejący klienci.',
customerOrganisationOptional: 'Organizacja klienta (opcjonalnie)',
noCustomerOrganisation: 'Brak organizacji',
customerOrganisationHelp: 'Opcjonalnie przypisz nowych klientów do tej organizacji i wymagaj członkostwa istniejących klientów. Pozostaw puste, aby nie ograniczać logowania do organizacji. Nigdy nie przyznaje dostępu do panelu wewnętrznego. Typu konta i przypisania organizacji nie można zmienić po utworzeniu dostawcy.',
manualUserCreationOnly: 'Tylko ręczne tworzenie użytkowników',
trustIdpEmailVerification: 'Łącz konta bez weryfikacji e-mail u dostawcy tożsamości',
trustIdpEmailVerificationDesc:
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/ru/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -706,9 +706,13 @@ export default {
oidc: 'OIDC',
enableThisProvider: 'Включить этого провайдера',
enableThisProviderDesc: 'Пользователи смогут входить через этого провайдера SSO',
autoProvisionUsers: 'Автоматически создавать пользователей',
autoProvisionUsers: 'Разрешить создание учётных записей',
customerAccountCreationHelp: 'Создавать учётные записи клиентов только для портала при первом входе. Если отключено, вход доступен только существующим клиентам.',
customerOrganisationOptional: 'Организация клиента (необязательно)',
noCustomerOrganisation: 'Без организации',
customerOrganisationHelp: 'При выборе новые клиенты назначаются этой организации, а существующие должны уже состоять в ней. Оставьте пустым для входа без ограничения по организации. Никогда не предоставляет доступ к внутренней системе. Тип учётной записи и назначение организации нельзя изменить после создания провайдера.',
autoProvisionUsersDesc:
'Автоматически создавать учётные записи при первом входе через SSO',
'Создавать внутренние учётные записи при первом входе. Если отключено, вход доступен только существующим учётным записям.',
manualUserCreationOnly: 'Только ручное создание пользователей',
trustIdpEmailVerification: 'Связывать учётные записи без проверки почты в IdP',
trustIdpEmailVerificationDesc:
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/lib/locales/zh-CN/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -504,8 +504,12 @@ export default {
oidc: 'OIDC',
enableThisProvider: '启用此提供商',
enableThisProviderDesc: '用户可以使用此 SSO 提供商登录',
autoProvisionUsers: '自动创建用户',
autoProvisionUsersDesc: '首次 SSO 登录时自动创建用户账户',
autoProvisionUsers: '允许创建账户',
autoProvisionUsersDesc: '首次登录时创建内部用户账户。关闭后,仅现有账户可以登录。',
customerAccountCreationHelp: '首次登录时创建仅限门户的客户账户。关闭后,仅现有客户可以登录。',
customerOrganisationOptional: '客户组织(可选)',
noCustomerOrganisation: '无组织',
customerOrganisationHelp: '可选择将新客户分配到此组织,并要求现有客户已属于该组织。留空则不限制客户所属组织。绝不会授予后台访问权限。提供商创建后,账户类型和组织分配不可更改。',
manualUserCreationOnly: '仅手动创建用户',
trustIdpEmailVerification: '在 IdP 未验证邮箱的情况下关联账户',
trustIdpEmailVerificationDesc: '启用后,即使提供商未验证邮箱地址,其身份也会通过邮箱与现有 Windshift 账户关联。禁用后,账户关联需要提供商验证过的邮箱。',
Expand Down
15 changes: 6 additions & 9 deletions frontend/src/lib/settings/SSOSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import Card from '../components/Card.svelte';
import EmptyState from '../components/EmptyState.svelte';
import Label from '../components/Label.svelte';
import FormField from '../components/FormField.svelte';
import Checkbox from '../components/Checkbox.svelte';
import Select from '../components/Select.svelte';
import CustomerOrganisationPicker from '../pickers/CustomerOrganisationPicker.svelte';
Expand Down Expand Up @@ -273,9 +274,6 @@
}

const organization = formData.github_organization.trim();
if (formData.account_type === 'customer' && !formData.customer_organisation_id) {
formErrors.customer_organisation_id = 'Select a customer organisation.';
}
if (formData.provider_type === 'github' && organization &&
(!/^[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$/.test(organization) || organization.includes('--'))) {
formErrors.github_organization = t('settings.sso.githubOrganizationInvalid');
Expand Down Expand Up @@ -805,10 +803,9 @@
{ value: 'customer', label: 'Portal-only customers' },
]} />
{#if formData.account_type === 'customer'}
<Label>Customer organisation</Label>
<CustomerOrganisationPicker id="sso-customer-organisation" disabled={showEditModal} bind:value={formData.customer_organisation_id} />
<DescriptionText>Creates only customer accounts in this organisation. Never grants backend access. Account type and organisation cannot be changed after creation.</DescriptionText>
{#if formErrors.customer_organisation_id}<p class="text-sm text-[var(--ds-text-danger)]">{formErrors.customer_organisation_id}</p>{/if}
<FormField id="sso-customer-organisation" label={t('settings.sso.customerOrganisationOptional')} helper={t('settings.sso.customerOrganisationHelp')}>
<CustomerOrganisationPicker id="sso-customer-organisation" disabled={showEditModal} showUnassigned unassignedLabel={t('settings.sso.noCustomerOrganisation')} bind:value={formData.customer_organisation_id} />
</FormField>
{/if}
<TextField
id="github_organization"
Expand All @@ -835,8 +832,8 @@
<Checkbox
dataTestid="sso-provider-signup"
bind:checked={formData.auto_provision_users}
label={formData.account_type === 'customer' ? 'Allow customer signup' : t('settings.sso.autoProvisionUsers')}
hint={formData.account_type === 'customer' ? 'Create customers in the selected organisation. Existing customers must already belong to it.' : t('settings.sso.autoProvisionUsersDesc')}
label={t('settings.sso.autoProvisionUsers')}
hint={formData.account_type === 'customer' ? t('settings.sso.customerAccountCreationHelp') : t('settings.sso.autoProvisionUsersDesc')}
size="small"
/>

Expand Down
6 changes: 3 additions & 3 deletions internal/handlers/customer_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ func (h *CustomerAccessHandler) resolve(w http.ResponseWriter, r *http.Request)
}

func (h *CustomerAccessHandler) providerAllowed(ctx context.Context, p *sso.SSOProvider, surface *models.CustomerSurface) bool {
if surface == nil || !p.Enabled || p.ProviderType != sso.ProviderTypeGitHub || p.AccountType != "customer" || p.CustomerOrganisationID == nil {
if surface == nil || !p.Enabled || p.ProviderType != sso.ProviderTypeGitHub || p.AccountType != "customer" {
return false
}
policy, err := h.repo.Policy(ctx, surface.Kind, surface.ID)
if err != nil || (policy.Mode != "public" && !slices.Contains(policy.OrganisationIDs, *p.CustomerOrganisationID)) {
if err != nil || (policy.Mode != "public" && (p.CustomerOrganisationID == nil || !slices.Contains(policy.OrganisationIDs, *p.CustomerOrganisationID))) {
return false
}
return true
Expand Down Expand Up @@ -401,7 +401,7 @@ func (h *CustomerAccessHandler) completeGitHub(w http.ResponseWriter, r *http.Re
err = h.portalAdmission(r.Context(), *surface, claims.Email)
var id int
if err == nil {
id, err = h.repo.GitHubCustomer(r.Context(), p.ID, claims.Subject, claims.Email, claims.Name, *p.CustomerOrganisationID, p.AutoProvisionUsers)
id, err = h.repo.GitHubCustomer(r.Context(), p.ID, claims.Subject, claims.Email, claims.Name, p.CustomerOrganisationID, p.AutoProvisionUsers)
}
if err == nil {
err = h.issueSession(w, r, *surface, id)
Expand Down
7 changes: 3 additions & 4 deletions internal/handlers/sso_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,15 @@ func (h *SSOHandler) validateCustomerProvider(w http.ResponseWriter, r *http.Req
respondValidationError(w, r, "Customer login currently requires a GitHub provider")
return false
}
if req.CustomerOrganisationID == nil || *req.CustomerOrganisationID <= 0 {
respondValidationError(w, r, "A customer organisation is required for customer login")
return false
if req.CustomerOrganisationID == nil {
return true
}
exists, err := repository.NewCustomerAccessRepository(h.db).OrganisationExists(r.Context(), *req.CustomerOrganisationID)
if err != nil {
respondInternalError(w, r, err)
return false
}
if !exists {
if *req.CustomerOrganisationID <= 0 || !exists {
respondValidationError(w, r, "Customer organisation does not exist")
return false
}
Expand Down
6 changes: 3 additions & 3 deletions internal/repository/customer_access_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (r *CustomerAccessRepository) PortalLoginAllowed(ctx context.Context, custo
}

// GitHubCustomer links only customer identities and never reassigns an existing organisation.
func (r *CustomerAccessRepository) GitHubCustomer(ctx context.Context, providerID int, externalID, email, name string, orgID int, signup bool) (int, error) {
func (r *CustomerAccessRepository) GitHubCustomer(ctx context.Context, providerID int, externalID, email, name string, orgID *int, signup bool) (int, error) {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return 0, err
Expand Down Expand Up @@ -198,7 +198,7 @@ func (r *CustomerAccessRepository) GitHubCustomer(ctx context.Context, providerI
if err := tx.QueryRow(`SELECT customer_organisation_id,deactivated_at FROM portal_customers WHERE id = ?`, id).Scan(&existingOrg, &deactivated); err != nil {
return 0, err
}
if !existingOrg.Valid || int(existingOrg.Int64) != orgID || deactivated.Valid {
if deactivated.Valid || (orgID != nil && (!existingOrg.Valid || int(existingOrg.Int64) != *orgID)) {
return 0, ErrCustomerAccessDenied
}
if _, err := tx.Exec(`INSERT INTO customer_external_accounts (provider_id,external_id,customer_id) VALUES (?,?,?) ON CONFLICT DO NOTHING`, providerID, externalID, id); err != nil {
Expand All @@ -215,7 +215,7 @@ func (r *CustomerAccessRepository) GitHubCustomer(ctx context.Context, providerI
return 0, err
}
var valid bool
if err := tx.QueryRow(`SELECT EXISTS(SELECT 1 FROM portal_customers WHERE id = ? AND customer_organisation_id = ? AND deactivated_at IS NULL)`, id, orgID).Scan(&valid); err != nil {
if err := tx.QueryRow(`SELECT EXISTS(SELECT 1 FROM portal_customers WHERE id = ? AND (? OR customer_organisation_id = ?) AND deactivated_at IS NULL)`, id, orgID == nil, orgID).Scan(&valid); err != nil {
return 0, err
}
if !valid {
Expand Down
Loading