Remove Demo Data (Users, Groups, ..)

Hi

We’re about to go live with our Flowable Setup, but realized that we still have demo users, groups and whatnot bootstrapped into the system. We’re using OAuth.

I have skimmed through this: Auto deployment overview | Flowable Enterprise Documentation

But I can’t find a configuration property to disable, nor a guideline on what IDM assets can/should be removed and how to remove them after they’ve been bootstrapped already.

Any help is appreciated, thanks!
Espen

Ok, it seems that the users are deployed from the default tenant in flowable-platform-default-idm-models-3.17.4.jar!/com/flowable/tenant-setup/default/default-tenant-setup.json

There are several properties that can be configured it seems:

But what is recommended for a production setup?

flowable.platform.idm.deploy-default-resources=false ?
flowable.platform.idm.minimal-setup=true ?

And what do I need to cleanup from the DB after deploying the defaults?

Answering my first question:
flowable.platform.idm.deploy-default-resources=false
flowable.platform.idm.minimal-setup=true

This bootstraps:

User Templates:

  • user-admin
  • user-default

Users:

  • admin

Groups:

  • flowableAdministrator
  • flowableUser

All demo users and all unnecessary groups are not bootstrapped.

This should be the default when nothing is set. Flowable needs to change this. Bootstrapping users with test passwords as a default is not secure.

And here’s the code to remove already bootstrapped demo data:

/**
 * Removes demo data bootstrapped by Flowable:
 * com.flowable.platform.tenant.TenantBootstrapper#TenantBootstrapper(boolean)
 * com.flowable.platform.tenant.TenantBootstrapper#setupTenants()
 */
@Slf4j
@Component
public class IdentityCleanupService {

    public static final List<String> DEMO_USERS = List.of(
            "jessica.adams",
            "shane.bowen",
            "anne.barton",
            "roger.black",
            "lilly.garden",
            "sunny.flower",
            "kenny.cole",
            "ben.snow",
            "james.cox",
            "mike.miller",
            "trevor.jones",
            "emma.gant",
            "peter.schmid",
            "lisa.schmid",
            "annie.austin",
            "stephen.springer",
            "oliver.morgan",
            "ella.martin",
            "clark.kent",
            "lois.lane",
            "amanda.long",
            "boris.blue",
            "david.davidson",
            "pippa.pepper",
            "tim.lee",
            "ryan.morrison",
            "sophie.may",
            "admin",
            "operation.admin"

    );

    public static final List<String> DEMO_GROUPS = List.of(
            "client",
            "clientLookup",
            "externalUser",
            "employee",
            "employeeLookup",
            "clientAdvisor",
            "clientSupporter",
            "reporting",
            "complianceOfficer",
            "operationAdmin"
    );

    public static final List<String> DEMO_USER_DEFINITIONS = List.of(
            "user-client-supporter",
            "user-compliance",
            "user-client-advisor",
            "user-reporting",
            "user-temporary",
            "user-external-client",
            "user-client",
            "user-operation-admin"
    );

    private final IdentityService identityService;
    private final UserDefinitionService userDefinitionService;
    private final ContentService contentService;

    public IdentityCleanupService(IdentityService identityService, UserDefinitionService userDefinitionService, ContentService contentService) {
        this.identityService = identityService;
        this.userDefinitionService = userDefinitionService;
        this.contentService = contentService;
    }

    @EventListener(ApplicationReadyEvent.class)
    public void cleanup() {

        // takes care of removing memberships as well
        // See com.flowable.idm.engine.impl.persistence.entity.GroupEntityManagerImpl#delete
        DEMO_GROUPS.forEach(id -> {
            if (identityService.createGroupQuery().groupId(id).count() > 0) {
                identityService.deleteGroup(id);
                log.info("Deleted group '{}'", id);
            }
        });
        DEMO_USERS.forEach(id -> {
            PlatformUserEntity user = (PlatformUserEntity) identityService.createUserQuery().userId(id).singleResult();
            if (user != null) {
                if (user.getAvatarId() != null) {
                    contentService.deleteContentItem(user.getAvatarId());
                    log.info("Deleted avatar for user '{}'", id);
                }
                // Removes other related resources as well:
                // See com.flowable.idm.engine.impl.persistence.entity.UserEntityManagerImpl#delete
                identityService.deleteUser(id);
                log.info("Deleted user '{}'", id);
            }
        });

        DEMO_USER_DEFINITIONS.forEach(key -> {
            var def = userDefinitionService.getUserDefinitionByKeyAndTenantId(key, "");
            if (def != null) {
                userDefinitionService.removeUserDefinition(def.getId());
                log.info("Deleted user definition for key '{}'", key);
            }
        });
    }
}

Beware that this also deletes the admin user, but keeps the user-default and user-admin user templates that can be used in OAuth2 setups to map to users.

And if you need to deploy custom resources, you need:

flowable.platform.idm.deploy-custom-resources=true
flowable.platform.idm.deploy-default-resources=false

The minimal setup will ignore those resources. As a consequence we had to copy the minimal resources into our classpath.

There’s definitely room for improvement here.