Complete the following steps to create a customized authorization for controlling the file access permissions.
In your application, you need to add files that define which role can access the folder, as shown in the image below. Once you have added the _roles file, you can read the roles information in authorization attribute.
To provide access to the folders based on the role assigned to the user, read the roles information in the authorization attribute. The authorization attribute identifies the user login and provides access to the files based on the role assigned to the users.
StorageAuthorizeAttribute.cs |
Copy Code
|
---|---|
using C1.Web.Api.Report; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Web.Http.Controllers; using System.Web.Http.Filters; using C1.Web.Api.Storage; namespace SalesReport.Controllers { internal class StorageAuthorizeAttribute : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { var principal = actionContext.ControllerContext.RequestContext.Principal; if (principal == null || principal.Identity == null || !principal.Identity.IsAuthenticated) { Unauthorize(actionContext); return; } var values = actionContext.RequestContext.RouteData.Values; object pathObj; if (!values.TryGetValue("path", out pathObj)) { return; } var path = (pathObj as string) ?? string.Empty; var defaultProvider = ReportProviderManager.Current.Get("") as FlexReportProvider; if (defaultProvider == null) { return; } var roles = GetRoles(defaultProvider.Storage, path); if(!roles.Any()) { return; } if (!roles.Any(r => principal.IsInRole(r))) { Unauthorize(actionContext); } } private static readonly object _locker = new object(); private static readonly IDictionary<string, IEnumerable<string>> _folderRoles = new Dictionary<string, IEnumerable<string>>(StringComparer.OrdinalIgnoreCase); private static IEnumerable<string> GetRoles(IStorageProvider storage, string path) { string folder = path; var fileStorage = storage.GetFileStorage(path); if (fileStorage.Exists) { var pathParts = path.Split('/'); pathParts = pathParts.Take(pathParts.Length - 1).ToArray(); folder = string.Join("/", pathParts); } lock (_locker) { IEnumerable<string> roles; if (_folderRoles.TryGetValue(folder, out roles)) { return roles; } var roleList = GetFolderRoles("", storage); var folderParts = folder.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); var currentFolder = ""; foreach (var part in folderParts) { currentFolder += part; var current = GetFolderRoles(currentFolder, storage); if(current != null && current.Any()) { roleList = current; } currentFolder += "/"; } return roleList; } } private static IEnumerable<string> GetFolderRoles(string path, IStorageProvider storage) { IEnumerable<string> roles; if (_folderRoles.TryGetValue(path, out roles)) { return roles; } var roleList = new List<string>(); var rolesFile = storage.GetFileStorage(path + "/_.roles"); if(rolesFile.Exists) { using (var reader = new StreamReader(rolesFile.Read())) { while (!reader.EndOfStream) { var line = reader.ReadLine(); if (!string.IsNullOrEmpty(line)) { roleList.Add(line); } } } } _folderRoles.Add(path, roleList); return roleList; } private static void Unauthorize(HttpActionContext actionContext) { actionContext.Response = new System.Net.Http.HttpResponseMessage(HttpStatusCode.Unauthorized); } } } |
ReportController
).ReportController.cs |
Copy Code
|
---|---|
using System.Web.Http; namespace SalesReport.Controllers { public class ReportController : C1.Web.Api.Report.ReportController { [StorageAuthorize] public override IHttpActionResult GetCatalogInfo(string path, bool recursive = false) { return base.GetCatalogInfo(path, recursive); } } } |
CustomDirectRouteProvider.cs |
Copy Code
|
---|---|
using System.Collections.Generic; using System.Linq; using System.Web.Http.Controllers; using System.Web.Http.Routing; namespace SalesReport { public class CustomDirectRouteProvider : DefaultDirectRouteProvider { protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor) { // inherit route attributes decorated on base class controller's actions return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(true); } protected override string GetRoutePrefix(HttpControllerDescriptor controllerDescriptor) { var prefix = base.GetRoutePrefix(controllerDescriptor); if (string.IsNullOrEmpty(prefix)) { var prefixAttr = controllerDescriptor.GetCustomAttributes<IRoutePrefix>(true).FirstOrDefault(); if (prefixAttr != null) { return prefixAttr.Prefix; } } return prefix; } } } |
There are two ReportControllers in this application. This code adds a customized IHttpControllerTypeResolver which helps the client application to identify the required ReportController at the time of execution.
ReportsControllerTypeResolver.cs |
Copy Code
|
---|---|
using System; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; namespace SalesReport { internal class ReportsControllerTypeResolver : DefaultHttpControllerTypeResolver { public ReportsControllerTypeResolver() : base(IsControllerType) { } private static bool IsControllerType(Type t) { if (t != null && t.IsClass && (t.IsVisible && !t.IsAbstract) && typeof(IHttpController).IsAssignableFrom(t)) return HasValidControllerName(t) && t != typeof(C1.Web.Api.Report.ReportController); return false; } private static bool HasValidControllerName(Type controllerType) { string str = DefaultHttpControllerSelector.ControllerSuffix; if (controllerType.Name.Length > str.Length) return controllerType.Name.EndsWith(str, StringComparison.OrdinalIgnoreCase); return false; } } } |
Register the HttpConfiguration in WebApiConfig.cs file. Also, configure the Web API to use only bearer token authentication.
WebApiConfig.cs |
Copy Code
|
---|---|
using System.Web.Http; using Microsoft.Owin.Security.OAuth; using System.Web.Http.Dispatcher; namespace SalesReport { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Configure Web API to use only bearer token authentication. config.SuppressDefaultHostAuthentication(); config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // Web API routes config.MapHttpAttributeRoutes(new CustomDirectRouteProvider()); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Services.Replace(typeof(IHttpControllerTypeResolver), new ReportsControllerTypeResolver()); } } |