Start basic LDAP server groundwork
This commit is contained in:
parent
dbdaf775df
commit
226b90b7bf
3
.gitignore
vendored
3
.gitignore
vendored
@ -129,8 +129,7 @@ out/
|
|||||||
# JIRA plugin
|
# JIRA plugin
|
||||||
atlassian-ide-plugin.xml
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
# Cursive Clojure plugin
|
.idea*
|
||||||
.idea/replstate.xml
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
com_crashlytics_export_strings.xml
|
com_crashlytics_export_strings.xml
|
||||||
|
@ -32,6 +32,8 @@ const FlitterUnits = {
|
|||||||
* available to the middleware-routing-controller stack.
|
* available to the middleware-routing-controller stack.
|
||||||
*/
|
*/
|
||||||
'Upload' : require('flitter-upload/UploadUnit'),
|
'Upload' : require('flitter-upload/UploadUnit'),
|
||||||
|
'LDAPServer' : require('./app/unit/LDAPServerUnit'),
|
||||||
|
'LDAPRegistry' : require('./app/unit/LDAPRegistry'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Core Flitter Units
|
* The Core Flitter Units
|
||||||
|
122
app/assets/auth/forms.css
Normal file
122
app/assets/auth/forms.css
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
:root {
|
||||||
|
--input-padding-x: 1.5rem;
|
||||||
|
--input-padding-y: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login,
|
||||||
|
.image {
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-image {
|
||||||
|
background-image: url('https://source.unsplash.com/4812YdII6W0/2592x1728');
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-heading {
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-login {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
letter-spacing: 0.05rem;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
border-radius: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group>input,
|
||||||
|
.form-label-group>label {
|
||||||
|
padding: var(--input-padding-y) var(--input-padding-x);
|
||||||
|
height: auto;
|
||||||
|
border-radius: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group>label {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 0;
|
||||||
|
/* Override default `<label>` margin */
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #495057;
|
||||||
|
cursor: text;
|
||||||
|
/* Match the input under the label */
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: .25rem;
|
||||||
|
transition: all .1s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input::-webkit-input-placeholder {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input:-ms-input-placeholder {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input::-ms-input-placeholder {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input::-moz-placeholder {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input::placeholder {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input:not(:placeholder-shown) {
|
||||||
|
padding-top: calc(var(--input-padding-y) + var(--input-padding-y) * (2 / 3));
|
||||||
|
padding-bottom: calc(var(--input-padding-y) / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label-group input:not(:placeholder-shown)~label {
|
||||||
|
padding-top: calc(var(--input-padding-y) / 3);
|
||||||
|
padding-bottom: calc(var(--input-padding-y) / 3);
|
||||||
|
font-size: 12px;
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-error-message {
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-submit-button {
|
||||||
|
margin-top: 50px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback for Edge
|
||||||
|
-------------------------------------------------- */
|
||||||
|
|
||||||
|
@supports (-ms-ime-align: auto) {
|
||||||
|
.form-label-group>label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.form-label-group input::-ms-input-placeholder {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback for IE
|
||||||
|
-------------------------------------------------- */
|
||||||
|
|
||||||
|
@media all and (-ms-high-contrast: none),
|
||||||
|
(-ms-high-contrast: active) {
|
||||||
|
.form-label-group>label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.form-label-group input:-ms-input-placeholder {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
}
|
12
app/controllers/auth/Forms.controller.js
Normal file
12
app/controllers/auth/Forms.controller.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const FormController = require('flitter-auth/controllers/Forms')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handles views and processing for auth registration/login/logout/etc.
|
||||||
|
* Most handlers are inherited from the default flitter-auth/controllers/Forms
|
||||||
|
* controller, however you can override them here as you need.
|
||||||
|
*/
|
||||||
|
class Forms extends FormController {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = Forms
|
16
app/controllers/auth/KeyAction.controller.js
Normal file
16
app/controllers/auth/KeyAction.controller.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
const Controller = require('flitter-auth/controllers/KeyAction')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KeyAction Controller
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Provides handler methods for flitter-auth's key actions.
|
||||||
|
* Key actions allow your application to dynamically generate
|
||||||
|
* one-time links that call methods on controllers and (optionally)
|
||||||
|
* can even automatically sign in a user for the request, then log
|
||||||
|
* them out. e.g. a password reset link could use a key action.
|
||||||
|
*/
|
||||||
|
class KeyAction extends Controller {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = KeyAction
|
13
app/controllers/auth/Oauth2.controller.js
Normal file
13
app/controllers/auth/Oauth2.controller.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const Oauth2Controller = require('flitter-auth/controllers/Oauth2')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handles views, processing, and data retrieval for flitter-auth's
|
||||||
|
* built-in OAuth2 server, if it is enabled. Most handlers are inherited
|
||||||
|
* from flitter-auth/controllers/Oauth2, but you can override them here
|
||||||
|
* as you need.
|
||||||
|
*/
|
||||||
|
class Oauth2 extends Oauth2Controller {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = Oauth2
|
7
app/ldap/controllers/LDAPController.js
Normal file
7
app/ldap/controllers/LDAPController.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
|
||||||
|
class LDAPController extends Injectable {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = LDAPController
|
10
app/ldap/middleware/LDAPMiddleware.js
Normal file
10
app/ldap/middleware/LDAPMiddleware.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const { Injectable } = require('flitter-di')
|
||||||
|
const ImplementationError = require('libflitter/errors/ImplementationError')
|
||||||
|
|
||||||
|
class LDAPMiddleware extends Injectable {
|
||||||
|
async test(req, res, next) {
|
||||||
|
throw new ImplementationError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = LDAPMiddleware
|
27
app/ldap/routes/example.routes.js
Normal file
27
app/ldap/routes/example.routes.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const example_routes = {
|
||||||
|
|
||||||
|
prefix: 'dc=base',
|
||||||
|
|
||||||
|
middleware: [
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
search: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
bind: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
add: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
del: {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = example_routes
|
10
app/models/LDAPBase.js
Normal file
10
app/models/LDAPBase.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const { Model } = require('flitter-orm')
|
||||||
|
const ImplementationError = require('libflitter/errors/ImplementationError')
|
||||||
|
|
||||||
|
class LDAPBase extends Model {
|
||||||
|
toLDAP() {
|
||||||
|
throw new ImplementationError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = LDAPBase
|
25
app/models/auth/KeyAction.model.js
Normal file
25
app/models/auth/KeyAction.model.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
const Model = require('flitter-auth/model/KeyAction')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KeyAction Model
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Represents a single available key action. Key actions
|
||||||
|
* are one-time use links that directly call a method on
|
||||||
|
* a controller. These actions:
|
||||||
|
*
|
||||||
|
* - Can pass along context
|
||||||
|
* - Have expiration dates
|
||||||
|
* - Are single-use only
|
||||||
|
* - Can automatically log in a user during the request lifecycle
|
||||||
|
*
|
||||||
|
* You can generate these actions using the request.security.keyaction()
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* See: module:flitter-auth/SecurityContext~SecurityContext#keyaction
|
||||||
|
* See: module:flitter-auth/model/KeyAction~KeyAction
|
||||||
|
*/
|
||||||
|
class KeyAction extends Model {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = KeyAction
|
18
app/models/auth/User.model.js
Normal file
18
app/models/auth/User.model.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const AuthUser = require('flitter-auth/model/User')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Auth user model. This inherits fields and methods from the default
|
||||||
|
* flitter-auth/model/User model, however you can override methods and
|
||||||
|
* properties here as you need.
|
||||||
|
*/
|
||||||
|
class User extends AuthUser {
|
||||||
|
static get schema() {
|
||||||
|
return {...super.schema, ...{
|
||||||
|
// other schema fields here
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other members and methods here
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = User
|
@ -9,6 +9,7 @@
|
|||||||
* routes file.
|
* routes file.
|
||||||
*/
|
*/
|
||||||
const Middleware = [
|
const Middleware = [
|
||||||
|
"auth:Utility",
|
||||||
|
|
||||||
// 'MiddlewareName',
|
// 'MiddlewareName',
|
||||||
|
|
||||||
|
15
app/routing/middleware/auth/GuestOnly.middleware.js
Normal file
15
app/routing/middleware/auth/GuestOnly.middleware.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* GuestOnly Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Allows the request to proceed unless there's an authenticated user
|
||||||
|
* in the session. If so, redirect to the auth flow destination if one
|
||||||
|
* exists. If not, redirect to the default login route.
|
||||||
|
*/
|
||||||
|
const Middleware = require('flitter-auth/middleware/GuestOnly')
|
||||||
|
class GuestOnly extends Middleware {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = GuestOnly
|
12
app/routing/middleware/auth/KeyAction.middleware.js
Normal file
12
app/routing/middleware/auth/KeyAction.middleware.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const Middleware = require('flitter-auth/middleware/KeyAction')
|
||||||
|
|
||||||
|
/*
|
||||||
|
* KeyAction Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Middleware for processing key actions.
|
||||||
|
*/
|
||||||
|
class KeyAction extends Middleware {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = KeyAction
|
14
app/routing/middleware/auth/Oauth2TokenOnly.middleware.js
Normal file
14
app/routing/middleware/auth/Oauth2TokenOnly.middleware.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Oauth2TokenOnly Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Allows the request to proceed if a valid OAuth2 bearer token was
|
||||||
|
* provided. If not, return a JSON-encoded error message.
|
||||||
|
*/
|
||||||
|
const Middleware = require('flitter-auth/middleware/Oauth2TokenOnly')
|
||||||
|
class Oauth2TokenOnly extends Middleware {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Oauth2TokenOnly
|
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* ProviderRegistrationEnabled Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Redirects the user to the login page if the registration page for
|
||||||
|
* a particular auth provider is not enabled.
|
||||||
|
*/
|
||||||
|
const Middleware = require('flitter-auth/middleware/ProviderRegistrationEnabled')
|
||||||
|
class ProviderRegistrationEnabled extends Middleware {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ProviderRegistrationEnabled
|
15
app/routing/middleware/auth/ProviderRoute.middleware.js
Normal file
15
app/routing/middleware/auth/ProviderRoute.middleware.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Auth ProviderRoute Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Many auth routes specify the name of a particular auth provider to
|
||||||
|
* use. This middleware looks up the provider by that name and injects
|
||||||
|
* it into the request.
|
||||||
|
*/
|
||||||
|
const Middleware = require('flitter-auth/middleware/ProviderRoute')
|
||||||
|
class ProviderRoute extends Middleware {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ProviderRoute
|
15
app/routing/middleware/auth/UserOnly.middleware.js
Normal file
15
app/routing/middleware/auth/UserOnly.middleware.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* UserOnly Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Allows the request to proceed if there's an authenticated user
|
||||||
|
* in the session. Otherwise, redirects the user to the login page
|
||||||
|
* of the default provider.
|
||||||
|
*/
|
||||||
|
const Middleware = require('flitter-auth/middleware/UserOnly')
|
||||||
|
class UserOnly extends Middleware {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = UserOnly
|
15
app/routing/middleware/auth/Utility.middleware.js
Normal file
15
app/routing/middleware/auth/Utility.middleware.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Auth Utility Middleware
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* This should be applied globally. Ensures basic things about the
|
||||||
|
* request are true. For example, it provides the auth session data
|
||||||
|
* and handles auth flow.
|
||||||
|
*/
|
||||||
|
const Middleware = require('flitter-auth/middleware/Utility')
|
||||||
|
class Utility extends Middleware {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Utility
|
113
app/routing/routers/auth/forms.routes.js
Normal file
113
app/routing/routers/auth/forms.routes.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Auth Form Routes
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* The routes here pertain to auth forms like register/login etc.
|
||||||
|
* The general structure is as follows:
|
||||||
|
*
|
||||||
|
* /auth/{provider name}/{action}
|
||||||
|
|
||||||
|
* Individual providers may be interacted with individually, therefore:
|
||||||
|
*
|
||||||
|
* /auth/flitter/register
|
||||||
|
*
|
||||||
|
* You can omit the provider name to use the default provider:
|
||||||
|
*
|
||||||
|
* /auth/register
|
||||||
|
*/
|
||||||
|
const index = {
|
||||||
|
|
||||||
|
prefix: '/auth',
|
||||||
|
|
||||||
|
middleware: [
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
get: {
|
||||||
|
'/:provider/register': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'middleware::auth:ProviderRegistrationEnabled',
|
||||||
|
'controller::auth:Forms.registration_provider_get',
|
||||||
|
],
|
||||||
|
'/register': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'middleware::auth:ProviderRegistrationEnabled',
|
||||||
|
'controller::auth:Forms.registration_provider_get',
|
||||||
|
],
|
||||||
|
|
||||||
|
'/:provider/login': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'controller::auth:Forms.login_provider_get',
|
||||||
|
],
|
||||||
|
'/login': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'controller::auth:Forms.login_provider_get',
|
||||||
|
],
|
||||||
|
|
||||||
|
'/:provider/logout': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:UserOnly',
|
||||||
|
'controller::auth:Forms.logout_provider_clean_session',
|
||||||
|
|
||||||
|
// Note, this separation is between when the auth action has happened properly
|
||||||
|
// and before the user is allowed to continue. You can use it to add your own
|
||||||
|
// custom middleware for auth flow handling.
|
||||||
|
|
||||||
|
'controller::auth:Forms.logout_provider_present_success',
|
||||||
|
],
|
||||||
|
'/logout': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:UserOnly',
|
||||||
|
'controller::auth:Forms.logout_provider_clean_session',
|
||||||
|
'controller::auth:Forms.logout_provider_present_success',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
post: {
|
||||||
|
'/:provider/register': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'middleware::auth:ProviderRegistrationEnabled',
|
||||||
|
'controller::auth:Forms.registration_provider_create_user',
|
||||||
|
'controller::auth:Forms.registration_provider_present_user_created',
|
||||||
|
],
|
||||||
|
'/register': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'middleware::auth:ProviderRegistrationEnabled',
|
||||||
|
'controller::auth:Forms.registration_provider_create_user',
|
||||||
|
'controller::auth:Forms.registration_provider_present_user_created',
|
||||||
|
],
|
||||||
|
|
||||||
|
'/:provider/login': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'controller::auth:Forms.login_provider_authenticate_user',
|
||||||
|
'controller::auth:Forms.login_provider_present_success',
|
||||||
|
],
|
||||||
|
'/login': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:GuestOnly',
|
||||||
|
'controller::auth:Forms.login_provider_authenticate_user',
|
||||||
|
'controller::auth:Forms.login_provider_present_success',
|
||||||
|
],
|
||||||
|
|
||||||
|
'/:provider/logout': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:UserOnly',
|
||||||
|
'controller::auth:Forms.logout_provider_clean_session',
|
||||||
|
'controller::auth:Forms.logout_provider_present_success',
|
||||||
|
],
|
||||||
|
'/logout': [
|
||||||
|
'middleware::auth:ProviderRoute',
|
||||||
|
'middleware::auth:UserOnly',
|
||||||
|
'controller::auth:Forms.logout_provider_clean_session',
|
||||||
|
'controller::auth:Forms.logout_provider_present_success',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = index
|
16
app/routing/routers/auth/keyaction.routes.js
Normal file
16
app/routing/routers/auth/keyaction.routes.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
module.exports = exports = {
|
||||||
|
prefix: '/auth/action', // This is assumed by flitter-auth. Don't change it.
|
||||||
|
middleware: [],
|
||||||
|
get: {
|
||||||
|
'/:key': [
|
||||||
|
'middleware::auth:KeyAction',
|
||||||
|
'controller::auth:KeyAction.handle',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
post: {
|
||||||
|
'/:key': [
|
||||||
|
'middleware::auth:KeyAction',
|
||||||
|
'controller::auth:KeyAction.handle',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
46
app/routing/routers/auth/oauth2.routes.js
Normal file
46
app/routing/routers/auth/oauth2.routes.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* oauth2 Routes
|
||||||
|
* -------------------------------------------------------------
|
||||||
|
* Routes pertaining to the flitter-auth OAuth2 server implementation.
|
||||||
|
*/
|
||||||
|
const oauth2 = {
|
||||||
|
|
||||||
|
// Route prefix for all below routes
|
||||||
|
prefix: '/auth/service/oauth2/',
|
||||||
|
|
||||||
|
middleware: [
|
||||||
|
// Return 404 errors for these routes if the oauth2 server isn't enabled
|
||||||
|
['util:Config', {key: 'auth.servers.oauth2.enable'}],
|
||||||
|
],
|
||||||
|
|
||||||
|
get: {
|
||||||
|
// Show the authorization page
|
||||||
|
'/authorize': [
|
||||||
|
'middleware::auth:UserOnly',
|
||||||
|
'controller::auth:Oauth2.authorize_get',
|
||||||
|
],
|
||||||
|
|
||||||
|
// Built-in data endpoints
|
||||||
|
// Get the user info using a bearer token
|
||||||
|
'/data/user': [
|
||||||
|
['util:Config', {key: 'auth.servers.oauth2.build_in_endpoints.user.enable'}],
|
||||||
|
'middleware::auth:Oauth2TokenOnly',
|
||||||
|
'controller::auth:Oauth2.data_user_get',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
post: {
|
||||||
|
// Handle a successful authorization
|
||||||
|
'/authorize': [
|
||||||
|
'middleware::auth:UserOnly',
|
||||||
|
'controller::auth:Oauth2.authorize_post',
|
||||||
|
],
|
||||||
|
|
||||||
|
// Redeem an authorization code for an OAuth2 bearer token
|
||||||
|
'/redeem': [
|
||||||
|
'controller::auth:Oauth2.redeem_token',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = oauth2
|
21
app/unit/LDAPRegistry.js
Normal file
21
app/unit/LDAPRegistry.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const Unit = require('libflitter/Unit')
|
||||||
|
|
||||||
|
class LDAPRegistry extends Unit {
|
||||||
|
static get name() {
|
||||||
|
return 'ldap_registry'
|
||||||
|
}
|
||||||
|
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'output']
|
||||||
|
}
|
||||||
|
|
||||||
|
async go(app) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanup(app) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = LDAPRegistry
|
44
app/unit/LDAPServerUnit.js
Normal file
44
app/unit/LDAPServerUnit.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
const Unit = require('libflitter/Unit')
|
||||||
|
const LDAP = require('ldapjs')
|
||||||
|
|
||||||
|
class LDAPServerUnit extends Unit {
|
||||||
|
static get name() {
|
||||||
|
return 'ldap_server'
|
||||||
|
}
|
||||||
|
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'configs', 'express', 'output']
|
||||||
|
}
|
||||||
|
|
||||||
|
async go(app) {
|
||||||
|
this.config = this.configs.get('ldap:server')
|
||||||
|
const server_config = {}
|
||||||
|
|
||||||
|
// If Flitter is configured to use an SSL certificate,
|
||||||
|
// use it to enable LDAPS in the server.
|
||||||
|
if ( this.express.use_ssl() ) {
|
||||||
|
this.output.info('[LDAP Server] Using configured SSL certificate to enable LDAPS.')
|
||||||
|
server_config.certificate = await this.express.ssl_certificate()
|
||||||
|
server_config.key = await this.express.ssl_key()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.server = LDAP.createServer(server_config)
|
||||||
|
|
||||||
|
if ( this.config.max_connections ) {
|
||||||
|
this.server.maxConnections = this.config.max_connections
|
||||||
|
}
|
||||||
|
|
||||||
|
this.output.info(`[LDAP Server] Will listen on ${this.config.interface}:${this.config.port}`)
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
this.server.listen(this.config.port, this.config.interface, () => {
|
||||||
|
res()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanup(app) {
|
||||||
|
this.server.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = LDAPServerUnit
|
17
app/views/auth/auth_page.pug
Normal file
17
app/views/auth/auth_page.pug
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
html
|
||||||
|
head
|
||||||
|
title #{title} | #{_app.name}
|
||||||
|
meta(name='viewport' content='width=device-width initial-scale=1')
|
||||||
|
link(rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css')
|
||||||
|
link(rel='stylesheet' href='/assets/auth/forms.css')
|
||||||
|
body
|
||||||
|
.container-fluid
|
||||||
|
.row.no-gutter
|
||||||
|
.d-none.d-md-flex.col-md-6.col-lg-8.bg-image
|
||||||
|
.col-md-6.col-lg-4
|
||||||
|
.login.d-flex.align-items-center.py-5
|
||||||
|
.container
|
||||||
|
.row
|
||||||
|
.col-md-9.col-lg-8.mx-auto
|
||||||
|
block content
|
||||||
|
script(src='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css')
|
9
app/views/auth/form.pug
Normal file
9
app/views/auth/form.pug
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
extends ./auth_page
|
||||||
|
|
||||||
|
block content
|
||||||
|
h3.login-heading.mb-4 #{heading_text}
|
||||||
|
if errors
|
||||||
|
each error in errors
|
||||||
|
p.form-error-message #{error}
|
||||||
|
form(method='post' enctype='multipart/form-data')
|
||||||
|
block form
|
5
app/views/auth/form_page.pug
Normal file
5
app/views/auth/form_page.pug
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
extends ./auth_page
|
||||||
|
|
||||||
|
block content
|
||||||
|
h3.login-heading.mb-4 #{message}
|
||||||
|
a.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(href=button_link) #{button_text}
|
17
app/views/auth/login.pug
Normal file
17
app/views/auth/login.pug
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
extends ./form
|
||||||
|
|
||||||
|
block form
|
||||||
|
.form-label-group
|
||||||
|
input#inputUsername.form-control(type='text' name='username' value=(form_data ? form_data.username : '') required placeholder='Username' autofocus)
|
||||||
|
label(for='inputUsername') Username
|
||||||
|
.form-label-group
|
||||||
|
input#inputPassword.form-control(type='password' name='password' required placeholder='Password')
|
||||||
|
label(for='inputPassword') Password
|
||||||
|
button.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(type='submit') Login
|
||||||
|
|
||||||
|
if registration_enabled
|
||||||
|
.text-center
|
||||||
|
span.small Need an account?
|
||||||
|
a(href='./register') Register here.
|
||||||
|
.text-center
|
||||||
|
span.small(style="color: #999999;") Provider: #{provider_name}
|
12
app/views/auth/oauth2_authorize.pug
Normal file
12
app/views/auth/oauth2_authorize.pug
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
extends ./auth_page
|
||||||
|
|
||||||
|
block content
|
||||||
|
h3.login-heading.mb-4 Authorize #{client.name}?
|
||||||
|
h5.login-heading.mb-4 #{client.name} wants to access basic user information about your #{_app.name} account.
|
||||||
|
h5.login-heading.mb-4 After authorization, you may not be prompted again.
|
||||||
|
form(method='post' enctype='multipart/form-data')
|
||||||
|
input(type='hidden' name='redirect_uri' value=uri.toString())
|
||||||
|
input(type='hidden' name='client_id' value=client.clientID)
|
||||||
|
button.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(type='submit') Authorize #{client.name}
|
||||||
|
.text-center
|
||||||
|
span.small(style="color: #999999;") Will redirect to: #{uri.host}
|
16
app/views/auth/register.pug
Normal file
16
app/views/auth/register.pug
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
extends ./form
|
||||||
|
|
||||||
|
block form
|
||||||
|
.form-label-group
|
||||||
|
input#inputUsername.form-control(type='text' name='username' value=(form_data ? form_data.username : '') required placeholder='Username' autofocus)
|
||||||
|
label(for='inputUsername') Username
|
||||||
|
.form-label-group
|
||||||
|
input#inputPassword.form-control(type='password' name='password' required placeholder='Password')
|
||||||
|
label(for='inputPassword') Password
|
||||||
|
button.btn.btn-lg.btn-primary.btn-block.btn-login.text-uppercase.font-weight-bold.mb-2.form-submit-button(type='submit') Register
|
||||||
|
.text-center
|
||||||
|
span.small Already registered?
|
||||||
|
a(href='./login') Log-in here.
|
||||||
|
.text-center
|
||||||
|
span.small(style="color: #999999;") Provider: #{provider_name}
|
||||||
|
|
177
config/auth.config.js
Normal file
177
config/auth.config.js
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
const auth_config = {
|
||||||
|
|
||||||
|
default_provider: env('AUTH_DEFAULT_PROVIDER', 'flitter'),
|
||||||
|
default_login_route: '/dash',
|
||||||
|
|
||||||
|
servers: {
|
||||||
|
// OAuth2 authorization server
|
||||||
|
oauth2: {
|
||||||
|
enable: env('OAUTH2_SERVER_ENABLE', false),
|
||||||
|
|
||||||
|
// Grants that are available to clients. Supported types are authorization_code, password
|
||||||
|
grants: ['authorization_code'],
|
||||||
|
|
||||||
|
// Built in data retrieval endpoints. These are protected by user-specific OAuth2 tokens
|
||||||
|
built_in_endpoints: {
|
||||||
|
|
||||||
|
// Get the token user's data
|
||||||
|
user: {
|
||||||
|
enable: env('OAUTH2_SERVER_ENABLE', true),
|
||||||
|
|
||||||
|
// Fields to return to the endpoint
|
||||||
|
// The keys are the keys in the request. The values are the keys in the user.
|
||||||
|
fields: {
|
||||||
|
username: 'uid',
|
||||||
|
id: 'uuid',
|
||||||
|
|
||||||
|
// Data is a special key. It's key-value pairs are included,
|
||||||
|
// unserialized, from the user's JSON data.
|
||||||
|
data: {
|
||||||
|
// Fields stored in serialized data can be included here:
|
||||||
|
// special_field: 'some_json_data_field',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Auth provider configurations
|
||||||
|
// You can have multiple of the same 'type' of auth source, but they
|
||||||
|
// must have unique names. The name is the key of the source config.
|
||||||
|
// Valid types are (by default): FlitterProvider, LdapProvider, Oauth2Provider
|
||||||
|
sources: {
|
||||||
|
// Default, database-backed auth provider
|
||||||
|
flitter: {
|
||||||
|
type: 'FlitterProvider',
|
||||||
|
enable: env('AUTH_FLITTER_ENABLE', true),
|
||||||
|
registration: env('AUTH_FLITTER_REGISTRATION', true),
|
||||||
|
min_password_length: env('AUTH_MIN_PASSWORD_LENGTH', 8),
|
||||||
|
},
|
||||||
|
|
||||||
|
// LDAP-backed auth provider
|
||||||
|
example_ldap: {
|
||||||
|
type: 'LdapProvider',
|
||||||
|
enable: env('AUTH_LDAP_ENABLE', false),
|
||||||
|
|
||||||
|
host: env('AUTH_LDAP_HOST', 'localhost'),
|
||||||
|
port: env('AUTH_LDAP_PORT', 389),
|
||||||
|
secure: env('AUTH_LDAP_BIND_SECURE', false),
|
||||||
|
bind_dn: env('AUTH_LDAP_BIND_DN', 'uid=auth_agent,ou=people,dc=domain,dc=local'),
|
||||||
|
bind_secret: env('AUTH_LDAP_BIND_PW'),
|
||||||
|
|
||||||
|
user_search_base: env('AUTH_LDAP_SEARCH_BASE', 'ou=people,dc=domain,dc=local'),
|
||||||
|
user_filter: env('AUTH_LDAP_USER_FILTER', '(uid=%u)'), // %u is the login provided username
|
||||||
|
|
||||||
|
min_password_length: env('AUTH_MIN_PASSWORD_LENGTH', 8),
|
||||||
|
|
||||||
|
// Maps flitter-auth roles to LDAP groups
|
||||||
|
role_groups: {
|
||||||
|
// Should correspond to existing auth roles
|
||||||
|
// role_name: 'cn=somegroup,ou=groups,dc=domain,dc=local',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Maps user attributes to LDAP data attributes
|
||||||
|
attributes: {
|
||||||
|
uid: env('AUTH_LDAP_ATTR_UID', 'uid'),
|
||||||
|
first_name: env('AUTH_LDAP_ATTR_FIRST_NAME', 'cn'),
|
||||||
|
last_name: env('AUTH_LDAP_ATTR_LAST_NAME', 'sn'),
|
||||||
|
email: env('AUTH_LDAP_ATTR_EMAIL', 'mail'),
|
||||||
|
|
||||||
|
// Special case - used to determine group memberships
|
||||||
|
group_membership: env('AUTH_LDAP_ATTR_GROUPS', 'memberOf'),
|
||||||
|
},
|
||||||
|
|
||||||
|
registration: env('AUTH_LDAP_REGISTRATION', false),
|
||||||
|
|
||||||
|
// Default attributes for new registered users
|
||||||
|
// %u can be used to interpolate the registered user's uid
|
||||||
|
registration_merge_attributes: {
|
||||||
|
objectClass: ['posixAccount', 'shadowAccount', 'inetOrgPerson'],
|
||||||
|
sn: '%u',
|
||||||
|
cn: '%u',
|
||||||
|
gecos: '%u',
|
||||||
|
uidNumber: -1,
|
||||||
|
gidNumber: -1,
|
||||||
|
homeDirectory: '/dev/null',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
example_oauth: {
|
||||||
|
type: 'Oauth2Provider',
|
||||||
|
enable: env('AUTH_OAUTH2_ENABLE', false),
|
||||||
|
|
||||||
|
source_name: env('AUTH_OAUTH2_SOURCE_NAME', 'GitHub'),
|
||||||
|
source_client_id: env('AUTH_OAUTH2_CLIENT_ID'),
|
||||||
|
source_client_secret: env('AUTH_OAUTH2_CLIENT_SECRET'),
|
||||||
|
|
||||||
|
// Login page destination where the user will be redirected to on login
|
||||||
|
// %c will be interpolated with the client id
|
||||||
|
// %r will be interpolated with the redirect callback url
|
||||||
|
// NOTE: This url is the same as the login page - /auth/oauth2/login
|
||||||
|
source_login_page: env('AUTH_OAUTH2_LOGIN_REDIRECT', 'https://github.com/login/oauth/authorize?client_id=%c'),
|
||||||
|
|
||||||
|
// Information about the OAuth2 Callback
|
||||||
|
callback: {
|
||||||
|
// URL query parameter name with the authorization_code token
|
||||||
|
// e.g. ?code=XXXXXXXXXX
|
||||||
|
token_key: 'code',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Information about the endpoint flitter-auth will use to redeem
|
||||||
|
// the authorization_code token for a bearer token
|
||||||
|
source_token: {
|
||||||
|
endpoint: 'https://github.com/login/oauth/access_token',
|
||||||
|
|
||||||
|
// Field name where the authorization_code token will be specified in the request
|
||||||
|
token_key: 'code',
|
||||||
|
|
||||||
|
// Field name for the client id
|
||||||
|
client_id_key: 'client_id',
|
||||||
|
|
||||||
|
// Field name for the client secret
|
||||||
|
client_secret_key: 'client_secret',
|
||||||
|
|
||||||
|
// Field name for the grant_type ('authorization_type')
|
||||||
|
grant_type_key: 'grant_type',
|
||||||
|
|
||||||
|
// Field name where the bearer token will be specified in the response
|
||||||
|
response_token_key: 'access_token',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Information about the endpoint flitter-auth will use to get
|
||||||
|
// user information after it retrieves a bearer token
|
||||||
|
user_data: {
|
||||||
|
endpoint: 'https://api.github.com/user',
|
||||||
|
method: 'get', // 'get' or 'post' only
|
||||||
|
|
||||||
|
// In the response data, what key is the user data in?
|
||||||
|
// e.g. if 'data', then {'data': { ... }}
|
||||||
|
// Set falsy to assume the data exists in the root: { ... }
|
||||||
|
// data_root: 'data',
|
||||||
|
|
||||||
|
// Value that prefixes the token in the 'Authorization: ' header.
|
||||||
|
// e.g. 'token ' would mean 'token a0fw93ja0w93ja093wj'
|
||||||
|
// 'Bearer ' would be 'Bearer 0329j0239dj209j3209jd'
|
||||||
|
token_prefix: 'token ',
|
||||||
|
|
||||||
|
// Mapping of user model attributes to OAuth2 return data from the endpoint
|
||||||
|
// Note that uuid is not allowed, and uid is required
|
||||||
|
attributes: {
|
||||||
|
uid: 'login',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
roles: {
|
||||||
|
|
||||||
|
// Roles can be defined here as arrays of permissions:
|
||||||
|
// 'role_name': [ 'permission1', 'permission2' ],
|
||||||
|
// Then, users with that role will automatically inherit the permissions.
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = auth_config
|
8
config/ldap/server.config.js
Normal file
8
config/ldap/server.config.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
// LDAP Server Configuration
|
||||||
|
const ldap_server = {
|
||||||
|
port: env('LDAP_SERVER_PORT', 389),
|
||||||
|
max_connections: env('LDAP_MAX_CONNECTIONS'),
|
||||||
|
interface: env('LDAP_LISTEN_INTERFACE', '0.0.0.0'),
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = ldap_server
|
@ -42,7 +42,7 @@ const server_config = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ssl: {
|
ssl: {
|
||||||
enable: (env("SSL_ENABLE") ? (env("SSL_ENABLE") === 'true') : false),
|
enable: env("SSL_ENABLE", false),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Path to your domain's certificate file.
|
* Path to your domain's certificate file.
|
||||||
@ -58,4 +58,4 @@ const server_config = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = server_config
|
module.exports = server_config
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
"flitter-forms": "^0.8.1",
|
"flitter-forms": "^0.8.1",
|
||||||
"flitter-orm": "^0.2.4",
|
"flitter-orm": "^0.2.4",
|
||||||
"flitter-upload": "^0.8.0",
|
"flitter-upload": "^0.8.0",
|
||||||
"libflitter": "^0.46.7"
|
"ldapjs": "^1.0.2",
|
||||||
|
"libflitter": "^0.47.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
108
yarn.lock
108
yarn.lock
@ -149,11 +149,21 @@ asn1@0.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.2.tgz#408fcea7db6a668f119c38a9c244fec90061a7ac"
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.2.tgz#408fcea7db6a668f119c38a9c244fec90061a7ac"
|
||||||
integrity sha1-QI/Op9tqZo8RnDipwkT+yQBhp6w=
|
integrity sha1-QI/Op9tqZo8RnDipwkT+yQBhp6w=
|
||||||
|
|
||||||
|
asn1@0.2.3:
|
||||||
|
version "0.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
|
||||||
|
integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=
|
||||||
|
|
||||||
assert-plus@0.1.5, assert-plus@0.1.x:
|
assert-plus@0.1.5, assert-plus@0.1.x:
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160"
|
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160"
|
||||||
integrity sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=
|
integrity sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=
|
||||||
|
|
||||||
|
assert-plus@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||||
|
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
|
||||||
|
|
||||||
ast-traverse@~0.1.1:
|
ast-traverse@~0.1.1:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ast-traverse/-/ast-traverse-0.1.1.tgz#69cf2b8386f19dcda1bb1e05d68fe359d8897de6"
|
resolved "https://registry.yarnpkg.com/ast-traverse/-/ast-traverse-0.1.1.tgz#69cf2b8386f19dcda1bb1e05d68fe359d8897de6"
|
||||||
@ -355,6 +365,13 @@ backoff@2.4.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
precond "0.2"
|
precond "0.2"
|
||||||
|
|
||||||
|
backoff@^2.5.0:
|
||||||
|
version "2.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
|
||||||
|
integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=
|
||||||
|
dependencies:
|
||||||
|
precond "0.2"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
@ -444,6 +461,16 @@ bunyan@1.3.3:
|
|||||||
mv "~2"
|
mv "~2"
|
||||||
safe-json-stringify "~1"
|
safe-json-stringify "~1"
|
||||||
|
|
||||||
|
bunyan@^1.8.3:
|
||||||
|
version "1.8.12"
|
||||||
|
resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797"
|
||||||
|
integrity sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=
|
||||||
|
optionalDependencies:
|
||||||
|
dtrace-provider "~0.8"
|
||||||
|
moment "^2.10.6"
|
||||||
|
mv "~2"
|
||||||
|
safe-json-stringify "~1"
|
||||||
|
|
||||||
busboy@*:
|
busboy@*:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
||||||
@ -643,7 +670,7 @@ core-js@^2.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
|
||||||
integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==
|
integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
@ -655,6 +682,13 @@ dashdash@1.7.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "0.1.x"
|
assert-plus "0.1.x"
|
||||||
|
|
||||||
|
dashdash@^1.14.0:
|
||||||
|
version "1.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
|
||||||
|
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.1.1:
|
debug@2.6.9, debug@^2.1.1:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
@ -790,6 +824,13 @@ dtrace-provider@0.4.0, dtrace-provider@~0.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
nan "~1.5.1"
|
nan "~1.5.1"
|
||||||
|
|
||||||
|
dtrace-provider@~0.8:
|
||||||
|
version "0.8.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e"
|
||||||
|
integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==
|
||||||
|
dependencies:
|
||||||
|
nan "^2.14.0"
|
||||||
|
|
||||||
editorconfig@^0.15.3:
|
editorconfig@^0.15.3:
|
||||||
version "0.15.3"
|
version "0.15.3"
|
||||||
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
|
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
|
||||||
@ -948,6 +989,11 @@ extsprintf@1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.2.0.tgz#5ad946c22f5b32ba7f8cd7426711c6e8a3fc2529"
|
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.2.0.tgz#5ad946c22f5b32ba7f8cd7426711c6e8a3fc2529"
|
||||||
integrity sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=
|
integrity sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=
|
||||||
|
|
||||||
|
extsprintf@^1.2.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||||
|
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||||
|
|
||||||
finalhandler@1.1.1:
|
finalhandler@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
|
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
|
||||||
@ -1479,6 +1525,13 @@ ldap-filter@0.2.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "0.1.5"
|
assert-plus "0.1.5"
|
||||||
|
|
||||||
|
ldap-filter@0.2.2:
|
||||||
|
version "0.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ldap-filter/-/ldap-filter-0.2.2.tgz#f2b842be0b86da3352798505b31ebcae590d77d0"
|
||||||
|
integrity sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "0.1.5"
|
||||||
|
|
||||||
ldap@^0.7.1:
|
ldap@^0.7.1:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/ldap/-/ldap-0.7.1.tgz#320165cd1065079607d83bfbf4308cb45ce791b9"
|
resolved "https://registry.yarnpkg.com/ldap/-/ldap-0.7.1.tgz#320165cd1065079607d83bfbf4308cb45ce791b9"
|
||||||
@ -1496,15 +1549,32 @@ ldap@^0.7.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
dtrace-provider "0.4.0"
|
dtrace-provider "0.4.0"
|
||||||
|
|
||||||
|
ldapjs@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ldapjs/-/ldapjs-1.0.2.tgz#544ff7032b7b83c68f0701328d9297aa694340f9"
|
||||||
|
integrity sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=
|
||||||
|
dependencies:
|
||||||
|
asn1 "0.2.3"
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
backoff "^2.5.0"
|
||||||
|
bunyan "^1.8.3"
|
||||||
|
dashdash "^1.14.0"
|
||||||
|
ldap-filter "0.2.2"
|
||||||
|
once "^1.4.0"
|
||||||
|
vasync "^1.6.4"
|
||||||
|
verror "^1.8.1"
|
||||||
|
optionalDependencies:
|
||||||
|
dtrace-provider "~0.8"
|
||||||
|
|
||||||
leven@^1.0.2:
|
leven@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3"
|
resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3"
|
||||||
integrity sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=
|
integrity sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=
|
||||||
|
|
||||||
libflitter@^0.46.7:
|
libflitter@^0.47.0:
|
||||||
version "0.46.7"
|
version "0.47.0"
|
||||||
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.46.7.tgz#be55386a53747e1e21b2aefd356977900fd40dd1"
|
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.47.0.tgz#a28253458316f9ae4d8e10f7058af512b82c0e01"
|
||||||
integrity sha512-PPPEp4vR36xAvjPyxmU8K6NBv6n5ggP/bfSJU/PZ6qCChbYh0gKIN6kH88GM38imSZJxjZM1hjvzio5veIGaAw==
|
integrity sha512-M01HtrkD1bFwrslYzA/5V3Ozv67iwJAoFBuh3c5BmADCchur6x84w3jPnl8tr7tdDjHr7HtH8ahOgFhI1QZGAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
colors "^1.3.3"
|
colors "^1.3.3"
|
||||||
connect-mongodb-session "^2.2.0"
|
connect-mongodb-session "^2.2.0"
|
||||||
@ -1684,6 +1754,11 @@ mkdirp@^1.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea"
|
||||||
integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==
|
integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==
|
||||||
|
|
||||||
|
moment@^2.10.6:
|
||||||
|
version "2.24.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
|
||||||
|
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
|
||||||
|
|
||||||
mongo-schematic-class@^1.0.3:
|
mongo-schematic-class@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/mongo-schematic-class/-/mongo-schematic-class-1.0.3.tgz#95ce8f092e1feee4d00565c452b38419518d966f"
|
resolved "https://registry.yarnpkg.com/mongo-schematic-class/-/mongo-schematic-class-1.0.3.tgz#95ce8f092e1feee4d00565c452b38419518d966f"
|
||||||
@ -1855,6 +1930,11 @@ nan@2.13.2:
|
|||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7"
|
||||||
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==
|
||||||
|
|
||||||
|
nan@^2.14.0:
|
||||||
|
version "2.14.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||||
|
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||||
|
|
||||||
nan@~1.5.1:
|
nan@~1.5.1:
|
||||||
version "1.5.3"
|
version "1.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-1.5.3.tgz#4cd0ecc133b7b0700a492a646add427ae8a318eb"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-1.5.3.tgz#4cd0ecc133b7b0700a492a646add427ae8a318eb"
|
||||||
@ -2000,7 +2080,7 @@ once@1.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
once@^1.3.0:
|
once@^1.3.0, once@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||||
@ -2907,6 +2987,13 @@ vasync@1.6.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
verror "1.1.0"
|
verror "1.1.0"
|
||||||
|
|
||||||
|
vasync@^1.6.4:
|
||||||
|
version "1.6.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.4.tgz#dfe93616ad0e7ae801b332a9d88bfc5cdc8e1d1f"
|
||||||
|
integrity sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=
|
||||||
|
dependencies:
|
||||||
|
verror "1.6.0"
|
||||||
|
|
||||||
verror@1.1.0:
|
verror@1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/verror/-/verror-1.1.0.tgz#2a4b4eb14a207051e75a6f94ee51315bf173a1b0"
|
resolved "https://registry.yarnpkg.com/verror/-/verror-1.1.0.tgz#2a4b4eb14a207051e75a6f94ee51315bf173a1b0"
|
||||||
@ -2921,6 +3008,15 @@ verror@1.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
extsprintf "1.2.0"
|
extsprintf "1.2.0"
|
||||||
|
|
||||||
|
verror@^1.8.1:
|
||||||
|
version "1.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||||
|
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
core-util-is "1.0.2"
|
||||||
|
extsprintf "^1.2.0"
|
||||||
|
|
||||||
void-elements@^2.0.1:
|
void-elements@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
||||||
|
Loading…
Reference in New Issue
Block a user