2017-11-14 11:49:19 +01:00
'use strict' ;
/ * *
* Auth . js controller
*
* @ description : A set of functions called "actions" for managing ` Auth ` .
* /
2018-04-30 18:26:56 +02:00
/* eslint-disable no-useless-escape */
2017-11-16 18:00:15 +01:00
const crypto = require ( 'crypto' ) ;
2018-04-30 18:26:56 +02:00
const _ = require ( 'lodash' ) ;
2018-01-23 13:35:51 +01:00
const emailRegExp = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ ;
2017-11-16 14:12:03 +01:00
2017-11-14 11:49:19 +01:00
module . exports = {
callback : async ( ctx ) => {
const provider = ctx . params . provider || 'local' ;
const params = ctx . request . body ;
2018-02-06 13:10:43 +01:00
const store = await strapi . store ( {
2018-02-13 15:04:21 +01:00
environment : '' ,
2018-02-06 13:10:43 +01:00
type : 'plugin' ,
name : 'users-permissions'
} ) ;
2017-11-14 11:49:19 +01:00
if ( provider === 'local' ) {
2018-02-06 13:10:43 +01:00
if ( ! _ . get ( await store . get ( { key : 'grant' } ) , 'email.enabled' ) && ! ctx . request . admin ) {
2018-01-18 16:01:52 +01:00
return ctx . badRequest ( null , 'This provider is disabled.' ) ;
}
2017-11-14 11:49:19 +01:00
// The identifier is required.
if ( ! params . identifier ) {
2017-12-06 11:38:00 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.email.provide' } ] } ] : 'Please provide your username or your e-mail.' ) ;
2017-11-14 11:49:19 +01:00
}
// The password is required.
if ( ! params . password ) {
2017-12-06 11:38:00 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.password.provide' } ] } ] : 'Please provide your password.' ) ;
2017-11-14 11:49:19 +01:00
}
const query = { } ;
// Check if the provided identifier is an email or not.
2018-01-23 13:35:51 +01:00
const isEmail = emailRegExp . test ( params . identifier ) ;
2017-11-14 11:49:19 +01:00
// Set the identifier to the appropriate query field.
if ( isEmail ) {
2018-01-23 13:35:51 +01:00
query . email = params . identifier . toLowerCase ( ) ;
2017-11-14 11:49:19 +01:00
} else {
query . username = params . identifier ;
}
// Check if the user exists.
2018-01-24 11:38:42 +01:00
const user = await strapi . query ( 'user' , 'users-permissions' ) . findOne ( query , [ 'role' ] ) ;
2017-11-20 16:28:50 +01:00
if ( ! user ) {
2017-12-06 11:38:00 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.invalid' } ] } ] : 'Identifier or password invalid.' ) ;
2017-11-20 16:28:50 +01:00
}
2018-01-24 11:38:42 +01:00
if ( user . role . type !== 'root' && ctx . request . admin ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.noAdminAccess' } ] } ] : ` You're not an administrator. ` ) ;
}
2018-03-14 16:56:12 +01:00
// The user never authenticated with the `local` provider.
2017-11-20 16:28:50 +01:00
if ( ! user . password ) {
2017-12-06 11:38:00 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.password.local' } ] } ] : 'This user never set a local password, please login thanks to the provider used during account creation.' ) ;
2017-11-20 16:28:50 +01:00
}
const validPassword = strapi . plugins [ 'users-permissions' ] . services . user . validatePassword ( params . password , user . password ) ;
if ( ! validPassword ) {
2017-12-06 11:38:00 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.invalid' } ] } ] : 'Identifier or password invalid.' ) ;
2017-11-20 16:28:50 +01:00
} else {
ctx . send ( {
2018-02-08 14:37:54 +01:00
jwt : strapi . plugins [ 'users-permissions' ] . services . jwt . issue ( _ . pick ( user . toJSON ? user . toJSON ( ) : user , [ '_id' , 'id' ] ) ) ,
2017-12-07 14:56:25 +01:00
user : _ . omit ( user . toJSON ? user . toJSON ( ) : user , [ 'password' , 'resetPasswordToken' ] )
2017-11-20 16:28:50 +01:00
} ) ;
2017-11-14 11:49:19 +01:00
}
} else {
2018-02-06 13:10:43 +01:00
if ( ! _ . get ( await store . get ( { key : 'grant' } ) , [ provider , 'enabled' ] ) ) {
2018-01-29 13:12:49 +01:00
return ctx . badRequest ( null , 'This provider is disabled.' ) ;
}
2017-11-14 11:49:19 +01:00
// Connect the user thanks to the third-party provider.
2018-01-25 15:04:42 +01:00
let user , error ;
2018-01-25 11:52:17 +01:00
try {
2018-01-25 15:04:42 +01:00
[ user , error ] = await strapi . plugins [ 'users-permissions' ] . services . providers . connect ( provider , ctx . query ) ;
2018-01-25 11:52:17 +01:00
} catch ( [ user , error ] ) {
2018-01-15 17:58:11 +01:00
return ctx . badRequest ( null , ( error === 'array' ) ? ( ctx . request . admin ? error [ 0 ] : error [ 1 ] ) : error ) ;
2018-01-15 15:19:59 +01:00
}
2018-01-25 15:04:42 +01:00
if ( ! user ) {
return ctx . badRequest ( null , ( error === 'array' ) ? ( ctx . request . admin ? error [ 0 ] : error [ 1 ] ) : error ) ;
}
2018-01-12 15:20:13 +01:00
ctx . send ( {
2018-02-08 14:37:54 +01:00
jwt : strapi . plugins [ 'users-permissions' ] . services . jwt . issue ( _ . pick ( user , [ '_id' , 'id' ] ) ) ,
2018-01-12 15:20:13 +01:00
user : _ . omit ( user . toJSON ? user . toJSON ( ) : user , [ 'password' , 'resetPasswordToken' ] )
} ) ;
2017-11-14 11:49:19 +01:00
}
2017-11-16 14:12:03 +01:00
} ,
2017-12-07 15:21:54 +01:00
changePassword : async ( ctx ) => {
const params = _ . assign ( { } , ctx . request . body , ctx . params ) ;
2017-11-16 14:12:03 +01:00
2017-12-07 15:21:54 +01:00
if ( params . password && params . passwordConfirmation && params . password === params . passwordConfirmation && params . code ) {
const user = await strapi . query ( 'user' , 'users-permissions' ) . findOne ( { resetPasswordToken : params . code } ) ;
2017-11-16 14:12:03 +01:00
2017-12-07 15:21:54 +01:00
if ( ! user ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.code.provide' } ] } ] : 'Incorrect code provided.' ) ;
}
2017-11-16 14:12:03 +01:00
2017-12-07 15:21:54 +01:00
// Delete the current code
user . resetPasswordToken = null ;
2017-11-16 14:12:03 +01:00
2017-12-07 15:21:54 +01:00
user . password = await strapi . plugins [ 'users-permissions' ] . services . user . hashPassword ( params ) ;
2017-11-16 14:29:49 +01:00
2018-06-14 17:15:49 +02:00
// Remove relations data to update user code.
const data = _ . omit ( user , strapi . plugins [ 'users-permissions' ] . models . user . associations . map ( ast => ast . alias ) ) ;
2017-12-07 15:21:54 +01:00
// Update the user.
2018-06-14 17:15:49 +02:00
await strapi . query ( 'user' , 'users-permissions' ) . update ( data ) ;
2017-12-06 11:47:39 +01:00
ctx . send ( {
2018-02-08 14:37:54 +01:00
jwt : strapi . plugins [ 'users-permissions' ] . services . jwt . issue ( _ . pick ( user . toJSON ? user . toJSON ( ) : user , [ '_id' , 'id' ] ) ) ,
2017-12-07 14:56:25 +01:00
user : _ . omit ( user . toJSON ? user . toJSON ( ) : user , [ 'password' , 'resetPasswordToken' ] )
2017-12-06 11:47:39 +01:00
} ) ;
2017-12-07 15:21:54 +01:00
} else if ( params . password && params . passwordConfirmation && params . password !== params . passwordConfirmation ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.password.matching' } ] } ] : 'Passwords do not match.' ) ;
} else {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.params.provide' } ] } ] : 'Incorrect params provided.' ) ;
2017-12-06 11:47:39 +01:00
}
2017-11-16 18:00:15 +01:00
} ,
2018-01-25 09:59:24 +01:00
connect : async ( ctx , next ) => {
2018-02-06 13:10:43 +01:00
const grantConfig = await strapi . store ( {
2018-02-13 15:04:21 +01:00
environment : '' ,
2018-02-06 13:10:43 +01:00
type : 'plugin' ,
name : 'users-permissions' ,
key : 'grant'
} ) . get ( ) ;
2018-02-01 18:12:38 +01:00
_ . defaultsDeep ( grantConfig , {
2018-01-25 09:59:24 +01:00
server : {
protocol : 'http' ,
2018-01-25 11:53:22 +01:00
host : ` ${ strapi . config . currentEnvironment . server . host } : ${ strapi . config . currentEnvironment . server . port } `
2018-01-25 09:59:24 +01:00
}
} ) ;
2018-05-11 22:18:02 +02:00
const provider = process . platform === 'win32' ? ctx . request . url . split ( '\\' ) [ 2 ] : ctx . request . url . split ( '/' ) [ 2 ] ;
2018-02-01 18:12:38 +01:00
const config = grantConfig [ provider ] ;
2018-01-25 09:59:24 +01:00
if ( ! _ . get ( config , 'enabled' ) ) {
return ctx . badRequest ( null , 'This provider is disabled.' ) ;
}
2018-02-09 16:36:23 +01:00
const Grant = require ( 'grant-koa' ) ;
2018-02-01 18:12:38 +01:00
const grant = new Grant ( grantConfig ) ;
2018-01-25 09:59:24 +01:00
return strapi . koaMiddlewares . compose ( grant . middleware ) ( ctx , next ) ;
} ,
2017-11-16 18:00:15 +01:00
forgotPassword : async ( ctx ) => {
2017-12-07 18:16:15 +01:00
const { email , url } = ctx . request . body ;
2017-11-16 18:00:15 +01:00
// Find the user user thanks to his email.
const user = await strapi . query ( 'user' , 'users-permissions' ) . findOne ( { email } ) ;
// User not found.
if ( ! user ) {
2017-12-06 11:38:00 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.user.not-exist' } ] } ] : 'This email does not exist.' ) ;
2017-11-16 18:00:15 +01:00
}
// Generate random token.
const resetPasswordToken = crypto . randomBytes ( 64 ) . toString ( 'hex' ) ;
2017-11-17 11:41:23 +01:00
// Set the property code.
2017-11-16 18:00:15 +01:00
user . resetPasswordToken = resetPasswordToken ;
2018-02-13 15:59:06 +01:00
const settings = ( await strapi . store ( {
environment : '' ,
type : 'plugin' ,
name : 'users-permissions'
} ) . get ( { key : 'email' } ) ) [ 'reset_password' ] . options ;
2017-12-04 14:11:00 +01:00
2018-01-25 08:38:46 +01:00
settings . message = await strapi . plugins [ 'users-permissions' ] . services . userspermissions . template ( settings . message , {
2018-01-26 10:18:36 +01:00
URL : url ,
2018-02-03 00:30:01 +11:00
USER : _ . omit ( user . toJSON ? user . toJSON ( ) : user , [ 'password' , 'resetPasswordToken' , 'role' , 'provider' ] ) ,
2018-01-26 10:18:36 +01:00
TOKEN : resetPasswordToken
2018-01-15 14:50:53 +01:00
} ) ;
2017-12-04 14:11:00 +01:00
2018-01-25 08:38:46 +01:00
settings . object = await strapi . plugins [ 'users-permissions' ] . services . userspermissions . template ( settings . object , {
2018-02-03 00:30:01 +11:00
USER : _ . omit ( user . toJSON ? user . toJSON ( ) : user , [ 'password' , 'resetPasswordToken' , 'role' , 'provider' ] )
2018-01-18 10:03:29 +01:00
} ) ;
2017-12-04 14:00:09 +01:00
try {
2018-01-15 14:50:53 +01:00
// Send an email to the user.
2017-12-04 14:00:09 +01:00
await strapi . plugins [ 'email' ] . services . email . send ( {
to : user . email ,
2018-01-25 08:38:46 +01:00
from : ( settings . from . email || settings . from . name ) ? ` " ${ settings . from . name } " < ${ settings . from . email } > ` : undefined ,
2018-01-19 13:34:55 +01:00
replyTo : settings . response _email ,
2018-01-25 08:38:46 +01:00
subject : settings . object ,
text : settings . message ,
html : settings . message
2017-12-04 14:00:09 +01:00
} ) ;
} catch ( err ) {
return ctx . badRequest ( null , err ) ;
}
2018-06-14 17:15:49 +02:00
// Remove relations data to update user code.
const data = _ . omit ( user , strapi . plugins [ 'users-permissions' ] . models . user . associations . map ( ast => ast . alias ) ) ;
2017-11-16 18:00:15 +01:00
// Update the user.
2018-06-14 17:15:49 +02:00
await strapi . query ( 'user' , 'users-permissions' ) . update ( data ) ;
2017-11-16 18:00:15 +01:00
2017-12-04 13:40:07 +01:00
ctx . send ( { ok : true } ) ;
2017-11-17 11:41:23 +01:00
} ,
2017-12-07 15:21:54 +01:00
register : async ( ctx ) => {
2018-03-12 16:06:54 +01:00
const settings = await strapi . store ( {
2018-02-13 15:04:21 +01:00
environment : '' ,
2018-02-06 13:10:43 +01:00
type : 'plugin' ,
name : 'users-permissions' ,
key : 'advanced'
2018-03-12 16:06:54 +01:00
} ) . get ( ) ;
if ( ! settings . allow _register ) {
2018-01-25 18:12:29 +01:00
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.advanced.allow_register' } ] } ] : 'Register action is currently disabled.' ) ;
2018-01-15 15:19:59 +01:00
}
2017-12-07 15:21:54 +01:00
const params = _ . assign ( ctx . request . body , {
provider : 'local'
} ) ;
2017-11-17 11:41:23 +01:00
2017-12-07 15:21:54 +01:00
// Password is required.
if ( ! params . password ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.password.provide' } ] } ] : 'Please provide your password.' ) ;
}
2017-11-17 11:41:23 +01:00
2017-12-07 15:21:54 +01:00
// Throw an error if the password selected by the user
// contains more than two times the symbol '$'.
if ( strapi . plugins [ 'users-permissions' ] . services . user . isHashed ( params . password ) ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.password.format' } ] } ] : 'Your password cannot contain more than three times the symbol `$`.' ) ;
}
2017-11-17 11:41:23 +01:00
2018-01-23 18:54:17 +01:00
// Retrieve root role.
const root = await strapi . query ( 'role' , 'users-permissions' ) . findOne ( { type : 'root' } , [ 'users' ] ) ;
2018-02-28 18:10:30 +01:00
const users = root . users || [ ] ;
2018-01-23 18:54:17 +01:00
2017-12-07 15:21:54 +01:00
// First, check if the user is the first one to register as admin.
2018-02-28 18:10:30 +01:00
const hasAdmin = users . length > 0 ;
2017-11-17 11:41:23 +01:00
2017-12-07 15:21:54 +01:00
// Check if the user is the first to register
2018-03-12 16:06:54 +01:00
const role = hasAdmin === false ? root : await strapi . query ( 'role' , 'users-permissions' ) . findOne ( { type : settings . default _role } , [ ] ) ;
2018-01-17 18:50:12 +01:00
if ( ! role ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.role.notFound' } ] } ] : 'Impossible to find the root role.' ) ;
2017-12-07 15:21:54 +01:00
}
2017-11-17 11:41:23 +01:00
2018-01-23 13:35:51 +01:00
// Check if the provided identifier is an email or not.
const isEmail = emailRegExp . test ( params . identifier ) ;
2018-01-24 11:52:09 +01:00
2018-01-23 13:35:51 +01:00
if ( isEmail ) {
params . identifier = params . identifier . toLowerCase ( ) ;
}
2018-01-24 11:52:09 +01:00
2018-01-17 18:50:12 +01:00
params . role = role . _id || role . id ;
2017-12-07 15:21:54 +01:00
params . password = await strapi . plugins [ 'users-permissions' ] . services . user . hashPassword ( params ) ;
2018-01-15 17:58:11 +01:00
const user = await strapi . query ( 'user' , 'users-permissions' ) . findOne ( {
email : params . email
} ) ;
if ( user && user . provider === params . provider ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.email.taken' } ] } ] : 'Email is already taken.' ) ;
}
if ( user && user . provider !== params . provider && strapi . plugins [ 'users-permissions' ] . config . advanced . unique _email ) {
return ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : 'Auth.form.error.email.taken' } ] } ] : 'Email is already taken.' ) ;
}
2017-12-07 15:21:54 +01:00
try {
const user = await strapi . query ( 'user' , 'users-permissions' ) . create ( params ) ;
2017-11-17 11:41:23 +01:00
2017-11-20 16:28:50 +01:00
ctx . send ( {
2018-02-08 14:37:54 +01:00
jwt : strapi . plugins [ 'users-permissions' ] . services . jwt . issue ( _ . pick ( user . toJSON ? user . toJSON ( ) : user , [ '_id' , 'id' ] ) ) ,
2017-12-07 14:56:25 +01:00
user : _ . omit ( user . toJSON ? user . toJSON ( ) : user , [ 'password' , 'resetPasswordToken' ] )
2017-11-20 16:28:50 +01:00
} ) ;
2017-12-07 15:21:54 +01:00
} catch ( err ) {
const adminError = _ . includes ( err . message , 'username' ) ? 'Auth.form.error.username.taken' : 'Auth.form.error.email.taken' ;
ctx . badRequest ( null , ctx . request . admin ? [ { messages : [ { id : adminError } ] } ] : err . message ) ;
2017-11-17 11:41:23 +01:00
}
2017-11-14 11:49:19 +01:00
}
} ;