Access Events
Access events in SOKit act as early-stage security checks that run before an operation is executed. They are designed to determine whether the current user has the necessary rights to interact with a document or perform a specific operation.
The purpose are:
- Prevent unauthorized access to specific operations or documents, also leveraging user roles
- Act like interceptors that guard each step operations
How It Works
Access events are linked to operations through the resolver and executed each time a user tries to call an operation (e.g., clicking "Review").
Specifically, in our case we ensures that:
Companycan only access their own companies registration, meaning documents they have created themselves, unless they’re performing aSUBMIT, which is always allowed.Officerusers are allowed to access any document, for any operation.- If the user is not authorized to access the document, the accept() method returns false, immediately preventing the operation from proceeding.
DefaultAccessEvent.java
package com.dev.registration.company.flow.access;
import static com.dev.registration.company.document.security.SecurityAll.OFFICER;
import com.dev.registration.company.data.CompanyEntity;
import com.dev.registration.company.document.CompanyDocument;
import com.dev.registration.company.document.Operations;
import com.dev.registration.company.document.StartOperations;
import com.dev.registration.company.document.States;
import com.dev.registration.company.document.document.events.CompanyAccessEvent;
import java.util.Optional;
import com.strategyobject.sokit.extensions.core.context.SOContext;
import com.strategyobject.sokit.extensions.document.api.annotations.DocumentAware;
@DocumentAware(CompanyDocument.class)
public class DefaultAccessEvent implements CompanyAccessEvent {
@Override
public String code() {
return "default";
}
@Override
public boolean accept(
Phase phase,
SOContext ctx,
States startState,
StartOperations startOperation,
Operations operation,
CompanyEntity entity) {
final var currentSubject = ctx.identity().getSubject();
final var isOfficer = ctx.identity().hasAnyRole(OFFICER);
if (!isOfficer && !Operations.SUBMIT.equals(operation)) {
return Optional.ofNullable(entity.getCreatorSubject())
.map(subject -> subject.equals(currentSubject))
.orElse(false);
}
return true;
}
}
By default, it should be to return true unless access must be explicitly denied.