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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
        }
Exemple #5
0
        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));
            }
        }
Exemple #7
0
        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);
            }
        }