예제 #1
0
        /// <summary>
        /// Create the member processor callbacks.
        /// </summary>
        private List <MemberProcessor> CreateMemberProcessors(ApiResourceMapping mapping, ReaderToEntityAdapterSettings settings)
        {
            var memberProcessors = new List <MemberProcessor>( );

            // Process mapped members
            // Note: we intentionally ignore unrecognised members.
            foreach (ApiMemberMapping memberMappings in mapping.ResourceMemberMappings)
            {
                MemberProcessor memberProcessor;

                // Fill field
                ApiFieldMapping fieldMapping = memberMappings.As <ApiFieldMapping>( );
                if (fieldMapping != null)
                {
                    memberProcessor = CreateFieldProcessor(fieldMapping, settings);
                    memberProcessors.Add(memberProcessor);
                    continue;
                }

                // Fill relationship
                ApiRelationshipMapping relMapping = memberMappings.As <ApiRelationshipMapping>( );
                if (relMapping != null)
                {
                    memberProcessor = CreateRelationshipProcessor(relMapping, settings);
                    memberProcessors.Add(memberProcessor);
                    continue;
                }

                // Assert false
                throw new InvalidOperationException("Unknown member mapping");
            }

            return(memberProcessors);
        }
        /// <summary>
        /// Creates a resolver to look up entities at the far end of a relationship.
        /// </summary>
        /// <param name="mapping">The relationship mapping rules.</param>
        /// <returns>
        /// The entity
        /// </returns>
        /// <exception cref="System.ArgumentNullException">mapping</exception>
        /// <exception cref="ConnectorConfigException"></exception>
        public IResourceResolver GetResolverForRelationshipMapping(ApiRelationshipMapping mapping)
        {
            if (mapping == null)
            {
                throw new ArgumentNullException(nameof(mapping));
            }

            // Get type of entity being mapped, and mapping field
            long typeId;
            long?fieldId;

            using (new SecurityBypassContext( ))
            {
                bool         isRev        = mapping.MapRelationshipInReverse == true;
                Relationship relationship = mapping.MappedRelationship;
                if (relationship == null)
                {
                    throw new ConnectorConfigException(Messages.RelationshipMappingHasNoRelationship);
                }

                EntityType entityType = isRev ? relationship.FromType : relationship.ToType;
                if (entityType == null)
                {
                    throw new Exception("Relationship is missing from-type or to-type.");
                }

                typeId = entityType.Id;

                Field field = mapping.MappedRelationshipLookupField;
                fieldId = field?.Id;
            }

            return(GetResolverImpl(typeId, fieldId));
        }
예제 #3
0
        /// <summary>
        /// Create a delegate that will copy a single relationship member from a reader to an entity.
        /// </summary>
        private MemberProcessor CreateRelationshipProcessor(ApiRelationshipMapping mapping, ReaderToEntityAdapterSettings settings)
        {
            // Get relationship definition
            Relationship relationship = mapping.MappedRelationship;
            Direction    dir          = mapping.MapRelationshipInReverse == true ? Direction.Reverse : Direction.Forward;

            if (relationship == null)
            {
                throw new ConnectorConfigException(string.Format(Messages.RelationshipMappingHasNoRelationship, mapping.Name));
            }

            // Determine if mandatory
            bool mandatory = mapping.ApiMemberIsRequired == true ||
                             (dir == Direction.Forward && relationship.RelationshipIsMandatory == true) ||
                             (dir == Direction.Reverse && relationship.RevRelationshipIsMandatory == true);

            // Get a resolver
            IResourceResolver resourceResolver = _resourceResolverProvider.GetResolverForRelationshipMapping(mapping);

            // Get mapping name
            string memberName    = mapping.Name;
            string relName       = (dir == Direction.Forward ? relationship.ToName : relationship.FromName) ?? relationship.Name;
            string reportingName = GetReportingName(memberName, relName, settings);

            // Support lookup on other fields
            Field lookupField = mapping.MappedRelationshipLookupField;

            // Create callback that can read the target identifier(s) out of an object reader.
            bool isLookup = relationship.IsLookup(dir);
            Func <IObjectReader, string, IReadOnlyCollection <object> > identityReader;

            if (lookupField != null && lookupField.Is <IntField>( ))
            {
                if (isLookup)
                {
                    identityReader = GetIntIdentityFromLookup;
                }
                else
                {
                    identityReader = GetIntIdentitiesFromRelationship;
                }
            }
            else
            {
                if (isLookup)
                {
                    identityReader = GetStringIdentityFromLookup;
                }
                else
                {
                    identityReader = GetStringIdentitiesFromRelationship;
                }
            }

            // Create processor that copies value.
            Action <IEnumerable <ReaderEntityPair>, IImportReporter> processor = (readerEntityPairs, reporter) => RelationshipProcessorImpl(readerEntityPairs, identityReader, resourceResolver, memberName, relationship.Id, dir, mandatory, reporter, reportingName);

            return(new MemberProcessor(processor));
        }
