1
0
mirror of https://github.com/hrfee/jfa-go.git synced 2024-12-22 09:00:10 +00:00

userpage: unlink accounts

This commit is contained in:
Harvey Tindall 2023-06-20 16:44:12 +01:00
parent d509abdd5c
commit 8e153cd92f
Signed by: hrfee
GPG Key ID: BBC65952848FB1A2
36 changed files with 93 additions and 47 deletions

View File

@ -449,3 +449,33 @@ func (app *appContext) MatrixCheckMyPIN(gc *gin.Context) {
delete(app.matrix.tokens, pin)
respondBool(200, true, gc)
}
// @Summary unlink the Discord account from your Jellyfin user. Always succeeds.
// @Produce json
// @Success 200 {object} boolResponse
// @Router /my/discord [delete]
// @Tags Users
func (app *appContext) UnlinkMyDiscord(gc *gin.Context) {
app.storage.DeleteDiscordKey(gc.GetString("jfId"))
respondBool(200, true, gc)
}
// @Summary unlink the Telegram account from your Jellyfin user. Always succeeds.
// @Produce json
// @Success 200 {object} boolResponse
// @Router /my/telegram [delete]
// @Tags Users
func (app *appContext) UnlinkMyTelegram(gc *gin.Context) {
app.storage.DeleteTelegramKey(gc.GetString("jfId"))
respondBool(200, true, gc)
}
// @Summary unlink the Matrix account from your Jellyfin user. Always succeeds.
// @Produce json
// @Success 200 {object} boolResponse
// @Router /my/matrix [delete]
// @Tags Users
func (app *appContext) UnlinkMyMatrix(gc *gin.Context) {
app.storage.DeleteMatrixKey(gc.GetString("jfId"))
respondBool(200, true, gc)
}

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "Send til",
"create": "Opret",
"apply": "Anvend",
"delete": "Slet",
"select": "Vælg",
"name": "Navn",
"date": "Dato",

View File

@ -15,7 +15,6 @@
"inviteSendToEmail": "Senden an",
"create": "Erstellen",
"apply": "Anwenden",
"delete": "Löschen",
"name": "Name",
"date": "Datum",
"lastActiveTime": "Zuletzt aktiv",

View File

@ -15,7 +15,6 @@
"inviteSendToEmail": "Αποστολή σε",
"create": "Δημιουργία",
"apply": "Εφαρμογή",
"delete": "Διαγραφή",
"name": "Όνομα",
"date": "Ημερομηνία",
"lastActiveTime": "Τελευταία Ενεργός",

View File

@ -69,7 +69,6 @@
"inviteInfiniteUsesWarning": "invites with infinite uses can be used abusively",
"inviteSendToEmail": "Send to",
"apply": "Apply",
"delete": "Delete",
"updates": "Updates",
"variables": "Variables",
"preview": "Preview",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "Send to",
"create": "Create",
"apply": "Apply",
"delete": "Delete",
"select": "Select",
"name": "Name",
"date": "Date",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "Enviar a",
"create": "Crear",
"apply": "Aplicar",
"delete": "Eliminar",
"name": "Nombre",
"date": "Fecha",
"updates": "Actualizaciones",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "Envoyer à",
"create": "Créer",
"apply": "Appliquer",
"delete": "Effacer",
"name": "Nom",
"date": "Date",
"lastActiveTime": "Dernière activité",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "Címzett",
"create": "Létrehozás",
"apply": "Alkalmaz",
"delete": "Törlés",
"select": "Kiválasztás",
"name": "Név",
"date": "Dátum",

View File

@ -15,7 +15,6 @@
"inviteSendToEmail": "Dikirim kepada",
"create": "Buat",
"apply": "Terapkan",
"delete": "Hapus",
"name": "Nama",
"date": "Tanggal",
"lastActiveTime": "Terakhir Aktif",

View File

@ -15,7 +15,6 @@
"inviteSendToEmail": "Stuur naar",
"create": "Aanmaken",
"apply": "Toepassen",
"delete": "Verwijderen",
"name": "Naam",
"date": "Datum",
"lastActiveTime": "Laatst actief",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "",
"create": "",
"apply": "",
"delete": "",
"select": "",
"name": "Imię",
"date": "Data",

View File

@ -15,7 +15,6 @@
"inviteSendToEmail": "Enviar para",
"create": "Criar",
"apply": "Aplicar",
"delete": "Deletar",
"name": "Nome",
"date": "Data",
"lastActiveTime": "Ativo pela última vez",

View File

@ -15,7 +15,6 @@
"inviteSendToEmail": "Skicka till",
"create": "Skapa",
"apply": "Tillämpa",
"delete": "Radera",
"name": "Namn",
"date": "Datum",
"lastActiveTime": "Senast aktiv",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "Gửi tới",
"create": "Tạo mới",
"apply": "Áp dụng",
"delete": "Xóa",
"select": "Chọn",
"name": "Tên",
"date": "Ngày",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "发送到",
"create": "创建",
"apply": "申请",
"delete": "删除",
"select": "选择",
"name": "名称",
"date": "日期",

