/// <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)); }
/// <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)); }
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)); } } }
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); }
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."); } }
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 }; }
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( )); } }