예제 #4
0
        public void Test_DefaultToRelationship(bool mapped, string json, string expect)
        {
            string jsonMember = "member";

            // Create a type mapping
            EntityType         entityTypeResource  = new EntityType( );
            EntityType         entityTypeResource2 = Entity.Get <EntityType>("test:allFields");
            Resource           referencedValue     = Factory.ScriptNameResolver.GetInstance("Test 10", entityTypeResource2.Id).As <Resource>( );
            Resource           defaultValue        = Factory.ScriptNameResolver.GetInstance("Test 11", entityTypeResource2.Id).As <Resource>( );
            ApiResourceMapping typeMapping         = new ApiResourceMapping( );

            typeMapping.MappedType = entityTypeResource;

            // Create a member mapping
            Relationship rel = new Relationship( );

            rel.FromType           = entityTypeResource;
            rel.ToType             = entityTypeResource2;
            rel.Cardinality_Enum   = CardinalityEnum_Enumeration.OneToOne;
            rel.ToTypeDefaultValue = defaultValue;
            ApiRelationshipMapping relMapping = new ApiRelationshipMapping( );

            relMapping.MappedRelationship = rel;
            relMapping.Name = jsonMember;

            entityTypeResource.Save( );
            rel.Save( );

            if (mapped)
            {
                typeMapping.ResourceMemberMappings.Add(relMapping.As <ApiMemberMapping>( ));
            }

            // Fill entity
            IEntity entity = RunTest(json, typeMapping);
            IEntity target = entity.GetRelationships(rel.Id, Direction.Forward).SingleOrDefault( );

            if (expect == "null")
            {
                Assert.That(target, Is.Null);
            }
            else
            {
                Assert.That(target, Is.Not.Null);
                if (expect == "default")
                {
                    Assert.That(target.Id, Is.EqualTo(defaultValue.Id));
                }
                else
                {
                    Assert.That(target.Id, Is.EqualTo(referencedValue.Id));
                }
            }
        }
예제 #5
0
        public static ApiRelationshipMapping CreateApiRelationshipMapping(ApiResourceMapping resourceMapping, EntityRef relationship, string memberName, bool isReverse)
        {
            Relationship           relResource = Entity.Get <Relationship>(relationship);
            ApiRelationshipMapping mapping     = new ApiRelationshipMapping( );

            mapping.MappedRelationship       = relResource;
            mapping.MapRelationshipInReverse = isReverse;
            mapping.Name = memberName;
            resourceMapping.ResourceMemberMappings.Add(mapping.As <ApiMemberMapping>( ));

            return(mapping);
        }
예제 #6
0
        public void Test_MandatoryRelationship(string mandatoryDefinedOn, bool provided, bool isNull)
        {
            // Create JSON
            string jsonMember = "member";
            string jsonData   = isNull ? "null" : "\"Test 10\"";
            string json       = "{\"" + jsonMember + "\":" + jsonData + "}";

            if (!provided)
            {
                json = json.Replace(jsonMember, "somethingelse");
            }

            // Create a type mapping
            EntityType         entityTypeResource  = new EntityType();
            EntityType         entityTypeResource2 = Entity.Get <EntityType>("test:allFields");
            ApiResourceMapping typeMapping         = new ApiResourceMapping();

            typeMapping.MappedType = entityTypeResource;

            // Create a member mapping
            Relationship rel = new Relationship();

            rel.FromType         = entityTypeResource;
            rel.ToType           = entityTypeResource2;
            rel.Cardinality_Enum = CardinalityEnum_Enumeration.OneToOne;
            ApiRelationshipMapping relMapping = new ApiRelationshipMapping();

            relMapping.MappedRelationship = rel;
            relMapping.Name = jsonMember;
            typeMapping.ResourceMemberMappings.Add(relMapping.As <ApiMemberMapping>());
            if (mandatoryDefinedOn == "Mapping")
            {
                relMapping.ApiMemberIsRequired = true;
            }
            if (mandatoryDefinedOn == "Schema")
            {
                rel.RelationshipIsMandatory = true;
            }
            entityTypeResource.Save( );

            // Fill entity
            if (provided && !isNull)
            {
                IEntity entity = RunTest(json, typeMapping);
            }
            else
            {
                Assert.Throws <ConnectorRequestException>(() => RunTest(json, typeMapping), "E1010 '" + jsonMember + "' value is required.");
            }
        }
