RangerServiceDefValidator extends RangerValidator { boolean isValidAccessTypes(final Long serviceDefId, final List<RangerAccessTypeDef> accessTypeDefs, final List<ValidationFailureDetails> failures, final Action action) { if(LOG.isDebugEnabled()) { LOG.debug(String.format("==> RangerServiceDefValidator.isValidAccessTypes(%s, %s)", accessTypeDefs, failures)); } boolean valid = true; if (CollectionUtils.isEmpty(accessTypeDefs)) { ValidationErrorCode error = ValidationErrorCode.SERVICE_DEF_VALIDATION_ERR_MISSING_FIELD; failures.add(new ValidationFailureDetailsBuilder() .field("access types") .isMissing() .errorCode(error.getErrorCode()) .becauseOf(error.getMessage("access types")) .build()); valid = false; } else { Map<Long, String> existingAccessTypeIDNameMap = new HashMap<>(); if (action == Action.UPDATE) { List<RangerAccessTypeDef> existingAccessTypes = this.getServiceDef(serviceDefId).getAccessTypes(); for (RangerAccessTypeDef existingAccessType : existingAccessTypes) { existingAccessTypeIDNameMap.put(existingAccessType.getItemId(), existingAccessType.getName()); } } if(LOG.isDebugEnabled()) { LOG.debug("accessType names from db = " + existingAccessTypeIDNameMap.values()); } List<RangerAccessTypeDef> defsWithImpliedGrants = new ArrayList<>(); Set<String> accessNames = new HashSet<>(); Set<Long> ids = new HashSet<>(); for (RangerAccessTypeDef def : accessTypeDefs) { String name = def.getName(); Long itemId = def.getItemId(); valid = isUnique(name, accessNames, "access type name", "access types", failures) && valid; valid = isUnique(def.getItemId(), ids, "access type itemId", "access types", failures) && valid; if (action == Action.UPDATE) { if (existingAccessTypeIDNameMap.get(itemId) != null && !existingAccessTypeIDNameMap.get(itemId).equals(name)) { ValidationErrorCode error; error = ValidationErrorCode.SERVICE_DEF_VALIDATION_ERR_SERVICE_DEF_NAME_CONFICT; failures.add((new ValidationFailureDetailsBuilder()).field("access type name").isSemanticallyIncorrect().errorCode(error.getErrorCode()).becauseOf(String.format("changing %s[%s] in %s is not supported", "access type name", name, "access types")).build()); valid = false; } } if (CollectionUtils.isNotEmpty(def.getImpliedGrants())) { defsWithImpliedGrants.add(def); } } for (RangerAccessTypeDef def : defsWithImpliedGrants) { Collection<String> impliedGrants = getImpliedGrants(def); Set<String> unknownAccessTypes = Sets.difference(Sets.newHashSet(impliedGrants), accessNames); if (!unknownAccessTypes.isEmpty()) { ValidationErrorCode error = ValidationErrorCode.SERVICE_DEF_VALIDATION_ERR_IMPLIED_GRANT_UNKNOWN_ACCESS_TYPE; failures.add(new ValidationFailureDetailsBuilder() .field("implied grants") .subField(unknownAccessTypes.iterator().next()) .isSemanticallyIncorrect() .errorCode(error.getErrorCode()) .becauseOf(error.getMessage(impliedGrants, unknownAccessTypes)) .build()); valid = false; } String name = def.getName(); if (impliedGrants.contains(name)) { ValidationErrorCode error = ValidationErrorCode.SERVICE_DEF_VALIDATION_ERR_IMPLIED_GRANT_IMPLIES_ITSELF; failures.add(new ValidationFailureDetailsBuilder() .field("implied grants") .subField(name) .isSemanticallyIncorrect() .errorCode(error.getErrorCode()) .becauseOf(error.getMessage(impliedGrants, name)) .build()); valid = false; } } } if(LOG.isDebugEnabled()) { LOG.debug(String.format("<== RangerServiceDefValidator.isValidAccessTypes(%s, %s): %s", accessTypeDefs, failures, valid)); } return valid; } RangerServiceDefValidator(ServiceStore store); void validate(final RangerServiceDef serviceDef, final Action action); boolean isValidResources(RangerServiceDef serviceDef, List<ValidationFailureDetails> failures, final Action action);  }
@Test public final void test_isValidAccessTypes_happyPath() { long id = 7; when(_serviceDef.getId()).thenReturn(id); List<RangerAccessTypeDef> input = _utils.createAccessTypeDefs(accessTypes_good); assertTrue(_validator.isValidAccessTypes(id, input, _failures, Action.CREATE)); assertTrue(_failures.isEmpty()); }
@Test public final void test_isValidAccessTypes_failures() { long id = 7; when(_serviceDef.getId()).thenReturn(id); List<RangerAccessTypeDef> accessTypeDefs = null; _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForMissingValue(_failures, "access types"); accessTypeDefs = new ArrayList<>(); _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForMissingValue(_failures, "access types"); accessTypeDefs = _utils.createAccessTypeDefs(new String[] { null, "", " " }); _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForMissingValue(_failures, "access type name"); accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "read" } ); _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForSemanticError(_failures, "access type name", "read"); accessTypeDefs = _utils.createAccessTypeDefs(new String[] { "read", "write", "execute", "READ" } ); _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForSemanticError(_failures, "access type name", "READ"); accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_unknownType); _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForSemanticError(_failures, "implied grants", "execute"); _utils.checkFailureForSemanticError(_failures, "access type itemId", "1"); accessTypeDefs = _utils.createAccessTypeDefs(accessTypes_bad_selfReference); _failures.clear(); assertFalse(_validator.isValidAccessTypes(id, accessTypeDefs, _failures, Action.CREATE)); _utils.checkFailureForSemanticError(_failures, "implied grants", "admin"); }