Domain verification

icon from font awsome
This commit is contained in:
Mathium05
2026-07-25 16:48:49 -05:00
parent 6c5fff86ec
commit 4b6b35d9d1
6 changed files with 94 additions and 2 deletions
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 7.3.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="m56 200 31 31q9 9 22 9h22q13 0 22 9l30 30q9 9 9 22v38q0 13 9 22l14 14q9 10 9 22v19a32 32 0 1 0 64 0v-3q1-13 10-22l45-46q9-10 9-22v-35c0-18-14-32-32-32h-83q-12 0-22-9l-16-16q-6-7-7-16 2-21 23-23h35a23 23 0 0 0 16-38l-20-20a19 19 0 0 1 0-28l17-17a31 31 0 0 0 3-41h-10c-95 0-176 64-200 152m408 56q0-52-23-96-10 2-18 9l-14 14q-9 9-9 22v35c0 18 14 32 32 32h24l7-1zM0 256a256 256 0 1 1 512 0 256 256 0 1 1-512 0"/></svg>

After

Width:  |  Height:  |  Size: 636 B

+57 -1
View File
@@ -2501,9 +2501,11 @@ class Localuser {
};
}
async getConnections() {
return fetch(this.info.api + "/connections", {
const json = await fetch(this.info.api + "/connections", {
headers: this.headers,
}).then((r) => r.json() as Promise<{[key: string]: {enabled: boolean; icon_url?: string}}>);
json["domain"] = {enabled: true, icon_url: "/icons/domain.svg"};
return json;
}
gifProvideors: {name: string; api_name: string}[] = [];
selectedGifProfidor?: {name: string; api_name: string};
@@ -2530,6 +2532,44 @@ class Localuser {
this.selectedGifProfidor =
this.gifProvideors.find((_) => _.api_name == prefs.gifProvidor) || this.gifProvideors[0];
}
domainVerification() {
const d = new Dialog(I18n.domain.title(), {noSubmit: true});
const text = d.options.addTextInput(I18n.domain.domain(), () => {});
d.options.addButtonInput("", I18n.submit(), async () => {
const dom = text.value;
d.options.removeAll();
console.log(dom);
const res = await fetch(this.info.api + "/users/@me/connections/domain/" + dom, {
method: "POST",
headers: this.headers,
});
if (res.ok) {
d.hide();
} else {
const json = (await res.json()) as {code?: number; message: string; proof: string};
if (json.code === 50187) {
const err = d.options.addErrorBox();
d.options.addMDText(new MarkDown(I18n.domain.dnsinst(dom, json.proof)));
d.options.addButtonInput("", I18n.submit(), async () => {
const dom = text.value;
const res = await fetch(this.info.api + "/users/@me/connections/domain/" + dom, {
method: "POST",
headers: this.headers,
});
if (res.ok) {
d.hide();
} else {
err.showError((await res.json()).message);
}
});
} else {
d.options.addText(json.message);
}
}
});
d.show();
}
async showusersettings() {
const prefs = await getPreferences();
const localSettings = getLocalSettings();
@@ -2695,6 +2735,7 @@ class Localuser {
serverConnections
.filter((_) => !actConMap.has(_))
.forEach((key) => {
if (key === "domain") return;
const connection = json[key];
const container = document.createElement("div");
@@ -2725,6 +2766,21 @@ class Localuser {
connectionContainer.appendChild(container);
});
//TODO enable this once domain verification is ready within Harmony
if (false as true) {
const container = document.createElement("div");
const span = document.createElement("span");
span.classList.add("conImg", "svgicon");
span.style.setProperty("mask", `url("/icons/domain.svg")`);
container.append(span);
container.addEventListener("click", async () => {
this.domainVerification();
});
connectionContainer.appendChild(container);
}
serverConnections
.filter((_) => actConMap.has(_))
.forEach((_) => {
+20
View File
@@ -263,6 +263,20 @@ class DateInput extends TextInput {
super.onChange();
}
}
class ErrorBox implements OptionsElement<void> {
div = document.createElement("div");
value!: void;
generateHTML(): HTMLElement {
this.div.classList = "";
return this.div;
}
showError(message: string) {
this.div.classList.add("errormsg");
this.div.textContent = message;
}
submit() {}
watchForChange() {}
}
class SettingsMDText implements OptionsElement<void> {
readonly onSubmit!: (str: string) => void;
value!: void;
@@ -1615,6 +1629,12 @@ class Options implements OptionsElement<void> {
this.generate(text);
return text;
}
addErrorBox() {
const box = new ErrorBox();
this.options.push(box);
this.generate(box);
return box;
}
addHR() {
const rule = new HorizontalRule();
this.options.push(rule);
+8 -1
View File
@@ -4120,6 +4120,7 @@ fieldset input[type="radio"] {
.SettingsButton {
width: auto;
border-radius: 3px 3px 1px 1px;
padding-right: 16px;
}
}
.reportMenu {
@@ -4363,6 +4364,12 @@ fieldset input[type="radio"] {
overflow: hidden;
flex-shrink: 0;
}
.errormsg {
background: #ff000038;
padding: 4px;
border-radius: 4px;
border: solid #ff54003b;
}
.permbox {
display: flex;
flex-wrap: wrap;
@@ -4434,7 +4441,7 @@ fieldset input[type="radio"] {
background: var(--primary-text);
}
.conProfImg {
margin-right: 4px;
margin-right: 12px;
}
.conProfDiv {
margin: 6px;
+3
View File
@@ -1167,6 +1167,9 @@ class User extends SnowFlake {
case "steam": {
return `https://steamcommunity.com/profiles/${con.external_id}`;
}
case "domain": {
return `https://${con.external_id}`;
}
}
}
note?: string;
+5
View File
@@ -988,6 +988,11 @@
"resolving": "resolving user",
"unknown": "@unknown-user"
},
"domain":{
"title":"Verify domain",
"domain":"Domain:",
"dnsinst":"1. Sign into your DNS provider\n\n2. Create a DNS record as follows:\n\nName:\n```\n_harmony.$1\n```\n\nType:\n```\nTXT\n```\n\nContent:\n```\n$2\n```\n\n-# It will likely take a few minutes for the DNS to propagate"
},
"vc": {
"joinForStream": "Join the voice channel to watch",
"joiningStream": "Joining stream...",