Permissions & Authorization for Users #24
Initial Release; Includes Database and MVC refactoring
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#>
|
||||
Reference in New Issue
Block a user