예제 #7
0
        public void Setup( )
        {
            // Getting Forbidden? Or ConnectorConfigException?
            // Maybe there's duplicate copies of these objects in the DB.

            // Define key and user
            using (new TenantAdministratorContext(TenantName))
            {
                // Define schema
                type = new EntityType( );
                type.Inherits.Add(UserResource.UserResource_Type);
                type.Name = "Test type " + Guid.NewGuid( );
                type.Save( );

                type2 = new EntityType();
                type2.Inherits.Add(UserResource.UserResource_Type);
                type2.Name = "Test type2 " + Guid.NewGuid();
                type2.Save();

                stringField               = new StringField( );
                stringField.Name          = "Field 1";
                stringField.FieldIsOnType = type;
                stringField.Save( );

                lookup = new Relationship();
                lookup.Cardinality_Enum = CardinalityEnum_Enumeration.OneToOne;
                lookup.FromType         = type;
                lookup.ToType           = type2;

                // Define API
                mapping            = new ApiResourceMapping( );
                mapping.Name       = "Test mapping " + Guid.NewGuid( );;
                mapping.MappedType = type;
                mapping.Save( );

                lookupMapping      = new ApiRelationshipMapping();
                lookupMapping.Name = "lookup1";
                lookupMapping.MappedRelationship       = lookup;
                lookupMapping.MemberForResourceMapping = mapping;
                lookupMapping.Save();

                fieldMapping             = new ApiFieldMapping( );
                fieldMapping.Name        = "field1";
                fieldMapping.MappedField = stringField.As <Field>( );
                fieldMapping.MemberForResourceMapping = mapping;
                fieldMapping.Save( );

                endpoint      = new ApiResourceEndpoint( );
                endpoint.Name = "Test endpoint " + Guid.NewGuid( );
                endpoint.ApiEndpointAddress      = EndpointAddress;
                endpoint.EndpointResourceMapping = mapping;
                endpoint.ApiEndpointEnabled      = true;
                endpoint.EndpointCanCreate       = true;
                endpoint.EndpointCanDelete       = true;
                endpoint.EndpointCanUpdate       = true;
                endpoint.Save( );

                api            = new Api( );
                api.Name       = "Test API " + Guid.NewGuid( );;
                api.ApiAddress = ApiAddress;
                api.ApiEnabled = true;
                api.ApiEndpoints.Add(endpoint.As <ApiEndpoint>( ));
                api.Save( );

                // Define access
                userAccount      = new UserAccount( );
                userAccount.Name = "Test user " + Guid.NewGuid( );
                userAccount.AccountStatus_Enum = UserAccountStatusEnum_Enumeration.Active;
                userAccount.Password           = "******";
                userAccount.Save( );

                key      = new ApiKey( );
                key.Name = ApiKey;
                key.ApiKeyUserAccount = userAccount;
                key.ApiKeyEnabled     = true;
                key.KeyForApis.Add(api);
                key.Save( );

                updateInstance             = Entity.Create(type).AsWritable <Resource>( );
                updateInstance.Name        = updateInstanceName = "ResourceToUpdate" + Guid.NewGuid( );
                updateInstance.Description = updateInstanceDesc = "ResourceToUpdate" + Guid.NewGuid( );
                updateInstance.Save( );
                updateInstanceGuid = updateInstance.UpgradeId;

                IAccessRuleFactory accessControlHelper = new AccessRuleFactory( );
                accessRule = accessControlHelper.AddAllowCreate(userAccount.As <Subject>( ), type.As <SecurableEntity>( ));
                accessRule = accessControlHelper.AddAllowByQuery(userAccount.As <Subject>( ), type.As <SecurableEntity>( ), new[] { Permissions.Read, Permissions.Modify, Permissions.Delete }, TestQueries.Entities(type).ToReport( ));
            }

            cleanup = new List <IEntity> {
                userAccount, key, api, type, mapping, endpoint, fieldMapping, stringField, accessRule, updateInstance
            };
        }