View File

@ -17,7 +17,6 @@
"inviteSendToEmail": "發送到",
"create": "創建",
"apply": "應用",
"delete": "刪除",
"select": "選擇",
"name": "帳戶名稱",
"date": "日期",

View File

@ -34,7 +34,8 @@
"disable": "Deaktiver",
"expiry": "Udløb",
"add": "Tilføj",
"edit": "Rediger"
"edit": "Rediger",
"delete": "Slet"
},
"notifications": {
"errorLoginBlank": "Brugernavnet og/eller adgangskoden blev efterladt tomme.",

View File

@ -34,7 +34,8 @@
"disable": "Deaktivieren",
"expiry": "Ablaufdatum",
"add": "Hinzufügen",
"edit": "Bearbeiten"
"edit": "Bearbeiten",
"delete": "Löschen"
},
"notifications": {
"errorLoginBlank": "Der Benutzername und/oder das Passwort wurden nicht ausgefüllt.",

View File

@ -24,7 +24,8 @@
"reEnable": "Επανα-ενεργοποίηση",
"disable": "Απενεργοποίηση",
"expiry": "Λήξη",
"edit": "Επεξεργασία"
"edit": "Επεξεργασία",
"delete": "Διαγραφή"
},
"notifications": {
"errorLoginBlank": "Το όνομα χρήστη και/ή ο κωδικός ήταν κενά.",

View File

@ -34,7 +34,8 @@
"disable": "Disable",
"expiry": "Expiry",
"add": "Add",
"edit": "Edit"
"edit": "Edit",
"delete": "Delete"
},
"notifications": {
"errorLoginBlank": "The username and/or password was left blank.",

View File

@ -33,13 +33,12 @@
"reEnable": "Re-enable",
"disable": "Disable",
"contactMethods": "Contact Methods",
"addContactMethod": "Add Contact Method",
"editContactMethod": "Edit Contact Method",
"accountStatus": "Account Status",
"notSet": "Not set",
"expiry": "Expiry",
"add": "Add",
"edit": "Edit"
"edit": "Edit",
"delete": "Delete"
},
"notifications": {
"errorLoginBlank": "The username and/or password were left blank.",
@ -62,4 +61,4 @@
"plural": "{n} Days"
}
}
}
}

View File

@ -34,7 +34,8 @@
"disable": "Desactivar",
"expiry": "Expiración",
"add": "Agregar",
"edit": "Editar"
"edit": "Editar",
"delete": "Eliminar"
},
"notifications": {
"errorLoginBlank": "El nombre de usuario y/o la contraseña se dejaron en blanco.",

View File

@ -34,7 +34,8 @@
"disable": "Désactivé",
"expiry": "Expiration",
"add": "Ajouter",
"edit": "Éditer"
"edit": "Éditer",
"delete": "Effacer"
},
"notifications": {
"errorLoginBlank": "Le nom d'utilisateur et/ou le mot de passe sont vides.",

View File

@ -12,7 +12,8 @@
"disable": "Letiltás",
"expiry": "Lejárat",
"add": "Hozzáadás",
"edit": "Szerkesztés"
"edit": "Szerkesztés",
"delete": "Törlés"
},
"notifications": {},
"quantityStrings": {}

View File

@ -18,7 +18,8 @@
"theme": "Tema",
"login": "Masuk",
"logout": "Keluar",
"edit": "Edit"
"edit": "Edit",
"delete": "Hapus"
},
"notifications": {
"errorLoginBlank": "Nama pengguna dan / atau sandi kosong.",

View File

@ -34,7 +34,8 @@
"disable": "Uitschakelen",
"expiry": "Verloop",
"add": "Voeg toe",
"edit": "Bewerken"
"edit": "Bewerken",
"delete": "Verwijderen"
},
"notifications": {
"errorLoginBlank": "De gebruikersnaam en/of wachtwoord is leeg.",

View File

@ -34,7 +34,8 @@
"disable": "Desativar",
"expiry": "Expira",
"add": "Adicionar",
"edit": "Editar"
"edit": "Editar",
"delete": "Deletar"
},
"notifications": {
"errorLoginBlank": "O nome de usuário e/ou senha foram deixados em branco.",

View File

@ -21,7 +21,8 @@
"enabled": "Aktiverad",
"disabled": "Inaktiverad",
"expiry": "Löper ut",
"edit": "Redigera"
"edit": "Redigera",
"delete": "Radera"
},
"notifications": {
"errorLoginBlank": "Användarnamnet och/eller lösenordet lämnades tomt.",

View File

@ -12,7 +12,8 @@
"disable": "Tắt",
"expiry": "Hết hạn",
"add": "Thêm",
"edit": "Chỉnh sửa"
"edit": "Chỉnh sửa",
"delete": "Xóa"
},
"notifications": {
"errorConnection": "Không thể kết nối với jfa-go.",

View File

@ -34,7 +34,8 @@
"disable": "禁用",
"expiry": "到期",
"add": "添加",
"edit": "编辑"
"edit": "编辑",
"delete": "删除"
},
"notifications": {
"errorLoginBlank": "用户名/密码留空。",

View File

@ -34,7 +34,8 @@
"disable": "禁用",
"expiry": "到期",
"add": "添加",
"edit": "編輯"
"edit": "編輯",
"delete": "刪除"
},
"notifications": {
"errorLoginBlank": "帳戶名稱和/或密碼留空。",

View File

@ -61,4 +61,4 @@
"plural": "Must have at least {n} special characters"
}
}
}
}

