login-plus 1.9.1 → 1.9.2

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 CHANGED
@@ -1,106 +1,106 @@
1
- # login-plus
2
- login service for express
3
-
4
- [![npm-version](https://img.shields.io/npm/v/login-plus.svg)](https://npmjs.org/package/login-plus)
5
- [![downloads](https://img.shields.io/npm/dm/login-plus.svg)](https://npmjs.org/package/login-plus)
6
- [![build](https://github.com/codenautas/login-plus/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/codenautas/login-plus/actions/workflows/build-and-test.yml)
7
- [![coverage](https://img.shields.io/coveralls/codenautas/login-plus/master.svg)](https://coveralls.io/r/codenautas/login-plus)
8
- [![qa-control](https://github.com/codenautas/login-plus/actions/workflows/qa-control.yml/badge.svg)](https://github.com/codenautas/login-plus/actions/workflows/qa-control.yml)
9
-
10
-
11
- language: ![English](https://raw.githubusercontent.com/codenautas/multilang/master/img/lang-en.png)
12
- also available in:
13
- [![Spanish](https://raw.githubusercontent.com/codenautas/multilang/master/img/lang-es.png)](LEEME.md)
14
-
15
-
16
- # install
17
-
18
-
19
- ```sh
20
- > npm install login-plus
21
- ```
22
-
23
-
24
- # Use
25
-
26
-
27
- ```js
28
-
29
- var express = require('express');
30
- var app = express();
31
- var bodyParser = require('body-parser');
32
-
33
- app.use(bodyParser.urlencoded({extended:true}));
34
-
35
- var loginPlus = new (require('login-plus').Manager);
36
-
37
- loginPlus.init(app,{ successRedirect:'/index' });
38
-
39
- loginPlus.setValidator(
40
- function(username, password, done) {
41
- if(username === 'admin' && password === 'secret.pass'){
42
- done(null, {username: 'admin', when: Date()});
43
- }else{
44
- done('username or password error');
45
- }
46
- }
47
- );
48
-
49
- app.get('/user-info',function(req,res){
50
- res.end(
51
- 'user: '+req.session.passport.username+
52
- ' logged since '+req.session.passport.when
53
- );
54
- });
55
-
56
- ```
57
-
58
-
59
- ## loginPlus.init(app, opts)
60
-
61
-
62
- From this line on, `loginPlus` controls whether the session is logged.
63
- If not, it redirects to `/login`.
64
-
65
- opts | default opts | use
66
- --------------------|----------------------|---------------
67
- loginPagePath | *internal [1]* | path to the .jade file that contains the login screen
68
- loginPageServe | *jade motor* | function that serves the login page (use this function when a .jade file is not desired)
69
- baseUrl | `/` | base URL for all other URLs
70
- successRedirect | *mandatory* | successful login path
71
- successReturns | false | returns to previous path when login
72
- loginUrlPath | `/login` | URL to the login page
73
- noLoggedUrlPath | `/login` | URL to the unlogged page where the authentification is required when trying to log in
74
- failedLoginUrlPath | `/login` | URL to the failing login page
75
- userFieldName | `username` | name of the "username" field
76
- secret | random key | keys for cookies
77
- alreadyLoggedIn | successRedirect | `/login` redirection when is already logged
78
- skipCheckAlreadyLoggedIn | false | allows `/login` redirects to login page even if the user is already logged
79
- **php** | false | hibrid login system mergin with PHP
80
- .save_path | | path of PHP session files
81
- .varLogged | | `$SESSION` variable name for login control
82
- **loginForm** | | opciones del formulario de login
83
- .usernameLabel | `Username` | username label
84
- .passwordLabel | `Password` | password label
85
- .buttonLabel | `Log In` | button label
86
- .formTitle | `login` | form title
87
- .formImg | | form image
88
- .autoLogin | false | enable direct login from URL with `?u=user&p=pass&a=1`
89
- store.module | null | function that returns the constructor of the module to store sessions (it receive the express-session instance as first argument)
90
-
91
- From this point on, the middlewares can access the data session contained in `req.user`.
92
-
93
-
94
-
95
- ## loginPlus.setValidator(fn)
96
-
97
-
98
- It registers the function that the user must validate and in case of success, obtains
99
- the additional necessary information for the session (for example, role or level of permission)
100
- that will be available in `req.session.passport`
101
-
102
-
103
- # License
104
-
105
-
106
- [MIT](LICENSE)
1
+ # login-plus
2
+ login service for express
3
+
4
+ [![npm-version](https://img.shields.io/npm/v/login-plus.svg)](https://npmjs.org/package/login-plus)
5
+ [![downloads](https://img.shields.io/npm/dm/login-plus.svg)](https://npmjs.org/package/login-plus)
6
+ [![build](https://github.com/codenautas/login-plus/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/codenautas/login-plus/actions/workflows/build-and-test.yml)
7
+ [![coverage](https://img.shields.io/coveralls/codenautas/login-plus/master.svg)](https://coveralls.io/r/codenautas/login-plus)
8
+ [![qa-control](https://github.com/codenautas/login-plus/actions/workflows/qa-control.yml/badge.svg)](https://github.com/codenautas/login-plus/actions/workflows/qa-control.yml)
9
+
10
+
11
+ language: ![English](https://raw.githubusercontent.com/codenautas/multilang/master/img/lang-en.png)
12
+ also available in:
13
+ [![Spanish](https://raw.githubusercontent.com/codenautas/multilang/master/img/lang-es.png)](LEEME.md)
14
+
15
+
16
+ # install
17
+
18
+
19
+ ```sh
20
+ > npm install login-plus
21
+ ```
22
+
23
+
24
+ # Use
25
+
26
+
27
+ ```js
28
+
29
+ var express = require('express');
30
+ var app = express();
31
+ var bodyParser = require('body-parser');
32
+
33
+ app.use(bodyParser.urlencoded({extended:true}));
34
+
35
+ var loginPlus = new (require('login-plus').Manager);
36
+
37
+ loginPlus.init(app,{ successRedirect:'/index' });
38
+
39
+ loginPlus.setValidator(
40
+ function(username, password, done) {
41
+ if(username === 'admin' && password === 'secret.pass'){
42
+ done(null, {username: 'admin', when: Date()});
43
+ }else{
44
+ done('username or password error');
45
+ }
46
+ }
47
+ );
48
+
49
+ app.get('/user-info',function(req,res){
50
+ res.end(
51
+ 'user: '+req.session.passport.username+
52
+ ' logged since '+req.session.passport.when
53
+ );
54
+ });
55
+
56
+ ```
57
+
58
+
59
+ ## loginPlus.init(app, opts)
60
+
61
+
62
+ From this line on, `loginPlus` controls whether the session is logged.
63
+ If not, it redirects to `/login`.
64
+
65
+ opts | default opts | use
66
+ --------------------|----------------------|---------------
67
+ loginPagePath | *internal [1]* | path to the .jade file that contains the login screen
68
+ loginPageServe | *jade motor* | function that serves the login page (use this function when a .jade file is not desired)
69
+ baseUrl | `/` | base URL for all other URLs
70
+ successRedirect | *mandatory* | successful login path
71
+ successReturns | false | returns to previous path when login
72
+ loginUrlPath | `/login` | URL to the login page
73
+ noLoggedUrlPath | `/login` | URL to the unlogged page where the authentification is required when trying to log in
74
+ failedLoginUrlPath | `/login` | URL to the failing login page
75
+ userFieldName | `username` | name of the "username" field
76
+ secret | random key | keys for cookies
77
+ alreadyLoggedIn | successRedirect | `/login` redirection when is already logged
78
+ skipCheckAlreadyLoggedIn | false | allows `/login` redirects to login page even if the user is already logged
79
+ **php** | false | hibrid login system mergin with PHP
80
+ .save_path | | path of PHP session files
81
+ .varLogged | | `$SESSION` variable name for login control
82
+ **loginForm** | | opciones del formulario de login
83
+ .usernameLabel | `Username` | username label
84
+ .passwordLabel | `Password` | password label
85
+ .buttonLabel | `Log In` | button label
86
+ .formTitle | `login` | form title
87
+ .formImg | | form image
88
+ .autoLogin | false | enable direct login from URL with `?u=user&p=pass&a=1`
89
+ store.module | null | function that returns the constructor of the module to store sessions (it receive the express-session instance as first argument)
90
+
91
+ From this point on, the middlewares can access the data session contained in `req.user`.
92
+
93
+
94
+
95
+ ## loginPlus.setValidator(fn)
96
+
97
+
98
+ It registers the function that the user must validate and in case of success, obtains
99
+ the additional necessary information for the session (for example, role or level of permission)
100
+ that will be available in `req.session.passport`
101
+
102
+
103
+ # License
104
+
105
+
106
+ [MIT](LICENSE)
@@ -1,21 +1,21 @@
1
- "use strict";
2
-
3
- window.addEventListener('load',function(){
4
- var params={};
5
- (window.location.hash||"").split(/[#&]/g).forEach(function(pair){
6
- var pos=pair.indexOf('=');
7
- if(pos>=0){
8
- params[pair.substr(0,pos)]=pair.substr(pos+1);
9
- }
10
- });
11
- ['username','password'].forEach(function(fieldName){
12
- var elem=document.getElementById(fieldName);
13
- var parameterName=fieldName.substr(0,1)
14
- if(params[parameterName]){
15
- elem.value=params[parameterName];
16
- }
17
- });
18
- if (params['a'] == 1) { /* eslint-disable-line eqeqeq */
19
- loginForm.submit();
20
- }
21
- });
1
+ "use strict";
2
+
3
+ window.addEventListener('load',function(){
4
+ var params={};
5
+ (window.location.hash||"").split(/[#&]/g).forEach(function(pair){
6
+ var pos=pair.indexOf('=');
7
+ if(pos>=0){
8
+ params[pair.substr(0,pos)]=pair.substr(pos+1);
9
+ }
10
+ });
11
+ ['username','password'].forEach(function(fieldName){
12
+ var elem=document.getElementById(fieldName);
13
+ var parameterName=fieldName.substr(0,1)
14
+ if(params[parameterName]){
15
+ elem.value=params[parameterName];
16
+ }
17
+ });
18
+ if (params['a'] == 1) { /* eslint-disable-line eqeqeq */
19
+ loginForm.submit();
20
+ }
21
+ });
@@ -1,31 +1,31 @@
1
- h2=formTitle
2
- form(id="chPassForm", action="chpass", method="post")
3
- table
4
- tr
5
- td
6
- label=oldPasswordLabel
7
- td
8
- input(id="oldPassword", type="password", name="oldPassword")
9
- td(rowspan=4)
10
- img(src=formImg, style="height:128px")
11
- tr
12
- td
13
- label=newPasswordLabel
14
- td
15
- input(id="newPassword", type="password", name="newPassword")
16
- td#resultStrength
17
- tr
18
- td
19
- label=repPasswordLabel
20
- td
21
- input(id="repPassword", type="password", name="repPassword")
22
- td#resultDiff
23
- tr
24
- td
25
- td
26
- input(type="submit", value=buttonLabel)
27
- each errorLine in (flash.error||[])
28
- tr(style={color:'red'})
29
- td(colspan=5)=errorLine
30
- if strength
31
- script(src="strength-pass.js")
1
+ h2=formTitle
2
+ form(id="chPassForm", action="chpass", method="post")
3
+ table
4
+ tr
5
+ td
6
+ label=oldPasswordLabel
7
+ td
8
+ input(id="oldPassword", type="password", name="oldPassword")
9
+ td(rowspan=4)
10
+ img(src=formImg, style="height:128px")
11
+ tr
12
+ td
13
+ label=newPasswordLabel
14
+ td
15
+ input(id="newPassword", type="password", name="newPassword")
16
+ td#resultStrength
17
+ tr
18
+ td
19
+ label=repPasswordLabel
20
+ td
21
+ input(id="repPassword", type="password", name="repPassword")
22
+ td#resultDiff
23
+ tr
24
+ td
25
+ td
26
+ input(type="submit", value=buttonLabel)
27
+ each errorLine in (flash.error||[])
28
+ tr(style={color:'red'})
29
+ td(colspan=5)=errorLine
30
+ if strength
31
+ script(src="strength-pass.js")
@@ -1,24 +1,24 @@
1
- h2=formTitle
2
- form(id="loginForm", action="login", method="post")
3
- table
4
- tr
5
- td
6
- label=usernameLabel
7
- td
8
- input(id="username", type="text", name="username", autofocus=true)
9
- td(rowspan=4)
10
- img(src=formImg, style="height:128px")
11
- tr
12
- td
13
- label=passwordLabel
14
- td
15
- input(id="password", type="password", name="password")
16
- tr
17
- td
18
- td
19
- input(type="submit", value=buttonLabel)
20
- each errorLine in (flash.error||[])
21
- tr(style={color:'red'})
22
- td(colspan=5)=errorLine
23
- if autoLogin
24
- script(src="auto-login.js")
1
+ h2=formTitle
2
+ form(id="loginForm", action="login", method="post")
3
+ table
4
+ tr
5
+ td
6
+ label=usernameLabel
7
+ td
8
+ input(id="username", type="text", name="username", autofocus=true)
9
+ td(rowspan=4)
10
+ img(src=formImg, style="height:128px")
11
+ tr
12
+ td
13
+ label=passwordLabel
14
+ td
15
+ input(id="password", type="password", name="password")
16
+ tr
17
+ td
18
+ td
19
+ input(type="submit", value=buttonLabel)
20
+ each errorLine in (flash.error||[])
21
+ tr(style={color:'red'})
22
+ td(colspan=5)=errorLine
23
+ if autoLogin
24
+ script(src="auto-login.js")
@@ -1,4 +1,4 @@
1
- "use strict";
2
-
3
- window.addEventListener('load', function(){
4
- });
1
+ "use strict";
2
+
3
+ window.addEventListener('load', function(){
4
+ });
package/lib/login-plus.js CHANGED
@@ -1,340 +1,340 @@
1
- "use strict";
2
-
3
- var loginPlus = {};
4
-
5
- var util = require('util');
6
- var crypto = require('crypto');
7
-
8
- var connectFlash = require('connect-flash');
9
- var MiniTools = require('mini-tools');
10
- var ensureLoggedIn = require('ensure-login').ensureLoggedIn;
11
- var session = require('express-session');
12
- var fs = require('fs-extra');
13
- var bestGlobals = require('best-globals');
14
- var changing = bestGlobals.changing;
15
- var Path = require('path');
16
- var Regexplicit = require('regexplicit');
17
-
18
- loginPlus.init = function AlertDeprecated(){
19
- console.log('deprecated loginPlus.init is now replaced with new (loginPlus.Manager).init');
20
- throw new Error('deprecated loginPlus.init is now replaced with new (loginPlus.Manager).init');
21
- };
22
-
23
- loginPlus.Manager = function LoginPlusManager(){
24
- this.validExts=[
25
- 'html',
26
- 'jpg','png','gif',
27
- 'css','js','manifest'
28
- ];
29
- this.secret = crypto.randomBytes(32).toString('hex');
30
- this.savedUser = {};
31
- };
32
-
33
- loginPlus.Manager.init = function AlertDeprecated(){
34
- console.log("lack outer parenthesis in: var loginPlus = new (require('login-plus').Manager);");
35
- throw new Error("lack outer parenthesis in: var loginPlus = new (require('login-plus').Manager);");
36
- };
37
-
38
- function serveJade(url, opts){
39
- return function(req, res, next){
40
- var flashInfo=req.flash();
41
- return MiniTools.serveJade(url, changing(opts,{flash:flashInfo}))(req, res, next);
42
- };
43
- }
44
-
45
- function completeOptions(opts){
46
- if(!opts || !opts.successRedirect){
47
- console.log('login-plus lack of mandatory: opts.successRedirect');
48
- throw new Error('login-plus lack of mandatory: opts.successRedirect');
49
- }
50
- ['unloggedPath'].forEach(function(optName){
51
- if(opts[optName]){
52
- console.log('deprecate login-plus.option.'+optName);
53
- }
54
- });
55
- opts = changing({
56
- loginPagePath : Path.join(__dirname,'../for-client'),
57
- baseUrl : '',
58
- redirBaseUrl : '.',
59
- successRedirect: '/index',
60
- successReturns :false,
61
- loginUrlPath : '/login',
62
- logoutUrlPath : '/logout',
63
- chPassUrlPath : '/chpass',
64
- userFieldName : "username",
65
- loginForm : {
66
- usernameLabel:'Username',
67
- passwordLabel:'Password',
68
- buttonLabel:'Log In',
69
- formTitle:'login',
70
- formImg:'Oxygen480-actions-key-enter.svg.png',
71
- autoLogin:false
72
- },
73
- chPassForm : {
74
- usernameLabel:'Username',
75
- oldPasswordLabel:'Old password',
76
- newPasswordLabel:'New password',
77
- repPasswordLabel:'Reenter password',
78
- buttonLabel:'Change',
79
- formTitle:'change password',
80
- strength:true
81
- },
82
- maxAge: 15*60*1000,
83
- passMinLength: 6,
84
- allowHttpLogin: false,
85
- log:{
86
- errors: new Date()
87
- },
88
- serializer:{
89
- serializeUser : function serializeUser (user, done){
90
- done(null, user);
91
- },
92
- deserializeUser: function deserializeUser (user, done){
93
- done(null, user);
94
- }
95
- },
96
- store:{},
97
- schrödinger:function(){}
98
- }, opts);
99
- opts.baseUrl = opts.baseUrl.replace(/\/$/g,'');
100
- opts = changing({
101
- loginPageServe : serveJade(opts.loginPageFile||opts.loginPagePath+'/login', opts.loginForm),
102
- chPassPageServe : serveJade(opts.loginPagePath+'/chpass', opts.chPassForm),
103
- noLoggedUrlPath : opts.loginUrlPath,
104
- failedLoginUrlPath: opts.loginUrlPath,
105
- alreadyLoggedIn : opts.successRedirect,
106
- },opts);
107
- opts = changing({
108
- logoutRedirect : opts.noLoggedUrlPath
109
- },opts);
110
- return opts;
111
- }
112
-
113
- function SetInitialOptions(app,opts){
114
- var Passport = require('passport').Passport;
115
- var passport = this.passport = new Passport();
116
- this.LocalStrategy = require('passport-local').Strategy;
117
- opts = this.opts = completeOptions(opts);
118
- var sessionOpts=opts.session||{};
119
- /* istanbul ignore next */
120
- if(opts.store.module){
121
- var sessionStoreConstructor = opts.store.module(session);
122
- sessionOpts.store=new sessionStoreConstructor(opts.store.opts);
123
- this.store=sessionOpts.store;
124
- }
125
- this.sessionOpts=changing({
126
- secret: opts.secret || this.secret,
127
- resave: false,
128
- saveUninitialized: true,
129
- rolling: true,
130
- cookie: {
131
- maxAge: opts.maxAge,
132
- httpOnly: true,
133
- sameSite: 'lax',
134
- secure:(opts.allowHttpLogin?false:true)
135
- }
136
- },sessionOpts);
137
- }
138
-
139
- loginPlus.Manager.prototype.initCookieParser = function initCookieParser(app,opts,cookieParser){
140
- SetInitialOptions.call(this,app,opts);
141
- app.use(cookieParser(this.sessionOpts.secret));
142
- };
143
-
144
- /* eslint global-require: 0 */
145
- loginPlus.Manager.prototype.phpInit = function phpInit(app,opts){
146
- var PhpSessionMiddleware = require('php-session');
147
- var phpMiddleware = new PhpSessionMiddleware({
148
- sessionName: '$SESSION',
149
- handler: 'file',
150
- opts: {
151
- path: opts.php.save_path
152
- }
153
- });
154
- app.use(phpMiddleware);
155
- /*
156
- app.use(function(req,res,next){
157
- phpMiddleware(req, res, function(){
158
- next.apply(null, arguments);
159
- });
160
- });
161
- */
162
- var ensureMiddlewareWihtoutPHP = this.ensureMiddleware;
163
- this.ensureMiddleware = function(req, res, next){
164
- if(req.$SESSION && req.$SESSION[opts.php.varLogged]){
165
- return next();
166
- }else{
167
- ensureMiddlewareWihtoutPHP(req, res, next);
168
- }
169
- };
170
- };
171
-
172
- function checkAlreadyLoggedIn(app, opts){
173
- var loginUrl=opts.baseUrl+opts.loginUrlPath;
174
- app.get(loginUrl, function(req,res,next){
175
- if(req.user){
176
- res.redirect(opts.redirBaseUrl+opts.alreadyLoggedIn);
177
- }else{
178
- return next();
179
- }
180
- });
181
- }
182
-
183
- loginPlus.Manager.prototype.init = function init(app,opts){ // eslint-disable-line max-statements
184
- var thisManager = this;
185
- if(!this.passport){
186
- var router = '_router' in app ? app._router : app.router;
187
- if(router){
188
- var forbidensMiddlewares=router.stack.filter(function(layer){
189
- return layer.name==='cookieParser';
190
- });
191
- if(forbidensMiddlewares.length){
192
- console.log('Forbien Middlewares in login-plus:');
193
- console.dir(forbidensMiddlewares);
194
- throw new Error('loginPlus unexpected router. Check that cookie-parse was set with initCookieParse');
195
- }
196
- }
197
- SetInitialOptions.call(this,app,opts);
198
- }
199
- opts = this.opts;
200
- this.ensureMiddleware = ensureLoggedIn({baseUrl: opts.baseUrl, redirectTo:opts.noLoggedUrlPath, setReturnTo:Regexplicit.detectNonEmptyUrlWithoutResources});
201
- // this.ensureMiddleware = ensureLoggedIn(opts.baseUrl+opts.noLoggedUrlPath);
202
- ['auto-login.js', 'strength-pass.js', 'Oxygen480-actions-key-enter.svg.png'].forEach(function(fileName){
203
- app.use(opts.baseUrl+'/'+fileName,
204
- MiniTools.serveFile(Path.join(opts.loginPagePath,fileName))
205
- );
206
- });
207
- app.set('trust proxy', 1);
208
- app.use(session(this.sessionOpts));
209
- app.use(connectFlash());
210
- app.use(this.passport.initialize());
211
- app.use(this.passport.session());
212
- var fileNameLogin=opts.fileNameLogin||Path.join(opts.loginPagePath,'login.jade');
213
- var promiseChain = Promise.resolve();
214
- promiseChain = promiseChain.then(function(){
215
- return fs.exists(fileNameLogin);
216
- }).then(function(exists){
217
- if(!exists){
218
- throw Error('login-plus.init fail "'+fileNameLogin+'" does not exists');
219
- }
220
- });
221
- app.get(opts.baseUrl+opts.logoutUrlPath, function(req,res,next){
222
- req.logout(function(err) {
223
- if (err) { return next(err); }
224
- req.session.returnTo = null;
225
- res.redirect(opts.redirBaseUrl+opts.logoutRedirect);
226
- });
227
- });
228
- /*
229
- app.post(opts.baseUrl+opts.loginUrlPath, function(req,res,next){
230
- if(req.query["return-to"] && req.session){
231
- console.log('XXXXXX- CHECK LOGIN PLUS', req.query["return-to"]);
232
- req.session.returnTo = req.query["return-to"];
233
- }
234
- next();
235
- });
236
- */
237
- if(!opts.skipCheckAlreadyLoggedIn){
238
- checkAlreadyLoggedIn(app, opts);
239
- }
240
- app.get(opts.baseUrl+opts.loginUrlPath, opts.loginPageServe);
241
- var authenticateOptions={
242
- failureRedirect: opts.redirBaseUrl+opts.failedLoginUrlPath,
243
- failureFlash: true,
244
- keepSessionInfo: true,
245
- }
246
- authenticateOptions[opts.successReturns?'successReturnToOrRedirect':'successRedirect'] = opts.redirBaseUrl+opts.successRedirect
247
- app.post(opts.baseUrl+opts.loginUrlPath,
248
- this.passport.authenticate('local', authenticateOptions)
249
- );
250
- /* istanbul ignore else*/
251
- if(opts.serializer){
252
- this.passport.serializeUser(opts.serializer.serializeUser);
253
- this.passport.deserializeUser(opts.serializer.deserializeUser);
254
- }else{
255
- this.passport.serializeUser(function serializeUser (user, done){
256
- console.log('serializeUser', user);
257
- done(null, user);
258
- });
259
- this.passport.deserializeUser(function deserializeUser (user, done){
260
- console.log('deserializeUser', user);
261
- done(null, user);
262
- });
263
- }
264
- if(opts.php){
265
- this.phpInit(app,opts);
266
- }
267
- opts.schrödinger();
268
- /////// ATENCIÓN NUNCA METER ensureLoggedIn dentro de una cadena de promesas. Necesitamos que se ejecute sí o sí
269
- app.use(opts.baseUrl,this.ensureMiddleware);
270
- //// NOW is logged in
271
- app.post(opts.baseUrl+opts.chPassUrlPath, function(req,res){
272
- if (!req.body.newPassword) {
273
- req.flash('error', (opts.messages?.passCantBeEmpty || "new pass cant be empty"));
274
- res.redirect(opts.redirBaseUrl+opts.chPassUrlPath)
275
- }else if (req.body.newPassword !== req.body.repPassword) {
276
- req.flash('error', (opts.messages?.passDoesntMatch || "new pass doesn't match"));
277
- res.redirect(opts.redirBaseUrl+opts.chPassUrlPath);
278
- }else if((req.body.newPassword||'').length>=opts.passMinLength){
279
- thisManager.passwordChanger(
280
- req,
281
- req.user[opts.userFieldName],
282
- req.body.oldPassword,
283
- req.body.newPassword,
284
- function(err, ok, flashMessage){
285
- if(ok){
286
- req.logout(function(err) {
287
- if (err) { return next(err); }
288
- req.session.returnTo = null;
289
- res.redirect(opts.redirBaseUrl+opts.loginUrlPath);
290
- });
291
- }else{
292
- if(err && opts.log.errors.getTime() > new Date().getTime()){
293
- console.log('chpass error',err);
294
- }
295
- req.flash('error', flashMessage || opts.messages?.internalError || 'internal error');
296
- console.log('probablemente hay un error en los campos de la tabla usuarios (quizas no coincidan con los esperados)')
297
- res.redirect(opts.redirBaseUrl+opts.chPassUrlPath);
298
- }
299
- }
300
- );
301
- }else{
302
- req.flash('error', (opts.messages?.passTooShort || 'pass too short (minimum length $1)').replace('$1',opts.passMinLength));
303
- res.redirect(opts.redirBaseUrl+opts.chPassUrlPath);
304
- }
305
- });
306
- return promiseChain;
307
- };
308
-
309
- /* istanbul ignore next */
310
- loginPlus.Manager.prototype.setValidator = util.deprecate(function setValidator(validatorStrategy){
311
- this.passport.use(new this.LocalStrategy(validatorStrategy));
312
- }, "use setValidatorStrategy");
313
-
314
- loginPlus.Manager.prototype.setValidatorStrategy = function setValidatorStrategy(){
315
- var validatorStrategy=arguments[arguments.length>1?1:0];
316
- var opts=arguments.length>1?arguments[0]:{};
317
- this.passport.use(new this.LocalStrategy(changing({passReqToCallback:true},opts), validatorStrategy));
318
- };
319
-
320
- loginPlus.Manager.prototype.setPasswordChanger = function setPasswordChanger(passwordChanger){
321
- this.passwordChanger = passwordChanger;
322
- };
323
-
324
- /* istanbul ignore next */
325
- loginPlus.Manager.prototype.closeManager = function closeManager(){
326
- /* istanbul ignore next */
327
- if(this.store){
328
- /* istanbul ignore next */
329
- this.store.stopInterval();
330
- }
331
- }
332
-
333
- loginPlus.spanishLoginForm={
334
- usernameLabel:'usuario',
335
- passwordLabel:'clave',
336
- buttonLabel:'entrar',
337
- formTitle:'entrada',
338
- };
339
-
340
- module.exports = loginPlus;
1
+ "use strict";
2
+
3
+ var loginPlus = {};
4
+
5
+ var util = require('util');
6
+ var crypto = require('crypto');
7
+
8
+ var connectFlash = require('connect-flash');
9
+ var MiniTools = require('mini-tools');
10
+ var ensureLoggedIn = require('ensure-login').ensureLoggedIn;
11
+ var session = require('express-session');
12
+ var fs = require('fs-extra');
13
+ var bestGlobals = require('best-globals');
14
+ var changing = bestGlobals.changing;
15
+ var Path = require('path');
16
+ var Regexplicit = require('regexplicit');
17
+
18
+ loginPlus.init = function AlertDeprecated(){
19
+ console.log('deprecated loginPlus.init is now replaced with new (loginPlus.Manager).init');
20
+ throw new Error('deprecated loginPlus.init is now replaced with new (loginPlus.Manager).init');
21
+ };
22
+
23
+ loginPlus.Manager = function LoginPlusManager(){
24
+ this.validExts=[
25
+ 'html',
26
+ 'jpg','png','gif',
27
+ 'css','js','manifest'
28
+ ];
29
+ this.secret = crypto.randomBytes(32).toString('hex');
30
+ this.savedUser = {};
31
+ };
32
+
33
+ loginPlus.Manager.init = function AlertDeprecated(){
34
+ console.log("lack outer parenthesis in: var loginPlus = new (require('login-plus').Manager);");
35
+ throw new Error("lack outer parenthesis in: var loginPlus = new (require('login-plus').Manager);");
36
+ };
37
+
38
+ function serveJade(url, opts){
39
+ return function(req, res, next){
40
+ var flashInfo=req.flash();
41
+ return MiniTools.serveJade(url, changing(opts,{flash:flashInfo}))(req, res, next);
42
+ };
43
+ }
44
+
45
+ function completeOptions(opts){
46
+ if(!opts || !opts.successRedirect){
47
+ console.log('login-plus lack of mandatory: opts.successRedirect');
48
+ throw new Error('login-plus lack of mandatory: opts.successRedirect');
49
+ }
50
+ ['unloggedPath'].forEach(function(optName){
51
+ if(opts[optName]){
52
+ console.log('deprecate login-plus.option.'+optName);
53
+ }
54
+ });
55
+ opts = changing({
56
+ loginPagePath : Path.join(__dirname,'../for-client'),
57
+ baseUrl : '',
58
+ redirBaseUrl : '.',
59
+ successRedirect: '/index',
60
+ successReturns :false,
61
+ loginUrlPath : '/login',
62
+ logoutUrlPath : '/logout',
63
+ chPassUrlPath : '/chpass',
64
+ userFieldName : "username",
65
+ loginForm : {
66
+ usernameLabel:'Username',
67
+ passwordLabel:'Password',
68
+ buttonLabel:'Log In',
69
+ formTitle:'login',
70
+ formImg:'Oxygen480-actions-key-enter.svg.png',
71
+ autoLogin:false
72
+ },
73
+ chPassForm : {
74
+ usernameLabel:'Username',
75
+ oldPasswordLabel:'Old password',
76
+ newPasswordLabel:'New password',
77
+ repPasswordLabel:'Reenter password',
78
+ buttonLabel:'Change',
79
+ formTitle:'change password',
80
+ strength:true
81
+ },
82
+ maxAge: 15*60*1000,
83
+ passMinLength: 6,
84
+ allowHttpLogin: false,
85
+ log:{
86
+ errors: new Date()
87
+ },
88
+ serializer:{
89
+ serializeUser : function serializeUser (user, done){
90
+ done(null, user);
91
+ },
92
+ deserializeUser: function deserializeUser (user, done){
93
+ done(null, user);
94
+ }
95
+ },
96
+ store:{},
97
+ schrödinger:function(){}
98
+ }, opts);
99
+ opts.baseUrl = opts.baseUrl.replace(/\/$/g,'');
100
+ opts = changing({
101
+ loginPageServe : serveJade(opts.loginPageFile||opts.loginPagePath+'/login', opts.loginForm),
102
+ chPassPageServe : serveJade(opts.loginPagePath+'/chpass', opts.chPassForm),
103
+ noLoggedUrlPath : opts.loginUrlPath,
104
+ failedLoginUrlPath: opts.loginUrlPath,
105
+ alreadyLoggedIn : opts.successRedirect,
106
+ },opts);
107
+ opts = changing({
108
+ logoutRedirect : opts.noLoggedUrlPath
109
+ },opts);
110
+ return opts;
111
+ }
112
+
113
+ function SetInitialOptions(app,opts){
114
+ var Passport = require('passport').Passport;
115
+ var passport = this.passport = new Passport();
116
+ this.LocalStrategy = require('passport-local').Strategy;
117
+ opts = this.opts = completeOptions(opts);
118
+ var sessionOpts=opts.session||{};
119
+ /* istanbul ignore next */
120
+ if(opts.store.module){
121
+ var sessionStoreConstructor = opts.store.module(session);
122
+ sessionOpts.store=new sessionStoreConstructor(opts.store.opts);
123
+ this.store=sessionOpts.store;
124
+ }
125
+ this.sessionOpts=changing({
126
+ secret: opts.secret || this.secret,
127
+ resave: false,
128
+ saveUninitialized: true,
129
+ rolling: true,
130
+ cookie: {
131
+ maxAge: opts.maxAge,
132
+ httpOnly: true,
133
+ sameSite: 'lax',
134
+ secure:(opts.allowHttpLogin?false:true)
135
+ }
136
+ },sessionOpts);
137
+ }
138
+
139
+ loginPlus.Manager.prototype.initCookieParser = function initCookieParser(app,opts,cookieParser){
140
+ SetInitialOptions.call(this,app,opts);
141
+ app.use(cookieParser(this.sessionOpts.secret));
142
+ };
143
+
144
+ /* eslint global-require: 0 */
145
+ loginPlus.Manager.prototype.phpInit = function phpInit(app,opts){
146
+ var PhpSessionMiddleware = require('php-session');
147
+ var phpMiddleware = new PhpSessionMiddleware({
148
+ sessionName: '$SESSION',
149
+ handler: 'file',
150
+ opts: {
151
+ path: opts.php.save_path
152
+ }
153
+ });
154
+ app.use(phpMiddleware);
155
+ /*
156
+ app.use(function(req,res,next){
157
+ phpMiddleware(req, res, function(){
158
+ next.apply(null, arguments);
159
+ });
160
+ });
161
+ */
162
+ var ensureMiddlewareWihtoutPHP = this.ensureMiddleware;
163
+ this.ensureMiddleware = function(req, res, next){
164
+ if(req.$SESSION && req.$SESSION[opts.php.varLogged]){
165
+ return next();
166
+ }else{
167
+ ensureMiddlewareWihtoutPHP(req, res, next);
168
+ }
169
+ };
170
+ };
171
+
172
+ function checkAlreadyLoggedIn(app, opts){
173
+ var loginUrl=opts.baseUrl+opts.loginUrlPath;
174
+ app.get(loginUrl, function(req,res,next){
175
+ if(req.user){
176
+ res.redirect(opts.redirBaseUrl+opts.alreadyLoggedIn);
177
+ }else{
178
+ return next();
179
+ }
180
+ });
181
+ }
182
+
183
+ loginPlus.Manager.prototype.init = function init(app,opts){ // eslint-disable-line max-statements
184
+ var thisManager = this;
185
+ if(!this.passport){
186
+ var router = '_router' in app ? app._router : app.router;
187
+ if(router){
188
+ var forbidensMiddlewares=router.stack.filter(function(layer){
189
+ return layer.name==='cookieParser';
190
+ });
191
+ if(forbidensMiddlewares.length){
192
+ console.log('Forbien Middlewares in login-plus:');
193
+ console.dir(forbidensMiddlewares);
194
+ throw new Error('loginPlus unexpected router. Check that cookie-parse was set with initCookieParse');
195
+ }
196
+ }
197
+ SetInitialOptions.call(this,app,opts);
198
+ }
199
+ opts = this.opts;
200
+ this.ensureMiddleware = ensureLoggedIn({baseUrl: opts.baseUrl, redirectTo:opts.noLoggedUrlPath, setReturnTo:Regexplicit.detectNonEmptyUrlWithoutResources});
201
+ // this.ensureMiddleware = ensureLoggedIn(opts.baseUrl+opts.noLoggedUrlPath);
202
+ ['auto-login.js', 'strength-pass.js', 'Oxygen480-actions-key-enter.svg.png'].forEach(function(fileName){
203
+ app.use(opts.baseUrl+'/'+fileName,
204
+ MiniTools.serveFile(Path.join(opts.loginPagePath,fileName))
205
+ );
206
+ });
207
+ app.set('trust proxy', 1);
208
+ app.use(session(this.sessionOpts));
209
+ app.use(connectFlash());
210
+ app.use(this.passport.initialize());
211
+ app.use(this.passport.session());
212
+ var fileNameLogin=opts.fileNameLogin||Path.join(opts.loginPagePath,'login.jade');
213
+ var promiseChain = Promise.resolve();
214
+ promiseChain = promiseChain.then(function(){
215
+ return fs.exists(fileNameLogin);
216
+ }).then(function(exists){
217
+ if(!exists){
218
+ throw Error('login-plus.init fail "'+fileNameLogin+'" does not exists');
219
+ }
220
+ });
221
+ app.get(opts.baseUrl+opts.logoutUrlPath, function(req,res,next){
222
+ req.logout(function(err) {
223
+ if (err) { return next(err); }
224
+ req.session.returnTo = null;
225
+ res.redirect(opts.redirBaseUrl+opts.logoutRedirect);
226
+ });
227
+ });
228
+ /*
229
+ app.post(opts.baseUrl+opts.loginUrlPath, function(req,res,next){
230
+ if(req.query["return-to"] && req.session){
231
+ console.log('XXXXXX- CHECK LOGIN PLUS', req.query["return-to"]);
232
+ req.session.returnTo = req.query["return-to"];
233
+ }
234
+ next();
235
+ });
236
+ */
237
+ if(!opts.skipCheckAlreadyLoggedIn){
238
+ checkAlreadyLoggedIn(app, opts);
239
+ }
240
+ app.get(opts.baseUrl+opts.loginUrlPath, opts.loginPageServe);
241
+ var authenticateOptions={
242
+ failureRedirect: opts.redirBaseUrl+opts.failedLoginUrlPath,
243
+ failureFlash: true,
244
+ keepSessionInfo: true,
245
+ }
246
+ authenticateOptions[opts.successReturns?'successReturnToOrRedirect':'successRedirect'] = opts.redirBaseUrl+opts.successRedirect
247
+ app.post(opts.baseUrl+opts.loginUrlPath,
248
+ this.passport.authenticate('local', authenticateOptions)
249
+ );
250
+ /* istanbul ignore else*/
251
+ if(opts.serializer){
252
+ this.passport.serializeUser(opts.serializer.serializeUser);
253
+ this.passport.deserializeUser(opts.serializer.deserializeUser);
254
+ }else{
255
+ this.passport.serializeUser(function serializeUser (user, done){
256
+ console.log('serializeUser', user);
257
+ done(null, user);
258
+ });
259
+ this.passport.deserializeUser(function deserializeUser (user, done){
260
+ console.log('deserializeUser', user);
261
+ done(null, user);
262
+ });
263
+ }
264
+ if(opts.php){
265
+ this.phpInit(app,opts);
266
+ }
267
+ opts.schrödinger();
268
+ /////// ATENCIÓN NUNCA METER ensureLoggedIn dentro de una cadena de promesas. Necesitamos que se ejecute sí o sí
269
+ app.use(opts.baseUrl,this.ensureMiddleware);
270
+ //// NOW is logged in
271
+ app.post(opts.baseUrl+opts.chPassUrlPath, function(req,res){
272
+ if (!req.body.newPassword) {
273
+ req.flash('error', (opts.messages?.passCantBeEmpty || "new pass cant be empty"));
274
+ res.redirect(opts.redirBaseUrl+opts.chPassUrlPath)
275
+ }else if (req.body.newPassword !== req.body.repPassword) {
276
+ req.flash('error', (opts.messages?.passDoesntMatch || "new pass doesn't match"));
277
+ res.redirect(opts.redirBaseUrl+opts.chPassUrlPath);
278
+ }else if((req.body.newPassword||'').length>=opts.passMinLength){
279
+ thisManager.passwordChanger(
280
+ req,
281
+ req.user[opts.userFieldName],
282
+ req.body.oldPassword,
283
+ req.body.newPassword,
284
+ function(err, ok, flashMessage){
285
+ if(ok){
286
+ req.logout(function(err) {
287
+ if (err) { return next(err); }
288
+ req.session.returnTo = null;
289
+ res.redirect(opts.redirBaseUrl+opts.loginUrlPath);
290
+ });
291
+ }else{
292
+ if(err && opts.log.errors.getTime() > new Date().getTime()){
293
+ console.log('chpass error',err);
294
+ }
295
+ req.flash('error', flashMessage || opts.messages?.internalError || 'internal error');
296
+ console.log('probablemente hay un error en los campos de la tabla usuarios (quizas no coincidan con los esperados)')
297
+ res.redirect(opts.redirBaseUrl+opts.chPassUrlPath);
298
+ }
299
+ }
300
+ );
301
+ }else{
302
+ req.flash('error', (opts.messages?.passTooShort || 'pass too short (minimum length $1)').replace('$1',opts.passMinLength));
303
+ res.redirect(opts.redirBaseUrl+opts.chPassUrlPath);
304
+ }
305
+ });
306
+ return promiseChain;
307
+ };
308
+
309
+ /* istanbul ignore next */
310
+ loginPlus.Manager.prototype.setValidator = util.deprecate(function setValidator(validatorStrategy){
311
+ this.passport.use(new this.LocalStrategy(validatorStrategy));
312
+ }, "use setValidatorStrategy");
313
+
314
+ loginPlus.Manager.prototype.setValidatorStrategy = function setValidatorStrategy(){
315
+ var validatorStrategy=arguments[arguments.length>1?1:0];
316
+ var opts=arguments.length>1?arguments[0]:{};
317
+ this.passport.use(new this.LocalStrategy(changing({passReqToCallback:true},opts), validatorStrategy));
318
+ };
319
+
320
+ loginPlus.Manager.prototype.setPasswordChanger = function setPasswordChanger(passwordChanger){
321
+ this.passwordChanger = passwordChanger;
322
+ };
323
+
324
+ /* istanbul ignore next */
325
+ loginPlus.Manager.prototype.closeManager = function closeManager(){
326
+ /* istanbul ignore next */
327
+ if(this.store){
328
+ /* istanbul ignore next */
329
+ this.store.stopInterval();
330
+ }
331
+ }
332
+
333
+ loginPlus.spanishLoginForm={
334
+ usernameLabel:'usuario',
335
+ passwordLabel:'clave',
336
+ buttonLabel:'entrar',
337
+ formTitle:'entrada',
338
+ };
339
+
340
+ module.exports = loginPlus;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "login-plus",
3
3
  "description": "login service for express",
4
- "version": "1.9.1",
4
+ "version": "1.9.2",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/login-plus",
@@ -34,7 +34,7 @@
34
34
  "ensure-login": "^0.1.6",
35
35
  "express-session": "^1.19.0",
36
36
  "fs-extra": "^11.4.1",
37
- "mini-tools": "^1.13.11",
37
+ "mini-tools": "^1.13.12",
38
38
  "passport": "^0.7.0",
39
39
  "passport-local": "^1.0.0",
40
40
  "regexplicit": "^0.1.3",
@@ -49,13 +49,13 @@
49
49
  "express": "^5.3.0",
50
50
  "mocha": "^12.0.3",
51
51
  "nyc": "^18.0.0",
52
- "pg-promise-strict": "^1.5.0",
52
+ "pg-promise-strict": "^1.5.3",
53
53
  "php-session": "^0.1.0",
54
54
  "pug": "^3.0.4",
55
- "qa-control": "^0.12.2",
55
+ "qa-control": "^0.14.0",
56
56
  "read-yaml-promise": "^1.0.2",
57
57
  "self-explain": "^0.11.0",
58
- "serve-content": "^1.0.6",
58
+ "serve-content": "^1.0.8",
59
59
  "sinon": "^22.1.0",
60
60
  "stylus": "^0.64.0",
61
61
  "supertest": "^7.3.1"