Permissions & Authorization for Users #24

Initial Release; Includes Database and MVC refactoring
This commit is contained in:
Gary Sharp
2013-10-10 19:13:16 +11:00
parent 172ce5524a
commit a099d68915
458 changed files with 40221 additions and 12130 deletions
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization
{
public class AccessDeniedException : Exception
{
private string _message { get; set; }
public AccessDeniedException(string Message)
{
this._message = Message;
}
public override string Message
{
get
{
if (this._message == null)
{
return "Your account does not have the required permission to access this Disco feature.";
}
else
{
return this._message;
}
}
}
}
}
@@ -0,0 +1,161 @@
using Disco.Models.Authorization;
using Disco.Models.Repository;
using Disco.Services.Authorization.Roles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization
{
public class AuthorizationToken : IAuthorizationToken
{
public User User { get; set; }
public List<string> GroupMembership { get; set; }
public List<IRoleToken> RoleTokens { get; set; }
#region Token Builders
public static AuthorizationToken BuildToken(User User, List<string> GroupMembership)
{
return new AuthorizationToken()
{
User = User,
GroupMembership = GroupMembership,
RoleTokens = RoleCache.GetRoleTokens(GroupMembership, User)
};
}
public static AuthorizationToken BuildComputerAccountToken(User User)
{
return new AuthorizationToken()
{
User = User,
GroupMembership = new List<string>(),
RoleTokens = new List<IRoleToken>()
{
(IRoleToken)RoleCache.GetRoleToken(RoleCache.ComputerAccountTokenId)
}
};
}
#endregion
#region Token Accessors
internal const string RequireAuthenticationMessage = "This Disco feature requires authentication.";
internal const string RequireDiscoAuthorizationMessage = "Your account does not have the required permission to access this Disco feature. This feature requires your account to be included in at least one Disco Authorization Role.";
internal const string RequireMessageTemplate = "Your account does not have the required permission ({0}) to access this Disco feature.";
internal const string RequireAllMessageTemplate = "Your account does not have the required permission to access this Disco feature. This feature requires permission for: {0}.";
internal const string RequireAnyMessageTemplate = "Your account does not have the required permission to access this Disco feature. This feature requires at least one of these permissions: {0}.";
internal static string BuildRequireMessage(string ClaimKey)
{
return string.Format(RequireMessageTemplate, Claims.GetClaimDetails(ClaimKey).Item1);
}
internal static string BuildRequireAllMessage(IEnumerable<string> ClaimKeys)
{
var claimFriendlyNames = ClaimKeys.Select(ck => Claims.GetClaimDetails(ck).Item1);
return string.Format(RequireAllMessageTemplate, string.Join("; ", claimFriendlyNames));
}
internal static string BuildRequireAnyMessage(IEnumerable<string> ClaimKeys)
{
var claimFriendlyNames = ClaimKeys.Select(ck => Claims.GetClaimDetails(ck).Item1);
return string.Format(RequireAnyMessageTemplate, string.Join("; ", claimFriendlyNames));
}
/// <summary>
/// Checks if token contains at least one of the claims requested.
/// </summary>
/// <param name="ClaimKeys">Claim Keys from <see cref="Disco.Services.Authorization.Claims"/></param>
/// <returns>true if the token satisfies the claim request, otherwise false.</returns>
public bool HasAny(params string[] ClaimKeys)
{
return HasAny((IEnumerable<string>)ClaimKeys);
}
/// <summary>
/// Checks if token contains at least one of the claims requested.
/// </summary>
/// <param name="ClaimKeys">Claim Keys from <see cref="Disco.Services.Authorization.Claims"/></param>
/// <returns>true if the token satisfies the claim request, otherwise false.</returns>
public bool HasAny(IEnumerable<string> ClaimKeys)
{
return ClaimKeys.Any(ck => Has(Claims.GetClaimAccessor(ck)));
}
/// <summary>
/// Checks if token contains all the claims requested.
/// </summary>
/// <param name="ClaimKeys">Claim Keys from <see cref="Disco.Services.Authorization.Claims"/></param>
/// <returns>true if the token satisfies the claim request, otherwise false.</returns>
public bool HasAll(params string[] ClaimKeys)
{
return HasAll((IEnumerable<string>)ClaimKeys);
}
/// <summary>
/// Checks if token contains all the claims requested.
/// </summary>
/// <param name="ClaimKeys">Claim Keys from <see cref="Disco.Services.Authorization.Claims"/></param>
/// <returns>true if the token satisfies the claim request, otherwise false.</returns>
public bool HasAll(IEnumerable<string> ClaimKeys)
{
return ClaimKeys.All(ck => Has(Claims.GetClaimAccessor(ck)));
}
/// <summary>
/// Checks if token contains the claim requested.
/// </summary>
/// <param name="ClaimKey">Claim Key from <see cref="Disco.Services.Authorization.Claims"/></param>
/// <returns>true if the token satisfies the claim request, otherwise false.</returns>
public bool Has(string ClaimKey)
{
Func<RoleClaims, bool> claimAccessor = Claims.GetClaimAccessor(ClaimKey);
return Has(claimAccessor);
}
/// <summary>
/// Checks if token contains the claim requested.
/// </summary>
/// <param name="ClaimAccessor">A lambda which validates the tokens <see cref="RoleClaims"/></param>
/// <returns>true if the token satisfies the claim request, otherwise false.</returns>
public bool Has(Func<RoleClaims, bool> ClaimAccessor)
{
return RoleTokens.Any(rt => ClaimAccessor.Invoke(((RoleToken)rt).Claims));
}
/// <summary>
/// Validates the token contains the claim required. An <see cref="Disco.Services.Authorization.AccessDeniedException"/> is thrown if the requirements are not met.
/// </summary>
/// <param name="ClaimKey">Claim Key from <see cref="Disco.Services.Authorization.Claims"/></param>
public void Require(string ClaimKey)
{
if (!Has(ClaimKey))
throw new AccessDeniedException(BuildRequireMessage(ClaimKey));
}
/// <summary>
/// Validates the token contains all the claims required. An <see cref="Disco.Services.Authorization.AccessDeniedException"/> is thrown if the requirements are not met.
/// </summary>
/// <param name="ClaimKeys">Claim Keys from <see cref="Disco.Services.Authorization.Claims"/></param>
public void RequireAll(params string[] ClaimKeys)
{
if (!HasAll(ClaimKeys))
throw new AccessDeniedException(BuildRequireAllMessage(ClaimKeys));
}
/// <summary>
/// Validates the token contains at least one of the claims required. An <see cref="Disco.Services.Authorization.AccessDeniedException"/> is thrown if the requirements are not met.
/// </summary>
/// <param name="ClaimKeys">Claim Keys from <see cref="Disco.Services.Authorization.Claims"/></param>
public void RequireAny(params string[] ClaimKeys)
{
if (!HasAny(ClaimKeys))
throw new AccessDeniedException(BuildRequireAnyMessage(ClaimKeys));
}
#endregion
}
}
@@ -0,0 +1,84 @@
using Disco.Models.Authorization;
using Disco.Services.Authorization.Roles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization
{
public class ClaimNavigatorItem : IClaimNavigatorItem
{
private Func<Roles.RoleClaims, bool> accessor { get; set; }
public string Key { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public bool Hidden { get; private set; }
public List<IClaimNavigatorItem> Children { get; private set; }
public bool IsGroup { get { return Children != null; } }
public bool? Value { get; private set; }
internal ClaimNavigatorItem(string Key, bool Hidden)
{
this.Key = Key;
var details = Claims.GetClaimDetails(Key);
this.Name = details.Item1;
this.Description = details.Item2;
this.accessor = Claims.GetClaimAccessor(Key);
this.Hidden = Hidden;
}
internal ClaimNavigatorItem(string Key, string Name, string Description, bool Hidden, List<IClaimNavigatorItem> Children)
{
this.Key = Key;
this.Name = Name;
this.Description = Description;
this.Hidden = Hidden;
this.Children = Children;
}
private ClaimNavigatorItem()
{
// Private Constructor
}
public IClaimNavigatorItem BuildClaimTree(RoleClaims RoleClaims)
{
return new ClaimNavigatorItem()
{
Key = this.Key,
Name = this.Name,
Description = this.Description,
Hidden = this.Hidden,
accessor = this.accessor,
Value = this.accessor == null ? (bool?)null : this.accessor(RoleClaims),
Children = this.Children == null ? null : this.Children.Cast<ClaimNavigatorItem>().Select(c => c.BuildClaimTree(RoleClaims)).ToList()
};
}
public IClaimNavigatorItem BuildClaimTree(IEnumerable<RoleClaims> RoleClaims)
{
return new ClaimNavigatorItem()
{
Key = this.Key,
Name = this.Name,
Description = this.Description,
Hidden = this.Hidden,
accessor = this.accessor,
Value = this.accessor == null ? (bool?)null : RoleClaims.Any(rc => this.accessor(rc)),
Children = this.Children == null ? null : this.Children.Cast<ClaimNavigatorItem>().Select(c => c.BuildClaimTree(RoleClaims)).ToList()
};
}
public override string ToString()
{
return string.Format("{0}: {1}={2}", this.Name, this.Key, this.Value);
}
}
}
File diff suppressed because it is too large Load Diff
+392
View File
@@ -0,0 +1,392 @@
<#@ template language="C#" debug="true" hostspecific="true" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="EnvDTE80" #>
<#@ assembly name="VSLangProj" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ assembly name="C:\Windows\Microsoft.NET\Framework\v4.0.30319\CustomMarshalers.dll" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="EnvDTE80" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#@ import namespace="System.Runtime.InteropServices.CustomMarshalers" #>
<#@ import namespace="System.Runtime.InteropServices" #>
<#@ import namespace="System.Reflection" #>
<#
// Get the DTE service from the host
EnvDTE.DTE Dte = null;
var serviceProvider = Host as IServiceProvider;
if (serviceProvider != null)
Dte = (EnvDTE.DTE)serviceProvider.GetService(typeof(EnvDTE.DTE));
// Fail if we couldn't get the DTE. This can happen when trying to run in TextTransform.exe
if (Dte == null)
throw new Exception("T4MVC can only execute through the Visual Studio host");
List<Permission> permissions = new List<Permission>();
List<Permission> groups = new List<Permission>();
var piRolePermission = Dte.Solution.FindProjectItem(Host.ResolvePath(@"Roles\RoleClaims.cs"));
var piGroups = FindClaimGroupProjectItems(piRolePermission.ContainingProject.ProjectItems.Item("Authorization").ProjectItems.Item("Roles").ProjectItems.Item("ClaimGroups")).ToList();
ParseProjectItem(piRolePermission, groups, permissions);
foreach (ProjectItem piItem in piGroups)
ParseProjectItem(piItem, groups, permissions);
var permissionRoot = BuildHierarchy(groups, permissions);
#>
// <auto-generated />
// This file was generated by a T4 template.
// Don't change it directly as your change would get overwritten. Instead, make changes
// to the .tt file (i.e. the T4 template) and save it to regenerate this file.
using Disco.Models.Authorization;
using Disco.Models.Repository;
using Disco.Services.Authorization.Roles;
using System;
using System.Collections.Generic;
namespace Disco.Services.Authorization
{
public static class Claims
{
private static Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string>> _roleClaims;
private static ClaimNavigatorItem _claimNavigator;
static Claims()
{
#region Role Claim Dictionary
_roleClaims = new Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string>>()
{
<#WriteAccessHashes(permissionRoot);#>
};
#endregion
#region Role Claim Navigator
_claimNavigator =
<#WriteNavigator(permissionRoot);#>;
#endregion
}
public static ClaimNavigatorItem RoleClaimNavigator
{
get { return _claimNavigator; }
}
public static Func<RoleClaims, bool> GetClaimAccessor(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string> claimFunc;
if (!_roleClaims.TryGetValue(ClaimKey, out claimFunc))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return claimFunc.Item1;
}
public static Action<RoleClaims, bool> GetClaimSetter(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string> claimFunc;
if (!_roleClaims.TryGetValue(ClaimKey, out claimFunc))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return claimFunc.Item2;
}
public static Tuple<string, string> GetClaimDetails(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string> claimFunc;
if (!_roleClaims.TryGetValue(ClaimKey, out claimFunc))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return new Tuple<string, string>(claimFunc.Item3, claimFunc.Item4);
}
public static RoleClaims BuildClaims(IEnumerable<string> ClaimKeys){
var c = new RoleClaims();
foreach (var claimKey in ClaimKeys)
c.Set(claimKey, true);
return c;
}
public static RoleClaims AdministratorClaims() {
var c = new RoleClaims();
#region Set All Administrator Claims
<#WriteAdministratorClaims(permissionRoot);#>
#endregion
return c;
}
public static RoleClaims ComputerAccountClaims() {
return new RoleClaims() {
ComputerAccount = true
};
}
#region Role Claim Constants
<#WritePermissionConsts(permissionRoot);#>
#endregion
}
public static class ClaimExtensions
{
public static bool Has(this RoleClaims c, string ClaimKey)
{
Func<RoleClaims, bool> claimFunc = Claims.GetClaimAccessor(ClaimKey);
return claimFunc(c);
}
public static void Set(this RoleClaims c, string ClaimKey, bool Value)
{
Action<RoleClaims, bool> claimSetter = Claims.GetClaimSetter(ClaimKey);
claimSetter(c, Value);
}
public static void SetClaims(this AuthorizationRole role, RoleClaims Claims)
{
role.ClaimsJson = Newtonsoft.Json.JsonConvert.SerializeObject(Claims);
}
}
}
<#+
void DumpPermission(Permission p){
PushIndent(" ");
WriteLine(p.Name);
foreach (Permission pChild in p.Children)
{
DumpPermission(pChild);
}
PopIndent();
}
void WriteNavigator(Permission root){
PushIndent(" ");
WriteLine("new ClaimNavigatorItem(\"Claims\", \"Permissions\", \"Top-level node for all permissions\", false, new List<IClaimNavigatorItem>() {");
PushIndent(" ");
for (int childIndex = 0; childIndex < root.Children.Count; childIndex++)
{
WriteNavigator_Recurse(root.Children[childIndex], string.Empty);
if (childIndex < root.Children.Count -1)
WriteLine(",");
}
WriteLine(string.Empty);
PopIndent();
Write("})");
PopIndent();
}
void WriteNavigator_Recurse(Permission p, string Prefix){
var key = string.Concat(Prefix, p.Name);
if (p.IsGroup){
var groupPrefix = string.Concat(key, ".");
WriteLine("new ClaimNavigatorItem(\"{0}{1}\", \"{2}\", \"{3}\", {4}, new List<IClaimNavigatorItem>() {{", Prefix, p.Name, p.FriendlyName, p.Description, p.Hidden ? "true" : "false");
PushIndent(" ");
for (int childIndex = 0; childIndex < p.Children.Count; childIndex++)
{
WriteNavigator_Recurse(p.Children[childIndex], groupPrefix);
if (childIndex < p.Children.Count -1)
WriteLine(",");
else
WriteLine(string.Empty);
}
PopIndent();
Write("})");
}else{
Write("new ClaimNavigatorItem(\"{0}{1}\", {2})", Prefix, p.Name, p.Hidden ? "true" : "false");
}
}
void WriteAdministratorClaims(Permission root){
PushIndent(" ");
Stack<string> parents = new Stack<string>();
parents.Push("c");
foreach (var pChild in root.Children)
WriteAdministratorClaims_Recurse(pChild, parents);
PopIndent();
}
void WriteAdministratorClaims_Recurse(Permission p, Stack<string> parents){
if (p.IsGroup){
parents.Push(string.Format("{0}.{1}", parents.Peek(), p.Name));
foreach (var pChild in p.Children)
WriteAdministratorClaims_Recurse(pChild, parents);
parents.Pop();
}else{
if (p.Name != "ComputerAccount")
WriteLine("{0}.{1} = true;", parents.Peek(), p.Name);
}
}
void WriteAccessHashes(Permission root){
StringBuilder hashes = new StringBuilder();
Stack<string> parents = new Stack<string>();
parents.Push("c");
foreach (var pChild in root.Children)
WriteAccessHashes_Recurse(pChild, string.Empty, parents, hashes);
WriteLine(hashes.ToString().TrimEnd().TrimEnd(','));
}
void WriteAccessHashes_Recurse(Permission p, string Prefix, Stack<string> parents, StringBuilder hashes){
if (p.IsGroup){
parents.Push(string.Format("{0}.{1}", parents.Peek(), p.Name));
foreach (var pChild in p.Children)
WriteAccessHashes_Recurse(pChild, string.Concat(Prefix, p.Name, "."), parents, hashes);
parents.Pop();
}else{
var fqn = string.Concat(Prefix, p.Name);
hashes.AppendFormat(" {{ \"{0}\", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string>(c => {1}.{2}, (c, v) => {1}.{2} = v, \"{3}\", \"{4}\") }},", fqn, parents.Peek(), p.Name, p.FriendlyName, p.Description);
hashes.AppendLine();
}
}
void WritePermissionConsts(Permission root){
PushIndent(" ");
PushIndent(" ");
foreach (var pChild in root.Children)
WritePermissionConsts_Recurse(pChild, string.Empty);
PopIndent();
PopIndent();
}
void WritePermissionConsts_Recurse(Permission p, string Prefix){
if (p.IsGroup){
WriteLine("");
WriteLine("/// <summary>{0}", p.FriendlyName);
WriteLine("/// <para>{0}</para>", p.Description);
WriteLine("/// </summary>");
WriteLine("public static class {0}", p.Name);
WriteLine("{");
PushIndent(" ");
foreach (var pChild in p.Children)
WritePermissionConsts_Recurse(pChild, string.Concat(Prefix, p.Name, "."));
PopIndent();
WriteLine("}");
}else{
WriteLine("");
WriteLine("/// <summary>{0}", p.FriendlyName);
WriteLine("/// <para>{0}</para>", p.Description);
WriteLine("/// </summary>");
WriteLine("public const string {0} = \"{1}{0}\";", p.Name, Prefix);
}
}
Permission BuildHierarchy(List<Permission> groups, List<Permission> permissions){
var top = groups[0];
// Find Parents
var groupDict = groups.ToDictionary(p => p.FullName);
// Hierarchy
foreach (var p in permissions.Where(p => p.IsGroup))
{
var g = groupDict[p.Type];
p.Children = g.Children;
p.FriendlyName = g.FriendlyName;
p.Description = g.Description;
}
return top;
}
void ParseProjectItem(ProjectItem item, List<Permission> groups, List<Permission> permissions){
foreach (var ns in item.FileCodeModel.CodeElements.OfType<CodeNamespace>())
{
foreach (var cl in ns.Members.OfType<CodeClass2>())
{
var g = BuildPermission(cl);
groups.Add(g);
foreach (var pr in cl.Members.OfType<CodeProperty2>())
{
var p = BuildPermission(pr);
permissions.Add(p);
g.Children.Add(p);
}
g.Children = g.Children.OrderBy(p => p.IsGroup).OrderBy(p => p.FriendlyName).ToList();
}
}
}
IEnumerable<ProjectItem> FindClaimGroupProjectItems(ProjectItem item){
const string collectionGuid = "{6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}";
if (item.Kind == collectionGuid)
foreach (ProjectItem subItem in item.ProjectItems)
foreach (var returnItem in FindClaimGroupProjectItems(subItem))
yield return returnItem;
else
yield return item;
}
Permission BuildPermission(CodeClass2 item){
return new Permission(item.FullName, item.Name, item.FullName, item.Attributes);
}
Permission BuildPermission(CodeProperty2 item){
return new Permission(item.FullName, item.Name, item.Type.AsFullName, item.Attributes);
}
[ComImport, Guid("00020400-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDispatch
{
void Reserved();
[PreserveSig]
int GetTypeInfo(uint nInfo, int lcid,
[MarshalAs(
UnmanagedType.CustomMarshaler,
MarshalTypeRef = typeof(TypeToTypeInfoMarshaler))]
out System.Type typeInfo);
}
class Permission {
public string FullName {get;set;}
public string Name {get;set;}
public string Type {get;set;}
public bool Hidden {get;set;}
public bool IsGroup {get { return Type != "System.Boolean"; } }
public List<Permission> Children {get;set;}
public string FriendlyName {get;set;}
public string Description {get;set;}
public Permission(string FullName, string Name, string Type, CodeElements Attributes)
{
this.FullName = FullName;
this.Name = Name;
this.Type = Type;
Children = new List<Permission>();
if (Attributes.Count > 0){
CodeAttribute att = (CodeAttribute)Attributes.Item("ClaimDetails");
if (att.Children != null){
var attChildren = att.Children.OfType<CodeAttributeArgument>().ToArray();
this.FriendlyName = attChildren[0].Value.Trim('"');
this.Description = attChildren[1].Value.Trim('"');
if (attChildren.Length > 2) {
this.Hidden = bool.Parse(attChildren[2].Value);
}
}
}
}
}
#>
@@ -0,0 +1,41 @@
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public class DiscoAuthorizeAllAttribute : AuthorizeAttribute
{
string[] authorizedClaims;
public DiscoAuthorizeAllAttribute(params string[] AuthorisedClaims)
{
if (AuthorisedClaims == null || AuthorisedClaims.Length == 0)
throw new ArgumentNullException("AuthorisedClaims");
this.authorizedClaims = AuthorisedClaims;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
return false; // No Current User
return authToken.HasAll(authorizedClaims);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new HttpUnauthorizedResult(AuthorizationToken.BuildRequireAllMessage(authorizedClaims));
}
}
}
@@ -0,0 +1,41 @@
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public class DiscoAuthorizeAnyAttribute : AuthorizeAttribute
{
string[] authorizedClaims;
public DiscoAuthorizeAnyAttribute(params string[] AuthorisedClaims)
{
if (AuthorisedClaims == null || AuthorisedClaims.Length == 0)
throw new ArgumentNullException("AuthorisedClaims");
this.authorizedClaims = AuthorisedClaims;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
return false; // No Current User
return authToken.HasAny(authorizedClaims);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new HttpUnauthorizedResult(AuthorizationToken.BuildRequireAnyMessage(authorizedClaims));
}
}
}
@@ -0,0 +1,53 @@
using Disco.Services.Users;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace Disco.Services.Authorization
{
public class DiscoAuthorizeAttribute : AuthorizeAttribute
{
string authorizedClaim;
public DiscoAuthorizeAttribute() { }
public DiscoAuthorizeAttribute(string AuthorisedClaim)
{
this.authorizedClaim = AuthorisedClaim;
}
protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
var authToken = UserService.CurrentAuthorization;
if (authToken == null)
return false; // No Current User
if (authorizedClaim == null)
return authToken.RoleTokens.Count > 0; // Just Authenticate - no Authorization (but require at least 1 role)
else
return authToken.Has(authorizedClaim);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
string resultMessage;
if (UserService.CurrentAuthorization == null)
resultMessage = AuthorizationToken.RequireAuthenticationMessage;
else
if (string.IsNullOrEmpty(authorizedClaim))
resultMessage = AuthorizationToken.RequireDiscoAuthorizationMessage;
else
resultMessage = AuthorizationToken.BuildRequireMessage(authorizedClaim);
filterContext.Result = new HttpUnauthorizedResult(resultMessage);
}
}
}
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles
{
public abstract class BaseRoleClaimGroup
{
}
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class ClaimDetailsAttribute : Attribute
{
public string Name { get; set; }
public string Description { get; set; }
public bool Hidden { get; set; }
public ClaimDetailsAttribute(string Name, string Description, bool Hidden = false)
{
this.Name = Name;
this.Description = Description;
this.Hidden = Hidden;
}
}
}
@@ -0,0 +1,59 @@
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceBatch;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceCertificate;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceModel;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceProfile;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DocumentTemplate;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Enrolment;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Logging;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Origanisation;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Plugin;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration.System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration
{
[ClaimDetails("Configuration", "Permissions related to Disco Configuration")]
public class ConfigClaims : BaseRoleClaimGroup
{
public ConfigClaims()
{
this.DeviceCertificate = new DeviceCertificateClaims();
this.Enrolment = new EnrolmentClaims();
this.DeviceBatch = new DeviceBatchClaims();
this.DeviceModel = new DeviceModelClaims();
this.DeviceProfile = new DeviceProfileClaims();
this.DocumentTemplate = new DocumentTemplateClaims();
this.Logging = new LoggingClaims();
this.Plugin = new PluginClaims();
this.System = new SystemClaims();
this.Organisation = new OrganisationClaims();
}
[ClaimDetails("Show Configuration", "Can show the configuration menu")]
public bool Show { get; set; }
public DeviceCertificateClaims DeviceCertificate { get; set; }
public EnrolmentClaims Enrolment { get; set; }
public DeviceBatchClaims DeviceBatch { get; set; }
public DeviceModelClaims DeviceModel { get; set; }
public DeviceProfileClaims DeviceProfile { get; set; }
public DocumentTemplateClaims DocumentTemplate { get; set; }
public LoggingClaims Logging { get; set; }
public PluginClaims Plugin { get; set; }
public SystemClaims System { get; set; }
public OrganisationClaims Organisation { get; set; }
}
}
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceBatch
{
[ClaimDetails("Device Batch", "Permissions related to Device Batches")]
public class DeviceBatchClaims : BaseRoleClaimGroup
{
[ClaimDetails("Configure Device Batches", "Can configure device batches")]
public bool Configure { get; set; }
[ClaimDetails("Create Device Batches", "Can create device batches")]
public bool Create { get; set; }
[ClaimDetails("Delete Device Batches", "Can delete device batches")]
public bool Delete { get; set; }
[ClaimDetails("Show Device Batches", "Can show device batches")]
public bool Show { get; set; }
[ClaimDetails("Show Timeline", "Can show device batch timeline")]
public bool ShowTimeline { get; set; }
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceCertificate
{
[ClaimDetails("Device Certificate", "Permissions related to Device Certificates")]
public class DeviceCertificateClaims : BaseRoleClaimGroup
{
[ClaimDetails("Download Certificates", "Can download certificates")]
public bool DownloadCertificates { get; set; }
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceModel
{
[ClaimDetails("Device Model", "Permissions related to Device Models")]
public class DeviceModelClaims : BaseRoleClaimGroup
{
[ClaimDetails("Configure Device Models", "Can configure device models")]
public bool Configure { get; set; }
[ClaimDetails("Configure Device Model Components", "Can configure device model components")]
public bool ConfigureComponents { get; set; }
[ClaimDetails("Delete Device Models", "Can delete device models")]
public bool Delete { get; set; }
[ClaimDetails("Show Device Models", "Can show device models")]
public bool Show { get; set; }
}
}
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DeviceProfile
{
[ClaimDetails("Device Profile", "Permissions related to Device Profiles")]
public class DeviceProfileClaims : BaseRoleClaimGroup
{
[ClaimDetails("Configure Device Profiles", "Can configure device profiles")]
public bool Configure { get; set; }
[ClaimDetails("Configure Computer Name Templates", "Can configure computer name templates for device profiles")]
public bool ConfigureComputerNameTemplate { get; set; }
[ClaimDetails("Configure Default Device Profiles", "Can configure default device profiles")]
public bool ConfigureDefaults { get; set; }
[ClaimDetails("Create Device Profiles", "Can create device profiles")]
public bool Create { get; set; }
[ClaimDetails("Delete Device Profiles", "Can delete device profiles")]
public bool Delete { get; set; }
[ClaimDetails("Show Device Profiles", "Can show device profiles")]
public bool Show { get; set; }
}
}
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.DocumentTemplate
{
[ClaimDetails("Document Template", "Permissions related to Document Templates")]
public class DocumentTemplateClaims : BaseRoleClaimGroup
{
[ClaimDetails("Configure Document Templates", "Can configure document templates")]
public bool Configure { get; set; }
[ClaimDetails("Configure Filter Expression", "Can configure filter expressions for document templates")]
public bool ConfigureFilterExpression { get; set; }
[ClaimDetails("Upload Document Templates", "Can upload document templates")]
public bool Upload { get; set; }
[ClaimDetails("Create Document Templates", "Can create document templates")]
public bool Create { get; set; }
[ClaimDetails("Delete Document Templates", "Can delete document templates")]
public bool Delete { get; set; }
[ClaimDetails("Show Document Templates", "Can show document templates")]
public bool Show { get; set; }
[ClaimDetails("Show Document Template Import Status", "Can show the document template import status")]
public bool ShowStatus { get; set; }
[ClaimDetails("Bulk Generate Document Templates", "Can bulk generate document templates")]
public bool BulkGenerate { get; set; }
[ClaimDetails("Undetected Pages", "Can show and assign imported documents which were not undetected")]
public bool UndetectedPages { get; set; }
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Enrolment
{
[ClaimDetails("Enrolment", "Permissions related to Device Enrolment")]
public class EnrolmentClaims
{
[ClaimDetails("Show Enrolment", "Can show device enrolment")]
public bool Show { get; set; }
[ClaimDetails("Configure Enrolment", "Can configure device enrolment")]
public bool Configure { get; set; }
[ClaimDetails("Show Enrolment Status", "Can show the enrolment status")]
public bool ShowStatus { get; set; }
[ClaimDetails("Download Bootstrapper", "Can download the Device Bootstrapper")]
public bool DownloadBootstrapper { get; set; }
}
}
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Logging
{
[ClaimDetails("Logging", "Permissions related to Logging")]
public class LoggingClaims : BaseRoleClaimGroup
{
[ClaimDetails("Show Logging", "Can show logging")]
public bool Show { get; set; }
}
}
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Origanisation
{
[ClaimDetails("Organisation Details", "Permissions related to the Organisation Details")]
public class OrganisationClaims : BaseRoleClaimGroup
{
[ClaimDetails("Show Organisation Details", "Can show the organisation details")]
public bool Show { get; set; }
[ClaimDetails("Configure Name", "Can configure the organisation name")]
public bool ConfigureName { get; set; }
[ClaimDetails("Configure Logo", "Can configure the organisation logo")]
public bool ConfigureLogo { get; set; }
[ClaimDetails("Configure Multi-Site Mode", "Can configure multi-site mode")]
public bool ConfigureMultiSiteMode { get; set; }
[ClaimDetails("Configure Addresses", "Can configure organisation addresses")]
public bool ConfigureAddresses { get; set; }
}
}
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.Plugin
{
[ClaimDetails("Plugin", "Permissions related to Plugins")]
public class PluginClaims : BaseRoleClaimGroup
{
[ClaimDetails("Show Plugins", "Can show plugins")]
public bool Show { get; set; }
[ClaimDetails("Install/Update Plugins", "Can install and update plugins")]
public bool Install { get; set; }
[ClaimDetails("Install/Update Local Plugins", "Can install and update locally uploaded plugins")]
public bool InstallLocal { get; set; }
[ClaimDetails("Uninstall Plugins", "Can uninstall plugins")]
public bool Uninstall { get; set; }
[ClaimDetails("Configure Plugins", "Can configure plugins")]
public bool Configure { get; set; }
}
}
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Configuration.System
{
[ClaimDetails("System", "Permissions related to System Configuration")]
public class SystemClaims : BaseRoleClaimGroup
{
[ClaimDetails("Show System Configuration", "Can show the system configuration")]
public bool Show { get; set; }
[ClaimDetails("Configure Proxy Settings", "Can configure the proxy settings")]
public bool ConfigureProxy { get; set; }
}
}
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Device
{
[ClaimDetails("Actions", "Permissions related to Device Actions")]
public class DeviceActionsClaims : BaseRoleClaimGroup
{
[ClaimDetails("Allow Unauthenticated Enrol", "Can allow devices to enrol without authentication")]
public bool AllowUnauthenticatedEnrol { get; set; }
[ClaimDetails("Assign User", "Can update the user assignment of devices")]
public bool AssignUser { get; set; }
[ClaimDetails("Decommission", "Can decommission devices")]
public bool Decommission { get; set; }
[ClaimDetails("Recommission", "Can recommission devices")]
public bool Recommission { get; set; }
[ClaimDetails("Delete", "Can delete devices")]
public bool Delete { get; set; }
[ClaimDetails("Add Attachments", "Can add attachments to devices")]
public bool AddAttachments { get; set; }
[ClaimDetails("Remove Any Attachments", "Can remove any attachments from devices")]
public bool RemoveAnyAttachments { get; set; }
[ClaimDetails("Remove Own Attachments", "Can remove own attachments from devices")]
public bool RemoveOwnAttachments { get; set; }
[ClaimDetails("Generate Documents", "Can generate documents for jobs")]
public bool GenerateDocuments { get; set; }
[ClaimDetails("Enrol Devices", "Can add devices offline and enrol devices with the Bootstrapper")]
public bool EnrolDevices { get; set; }
[ClaimDetails("Import Devices", "Can bulk import devices")]
public bool Import { get; set; }
[ClaimDetails("Export Devices", "Can export devices in a bulk format")]
public bool Export { get; set; }
}
}
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Device
{
[ClaimDetails("Device", "Permissions related to Devices")]
public class DeviceClaims : BaseRoleClaimGroup
{
public DeviceClaims()
{
this.Properties = new DevicePropertiesClaims();
this.Actions = new DeviceActionsClaims();
}
[ClaimDetails("Search Devices", "Can search devices")]
public bool Search { get; set; }
[ClaimDetails("Show Devices", "Can show devices")]
public bool Show { get; set; }
[ClaimDetails("Show Details", "Can show details associated with devices")]
public bool ShowDetails { get; set; }
[ClaimDetails("Show Attachments", "Can show device attachments")]
public bool ShowAttachments { get; set; }
[ClaimDetails("Show Certificates", "Can show certificates associated with devices")]
public bool ShowCertificates { get; set; }
[ClaimDetails("Show Devices Jobs", "Can show jobs associated with devices")]
public bool ShowJobs { get; set; }
[ClaimDetails("Show Assignment History", "Can show the assignment history for devices")]
public bool ShowAssignmentHistory { get; set; }
public DevicePropertiesClaims Properties { get; set; }
public DeviceActionsClaims Actions { get; set; }
}
}
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Device
{
[ClaimDetails("Device Properties", "Permissions related to Device Properties")]
public class DevicePropertiesClaims : BaseRoleClaimGroup
{
[ClaimDetails("Device Profile Property", "Can update property")]
public bool DeviceProfile { get; set; }
[ClaimDetails("Device Batch Property", "Can update property")]
public bool DeviceBatch { get; set; }
[ClaimDetails("Asset Number Property", "Can update property")]
public bool AssetNumber { get; set; }
[ClaimDetails("Location Property", "Can update property")]
public bool Location { get; set; }
}
}
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Actions", "Permissions related to Job Actions")]
public class JobActionsClaims : BaseRoleClaimGroup
{
[ClaimDetails("Create Jobs", "Can create jobs")]
public bool Create { get; set; }
[ClaimDetails("Close Jobs", "Can close jobs")]
public bool Close { get; set; }
[ClaimDetails("Force Close Jobs", "Can force close jobs")]
public bool ForceClose { get; set; }
[ClaimDetails("Reopen Jobs", "Can reopen jobs")]
public bool Reopen { get; set; }
[ClaimDetails("Delete Jobs", "Can delete jobs")]
public bool Delete { get; set; }
[ClaimDetails("Log Warranty", "Can log warranty for jobs")]
public bool LogWarranty { get; set; }
[ClaimDetails("Log Repair", "Can log repair for non-warranty jobs")]
public bool LogRepair { get; set; }
[ClaimDetails("Convert HWar Jobs To HNWar", "Can convert warranty jobs to non-warranty jobs")]
public bool ConvertHWarToHNWar { get; set; }
[ClaimDetails("Add Logs", "Can add job logs")]
public bool AddLogs { get; set; }
[ClaimDetails("Remove Any Logs", "Can remove any job logs")]
public bool RemoveAnyLogs { get; set; }
[ClaimDetails("Remove Own Logs", "Can remove own job logs")]
public bool RemoveOwnLogs { get; set; }
[ClaimDetails("Add Attachments", "Can add attachments to jobs")]
public bool AddAttachments { get; set; }
[ClaimDetails("Remove Any Attachments", "Can remove any attachments from jobs")]
public bool RemoveAnyAttachments { get; set; }
[ClaimDetails("Remove Own Attachments", "Can remove own attachments from jobs")]
public bool RemoveOwnAttachments { get; set; }
[ClaimDetails("Generate Documents", "Can generate documents for jobs")]
public bool GenerateDocuments { get; set; }
[ClaimDetails("Update Sub Types", "Can update sub types for jobs")]
public bool UpdateSubTypes { get; set; }
}
}
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Job", "Permissions related to Jobs")]
public class JobClaims : BaseRoleClaimGroup
{
public JobClaims()
{
this.Lists = new JobListsClaims();
this.Actions = new JobActionsClaims();
this.Properties = new JobPropertiesClaims();
this.Types = new JobTypesClaims();
}
[ClaimDetails("Search Jobs", "Can search jobs")]
public bool Search { get; set; }
[ClaimDetails("Show Jobs", "Can show jobs")]
public bool Show { get; set; }
[ClaimDetails("Show Daily Opened & Closed", "Can show daily opened & closed chart")]
public bool ShowDailyChart { get; set; }
[ClaimDetails("Show Logs", "Can show job logs")]
public bool ShowLogs { get; set; }
[ClaimDetails("Show Attachments", "Can show job attachments")]
public bool ShowAttachments { get; set; }
[ClaimDetails("Show Non-Warranty Components", "Can show non-warranty job components")]
public bool ShowNonWarrantyComponents { get; set; }
[ClaimDetails("Show Non-Warranty Finance", "Can show non-warranty job finance")]
public bool ShowNonWarrantyFinance { get; set; }
[ClaimDetails("Show Non-Warranty Repairs", "Can show non-warranty job repairs")]
public bool ShowNonWarrantyRepairs { get; set; }
[ClaimDetails("Show Non-Warranty Insurance", "Can show non-warranty job insurance")]
public bool ShowNonWarrantyInsurance { get; set; }
[ClaimDetails("Show Warranty", "Can show job warranty")]
public bool ShowWarranty { get; set; }
[ClaimDetails("Show Flags", "Can show job flags")]
public bool ShowFlags { get; set; }
public JobListsClaims Lists { get; set; }
public JobActionsClaims Actions { get; set; }
public JobPropertiesClaims Properties { get; set; }
public JobTypesClaims Types { get; set; }
}
}
@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Lists", "Permissions related to Job Lists")]
public class JobListsClaims : BaseRoleClaimGroup
{
[ClaimDetails("Awaiting Technician Action List", "Can show list")]
public bool AwaitingTechnicianAction { get; set; }
[ClaimDetails("Long Running Jobs List", "Can show list")]
public bool LongRunningJobs { get; set; }
[ClaimDetails("All Open List", "Can show list")]
public bool AllOpen { get; set; }
[ClaimDetails("Devices Ready For Return List", "Can show list")]
public bool DevicesReadyForReturn { get; set; }
[ClaimDetails("Devices Awaiting Repair List", "Can show list")]
public bool DevicesAwaitingRepair { get; set; }
[ClaimDetails("Awaiting Finance List", "Can show list")]
public bool AwaitingFinance { get; set; }
[ClaimDetails("Awaiting Finance Charge List", "Can show list (NOTE: Requires Awaiting Finance List)")]
public bool AwaitingFinanceCharge { get; set; }
[ClaimDetails("Awaiting Finance Payment List", "Can show list (NOTE: Requires Awaiting Finance List)")]
public bool AwaitingFinancePayment { get; set; }
[ClaimDetails("Awaiting Finance Insurance Processing List", "Can show list (NOTE: Requires Awaiting Finance List)")]
public bool AwaitingFinanceInsuranceProcessing { get; set; }
[ClaimDetails("Awaiting Finance Agreement Breach List", "Can show list (NOTE: Requires Awaiting Finance List)")]
public bool AwaitingFinanceAgreementBreach { get; set; }
[ClaimDetails("Awaiting User Action List", "Can show list")]
public bool AwaitingUserAction { get; set; }
[ClaimDetails("Recently Closed List", "Can show list")]
public bool RecentlyClosed { get; set; }
[ClaimDetails("Locations List", "Can show list")]
public bool Locations { get; set; }
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Non Warranty Properties", "Permissions related to Non-Warranty Job Properties")]
public class JobNonWarrantyPropertiesClaims : BaseRoleClaimGroup
{
[ClaimDetails("Add Components", "Can add job components (NOTE: Requires Edit Components)")]
public bool AddComponents { get; set; }
[ClaimDetails("Edit Components", "Can edit and remove job components")]
public bool EditComponents { get; set; }
[ClaimDetails("Is Insurance Claim Property", "Can update property")]
public bool IsInsuranceClaim { get; set; }
[ClaimDetails("Insurance Claim Form Sent Property", "Can update property")]
public bool InsuranceClaimFormSent { get; set; }
[ClaimDetails("Accounting Charge Required Property", "Can update property")]
public bool AccountingChargeRequired { get; set; }
[ClaimDetails("Accounting Charge Added Property", "Can update property")]
public bool AccountingChargeAdded { get; set; }
[ClaimDetails("Accounting Charge Paid Property", "Can update property")]
public bool AccountingChargePaid { get; set; }
[ClaimDetails("Purchase Order Raised Property", "Can update property")]
public bool PurchaseOrderRaised { get; set; }
[ClaimDetails("Purchase Order Reference Property", "Can update property")]
public bool PurchaseOrderReference { get; set; }
[ClaimDetails("Purchase Order Sent Property", "Can update property")]
public bool PurchaseOrderSent { get; set; }
[ClaimDetails("Invoice Received Property", "Can update property")]
public bool InvoiceReceived { get; set; }
[ClaimDetails("Repairer Name Property", "Can update property")]
public bool RepairerName { get; set; }
[ClaimDetails("Repairer Completed Date Property", "Can update property")]
public bool RepairerCompletedDate { get; set; }
[ClaimDetails("Repairer Logged Date Property", "Can update property")]
public bool RepairerLoggedDate { get; set; }
[ClaimDetails("Repairer Reference Property", "Can update property")]
public bool RepairerReference { get; set; }
[ClaimDetails("Insurance Detail Properties", "Can update insurance detail properties")]
public bool InsuranceDetails { get; set; }
}
}
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Job Properties", "Permissions related to Job Properties")]
public class JobPropertiesClaims : BaseRoleClaimGroup
{
public JobPropertiesClaims()
{
this.WarrantyProperties = new JobWarrantyPropertiesClaims();
this.NonWarrantyProperties = new JobNonWarrantyPropertiesClaims();
}
public JobWarrantyPropertiesClaims WarrantyProperties { get; set; }
public JobNonWarrantyPropertiesClaims NonWarrantyProperties { get; set; }
[ClaimDetails("Device Held Property", "Can update property")]
public bool DeviceHeld { get; set; }
[ClaimDetails("Device Ready For Return Property", "Can update property")]
public bool DeviceReadyForReturn { get; set; }
[ClaimDetails("Device Returned Property", "Can update property")]
public bool DeviceReturned { get; set; }
[ClaimDetails("Waiting For User Action Property", "Can update property")]
public bool WaitingForUserAction { get; set; }
[ClaimDetails("Not Waiting For User Action Property", "Can update property")]
public bool NotWaitingForUserAction { get; set; }
[ClaimDetails("Flags Property", "Can update property")]
public bool Flags { get; set; }
[ClaimDetails("Expected Closed Date Property", "Can update property")]
public bool ExpectedClosedDate { get; set; }
[ClaimDetails("Device Held Location Property", "Can update property")]
public bool DeviceHeldLocation { get; set; }
}
}
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Types", "Permissions related to Job Types")]
public class JobTypesClaims : BaseRoleClaimGroup
{
[ClaimDetails("Show Hardware - Miscellaneous Jobs", "Can show jobs of this type")]
public bool ShowHMisc { get; set; }
[ClaimDetails("Show Hardware - Non-Warranty Jobs", "Can show jobs of this type")]
public bool ShowHNWar { get; set; }
[ClaimDetails("Show Hardware - Warranty Jobs", "Can show jobs of this type")]
public bool ShowHWar { get; set; }
[ClaimDetails("Show Software - Application Jobs", "Can show jobs of this type")]
public bool ShowSApp { get; set; }
[ClaimDetails("Show Software - Reimage Jobs", "Can show jobs of this type")]
public bool ShowSImg { get; set; }
[ClaimDetails("Show Software - Operating System Jobs", "Can show jobs of this type")]
public bool ShowSOS { get; set; }
[ClaimDetails("Show User Management Jobs", "Can show jobs of this type")]
public bool ShowUMgmt { get; set; }
}
}
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.Job
{
[ClaimDetails("Warranty Properties", "Permissions related to Warranty Job Properties")]
public class JobWarrantyPropertiesClaims : BaseRoleClaimGroup
{
[ClaimDetails("Warranty Completed Property", "Can update property")]
public bool WarrantyCompleted { get; set; }
[ClaimDetails("External Name Property", "Can update property")]
public bool ExternalName { get; set; }
[ClaimDetails("External Logged Date Property", "Can update property")]
public bool ExternalLoggedDate { get; set; }
[ClaimDetails("External Reference Property", "Can update property")]
public bool ExternalReference { get; set; }
[ClaimDetails("External Completed Date Property", "Can update property")]
public bool ExternalCompletedDate { get; set; }
[ClaimDetails("Provider Details", "Can access warranty provider details")]
public bool ProviderDetails { get; set; }
}
}
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.User
{
[ClaimDetails("Actions", "Permissions related to User Actions")]
public class UserActionsClaims : BaseRoleClaimGroup
{
[ClaimDetails("Add Attachments", "Can add attachments to users")]
public bool AddAttachments { get; set; }
[ClaimDetails("Remove Any Attachments", "Can remove any attachments from users")]
public bool RemoveAnyAttachments { get; set; }
[ClaimDetails("Remove Own Attachments", "Can remove own attachments from users")]
public bool RemoveOwnAttachments { get; set; }
[ClaimDetails("Generate Documents", "Can generate documents for users")]
public bool GenerateDocuments { get; set; }
}
}
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles.ClaimGroups.User
{
[ClaimDetails("User", "Permissions related to Users")]
public class UserClaims : BaseRoleClaimGroup
{
public UserClaims()
{
this.Actions = new UserActionsClaims();
}
[ClaimDetails("Search Users", "Can search users")]
public bool Search { get; set; }
[ClaimDetails("Show Users", "Can show users")]
public bool Show { get; set; }
[ClaimDetails("Show Attachments", "Can show user attachments")]
public bool ShowAttachments { get; set; }
[ClaimDetails("Show Device Assignment History", "Can show the device assignment history for users")]
public bool ShowAssignmentHistory { get; set; }
[ClaimDetails("Show Users Jobs", "Can show jobs associated with users")]
public bool ShowJobs { get; set; }
[ClaimDetails("Show Users Authorization", "Can show authorization permissions associated with users")]
public bool ShowAuthorization { get; set; }
public UserActionsClaims Actions { get; set; }
}
}
@@ -0,0 +1,106 @@
using Disco.Data.Repository;
using Disco.Models.Authorization;
using Disco.Models.Repository;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles
{
public static class RoleCache
{
internal const int AdministratorsTokenId = -1;
internal const int ComputerAccountTokenId = -200;
internal const string AdministratorsTokenSubjectIds = "Domain Admins,Disco Admins";
internal const string ClaimsJsonEmpty = "null";
private static List<RoleToken> _Cache;
internal static void Initialize(DiscoDataContext Database)
{
_Cache = Database.AuthorizationRoles.ToList().Select(ar => RoleToken.FromAuthorizationRole(ar)).ToList();
// Add System Roles
AddSystemRoles();
}
private static void AddSystemRoles()
{
// Disco Administrators
_Cache.Add(RoleToken.FromAuthorizationRole(new AuthorizationRole()
{
Id = AdministratorsTokenId,
Name = "Disco Administrators",
SubjectIds = AdministratorsTokenSubjectIds
}, Claims.AdministratorClaims()));
// Computer Accounts
_Cache.Add(RoleToken.FromAuthorizationRole(new AuthorizationRole()
{
Id = ComputerAccountTokenId,
Name = "Domain Computer Account"
}, Claims.ComputerAccountClaims()));
}
/// <summary>
/// Create a clone of an Authorization Role
/// <para>Creates immutable clones to avoid side-effects</para>
/// </summary>
/// <param name="TemplateRole">Authorization Role to Clone</param>
/// <returns>A copy of the Authorization Role</returns>
private static AuthorizationRole CloneAuthoriationRole(AuthorizationRole TemplateRole)
{
return new AuthorizationRole()
{
Id = TemplateRole.Id,
Name = TemplateRole.Name,
ClaimsJson = TemplateRole.ClaimsJson,
SubjectIds = TemplateRole.SubjectIds
};
}
internal static RoleToken AddRole(AuthorizationRole Role)
{
var token = RoleToken.FromAuthorizationRole(CloneAuthoriationRole(Role));
_Cache.Add(token);
return token;
}
internal static void RemoveRole(AuthorizationRole Role)
{
var token = GetRoleToken(Role.Id);
if (token != null)
_Cache.Remove(token);
}
internal static RoleToken UpdateRole(AuthorizationRole Role)
{
RemoveRole(Role);
return AddRole(Role);
}
internal static RoleToken GetRoleToken(int Id)
{
return _Cache.FirstOrDefault(t => t.Role.Id == Id);
}
internal static RoleToken GetRoleToken(string SecurityGroup)
{
return _Cache.FirstOrDefault(t => t.SubjectIdHashes.Contains(SecurityGroup.ToLower()));
}
internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> SecurityGroup)
{
var securityGroups = SecurityGroup.Select(sg => sg.ToLower());
return _Cache.Where(t => securityGroups.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList();
}
internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> SecurityGroup, User User)
{
var subjectIds = (new string[] { User.Id }).Concat(SecurityGroup).Select(sg => sg.ToLower());
return _Cache.Where(t => subjectIds.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList();
}
}
}
@@ -0,0 +1,39 @@
using Disco.Services.Authorization.Roles.ClaimGroups;
using Disco.Services.Authorization.Roles.ClaimGroups.Configuration;
using Disco.Services.Authorization.Roles.ClaimGroups.Device;
using Disco.Services.Authorization.Roles.ClaimGroups.Job;
using Disco.Services.Authorization.Roles.ClaimGroups.User;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles
{
public class RoleClaims : BaseRoleClaimGroup
{
public RoleClaims()
{
this.Config = new ConfigClaims();
this.Job = new JobClaims();
this.Device = new DeviceClaims();
this.User = new UserClaims();
}
[ClaimDetails("Computer Account", "Represents a computer account", true)]
public bool ComputerAccount { get; set; }
[ClaimDetails("Disco Administrator Account", "Represents a Disco Administrator account", true)]
public bool DiscoAdminAccount { get; set; }
public ConfigClaims Config { get; set; }
public JobClaims Job { get; set; }
public DeviceClaims Device { get; set; }
public UserClaims User { get; set; }
}
}
@@ -0,0 +1,39 @@
using Disco.Models.Authorization;
using Disco.Models.Repository;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Disco.Services.Authorization.Roles
{
public class RoleToken : IRoleToken
{
public AuthorizationRole Role { get; set; }
internal HashSet<string> SubjectIdHashes { get; set; }
public List<string> SubjectIds { get; set; }
public RoleClaims Claims { get; set; }
public static RoleToken FromAuthorizationRole(AuthorizationRole Role)
{
var claims = JsonConvert.DeserializeObject<RoleClaims>(Role.ClaimsJson);
return FromAuthorizationRole(Role, claims);
}
internal static RoleToken FromAuthorizationRole(AuthorizationRole Role, RoleClaims Claims)
{
string[] sg = (Role.SubjectIds == null ? new string[0] : Role.SubjectIds.Split(',').ToArray());
return new RoleToken()
{
Role = Role,
SubjectIdHashes = new HashSet<string>(sg.Select(i => i.ToLower())),
SubjectIds = sg.ToList(),
Claims = Claims
};
}
}
}