Process Engine REST API - runtime/process-instances

In my application I am using the Process Engine REST API to start a process instance:

I would like the process instances my application starts to be functional (e.g., show details, show form, show diagram, cancel process) in Flowable Task.

I can get the process instances to be visible in Flowable Task by setting the initiator variable:

    const processModel = {
      'name' : this.selectedItem.name,
      'processDefinitionId' : this.selectedItem.id,
      'variables': [
        {
          'name': 'initiator',
          'type' : 'string',
          'value': 'flowable',
          'scope' : 'local'
        }
      ]
    };

Where ‘flowable’ is the Flowable Admin User’s user id.

application.properties:

# Default Flowable Admin Accounts - see: flowable.ldif
flowable.idm.app.admin.user-id=flowable
flowable.idm.app.admin.password=test
flowable.idm.app.admin.first-name=
flowable.idm.app.admin.last-name=Administrator
flowable.idm.app.admin.email=admin@serendipity.org.au

flowable.common.app.idm-admin.user=flowable
flowable.common.app.idm-admin.password=test

flowable.ldif:

# Flowable (UI Applications) Admin User

dn: sn=Admin, ou=users,dc=flowable,dc=org
changetype: add
objectclass: inetOrgPerson
cn: Flowable
sn: Admin
mail: admin@serendipity.org.au
uid: flowable
userPassword: test

However, the ‘Cancel process’ button isn’t visible?

It seems that Flowable Task is also setting the startedBy variable:

startedBy: {id: "flowable", firstName: "Flowable", lastName: "Admin", email: "admin@serendipity.org.au",…}

Is this supported by the Process Engine REST API?

The startedBy is set by the following code:

So, it takes the authenticated user from that moment. Are you doing the REST call with a user, as that user should be used?

The server component of my application leverages Spring Security’s support for OAuth 2.0 and Jason Web Tokens (JWTs) and embeds Flowable’s BPMN engine and exposes the BPMN engine’s RESTful API (by utilising the Flowable Spring Boot Starters). As per this post.

All requests must be authenticated as per the DefaultSecurityConfig (extends WebSecurityConfigurerAdapter):

@EnableWebSecurity
@Profile({"dev", "test", "prod"})
@Slf4j
public class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {

  @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
  private String jwkSetUri;

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    log.info("DefaultSecurityConfig: configure()");

    http.cors().and()
      .authorizeRequests()
      .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
      .antMatchers("/h2-console/**").permitAll()
      .antMatchers("/docs/**").permitAll()
      .anyRequest().authenticated();

    http.csrf().ignoringAntMatchers("/h2-console/**");
    http.headers().frameOptions().sameOrigin();

    http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
  }

  @Bean
  JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build();
  }

  @Bean
  CorsConfigurationSource corsConfigurationSource() {

    CorsConfiguration configuration = new CorsConfiguration();

    configuration.applyPermitDefaultValues();
    configuration.setAllowedOrigins(Collections.singletonList("*"));
    configuration.setAllowedMethods(Arrays.asList("POST", "GET", "PATCH", "PUT", "DELETE"));
    configuration.setAllowCredentials(true);

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);

    return source;
  }

}

The Bearer token is included in all requests from the client component of my application:

...

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService,
              private logger: LoggerService) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler) {

    const accessToken = this.authService.getAccessToken();

    if (accessToken) {

      const authReq = req.clone({ setHeaders: { Authorization: 'Bearer ' + accessToken } });
      return next.handle(authReq);
    }

    return next.handle(req);
  }

}

For example, IndividualController.java:

  ...

  @GetMapping("/individuals")
  @PreAuthorize("hasAuthority('SCOPE_individual:read')")
  public ResponseEntity<PagedModel<IndividualModel>> findAll(
    Pageable pageable) throws ResponseStatusException {

    log.info("IndividualController GET /individuals");

    try {

      Page<Individual> entities = repository.findAll(pageable);
      PagedModel<IndividualModel> models = pagedResourcesAssembler.toModel(entities, assembler);

      return ResponseEntity.ok(models);

    } catch (Exception e) {

      log.error("{}", e.getLocalizedMessage());

      throw new ResponseStatusException(HttpStatus.BAD_REQUEST);
    }

  }