Permissions & Authorization for Users #24
Initial Release; Includes Database and MVC refactoring
This commit is contained in:
@@ -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
@@ -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; }
|
||||
}
|
||||
}
|
||||
+27
@@ -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; }
|
||||
}
|
||||
}
|
||||
+15
@@ -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; }
|
||||
}
|
||||
}
|
||||
+24
@@ -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; }
|
||||
}
|
||||
}
|
||||
+30
@@ -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; }
|
||||
}
|
||||
}
|
||||
+39
@@ -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; }
|
||||
}
|
||||
}
|
||||
+24
@@ -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; }
|
||||
}
|
||||
}
|
||||
+27
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,7 @@
|
||||
<Private>True</Private>
|
||||
<HintPath>..\packages\Microsoft.SqlServer.Compact.4.0.8876.1\lib\net40\System.Data.SqlServerCe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Web" />
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
@@ -88,6 +89,45 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Authorization\AccessDeniedException.cs" />
|
||||
<Compile Include="Authorization\AuthorizationToken.cs" />
|
||||
<Compile Include="Authorization\ClaimNavigatorItem.cs" />
|
||||
<Compile Include="Authorization\DiscoAuthorizeAllAttribute.cs" />
|
||||
<Compile Include="Authorization\DiscoAuthorizeAnyAttribute.cs" />
|
||||
<Compile Include="Authorization\DiscoAuthorizeAttribute.cs" />
|
||||
<Compile Include="Authorization\Roles\BaseRoleClaimGroup.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\ConfigClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceBatch\DeviceBatchClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceCertificate\DeviceCertificateClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceModel\DeviceModelClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DeviceProfile\DeviceProfileClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\DocumentTemplate\DocumentTemplateClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\Enrolment\EnrolmentClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\Logging\LoggingClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\Origanisation\OrganisationClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\Plugin\PluginClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Configuration\System\SystemClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Device\DeviceActionsClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Device\DeviceClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Device\DevicePropertiesClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobActionsClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobListsClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobNonWarrantyPropertiesClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobPropertiesClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobTypesClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\Job\JobWarrantyPropertiesClaims.cs" />
|
||||
<Compile Include="Authorization\Claims.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Claims.tt</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Authorization\Roles\ClaimDetailsAttribute.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\User\UserActionsClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\ClaimGroups\User\UserClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\RoleCache.cs" />
|
||||
<Compile Include="Authorization\Roles\RoleClaims.cs" />
|
||||
<Compile Include="Authorization\Roles\RoleToken.cs" />
|
||||
<Compile Include="Logging\LogBase.cs" />
|
||||
<Compile Include="Logging\LogContext.cs" />
|
||||
<Compile Include="Logging\LogReInitalizeJob.cs" />
|
||||
@@ -141,6 +181,19 @@
|
||||
<Compile Include="Tasks\ScheduledTaskStatus.cs" />
|
||||
<Compile Include="Tasks\ScheduledTaskStatusLive.cs" />
|
||||
<Compile Include="Plugins\Features\UIExtension\UIExtensions.cs" />
|
||||
<Compile Include="Users\Cache.cs" />
|
||||
<Compile Include="Users\CacheCleanTask.cs" />
|
||||
<Compile Include="Users\Searching.cs" />
|
||||
<Compile Include="Users\UserService.cs" />
|
||||
<Compile Include="Web\AuthorizedController.cs" />
|
||||
<Compile Include="Web\AuthorizedDatabaseController.cs" />
|
||||
<Compile Include="Web\Bundles\Bundle.cs" />
|
||||
<Compile Include="Web\Bundles\BundleExtensions.cs" />
|
||||
<Compile Include="Web\Bundles\BundleHandler.cs" />
|
||||
<Compile Include="Web\Bundles\BundleModule.cs" />
|
||||
<Compile Include="Web\Bundles\BundleTable.cs" />
|
||||
<Compile Include="Web\DatabaseController.cs" />
|
||||
<Compile Include="Web\WebViewPage.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Disco.Data\Disco.Data.csproj">
|
||||
@@ -154,8 +207,15 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="Authorization\Claims.tt">
|
||||
<Generator>TextTemplatingFileGenerator</Generator>
|
||||
<LastGenOutput>Claims.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
|
||||
@@ -70,10 +70,10 @@ namespace Disco.Services.Logging
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitalizeDatabase(Targets.LogPersistContext logDbContext)
|
||||
private static void InitalizeDatabase(Targets.LogPersistContext LogDatabase)
|
||||
{
|
||||
// Add Modules
|
||||
var existingModules = logDbContext.Modules.Include("EventTypes").ToDictionary(m => m.Id);
|
||||
var existingModules = LogDatabase.Modules.Include("EventTypes").ToDictionary(m => m.Id);
|
||||
foreach (var module in LogModules)
|
||||
{
|
||||
// Update/Insert Module
|
||||
@@ -95,7 +95,7 @@ namespace Disco.Services.Logging
|
||||
Name = module.Value.ModuleName,
|
||||
Description = module.Value.ModuleDescription
|
||||
};
|
||||
logDbContext.Modules.Add(dbModule);
|
||||
LogDatabase.Modules.Add(dbModule);
|
||||
}
|
||||
// Update/Insert Event Types
|
||||
Dictionary<int, Models.LogEventType> existingEventTypes = (dbModule.EventTypes == null) ? new Dictionary<int, Models.LogEventType>() : dbModule.EventTypes.ToDictionary(et => et.Id);
|
||||
@@ -123,17 +123,17 @@ namespace Disco.Services.Logging
|
||||
Severity = eventType.Value.Severity,
|
||||
Format = eventType.Value.Format
|
||||
};
|
||||
logDbContext.EventTypes.Add(dbEventType);
|
||||
LogDatabase.EventTypes.Add(dbEventType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logDbContext.SaveChanges();
|
||||
LogDatabase.SaveChanges();
|
||||
}
|
||||
|
||||
public static string LogFileBasePath(DiscoDataContext DiscoContext)
|
||||
public static string LogFileBasePath(DiscoDataContext Database)
|
||||
{
|
||||
var logDirectoryBase = Path.Combine(DiscoContext.DiscoConfiguration.DataStoreLocation, "Logs");
|
||||
var logDirectoryBase = Path.Combine(Database.DiscoConfiguration.DataStoreLocation, "Logs");
|
||||
// Create Directory Structure
|
||||
if (!Directory.Exists(logDirectoryBase))
|
||||
{
|
||||
@@ -155,9 +155,9 @@ namespace Disco.Services.Logging
|
||||
return logDirectoryBase;
|
||||
}
|
||||
|
||||
public static string LogFilePath(DiscoDataContext DiscoContext, DateTime Date, bool CreateDirectory = true)
|
||||
public static string LogFilePath(DiscoDataContext Database, DateTime Date, bool CreateDirectory = true)
|
||||
{
|
||||
var logDirectoryBase = LogFileBasePath(DiscoContext);
|
||||
var logDirectoryBase = LogFileBasePath(Database);
|
||||
var logDirectory = Path.Combine(logDirectoryBase, Date.Year.ToString());
|
||||
if (CreateDirectory && !Directory.Exists(logDirectory))
|
||||
{
|
||||
@@ -167,11 +167,11 @@ namespace Disco.Services.Logging
|
||||
return Path.Combine(logDirectory, logFileName);
|
||||
}
|
||||
|
||||
internal static void ReInitalize(DiscoDataContext DiscoContext)
|
||||
internal static void ReInitalize(DiscoDataContext Database)
|
||||
{
|
||||
lock (_CurrentLock)
|
||||
{
|
||||
var logPath = LogFilePath(DiscoContext, DateTime.Today);
|
||||
var logPath = LogFilePath(Database, DateTime.Today);
|
||||
|
||||
//var connectionString = string.Format("Data Source=\"{0}\"", logPath);
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace Disco.Services.Logging
|
||||
try
|
||||
{
|
||||
// Get Yesterdays Log
|
||||
var yesterdaysLogPath = LogFilePath(DiscoContext, DateTime.Today.AddDays(-1), false);
|
||||
var yesterdaysLogPath = LogFilePath(Database, DateTime.Today.AddDays(-1), false);
|
||||
if (File.Exists(yesterdaysLogPath))
|
||||
{
|
||||
SqlCeConnectionStringBuilder sqlCeCSB = new SqlCeConnectionStringBuilder();
|
||||
@@ -229,9 +229,9 @@ namespace Disco.Services.Logging
|
||||
}
|
||||
|
||||
private static IScheduler _ReInitializeScheduler;
|
||||
public static void Initalize(DiscoDataContext DiscoContext, ISchedulerFactory SchedulerFactory)
|
||||
public static void Initalize(DiscoDataContext Database, ISchedulerFactory SchedulerFactory)
|
||||
{
|
||||
ReInitalize(DiscoContext);
|
||||
ReInitalize(Database);
|
||||
|
||||
_ReInitializeScheduler = SchedulerFactory.GetScheduler();
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace Disco.Services.Logging
|
||||
{
|
||||
public void Execute(IJobExecutionContext context)
|
||||
{
|
||||
using (DiscoDataContext DiscoContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
LogContext.ReInitalize(DiscoContext);
|
||||
LogContext.ReInitalize(database);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ namespace Disco.Services.Logging
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Models.LogLiveEvent> Query(DiscoDataContext DiscoContext)
|
||||
public List<Models.LogLiveEvent> Query(DiscoDataContext Database)
|
||||
{
|
||||
List<Models.LogLiveEvent> results = new List<LogLiveEvent>();
|
||||
|
||||
// Validate Options
|
||||
this.Validate();
|
||||
|
||||
var relevantLogFiles = RelevantLogFiles(DiscoContext);
|
||||
var relevantLogFiles = RelevantLogFiles(Database);
|
||||
relevantLogFiles.Reverse();
|
||||
foreach (var logFile in relevantLogFiles)
|
||||
{
|
||||
@@ -73,10 +73,10 @@ namespace Disco.Services.Logging
|
||||
}
|
||||
}
|
||||
|
||||
private List<Tuple<string, DateTime>> RelevantLogFiles(DiscoDataContext DiscoContext)
|
||||
private List<Tuple<string, DateTime>> RelevantLogFiles(DiscoDataContext Database)
|
||||
{
|
||||
List<Tuple<string, DateTime>> relevantFiles = new List<Tuple<string, DateTime>>();
|
||||
var logDirectoryBase = LogContext.LogFileBasePath(DiscoContext);
|
||||
var logDirectoryBase = LogContext.LogFileBasePath(Database);
|
||||
var logDirectoryBaseInfo = new DirectoryInfo(logDirectoryBase);
|
||||
var endDate = this.End.HasValue ? this.End.Value : DateTime.Now;
|
||||
var endDateYear = endDate.Year.ToString();
|
||||
@@ -91,7 +91,7 @@ namespace Disco.Services.Logging
|
||||
var queryDate = this.Start.Value.Date;
|
||||
while (queryDate <= endDate)
|
||||
{
|
||||
var fileName = LogContext.LogFilePath(DiscoContext, queryDate, false);
|
||||
var fileName = LogContext.LogFilePath(Database, queryDate, false);
|
||||
if (File.Exists(fileName))
|
||||
relevantFiles.Add(new Tuple<string, DateTime>(fileName, LogFileDate(fileName).Value));
|
||||
|
||||
|
||||
@@ -48,13 +48,13 @@ namespace Disco.Services.Plugins.CommunityInterop
|
||||
|
||||
Status.UpdateStatus(1, "Updating Plugin Library Catalogue", "Building Request");
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
catalogueFile = Plugins.CatalogueFile(dbContext);
|
||||
catalogueFile = Plugins.CatalogueFile(database);
|
||||
|
||||
updateRequestBody = new PluginLibraryUpdateRequest()
|
||||
{
|
||||
DeploymentId = dbContext.DiscoConfiguration.DeploymentId,
|
||||
DeploymentId = database.DiscoConfiguration.DeploymentId,
|
||||
HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
|
||||
};
|
||||
}
|
||||
@@ -111,13 +111,13 @@ namespace Disco.Services.Plugins.CommunityInterop
|
||||
|
||||
Status.UpdateStatus(50, "Updating Plugin Library Compatibility", "Building Request");
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
compatibilityFile = Plugins.CompatibilityFile(dbContext);
|
||||
compatibilityFile = Plugins.CompatibilityFile(database);
|
||||
|
||||
compatRequestBody = new PluginLibraryCompatibilityRequest()
|
||||
{
|
||||
DeploymentId = dbContext.DiscoConfiguration.DeploymentId,
|
||||
DeploymentId = database.DiscoConfiguration.DeploymentId,
|
||||
HostVersion = typeof(Plugins).Assembly.GetName().Version.ToString(4)
|
||||
};
|
||||
}
|
||||
@@ -200,7 +200,7 @@ namespace Disco.Services.Plugins.CommunityInterop
|
||||
}
|
||||
}
|
||||
|
||||
public override void InitalizeScheduledTask(DiscoDataContext dbContext)
|
||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||
{
|
||||
// Random time between midday and midnight.
|
||||
var rnd = new Random();
|
||||
|
||||
@@ -13,6 +13,6 @@ namespace Disco.Services.Plugins.Features.CertificateProvider
|
||||
{
|
||||
// Certificate Plugin Requirements
|
||||
public abstract string CertificateProviderId { get; }
|
||||
public abstract Tuple<DeviceCertificate, List<string>> AllocateCertificate(DiscoDataContext dbContext, Device Device);
|
||||
public abstract Tuple<DeviceCertificate, List<string>> AllocateCertificate(DiscoDataContext Database, Device Device);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ namespace Disco.Services.Plugins.Features.WarrantyProvider
|
||||
// Warranty Plugin Requirements
|
||||
public abstract string WarrantyProviderId { get; }
|
||||
public abstract Type SubmitJobViewType { get; }
|
||||
public abstract dynamic SubmitJobViewModel(DiscoDataContext dbContext, Controller controller, Job Job, OrganisationAddress Address, User TechUser);
|
||||
public abstract Dictionary<string, string> SubmitJobParseProperties(DiscoDataContext dbContext, FormCollection form, Controller controller, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription);
|
||||
public abstract Dictionary<string, string> SubmitJobDiscloseInfo(DiscoDataContext dbContext, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription, Dictionary<string, string> WarrantyProviderProperties);
|
||||
public abstract string SubmitJob(DiscoDataContext dbContext, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription, Dictionary<string, string> WarrantyProviderProperties);
|
||||
public abstract dynamic SubmitJobViewModel(DiscoDataContext Database, Controller controller, Job Job, OrganisationAddress Address, User TechUser);
|
||||
public abstract Dictionary<string, string> SubmitJobParseProperties(DiscoDataContext Database, FormCollection form, Controller controller, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription);
|
||||
public abstract Dictionary<string, string> SubmitJobDiscloseInfo(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription, Dictionary<string, string> WarrantyProviderProperties);
|
||||
public abstract string SubmitJob(DiscoDataContext Database, Job Job, OrganisationAddress Address, User TechUser, string FaultDescription, Dictionary<string, string> WarrantyProviderProperties);
|
||||
|
||||
public abstract Type JobDetailsViewType { get; }
|
||||
public bool JobDetailsSupported { get { return this.JobDetailsViewType != null; } }
|
||||
public abstract dynamic JobDetailsViewModel(DiscoDataContext dbContext, Controller controller, Job Job);
|
||||
public abstract dynamic JobDetailsViewModel(DiscoDataContext Database, Controller controller, Job Job);
|
||||
|
||||
public static PluginFeatureManifest FindPluginFeature(string PluginIdOrWarrantyProviderId)
|
||||
{
|
||||
|
||||
@@ -95,12 +95,12 @@ namespace Disco.Services.Plugins
|
||||
if (Plugins.GetPlugins().FirstOrDefault(p => p.Id == packageManifest.Id) != null)
|
||||
throw new InvalidOperationException(string.Format("The '{0} [{1}]' Plugin is already installed, please uninstall any existing versions before trying again", packageManifest.Name, packageManifest.Id));
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
string packagePath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
string packagePath = Path.Combine(database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
|
||||
// Check for Compatibility
|
||||
var compatibilityData = Plugins.LoadCompatibilityData(dbContext);
|
||||
var compatibilityData = Plugins.LoadCompatibilityData(database);
|
||||
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.InvariantCultureIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
|
||||
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
|
||||
@@ -144,11 +144,11 @@ namespace Disco.Services.Plugins
|
||||
|
||||
// Install Plugin
|
||||
this.Status.UpdateStatus(80, "Initial Package Configuration");
|
||||
packageManifest.InstallPlugin(dbContext, this.Status);
|
||||
packageManifest.InstallPlugin(database, this.Status);
|
||||
|
||||
// Initialize Plugin
|
||||
this.Status.UpdateStatus(98, "Initializing Plugin for Use");
|
||||
packageManifest.InitializePlugin(dbContext);
|
||||
packageManifest.InitializePlugin(database);
|
||||
|
||||
// Add Plugin Manifest to Host Environment
|
||||
Plugins.AddPlugin(packageManifest);
|
||||
|
||||
@@ -14,10 +14,10 @@ namespace Disco.Services.Plugins
|
||||
|
||||
#region Lifecycle
|
||||
// Events/Triggers for Custom Plugin Initialization (Optional)
|
||||
public virtual void Install(DiscoDataContext dbContext, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void Initialize(DiscoDataContext dbContext) { return; }
|
||||
public virtual void Uninstall(DiscoDataContext dbContext, bool UninstallData, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void AfterUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest) { return; }
|
||||
public virtual void Install(DiscoDataContext Database, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void Initialize(DiscoDataContext Database) { return; }
|
||||
public virtual void Uninstall(DiscoDataContext Database, bool UninstallData, ScheduledTaskStatus Status) { return; }
|
||||
public virtual void AfterUpdate(DiscoDataContext Database, PluginManifest PreviousManifest) { return; }
|
||||
#endregion
|
||||
|
||||
public virtual void Dispose()
|
||||
|
||||
@@ -12,8 +12,8 @@ namespace Disco.Services.Plugins
|
||||
{
|
||||
public PluginManifest Manifest { get; set; }
|
||||
|
||||
public abstract PluginConfigurationHandlerGetResponse Get(DiscoDataContext dbContext, Controller controller);
|
||||
public abstract bool Post(DiscoDataContext dbContext, FormCollection form, Controller controller);
|
||||
public abstract PluginConfigurationHandlerGetResponse Get(DiscoDataContext Database, Controller controller);
|
||||
public abstract bool Post(DiscoDataContext Database, FormCollection form, Controller controller);
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Disco.Services.Plugins
|
||||
public PluginFeatureManifest Manifest {get; internal set;}
|
||||
|
||||
// Allow Custom Initialization (Optional)
|
||||
public virtual void Initialize(DiscoDataContext dbContext) { return; }
|
||||
public virtual void Initialize(DiscoDataContext Database) { return; }
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Disco.Services.Plugins
|
||||
[JsonIgnore]
|
||||
public Type CategoryType { get; private set; }
|
||||
|
||||
internal bool Initialize(DiscoDataContext dbContext, PluginManifest pluginManifest)
|
||||
internal bool Initialize(DiscoDataContext Database, PluginManifest pluginManifest)
|
||||
{
|
||||
this.PluginManifest = pluginManifest;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Disco.Services.Plugins
|
||||
|
||||
using (var instance = this.CreateInstance())
|
||||
{
|
||||
instance.Initialize(dbContext);
|
||||
instance.Initialize(Database);
|
||||
}
|
||||
|
||||
PluginsLog.LogInitializedPluginFeature(this.PluginManifest, this);
|
||||
|
||||
@@ -284,7 +284,7 @@ namespace Disco.Services.Plugins
|
||||
{
|
||||
return JsonConvert.SerializeObject(this, Formatting.Indented, new VersionConverter());
|
||||
}
|
||||
private bool InitializePluginEnvironment(DiscoDataContext dbContext)
|
||||
private bool InitializePluginEnvironment(DiscoDataContext Database)
|
||||
{
|
||||
if (!environmentInitalized)
|
||||
{
|
||||
@@ -316,58 +316,58 @@ namespace Disco.Services.Plugins
|
||||
this.WebHandlerType = this.PluginAssembly.GetType(this.WebHandlerTypeName, true, true);
|
||||
|
||||
// Update non-static values
|
||||
this.StorageLocation = Path.Combine(dbContext.DiscoConfiguration.PluginStorageLocation, this.Id);
|
||||
this.StorageLocation = Path.Combine(Database.DiscoConfiguration.PluginStorageLocation, this.Id);
|
||||
|
||||
environmentInitalized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool AfterPluginUpdate(DiscoDataContext dbContext, PluginManifest PreviousManifest)
|
||||
internal bool AfterPluginUpdate(DiscoDataContext Database, PluginManifest PreviousManifest)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
InitializePluginEnvironment(Database);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.AfterUpdate(dbContext, PreviousManifest);
|
||||
pluginInstance.AfterUpdate(Database, PreviousManifest);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool UninstallPlugin(DiscoDataContext dbContext, bool UninstallData, ScheduledTaskStatus Status)
|
||||
internal bool UninstallPlugin(DiscoDataContext Database, bool UninstallData, ScheduledTaskStatus Status)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
InitializePluginEnvironment(Database);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Uninstall(dbContext, UninstallData, Status);
|
||||
pluginInstance.Uninstall(Database, UninstallData, Status);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool InstallPlugin(DiscoDataContext dbContext, ScheduledTaskStatus Status)
|
||||
internal bool InstallPlugin(DiscoDataContext Database, ScheduledTaskStatus Status)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
InitializePluginEnvironment(Database);
|
||||
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Install(dbContext, Status);
|
||||
pluginInstance.Install(Database, Status);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool InitializePlugin(DiscoDataContext dbContext)
|
||||
internal bool InitializePlugin(DiscoDataContext Database)
|
||||
{
|
||||
// Initialize Plugin
|
||||
InitializePluginEnvironment(dbContext);
|
||||
InitializePluginEnvironment(Database);
|
||||
|
||||
// Initialize Plugin
|
||||
using (var pluginInstance = this.CreateInstance())
|
||||
{
|
||||
pluginInstance.Initialize(dbContext);
|
||||
pluginInstance.Initialize(Database);
|
||||
}
|
||||
PluginsLog.LogInitializedPlugin(this);
|
||||
|
||||
@@ -376,7 +376,7 @@ namespace Disco.Services.Plugins
|
||||
{
|
||||
foreach (var feature in Features)
|
||||
{
|
||||
feature.Initialize(dbContext, this);
|
||||
feature.Initialize(Database, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -250,18 +250,18 @@ namespace Disco.Services.Plugins
|
||||
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
|
||||
}
|
||||
|
||||
public static string CatalogueFile(DiscoDataContext dbContext)
|
||||
public static string CatalogueFile(DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(dbContext.DiscoConfiguration.PluginPackagesLocation, "Catalogue.json");
|
||||
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Catalogue.json");
|
||||
}
|
||||
public static string CompatibilityFile(DiscoDataContext dbContext)
|
||||
public static string CompatibilityFile(DiscoDataContext Database)
|
||||
{
|
||||
return Path.Combine(dbContext.DiscoConfiguration.PluginPackagesLocation, "Compatibility.json");
|
||||
return Path.Combine(Database.DiscoConfiguration.PluginPackagesLocation, "Compatibility.json");
|
||||
}
|
||||
|
||||
public static PluginLibraryUpdateResponse LoadCatalogue(DiscoDataContext dbContext)
|
||||
public static PluginLibraryUpdateResponse LoadCatalogue(DiscoDataContext Database)
|
||||
{
|
||||
var catalogueFile = CatalogueFile(dbContext);
|
||||
var catalogueFile = CatalogueFile(Database);
|
||||
|
||||
if (!File.Exists(catalogueFile))
|
||||
return null;
|
||||
@@ -269,13 +269,13 @@ namespace Disco.Services.Plugins
|
||||
return JsonConvert.DeserializeObject<PluginLibraryUpdateResponse>(File.ReadAllText(catalogueFile));
|
||||
}
|
||||
|
||||
public static PluginLibraryCompatibilityResponse LoadCompatibilityData(DiscoDataContext dbContext)
|
||||
public static PluginLibraryCompatibilityResponse LoadCompatibilityData(DiscoDataContext Database)
|
||||
{
|
||||
var pluginAssembly = typeof(Plugins).Assembly;
|
||||
Version hostVersion = pluginAssembly.GetName().Version;
|
||||
PluginLibraryCompatibilityResponse Data = null;
|
||||
var localCompatFile = Path.Combine(Path.GetDirectoryName(pluginAssembly.Location), "ReleasePluginCompatibility.json");
|
||||
var serverCompatFile = CompatibilityFile(dbContext);
|
||||
var serverCompatFile = CompatibilityFile(Database);
|
||||
|
||||
if (File.Exists(localCompatFile))
|
||||
{
|
||||
@@ -325,7 +325,7 @@ namespace Disco.Services.Plugins
|
||||
return Data;
|
||||
}
|
||||
|
||||
public static void InitalizePlugins(DiscoDataContext dbContext)
|
||||
public static void InitalizePlugins(DiscoDataContext Database)
|
||||
{
|
||||
if (_PluginManifests == null)
|
||||
{
|
||||
@@ -334,10 +334,10 @@ namespace Disco.Services.Plugins
|
||||
if (_PluginManifests == null)
|
||||
{
|
||||
Version hostVersion = typeof(Plugins).Assembly.GetName().Version;
|
||||
var compatibilityData = new Lazy<PluginLibraryCompatibilityResponse>(() => LoadCompatibilityData(dbContext));
|
||||
var compatibilityData = new Lazy<PluginLibraryCompatibilityResponse>(() => LoadCompatibilityData(Database));
|
||||
Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>();
|
||||
|
||||
PluginPath = dbContext.DiscoConfiguration.PluginsLocation;
|
||||
PluginPath = Database.DiscoConfiguration.PluginsLocation;
|
||||
|
||||
AppDomain appDomain = AppDomain.CurrentDomain;
|
||||
|
||||
@@ -367,7 +367,7 @@ namespace Disco.Services.Plugins
|
||||
if (File.Exists(updatePackagePath))
|
||||
{
|
||||
// Update Plugin
|
||||
pluginManifest = UpdatePlugin(dbContext, pluginManifest, updatePackagePath, compatibilityData.Value);
|
||||
pluginManifest = UpdatePlugin(Database, pluginManifest, updatePackagePath, compatibilityData.Value);
|
||||
}
|
||||
|
||||
if (pluginManifest != null)
|
||||
@@ -382,7 +382,7 @@ namespace Disco.Services.Plugins
|
||||
if (pluginManifest.HostVersionMax != null && pluginManifest.HostVersionMax < hostVersion)
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Support expired as of v{2})", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMax.ToString()));
|
||||
|
||||
pluginManifest.InitializePlugin(dbContext);
|
||||
pluginManifest.InitializePlugin(Database);
|
||||
loadedPlugins[pluginManifest.Id] = pluginManifest;
|
||||
}
|
||||
}
|
||||
@@ -414,7 +414,7 @@ namespace Disco.Services.Plugins
|
||||
|
||||
// Check for Data Removal
|
||||
bool DataUninstalled = false;
|
||||
string pluginStorageLocation = Path.Combine(dbContext.DiscoConfiguration.PluginStorageLocation, uninstallManifest.Id);
|
||||
string pluginStorageLocation = Path.Combine(Database.DiscoConfiguration.PluginStorageLocation, uninstallManifest.Id);
|
||||
|
||||
string pluginManifestUninstallDataFilename = Path.Combine(pluginStorageLocation, "manifest.uninstall.json");
|
||||
if (File.Exists(pluginManifestUninstallDataFilename))
|
||||
@@ -443,13 +443,13 @@ namespace Disco.Services.Plugins
|
||||
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
|
||||
}
|
||||
|
||||
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryCompatibilityResponse CompatibilityData = null)
|
||||
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryCompatibilityResponse CompatibilityData = null)
|
||||
{
|
||||
PluginManifest updatedManifest;
|
||||
|
||||
using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath))
|
||||
{
|
||||
updatedManifest = UpdatePlugin(dbContext, ExistingManifest, packageStream, CompatibilityData);
|
||||
updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, CompatibilityData);
|
||||
}
|
||||
|
||||
// Remove Update after processing
|
||||
@@ -458,7 +458,7 @@ namespace Disco.Services.Plugins
|
||||
return updatedManifest;
|
||||
}
|
||||
|
||||
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryCompatibilityResponse CompatibilityData = null)
|
||||
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryCompatibilityResponse CompatibilityData = null)
|
||||
{
|
||||
using (MemoryStream packageStream = new MemoryStream())
|
||||
{
|
||||
@@ -495,12 +495,12 @@ namespace Disco.Services.Plugins
|
||||
|
||||
// Check Compatibility
|
||||
if (CompatibilityData == null)
|
||||
CompatibilityData = LoadCompatibilityData(dbContext);
|
||||
CompatibilityData = LoadCompatibilityData(Database);
|
||||
var pluginCompatibility = CompatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.InvariantCultureIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
|
||||
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
|
||||
|
||||
string packagePath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
string packagePath = Path.Combine(Database.DiscoConfiguration.PluginsLocation, packageManifest.Id);
|
||||
|
||||
// Force Delete of Existing Folder
|
||||
if (Directory.Exists(packagePath))
|
||||
@@ -530,7 +530,7 @@ namespace Disco.Services.Plugins
|
||||
packageManifest = PluginManifest.FromPluginManifestFile(Path.Combine(packagePath, "manifest.json"));
|
||||
|
||||
// Trigger AfterPluginUpdate
|
||||
packageManifest.AfterPluginUpdate(dbContext, ExistingManifest);
|
||||
packageManifest.AfterPluginUpdate(Database, ExistingManifest);
|
||||
|
||||
PluginsLog.LogAfterUpdate(ExistingManifest, packageManifest);
|
||||
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace Disco.Services.Plugins
|
||||
if (!File.Exists(manifestFileLocation))
|
||||
throw new FileNotFoundException("Plugin Manifest File Not Found", manifestFileLocation);
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
manifest.UninstallPlugin(dbContext, UninstallData, this.Status);
|
||||
manifest.UninstallPlugin(database, UninstallData, this.Status);
|
||||
}
|
||||
|
||||
string manifestUninstallFileLocation = Path.Combine(manifest.PluginLocation, "manifest.uninstall.json");
|
||||
|
||||
@@ -32,10 +32,10 @@ namespace Disco.Services.Plugins
|
||||
|
||||
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins;
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
catalogue = Plugins.LoadCatalogue(dbContext);
|
||||
pluginPackagesLocation = dbContext.DiscoConfiguration.PluginPackagesLocation;
|
||||
catalogue = Plugins.LoadCatalogue(database);
|
||||
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(pluginId))
|
||||
@@ -82,10 +82,10 @@ namespace Disco.Services.Plugins
|
||||
Plugins.RestartApp(1500);
|
||||
}
|
||||
|
||||
public static List<PluginManifest> OfflineInstalledPlugins(DiscoDataContext dbContext)
|
||||
public static List<PluginManifest> OfflineInstalledPlugins(DiscoDataContext Database)
|
||||
{
|
||||
string pluginsLocation = dbContext.DiscoConfiguration.PluginsLocation;
|
||||
string pluginsStorageLocation = dbContext.DiscoConfiguration.PluginStorageLocation;
|
||||
string pluginsLocation = Database.DiscoConfiguration.PluginsLocation;
|
||||
string pluginsStorageLocation = Database.DiscoConfiguration.PluginStorageLocation;
|
||||
|
||||
List<PluginManifest> installedPluginManifests = new List<PluginManifest>();
|
||||
|
||||
@@ -121,13 +121,13 @@ namespace Disco.Services.Plugins
|
||||
List<Tuple<PluginManifest, string, PluginLibraryItem>> updatePlugins = new List<Tuple<PluginManifest, string, PluginLibraryItem>>();
|
||||
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
pluginPackagesLocation = dbContext.DiscoConfiguration.PluginPackagesLocation;
|
||||
installedPluginManifests = OfflineInstalledPlugins(dbContext);
|
||||
pluginPackagesLocation = database.DiscoConfiguration.PluginPackagesLocation;
|
||||
installedPluginManifests = OfflineInstalledPlugins(database);
|
||||
|
||||
if (installedPluginManifests.Count > 0)
|
||||
pluginCatalogue = Plugins.LoadCatalogue(dbContext);
|
||||
pluginCatalogue = Plugins.LoadCatalogue(database);
|
||||
}
|
||||
|
||||
if (pluginCatalogue != null && installedPluginManifests.Count > 0)
|
||||
@@ -231,15 +231,15 @@ namespace Disco.Services.Plugins
|
||||
|
||||
Status.UpdateStatus(20, string.Format("{0} [{1} v{2}] by {3}", updateManifest.Name, updateManifest.Id, updateManifest.Version.ToString(4), updateManifest.Author), "Initializing Update Environment");
|
||||
|
||||
using (DiscoDataContext dbContext = new DiscoDataContext())
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
// Check for Compatibility
|
||||
var compatibilityData = Plugins.LoadCompatibilityData(dbContext);
|
||||
var compatibilityData = Plugins.LoadCompatibilityData(database);
|
||||
var pluginCompatibility = compatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(updateManifest.Id, StringComparison.InvariantCultureIgnoreCase) && updateManifest.Version == Version.Parse(i.Version));
|
||||
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
|
||||
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", updateManifest.Id, updateManifest.VersionFormatted, pluginCompatibility.Reason));
|
||||
|
||||
var updatePluginPath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
|
||||
var updatePluginPath = Path.Combine(database.DiscoConfiguration.PluginsLocation, string.Format("{0}.discoPlugin", updateManifest.Id));
|
||||
File.Move(packageTempFilePath, updatePluginPath);
|
||||
|
||||
if (existingManifest != null)
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.2.0725.2249")]
|
||||
[assembly: AssemblyFileVersion("1.2.0725.2249")]
|
||||
[assembly: AssemblyVersion("1.2.1001.1541")]
|
||||
[assembly: AssemblyFileVersion("1.2.1001.1541")]
|
||||
@@ -9,7 +9,7 @@ namespace Disco.Services.Tasks
|
||||
{
|
||||
public abstract class ScheduledTask : IJob
|
||||
{
|
||||
public virtual void InitalizeScheduledTask(DiscoDataContext dbContext) { return; }
|
||||
public virtual void InitalizeScheduledTask(DiscoDataContext Database) { return; }
|
||||
|
||||
internal protected ScheduledTaskStatus Status { get; private set; }
|
||||
internal protected IJobExecutionContext ExecutionContext { get; private set; }
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Disco.Services.Tasks
|
||||
private static object _RunningTasksLock = new object();
|
||||
private static List<ScheduledTaskStatus> _RunningTasks = new List<ScheduledTaskStatus>();
|
||||
|
||||
public static void InitalizeScheduledTasks(DiscoDataContext dbContext, ISchedulerFactory SchedulerFactory, bool InitiallySchedule)
|
||||
public static void InitalizeScheduledTasks(DiscoDataContext database, ISchedulerFactory SchedulerFactory, bool InitiallySchedule)
|
||||
{
|
||||
ScheduledTasksLog.LogInitializingScheduledTasks();
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Disco.Services.Tasks
|
||||
ScheduledTask instance = (ScheduledTask)Activator.CreateInstance(scheduledTaskType);
|
||||
try
|
||||
{
|
||||
instance.InitalizeScheduledTask(dbContext);
|
||||
instance.InitalizeScheduledTask(database);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Services.Users
|
||||
{
|
||||
internal static class Cache
|
||||
{
|
||||
private static ConcurrentDictionary<string, Tuple<User, AuthorizationToken, DateTime>> _Cache = new ConcurrentDictionary<string, Tuple<User, AuthorizationToken, DateTime>>();
|
||||
private const long CacheTimeoutTicks = 6000000000; // 10 Minutes
|
||||
|
||||
internal static AuthorizationToken GetAuthorization(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> record = Get(UserId, Database, ForceRefresh);
|
||||
|
||||
if (record == null)
|
||||
return null;
|
||||
else
|
||||
return record.Item2;
|
||||
}
|
||||
internal static AuthorizationToken GetAuthorization(string UserId, bool ForceRefresh)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> record = Get(UserId, ForceRefresh);
|
||||
|
||||
if (record == null)
|
||||
return null;
|
||||
else
|
||||
return record.Item2;
|
||||
}
|
||||
internal static AuthorizationToken GetAuthorization(string UserId, DiscoDataContext Database)
|
||||
{
|
||||
return GetAuthorization(UserId, Database, false);
|
||||
}
|
||||
internal static AuthorizationToken GetAuthorization(string UserId)
|
||||
{
|
||||
return GetAuthorization(UserId, false);
|
||||
}
|
||||
|
||||
internal static User GetUser(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> record = Get(UserId, Database, ForceRefresh);
|
||||
|
||||
if (record == null)
|
||||
return null;
|
||||
else
|
||||
return record.Item1;
|
||||
}
|
||||
internal static User GetUser(string UserId, bool ForceRefresh)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> record = Get(UserId, ForceRefresh);
|
||||
|
||||
if (record == null)
|
||||
return null;
|
||||
else
|
||||
return record.Item1;
|
||||
}
|
||||
internal static User GetUser(string UserId, DiscoDataContext Database)
|
||||
{
|
||||
return GetUser(UserId, Database, false);
|
||||
}
|
||||
internal static User GetUser(string UserId)
|
||||
{
|
||||
return GetUser(UserId, false);
|
||||
}
|
||||
|
||||
internal static Tuple<User, AuthorizationToken, DateTime> Get(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> record = null;
|
||||
|
||||
// Check Cache
|
||||
if (!ForceRefresh)
|
||||
record = TryUserCache(UserId);
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
var importedUser = UserService.ImportUser(Database, UserId);
|
||||
record = SetValue(UserId, importedUser);
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
internal static Tuple<User, AuthorizationToken, DateTime> Get(string UserId, DiscoDataContext Database)
|
||||
{
|
||||
return Get(UserId, Database, false);
|
||||
}
|
||||
internal static Tuple<User, AuthorizationToken, DateTime> Get(string UserId, bool ForceRefresh)
|
||||
{
|
||||
// Check Cache
|
||||
Tuple<User, AuthorizationToken, DateTime> record = null;
|
||||
|
||||
if (!ForceRefresh)
|
||||
record = TryUserCache(UserId);
|
||||
|
||||
if (record == null)
|
||||
{
|
||||
// Load from Repository
|
||||
using (DiscoDataContext database = new DiscoDataContext())
|
||||
{
|
||||
record = Get(UserId, database, true);
|
||||
}
|
||||
}
|
||||
return record;
|
||||
}
|
||||
internal static Tuple<User, AuthorizationToken, DateTime> Get(string UserId)
|
||||
{
|
||||
return Get(UserId, false);
|
||||
}
|
||||
|
||||
internal static Tuple<User, AuthorizationToken, DateTime> TryUserCache(string UserId)
|
||||
{
|
||||
var cache = _Cache;
|
||||
|
||||
string userId = UserId.ToLower();
|
||||
Tuple<User, AuthorizationToken, DateTime> record;
|
||||
if (cache.TryGetValue(userId, out record))
|
||||
{
|
||||
if (record.Item3 > DateTime.Now)
|
||||
return record;
|
||||
else
|
||||
cache.TryRemove(userId, out record);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static Tuple<User, AuthorizationToken, DateTime> SetValue(string UserId, Tuple<User, AuthorizationToken> Record)
|
||||
{
|
||||
var cache = _Cache;
|
||||
|
||||
string userId = UserId.ToLower();
|
||||
Tuple<User, AuthorizationToken, DateTime> record = new Tuple<User, AuthorizationToken, DateTime>(Record.Item1, Record.Item2, DateTime.Now.AddTicks(CacheTimeoutTicks));
|
||||
if (cache.ContainsKey(userId))
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> oldRecord;
|
||||
if (cache.TryGetValue(userId, out oldRecord))
|
||||
{
|
||||
cache.TryUpdate(userId, record, oldRecord);
|
||||
return record;
|
||||
}
|
||||
}
|
||||
cache.TryAdd(userId, record);
|
||||
return record;
|
||||
}
|
||||
|
||||
internal static bool InvalidateRecord(string UserId)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> userRecord;
|
||||
return _Cache.TryRemove(UserId, out userRecord);
|
||||
}
|
||||
|
||||
internal static void CleanStaleCache()
|
||||
{
|
||||
var cache = _Cache;
|
||||
|
||||
var userIds = cache.Keys.ToArray();
|
||||
foreach (string userId in userIds)
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> record;
|
||||
if (cache.TryGetValue(userId, out record))
|
||||
{
|
||||
if (record.Item3 <= DateTime.Now)
|
||||
cache.TryRemove(userId, out record);
|
||||
}
|
||||
}
|
||||
}
|
||||
internal static void FlushCache()
|
||||
{
|
||||
_Cache = new ConcurrentDictionary<string, Tuple<User, AuthorizationToken, DateTime>>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Services.Tasks;
|
||||
using Quartz;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Services.Users
|
||||
{
|
||||
public class CacheCleanTask : ScheduledTask
|
||||
{
|
||||
public override string TaskName { get { return "User Cache - Clean Stale Cache"; } }
|
||||
|
||||
public override bool SingleInstanceTask { get { return true; } }
|
||||
public override bool CancelInitiallySupported { get { return false; } }
|
||||
public override bool LogExceptionsOnly { get { return true; } }
|
||||
|
||||
public override void InitalizeScheduledTask(DiscoDataContext Database)
|
||||
{
|
||||
// Run @ every 15mins
|
||||
|
||||
// Next 15min interval
|
||||
DateTime now = DateTime.Now;
|
||||
int mins = (15 - (now.Minute % 15));
|
||||
if (mins < 10)
|
||||
mins += 15;
|
||||
DateTimeOffset startAt = new DateTimeOffset(now).AddMinutes(mins).AddSeconds(now.Second * -1).AddMilliseconds(now.Millisecond * -1);
|
||||
|
||||
TriggerBuilder triggerBuilder = TriggerBuilder.Create().StartAt(startAt).
|
||||
WithSchedule(SimpleScheduleBuilder.RepeatMinutelyForever(15));
|
||||
|
||||
this.ScheduleTask(triggerBuilder);
|
||||
}
|
||||
|
||||
protected override void ExecuteTask()
|
||||
{
|
||||
Cache.CleanStaleCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Services.Users
|
||||
{
|
||||
public static class Searching
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
using Disco.Data.Repository;
|
||||
using Disco.Models.Interop.ActiveDirectory;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Authorization.Roles;
|
||||
using Disco.Services.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Entity.Infrastructure;
|
||||
using System.DirectoryServices.ActiveDirectory;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.Services.Users
|
||||
{
|
||||
public static class UserService
|
||||
{
|
||||
private const string _cacheHttpRequestKey = "Disco_CurrentUserToken";
|
||||
private static Func<string, string[], ActiveDirectoryUserAccount> _GetActiveDirectoryUserAccount;
|
||||
private static Func<string, string[], ActiveDirectoryMachineAccount> _GetActiveDirectoryMachineAccount;
|
||||
|
||||
public static void Initialize(DiscoDataContext Database,
|
||||
Func<string, string[], ActiveDirectoryUserAccount> GetActiveDirectoryUserAccount,
|
||||
Func<string, string[], ActiveDirectoryMachineAccount> GetActiveDirectoryMachineAccount)
|
||||
{
|
||||
_GetActiveDirectoryUserAccount = GetActiveDirectoryUserAccount;
|
||||
_GetActiveDirectoryMachineAccount = GetActiveDirectoryMachineAccount;
|
||||
|
||||
Authorization.Roles.RoleCache.Initialize(Database);
|
||||
}
|
||||
|
||||
public static string CurrentUserId
|
||||
{
|
||||
get
|
||||
{
|
||||
// Check for ASP.NET
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
if (HttpContext.Current.Request.IsAuthenticated)
|
||||
return HttpContext.Current.User.Identity.Name;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
// User default User
|
||||
return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
|
||||
}
|
||||
}
|
||||
|
||||
private static Tuple<User, AuthorizationToken, DateTime> CurrentUserToken
|
||||
{
|
||||
get
|
||||
{
|
||||
Tuple<User, AuthorizationToken, DateTime> token = null;
|
||||
|
||||
if (HttpContext.Current != null)
|
||||
{
|
||||
if (HttpContext.Current.Request.IsAuthenticated)
|
||||
token = (Tuple<User, AuthorizationToken, DateTime>)HttpContext.Current.Items[_cacheHttpRequestKey];
|
||||
else
|
||||
return null; // Not Authenticated
|
||||
}
|
||||
|
||||
if (token == null)
|
||||
{
|
||||
var userId = CurrentUserId;
|
||||
|
||||
if (userId != null)
|
||||
{
|
||||
token = Cache.Get(userId);
|
||||
|
||||
if (HttpContext.Current != null && HttpContext.Current.Request.IsAuthenticated)
|
||||
HttpContext.Current.Items[_cacheHttpRequestKey] = token;
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
public static User CurrentUser
|
||||
{
|
||||
get
|
||||
{
|
||||
var token = CurrentUserToken;
|
||||
|
||||
if (token == null)
|
||||
return null;
|
||||
else
|
||||
return token.Item1;
|
||||
}
|
||||
}
|
||||
public static AuthorizationToken CurrentAuthorization
|
||||
{
|
||||
get
|
||||
{
|
||||
var token = CurrentUserToken;
|
||||
|
||||
if (token == null)
|
||||
return null;
|
||||
else
|
||||
return token.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
public static User GetUser(string UserId)
|
||||
{
|
||||
return Cache.GetUser(UserId);
|
||||
}
|
||||
public static User GetUser(string UserId, DiscoDataContext Database)
|
||||
{
|
||||
return Cache.GetUser(UserId, Database);
|
||||
}
|
||||
public static User GetUser(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||
{
|
||||
return Cache.GetUser(UserId, Database, ForceRefresh);
|
||||
}
|
||||
|
||||
public static AuthorizationToken GetAuthorization(string UserId)
|
||||
{
|
||||
return Cache.GetAuthorization(UserId);
|
||||
}
|
||||
public static AuthorizationToken GetAuthorization(string UserId, DiscoDataContext Database)
|
||||
{
|
||||
return Cache.GetAuthorization(UserId, Database);
|
||||
}
|
||||
public static AuthorizationToken GetAuthorization(string UserId, DiscoDataContext Database, bool ForceRefresh)
|
||||
{
|
||||
return Cache.GetAuthorization(UserId, Database, ForceRefresh);
|
||||
}
|
||||
|
||||
public static bool InvalidateCachedUser(string UserId)
|
||||
{
|
||||
return Cache.InvalidateRecord(UserId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static int CreateAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role)
|
||||
{
|
||||
if (Role == null)
|
||||
throw new ArgumentNullException("Role");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Role.ClaimsJson))
|
||||
Role.ClaimsJson = JsonConvert.SerializeObject(new RoleClaims());
|
||||
|
||||
Database.AuthorizationRoles.Add(Role);
|
||||
Database.SaveChanges();
|
||||
|
||||
// Add to Cache
|
||||
RoleCache.AddRole(Role);
|
||||
|
||||
// Flush User Cache
|
||||
Cache.FlushCache();
|
||||
|
||||
return Role.Id;
|
||||
}
|
||||
public static void DeleteAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role)
|
||||
{
|
||||
if (Role == null)
|
||||
throw new ArgumentNullException("Role");
|
||||
|
||||
Database.AuthorizationRoles.Remove(Role);
|
||||
Database.SaveChanges();
|
||||
|
||||
// Remove from Role Cache
|
||||
RoleCache.RemoveRole(Role);
|
||||
|
||||
// Flush User Cache
|
||||
Cache.FlushCache();
|
||||
}
|
||||
public static void UpdateAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role)
|
||||
{
|
||||
if (Role == null)
|
||||
throw new ArgumentNullException("Role");
|
||||
if (Database == null)
|
||||
throw new ArgumentNullException("Database");
|
||||
|
||||
Database.SaveChanges();
|
||||
|
||||
// Update Role Cache
|
||||
RoleCache.UpdateRole(Role);
|
||||
|
||||
// Flush User Cache
|
||||
Cache.FlushCache();
|
||||
}
|
||||
|
||||
internal static Tuple<User, AuthorizationToken> ImportUser(DiscoDataContext Database, string UserId)
|
||||
{
|
||||
if (_GetActiveDirectoryUserAccount == null)
|
||||
throw new InvalidOperationException("UserServer has not been Initialized");
|
||||
if (string.IsNullOrEmpty(UserId))
|
||||
throw new ArgumentNullException("UserId is required", "UserId");
|
||||
|
||||
if (UserId.EndsWith("$"))
|
||||
{
|
||||
// Machine Account
|
||||
var adAccount = _GetActiveDirectoryMachineAccount(UserId, null);
|
||||
|
||||
if (adAccount == null)
|
||||
return null;
|
||||
|
||||
var user = adAccount.ToRepositoryUser();
|
||||
var token = AuthorizationToken.BuildComputerAccountToken(user);
|
||||
|
||||
return new Tuple<User, AuthorizationToken>(user, token);
|
||||
}
|
||||
else
|
||||
{
|
||||
// User Account
|
||||
|
||||
ActiveDirectoryUserAccount adAccount;
|
||||
try
|
||||
{
|
||||
adAccount = _GetActiveDirectoryUserAccount(UserId, null);
|
||||
|
||||
if (adAccount == null)
|
||||
throw new ArgumentException(string.Format("Invalid Username: '{0}'; User doesn't in AD", UserId), "Username");
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
// If "Server is not operational" then Try Cache
|
||||
if (ex.ErrorCode == -2147016646)
|
||||
SystemLog.LogException("Server is not operational; Primary Domain Controller Down?", ex);
|
||||
|
||||
throw ex;
|
||||
}
|
||||
catch (ActiveDirectoryOperationException ex)
|
||||
{
|
||||
// Try From Cache...
|
||||
SystemLog.LogException("Primary Domain Controller Down?", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
var user = adAccount.ToRepositoryUser();
|
||||
|
||||
// Update Repository
|
||||
User existingUser = Database.Users.Find(user.Id);
|
||||
if (existingUser == null)
|
||||
Database.Users.Add(user);
|
||||
else
|
||||
{
|
||||
existingUser.UpdateSelf(user);
|
||||
user = existingUser;
|
||||
}
|
||||
Database.SaveChanges();
|
||||
|
||||
var token = AuthorizationToken.BuildToken(user, adAccount.Groups);
|
||||
|
||||
return new Tuple<User, AuthorizationToken>(user, token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
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.Web
|
||||
{
|
||||
[DiscoAuthorize]
|
||||
public abstract class AuthorizedController : Controller
|
||||
{
|
||||
public AuthorizationToken Authorization
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserService.CurrentAuthorization;
|
||||
}
|
||||
}
|
||||
|
||||
public User CurrentUser
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserService.CurrentUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Users;
|
||||
|
||||
namespace Disco.Services.Web
|
||||
{
|
||||
[DiscoAuthorize]
|
||||
public abstract class AuthorizedDatabaseController : DatabaseController
|
||||
{
|
||||
public AuthorizationToken Authorization
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserService.CurrentAuthorization;
|
||||
}
|
||||
}
|
||||
|
||||
public User CurrentUser
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserService.CurrentUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.Services.Web.Bundles
|
||||
{
|
||||
public class Bundle
|
||||
{
|
||||
private DateTime? _FileLastModified { get; set; }
|
||||
private string _FileHash { get; set; }
|
||||
private string _VersionUrl { get; set; }
|
||||
|
||||
public string Url { get; private set; }
|
||||
public string File { get; private set; }
|
||||
public string FileHash
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
UpdateFileHash();
|
||||
#endif
|
||||
return _FileHash;
|
||||
}
|
||||
}
|
||||
public string ContentType { get; private set; }
|
||||
public string VersionUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
return string.Format("{0}?v={1}", this.Url, this.FileHash);
|
||||
#else
|
||||
return _VersionUrl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public Bundle(string Url, string File)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Url))
|
||||
throw new ArgumentNullException("Url");
|
||||
if (string.IsNullOrWhiteSpace(File))
|
||||
throw new ArgumentNullException("File");
|
||||
|
||||
Uri fileUri;
|
||||
if (!Uri.TryCreate(File, UriKind.Absolute, out fileUri))
|
||||
{
|
||||
File = HttpContext.Current.Server.MapPath(File);
|
||||
}
|
||||
|
||||
var fileInfo = new FileInfo(File);
|
||||
|
||||
if (!fileInfo.Exists)
|
||||
throw new FileNotFoundException(string.Format("Not Found: {0}", File), File);
|
||||
|
||||
this.Url = Url;
|
||||
this.File = File;
|
||||
|
||||
switch (fileInfo.Extension.ToLower())
|
||||
{
|
||||
case ".css":
|
||||
this.ContentType = "text/css";
|
||||
break;
|
||||
case ".js":
|
||||
this.ContentType = "text/javascript";
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unsupported Bundle File Extension");
|
||||
}
|
||||
|
||||
// Write File Hash
|
||||
if (fileInfo.Length > 0)
|
||||
UpdateFileHash();
|
||||
else
|
||||
this._FileHash = string.Empty;
|
||||
|
||||
//this.Version = fileInfo.LastWriteTimeUtc.Ticks;
|
||||
|
||||
this._VersionUrl = string.Format("{0}?v={1}", this.Url, this.FileHash);
|
||||
}
|
||||
|
||||
private void UpdateFileHash()
|
||||
{
|
||||
if (System.IO.File.Exists(this.File))
|
||||
{
|
||||
var fileLastModified = System.IO.File.GetLastWriteTimeUtc(this.File);
|
||||
if (!this._FileLastModified.HasValue || this._FileLastModified.Value != fileLastModified)
|
||||
{
|
||||
this._FileLastModified = fileLastModified;
|
||||
var fileBytes = System.IO.File.ReadAllBytes(this.File);
|
||||
if (fileBytes.Length > 0)
|
||||
{
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
byte[] hash = sha.ComputeHash(fileBytes);
|
||||
this._FileHash = HttpServerUtility.UrlTokenEncode(hash);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Already Updated
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._FileHash = string.Empty;
|
||||
}
|
||||
|
||||
internal void ProcessRequest(HttpContext context)
|
||||
{
|
||||
// Write Content Type
|
||||
context.Response.ContentType = this.ContentType;
|
||||
|
||||
// Write Headers
|
||||
var cache = context.Response.Cache;
|
||||
cache.SetOmitVaryStar(true);
|
||||
cache.SetExpires(DateTime.Now.AddYears(1));
|
||||
cache.SetValidUntilExpires(true);
|
||||
cache.SetMaxAge(TimeSpan.FromDays(365));
|
||||
cache.SetCacheability(HttpCacheability.Public);
|
||||
|
||||
// Write File
|
||||
context.Response.WriteFile(this.File);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using Disco.Services.Web.Bundles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Disco.Services.Web
|
||||
{
|
||||
public static class BundleExtensions
|
||||
{
|
||||
public static void BundleDeferred(this HtmlHelper htmlHelper, string BundleUrl)
|
||||
{
|
||||
// Ensure 'App-Relative' Url:
|
||||
BundleUrl = BundleUrl.StartsWith("~/") ? BundleUrl : (BundleUrl.StartsWith("/") ? string.Concat("~", BundleUrl) : string.Concat("~/", BundleUrl));
|
||||
|
||||
var deferredBundles = htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] as List<string>;
|
||||
if (deferredBundles == null)
|
||||
{
|
||||
deferredBundles = new List<string>();
|
||||
htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] = deferredBundles;
|
||||
}
|
||||
if (!deferredBundles.Contains(BundleUrl))
|
||||
deferredBundles.Add(BundleUrl);
|
||||
}
|
||||
public static HtmlString BundleRenderDeferred(this HtmlHelper htmlHelper)
|
||||
{
|
||||
var deferredBundles = htmlHelper.ViewContext.HttpContext.Items["Bundles.Deferred"] as List<string>;
|
||||
|
||||
var uiExtensionScripts = htmlHelper.ViewContext.HttpContext.Items["Bundles.UIExtensionScripts"] as List<HtmlString>;
|
||||
var uiExtensionCss = htmlHelper.ViewContext.HttpContext.Items["Bundles.UIExtensionCss"] as List<HtmlString>;
|
||||
|
||||
if (deferredBundles != null || uiExtensionScripts != null || uiExtensionCss != null)
|
||||
{
|
||||
StringBuilder bundleUrls = new StringBuilder();
|
||||
|
||||
if (deferredBundles != null)
|
||||
{
|
||||
deferredBundles.Reverse();
|
||||
foreach (string bundleUrl in deferredBundles)
|
||||
{
|
||||
bundleUrls.AppendLine(BundleTable.ResolveBundleHtmlElement(bundleUrl));
|
||||
}
|
||||
}
|
||||
if (uiExtensionCss != null)
|
||||
{
|
||||
foreach (HtmlString extensionUrl in uiExtensionCss)
|
||||
bundleUrls.Append("<link href=\"").Append(extensionUrl).AppendLine("\" rel=\"stylesheet\" type=\"text/css\" />");
|
||||
}
|
||||
if (uiExtensionScripts != null)
|
||||
{
|
||||
foreach (HtmlString extensionUrl in uiExtensionScripts)
|
||||
bundleUrls.Append("<script src=\"").Append(extensionUrl).AppendLine("\" type=\"text/javascript\"></script>");
|
||||
}
|
||||
|
||||
return new HtmlString(bundleUrls.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return new HtmlString(string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.Services.Web.Bundles
|
||||
{
|
||||
internal sealed class BundleHandler : IHttpHandler
|
||||
{
|
||||
public Bundle RequestBundle { get; private set; }
|
||||
public string BundleVirtualPath { get; private set; }
|
||||
|
||||
public BundleHandler(Bundle requestBundle, string bundleVirtualPath)
|
||||
{
|
||||
this.RequestBundle = requestBundle;
|
||||
this.BundleVirtualPath = bundleVirtualPath;
|
||||
}
|
||||
|
||||
public bool IsReusable
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void ProcessRequest(HttpContext context)
|
||||
{
|
||||
context.Response.Clear();
|
||||
|
||||
if (!string.IsNullOrEmpty(context.Request.Headers["If-Modified-Since"]))
|
||||
context.Response.StatusCode = 304;
|
||||
else
|
||||
this.RequestBundle.ProcessRequest(context);
|
||||
}
|
||||
|
||||
internal static bool RemapHandlerForBundleRequests(HttpApplication app)
|
||||
{
|
||||
var context = app.Context;
|
||||
|
||||
string bundleUrlFromContext = context.Request.AppRelativeCurrentExecutionFilePath + context.Request.PathInfo;
|
||||
var bundle = BundleTable.GetBundleFor(bundleUrlFromContext);
|
||||
|
||||
if (bundle != null)
|
||||
{
|
||||
context.RemapHandler(new BundleHandler(bundle, bundleUrlFromContext));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Disco.Services.Web.Bundles.BundleModule), "PreApplicationStart")]
|
||||
|
||||
namespace Disco.Services.Web.Bundles
|
||||
{
|
||||
public class BundleModule : IHttpModule
|
||||
{
|
||||
public void Init(HttpApplication context)
|
||||
{
|
||||
context.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
|
||||
}
|
||||
|
||||
private void OnApplicationPostResolveRequestCache(object sender, EventArgs e)
|
||||
{
|
||||
HttpApplication app = (HttpApplication)sender;
|
||||
if (BundleTable.Count > 0)
|
||||
{
|
||||
BundleHandler.RemapHandlerForBundleRequests(app);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _startWasCalled;
|
||||
public static void PreApplicationStart()
|
||||
{
|
||||
if (!_startWasCalled)
|
||||
{
|
||||
_startWasCalled = true;
|
||||
DynamicModuleUtility.RegisterModule(typeof(BundleModule));
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Dispose Nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Disco.Services.Web.Bundles
|
||||
{
|
||||
public static class BundleTable
|
||||
{
|
||||
private static Dictionary<string, Bundle> _bundles;
|
||||
|
||||
static BundleTable()
|
||||
{
|
||||
_bundles = new Dictionary<string, Bundle>();
|
||||
}
|
||||
|
||||
public static void Add(Bundle Bundle)
|
||||
{
|
||||
_bundles[Bundle.Url] = Bundle;
|
||||
}
|
||||
|
||||
public static int Count
|
||||
{
|
||||
get
|
||||
{
|
||||
return _bundles.Count;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Bundle GetBundleFor(string Url)
|
||||
{
|
||||
if (_bundles.ContainsKey(Url))
|
||||
{
|
||||
return _bundles[Url];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string ResolveBundleUrl(string BundleUrl)
|
||||
{
|
||||
var bundle = GetBundleFor(BundleUrl);
|
||||
|
||||
if (bundle == null)
|
||||
throw new ArgumentException(string.Format("Unknown Bundle Url: {0}", BundleUrl), "BundleUrl");
|
||||
|
||||
return VirtualPathUtility.ToAbsolute(bundle.VersionUrl);
|
||||
}
|
||||
public static string ResolveBundleHtmlElement(string BundleUrl)
|
||||
{
|
||||
var bundle = GetBundleFor(BundleUrl);
|
||||
|
||||
if (bundle == null)
|
||||
throw new ArgumentException(string.Format("Unknown Bundle Url: {0}", BundleUrl), "BundleUrl");
|
||||
|
||||
var bundleUrl = VirtualPathUtility.ToAbsolute(bundle.VersionUrl);
|
||||
|
||||
switch (bundle.ContentType)
|
||||
{
|
||||
case "text/css":
|
||||
return string.Format("<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\" />", bundleUrl);
|
||||
case "text/javascript":
|
||||
return string.Format("<script src=\"{0}\" type=\"text/javascript\"></script>", bundleUrl);
|
||||
default:
|
||||
throw new ArgumentException("Unsupported Bundle Content Type", "BundleUrl");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Disco.Data.Repository;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace Disco.Services.Web
|
||||
{
|
||||
[OutputCache(Duration = 0, Location = System.Web.UI.OutputCacheLocation.None)]
|
||||
public abstract class DatabaseController : Controller
|
||||
{
|
||||
protected DiscoDataContext Database;
|
||||
|
||||
protected override void OnActionExecuting(ActionExecutingContext filterContext)
|
||||
{
|
||||
this.Database = new DiscoDataContext();
|
||||
this.Database.Configuration.LazyLoadingEnabled = false;
|
||||
|
||||
base.OnActionExecuting(filterContext);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (this.Database != null)
|
||||
{
|
||||
this.Database.Dispose();
|
||||
this.Database = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Disco.Models.Repository;
|
||||
using Disco.Services.Authorization;
|
||||
using Disco.Services.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Disco.Services.Web
|
||||
{
|
||||
public abstract class WebViewPage<T> : System.Web.Mvc.WebViewPage<T>
|
||||
{
|
||||
|
||||
public AuthorizationToken Authorization
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserService.CurrentAuthorization;
|
||||
}
|
||||
}
|
||||
|
||||
public User CurrentUser
|
||||
{
|
||||
get
|
||||
{
|
||||
return UserService.CurrentUser;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user