feat(ui:profile): permit change of username, givenname, familyname

usernam: can be set once, after Nextcloud gateway depends on it
This commit is contained in:
Edouard Vanbelle
2026-06-03 09:35:38 +02:00
parent 45ba118c35
commit cea315fcfd
20 changed files with 361 additions and 4 deletions
+4 -3
View File
@@ -149,7 +149,7 @@
*
* @typedef {Object} User
* @property {string} id
* @property {string} username
* @property {string} [username] Optional handle (PR 16); claim-once via /api/auth/me/profile (PR 24). Omitted from JSON when null.
* @property {string} email
* @property {string} role
* @property {number} storage_quota_bytes
@@ -162,8 +162,9 @@
* @property {string|null} [image] Avatar URL or data URI
* @property {boolean} can_edit_image False for OIDC-only users
* @property {boolean} is_external True for magic-link / OIDC-only / OCM recipients
* @property {string} [given_name] OIDC `given_name` claim, when set
* @property {string} [family_name] OIDC `family_name` claim, when set
* @property {string} [given_name] First/given name; set at OIDC JIT or via PATCH /api/auth/me/profile (PR 24)
* @property {string} [family_name] Last/family name; set at OIDC JIT or via PATCH /api/auth/me/profile (PR 24)
* @property {string} [email_verified_at] ISO 8601 timestamp of the first proof-of-email-control (PR 23). Omitted when unverified.
*/
/**
+134
View File
@@ -336,6 +336,8 @@ async function init() {
document.getElementById('password-section').classList.add('hidden');
}
_renderProfileEdit(user);
loadAppPasswords();
try {
@@ -597,6 +599,137 @@ async function revokeAppPassword(id, label) {
}
}
/**
* Render the Edit Profile card based on the current user.
*
* For OIDC users: the entire form is hidden and a single alert tells
* them their profile is managed at the IdP. For local users: the form
* is populated from the current values, and the username input is
* disabled when a handle is already claimed (PR 24's claim-once
* policy).
*
* @param {import('../../core/types.js').User} user
*/
function _renderProfileEdit(user) {
const oidcNote = document.getElementById('profile-edit-oidc-note');
const form = document.getElementById('profile-edit-form');
if (!oidcNote || !form) return;
const isOidc = user.auth_provider && user.auth_provider !== 'local';
if (isOidc) {
oidcNote.classList.remove('hidden');
form.classList.add('hidden');
return;
}
oidcNote.classList.add('hidden');
form.classList.remove('hidden');
const usernameInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-username'));
const usernameHint = document.getElementById('profile-edit-username-hint');
const givenInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-given-name'));
const familyInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-family-name'));
if (user.username) {
usernameInput.value = user.username;
usernameInput.disabled = true;
if (usernameHint) {
usernameHint.textContent = i18n.t('profile.username_already_claimed');
}
} else {
usernameInput.value = '';
usernameInput.disabled = false;
if (usernameHint) {
usernameHint.textContent = i18n.t('profile.username_claim_hint');
}
}
givenInput.value = user.given_name || '';
familyInput.value = user.family_name || '';
}
/**
* Submit the profile edit form. Only sends fields the user can change:
* - Username only if not already claimed (input wasn't disabled).
* - Given/family names only when their value differs from the
* current (avoids 400-rejecting an empty string the user never
* touched).
*
* @param {Event} e
*/
async function submitProfile(e) {
e.preventDefault();
const statusEl = document.getElementById('profile-edit-status');
const btn = /** @type {HTMLButtonElement} */ (document.getElementById('profile-edit-submit'));
const usernameInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-username'));
const givenInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-given-name'));
const familyInput = /** @type {HTMLInputElement} */ (document.getElementById('profile-edit-family-name'));
/** @type {{ username?: string, given_name?: string, family_name?: string }} */
const body = {};
if (!usernameInput.disabled && usernameInput.value.trim()) {
body.username = usernameInput.value.trim();
}
const given = givenInput.value.trim();
if (given) body.given_name = given;
const family = familyInput.value.trim();
if (family) body.family_name = family;
if (Object.keys(body).length === 0) {
statusEl.innerHTML = `<div class="alert alert-info"><i class="fas fa-info-circle"></i> ${escapeHtml(i18n.t('profile.profile_no_changes'))}</div>`;
return false;
}
btn.disabled = true;
btn.innerHTML = `<i class="fas fa-spinner fa-spin"></i> ${escapeHtml(i18n.t('profile.updating'))}`;
try {
const resp = await fetch(`${API}/auth/me/profile`, {
method: 'PATCH',
headers: headers(),
credentials: 'same-origin',
body: JSON.stringify(body)
});
if (resp.ok) {
/** @type {import('../../core/types.js').User} */
const updated = await resp.json();
_renderProfileEdit(updated);
// Also refresh the read-only "Account Details" username field.
const detailUsername = document.getElementById('p-detail-username');
if (detailUsername) detailUsername.textContent = updated.username || '—';
const topUsername = document.getElementById('p-username');
if (topUsername && updated.username) topUsername.textContent = updated.username;
statusEl.innerHTML = `<div class="alert alert-success"><i class="fas fa-check-circle"></i> ${escapeHtml(i18n.t('profile.profile_saved'))}</div>`;
} else if (resp.status === 409) {
const err = await resp.json().catch(() => ({}));
// Distinguish "username taken" from "username immutable" using the
// human-readable message — both are 409. Server audit has the
// structured `reason` field; the JSON body just carries `message`.
const msg = (err.message || '').toLowerCase();
const key = msg.includes('already claimed') ? 'profile.username_immutable_error' : 'profile.username_taken_error';
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(i18n.t(key))}</div>`;
} else if (resp.status === 403) {
statusEl.innerHTML = `<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ${escapeHtml(i18n.t('profile.edit_oidc_managed'))}</div>`;
} else {
const err = await resp.json().catch(() => ({}));
statusEl.innerHTML =
'<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ' +
escapeHtml(err.message || i18n.t('profile.profile_save_failed')) +
'</div>';
}
} catch (err) {
statusEl.innerHTML =
'<div class="alert alert-error"><i class="fas fa-exclamation-circle"></i> ' +
escapeHtml(i18n.t('profile.error_network', { message: /** @type {Error} */ (err).message })) +
'</div>';
}
btn.disabled = false;
btn.innerHTML = `<i class="fas fa-save"></i> ${escapeHtml(i18n.t('profile.save_profile'))}`;
return false;
}
/** @param {string} str */
function escapeHtml(str) {
var div = document.createElement('div');
@@ -608,6 +741,7 @@ init();
/* Wire up event handlers (replaces inline onclick/onsubmit) */
document.getElementById('password-form').addEventListener('submit', changePassword);
document.getElementById('profile-edit-form')?.addEventListener('submit', submitProfile);
document.getElementById('app-pw-generate').addEventListener('click', createAppPassword);
document.getElementById('app-pw-copy-btn').addEventListener('click', copyAppPassword);
document.getElementById('app-pw-auto-toggle').addEventListener('click', toggleAutoPasswords);
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "منذ {{n}} دقيقة",
"hours_ago": "منذ {{n}} ساعة",
"days_ago": "منذ {{n}} يوم",
"edit_profile": "تعديل الملف الشخصي",
"edit_oidc_managed": "لتغيير معلوماتك (الاسم، الاسم الأول، صورة الملف الشخصي، …)، يرجى تحديثها لدى مزود الهوية. ستظهر تغييراتك عند تسجيل الدخول التالي.",
"username_claim_hint": "2-64 حرفًا، أحرف / أرقام / نقطة / شرطة / شرطة سفلية. بمجرد الاختيار، لا يمكن تغيير اسم المستخدم (عملاء DAV/NextCloud يعتمدون عليه).",
"username_already_claimed": "اسم المستخدم محدد ولا يمكن تغييره (عملاء DAV/NextCloud يعتمدون عليه).",
"given_name": "الاسم الأول",
"family_name": "اسم العائلة",
"save_profile": "حفظ التغييرات",
"profile_saved": "تم تحديث الملف الشخصي",
"profile_no_changes": "لا توجد تغييرات لحفظها.",
"profile_save_failed": "فشل الحفظ",
"username_taken_error": "اسم المستخدم هذا مستخدم بالفعل.",
"username_immutable_error": "اسم المستخدم الخاص بك محدد بالفعل ولا يمكن تغييره هنا. اتصل بالمسؤول إذا كنت بحاجة إلى إعادة التسمية.",
"change_password": "تغيير كلمة المرور",
"current_password": "كلمة المرور الحالية",
"new_password": "كلمة المرور الجديدة",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "vor {{n}} Min",
"hours_ago": "vor {{n}} Std",
"days_ago": "vor {{n}} Tagen",
"edit_profile": "Profil bearbeiten",
"edit_oidc_managed": "Um Ihre Informationen (Name, Vorname, Profilbild, …) zu ändern, aktualisieren Sie sie bitte bei Ihrem Identity-Provider. Ihre Änderungen erscheinen bei der nächsten Anmeldung.",
"username_claim_hint": "2–64 Zeichen, Buchstaben / Ziffern / Punkt / Bindestrich / Unterstrich. Nach der Wahl kann der Benutzername nicht mehr geändert werden (DAV/NextCloud-Clients hängen davon ab).",
"username_already_claimed": "Benutzername ist gesetzt und kann nicht geändert werden (DAV/NextCloud-Clients hängen davon ab).",
"given_name": "Vorname",
"family_name": "Nachname",
"save_profile": "Änderungen speichern",
"profile_saved": "Profil aktualisiert",
"profile_no_changes": "Keine Änderungen zu speichern.",
"profile_save_failed": "Speichern fehlgeschlagen",
"username_taken_error": "Dieser Benutzername ist bereits vergeben.",
"username_immutable_error": "Ihr Benutzername ist bereits gesetzt und kann hier nicht geändert werden. Wenden Sie sich an einen Administrator, wenn Sie umbenennen möchten.",
"change_password": "Passwort ändern",
"current_password": "Aktuelles Passwort",
"new_password": "Neues Passwort",
+12
View File
@@ -720,6 +720,18 @@
"minutes_ago": "{{n}} min ago",
"hours_ago": "{{n}}h ago",
"days_ago": "{{n}} days ago",
"edit_profile": "Edit Profile",
"edit_oidc_managed": "To change your information (name, first name, profile picture, …), please update it at your identity provider. Your changes will appear on your next sign-in.",
"username_claim_hint": "2–64 characters, letters/digits/dot/dash/underscore. Once chosen, the username can't be changed (DAV/NextCloud clients depend on it).",
"username_already_claimed": "Username is set and can't be changed (DAV/NextCloud clients depend on it).",
"given_name": "First name",
"family_name": "Last name",
"save_profile": "Save changes",
"profile_saved": "Profile updated",
"profile_no_changes": "No changes to save.",
"profile_save_failed": "Save failed",
"username_taken_error": "That username is already taken.",
"username_immutable_error": "Your username is already set and can't be changed here. Contact an administrator if you need a rename.",
"change_password": "Change Password",
"current_password": "Current Password",
"new_password": "New Password",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "hace {{n}} min",
"hours_ago": "hace {{n}}h",
"days_ago": "hace {{n}} días",
"edit_profile": "Editar perfil",
"edit_oidc_managed": "Para cambiar tu información (nombre, apellidos, foto de perfil, …), actualízala en tu proveedor de identidad. Los cambios se aplicarán en tu próximo inicio de sesión.",
"username_claim_hint": "Entre 2 y 64 caracteres, letras / dígitos / punto / guion / subrayado. Una vez elegido, el nombre de usuario no se puede cambiar (los clientes DAV/NextCloud dependen de él).",
"username_already_claimed": "Nombre de usuario fijado y no modificable (los clientes DAV/NextCloud dependen de él).",
"given_name": "Nombre",
"family_name": "Apellidos",
"save_profile": "Guardar cambios",
"profile_saved": "Perfil actualizado",
"profile_no_changes": "Sin cambios que guardar.",
"profile_save_failed": "Error al guardar",
"username_taken_error": "Ese nombre de usuario ya está en uso.",
"username_immutable_error": "Tu nombre de usuario ya está fijado y no se puede cambiar aquí. Contacta con un administrador si necesitas renombrarlo.",
"change_password": "Cambiar Contraseña",
"current_password": "Contraseña Actual",
"new_password": "Nueva Contraseña",
+12
View File
@@ -686,6 +686,18 @@
"minutes_ago": "{{n}} دقیقه پیش",
"hours_ago": "{{n}} ساعت پیش",
"days_ago": "{{n}} روز پیش",
"edit_profile": "ویرایش نمایه",
"edit_oidc_managed": "برای تغییر اطلاعات خود (نام، نام خانوادگی، عکس نمایه، …)، لطفاً آن‌ها را در ارائه‌دهنده هویت خود به‌روز کنید. تغییرات شما در ورود بعدی ظاهر خواهد شد.",
"username_claim_hint": "۲ تا ۶۴ کاراکتر، حروف / ارقام / نقطه / خط تیره / زیرخط. پس از انتخاب، نام کاربری قابل تغییر نیست (کلاینت‌های DAV/NextCloud به آن وابسته‌اند).",
"username_already_claimed": "نام کاربری تنظیم شده و قابل تغییر نیست (کلاینت‌های DAV/NextCloud به آن وابسته‌اند).",
"given_name": "نام",
"family_name": "نام خانوادگی",
"save_profile": "ذخیره تغییرات",
"profile_saved": "نمایه به‌روز شد",
"profile_no_changes": "تغییری برای ذخیره وجود ندارد.",
"profile_save_failed": "ذخیره ناموفق بود",
"username_taken_error": "این نام کاربری قبلاً گرفته شده است.",
"username_immutable_error": "نام کاربری شما قبلاً تنظیم شده و در اینجا قابل تغییر نیست. در صورت نیاز به تغییر نام، با مدیر تماس بگیرید.",
"change_password": "تغییر رمز عبور",
"current_password": "رمز فعلی",
"new_password": "رمز جدید",
+12
View File
@@ -720,6 +720,18 @@
"minutes_ago": "il y a {{n}} min",
"hours_ago": "il y a {{n}}h",
"days_ago": "il y a {{n}} jours",
"edit_profile": "Modifier le profil",
"edit_oidc_managed": "Pour modifier vos informations (nom, prénom, photo de profil, …), veuillez les mettre à jour chez votre fournisseur d'identité. Vos changements apparaîtront à votre prochaine connexion.",
"username_claim_hint": "2 à 64 caractères, lettres / chiffres / point / tiret / souligné. Une fois choisi, le nom d'utilisateur ne peut plus être modifié (les clients DAV/NextCloud en dépendent).",
"username_already_claimed": "Nom d'utilisateur fixé et non modifiable (les clients DAV/NextCloud en dépendent).",
"given_name": "Prénom",
"family_name": "Nom",
"save_profile": "Enregistrer",
"profile_saved": "Profil mis à jour",
"profile_no_changes": "Aucun changement à enregistrer.",
"profile_save_failed": "Échec de l'enregistrement",
"username_taken_error": "Ce nom d'utilisateur est déjà pris.",
"username_immutable_error": "Votre nom d'utilisateur est déjà défini et ne peut plus être modifié ici. Contactez un administrateur si vous souhaitez le renommer.",
"change_password": "Changer le mot de passe",
"current_password": "Mot de passe actuel",
"new_password": "Nouveau mot de passe",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}} मिनट पहले",
"hours_ago": "{{n}} घंटे पहले",
"days_ago": "{{n}} दिन पहले",
"edit_profile": "प्रोफ़ाइल संपादित करें",
"edit_oidc_managed": "अपनी जानकारी (नाम, प्रथम नाम, प्रोफ़ाइल चित्र, …) बदलने के लिए, कृपया अपने पहचान प्रदाता पर इसे अद्यतन करें। आपके परिवर्तन अगले साइन-इन पर दिखाई देंगे।",
"username_claim_hint": "2–64 अक्षर, अक्षर / अंक / डॉट / डैश / अंडरस्कोर। एक बार चुनने के बाद, उपयोगकर्ता नाम नहीं बदला जा सकता (DAV/NextCloud क्लाइंट इस पर निर्भर करते हैं)।",
"username_already_claimed": "उपयोगकर्ता नाम सेट है और बदला नहीं जा सकता (DAV/NextCloud क्लाइंट इस पर निर्भर करते हैं)।",
"given_name": "प्रथम नाम",
"family_name": "अंतिम नाम",
"save_profile": "परिवर्तन सहेजें",
"profile_saved": "प्रोफ़ाइल अद्यतन की गई",
"profile_no_changes": "सहेजने के लिए कोई परिवर्तन नहीं।",
"profile_save_failed": "सहेजना विफल",
"username_taken_error": "यह उपयोगकर्ता नाम पहले से उपयोग में है।",
"username_immutable_error": "आपका उपयोगकर्ता नाम पहले से सेट है और यहाँ नहीं बदला जा सकता। यदि आपको नाम बदलने की आवश्यकता है तो किसी व्यवस्थापक से संपर्क करें।",
"change_password": "पासवर्ड बदलें",
"current_password": "वर्तमान पासवर्ड",
"new_password": "नया पासवर्ड",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}} min fa",
"hours_ago": "{{n}}h fa",
"days_ago": "{{n}} giorni fa",
"edit_profile": "Modifica profilo",
"edit_oidc_managed": "Per modificare le tue informazioni (nome, cognome, foto profilo, …), aggiornale presso il tuo identity provider. Le modifiche compariranno al prossimo accesso.",
"username_claim_hint": "Da 2 a 64 caratteri, lettere / cifre / punto / trattino / sottolineatura. Una volta scelto, il nome utente non può essere modificato (i client DAV/NextCloud dipendono da esso).",
"username_already_claimed": "Nome utente impostato e non modificabile (i client DAV/NextCloud dipendono da esso).",
"given_name": "Nome",
"family_name": "Cognome",
"save_profile": "Salva modifiche",
"profile_saved": "Profilo aggiornato",
"profile_no_changes": "Nessuna modifica da salvare.",
"profile_save_failed": "Salvataggio non riuscito",
"username_taken_error": "Questo nome utente è già in uso.",
"username_immutable_error": "Il tuo nome utente è già impostato e non può essere cambiato qui. Contatta un amministratore se desideri rinominarlo.",
"change_password": "Cambia Password",
"current_password": "Password Attuale",
"new_password": "Nuova Password",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}}分前",
"hours_ago": "{{n}}時間前",
"days_ago": "{{n}}日前",
"edit_profile": "プロフィールを編集",
"edit_oidc_managed": "情報(姓、名、プロフィール写真など)を変更するには、IDプロバイダーで更新してください。次回サインイン時に反映されます。",
"username_claim_hint": "2〜64文字、英数字 / ドット / ハイフン / アンダースコア。一度選択すると、ユーザー名は変更できません(DAV/NextCloudクライアントが依存します)。",
"username_already_claimed": "ユーザー名は設定済みで変更できません(DAV/NextCloudクライアントが依存します)。",
"given_name": "名",
"family_name": "姓",
"save_profile": "変更を保存",
"profile_saved": "プロフィールを更新しました",
"profile_no_changes": "保存する変更はありません。",
"profile_save_failed": "保存に失敗しました",
"username_taken_error": "このユーザー名はすでに使用されています。",
"username_immutable_error": "ユーザー名はすでに設定されており、ここでは変更できません。名前を変更したい場合は管理者にお問い合わせください。",
"change_password": "パスワード変更",
"current_password": "現在のパスワード",
"new_password": "新しいパスワード",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}}분 전",
"hours_ago": "{{n}}시간 전",
"days_ago": "{{n}}일 전",
"edit_profile": "프로필 편집",
"edit_oidc_managed": "정보(이름, 성, 프로필 사진 등)를 변경하려면 ID 공급자에서 업데이트하세요. 변경 사항은 다음 로그인 시 반영됩니다.",
"username_claim_hint": "2~64자, 영문자 / 숫자 / 점 / 하이픈 / 밑줄. 선택한 후에는 사용자 이름을 변경할 수 없습니다(DAV/NextCloud 클라이언트가 이에 의존합니다).",
"username_already_claimed": "사용자 이름이 설정되어 있어 변경할 수 없습니다(DAV/NextCloud 클라이언트가 이에 의존합니다).",
"given_name": "이름",
"family_name": "성",
"save_profile": "변경 사항 저장",
"profile_saved": "프로필이 업데이트되었습니다",
"profile_no_changes": "저장할 변경 사항이 없습니다.",
"profile_save_failed": "저장 실패",
"username_taken_error": "이미 사용 중인 사용자 이름입니다.",
"username_immutable_error": "사용자 이름이 이미 설정되어 있어 여기서 변경할 수 없습니다. 이름을 변경하려면 관리자에게 문의하세요.",
"change_password": "비밀번호 변경",
"current_password": "현재 비밀번호",
"new_password": "새 비밀번호",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}} min geleden",
"hours_ago": "{{n}}u geleden",
"days_ago": "{{n}} dagen geleden",
"edit_profile": "Profiel bewerken",
"edit_oidc_managed": "Om uw gegevens (naam, voornaam, profielfoto, …) te wijzigen, werk ze bij bij uw identity provider. De wijzigingen verschijnen bij uw volgende aanmelding.",
"username_claim_hint": "2–64 tekens, letters / cijfers / punt / streepje / underscore. Eenmaal gekozen kan de gebruikersnaam niet meer worden gewijzigd (DAV/NextCloud-clients zijn ervan afhankelijk).",
"username_already_claimed": "Gebruikersnaam ingesteld en niet wijzigbaar (DAV/NextCloud-clients zijn ervan afhankelijk).",
"given_name": "Voornaam",
"family_name": "Achternaam",
"save_profile": "Wijzigingen opslaan",
"profile_saved": "Profiel bijgewerkt",
"profile_no_changes": "Geen wijzigingen om op te slaan.",
"profile_save_failed": "Opslaan mislukt",
"username_taken_error": "Die gebruikersnaam is al in gebruik.",
"username_immutable_error": "Uw gebruikersnaam is al ingesteld en kan hier niet worden gewijzigd. Neem contact op met een beheerder als u wilt hernoemen.",
"change_password": "Wachtwoord wijzigen",
"current_password": "Huidig wachtwoord",
"new_password": "Nieuw wachtwoord",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}} min temu",
"hours_ago": "{{n}} godz. temu",
"days_ago": "{{n}} dni temu",
"edit_profile": "Edytuj profil",
"edit_oidc_managed": "Aby zmienić swoje dane (nazwisko, imię, zdjęcie profilowe, …), zaktualizuj je u swojego dostawcy tożsamości. Twoje zmiany pojawią się przy następnym logowaniu.",
"username_claim_hint": "2–64 znaki, litery / cyfry / kropka / myślnik / podkreślenie. Po wybraniu nazwy użytkownika nie można jej zmienić (klienty DAV/NextCloud są od niej zależne).",
"username_already_claimed": "Nazwa użytkownika jest ustawiona i nie może być zmieniona (klienty DAV/NextCloud są od niej zależne).",
"given_name": "Imię",
"family_name": "Nazwisko",
"save_profile": "Zapisz zmiany",
"profile_saved": "Profil zaktualizowany",
"profile_no_changes": "Brak zmian do zapisania.",
"profile_save_failed": "Zapis nie powiódł się",
"username_taken_error": "Ta nazwa użytkownika jest już zajęta.",
"username_immutable_error": "Twoja nazwa użytkownika jest już ustawiona i nie można jej tutaj zmienić. Skontaktuj się z administratorem, jeśli chcesz ją zmienić.",
"change_password": "Zmień hasło",
"current_password": "Bieżące hasło",
"new_password": "Nowe hasło",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}} min atrás",
"hours_ago": "{{n}}h atrás",
"days_ago": "{{n}} dias atrás",
"edit_profile": "Editar perfil",
"edit_oidc_managed": "Para alterar suas informações (nome, sobrenome, foto de perfil, …), atualize-as no seu provedor de identidade. As mudanças aparecerão no próximo login.",
"username_claim_hint": "De 2 a 64 caracteres, letras / dígitos / ponto / hífen / sublinhado. Uma vez escolhido, o nome de usuário não pode ser alterado (clientes DAV/NextCloud dependem dele).",
"username_already_claimed": "Nome de usuário definido e não pode ser alterado (clientes DAV/NextCloud dependem dele).",
"given_name": "Nome",
"family_name": "Sobrenome",
"save_profile": "Salvar alterações",
"profile_saved": "Perfil atualizado",
"profile_no_changes": "Sem alterações para salvar.",
"profile_save_failed": "Falha ao salvar",
"username_taken_error": "Este nome de usuário já está em uso.",
"username_immutable_error": "Seu nome de usuário já está definido e não pode ser alterado aqui. Contate um administrador se desejar renomeá-lo.",
"change_password": "Alterar Senha",
"current_password": "Senha Atual",
"new_password": "Nova Senha",
+12
View File
@@ -703,6 +703,18 @@
"minutes_ago": "{{n}} мин назад",
"hours_ago": "{{n}} ч назад",
"days_ago": "{{n}} дн назад",
"edit_profile": "Редактировать профиль",
"edit_oidc_managed": "Чтобы изменить ваши данные (имя, фамилию, фотографию профиля, …), обновите их у вашего провайдера идентификации. Изменения появятся при следующем входе.",
"username_claim_hint": "2–64 символа, буквы / цифры / точка / дефис / подчёркивание. После выбора имя пользователя нельзя изменить (клиенты DAV/NextCloud зависят от него).",
"username_already_claimed": "Имя пользователя установлено и не может быть изменено (клиенты DAV/NextCloud зависят от него).",
"given_name": "Имя",
"family_name": "Фамилия",
"save_profile": "Сохранить изменения",
"profile_saved": "Профиль обновлён",
"profile_no_changes": "Нет изменений для сохранения.",
"profile_save_failed": "Не удалось сохранить",
"username_taken_error": "Это имя пользователя уже занято.",
"username_immutable_error": "Ваше имя пользователя уже установлено и не может быть изменено здесь. Свяжитесь с администратором, если нужно переименовать.",
"change_password": "Изменить пароль",
"current_password": "Текущий пароль",
"new_password": "Новый пароль",
+12
View File
@@ -686,6 +686,18 @@
"minutes_ago": "{{n}}分鐘前",
"hours_ago": "{{n}}小時前",
"days_ago": "{{n}}天前",
"edit_profile": "編輯個人資料",
"edit_oidc_managed": "要更改您的資訊(姓名、名字、頭像等),請前往您的身分提供者更新。變更將在您下次登入時顯示。",
"username_claim_hint": "2-64 個字元,字母 / 數字 / 點 / 短橫線 / 底線。一旦選定,使用者名稱將無法更改(DAV/NextCloud 用戶端依賴它)。",
"username_already_claimed": "使用者名稱已設定,不可更改(DAV/NextCloud 用戶端依賴它)。",
"given_name": "名",
"family_name": "姓",
"save_profile": "儲存變更",
"profile_saved": "個人資料已更新",
"profile_no_changes": "沒有變更可儲存。",
"profile_save_failed": "儲存失敗",
"username_taken_error": "該使用者名稱已被使用。",
"username_immutable_error": "您的使用者名稱已設定,無法在此更改。如需重新命名,請聯絡管理員。",
"change_password": "修改密碼",
"current_password": "當前密碼",
"new_password": "新密碼",
+12
View File
@@ -686,6 +686,18 @@
"minutes_ago": "{{n}}分钟前",
"hours_ago": "{{n}}小时前",
"days_ago": "{{n}}天前",
"edit_profile": "编辑个人资料",
"edit_oidc_managed": "要更改您的信息(姓名、名字、头像等),请前往您的身份提供商更新。变更将在您下次登录时显示。",
"username_claim_hint": "2-64 个字符,字母 / 数字 / 点 / 短横线 / 下划线。一旦选定,用户名将无法更改(DAV/NextCloud 客户端依赖它)。",
"username_already_claimed": "用户名已设置,不可更改(DAV/NextCloud 客户端依赖它)。",
"given_name": "名",
"family_name": "姓",
"save_profile": "保存更改",
"profile_saved": "个人资料已更新",
"profile_no_changes": "无更改可保存。",
"profile_save_failed": "保存失败",
"username_taken_error": "该用户名已被占用。",
"username_immutable_error": "您的用户名已设置,无法在此更改。如需重命名,请联系管理员。",
"change_password": "修改密码",
"current_password": "当前密码",
"new_password": "新密码",
+30
View File
@@ -116,6 +116,36 @@
</div>
</div>
<div class="profile-card" id="profile-edit-section">
<h2><i class="fas fa-id-badge"></i> <span data-i18n="profile.edit_profile">Edit Profile</span></h2>
<div id="profile-edit-oidc-note" class="alert alert-info hidden">
<i class="fas fa-info-circle"></i>
<span data-i18n="profile.edit_oidc_managed">To change your information (name, first name, profile picture, …), please update it at your identity provider. Your changes will appear on your next sign-in.</span>
</div>
<form id="profile-edit-form">
<div class="form-group">
<label for="profile-edit-username" data-i18n="profile.username">Username</label>
<input type="text" id="profile-edit-username" maxlength="64" autocomplete="username"
data-i18n-placeholder="profile.username_placeholder" placeholder="e.g. alice">
<small id="profile-edit-username-hint" data-i18n="profile.username_claim_hint">2–64 characters, letters/digits/dot/dash/underscore. Once chosen, the username can't be changed (DAV/NextCloud clients depend on it).</small>
</div>
<div class="form-group">
<label for="profile-edit-given-name" data-i18n="profile.given_name">First name</label>
<input type="text" id="profile-edit-given-name" maxlength="128" autocomplete="given-name">
</div>
<div class="form-group">
<label for="profile-edit-family-name" data-i18n="profile.family_name">Last name</label>
<input type="text" id="profile-edit-family-name" maxlength="128" autocomplete="family-name">
</div>
<button type="submit" class="btn btn-primary" id="profile-edit-submit">
<i class="fas fa-save"></i> <span data-i18n="profile.save_profile">Save changes</span>
</button>
<div id="profile-edit-status"></div>
</form>
</div>
<div class="profile-card">
<h2><i class="fas fa-hdd"></i> <span data-i18n="profile.storage">Storage</span></h2>
<div class="storage-stats">
+1 -1
View File
@@ -1,6 +1,6 @@
// OxiCloud Service Worker
// FIXME: generate cache name according build ?
const CACHE_NAME = 'oxicloud-cache-v24';
const CACHE_NAME = 'oxicloud-cache-v25';
// Only cache static assets — NOT HTML files.
// HTML files are served network-first so browsers always get the latest