package org.bonitasoft.console.common.server.utils;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bonitasoft.console.common.server.login.LoginFailedException;
import org.bonitasoft.console.common.server.preferences.properties.CompoundPermissionsMapping;
import org.bonitasoft.console.common.server.preferences.properties.CustomPermissionsMapping;
import org.bonitasoft.console.common.server.preferences.properties.SecurityProperties;
import org.bonitasoft.engine.api.ApplicationAPI;
import org.bonitasoft.engine.api.ProfileAPI;
import org.bonitasoft.engine.exception.SearchException;
import org.bonitasoft.engine.profile.Profile;
import org.bonitasoft.engine.profile.ProfileCriterion;
import org.bonitasoft.engine.profile.ProfileEntry;
import org.bonitasoft.engine.profile.ProfileEntrySearchDescriptor;
import org.bonitasoft.engine.search.SearchOptionsBuilder;
import org.bonitasoft.engine.search.SearchResult;
import org.bonitasoft.engine.session.APISession;
import org.bonitasoft.web.rest.model.portal.profile.ProfileEntryItem;
public class PermissionsBuilder {
public static final String PROFILE_TYPE_AUTHORIZATION_PREFIX = "profile";
public static final String USER_TYPE_AUTHORIZATION_PREFIX = "user";
protected static final int MAX_ELEMENTS_RETRIEVED = 200;
protected final APISession session;
private final ProfileAPI profileAPI;
private final ApplicationAPI applicationAPI;
private final CustomPermissionsMapping customPermissionsMapping;
private final CompoundPermissionsMapping compoundPermissionsMapping;
private final boolean apiAuthorizationsCheckEnabled;
protected PermissionsBuilder(final APISession session, final ProfileAPI profileAPI,final ApplicationAPI applicationAPI, final CustomPermissionsMapping customPermissionsMapping,
final CompoundPermissionsMapping compoundPermissionsMapping, final SecurityProperties securityProperties) {
this.session = session;
this.profileAPI = profileAPI;
this.applicationAPI = applicationAPI;
this.customPermissionsMapping = customPermissionsMapping;
this.compoundPermissionsMapping = compoundPermissionsMapping;
apiAuthorizationsCheckEnabled = securityProperties.isAPIAuthorizationsCheckEnabled();
}
public Set<String> getPermissions() throws LoginFailedException {
Set<String> permissions;
if (session.isTechnicalUser()) {
permissions = Collections.emptySet();
} else {
permissions = new HashSet<>();
if (apiAuthorizationsCheckEnabled) {
addProfilesPermissions(permissions);
addCustomUserPermissions(permissions);
}
}
return permissions;
}
void addProfilesPermissions(final Set<String> permissions) throws LoginFailedException {
final Set<String> pageTokens;
try {
pageTokens = getAllPagesForUser(permissions);
} catch (final SearchException e) {
throw new LoginFailedException(e);
}
for (final String pageToken : pageTokens) {
permissions.addAll(getCompoundPermissions(pageToken));
}
}
/**
* return the page names the user can access and add custom permissions of the profile in the permissions set
*
* @param permissions
* the set to complete
* @return
* the page names the user can access
* @throws SearchException
*/
Set<String> getAllPagesForUser(final Set<String> permissions) throws SearchException {
final Set<String> pageTokens = new HashSet<>();
int profilesIndex = 0;
int nbOfProfilesRetrieved = MAX_ELEMENTS_RETRIEVED;
while (nbOfProfilesRetrieved == MAX_ELEMENTS_RETRIEVED) {
final List<Profile> profiles = profileAPI.getProfilesForUser(session.getUserId(), profilesIndex, MAX_ELEMENTS_RETRIEVED, ProfileCriterion.ID_ASC);
nbOfProfilesRetrieved = profiles.size();
for (final Profile profile : profiles) {
addPageAndCustomPermissionsOfProfile(permissions, pageTokens, profile);
}
profilesIndex = profilesIndex + nbOfProfilesRetrieved;
}
return pageTokens;
}
void addPageAndCustomPermissionsOfProfile(final Set<String> permissions, final Set<String> pageTokens, final Profile profile) throws SearchException {
addPagesOfProfile(profile, pageTokens);
addPagesOfApplication(profile, pageTokens);
addCustomProfilePermissions(permissions, profile);
addProfilesPermissions(permissions, profile);
}
void addProfilesPermissions(final Set<String> permissions, final Profile profile) {
permissions.add(PROFILE_TYPE_AUTHORIZATION_PREFIX + "|" + profile.getName());
}
void addPagesOfProfile(final Profile profile, final Set<String> pageTokens) throws SearchException {
int entriesIndex = 0;
int nbOfProfileEntriesRetrieved = MAX_ELEMENTS_RETRIEVED;
while (nbOfProfileEntriesRetrieved == MAX_ELEMENTS_RETRIEVED) {
final List<ProfileEntry> profileEntries = getProfileEntriesForProfile(profile, entriesIndex);
nbOfProfileEntriesRetrieved = profileEntries.size();
for (final ProfileEntry profileEntry : profileEntries) {
if (profileEntry.getType().equals(ProfileEntryItem.VALUE_TYPE.link.name())) {
pageTokens.add(profileEntry.getPage());
}
}
entriesIndex = entriesIndex + nbOfProfileEntriesRetrieved;
}
}
void addPagesOfApplication(final Profile profile, final Set<String> pageTokens) throws SearchException {
final List<String> allPagesForProfile = applicationAPI.getAllPagesForProfile(profile.getId());
pageTokens.addAll(allPagesForProfile);
}
void addCustomProfilePermissions(final Set<String> permissions, final Profile profile) {
permissions.addAll(getCustomPermissions(PROFILE_TYPE_AUTHORIZATION_PREFIX, profile.getName()));
}
void addCustomUserPermissions(final Set<String> permissions) {
permissions.addAll(getCustomPermissions(USER_TYPE_AUTHORIZATION_PREFIX, session.getUserName()));
}
Set<String> getCustomPermissions(final String type, final String identifier) {
final Set<String> profileSinglePermissions = new HashSet<>();
final Set<String> customPermissionsForEntity = getCustomPermissionsRaw(type, identifier);
for (final String customPermissionForEntity : customPermissionsForEntity) {
final Set<String> simplePermissions = getCompoundPermissions(customPermissionForEntity);
if (!simplePermissions.isEmpty()) {
profileSinglePermissions.addAll(simplePermissions);
} else {
profileSinglePermissions.add(customPermissionForEntity);
}
}
return profileSinglePermissions;
}
Set<String> getCustomPermissionsRaw(final String type, final String identifier) {
return customPermissionsMapping.getPropertyAsSet(type + "|" + identifier);
}
Set<String> getCompoundPermissions(final String compoundName) {
return compoundPermissionsMapping.getPropertyAsSet(compoundName);
}
List<ProfileEntry> getProfileEntriesForProfile(final Profile profile, final int entriesIndex) throws SearchException {
final SearchOptionsBuilder searchOptionsBuilder = new SearchOptionsBuilder(entriesIndex, MAX_ELEMENTS_RETRIEVED);
searchOptionsBuilder.filter(ProfileEntrySearchDescriptor.PROFILE_ID, profile.getId());
final SearchResult<ProfileEntry> profileEntriesResult = profileAPI.searchProfileEntries(searchOptionsBuilder.done());
return profileEntriesResult.getResult();
}
}