diff --git a/rest/taskana-rest-spring-example/src/main/java/pro/taskana/ldap/LdapCacheTestImpl.java b/rest/taskana-rest-spring-example/src/main/java/pro/taskana/ldap/LdapCacheTestImpl.java index 0ad305c67..aa3492c45 100644 --- a/rest/taskana-rest-spring-example/src/main/java/pro/taskana/ldap/LdapCacheTestImpl.java +++ b/rest/taskana-rest-spring-example/src/main/java/pro/taskana/ldap/LdapCacheTestImpl.java @@ -288,8 +288,8 @@ public class LdapCacheTestImpl implements LdapCache { new AccessIdResource("team_4", "cn=team_4" + ",ou=groups,o=TaskanaTest"))); @Override - public List findMatchingAccessId(String searchFor, int maxNumerOfReturnedAccessIds) { - return findAccessIdResource(searchFor, maxNumerOfReturnedAccessIds, false); + public List findMatchingAccessId(String searchFor, int maxNumberOfReturnedAccessIds) { + return findAcessIdResource(searchFor, maxNumberOfReturnedAccessIds, false); } @Override @@ -297,10 +297,17 @@ public class LdapCacheTestImpl implements LdapCache { if (users == null) { addUsersToGroups(); } - return findAccessIdResource(searchFor, maxNumberOfReturnedAccessIds, true); + return findAcessIdResource(searchFor, maxNumberOfReturnedAccessIds, true); } - private List findAccessIdResource(String searchFor, int maxNumerOfReturnedAccessIds, + @Override + public List validateAccessId(String accessId) { + return accessIds.stream() + .filter(t -> (t.getAccessId().equalsIgnoreCase(accessId.toLowerCase()))) + .collect(Collectors.toList()); + } + + private List findAcessIdResource(String searchFor, int maxNumberOfReturnedAccessIds, boolean groupMember) { List usersAndGroups = accessIds.stream() .filter(t -> (t.getName().toLowerCase().contains(searchFor.toLowerCase()) @@ -321,7 +328,7 @@ public class LdapCacheTestImpl implements LdapCache { }); List result = usersAndGroups.subList(0, - Math.min(usersAndGroups.size(), maxNumerOfReturnedAccessIds)); + Math.min(usersAndGroups.size(), maxNumberOfReturnedAccessIds)); return result; } diff --git a/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/AccessIdValidationControllerTest.java b/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/AccessIdValidationControllerTest.java index 2eee3fe5a..f12adf136 100644 --- a/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/AccessIdValidationControllerTest.java +++ b/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/AccessIdValidationControllerTest.java @@ -51,7 +51,7 @@ public class AccessIdValidationControllerTest { headers.add("Authorization", "Basic dGVhbWxlYWRfMTp0ZWFtbGVhZF8x"); HttpEntity request = new HttpEntity(headers); ResponseEntity> response = template.exchange( - "http://127.0.0.1:" + port + "/v1/access-ids?searchFor=ali", HttpMethod.GET, request, + "http://127.0.0.1:" + port + "/v1/access-ids?search-for=ali", HttpMethod.GET, request, new ParameterizedTypeReference>() { }); @@ -73,7 +73,7 @@ public class AccessIdValidationControllerTest { HttpEntity request = new HttpEntity(headers); try { template.exchange( - "http://127.0.0.1:" + port + "/v1/access-ids?searchFor=al", HttpMethod.GET, request, + "http://127.0.0.1:" + port + "/v1/access-ids?search-for=al", HttpMethod.GET, request, new ParameterizedTypeReference>() { }); diff --git a/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/GenenalExceptionHandlingTest.java b/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/GenenalExceptionHandlingTest.java index a8079fd3f..237a1a19d 100644 --- a/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/GenenalExceptionHandlingTest.java +++ b/rest/taskana-rest-spring-example/src/test/java/pro/taskana/rest/GenenalExceptionHandlingTest.java @@ -90,7 +90,7 @@ public class GenenalExceptionHandlingTest { AccessIdController.setLdapCache(new LdapCacheTestImpl()); template.exchange( - server + port + "/v1/access-ids?searchFor=al", HttpMethod.GET, request, + server + port + "/v1/access-ids?search-for=al", HttpMethod.GET, request, new ParameterizedTypeReference>() { }); diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/ldap/LdapCache.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/ldap/LdapCache.java index f53b13a6a..f6e026fd3 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/ldap/LdapCache.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/ldap/LdapCache.java @@ -16,17 +16,24 @@ public interface LdapCache { * * @param searchFor * the search string. The search is performed over names and ids of users and groups. - * @param maxNumerOfReturnedAccessIds + * @param maxNumberOfReturnedAccessIds * the maximum number of results to return. * @return a List of access ids for users and group where the name or id contains the search string. */ - List findMatchingAccessId(String searchFor, int maxNumerOfReturnedAccessIds); + List findMatchingAccessId(String searchFor, int maxNumberOfReturnedAccessIds); /** - * + * Find the groups belong to a user. * @param searchFor the search string. The search is performed over names and ids of group . - * @param maxNumerOfReturnedAccessIds + * @param maxNumberOfReturnedAccessIds the maximum number of results to return. * @return */ - List findGroupsOfUser(String searchFor, int maxNumerOfReturnedAccessIds); + List findGroupsOfUser(String searchFor, int maxNumberOfReturnedAccessIds); + + /** + * Validate a access id. + * @param accessId the search string. + * @return the corresponding access id. + */ + List validateAccessId(String accessId); } diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/AccessIdController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/AccessIdController.java index 8463858fe..c3568644b 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/AccessIdController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/AccessIdController.java @@ -35,28 +35,40 @@ public class AccessIdController { @GetMapping public ResponseEntity> validateAccessIds( - @RequestParam String searchFor, @RequestParam(required = false) boolean searchInGroups) throws InvalidArgumentException { + @RequestParam("search-for") String searchFor) throws InvalidArgumentException { if (searchFor.length() < ldapClient.getMinSearchForLength()) { - throw new InvalidArgumentException("searchFor string '" + searchFor + "' is too short. Minimum searchFor length = " - + ldapClient.getMinSearchForLength()); + throw new InvalidArgumentException( + "searchFor string '" + searchFor + "' is too short. Minimum searchFor length = " + + ldapClient.getMinSearchForLength()); } if (ldapClient.useLdap()) { List accessIdUsers = ldapClient.searchUsersAndGroups(searchFor); - if (searchInGroups) { - List accessIdGroups = ldapClient.searchGroupsofUsersIsMember(searchFor); - accessIdUsers.addAll(accessIdGroups); - } return new ResponseEntity<>(accessIdUsers, HttpStatus.OK); } else if (ldapCache != null) { - if (searchInGroups) { - return new ResponseEntity<>( - ldapCache.findGroupsOfUser(searchFor, ldapClient.getMaxNumberOfReturnedAccessIds()), - HttpStatus.OK); - } else { - return new ResponseEntity<>( - ldapCache.findMatchingAccessId(searchFor, ldapClient.getMaxNumberOfReturnedAccessIds()), - HttpStatus.OK); + return new ResponseEntity<>( + ldapCache.findMatchingAccessId(searchFor, ldapClient.getMaxNumberOfReturnedAccessIds()), + HttpStatus.OK); + } else { + return new ResponseEntity<>(new ArrayList<>(), HttpStatus.NOT_FOUND); + } + } + + @GetMapping(path = "/groups") + public ResponseEntity> getGroupsByAccessId( + @RequestParam("access-id") String accessId) throws InvalidArgumentException { + if (ldapClient.useLdap() || ldapCache != null) { + if (!validateAccessId(accessId)) { + throw new InvalidArgumentException("The accessId is invalid"); } + } + List accessIdUsers; + if (ldapClient.useLdap()) { + accessIdUsers = ldapClient.searchUsersAndGroups(accessId); + accessIdUsers.addAll(ldapClient.searchGroupsofUsersIsMember(accessId)); + return new ResponseEntity<>(accessIdUsers, HttpStatus.OK); + } else if (ldapCache != null) { + accessIdUsers = ldapCache.findGroupsOfUser(accessId, ldapClient.getMaxNumberOfReturnedAccessIds()); + return new ResponseEntity<>(accessIdUsers, HttpStatus.OK); } else { return new ResponseEntity<>(new ArrayList<>(), HttpStatus.NOT_FOUND); } @@ -66,4 +78,9 @@ public class AccessIdController { ldapCache = cache; } + private boolean validateAccessId(String accessId) throws InvalidArgumentException { + return (ldapClient.useLdap() && ldapClient.searchUsersAndGroups(accessId).size() == 1) || (!ldapClient.useLdap() + && ldapCache.validateAccessId(accessId).size() == 1); + } + } diff --git a/web/src/app/administration/access-items-management/access-items-management.component.html b/web/src/app/administration/access-items-management/access-items-management.component.html index 6293f6a43..48cc1b0b9 100644 --- a/web/src/app/administration/access-items-management/access-items-management.component.html +++ b/web/src/app/administration/access-items-management/access-items-management.component.html @@ -1,10 +1,5 @@
-
- -

Acces items management

@@ -13,8 +8,8 @@ (onSelect)="onSelectAccessId($event)" displayError=true>
-

Select an access id

- +

Select an access id

+
@@ -50,7 +45,8 @@ - @@ -80,8 +76,9 @@
- +
@@ -163,6 +160,41 @@ + + + + +
+ +
diff --git a/web/src/app/administration/access-items-management/access-items-management.component.scss b/web/src/app/administration/access-items-management/access-items-management.component.scss index cc635231a..ac2cb65fc 100644 --- a/web/src/app/administration/access-items-management/access-items-management.component.scss +++ b/web/src/app/administration/access-items-management/access-items-management.component.scss @@ -6,8 +6,8 @@ } .required-header:after { - - content:" *"; + + content:" *"; color: $invalid; } @@ -31,3 +31,8 @@ td { word-wrap:break-word; } .min-width{ min-width: 135px;} + +.modal-title { + font-weight: bold; + display: inline; +} diff --git a/web/src/app/administration/access-items-management/access-items-management.component.ts b/web/src/app/administration/access-items-management/access-items-management.component.ts index 197859c64..c02a56ec9 100644 --- a/web/src/app/administration/access-items-management/access-items-management.component.ts +++ b/web/src/app/administration/access-items-management/access-items-management.component.ts @@ -32,8 +32,11 @@ export class AccessItemsManagementComponent implements OnInit, OnDestroy { accessItemPermissionsSubscription: Subscription; accessItemInformationsubscription: Subscription; accessIdsWithGroups: Array; + belongingGroups: Array; sortingFields = new Map([['workbasket-key', 'Workbasket Key'], ['access-id', 'Access id']]); sortModel: SortingModel; + isGroup: boolean; + groupsKey = 'ou=groups'; accessIdField = this.customFieldsService.getCustomField('Owner', 'workbaskets.access-items.accessId'); @@ -89,11 +92,13 @@ export class AccessItemsManagementComponent implements OnInit, OnDestroy { } if (!this.AccessItemsForm || this.accessIdPrevious !== selected.accessId) { this.accessIdPrevious = selected.accessId + this.isGroup = selected.accessId.includes(this.groupsKey); this.unSubscribe(this.accessItemInformationsubscription) this.accessItemInformationsubscription = this.accessIdsService.getAccessItemsInformation(selected.accessId, true) .subscribe((accessIdsWithGroups: Array) => { this.accessIdsWithGroups = accessIdsWithGroups; + this.belongingGroups = accessIdsWithGroups.filter(item => item.accessId.includes(this.groupsKey)); this.searchForAccessItemsWorkbaskets(); }, error => { diff --git a/web/src/app/shared/services/access-ids/access-ids.service.ts b/web/src/app/shared/services/access-ids/access-ids.service.ts index b13848296..1ef007abc 100644 --- a/web/src/app/shared/services/access-ids/access-ids.service.ts +++ b/web/src/app/shared/services/access-ids/access-ids.service.ts @@ -21,7 +21,11 @@ export class AccessIdsService { if (!token || token.length < 3) { return of([]); } - return this.httpClient.get>(`${this.url}?searchFor=${token}&searchInGroups=${searchInGroups}`); + if (searchInGroups) { + return this.httpClient.get>(`${this.url}/groups?access-id=${token}`); + } else { + return this.httpClient.get>(`${this.url}?search-for=${token}`); + } }; getAccessItemsPermissions( diff --git a/web/src/app/shared/sort/sort.component.scss b/web/src/app/shared/sort/sort.component.scss index 3b3c0ca5c..595438f1e 100644 --- a/web/src/app/shared/sort/sort.component.scss +++ b/web/src/app/shared/sort/sort.component.scss @@ -6,3 +6,7 @@ .sortby-dropdown { min-width: 200px; } + +ul { + list-style-type: none; +} diff --git a/web/src/app/shared/type-ahead/type-ahead.component.html b/web/src/app/shared/type-ahead/type-ahead.component.html index 5ae95d72f..7236f4388 100644 --- a/web/src/app/shared/type-ahead/type-ahead.component.html +++ b/web/src/app/shared/type-ahead/type-ahead.component.html @@ -33,7 +33,7 @@
-
- \ No newline at end of file + diff --git a/web/src/app/shared/type-ahead/type-ahead.component.scss b/web/src/app/shared/type-ahead/type-ahead.component.scss index 721521b49..1404e2351 100644 --- a/web/src/app/shared/type-ahead/type-ahead.component.scss +++ b/web/src/app/shared/type-ahead/type-ahead.component.scss @@ -23,7 +23,7 @@ white-space: nowrap; padding-right: 35px; } - + } .custom-form-control { height: 50px; @@ -46,7 +46,7 @@ } padding-left: 12px; padding-right: 35px; - + } .field-label-wrapper{ @@ -55,7 +55,7 @@ padding-left: 12px; box-sizing: content-box; overflow: hidden; - pointer-events: none; + pointer-events: none; } .form-control:focus { @@ -73,7 +73,7 @@ position: absolute; top: 0px; right: 0px; - + } ::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */ @@ -90,4 +90,8 @@ .disable { cursor: not-allowed; -} \ No newline at end of file +} + +.invalid { + color: $invalid; +} diff --git a/web/src/assets/_colors.scss b/web/src/assets/_colors.scss index 63a937ffe..2c45900e5 100644 --- a/web/src/assets/_colors.scss +++ b/web/src/assets/_colors.scss @@ -9,3 +9,4 @@ $invalid: #d82626; $aquamarine: #22a39f; $pallete-blue: #36bcee; $pallete-green: #5fbca1; +$transparent-grey: rgba(192, 192, 192, 0.65); diff --git a/web/src/assets/_site.scss b/web/src/assets/_site.scss index 75d464efe..b7ef5b67f 100644 --- a/web/src/assets/_site.scss +++ b/web/src/assets/_site.scss @@ -353,3 +353,7 @@ li.list-group-item:hover { outline: none; } } + +.modal-backdrop.show { + background-color: $transparent-grey; +}