Skip to content

Commit

Permalink
Throw error if user leader is missing when accepting requests (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
boavenn authored Nov 15, 2024
1 parent 07fcb7d commit b0930fe
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,37 +43,37 @@ public ActiveDirectorySearcher objectClasses(List<ActiveDirectoryObjectClass> ob
}

public ActiveDirectorySearcher memberOf(String group) {
var value = String.format("(memberOf=%s)", group);
var value = String.format("(memberOf=%s)", escapeSpecialCharacters(group));
filter.append(value);
return this;
}

public ActiveDirectorySearcher principalName(String principalName) {
var value = String.format("(userPrincipalName=%s)", principalName);
var value = String.format("(userPrincipalName=%s)", escapeSpecialCharacters(principalName));
filter.append(value);
return this;
}

public ActiveDirectorySearcher mail(String mail) {
var value = String.format("(mail=%s)", mail);
var value = String.format("(mail=%s)", escapeSpecialCharacters(mail));
filter.append(value);
return this;
}

public ActiveDirectorySearcher name(String name) {
var value = String.format("(name=%s)", name);
var value = String.format("(name=%s)", escapeSpecialCharacters(name));
filter.append(value);
return this;
}

public ActiveDirectorySearcher distinguishedName(String distinguishedName) {
var value = String.format("(distinguishedName=%s)", distinguishedName);
var value = String.format("(distinguishedName=%s)", escapeSpecialCharacters(distinguishedName));
filter.append(value);
return this;
}

public ActiveDirectorySearcher excludeDistinguishedName(String distinguishedName) {
var value = String.format("(!(distinguishedName=%s))", distinguishedName);
var value = String.format("(!(distinguishedName=%s))", escapeSpecialCharacters(distinguishedName));
filter.append(value);
return this;
}
Expand All @@ -89,6 +89,11 @@ public ActiveDirectorySearcher isDisabled(){
return this;
}

// Based on https://learn.microsoft.com/en-us/archive/technet-wiki/5392.active-directory-ldap-syntax-filters#Special_Characters
private String escapeSpecialCharacters(String query) {
return query.replaceAll("\\\\", "\\\\5C");
}

public List<SearchResult> search() {
var controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package info.fingo.urlopia.request;

import info.fingo.urlopia.api.v2.BaseCustomException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(code = HttpStatus.PRECONDITION_FAILED, reason = "LEADER_NOT_FOUND")
public class LeaderNotFoundException extends BaseCustomException {
private static final String ERROR_MSG = "Leader has not been found";

public LeaderNotFoundException() {
super(ERROR_MSG);
}

@Override
public HttpStatus getHttpStatus() {
return HttpStatus.PRECONDITION_FAILED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ public Request create(Long userId, BaseRequestInput requestInput) {
log.info("New normal request with id: %d has been created".formatted(request.getId()));

var leader = userService.getAcceptanceLeaderForUser(user);
if (leader != null) {
this.acceptanceService.create(request, leader);
} else {
this.accept(request);
if (leader == null) {
throw new LeaderNotFoundException();
}

this.acceptanceService.create(request, leader);

return requestRepository
.findById(request.getId())
.orElseThrow(NoSuchElementException::new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,34 @@ private User getUserLeaderUnsafe(User user) throws NamingException {
var userDN = userSearch.stream().findFirst().map(NameClassPair::getNameInNamespace).orElse("");
var organizationalUnits = extractOrganizationalUnitsDNs(userDN);

LOGGER.info("Starting search of the '{}' manager", userDN);

// Step 2: Find first existing and valid OU manager.
for (var ouDn : organizationalUnits) {
LOGGER.info("Looking for a manager in the '{}' group", ouDn);
var controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);

var ouSearch = activeDirectory.newSearch().distinguishedName(ouDn).search(controls);
if (ouSearch.isEmpty()) {
LOGGER.warn("No search results for '{}' OU", ouDn);
}

for (var result : ouSearch) {
var attributes = result.getAttributes();
var managedBy = attributes.get(Attribute.MANAGED_BY.getKey());
var managedByDN = managedBy != null ? (String) managedBy.get() : "";
if (!managedByDN.isBlank() && !managedByDN.equals(userDN)) {
var managedBy = result.getAttributes().get(Attribute.MANAGED_BY.getKey());
if (managedBy == null) {
LOGGER.warn("Missing managedBy attribute for '{}' OU", ouDn);
continue;
}

var managedByDN = (String) managedBy.get();
if (!managedByDN.equals(userDN)) {
var manager = getManagerDetails(managedByDN);
if (manager.isPresent()) {
LOGGER.info("Manager of '{}' OU found: '{}'", ouDn, managedByDN);
return manager.get();
} else {
LOGGER.warn("Manager of '{}' OU has not been found", ouDn);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE UNIQUE INDEX users_mail_index ON users (mail);
CREATE UNIQUE INDEX users_mail_key ON users (mail);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_mail_key;
DROP INDEX IF EXISTS users_mail_key;
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class NormalRequestServiceSpec extends Specification{
getTeams() >> Set.of(team)
}
userRepository.findById(userId) >> Optional.of(user)
userService.getAcceptanceLeaderForUser(user) >> team.getLeader()

and: "request mock with repo with endDate before startDate"
def request = Mock(Request){
Expand Down
1 change: 1 addition & 0 deletions view.react/src/helpers/errors/ErrorCodeMappings.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const loginErrorCodeMappings = {
const requestsErrorCodeMappings = {
"END_DATE_IS_BEFORE_START_DATE": "Data końcowa nie powinna być przed datą początkową",
"NOT_ENOUGH_DAYS": "Nie posiadasz wystarczającej liczby dni urlopowych",
"LEADER_NOT_FOUND": "Nie została znaleziona osoba wymagana do akceptacji wniosku",
"REQUEST_OVERLAPPING": "Wybrany termin pokrywa się z terminem jednej z wcześniej utworzonych okoliczności",
}

Expand Down

0 comments on commit b0930fe

Please sign in to comment.