public static void MergeReadRest(ReadRestrictionsType existing, ReadRestrictionsType newRead, string target) { if (existing.ReadByKeyRestrictions != null && newRead.ReadByKeyRestrictions != null) { throw new Exception($"Found mutltiple read by key restrctions for one target '{target}'."); } if (existing.ReadByKeyRestrictions == null && newRead.ReadByKeyRestrictions == null) { throw new Exception($"Found mutltiple read restrctions for one target '{target}'."); } if (existing.ReadByKeyRestrictions != null) { existing.Readable = newRead.Readable; if (newRead.Permissions != null) { foreach (var item in newRead.Permissions) { existing.Append(item); } } } else // newRead.ReadByKeyRestrictions != null { existing.ReadByKeyRestrictions = newRead.ReadByKeyRestrictions; } }
/// <inheritdoc/> protected override void SetSecurity(OpenApiOperation operation) { ReadRestrictionsType read = EntitySet != null ? Context.Model.GetRecord <ReadRestrictionsType>(EntitySet, CapabilitiesConstants.ReadRestrictions) : Context.Model.GetRecord <ReadRestrictionsType>(Singleton, CapabilitiesConstants.ReadRestrictions); if (read == null) { return; } ReadRestrictionsBase readBase = read; if (read.ReadByKeyRestrictions != null) { readBase = read.ReadByKeyRestrictions; } if (readBase == null && readBase.Permissions == null) { return; } operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList(); }
/// <inheritdoc/> protected override void SetOperations(OpenApiPathItem item) { if (EdmOperationImport.IsActionImport()) { // Each action import is represented as a name/value pair whose name is the service-relative // resource path of the action import prepended with a forward slash, and whose value is a Path // Item Object containing the keyword post with an Operation Object as value that describes // how to invoke the action import. AddOperation(item, OperationType.Post); } else { // Each function import is represented as a name/value pair whose name is the service-relative // resource path of the function import prepended with a forward slash, and whose value is a Path // Item Object containing the keyword get with an Operation Object as value that describes // how to invoke the function import. // so far, <Term Name="ReadRestrictions" Type="Capabilities.ReadRestrictionsType" AppliesTo="EntitySet Singleton FunctionImport"> ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(EdmOperationImport, CapabilitiesConstants.ReadRestrictions); if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } } }
public void InitializReadRestrictionsTypeWithRecordSuccess() { // Assert IEdmRecordExpression record = new EdmRecordExpression( new EdmPropertyConstructor("Readable", new EdmBooleanConstant(false)), new EdmPropertyConstructor("CustomQueryOptions", new EdmCollectionExpression( new EdmRecordExpression(new EdmPropertyConstructor("Name", new EdmStringConstant("root query name"))))), // Root Permission // Root CustomHeaders new EdmPropertyConstructor("ReadByKeyRestrictions", new EdmRecordExpression( new EdmPropertyConstructor("Readable", new EdmBooleanConstant(true)), new EdmPropertyConstructor("CustomHeaders", new EdmCollectionExpression( new EdmRecordExpression(new EdmPropertyConstructor("Name", new EdmStringConstant("by key head name"))))) // ByKey Permission // ByKey CustomQueryOptions )) ); // Act ReadRestrictionsType read = new ReadRestrictionsType(); read.Initialize(record); // Assert VerifyReadRestrictions(read); }
private static void VerifyReadRestrictions(ReadRestrictionsType read) { Assert.NotNull(read); Assert.NotNull(read.Readable); Assert.False(read.Readable.Value); Assert.Null(read.Permissions); Assert.Null(read.CustomHeaders); Assert.NotNull(read.CustomQueryOptions); CustomParameter parameter = Assert.Single(read.CustomQueryOptions); Assert.Equal("root query name", parameter.Name); Assert.Null(parameter.DocumentationURL); Assert.Null(parameter.ExampleValues); // ReadByKeyRestrictions Assert.NotNull(read.ReadByKeyRestrictions); Assert.NotNull(read.ReadByKeyRestrictions.Readable); Assert.True(read.ReadByKeyRestrictions.Readable.Value); Assert.Null(read.ReadByKeyRestrictions.Permissions); Assert.Null(read.ReadByKeyRestrictions.CustomQueryOptions); Assert.NotNull(read.ReadByKeyRestrictions.CustomHeaders); parameter = Assert.Single(read.ReadByKeyRestrictions.CustomHeaders); Assert.Equal("by key head name", parameter.Name); Assert.Null(parameter.DocumentationURL); Assert.Null(parameter.ExampleValues); }
/// <inheritdoc/> protected override void SetOperations(OpenApiPathItem item) { ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(EntitySet); if (read == null || (read.ReadByKeyRestrictions == null && read.IsReadable) || (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.IsReadable)) { // If we don't have Read by key read restriction, we should check the set read restrction. AddOperation(item, OperationType.Get); } UpdateRestrictionsType update = Context.Model.GetRecord <UpdateRestrictionsType>(EntitySet); if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Patch); } DeleteRestrictionsType delete = Context.Model.GetRecord <DeleteRestrictionsType>(EntitySet); if (delete == null || delete.IsDeletable) { AddOperation(item, OperationType.Delete); } }
protected override void AppendCustomParameters(OpenApiOperation operation) { ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(EntitySet, CapabilitiesConstants.ReadRestrictions); if (read == null) { return; } ReadRestrictionsBase readBase = read; if (read.ReadByKeyRestrictions != null) { readBase = read.ReadByKeyRestrictions; } if (readBase.CustomHeaders != null) { AppendCustomParameters(operation, readBase.CustomHeaders, ParameterLocation.Header); } if (readBase.CustomQueryOptions != null) { AppendCustomParameters(operation, readBase.CustomQueryOptions, ParameterLocation.Query); } }
private void AddReadOperation(OpenApiPathItem item, NavigationPropertyRestriction restriction) { ReadRestrictionsType read = restriction?.ReadRestrictions; if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } }
public void Add(IDictionary <UriPath, IList <ApiPermissionType> > permissions) { IDictionary <string, IList <IRecord> > targetStringMerged = new Dictionary <string, IList <IRecord> >(); foreach (var permission in permissions) { UriPath path = permission.Key; PathKind kind = path.Kind; string target = path.GetTargetString(); IList <IRecord> records; if (!targetStringMerged.TryGetValue(target, out records)) { records = new List <IRecord>(); targetStringMerged[target] = records; } foreach (var perm in permission.Value) { PermissionsRecord permissionRecord; try { permissionRecord = ApiPermissionHelper.ConvertToRecord(kind, perm); ReadRestrictionsType readRest = permissionRecord as ReadRestrictionsType; if (readRest != null) { var existingReadRest = records.FirstOrDefault(r => r is ReadRestrictionsType); if (existingReadRest != null) { MergeReadRest(existingReadRest as ReadRestrictionsType, readRest, target); continue; } } // TODO: verify only one Restriction existing for one target? records.Add(permissionRecord as IRecord); } catch (Exception ex) { //var color = Console.BackgroundColor; //Console.BackgroundColor = ConsoleColor.Red; Console.WriteLine(" [PermssionError]: " + ex.Message); //Console.BackgroundColor = color; PermissionsError[target] = ex; } } } foreach (var item in targetStringMerged) { Write(item.Key, item.Value); } }
/// <inheritdoc/> protected override void SetSecurity(OpenApiOperation operation) { ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(Singleton, CapabilitiesConstants.ReadRestrictions); if (read == null || read.Permissions == null) { return; } operation.Security = Context.CreateSecurityRequirements(read.Permissions).ToList(); }
private void AddGetOperation(OpenApiPathItem item, NavigationPropertyRestriction restriction) { ReadRestrictionsType read = restriction?.ReadRestrictions; if (read == null) { AddOperation(item, OperationType.Get); return; } if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { // TODO: $ref also supports Get ? if (LastSegmentIsKeySegment) { if (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.Readable != null) { if (read.ReadByKeyRestrictions.Readable.Value) { AddOperation(item, OperationType.Get); } } else { ReadRestrictionsType readEntity = Context.Model.GetRecord <ReadRestrictionsType>(_entityType); if (readEntity?.IsReadable ?? true) { AddOperation(item, OperationType.Get); } } } else { if (read.IsReadable) { AddOperation(item, OperationType.Get); } } } else { Debug.Assert(LastSegmentIsKeySegment == false); if (read.IsReadable) { AddOperation(item, OperationType.Get); } } }
/// <inheritdoc/> protected override void SetOperations(OpenApiPathItem item) { ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(EntitySet); if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } InsertRestrictionsType insert = Context.Model.GetRecord <InsertRestrictionsType>(EntitySet); if (insert == null || insert.IsInsertable) { AddOperation(item, OperationType.Post); } }
private void AddGetOperation(OpenApiPathItem item, NavigationPropertyRestriction restriction) { ReadRestrictionsType read = restriction?.ReadRestrictions; if (read == null) { AddOperation(item, OperationType.Get); return; } if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { if (LastSegmentIsKeySegment) { if (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.Readable != null) { if (read.ReadByKeyRestrictions.Readable.Value) { AddOperation(item, OperationType.Get); } } else { if (read.IsReadable) { AddOperation(item, OperationType.Get); } } } else { if (read.IsReadable) { AddOperation(item, OperationType.Get); } } } else { Debug.Assert(LastSegmentIsKeySegment == false); if (read.IsReadable) { AddOperation(item, OperationType.Get); } } }
/// <inheritdoc/> protected override void SetOperations(OpenApiPathItem item) { // Retrieve a singleton. ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(Singleton); if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } // Update a singleton UpdateRestrictionsType update = Context.Model.GetRecord <UpdateRestrictionsType>(Singleton); if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Patch); } }
public static PermissionsRecord ConvertToRecord(PathKind pathKind, ApiPermissionType perm) { PermissionsRecord record = null; switch (perm.HttpVerb) { case "GET": record = CreateGetPermissionRecord(pathKind); break; case "PATCH": record = CreatePatchPermissionRecord(pathKind); break; case "POST": record = CreatePostPermissionRecord(pathKind); break; case "DELETE": record = CreateDeletePermissionRecord(pathKind); break; default: throw new Exception($"Unknown http verb {perm.HttpVerb}"); } if (record == null) { throw new Exception($"Invalid HttpVerb {perm.HttpVerb} in {pathKind} path"); } ReadRestrictionsType read = record as ReadRestrictionsType; if (read != null && read.ReadByKeyRestrictions != null) { read.ReadByKeyRestrictions.InitializeFrom(perm); return(read); } record.InitializeFrom(perm); return(record); }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary string placeholderValue = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "media content"; operation.Summary = IsNavigationPropertyPath ? $"Get {placeholderValue} for the navigation property {NavigationProperty.Name} from {NavigationSource.Name}" : $"Get {placeholderValue} for {NavigationSourceSegment.EntityType.Name} from {NavigationSourceSegment.Identifier}"; // Description if (LastSegmentIsStreamPropertySegment) { IEdmVocabularyAnnotatable annotatable = GetAnnotatableElement(); string description; if (annotatable is IEdmNavigationProperty) { ReadRestrictionsType readRestriction = Context.Model.GetRecord <NavigationRestrictionsType>(annotatable, CapabilitiesConstants.NavigationRestrictions)? .RestrictedProperties?.FirstOrDefault()?.ReadRestrictions; description = LastSegmentIsKeySegment ? readRestriction?.ReadByKeyRestrictions?.Description : readRestriction?.Description ?? Context.Model.GetDescriptionAnnotation(annotatable); } else { // Structural property description = Context.Model.GetDescriptionAnnotation(annotatable); } operation.Description = description; } // OperationId if (Context.Settings.EnableOperationId) { string identifier = LastSegmentIsStreamPropertySegment ? Path.LastSegment.Identifier : "Content"; operation.OperationId = GetOperationId("Get", identifier); } }
public void TargetOnEntitySetReturnsCorrectReadRestrictionsValue(EdmVocabularyAnnotationSerializationLocation location) { // Arrange const string template = @" <Annotations Target=""NS.Default/Calendars""> {0} </Annotations>"; IEdmModel model = GetEdmModel(template, location); Assert.NotNull(model); // guard IEdmEntitySet calendars = model.EntityContainer.FindEntitySet("Calendars"); Assert.NotNull(calendars); // guard // Act ReadRestrictionsType read = model.GetRecord <ReadRestrictionsType>(calendars); // Assert VerifyReadRestrictions(read); }
/// <inheritdoc/> protected override void SetOperations(OpenApiPathItem item) { ReadRestrictionsType read = EntitySet != null ? Context.Model.GetRecord <ReadRestrictionsType>(EntitySet) : Context.Model.GetRecord <ReadRestrictionsType>(Singleton); if (read == null || (read.ReadByKeyRestrictions == null && read.IsReadable) || (read.ReadByKeyRestrictions != null && read.ReadByKeyRestrictions.IsReadable)) { AddOperation(item, OperationType.Get); } UpdateRestrictionsType update = EntitySet != null ? Context.Model.GetRecord <UpdateRestrictionsType>(EntitySet) : Context.Model.GetRecord <UpdateRestrictionsType>(Singleton); if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Put); } }
/// <inheritdoc/> protected override void SetBasicInfo(OpenApiOperation operation) { // Summary and Description ReadRestrictionsType readRestriction = Restriction?.ReadRestrictions; string placeHolder = "Get ref of " + NavigationProperty.Name + " from " + NavigationSource.Name; operation.Summary = (LastSegmentIsKeySegment ? readRestriction?.ReadByKeyRestrictions?.Description : readRestriction?.Description) ?? placeHolder; operation.Description = (LastSegmentIsKeySegment ? readRestriction?.ReadByKeyRestrictions?.LongDescription : readRestriction?.LongDescription) ?? Context.Model.GetDescriptionAnnotation(NavigationProperty); // OperationId if (Context.Settings.EnableOperationId) { string prefix = "GetRef"; if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { prefix = "ListRef"; } operation.OperationId = GetOperationId(prefix); } }
/// <inheritdoc/> protected override void SetSecurity(OpenApiOperation operation) { IEdmVocabularyAnnotatable annotatableNavigationSource = (IEdmVocabularyAnnotatable)NavigationSourceSegment.NavigationSource; ReadRestrictionsType read = Context.Model.GetRecord <ReadRestrictionsType>(annotatableNavigationSource, CapabilitiesConstants.ReadRestrictions); if (read == null) { return; } ReadRestrictionsBase readBase = read; if (read.ReadByKeyRestrictions != null) { readBase = read.ReadByKeyRestrictions; } if (readBase == null && readBase.Permissions == null) { return; } operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList(); }
private static ITerm CreateDefaultTerm() { ReadRestrictions term = new ReadRestrictions(); term.Target = "Ns.Container/Users"; term.IsInLine = true; ReadRestrictionsType record = new ReadRestrictionsType(); record.ReadByKeyRestrictions = new ReadByKeyRestrictions(); PermissionType permission = new PermissionType { SchemeName = "Delegated (work or school account)", Scopes = new List <ScopeType> { new ScopeType { Scope = "User.ReadBasic.All" }, new ScopeType { Scope = "User.Read.All" }, new ScopeType { Scope = "User.ReadWrite.All" }, new ScopeType { Scope = "Directory.Read.All" }, new ScopeType { Scope = "Directory.ReadWrite.All" }, new ScopeType { Scope = "Directory.AccessAsUser.All" } } }; record.ReadByKeyRestrictions.Append(permission); permission = new PermissionType { SchemeName = "Application", Scopes = new List <ScopeType> { new ScopeType { Scope = "User.Read.All" }, new ScopeType { Scope = "User.ReadWrite.All" }, new ScopeType { Scope = "Directory.Read.All" }, new ScopeType { Scope = "Directory.ReadWrite.All" }, } }; record.ReadByKeyRestrictions.Append(permission); term.Records.Add(record); return(term); }
/// <inheritdoc/> protected override void SetOperations(OpenApiPathItem item) { IEdmEntitySet entitySet = NavigationSource as IEdmEntitySet; IEdmVocabularyAnnotatable target = entitySet; if (target == null) { target = NavigationSource as IEdmSingleton; } string navigationPropertyPath = String.Join("/", Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment)).Select(e => e.Identifier)); NavigationRestrictionsType navigation = Context.Model.GetRecord <NavigationRestrictionsType>(target, CapabilitiesConstants.NavigationRestrictions); NavigationPropertyRestriction restriction = navigation?.RestrictedProperties?.FirstOrDefault(r => r.NavigationProperty == navigationPropertyPath); // verify using individual first if (restriction != null && restriction.Navigability != null && restriction.Navigability.Value == NavigationType.None) { return; } if (restriction == null || restriction.Navigability == null) { // if the individual has not navigability setting, use the global navigability setting if (navigation != null && navigation.Navigability != null && navigation.Navigability.Value == NavigationType.None) { // Default navigability for all navigation properties of the annotation target. // Individual navigation properties can override this value via `RestrictedProperties/Navigability`. return; } } // So far, we only consider the non-containment Debug.Assert(!NavigationProperty.ContainsTarget); // It seems OData supports to "GetRef, DeleteRef", // Here at this time,let's only consider the "delete" ReadRestrictionsType read = restriction?.ReadRestrictions; if (read == null || read.IsReadable) { AddOperation(item, OperationType.Get); } // Create the ref if (NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many) { InsertRestrictionsType insert = restriction?.InsertRestrictions; if (insert == null || insert.IsInsertable) { AddOperation(item, OperationType.Post); } } else { UpdateRestrictionsType update = restriction?.UpdateRestrictions; if (update == null || update.IsUpdatable) { AddOperation(item, OperationType.Put); } // delete the link DeleteRestrictionsType delete = restriction?.DeleteRestrictions; if (delete == null || delete.IsDeletable) { AddOperation(item, OperationType.Delete); } } }
protected override void Initialize(ODataContext context, ODataPath path) { base.Initialize(context, path); _readRestrictions = Context.Model.GetRecord <ReadRestrictionsType>(EntitySet, CapabilitiesConstants.ReadRestrictions); }