Skip to content

Commit

Permalink
Using IEnumerables for Options (#80)
Browse files Browse the repository at this point in the history
* adding changes for using ienumerables for options

* removes redundant conversion

* Adding checks for empty items

* fixing console output messages

* adding empty checks for ienumerable options in addition to null

* checking in hawaii-engine sub-module

* Checking in changes from engine

* fixes formatting

* adding test for update command with multiple mapping fields

* fix formatting

* removing extra spaces

* incorporating PR review suggestions

* checnking-in latest changes from hawaii engine

* adding changes to remove empty mappings property in config json

* minor correction in the test command

* adding a test to validate the config json generated

* minor correction in the test
  • Loading branch information
severussundar committed Jul 19, 2022
1 parent 9bac47d commit 05bc379
Show file tree
Hide file tree
Showing 9 changed files with 515 additions and 270 deletions.
2 changes: 1 addition & 1 deletion Hawaii-Cli/hawaii-engine
Submodule hawaii-engine updated from 569afb to f62299
50 changes: 25 additions & 25 deletions Hawaii-Cli/src/Models/CommandLineOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ public class EntityOptions : Options
string entity,
string? restRoute,
string? graphQLType,
string? fieldsToInclude,
string? fieldsToExclude,
IEnumerable<string>? fieldsToInclude,
IEnumerable<string>? fieldsToExclude,
string? policyRequest,
string? policyDatabase,
string name)
Expand All @@ -99,11 +99,11 @@ public class EntityOptions : Options
[Option("graphql", Required = false, HelpText = "Type of graphQL.")]
public string? GraphQLType { get; }

[Option("fields.include", Required = false, HelpText = "Fields that are allowed access to permission.")]
public string? FieldsToInclude { get; }
[Option("fields.include", Required = false, Separator = ',', HelpText = "Fields that are allowed access to permission.")]
public IEnumerable<string>? FieldsToInclude { get; }

[Option("fields.exclude", Required = false, HelpText = "Fields that are excluded from the action lists.")]
public string? FieldsToExclude { get; }
[Option("fields.exclude", Required = false, Separator = ',', HelpText = "Fields that are excluded from the action lists.")]
public IEnumerable<string>? FieldsToExclude { get; }

[Option("policy-request", Required = false, HelpText = "Specify the rule to be checked before sending any request to the database.")]
public string? PolicyRequest { get; }
Expand All @@ -120,12 +120,12 @@ public class AddOptions : EntityOptions
{
public AddOptions(
string source,
string permissions,
IEnumerable<string> permissions,
string entity,
string? restRoute,
string? graphQLType,
string? fieldsToInclude,
string? fieldsToExclude,
IEnumerable<string>? fieldsToInclude,
IEnumerable<string>? fieldsToExclude,
string? policyRequest,
string? policyDatabase,
string name)
Expand All @@ -145,8 +145,8 @@ public class AddOptions : EntityOptions
[Option('s', "source", Required = true, HelpText = "Name of the source table or container.")]
public string Source { get; }

[Option("permissions", Required = true, HelpText = "Permissions required to access the source table or container.")]
public string Permissions { get; }
[Option("permissions", Required = true, Separator = ':', HelpText = "Permissions required to access the source table or container.")]
public IEnumerable<string> Permissions { get; }
}

