Просмотр исходного кода

Merge pull request #543 from weseek/imprv/add-ldap-attr-mapping-mail

Imprv/add ldap attr mapping mail
Yuki Takei 7 лет назад
Родитель
Сommit
8c4c2be850

+ 1 - 0
lib/form/admin/securityPassportLdap.js

@@ -17,6 +17,7 @@ module.exports = form(
   field('settingForm[security:passport-ldap:searchFilter]'),
   field('settingForm[security:passport-ldap:attrMapUsername]'),
   field('settingForm[security:passport-ldap:attrMapName]'),
+  field('settingForm[security:passport-ldap:attrMapMail]'),
   field('settingForm[security:passport-ldap:isSameUsernameTreatedAsIdenticalUser]').trim().toBooleanStrict(),
   field('settingForm[security:passport-ldap:groupSearchBase]'),
   field('settingForm[security:passport-ldap:groupSearchFilter]'),

+ 2 - 1
lib/locales/en-US/translation.json

@@ -362,7 +362,8 @@
       "search_filter_example1": "Match with 'uid' or 'mail'",
       "search_filter_example2": "Match with 'sAMAccountName' for Active Directory",
       "username_detail": "Specification of mappings for <code>username</code> when creating new users",
-      "name_detail": "Specification of mappings for <code>name</code> when creating new users",
+      "name_detail": "Specification of mappings for full name when creating new users",
+      "mail_detail": "Specification of mappings for mail address when creating new users",
       "group_search_base_DN": "Group Search Base DN",
       "group_search_base_DN_detail": "The base DN from which to search for groups. If defined, also <code>Group Search Filter</code> must be defined for the search to work.",
       "group_search_filter": "Group Search Filter",

+ 2 - 1
lib/locales/ja/translation.json

@@ -379,7 +379,8 @@
       "search_filter_example1": "'uid' または 'mail' に一致",
       "search_filter_example2": "'sAMAccountName' に一致 (Active Directory)",
       "username_detail": "新規ユーザーのアカウント名(<code>username</code>)に関連付ける属性",
-      "name_detail": "新規ユーザーの表示名(<code>name</code>)に関連付ける属性",
+      "name_detail": "新規ユーザーの表示名に関連付ける属性",
+      "mail_detail": "新規ユーザーのメールアドレスに関連付ける属性",
       "group_search_base_DN": "グループ検索ベース DN",
       "group_search_base_DN_detail": "グループ検索を実行するベース DN。利用する場合は <code>グループ検索フィルター</code> も入力する必要があります。",
       "group_search_filter": "グループ検索フィルター",

+ 1 - 0
lib/models/config.js

@@ -61,6 +61,7 @@ module.exports = function(crowi) {
       'security:passport-ldap:searchFilter' : undefined,
       'security:passport-ldap:attrMapUsername' : undefined,
       'security:passport-ldap:attrMapName' : undefined,
+      'security:passport-ldap:attrMapMail' : undefined,
       'security:passport-ldap:groupSearchBase' : undefined,
       'security:passport-ldap:groupSearchFilter' : undefined,
       'security:passport-ldap:groupDnProperty' : undefined,

+ 4 - 2
lib/models/external-account.js

@@ -65,10 +65,12 @@ class ExternalAccount {
    * @param {string} providerType
    * @param {string} accountId
    * @param {object} usernameToBeRegistered the username of User entity that will be created when accountId is not found
+   * @param {object} nameToBeRegistered the name of User entity that will be created when accountId is not found
+   * @param {object} mailToBeRegistered the mail of User entity that will be created when accountId is not found
    * @returns {Promise<ExternalAccount>}
    * @memberof ExternalAccount
    */
-  static findOrRegister(providerType, accountId, usernameToBeRegistered, nameToBeRegistered) {
+  static findOrRegister(providerType, accountId, usernameToBeRegistered, nameToBeRegistered, mailToBeRegistered) {
 
     return this.findOne({ providerType, accountId })
       .then(account => {
@@ -92,7 +94,7 @@ class ExternalAccount {
 
             // create a new User with STATUS_ACTIVE
             debug(`ExternalAccount '${accountId}' is not found, it is going to be registered.`);
-            return User.createUser(nameToBeRegistered, usernameToBeRegistered, undefined, undefined, undefined, User.STATUS_ACTIVE);
+            return User.createUser(nameToBeRegistered, usernameToBeRegistered, mailToBeRegistered, undefined, undefined, User.STATUS_ACTIVE);
           })
           .then(newUser => {
             return this.associate(providerType, accountId, newUser);

+ 10 - 5
lib/models/user.js

@@ -680,13 +680,19 @@ module.exports = function(crowi) {
     );
   };
 
-  userSchema.statics.createUserByEmailAndPasswordAndStatus = function(name, username, email, password, lang, status, callback) {
-    var User = this
+  userSchema.statics.createUserByEmailAndPasswordAndStatus = async function(name, username, email, password, lang, status, callback) {
+    const User = this
       , newUser = new User();
 
+    // check email duplication because email must be unique
+    const count = await this.count({ email });
+    if (count > 0) {
+      email = generateRandomEmail();
+    }
+
     newUser.name = name;
     newUser.username = username;
-    newUser.email = email || generateRandomEmail();   // don't set undefined for backward compatibility -- 2017.12.27 Yuki Takei
+    newUser.email = email;
     if (password != null) {
       newUser.setPassword(password);
     }
@@ -710,9 +716,8 @@ module.exports = function(crowi) {
   };
 
   /**
-   * A wrapper function of createUserByEmailAndPasswordAndStatus
+   * A wrapper function of createUserByEmailAndPasswordAndStatus with callback
    *
-   * @return {Promise<User>}
    */
   userSchema.statics.createUserByEmailAndPassword = function(name, username, email, password, lang, callback) {
     this.createUserByEmailAndPasswordAndStatus(name, username, email, password, lang, undefined, callback);

+ 6 - 2
lib/routes/login-passport.js

@@ -95,12 +95,15 @@ module.exports = function(crowi, app) {
     const ldapAccountId = passportService.getLdapAccountIdFromReq(req);
     const attrMapUsername = passportService.getLdapAttrNameMappedToUsername();
     const attrMapName = passportService.getLdapAttrNameMappedToName();
+    const attrMapMail = passportService.getLdapAttrNameMappedToMail();
     const usernameToBeRegistered = ldapAccountInfo[attrMapUsername];
     const nameToBeRegistered = ldapAccountInfo[attrMapName];
+    const mailToBeRegistered = ldapAccountInfo[attrMapMail];
     const userInfo = {
       'id': ldapAccountId,
       'username': usernameToBeRegistered,
-      'name': nameToBeRegistered
+      'name': nameToBeRegistered,
+      'email': mailToBeRegistered,
     };
 
     const externalAccount = await getOrCreateUser(req, res, next, userInfo, providerId);
@@ -304,7 +307,8 @@ module.exports = function(crowi, app) {
         providerId,
         userInfo.id,
         userInfo.username,
-        userInfo.name
+        userInfo.name,
+        userInfo.email,
       );
       return externalAccount;
     }

+ 10 - 0
lib/service/passport.js

@@ -154,6 +154,16 @@ class PassportService {
     const config = this.crowi.config;
     return config.crowi['security:passport-ldap:attrMapName'] || '';
   }
+  /**
+   * return attribute name for mapping to name of Crowi DB
+   *
+   * @returns
+   * @memberof PassportService
+   */
+  getLdapAttrNameMappedToMail() {
+    const config = this.crowi.config;
+    return config.crowi['security:passport-ldap:attrMapMail'] || 'mail';
+  }
 
   /**
    * CAUTION: this method is capable to use only when `req.body.loginForm` is not null

+ 17 - 6
lib/views/admin/widget/passport/ldap.html

@@ -120,7 +120,6 @@
       <h4>Attribute Mapping ({{ t("security_setting.optional") }})</h4>
 
       <div class="form-group">
-        <div class="row">
         <label for="settingForm[security:passport-ldap:attrMapUsername]" class="col-xs-3 control-label">username</label>
         <div class="col-xs-6">
           <input class="form-control" type="text" placeholder="Default: uid"
@@ -131,9 +130,9 @@
             </small>
           </p>
         </div>
-        </div>
+      </div>
 
-        <div class="row">
+      <div class="form-group">
         <div class="col-xs-6 col-xs-offset-3">
           <div class="checkbox checkbox-info">
             <input type="checkbox" id="cbSameUsernameTreatedAsIdenticalUser" name="settingForm[security:passport-ldap:isSameUsernameTreatedAsIdenticalUser]" value="1"
@@ -148,11 +147,23 @@
             </p>
           </div>
         </div>
+      </div>
+
+      <div class="form-group">
+        <label for="settingForm[security:passport-ldap:attrMapMail]" class="col-xs-3 control-label">Mail</label>
+        <div class="col-xs-6">
+          <input class="form-control" type="text" placeholder="Default: mail"
+              name="settingForm[security:passport-ldap:attrMapMail]" value="{{ settingForm['security:passport-ldap:attrMapMail'] || '' }}">
+          <p class="help-block">
+            <small>
+              {{ t("security_setting.ldap.mail_detail") }}
+            </small>
+          </p>
         </div>
       </div>
 
-      <div class="row">
-        <label for="settingForm[security:passport-ldap:attrMapName]" class="col-xs-3 control-label">name</label>
+      <div class="form-group">
+        <label for="settingForm[security:passport-ldap:attrMapName]" class="col-xs-3 control-label">Name</label>
         <div class="col-xs-6">
           <input class="form-control" type="text"
               name="settingForm[security:passport-ldap:attrMapName]" value="{{ settingForm['security:passport-ldap:attrMapName'] || '' }}">
@@ -162,7 +173,7 @@
             </small>
           </p>
         </div>
-        </div>
+      </div>
 
       <h4>{{ t("security_setting.ldap.group_search_filter") }} ({{ t("security_setting.optional") }})</h4>