예제 #8
0
        private void CreateScenarioImpl(string testInstanceName, Func <EntityRef[]> permissionsCallback)
        {
            // Define key and user
            using (new TenantAdministratorContext(TenantName))
            {
                // Define schema
                type = new EntityType( );
                type.Inherits.Add(UserResource.UserResource_Type);
                type.Name = "Test type " + Guid.NewGuid( );
                type.Save( );

                type2 = new EntityType( );
                type2.Inherits.Add(UserResource.UserResource_Type);
                type2.Name = "Test type2 " + Guid.NewGuid( );
                type2.Save( );

                stringField               = new StringField( );
                stringField.Name          = "Field 1";
                stringField.FieldIsOnType = type;
                stringField.MaxLength     = 50;
                stringField.Save( );

                lookup = new Relationship( );
                lookup.Cardinality_Enum = CardinalityEnum_Enumeration.OneToOne;
                lookup.FromType         = type;
                lookup.ToType           = type2;

                relationship = new Relationship( );
                relationship.Cardinality_Enum = CardinalityEnum_Enumeration.ManyToMany;
                relationship.FromType         = type;
                relationship.ToType           = type2;

                // Define API
                mapping            = new ApiResourceMapping( );
                mapping.Name       = "Test mapping " + Guid.NewGuid( );;
                mapping.MappedType = type;
                mapping.Save( );

                fieldMapping             = new ApiFieldMapping( );
                fieldMapping.Name        = "field1";
                fieldMapping.MappedField = stringField.As <Field>( );
                fieldMapping.MemberForResourceMapping = mapping;
                fieldMapping.Save( );

                lookupMapping      = new ApiRelationshipMapping( );
                lookupMapping.Name = "lookup1";
                lookupMapping.MappedRelationship       = lookup;
                lookupMapping.MemberForResourceMapping = mapping;
                lookupMapping.Save( );

                relationshipMapping      = new ApiRelationshipMapping( );
                relationshipMapping.Name = "rel1";
                relationshipMapping.MappedRelationship       = relationship;
                relationshipMapping.MemberForResourceMapping = mapping;
                relationshipMapping.Save( );

                endpoint      = new ApiResourceEndpoint( );
                endpoint.Name = "Test endpoint " + Guid.NewGuid( );;
                endpoint.ApiEndpointAddress      = EndpointAddress;
                endpoint.EndpointResourceMapping = mapping;
                endpoint.ApiEndpointEnabled      = true;
                endpoint.EndpointCanCreate       = true;
                endpoint.EndpointCanUpdate       = true;
                endpoint.EndpointCanDelete       = true;
                endpoint.Save( );

                api            = new Api( );
                api.Name       = "Test API " + Guid.NewGuid( );;
                api.ApiAddress = ApiAddress;
                api.ApiEnabled = true;
                api.ApiEndpoints.Add(endpoint.As <ApiEndpoint>( ));
                api.Save( );

                // Define access
                userAccount      = new UserAccount( );
                userAccount.Name = "Test user " + Guid.NewGuid( );
                userAccount.AccountStatus_Enum = UserAccountStatusEnum_Enumeration.Active;
                userAccount.Password           = "******";
                userAccount.Save( );

                key      = new ApiKey( );
                key.Name = ApiKey;
                key.ApiKeyUserAccount = userAccount;
                key.ApiKeyEnabled     = true;
                key.KeyForApis.Add(api);
                key.Save( );

                if (testInstanceName != null)
                {
                    scenarioInstance = Entity.Create(type);
                    scenarioInstance.SetField("core:name", testInstanceName);
                    scenarioInstance.Save( );
                }

                foreignName     = "Foreign" + Guid.NewGuid( ).ToString( );
                foreignInstance = Entity.Create(type2);
                foreignInstance.SetField("core:name", foreignName);
                foreignInstance.Save( );

                // Grant create
                var permissions = permissionsCallback( );
                IAccessRuleFactory accessControlHelper = new AccessRuleFactory( );
                if (permissions [0] == Permissions.Create)
                {
                    accessControlHelper.AddAllowCreate(userAccount.As <Subject>( ), type.As <SecurableEntity>( ));
                }
                else if (permissions.Length > 0)
                {
                    accessControlHelper.AddAllowByQuery(userAccount.As <Subject>( ), type.As <SecurableEntity>( ), permissions, TestQueries.Entities(type).ToReport( ));
                }

                accessControlHelper.AddAllowByQuery(userAccount.As <Subject>( ), type2.As <SecurableEntity>( ), new [] { Permissions.Read, Permissions.Modify }, TestQueries.Entities(type2).ToReport( ));
            }
        }