/* 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.flowable.app.conf;

import org.flowable.app.security.DefaultPrivileges;
import org.flowable.idm.api.IdmIdentityService;
import org.flowable.idm.api.Privilege;
import org.flowable.idm.api.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * Responsible for executing all action required after booting up the Spring container.
 * 
 * @author Joram Barrez
 * @author Tijs Rademakers
 */
@Component
public class Bootstrapper implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(Bootstrapper.class);

    @Autowired
    private IdmIdentityService identityService;

    @Autowired
    private Environment env;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() == null) { // Using Spring MVC, there are multiple child contexts. We only care about the root

            if (!env.getProperty("ldap.enabled", Boolean.class, false)) {
                // First create the default IDM entities
                createDefaultAdmin();
            
            } else {
                if (identityService.createPrivilegeQuery().count() == 0) {
                    String adminUserId = env.getRequiredProperty("admin.userid");
                    initializeDefaultPrivileges(adminUserId);
                }
            }
        }
    }

    protected void createDefaultAdmin() {
        if (identityService.createUserQuery().count() == 0) {
            LOGGER.info("No users found, initializing default entities");
            User user = initializeSuperUser();
            initializeDefaultPrivileges(user.getId());
        }
    }

    protected User initializeSuperUser() {
        String adminUserId = env.getRequiredProperty("admin.userid");
        String adminPassword = env.getRequiredProperty("admin.password");
        String adminFirstname = env.getRequiredProperty("admin.firstname");
        String adminLastname = env.getRequiredProperty("admin.lastname");
        String adminEmail = env.getProperty("admin.email");

        User admin = identityService.newUser(adminUserId);
        admin.setFirstName(adminFirstname);
        admin.setLastName(adminLastname);
        admin.setEmail(adminEmail);
        admin.setPassword(adminPassword);
        identityService.saveUser(admin);
        return admin;
    }

    protected void initializeDefaultPrivileges(String adminId) {
        Privilege idmAppPrivilege = identityService.createPrivilege(DefaultPrivileges.ACCESS_IDM);
        identityService.addUserPrivilegeMapping(idmAppPrivilege.getId(), adminId);

        Privilege adminAppPrivilege = identityService.createPrivilege(DefaultPrivileges.ACCESS_ADMIN);
        identityService.addUserPrivilegeMapping(adminAppPrivilege.getId(), adminId);

        Privilege modelerAppPrivilege = identityService.createPrivilege(DefaultPrivileges.ACCESS_MODELER);
        identityService.addUserPrivilegeMapping(modelerAppPrivilege.getId(), adminId);

        Privilege taskAppPrivilege = identityService.createPrivilege(DefaultPrivileges.ACCESS_TASK);
        identityService.addUserPrivilegeMapping(taskAppPrivilege.getId(), adminId);
    }

}

@@ -585,16 +585,88 @@
 .conf;%0A%0A
+import java.util.HashMap;%0Aimport java.util.List;%0Aimport java.util.Map;%0A%0A
 import o
@@ -3364,32 +3364,37 @@
 inId) %7B%0A        
+List%3C
 Privilege idmApp
@@ -3390,24 +3390,19 @@
 lege
- idmAppP
+%3E p
 rivilege
  = i
@@ -3389,32 +3389,33 @@
 ilege%3E privilege
+s
  = identityServi
@@ -3424,32 +3424,298 @@
 .createPrivilege
+Query().list();%0A        Map%3CString, Privilege%3E privilegeMap = new HashMap%3C%3E();%0A        for (Privilege privilege : privileges) %7B%0A            privilegeMap.put(privilege.getName(), privilege);%0A        %7D%0A        %0A        Privilege idmAppPrivilege = findOrCreatePrivilege
 (DefaultPrivileg
@@ -3727,16 +3727,30 @@
 CESS_IDM
+, privilegeMap
 );%0A     
@@ -3866,33 +3866,23 @@
 ilege = 
-identityService.c
+findOrC
 reatePri
@@ -3918,16 +3918,30 @@
 SS_ADMIN
+, privilegeMap
 );%0A     
@@ -4061,33 +4061,23 @@
 ilege = 
-identityService.c
+findOrC
 reatePri
@@ -4115,16 +4115,30 @@
 _MODELER
+, privilegeMap
 );%0A     
@@ -4257,33 +4257,23 @@
 ilege = 
-identityService.c
+findOrC
 reatePri
@@ -4308,16 +4308,30 @@
 ESS_TASK
+, privilegeMap
 );%0A     
@@ -4414,12 +4414,404 @@
 );%0A    %7D
+%0A    %0A    protected Privilege findOrCreatePrivilege(String privilegeId, Map%3CString, Privilege%3E privilegeMap) %7B%0A        Privilege privilege = null;%0A        if (privilegeMap.containsKey(privilegeId)) %7B%0A            privilege = privilegeMap.get(privilegeId);%0A        %7D else %7B%0A            privilege = identityService.createPrivilege(privilegeId);%0A        %7D%0A        %0A        return privilege;%0A    %7D
 %0A%0A%7D%0A

Fix #530: check if privilege is already present