mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
🔒 feature(auth): LDAP Authentication (#2859)
* 🔧 chore: npm install passport-ldapauth * ✨ feat(auth): add ldap authentication support * chore: merge conflict fix --------- Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
parent
d5a7806e32
commit
a618266905
14 changed files with 303 additions and 3 deletions
|
@ -360,6 +360,14 @@ OPENID_REQUIRED_ROLE_PARAMETER_PATH=
|
|||
OPENID_BUTTON_LABEL=
|
||||
OPENID_IMAGE_URL=
|
||||
|
||||
# LDAP
|
||||
LDAP_URL=
|
||||
LDAP_BIND_DN=
|
||||
LDAP_BIND_CREDENTIALS=
|
||||
LDAP_USER_SEARCH_BASE=
|
||||
LDAP_SEARCH_FILTER=mail={{username}}
|
||||
LDAP_CA_CERT_PATH=
|
||||
|
||||
#========================#
|
||||
# Email Password Reset #
|
||||
#========================#
|
||||
|
|
|
@ -64,6 +64,11 @@ const userSchema = mongoose.Schema(
|
|||
unique: true,
|
||||
sparse: true,
|
||||
},
|
||||
ldapId: {
|
||||
type: String,
|
||||
unique: true,
|
||||
sparse: true,
|
||||
},
|
||||
githubId: {
|
||||
type: String,
|
||||
unique: true,
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
"passport-github2": "^0.1.12",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"passport-ldapauth": "^3.0.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"pino": "^8.12.1",
|
||||
"sharp": "^0.32.6",
|
||||
|
|
|
@ -15,7 +15,7 @@ const AppService = require('./services/AppService');
|
|||
const noIndex = require('./middleware/noIndex');
|
||||
const { isEnabled } = require('~/server/utils');
|
||||
const { logger } = require('~/config');
|
||||
|
||||
const { ldapLogin } = require('~/strategies');
|
||||
const routes = require('./routes');
|
||||
|
||||
const { PORT, HOST, ALLOW_SOCIAL_LOGIN } = process.env ?? {};
|
||||
|
@ -60,6 +60,11 @@ const startServer = async () => {
|
|||
passport.use(await jwtLogin());
|
||||
passport.use(passportLogin());
|
||||
|
||||
// LDAP Auth
|
||||
if (process.env.LDAP_URL && process.env.LDAP_BIND_DN && process.env.LDAP_USER_SEARCH_BASE) {
|
||||
passport.use(ldapLogin);
|
||||
}
|
||||
|
||||
if (isEnabled(ALLOW_SOCIAL_LOGIN)) {
|
||||
configureSocialLogins(app);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ const setHeaders = require('./setHeaders');
|
|||
const loginLimiter = require('./loginLimiter');
|
||||
const validateModel = require('./validateModel');
|
||||
const requireJwtAuth = require('./requireJwtAuth');
|
||||
const requireLdapAuth = require('./requireLdapAuth');
|
||||
const uploadLimiters = require('./uploadLimiters');
|
||||
const registerLimiter = require('./registerLimiter');
|
||||
const messageLimiters = require('./messageLimiters');
|
||||
|
@ -29,6 +30,7 @@ module.exports = {
|
|||
setHeaders,
|
||||
loginLimiter,
|
||||
requireJwtAuth,
|
||||
requireLdapAuth,
|
||||
registerLimiter,
|
||||
requireLocalAuth,
|
||||
validateEndpoint,
|
||||
|
|
22
api/server/middleware/requireLdapAuth.js
Normal file
22
api/server/middleware/requireLdapAuth.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const passport = require('passport');
|
||||
|
||||
const requireLdapAuth = (req, res, next) => {
|
||||
passport.authenticate('ldapauth', (err, user, info) => {
|
||||
if (err) {
|
||||
console.log({
|
||||
title: '(requireLdapAuth) Error at passport.authenticate',
|
||||
parameters: [{ name: 'error', value: err }],
|
||||
});
|
||||
return next(err);
|
||||
}
|
||||
if (!user) {
|
||||
console.log({
|
||||
title: '(requireLdapAuth) Error: No user',
|
||||
});
|
||||
return res.status(422).send(info);
|
||||
}
|
||||
req.user = user;
|
||||
next();
|
||||
})(req, res, next);
|
||||
};
|
||||
module.exports = requireLdapAuth;
|
|
@ -25,6 +25,11 @@ afterEach(() => {
|
|||
delete process.env.DOMAIN_SERVER;
|
||||
delete process.env.ALLOW_REGISTRATION;
|
||||
delete process.env.ALLOW_SOCIAL_LOGIN;
|
||||
delete process.env.LDAP_URL;
|
||||
delete process.env.LDAP_BIND_DN;
|
||||
delete process.env.LDAP_BIND_CREDENTIALS;
|
||||
delete process.env.LDAP_USER_SEARCH_BASE;
|
||||
delete process.env.LDAP_SEARCH_FILTER;
|
||||
});
|
||||
|
||||
//TODO: This works/passes locally but http request tests fail with 404 in CI. Need to figure out why.
|
||||
|
@ -50,6 +55,11 @@ describe.skip('GET /', () => {
|
|||
process.env.DOMAIN_SERVER = 'http://test-server.com';
|
||||
process.env.ALLOW_REGISTRATION = 'true';
|
||||
process.env.ALLOW_SOCIAL_LOGIN = 'true';
|
||||
process.env.LDAP_URL = 'Test LDAP URL';
|
||||
process.env.LDAP_BIND_DN = 'Test LDAP Bind DN';
|
||||
process.env.LDAP_BIND_CREDENTIALS = 'Test LDAP Bind Credentials';
|
||||
process.env.LDAP_USER_SEARCH_BASE = 'Test LDAP User Search Base';
|
||||
process.env.LDAP_SEARCH_FILTER = 'Test LDAP Search Filter';
|
||||
|
||||
const response = await request(app).get('/');
|
||||
|
||||
|
@ -64,6 +74,7 @@ describe.skip('GET /', () => {
|
|||
openidLoginEnabled: true,
|
||||
openidLabel: 'Test OpenID',
|
||||
openidImageUrl: 'http://test-server.com',
|
||||
ldapLoginEnabled: true,
|
||||
serverDomain: 'http://test-server.com',
|
||||
emailLoginEnabled: 'true',
|
||||
registrationEnabled: 'true',
|
||||
|
|
|
@ -12,15 +12,24 @@ const {
|
|||
loginLimiter,
|
||||
registerLimiter,
|
||||
requireJwtAuth,
|
||||
requireLdapAuth,
|
||||
requireLocalAuth,
|
||||
validateRegistration,
|
||||
} = require('../middleware');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
const ldapAuth =
|
||||
!!process.env.LDAP_URL && !!process.env.LDAP_BIND_DN && !!process.env.LDAP_USER_SEARCH_BASE;
|
||||
//Local
|
||||
router.post('/logout', requireJwtAuth, logoutController);
|
||||
router.post('/login', loginLimiter, checkBan, requireLocalAuth, loginController);
|
||||
router.post(
|
||||
'/login',
|
||||
loginLimiter,
|
||||
checkBan,
|
||||
ldapAuth ? requireLdapAuth : requireLocalAuth,
|
||||
loginController,
|
||||
);
|
||||
router.post('/refresh', refreshController);
|
||||
router.post('/register', registerLimiter, checkBan, validateRegistration, registrationController);
|
||||
router.post('/requestPasswordReset', resetPasswordRequestController);
|
||||
|
|
|
@ -13,6 +13,8 @@ router.get('/', async function (req, res) {
|
|||
return today.getMonth() === 1 && today.getDate() === 11;
|
||||
};
|
||||
|
||||
const ldapLoginEnabled =
|
||||
!!process.env.LDAP_URL && !!process.env.LDAP_BIND_DN && !!process.env.LDAP_USER_SEARCH_BASE;
|
||||
try {
|
||||
/** @type {TStartupConfig} */
|
||||
const payload = {
|
||||
|
@ -30,9 +32,10 @@ router.get('/', async function (req, res) {
|
|||
!!process.env.OPENID_SESSION_SECRET,
|
||||
openidLabel: process.env.OPENID_BUTTON_LABEL || 'Continue with OpenID',
|
||||
openidImageUrl: process.env.OPENID_IMAGE_URL,
|
||||
ldapLoginEnabled,
|
||||
serverDomain: process.env.DOMAIN_SERVER || 'http://localhost:3080',
|
||||
emailLoginEnabled,
|
||||
registrationEnabled: isEnabled(process.env.ALLOW_REGISTRATION),
|
||||
registrationEnabled: !ldapLoginEnabled && isEnabled(process.env.ALLOW_REGISTRATION),
|
||||
socialLoginEnabled: isEnabled(process.env.ALLOW_SOCIAL_LOGIN),
|
||||
emailEnabled:
|
||||
(!!process.env.EMAIL_SERVICE || !!process.env.EMAIL_HOST) &&
|
||||
|
|
|
@ -5,6 +5,7 @@ const discordLogin = require('./discordStrategy');
|
|||
const facebookLogin = require('./facebookStrategy');
|
||||
const setupOpenId = require('./openidStrategy');
|
||||
const jwtLogin = require('./jwtStrategy');
|
||||
const ldapLogin = require('./ldapStrategy');
|
||||
|
||||
module.exports = {
|
||||
passportLogin,
|
||||
|
@ -14,4 +15,5 @@ module.exports = {
|
|||
jwtLogin,
|
||||
facebookLogin,
|
||||
setupOpenId,
|
||||
ldapLogin,
|
||||
};
|
||||
|
|
67
api/strategies/ldapStrategy.js
Normal file
67
api/strategies/ldapStrategy.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
const LdapStrategy = require('passport-ldapauth');
|
||||
const User = require('~/models/User');
|
||||
const fs = require('fs');
|
||||
|
||||
const ldapOptions = {
|
||||
server: {
|
||||
url: process.env.LDAP_URL,
|
||||
bindDN: process.env.LDAP_BIND_DN,
|
||||
bindCredentials: process.env.LDAP_BIND_CREDENTIALS,
|
||||
searchBase: process.env.LDAP_USER_SEARCH_BASE,
|
||||
searchFilter: process.env.LDAP_SEARCH_FILTER || 'mail={{username}}',
|
||||
searchAttributes: ['displayName', 'mail', 'uid', 'cn', 'name', 'commonname', 'givenName', 'sn'],
|
||||
...(process.env.LDAP_CA_CERT_PATH && {
|
||||
tlsOptions: { ca: [fs.readFileSync(process.env.LDAP_CA_CERT_PATH)] },
|
||||
}),
|
||||
},
|
||||
usernameField: 'email',
|
||||
passwordField: 'password',
|
||||
};
|
||||
|
||||
const ldapLogin = new LdapStrategy(ldapOptions, async (userinfo, done) => {
|
||||
if (!userinfo) {
|
||||
return done(null, false, { message: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
try {
|
||||
const firstName = userinfo.givenName;
|
||||
const familyName = userinfo.surname || userinfo.sn;
|
||||
const fullName =
|
||||
firstName && familyName
|
||||
? `${firstName} ${familyName}`
|
||||
: userinfo.cn ||
|
||||
userinfo.name ||
|
||||
userinfo.commonname ||
|
||||
userinfo.displayName ||
|
||||
userinfo.mail;
|
||||
|
||||
const username = userinfo.givenName || userinfo.mail;
|
||||
let user = await User.findOne({ email: userinfo.mail });
|
||||
if (user && user.provider !== 'ldap') {
|
||||
return done(null, false, { message: 'Invalid credentials' });
|
||||
}
|
||||
if (!user) {
|
||||
user = new User({
|
||||
provider: 'ldap',
|
||||
ldapId: userinfo.uid,
|
||||
username,
|
||||
email: userinfo.mail || '',
|
||||
emailVerified: true,
|
||||
name: fullName,
|
||||
});
|
||||
} else {
|
||||
user.provider = 'ldap';
|
||||
user.ldapId = userinfo.uid;
|
||||
user.username = username;
|
||||
user.name = fullName;
|
||||
}
|
||||
|
||||
await user.save();
|
||||
|
||||
done(null, user);
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ldapLogin;
|
|
@ -21,6 +21,7 @@ const mockStartupConfig = {
|
|||
openidLoginEnabled: true,
|
||||
openidLabel: 'Test OpenID',
|
||||
openidImageUrl: 'http://test-server.com',
|
||||
ldapLoginEnabled: false,
|
||||
registrationEnabled: true,
|
||||
emailLoginEnabled: true,
|
||||
socialLoginEnabled: true,
|
||||
|
|
163
package-lock.json
generated
163
package-lock.json
generated
|
@ -94,6 +94,7 @@
|
|||
"passport-github2": "^0.1.12",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"passport-ldapauth": "^3.0.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"pino": "^8.12.1",
|
||||
"sharp": "^0.32.6",
|
||||
|
@ -9992,6 +9993,14 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz",
|
||||
"integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA=="
|
||||
},
|
||||
"node_modules/@types/ldapjs": {
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-2.2.5.tgz",
|
||||
"integrity": "sha512-Lv/nD6QDCmcT+V1vaTRnEKE8UgOilVv5pHcQuzkU1LcRe4mbHHuUo/KHi0LKrpdHhQY8FJzryF38fcVdeUIrzg==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mdast": {
|
||||
"version": "3.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz",
|
||||
|
@ -11144,6 +11153,14 @@
|
|||
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/asn1": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
|
||||
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
|
||||
"dependencies": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1.js": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
|
||||
|
@ -11175,6 +11192,14 @@
|
|||
"util": "^0.12.5"
|
||||
}
|
||||
},
|
||||
"node_modules/assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "3.2.5",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
|
||||
|
@ -11506,6 +11531,17 @@
|
|||
"@babel/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/backoff": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
|
||||
"integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==",
|
||||
"dependencies": {
|
||||
"precond": "0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/bail": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
|
||||
|
@ -14719,6 +14755,14 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/extsprintf": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
|
||||
"integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
]
|
||||
},
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz",
|
||||
|
@ -19050,6 +19094,58 @@
|
|||
"langsmith": "dist/cli/main.cjs"
|
||||
}
|
||||
},
|
||||
"node_modules/ldap-filter": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz",
|
||||
"integrity": "sha512-/tFkx5WIn4HuO+6w9lsfxq4FN3O+fDZeO9Mek8dCD8rTUpqzRa766BOBO7BcGkn3X86m5+cBm1/2S/Shzz7gMg==",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/ldapauth-fork": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ldapauth-fork/-/ldapauth-fork-5.0.5.tgz",
|
||||
"integrity": "sha512-LWUk76+V4AOZbny/3HIPQtGPWZyA3SW2tRhsWIBi9imP22WJktKLHV1ofd8Jo/wY7Ve6vAT7FCI5mEn3blZTjw==",
|
||||
"dependencies": {
|
||||
"@types/ldapjs": "^2.2.2",
|
||||
"bcryptjs": "^2.4.0",
|
||||
"ldapjs": "^2.2.1",
|
||||
"lru-cache": "^7.10.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ldapauth-fork/node_modules/lru-cache": {
|
||||
"version": "7.18.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ldapjs": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.3.tgz",
|
||||
"integrity": "sha512-75QiiLJV/PQqtpH+HGls44dXweviFwQ6SiIK27EqzKQ5jU/7UFrl2E5nLdQ3IYRBzJ/AVFJI66u0MZ0uofKYwg==",
|
||||
"deprecated": "This package has been decomissioned. See https://github.com/ldapjs/node-ldapjs/blob/8ffd0bc9c149088a10ec4c1ec6a18450f76ad05d/README.md",
|
||||
"dependencies": {
|
||||
"abstract-logging": "^2.0.0",
|
||||
"asn1": "^0.2.4",
|
||||
"assert-plus": "^1.0.0",
|
||||
"backoff": "^2.5.0",
|
||||
"ldap-filter": "^0.3.3",
|
||||
"once": "^1.4.0",
|
||||
"vasync": "^2.2.0",
|
||||
"verror": "^1.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
|
@ -22159,6 +22255,18 @@
|
|||
"passport-strategy": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/passport-ldapauth": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/passport-ldapauth/-/passport-ldapauth-3.0.1.tgz",
|
||||
"integrity": "sha512-TRRx3BHi8GC8MfCT9wmghjde/EGeKjll7zqHRRfGRxXbLcaDce2OftbQrFG7/AWaeFhR6zpZHtBQ/IkINdLVjQ==",
|
||||
"dependencies": {
|
||||
"ldapauth-fork": "^5.0.1",
|
||||
"passport-strategy": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/passport-local": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
|
||||
|
@ -23383,6 +23491,14 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/precond": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
|
||||
"integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
|
@ -27773,6 +27889,53 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/vasync": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/vasync/-/vasync-2.2.1.tgz",
|
||||
"integrity": "sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"dependencies": {
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vasync/node_modules/core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
|
||||
},
|
||||
"node_modules/vasync/node_modules/verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
|
||||
"engines": [
|
||||
"node >=0.6.0"
|
||||
],
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/verror": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
|
||||
"integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
|
||||
"dependencies": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/verror/node_modules/core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
|
||||
},
|
||||
"node_modules/vfile": {
|
||||
"version": "5.3.7",
|
||||
"resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz",
|
||||
|
|
|
@ -271,6 +271,7 @@ export type TStartupConfig = {
|
|||
openidLoginEnabled: boolean;
|
||||
openidLabel: string;
|
||||
openidImageUrl: string;
|
||||
ldapLoginEnabled: boolean;
|
||||
serverDomain: string;
|
||||
emailLoginEnabled: boolean;
|
||||
registrationEnabled: boolean;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue