private IQueryable <SCIMRepresentation> ParseAndExecuteFilter(IQueryable <SCIMRepresentation> representations, string filter) { var parsed = SCIMFilterParser.Parse(filter, new List <SCIMSchema> { SCIMConstants.StandardSchemas.UserSchema, SCIMConstants.StandardSchemas.CommonSchema }); var evaluatedExpression = parsed.Evaluate(representations); return((IQueryable <SCIMRepresentation>)evaluatedExpression.Compile().DynamicInvoke(representations)); }
private IOrderedEnumerable <SCIMRepresentation> ParseAndExecutOrderBy(IQueryable <SCIMRepresentation> representations, string filter, SearchSCIMRepresentationOrders order) { var parsed = SCIMFilterParser.Parse(filter, new List <SCIMSchema> { StandardSchemas.UserSchema, CustomSchema }); var evaluatedExpression = parsed.EvaluateOrderBy(representations, order); return((IOrderedEnumerable <SCIMRepresentation>)evaluatedExpression.Compile().DynamicInvoke(representations)); }
private IQueryable <SCIMRepresentation> ParseAndExecuteFilter(IQueryable <SCIMRepresentation> representations, string filter) { var p = SCIMFilterParser.Parse("members[(value eq \"06259893-b0ae-4f76-bb1f-fe684843cfbd\" or value eq \"7a2148ba-9427-4d5d-8ae2-8aa4c4a14ce3\") or value eq \"7a2148ba-9427-4d5d-8ae2-8aa4c4a14ce3\"]", new List <SCIMSchema> { SCIMConstants.StandardSchemas.UserSchema }); var parsed = SCIMFilterParser.Parse(filter, new List <SCIMSchema> { SCIMConstants.StandardSchemas.UserSchema }); var evaluatedExpression = parsed.Evaluate(representations); return((IQueryable <SCIMRepresentation>)evaluatedExpression.Compile().DynamicInvoke(representations)); }
public void When_Extract_Attributes() { var userSchema = SCIMSchemaBuilder.Create("urn:ietf:params:scim:schemas:core:2.0:User", "User", "User Account") .AddStringAttribute("userName", caseExact: true, uniqueness: SCIMSchemaAttributeUniqueness.SERVER) .AddComplexAttribute("phones", opt => { opt.AddStringAttribute("phoneNumber", description: "Phone number"); opt.AddStringAttribute("type", description: "Type"); }, multiValued: true, mutability: SCIMSchemaAttributeMutabilities.READWRITE) .Build(); var userRepresentation = SCIMRepresentationBuilder.Create(new List <SCIMSchema> { userSchema }) .AddStringAttribute("userName", "urn:ietf:params:scim:schemas:core:2.0:User", new List <string> { "john" }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "01" }); b.AddStringAttribute("type", new List <string> { "mobile" }); }) .AddComplexAttribute("phones", "urn:ietf:params:scim:schemas:core:2.0:User", (b) => { b.AddStringAttribute("phoneNumber", new List <string> { "02" }); b.AddStringAttribute("type", new List <string> { "home" }); }) .Build(); var firstFilter = SCIMFilterParser.Parse("phones.phoneNumber", new List <SCIMSchema> { userSchema }); var secondFilter = SCIMFilterParser.Parse("phones[phoneNumber eq 02]", new List <SCIMSchema> { userSchema }); var thirdFilter = SCIMFilterParser.Parse("userName", new List <SCIMSchema> { userSchema }); var fourthFilter = SCIMFilterParser.Parse("phones.phoneNumber", new List <SCIMSchema> { userSchema }); var fifthFilter = SCIMFilterParser.Parse("phones[phoneNumber eq 02]", new List <SCIMSchema> { userSchema }); var sixFilter = SCIMFilterParser.Parse("meta.lastModified", new List <SCIMSchema> { userSchema }); var sevenFilter = SCIMFilterParser.Parse("meta.lastModified", new List <SCIMSchema> { userSchema }); var eightFilter = SCIMFilterParser.Parse("id", new List <SCIMSchema> { userSchema }); var nineFilter = SCIMFilterParser.Parse("id", new List <SCIMSchema> { userSchema }); var firstJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { firstFilter }); var secondJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { secondFilter }); var thirdJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { thirdFilter }, "http://localhost"); var fourthJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { fourthFilter }, "http://localhost"); var fifthJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { fifthFilter }, "http://localhost"); var sixJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { sixFilter }); var sevenJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { sevenFilter }, "http://localhost"); var eightJSON = userRepresentation.ToResponseWithExcludedAttributes(new List <SCIMExpression> { eightFilter }, "http://localhost"); var nineJSON = userRepresentation.ToResponseWithIncludedAttributes(new List <SCIMExpression> { nineFilter }); Assert.Equal("01", firstJSON.SelectToken("phones[0].phoneNumber").ToString()); Assert.Equal("02", secondJSON.SelectToken("phones[0].phoneNumber").ToString()); Assert.Equal("home", secondJSON.SelectToken("phones[0].type").ToString()); Assert.Null(thirdJSON.SelectToken("userName")); Assert.Null(fourthJSON.SelectToken("phones[0].phoneNumber")); Assert.True((fifthJSON.SelectToken("phones") as JArray).Count == 1); Assert.NotNull(sixJSON.SelectToken("meta.lastModified")); Assert.Null(sevenJSON.SelectToken("meta.lastModified")); Assert.NotNull(eightJSON.SelectToken("id")); Assert.NotNull(nineJSON.SelectToken("id")); }
private async Task <IActionResult> InternalSearch(SearchSCIMResourceParameter searchRequest) { _logger.LogInformation(Global.StartGetResources); try { if (searchRequest.Count > _options.MaxResults) { searchRequest.Count = _options.MaxResults; } var schema = await _scimSchemaQueryRepository.FindRootSCIMSchemaByResourceType(_resourceType); var schemaIds = new List <string> { schema.Id }; schemaIds.AddRange(schema.SchemaExtensions.Select(s => s.Schema)); var schemas = (await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(schemaIds)).ToList(); var result = await _scimRepresentationQueryRepository.FindSCIMRepresentations(new SearchSCIMRepresentationsParameter(_resourceType, searchRequest.StartIndex - 1, searchRequest.Count, searchRequest.SortBy, searchRequest.SortOrder, SCIMFilterParser.Parse(searchRequest.Filter, schemas))); var jObj = new JObject { { SCIMConstants.StandardSCIMRepresentationAttributes.Schemas, new JArray(new [] { SCIMConstants.StandardSchemas.ListResponseSchemas.Id }) }, { SCIMConstants.StandardSCIMRepresentationAttributes.TotalResults, result.TotalResults }, { SCIMConstants.StandardSCIMRepresentationAttributes.ItemsPerPage, searchRequest.Count }, { SCIMConstants.StandardSCIMRepresentationAttributes.StartIndex, searchRequest.StartIndex } }; var resources = new JArray(); var baseUrl = Request.GetAbsoluteUriWithVirtualPath(); var representations = result.Content.ToList(); await _attributeReferenceEnricher.Enrich(_resourceType, representations, baseUrl); foreach (var record in representations) { JObject newJObj = null; var location = $"{baseUrl}/{_resourceType}/{record.Id}"; if (searchRequest.Attributes.Any()) { newJObj = record.ToResponseWithIncludedAttributes(searchRequest.Attributes.Select(a => SCIMFilterParser.Parse(a, schemas)).ToList()); } else if (searchRequest.ExcludedAttributes.Any()) { newJObj = record.ToResponseWithExcludedAttributes(searchRequest.ExcludedAttributes.Select(a => SCIMFilterParser.Parse(a, schemas)).ToList(), location); } else { newJObj = record.ToResponse(location, true); } resources.Add(newJObj); } jObj.Add(SCIMConstants.StandardSCIMRepresentationAttributes.Resources, resources); return(new ContentResult { StatusCode = (int)HttpStatusCode.OK, Content = jObj.ToString(), ContentType = SCIMConstants.STANDARD_SCIM_CONTENT_TYPE }); } catch (SCIMFilterException ex) { _logger.LogError(ex, ex.Message); return(this.BuildError(HttpStatusCode.BadRequest, ex.Message, SCIMConstants.ErrorSCIMTypes.InvalidFilter)); } catch (Exception ex) { _logger.LogError(ex, ex.Message); return(this.BuildError(HttpStatusCode.InternalServerError, ex.ToString(), SCIMConstants.ErrorSCIMTypes.InternalServerError)); } }
public static void ApplyPatches(this SCIMRepresentation representation, ICollection <SCIMPatchOperationRequest> patches) { var queryableRepresentationAttributes = representation.Attributes.AsQueryable(); foreach (var patch in patches) { var attributes = GetRepresentationAttributeFromPath(queryableRepresentationAttributes, SCIMFilterParser.Parse(patch.Path, representation.Schemas)).ToList(); if (!attributes.Any()) { throw new SCIMAttributeException("PATCH can be applied only on existing attributes"); } var removeCallback = new Action <ICollection <SCIMRepresentationAttribute> >((attrs) => { foreach (var a in attrs) { if (a.Parent != null) { a.Parent.Values.Remove(a); } else { representation.Attributes.Remove(a); } } }); if (patch.Operation == SCIMPatchOperations.REMOVE || patch.Operation == SCIMPatchOperations.REPLACE) { removeCallback(attributes); } if (patch.Operation == SCIMPatchOperations.ADD) { removeCallback(attributes.Where(a => !a.SchemaAttribute.MultiValued).ToList()); } if (patch.Operation == SCIMPatchOperations.ADD || patch.Operation == SCIMPatchOperations.REPLACE) { var firstAttribute = attributes.First(); var newAttributes = ExtractRepresentationAttributesFromJSON(firstAttribute.SchemaAttribute, patch.Value); foreach (var newAttribute in newAttributes) { if (firstAttribute.Parent != null) { firstAttribute.Parent.Values.Add(newAttribute); } else { representation.Attributes.Add(newAttribute); } } } } }
public static List <SCIMPatchResult> ApplyPatches(this SCIMRepresentation representation, ICollection <PatchOperationParameter> patches, bool ignoreUnsupportedCanonicalValues) { var result = new List <SCIMPatchResult>(); foreach (var patch in patches) { var scimFilter = SCIMFilterParser.Parse(patch.Path, representation.Schemas); var schemaAttributes = representation.Schemas.SelectMany(_ => _.Attributes); List <SCIMRepresentationAttribute> attributes = null; string fullPath = null; if (scimFilter != null) { var scimAttributeExpression = scimFilter as SCIMAttributeExpression; if (scimAttributeExpression == null) { throw new SCIMAttributeException(Global.InvalidAttributeExpression); } fullPath = scimAttributeExpression.GetFullPath(); schemaAttributes = representation.Schemas .Select(s => s.GetAttribute(fullPath)) .Where(s => s != null); attributes = scimAttributeExpression.EvaluateAttributes(representation.HierarchicalAttributes.AsQueryable(), true).ToList(); } else { attributes = representation.FlatAttributes.Where(h => h.IsLeaf()).ToList(); } var removeCallback = new Action <ICollection <SCIMRepresentationAttribute> >((attrs) => { foreach (var a in attrs) { var removedAttrs = representation.RemoveAttributeById(a); foreach (var removedAttr in removedAttrs) { result.Add(new SCIMPatchResult { Attr = removedAttr, Operation = SCIMPatchOperations.REMOVE, Path = removedAttr.FullPath }); } } }); switch (patch.Operation) { case SCIMPatchOperations.ADD: try { if (schemaAttributes == null || !schemaAttributes.Any()) { throw new SCIMNoTargetException(string.Format(Global.AttributeIsNotRecognirzed, patch.Path)); } var newAttributes = ExtractRepresentationAttributesFromJSON(representation.Schemas, schemaAttributes.ToList(), patch.Value, ignoreUnsupportedCanonicalValues); CheckDuplicate(attributes, newAttributes); removeCallback(attributes.Where(a => !a.SchemaAttribute.MultiValued && a.FullPath == fullPath).ToList()); var isAttributeExits = !string.IsNullOrWhiteSpace(fullPath) && attributes.Any(a => a.FullPath == fullPath); foreach (var newAttribute in newAttributes.OrderBy(a => a.GetLevel())) { var path = newAttribute.FullPath; var schemaAttr = newAttribute.SchemaAttribute; IEnumerable <SCIMRepresentationAttribute> parentAttributes = null; if (fullPath == path) { var attr = attributes.FirstOrDefault(a => a.FullPath == fullPath); if (attr != null) { var parent = representation.GetParentAttribute(attr); if (parent != null) { parentAttributes = new[] { parent }; } } else { parentAttributes = representation.GetParentAttributesByPath(fullPath).ToList(); } } if (schemaAttr.MultiValued && schemaAttr.Type != SCIMSchemaAttributeTypes.COMPLEX) { var filteredAttribute = attributes.FirstOrDefault(_ => _.FullPath == path); if (filteredAttribute != null) { newAttribute.AttributeId = filteredAttribute.AttributeId; } representation.AddAttribute(newAttribute); } else if (parentAttributes != null && parentAttributes.Any()) { foreach (var parentAttribute in parentAttributes) { representation.AddAttribute(parentAttribute, newAttribute); } } else { representation.FlatAttributes.Add(newAttribute); } attributes.Add(newAttribute); result.Add(new SCIMPatchResult { Attr = newAttribute, Operation = SCIMPatchOperations.ADD, Path = fullPath }); } if (TryGetExternalId(patch, out string externalId)) { representation.ExternalId = externalId; } } catch (SCIMSchemaViolatedException) { continue; } break; case SCIMPatchOperations.REMOVE: { if (scimFilter == null) { throw new SCIMNoTargetException(string.Format(Global.InvalidPath, patch.Path)); } if (SCIMFilterParser.DontContainsFilter(patch.Path) && patch.Value != null) { var excludedAttributes = ExtractRepresentationAttributesFromJSON(representation.Schemas, schemaAttributes.ToList(), patch.Value, ignoreUnsupportedCanonicalValues); excludedAttributes = SCIMRepresentation.BuildHierarchicalAttributes(excludedAttributes); attributes = attributes.Where(a => excludedAttributes.Any(ea => ea.IsSimilar(a, true))).ToList(); } removeCallback(attributes); } break; case SCIMPatchOperations.REPLACE: { if (TryGetExternalId(patch, out string externalId)) { representation.ExternalId = externalId; continue; } if (schemaAttributes == null || !schemaAttributes.Any()) { throw new SCIMNoTargetException(string.Format(Global.AttributeIsNotRecognirzed, patch.Path)); } var complexAttr = scimFilter as SCIMComplexAttributeExpression; if (complexAttr != null && !attributes.Any() && complexAttr.GroupingFilter != null) { throw new SCIMNoTargetException(Global.PatchMissingAttribute); } try { List <SCIMRepresentationAttribute> parents = new List <SCIMRepresentationAttribute>(); if (complexAttr != null) { var attr = attributes.First(a => a.FullPath == fullPath); var parent = string.IsNullOrWhiteSpace(attr.ParentAttributeId) ? attr : representation.GetParentAttribute(attributes.First(a => a.FullPath == fullPath)); if (parent != null) { parents = new List <SCIMRepresentationAttribute> { parent }; } } else { parents = representation.GetParentAttributesByPath(fullPath).ToList(); } if (scimFilter != null && parents.Any()) { foreach (var parent in parents) { var flatHiearchy = representation.GetFlatHierarchicalChildren(parent).ToList(); var scimAttributeExpression = scimFilter as SCIMAttributeExpression; var newAttributes = ExtractRepresentationAttributesFromJSON(representation.Schemas, schemaAttributes.ToList(), patch.Value, ignoreUnsupportedCanonicalValues); foreach (var newAttribute in newAttributes.OrderBy(l => l.GetLevel())) { if (!flatHiearchy.Any(a => a.FullPath == newAttribute.FullPath)) { var parentPath = SCIMRepresentation.GetParentPath(newAttribute.FullPath); var p = flatHiearchy.FirstOrDefault(a => a.FullPath == parentPath); if (p != null) { representation.AddAttribute(p, newAttribute); } else { representation.AddAttribute(newAttribute); } result.Add(new SCIMPatchResult { Attr = newAttribute, Operation = SCIMPatchOperations.ADD, Path = fullPath }); } } result.AddRange(Merge(flatHiearchy, newAttributes, fullPath)); } } else { var newAttributes = ExtractRepresentationAttributesFromJSON(representation.Schemas, schemaAttributes.ToList(), patch.Value, ignoreUnsupportedCanonicalValues); var flatHiearchy = representation.FlatAttributes.ToList(); var missingAttributes = newAttributes.Where(na => string.IsNullOrEmpty(na.ParentAttributeId) && !flatHiearchy.Any(fh => string.IsNullOrWhiteSpace(fh.ParentAttributeId) && fh.SchemaAttributeId == na.SchemaAttributeId)).ToList(); missingAttributes.ForEach((ma) => { representation.AddAttribute(ma); result.Add(new SCIMPatchResult { Attr = ma, Operation = SCIMPatchOperations.ADD, Path = ma.FullPath }); }); result.AddRange(Merge(flatHiearchy, newAttributes, fullPath)); } } catch (SCIMSchemaViolatedException) { continue; } } break; } } var displayNameAttr = representation.FlatAttributes.FirstOrDefault(a => a.FullPath == "displayName"); if (displayNameAttr != null) { representation.SetDisplayName(displayNameAttr.ValueString); } return(result); }
public static void ApplyPatches(this SCIMRepresentation representation, ICollection <PatchOperationParameter> patches, bool ignoreUnsupportedCanonicalValues) { var queryableRepresentationAttributes = representation.Attributes.AsQueryable(); foreach (var patch in patches) { var scimFilter = SCIMFilterParser.Parse(patch.Path, representation.Schemas); var attributeExpression = scimFilter as SCIMAttributeExpression; if (attributeExpression == null) { throw new SCIMAttributeException(string.Format(Global.InvalidPath, patch.Path)); } var fullPath = attributeExpression.GetFullPath(); var schemaAttributes = representation.Schemas.Select(s => s.GetAttribute(fullPath)).Where(s => s != null); if (!schemaAttributes.Any()) { throw new SCIMAttributeException(string.Format(Global.UnknownPath, patch.Path)); } var schemaAttribute = schemaAttributes.First(); var attributes = GetRepresentationAttributeFromPath(queryableRepresentationAttributes, scimFilter).ToList(); if (!attributes.Any() && schemaAttribute.Type != SCIMSchemaAttributeTypes.COMPLEX && !schemaAttribute.MultiValued) { throw new SCIMAttributeException(Global.PatchMissingAttribute); } var removeCallback = new Action <ICollection <SCIMRepresentationAttribute> >((attrs) => { foreach (var a in attrs) { if (a.Parent != null) { a.Parent.Values.Remove(a); } else { representation.Attributes.Remove(a); } } }); if (patch.Operation == SCIMPatchOperations.REMOVE || patch.Operation == SCIMPatchOperations.REPLACE) { removeCallback(attributes); } if (patch.Operation == SCIMPatchOperations.ADD) { removeCallback(attributes.Where(a => !a.SchemaAttribute.MultiValued).ToList()); } if (patch.Operation == SCIMPatchOperations.ADD || patch.Operation == SCIMPatchOperations.REPLACE) { var newAttributes = ExtractRepresentationAttributesFromJSON(schemaAttribute, patch.Value, ignoreUnsupportedCanonicalValues); foreach (var newAttribute in newAttributes) { var parentAttribute = representation.GetParentAttribute(fullPath); var attribute = representation.GetAttribute(fullPath); if (schemaAttribute.Type == SCIMSchemaAttributeTypes.COMPLEX && parentAttribute != null) { parentAttribute.Values.Add(newAttribute); continue; } if (attribute != null && schemaAttribute.Type != SCIMSchemaAttributeTypes.COMPLEX) { if (schemaAttribute.Type == SCIMSchemaAttributeTypes.BOOLEAN) { foreach (var b in newAttribute.ValuesBoolean) { attribute.ValuesBoolean.Add(b); } } else if (schemaAttribute.Type == SCIMSchemaAttributeTypes.DATETIME) { foreach (var d in newAttribute.ValuesDateTime) { attribute.ValuesDateTime.Add(d); } } else if (schemaAttribute.Type == SCIMSchemaAttributeTypes.INTEGER) { foreach (var i in newAttribute.ValuesInteger) { attribute.ValuesInteger.Add(i); } } else if (schemaAttribute.Type == SCIMSchemaAttributeTypes.REFERENCE) { foreach (var r in newAttribute.ValuesReference) { attribute.ValuesReference.Add(r); } } else if (schemaAttribute.Type == SCIMSchemaAttributeTypes.STRING) { foreach (var s in newAttribute.ValuesString) { attribute.ValuesString.Add(s); } } else if (schemaAttribute.Type == SCIMSchemaAttributeTypes.DECIMAL) { foreach (var d in newAttribute.ValuesDecimal) { attribute.ValuesDecimal.Add(d); } } else if (schemaAttribute.Type == SCIMSchemaAttributeTypes.BINARY) { foreach (var b in newAttribute.ValuesBinary) { attribute.ValuesBinary.Add(b); } } } else { representation.Attributes.Add(newAttribute); } } } } }
public static void ApplyPatches(this SCIMRepresentation representation, ICollection <PatchOperationParameter> patches, bool ignoreUnsupportedCanonicalValues) { var queryableRepresentationAttributes = representation.Attributes.AsQueryable(); foreach (var patch in patches) { var scimFilter = SCIMFilterParser.Parse(patch.Path, representation.Schemas); var attributeExpression = scimFilter as SCIMAttributeExpression; var schemaAttributes = representation.Schemas.SelectMany(_ => _.Attributes); List <SCIMRepresentationAttribute> attributes = null; string fullPath = null; if (attributeExpression != null) { fullPath = attributeExpression.GetFullPath(); schemaAttributes = representation.Schemas .Select(s => s.GetAttribute(fullPath)) .Where(s => s != null); attributes = GetRepresentationAttributeFromPath(queryableRepresentationAttributes, scimFilter).ToList(); } else { attributes = queryableRepresentationAttributes.ToList(); } var removeCallback = new Func <ICollection <SCIMRepresentationAttribute>, List <SCIMRepresentationAttribute> >((attrs) => { var result = new List <SCIMRepresentationAttribute>(); foreach (var a in attrs) { if (a.Parent != null) { a.Parent.Values.Remove(a); result.Add(a.Parent); } else { representation.Attributes.Remove(a); } } return(result); }); switch (patch.Operation) { case SCIMPatchOperations.ADD: try { // If the target location already contains the value then do nothing ... if (schemaAttributes == null || !schemaAttributes.Any()) { throw new SCIMNoTargetException(string.Format(Global.AttributeIsNotRecognirzed, patch.Path)); } var newAttributes = ExtractRepresentationAttributesFromJSON(representation.Schemas, schemaAttributes.ToList(), patch.Value, ignoreUnsupportedCanonicalValues); var parentAttrs = removeCallback(attributes.Where(a => !a.SchemaAttribute.MultiValued && newAttributes.Any(_ => _.SchemaAttribute.Name == a.SchemaAttribute.Name)).ToList()); foreach (var newAttribute in newAttributes.Where(x => x.HasValue)) { var path = string.IsNullOrWhiteSpace(fullPath) ? newAttribute.SchemaAttribute.Name : fullPath; var schemaAttr = newAttribute.SchemaAttribute; var parentAttribute = representation.GetParentAttribute(path); if (schemaAttr.MultiValued && schemaAttr.Type != SCIMSchemaAttributeTypes.COMPLEX) { var filteredAttributes = attributes.Where(_ => _.GetFullPath() == path); foreach (var attribute in filteredAttributes) { if (schemaAttr.Type == SCIMSchemaAttributeTypes.BOOLEAN) { foreach (var b in newAttribute.ValuesBoolean) { attribute.ValuesBoolean.Add(b); } } else if (schemaAttr.Type == SCIMSchemaAttributeTypes.DATETIME) { foreach (var d in newAttribute.ValuesDateTime) { attribute.ValuesDateTime.Add(d); } } else if (schemaAttr.Type == SCIMSchemaAttributeTypes.INTEGER) { foreach (var i in newAttribute.ValuesInteger) { attribute.ValuesInteger.Add(i); } } else if (schemaAttr.Type == SCIMSchemaAttributeTypes.REFERENCE) { foreach (var r in newAttribute.ValuesReference) { attribute.ValuesReference.Add(r); } } else if (schemaAttr.Type == SCIMSchemaAttributeTypes.STRING) { foreach (var s in newAttribute.ValuesString) { attribute.ValuesString.Add(s); } } else if (schemaAttr.Type == SCIMSchemaAttributeTypes.DECIMAL) { foreach (var d in newAttribute.ValuesDecimal) { attribute.ValuesDecimal.Add(d); } } else if (schemaAttr.Type == SCIMSchemaAttributeTypes.BINARY) { foreach (var b in newAttribute.ValuesBinary) { attribute.ValuesBinary.Add(b); } } } } else if (parentAttribute != null) { if (parentAttrs.Any()) { foreach (var parentAttr in parentAttrs) { parentAttr.Add(newAttribute); } } else { parentAttribute.Add(newAttribute); } } else { if (!representation.ContainsAttribute(newAttribute)) { representation.Attributes.Add(newAttribute); } } } } catch (SCIMSchemaViolatedException) { continue; } break; case SCIMPatchOperations.REMOVE: { if (attributeExpression == null) { throw new SCIMNoTargetException(string.Format(Global.InvalidPath, patch.Path)); } removeCallback(attributes); } break; case SCIMPatchOperations.REPLACE: { if (schemaAttributes == null || !schemaAttributes.Any()) { throw new SCIMNoTargetException(string.Format(Global.AttributeIsNotRecognirzed, patch.Path)); } var complexAttr = attributeExpression as SCIMComplexAttributeExpression; if (complexAttr != null && !attributes.Any() && complexAttr.GroupingFilter != null) { throw new SCIMNoTargetException(Global.PatchMissingAttribute); } try { var newAttributes = ExtractRepresentationAttributesFromJSON(representation.Schemas, schemaAttributes.ToList(), patch.Value, ignoreUnsupportedCanonicalValues); var parentFullPath = attributes.First().Parent?.GetFullPath(); if (!string.IsNullOrWhiteSpace(parentFullPath)) { scimFilter = SCIMFilterParser.Parse(parentFullPath, representation.Schemas); var allAttrs = GetRepresentationAttributeFromPath(queryableRepresentationAttributes, scimFilter); foreach (var attr in allAttrs) { if (!attr.Values.Any(_ => attributes.Any(a => a.SchemaAttribute.Name == _.SchemaAttribute.Name))) { attr.Add(attributes.First()); } } } Merge(attributes, newAttributes); } catch (SCIMSchemaViolatedException) { continue; } } break; } } }
public async Task <IActionResult> Get() { var searchRequest = SearchSCIMResourceParameter.Create(Request.Query); try { if (searchRequest.Count > _options.MaxResults) { searchRequest.Count = _options.MaxResults; } var result = await _scimRepresentationQueryRepository.FindSCIMRepresentations(new SearchSCIMRepresentationsParameter(_scimEndpoint, searchRequest.StartIndex, searchRequest.Count, searchRequest.SortBy, searchRequest.SortOrder, SCIMFilterParser.Parse(searchRequest.Filter, _schemas))); var jObj = new JObject { { SCIMConstants.StandardSCIMRepresentationAttributes.Schemas, new JArray(new [] { SCIMConstants.StandardSchemas.ListResponseSchemas.Id }) }, { SCIMConstants.StandardSCIMRepresentationAttributes.TotalResults, result.TotalResults }, { SCIMConstants.StandardSCIMRepresentationAttributes.ItemsPerPage, searchRequest.Count }, { SCIMConstants.StandardSCIMRepresentationAttributes.StartIndex, searchRequest.StartIndex } }; var resources = new JArray(); foreach (var record in result.Content) { JObject newJObj = null; var location = $"{Request.GetAbsoluteUriWithVirtualPath()}/{_scimEndpoint}/{record.Id}"; if (searchRequest.Attributes.Any()) { newJObj = record.ToResponseWithIncludedAttributes(searchRequest.Attributes.Select(a => SCIMFilterParser.Parse(a, _schemas)).ToList()); } else if (searchRequest.ExcludedAttributes.Any()) { newJObj = record.ToResponseWithExcludedAttributes(searchRequest.ExcludedAttributes.Select(a => SCIMFilterParser.Parse(a, _schemas)).ToList(), location); } else { newJObj = record.ToResponse(location, true); } resources.Add(newJObj); } jObj.Add(SCIMConstants.StandardSCIMRepresentationAttributes.Resources, resources); return(new ContentResult { StatusCode = (int)HttpStatusCode.OK, Content = jObj.ToString(), ContentType = SCIMConstants.STANDARD_SCIM_CONTENT_TYPE }); } catch (SCIMFilterException ex) { return(this.BuildError(HttpStatusCode.BadRequest, ex.Message, "invalidFilter")); } }
protected async Task <IActionResult> InternalSearch(SearchSCIMResourceParameter searchRequest, string resourceType) { try { var schema = await _scimSchemaQueryRepository.FindRootSCIMSchemaByResourceType(resourceType); var schemaIds = new List <string> { schema.Id }; schemaIds.AddRange(schema.SchemaExtensions.Select(s => s.Schema)); var schemas = (await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(schemaIds)).ToList(); if (searchRequest.StartIndex <= 0) { return(this.BuildError(HttpStatusCode.BadRequest, Global.StartIndexMustBeSuperiorOrEqualTo1)); } var sortByFilter = SCIMFilterParser.Parse(searchRequest.SortBy, schemas); var standardSchemas = new List <SCIMSchema> { StandardSchemas.StandardResponseSchemas }; standardSchemas.AddRange(schemas); var includedAttributes = searchRequest.Attributes == null ? new List <SCIMAttributeExpression>() : searchRequest.Attributes.Select(a => SCIMFilterParser.Parse(a, standardSchemas)).Cast <SCIMAttributeExpression>().ToList(); var excludedAttributes = searchRequest.ExcludedAttributes == null ? new List <SCIMAttributeExpression>() : searchRequest.ExcludedAttributes.Select(a => SCIMFilterParser.Parse(a, standardSchemas)).Cast <SCIMAttributeExpression>().ToList(); var result = await _scimRepresentationQueryRepository.FindSCIMRepresentations(new SearchSCIMRepresentationsParameter(resourceType, searchRequest.StartIndex, searchRequest.Count.Value, sortByFilter, searchRequest.SortOrder, SCIMFilterParser.Parse(searchRequest.Filter, schemas), includedAttributes, excludedAttributes)); var jObj = new JObject { { StandardSCIMRepresentationAttributes.Schemas, new JArray(new [] { StandardSchemas.ListResponseSchemas.Id }) }, { StandardSCIMRepresentationAttributes.TotalResults, result.TotalResults }, { StandardSCIMRepresentationAttributes.ItemsPerPage, searchRequest.Count }, { StandardSCIMRepresentationAttributes.StartIndex, searchRequest.StartIndex } }; var resources = new JArray(); var baseUrl = Request.GetAbsoluteUriWithVirtualPath(); var representations = result.Content.ToList(); foreach (var representation in representations) { representation.Schemas = schemas; } await _attributeReferenceEnricher.Enrich(resourceType, representations, baseUrl); foreach (var record in representations) { JObject newJObj = null; var location = $"{baseUrl}/{_resourceTypeResolver.ResolveByResourceType(resourceType).ControllerName}/{record.Id}"; bool includeStandardRequest = true; if (searchRequest.Attributes.Any()) { record.AddStandardAttributes(location, searchRequest.Attributes, true, false); includeStandardRequest = false; } else if (searchRequest.ExcludedAttributes.Any()) { record.AddStandardAttributes(location, searchRequest.ExcludedAttributes, false, false); includeStandardRequest = false; } else { record.ApplyEmptyArray(); } newJObj = record.ToResponse(location, true, includeStandardRequest); resources.Add(newJObj); } jObj.Add(StandardSCIMRepresentationAttributes.Resources, resources); return(new ContentResult { StatusCode = (int)HttpStatusCode.OK, Content = jObj.ToString(), ContentType = SCIMConstants.STANDARD_SCIM_CONTENT_TYPE }); } catch (SCIMFilterException ex) { return(this.BuildError(HttpStatusCode.BadRequest, ex.Message, SCIMConstants.ErrorSCIMTypes.InvalidFilter)); } catch (Exception ex) { return(this.BuildError(HttpStatusCode.InternalServerError, ex.ToString(), SCIMConstants.ErrorSCIMTypes.InternalServerError)); } }
public void When_Parse_Filters() { var firstFilter = SCIMFilterParser.Parse("members[display eq \"Babs Jensen\" and value co \"2819\"]"); Assert.NotNull(firstFilter); }