Preliminary SASL UI
This commit is contained in:
parent
f8f692af05
commit
8a281bacd8
@ -56,6 +56,23 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="connect-row">
|
||||
<label for="connect:password">Password</label>
|
||||
<RevealPassword
|
||||
v-slot:default="slotProps"
|
||||
class="input-wrap password-container"
|
||||
>
|
||||
<input
|
||||
id="connect:password"
|
||||
v-model="defaults.password"
|
||||
class="input"
|
||||
:type="slotProps.isVisible ? 'text' : 'password'"
|
||||
placeholder="Server password (optional)"
|
||||
name="password"
|
||||
maxlength="300"
|
||||
/>
|
||||
</RevealPassword>
|
||||
</div>
|
||||
<div class="connect-row">
|
||||
<label></label>
|
||||
<div class="input-wrap">
|
||||
@ -117,19 +134,6 @@
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<div class="connect-row">
|
||||
<label for="connect:password">Password</label>
|
||||
<RevealPassword v-slot:default="slotProps" class="input-wrap password-container">
|
||||
<input
|
||||
id="connect:password"
|
||||
v-model="defaults.password"
|
||||
class="input"
|
||||
:type="slotProps.isVisible ? 'text' : 'password'"
|
||||
name="password"
|
||||
maxlength="300"
|
||||
/>
|
||||
</RevealPassword>
|
||||
</div>
|
||||
<div class="connect-row">
|
||||
<label for="connect:realname">Real name</label>
|
||||
<input
|
||||
@ -151,27 +155,162 @@
|
||||
:value="defaults.commands ? defaults.commands.join('\n') : ''"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="btn" :disabled="disabled ? true : false">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="connect-row">
|
||||
<label for="connect:channels">Channels</label>
|
||||
<input id="connect:channels" class="input" name="join" :value="defaults.join" />
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="btn" :disabled="disabled ? true : false">
|
||||
Connect
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<template v-if="$store.state.serverConfiguration.public">
|
||||
<template v-if="!config.displayNetwork">
|
||||
<div class="connect-row">
|
||||
<label></label>
|
||||
<div class="input-wrap">
|
||||
<label class="tls">
|
||||
<input v-model="displayPasswordField" type="checkbox" />
|
||||
I have a password
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="displayPasswordField" class="connect-row">
|
||||
<label for="connect:password">Password</label>
|
||||
<RevealPassword
|
||||
v-slot:default="slotProps"
|
||||
class="input-wrap password-container"
|
||||
>
|
||||
<input
|
||||
id="connect:password"
|
||||
v-model="defaults.password"
|
||||
class="input"
|
||||
:type="slotProps.isVisible ? 'text' : 'password'"
|
||||
placeholder="Server password (optional)"
|
||||
name="password"
|
||||
maxlength="300"
|
||||
/>
|
||||
</RevealPassword>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<h2 id="label-auth">Authentication</h2>
|
||||
<div class="connect-row connect-auth" role="group" aria-labelledby="label-auth">
|
||||
<label class="opt">
|
||||
<input
|
||||
:checked="!defaults.sasl"
|
||||
type="radio"
|
||||
name="sasl"
|
||||
value=""
|
||||
@change="setSaslAuth('')"
|
||||
/>
|
||||
No authentication
|
||||
</label>
|
||||
<label class="opt">
|
||||
<input
|
||||
:checked="defaults.sasl === 'plain'"
|
||||
type="radio"
|
||||
name="sasl"
|
||||
value="plain"
|
||||
@change="setSaslAuth('plain')"
|
||||
/>
|
||||
Username + password (SASL PLAIN)
|
||||
</label>
|
||||
<label
|
||||
v-if="!$store.state.serverConfiguration.public && defaults.tls"
|
||||
class="opt"
|
||||
>
|
||||
<input
|
||||
:checked="defaults.sasl === 'external'"
|
||||
type="radio"
|
||||
name="sasl"
|
||||
value="external"
|
||||
@change="setSaslAuth('external')"
|
||||
/>
|
||||
Client certificate (SASL EXTERNAL)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<template v-if="defaults.sasl === 'plain'">
|
||||
<div class="connect-row">
|
||||
<label for="connect:username">Account</label>
|
||||
<input
|
||||
id="connect:saslAccount"
|
||||
:value="defaults.saslAccount"
|
||||
class="input"
|
||||
name="saslAccount"
|
||||
maxlength="100"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="connect-row">
|
||||
<label for="connect:password">Password</label>
|
||||
<RevealPassword
|
||||
v-slot:default="slotProps"
|
||||
class="input-wrap password-container"
|
||||
>
|
||||
<input
|
||||
id="connect:saslPassword"
|
||||
:value="defaults.saslPassword"
|
||||
class="input"
|
||||
:type="slotProps.isVisible ? 'text' : 'password'"
|
||||
name="saslPassword"
|
||||
maxlength="300"
|
||||
required
|
||||
/>
|
||||
</RevealPassword>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else-if="defaults.sasl === 'external'" class="connect-sasl-external">
|
||||
<p>
|
||||
The Lounge automatically generates and manages the client certificate.
|
||||
</p>
|
||||
<p>
|
||||
On the IRC server, you will need to tell the services to attach the
|
||||
certificate fingerprint (certfp) to your account, for example:
|
||||
</p>
|
||||
<pre><code>/msg NickServ CERT ADD</code></pre>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn" :disabled="disabled ? true : false">
|
||||
<template v-if="defaults.uuid">Save network</template>
|
||||
<template v-else>Connect</template>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#connect .connect-auth {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#connect .connect-auth .opt {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#connect .connect-auth input {
|
||||
margin: 3px 10px 0 0;
|
||||
}
|
||||
|
||||
#connect .connect-sasl-external {
|
||||
padding: 10px;
|
||||
border-radius: 2px;
|
||||
background-color: #d9edf7;
|
||||
color: #31708f;
|
||||
}
|
||||
|
||||
#connect .connect-sasl-external pre {
|
||||
margin: 0;
|
||||
user-select: text;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import RevealPassword from "./RevealPassword.vue";
|
||||
import SidebarToggle from "./SidebarToggle.vue";
|
||||
@ -191,9 +330,13 @@ export default {
|
||||
return {
|
||||
config: this.$store.state.serverConfiguration,
|
||||
previousUsername: this.defaults.username,
|
||||
displayPasswordField: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
setSaslAuth(type) {
|
||||
this.defaults.sasl = type;
|
||||
},
|
||||
onNickChanged(event) {
|
||||
// Username input is not available when useHexIp is set
|
||||
if (!this.$refs.usernameInput) {
|
||||
|
@ -1826,8 +1826,8 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
|
||||
}
|
||||
|
||||
#connect .btn {
|
||||
margin-left: 25%;
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#settings .apple-push-unsupported,
|
||||
@ -2621,11 +2621,6 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#connect .btn {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#help .help-version-title {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
@ -238,6 +238,9 @@ Client.prototype.connect = function (args, isStartup = false) {
|
||||
nick: String(args.nick || ""),
|
||||
username: String(args.username || ""),
|
||||
realname: String(args.realname || ""),
|
||||
sasl: String(args.sasl || ""),
|
||||
saslAccount: String(args.saslAccount || ""),
|
||||
saslPassword: String(args.saslPassword || ""),
|
||||
commands: args.commands || [],
|
||||
channels: channels,
|
||||
ignoreList: args.ignoreList ? args.ignoreList : [],
|
||||
|
@ -35,6 +35,9 @@ function Network(attr) {
|
||||
commands: [],
|
||||
username: "",
|
||||
realname: "",
|
||||
sasl: "",
|
||||
saslAccount: "",
|
||||
saslPassword: "",
|
||||
channels: [],
|
||||
irc: null,
|
||||
serverOptions: {
|
||||
@ -82,11 +85,17 @@ Network.prototype.validate = function (client) {
|
||||
this.password = cleanString(this.password);
|
||||
this.host = cleanString(this.host).toLowerCase();
|
||||
this.name = cleanString(this.name);
|
||||
this.saslAccount = cleanString(this.saslAccount);
|
||||
this.saslPassword = cleanString(this.saslPassword);
|
||||
|
||||
if (!this.port) {
|
||||
this.port = this.tls ? 6697 : 6667;
|
||||
}
|
||||
|
||||
if (!["", "plain", "external"].includes(this.sasl)) {
|
||||
this.sasl = "";
|
||||
}
|
||||
|
||||
if (!this.tls) {
|
||||
ClientCertificate.remove(this.uuid);
|
||||
}
|
||||
@ -190,10 +199,18 @@ Network.prototype.setIrcFrameworkOptions = function (client) {
|
||||
|
||||
this.irc.options.client_certificate = this.tls ? ClientCertificate.get(this.uuid) : null;
|
||||
|
||||
if (this.irc.options.client_certificate && !this.irc.options.password) {
|
||||
this.irc.options.sasl_mechanism = "EXTERNAL";
|
||||
} else {
|
||||
if (!this.sasl) {
|
||||
delete this.irc.options.sasl_mechanism;
|
||||
delete this.irc.options.account;
|
||||
} else if (this.sasl === "external") {
|
||||
this.irc.options.sasl_mechanism = "EXTERNAL";
|
||||
this.irc.options.account = {};
|
||||
} else if (this.sasl === "plain") {
|
||||
delete this.irc.options.sasl_mechanism;
|
||||
this.irc.options.account = {
|
||||
account: this.saslAccount,
|
||||
password: this.saslPassword,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -241,6 +258,9 @@ Network.prototype.edit = function (client, args) {
|
||||
this.password = String(args.password || "");
|
||||
this.username = String(args.username || "");
|
||||
this.realname = String(args.realname || "");
|
||||
this.sasl = String(args.sasl || "");
|
||||
this.saslAccount = String(args.saslAccount || "");
|
||||
this.saslPassword = String(args.saslPassword || "");
|
||||
|
||||
// Split commands into an array
|
||||
this.commands = String(args.commands || "")
|
||||
@ -403,26 +423,24 @@ Network.prototype.quit = function (quitMessage) {
|
||||
};
|
||||
|
||||
Network.prototype.exportForEdit = function () {
|
||||
let fieldsToReturn;
|
||||
const fieldsToReturn = [
|
||||
"uuid",
|
||||
"name",
|
||||
"nick",
|
||||
"password",
|
||||
"username",
|
||||
"realname",
|
||||
"sasl",
|
||||
"saslAccount",
|
||||
"saslPassword",
|
||||
"commands",
|
||||
];
|
||||
|
||||
if (Helper.config.displayNetwork) {
|
||||
// Return fields required to edit a network
|
||||
fieldsToReturn = [
|
||||
"uuid",
|
||||
"nick",
|
||||
"name",
|
||||
"host",
|
||||
"port",
|
||||
"tls",
|
||||
"rejectUnauthorized",
|
||||
"password",
|
||||
"username",
|
||||
"realname",
|
||||
"commands",
|
||||
];
|
||||
} else {
|
||||
// Same fields as in getClientConfiguration when network is hidden
|
||||
fieldsToReturn = ["name", "nick", "username", "password", "realname"];
|
||||
fieldsToReturn.push("host");
|
||||
fieldsToReturn.push("port");
|
||||
fieldsToReturn.push("tls");
|
||||
fieldsToReturn.push("rejectUnauthorized");
|
||||
}
|
||||
|
||||
const data = _.pick(this, fieldsToReturn);
|
||||
@ -446,6 +464,9 @@ Network.prototype.export = function () {
|
||||
"password",
|
||||
"username",
|
||||
"realname",
|
||||
"sasl",
|
||||
"saslAccount",
|
||||
"saslPassword",
|
||||
"commands",
|
||||
"ignoreList",
|
||||
]);
|
||||
|
@ -738,6 +738,9 @@ function getClientConfiguration() {
|
||||
config.themes = themes.getAll();
|
||||
config.defaultTheme = Helper.config.theme;
|
||||
config.defaults.nick = Helper.getDefaultNick();
|
||||
config.defaults.sasl = "";
|
||||
config.defaults.saslAccount = "";
|
||||
config.defaults.saslPassword = "";
|
||||
|
||||
if (Uploader) {
|
||||
config.fileUploadMaxFileSize = Uploader.getMaxFileSize();
|
||||
|
@ -14,6 +14,9 @@ describe("Network", function () {
|
||||
uuid: "hello world",
|
||||
awayMessage: "I am away",
|
||||
name: "networkName",
|
||||
sasl: "plain",
|
||||
saslAccount: "testaccount",
|
||||
saslPassword: "testpassword",
|
||||
channels: [
|
||||
new Chan({name: "#thelounge", key: ""}),
|
||||
new Chan({name: "&foobar", key: ""}),
|
||||
@ -37,6 +40,9 @@ describe("Network", function () {
|
||||
password: "",
|
||||
username: "",
|
||||
realname: "",
|
||||
sasl: "plain",
|
||||
saslAccount: "testaccount",
|
||||
saslPassword: "testpassword",
|
||||
commands: [],
|
||||
nick: "chillin`",
|
||||
channels: [
|
||||
@ -121,6 +127,9 @@ describe("Network", function () {
|
||||
username: 1234,
|
||||
password: 4567,
|
||||
realname: 8901,
|
||||
sasl: "something",
|
||||
saslAccount: 1337,
|
||||
saslPassword: 1337,
|
||||
commands: "/command 1 2 3\r\n/ping HELLO\r\r\r\r/whois test\r\n\r\n",
|
||||
ip: "newIp",
|
||||
hostname: "newHostname",
|
||||
@ -144,6 +153,9 @@ describe("Network", function () {
|
||||
expect(network.username).to.equal("1234");
|
||||
expect(network.password).to.equal("4567");
|
||||
expect(network.realname).to.equal("8901");
|
||||
expect(network.sasl).to.equal("");
|
||||
expect(network.saslAccount).to.equal("1337");
|
||||
expect(network.saslPassword).to.equal("1337");
|
||||
expect(network.commands).to.deep.equal([
|
||||
"/command 1 2 3",
|
||||
"/ping HELLO",
|
||||
|
Loading…
Reference in New Issue
Block a user