@lordbex/thelounge 4.4.3-blowfish → 4.5.0-blowfish-pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -7
- package/dist/defaults/config.js +31 -2
- package/dist/package.json +94 -91
- package/dist/server/client.js +188 -194
- package/dist/server/clientManager.js +75 -72
- package/dist/server/command-line/index.js +44 -43
- package/dist/server/command-line/install.js +37 -70
- package/dist/server/command-line/outdated.js +12 -17
- package/dist/server/command-line/start.js +25 -26
- package/dist/server/command-line/storage.js +26 -31
- package/dist/server/command-line/uninstall.js +16 -23
- package/dist/server/command-line/upgrade.js +20 -26
- package/dist/server/command-line/users/add.js +33 -40
- package/dist/server/command-line/users/edit.js +18 -24
- package/dist/server/command-line/users/index.js +12 -16
- package/dist/server/command-line/users/list.js +11 -39
- package/dist/server/command-line/users/remove.js +16 -22
- package/dist/server/command-line/users/reset.js +34 -35
- package/dist/server/command-line/utils.js +231 -87
- package/dist/server/config.js +61 -52
- package/dist/server/helper.js +29 -28
- package/dist/server/identification.js +39 -34
- package/dist/server/index.js +1 -3
- package/dist/server/log.js +19 -16
- package/dist/server/models/chan.js +36 -33
- package/dist/server/models/msg.js +15 -19
- package/dist/server/models/network.js +102 -104
- package/dist/server/models/prefix.js +4 -7
- package/dist/server/models/user.js +5 -10
- package/dist/server/path-helper.js +8 -0
- package/dist/server/plugins/auth/ldap.js +177 -112
- package/dist/server/plugins/auth/local.js +10 -15
- package/dist/server/plugins/auth.js +6 -35
- package/dist/server/plugins/changelog.js +30 -27
- package/dist/server/plugins/clientCertificate.js +33 -37
- package/dist/server/plugins/dev-server.js +15 -21
- package/dist/server/plugins/inputs/action.js +9 -14
- package/dist/server/plugins/inputs/away.js +1 -3
- package/dist/server/plugins/inputs/ban.js +9 -14
- package/dist/server/plugins/inputs/blow.js +9 -14
- package/dist/server/plugins/inputs/connect.js +5 -10
- package/dist/server/plugins/inputs/ctcp.js +7 -12
- package/dist/server/plugins/inputs/disconnect.js +1 -3
- package/dist/server/plugins/inputs/ignore.js +23 -29
- package/dist/server/plugins/inputs/ignorelist.js +12 -18
- package/dist/server/plugins/inputs/index.js +8 -34
- package/dist/server/plugins/inputs/invite.js +7 -12
- package/dist/server/plugins/inputs/kick.js +7 -12
- package/dist/server/plugins/inputs/kill.js +1 -3
- package/dist/server/plugins/inputs/list.js +1 -3
- package/dist/server/plugins/inputs/mode.js +10 -15
- package/dist/server/plugins/inputs/msg.js +13 -18
- package/dist/server/plugins/inputs/mute.js +9 -15
- package/dist/server/plugins/inputs/nick.js +9 -14
- package/dist/server/plugins/inputs/notice.js +5 -7
- package/dist/server/plugins/inputs/part.js +11 -16
- package/dist/server/plugins/inputs/quit.js +7 -13
- package/dist/server/plugins/inputs/rainbow.js +55 -0
- package/dist/server/plugins/inputs/raw.js +1 -3
- package/dist/server/plugins/inputs/rejoin.js +7 -12
- package/dist/server/plugins/inputs/topic.js +7 -12
- package/dist/server/plugins/inputs/whois.js +1 -3
- package/dist/server/plugins/irc-events/away.js +14 -20
- package/dist/server/plugins/irc-events/cap.js +16 -22
- package/dist/server/plugins/irc-events/chghost.js +14 -13
- package/dist/server/plugins/irc-events/connection.js +61 -63
- package/dist/server/plugins/irc-events/ctcp.js +22 -28
- package/dist/server/plugins/irc-events/error.js +20 -26
- package/dist/server/plugins/irc-events/help.js +7 -13
- package/dist/server/plugins/irc-events/info.js +7 -13
- package/dist/server/plugins/irc-events/invite.js +7 -13
- package/dist/server/plugins/irc-events/join.js +30 -27
- package/dist/server/plugins/irc-events/kick.js +21 -17
- package/dist/server/plugins/irc-events/link.js +122 -109
- package/dist/server/plugins/irc-events/list.js +23 -26
- package/dist/server/plugins/irc-events/message.js +46 -52
- package/dist/server/plugins/irc-events/mode.js +66 -63
- package/dist/server/plugins/irc-events/modelist.js +29 -35
- package/dist/server/plugins/irc-events/motd.js +10 -16
- package/dist/server/plugins/irc-events/names.js +3 -6
- package/dist/server/plugins/irc-events/nick.js +26 -23
- package/dist/server/plugins/irc-events/part.js +19 -15
- package/dist/server/plugins/irc-events/quit.js +17 -14
- package/dist/server/plugins/irc-events/sasl.js +9 -15
- package/dist/server/plugins/irc-events/spgroups.js +38 -0
- package/dist/server/plugins/irc-events/spjoin.js +52 -0
- package/dist/server/plugins/irc-events/topic.js +12 -18
- package/dist/server/plugins/irc-events/unhandled.js +12 -12
- package/dist/server/plugins/irc-events/welcome.js +7 -13
- package/dist/server/plugins/irc-events/whois.js +20 -24
- package/dist/server/plugins/massEventAggregator.js +214 -0
- package/dist/server/plugins/messageStorage/sqlite.js +322 -141
- package/dist/server/plugins/messageStorage/text.js +21 -26
- package/dist/server/plugins/packages/index.js +105 -74
- package/dist/server/plugins/packages/publicClient.js +7 -16
- package/dist/server/plugins/packages/themes.js +11 -16
- package/dist/server/plugins/storage.js +28 -33
- package/dist/server/plugins/sts.js +12 -17
- package/dist/server/plugins/uploader.js +40 -43
- package/dist/server/plugins/webpush.js +23 -51
- package/dist/server/server.js +318 -271
- package/dist/server/storageCleaner.js +29 -37
- package/dist/server/utils/fish.js +349 -389
- package/dist/shared/irc.js +3 -6
- package/dist/shared/linkify.js +7 -14
- package/dist/shared/types/chan.js +6 -9
- package/dist/shared/types/changelog.js +1 -2
- package/dist/shared/types/config.js +1 -2
- package/dist/shared/types/mention.js +1 -2
- package/dist/shared/types/msg.js +3 -5
- package/dist/shared/types/network.js +1 -2
- package/dist/shared/types/storage.js +1 -2
- package/dist/shared/types/user.js +1 -2
- package/index.js +14 -10
- package/package.json +94 -91
- package/public/css/style.css +9 -6
- package/public/css/style.css.map +1 -1
- package/public/fonts/font-awesome/fa-brands-400.ttf +0 -0
- package/public/fonts/font-awesome/fa-brands-400.woff2 +0 -0
- package/public/fonts/font-awesome/fa-duotone-900.ttf +0 -0
- package/public/fonts/font-awesome/fa-duotone-900.woff2 +0 -0
- package/public/fonts/font-awesome/fa-light-300.ttf +0 -0
- package/public/fonts/font-awesome/fa-light-300.woff2 +0 -0
- package/public/fonts/font-awesome/fa-regular-400.ttf +0 -0
- package/public/fonts/font-awesome/fa-regular-400.woff2 +0 -0
- package/public/fonts/font-awesome/fa-solid-900.ttf +0 -0
- package/public/fonts/font-awesome/fa-solid-900.woff2 +0 -0
- package/public/fonts/font-awesome/fa-thin-100.ttf +0 -0
- package/public/fonts/font-awesome/fa-thin-100.woff2 +0 -0
- package/public/fonts/font-awesome/fa-v4compatibility.ttf +0 -0
- package/public/fonts/font-awesome/fa-v4compatibility.woff2 +0 -0
- package/public/js/bundle.js +1 -1
- package/public/js/bundle.js.map +1 -1
- package/public/js/bundle.vendor.js +1 -1
- package/public/js/bundle.vendor.js.LICENSE.txt +24 -6
- package/public/js/bundle.vendor.js.map +1 -1
- package/public/js/loading-error-handlers.js +1 -1
- package/public/service-worker.js +1 -1
- package/public/themes/default.css +1 -1
- package/public/themes/morning.css +1 -1
- package/dist/webpack.config.js +0 -224
|
@@ -1,102 +1,153 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { Client, InvalidCredentialsError } from "ldapts";
|
|
2
|
+
import colors from "chalk";
|
|
3
|
+
import log from "../../log.js";
|
|
4
|
+
import Config from "../../config.js";
|
|
5
|
+
const CONNECTION_ERROR_CODES = new Set([
|
|
6
|
+
"ECONNREFUSED",
|
|
7
|
+
"ECONNRESET",
|
|
8
|
+
"ENOTFOUND",
|
|
9
|
+
"ETIMEDOUT",
|
|
10
|
+
"EHOSTUNREACH",
|
|
11
|
+
"EAI_AGAIN",
|
|
12
|
+
]);
|
|
13
|
+
function errorToString(err) {
|
|
14
|
+
if (err instanceof Error) {
|
|
15
|
+
return err.toString();
|
|
16
|
+
}
|
|
17
|
+
return String(err);
|
|
18
|
+
}
|
|
19
|
+
function isConnectionError(err) {
|
|
20
|
+
if (!err || typeof err !== "object") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const code = err.code;
|
|
24
|
+
if (code && CONNECTION_ERROR_CODES.has(code)) {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (typeof err.message === "string") {
|
|
28
|
+
const message = err.message;
|
|
29
|
+
for (const possibleCode of CONNECTION_ERROR_CODES) {
|
|
30
|
+
if (message.includes(possibleCode)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
async function safeUnbind(client) {
|
|
38
|
+
try {
|
|
39
|
+
await client.unbind();
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Ignore unbind errors
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function ldapAuthCommon(user, bindDN, password, callback) {
|
|
46
|
+
const config = Config.values;
|
|
47
|
+
const ldapclient = new Client({
|
|
13
48
|
url: config.ldap.url,
|
|
14
49
|
tlsOptions: config.ldap.tlsOptions,
|
|
15
50
|
});
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
51
|
+
let success = false;
|
|
52
|
+
let caughtError;
|
|
53
|
+
try {
|
|
54
|
+
await ldapclient.bind(bindDN, password);
|
|
55
|
+
success = true;
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
caughtError = err;
|
|
59
|
+
}
|
|
60
|
+
await safeUnbind(ldapclient);
|
|
61
|
+
if (success) {
|
|
62
|
+
callback(true);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (caughtError) {
|
|
66
|
+
if (isConnectionError(caughtError)) {
|
|
67
|
+
log.error(`Unable to connect to LDAP server: ${errorToString(caughtError)}`);
|
|
25
68
|
}
|
|
26
69
|
else {
|
|
27
|
-
|
|
70
|
+
log.error(`LDAP bind failed: ${errorToString(caughtError)}`);
|
|
28
71
|
}
|
|
29
|
-
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
log.error("LDAP bind failed");
|
|
75
|
+
}
|
|
76
|
+
callback(false);
|
|
30
77
|
}
|
|
31
78
|
function simpleLdapAuth(user, password, callback) {
|
|
32
79
|
if (!user || !password) {
|
|
33
80
|
return callback(false);
|
|
34
81
|
}
|
|
35
|
-
const config =
|
|
82
|
+
const config = Config.values;
|
|
36
83
|
const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1");
|
|
37
84
|
const bindDN = `${config.ldap.primaryKey}=${userDN},${config.ldap.baseDN || ""}`;
|
|
38
|
-
|
|
39
|
-
ldapAuthCommon(user, bindDN, password, callback);
|
|
85
|
+
log.info(`Auth against LDAP ${config.ldap.url} with provided bindDN ${bindDN}`);
|
|
86
|
+
void ldapAuthCommon(user, bindDN, password, callback);
|
|
40
87
|
}
|
|
41
88
|
/**
|
|
42
89
|
* LDAP auth using initial DN search (see config comment for ldap.searchDN)
|
|
43
90
|
*/
|
|
44
91
|
function advancedLdapAuth(user, password, callback) {
|
|
45
92
|
if (!user || !password) {
|
|
46
|
-
|
|
93
|
+
callback(false);
|
|
94
|
+
return;
|
|
47
95
|
}
|
|
48
|
-
const config =
|
|
96
|
+
const config = Config.values;
|
|
49
97
|
const userDN = user.replace(/([,\\/#+<>;"= ])/g, "\\$1");
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
98
|
+
void (async () => {
|
|
99
|
+
const ldapclient = new Client({
|
|
100
|
+
url: config.ldap.url,
|
|
101
|
+
tlsOptions: config.ldap.tlsOptions,
|
|
102
|
+
});
|
|
103
|
+
const base = config.ldap.searchDN.base;
|
|
104
|
+
const searchOptions = {
|
|
105
|
+
scope: config.ldap.searchDN.scope,
|
|
106
|
+
filter: `(&(${config.ldap.primaryKey}=${userDN})${config.ldap.searchDN.filter})`,
|
|
107
|
+
attributes: ["dn"],
|
|
108
|
+
};
|
|
109
|
+
try {
|
|
110
|
+
await ldapclient.bind(config.ldap.searchDN.rootDN, config.ldap.searchDN.rootPassword);
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
if (err instanceof InvalidCredentialsError) {
|
|
114
|
+
log.error("Invalid LDAP root credentials");
|
|
115
|
+
}
|
|
116
|
+
else if (isConnectionError(err)) {
|
|
117
|
+
log.error(`Unable to connect to LDAP server: ${errorToString(err)}`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
log.error(`LDAP error: ${errorToString(err)}`);
|
|
121
|
+
}
|
|
122
|
+
await safeUnbind(ldapclient);
|
|
68
123
|
callback(false);
|
|
69
124
|
return;
|
|
70
125
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
126
|
+
let searchResult;
|
|
127
|
+
try {
|
|
128
|
+
searchResult = await ldapclient.search(base, searchOptions);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
if (isConnectionError(err)) {
|
|
132
|
+
log.error(`Unable to connect to LDAP server: ${errorToString(err)}`);
|
|
77
133
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
callback(false);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
});
|
|
134
|
+
else {
|
|
135
|
+
log.warn(`LDAP User not found: ${userDN}`);
|
|
136
|
+
}
|
|
137
|
+
await safeUnbind(ldapclient);
|
|
138
|
+
callback(false);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
await safeUnbind(ldapclient);
|
|
142
|
+
if (!searchResult.searchEntries.length) {
|
|
143
|
+
log.warn(`LDAP Search did not find anything for: ${userDN}`);
|
|
144
|
+
callback(false);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const bindDN = searchResult.searchEntries[0].dn;
|
|
148
|
+
log.info(`Auth against LDAP ${config.ldap.url} with found bindDN ${bindDN}`);
|
|
149
|
+
void ldapAuthCommon(user, bindDN, password, callback);
|
|
150
|
+
})();
|
|
100
151
|
}
|
|
101
152
|
const ldapAuth = (manager, client, user, password, callback) => {
|
|
102
153
|
// TODO: Enable the use of starttls() as an alternative to ldaps
|
|
@@ -109,7 +160,7 @@ const ldapAuth = (manager, client, user, password, callback) => {
|
|
|
109
160
|
callback(valid);
|
|
110
161
|
}
|
|
111
162
|
let auth;
|
|
112
|
-
if ("baseDN" in
|
|
163
|
+
if ("baseDN" in Config.values.ldap) {
|
|
113
164
|
auth = simpleLdapAuth;
|
|
114
165
|
}
|
|
115
166
|
else {
|
|
@@ -122,54 +173,68 @@ const ldapAuth = (manager, client, user, password, callback) => {
|
|
|
122
173
|
* via the supplied callback function.
|
|
123
174
|
*/
|
|
124
175
|
function advancedLdapLoadUsers(users, callbackLoadUser) {
|
|
125
|
-
const config =
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
176
|
+
const config = Config.values;
|
|
177
|
+
void (async () => {
|
|
178
|
+
const ldapclient = new Client({
|
|
179
|
+
url: config.ldap.url,
|
|
180
|
+
tlsOptions: config.ldap.tlsOptions,
|
|
181
|
+
});
|
|
182
|
+
try {
|
|
183
|
+
await ldapclient.bind(config.ldap.searchDN.rootDN, config.ldap.searchDN.rootPassword);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
if (err instanceof InvalidCredentialsError) {
|
|
187
|
+
log.error("Invalid LDAP root credentials");
|
|
188
|
+
}
|
|
189
|
+
else if (isConnectionError(err)) {
|
|
190
|
+
log.error(`Unable to connect to LDAP server: ${errorToString(err)}`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
log.error(`LDAP error: ${errorToString(err)}`);
|
|
194
|
+
}
|
|
195
|
+
await safeUnbind(ldapclient);
|
|
196
|
+
return;
|
|
138
197
|
}
|
|
139
198
|
const remainingUsers = new Set(users);
|
|
199
|
+
const base = config.ldap.searchDN.base;
|
|
140
200
|
const searchOptions = {
|
|
141
201
|
scope: config.ldap.searchDN.scope,
|
|
142
202
|
filter: `${config.ldap.searchDN.filter}`,
|
|
143
203
|
attributes: [config.ldap.primaryKey],
|
|
144
204
|
paged: true,
|
|
145
205
|
};
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
206
|
+
let searchResult;
|
|
207
|
+
try {
|
|
208
|
+
searchResult = await ldapclient.search(base, searchOptions);
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
if (isConnectionError(err)) {
|
|
212
|
+
log.error(`Unable to connect to LDAP server: ${errorToString(err)}`);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
log.error(`LDAP search error: ${errorToString(err)}`);
|
|
216
|
+
}
|
|
217
|
+
await safeUnbind(ldapclient);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
await safeUnbind(ldapclient);
|
|
221
|
+
for (const entry of searchResult.searchEntries) {
|
|
222
|
+
const userAttr = entry[config.ldap.primaryKey];
|
|
223
|
+
const user = Array.isArray(userAttr) ? userAttr[0] : userAttr;
|
|
224
|
+
const userStr = typeof user === "string" ? user : String(user);
|
|
225
|
+
if (remainingUsers.has(userStr)) {
|
|
226
|
+
remainingUsers.delete(userStr);
|
|
227
|
+
callbackLoadUser(userStr);
|
|
150
228
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
remainingUsers.delete(user);
|
|
155
|
-
callbackLoadUser(user);
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
res.on("error", function (err3) {
|
|
159
|
-
log_1.default.error(`LDAP error: ${err3.toString()}`);
|
|
160
|
-
});
|
|
161
|
-
res.on("end", function () {
|
|
162
|
-
remainingUsers.forEach((user) => {
|
|
163
|
-
log_1.default.warn(`No account info in LDAP for ${chalk_1.default.bold(user)} but user config file exists`);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
229
|
+
}
|
|
230
|
+
remainingUsers.forEach((user) => {
|
|
231
|
+
log.warn(`No account info in LDAP for ${colors.bold(user)} but user config file exists`);
|
|
166
232
|
});
|
|
167
|
-
|
|
168
|
-
});
|
|
233
|
+
})();
|
|
169
234
|
return true;
|
|
170
235
|
}
|
|
171
236
|
function ldapLoadUsers(users, callbackLoadUser) {
|
|
172
|
-
if ("baseDN" in
|
|
237
|
+
if ("baseDN" in Config.values.ldap) {
|
|
173
238
|
// simple LDAP case can't test for user existence without access to the
|
|
174
239
|
// user's unhashed password, so indicate need to fallback to default
|
|
175
240
|
// loadUser behaviour by returning false
|
|
@@ -178,9 +243,9 @@ function ldapLoadUsers(users, callbackLoadUser) {
|
|
|
178
243
|
return advancedLdapLoadUsers(users, callbackLoadUser);
|
|
179
244
|
}
|
|
180
245
|
function isLdapEnabled() {
|
|
181
|
-
return !
|
|
246
|
+
return !Config.values.public && Config.values.ldap.enable;
|
|
182
247
|
}
|
|
183
|
-
|
|
248
|
+
export default {
|
|
184
249
|
moduleName: "ldap",
|
|
185
250
|
auth: ldapAuth,
|
|
186
251
|
isEnabled: isLdapEnabled,
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
7
|
-
const log_1 = __importDefault(require("../../log"));
|
|
8
|
-
const helper_1 = __importDefault(require("../../helper"));
|
|
1
|
+
import colors from "chalk";
|
|
2
|
+
import log from "../../log.js";
|
|
3
|
+
import Helper from "../../helper.js";
|
|
9
4
|
const localAuth = (_manager, client, user, password, callback) => {
|
|
10
5
|
// If no user is found, or if the client has not provided a password,
|
|
11
6
|
// fail the authentication straight away
|
|
@@ -14,27 +9,27 @@ const localAuth = (_manager, client, user, password, callback) => {
|
|
|
14
9
|
}
|
|
15
10
|
// If this user has no password set, fail the authentication
|
|
16
11
|
if (!client.config.password) {
|
|
17
|
-
|
|
12
|
+
log.error(`User ${colors.bold(user)} with no local password set tried to sign in. (Probably a LDAP user)`);
|
|
18
13
|
return callback(false);
|
|
19
14
|
}
|
|
20
|
-
|
|
15
|
+
Helper.password
|
|
21
16
|
.compare(password, client.config.password)
|
|
22
17
|
.then((matching) => {
|
|
23
|
-
if (matching &&
|
|
24
|
-
const hash =
|
|
18
|
+
if (matching && Helper.password.requiresUpdate(client.config.password)) {
|
|
19
|
+
const hash = Helper.password.hash(password);
|
|
25
20
|
client.setPassword(hash, (success) => {
|
|
26
21
|
if (success) {
|
|
27
|
-
|
|
22
|
+
log.info(`User ${colors.bold(client.name)} logged in and their hashed password has been updated to match new security requirements`);
|
|
28
23
|
}
|
|
29
24
|
});
|
|
30
25
|
}
|
|
31
26
|
callback(matching);
|
|
32
27
|
})
|
|
33
28
|
.catch((error) => {
|
|
34
|
-
|
|
29
|
+
log.error(`Error while checking users password. Error: ${error}`);
|
|
35
30
|
});
|
|
36
31
|
};
|
|
37
|
-
|
|
32
|
+
export default {
|
|
38
33
|
moduleName: "local",
|
|
39
34
|
auth: localAuth,
|
|
40
35
|
isEnabled: () => true,
|
|
@@ -1,36 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
30
|
-
const log_1 = __importDefault(require("../log"));
|
|
1
|
+
import colors from "chalk";
|
|
2
|
+
import log from "../log.js";
|
|
31
3
|
// The order defines priority: the first available plugin is used.
|
|
32
4
|
// Always keep 'local' auth plugin at the end of the list; it should always be enabled.
|
|
33
|
-
const plugins = [
|
|
5
|
+
const plugins = [import("./auth/ldap.js"), import("./auth/local.js")];
|
|
34
6
|
const toExport = {
|
|
35
7
|
moduleName: "<module with no name>",
|
|
36
8
|
// Must override: implements authentication mechanism
|
|
@@ -42,7 +14,6 @@ const toExport = {
|
|
|
42
14
|
loadUsers: () => false,
|
|
43
15
|
// local auth should always be enabled, but check here to verify
|
|
44
16
|
initialized: false,
|
|
45
|
-
// TODO: fix typing
|
|
46
17
|
async initialize() {
|
|
47
18
|
if (toExport.initialized) {
|
|
48
19
|
return;
|
|
@@ -59,12 +30,12 @@ const toExport = {
|
|
|
59
30
|
}
|
|
60
31
|
}
|
|
61
32
|
if (!toExport.initialized) {
|
|
62
|
-
|
|
33
|
+
log.error("None of the auth plugins is enabled");
|
|
63
34
|
}
|
|
64
35
|
},
|
|
65
36
|
};
|
|
66
37
|
function unimplemented(funcName) {
|
|
67
|
-
|
|
38
|
+
log.debug(`Auth module ${colors.bold(toExport.moduleName)} doesn't implement function ${colors.bold(funcName)}`);
|
|
68
39
|
}
|
|
69
40
|
// Default API implementations
|
|
70
|
-
|
|
41
|
+
export default toExport;
|
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const got_1 = __importDefault(require("got"));
|
|
7
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
-
const log_1 = __importDefault(require("../log"));
|
|
9
|
-
const package_json_1 = __importDefault(require("../../package.json"));
|
|
10
|
-
const config_1 = __importDefault(require("../config"));
|
|
1
|
+
import colors from "chalk";
|
|
2
|
+
import log from "../log.js";
|
|
3
|
+
import pkg from "../../package.json" with { type: "json" };
|
|
11
4
|
const TIME_TO_LIVE = 15 * 60 * 1000; // 15 minutes, in milliseconds
|
|
12
|
-
|
|
5
|
+
let updateCheckTimeout = null;
|
|
6
|
+
const changelog = {
|
|
13
7
|
isUpdateAvailable: false,
|
|
14
8
|
fetch,
|
|
15
9
|
checkForUpdates,
|
|
10
|
+
stopUpdateChecks,
|
|
16
11
|
};
|
|
12
|
+
export default changelog;
|
|
17
13
|
const versions = {
|
|
18
14
|
current: {
|
|
19
15
|
prerelease: false,
|
|
20
|
-
version: `v${
|
|
16
|
+
version: `v${pkg.version}`,
|
|
21
17
|
changelog: undefined,
|
|
22
18
|
url: "", // TODO: properly init
|
|
23
19
|
},
|
|
@@ -32,31 +28,32 @@ async function fetch() {
|
|
|
32
28
|
return versions;
|
|
33
29
|
}
|
|
34
30
|
try {
|
|
35
|
-
const
|
|
31
|
+
const fetchOptions = {
|
|
36
32
|
headers: {
|
|
37
33
|
Accept: "application/vnd.github.v3.html", // Request rendered markdown
|
|
38
|
-
"User-Agent":
|
|
34
|
+
"User-Agent": pkg.name + "; +" + pkg.repository.url, // Identify the client
|
|
39
35
|
},
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (response.
|
|
36
|
+
};
|
|
37
|
+
const response = await globalThis.fetch("https://api.github.com/repos/lordbex/thelounge/releases", fetchOptions);
|
|
38
|
+
if (response.status !== 200) {
|
|
43
39
|
return versions;
|
|
44
40
|
}
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
const body = await response.text();
|
|
42
|
+
updateVersions(body);
|
|
43
|
+
// Add the expiration date to the data to send to the client for later refresh
|
|
47
44
|
versions.expiresAt = time + TIME_TO_LIVE;
|
|
48
45
|
}
|
|
49
46
|
catch (error) {
|
|
50
47
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
51
|
-
|
|
48
|
+
log.error(`Failed to fetch changelog: ${error}`);
|
|
52
49
|
}
|
|
53
50
|
return versions;
|
|
54
51
|
}
|
|
55
|
-
function updateVersions(
|
|
52
|
+
function updateVersions(responseBody) {
|
|
56
53
|
let i;
|
|
57
54
|
let release;
|
|
58
55
|
let prerelease = false;
|
|
59
|
-
const body = JSON.parse(
|
|
56
|
+
const body = JSON.parse(responseBody);
|
|
60
57
|
// Find the current release among releases on GitHub
|
|
61
58
|
for (i = 0; i < body.length; i++) {
|
|
62
59
|
release = body[i];
|
|
@@ -72,7 +69,7 @@ function updateVersions(response) {
|
|
|
72
69
|
release = body[j];
|
|
73
70
|
// Find latest release or pre-release if current version is also a pre-release
|
|
74
71
|
if (!release.prerelease || release.prerelease === prerelease) {
|
|
75
|
-
|
|
72
|
+
changelog.isUpdateAvailable = true;
|
|
76
73
|
versions.latest = {
|
|
77
74
|
prerelease: release.prerelease,
|
|
78
75
|
version: release.tag_name,
|
|
@@ -86,18 +83,24 @@ function updateVersions(response) {
|
|
|
86
83
|
function checkForUpdates(manager) {
|
|
87
84
|
fetch()
|
|
88
85
|
.then((versionData) => {
|
|
89
|
-
if (!
|
|
86
|
+
if (!changelog.isUpdateAvailable) {
|
|
90
87
|
// Check for updates every 24 hours + random jitter of <3 hours
|
|
91
|
-
setTimeout(() => checkForUpdates(manager), 24 * 3600 * 1000 + Math.floor(Math.random() * 10000000));
|
|
88
|
+
updateCheckTimeout = setTimeout(() => checkForUpdates(manager), 24 * 3600 * 1000 + Math.floor(Math.random() * 10000000));
|
|
92
89
|
}
|
|
93
90
|
if (!versionData.latest) {
|
|
94
91
|
return;
|
|
95
92
|
}
|
|
96
|
-
|
|
93
|
+
log.info(`The Lounge ${colors.green(versionData.latest.version)} is available. Read more on GitHub: ${versionData.latest.url}`);
|
|
97
94
|
// Notify all connected clients about the new version
|
|
98
95
|
manager.clients.forEach((client) => client.emit("changelog:newversion"));
|
|
99
96
|
})
|
|
100
97
|
.catch((error) => {
|
|
101
|
-
|
|
98
|
+
log.error(`Failed to check for updates: ${error.message}`);
|
|
102
99
|
});
|
|
103
100
|
}
|
|
101
|
+
function stopUpdateChecks() {
|
|
102
|
+
if (updateCheckTimeout) {
|
|
103
|
+
clearTimeout(updateCheckTimeout);
|
|
104
|
+
updateCheckTimeout = null;
|
|
105
|
+
}
|
|
106
|
+
}
|