/// <summary>
Expand All @@ -157,20 +157,20 @@ public class UpdateOptions : EntityOptions
{
public UpdateOptions(
string? source,
string? permissions,
IEnumerable<string>? permissions,
string? relationship,
string? cardinality,
string? targetEntity,
string? linkingObject,
string? linkingSourceFields,
string? linkingTargetFields,
string? mappingFields,
IEnumerable<string>? linkingSourceFields,
IEnumerable<string>? linkingTargetFields,
IEnumerable<string>? mappingFields,
IEnumerable<string>? map,
string entity,
string? restRoute,
string? graphQLType,
string? fieldsToInclude,
string? fieldsToExclude,
IEnumerable<string>? fieldsToInclude,
IEnumerable<string>? fieldsToExclude,
string? policyRequest,
string? policyDatabase,
string name)
Expand Down Expand Up @@ -198,8 +198,8 @@ public class UpdateOptions : EntityOptions
[Option('s', "source", Required = false, HelpText = "Name of the source table or container.")]
public string? Source { get; }

[Option("permissions", Required = false, HelpText = "Permissions required to access the source table or container.")]
public string? Permissions { get; }
[Option("permissions", Required = false, Separator = ':', HelpText = "Permissions required to access the source table or container.")]
public IEnumerable<string>? Permissions { get; }

[Option("relationship", Required = false, HelpText = "Specify relationship between two entities.")]
public string? Relationship { get; }
Expand All @@ -213,14 +213,14 @@ public class UpdateOptions : EntityOptions
[Option("linking.object", Required = false, HelpText = "Database object that is used to support an M:N relationship.")]
public string? LinkingObject { get; }

[Option("linking.source.fields", Required = false, HelpText = "Database fields in the linking object to connect to the related item in the source entity.")]
public string? LinkingSourceFields { get; }
[Option("linking.source.fields", Required = false, Separator = ',', HelpText = "Database fields in the linking object to connect to the related item in the source entity.")]
public IEnumerable<string>? LinkingSourceFields { get; }

[Option("linking.target.fields", Required = false, HelpText = "Database fields in the linking object to connect to the related item in the target entity.")]
public string? LinkingTargetFields { get; }
[Option("linking.target.fields", Required = false, Separator = ',', HelpText = "Database fields in the linking object to connect to the related item in the target entity.")]
public IEnumerable<string>? LinkingTargetFields { get; }

[Option("mapping.fields", Required = false, HelpText = "Specify fields to be used for mapping the entities.")]
public string? MappingFields { get; }
[Option("mapping.fields", Required = false, Separator = ':', HelpText = "Specify fields to be used for mapping the entities.")]
public IEnumerable<string>? MappingFields { get; }

[Option('m', "map", Separator = ',', Required = false, HelpText = "Specify mappings between database fields and GraphQL and REST fields. format: --map \"backendName1:exposedName1,backendName2:exposedName2,...\".")]
public IEnumerable<string>? Map { get; }
Expand Down
97 changes: 39 additions & 58 deletions Hawaii-Cli/src/Models/ConfigGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ public static bool TryAddNewEntity(AddOptions options, ref string runtimeConfigJ
PermissionSetting[]? permissionSettings = ParsePermission(options.Permissions, policy, field);
if (permissionSettings is null)
{
Console.Error.WriteLine("Please add permission in the following format. --permission \"<<role>>:<<actions>>\"");
Console.Error.WriteLine("Please add permission in the following format. --permissions \"<<role>>:<<actions>>\"");
return false;
}

Expand Down Expand Up @@ -187,18 +187,18 @@ public static bool TryAddNewEntity(AddOptions options, ref string runtimeConfigJ
/// <summary>
/// Parse permission string to create PermissionSetting array.
/// </summary>
/// <param name="permissions">Permission string input.</param>
/// <param name="fieldsToInclude">fields to include for this permission.</param>
/// <param name="fieldsToExclude">fields to exclude for this permission.</param>
/// <param name="permissions">Permission input string as IEnumerable.</param>
/// <param name="policy">policy to add for this permission.</param>
/// <param name="fields">fields to include and exclude for this permission.</param>
/// <returns></returns>
public static PermissionSetting[]? ParsePermission(string permissions, Policy? policy, Field? fields)
public static PermissionSetting[]? ParsePermission(IEnumerable<string> permissions, Policy? policy, Field? fields)
{
// Getting Role and Actions from permission string
//
string? role, actions;
if (!TryGetRoleAndActionFromPermissionString(permissions, out role, out actions))
if (!TryGetRoleAndActionFromPermission(permissions, out role, out actions))
{
Console.Error.Write($"Failed to fetch the role and action from the given permission string: {permissions}.");
Console.Error.Write($"Failed to fetch the role and action from the given permission string: {string.Join(":", permissions.ToArray())}.");
return null;
}

Expand Down Expand Up @@ -249,19 +249,6 @@ public static bool TryUpdateEntityWithOptions(UpdateOptions options)
/// <returns>True on success. False otherwise.</returns>
public static bool TryUpdateExistingEntity(UpdateOptions options, ref string runtimeConfigJson)
{
string? source = options.Source;
string? rest = options.RestRoute;
string? graphQL = options.GraphQLType;
string? permissions = options.Permissions;
string? fieldsToInclude = options.FieldsToInclude;
string? fieldsToExclude = options.FieldsToExclude;
string? policyRequest = options.PolicyRequest;
string? policyDatabase = options.PolicyDatabase;
string? relationship = options.Relationship;
string? cardinality = options.Cardinality;
string? targetEntity = options.TargetEntity;
IEnumerable<string>? mappings = options.Map;

// Deserialize the json string to RuntimeConfig object.
//
RuntimeConfig? runtimeConfig;
Expand All @@ -282,27 +269,26 @@ public static bool TryUpdateExistingEntity(UpdateOptions options, ref string run
// Check if Entity is present
//
Entity? entity;
bool IsEntityPresent = runtimeConfig.Entities.TryGetValue(options.Entity, out entity);
if (!IsEntityPresent)
if (!runtimeConfig.Entities.TryGetValue(options.Entity, out entity))
{
Console.WriteLine($"Entity:{options.Entity} not found. Please add the entity first.");
return false;
}

object updatedSource = source is null ? entity!.Source : source;
object? updatedRestDetails = rest is null ? entity!.Rest : GetRestDetails(rest);
object? updatedGraphqlDetails = graphQL is null ? entity!.GraphQL : GetGraphQLDetails(graphQL);
object updatedSource = options.Source is null ? entity!.Source : options.Source;
object? updatedRestDetails = options.RestRoute is null ? entity!.Rest : GetRestDetails(options.RestRoute);
object? updatedGraphqlDetails = options.GraphQLType is null ? entity!.GraphQL : GetGraphQLDetails(options.GraphQLType);
PermissionSetting[]? updatedPermissions = entity!.Permissions;
Dictionary<string, Relationship>? updatedRelationships = entity.Relationships;
Dictionary<string, string>? updatedMappings = entity.Mappings;
Policy? updatedPolicy = GetPolicyForAction(policyRequest, policyDatabase);
Field? updatedFields = GetFieldsForAction(fieldsToInclude, fieldsToExclude);
Policy? updatedPolicy = GetPolicyForAction(options.PolicyRequest, options.PolicyDatabase);
Field? updatedFields = GetFieldsForAction(options.FieldsToInclude, options.FieldsToExclude);

if (permissions is not null)
if (options.Permissions is not null && options.Permissions.Any())
{
// Get the Updated Permission Settings
//
updatedPermissions = GetUpdatedPermissionSettings(entity, permissions, updatedPolicy, updatedFields);
updatedPermissions = GetUpdatedPermissionSettings(entity, options.Permissions, updatedPolicy, updatedFields);

if (updatedPermissions is null)
{
Expand All @@ -312,22 +298,24 @@ public static bool TryUpdateExistingEntity(UpdateOptions options, ref string run
}
else
{
if (fieldsToInclude is not null || fieldsToExclude is not null)

if ((options.FieldsToInclude is not null && options.FieldsToInclude.Any())
|| (options.FieldsToExclude is not null && options.FieldsToExclude.Any()))
{
Console.WriteLine($"--permission is mandatory with --fields.include and --fields.exclude.");
Console.WriteLine($"--permissions is mandatory with --fields.include and --fields.exclude.");
return false;
}

if (policyRequest is not null || policyDatabase is not null)
if (options.PolicyRequest is not null || options.PolicyDatabase is not null)
{
Console.WriteLine($"--permission is mandatory with --policy-request and --policy-database.");
Console.WriteLine($"--permissions is mandatory with --policy-request and --policy-database.");
return false;
}
}

if (relationship is not null)
if (options.Relationship is not null)
{
if (!VerifyCanUpdateRelationship(runtimeConfig, cardinality, targetEntity))
if (!VerifyCanUpdateRelationship(runtimeConfig, options.Cardinality, options.TargetEntity))
{
return false;
}
Expand All @@ -343,13 +331,13 @@ public static bool TryUpdateExistingEntity(UpdateOptions options, ref string run
return false;
}

updatedRelationships[relationship] = new_relationship;
updatedRelationships[options.Relationship] = new_relationship;
}

if (mappings is not null)
if (options.Map is not null && options.Map.Any())
{
// Parsing mappings dictionary from Collection
if (!TryParseMappingDictionary(mappings, out updatedMappings))
if (!TryParseMappingDictionary(options.Map, out updatedMappings))
{
return false;
}
Expand All @@ -372,19 +360,19 @@ public static bool TryUpdateExistingEntity(UpdateOptions options, ref string run
/// </summary>
/// <param name="entityToUpdate">entity whose permission needs to be updated</param>
/// <param name="permissions">New permission to be applied.</param>
/// <param name="fieldsToInclude">fields to allow the action permission</param>
/// <param name="fieldsToExclude">fields that will be excluded from the action permission.</param>
/// <param name="policy">policy to added for this permission</param>
/// <param name="fields">fields to be included and excluded from the action permission.</param>
/// <returns> On failure, returns null. Else updated PermissionSettings array will be returned.</returns>
private static PermissionSetting[]? GetUpdatedPermissionSettings(Entity entityToUpdate,
string permissions,
IEnumerable<string> permissions,
Policy? policy,
Field? fields)
{
string? newRole, newActions;

// Parse role and actions from the permissions string
//
if (!TryGetRoleAndActionFromPermissionString(permissions, out newRole, out newActions))
if (!TryGetRoleAndActionFromPermission(permissions, out newRole, out newActions))
{
Console.Error.Write($"Failed to fetch the role and action from the given permission string: {permissions}.");
return null;
Expand Down Expand Up @@ -580,39 +568,32 @@ public static bool VerifyCanUpdateRelationship(RuntimeConfig runtimeConfig, stri
/// <returns>Returns a Relationship Object</returns>
public static Relationship? CreateNewRelationshipWithUpdateOptions(UpdateOptions options)
{
string? cardinality = options.Cardinality;
string? targetEntity = options.TargetEntity;
string? linkingObject = options.LinkingObject;
string? linkingSourceFields = options.LinkingSourceFields;
string? linkingTargetFields = options.LinkingTargetFields;
string? mappingFields = options.MappingFields;
string[]? updatedSourceFields = null;
string[]? updatedTargetFields = null;
string[]? updatedLinkingSourceFields = linkingSourceFields is null ? null : linkingSourceFields.Split(",");
string[]? updatedLinkingTargetFields = linkingTargetFields is null ? null : linkingTargetFields.Split(",");
string[]? updatedLinkingSourceFields = (options.LinkingSourceFields is null || !options.LinkingSourceFields.Any()) ? null : options.LinkingSourceFields.ToArray();
string[]? updatedLinkingTargetFields = (options.LinkingTargetFields is null || !options.LinkingTargetFields.Any()) ? null : options.LinkingTargetFields.ToArray();

Cardinality updatedCardinality = Enum.Parse<Cardinality>(cardinality!, ignoreCase: true);
Cardinality updatedCardinality = Enum.Parse<Cardinality>(options.Cardinality!, ignoreCase: true);

if (mappingFields is not null)
if (options.MappingFields is not null && options.MappingFields.Any())
{
// Getting source and target fields from mapping fields
//
string[] mappingFieldsArray = mappingFields.Split(":");
if (mappingFieldsArray.Length != 2)
if (options.MappingFields.Count() != 2)
{
Console.WriteLine("Please provide the --mapping.fields in the correct format using ':' between source and target fields.");
return null;
}

updatedSourceFields = mappingFieldsArray[0].Split(",");
updatedTargetFields = mappingFieldsArray[1].Split(",");
updatedSourceFields = options.MappingFields.ElementAt(0).Split(",");
updatedTargetFields = options.MappingFields.ElementAt(1).Split(",");
}

return new Relationship(updatedCardinality,
targetEntity!,
options.TargetEntity!,
updatedSourceFields,
updatedTargetFields,
linkingObject,
options.LinkingObject,
updatedLinkingSourceFields,
updatedLinkingTargetFields);
}
Expand Down
Loading

0 comments on commit 05bc379

Please sign in to comment.