فهرست منبع

Merge branch 'master' of https://github.com/codelibs/fess

y_fujita 9 سال پیش
والد
کامیت
3bceff62d8

+ 5 - 0
pom.xml

@@ -494,6 +494,11 @@
 			<artifactId>jsonic</artifactId>
 			<version>1.3.8</version>
 		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>2.6.3</version>
+		</dependency>
 
 		<!-- template -->
 		<dependency>

+ 2 - 0
src/main/java/org/codelibs/fess/Constants.java

@@ -328,4 +328,6 @@ public class Constants extends CoreLibConstants {
     public static final String ELASTICSEARCH_WEB_URL = "http://localhost:9201";
 
     public static final String ES_API_ACCESS_TOKEN = "esApiAccessToken";
+
+    public static final String ADMIN_PACKAGE = "org.codelibs.fess.app.web.admin";
 }

+ 4 - 2
src/main/java/org/codelibs/fess/app/web/admin/group/AdminGroupAction.java

@@ -216,7 +216,10 @@ public class AdminGroupAction extends FessAdminAction {
         switch (form.crudMode) {
         case CrudMode.CREATE:
             if (form instanceof CreateForm) {
-                return OptionalEntity.of(new Group());
+                return OptionalEntity.of(new Group()).map(entity -> {
+                    entity.setId(Base64.getEncoder().encodeToString(form.name.getBytes(Constants.CHARSET_UTF_8)));
+                    return entity;
+                });
             }
             break;
         case CrudMode.EDIT:
@@ -233,7 +236,6 @@ public class AdminGroupAction extends FessAdminAction {
     protected OptionalEntity<Group> createGroup(final CreateForm form) {
         return getEntity(form).map(entity -> {
             copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
-            entity.setId(Base64.getEncoder().encodeToString(entity.getName().getBytes(Constants.CHARSET_UTF_8)));
             return entity;
         });
     }

+ 4 - 2
src/main/java/org/codelibs/fess/app/web/admin/role/AdminRoleAction.java

@@ -216,7 +216,10 @@ public class AdminRoleAction extends FessAdminAction {
         switch (form.crudMode) {
         case CrudMode.CREATE:
             if (form instanceof CreateForm) {
-                return OptionalEntity.of(new Role());
+                return OptionalEntity.of(new Role()).map(entity -> {
+                    entity.setId(Base64.getEncoder().encodeToString(form.name.getBytes(Constants.CHARSET_UTF_8)));
+                    return entity;
+                });
             }
             break;
         case CrudMode.EDIT:
@@ -233,7 +236,6 @@ public class AdminRoleAction extends FessAdminAction {
     protected OptionalEntity<Role> createRole(final CreateForm form) {
         return getEntity(form).map(entity -> {
             copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
-            entity.setId(Base64.getEncoder().encodeToString(entity.getName().getBytes(Constants.CHARSET_UTF_8)));
             return entity;
         });
     }

+ 16 - 8
src/main/java/org/codelibs/fess/app/web/admin/user/AdminUserAction.java

@@ -31,6 +31,7 @@ import org.codelibs.fess.app.web.CrudMode;
 import org.codelibs.fess.app.web.base.FessAdminAction;
 import org.codelibs.fess.es.user.exentity.User;
 import org.codelibs.fess.helper.SystemHelper;
+import org.codelibs.fess.lang3.ArrayUtils;
 import org.dbflute.optional.OptionalEntity;
 import org.dbflute.optional.OptionalThing;
 import org.lastaflute.web.Execute;
@@ -202,6 +203,8 @@ public class AdminUserAction extends FessAdminAction {
     public HtmlResponse create(final CreateForm form) {
         verifyCrudMode(form.crudMode, CrudMode.CREATE);
         validate(form, messages -> {}, toEditHtml());
+        verifyPassword(form);
+        storePassword(form);
         createUser(form).ifPresent(entity -> {
             userService.store(entity);
             saveInfo(messages -> messages.addSuccessCrudCreateCrudTable(GLOBAL));
@@ -215,7 +218,10 @@ public class AdminUserAction extends FessAdminAction {
     public HtmlResponse update(final EditForm form) {
         verifyCrudMode(form.crudMode, CrudMode.EDIT);
         validate(form, messages -> {}, toEditHtml());
-        //verifyPassword(form);
+        verifyPassword(form);
+        if (StringUtil.isNotBlank(form.password)) {
+            storePassword(form);
+        }
         createUser(form).ifPresent(entity -> {
             userService.store(entity);
             saveInfo(messages -> messages.addSuccessCrudUpdateCrudTable(GLOBAL));
@@ -240,16 +246,14 @@ public class AdminUserAction extends FessAdminAction {
     }
 
     //===================================================================================
-    //                                                                        Assist Logic
-    //                                                                        ============
+    //                                                                       Assist Logic
+    //                                                                       ============
     private OptionalEntity<User> getEntity(final CreateForm form) {
         switch (form.crudMode) {
         case CrudMode.CREATE:
             if (form instanceof CreateForm) {
                 return OptionalEntity.of(new User()).map(entity -> {
-                    sessionManager.getAttribute(TEMPORARY_PASSWORD, String.class).ifPresent(password -> {
-                        entity.setPassword(password);
-                    });
+                    entity.setId(Base64.getEncoder().encodeToString(form.name.getBytes(Constants.CHARSET_UTF_8)));
                     return entity;
                 });
             }
@@ -267,8 +271,10 @@ public class AdminUserAction extends FessAdminAction {
 
     protected OptionalEntity<User> createUser(final CreateForm form) {
         return getEntity(form).map(entity -> {
-            copyBeanToBean(form, entity, op -> op.exclude(Constants.COMMON_CONVERSION_RULE));
-            entity.setId(Base64.getEncoder().encodeToString(entity.getName().getBytes(Constants.CHARSET_UTF_8)));
+            copyBeanToBean(form, entity, op -> op.exclude(ArrayUtils.addAll(Constants.COMMON_CONVERSION_RULE, "password")));
+            sessionManager.getAttribute(TEMPORARY_PASSWORD, String.class).ifPresent(password -> {
+                entity.setPassword(password);
+            });
             return entity;
         });
     }
@@ -294,11 +300,13 @@ public class AdminUserAction extends FessAdminAction {
 
     protected void verifyPassword(final CreateForm form) {
         if (form.crudMode == CrudMode.CREATE && StringUtil.isBlank(form.password)) {
+            form.confirmPassword = null;
             throwValidationError(messages -> {
                 messages.addErrorsBlankPassword(GLOBAL);
             }, toEditHtml());
         }
         if (form.password != null && !form.password.equals(form.confirmPassword)) {
+            form.confirmPassword = null;
             throwValidationError(messages -> {
                 messages.addErrorsInvalidConfirmPassword(GLOBAL);
             }, toEditHtml());

+ 16 - 0
src/main/java/org/codelibs/fess/app/web/base/FessAdminAction.java

@@ -21,12 +21,15 @@ import javax.servlet.ServletContext;
 
 import org.codelibs.core.beans.util.BeanUtil;
 import org.codelibs.core.beans.util.CopyOptions;
+import org.codelibs.fess.exception.UserRoleLoginException;
 import org.codelibs.fess.mylasta.action.FessMessages;
 import org.dbflute.optional.OptionalThing;
 import org.lastaflute.di.util.LdiFileUtil;
+import org.lastaflute.web.callback.ActionRuntime;
 import org.lastaflute.web.callback.TypicalEmbeddedKeySupplier;
 import org.lastaflute.web.callback.TypicalKey.TypicalSimpleEmbeddedKeySupplier;
 import org.lastaflute.web.login.LoginManager;
+import org.lastaflute.web.response.ActionResponse;
 import org.lastaflute.web.util.LaServletContextUtil;
 import org.lastaflute.web.validation.VaMessenger;
 
@@ -106,4 +109,17 @@ public abstract class FessAdminAction extends FessBaseAction {
             }
         };
     }
+
+    // ===================================================================================
+    //                                                                               Hook
+    //                                                                              ======
+    @Override
+    public ActionResponse godHandPrologue(final ActionRuntime runtime) {
+        try {
+            return super.godHandPrologue(runtime);
+        } catch (UserRoleLoginException e) {
+            return redirect(e.getActionClass());
+        }
+    }
+
 }

+ 1 - 1
src/main/java/org/codelibs/fess/app/web/base/FessBaseAction.java

@@ -77,7 +77,7 @@ public abstract class FessBaseAction extends TypicalAction // has several interf
     // to suppress unexpected override by sub-class
     // you should remove the 'final' if you need to override this
     @Override
-    public final ActionResponse godHandPrologue(final ActionRuntime runtime) {
+    public ActionResponse godHandPrologue(final ActionRuntime runtime) {
         return super.godHandPrologue(runtime);
     }
 

+ 10 - 1
src/main/java/org/codelibs/fess/app/web/base/login/FessLoginAssist.java

@@ -17,9 +17,12 @@ package org.codelibs.fess.app.web.base.login;
 
 import javax.annotation.Resource;
 
+import org.codelibs.fess.Constants;
+import org.codelibs.fess.app.web.RootAction;
 import org.codelibs.fess.app.web.login.LoginAction;
 import org.codelibs.fess.es.user.exbhv.UserBhv;
 import org.codelibs.fess.es.user.exentity.User;
+import org.codelibs.fess.exception.UserRoleLoginException;
 import org.codelibs.fess.mylasta.action.FessUserBean;
 import org.codelibs.fess.mylasta.direction.FessConfig;
 import org.dbflute.optional.OptionalEntity;
@@ -104,7 +107,13 @@ public class FessLoginAssist extends TypicalLoginAssist<String, FessUserBean, Us
 
     @Override
     protected void checkPermission(final LoginHandlingResource resource) throws LoginRequiredException {
-        super.checkPermission(resource);
+        if (resource.getActionClass().getName().startsWith(Constants.ADMIN_PACKAGE)) {
+            getSessionUserBean().ifPresent(user -> {
+                if (!user.hasRoles(fessConfig.getAuthenticationAdminRoles().split(","))) {
+                    throw new UserRoleLoginException(RootAction.class);
+                }
+            });
+        }
     }
 
     // ===================================================================================

+ 10 - 1
src/main/java/org/codelibs/fess/app/web/login/LoginAction.java

@@ -18,6 +18,7 @@ package org.codelibs.fess.app.web.login;
 import org.codelibs.fess.app.web.admin.dashboard.AdminDashboardAction;
 import org.codelibs.fess.app.web.base.FessSearchAction;
 import org.lastaflute.web.Execute;
+import org.lastaflute.web.login.exception.LoginFailureException;
 import org.lastaflute.web.response.HtmlResponse;
 
 public class LoginAction extends FessSearchAction {
@@ -55,7 +56,15 @@ public class LoginAction extends FessSearchAction {
         });
         final String email = form.username;
         final String password = form.password;
-        return fessLoginAssist.loginRedirect(email, password, op -> {}, () -> getHtmlResponse());
+        form.clearSecurityInfo();
+        try {
+            return fessLoginAssist.loginRedirect(email, password, op -> {}, () -> getHtmlResponse());
+        } catch (LoginFailureException lfe) {
+            throwValidationError(messages -> messages.addErrorsLoginError(GLOBAL), () -> {
+                return asHtml(path_Login_IndexJsp);
+            });
+        }
+        return redirect(getClass());
     }
 
 }

+ 32 - 14
src/main/java/org/codelibs/fess/es/client/FessEsClient.java

@@ -163,6 +163,8 @@ import org.elasticsearch.threadpool.ThreadPool;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.io.BaseEncoding;
 
 public class FessEsClient implements Client {
@@ -396,21 +398,37 @@ public class FessEsClient implements Client {
                 if (ResourceUtil.isExist(dataPath)) {
                     try {
                         final BulkRequestBuilder builder = client.prepareBulk();
-                        Arrays.stream(FileUtil.readUTF8(dataPath).split("\n")).reduce((prev, line) -> {
-                            if (StringUtil.isBlank(prev)) {
-                                if (line.startsWith("{\"index\":{")) {
-                                    return line;
-                                } else if (line.startsWith("{\"update\":{")) {
-                                    return line;
-                                } else if (line.startsWith("{\"delete\":{")) {
+                        ObjectMapper mapper = new ObjectMapper();
+                        Arrays.stream(FileUtil.readUTF8(dataPath).split("\n")).reduce(
+                                (prev, line) -> {
+                                    try {
+                                        if (StringUtil.isBlank(prev)) {
+                                            Map<String, Map<String, String>> result =
+                                                    mapper.readValue(line, new TypeReference<Map<String, Map<String, String>>>() {
+                                                    });
+                                            if (result.keySet().contains("index")) {
+                                                return line;
+                                            } else if (result.keySet().contains("update")) {
+                                                return line;
+                                            } else if (result.keySet().contains("delete")) {
+                                                return StringUtil.EMPTY;
+                                            }
+                                        } else {
+                                            Map<String, Map<String, String>> result =
+                                                    mapper.readValue(prev, new TypeReference<Map<String, Map<String, String>>>() {
+                                                    });
+                                            if (result.keySet().contains("index")) {
+                                                final IndexRequestBuilder requestBuilder =
+                                                        client.prepareIndex(configIndex, configType, result.get("index").get("_id"))
+                                                                .setSource(line);
+                                                builder.add(requestBuilder);
+                                            }
+                                        }
+                                    } catch (Exception e) {
+                                        logger.warn("Failed to parse " + dataPath.toString());
+                                    }
                                     return StringUtil.EMPTY;
-                                }
-                            } else if (prev.startsWith("{\"index\":{")) {
-                                final IndexRequestBuilder requestBuilder = client.prepareIndex(configIndex, configType).setSource(line);
-                                builder.add(requestBuilder);
-                            }
-                            return StringUtil.EMPTY;
-                        });
+                                });
                         final BulkResponse response = builder.execute().actionGet();
                         if (response.hasFailures()) {
                             logger.warn("Failed to register " + dataPath.toString() + ": " + response.buildFailureMessage());

+ 38 - 0
src/main/java/org/codelibs/fess/exception/UserRoleLoginException.java

@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012-2015 CodeLibs Project and the Others.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.codelibs.fess.exception;
+
+import org.codelibs.fess.app.web.RootAction;
+
+public class UserRoleLoginException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    private Class<?> actionClass;
+
+    public UserRoleLoginException(Class<RootAction> actionClass) {
+        this.actionClass = actionClass;
+    }
+
+    public Class<?> getActionClass() {
+        return actionClass;
+    }
+
+    @Override
+    public Throwable fillInStackTrace() {
+        return null;
+    }
+}

+ 15 - 0
src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java

@@ -25,6 +25,9 @@ public interface FessConfig extends FessEnv {
     /** The key of the configuration. e.g. Fess */
     String DOMAIN_TITLE = "domain.title";
 
+    /** The key of the configuration. e.g. admin */
+    String AUTHENTICATION_ADMIN_ROLES = "authentication.admin.roles";
+
     /** The key of the configuration. e.g. / */
     String COOKIE_DEFAULT_PATH = "cookie.default.path";
 
@@ -76,6 +79,14 @@ public interface FessConfig extends FessEnv {
      */
     String getDomainTitle();
 
+    /**
+     * Get the value for the key 'authentication.admin.roles'. <br>
+     * The value is, e.g. admin <br>
+     * comment: ------
+     * @return The value of found property. (NotNull: if not found, exception but basically no way)
+     */
+    String getAuthenticationAdminRoles();
+
     /**
      * Get the value for the key 'cookie.default.path'. <br>
      * The value is, e.g. / <br>
@@ -204,6 +215,10 @@ public interface FessConfig extends FessEnv {
             return get(FessConfig.DOMAIN_TITLE);
         }
 
+        public String getAuthenticationAdminRoles() {
+            return get(FessConfig.AUTHENTICATION_ADMIN_ROLES);
+        }
+
         public String getCookieDefaultPath() {
             return get(FessConfig.COOKIE_DEFAULT_PATH);
         }

+ 6 - 0
src/main/resources/fess_config.properties

@@ -17,6 +17,11 @@ domain.title = Fess
 # ========================================================================================
 #                                                                                     Web
 #                                                                                    =====
+# ----------------------------------------------------------
+#                                                 Permission
+#                                                     ------
+authentication.admin.roles=admin
+
 # ----------------------------------------------------------
 #                                                     Cookie
 #                                                     ------
@@ -51,3 +56,4 @@ paging.page.range.fill.limit = true
 mail.from.name = Administrator
 mail.from.address = root@localhost
 
+

+ 1 - 1
src/main/resources/fess_indices/.fess_user/role.bulk

@@ -1,2 +1,2 @@
 {"index":{"_index":".fess_user","_type":"role","_id":"YWRtaW4="}}
-{"name":"admin","id":"YWRtaW4="}
+{"name":"admin"}

+ 1 - 1
src/main/resources/fess_indices/.fess_user/user.bulk

@@ -1,2 +1,2 @@
 {"index":{"_index":".fess_user","_type":"user","_id":"YWRtaW4="}}
-{"password":"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918","roles":["YWRtaW4="],"name":"admin","id":"YWRtaW4="}
+{"password":"8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918","roles":["YWRtaW4="],"name":"admin"}