From a22f032924208c4d27fa1445b51db0240360c30a Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Sat, 17 Jun 2023 17:26:36 +0100 Subject: [PATCH] userpage: show and allow modification of contact methods --- api-messages.go | 4 + api-userpage.go | 82 ++++++++++++++++++ html/user.html | 8 ++ lang/admin/da-dk.json | 6 -- lang/admin/de-de.json | 6 -- lang/admin/el-gr.json | 6 -- lang/admin/en-gb.json | 6 -- lang/admin/en-us.json | 6 -- lang/admin/es-es.json | 6 -- lang/admin/fr-fr.json | 6 -- lang/admin/hu-hu.json | 6 -- lang/admin/id-id.json | 1 - lang/admin/nl-nl.json | 6 -- lang/admin/pl-pl.json | 6 -- lang/admin/pt-br.json | 6 -- lang/admin/sv-se.json | 4 - lang/admin/vi-vn.json | 6 -- lang/admin/zh-hans.json | 6 -- lang/admin/zh-hant.json | 6 -- lang/common/da-dk.json | 10 ++- lang/common/de-de.json | 10 ++- lang/common/el-gr.json | 10 ++- lang/common/en-gb.json | 10 ++- lang/common/en-us.json | 13 ++- lang/common/es-es.json | 10 ++- lang/common/fr-fr.json | 10 ++- lang/common/hu-hu.json | 7 +- lang/common/id-id.json | 3 +- lang/common/nl-nl.json | 10 ++- lang/common/pl-pl.json | 6 +- lang/common/pt-br.json | 10 ++- lang/common/sv-se.json | 8 +- lang/common/vi-vn.json | 7 +- lang/common/zh-hans.json | 10 ++- lang/common/zh-hant.json | 10 ++- lang/form/en-us.json | 2 +- models.go | 16 +++- router.go | 2 + scripts/langmover/login.json | 18 ++-- storage.go | 11 ++- ts/admin.ts | 10 +-- ts/modules/login.ts | 25 +++++- ts/user.ts | 158 +++++++++++++++++++++++++++++++++-- 43 files changed, 421 insertions(+), 148 deletions(-) diff --git a/api-messages.go b/api-messages.go index 676ec15..8009adc 100644 --- a/api-messages.go +++ b/api-messages.go @@ -336,6 +336,10 @@ func (app *appContext) SetContactMethods(gc *gin.Context) { respondBool(400, false, gc) return } + app.setContactMethods(req, gc) +} + +func (app *appContext) setContactMethods(req SetContactMethodsDTO, gc *gin.Context) { if tgUser, ok := app.storage.telegram[req.ID]; ok { change := tgUser.Contact != req.Telegram tgUser.Contact = req.Telegram diff --git a/api-userpage.go b/api-userpage.go index 65a0dd4..fd49c27 100644 --- a/api-userpage.go +++ b/api-userpage.go @@ -19,6 +19,88 @@ func (app *appContext) MyDetails(gc *gin.Context) { return } resp.Username = user.Name + resp.Admin = user.Policy.IsAdministrator + resp.Disabled = user.Policy.IsDisabled + + if exp, ok := app.storage.users[user.ID]; ok { + resp.Expiry = exp.Unix() + } + + app.storage.loadEmails() + app.storage.loadDiscordUsers() + app.storage.loadMatrixUsers() + app.storage.loadTelegramUsers() + + if emailEnabled { + resp.Email = &MyDetailsContactMethodsDTO{} + if email, ok := app.storage.emails[user.ID]; ok { + resp.Email.Value = email.Addr + resp.Email.Enabled = email.Contact + } + } + + if discordEnabled { + resp.Discord = &MyDetailsContactMethodsDTO{} + if discord, ok := app.storage.discord[user.ID]; ok { + resp.Discord.Value = RenderDiscordUsername(discord) + resp.Discord.Enabled = discord.Contact + } + } + + if telegramEnabled { + resp.Telegram = &MyDetailsContactMethodsDTO{} + if telegram, ok := app.storage.telegram[user.ID]; ok { + resp.Telegram.Value = telegram.Username + resp.Telegram.Enabled = telegram.Contact + } + } + + if matrixEnabled { + resp.Matrix = &MyDetailsContactMethodsDTO{} + if matrix, ok := app.storage.matrix[user.ID]; ok { + resp.Matrix.Value = matrix.UserID + resp.Matrix.Enabled = matrix.Contact + } + } gc.JSON(200, resp) } + +// @Summary Sets whether to notify yourself through telegram/discord/matrix/email or not. +// @Produce json +// @Param SetContactMethodsDTO body SetContactMethodsDTO true "User's Jellyfin ID and whether or not to notify then through Telegram." +// @Success 200 {object} boolResponse +// @Success 400 {object} boolResponse +// @Success 500 {object} boolResponse +// @Router /my/contact [post] +// @Security Bearer +// @tags User Page +func (app *appContext) SetMyContactMethods(gc *gin.Context) { + var req SetContactMethodsDTO + gc.BindJSON(&req) + req.ID = gc.GetString("jfId") + if req.ID == "" { + respondBool(400, false, gc) + return + } + app.setContactMethods(req, gc) +} + +// @Summary Logout by deleting refresh token from cookies. +// @Produce json +// @Success 200 {object} boolResponse +// @Failure 500 {object} stringResponse +// @Router /my/logout [post] +// @Security Bearer +// @tags User Page +func (app *appContext) LogoutUser(gc *gin.Context) { + cookie, err := gc.Cookie("refresh") + if err != nil { + app.debug.Printf("Couldn't get cookies: %s", err) + respond(500, "Couldn't fetch cookies", gc) + return + } + app.invalidTokens = append(app.invalidTokens, cookie) + gc.SetCookie("refresh", "invalid", -1, "/my", gc.Request.URL.Hostname(), true, true) + respondBool(200, true, gc) +} diff --git a/html/user.html b/html/user.html index 8dbc97b..68acc52 100644 --- a/html/user.html +++ b/html/user.html @@ -46,6 +46,14 @@
+
+
+
+
+ {{ .strings.contactMethods }} +
+
+
diff --git a/lang/admin/da-dk.json b/lang/admin/da-dk.json index 63fd01f..9170563 100644 --- a/lang/admin/da-dk.json +++ b/lang/admin/da-dk.json @@ -22,11 +22,6 @@ "select": "Vælg", "name": "Navn", "date": "Dato", - "enabled": "Aktiveret", - "disabled": "Deaktiveret", - "reEnable": "Genaktiver", - "disable": "Deaktiver", - "admin": "Administrator", "updates": "Opdateringer", "update": "Opdatering", "download": "Hent", @@ -136,7 +131,6 @@ "errorCreateProfile": "Kunne ikke oprette profilen {n}", "errorSetDefaultProfile": "Standard profilen kunne ikke indstilles.", "errorLoadUsers": "Kunne ikke indlæse brugere.", - "errorSaveSettings": "Kunne ikke gemme indstillingerne.", "errorLoadSettings": "Indstillingerne kunne ikke indlæses.", "errorSetOmbiDefaults": "Ombi standarderne kunne ikke gemmes.", "errorLoadOmbiUsers": "Kunne ikke indlæse ombi brugere.", diff --git a/lang/admin/de-de.json b/lang/admin/de-de.json index 2a93467..4b59b80 100644 --- a/lang/admin/de-de.json +++ b/lang/admin/de-de.json @@ -77,17 +77,12 @@ "search": "Suchen", "userExpiry": "Benutzer Ablaufdatum", "inviteDuration": "Invite Dauer", - "enabled": "Aktiviert", "userExpiryDescription": "Eine bestimmte Zeit nach der Anmeldung wird jfa-go das Konto löschen/deaktivieren. Du kannst dieses Verhalten in den Einstellungen ändern.", - "disabled": "Deaktiviert", - "admin": "Admin", "download": "Herunterladen", "update": "Aktualisieren", "updates": "Aktualisierungen", "expiry": "Ablaufdatum", "extendExpiry": "Ablaufdatum verlängern", - "reEnable": "Wieder aktivieren", - "disable": "Deaktivieren", "donate": "Spenden", "conditionals": "Bedingungen", "contactThrough": "Kontakt über:", @@ -129,7 +124,6 @@ "errorCreateProfile": "Fehler beim Erstellen des Profils {n}", "errorSetDefaultProfile": "Fehler beim Setzen des Standardprofils.", "errorLoadUsers": "Fehler beim Laden der Benutzer.", - "errorSaveSettings": "Einstellungen konnten nicht gespeichert werden.", "errorLoadSettings": "Fehler beim Laden der Einstellungen.", "errorSetOmbiDefaults": "Fehler beim Speichern der Ombi-Standardeinstellungen.", "errorLoadOmbiUsers": "Fehler beim Laden der Ombi-Benutzer.", diff --git a/lang/admin/el-gr.json b/lang/admin/el-gr.json index 98b2310..3700829 100644 --- a/lang/admin/el-gr.json +++ b/lang/admin/el-gr.json @@ -75,9 +75,6 @@ "download": "Λήψη", "search": "Αναζήτηση", "inviteDuration": "Διάρκεια Πρόσκλησης", - "enabled": "Ενεργοποιημένο", - "disabled": "Απενεργοποιημένο", - "admin": "Διαχειριστής", "expiry": "Λήξη", "userExpiry": "Λήξη Χρήστη", "userExpiryDescription": "Μετά απο ένα καθορισμένο χρόνο μετά απο κάθε εγγραφή, το jfa-go θα διαγράφει/απενεργοποιεί τον λογαριασμό. Μπορείτε να αλλάξετε αυτή την συμπεριφορά στις ρυθμίσεις.", @@ -86,8 +83,6 @@ "message": "Μήνυμα", "extendExpiry": "Παράταση λήξης", "markdownSupported": "Το Markdown υποστυρίζεται.", - "reEnable": "Επανα-ενεργοποίηση", - "disable": "Απενεργοποίηση", "inviteMonths": "Μήνες" }, "notifications": { @@ -105,7 +100,6 @@ "errorCreateProfile": "Αποτυχία δημιουργίας του προφίλ {n}", "errorSetDefaultProfile": "Αποτυχία ορισμού του προκαθορισμένου προφίλ.", "errorLoadUsers": "Αποτυχία φόρτωσης χρηστών.", - "errorSaveSettings": "Αποτυχία αποθήκευσης ρυθμίσεων.", "errorLoadSettings": "Αποτυχία φόρτωσης ρυθμίσεων.", "errorSetOmbiDefaults": "Αποτυχία αποθήκευσης προκαθορισμένων ρυθμίσεων για το Ombi.", "errorLoadOmbiUsers": "Αποτυχία φόρτωσης χρηστών Ombi.", diff --git a/lang/admin/en-gb.json b/lang/admin/en-gb.json index 705d837..2597713 100644 --- a/lang/admin/en-gb.json +++ b/lang/admin/en-gb.json @@ -94,16 +94,12 @@ "contactThrough": "Contact through:", "select": "Select", "date": "Date", - "enabled": "Enabled", - "disabled": "Disabled", - "disable": "Disable", "edit": "Edit", "extendExpiry": "Extend expiry", "sendPWR": "Send Password Reset", "inviteMonths": "Months", "inviteDuration": "Invite Duration", "add": "Add", - "reEnable": "Re-enable", "update": "Update", "user": "User", "userExpiryDescription": "A specified amount of time after each signup, jfa-go will delete/disable the account. You can change this behaviour in settings.", @@ -148,7 +144,6 @@ "settingsApplyRestartLater": "Apply, restart later", "subject": "Subject", "setExpiry": "Set expiry", - "admin": "Admin", "download": "Download", "search": "Search", "advancedSettings": "Advanced Settings", @@ -187,7 +182,6 @@ "errorLoadProfiles": "Failed to load profiles.", "errorCreateProfile": "Failed to create profile {n}", "errorLoadUsers": "Failed to load users.", - "errorSaveSettings": "Couldn't save settings.", "errorSetOmbiProfile": "Failed to store ombi profile.", "errorLoadOmbiUsers": "Failed to load ombi users.", "errorFailureCheckLogs": "Failed (check console/logs)", diff --git a/lang/admin/en-us.json b/lang/admin/en-us.json index 64512cc..911ae84 100644 --- a/lang/admin/en-us.json +++ b/lang/admin/en-us.json @@ -22,12 +22,7 @@ "select": "Select", "name": "Name", "date": "Date", - "enabled": "Enabled", - "disabled": "Disabled", - "reEnable": "Re-enable", "setExpiry": "Set expiry", - "disable": "Disable", - "admin": "Admin", "updates": "Updates", "update": "Update", "download": "Download", @@ -147,7 +142,6 @@ "errorCreateProfile": "Failed to create profile {n}", "errorSetDefaultProfile": "Failed to set default profile.", "errorLoadUsers": "Failed to load users.", - "errorSaveSettings": "Couldn't save settings.", "errorLoadSettings": "Failed to load settings.", "errorSetOmbiProfile": "Failed to store ombi profile.", "errorLoadOmbiUsers": "Failed to load ombi users.", diff --git a/lang/admin/es-es.json b/lang/admin/es-es.json index 253349c..de45bb2 100644 --- a/lang/admin/es-es.json +++ b/lang/admin/es-es.json @@ -20,11 +20,6 @@ "delete": "Eliminar", "name": "Nombre", "date": "Fecha", - "enabled": "Activado", - "disabled": "Desactivado", - "reEnable": "Reactivar", - "disable": "Desactivar", - "admin": "Administrador", "updates": "Actualizaciones", "update": "Actualizar", "download": "Descargar", @@ -133,7 +128,6 @@ "errorCreateProfile": "No se pudo crear el perfil {n}", "errorSetDefaultProfile": "No se pudo establecer el perfil predeterminado.", "errorLoadUsers": "No se pudieron cargar los usuarios.", - "errorSaveSettings": "No se pudo guardar la configuración.", "errorLoadSettings": "No se pudo cargar la configuración.", "errorSetOmbiDefaults": "No se pudieron almacenar los valores predeterminados de ombi.", "errorLoadOmbiUsers": "No se pudieron cargar los usuarios de Ombi.", diff --git a/lang/admin/fr-fr.json b/lang/admin/fr-fr.json index 142fdca..9f57f7c 100644 --- a/lang/admin/fr-fr.json +++ b/lang/admin/fr-fr.json @@ -76,11 +76,6 @@ "edit": "Éditer", "customizeMessages": "Personnaliser les e-mails", "inviteDuration": "Durée de l'invitation", - "enabled": "Activé", - "disabled": "Désactivé", - "reEnable": "Ré-activé", - "disable": "Désactivé", - "admin": "Administrateur", "expiry": "Expiration", "advancedSettings": "Paramètres avancés", "userExpiry": "Expiration de l'utilisateur", @@ -130,7 +125,6 @@ "errorCreateProfile": "Échec de la création du profil {n}", "errorSetDefaultProfile": "Échec de la définition du profil par défaut.", "errorLoadUsers": "Échec du chargement des utilisateurs.", - "errorSaveSettings": "Impossible d'enregistrer les paramètres.", "errorLoadSettings": "Échec du chargement des paramètres.", "errorSetOmbiDefaults": "Impossible de stocker les valeurs par défaut d'Ombi.", "errorLoadOmbiUsers": "Échec du chargement des utilisateurs Ombi.", diff --git a/lang/admin/hu-hu.json b/lang/admin/hu-hu.json index f439b09..3f83575 100644 --- a/lang/admin/hu-hu.json +++ b/lang/admin/hu-hu.json @@ -22,12 +22,7 @@ "select": "Kiválasztás", "name": "Név", "date": "Dátum", - "enabled": "Engedélyezve", - "disabled": "Tiltva", - "reEnable": "Újra engedélyezés", "setExpiry": "Lejárat beállítása", - "disable": "Letiltás", - "admin": "Adminisztrátor", "updates": "Frissítések", "update": "Frissítés", "download": "Letöltés", @@ -134,7 +129,6 @@ "errorCreateProfile": "", "errorSetDefaultProfile": "", "errorLoadUsers": "", - "errorSaveSettings": "", "errorLoadSettings": "", "errorSetOmbiProfile": "", "errorLoadOmbiUsers": "", diff --git a/lang/admin/id-id.json b/lang/admin/id-id.json index e77932f..6161673 100644 --- a/lang/admin/id-id.json +++ b/lang/admin/id-id.json @@ -89,7 +89,6 @@ "errorCreateProfile": "Gagal membuat profil {n}", "errorSetDefaultProfile": "Gagal menyetel profil default.", "errorLoadUsers": "Gagal memuat pengguna.", - "errorSaveSettings": "Tidak dapat menyimpan pengaturan.", "errorLoadSettings": "Gagal memuat pengaturan.", "errorSetOmbiDefaults": "Gagal menyimpan default ombi.", "errorLoadOmbiUsers": "Gagal memuat pengguna ombi.", diff --git a/lang/admin/nl-nl.json b/lang/admin/nl-nl.json index ff4e71b..62b859a 100644 --- a/lang/admin/nl-nl.json +++ b/lang/admin/nl-nl.json @@ -75,9 +75,6 @@ "customizeMessages": "E-mails aanpassen", "inviteDuration": "Geldigheidsduur uitnodiging", "userExpiryDescription": "Een bepaalde tijd na elke aanmelding, wordt de account verwijderd/uitgeschakeld door jfa-go. Dit kan aangepast worden in de instellingen.", - "enabled": "Ingeschakeld", - "disabled": "Uitgeschakeld", - "admin": "Beheerder", "expiry": "Verloop", "userExpiry": "Gebruikersverloop", "extendExpiry": "Verleng verloop", @@ -87,8 +84,6 @@ "search": "Zoeken", "advancedSettings": "Geavanceerde instellingen", "inviteMonths": "Maanden", - "reEnable": "Opnieuw inschakelen", - "disable": "Uitschakelen", "conditionals": "Voorwaarden", "donate": "Doneer", "contactThrough": "Stuur bericht via:", @@ -129,7 +124,6 @@ "errorCreateProfile": "Aanmaken van profile {n} mislukt", "errorSetDefaultProfile": "Fout bij instellen van standaardprofiel.", "errorLoadUsers": "Laden van gebruikers mislukt.", - "errorSaveSettings": "Opslaan van instellingen mislukt.", "errorLoadSettings": "Laden van instellingen mislukt.", "errorSetOmbiDefaults": "Opslaan van ombi standaardinstellingen mislukt.", "errorLoadOmbiUsers": "Laden van ombi gebruikers mislukt.", diff --git a/lang/admin/pl-pl.json b/lang/admin/pl-pl.json index 054448d..e229017 100644 --- a/lang/admin/pl-pl.json +++ b/lang/admin/pl-pl.json @@ -22,12 +22,7 @@ "select": "", "name": "Imię", "date": "Data", - "enabled": "Włączone", - "disabled": "Wyłączone", - "reEnable": "", "setExpiry": "", - "disable": "Wyłączone", - "admin": "Admin", "updates": "Aktualizacje", "update": "Aktualizacja", "download": "Pobierz", @@ -136,7 +131,6 @@ "errorCreateProfile": "", "errorSetDefaultProfile": "", "errorLoadUsers": "", - "errorSaveSettings": "", "errorLoadSettings": "", "errorSetOmbiProfile": "", "errorLoadOmbiUsers": "", diff --git a/lang/admin/pt-br.json b/lang/admin/pt-br.json index a4017be..5b4149d 100644 --- a/lang/admin/pt-br.json +++ b/lang/admin/pt-br.json @@ -73,11 +73,8 @@ "reset": "Redefinir", "edit": "Editar", "customizeMessages": "Customizar Emails", - "disabled": "Desativado", "userExpiryDescription": "Após um determinado período de tempo de cada inscrição, o jfa-go apagará/desabilitará a conta. Você pode alterar essa opção nas configurações.", "inviteDuration": "Duração do Convite", - "enabled": "Habilitado", - "admin": "Admin", "expiry": "Expira", "userExpiry": "Vencimento do Usuário", "extendExpiry": "Extender o vencimento", @@ -87,8 +84,6 @@ "search": "Procurar", "advancedSettings": "Configurações Avançada", "inviteMonths": "Meses", - "reEnable": "Reativar", - "disable": "Desativar", "conditionals": "Condicionais", "donate": "Doar", "contactThrough": "Contato através:", @@ -129,7 +124,6 @@ "errorCreateProfile": "Falha ao criar perfil {n}", "errorSetDefaultProfile": "Falha ao definir o perfil padrão.", "errorLoadUsers": "Falha ao carregar usuários.", - "errorSaveSettings": "Não foi possível salvar as configurações.", "errorLoadSettings": "Falha ao carregar as configurações.", "errorSetOmbiDefaults": "Falha em armazenar os padrões ombi.", "errorLoadOmbiUsers": "Falha ao carregar usuários ombi.", diff --git a/lang/admin/sv-se.json b/lang/admin/sv-se.json index 2996d70..f16995f 100644 --- a/lang/admin/sv-se.json +++ b/lang/admin/sv-se.json @@ -73,10 +73,7 @@ "notifyEvent": "Meddela den:", "notifyInviteExpiry": "Vid utgång", "notifyUserCreation": "Vid användarskapande", - "disabled": "Inaktiverad", - "enabled": "Aktiverad", "inviteDuration": "Varaktighet för inbjudan", - "admin": "Admin", "expiry": "Löper ut", "userExpiry": "Användarutgång", "userExpiryDescription": "Efter en angiven tid efter varje registrering så tar jfa-go bort/inaktiverar kontot. Du kan ändra detta beteende i inställningarna.", @@ -100,7 +97,6 @@ "errorCreateProfile": "Det gick inte att skapa profilen {n}", "errorSetDefaultProfile": "Det gick inte att ange standardprofil.", "errorLoadUsers": "Det gick inte att läsa in användare.", - "errorSaveSettings": "Det gick inte att spara inställningarna.", "errorLoadSettings": "Det gick inte att läsa in inställningarna.", "errorSetOmbiDefaults": "Det gick inte att lagra ombi-standardvärden.", "errorLoadOmbiUsers": "Det gick inte att ladda ombi-användare.", diff --git a/lang/admin/vi-vn.json b/lang/admin/vi-vn.json index c3d4930..358e1cb 100644 --- a/lang/admin/vi-vn.json +++ b/lang/admin/vi-vn.json @@ -22,12 +22,7 @@ "select": "Chọn", "name": "Tên", "date": "Ngày", - "enabled": "Mở", - "disabled": "Tắt", - "reEnable": "Mở lại", "setExpiry": "Đặt hết hạn", - "disable": "Tắt", - "admin": "Admin", "updates": "Cập nhật", "update": "Cập nhật", "download": "Tải về", @@ -135,7 +130,6 @@ "errorCreateProfile": "", "errorSetDefaultProfile": "", "errorLoadUsers": "", - "errorSaveSettings": "", "errorLoadSettings": "", "errorSetOmbiProfile": "", "errorLoadOmbiUsers": "", diff --git a/lang/admin/zh-hans.json b/lang/admin/zh-hans.json index 7460242..cbe051e 100644 --- a/lang/admin/zh-hans.json +++ b/lang/admin/zh-hans.json @@ -22,11 +22,6 @@ "select": "选择", "name": "名称", "date": "日期", - "enabled": "已启用", - "disabled": "已禁用", - "reEnable": "重新启用", - "disable": "禁用", - "admin": "管理员", "updates": "更新", "update": "更新", "download": "下载", @@ -137,7 +132,6 @@ "errorCreateProfile": "创建配置文件{n}失败", "errorSetDefaultProfile": "设置默认配置文件失败。", "errorLoadUsers": "加载用户列表失败。", - "errorSaveSettings": "无法保存设置。", "errorLoadSettings": "加载配置列表失败。", "errorSetOmbiDefaults": "存储Ombi默认值失败。", "errorLoadOmbiUsers": "加载ombi用户列表失败。", diff --git a/lang/admin/zh-hant.json b/lang/admin/zh-hant.json index b935390..c4d24d4 100644 --- a/lang/admin/zh-hant.json +++ b/lang/admin/zh-hant.json @@ -22,12 +22,7 @@ "select": "選擇", "name": "帳戶名稱", "date": "日期", - "enabled": "已啟用", - "disabled": "已禁用", - "reEnable": "重新啟用", "setExpiry": "設置到期時間", - "disable": "禁用", - "admin": "管理員", "updates": "更新", "update": "更新", "download": "下載", @@ -136,7 +131,6 @@ "errorCreateProfile": "無法創建設置文件 {n}", "errorSetDefaultProfile": "無法設置預設設置文件。", "errorLoadUsers": "無法讀取帳戶。", - "errorSaveSettings": "無法儲存設置。", "errorLoadSettings": "無法讀取設置。", "errorSetOmbiProfile": "無法儲存 ombi 設置文件。", "errorLoadOmbiUsers": "無法讀取 ombi 帳戶。", diff --git a/lang/common/da-dk.json b/lang/common/da-dk.json index 8928254..8a89fd6 100644 --- a/lang/common/da-dk.json +++ b/lang/common/da-dk.json @@ -26,12 +26,18 @@ "refresh": "Opdater", "required": "Påkrævet", "login": "Log på", - "logout": "Log ud" + "logout": "Log ud", + "admin": "Administrator", + "enabled": "Aktiveret", + "disabled": "Deaktiveret", + "reEnable": "Genaktiver", + "disable": "Deaktiver" }, "notifications": { "errorLoginBlank": "Brugernavnet og/eller adgangskoden blev efterladt tomme.", "errorConnection": "Kunne ikke oprette forbindelse til jfa-go.", "errorUnknown": "Ukendt fejl.", - "error401Unauthorized": "Adgang nægtet. Prøv at genindlæse siden." + "error401Unauthorized": "Adgang nægtet. Prøv at genindlæse siden.", + "errorSaveSettings": "Kunne ikke gemme indstillingerne." } } \ No newline at end of file diff --git a/lang/common/de-de.json b/lang/common/de-de.json index c5413a6..da17b61 100644 --- a/lang/common/de-de.json +++ b/lang/common/de-de.json @@ -26,12 +26,18 @@ "refresh": "Aktualisieren", "required": "Erforderlich", "login": "Anmelden", - "logout": "Abmelden" + "logout": "Abmelden", + "admin": "Admin", + "enabled": "Aktiviert", + "disabled": "Deaktiviert", + "reEnable": "Wieder aktivieren", + "disable": "Deaktivieren" }, "notifications": { "errorLoginBlank": "Der Benutzername und/oder das Passwort wurden nicht ausgefüllt.", "errorConnection": "Konnte keine Verbindung zu jfa-go herstellen.", "errorUnknown": "Unbekannter Fehler.", - "error401Unauthorized": "Unberechtigt. Versuch, die Seite zu aktualisieren." + "error401Unauthorized": "Unberechtigt. Versuch, die Seite zu aktualisieren.", + "errorSaveSettings": "Einstellungen konnten nicht gespeichert werden." } } \ No newline at end of file diff --git a/lang/common/el-gr.json b/lang/common/el-gr.json index b2e2cb4..33031b9 100644 --- a/lang/common/el-gr.json +++ b/lang/common/el-gr.json @@ -17,12 +17,18 @@ "time12h": "12 Ώρες", "theme": "Θέμα", "login": "Σύνδεση", - "logout": "Αποσύνδεση" + "logout": "Αποσύνδεση", + "admin": "Διαχειριστής", + "enabled": "Ενεργοποιημένο", + "disabled": "Απενεργοποιημένο", + "reEnable": "Επανα-ενεργοποίηση", + "disable": "Απενεργοποίηση" }, "notifications": { "errorLoginBlank": "Το όνομα χρήστη και/ή ο κωδικός ήταν κενά.", "errorConnection": "Δεν μπόρεσε να συνδεθεί με το jfa-go.", "errorUnknown": "Άγνωστο σφάλμα.", - "error401Unauthorized": "Ανεξουσιοδότητος. Προσπαθήστε να κάνετε επαναφόρτωση την σελίδα." + "error401Unauthorized": "Ανεξουσιοδότητος. Προσπαθήστε να κάνετε επαναφόρτωση την σελίδα.", + "errorSaveSettings": "Αποτυχία αποθήκευσης ρυθμίσεων." } } \ No newline at end of file diff --git a/lang/common/en-gb.json b/lang/common/en-gb.json index bb1de9f..c4451e6 100644 --- a/lang/common/en-gb.json +++ b/lang/common/en-gb.json @@ -26,12 +26,18 @@ "refresh": "Refresh", "required": "Required", "login": "Login", - "logout": "Logout" + "logout": "Logout", + "admin": "Admin", + "enabled": "Enabled", + "disabled": "Disabled", + "reEnable": "Re-enable", + "disable": "Disable" }, "notifications": { "errorLoginBlank": "The username and/or password was left blank.", "errorConnection": "Couldn't connect to jfa-go.", "errorUnknown": "Unknown error.", - "error401Unauthorized": "Unauthorised. Try refreshing the page." + "error401Unauthorized": "Unauthorised. Try refreshing the page.", + "errorSaveSettings": "Couldn't save settings." } } \ No newline at end of file diff --git a/lang/common/en-us.json b/lang/common/en-us.json index ac80cc3..b8bb943 100644 --- a/lang/common/en-us.json +++ b/lang/common/en-us.json @@ -26,12 +26,19 @@ "refresh": "Refresh", "required": "Required", "login": "Login", - "logout": "Logout" + "logout": "Logout", + "admin": "Admin", + "enabled": "Enabled", + "disabled": "Disabled", + "reEnable": "Re-enable", + "disable": "Disable", + "contactMethods": "Contact Methods" }, "notifications": { "errorLoginBlank": "The username and/or password were left blank.", "errorConnection": "Couldn't connect to jfa-go.", "errorUnknown": "Unknown error.", - "error401Unauthorized": "Unauthorized. Try refreshing the page." + "error401Unauthorized": "Unauthorized. Try refreshing the page.", + "errorSaveSettings": "Couldn't save settings." } -} \ No newline at end of file +} diff --git a/lang/common/es-es.json b/lang/common/es-es.json index c20c3fe..fdc7cde 100644 --- a/lang/common/es-es.json +++ b/lang/common/es-es.json @@ -26,12 +26,18 @@ "refresh": "Refrescar", "required": "Requerido", "login": "Acceso", - "logout": "Cerrar sesión" + "logout": "Cerrar sesión", + "admin": "Administrador", + "enabled": "Activado", + "disabled": "Desactivado", + "reEnable": "Reactivar", + "disable": "Desactivar" }, "notifications": { "errorLoginBlank": "El nombre de usuario y/o la contraseña se dejaron en blanco.", "errorConnection": "No se pudo conectar a jfa-go.", "errorUnknown": "Error desconocido.", - "error401Unauthorized": "No autorizado. Intente actualizar la página." + "error401Unauthorized": "No autorizado. Intente actualizar la página.", + "errorSaveSettings": "No se pudo guardar la configuración." } } \ No newline at end of file diff --git a/lang/common/fr-fr.json b/lang/common/fr-fr.json index a47a19f..c97561d 100644 --- a/lang/common/fr-fr.json +++ b/lang/common/fr-fr.json @@ -26,12 +26,18 @@ "refresh": "Actualiser", "required": "Requis", "login": "S'identifier", - "logout": "Se déconnecter" + "logout": "Se déconnecter", + "admin": "Administrateur", + "enabled": "Activé", + "disabled": "Désactivé", + "reEnable": "Ré-activé", + "disable": "Désactivé" }, "notifications": { "errorLoginBlank": "Le nom d'utilisateur et/ou le mot de passe sont vides.", "errorConnection": "Impossible de se connecter à jfa-go.", "errorUnknown": "Erreur inconnue.", - "error401Unauthorized": "Non autorisé. Essayez d'actualiser la page." + "error401Unauthorized": "Non autorisé. Essayez d'actualiser la page.", + "errorSaveSettings": "Impossible d'enregistrer les paramètres." } } \ No newline at end of file diff --git a/lang/common/hu-hu.json b/lang/common/hu-hu.json index 7758357..0c934a4 100644 --- a/lang/common/hu-hu.json +++ b/lang/common/hu-hu.json @@ -4,7 +4,12 @@ }, "strings": { "login": "Belépés", - "logout": "Kijelentkezés" + "logout": "Kijelentkezés", + "admin": "Adminisztrátor", + "enabled": "Engedélyezve", + "disabled": "Tiltva", + "reEnable": "Újra engedélyezés", + "disable": "Letiltás" }, "notifications": {} } \ No newline at end of file diff --git a/lang/common/id-id.json b/lang/common/id-id.json index 71a1691..8c5f511 100644 --- a/lang/common/id-id.json +++ b/lang/common/id-id.json @@ -23,6 +23,7 @@ "errorLoginBlank": "Nama pengguna dan / atau sandi kosong.", "errorConnection": "Tidak dapat terhubung ke jfa-go.", "errorUnknown": "Kesalahan yang tidak diketahui.", - "error401Unauthorized": "Tidak ter-otorisasi. Coba segarkan halaman." + "error401Unauthorized": "Tidak ter-otorisasi. Coba segarkan halaman.", + "errorSaveSettings": "Tidak dapat menyimpan pengaturan." } } \ No newline at end of file diff --git a/lang/common/nl-nl.json b/lang/common/nl-nl.json index 5e0e141..3ba8c08 100644 --- a/lang/common/nl-nl.json +++ b/lang/common/nl-nl.json @@ -26,12 +26,18 @@ "refresh": "Ververs", "required": "Verplicht", "login": "Inloggen", - "logout": "Uitloggen" + "logout": "Uitloggen", + "admin": "Beheerder", + "enabled": "Ingeschakeld", + "disabled": "Uitgeschakeld", + "reEnable": "Opnieuw inschakelen", + "disable": "Uitschakelen" }, "notifications": { "errorLoginBlank": "De gebruikersnaam en/of wachtwoord is leeg.", "errorConnection": "Kon geen verbinding maken met jfa-go.", "errorUnknown": "Onbekende fout.", - "error401Unauthorized": "Geen toegang. Probeer de pagina te vernieuwen." + "error401Unauthorized": "Geen toegang. Probeer de pagina te vernieuwen.", + "errorSaveSettings": "Opslaan van instellingen mislukt." } } \ No newline at end of file diff --git a/lang/common/pl-pl.json b/lang/common/pl-pl.json index 880f08e..530fda0 100644 --- a/lang/common/pl-pl.json +++ b/lang/common/pl-pl.json @@ -24,7 +24,11 @@ "contactDiscord": "Kontakt przez Discord", "theme": "Motyw", "refresh": "Odśwież", - "required": "Wymagane" + "required": "Wymagane", + "admin": "Admin", + "enabled": "Włączone", + "disabled": "Wyłączone", + "disable": "Wyłączone" }, "notifications": { "errorConnection": "Nie udało się połączyć z jfa-go.", diff --git a/lang/common/pt-br.json b/lang/common/pt-br.json index cc5ec2c..16a0bae 100644 --- a/lang/common/pt-br.json +++ b/lang/common/pt-br.json @@ -26,12 +26,18 @@ "refresh": "Atualizar", "required": "Requeridos", "login": "Login", - "logout": "Sair" + "logout": "Sair", + "admin": "Admin", + "enabled": "Habilitado", + "disabled": "Desativado", + "reEnable": "Reativar", + "disable": "Desativar" }, "notifications": { "errorLoginBlank": "O nome de usuário e/ou senha foram deixados em branco.", "errorConnection": "Não foi possível conectar ao jfa-go.", "errorUnknown": "Erro desconhecido.", - "error401Unauthorized": "Não autorizado. Tente atualizar a página." + "error401Unauthorized": "Não autorizado. Tente atualizar a página.", + "errorSaveSettings": "Não foi possível salvar as configurações." } } \ No newline at end of file diff --git a/lang/common/sv-se.json b/lang/common/sv-se.json index e1285d1..674198f 100644 --- a/lang/common/sv-se.json +++ b/lang/common/sv-se.json @@ -16,12 +16,16 @@ "time12h": "12 timmarsklocka", "theme": "Tema", "login": "Logga in", - "logout": "Logga ut" + "logout": "Logga ut", + "admin": "Admin", + "enabled": "Aktiverad", + "disabled": "Inaktiverad" }, "notifications": { "errorLoginBlank": "Användarnamnet och/eller lösenordet lämnades tomt.", "errorConnection": "Det gick inte att ansluta till jfa-go.", "errorUnknown": "Okänt fel.", - "error401Unauthorized": "Obehörig. Prova att uppdatera sidan." + "error401Unauthorized": "Obehörig. Prova att uppdatera sidan.", + "errorSaveSettings": "Det gick inte att spara inställningarna." } } \ No newline at end of file diff --git a/lang/common/vi-vn.json b/lang/common/vi-vn.json index 78959fe..6122823 100644 --- a/lang/common/vi-vn.json +++ b/lang/common/vi-vn.json @@ -4,7 +4,12 @@ }, "strings": { "login": "Đăng nhập", - "logout": "Đăng xuất" + "logout": "Đăng xuất", + "admin": "Admin", + "enabled": "Mở", + "disabled": "Tắt", + "reEnable": "Mở lại", + "disable": "Tắt" }, "notifications": { "errorConnection": "Không thể kết nối với jfa-go.", diff --git a/lang/common/zh-hans.json b/lang/common/zh-hans.json index fa2b4da..2f90602 100644 --- a/lang/common/zh-hans.json +++ b/lang/common/zh-hans.json @@ -26,12 +26,18 @@ "refresh": "刷新", "required": "必需的", "login": "登录", - "logout": "登出" + "logout": "登出", + "admin": "管理员", + "enabled": "已启用", + "disabled": "已禁用", + "reEnable": "重新启用", + "disable": "禁用" }, "notifications": { "errorLoginBlank": "用户名/密码留空。", "errorConnection": "无法连接到 jfa-go。", "errorUnknown": "未知错误。", - "error401Unauthorized": "无授权。尝试刷新页面。" + "error401Unauthorized": "无授权。尝试刷新页面。", + "errorSaveSettings": "无法保存设置。" } } \ No newline at end of file diff --git a/lang/common/zh-hant.json b/lang/common/zh-hant.json index f80852e..9d69d0d 100644 --- a/lang/common/zh-hant.json +++ b/lang/common/zh-hant.json @@ -26,12 +26,18 @@ "refresh": "重新整理", "required": "必填", "login": "登錄", - "logout": "登出" + "logout": "登出", + "admin": "管理員", + "enabled": "已啟用", + "disabled": "已禁用", + "reEnable": "重新啟用", + "disable": "禁用" }, "notifications": { "errorLoginBlank": "帳戶名稱和/或密碼留空。", "errorConnection": "無法連接到 jfa-go。", "errorUnknown": "未知的錯誤。", - "error401Unauthorized": "未經授權。嘗試重新整理頁面。" + "error401Unauthorized": "未經授權。嘗試重新整理頁面。", + "errorSaveSettings": "無法儲存設置。" } } \ No newline at end of file diff --git a/lang/form/en-us.json b/lang/form/en-us.json index 57b680c..43b2928 100644 --- a/lang/form/en-us.json +++ b/lang/form/en-us.json @@ -20,7 +20,7 @@ "sendPIN": "Send the PIN below to the bot, then come back here to link your account.", "sendPINDiscord": "Type {command} in {server_channel} on Discord, then send the PIN below.", "matrixEnterUser": "Enter your User ID, press submit, and a PIN will be sent to you. Enter it here to continue.", - "welcomeUser": "Welcome, {user}" + "welcomeUser": "Welcome, {user}!" }, "notifications": { "errorUserExists": "User already exists.", diff --git a/models.go b/models.go index 6ce0e84..136bcb0 100644 --- a/models.go +++ b/models.go @@ -376,6 +376,18 @@ type ReCaptchaResponseDTO struct { // MyDetailsDTO is sent to the user page to personalize it for the user. type MyDetailsDTO struct { - Id string `json:"id"` - Username string `json:"username"` + Id string `json:"id"` + Username string `json:"username"` + Expiry int64 `json:"expiry"` + Admin bool `json:"admin"` + Disabled bool `json:"disabled"` + Email *MyDetailsContactMethodsDTO `json:"email,omitempty"` + Discord *MyDetailsContactMethodsDTO `json:"discord,omitempty"` + Telegram *MyDetailsContactMethodsDTO `json:"telegram,omitempty"` + Matrix *MyDetailsContactMethodsDTO `json:"matrix,omitempty"` +} + +type MyDetailsContactMethodsDTO struct { + Value string `json:"value"` + Enabled bool `json:"enabled"` } diff --git a/router.go b/router.go index 261bd97..9e026e1 100644 --- a/router.go +++ b/router.go @@ -227,6 +227,8 @@ func (app *appContext) loadRoutes(router *gin.Engine) { if userPageEnabled { user.GET(p+"/details", app.MyDetails) + user.POST(p+"/contact", app.SetMyContactMethods) + user.POST(p+"/logout", app.LogoutUser) } } } diff --git a/scripts/langmover/login.json b/scripts/langmover/login.json index 433fbf8..7471db3 100644 --- a/scripts/langmover/login.json +++ b/scripts/langmover/login.json @@ -23,13 +23,19 @@ "theme": "common", "refresh": "common", "required": "common", - "login": "admin", - "logout": "admin" + "login": "common", + "logout": "common", + "admin": "common", + "enabled": "common", + "disabled": "common", + "reEnable": "common", + "disable": "common" }, "notifications": { - "errorLoginBlank": "admin", - "errorConnection": "admin", - "errorUnknown": "admin", - "error401Unauthorized": "admin" + "errorLoginBlank": "common", + "errorConnection": "common", + "errorUnknown": "common", + "error401Unauthorized": "common", + "errorSaveSettings": "admin" } } diff --git a/storage.go b/storage.go index 1626cb5..16d179c 100644 --- a/storage.go +++ b/storage.go @@ -144,15 +144,15 @@ func (st *Storage) loadLang(filesystems ...fs.FS) (err error) { if err != nil { return } - err = st.loadLangUser(filesystems...) + err = st.loadLangEmail(filesystems...) if err != nil { return } - err = st.loadLangPWR(filesystems...) + err = st.loadLangUser(filesystems...) if err != nil { return } - err = st.loadLangEmail(filesystems...) + err = st.loadLangPWR(filesystems...) if err != nil { return } @@ -437,6 +437,11 @@ func (st *Storage) loadLangUser(filesystems ...fs.FS) error { } st.lang.Common.patchCommonStrings(&lang.Strings, index) st.lang.Common.patchCommonNotifications(&lang.Notifications, index) + // turns out, a lot of email strings are useful on the user page. + emailLang := []langSection{st.lang.Email[index].WelcomeEmail, st.lang.Email[index].UserDisabled, st.lang.Email[index].UserExpired} + for _, v := range emailLang { + patchLang(&lang.Strings, &v) + } if fname != "en-us.json" { if lang.Meta.Fallback != "" { fallback, ok := st.lang.User[lang.Meta.Fallback] diff --git a/ts/admin.ts b/ts/admin.ts index a13bcb5..df65535 100644 --- a/ts/admin.ts +++ b/ts/admin.ts @@ -177,12 +177,6 @@ login.onLogin = () => { } } -login.login("", ""); +login.bindLogout(document.getElementById("logout-button")); -(document.getElementById('logout-button') as HTMLButtonElement).onclick = () => _post("/logout", null, (req: XMLHttpRequest): boolean => { - if (req.readyState == 4 && req.status == 200) { - window.token = ""; - location.reload(); - return false; - } -}); +login.login("", ""); diff --git a/ts/modules/login.ts b/ts/modules/login.ts index cb9a923..c9248c4 100644 --- a/ts/modules/login.ts +++ b/ts/modules/login.ts @@ -1,17 +1,17 @@ import { Modal } from "../modules/modal.js"; -import { toggleLoader } from "../modules/common.js"; +import { toggleLoader, _post } from "../modules/common.js"; export class Login { private _modal: Modal; private _form: HTMLFormElement; private _url: string; private _onLogin: (username: string, password: string) => void; + private _logoutButton: HTMLElement = null; constructor(modal: Modal, endpoint: string) { this._url = window.URLBase + endpoint; if (this._url[this._url.length-1] != '/') this._url += "/"; - this._url += "token/"; this._modal = modal; this._form = this._modal.asElement().querySelector(".form-login") as HTMLFormElement; @@ -29,6 +29,18 @@ export class Login { }; } + bindLogout = (button: HTMLElement) => { + this._logoutButton = button; + this._logoutButton.classList.add("unfocused"); + this._logoutButton.onclick = () => _post(this._url + "logout", null, (req: XMLHttpRequest): boolean => { + if (req.readyState == 4 && req.status == 200) { + window.token = ""; + location.reload(); + return false; + } + }); + }; + get onLogin() { return this._onLogin; } set onLogin(f: (username: string, password: string) => void) { this._onLogin = f; } @@ -36,7 +48,7 @@ export class Login { const req = new XMLHttpRequest(); req.responseType = 'json'; const refresh = (username == "" && password == ""); - req.open("GET", this._url + (refresh ? "refresh" : "login"), true); + req.open("GET", this._url + (refresh ? "token/refresh" : "token/login"), true); if (!refresh) { req.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password)); } @@ -46,6 +58,10 @@ export class Login { let errorMsg = window.lang.notif("errorConnection"); if (req.response) { errorMsg = req.response["error"]; + const langErrorMsg = window.lang.strings(errorMsg); + if (langErrorMsg) { + errorMsg = langErrorMsg; + } } if (!errorMsg) { errorMsg = window.lang.notif("errorUnknown"); @@ -62,7 +78,8 @@ export class Login { this._onLogin(username, password); } this._modal.close(); - document.getElementById("logout-button").classList.remove("unfocused"); + if (this._logoutButton != null) + this._logoutButton.classList.remove("unfocused"); } if (run) { run(+req.status); } } diff --git a/ts/user.ts b/ts/user.ts index fc0eed5..68af79c 100644 --- a/ts/user.ts +++ b/ts/user.ts @@ -30,21 +30,167 @@ window.modals = {} as Modals; window.notifications = new notificationBox(document.getElementById('notification-box') as HTMLDivElement, 5); var rootCard = document.getElementById("card-user"); +var contactCard = document.getElementById("card-contact"); -const login = new Login(window.modals.login as Modal, "/my/"); -login.onLogin = () => { - console.log("Logged in."); +interface MyDetailsContactMethod { + value: string; + enabled: boolean; +} + +interface MyDetails { + id: string; + username: string; + expiry: number; + admin: boolean; + disabled: boolean; + email?: MyDetailsContactMethod; + discord?: MyDetailsContactMethod; + telegram?: MyDetailsContactMethod; + matrix?: MyDetailsContactMethod; +} + +interface ContactDTO { + email?: boolean; + discord?: boolean; + telegram?: boolean; + matrix?: boolean; +} + +class ContactMethods { + private _card: HTMLElement; + private _buttons: { [name: string]: { element: HTMLElement, details: MyDetailsContactMethod } }; + + constructor (card: HTMLElement) { + this._card = card; + this._buttons = {}; + } + + clear = () => { + this._card.textContent = ""; + this._buttons = {}; + } + + append = (name: string, details: MyDetailsContactMethod, icon: string) => { + const row = document.createElement("div"); + row.classList.add("row", "flex-expand", "my-2"); + row.innerHTML = ` +
+ + + ${icon} + + + ${details.value} +
+
+ +
+ `; + + this._buttons[name] = { + element: row, + details: details + }; + + const button = row.querySelector(".user-contact-enabled-disabled") as HTMLButtonElement; + const checkbox = button.querySelector("input[type=checkbox]") as HTMLInputElement; + const setButtonAppearance = () => { + if (checkbox.checked) { + button.classList.add("~info"); + button.classList.remove("~neutral"); + } else { + button.classList.add("~neutral"); + button.classList.remove("~info"); + } + }; + const onPress = () => { + this._buttons[name].details.enabled = checkbox.checked; + setButtonAppearance(); + this._save(); + }; + + checkbox.onchange = onPress; + button.onclick = () => { + checkbox.checked = !checkbox.checked; + onPress(); + }; + + checkbox.checked = details.enabled; + setButtonAppearance(); + + this._card.appendChild(row); + }; + + private _save = () => { + let data: ContactDTO = {}; + for (let method of Object.keys(this._buttons)) { + data[method] = this._buttons[method].details.enabled; + } + + _post("/my/contact", data, (req: XMLHttpRequest) => { + if (req.readyState == 4) { + if (req.status != 200) { + window.notifications.customError("errorSetNotify", window.lang.notif("errorSaveSettings")); + document.dispatchEvent(new CustomEvent("details-reload")); + } + } + }); + }; +} + +var contactMethodList = new ContactMethods(contactCard); + +document.addEventListener("details-reload", () => { _get("/my/details", null, (req: XMLHttpRequest) => { if (req.readyState == 4) { if (req.status != 200) { window.notifications.customError("myDetailsError", req.response["error"]); return; } - window.jellyfinID = req.response["id"]; - window.username = req.response["username"]; - rootCard.querySelector(".heading").textContent = window.lang.strings("welcomeUser").replace("{user}", window.username); + const details: MyDetails = req.response as MyDetails; + window.jellyfinID = details.id; + window.username = details.username; + let innerHTML = ` + ${window.lang.strings("welcomeUser").replace("{user}", window.username)} + `; + if (details.admin) { + innerHTML += `${window.lang.strings("admin")}`; + } + if (details.disabled) { + innerHTML += `${window.lang.strings("disabled")}`; + } + + rootCard.querySelector(".heading").innerHTML = innerHTML; + + contactMethodList.clear(); + + const contactMethods = [ + ["email", ``], + ["discord", ``], + ["telegram", ``], + ["matrix", `[m]`] + ]; + + for (let method of contactMethods) { + if (method[0] in details) { + contactMethodList.append(method[0], details[method[0]], method[1]); + } + } } }); +}); + +const login = new Login(window.modals.login as Modal, "/my/"); +login.onLogin = () => { + console.log("Logged in."); + document.dispatchEvent(new CustomEvent("details-reload")); }; + + +login.bindLogout(document.getElementById("logout-button")); + login.login("", "");