View File

@ -237,6 +237,9 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
user.GET(p+"/telegram/verified/:pin", app.MyTelegramVerifiedInvite)
user.POST(p+"/matrix/user", app.MatrixSendMyPIN)
user.POST(p+"/matrix/verified/:userID/:pin", app.MatrixCheckMyPIN)
user.DELETE(p+"/discord", app.UnlinkMyDiscord)
user.DELETE(p+"/telegram", app.UnlinkMyTelegram)
user.DELETE(p+"/matrix", app.UnlinkMyMatrix)
}
}
}

View File

@ -36,8 +36,9 @@
"accountStatus": "common",
"notSet": "common",
"expiry": "common",
"add": "admin",
"edit": "admin"
"add": "common",
"edit": "common",
"delete": "admin"
},
"notifications": {
"errorLoginBlank": "common",

View File

@ -1,7 +1,7 @@
import { ThemeManager } from "./modules/theme.js";
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
import { Modal } from "./modules/modal.js";
import { _get, _post, notificationBox, whichAnimationEvent, toDateString, toggleLoader } from "./modules/common.js";
import { _get, _post, _delete, notificationBox, whichAnimationEvent, toDateString, toggleLoader } from "./modules/common.js";
import { Login } from "./modules/login.js";
import { Discord, Telegram, Matrix, ServiceConfiguration, MatrixConfiguration } from "./modules/account-linking.js";
@ -92,7 +92,7 @@ class ContactMethods {
this._buttons = {};
}
append = (name: string, details: MyDetailsContactMethod, icon: string, addEditFunc?: (add: boolean) => void) => {
append = (name: string, details: MyDetailsContactMethod, icon: string, addEditFunc?: (add: boolean) => void, required?: boolean) => {
const row = document.createElement("div");
row.classList.add("row", "flex-expand", "my-2");
let innerHTML = `
@ -118,6 +118,15 @@ class ContactMethods {
</button>
`;
}
if (!required && details.value != "") {
innerHTML += `
<button class="user-contact-delete button ~critical ml-2" alt="${window.lang.strings("delete")}" text="${window.lang.strings("delete")}">
&times;
</button>
`;
}
innerHTML += `
</div>
`;
@ -159,6 +168,14 @@ class ContactMethods {
const addEditButton = row.querySelector(".user-contact-edit") as HTMLButtonElement;
addEditButton.onclick = () => addEditFunc(details.value == "");
}
if (!required && details.value != "") {
const deleteButton = row.querySelector(".user-contact-delete") as HTMLButtonElement;
deleteButton.onclick = () => _delete("/my/" + name, null, (req: XMLHttpRequest) => {
if (req.readyState != 4) return;
window.location.reload();
});
}
this._content.appendChild(row);
};
@ -248,8 +265,6 @@ class ExpiryCard {
this._interval = window.setInterval(this._drawCountdown, 60*1000);
this._drawCountdown();
}
}
var expiryCard = new ExpiryCard(statusCard);
@ -359,16 +374,16 @@ document.addEventListener("details-reload", () => {
// Note the weird format of the functions for discord/telegram:
// "this" was being redefined within the onclick() method, so
// they had to be wrapped in an anonymous function.
const contactMethods: { name: string, icon: string, f: (add: boolean) => void }[] = [
{name: "email", icon: `<i class="ri-mail-fill ri-lg"></i>`, f: addEditEmail},
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: (add: boolean) => { discord.onclick(); }},
{name: "telegram", icon: `<i class="ri-telegram-fill ri-lg"></i>`, f: (add: boolean) => { telegram.onclick() }},
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: (add: boolean) => { matrix.show(); }}
const contactMethods: { name: string, icon: string, f: (add: boolean) => void, required: boolean }[] = [
{name: "email", icon: `<i class="ri-mail-fill ri-lg"></i>`, f: addEditEmail, required: true},
{name: "discord", icon: `<i class="ri-discord-fill ri-lg"></i>`, f: (add: boolean) => { discord.onclick(); }, required: window.discordRequired},
{name: "telegram", icon: `<i class="ri-telegram-fill ri-lg"></i>`, f: (add: boolean) => { telegram.onclick() }, required: window.telegramRequired},
{name: "matrix", icon: `<span class="font-bold">[m]</span>`, f: (add: boolean) => { matrix.show(); }, required: window.matrixRequired}
];
for (let method of contactMethods) {
if (method.name in details) {
contactMethodList.append(method.name, details[method.name], method.icon, method.f);
contactMethodList.append(method.name, details[method.name], method.icon, method.f, method.required);
}
}