Files
Disco/Disco.Services/Authorization/Claims.tt
T
Gary Sharp 7748f15d76 Update: Auth Claims Refinement, Job Creation
Auth Claims for Job Creation types, user details.
2014-02-04 17:41:00 +11:00

410 lines
13 KiB
Plaintext

<#@ 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.Services.Authorization;
using Disco.Models.Repository;
using Disco.Services.Authorization.Roles;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Disco.Services.Authorization
{
public static class Claims
{
private static Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>> _roleClaims;
private static ClaimNavigatorItem _claimNavigator;
static Claims()
{
#region Role Claim Dictionary
_roleClaims = new Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>>()
{
<#WriteAccessHashes(permissionRoot);#>
};
#endregion
#region Role Claim Navigator
_claimNavigator =
<#WriteNavigator(permissionRoot);#>;
#endregion
}
public static ClaimNavigatorItem RoleClaimNavigator
{
get { return _claimNavigator; }
}
internal static Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> GetClaimDefinition(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> claimDef;
if (!_roleClaims.TryGetValue(ClaimKey, out claimDef))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(claimDef.Item1, claimDef.Item2, claimDef.Item3, claimDef.Item4, claimDef.Item5);
}
public static Func<RoleClaims, bool> GetClaimAccessor(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> claimDef;
if (!_roleClaims.TryGetValue(ClaimKey, out claimDef))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return claimDef.Item1;
}
public static Action<RoleClaims, bool> GetClaimSetter(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> claimDef;
if (!_roleClaims.TryGetValue(ClaimKey, out claimDef))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return claimDef.Item2;
}
public static Tuple<string, string, bool> GetClaimDetails(string ClaimKey) {
Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> claimDef;
if (!_roleClaims.TryGetValue(ClaimKey, out claimDef))
throw new ArgumentException("Unknown Claim Key", "ClaimKey");
return new Tuple<string, string, bool>(claimDef.Item3, claimDef.Item4, claimDef.Item5);
}
public static RoleClaims BuildClaims(IEnumerable<string> ClaimKeys){
var c = new RoleClaims();
foreach (var claimKey in ClaimKeys)
c.Set(claimKey, true);
return c;
}
public static List<string> GetClaimKeys(RoleClaims Claims)
{
var claims = Claims;
return _roleClaims.Where(rc => rc.Value.Item1(claims)).Select(rc => rc.Key).ToList();
}
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)
{
var claimDefinition = Claims.GetClaimDefinition(ClaimKey);
if (!claimDefinition.Item5)
claimDefinition.Item2(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(" ");
var children = p.Children.OrderBy(c => !c.IsGroup).ThenBy(c => c.FriendlyName).ToList();
for (int childIndex = 0; childIndex < children.Count; childIndex++)
{
WriteNavigator_Recurse(children[childIndex], groupPrefix);
if (childIndex < 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, bool>(c => {1}.{2}, (c, v) => {1}.{2} = v, \"{3}\", \"{4}\", {5}) }},", fqn, parents.Peek(), p.Name, p.FriendlyName, p.Description, p.Hidden ? "true" : "false");
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);
}
}
}
}
}
#>