public async Task <SCIMRepresentation> Handle(ReplaceRepresentationCommand replaceRepresentationCommand) { var requestedSchemas = replaceRepresentationCommand.Representation.GetSchemas(); if (!requestedSchemas.Any()) { throw new SCIMBadRequestException("invalidRequest", $"{SCIMConstants.StandardSCIMRepresentationAttributes.Schemas} attribute is missing"); } if (!replaceRepresentationCommand.SchemaIds.Any(s => requestedSchemas.Contains(s))) { throw new SCIMBadRequestException("invalidRequest", $"some schemas are not recognized by the endpoint"); } var schemas = await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(requestedSchemas); var unsupportedSchemas = requestedSchemas.Where(s => !schemas.Any(sh => sh.Id == s)); if (unsupportedSchemas.Any()) { throw new SCIMBadRequestException("invalidRequest", $"{string.Join(",", unsupportedSchemas)} schemas are unknown"); } var existingRepresentation = await _scimRepresentationQueryRepository.FindSCIMRepresentationById(replaceRepresentationCommand.Id); if (existingRepresentation == null) { throw new SCIMNotFoundException("notFound", "Resource does not exist"); } var updatedRepresentation = _scimRepresentationHelper.ExtractSCIMRepresentationFromJSON(replaceRepresentationCommand.Representation, schemas.ToList()); foreach (var updatedAttribute in updatedRepresentation.Attributes) { if (updatedAttribute.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.IMMUTABLE) { throw new SCIMImmutableAttributeException($"attribute {updatedAttribute.Id} is immutable"); } if (updatedAttribute.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.WRITEONLY || updatedAttribute.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.READWRITE) { var existingAttribute = existingRepresentation.Attributes.FirstOrDefault(a => a.SchemaAttribute.Id == updatedAttribute.SchemaAttribute.Id); if (existingAttribute == null) { existingRepresentation.AddAttribute(updatedAttribute); } else { existingRepresentation.Attributes.Remove(existingAttribute); existingRepresentation.AddAttribute(updatedAttribute); } } } existingRepresentation.SetUpdated(DateTime.UtcNow); _scimRepresentationCommandRepository.Update(existingRepresentation); await _scimRepresentationCommandRepository.SaveChanges(); return(existingRepresentation); }
public async Task <SCIMRepresentation> Handle(AddRepresentationCommand addRepresentationCommand) { var requestedSchemas = addRepresentationCommand.Representation.Schemas; if (!requestedSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.AttributeMissing, SCIMConstants.StandardSCIMRepresentationAttributes.Schemas)); } var schema = await _scimSchemaQueryRepository.FindRootSCIMSchemaByResourceType(addRepresentationCommand.ResourceType); var allSchemas = new List <string> { schema.Id }; var requiredSchemas = new List <string> { schema.Id }; allSchemas.AddRange(schema.SchemaExtensions.Select(s => s.Schema)); requiredSchemas.AddRange(schema.SchemaExtensions.Where(s => s.Required).Select(s => s.Schema)); var missingRequiredSchemas = requiredSchemas.Where(s => !requestedSchemas.Contains(s)); if (missingRequiredSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.RequiredSchemasAreMissing, string.Join(",", missingRequiredSchemas))); } var unsupportedSchemas = requestedSchemas.Where(s => !allSchemas.Contains(s)); if (unsupportedSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.SchemasAreUnknown, string.Join(",", unsupportedSchemas))); } var schemas = await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(requestedSchemas); var version = Guid.NewGuid().ToString(); var scimRepresentation = _scimRepresentationHelper.ExtractSCIMRepresentationFromJSON(addRepresentationCommand.Representation.Attributes, addRepresentationCommand.Representation.ExternalId, schema, schemas.Where(s => s.Id != schema.Id).ToList()); scimRepresentation.Id = Guid.NewGuid().ToString(); scimRepresentation.SetCreated(DateTime.UtcNow); scimRepresentation.SetUpdated(DateTime.UtcNow); scimRepresentation.SetVersion(version); scimRepresentation.SetResourceType(addRepresentationCommand.ResourceType); var uniqueServerAttributeIds = scimRepresentation.Attributes.Where(a => a.SchemaAttribute.MultiValued == false && a.SchemaAttribute.Uniqueness == SCIMSchemaAttributeUniqueness.SERVER); var uniqueGlobalAttributes = scimRepresentation.Attributes.Where(a => a.SchemaAttribute.MultiValued == false && a.SchemaAttribute.Uniqueness == SCIMSchemaAttributeUniqueness.GLOBAL); await CheckSCIMRepresentationExistsForGivenUniqueAttributes(uniqueServerAttributeIds, addRepresentationCommand.ResourceType); await CheckSCIMRepresentationExistsForGivenUniqueAttributes(uniqueGlobalAttributes); using (var transaction = await _scimRepresentationCommandRepository.StartTransaction()) { await _scimRepresentationCommandRepository.Add(scimRepresentation); await transaction.Commit(); } scimRepresentation.ApplyEmptyArray(); return(scimRepresentation); }
public async Task <SCIMRepresentation> Handle(ReplaceRepresentationCommand replaceRepresentationCommand) { var requestedSchemas = replaceRepresentationCommand.Representation.GetSchemas(); if (!requestedSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.AttributeMissing, SCIMConstants.StandardSCIMRepresentationAttributes.Schemas)); } var schema = await _scimSchemaQueryRepository.FindRootSCIMSchemaByResourceType(replaceRepresentationCommand.ResourceType); var allSchemas = new List <string> { schema.Id }; allSchemas.AddRange(schema.SchemaExtensions.Select(s => s.Schema)); var unsupportedSchemas = requestedSchemas.Where(s => !allSchemas.Contains(s)); if (unsupportedSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.SchemasAreUnknown, string.Join(",", unsupportedSchemas))); } var schemas = await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(requestedSchemas); var existingRepresentation = await _scimRepresentationQueryRepository.FindSCIMRepresentationById(replaceRepresentationCommand.Id); if (existingRepresentation == null) { throw new SCIMNotFoundException(string.Format(Global.ResourceNotFound, replaceRepresentationCommand.Id)); } var updatedRepresentation = _scimRepresentationHelper.ExtractSCIMRepresentationFromJSON(replaceRepresentationCommand.Representation, schemas.ToList()); existingRepresentation.RemoveAttributes(updatedRepresentation.Attributes.Select(_ => _.SchemaAttribute.Id)); foreach (var updatedAttribute in updatedRepresentation.Attributes) { if (updatedAttribute.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.IMMUTABLE) { throw new SCIMImmutableAttributeException(string.Format(Global.AttributeImmutable, updatedAttribute.Id)); } if (updatedAttribute.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.WRITEONLY || updatedAttribute.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.READWRITE) { existingRepresentation.AddAttribute(updatedAttribute); } } existingRepresentation.SetUpdated(DateTime.UtcNow); using (var transaction = await _scimRepresentationCommandRepository.StartTransaction()) { await _scimRepresentationCommandRepository.Update(existingRepresentation); await transaction.Commit(); } return(existingRepresentation); }
public async Task <SCIMRepresentation> Handle(AddRepresentationCommand addRepresentationCommand) { var requestedSchemas = addRepresentationCommand.Representation.GetSchemas(); if (!requestedSchemas.Any()) { throw new SCIMBadRequestException("invalidRequest", $"{SCIMConstants.StandardSCIMRepresentationAttributes.Schemas} attribute is missing"); } if (!addRepresentationCommand.SchemaIds.Any(s => requestedSchemas.Contains(s))) { throw new SCIMBadRequestException("invalidRequest", $"some schemas are not recognized by the endpoint"); } var schemas = await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(requestedSchemas); var unsupportedSchemas = requestedSchemas.Where(s => !schemas.Any(sh => sh.Id == s)); if (unsupportedSchemas.Any()) { throw new SCIMBadRequestException("invalidRequest", $"{string.Join(",", unsupportedSchemas)} schemas are unknown"); } var version = Guid.NewGuid().ToString(); var scimRepresentation = _scimRepresentationHelper.ExtractSCIMRepresentationFromJSON(addRepresentationCommand.Representation, schemas.ToList()); scimRepresentation.Id = Guid.NewGuid().ToString(); scimRepresentation.SetCreated(DateTime.UtcNow); scimRepresentation.SetUpdated(DateTime.UtcNow); scimRepresentation.SetVersion(version); scimRepresentation.SetResourceType(addRepresentationCommand.ResourceType); var uniqueServerAttributeIds = scimRepresentation.Attributes.Where(a => a.SchemaAttribute.MultiValued == false && a.SchemaAttribute.Uniqueness == SCIMSchemaAttributeUniqueness.SERVER); var uniqueGlobalAttributes = scimRepresentation.Attributes.Where(a => a.SchemaAttribute.MultiValued == false && a.SchemaAttribute.Uniqueness == SCIMSchemaAttributeUniqueness.GLOBAL); await CheckSCIMRepresentationExistsForGivenUniqueAttributes(uniqueServerAttributeIds, addRepresentationCommand.ResourceType); await CheckSCIMRepresentationExistsForGivenUniqueAttributes(uniqueGlobalAttributes); _scimRepresentationCommandRepository.Add(scimRepresentation); await _scimRepresentationCommandRepository.SaveChanges(); return(scimRepresentation); }
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)); } }
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 async Task <SCIMRepresentation> Handle(ReplaceRepresentationCommand replaceRepresentationCommand) { var requestedSchemas = replaceRepresentationCommand.Representation.Schemas; if (!requestedSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.AttributeMissing, StandardSCIMRepresentationAttributes.Schemas)); } var schema = await _scimSchemaQueryRepository.FindRootSCIMSchemaByResourceType(replaceRepresentationCommand.ResourceType); var allSchemas = new List <string> { schema.Id }; allSchemas.AddRange(schema.SchemaExtensions.Select(s => s.Schema)); var unsupportedSchemas = requestedSchemas.Where(s => !allSchemas.Contains(s)); if (unsupportedSchemas.Any()) { throw new SCIMBadSyntaxException(string.Format(Global.SchemasAreUnknown, string.Join(",", unsupportedSchemas))); } var schemas = await _scimSchemaQueryRepository.FindSCIMSchemaByIdentifiers(requestedSchemas); var lockName = $"representation-{replaceRepresentationCommand.Id}"; await _distributedLock.WaitLock(lockName, CancellationToken.None); try { var existingRepresentation = await _scimRepresentationQueryRepository.FindSCIMRepresentationById(replaceRepresentationCommand.Id); if (existingRepresentation == null) { throw new SCIMNotFoundException(string.Format(Global.ResourceNotFound, replaceRepresentationCommand.Id)); } var oldRepresentation = (SCIMRepresentation)existingRepresentation.Clone(); var mainSchema = schemas.First(s => s.Id == schema.Id); var extensionSchemas = schemas.Where(s => s.Id != schema.Id).ToList(); var updatedRepresentation = _scimRepresentationHelper.ExtractSCIMRepresentationFromJSON( replaceRepresentationCommand.Representation.Attributes, replaceRepresentationCommand.Representation.ExternalId, mainSchema, extensionSchemas); var allExistingAttributes = existingRepresentation.HierarchicalAttributes; existingRepresentation.RemoveAttributesBySchemaAttrId(updatedRepresentation.FlatAttributes.Select(_ => _.SchemaAttribute.Id)); foreach (var kvp in updatedRepresentation.HierarchicalAttributes.GroupBy(h => h.FullPath)) { var fullPath = kvp.Key; var filteredExistingAttributes = allExistingAttributes.Where(a => a.FullPath == fullPath); var invalidAttrs = filteredExistingAttributes.Where(fa => !kvp.Any(a => a.IsMutabilityValid(fa))); if (invalidAttrs.Any()) { throw new SCIMImmutableAttributeException(string.Format(Global.AttributeImmutable, string.Join(",", invalidAttrs.Select(a => a.FullPath)))); } foreach (var rootAttr in kvp) { if (rootAttr.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.WRITEONLY || rootAttr.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.READWRITE || rootAttr.SchemaAttribute.Mutability == SCIMSchemaAttributeMutabilities.IMMUTABLE) { var flatAttrs = rootAttr.ToFlat(); foreach (var attr in flatAttrs) { existingRepresentation.AddAttribute(attr); } } } } existingRepresentation.SetDisplayName(updatedRepresentation.DisplayName); existingRepresentation.SetExternalId(updatedRepresentation.ExternalId); existingRepresentation.SetUpdated(DateTime.UtcNow); var isReferenceProperty = await _representationReferenceSync.IsReferenceProperty(replaceRepresentationCommand.Representation.Attributes.GetKeys()); var references = await _representationReferenceSync.Sync(replaceRepresentationCommand.ResourceType, oldRepresentation, existingRepresentation, replaceRepresentationCommand.Location, !isReferenceProperty); using (var transaction = await _scimRepresentationCommandRepository.StartTransaction()) { await _scimRepresentationCommandRepository.Update(existingRepresentation); foreach (var reference in references.Representations) { await _scimRepresentationCommandRepository.Update(reference); } await transaction.Commit(); } await Notify(references); existingRepresentation.ApplyEmptyArray(); return(existingRepresentation); } finally { await _distributedLock.ReleaseLock(lockName, CancellationToken.None); } }