feature: flag permissions

feature: flag permissions
This commit is contained in:
Gary Sharp
2025-07-20 10:45:55 +10:00
parent 7deead494b
commit be7ee4cae8
72 changed files with 5590 additions and 2109 deletions
+7
View File
@@ -197,6 +197,10 @@
<Compile Include="Migrations\202507110430252_DBv27.Designer.cs"> <Compile Include="Migrations\202507110430252_DBv27.Designer.cs">
<DependentUpon>202507110430252_DBv27.cs</DependentUpon> <DependentUpon>202507110430252_DBv27.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Migrations\202507170522576_DBv28.cs" />
<Compile Include="Migrations\202507170522576_DBv28.Designer.cs">
<DependentUpon>202507170522576_DBv28.cs</DependentUpon>
</Compile>
<Compile Include="Migrations\Configuration.cs" /> <Compile Include="Migrations\Configuration.cs" />
<Compile Include="Migrations\DiscoDataMigrator.cs" /> <Compile Include="Migrations\DiscoDataMigrator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
@@ -293,6 +297,9 @@
<EmbeddedResource Include="Migrations\202507110430252_DBv27.resx"> <EmbeddedResource Include="Migrations\202507110430252_DBv27.resx">
<DependentUpon>202507110430252_DBv27.cs</DependentUpon> <DependentUpon>202507110430252_DBv27.cs</DependentUpon>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Migrations\202507170522576_DBv28.resx">
<DependentUpon>202507170522576_DBv28.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+27
View File
@@ -0,0 +1,27 @@
// <auto-generated />
namespace Disco.Data.Migrations
{
using System.Data.Entity.Migrations;
using System.Data.Entity.Migrations.Infrastructure;
using System.Resources;
public sealed partial class DBv28 : IMigrationMetadata
{
private readonly ResourceManager Resources = new ResourceManager(typeof(DBv28));
string IMigrationMetadata.Id
{
get { return "202507170522576_DBv28"; }
}
string IMigrationMetadata.Source
{
get { return null; }
}
string IMigrationMetadata.Target
{
get { return Resources.GetString("Target"); }
}
}
}
@@ -0,0 +1,40 @@
namespace Disco.Data.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class DBv28 : DbMigration
{
public override void Up()
{
AddColumn("dbo.UserFlagAssignments", "RemoveDate", c => c.DateTime());
AddColumn("dbo.UserFlagAssignments", "RemoveUserId", c => c.String(maxLength: 50));
AddColumn("dbo.UserFlags", "Permissions", c => c.String());
AddColumn("dbo.UserFlags", "DefaultRemoveDays", c => c.Int());
AddColumn("dbo.DeviceFlagAssignments", "RemoveDate", c => c.DateTime());
AddColumn("dbo.DeviceFlagAssignments", "RemoveUserId", c => c.String(maxLength: 50));
AddColumn("dbo.DeviceFlags", "Permissions", c => c.String());
AddColumn("dbo.DeviceFlags", "DefaultRemoveDays", c => c.Int());
AddForeignKey("dbo.UserFlagAssignments", "RemoveUserId", "dbo.Users", "Id");
AddForeignKey("dbo.DeviceFlagAssignments", "RemoveUserId", "dbo.Users", "Id");
CreateIndex("dbo.UserFlagAssignments", "RemoveUserId");
CreateIndex("dbo.DeviceFlagAssignments", "RemoveUserId");
}
public override void Down()
{
DropIndex("dbo.DeviceFlagAssignments", new[] { "RemoveUserId" });
DropIndex("dbo.UserFlagAssignments", new[] { "RemoveUserId" });
DropForeignKey("dbo.DeviceFlagAssignments", "RemoveUserId", "dbo.Users");
DropForeignKey("dbo.UserFlagAssignments", "RemoveUserId", "dbo.Users");
DropColumn("dbo.DeviceFlags", "DefaultRemoveDays");
DropColumn("dbo.DeviceFlags", "Permissions");
DropColumn("dbo.DeviceFlagAssignments", "RemoveUserId");
DropColumn("dbo.DeviceFlagAssignments", "RemoveDate");
DropColumn("dbo.UserFlags", "DefaultRemoveDays");
DropColumn("dbo.UserFlags", "Permissions");
DropColumn("dbo.UserFlagAssignments", "RemoveUserId");
DropColumn("dbo.UserFlagAssignments", "RemoveDate");
}
}
}
File diff suppressed because one or more lines are too long
+2
View File
@@ -59,7 +59,9 @@
<Compile Include="Repository\Device\Flag\DeviceFlag.cs" /> <Compile Include="Repository\Device\Flag\DeviceFlag.cs" />
<Compile Include="Repository\Device\Flag\DeviceFlagAssignment.cs" /> <Compile Include="Repository\Device\Flag\DeviceFlagAssignment.cs" />
<Compile Include="Repository\Device\DeviceComment.cs" /> <Compile Include="Repository\Device\DeviceComment.cs" />
<Compile Include="Repository\FlagType.cs" />
<Compile Include="Repository\User\UserComment.cs" /> <Compile Include="Repository\User\UserComment.cs" />
<Compile Include="Repository\FlagPermission.cs" />
<Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportOptions.cs" /> <Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportOptions.cs" />
<Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportRecord.cs" /> <Compile Include="Services\Devices\DeviceFlags\DeviceFlagExportRecord.cs" />
<Compile Include="Services\Documents\DocumentExportOptions.cs" /> <Compile Include="Services\Documents\DocumentExportOptions.cs" />
@@ -1,5 +1,7 @@
using System.Collections.Generic; using Disco.Models.Services.Authorization;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository namespace Disco.Models.Repository
{ {
@@ -27,11 +29,20 @@ namespace Disco.Models.Repository
[DataType(DataType.MultilineText)] [DataType(DataType.MultilineText)]
public string OnUnassignmentExpression { get; set; } public string OnUnassignmentExpression { get; set; }
[Column("Permissions")]
public string PermissionsJson { get; set; }
[NotMapped]
public FlagPermission Permissions
{
get => FlagPermission.FromFlag(this);
set => PermissionsJson = value?.ToJson();
}
public int? DefaultRemoveDays { get; set; }
public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; } public virtual IList<DeviceFlagAssignment> DeviceFlagAssignments { get; set; }
public override string ToString() public override string ToString()
{ => Name;
return Name;
}
} }
} }
@@ -19,26 +19,28 @@ namespace Disco.Models.Repository
public string AddedUserId { get; set; } public string AddedUserId { get; set; }
public DateTime? RemovedDate { get; set; } public DateTime? RemovedDate { get; set; }
public string RemovedUserId { get; set; } public string RemovedUserId { get; set; }
public DateTime? RemoveDate { get; set; }
public string RemoveUserId { get; set; }
public string Comments { get; set; } public string Comments { get; set; }
public string OnAssignmentExpressionResult { get; set; } public string OnAssignmentExpressionResult { get; set; }
public string OnUnassignmentExpressionResult { get; set; } public string OnUnassignmentExpressionResult { get; set; }
[ForeignKey(nameof(DeviceFlagId)), InverseProperty("DeviceFlagAssignments")] [ForeignKey(nameof(DeviceFlagId)), InverseProperty(nameof(Repository.DeviceFlag.DeviceFlagAssignments))]
public virtual DeviceFlag DeviceFlag { get; set; } public virtual DeviceFlag DeviceFlag { get; set; }
[ForeignKey(nameof(DeviceSerialNumber)), InverseProperty("DeviceFlagAssignments")] [ForeignKey(nameof(DeviceSerialNumber)), InverseProperty(nameof(Repository.Device.DeviceFlagAssignments))]
public virtual Device Device { get; set; } public virtual Device Device { get; set; }
[ForeignKey("AddedUserId")] [ForeignKey(nameof(AddedUserId))]
public virtual User AddedUser { get; set; } public virtual User AddedUser { get; set; }
[ForeignKey("RemovedUserId")] [ForeignKey(nameof(RemovedUserId))]
public virtual User RemovedUser { get; set; } public virtual User RemovedUser { get; set; }
[ForeignKey(nameof(RemoveUserId))]
public virtual User RemoveUser { get; set; }
public override string ToString() public override string ToString()
{ => $"Device Flag Id: {DeviceFlagId}; Device Serial Number: {DeviceSerialNumber}; Added: {AddedDate:s}";
return $"Device Flag Id: {DeviceFlagId}; Device Serial Number: {DeviceSerialNumber}; Added: {AddedDate:s}";
}
} }
} }
+121
View File
@@ -0,0 +1,121 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace Disco.Models.Repository
{
public class FlagPermission
{
private static readonly FlagPermission DefaultDeviceFlagPermissions = new FlagPermission(FlagType.Device, 0);
private static readonly FlagPermission DefaultUserFlagPermissions = new FlagPermission(FlagType.User, 0);
[JsonIgnore]
public FlagType FlagType { get; }
[JsonIgnore]
public int FlagId { get; }
public bool Inherit { get; set; }
public HashSet<string> CanShowSubjectIds { get; }
public HashSet<string> CanAssignSubjectIds { get; }
public HashSet<string> CanEditSubjectIds { get; }
public HashSet<string> CanRemoveSubjectIds { get; }
private FlagPermission(FlagType flagType, int flagId)
{
FlagType = flagType;
FlagId = flagId;
Inherit = true;
CanShowSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
CanAssignSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
CanEditSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
CanRemoveSubjectIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
}
public bool IsDefault()
{
return ReferenceEquals(this, DefaultDeviceFlagPermissions) ||
ReferenceEquals(this, DefaultUserFlagPermissions);
}
public bool IsSimple()
{
return CanShowSubjectIds.SetEquals(CanAssignSubjectIds) &&
CanAssignSubjectIds.SetEquals(CanEditSubjectIds) &&
CanEditSubjectIds.SetEquals(CanRemoveSubjectIds);
}
public bool HasSubjects()
{
return CanShowSubjectIds.Count > 0 ||
CanAssignSubjectIds.Count > 0 ||
CanEditSubjectIds.Count > 0 ||
CanRemoveSubjectIds.Count > 0;
}
public HashSet<string> AllSubjects()
{
var allSubjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
allSubjects.UnionWith(CanShowSubjectIds);
allSubjects.UnionWith(CanAssignSubjectIds);
allSubjects.UnionWith(CanEditSubjectIds);
allSubjects.UnionWith(CanRemoveSubjectIds);
return allSubjects;
}
public static FlagPermission FromFlag(UserFlag userFlag)
{
if (userFlag.PermissionsJson == null)
return DefaultUserFlagPermissions;
var permission = new FlagPermission(FlagType.User, userFlag.Id);
JsonConvert.PopulateObject(userFlag.PermissionsJson, permission);
return permission;
}
public static FlagPermission FromFlag(DeviceFlag deviceFlag)
{
if (deviceFlag.PermissionsJson == null)
return DefaultDeviceFlagPermissions;
var permission = new FlagPermission(FlagType.Device, deviceFlag.Id);
JsonConvert.PopulateObject(deviceFlag.PermissionsJson, permission);
return permission;
}
public static FlagPermission Create(UserFlag userFlag, bool inherit, IEnumerable<string> canShow, IEnumerable<string> canAssign, IEnumerable<string> canEdit, IEnumerable<string> canRemove)
{
var permission = new FlagPermission(FlagType.User, userFlag.Id);
return Create(permission, inherit, canShow, canAssign, canEdit, canRemove);
}
public static FlagPermission Create(DeviceFlag deviceFlag, bool inherit, IEnumerable<string> canShow, IEnumerable<string> canAssign, IEnumerable<string> canEdit, IEnumerable<string> canRemove)
{
var permission = new FlagPermission(FlagType.Device, deviceFlag.Id);
return Create(permission, inherit, canShow, canAssign, canEdit, canRemove);
}
private static FlagPermission Create(FlagPermission permission, bool inherit, IEnumerable<string> canShow, IEnumerable<string> canAssign, IEnumerable<string> canEdit, IEnumerable<string> canRemove)
{
permission.Inherit = inherit;
if (canShow != null)
permission.CanShowSubjectIds.UnionWith(canShow);
if (canAssign != null)
permission.CanAssignSubjectIds.UnionWith(canAssign);
if (canEdit != null)
permission.CanEditSubjectIds.UnionWith(canEdit);
if (canRemove != null)
permission.CanRemoveSubjectIds.UnionWith(canRemove);
return permission;
}
public string ToJson()
{
if (IsDefault())
return null;
return JsonConvert.SerializeObject(this);
}
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace Disco.Models.Repository
{
public enum FlagType
{
User = 1,
Device = 2,
}
}
+15 -4
View File
@@ -1,5 +1,7 @@
using System.Collections.Generic; using Disco.Models.Services.Authorization;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Disco.Models.Repository namespace Disco.Models.Repository
{ {
@@ -27,11 +29,20 @@ namespace Disco.Models.Repository
[DataType(DataType.MultilineText)] [DataType(DataType.MultilineText)]
public string OnUnassignmentExpression { get; set; } public string OnUnassignmentExpression { get; set; }
[Column("Permissions")]
public string PermissionsJson { get; set; }
[NotMapped]
public FlagPermission Permissions
{
get => FlagPermission.FromFlag(this);
set => PermissionsJson = value?.ToJson();
}
public int? DefaultRemoveDays { get; set; }
public virtual IList<UserFlagAssignment> UserFlagAssignments { get; set; } public virtual IList<UserFlagAssignment> UserFlagAssignments { get; set; }
public override string ToString() public override string ToString()
{ => Name;
return Name;
}
} }
} }
@@ -19,26 +19,28 @@ namespace Disco.Models.Repository
public string AddedUserId { get; set; } public string AddedUserId { get; set; }
public DateTime? RemovedDate { get; set; } public DateTime? RemovedDate { get; set; }
public string RemovedUserId { get; set; } public string RemovedUserId { get; set; }
public DateTime? RemoveDate { get; set; }
public string RemoveUserId { get; set; }
public string Comments { get; set; } public string Comments { get; set; }
public string OnAssignmentExpressionResult { get; set; } public string OnAssignmentExpressionResult { get; set; }
public string OnUnassignmentExpressionResult { get; set; } public string OnUnassignmentExpressionResult { get; set; }
[ForeignKey("UserFlagId"), InverseProperty("UserFlagAssignments")] [ForeignKey(nameof(UserFlagId)), InverseProperty(nameof(Repository.UserFlag.UserFlagAssignments))]
public virtual UserFlag UserFlag { get; set; } public virtual UserFlag UserFlag { get; set; }
[ForeignKey("UserId"), InverseProperty("UserFlagAssignments")] [ForeignKey(nameof(UserId)), InverseProperty(nameof(Repository.User.UserFlagAssignments))]
public virtual User User { get; set; } public virtual User User { get; set; }
[ForeignKey("AddedUserId")] [ForeignKey(nameof(AddedUserId))]
public virtual User AddedUser { get; set; } public virtual User AddedUser { get; set; }
[ForeignKey("RemovedUserId")] [ForeignKey(nameof(RemovedUserId))]
public virtual User RemovedUser { get; set; } public virtual User RemovedUser { get; set; }
[ForeignKey(nameof(RemoveUserId))]
public virtual User RemoveUser { get; set; }
public override string ToString() public override string ToString()
{ => $"User Flag Id: {UserFlagId}; User Id: {UserId}; Added: {AddedDate:s}";
return $"User Flag Id: {UserFlagId}; User Id: {UserId}; Added: {AddedDate:s}";
}
} }
} }
@@ -1,4 +1,5 @@
using System.Collections.Generic; using Disco.Models.Repository;
using System.Collections.Generic;
namespace Disco.Models.UI.Config.DeviceFlag namespace Disco.Models.UI.Config.DeviceFlag
{ {
@@ -11,5 +12,7 @@ namespace Disco.Models.UI.Config.DeviceFlag
IEnumerable<KeyValuePair<string, string>> Icons { get; set; } IEnumerable<KeyValuePair<string, string>> Icons { get; set; }
IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; } IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; }
FlagPermission Permission { get; set; }
} }
} }
@@ -1,4 +1,5 @@
using System.Collections.Generic; using Disco.Models.Repository;
using System.Collections.Generic;
namespace Disco.Models.UI.Config.UserFlag namespace Disco.Models.UI.Config.UserFlag
{ {
@@ -11,5 +12,7 @@ namespace Disco.Models.UI.Config.UserFlag
IEnumerable<KeyValuePair<string, string>> Icons { get; set; } IEnumerable<KeyValuePair<string, string>> Icons { get; set; }
IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; } IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; }
FlagPermission Permission { get; set; }
} }
} }
+24 -16
View File
@@ -18,7 +18,7 @@ namespace Disco.Services.Authorization
static Claims() static Claims()
{ {
#region Role Claim Dictionary #region Role Claim Dictionary
_roleClaims = new Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>>() _roleClaims = new Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>>()
{ {
{ "Config.DeviceCertificate.DownloadCertificates", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceCertificate.DownloadCertificates, (c, v) => c.Config.DeviceCertificate.DownloadCertificates = v, "Download Certificates", "Can download certificates", false) }, { "Config.DeviceCertificate.DownloadCertificates", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.Config.DeviceCertificate.DownloadCertificates, (c, v) => c.Config.DeviceCertificate.DownloadCertificates = v, "Download Certificates", "Can download certificates", false) },
@@ -242,9 +242,9 @@ namespace Disco.Services.Authorization
{ "ComputerAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.ComputerAccount, (c, v) => c.ComputerAccount = v, "Computer Account", "Represents a computer account", true) }, { "ComputerAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.ComputerAccount, (c, v) => c.ComputerAccount = v, "Computer Account", "Represents a computer account", true) },
{ "DiscoAdminAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.DiscoAdminAccount, (c, v) => c.DiscoAdminAccount = v, "Disco Administrator Account", "Represents a Disco ICT Administrator account", true) } { "DiscoAdminAccount", new Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>(c => c.DiscoAdminAccount, (c, v) => c.DiscoAdminAccount = v, "Disco Administrator Account", "Represents a Disco ICT Administrator account", true) }
}; };
#endregion #endregion
#region Role Claim Navigator #region Role Claim Navigator
_claimNavigator = _claimNavigator =
new ClaimNavigatorItem("Claims", "Permissions", "Top-level node for all permissions", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Claims", "Permissions", "Top-level node for all permissions", false, new List<IClaimNavigatorItem>() {
new ClaimNavigatorItem("Config", "Configuration", "Permissions related to Disco ICT Configuration", false, new List<IClaimNavigatorItem>() { new ClaimNavigatorItem("Config", "Configuration", "Permissions related to Disco ICT Configuration", false, new List<IClaimNavigatorItem>() {
@@ -524,7 +524,7 @@ namespace Disco.Services.Authorization
new ClaimNavigatorItem("ComputerAccount", true), new ClaimNavigatorItem("ComputerAccount", true),
new ClaimNavigatorItem("DiscoAdminAccount", true) new ClaimNavigatorItem("DiscoAdminAccount", true)
}); });
#endregion #endregion
} }
public static ClaimNavigatorItem RoleClaimNavigator public static ClaimNavigatorItem RoleClaimNavigator
@@ -532,31 +532,36 @@ namespace Disco.Services.Authorization
get { return _claimNavigator; } get { return _claimNavigator; }
} }
internal static Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> GetClaimDefinition(string ClaimKey) { internal static Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> GetClaimDefinition(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return claimDef; return claimDef;
throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey)); throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey));
} }
public static Func<RoleClaims, bool> GetClaimAccessor(string ClaimKey) { public static Func<RoleClaims, bool> GetClaimAccessor(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return claimDef.Item1; return claimDef.Item1;
throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey)); throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey));
} }
public static Action<RoleClaims, bool> GetClaimSetter(string ClaimKey) { public static Action<RoleClaims, bool> GetClaimSetter(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return claimDef.Item2; return claimDef.Item2;
throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey)); throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey));
} }
public static Tuple<string, string, bool> GetClaimDetails(string ClaimKey) { public static Tuple<string, string, bool> GetClaimDetails(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return Tuple.Create(claimDef.Item3, claimDef.Item4, claimDef.Item5); return Tuple.Create(claimDef.Item3, claimDef.Item4, claimDef.Item5);
throw new ArgumentException("Unknown Claim Key", "ClaimKey"); throw new ArgumentException("Unknown Claim Key", "ClaimKey");
} }
public static RoleClaims BuildClaims(IEnumerable<string> ClaimKeys){ public static RoleClaims BuildClaims(IEnumerable<string> ClaimKeys)
{
var c = new RoleClaims(); var c = new RoleClaims();
foreach (var claimKey in ClaimKeys) foreach (var claimKey in ClaimKeys)
c.Set(claimKey, true); c.Set(claimKey, true);
@@ -570,9 +575,10 @@ namespace Disco.Services.Authorization
return _roleClaims.Where(rc => rc.Value.Item1(claims)).Select(rc => rc.Key).ToList(); return _roleClaims.Where(rc => rc.Value.Item1(claims)).Select(rc => rc.Key).ToList();
} }
public static RoleClaims AdministratorClaims() { public static RoleClaims AdministratorClaims()
{
var c = new RoleClaims(); var c = new RoleClaims();
#region Set All Administrator Claims #region Set All Administrator Claims
c.Config.DeviceCertificate.DownloadCertificates = true; c.Config.DeviceCertificate.DownloadCertificates = true;
c.Config.Enrolment.Configure = true; c.Config.Enrolment.Configure = true;
c.Config.Enrolment.DownloadBootstrapper = true; c.Config.Enrolment.DownloadBootstrapper = true;
@@ -792,17 +798,19 @@ namespace Disco.Services.Authorization
c.User.ShowFlagAssignments = true; c.User.ShowFlagAssignments = true;
c.User.ShowJobs = true; c.User.ShowJobs = true;
c.DiscoAdminAccount = true; c.DiscoAdminAccount = true;
#endregion #endregion
return c; return c;
} }
public static RoleClaims ComputerAccountClaims() { public static RoleClaims ComputerAccountClaims()
return new RoleClaims() { {
return new RoleClaims()
{
ComputerAccount = true ComputerAccount = true
}; };
} }
#region Role Claim Constants #region Role Claim Constants
/// <summary>Configuration /// <summary>Configuration
/// <para>Permissions related to Disco ICT Configuration</para> /// <para>Permissions related to Disco ICT Configuration</para>
@@ -2099,7 +2107,7 @@ namespace Disco.Services.Authorization
/// <para>Represents a Disco ICT Administrator account</para> /// <para>Represents a Disco ICT Administrator account</para>
/// </summary> /// </summary>
public const string DiscoAdminAccount = "DiscoAdminAccount"; public const string DiscoAdminAccount = "DiscoAdminAccount";
#endregion #endregion
} }
public static class ClaimExtensions public static class ClaimExtensions
{ {
+24 -16
View File
@@ -66,17 +66,17 @@ namespace Disco.Services.Authorization
static Claims() static Claims()
{ {
#region Role Claim Dictionary #region Role Claim Dictionary
_roleClaims = new Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>>() _roleClaims = new Dictionary<string, Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool>>()
{ {
<#WriteAccessHashes(permissionRoot);#> <#WriteAccessHashes(permissionRoot);#>
}; };
#endregion #endregion
#region Role Claim Navigator #region Role Claim Navigator
_claimNavigator = _claimNavigator =
<#WriteNavigator(permissionRoot);#>; <#WriteNavigator(permissionRoot);#>;
#endregion #endregion
} }
public static ClaimNavigatorItem RoleClaimNavigator public static ClaimNavigatorItem RoleClaimNavigator
@@ -84,31 +84,36 @@ namespace Disco.Services.Authorization
get { return _claimNavigator; } get { return _claimNavigator; }
} }
internal static Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> GetClaimDefinition(string ClaimKey) { internal static Tuple<Func<RoleClaims, bool>, Action<RoleClaims, bool>, string, string, bool> GetClaimDefinition(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return claimDef; return claimDef;
throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey)); throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey));
} }
public static Func<RoleClaims, bool> GetClaimAccessor(string ClaimKey) { public static Func<RoleClaims, bool> GetClaimAccessor(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return claimDef.Item1; return claimDef.Item1;
throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey)); throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey));
} }
public static Action<RoleClaims, bool> GetClaimSetter(string ClaimKey) { public static Action<RoleClaims, bool> GetClaimSetter(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return claimDef.Item2; return claimDef.Item2;
throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey)); throw new ArgumentException("Unknown Claim Key", nameof(ClaimKey));
} }
public static Tuple<string, string, bool> GetClaimDetails(string ClaimKey) { public static Tuple<string, string, bool> GetClaimDetails(string ClaimKey)
{
if (_roleClaims.TryGetValue(ClaimKey, out var claimDef)) if (_roleClaims.TryGetValue(ClaimKey, out var claimDef))
return Tuple.Create(claimDef.Item3, claimDef.Item4, claimDef.Item5); return Tuple.Create(claimDef.Item3, claimDef.Item4, claimDef.Item5);
throw new ArgumentException("Unknown Claim Key", "ClaimKey"); throw new ArgumentException("Unknown Claim Key", "ClaimKey");
} }
public static RoleClaims BuildClaims(IEnumerable<string> ClaimKeys){ public static RoleClaims BuildClaims(IEnumerable<string> ClaimKeys)
{
var c = new RoleClaims(); var c = new RoleClaims();
foreach (var claimKey in ClaimKeys) foreach (var claimKey in ClaimKeys)
c.Set(claimKey, true); c.Set(claimKey, true);
@@ -122,23 +127,26 @@ namespace Disco.Services.Authorization
return _roleClaims.Where(rc => rc.Value.Item1(claims)).Select(rc => rc.Key).ToList(); return _roleClaims.Where(rc => rc.Value.Item1(claims)).Select(rc => rc.Key).ToList();
} }
public static RoleClaims AdministratorClaims() { public static RoleClaims AdministratorClaims()
{
var c = new RoleClaims(); var c = new RoleClaims();
#region Set All Administrator Claims #region Set All Administrator Claims
<#WriteAdministratorClaims(permissionRoot);#> <#WriteAdministratorClaims(permissionRoot);#>
#endregion #endregion
return c; return c;
} }
public static RoleClaims ComputerAccountClaims() { public static RoleClaims ComputerAccountClaims()
return new RoleClaims() { {
return new RoleClaims()
{
ComputerAccount = true ComputerAccount = true
}; };
} }
#region Role Claim Constants #region Role Claim Constants
<#WritePermissionConsts(permissionRoot);#> <#WritePermissionConsts(permissionRoot);#>
#endregion #endregion
} }
public static class ClaimExtensions public static class ClaimExtensions
{ {
+44 -58
View File
@@ -4,6 +4,7 @@ using Disco.Models.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -16,41 +17,41 @@ namespace Disco.Services.Authorization.Roles
internal const string ClaimsJsonEmpty = "null"; internal const string ClaimsJsonEmpty = "null";
internal static readonly string[] _RequiredAdministratorSubjectIds = new string[] { "Domain Admins" }; internal static readonly string[] _RequiredAdministratorSubjectIds = new string[] { "Domain Admins" };
private static List<RoleToken> _Cache; private static ConcurrentDictionary<int, RoleToken> cache;
private static RoleToken _AdministratorToken; private static RoleToken _AdministratorToken;
internal static void Initialize(DiscoDataContext Database) internal static void Initialize(DiscoDataContext database)
{ {
MigrateAuthorizationRoles(Database); MigrateAuthorizationRoles(database);
_Cache = Database.AuthorizationRoles.ToList().Select(ar => RoleToken.FromAuthorizationRole(ar)).ToList(); cache = new ConcurrentDictionary<int, RoleToken>(database.AuthorizationRoles.ToList().Select(ar => RoleToken.FromAuthorizationRole(ar)).ToDictionary(r => r.Role.Id));
// Add System Roles // Add System Roles
AddSystemRoles(Database); AddSystemRoles(database);
} }
private static void AddSystemRoles(DiscoDataContext Database) private static void AddSystemRoles(DiscoDataContext database)
{ {
// Disco Administrators // Disco Administrators
_AdministratorToken = RoleToken.FromAuthorizationRole(new AuthorizationRole() _AdministratorToken = RoleToken.FromAuthorizationRole(new AuthorizationRole()
{ {
Id = AdministratorsTokenId, Id = AdministratorsTokenId,
Name = "Disco Administrators", Name = "Disco Administrators",
SubjectIds = string.Join(",", GenerateAdministratorSubjectIds(Database)) SubjectIds = string.Join(",", GenerateAdministratorSubjectIds(database))
}, Claims.AdministratorClaims()); }, Claims.AdministratorClaims());
_Cache.Add(_AdministratorToken); cache.TryAdd(AdministratorsTokenId, _AdministratorToken);
// Computer Accounts // Computer Accounts
_Cache.Add(RoleToken.FromAuthorizationRole(new AuthorizationRole() cache.TryAdd(ComputerAccountTokenId, RoleToken.FromAuthorizationRole(new AuthorizationRole()
{ {
Id = ComputerAccountTokenId, Id = ComputerAccountTokenId,
Name = "Domain Computer Account" Name = "Domain Computer Account"
}, Claims.ComputerAccountClaims())); }, Claims.ComputerAccountClaims()));
} }
private static IEnumerable<string> GenerateAdministratorSubjectIds(DiscoDataContext Database) private static IEnumerable<string> GenerateAdministratorSubjectIds(DiscoDataContext database)
{ {
var configuredSubjectIds = Database.DiscoConfiguration.Administrators.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => ActiveDirectory.ParseDomainAccountId(s)); var configuredSubjectIds = database.DiscoConfiguration.Administrators.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => ActiveDirectory.ParseDomainAccountId(s));
return RequiredAdministratorSubjectIds return RequiredAdministratorSubjectIds
.Concat(configuredSubjectIds) .Concat(configuredSubjectIds)
@@ -58,94 +59,79 @@ namespace Disco.Services.Authorization.Roles
.OrderBy(s => s); .OrderBy(s => s);
} }
public static IEnumerable<string> RequiredAdministratorSubjectIds public static IEnumerable<string> RequiredAdministratorSubjectIds
{ => _RequiredAdministratorSubjectIds.Select(s => ActiveDirectory.ParseDomainAccountId(s));
get
{
return _RequiredAdministratorSubjectIds.Select(s => ActiveDirectory.ParseDomainAccountId(s));
}
}
public static IEnumerable<string> AdministratorSubjectIds public static IEnumerable<string> AdministratorSubjectIds
{ => _AdministratorToken.SubjectIds.ToList();
get
{
return _AdministratorToken.SubjectIds.ToList();
}
}
public static void UpdateAdministratorSubjectIds(DiscoDataContext Database, IEnumerable<string> SubjectIds) public static void UpdateAdministratorSubjectIds(DiscoDataContext database, IEnumerable<string> subjectIds)
{ {
// Clean // Clean
SubjectIds = SubjectIds subjectIds = subjectIds
.Where(s => !string.IsNullOrWhiteSpace(s)) .Where(s => !string.IsNullOrWhiteSpace(s))
.Concat(RequiredAdministratorSubjectIds) .Concat(RequiredAdministratorSubjectIds)
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(s => s); .OrderBy(s => s);
var subjectIdsString = string.Join(",", SubjectIds); var subjectIdsString = string.Join(",", subjectIds);
// Update Database // Update Database
Database.DiscoConfiguration.Administrators = subjectIdsString; database.DiscoConfiguration.Administrators = subjectIdsString;
Database.SaveChanges(); database.SaveChanges();
// Update State // Update State
_AdministratorToken.SubjectIds = SubjectIds.ToList(); _AdministratorToken.SubjectIds = subjectIds.ToList();
_AdministratorToken.SubjectIdHashes = new HashSet<string>(SubjectIds, StringComparer.OrdinalIgnoreCase); _AdministratorToken.SubjectIdHashes = new HashSet<string>(subjectIds, StringComparer.OrdinalIgnoreCase);
} }
/// <summary> /// <summary>
/// Create a clone of an Authorization Role /// Create a clone of an Authorization Role
/// <para>Creates immutable clones to avoid side-effects</para> /// <para>Creates immutable clones to avoid side-effects</para>
/// </summary> /// </summary>
/// <param name="TemplateRole">Authorization Role to Clone</param> /// <param name="templateRole">Authorization Role to Clone</param>
/// <returns>A copy of the Authorization Role</returns> /// <returns>A copy of the Authorization Role</returns>
private static AuthorizationRole CloneAuthoriationRole(AuthorizationRole TemplateRole) private static AuthorizationRole CloneAuthoriationRole(AuthorizationRole templateRole)
{ {
return new AuthorizationRole() return new AuthorizationRole()
{ {
Id = TemplateRole.Id, Id = templateRole.Id,
Name = TemplateRole.Name, Name = templateRole.Name,
ClaimsJson = TemplateRole.ClaimsJson, ClaimsJson = templateRole.ClaimsJson,
SubjectIds = TemplateRole.SubjectIds 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) internal static void RemoveRole(AuthorizationRole Role)
{ {
var token = GetRoleToken(Role.Id); cache.TryRemove(Role.Id, out _);
if (token != null)
_Cache.Remove(token);
} }
internal static RoleToken UpdateRole(AuthorizationRole Role) internal static RoleToken AddOrUpdateRole(AuthorizationRole role)
{ {
RemoveRole(Role); var token = RoleToken.FromAuthorizationRole(CloneAuthoriationRole(role));
return AddRole(Role); cache.AddOrUpdate(token.Role.Id, token, (i, e) => token);
return token;
} }
internal static RoleToken GetRoleToken(int Id) internal static RoleToken GetRoleToken(int id)
{ {
return _Cache.FirstOrDefault(t => t.Role.Id == Id); if (cache.TryGetValue(id, out var result))
return result;
else
return null;
} }
internal static RoleToken GetRoleToken(string SecurityGroup) internal static RoleToken GetRoleToken(string securityGroup)
{ {
return _Cache.FirstOrDefault(t => t.SubjectIdHashes.Contains(SecurityGroup)); return cache.Values.FirstOrDefault(t => t.SubjectIdHashes.Contains(securityGroup));
} }
internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> SecurityGroup) internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> securityGroups)
{ {
return _Cache.Where(t => SecurityGroup.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList(); return cache.Values.Where(t => securityGroups.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList();
} }
internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> SecurityGroup, User User) internal static List<IRoleToken> GetRoleTokens(IEnumerable<string> securityGroups, User user)
{ {
var subjectIds = SecurityGroup.Concat(new string[] { User.UserId }); var subjectIds = securityGroups.Concat(new string[] { user.UserId });
return _Cache.Where(t => subjectIds.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList(); return cache.Values.Where(t => subjectIds.Any(sg => t.SubjectIdHashes.Contains(sg))).Cast<IRoleToken>().ToList();
} }
/// <summary> /// <summary>
+11 -17
View File
@@ -8,7 +8,7 @@ namespace Disco.Services.Devices.DeviceFlags
{ {
internal class Cache internal class Cache
{ {
private ConcurrentDictionary<int, DeviceFlag> _Cache; private ConcurrentDictionary<int, (DeviceFlag, FlagPermission permission)> cache;
public Cache(DiscoDataContext Database) public Cache(DiscoDataContext Database)
{ {
@@ -26,36 +26,30 @@ namespace Disco.Services.Devices.DeviceFlags
var flags = Database.DeviceFlags.ToList(); var flags = Database.DeviceFlags.ToList();
// Add Queues to In-Memory Cache // Add Queues to In-Memory Cache
_Cache = new ConcurrentDictionary<int, DeviceFlag>(flags.Select(f => new KeyValuePair<int, DeviceFlag>(f.Id, f))); cache = new ConcurrentDictionary<int, (DeviceFlag, FlagPermission permission)>(flags.Select(f => new KeyValuePair<int, (DeviceFlag, FlagPermission permission)>(f.Id, (f, f.Permissions))));
} }
public DeviceFlag GetDeviceFlag(int deviceFlagId) public (DeviceFlag flag, FlagPermission permission) GetDeviceFlag(int deviceFlagId)
{ {
if (_Cache.TryGetValue(deviceFlagId, out var item)) if (cache.TryGetValue(deviceFlagId, out var item))
return item; return item;
else else
return null; return (null, null);
} }
public List<DeviceFlag> GetDeviceFlags() public List<(DeviceFlag flag, FlagPermission permission)> GetDeviceFlags()
{ {
return _Cache.Values.ToList(); return cache.Values.ToList();
} }
public void AddOrUpdate(DeviceFlag flag) public void AddOrUpdate(DeviceFlag flag)
{ {
_Cache.AddOrUpdate(flag.Id, flag, (key, existingItem) => flag); var value = (flag, flag.Permissions);
cache.AddOrUpdate(flag.Id, value, (key, existingItem) => value);
} }
public DeviceFlag Remove(int deviceFlagId) public void Remove(int deviceFlagId)
{ {
if (_Cache.TryRemove(deviceFlagId, out var item)) cache.TryRemove(deviceFlagId, out _);
return item;
else
return null;
}
public DeviceFlag Remove(DeviceFlag deviceFlag)
{
return Remove(deviceFlag.Id);
} }
} }
} }
@@ -1,6 +1,7 @@
using Disco.Data.Repository; using Disco.Data.Repository;
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Services.Authorization; using Disco.Services.Authorization;
using Disco.Services.Devices.DeviceFlags;
using Disco.Services.Expressions; using Disco.Services.Expressions;
using Disco.Services.Logging; using Disco.Services.Logging;
using Disco.Services.Users; using Disco.Services.Users;
@@ -15,16 +16,18 @@ namespace Disco.Services
{ {
#region Edit Comments #region Edit Comments
public static bool CanEditComments(this DeviceFlagAssignment fa) public static bool CanEdit(this DeviceFlagAssignment fa)
{ {
return UserService.CurrentAuthorization.Has(Claims.Device.Actions.EditFlags); var (_, permission) = DeviceFlagService.GetDeviceFlag(fa.DeviceFlagId);
return permission.CanEdit();
} }
public static void OnEditComments(this DeviceFlagAssignment fa, string Comments) public static void OnEdit(this DeviceFlagAssignment fa, string comments)
{ {
if (!fa.CanEditComments()) if (!fa.CanEdit())
throw new InvalidOperationException("Editing comments for device flags is denied"); throw new InvalidOperationException("Editing comments for device flags is denied");
fa.Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim(); fa.Comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
} }
#endregion #endregion
@@ -34,36 +37,38 @@ namespace Disco.Services
if (fa.RemovedDate.HasValue) if (fa.RemovedDate.HasValue)
return false; return false;
return UserService.CurrentAuthorization.Has(Claims.Device.Actions.RemoveFlags); var (_, permission) = DeviceFlagService.GetDeviceFlag(fa.DeviceFlagId);
return permission.CanRemove();
} }
public static void OnRemove(this DeviceFlagAssignment fa, DiscoDataContext Database, User RemovingUser) public static void OnRemove(this DeviceFlagAssignment fa, DiscoDataContext database)
{ {
if (!fa.CanRemove()) if (!fa.CanRemove())
throw new InvalidOperationException("Removing device flags is denied"); throw new InvalidOperationException("Removing device flags is denied");
fa.OnRemoveUnsafe(Database, RemovingUser); fa.OnRemoveUnsafe(database, UserService.CurrentUser);
} }
public static void OnRemoveUnsafe(this DeviceFlagAssignment fa, DiscoDataContext Database, User RemovingUser) public static void OnRemoveUnsafe(this DeviceFlagAssignment fa, DiscoDataContext database, User removingUser)
{ {
fa = Database.DeviceFlagAssignments fa = database.DeviceFlagAssignments
.Include(a => a.DeviceFlag) .Include(a => a.DeviceFlag)
.First(a => a.Id == fa.Id); .First(a => a.Id == fa.Id);
RemovingUser = Database.Users.First(u => u.UserId == RemovingUser.UserId); removingUser = database.Users.First(u => u.UserId == removingUser.UserId);
fa.RemovedDate = DateTime.Now; fa.RemovedDate = DateTime.Now;
fa.RemovedUserId = RemovingUser.UserId; fa.RemovedUserId = removingUser.UserId;
if (!string.IsNullOrWhiteSpace(fa.DeviceFlag.OnUnassignmentExpression)) if (!string.IsNullOrWhiteSpace(fa.DeviceFlag.OnUnassignmentExpression))
{ {
try try
{ {
Database.SaveChanges(); database.SaveChanges();
var expressionResult = fa.EvaluateOnUnassignmentExpression(Database, RemovingUser, fa.AddedDate); var expressionResult = fa.EvaluateOnUnassignmentExpression(database, removingUser, fa.AddedDate);
if (!string.IsNullOrWhiteSpace(expressionResult)) if (!string.IsNullOrWhiteSpace(expressionResult))
{ {
fa.OnUnassignmentExpressionResult = expressionResult; fa.OnUnassignmentExpressionResult = expressionResult;
Database.SaveChanges(); database.SaveChanges();
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -75,58 +80,52 @@ namespace Disco.Services
#endregion #endregion
#region Add #region Add
public static bool CanAddDeviceFlags(this Device d)
{
return UserService.CurrentAuthorization.Has(Claims.Device.Actions.AddFlags);
}
public static bool CanAddDeviceFlag(this Device d, DeviceFlag flag) public static bool CanAddDeviceFlag(this Device d, DeviceFlag flag)
{ {
// Shortcut
if (!d.CanAddDeviceFlags())
return false;
// Already has Device Flag? // Already has Device Flag?
if (d.DeviceFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.DeviceFlagId == flag.Id)) if (d.DeviceFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.DeviceFlagId == flag.Id))
return false; return false;
return true; var (_, permission) = DeviceFlagService.GetDeviceFlag(flag.Id);
return permission.CanAssign();
} }
public static DeviceFlagAssignment OnAddDeviceFlag(this Device d, DiscoDataContext Database, DeviceFlag flag, User AddingUser, string Comments) public static DeviceFlagAssignment OnAddDeviceFlag(this Device d, DiscoDataContext database, DeviceFlag flag, string comments)
{ {
if (!d.CanAddDeviceFlag(flag)) if (!d.CanAddDeviceFlag(flag))
throw new InvalidOperationException("Adding device flag is denied"); throw new InvalidOperationException("Adding device flag is denied");
return d.OnAddDeviceFlagUnsafe(Database, flag, AddingUser, Comments); return d.OnAddDeviceFlagUnsafe(database, flag, UserService.CurrentUser, comments);
} }
public static DeviceFlagAssignment OnAddDeviceFlagUnsafe(this Device d, DiscoDataContext Database, DeviceFlag flag, User AddingUser, string Comments) public static DeviceFlagAssignment OnAddDeviceFlagUnsafe(this Device d, DiscoDataContext database, DeviceFlag flag, User addingUser, string comments)
{ {
flag = Database.DeviceFlags.First(f => f.Id == flag.Id); flag = database.DeviceFlags.First(f => f.Id == flag.Id);
d = Database.Devices.First(de => de.SerialNumber == d.SerialNumber); d = database.Devices.First(de => de.SerialNumber == d.SerialNumber);
AddingUser = Database.Users.First(user => user.UserId == AddingUser.UserId); addingUser = database.Users.First(user => user.UserId == addingUser.UserId);
var fa = new DeviceFlagAssignment() var fa = new DeviceFlagAssignment()
{ {
DeviceFlag = flag, DeviceFlag = flag,
Device = d, Device = d,
AddedDate = DateTime.Now, AddedDate = DateTime.Now,
AddedUser = AddingUser, AddedUser = addingUser,
AddedUserId = AddingUser.UserId, AddedUserId = addingUser.UserId,
Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim() Comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim()
}; };
Database.DeviceFlagAssignments.Add(fa); database.DeviceFlagAssignments.Add(fa);
if (!string.IsNullOrWhiteSpace(flag.OnAssignmentExpression)) if (!string.IsNullOrWhiteSpace(flag.OnAssignmentExpression))
{ {
try try
{ {
Database.SaveChanges(); database.SaveChanges();
var expressionResult = fa.EvaluateOnAssignmentExpression(Database, AddingUser, fa.AddedDate); var expressionResult = fa.EvaluateOnAssignmentExpression(database, addingUser, fa.AddedDate);
if (!string.IsNullOrWhiteSpace(expressionResult)) if (!string.IsNullOrWhiteSpace(expressionResult))
{ {
fa.OnAssignmentExpressionResult = expressionResult; fa.OnAssignmentExpressionResult = expressionResult;
Database.SaveChanges(); database.SaveChanges();
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -13,7 +13,7 @@ namespace Disco.Services.Devices.DeviceFlags
{ {
public static class DeviceFlagService public static class DeviceFlagService
{ {
private static Cache _cache; private static Cache cache;
internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceFlagAssignmentRepositoryEvents; internal static Lazy<IObservable<RepositoryMonitorEvent>> DeviceFlagAssignmentRepositoryEvents;
static DeviceFlagService() static DeviceFlagService()
@@ -31,18 +31,51 @@ namespace Disco.Services.Devices.DeviceFlags
public static void Initialize(DiscoDataContext database) public static void Initialize(DiscoDataContext database)
{ {
_cache = new Cache(database); cache = new Cache(database);
// Initialize Managed Groups (if configured) // Initialize Managed Groups (if configured)
_cache.GetDeviceFlags().ForEach(uf => cache.GetDeviceFlags().ForEach(uf =>
{ {
DeviceFlagDevicesManagedGroup.Initialize(uf); DeviceFlagDevicesManagedGroup.Initialize(uf.flag);
DeviceFlagDeviceAssignedUsersManagedGroup.Initialize(uf); DeviceFlagDeviceAssignedUsersManagedGroup.Initialize(uf.flag);
}); });
} }
public static List<DeviceFlag> GetDeviceFlags() { return _cache.GetDeviceFlags(); } public static IEnumerable<(DeviceFlag flag, FlagPermission permission)> GetDeviceFlags() { return cache.GetDeviceFlags(); }
public static DeviceFlag GetDeviceFlag(int deviceFlagId) { return _cache.GetDeviceFlag(deviceFlagId); } public static (DeviceFlag flag, FlagPermission permission) GetDeviceFlag(int deviceFlagId) { return cache.GetDeviceFlag(deviceFlagId); }
public static DeviceFlag GetAvailableUserFlag(int deviceFlagId, Device targetDevice)
{
var (deviceFlag, permission) = cache.GetDeviceFlag(deviceFlagId);
if (targetDevice.DeviceFlagAssignments
.Where(a => a.DeviceFlagId == deviceFlagId && !a.RemovedDate.HasValue).Any())
return null;
if (permission.CanAssign())
return deviceFlag;
return null;
}
public static IEnumerable<DeviceFlag> GetAvailableDeviceFlags(Device targetDevice)
{
var records = cache.GetDeviceFlags();
var usedFlags = targetDevice.DeviceFlagAssignments
.Where(a => !a.RemovedDate.HasValue)
.Select(a => a.DeviceFlagId)
.ToList();
foreach (var (flag, permission) in records)
{
if (usedFlags.Contains(flag.Id))
continue;
if (permission.CanAssign())
yield return flag;
}
}
#region Device Flag Maintenance #region Device Flag Maintenance
public static DeviceFlag CreateDeviceFlag(DiscoDataContext database, string name, string description) public static DeviceFlag CreateDeviceFlag(DiscoDataContext database, string name, string description)
@@ -52,7 +85,7 @@ namespace Disco.Services.Devices.DeviceFlags
throw new ArgumentException("The Device Flag Name is required", nameof(name)); throw new ArgumentException("The Device Flag Name is required", nameof(name));
// Name Unique // Name Unique
if (_cache.GetDeviceFlags().Any(f => f.Name.Equals(name, StringComparison.Ordinal))) if (cache.GetDeviceFlags().Any(f => f.flag.Name.Equals(name, StringComparison.Ordinal)))
throw new ArgumentException("Another Device Flag already exists with that name", nameof(name)); throw new ArgumentException("Another Device Flag already exists with that name", nameof(name));
// Clone to break reference // Clone to break reference
@@ -67,7 +100,7 @@ namespace Disco.Services.Devices.DeviceFlags
database.DeviceFlags.Add(flag); database.DeviceFlags.Add(flag);
database.SaveChanges(); database.SaveChanges();
_cache.AddOrUpdate(flag); cache.AddOrUpdate(flag);
return flag; return flag;
} }
@@ -78,12 +111,12 @@ namespace Disco.Services.Devices.DeviceFlags
throw new ArgumentException("The Device Flag Name is required", nameof(deviceFlag)); throw new ArgumentException("The Device Flag Name is required", nameof(deviceFlag));
// Name Unique // Name Unique
if (_cache.GetDeviceFlags().Any(f => f.Id != deviceFlag.Id && f.Name == deviceFlag.Name)) if (cache.GetDeviceFlags().Any(f => f.flag.Id != deviceFlag.Id && f.flag.Name == deviceFlag.Name))
throw new ArgumentException("Another Device Flag already exists with that name", nameof(deviceFlag)); throw new ArgumentException("Another Device Flag already exists with that name", nameof(deviceFlag));
database.SaveChanges(); database.SaveChanges();
_cache.AddOrUpdate(deviceFlag); cache.AddOrUpdate(deviceFlag);
DeviceFlagDevicesManagedGroup.Initialize(deviceFlag); DeviceFlagDevicesManagedGroup.Initialize(deviceFlag);
DeviceFlagDeviceAssignedUsersManagedGroup.Initialize(deviceFlag); DeviceFlagDeviceAssignedUsersManagedGroup.Initialize(deviceFlag);
@@ -113,7 +146,7 @@ namespace Disco.Services.Devices.DeviceFlags
database.SaveChanges(); database.SaveChanges();
// Remove from Cache // Remove from Cache
_cache.Remove(deviceFlagId); cache.Remove(deviceFlagId);
status.Finished($"Successfully Deleted Device Flag: '{flag.Name}' [{flag.Id}]"); status.Finished($"Successfully Deleted Device Flag: '{flag.Name}' [{flag.Id}]");
} }
@@ -140,7 +173,7 @@ namespace Disco.Services.Devices.DeviceFlags
{ {
status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {device}"); status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {device}");
return device.OnAddDeviceFlag(database, deviceFlag, technician, comments); return device.OnAddDeviceFlagUnsafe(database, deviceFlag, technician, comments);
}).ToList(); }).ToList();
// Save Chunk Items to Database // Save Chunk Items to Database
@@ -206,7 +239,7 @@ namespace Disco.Services.Devices.DeviceFlags
{ {
status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {device}"); status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {device}");
return device.OnAddDeviceFlag(database, deviceFlag, technician, comments); return device.OnAddDeviceFlagUnsafe(database, deviceFlag, technician, comments);
}).ToList(); }).ToList();
// Save Chunk Items to Database // Save Chunk Items to Database
@@ -229,11 +262,11 @@ namespace Disco.Services.Devices.DeviceFlags
public static string RandomUnusedIcon() public static string RandomUnusedIcon()
{ {
return UIHelpers.RandomIcon(_cache.GetDeviceFlags().Select(f => f.Icon)); return UIHelpers.RandomIcon(cache.GetDeviceFlags().Select(f => f.flag.Icon));
} }
public static string RandomUnusedThemeColour() public static string RandomUnusedThemeColour()
{ {
return UIHelpers.RandomThemeColour(_cache.GetDeviceFlags().Select(f => f.IconColour)); return UIHelpers.RandomThemeColour(cache.GetDeviceFlags().Select(f => f.flag.IconColour));
} }
} }
} }
+1
View File
@@ -609,6 +609,7 @@
<Compile Include="Users\Contact\UserContactService.cs" /> <Compile Include="Users\Contact\UserContactService.cs" />
<Compile Include="Users\UserExtensions.cs" /> <Compile Include="Users\UserExtensions.cs" />
<Compile Include="Users\UserFlags\Cache.cs" /> <Compile Include="Users\UserFlags\Cache.cs" />
<Compile Include="Users\UserFlags\FlagPermissionExtensions.cs" />
<Compile Include="Users\UserFlags\UserFlagExport.cs" /> <Compile Include="Users\UserFlags\UserFlagExport.cs" />
<Compile Include="Users\UserFlags\UserFlagExtensions.cs" /> <Compile Include="Users\UserFlags\UserFlagExtensions.cs" />
<Compile Include="Users\UserFlags\UserFlagUserDevicesManagedGroup.cs" /> <Compile Include="Users\UserFlags\UserFlagUserDevicesManagedGroup.cs" />
+11 -17
View File
@@ -8,7 +8,7 @@ namespace Disco.Services.Users.UserFlags
{ {
internal class Cache internal class Cache
{ {
private ConcurrentDictionary<int, UserFlag> _Cache; private ConcurrentDictionary<int, (UserFlag flag, FlagPermission permission)> cache;
public Cache(DiscoDataContext Database) public Cache(DiscoDataContext Database)
{ {
@@ -26,36 +26,30 @@ namespace Disco.Services.Users.UserFlags
var flags = Database.UserFlags.ToList(); var flags = Database.UserFlags.ToList();
// Add Queues to In-Memory Cache // Add Queues to In-Memory Cache
_Cache = new ConcurrentDictionary<int, UserFlag>(flags.Select(f => new KeyValuePair<int, UserFlag>(f.Id, f))); cache = new ConcurrentDictionary<int, (UserFlag, FlagPermission)>(flags.Select(f => new KeyValuePair<int, (UserFlag, FlagPermission)>(f.Id, (f, f.Permissions))));
} }
public UserFlag GetUserFlag(int UserFlagId) public (UserFlag flag, FlagPermission permission) GetUserFlag(int UserFlagId)
{ {
if (_Cache.TryGetValue(UserFlagId, out var item)) if (cache.TryGetValue(UserFlagId, out var item))
return item; return item;
else else
return null; return (null, null);
} }
public List<UserFlag> GetUserFlags() public List<(UserFlag flag, FlagPermission permission)> GetUserFlags()
{ {
return _Cache.Values.ToList(); return cache.Values.ToList();
} }
public void AddOrUpdate(UserFlag UserFlag) public void AddOrUpdate(UserFlag UserFlag)
{ {
_Cache.AddOrUpdate(UserFlag.Id, UserFlag, (key, existingItem) => UserFlag); var value = (UserFlag, UserFlag.Permissions);
cache.AddOrUpdate(UserFlag.Id, value, (key, existingItem) => value);
} }
public UserFlag Remove(int UserFlagId) public void Remove(int UserFlagId)
{ {
if (_Cache.TryRemove(UserFlagId, out var item)) cache.TryRemove(UserFlagId, out _);
return item;
else
return null;
}
public UserFlag Remove(UserFlag UserFlag)
{
return Remove(UserFlag.Id);
} }
} }
} }
@@ -0,0 +1,144 @@
using Disco.Models.Repository;
using Disco.Services.Authorization;
using Disco.Services.Devices.DeviceFlags;
using Disco.Services.Users;
using Disco.Services.Users.UserFlags;
using System.Collections.Generic;
using System.Linq;
namespace Disco
{
public static class FlagPermissionExtensions
{
public static bool CanShow(this FlagPermission permission)
{
var authorization = UserService.CurrentAuthorization;
// inherited permission
if (permission.Inherit &&
authorization.Has(permission.FlagType == FlagType.User ? Claims.User.ShowFlagAssignments : Claims.Device.ShowFlagAssignments))
{
return true;
}
// permission override
if (permission != null && (
permission.CanShowSubjectIds.Contains(authorization.User.UserId) ||
permission.CanShowSubjectIds.Overlaps(authorization.GroupMembership) ||
permission.CanShowSubjectIds.Overlaps(authorization.RoleTokens.Select(r => $"[{r.Role.Id}]"))
))
{
return true;
}
return false;
}
public static bool CanAssign(this FlagPermission permission)
{
var authorization = UserService.CurrentAuthorization;
// inherited permission
if (permission.Inherit &&
authorization.Has(permission.FlagType == FlagType.User ? Claims.User.Actions.AddFlags : Claims.Device.Actions.AddFlags))
{
return true;
}
// permission override
if (permission != null && (
permission.CanAssignSubjectIds.Contains(authorization.User.UserId) ||
permission.CanAssignSubjectIds.Overlaps(authorization.GroupMembership) ||
permission.CanAssignSubjectIds.Overlaps(authorization.RoleTokens.Select(r => $"[{r.Role.Id}]"))
))
{
return true;
}
return false;
}
public static bool CanEdit(this FlagPermission permission)
{
var authorization = UserService.CurrentAuthorization;
// inherited permission
if (permission.Inherit &&
authorization.Has(permission.FlagType == FlagType.User ? Claims.User.Actions.EditFlags : Claims.Device.Actions.EditFlags))
{
return true;
}
// permission override
if (permission != null && (
permission.CanEditSubjectIds.Contains(authorization.User.UserId) ||
permission.CanEditSubjectIds.Overlaps(authorization.GroupMembership) ||
permission.CanEditSubjectIds.Overlaps(authorization.RoleTokens.Select(r => $"[{r.Role.Id}]"))
))
{
return true;
}
return false;
}
public static bool CanRemove(this FlagPermission permission)
{
var authorization = UserService.CurrentAuthorization;
// inherited permission
if (permission.Inherit &&
authorization.Has(permission.FlagType == FlagType.User ? Claims.User.Actions.RemoveFlags : Claims.Device.Actions.RemoveFlags))
{
return true;
}
// permission override
if (permission != null && (
permission.CanRemoveSubjectIds.Contains(authorization.User.UserId) ||
permission.CanRemoveSubjectIds.Overlaps(authorization.GroupMembership) ||
permission.CanRemoveSubjectIds.Overlaps(authorization.RoleTokens.Select(r => $"[{r.Role.Id}]"))
))
{
return true;
}
return false;
}
public static bool CanShowAny(this IEnumerable<UserFlagAssignment> assignments)
{
if (assignments == null)
return false;
foreach (var assignment in assignments)
{
if (assignment.RemovedDate.HasValue)
continue;
var (_, permission) = UserFlagService.GetUserFlag(assignment.UserFlagId);
if (permission.CanShow())
return true;
}
return false;
}
public static bool CanShowAny(this IEnumerable<DeviceFlagAssignment> assignments)
{
if (assignments == null)
return false;
foreach (var assignment in assignments)
{
if (assignment.RemovedDate.HasValue)
continue;
var (_, permission) = DeviceFlagService.GetDeviceFlag(assignment.DeviceFlagId);
if (permission.CanShow())
return true;
}
return false;
}
}
}
@@ -4,6 +4,7 @@ using Disco.Services.Authorization;
using Disco.Services.Expressions; using Disco.Services.Expressions;
using Disco.Services.Logging; using Disco.Services.Logging;
using Disco.Services.Users; using Disco.Services.Users;
using Disco.Services.Users.UserFlags;
using System; using System;
using System.Collections; using System.Collections;
using System.Linq; using System.Linq;
@@ -14,16 +15,18 @@ namespace Disco.Services
{ {
#region Edit Comments #region Edit Comments
public static bool CanEditComments(this UserFlagAssignment fa) public static bool CanEdit(this UserFlagAssignment fa)
{ {
return UserService.CurrentAuthorization.Has(Claims.User.Actions.EditFlags); var (_, permission) = UserFlagService.GetUserFlag(fa.UserFlagId);
return permission.CanEdit();
} }
public static void OnEditComments(this UserFlagAssignment fa, string Comments) public static void OnEdit(this UserFlagAssignment fa, string comments)
{ {
if (!fa.CanEditComments()) if (!fa.CanEdit())
throw new InvalidOperationException("Editing comments for user flags is denied"); throw new InvalidOperationException("Editing comments for user flags is denied");
fa.Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim(); fa.Comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
} }
#endregion #endregion
@@ -33,34 +36,36 @@ namespace Disco.Services
if (fa.RemovedDate.HasValue) if (fa.RemovedDate.HasValue)
return false; return false;
return UserService.CurrentAuthorization.Has(Claims.User.Actions.RemoveFlags); var (_, permission) = UserFlagService.GetUserFlag(fa.UserFlagId);
return permission.CanRemove();
} }
public static void OnRemove(this UserFlagAssignment fa, DiscoDataContext Database, User RemovingUser) public static void OnRemove(this UserFlagAssignment fa, DiscoDataContext database)
{ {
if (!fa.CanRemove()) if (!fa.CanRemove())
throw new InvalidOperationException("Removing user flags is denied"); throw new InvalidOperationException("Removing user flags is denied");
fa.OnRemoveUnsafe(Database, RemovingUser); fa.OnRemoveUnsafe(database, UserService.CurrentUser);
} }
public static void OnRemoveUnsafe(this UserFlagAssignment fa, DiscoDataContext Database, User RemovingUser) public static void OnRemoveUnsafe(this UserFlagAssignment fa, DiscoDataContext database, User removingUser)
{ {
fa = Database.UserFlagAssignments.First(a => a.Id == fa.Id); fa = database.UserFlagAssignments.First(a => a.Id == fa.Id);
RemovingUser = Database.Users.First(u => u.UserId == RemovingUser.UserId); removingUser = database.Users.First(u => u.UserId == removingUser.UserId);
fa.RemovedDate = DateTime.Now; fa.RemovedDate = DateTime.Now;
fa.RemovedUserId = RemovingUser.UserId; fa.RemovedUserId = removingUser.UserId;
if (!string.IsNullOrWhiteSpace(fa.UserFlag.OnUnassignmentExpression)) if (!string.IsNullOrWhiteSpace(fa.UserFlag.OnUnassignmentExpression))
{ {
try try
{ {
Database.SaveChanges(); database.SaveChanges();
var expressionResult = fa.EvaluateOnUnassignmentExpression(Database, RemovingUser, fa.AddedDate); var expressionResult = fa.EvaluateOnUnassignmentExpression(database, removingUser, fa.AddedDate);
if (!string.IsNullOrWhiteSpace(expressionResult)) if (!string.IsNullOrWhiteSpace(expressionResult))
{ {
fa.OnUnassignmentExpressionResult = expressionResult; fa.OnUnassignmentExpressionResult = expressionResult;
Database.SaveChanges(); database.SaveChanges();
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -72,58 +77,52 @@ namespace Disco.Services
#endregion #endregion
#region Add #region Add
public static bool CanAddUserFlags(this User u)
{
return UserService.CurrentAuthorization.Has(Claims.User.Actions.AddFlags);
}
public static bool CanAddUserFlag(this User u, UserFlag flag) public static bool CanAddUserFlag(this User u, UserFlag flag)
{ {
// Shortcut
if (!u.CanAddUserFlags())
return false;
// Already has User Flag? // Already has User Flag?
if (u.UserFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.UserFlagId == flag.Id)) if (u.UserFlagAssignments.Any(fa => !fa.RemovedDate.HasValue && fa.UserFlagId == flag.Id))
return false; return false;
return true; var (_, permission) = UserFlagService.GetUserFlag(flag.Id);
return permission.CanAssign();
} }
public static UserFlagAssignment OnAddUserFlag(this User u, DiscoDataContext Database, UserFlag flag, User AddingUser, string Comments) public static UserFlagAssignment OnAddUserFlag(this User u, DiscoDataContext database, UserFlag flag, string comments)
{ {
if (!u.CanAddUserFlag(flag)) if (!u.CanAddUserFlag(flag))
throw new InvalidOperationException("Adding user flag is denied"); throw new InvalidOperationException("Adding user flag is denied");
return u.OnAddUserFlagUnsafe(Database, flag, AddingUser, Comments); return u.OnAddUserFlagUnsafe(database, flag, UserService.CurrentUser, comments);
} }
public static UserFlagAssignment OnAddUserFlagUnsafe(this User u, DiscoDataContext Database, UserFlag flag, User AddingUser, string Comments) public static UserFlagAssignment OnAddUserFlagUnsafe(this User u, DiscoDataContext database, UserFlag flag, User addingUser, string comments)
{ {
flag = Database.UserFlags.First(f => f.Id == flag.Id); flag = database.UserFlags.First(f => f.Id == flag.Id);
u = Database.Users.First(user => user.UserId == u.UserId); u = database.Users.First(user => user.UserId == u.UserId);
AddingUser = Database.Users.First(user => user.UserId == AddingUser.UserId); addingUser = database.Users.First(user => user.UserId == addingUser.UserId);
var fa = new UserFlagAssignment() var fa = new UserFlagAssignment()
{ {
UserFlag = flag, UserFlag = flag,
User = u, User = u,
AddedDate = DateTime.Now, AddedDate = DateTime.Now,
AddedUser = AddingUser, AddedUser = addingUser,
AddedUserId = AddingUser.UserId, AddedUserId = addingUser.UserId,
Comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim() Comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim()
}; };
Database.UserFlagAssignments.Add(fa); database.UserFlagAssignments.Add(fa);
if (!string.IsNullOrWhiteSpace(flag.OnAssignmentExpression)) if (!string.IsNullOrWhiteSpace(flag.OnAssignmentExpression))
{ {
try try
{ {
Database.SaveChanges(); database.SaveChanges();
var expressionResult = fa.EvaluateOnAssignmentExpression(Database, AddingUser, fa.AddedDate); var expressionResult = fa.EvaluateOnAssignmentExpression(database, addingUser, fa.AddedDate);
if (!string.IsNullOrWhiteSpace(expressionResult)) if (!string.IsNullOrWhiteSpace(expressionResult))
{ {
fa.OnAssignmentExpressionResult = expressionResult; fa.OnAssignmentExpressionResult = expressionResult;
Database.SaveChanges(); database.SaveChanges();
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -5,6 +5,7 @@ using Disco.Services.Extensions;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Entity;
using System.Linq; using System.Linq;
using System.Reactive.Linq; using System.Reactive.Linq;
@@ -12,7 +13,7 @@ namespace Disco.Services.Users.UserFlags
{ {
public static class UserFlagService public static class UserFlagService
{ {
private static Cache _cache; private static Cache cache;
internal static Lazy<IObservable<RepositoryMonitorEvent>> UserFlagAssignmentRepositoryEvents; internal static Lazy<IObservable<RepositoryMonitorEvent>> UserFlagAssignmentRepositoryEvents;
static UserFlagService() static UserFlagService()
@@ -24,25 +25,58 @@ namespace Disco.Services.Users.UserFlags
RepositoryMonitor.StreamAfterCommit.Where(e => RepositoryMonitor.StreamAfterCommit.Where(e =>
e.EntityType == typeof(UserFlagAssignment) && e.EntityType == typeof(UserFlagAssignment) &&
(e.EventType != RepositoryMonitorEventType.Modified || (e.EventType != RepositoryMonitorEventType.Modified ||
e.ModifiedProperties.Contains("RemovedDate")) e.ModifiedProperties.Contains(nameof(UserFlagAssignment.RemovedDate)))
) )
); );
} }
public static void Initialize(DiscoDataContext Database) public static void Initialize(DiscoDataContext Database)
{ {
_cache = new Cache(Database); cache = new Cache(Database);
// Initialize Managed Groups (if configured) // Initialize Managed Groups (if configured)
_cache.GetUserFlags().ForEach(uf => cache.GetUserFlags().ForEach(uf =>
{ {
UserFlagUsersManagedGroup.Initialize(uf); UserFlagUsersManagedGroup.Initialize(uf.flag);
UserFlagUserDevicesManagedGroup.Initialize(uf); UserFlagUserDevicesManagedGroup.Initialize(uf.flag);
}); });
} }
public static List<UserFlag> GetUserFlags() { return _cache.GetUserFlags(); } public static IEnumerable<(UserFlag flag, FlagPermission permission)> GetUserFlags() { return cache.GetUserFlags(); }
public static UserFlag GetUserFlag(int UserFlagId) { return _cache.GetUserFlag(UserFlagId); } public static (UserFlag flag, FlagPermission permission) GetUserFlag(int UserFlagId) { return cache.GetUserFlag(UserFlagId); }
public static UserFlag GetAvailableUserFlag(int userFlagId, User targetUser)
{
var (userFlag, permission) = cache.GetUserFlag(userFlagId);
if (targetUser.UserFlagAssignments
.Where(a => a.UserFlagId == userFlagId && !a.RemovedDate.HasValue).Any())
return null;
if (permission.CanAssign())
return userFlag;
return null;
}
public static IEnumerable<UserFlag> GetAvailableUserFlags(User targetUser)
{
var records = cache.GetUserFlags();
var usedFlags = targetUser.UserFlagAssignments
.Where(a => !a.RemovedDate.HasValue)
.Select(a => a.UserFlagId)
.ToList();
foreach (var (flag, permission) in records)
{
if (usedFlags.Contains(flag.Id))
continue;
if (permission.CanAssign())
yield return flag;
}
}
#region User Flag Maintenance #region User Flag Maintenance
public static UserFlag CreateUserFlag(DiscoDataContext Database, string name, string description) public static UserFlag CreateUserFlag(DiscoDataContext Database, string name, string description)
@@ -52,7 +86,7 @@ namespace Disco.Services.Users.UserFlags
throw new ArgumentException("The User Flag Name is required", nameof(name)); throw new ArgumentException("The User Flag Name is required", nameof(name));
// Name Unique // Name Unique
if (_cache.GetUserFlags().Any(f => f.Name.Equals(name, StringComparison.Ordinal))) if (cache.GetUserFlags().Any(f => f.flag.Name.Equals(name, StringComparison.Ordinal)))
throw new ArgumentException("Another User Flag already exists with that name", nameof(name)); throw new ArgumentException("Another User Flag already exists with that name", nameof(name));
// Clone to break reference // Clone to break reference
@@ -67,7 +101,7 @@ namespace Disco.Services.Users.UserFlags
Database.UserFlags.Add(flag); Database.UserFlags.Add(flag);
Database.SaveChanges(); Database.SaveChanges();
_cache.AddOrUpdate(flag); cache.AddOrUpdate(flag);
return flag; return flag;
} }
@@ -78,12 +112,12 @@ namespace Disco.Services.Users.UserFlags
throw new ArgumentException("The User Flag Name is required"); throw new ArgumentException("The User Flag Name is required");
// Name Unique // Name Unique
if (_cache.GetUserFlags().Any(f => f.Id != UserFlag.Id && f.Name == UserFlag.Name)) if (cache.GetUserFlags().Any(f => f.flag.Id != UserFlag.Id && f.flag.Name == UserFlag.Name))
throw new ArgumentException("Another User Flag already exists with that name", "UserFlag"); throw new ArgumentException("Another User Flag already exists with that name", nameof(UserFlag));
Database.SaveChanges(); Database.SaveChanges();
_cache.AddOrUpdate(UserFlag); cache.AddOrUpdate(UserFlag);
UserFlagUsersManagedGroup.Initialize(UserFlag); UserFlagUsersManagedGroup.Initialize(UserFlag);
UserFlagUserDevicesManagedGroup.Initialize(UserFlag); UserFlagUserDevicesManagedGroup.Initialize(UserFlag);
@@ -113,22 +147,22 @@ namespace Disco.Services.Users.UserFlags
Database.SaveChanges(); Database.SaveChanges();
// Remove from Cache // Remove from Cache
_cache.Remove(UserFlagId); cache.Remove(UserFlagId);
Status.Finished($"Successfully Deleted User Flag: '{flag.Name}' [{flag.Id}]"); Status.Finished($"Successfully Deleted User Flag: '{flag.Name}' [{flag.Id}]");
} }
#endregion #endregion
#region Bulk Assignment #region Bulk Assignment
public static IEnumerable<UserFlagAssignment> BulkAssignAddUsers(DiscoDataContext Database, UserFlag UserFlag, User Technician, string Comments, List<User> Users, IScheduledTaskStatus Status) public static IEnumerable<UserFlagAssignment> BulkAssignAddUsers(DiscoDataContext database, UserFlag userFlag, User techUser, string comments, List<User> users, IScheduledTaskStatus status)
{ {
if (Users.Count > 0) if (users.Count > 0)
{ {
double progressInterval; double progressInterval;
const int databaseChunkSize = 100; const int databaseChunkSize = 100;
string comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim(); comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
var addUsers = Users.Where(u => !u.UserFlagAssignments.Any(a => a.UserFlagId == UserFlag.Id && !a.RemovedDate.HasValue)).ToList(); var addUsers = users.Where(u => !u.UserFlagAssignments.Any(a => a.UserFlagId == userFlag.Id && !a.RemovedDate.HasValue)).ToList();
progressInterval = (double)100 / addUsers.Count; progressInterval = (double)100 / addUsers.Count;
@@ -138,39 +172,39 @@ namespace Disco.Services.Users.UserFlags
var chunkResults = chunk.Select((user, index) => var chunkResults = chunk.Select((user, index) =>
{ {
Status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {user.ToString()}"); status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {user}");
return user.OnAddUserFlag(Database, UserFlag, Technician, comments); return user.OnAddUserFlagUnsafe(database, userFlag, techUser, comments);
}).ToList(); }).ToList();
// Save Chunk Items to Database // Save Chunk Items to Database
Database.SaveChanges(); database.SaveChanges();
return chunkResults; return chunkResults;
}).Where(fa => fa != null).ToList(); }).Where(fa => fa != null).ToList();
Status.SetFinishedMessage($"{addUsers.Count} Users/s Added; {(Users.Count - addUsers.Count)} User/s Skipped"); status.SetFinishedMessage($"{addUsers.Count} Users/s Added; {users.Count - addUsers.Count} User/s Skipped");
return addedUserAssignments; return addedUserAssignments;
} }
else else
{ {
Status.SetFinishedMessage("No changes found"); status.SetFinishedMessage("No changes found");
return Enumerable.Empty<UserFlagAssignment>(); return Enumerable.Empty<UserFlagAssignment>();
} }
} }
public static IEnumerable<UserFlagAssignment> BulkAssignOverrideUsers(DiscoDataContext Database, UserFlag UserFlag, User Technician, string Comments, List<User> Users, IScheduledTaskStatus Status) public static IEnumerable<UserFlagAssignment> BulkAssignOverrideUsers(DiscoDataContext database, UserFlag userFlag, User techUser, string comments, List<User> users, IScheduledTaskStatus status)
{ {
double progressInterval; double progressInterval;
const int databaseChunkSize = 100; const int databaseChunkSize = 100;
string comments = string.IsNullOrWhiteSpace(Comments) ? null : Comments.Trim(); comments = string.IsNullOrWhiteSpace(comments) ? null : comments.Trim();
Status.UpdateStatus(0, "Calculating assignment changes"); status.UpdateStatus(0, "Calculating assignment changes");
var currentAssignments = Database.UserFlagAssignments.Include("User").Where(a => a.UserFlagId == UserFlag.Id && !a.RemovedDate.HasValue).ToList(); var currentAssignments = database.UserFlagAssignments.Include(a => a.User).Where(a => a.UserFlagId == userFlag.Id && !a.RemovedDate.HasValue).ToList();
var removeAssignments = currentAssignments.Where(ca => !Users.Any(u => u.UserId.Equals(ca.UserId, StringComparison.OrdinalIgnoreCase))).ToList(); var removeAssignments = currentAssignments.Where(ca => !users.Any(u => u.UserId.Equals(ca.UserId, StringComparison.OrdinalIgnoreCase))).ToList();
var addUsers = Users.Where(u => !currentAssignments.Any(ca => ca.UserId.Equals(u.UserId, StringComparison.OrdinalIgnoreCase))).ToList(); var addUsers = users.Where(u => !currentAssignments.Any(ca => ca.UserId.Equals(u.UserId, StringComparison.OrdinalIgnoreCase))).ToList();
if (removeAssignments.Count > 0 || addUsers.Count > 0) if (removeAssignments.Count > 0 || addUsers.Count > 0)
{ {
@@ -184,15 +218,15 @@ namespace Disco.Services.Users.UserFlags
var chunkResults = chunk.Select((flagAssignment, index) => var chunkResults = chunk.Select((flagAssignment, index) =>
{ {
Status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Removing Flag: {flagAssignment.User.ToString()}"); status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Removing Flag: {flagAssignment.User}");
flagAssignment.OnRemoveUnsafe(Database, Technician); flagAssignment.OnRemoveUnsafe(database, techUser);
return flagAssignment; return flagAssignment;
}).ToList(); }).ToList();
// Save Chunk Items to Database // Save Chunk Items to Database
Database.SaveChanges(); database.SaveChanges();
return chunkResults; return chunkResults;
}).ToList(); }).ToList();
@@ -204,24 +238,24 @@ namespace Disco.Services.Users.UserFlags
var chunkResults = chunk.Select((user, index) => var chunkResults = chunk.Select((user, index) =>
{ {
Status.UpdateStatus((chunkIndexOffset + index) * progressInterval, $"Assigning Flag: {user.ToString()}"); status.UpdateStatus((chunkIndexOffset + index) * progressInterval, string.Format("Assigning Flag: {0}", user.ToString()));
return user.OnAddUserFlag(Database, UserFlag, Technician, comments); return user.OnAddUserFlagUnsafe(database, userFlag, techUser, comments);
}).ToList(); }).ToList();
// Save Chunk Items to Database // Save Chunk Items to Database
Database.SaveChanges(); database.SaveChanges();
return chunkResults; return chunkResults;
}).ToList(); }).ToList();
Status.SetFinishedMessage($"{addUsers.Count} Users/s Added; {removeAssignments.Count} User/s Removed; {(Users.Count - addUsers.Count)} User/s Skipped"); status.SetFinishedMessage($"{addUsers.Count} Users/s Added; {removeAssignments.Count} User/s Removed; {users.Count - addUsers.Count} User/s Skipped");
return addedUserAssignments; return addedUserAssignments;
} }
else else
{ {
Status.SetFinishedMessage("No changes found"); status.SetFinishedMessage("No changes found");
return Enumerable.Empty<UserFlagAssignment>(); return Enumerable.Empty<UserFlagAssignment>();
} }
} }
@@ -229,11 +263,11 @@ namespace Disco.Services.Users.UserFlags
public static string RandomUnusedIcon() public static string RandomUnusedIcon()
{ {
return UIHelpers.RandomIcon(_cache.GetUserFlags().Select(f => f.Icon)); return UIHelpers.RandomIcon(cache.GetUserFlags().Select(f => f.flag.Icon));
} }
public static string RandomUnusedThemeColour() public static string RandomUnusedThemeColour()
{ {
return UIHelpers.RandomThemeColour(_cache.GetUserFlags().Select(f => f.IconColour)); return UIHelpers.RandomThemeColour(cache.GetUserFlags().Select(f => f.flag.IconColour));
} }
} }
} }
+13 -5
View File
@@ -154,7 +154,7 @@ namespace Disco.Services.Users
AuthorizationLog.LogRoleCreated(role, CurrentUserId); AuthorizationLog.LogRoleCreated(role, CurrentUserId);
// Add to Cache // Add to Cache
RoleCache.AddRole(role); RoleCache.AddOrUpdateRole(role);
// Flush User Cache // Flush User Cache
Cache.FlushCache(); Cache.FlushCache();
@@ -164,7 +164,7 @@ namespace Disco.Services.Users
public static void DeleteAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role) public static void DeleteAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role)
{ {
if (Role == null) if (Role == null)
throw new ArgumentNullException("Role"); throw new ArgumentNullException(nameof(Role));
Database.AuthorizationRoles.Remove(Role); Database.AuthorizationRoles.Remove(Role);
Database.SaveChanges(); Database.SaveChanges();
@@ -180,19 +180,27 @@ namespace Disco.Services.Users
public static void UpdateAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role) public static void UpdateAuthorizationRole(DiscoDataContext Database, AuthorizationRole Role)
{ {
if (Role == null) if (Role == null)
throw new ArgumentNullException("Role"); throw new ArgumentNullException(nameof(Role));
if (Database == null) if (Database == null)
throw new ArgumentNullException("Database"); throw new ArgumentNullException(nameof(Database));
Database.SaveChanges(); Database.SaveChanges();
// Update Role Cache // Update Role Cache
RoleCache.UpdateRole(Role); RoleCache.AddOrUpdateRole(Role);
// Flush User Cache // Flush User Cache
Cache.FlushCache(); Cache.FlushCache();
} }
public static string GetAuthorizationRoleName(int roleId)
{
var role = RoleCache.GetRoleToken(roleId);
if (role == null)
return "Unknown authorization role";
return role.Role.Name;
}
public static IEnumerable<string> AdministratorSubjectIds public static IEnumerable<string> AdministratorSubjectIds
{ {
get get
+8 -2
View File
@@ -12,7 +12,13 @@ namespace Disco.Services.Web
protected static HttpStatusCodeResult BadRequest(string message = null) protected static HttpStatusCodeResult BadRequest(string message = null)
=> StatusCode(HttpStatusCode.BadRequest, message); => StatusCode(HttpStatusCode.BadRequest, message);
protected static HttpStatusCodeResult StatusCode(HttpStatusCode statusCode, string message = null) protected static HttpStatusCodeResult StatusCode(HttpStatusCode statusCode, string statusDescription = null)
=> new HttpStatusCodeResult(statusCode, message); => new HttpStatusCodeResult(statusCode, statusDescription);
protected static HttpNotFoundResult NotFound(string statusDescription = null)
=> new HttpNotFoundResult(statusDescription);
protected static HttpUnauthorizedResult Unauthorized(string statusDescription = null)
=> new HttpUnauthorizedResult(statusDescription);
} }
} }
@@ -78,14 +78,16 @@ namespace Disco.Web.Areas.API.Controllers
} }
} }
private void UpdateClaims(AuthorizationRole AuthorizationRole, string[] ClaimKeys) private void UpdateClaims(AuthorizationRole AuthorizationRole, string[] claimKeys)
{ {
var proposedClaims = Claims.BuildClaims(ClaimKeys); claimKeys = claimKeys ?? Array.Empty<string>();
var proposedClaims = Claims.BuildClaims(claimKeys);
var currentToken = RoleToken.FromAuthorizationRole(AuthorizationRole); var currentToken = RoleToken.FromAuthorizationRole(AuthorizationRole);
var currentClaimKeys = Claims.GetClaimKeys(currentToken.Claims); var currentClaimKeys = Claims.GetClaimKeys(currentToken.Claims);
var removedClaims = currentClaimKeys.Except(ClaimKeys).ToArray(); var removedClaims = currentClaimKeys.Except(claimKeys).ToArray();
var addedClaims = ClaimKeys.Except(currentClaimKeys).ToArray(); var addedClaims = claimKeys.Except(currentClaimKeys).ToArray();
AuthorizationRole.SetClaims(proposedClaims); AuthorizationRole.SetClaims(proposedClaims);
UserService.UpdateAuthorizationRole(Database, AuthorizationRole); UserService.UpdateAuthorizationRole(Database, AuthorizationRole);
@@ -1,6 +1,5 @@
using Disco.Models.Repository; using Disco.Models.Repository;
using Disco.Services; using Disco.Services;
using Disco.Services.Authorization;
using Disco.Services.Web; using Disco.Services.Web;
using System; using System;
using System.Data.Entity; using System.Data.Entity;
@@ -12,7 +11,7 @@ namespace Disco.Web.Areas.API.Controllers
public partial class DeviceFlagAssignmentController : AuthorizedDatabaseController public partial class DeviceFlagAssignmentController : AuthorizedDatabaseController
{ {
const string pComments = "comments"; const string pComments = "comments";
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null) public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null)
{ {
try try
@@ -21,7 +20,9 @@ namespace Disco.Web.Areas.API.Controllers
throw new ArgumentOutOfRangeException(nameof(id)); throw new ArgumentOutOfRangeException(nameof(id));
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key)); throw new ArgumentNullException(nameof(key));
var assignment = Database.DeviceFlagAssignments.FirstOrDefault(a => a.Id == id); var assignment = Database.DeviceFlagAssignments
.Include(a => a.DeviceFlag)
.FirstOrDefault(a => a.Id == id);
if (assignment != null) if (assignment != null)
{ {
switch (key.ToLower()) switch (key.ToLower())
@@ -52,7 +53,7 @@ namespace Disco.Web.Areas.API.Controllers
} }
#region Update Shortcut Methods #region Update Shortcut Methods
[DiscoAuthorizeAny(Claims.Device.Actions.EditFlags)] [HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null) public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null)
{ {
return Update(id, pComments, Comments, redirect); return Update(id, pComments, Comments, redirect);
@@ -60,20 +61,19 @@ namespace Disco.Web.Areas.API.Controllers
#endregion #endregion
#region Update Properties #region Update Properties
private void UpdateComments(DeviceFlagAssignment assignment, string Comments) private void UpdateComments(DeviceFlagAssignment assignment, string comments)
{ {
if (!assignment.CanEditComments()) if (!assignment.CanEdit())
throw new InvalidOperationException("Editing comments for device flags is denied"); throw new InvalidOperationException("Editing comments for device flags is denied");
assignment.OnEditComments(Comments); assignment.OnEdit(comments);
Database.SaveChanges(); Database.SaveChanges();
} }
#endregion #endregion
#region Actions #region Actions
[HttpPost, ValidateAntiForgeryToken]
[DiscoAuthorizeAny(Claims.Device.Actions.AddFlags)] public virtual ActionResult AddDevice(int id, string deviceSerialNumber, string comments)
public virtual ActionResult AddDevice(int id, string DeviceSerialNumber, string Comments)
{ {
Database.Configuration.LazyLoadingEnabled = true; Database.Configuration.LazyLoadingEnabled = true;
@@ -81,37 +81,35 @@ namespace Disco.Web.Areas.API.Controllers
if (flag == null) if (flag == null)
throw new ArgumentException("Invalid Device Flag Id", nameof(id)); throw new ArgumentException("Invalid Device Flag Id", nameof(id));
var device = Database.Devices.Include(u => u.DeviceFlagAssignments).FirstOrDefault(d => d.SerialNumber == DeviceSerialNumber); var device = Database.Devices.Include(u => u.DeviceFlagAssignments).FirstOrDefault(d => d.SerialNumber == deviceSerialNumber);
if (device == null) if (device == null)
throw new ArgumentException("Invalid Device Serial Number", nameof(DeviceSerialNumber)); throw new ArgumentException("Invalid Device Serial Number", nameof(deviceSerialNumber));
if (!device.CanAddDeviceFlag(flag)) if (!device.CanAddDeviceFlag(flag))
throw new InvalidOperationException("Adding device flag is denied"); return Unauthorized("Adding device flag is denied");
var addingUser = Database.Users.Find(CurrentUser.UserId); var assignment = device.OnAddDeviceFlag(Database, flag, comments);
var assignment = device.OnAddDeviceFlag(Database, flag, addingUser, Comments);
Database.SaveChanges(); Database.SaveChanges();
return Redirect($"{Url.Action(MVC.Device.Show(device.SerialNumber))}#DeviceDetailTab-Flags"); return Redirect($"{Url.Action(MVC.Device.Show(device.SerialNumber))}#DeviceDetailTab-Flags");
} }
[DiscoAuthorizeAny(Claims.Device.Actions.RemoveFlags)] [HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult RemoveDevice(int id) public virtual ActionResult RemoveDevice(int id)
{ {
Database.Configuration.LazyLoadingEnabled = true; Database.Configuration.LazyLoadingEnabled = true;
var assignment = Database.DeviceFlagAssignments.FirstOrDefault(a => a.Id == id); var assignment = Database.DeviceFlagAssignments
.Include(a => a.DeviceFlag)
.FirstOrDefault(a => a.Id == id);
if (assignment == null) if (assignment == null)
throw new ArgumentException("Invalid Device Flag Assignment Id", nameof(id)); throw new ArgumentException("Invalid Device Flag Assignment Id", nameof(id));
if (!assignment.CanRemove()) if (!assignment.CanRemove())
throw new InvalidOperationException("Removing device flag assignment is denied"); return Unauthorized("Removing device flag assignment is denied");
var removingUser = Database.Users.Find(CurrentUser.UserId); assignment.OnRemove(Database);
assignment.OnRemove(Database, removingUser);
Database.SaveChanges(); Database.SaveChanges();
return Redirect($"{Url.Action(MVC.Device.Show(assignment.DeviceSerialNumber))}#DeviceDetailTab-Flags"); return Redirect($"{Url.Action(MVC.Device.Show(assignment.DeviceSerialNumber))}#DeviceDetailTab-Flags");
@@ -120,4 +118,4 @@ namespace Disco.Web.Areas.API.Controllers
#endregion #endregion
} }
} }
@@ -5,7 +5,9 @@ using Disco.Services.Devices.DeviceFlags;
using Disco.Services.Exporting; using Disco.Services.Exporting;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Disco.Services.Users.UserFlags;
using Disco.Services.Web; using Disco.Services.Web;
using Disco.Web.Areas.API.Models.Shared;
using Disco.Web.Areas.Config.Models.DeviceFlag; using Disco.Web.Areas.Config.Models.DeviceFlag;
using Disco.Web.Extensions; using Disco.Web.Extensions;
using System; using System;
@@ -467,6 +469,24 @@ namespace Disco.Web.Areas.API.Controllers
return RedirectToAction(MVC.Config.Export.Create(savedExport.Id)); return RedirectToAction(MVC.Config.Export.Create(savedExport.Id));
} }
[DiscoAuthorize(Claims.Config.DeviceFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Permission(int id, FlagPermissionModel model = null)
{
var deviceFlag = Database.DeviceFlags.Find(id);
if (deviceFlag == null)
return NotFound();
if (model == null || !model.IsOverride)
deviceFlag.Permissions = null;
else
deviceFlag.Permissions = model.ToFlagPermission(deviceFlag);
DeviceFlagService.Update(Database, deviceFlag);
return RedirectToAction(MVC.Config.DeviceFlag.Index(deviceFlag.Id));
}
#endregion #endregion
} }
} }
@@ -4,7 +4,9 @@ using Disco.Services.Authorization;
using Disco.Services.Interop.ActiveDirectory; using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Interop.DiscoServices; using Disco.Services.Interop.DiscoServices;
using Disco.Services.Messaging; using Disco.Services.Messaging;
using Disco.Services.Users;
using Disco.Services.Web; using Disco.Services.Web;
using Disco.Web.Areas.API.Models.Shared;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
@@ -320,38 +322,64 @@ namespace Disco.Web.Areas.API.Controllers
}; };
} }
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure)] [DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure, Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure)]
public virtual ActionResult SearchSubjects(string term) public virtual ActionResult SearchSubjects(string term, bool includeAuthorizationRoles = false)
{ {
var groupResults = ActiveDirectory.SearchADGroups(term).Cast<IADObject>(); var groupResults = ActiveDirectory.SearchADGroups(term).Select(r => SubjectDescriptorModel.FromActiveDirectoryObject(r));
var userResults = ActiveDirectory.SearchADUserAccounts(term, true).Cast<IADObject>(); var userResults = ActiveDirectory.SearchADUserAccounts(term, true).Select(r => SubjectDescriptorModel.FromActiveDirectoryObject(r));
var results = groupResults.Concat(userResults).OrderBy(r => r.SamAccountName) IEnumerable<SubjectDescriptorModel> roleResults;
.Select(r => Models.Shared.SubjectDescriptorModel.FromActiveDirectoryObject(r)).ToList(); if (includeAuthorizationRoles)
{
roleResults = Database.AuthorizationRoles.AsNoTracking().Where(r => r.Name.Contains(term))
.ToList()
.Select(r => SubjectDescriptorModel.FromAuthorizationRole(r));
}
else
roleResults = Enumerable.Empty<SubjectDescriptorModel>();
var results = groupResults.Concat(userResults).Concat(roleResults)
.OrderBy(r => r.Id).ToList();
return Json(results, JsonRequestBehavior.AllowGet); return Json(results, JsonRequestBehavior.AllowGet);
} }
[DiscoAuthorizeAny(Claims.Config.UserFlag.Configure)] [DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.DeviceProfile.Configure, Claims.Config.DocumentTemplate.Configure, Claims.Config.Plugin.Configure, Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure)]
public virtual ActionResult SearchGroupSubjects(string term) public virtual ActionResult SearchGroupSubjects(string term)
{ {
var groupResults = ActiveDirectory.SearchADGroups(term).Cast<IADObject>(); var groupResults = ActiveDirectory.SearchADGroups(term).Cast<IADObject>();
var results = groupResults.OrderBy(r => r.SamAccountName) var results = groupResults.OrderBy(r => r.SamAccountName)
.Select(r => Models.Shared.SubjectDescriptorModel.FromActiveDirectoryObject(r)).ToList(); .Select(r => SubjectDescriptorModel.FromActiveDirectoryObject(r)).ToList();
return Json(results, JsonRequestBehavior.AllowGet); return Json(results, JsonRequestBehavior.AllowGet);
} }
[DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure)] [DiscoAuthorizeAny(Claims.DiscoAdminAccount, Claims.Config.JobQueue.Configure, Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure)]
public virtual ActionResult Subject(string Id) public virtual ActionResult Subject(string Id, bool includeAuthorizationRoles = false)
{ {
if (string.IsNullOrWhiteSpace(Id))
return Json(null, JsonRequestBehavior.AllowGet);
if (Id.StartsWith("[", StringComparison.Ordinal))
{
if (includeAuthorizationRoles && int.TryParse(Id.Trim('[', ']'), out var roleId))
{
var roleName = UserService.GetAuthorizationRoleName(roleId);
if (roleName != null)
{
return Json(SubjectDescriptorModel.FromAuthorizationRole(roleId, roleName), JsonRequestBehavior.AllowGet);
}
}
return Json(null, JsonRequestBehavior.AllowGet);
}
var subject = ActiveDirectory.RetrieveADObject(Id, Quick: true); var subject = ActiveDirectory.RetrieveADObject(Id, Quick: true);
if (subject == null) if (subject == null)
return Json(null, JsonRequestBehavior.AllowGet); return Json(null, JsonRequestBehavior.AllowGet);
else else
return Json(Models.Shared.SubjectDescriptorModel.FromActiveDirectoryObject(subject), JsonRequestBehavior.AllowGet); return Json(SubjectDescriptorModel.FromActiveDirectoryObject(subject), JsonRequestBehavior.AllowGet);
} }
[DiscoAuthorizeAny(Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure, Claims.Config.DeviceProfile.Configure, Claims.Config.DocumentTemplate.Configure)] [DiscoAuthorizeAny(Claims.Config.UserFlag.Configure, Claims.Config.DeviceFlag.Configure, Claims.Config.DeviceProfile.Configure, Claims.Config.DocumentTemplate.Configure)]
@@ -12,7 +12,7 @@ namespace Disco.Web.Areas.API.Controllers
public partial class UserFlagAssignmentController : AuthorizedDatabaseController public partial class UserFlagAssignmentController : AuthorizedDatabaseController
{ {
const string pComments = "comments"; const string pComments = "comments";
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null) public virtual ActionResult Update(int id, string key, string value = null, bool? redirect = null)
{ {
try try
@@ -21,7 +21,9 @@ namespace Disco.Web.Areas.API.Controllers
throw new ArgumentOutOfRangeException(nameof(id)); throw new ArgumentOutOfRangeException(nameof(id));
if (string.IsNullOrEmpty(key)) if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key)); throw new ArgumentNullException(nameof(key));
var userFlagAssignment = Database.UserFlagAssignments.FirstOrDefault(a => a.Id == id); var userFlagAssignment = Database.UserFlagAssignments
.Include(a => a.UserFlag)
.FirstOrDefault(a => a.Id == id);
if (userFlagAssignment != null) if (userFlagAssignment != null)
{ {
switch (key.ToLower()) switch (key.ToLower())
@@ -52,7 +54,7 @@ namespace Disco.Web.Areas.API.Controllers
} }
#region Update Shortcut Methods #region Update Shortcut Methods
[DiscoAuthorizeAny(Claims.User.Actions.EditFlags)] [HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null) public virtual ActionResult UpdateComments(int id, string Comments = null, bool? redirect = null)
{ {
return Update(id, pComments, Comments, redirect); return Update(id, pComments, Comments, redirect);
@@ -60,19 +62,19 @@ namespace Disco.Web.Areas.API.Controllers
#endregion #endregion
#region Update Properties #region Update Properties
private void UpdateComments(UserFlagAssignment userFlagAssignment, string Comments) private void UpdateComments(UserFlagAssignment userFlagAssignment, string comments)
{ {
if (!userFlagAssignment.CanEditComments()) if (!userFlagAssignment.CanEdit())
throw new InvalidOperationException("Editing comments for user flags is denied"); throw new InvalidOperationException("Editing comments for user flags is denied");
userFlagAssignment.OnEditComments(Comments); userFlagAssignment.OnEdit(comments);
Database.SaveChanges(); Database.SaveChanges();
} }
#endregion #endregion
#region Actions #region Actions
[DiscoAuthorizeAny(Claims.User.Actions.AddFlags)] [HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult AddUser(int id, string UserId, string Comments) public virtual ActionResult AddUser(int id, string UserId, string Comments)
{ {
Database.Configuration.LazyLoadingEnabled = true; Database.Configuration.LazyLoadingEnabled = true;
@@ -86,32 +88,30 @@ namespace Disco.Web.Areas.API.Controllers
throw new ArgumentException("Invalid User Id", nameof(UserId)); throw new ArgumentException("Invalid User Id", nameof(UserId));
if (!user.CanAddUserFlag(userFlag)) if (!user.CanAddUserFlag(userFlag))
throw new InvalidOperationException("Adding user flag is denied"); return Unauthorized("Adding user flag is denied");
var addingUser = Database.Users.Find(CurrentUser.UserId); var userFlagAssignment = user.OnAddUserFlag(Database, userFlag, Comments);
var userFlagAssignment = user.OnAddUserFlag(Database, userFlag, addingUser, Comments);
Database.SaveChanges(); Database.SaveChanges();
return Redirect($"{Url.Action(MVC.User.Show(user.UserId))}#UserDetailTab-Flags"); return Redirect($"{Url.Action(MVC.User.Show(user.UserId))}#UserDetailTab-Flags");
} }
[DiscoAuthorizeAny(Claims.User.Actions.RemoveFlags)] [HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult RemoveUser(int id) public virtual ActionResult RemoveUser(int id)
{ {
Database.Configuration.LazyLoadingEnabled = true; Database.Configuration.LazyLoadingEnabled = true;
var userFlagAssignment = Database.UserFlagAssignments.FirstOrDefault(a => a.Id == id); var userFlagAssignment = Database.UserFlagAssignments
.Include(a => a.UserFlag)
.FirstOrDefault(a => a.Id == id);
if (userFlagAssignment == null) if (userFlagAssignment == null)
throw new ArgumentException("Invalid User Flag Assignment Id", nameof(id)); throw new ArgumentException("Invalid User Flag Assignment Id", nameof(id));
if (!userFlagAssignment.CanRemove()) if (!userFlagAssignment.CanRemove())
throw new InvalidOperationException("Removing user flag assignment is denied"); return Unauthorized("Removing user flag assignment is denied");
var removingUser = Database.Users.Find(CurrentUser.UserId); userFlagAssignment.OnRemove(Database);
userFlagAssignment.OnRemove(Database, removingUser);
Database.SaveChanges(); Database.SaveChanges();
return Redirect($"{Url.Action(MVC.User.Show(userFlagAssignment.UserId))}#UserDetailTab-Flags"); return Redirect($"{Url.Action(MVC.User.Show(userFlagAssignment.UserId))}#UserDetailTab-Flags");
@@ -120,4 +120,4 @@ namespace Disco.Web.Areas.API.Controllers
#endregion #endregion
} }
} }
@@ -6,6 +6,7 @@ using Disco.Services.Interop.ActiveDirectory;
using Disco.Services.Tasks; using Disco.Services.Tasks;
using Disco.Services.Users.UserFlags; using Disco.Services.Users.UserFlags;
using Disco.Services.Web; using Disco.Services.Web;
using Disco.Web.Areas.API.Models.Shared;
using Disco.Web.Areas.Config.Models.UserFlag; using Disco.Web.Areas.Config.Models.UserFlag;
using Disco.Web.Extensions; using Disco.Web.Extensions;
using System; using System;
@@ -467,6 +468,24 @@ namespace Disco.Web.Areas.API.Controllers
return RedirectToAction(MVC.Config.Export.Create(savedExport.Id)); return RedirectToAction(MVC.Config.Export.Create(savedExport.Id));
} }
[DiscoAuthorize(Claims.Config.UserFlag.Configure)]
[HttpPost, ValidateAntiForgeryToken]
public virtual ActionResult Permission(int id, FlagPermissionModel model = null)
{
var userFlag = Database.UserFlags.Find(id);
if (userFlag == null)
return NotFound();
if (model == null || !model.IsOverride)
userFlag.Permissions = null;
else
userFlag.Permissions = model.ToFlagPermission(userFlag);
UserFlagService.Update(Database, userFlag);
return RedirectToAction(MVC.Config.UserFlag.Index(userFlag.Id));
}
#endregion #endregion
} }
} }
@@ -0,0 +1,21 @@
using Disco.Models.Repository;
using System.Collections.Generic;
namespace Disco.Web.Areas.API.Models.Shared
{
public class FlagPermissionModel
{
public bool IsOverride { get; set; }
public bool Inherit { get; set; }
public List<string> CanShow { get; set; }
public List<string> CanAssign { get; set; }
public List<string> CanEdit { get; set; }
public List<string> CanRemove { get; set; }
public FlagPermission ToFlagPermission(UserFlag userFlag)
=> FlagPermission.Create(userFlag, Inherit, CanShow, CanAssign, CanEdit, CanRemove);
public FlagPermission ToFlagPermission(DeviceFlag deviceFlag)
=> FlagPermission.Create(deviceFlag, Inherit, CanShow, CanAssign, CanEdit, CanRemove);
}
}
@@ -1,4 +1,5 @@
using Disco.Services.Interop.ActiveDirectory; using Disco.Models.Repository;
using Disco.Services.Interop.ActiveDirectory;
namespace Disco.Web.Areas.API.Models.Shared namespace Disco.Web.Areas.API.Models.Shared
{ {
@@ -43,5 +44,19 @@ namespace Disco.Web.Areas.API.Models.Shared
return item; return item;
} }
public static SubjectDescriptorModel FromAuthorizationRole(int roleId, string roleName)
{
return new SubjectDescriptorModel()
{
Id = $"[{roleId}]",
Name = roleName,
Type = "role",
IsGroup = true
};
}
public static SubjectDescriptorModel FromAuthorizationRole(AuthorizationRole role)
=> FromAuthorizationRole(role.Id, role.Name);
} }
} }
@@ -47,6 +47,9 @@ namespace Disco.Web.Areas.Config.Controllers
m.ThemeColours = UIHelpers.ThemeColours; m.ThemeColours = UIHelpers.ThemeColours;
} }
var (_, permission) = DeviceFlagService.GetDeviceFlag(m.DeviceFlag.Id);
m.Permission = permission;
// UI Extensions // UI Extensions
UIExtensions.ExecuteExtensions<ConfigDeviceFlagShowModel>(ControllerContext, m); UIExtensions.ExecuteExtensions<ConfigDeviceFlagShowModel>(ControllerContext, m);
@@ -121,7 +124,7 @@ namespace Disco.Web.Areas.Config.Controllers
var m = new ExportModel() var m = new ExportModel()
{ {
Options = Database.DiscoConfiguration.DeviceFlags.LastExportOptions, Options = Database.DiscoConfiguration.DeviceFlags.LastExportOptions,
DeviceFlags = DeviceFlagService.GetDeviceFlags(), DeviceFlags = DeviceFlagService.GetDeviceFlags().Select(f => f.flag).ToList(),
}; };
m.Fields = ExportFieldsModel.Create(m.Options, DeviceFlagExportOptions.DefaultOptions(), nameof(DeviceFlagExportOptions.CurrentOnly)); m.Fields = ExportFieldsModel.Create(m.Options, DeviceFlagExportOptions.DefaultOptions(), nameof(DeviceFlagExportOptions.CurrentOnly));
@@ -46,6 +46,9 @@ namespace Disco.Web.Areas.Config.Controllers
m.ThemeColours = UIHelpers.ThemeColours; m.ThemeColours = UIHelpers.ThemeColours;
} }
var (flag, permission) = UserFlagService.GetUserFlag(m.UserFlag.Id);
m.Permission = permission;
// UI Extensions // UI Extensions
UIExtensions.ExecuteExtensions<ConfigUserFlagShowModel>(ControllerContext, m); UIExtensions.ExecuteExtensions<ConfigUserFlagShowModel>(ControllerContext, m);
@@ -122,7 +125,7 @@ namespace Disco.Web.Areas.Config.Controllers
var m = new ExportModel() var m = new ExportModel()
{ {
Options = Database.DiscoConfiguration.UserFlags.LastExportOptions, Options = Database.DiscoConfiguration.UserFlags.LastExportOptions,
UserFlags = UserFlagService.GetUserFlags(), UserFlags = UserFlagService.GetUserFlags().Select(f => f.flag).ToList(),
}; };
m.Fields = ExportFieldsModel.Create(m.Options, UserFlagExportOptions.DefaultOptions(), nameof(UserFlagExportOptions.CurrentOnly)); m.Fields = ExportFieldsModel.Create(m.Options, UserFlagExportOptions.DefaultOptions(), nameof(UserFlagExportOptions.CurrentOnly));
@@ -1,4 +1,5 @@
using Disco.Models.UI.Config.DeviceFlag; using Disco.Models.Repository;
using Disco.Models.UI.Config.DeviceFlag;
using Disco.Services.Devices.DeviceFlags; using Disco.Services.Devices.DeviceFlags;
using System.Collections.Generic; using System.Collections.Generic;
@@ -16,5 +17,7 @@ namespace Disco.Web.Areas.Config.Models.DeviceFlag
public IEnumerable<KeyValuePair<string, string>> Icons { get; set; } public IEnumerable<KeyValuePair<string, string>> Icons { get; set; }
public IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; } public IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; }
public FlagPermission Permission { get; set; }
} }
} }
@@ -1,4 +1,5 @@
using Disco.Models.UI.Config.UserFlag; using Disco.Models.Repository;
using Disco.Models.UI.Config.UserFlag;
using Disco.Services.Users.UserFlags; using Disco.Services.Users.UserFlags;
using System.Collections.Generic; using System.Collections.Generic;
@@ -16,5 +17,7 @@ namespace Disco.Web.Areas.Config.Models.UserFlag
public IEnumerable<KeyValuePair<string, string>> Icons { get; set; } public IEnumerable<KeyValuePair<string, string>> Icons { get; set; }
public IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; } public IEnumerable<KeyValuePair<string, string>> ThemeColours { get; set; }
public FlagPermission Permission { get; set; }
} }
} }
@@ -237,7 +237,7 @@
<div id="Config_AuthRoles_Claims_Tree"> <div id="Config_AuthRoles_Claims_Tree">
</div> </div>
<div> <div>
<button type="button" id="Config_AuthRoles_Claims_SaveChanges" class="button small disabled" data-saveurl="@Url.Action(MVC.API.AuthorizationRole.UpdateClaims(Model.Token.Role.Id))">Save Changes</button>@AjaxHelpers.AjaxLoader() <button type="button" typeof="button" id="Config_AuthRoles_Claims_SaveChanges" class="button small disabled" data-saveurl="@Url.Action(MVC.API.AuthorizationRole.UpdateClaims(Model.Token.Role.Id))">Save Changes</button>@AjaxHelpers.AjaxLoader()
</div> </div>
<script id="Config_AuthRoles_Claims_NodesJson" type="application/json"> <script id="Config_AuthRoles_Claims_NodesJson" type="application/json">
@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.ClaimNavigatorFancyTreeNodes)) @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.ClaimNavigatorFancyTreeNodes))
@@ -286,7 +286,7 @@
saveButton.addClass('disabled'); saveButton.addClass('disabled');
ajaxLoading.next('.ajaxOk').show().delay('fast').fadeOut('slow'); ajaxLoading.next('.ajaxOk').show().delay('fast').fadeOut('slow');
} else { } else {
alert('Unable to save changes:\n' + response); alert('Unable to save changes:\n' + response.statusText);
} }
} catch (e) { } catch (e) {
alert('Error: ' + e); alert('Error: ' + e);
@@ -656,6 +656,8 @@ WriteLiteral(">\r\n </div>\r\n <div>\r\n
WriteLiteral(" type=\"button\""); WriteLiteral(" type=\"button\"");
WriteLiteral(" typeof=\"button\"");
WriteLiteral(" id=\"Config_AuthRoles_Claims_SaveChanges\""); WriteLiteral(" id=\"Config_AuthRoles_Claims_SaveChanges\"");
WriteLiteral(" class=\"button small disabled\""); WriteLiteral(" class=\"button small disabled\"");
@@ -664,7 +666,7 @@ WriteLiteral(" data-saveurl=\"");
#line 240 "..\..\Areas\Config\Views\AuthorizationRole\Show.cshtml" #line 240 "..\..\Areas\Config\Views\AuthorizationRole\Show.cshtml"
Write(Url.Action(MVC.API.AuthorizationRole.UpdateClaims(Model.Token.Role.Id))); Write(Url.Action(MVC.API.AuthorizationRole.UpdateClaims(Model.Token.Role.Id)));
#line default #line default
@@ -675,7 +677,7 @@ WriteLiteral(">Save Changes</button>");
#line 240 "..\..\Areas\Config\Views\AuthorizationRole\Show.cshtml" #line 240 "..\..\Areas\Config\Views\AuthorizationRole\Show.cshtml"
Write(AjaxHelpers.AjaxLoader()); Write(AjaxHelpers.AjaxLoader());
#line default #line default
@@ -728,13 +730,13 @@ WriteLiteral("\r\n </script>\r\n <script>\r\n
"dClass(\'disabled\');\r\n ajaxLoading.nex" + "dClass(\'disabled\');\r\n ajaxLoading.nex" +
"t(\'.ajaxOk\').show().delay(\'fast\').fadeOut(\'slow\');\r\n " + "t(\'.ajaxOk\').show().delay(\'fast\').fadeOut(\'slow\');\r\n " +
" } else {\r\n alert(\'Unable " + " } else {\r\n alert(\'Unable " +
"to save changes:\\n\' + response);\r\n }\r\n " + "to save changes:\\n\' + response.statusText);\r\n " +
" } catch (e) {\r\n " + " }\r\n } catch (e) {\r\n " +
" alert(\'Error: \' + e);\r\n }\r\n " + " alert(\'Error: \' + e);\r\n }\r" +
" ajaxLoading.hide();\r\n }" + "\n ajaxLoading.hide();\r\n " +
"\r\n });\r\n });\r\n " + " }\r\n });\r\n });\r\n " +
" })();\r\n </script>\r\n </td>\r\n </tr>\r\n </ta" + " })();\r\n </script>\r\n </td>\r\n </tr" +
"ble>\r\n</div>\r\n<div"); ">\r\n </table>\r\n</div>\r\n<div");
WriteLiteral(" class=\"actionBar\""); WriteLiteral(" class=\"actionBar\"");
@@ -15,6 +15,7 @@
var canExportAll = Model.TotalAssignmentCount > 0 && Authorization.Has(Claims.Config.DeviceFlag.Export); var canExportAll = Model.TotalAssignmentCount > 0 && Authorization.Has(Claims.Config.DeviceFlag.Export);
var hideAdvanced = var hideAdvanced =
Model.Permission.IsDefault() &&
Model.DeviceFlag.DevicesLinkedGroup == null && Model.DeviceFlag.DevicesLinkedGroup == null &&
Model.DeviceFlag.DeviceUsersLinkedGroup == null && Model.DeviceFlag.DeviceUsersLinkedGroup == null &&
Model.DeviceFlag.OnAssignmentExpression == null && Model.DeviceFlag.OnAssignmentExpression == null &&
@@ -38,10 +39,11 @@
</th> </th>
<td> <td>
@if (canConfig) @if (canConfig)
{@Html.EditorFor(model => model.DeviceFlag.Name) {
@AjaxHelpers.AjaxSave() @Html.EditorFor(model => model.DeviceFlag.Name)
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxSave()
<script type="text/javascript"> @AjaxHelpers.AjaxLoader()
<script type="text/javascript">
$(function () { $(function () {
document.DiscoFunctions.PropertyChangeHelper( document.DiscoFunctions.PropertyChangeHelper(
$('#DeviceFlag_Name'), $('#DeviceFlag_Name'),
@@ -50,12 +52,12 @@
'FlagName' 'FlagName'
); );
}); });
</script> </script>
} }
else else
{ {
@Model.DeviceFlag.Name @Model.DeviceFlag.Name
} }
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -227,6 +229,340 @@
</td> </td>
</tr> </tr>
} }
<tr class="Config_HideAdvanced_Item">
<th>
Assignment Permission<br />
Override:
</th>
<td>
@if (!Model.Permission.IsDefault())
{
var permission = Model.Permission;
<div>
@if (permission.Inherit)
{
<span><i class="fa fa-check-square-o"></i> Inheriting from Authorization Roles</span>
}
else
{
<span><i class="fa fa-square-o"></i> Authorization Roles are Ignored</span>
}
</div>
if (!permission.HasSubjects())
{
<span class="smallMessage">There are no users/groups associated with this permission override</span>
}
else
{
if (permission.IsSimple())
{
<table class="tableData">
<thead>
<tr>
<th>Users/Groups/Roles</th>
</tr>
</thead>
<tbody>
@foreach (var subjectId in permission.CanShowSubjectIds)
{
<tr>
<td>
@{
int roleId;
if (subjectId.StartsWith("[") && int.TryParse(subjectId.Trim('[', ']'), out roleId))
{
<span>@Disco.Services.Users.UserService.GetAuthorizationRoleName(roleId) @subjectId</span>
}
else
{
<span>@subjectId</span>
}
}
</td>
</tr>
}
</tbody>
</table>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-fw fa-info-circle"></i> All users/groups/roles can view, assign, edit assignments, and remove assignments for this flag.
</p>
</div>
}
else
{
var subjects = permission.AllSubjects();
<table class="tableData">
<thead>
<tr>
<th>Users/Groups/Roles</th>
<th>View</th>
<th>Assign</th>
<th>Edit</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
@foreach (var subjectId in subjects.OrderBy(s => s))
{
<tr>
<td>
<i class="fa"></i> @{
int roleId;
if (subjectId.StartsWith("[") && int.TryParse(subjectId.Trim('[', ']'), out roleId))
{
<span>@Disco.Services.Users.UserService.GetAuthorizationRoleName(roleId) @subjectId</span>
}
else
{
<span>@subjectId</span>
}
}
</td>
<td>
@if (permission.CanShowSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
<td>
@if (permission.CanAssignSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
<td>
@if (permission.CanEditSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
<td>
@if (permission.CanRemoveSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
</tr>
}
</tbody>
</table>
}
}
}
@if (canConfig)
{
var permission = Model.Permission;
<button id="Config_Flag_Permission_Edit" class="button small">@(permission.IsDefault() ? "Override" : "Edit") Permission</button>
<div id="Config_Flag_Permissions" class="dialog" title="Flag Assignment Permission Override">
@using (Html.BeginForm(MVC.API.DeviceFlag.Permission(Model.DeviceFlag.Id)))
{
@Html.AntiForgeryToken()
<input type="hidden" name="IsOverride" value="true" />
<div id="Config_Flag_Permissions_Inherit_Container">
<label>
<input id="Config_Flag_Permissions_Inherit" type="checkbox" name="Inherit" value="true" @(permission.Inherit ? "checked" : null) /> Inherit Authorization from Authorization Roles
</label>
</div>
<div class="tableDataContainer">
<table class="tableData">
<thead>
<tr>
<th>User/Group/Role</th>
<th>View</th>
<th>Assign</th>
<th>Edit</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
@{
var subjects = permission.AllSubjects();
foreach (var subjectId in subjects.OrderBy(s => s))
{
<tr data-subjectid="@subjectId">
<td><i class="fa type"></i> <span>@subjectId</span><i class="fa fa-times-circle remove"></i></td>
<td>
<input type="checkbox" name="CanShow" value="@subjectId" @(permission.CanShowSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
<td>
<input type="checkbox" name="CanAssign" value="@subjectId" @(permission.CanAssignSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
<td>
<input type="checkbox" name="CanEdit" value="@subjectId" @(permission.CanEditSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
<td>
<input type="checkbox" name="CanRemove" value="@subjectId" @(permission.CanRemoveSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
</tr>
}
}
</tbody>
</table>
</div>
<div>
<input type="text" id="Config_Flag_Permissions_Subject_Input" placeholder="Search Users/Groups/Roles" data-autocompleteurl="@(Url.Action(MVC.API.System.SearchSubjects(null, includeAuthorizationRoles: true)))" />
<button type="button" id="Config_Flag_Permissions_Subject_Add" class="button small" data-subjecturl="@Url.Action(MVC.API.System.Subject(null, includeAuthorizationRoles: true))">Add</button>
</div>
}
</div>
<script>
$(function () {
let $dialog = null;
let originalSubjects = null;
let originalInherit = null;
$('#Config_Flag_Permission_Edit').on('click', async function () {
if (!$dialog) {
$dialog = $('#Config_Flag_Permissions');
const $tbody = $dialog.find('tbody');
const $inherit = $dialog.find('#Config_Flag_Permissions_Inherit');
const $input = $dialog.find('#Config_Flag_Permissions_Subject_Input');
const $add = $dialog.find('#Config_Flag_Permissions_Subject_Add');
$dialog.dialog({
resizable: false,
modal: true,
autoOpen: false,
width: 550,
height: 420,
buttons: {
Cancel: function () {
$(this).dialog('close');
$tbody.html(originalSubjects);
$inherit.prop('checked', originalInherit);
},
'Remove Override': function () {
const $this = $(this);
$(this).dialog('option', 'buttons', null);
$this.find('input[name="IsOverride"]').val('false');
$this.find('form').trigger('submit');
},
'Save Changes': function () {
$(this).dialog('option', 'buttons', null);
$(this).find('form').trigger('submit');
}
}
});
$tbody.on('click', 'i.remove', function () {
$(this).closest('tr').remove();
});
$input
.autocomplete({
source: $input.attr('data-autocompleteurl'),
minLength: 2,
focus: function (e, ui) {
$input.val(ui.item.Id);
return false;
},
select: function (e, ui) {
$input.val(ui.item.Id).blur();
$add.trigger('click');
$input.val('');
return false;
}
}).data('ui-autocomplete')._renderItem = function (ul, item) {
return $("<li></li>")
.data('item.autocomplete', item)
.append('<a><strong>' + item.Name + '</strong><br>' + item.Id + ' (' + item.Type + ')</a>')
.appendTo(ul);
};
$add.on('click', async function () {
const value = $input.val();
if (!value) {
$input.focus();
return;
}
const existing = $tbody.find('tr').filter(function () {
return $(this).attr('data-subjectid') === value;
});
if (existing.length !== 0) {
$input.val('');
$input.focus();
return;
}
const body = new FormData();
body.append('id', value);
const response = await fetch($add.attr('data-subjecturl'), {
body: body,
method: 'POST'
});
if (!response.ok) {
alert('Unable to lookup User/Group/Role: ' + response.statusText);
$input.focus();
return;
}
const subject = await response.json();
if (!subject) {
alert('Invalid User/Group/Role');
$input.focus();
return;
}
const $record = $('<tr><td><i class="fa type"></i> <span></span><i class="fa fa-times-circle remove"></i></td><td><input type="checkbox" name="CanShow" checked /></td><td><input type="checkbox" name="CanAssign" checked /></td><td><input type="checkbox" name="CanEdit" checked /></td><td><input type="checkbox" name="CanRemove" checked /></td></tr>');
$record.attr('data-subjectid', subject.Id);
$record.find('span').text(subject.Name + ' ' + subject.Id);
$record.find('i.type').addClass(subject.Type === 'role' ? 'fa-lock' : subject.IsGroup ? 'fa-users' : 'fa-user');
$record.find('input').val(subject.Id);
$tbody.append($record);
$input.val('');
$input.focus();
});
const $records = $tbody.find('tr');
for (var i = 0; i < $records.length; i++) {
const $record = $($records[i]);
const body = new FormData();
body.append('id', $record.attr('data-subjectid'));
const response = await fetch($add.attr('data-subjecturl'), {
body: body,
method: 'POST'
});
if (response.ok) {
const subject = await response.json();
if (subject) {
$record.find('span').text(subject.Name + ' ' + subject.Id);
$record.find('i.type').addClass(subject.Type === 'role' ? 'fa-lock' : subject.IsGroup ? 'fa-users' : 'fa-user');
continue;
}
}
$record.remove();
}
originalInherit = $inherit.prop('checked');
originalSubjects = $tbody.html();
$dialog.dialog('open');
} else {
$dialog.dialog('open');
}
});
});
</script>
}
<div class="info-box">
<p class="fa-p">
<i class="fa fa-fw fa-info-circle"></i> Flag actions are normally authorized globally by
@if (Authorization.Has(Claims.DiscoAdminAccount))
{
<span><a href="@Url.Action(MVC.Config.AuthorizationRole.Index(null))">Authorization Roles</a>.</span>
}
else
{
<span>Authorization Roles.</span>
}
Overriding individual flag permissions allows for targeted authorization.
</p>
</div>
</td>
</tr>
<tr class="Config_HideAdvanced_Item"> <tr class="Config_HideAdvanced_Item">
<th> <th>
On Assignment<br />Expression: On Assignment<br />Expression:
File diff suppressed because it is too large Load Diff
@@ -15,6 +15,7 @@
var canExportAll = Model.TotalAssignmentCount > 0 && Authorization.Has(Claims.Config.UserFlag.Export); var canExportAll = Model.TotalAssignmentCount > 0 && Authorization.Has(Claims.Config.UserFlag.Export);
var hideAdvanced = var hideAdvanced =
Model.Permission.IsDefault() &&
Model.UserFlag.UserDevicesLinkedGroup == null && Model.UserFlag.UserDevicesLinkedGroup == null &&
Model.UserFlag.UsersLinkedGroup == null && Model.UserFlag.UsersLinkedGroup == null &&
Model.UserFlag.OnAssignmentExpression == null && Model.UserFlag.OnAssignmentExpression == null &&
@@ -229,6 +230,340 @@
</td> </td>
</tr> </tr>
} }
<tr class="Config_HideAdvanced_Item">
<th>
Assignment Permission<br />
Override:
</th>
<td>
@if (!Model.Permission.IsDefault())
{
var permission = Model.Permission;
<div>
@if (permission.Inherit)
{
<span><i class="fa fa-check-square-o"></i> Inheriting from Authorization Roles</span>
}
else
{
<span><i class="fa fa-square-o"></i> Authorization Roles are Ignored</span>
}
</div>
if (!permission.HasSubjects())
{
<span class="smallMessage">There are no users/groups associated with this permission override</span>
}
else
{
if (permission.IsSimple())
{
<table class="tableData">
<thead>
<tr>
<th>Users/Groups/Roles</th>
</tr>
</thead>
<tbody>
@foreach (var subjectId in permission.CanShowSubjectIds)
{
<tr>
<td>
@{
int roleId;
if (subjectId.StartsWith("[") && int.TryParse(subjectId.Trim('[', ']'), out roleId))
{
<span>@Disco.Services.Users.UserService.GetAuthorizationRoleName(roleId) @subjectId</span>
}
else
{
<span>@subjectId</span>
}
}
</td>
</tr>
}
</tbody>
</table>
<div class="info-box">
<p class="fa-p">
<i class="fa fa-fw fa-info-circle"></i> All users/groups/roles can view, assign, edit assignments, and remove assignments for this flag.
</p>
</div>
}
else
{
var subjects = permission.AllSubjects();
<table class="tableData">
<thead>
<tr>
<th>Users/Groups/Roles</th>
<th>View</th>
<th>Assign</th>
<th>Edit</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
@foreach (var subjectId in subjects.OrderBy(s => s))
{
<tr>
<td>
<i class="fa"></i> @{
int roleId;
if (subjectId.StartsWith("[") && int.TryParse(subjectId.Trim('[', ']'), out roleId))
{
<span>@Disco.Services.Users.UserService.GetAuthorizationRoleName(roleId) @subjectId</span>
}
else
{
<span>@subjectId</span>
}
}
</td>
<td>
@if (permission.CanShowSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
<td>
@if (permission.CanAssignSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
<td>
@if (permission.CanEditSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
<td>
@if (permission.CanRemoveSubjectIds.Contains(subjectId))
{
<i class="fa fa-fw fa-check"></i>
}
</td>
</tr>
}
</tbody>
</table>
}
}
}
@if (canConfig)
{
var permission = Model.Permission;
<button id="Config_Flag_Permission_Edit" class="button small">@(permission.IsDefault() ? "Override" : "Edit") Permission</button>
<div id="Config_Flag_Permissions" class="dialog" title="Flag Assignment Permission Override">
@using (Html.BeginForm(MVC.API.UserFlag.Permission(Model.UserFlag.Id)))
{
@Html.AntiForgeryToken()
<input type="hidden" name="IsOverride" value="true" />
<div id="Config_Flag_Permissions_Inherit_Container">
<label>
<input id="Config_Flag_Permissions_Inherit" type="checkbox" name="Inherit" value="true" @(permission.Inherit ? "checked" : null) /> Inherit Authorization from Authorization Roles
</label>
</div>
<div class="tableDataContainer">
<table class="tableData">
<thead>
<tr>
<th>User/Group/Role</th>
<th>View</th>
<th>Assign</th>
<th>Edit</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
@{
var subjects = permission.AllSubjects();
foreach (var subjectId in subjects.OrderBy(s => s))
{
<tr data-subjectid="@subjectId">
<td><i class="fa type"></i> <span>@subjectId</span><i class="fa fa-times-circle remove"></i></td>
<td>
<input type="checkbox" name="CanShow" value="@subjectId" @(permission.CanShowSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
<td>
<input type="checkbox" name="CanAssign" value="@subjectId" @(permission.CanAssignSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
<td>
<input type="checkbox" name="CanEdit" value="@subjectId" @(permission.CanEditSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
<td>
<input type="checkbox" name="CanRemove" value="@subjectId" @(permission.CanRemoveSubjectIds.Contains(subjectId) ? " checked" : null) />
</td>
</tr>
}
}
</tbody>
</table>
</div>
<div>
<input type="text" id="Config_Flag_Permissions_Subject_Input" placeholder="Search Users/Groups" data-autocompleteurl="@(Url.Action(MVC.API.System.SearchSubjects(null, includeAuthorizationRoles: true)))" />
<button type="button" id="Config_Flag_Permissions_Subject_Add" class="button small" data-subjecturl="@Url.Action(MVC.API.System.Subject(null, includeAuthorizationRoles: true))">Add</button>
</div>
}
</div>
<script>
$(function () {
let $dialog = null;
let originalSubjects = null;
let originalInherit = null;
$('#Config_Flag_Permission_Edit').on('click', async function () {
if (!$dialog) {
$dialog = $('#Config_Flag_Permissions');
const $tbody = $dialog.find('tbody');
const $inherit = $dialog.find('#Config_Flag_Permissions_Inherit');
const $input = $dialog.find('#Config_Flag_Permissions_Subject_Input');
const $add = $dialog.find('#Config_Flag_Permissions_Subject_Add');
$dialog.dialog({
resizable: false,
modal: true,
autoOpen: false,
width: 550,
height: 420,
buttons: {
Cancel: function () {
$(this).dialog('close');
$tbody.html(originalSubjects);
$inherit.prop('checked', originalInherit);
},
'Remove Override': function () {
const $this = $(this);
$(this).dialog('option', 'buttons', null);
$this.find('input[name="IsOverride"]').val('false');
$this.find('form').trigger('submit');
},
'Save Changes': function () {
$(this).dialog('option', 'buttons', null);
$(this).find('form').trigger('submit');
}
}
});
$tbody.on('click', 'i.remove', function () {
$(this).closest('tr').remove();
});
$input
.autocomplete({
source: $input.attr('data-autocompleteurl'),
minLength: 2,
focus: function (e, ui) {
$input.val(ui.item.Id);
return false;
},
select: function (e, ui) {
$input.val(ui.item.Id).blur();
$add.trigger('click');
$input.val('');
return false;
}
}).data('ui-autocomplete')._renderItem = function (ul, item) {
return $("<li></li>")
.data('item.autocomplete', item)
.append('<a><strong>' + item.Name + '</strong><br>' + item.Id + ' (' + item.Type + ')</a>')
.appendTo(ul);
};
$add.on('click', async function () {
const value = $input.val();
if (!value) {
$input.focus();
return;
}
const existing = $tbody.find('tr').filter(function () {
return $(this).attr('data-subjectid') === value;
});
if (existing.length !== 0) {
$input.val('');
$input.focus();
return;
}
const body = new FormData();
body.append('id', value);
const response = await fetch($add.attr('data-subjecturl'), {
body: body,
method: 'POST'
});
if (!response.ok) {
alert('Unable to lookup User/Group/Role: ' + response.statusText);
$input.focus();
return;
}
const subject = await response.json();
if (!subject) {
alert('Invalid User/Group');
$input.focus();
return;
}
const $record = $('<tr><td><i class="fa type"></i> <span></span><i class="fa fa-times-circle remove"></i></td><td><input type="checkbox" name="CanShow" checked /></td><td><input type="checkbox" name="CanAssign" checked /></td><td><input type="checkbox" name="CanEdit" checked /></td><td><input type="checkbox" name="CanRemove" checked /></td></tr>');
$record.attr('data-subjectid', subject.Id);
$record.find('span').text(subject.Name + ' ' + subject.Id);
$record.find('i.type').addClass(subject.Type === 'role' ? 'fa-lock' : subject.IsGroup ? 'fa-users' : 'fa-user');
$record.find('input').val(subject.Id);
$tbody.append($record);
$input.val('');
$input.focus();
});
const $records = $tbody.find('tr');
for (var i = 0; i < $records.length; i++) {
const $record = $($records[i]);
const body = new FormData();
body.append('id', $record.attr('data-subjectid'));
const response = await fetch($add.attr('data-subjecturl'), {
body: body,
method: 'POST'
});
if (response.ok) {
const subject = await response.json();
if (subject) {
$record.find('span').text(subject.Name + ' ' + subject.Id);
$record.find('i.type').addClass(subject.Type === 'role' ? 'fa-lock' : subject.IsGroup ? 'fa-users' : 'fa-user');
continue;
}
}
$record.remove();
}
originalInherit = $inherit.prop('checked');
originalSubjects = $tbody.html();
$dialog.dialog('open');
} else {
$dialog.dialog('open');
}
});
});
</script>
}
<div class="info-box">
<p class="fa-p">
<i class="fa fa-fw fa-info-circle"></i> Flag actions are normally authorized globally by
@if (Authorization.Has(Claims.DiscoAdminAccount))
{
<span><a href="@Url.Action(MVC.Config.AuthorizationRole.Index(null))">Authorization Roles</a>.</span>
}
else
{
<span>Authorization Roles.</span>
}
Overriding individual flag permissions allows for targeted authorization.
</p>
</div>
</td>
</tr>
<tr class="Config_HideAdvanced_Item"> <tr class="Config_HideAdvanced_Item">
<th> <th>
On Assignment<br />Expression: On Assignment<br />Expression:
@@ -369,7 +704,6 @@
</div> </div>
</td> </td>
</tr> </tr>
<tr class="Config_HideAdvanced_Item"> <tr class="Config_HideAdvanced_Item">
<th> <th>
Linked Groups: Linked Groups:
@@ -605,4 +939,4 @@
@Html.ActionLinkButton(string.Format("Show {0} user{1}", Model.CurrentAssignmentCount, (Model.CurrentAssignmentCount == 1 ? null : "s")), MVC.Search.Query(Model.UserFlag.Id.ToString(), "UserFlag"), "Config_UserFlags_Actions_ShowUsers_Button") @Html.ActionLinkButton(string.Format("Show {0} user{1}", Model.CurrentAssignmentCount, (Model.CurrentAssignmentCount == 1 ? null : "s")), MVC.Search.Query(Model.UserFlag.Id.ToString(), "UserFlag"), "Config_UserFlags_Actions_ShowUsers_Button")
} }
</div> </div>
} }
File diff suppressed because it is too large Load Diff
+17
View File
@@ -1960,6 +1960,23 @@ h1.Config_DocumentTemplates {
#Config_DeviceFlags_BulkAssign_AssignDialog.loading > form { #Config_DeviceFlags_BulkAssign_AssignDialog.loading > form {
display: none; display: none;
} }
#Config_Flag_Permissions #Config_Flag_Permissions_Inherit_Container {
margin: 5px 0;
}
#Config_Flag_Permissions .tableDataContainer {
min-height: 260px;
}
#Config_Flag_Permissions .tableDataContainer td i.remove {
float: right;
cursor: pointer;
visibility: hidden;
color: #e51400;
font-size: 1.4em;
opacity: 0.8;
}
#Config_Flag_Permissions .tableDataContainer td:hover i.remove {
visibility: visible;
}
#DocumentTemplate_BulkGenerate .actions { #DocumentTemplate_BulkGenerate .actions {
padding-bottom: 0.5em; padding-bottom: 0.5em;
text-align: right; text-align: right;
+27
View File
@@ -2354,6 +2354,33 @@ h1.Config_DocumentTemplates {
} }
} }
#Config_Flag_Permissions {
#Config_Flag_Permissions_Inherit_Container {
margin: 5px 0;
}
.tableDataContainer {
min-height: 260px;
td {
i.remove {
float: right;
cursor: pointer;
visibility: hidden;
color: @StatusRemove;
font-size: 1.4em;
opacity: .8;
}
}
td:hover {
i.remove {
visibility: visible;
}
}
}
}
#DocumentTemplate_BulkGenerate { #DocumentTemplate_BulkGenerate {
.actions { .actions {
padding-bottom: .5em; padding-bottom: .5em;
File diff suppressed because one or more lines are too long
+2 -9
View File
@@ -235,6 +235,7 @@ namespace Disco.Web.Controllers
.Include(d => d.DeviceCertificates) .Include(d => d.DeviceCertificates)
.Include(d => d.DeviceAttachments.Select(a => a.TechUser)) .Include(d => d.DeviceAttachments.Select(a => a.TechUser))
.Include(d => d.DeviceAttachments.Select(a => a.DocumentTemplate)) .Include(d => d.DeviceAttachments.Select(a => a.DocumentTemplate))
.Include(d => d.DeviceFlagAssignments.Select(a => a.DeviceFlag))
.Include(d => d.DeviceFlagAssignments.Select(a => a.AddedUser)) .Include(d => d.DeviceFlagAssignments.Select(a => a.AddedUser))
.Include(d => d.DeviceFlagAssignments.Select(a => a.RemovedUser)) .Include(d => d.DeviceFlagAssignments.Select(a => a.RemovedUser))
.FirstOrDefault(d => d.SerialNumber == id); .FirstOrDefault(d => d.SerialNumber == id);
@@ -311,15 +312,7 @@ namespace Disco.Web.Controllers
m.DeviceProfileWirelessProfileProviders = m.Device.DeviceProfile.GetWirelessProfileProviders().ToList(); m.DeviceProfileWirelessProfileProviders = m.Device.DeviceProfile.GetWirelessProfileProviders().ToList();
} }
if (Authorization.Has(Claims.Device.ShowFlagAssignments)) m.AvailableDeviceFlags = DeviceFlagService.GetAvailableDeviceFlags(m.Device).ToList();
{
var usedFlags = m.Device.DeviceFlagAssignments
.Where(a => !a.RemovedDate.HasValue)
.Select(a => a.DeviceFlagId)
.Distinct().ToList();
m.AvailableDeviceFlags = DeviceFlagService.GetDeviceFlags().Where(f => !usedFlags.Contains(f.Id)).ToList();
}
if (Authorization.Has(Claims.User.ShowDetails)) if (Authorization.Has(Claims.User.ShowDetails))
{ {
+2 -9
View File
@@ -61,6 +61,7 @@ namespace Disco.Web.Controllers
.Include(u => u.DeviceUserAssignments.Select(dua => dua.Device.DeviceDetails)) .Include(u => u.DeviceUserAssignments.Select(dua => dua.Device.DeviceDetails))
.Include(u => u.UserAttachments.Select(ua => ua.TechUser)) .Include(u => u.UserAttachments.Select(ua => ua.TechUser))
.Include(u => u.UserAttachments.Select(ua => ua.DocumentTemplate)) .Include(u => u.UserAttachments.Select(ua => ua.DocumentTemplate))
.Include(u => u.UserFlagAssignments.Select(ufa => ufa.UserFlag))
.Include(u => u.UserFlagAssignments.Select(ufa => ufa.AddedUser)) .Include(u => u.UserFlagAssignments.Select(ufa => ufa.AddedUser))
.Include(u => u.UserFlagAssignments.Select(ufa => ufa.RemovedUser)) .Include(u => u.UserFlagAssignments.Select(ufa => ufa.RemovedUser))
.Include(u => u.UserDetails) .Include(u => u.UserDetails)
@@ -84,15 +85,7 @@ namespace Disco.Web.Controllers
m.Jobs.Fill(Database, Services.Searching.Search.BuildJobTableModel(Database).Where(j => j.UserId == id).OrderByDescending(j => j.Id), true); m.Jobs.Fill(Database, Services.Searching.Search.BuildJobTableModel(Database).Where(j => j.UserId == id).OrderByDescending(j => j.Id), true);
} }
if (Authorization.Has(Claims.User.ShowFlagAssignments)) m.AvailableUserFlags = UserFlagService.GetAvailableUserFlags(m.User).ToList();
{
var usedFlags = m.User.UserFlagAssignments
.Where(a => !a.RemovedDate.HasValue)
.Select(a => a.UserFlagId)
.Distinct().ToList();
m.AvailableUserFlags = UserFlagService.GetUserFlags().Where(f => !usedFlags.Contains(f.Id)).ToList();
}
try try
{ {
+1
View File
@@ -227,6 +227,7 @@
<Compile Include="Areas\API\Models\Job\DeviceHeldLocationModel.cs" /> <Compile Include="Areas\API\Models\Job\DeviceHeldLocationModel.cs" />
<Compile Include="Areas\API\Models\Shared\SubjectDescriptorModel.cs" /> <Compile Include="Areas\API\Models\Shared\SubjectDescriptorModel.cs" />
<Compile Include="Areas\API\Models\System\DomainOrganisationalUnitsModel.cs" /> <Compile Include="Areas\API\Models\System\DomainOrganisationalUnitsModel.cs" />
<Compile Include="Areas\API\Models\Shared\FlagPermissionModel.cs" />
<Compile Include="Areas\API\Views\_ViewStart.generated.cs"> <Compile Include="Areas\API\Views\_ViewStart.generated.cs">
<DependentUpon>_ViewStart.cshtml</DependentUpon> <DependentUpon>_ViewStart.cshtml</DependentUpon>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
@@ -143,8 +143,8 @@ namespace Disco.Web.Areas.API.Controllers
public class ActionParamsClass_AddDevice public class ActionParamsClass_AddDevice
{ {
public readonly string id = "id"; public readonly string id = "id";
public readonly string DeviceSerialNumber = "DeviceSerialNumber"; public readonly string deviceSerialNumber = "deviceSerialNumber";
public readonly string Comments = "Comments"; public readonly string comments = "comments";
} }
static readonly ActionParamsClass_RemoveDevice s_params_RemoveDevice = new ActionParamsClass_RemoveDevice(); static readonly ActionParamsClass_RemoveDevice s_params_RemoveDevice = new ActionParamsClass_RemoveDevice();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -203,16 +203,16 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
partial void AddDeviceOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string DeviceSerialNumber, string Comments); partial void AddDeviceOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, string deviceSerialNumber, string comments);
[NonAction] [NonAction]
public override System.Web.Mvc.ActionResult AddDevice(int id, string DeviceSerialNumber, string Comments) public override System.Web.Mvc.ActionResult AddDevice(int id, string deviceSerialNumber, string comments)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.AddDevice); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.AddDevice);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "DeviceSerialNumber", DeviceSerialNumber); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "deviceSerialNumber", deviceSerialNumber);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "Comments", Comments); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "comments", comments);
AddDeviceOverride(callInfo, id, DeviceSerialNumber, Comments); AddDeviceOverride(callInfo, id, deviceSerialNumber, comments);
return callInfo; return callInfo;
} }
@@ -155,6 +155,12 @@ namespace Disco.Web.Areas.API.Controllers
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SaveExport); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SaveExport);
} }
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult Permission()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Permission);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public DeviceFlagController Actions { get { return MVC.API.DeviceFlag; } } public DeviceFlagController Actions { get { return MVC.API.DeviceFlag; } }
@@ -187,6 +193,7 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string Export = "Export"; public readonly string Export = "Export";
public readonly string ExportRetrieve = "ExportRetrieve"; public readonly string ExportRetrieve = "ExportRetrieve";
public readonly string SaveExport = "SaveExport"; public readonly string SaveExport = "SaveExport";
public readonly string Permission = "Permission";
} }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -208,6 +215,7 @@ namespace Disco.Web.Areas.API.Controllers
public const string Export = "Export"; public const string Export = "Export";
public const string ExportRetrieve = "ExportRetrieve"; public const string ExportRetrieve = "ExportRetrieve";
public const string SaveExport = "SaveExport"; public const string SaveExport = "SaveExport";
public const string Permission = "Permission";
} }
@@ -367,6 +375,15 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public readonly string model = "model"; public readonly string model = "model";
} }
static readonly ActionParamsClass_Permission s_params_Permission = new ActionParamsClass_Permission();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Permission PermissionParams { get { return s_params_Permission; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_Permission
{
public readonly string id = "id";
public readonly string model = "model";
}
static readonly ViewsClass s_views = new ViewsClass(); static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } } public ViewsClass Views { get { return s_views; } }
@@ -606,6 +623,19 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void PermissionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, Disco.Web.Areas.API.Models.Shared.FlagPermissionModel model);
[NonAction]
public override System.Web.Mvc.ActionResult Permission(int id, Disco.Web.Areas.API.Models.Shared.FlagPermissionModel model)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Permission);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "model", model);
PermissionOverride(callInfo, id, model);
return callInfo;
}
} }
} }
@@ -308,6 +308,7 @@ namespace Disco.Web.Areas.API.Controllers
public class ActionParamsClass_SearchSubjects public class ActionParamsClass_SearchSubjects
{ {
public readonly string term = "term"; public readonly string term = "term";
public readonly string includeAuthorizationRoles = "includeAuthorizationRoles";
} }
static readonly ActionParamsClass_SearchGroupSubjects s_params_SearchGroupSubjects = new ActionParamsClass_SearchGroupSubjects(); static readonly ActionParamsClass_SearchGroupSubjects s_params_SearchGroupSubjects = new ActionParamsClass_SearchGroupSubjects();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -324,6 +325,7 @@ namespace Disco.Web.Areas.API.Controllers
public class ActionParamsClass_Subject public class ActionParamsClass_Subject
{ {
public readonly string Id = "Id"; public readonly string Id = "Id";
public readonly string includeAuthorizationRoles = "includeAuthorizationRoles";
} }
static readonly ActionParamsClass_SyncActiveDirectoryManagedGroup s_params_SyncActiveDirectoryManagedGroup = new ActionParamsClass_SyncActiveDirectoryManagedGroup(); static readonly ActionParamsClass_SyncActiveDirectoryManagedGroup s_params_SyncActiveDirectoryManagedGroup = new ActionParamsClass_SyncActiveDirectoryManagedGroup();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -587,14 +589,15 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
partial void SearchSubjectsOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string term); partial void SearchSubjectsOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string term, bool includeAuthorizationRoles);
[NonAction] [NonAction]
public override System.Web.Mvc.ActionResult SearchSubjects(string term) public override System.Web.Mvc.ActionResult SearchSubjects(string term, bool includeAuthorizationRoles)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SearchSubjects); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SearchSubjects);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "term", term); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "term", term);
SearchSubjectsOverride(callInfo, term); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "includeAuthorizationRoles", includeAuthorizationRoles);
SearchSubjectsOverride(callInfo, term, includeAuthorizationRoles);
return callInfo; return callInfo;
} }
@@ -611,14 +614,15 @@ namespace Disco.Web.Areas.API.Controllers
} }
[NonAction] [NonAction]
partial void SubjectOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string Id); partial void SubjectOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, string Id, bool includeAuthorizationRoles);
[NonAction] [NonAction]
public override System.Web.Mvc.ActionResult Subject(string Id) public override System.Web.Mvc.ActionResult Subject(string Id, bool includeAuthorizationRoles)
{ {
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Subject); var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Subject);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "Id", Id); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "Id", Id);
SubjectOverride(callInfo, Id); ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "includeAuthorizationRoles", includeAuthorizationRoles);
SubjectOverride(callInfo, Id, includeAuthorizationRoles);
return callInfo; return callInfo;
} }
@@ -155,6 +155,12 @@ namespace Disco.Web.Areas.API.Controllers
{ {
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SaveExport); return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.SaveExport);
} }
[NonAction]
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public virtual System.Web.Mvc.ActionResult Permission()
{
return new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Permission);
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public UserFlagController Actions { get { return MVC.API.UserFlag; } } public UserFlagController Actions { get { return MVC.API.UserFlag; } }
@@ -187,6 +193,7 @@ namespace Disco.Web.Areas.API.Controllers
public readonly string Export = "Export"; public readonly string Export = "Export";
public readonly string ExportRetrieve = "ExportRetrieve"; public readonly string ExportRetrieve = "ExportRetrieve";
public readonly string SaveExport = "SaveExport"; public readonly string SaveExport = "SaveExport";
public readonly string Permission = "Permission";
} }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -208,6 +215,7 @@ namespace Disco.Web.Areas.API.Controllers
public const string Export = "Export"; public const string Export = "Export";
public const string ExportRetrieve = "ExportRetrieve"; public const string ExportRetrieve = "ExportRetrieve";
public const string SaveExport = "SaveExport"; public const string SaveExport = "SaveExport";
public const string Permission = "Permission";
} }
@@ -367,6 +375,15 @@ namespace Disco.Web.Areas.API.Controllers
{ {
public readonly string model = "model"; public readonly string model = "model";
} }
static readonly ActionParamsClass_Permission s_params_Permission = new ActionParamsClass_Permission();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ActionParamsClass_Permission PermissionParams { get { return s_params_Permission; } }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class ActionParamsClass_Permission
{
public readonly string id = "id";
public readonly string model = "model";
}
static readonly ViewsClass s_views = new ViewsClass(); static readonly ViewsClass s_views = new ViewsClass();
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode] [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public ViewsClass Views { get { return s_views; } } public ViewsClass Views { get { return s_views; } }
@@ -606,6 +623,19 @@ namespace Disco.Web.Areas.API.Controllers
return callInfo; return callInfo;
} }
[NonAction]
partial void PermissionOverride(T4MVC_System_Web_Mvc_ActionResult callInfo, int id, Disco.Web.Areas.API.Models.Shared.FlagPermissionModel model);
[NonAction]
public override System.Web.Mvc.ActionResult Permission(int id, Disco.Web.Areas.API.Models.Shared.FlagPermissionModel model)
{
var callInfo = new T4MVC_System_Web_Mvc_ActionResult(Area, Name, ActionNames.Permission);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "id", id);
ModelUnbinderHelpers.AddRouteValues(callInfo.RouteValueDictionary, "model", model);
PermissionOverride(callInfo, id, model);
return callInfo;
}
} }
} }
@@ -1,15 +1,8 @@
@model Disco.Web.Models.Device.ShowModel @model Disco.Web.Models.Device.ShowModel
@using Disco.Services.Devices.DeviceFlags; @using Disco.Services.Devices.DeviceFlags;
@{ @{
Authorization.Require(Claims.Device.ShowFlagAssignments); var flagAssignments = Model.Device.DeviceFlagAssignments.Select(a => Tuple.Create(a, DeviceFlagService.GetDeviceFlag(a.DeviceFlagId))).Where(a => a.Item2.permission.CanShow()).ToList();
var activeAssignmentCount = flagAssignments.Count(a => !a.Item1.RemovedDate.HasValue);
var hasRemove = Authorization.Has(Claims.Device.Actions.RemoveFlags);
var hasEdit = Authorization.Has(Claims.Device.Actions.EditFlags);
var hasDeviceFlagShow = Authorization.Has(Claims.Config.DeviceFlag.Show);
var activeAssignmentCount = Model.Device.DeviceFlagAssignments == null ? 0 : Model.Device.DeviceFlagAssignments.Count(a => !a.RemovedDate.HasValue);
var flagAssignments = Model.Device.DeviceFlagAssignments.Select(a => Tuple.Create(a, DeviceFlagService.GetDeviceFlag(a.DeviceFlagId))).ToList();
} }
<div id="DeviceDetailTab-Flags" class="DevicePart"> <div id="DeviceDetailTab-Flags" class="DevicePart">
@if (flagAssignments.Count > 0) @if (flagAssignments.Count > 0)
@@ -25,14 +18,14 @@
{ {
<tr data-deviceflagassignmentid="@fa.Item1.Id" data-flagassignmentaddeddate="@(fa.Item1.AddedDate.ToString("s"))" class="@(!fa.Item1.RemovedDate.HasValue ? "added" : "removed")"> <tr data-deviceflagassignmentid="@fa.Item1.Id" data-flagassignmentaddeddate="@(fa.Item1.AddedDate.ToString("s"))" class="@(!fa.Item1.RemovedDate.HasValue ? "added" : "removed")">
<td class="name"> <td class="name">
<i class="fa fa-@(fa.Item2.Icon) fa-fw fa-lg d-@(fa.Item2.IconColour)"></i> <i class="fa fa-@(fa.Item2.flag.Icon) fa-fw fa-lg d-@(fa.Item2.flag.IconColour)"></i>
@if (hasDeviceFlagShow) @if (Authorization.Has(Claims.Config.DeviceFlag.Show))
{ {
@Html.ActionLink(fa.Item2.Name, MVC.Config.DeviceFlag.Index(fa.Item2.Id)) @Html.ActionLink(fa.Item2.flag.Name, MVC.Config.DeviceFlag.Index(fa.Item2.flag.Id))
} }
else else
{ {
@fa.Item2.Name @fa.Item2.flag.Name
} }
</td> </td>
<td class="added"> <td class="added">
@@ -43,7 +36,7 @@
} }
</td> </td>
<td class="comments"> <td class="comments">
@if (hasEdit) @if (fa.Item2.permission.CanEdit())
{ {
<div class="editable"><i class="fa fa-fw fa-edit" title="Edit Comments"></i></div> <div class="editable"><i class="fa fa-fw fa-edit" title="Edit Comments"></i></div>
} }
@@ -77,6 +70,7 @@
<div id="Device_Show_Flags_Actions_Remove_Dialog" class="dialog" title="Remove this flag from the device?"> <div id="Device_Show_Flags_Actions_Remove_Dialog" class="dialog" title="Remove this flag from the device?">
@using (Html.BeginForm(MVC.API.DeviceFlagAssignment.RemoveDevice())) @using (Html.BeginForm(MVC.API.DeviceFlagAssignment.RemoveDevice()))
{ {
@Html.AntiForgeryToken()
<input id="Device_Show_Flags_Actions_Remove_Dialog_Id" type="hidden" name="id" value="" /> <input id="Device_Show_Flags_Actions_Remove_Dialog_Id" type="hidden" name="id" value="" />
<p> <p>
<i class="fa fa-exclamation-triangle fa-lg"></i>&nbsp;Are you sure? <i class="fa fa-exclamation-triangle fa-lg"></i>&nbsp;Are you sure?
@@ -86,6 +80,7 @@
<div id="Device_Show_Flags_Actions_EditComments_Dialog" class="dialog" title="Edit the Comments"> <div id="Device_Show_Flags_Actions_EditComments_Dialog" class="dialog" title="Edit the Comments">
@using (Html.BeginForm(MVC.API.DeviceFlagAssignment.UpdateComments())) @using (Html.BeginForm(MVC.API.DeviceFlagAssignment.UpdateComments()))
{ {
@Html.AntiForgeryToken()
<input id="Device_Show_Flags_Actions_EditComments_Dialog_Id" type="hidden" name="id" value="" /> <input id="Device_Show_Flags_Actions_EditComments_Dialog_Id" type="hidden" name="id" value="" />
<input type="hidden" name="redirect" value="true" /> <input type="hidden" name="redirect" value="true" />
<h4>Comments:</h4> <h4>Comments:</h4>
@@ -52,15 +52,8 @@ namespace Disco.Web.Views.Device.DeviceParts
#line 3 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 3 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Authorization.Require(Claims.Device.ShowFlagAssignments); var flagAssignments = Model.Device.DeviceFlagAssignments.Select(a => Tuple.Create(a, DeviceFlagService.GetDeviceFlag(a.DeviceFlagId))).Where(a => a.Item2.permission.CanShow()).ToList();
var activeAssignmentCount = flagAssignments.Count(a => !a.Item1.RemovedDate.HasValue);
var hasRemove = Authorization.Has(Claims.Device.Actions.RemoveFlags);
var hasEdit = Authorization.Has(Claims.Device.Actions.EditFlags);
var hasDeviceFlagShow = Authorization.Has(Claims.Config.DeviceFlag.Show);
var activeAssignmentCount = Model.Device.DeviceFlagAssignments == null ? 0 : Model.Device.DeviceFlagAssignments.Count(a => !a.RemovedDate.HasValue);
var flagAssignments = Model.Device.DeviceFlagAssignments.Select(a => Tuple.Create(a, DeviceFlagService.GetDeviceFlag(a.DeviceFlagId))).ToList();
#line default #line default
@@ -74,13 +67,13 @@ WriteLiteral(" class=\"DevicePart\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 15 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 8 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 15 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 8 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (flagAssignments.Count > 0) if (flagAssignments.Count > 0)
{ {
@@ -110,13 +103,13 @@ WriteLiteral(" class=\"removed\"");
WriteLiteral(">Removed</th>\r\n </tr>\r\n"); WriteLiteral(">Removed</th>\r\n </tr>\r\n");
#line 24 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 17 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 24 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 17 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
foreach (var fa in flagAssignments.OrderByDescending(a => a.Item1.AddedDate)) foreach (var fa in flagAssignments.OrderByDescending(a => a.Item1.AddedDate))
{ {
@@ -128,7 +121,7 @@ WriteLiteral(" <tr");
WriteLiteral(" data-deviceflagassignmentid=\""); WriteLiteral(" data-deviceflagassignmentid=\"");
#line 26 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 19 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item1.Id); Write(fa.Item1.Id);
@@ -139,7 +132,7 @@ WriteLiteral("\"");
WriteLiteral(" data-flagassignmentaddeddate=\""); WriteLiteral(" data-flagassignmentaddeddate=\"");
#line 26 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 19 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item1.AddedDate.ToString("s")); Write(fa.Item1.AddedDate.ToString("s"));
@@ -147,14 +140,14 @@ WriteLiteral(" data-flagassignmentaddeddate=\"");
#line hidden #line hidden
WriteLiteral("\""); WriteLiteral("\"");
WriteAttribute("class", Tuple.Create(" class=\"", 1282), Tuple.Create("\"", 1345) WriteAttribute("class", Tuple.Create(" class=\"", 967), Tuple.Create("\"", 1030)
#line 26 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 19 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 1290), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? "added" : "removed" , Tuple.Create(Tuple.Create("", 975), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? "added" : "removed"
#line default #line default
#line hidden #line hidden
, 1290), false) , 975), false)
); );
WriteLiteral(">\r\n <td"); WriteLiteral(">\r\n <td");
@@ -163,54 +156,54 @@ WriteLiteral(" class=\"name\"");
WriteLiteral(">\r\n <i"); WriteLiteral(">\r\n <i");
WriteAttribute("class", Tuple.Create(" class=\"", 1414), Tuple.Create("\"", 1481) WriteAttribute("class", Tuple.Create(" class=\"", 1099), Tuple.Create("\"", 1176)
, Tuple.Create(Tuple.Create("", 1422), Tuple.Create("fa", 1422), true) , Tuple.Create(Tuple.Create("", 1107), Tuple.Create("fa", 1107), true)
, Tuple.Create(Tuple.Create(" ", 1424), Tuple.Create("fa-", 1425), true) , Tuple.Create(Tuple.Create(" ", 1109), Tuple.Create("fa-", 1110), true)
#line 28 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 21 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 1428), Tuple.Create<System.Object, System.Int32>(fa.Item2.Icon , Tuple.Create(Tuple.Create("", 1113), Tuple.Create<System.Object, System.Int32>(fa.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 1428), false) , 1113), false)
, Tuple.Create(Tuple.Create(" ", 1444), Tuple.Create("fa-fw", 1445), true) , Tuple.Create(Tuple.Create(" ", 1134), Tuple.Create("fa-fw", 1135), true)
, Tuple.Create(Tuple.Create(" ", 1450), Tuple.Create("fa-lg", 1451), true) , Tuple.Create(Tuple.Create(" ", 1140), Tuple.Create("fa-lg", 1141), true)
, Tuple.Create(Tuple.Create(" ", 1456), Tuple.Create("d-", 1457), true) , Tuple.Create(Tuple.Create(" ", 1146), Tuple.Create("d-", 1147), true)
#line 28 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 21 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 1459), Tuple.Create<System.Object, System.Int32>(fa.Item2.IconColour , Tuple.Create(Tuple.Create("", 1149), Tuple.Create<System.Object, System.Int32>(fa.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 1459), false) , 1149), false)
); );
WriteLiteral("></i>\r\n"); WriteLiteral("></i>\r\n");
#line 29 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 22 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 29 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 22 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (hasDeviceFlagShow) if (Authorization.Has(Claims.Config.DeviceFlag.Show))
{ {
#line default #line default
#line hidden #line hidden
#line 31 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 24 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(Html.ActionLink(fa.Item2.Name, MVC.Config.DeviceFlag.Index(fa.Item2.Id))); Write(Html.ActionLink(fa.Item2.flag.Name, MVC.Config.DeviceFlag.Index(fa.Item2.flag.Id)));
#line default #line default
#line hidden #line hidden
#line 31 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 24 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
else else
{ {
@@ -219,15 +212,15 @@ WriteLiteral("></i>\r\n");
#line default #line default
#line hidden #line hidden
#line 35 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 28 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item2.Name); Write(fa.Item2.flag.Name);
#line default #line default
#line hidden #line hidden
#line 35 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 28 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -242,7 +235,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 39 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 32 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.AddedDate, fa.Item1.AddedUser)); Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.AddedDate, fa.Item1.AddedUser));
@@ -251,13 +244,13 @@ WriteLiteral(" ");
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 40 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 33 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 40 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 33 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (fa.Item1.OnAssignmentExpressionResult != null) if (fa.Item1.OnAssignmentExpressionResult != null)
{ {
@@ -271,7 +264,7 @@ WriteLiteral(" class=\"expressionResult\"");
WriteLiteral(">"); WriteLiteral(">");
#line 42 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 35 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item1.OnAssignmentExpressionResult); Write(fa.Item1.OnAssignmentExpressionResult);
@@ -280,7 +273,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n"); WriteLiteral("</div>\r\n");
#line 43 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 36 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -293,14 +286,14 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 46 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 39 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 46 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 39 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (hasEdit) if (fa.Item2.permission.CanEdit())
{ {
@@ -319,7 +312,7 @@ WriteLiteral(" title=\"Edit Comments\"");
WriteLiteral("></i></div>\r\n"); WriteLiteral("></i></div>\r\n");
#line 49 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 42 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -328,7 +321,7 @@ WriteLiteral("></i></div>\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 50 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 43 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (fa.Item1.Comments == null) if (fa.Item1.Comments == null)
{ {
@@ -342,7 +335,7 @@ WriteLiteral(" class=\"comments smallMessage\"");
WriteLiteral(">[no comments]</div>\r\n"); WriteLiteral(">[no comments]</div>\r\n");
#line 53 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 46 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
else else
{ {
@@ -357,7 +350,7 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">"); WriteLiteral(">");
#line 56 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 49 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item1.Comments.ToHtmlComment()); Write(fa.Item1.Comments.ToHtmlComment());
@@ -372,7 +365,7 @@ WriteLiteral(" class=\"commentsRaw\"");
WriteLiteral(">"); WriteLiteral(">");
#line 57 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 50 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item1.Comments); Write(fa.Item1.Comments);
@@ -381,7 +374,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n"); WriteLiteral("</div>\r\n");
#line 58 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 51 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -389,27 +382,27 @@ WriteLiteral("</div>\r\n");
#line hidden #line hidden
WriteLiteral(" </td>\r\n <td"); WriteLiteral(" </td>\r\n <td");
WriteAttribute("class", Tuple.Create(" class=\"", 3000), Tuple.Create("\"", 3063) WriteAttribute("class", Tuple.Create(" class=\"", 2763), Tuple.Create("\"", 2826)
, Tuple.Create(Tuple.Create("", 3008), Tuple.Create("removed", 3008), true) , Tuple.Create(Tuple.Create("", 2771), Tuple.Create("removed", 2771), true)
#line 60 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 53 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 3015), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? " na" : null , Tuple.Create(Tuple.Create("", 2778), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? " na" : null
#line default #line default
#line hidden #line hidden
, 3015), false) , 2778), false)
); );
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 61 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 54 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 61 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 54 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (fa.Item1.RemovedDate.HasValue) if (fa.Item1.RemovedDate.HasValue)
{ {
@@ -417,14 +410,14 @@ WriteLiteral(">\r\n");
#line default #line default
#line hidden #line hidden
#line 63 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 56 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.RemovedDate.Value, fa.Item1.RemovedUser)); Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.RemovedDate.Value, fa.Item1.RemovedUser));
#line default #line default
#line hidden #line hidden
#line 63 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 56 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
if (fa.Item1.OnUnassignmentExpressionResult != null) if (fa.Item1.OnUnassignmentExpressionResult != null)
{ {
@@ -439,7 +432,7 @@ WriteLiteral(" class=\"expressionResult\"");
WriteLiteral(">"); WriteLiteral(">");
#line 66 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 59 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(fa.Item1.OnUnassignmentExpressionResult); Write(fa.Item1.OnUnassignmentExpressionResult);
@@ -448,7 +441,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n"); WriteLiteral("</div>\r\n");
#line 67 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 60 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
} }
else if (fa.Item1.CanRemove()) else if (fa.Item1.CanRemove())
@@ -466,7 +459,7 @@ WriteLiteral(" class=\"button small remove\"");
WriteLiteral(">Remove</a>\r\n"); WriteLiteral(">Remove</a>\r\n");
#line 72 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 65 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -475,7 +468,7 @@ WriteLiteral(">Remove</a>\r\n");
WriteLiteral(" </td>\r\n </tr>\r\n"); WriteLiteral(" </td>\r\n </tr>\r\n");
#line 75 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 68 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -494,15 +487,29 @@ WriteLiteral(" title=\"Remove this flag from the device?\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 78 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 71 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 78 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 71 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
using (Html.BeginForm(MVC.API.DeviceFlagAssignment.RemoveDevice())) using (Html.BeginForm(MVC.API.DeviceFlagAssignment.RemoveDevice()))
{ {
#line default
#line hidden
#line 73 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
#line 73 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
@@ -526,7 +533,7 @@ WriteLiteral(" class=\"fa fa-exclamation-triangle fa-lg\"");
WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n"); WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n");
#line 84 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 78 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -545,15 +552,29 @@ WriteLiteral(" title=\"Edit the Comments\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 87 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 81 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 87 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 81 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
using (Html.BeginForm(MVC.API.DeviceFlagAssignment.UpdateComments())) using (Html.BeginForm(MVC.API.DeviceFlagAssignment.UpdateComments()))
{ {
#line default
#line hidden
#line 83 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
#line 83 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
#line default #line default
@@ -593,7 +614,7 @@ WriteLiteral(" class=\"block\"");
WriteLiteral("></textarea>\r\n </p>\r\n"); WriteLiteral("></textarea>\r\n </p>\r\n");
#line 95 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 90 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -651,7 +672,7 @@ WriteLiteral(">\r\n $(function () {\r\n var deviceFlag
"eturn false;\r\n });\r\n });\r\n </script>\r\n"); "eturn false;\r\n });\r\n });\r\n </script>\r\n");
#line 174 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 169 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
else else
{ {
@@ -666,7 +687,7 @@ WriteLiteral(" class=\"none\"");
WriteLiteral(">This device has no associated flags</div>\r\n"); WriteLiteral(">This device has no associated flags</div>\r\n");
#line 178 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 173 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
} }
@@ -676,7 +697,7 @@ WriteLiteral(" <script>\r\n $(\'#DeviceDetailTabItems\').append(\'<li>
"ilTab-Flags\">Flags ["); "ilTab-Flags\">Flags [");
#line 180 "..\..\Views\Device\DeviceParts\_Flags.cshtml" #line 175 "..\..\Views\Device\DeviceParts\_Flags.cshtml"
Write(activeAssignmentCount); Write(activeAssignmentCount);
@@ -239,17 +239,20 @@
<div id="Device_Show_User_EmailAddress" title="Email Address"><a href="mailto:@(Model.Device.AssignedUser.EmailAddress)" data-clipboard="@assignedUser.DisplayName &lt;@assignedUser.EmailAddress&gt;">@assignedUser.EmailAddress</a></div> <div id="Device_Show_User_EmailAddress" title="Email Address"><a href="mailto:@(Model.Device.AssignedUser.EmailAddress)" data-clipboard="@assignedUser.DisplayName &lt;@assignedUser.EmailAddress&gt;">@assignedUser.EmailAddress</a></div>
} }
} }
@if (Authorization.Has(Claims.User.ShowFlagAssignments)) @if (assignedUser.UserFlagAssignments.CanShowAny())
{ {
<div id="Device_Show_User_Flags"> <div id="Device_Show_User_Flags">
@foreach (var flag in assignedUser.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) @foreach (var flag in assignedUser.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
<span class="details"> {
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw d-@(flag.Item2.flag.IconColour)">
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span> <span class="details">
</span> <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
</i> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span>
</span>
</i>
}
} }
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
@@ -765,12 +768,13 @@
}); });
</script> </script>
} }
@if (Model.Device.CanAddDeviceFlags() && Model.AvailableDeviceFlags != null && Model.AvailableDeviceFlags.Count > 0) @if (Model.AvailableDeviceFlags != null && Model.AvailableDeviceFlags.Count > 0)
{ {
@Html.ActionLinkSmallButton("Add Flag", MVC.API.DeviceFlagAssignment.AddDevice(), "Device_Show_Details_Actions_AddFlag_Button") <button id="Device_Show_Details_Actions_AddFlag_Button" type="button" class="button small">Add Flag</button>
<div id="Device_Show_Details_Actions_AddFlag_Dialog" class="dialog" title="Add Device Flag"> <div id="Device_Show_Details_Actions_AddFlag_Dialog" class="dialog" title="Add Device Flag">
@using (Html.BeginForm(MVC.API.DeviceFlagAssignment.AddDevice())) @using (Html.BeginForm(MVC.API.DeviceFlagAssignment.AddDevice()))
{ {
@Html.AntiForgeryToken()
<input id="Device_Show_Details_Actions_AddFlag_Dialog_Id" type="hidden" name="id" /> <input id="Device_Show_Details_Actions_AddFlag_Dialog_Id" type="hidden" name="id" />
<input id="Device_Show_Details_Actions_AddFlag_Dialog_DeviceSerialNumber" type="hidden" name="DeviceSerialNumber" value="@Model.Device.SerialNumber" /> <input id="Device_Show_Details_Actions_AddFlag_Dialog_DeviceSerialNumber" type="hidden" name="DeviceSerialNumber" value="@Model.Device.SerialNumber" />
<div class="flagPicker"> <div class="flagPicker">
@@ -794,7 +798,6 @@
$(function () { $(function () {
const button = $('#Device_Show_Details_Actions_AddFlag_Button'); const button = $('#Device_Show_Details_Actions_AddFlag_Button');
let buttonDialog = null; let buttonDialog = null;
const buttonLink = button.attr('href');
let flagPicker = null; let flagPicker = null;
let flagAddId = null; let flagAddId = null;
@@ -814,9 +817,7 @@
flagAddComments.focus().select(); flagAddComments.focus().select();
} }
button.attr('href', '#').click(function (e) { button.click(function (e) {
e.preventDefault();
if (!buttonDialog) { if (!buttonDialog) {
buttonDialog = $('#Device_Show_Details_Actions_AddFlag_Dialog'); buttonDialog = $('#Device_Show_Details_Actions_AddFlag_Dialog');
buttonDialog.dialog({ buttonDialog.dialog({
@@ -831,10 +832,9 @@
}, },
"Add Flag": function () { "Add Flag": function () {
if (!!flagAddId.val()) { if (!!flagAddId.val()) {
const $this = $(this); buttonDialog
$this.dialog("disable"); .dialog("option", "buttons", null)
$this.dialog("option", "buttons", null); .find('form').submit();
buttonDialog.find('form').submit();
} else { } else {
alert('Select a Device Flag'); alert('Select a Device Flag');
} }
@@ -868,7 +868,6 @@
$('#Device_Show_Details_Actions_AddFlag_Dialog_Filter').val(''); $('#Device_Show_Details_Actions_AddFlag_Dialog_Filter').val('');
buttonDialog.dialog('open'); buttonDialog.dialog('open');
return false;
}); });
}); });
</script> </script>
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -19,17 +19,20 @@
}); });
</script> </script>
</div> </div>
@if (Authorization.Has(Claims.Device.ShowFlagAssignments)) @if (Model.Device.DeviceFlagAssignments.CanShowAny())
{ {
<div id="Device_Show_Flags"> <div id="Device_Show_Flags">
@foreach (var flag in Model.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) @foreach (var flag in Model.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw fa-lg d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
<span class="details"> {
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw fa-lg d-@(flag.Item2.flag.IconColour)">
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)</span> <span class="details">
</span> <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
</i> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)</span>
</span>
</i>
}
} }
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
@@ -116,7 +119,7 @@
{ {
@Html.Partial(MVC.Device.Views.DeviceParts._Resources, Model) @Html.Partial(MVC.Device.Views.DeviceParts._Resources, Model)
} }
@if (Authorization.Has(Claims.Device.ShowFlagAssignments)) @if (Authorization.Has(Claims.Device.ShowFlagAssignments) || Model.Device.DeviceFlagAssignments.CanShowAny())
{ {
@Html.Partial(MVC.Device.Views.DeviceParts._Flags, Model) @Html.Partial(MVC.Device.Views.DeviceParts._Flags, Model)
} }
+58 -55
View File
@@ -122,7 +122,7 @@ WriteLiteral(">\r\n $(function () {\r\n $(\'#Device_Sh
#line hidden #line hidden
#line 22 "..\..\Views\Device\Show.cshtml" #line 22 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowFlagAssignments)) if (Model.Device.DeviceFlagAssignments.CanShowAny())
{ {
@@ -144,48 +144,50 @@ WriteLiteral(">\r\n");
#line 25 "..\..\Views\Device\Show.cshtml" #line 25 "..\..\Views\Device\Show.cshtml"
foreach (var flag in Model.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) foreach (var flag in Model.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{ {
if (flag.Item2.permission.CanShow())
{
#line default #line default
#line hidden #line hidden
WriteLiteral(" <i"); WriteLiteral(" <i");
WriteAttribute("class", Tuple.Create(" class=\"", 1178), Tuple.Create("\"", 1254) WriteAttribute("class", Tuple.Create(" class=\"", 1250), Tuple.Create("\"", 1336)
, Tuple.Create(Tuple.Create("", 1186), Tuple.Create("flag", 1186), true) , Tuple.Create(Tuple.Create("", 1258), Tuple.Create("flag", 1258), true)
, Tuple.Create(Tuple.Create(" ", 1190), Tuple.Create("fa", 1191), true) , Tuple.Create(Tuple.Create(" ", 1262), Tuple.Create("fa", 1263), true)
, Tuple.Create(Tuple.Create(" ", 1193), Tuple.Create("fa-", 1194), true) , Tuple.Create(Tuple.Create(" ", 1265), Tuple.Create("fa-", 1266), true)
#line 27 "..\..\Views\Device\Show.cshtml" #line 29 "..\..\Views\Device\Show.cshtml"
, Tuple.Create(Tuple.Create("", 1197), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon , Tuple.Create(Tuple.Create("", 1269), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 1197), false) , 1269), false)
, Tuple.Create(Tuple.Create(" ", 1215), Tuple.Create("fa-fw", 1216), true) , Tuple.Create(Tuple.Create(" ", 1292), Tuple.Create("fa-fw", 1293), true)
, Tuple.Create(Tuple.Create(" ", 1221), Tuple.Create("fa-lg", 1222), true) , Tuple.Create(Tuple.Create(" ", 1298), Tuple.Create("fa-lg", 1299), true)
, Tuple.Create(Tuple.Create(" ", 1227), Tuple.Create("d-", 1228), true) , Tuple.Create(Tuple.Create(" ", 1304), Tuple.Create("d-", 1305), true)
#line 27 "..\..\Views\Device\Show.cshtml" #line 29 "..\..\Views\Device\Show.cshtml"
, Tuple.Create(Tuple.Create("", 1230), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour , Tuple.Create(Tuple.Create("", 1307), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 1230), false) , 1307), false)
); );
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"details\""); WriteLiteral(" class=\"details\"");
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"name\""); WriteLiteral(" class=\"name\"");
WriteLiteral(">"); WriteLiteral(">");
#line 29 "..\..\Views\Device\Show.cshtml" #line 31 "..\..\Views\Device\Show.cshtml"
Write(flag.Item2.Name); Write(flag.Item2.flag.Name);
#line default #line default
@@ -193,9 +195,9 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 29 "..\..\Views\Device\Show.cshtml" #line 31 "..\..\Views\Device\Show.cshtml"
if (flag.Item1.Comments != null) if (flag.Item1.Comments != null)
{ {
#line default #line default
#line hidden #line hidden
@@ -206,8 +208,8 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">"); WriteLiteral(">");
#line 30 "..\..\Views\Device\Show.cshtml" #line 32 "..\..\Views\Device\Show.cshtml"
Write(flag.Item1.Comments.ToHtmlComment()); Write(flag.Item1.Comments.ToHtmlComment());
#line default #line default
@@ -215,8 +217,8 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 30 "..\..\Views\Device\Show.cshtml" #line 32 "..\..\Views\Device\Show.cshtml"
} }
#line default #line default
#line hidden #line hidden
@@ -227,16 +229,17 @@ WriteLiteral(" class=\"added\"");
WriteLiteral(">"); WriteLiteral(">");
#line 30 "..\..\Views\Device\Show.cshtml" #line 32 "..\..\Views\Device\Show.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)); Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser));
#line default #line default
#line hidden #line hidden
WriteLiteral("</span>\r\n </span>\r\n </i>\r\n"); WriteLiteral("</span>\r\n </span>\r\n </i>\r\n");
#line 33 "..\..\Views\Device\Show.cshtml" #line 35 "..\..\Views\Device\Show.cshtml"
}
} }
@@ -282,7 +285,7 @@ WriteLiteral(@">
"); ");
#line 66 "..\..\Views\Device\Show.cshtml" #line 69 "..\..\Views\Device\Show.cshtml"
} }
@@ -291,7 +294,7 @@ WriteLiteral(@">
WriteLiteral(" "); WriteLiteral(" ");
#line 67 "..\..\Views\Device\Show.cshtml" #line 70 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Subject, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Subject, Model));
@@ -332,13 +335,13 @@ WriteLiteral(" id=\"DeviceDetailTabItems\"");
WriteLiteral("></ul>\r\n"); WriteLiteral("></ul>\r\n");
#line 103 "..\..\Views\Device\Show.cshtml" #line 106 "..\..\Views\Device\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 103 "..\..\Views\Device\Show.cshtml" #line 106 "..\..\Views\Device\Show.cshtml"
if (Authorization.HasAny(Claims.Device.ShowComments, Claims.Device.ShowJobs)) if (Authorization.HasAny(Claims.Device.ShowComments, Claims.Device.ShowJobs))
{ {
@@ -346,14 +349,14 @@ WriteLiteral("></ul>\r\n");
#line default #line default
#line hidden #line hidden
#line 105 "..\..\Views\Device\Show.cshtml" #line 108 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._CommentsAndJobs, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._CommentsAndJobs, Model));
#line default #line default
#line hidden #line hidden
#line 105 "..\..\Views\Device\Show.cshtml" #line 108 "..\..\Views\Device\Show.cshtml"
} }
@@ -363,7 +366,7 @@ WriteLiteral("></ul>\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 107 "..\..\Views\Device\Show.cshtml" #line 110 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowDetails)) if (Authorization.Has(Claims.Device.ShowDetails))
{ {
@@ -371,14 +374,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 109 "..\..\Views\Device\Show.cshtml" #line 112 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Details, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Details, Model));
#line default #line default
#line hidden #line hidden
#line 109 "..\..\Views\Device\Show.cshtml" #line 112 "..\..\Views\Device\Show.cshtml"
} }
@@ -388,7 +391,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 111 "..\..\Views\Device\Show.cshtml" #line 114 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowAssignmentHistory)) if (Authorization.Has(Claims.Device.ShowAssignmentHistory))
{ {
@@ -396,14 +399,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 113 "..\..\Views\Device\Show.cshtml" #line 116 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._AssignmentHistory, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._AssignmentHistory, Model));
#line default #line default
#line hidden #line hidden
#line 113 "..\..\Views\Device\Show.cshtml" #line 116 "..\..\Views\Device\Show.cshtml"
} }
@@ -413,7 +416,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 115 "..\..\Views\Device\Show.cshtml" #line 118 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowAttachments)) if (Authorization.Has(Claims.Device.ShowAttachments))
{ {
@@ -421,14 +424,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 117 "..\..\Views\Device\Show.cshtml" #line 120 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Resources, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Resources, Model));
#line default #line default
#line hidden #line hidden
#line 117 "..\..\Views\Device\Show.cshtml" #line 120 "..\..\Views\Device\Show.cshtml"
} }
@@ -438,22 +441,22 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 119 "..\..\Views\Device\Show.cshtml" #line 122 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowFlagAssignments)) if (Authorization.Has(Claims.Device.ShowFlagAssignments) || Model.Device.DeviceFlagAssignments.CanShowAny())
{ {
#line default #line default
#line hidden #line hidden
#line 121 "..\..\Views\Device\Show.cshtml" #line 124 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Flags, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Flags, Model));
#line default #line default
#line hidden #line hidden
#line 121 "..\..\Views\Device\Show.cshtml" #line 124 "..\..\Views\Device\Show.cshtml"
} }
@@ -463,7 +466,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 123 "..\..\Views\Device\Show.cshtml" #line 126 "..\..\Views\Device\Show.cshtml"
if (Authorization.Has(Claims.Device.ShowCertificates)) if (Authorization.Has(Claims.Device.ShowCertificates))
{ {
@@ -471,14 +474,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 125 "..\..\Views\Device\Show.cshtml" #line 128 "..\..\Views\Device\Show.cshtml"
Write(Html.Partial(MVC.Device.Views.DeviceParts._Certificates, Model)); Write(Html.Partial(MVC.Device.Views.DeviceParts._Certificates, Model));
#line default #line default
#line hidden #line hidden
#line 125 "..\..\Views\Device\Show.cshtml" #line 128 "..\..\Views\Device\Show.cshtml"
} }
@@ -488,13 +491,13 @@ WriteLiteral(" ");
WriteLiteral(" </div>\r\n"); WriteLiteral(" </div>\r\n");
#line 128 "..\..\Views\Device\Show.cshtml" #line 131 "..\..\Views\Device\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 128 "..\..\Views\Device\Show.cshtml" #line 131 "..\..\Views\Device\Show.cshtml"
if (requiresLive) if (requiresLive)
{ {
@@ -550,7 +553,7 @@ WriteLiteral(" <script>\r\n $(function () {\r\n
" </script>\r\n"); " </script>\r\n");
#line 197 "..\..\Views\Device\Show.cshtml" #line 200 "..\..\Views\Device\Show.cshtml"
} }
+41 -41
View File
@@ -32,22 +32,22 @@
{@Html.ActionLink(item.Id, MVC.Device.Show(item.Id))} {@Html.ActionLink(item.Id, MVC.Device.Show(item.Id))}
else else
{@item.Id} {@item.Id}
@if (Authorization.Has(Claims.Device.ShowFlagAssignments)) @if (item.DeviceFlagAssignments.CanShowAny())
{ {
@if (item.DeviceFlagAssignments != null && item.DeviceFlagAssignments.Count > 0) <div class="flags">
{ @foreach (var flag in item.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
<div class="flags"> {
@foreach (var flag in item.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) @if (flag.Item2.permission.CanShow())
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw d-@(flag.Item2.flag.IconColour)">
<span class="details"> <span class="details">
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span>
</span> </span>
</i> </i>
} }
</div> }
} </div>
} }
</td> </td>
<td> <td>
@@ -117,43 +117,43 @@
</tbody> </tbody>
</table> </table>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
var userTable = $('table.deviceTable'); var userTable = $('table.deviceTable');
userTable.each(function () { userTable.each(function () {
var $this = $(this); var $this = $(this);
if (!$this.data('deviceTable_Flags')) { if (!$this.data('deviceTable_Flags')) {
$this.tooltip({ $this.tooltip({
items: 'i.flag', items: 'i.flag',
content: function () { content: function () {
var $this = $(this); var $this = $(this);
return $this.children('.details').html(); return $this.children('.details').html();
},
tooltipClass: 'FlagAssignment_Tooltip',
position: {
my: "right top",
at: "right bottom",
collision: "flipfit flip"
},
hade: {
effect: ''
},
close: function (e, ui) {
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(100, 1);
}, },
function () { tooltipClass: 'FlagAssignment_Tooltip',
$(this).fadeOut(100, function () { $(this).remove(); }); position: {
}); my: "right top",
at: "right bottom",
collision: "flipfit flip"
},
hade: {
effect: ''
},
close: function (e, ui) {
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(100, 1);
},
function () {
$(this).fadeOut(100, function () { $(this).remove(); });
});
}
});
$this.data('deviceTable_Flags', true)
} }
}); });
});
$this.data('deviceTable_Flags', true)
}
});
});
</script> </script>
} }
else else
@@ -175,35 +175,35 @@ WriteLiteral(" ");
#line 35 "..\..\Views\Device\_DeviceTable.cshtml" #line 35 "..\..\Views\Device\_DeviceTable.cshtml"
if (Authorization.Has(Claims.Device.ShowFlagAssignments)) if (item.DeviceFlagAssignments.CanShowAny())
{ {
#line default
#line hidden
#line 37 "..\..\Views\Device\_DeviceTable.cshtml"
if (item.DeviceFlagAssignments != null && item.DeviceFlagAssignments.Count > 0)
{
#line default #line default
#line hidden #line hidden
WriteLiteral(" <div"); WriteLiteral(" <div");
WriteLiteral(" class=\"flags\""); WriteLiteral(" class=\"flags\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 40 "..\..\Views\Device\_DeviceTable.cshtml" #line 38 "..\..\Views\Device\_DeviceTable.cshtml"
#line default
#line hidden
#line 38 "..\..\Views\Device\_DeviceTable.cshtml"
foreach (var flag in item.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{
#line default #line default
#line hidden #line hidden
#line 40 "..\..\Views\Device\_DeviceTable.cshtml" #line 40 "..\..\Views\Device\_DeviceTable.cshtml"
foreach (var flag in item.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) if (flag.Item2.permission.CanShow())
{ {
@@ -211,26 +211,26 @@ WriteLiteral(">\r\n");
#line hidden #line hidden
WriteLiteral(" <i"); WriteLiteral(" <i");
WriteAttribute("class", Tuple.Create(" class=\"", 1953), Tuple.Create("\"", 2023) WriteAttribute("class", Tuple.Create(" class=\"", 1901), Tuple.Create("\"", 1981)
, Tuple.Create(Tuple.Create("", 1961), Tuple.Create("flag", 1961), true) , Tuple.Create(Tuple.Create("", 1909), Tuple.Create("flag", 1909), true)
, Tuple.Create(Tuple.Create(" ", 1965), Tuple.Create("fa", 1966), true) , Tuple.Create(Tuple.Create(" ", 1913), Tuple.Create("fa", 1914), true)
, Tuple.Create(Tuple.Create(" ", 1968), Tuple.Create("fa-", 1969), true) , Tuple.Create(Tuple.Create(" ", 1916), Tuple.Create("fa-", 1917), true)
#line 42 "..\..\Views\Device\_DeviceTable.cshtml" #line 42 "..\..\Views\Device\_DeviceTable.cshtml"
, Tuple.Create(Tuple.Create("", 1972), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon , Tuple.Create(Tuple.Create("", 1920), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 1972), false) , 1920), false)
, Tuple.Create(Tuple.Create(" ", 1990), Tuple.Create("fa-fw", 1991), true) , Tuple.Create(Tuple.Create(" ", 1943), Tuple.Create("fa-fw", 1944), true)
, Tuple.Create(Tuple.Create(" ", 1996), Tuple.Create("d-", 1997), true) , Tuple.Create(Tuple.Create(" ", 1949), Tuple.Create("d-", 1950), true)
#line 42 "..\..\Views\Device\_DeviceTable.cshtml" #line 42 "..\..\Views\Device\_DeviceTable.cshtml"
, Tuple.Create(Tuple.Create("", 1999), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour , Tuple.Create(Tuple.Create("", 1952), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 1999), false) , 1952), false)
); );
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
@@ -245,7 +245,7 @@ WriteLiteral(">");
#line 44 "..\..\Views\Device\_DeviceTable.cshtml" #line 44 "..\..\Views\Device\_DeviceTable.cshtml"
Write(flag.Item2.Name); Write(flag.Item2.flag.Name);
#line default #line default
@@ -254,7 +254,7 @@ WriteLiteral("</span>");
#line 44 "..\..\Views\Device\_DeviceTable.cshtml" #line 44 "..\..\Views\Device\_DeviceTable.cshtml"
if (flag.Item1.Comments != null) if (flag.Item1.Comments != null)
{ {
#line default #line default
@@ -302,17 +302,18 @@ WriteLiteral("</span>\r\n </span>
#line default #line default
#line hidden #line hidden
WriteLiteral("\r\n </div>\r\n");
#line 50 "..\..\Views\Device\_DeviceTable.cshtml" #line 48 "..\..\Views\Device\_DeviceTable.cshtml"
}
}
#line default #line default
#line hidden #line hidden
WriteLiteral(" </div>\r\n");
#line 50 "..\..\Views\Device\_DeviceTable.cshtml" #line 51 "..\..\Views\Device\_DeviceTable.cshtml"
} }
@@ -627,46 +628,27 @@ WriteLiteral(" <script");
WriteLiteral(" type=\"text/javascript\""); WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(@"> WriteLiteral(">\r\n $(function () {\r\n var userTable = $(\'table.deviceTa" +
$(function () { "ble\');\r\n\r\n userTable.each(function () {\r\n var " +
var userTable = $('table.deviceTable'); "$this = $(this);\r\n\r\n if (!$this.data(\'deviceTable_Flags\')) {\r" +
"\n $this.tooltip({\r\n items: \'i." +
userTable.each(function () { "flag\',\r\n content: function () {\r\n " +
var $this = $(this); " var $this = $(this);\r\n return $this.c" +
"hildren(\'.details\').html();\r\n },\r\n " +
if (!$this.data('deviceTable_Flags')) { " tooltipClass: \'FlagAssignment_Tooltip\',\r\n po" +
$this.tooltip({ "sition: {\r\n my: \"right top\",\r\n " +
items: 'i.flag', " at: \"right bottom\",\r\n collision: \"fl" +
content: function () { "ipfit flip\"\r\n },\r\n hade: {" +
var $this = $(this); "\r\n effect: \'\'\r\n },\r\n " +
return $this.children('.details').html(); " close: function (e, ui) {\r\n " +
}, " ui.tooltip.hover(\r\n function () {\r\n " +
tooltipClass: 'FlagAssignment_Tooltip', " $(this).stop(true).fadeTo(100, 1);\r\n " +
position: { " },\r\n function () {" +
my: ""right top"", "\r\n $(this).fadeOut(100, function () { $(t" +
at: ""right bottom"", "his).remove(); });\r\n });\r\n " +
collision: ""flipfit flip"" " }\r\n });\r\n\r\n $this.data(\'d" +
}, "eviceTable_Flags\', true)\r\n }\r\n });\r\n " +
hade: { " });\r\n </script>\r\n");
effect: ''
},
close: function (e, ui) {
ui.tooltip.hover(
function () {
$(this).stop(true).fadeTo(100, 1);
},
function () {
$(this).fadeOut(100, function () { $(this).remove(); });
});
}
});
$this.data('deviceTable_Flags', true)
}
});
});
</script>
");
#line 158 "..\..\Views\Device\_DeviceTable.cshtml" #line 158 "..\..\Views\Device\_DeviceTable.cshtml"
+20 -16
View File
@@ -256,19 +256,20 @@
</div> </div>
} }
} }
@if (Authorization.Has(Claims.Device.ShowFlagAssignments) && @if (Model.Job.Device.DeviceFlagAssignments.CanShowAny())
Model.Job.Device.DeviceFlagAssignments != null &&
Model.Job.Device.DeviceFlagAssignments.Any(a => !a.RemovedDate.HasValue))
{ {
<div id="Job_Show_Device_Flags"> <div id="Job_Show_Device_Flags">
@foreach (var flag in Model.Job.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) @foreach (var flag in Model.Job.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
<span class="details"> {
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw d-@(flag.Item2.flag.IconColour)">
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span> <span class="details">
</span> <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
</i> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span>
</span>
</i>
}
} }
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
@@ -506,17 +507,20 @@
if (!string.IsNullOrWhiteSpace(Model.Job.User.EmailAddress)) if (!string.IsNullOrWhiteSpace(Model.Job.User.EmailAddress))
{<div id="Job_Show_User_EmailAddress" title="Email Address">Email: <a href="mailto:@(Model.Job.User.EmailAddress)" data-clipboard="@Model.Job.User.DisplayName &lt;@Model.Job.User.EmailAddress&gt;">@Model.Job.User.EmailAddress</a></div>} {<div id="Job_Show_User_EmailAddress" title="Email Address">Email: <a href="mailto:@(Model.Job.User.EmailAddress)" data-clipboard="@Model.Job.User.DisplayName &lt;@Model.Job.User.EmailAddress&gt;">@Model.Job.User.EmailAddress</a></div>}
} }
@if (Authorization.Has(Claims.User.ShowFlagAssignments)) @if (Model.Job.User.UserFlagAssignments.CanShowAny())
{ {
<div id="Job_Show_User_Flags"> <div id="Job_Show_User_Flags">
@foreach (var flag in Model.Job.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) @foreach (var flag in Model.Job.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
<span class="details"> {
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw d-@(flag.Item2.flag.IconColour)">
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span> <span class="details">
</span> <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
</i> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span>
</span>
</i>
}
} }
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -13,17 +13,20 @@
} }
} }
<div id="User_Show" data-userid="@Model.User.UserId"> <div id="User_Show" data-userid="@Model.User.UserId">
@if (Authorization.Has(Claims.User.ShowFlagAssignments)) @if (Model.User.UserFlagAssignments.CanShowAny())
{ {
<div id="User_Show_Flags"> <div id="User_Show_Flags">
@foreach (var flag in Model.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) @foreach (var flag in Model.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw fa-lg d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
<span class="details"> {
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw fa-lg d-@(flag.Item2.flag.IconColour)">
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)</span> <span class="details">
</span> <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
</i> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)</span>
</span>
</i>
}
} }
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
@@ -106,7 +109,7 @@
{ {
@Html.Partial(MVC.User.Views.UserParts._Resources, Model) @Html.Partial(MVC.User.Views.UserParts._Resources, Model)
} }
@if (Authorization.Has(Claims.User.ShowFlagAssignments)) @if (Authorization.Has(Claims.User.ShowFlagAssignments) || Model.User.UserFlagAssignments.CanShowAny())
{ {
@Html.Partial(MVC.User.Views.UserParts._Flags, Model) @Html.Partial(MVC.User.Views.UserParts._Flags, Model)
} }
+55 -52
View File
@@ -91,7 +91,7 @@ WriteLiteral(">\r\n");
#line hidden #line hidden
#line 16 "..\..\Views\User\Show.cshtml" #line 16 "..\..\Views\User\Show.cshtml"
if (Authorization.Has(Claims.User.ShowFlagAssignments)) if (Model.User.UserFlagAssignments.CanShowAny())
{ {
@@ -113,48 +113,50 @@ WriteLiteral(">\r\n");
#line 19 "..\..\Views\User\Show.cshtml" #line 19 "..\..\Views\User\Show.cshtml"
foreach (var flag in Model.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) foreach (var flag in Model.User.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId))))
{ {
if (flag.Item2.permission.CanShow())
{
#line default #line default
#line hidden #line hidden
WriteLiteral(" <i"); WriteLiteral(" <i");
WriteAttribute("class", Tuple.Create(" class=\"", 867), Tuple.Create("\"", 943) WriteAttribute("class", Tuple.Create(" class=\"", 937), Tuple.Create("\"", 1023)
, Tuple.Create(Tuple.Create("", 875), Tuple.Create("flag", 875), true) , Tuple.Create(Tuple.Create("", 945), Tuple.Create("flag", 945), true)
, Tuple.Create(Tuple.Create(" ", 879), Tuple.Create("fa", 880), true) , Tuple.Create(Tuple.Create(" ", 949), Tuple.Create("fa", 950), true)
, Tuple.Create(Tuple.Create(" ", 882), Tuple.Create("fa-", 883), true) , Tuple.Create(Tuple.Create(" ", 952), Tuple.Create("fa-", 953), true)
#line 21 "..\..\Views\User\Show.cshtml" #line 23 "..\..\Views\User\Show.cshtml"
, Tuple.Create(Tuple.Create("", 886), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon , Tuple.Create(Tuple.Create("", 956), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 886), false) , 956), false)
, Tuple.Create(Tuple.Create(" ", 904), Tuple.Create("fa-fw", 905), true) , Tuple.Create(Tuple.Create(" ", 979), Tuple.Create("fa-fw", 980), true)
, Tuple.Create(Tuple.Create(" ", 910), Tuple.Create("fa-lg", 911), true) , Tuple.Create(Tuple.Create(" ", 985), Tuple.Create("fa-lg", 986), true)
, Tuple.Create(Tuple.Create(" ", 916), Tuple.Create("d-", 917), true) , Tuple.Create(Tuple.Create(" ", 991), Tuple.Create("d-", 992), true)
#line 21 "..\..\Views\User\Show.cshtml" #line 23 "..\..\Views\User\Show.cshtml"
, Tuple.Create(Tuple.Create("", 919), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour , Tuple.Create(Tuple.Create("", 994), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 919), false) , 994), false)
); );
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"details\""); WriteLiteral(" class=\"details\"");
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
WriteLiteral(" class=\"name\""); WriteLiteral(" class=\"name\"");
WriteLiteral(">"); WriteLiteral(">");
#line 23 "..\..\Views\User\Show.cshtml" #line 25 "..\..\Views\User\Show.cshtml"
Write(flag.Item2.Name); Write(flag.Item2.flag.Name);
#line default #line default
@@ -162,9 +164,9 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 23 "..\..\Views\User\Show.cshtml" #line 25 "..\..\Views\User\Show.cshtml"
if (flag.Item1.Comments != null) if (flag.Item1.Comments != null)
{ {
#line default #line default
#line hidden #line hidden
@@ -175,8 +177,8 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">"); WriteLiteral(">");
#line 24 "..\..\Views\User\Show.cshtml" #line 26 "..\..\Views\User\Show.cshtml"
Write(flag.Item1.Comments.ToHtmlComment()); Write(flag.Item1.Comments.ToHtmlComment());
#line default #line default
@@ -184,8 +186,8 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 24 "..\..\Views\User\Show.cshtml" #line 26 "..\..\Views\User\Show.cshtml"
} }
#line default #line default
#line hidden #line hidden
@@ -196,16 +198,17 @@ WriteLiteral(" class=\"added\"");
WriteLiteral(">"); WriteLiteral(">");
#line 24 "..\..\Views\User\Show.cshtml" #line 26 "..\..\Views\User\Show.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)); Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser));
#line default #line default
#line hidden #line hidden
WriteLiteral("</span>\r\n </span>\r\n </i>\r\n"); WriteLiteral("</span>\r\n </span>\r\n </i>\r\n");
#line 27 "..\..\Views\User\Show.cshtml" #line 29 "..\..\Views\User\Show.cshtml"
}
} }
@@ -251,7 +254,7 @@ WriteLiteral(@">
"); ");
#line 60 "..\..\Views\User\Show.cshtml" #line 63 "..\..\Views\User\Show.cshtml"
} }
@@ -260,7 +263,7 @@ WriteLiteral(@">
WriteLiteral(" "); WriteLiteral(" ");
#line 61 "..\..\Views\User\Show.cshtml" #line 64 "..\..\Views\User\Show.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts._Subject, Model)); Write(Html.Partial(MVC.User.Views.UserParts._Subject, Model));
@@ -300,13 +303,13 @@ WriteLiteral(" id=\"UserDetailTabItems\"");
WriteLiteral("></ul>\r\n"); WriteLiteral("></ul>\r\n");
#line 97 "..\..\Views\User\Show.cshtml" #line 100 "..\..\Views\User\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 97 "..\..\Views\User\Show.cshtml" #line 100 "..\..\Views\User\Show.cshtml"
if (Authorization.HasAny(Claims.User.ShowComments, Claims.User.ShowJobs)) if (Authorization.HasAny(Claims.User.ShowComments, Claims.User.ShowJobs))
{ {
@@ -314,14 +317,14 @@ WriteLiteral("></ul>\r\n");
#line default #line default
#line hidden #line hidden
#line 99 "..\..\Views\User\Show.cshtml" #line 102 "..\..\Views\User\Show.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts._CommentsAndJobs, Model)); Write(Html.Partial(MVC.User.Views.UserParts._CommentsAndJobs, Model));
#line default #line default
#line hidden #line hidden
#line 99 "..\..\Views\User\Show.cshtml" #line 102 "..\..\Views\User\Show.cshtml"
} }
@@ -331,7 +334,7 @@ WriteLiteral("></ul>\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 101 "..\..\Views\User\Show.cshtml" #line 104 "..\..\Views\User\Show.cshtml"
if (Authorization.Has(Claims.User.ShowAssignmentHistory)) if (Authorization.Has(Claims.User.ShowAssignmentHistory))
{ {
@@ -339,14 +342,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 103 "..\..\Views\User\Show.cshtml" #line 106 "..\..\Views\User\Show.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts._AssignmentHistory, Model)); Write(Html.Partial(MVC.User.Views.UserParts._AssignmentHistory, Model));
#line default #line default
#line hidden #line hidden
#line 103 "..\..\Views\User\Show.cshtml" #line 106 "..\..\Views\User\Show.cshtml"
} }
@@ -356,7 +359,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 105 "..\..\Views\User\Show.cshtml" #line 108 "..\..\Views\User\Show.cshtml"
if (Authorization.Has(Claims.User.ShowAttachments)) if (Authorization.Has(Claims.User.ShowAttachments))
{ {
@@ -364,14 +367,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 107 "..\..\Views\User\Show.cshtml" #line 110 "..\..\Views\User\Show.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts._Resources, Model)); Write(Html.Partial(MVC.User.Views.UserParts._Resources, Model));
#line default #line default
#line hidden #line hidden
#line 107 "..\..\Views\User\Show.cshtml" #line 110 "..\..\Views\User\Show.cshtml"
} }
@@ -381,22 +384,22 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 109 "..\..\Views\User\Show.cshtml" #line 112 "..\..\Views\User\Show.cshtml"
if (Authorization.Has(Claims.User.ShowFlagAssignments)) if (Authorization.Has(Claims.User.ShowFlagAssignments) || Model.User.UserFlagAssignments.CanShowAny())
{ {
#line default #line default
#line hidden #line hidden
#line 111 "..\..\Views\User\Show.cshtml" #line 114 "..\..\Views\User\Show.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts._Flags, Model)); Write(Html.Partial(MVC.User.Views.UserParts._Flags, Model));
#line default #line default
#line hidden #line hidden
#line 111 "..\..\Views\User\Show.cshtml" #line 114 "..\..\Views\User\Show.cshtml"
} }
@@ -406,7 +409,7 @@ WriteLiteral(" ");
WriteLiteral(" "); WriteLiteral(" ");
#line 113 "..\..\Views\User\Show.cshtml" #line 116 "..\..\Views\User\Show.cshtml"
if (Authorization.Has(Claims.User.ShowAuthorization)) if (Authorization.Has(Claims.User.ShowAuthorization))
{ {
@@ -414,14 +417,14 @@ WriteLiteral(" ");
#line default #line default
#line hidden #line hidden
#line 115 "..\..\Views\User\Show.cshtml" #line 118 "..\..\Views\User\Show.cshtml"
Write(Html.Partial(MVC.User.Views.UserParts._Authorization, Model)); Write(Html.Partial(MVC.User.Views.UserParts._Authorization, Model));
#line default #line default
#line hidden #line hidden
#line 115 "..\..\Views\User\Show.cshtml" #line 118 "..\..\Views\User\Show.cshtml"
} }
@@ -431,13 +434,13 @@ WriteLiteral(" ");
WriteLiteral(" </div>\r\n"); WriteLiteral(" </div>\r\n");
#line 118 "..\..\Views\User\Show.cshtml" #line 121 "..\..\Views\User\Show.cshtml"
#line default #line default
#line hidden #line hidden
#line 118 "..\..\Views\User\Show.cshtml" #line 121 "..\..\Views\User\Show.cshtml"
if (requiresLive) if (requiresLive)
{ {
@@ -492,7 +495,7 @@ WriteLiteral(" <script>\r\n $(function () {\r\n
" });\r\n });\r\n </script>\r\n"); " });\r\n });\r\n </script>\r\n");
#line 187 "..\..\Views\User\Show.cshtml" #line 190 "..\..\Views\User\Show.cshtml"
} }
+9 -14
View File
@@ -1,15 +1,8 @@
@model Disco.Web.Models.User.ShowModel @model Disco.Web.Models.User.ShowModel
@using Disco.Services.Users.UserFlags; @using Disco.Services.Users.UserFlags;
@{ @{
Authorization.Require(Claims.User.ShowFlagAssignments); var flagAssignments = Model.User.UserFlagAssignments.Select(a => Tuple.Create(a, UserFlagService.GetUserFlag(a.UserFlagId))).Where(g => g.Item2.permission.CanShow()).ToList();
var activeAssignmentCount = flagAssignments.Count(a => !a.Item1.RemovedDate.HasValue);
var hasRemove = Authorization.Has(Claims.User.Actions.RemoveFlags);
var hasEdit = Authorization.Has(Claims.User.Actions.EditFlags);
var hasUserFlagShow = Authorization.Has(Claims.Config.UserFlag.Show);
var activeAssignmentCount = Model.User.UserFlagAssignments == null ? 0 : Model.User.UserFlagAssignments.Count(a => !a.RemovedDate.HasValue);
var flagAssignments = Model.User.UserFlagAssignments.Select(a => Tuple.Create(a, UserFlagService.GetUserFlag(a.UserFlagId))).ToList();
} }
<div id="UserDetailTab-Flags" class="UserPart"> <div id="UserDetailTab-Flags" class="UserPart">
@if (flagAssignments.Count > 0) @if (flagAssignments.Count > 0)
@@ -25,14 +18,14 @@
{ {
<tr data-userflagassignmentid="@fa.Item1.Id" data-flagassignmentaddeddate="@(fa.Item1.AddedDate.ToString("s"))" class="@(!fa.Item1.RemovedDate.HasValue ? "added" : "removed")"> <tr data-userflagassignmentid="@fa.Item1.Id" data-flagassignmentaddeddate="@(fa.Item1.AddedDate.ToString("s"))" class="@(!fa.Item1.RemovedDate.HasValue ? "added" : "removed")">
<td class="name"> <td class="name">
<i class="fa fa-@(fa.Item2.Icon) fa-fw fa-lg d-@(fa.Item2.IconColour)"></i> <i class="fa fa-@(fa.Item2.flag.Icon) fa-fw fa-lg d-@(fa.Item2.flag.IconColour)"></i>
@if (hasUserFlagShow) @if (Authorization.Has(Claims.Config.UserFlag.Show))
{ {
@Html.ActionLink(fa.Item2.Name, MVC.Config.UserFlag.Index(fa.Item2.Id)) @Html.ActionLink(fa.Item2.flag.Name, MVC.Config.UserFlag.Index(fa.Item2.flag.Id))
} }
else else
{ {
@fa.Item2.Name @fa.Item2.flag.Name
} }
</td> </td>
<td class="added"> <td class="added">
@@ -43,7 +36,7 @@
} }
</td> </td>
<td class="comments"> <td class="comments">
@if (hasEdit) @if (fa.Item2.permission.CanEdit())
{ {
<div class="editable"><i class="fa fa-fw fa-edit" title="Edit Comments"></i></div> <div class="editable"><i class="fa fa-fw fa-edit" title="Edit Comments"></i></div>
} }
@@ -77,6 +70,7 @@
<div id="User_Show_Flags_Actions_Remove_Dialog" class="dialog" title="Remove this flag from the user?"> <div id="User_Show_Flags_Actions_Remove_Dialog" class="dialog" title="Remove this flag from the user?">
@using (Html.BeginForm(MVC.API.UserFlagAssignment.RemoveUser())) @using (Html.BeginForm(MVC.API.UserFlagAssignment.RemoveUser()))
{ {
@Html.AntiForgeryToken()
<input id="User_Show_Flags_Actions_Remove_Dialog_Id" type="hidden" name="id" value="" /> <input id="User_Show_Flags_Actions_Remove_Dialog_Id" type="hidden" name="id" value="" />
<p> <p>
<i class="fa fa-exclamation-triangle fa-lg"></i>&nbsp;Are you sure? <i class="fa fa-exclamation-triangle fa-lg"></i>&nbsp;Are you sure?
@@ -86,6 +80,7 @@
<div id="User_Show_Flags_Actions_EditComments_Dialog" class="dialog" title="Edit the Comments"> <div id="User_Show_Flags_Actions_EditComments_Dialog" class="dialog" title="Edit the Comments">
@using (Html.BeginForm(MVC.API.UserFlagAssignment.UpdateComments())) @using (Html.BeginForm(MVC.API.UserFlagAssignment.UpdateComments()))
{ {
@Html.AntiForgeryToken()
<input id="User_Show_Flags_Actions_EditComments_Dialog_Id" type="hidden" name="id" value="" /> <input id="User_Show_Flags_Actions_EditComments_Dialog_Id" type="hidden" name="id" value="" />
<input type="hidden" name="redirect" value="true" /> <input type="hidden" name="redirect" value="true" />
<h4>Comments:</h4> <h4>Comments:</h4>
@@ -52,15 +52,8 @@ namespace Disco.Web.Views.User.UserParts
#line 3 "..\..\Views\User\UserParts\_Flags.cshtml" #line 3 "..\..\Views\User\UserParts\_Flags.cshtml"
Authorization.Require(Claims.User.ShowFlagAssignments); var flagAssignments = Model.User.UserFlagAssignments.Select(a => Tuple.Create(a, UserFlagService.GetUserFlag(a.UserFlagId))).Where(g => g.Item2.permission.CanShow()).ToList();
var activeAssignmentCount = flagAssignments.Count(a => !a.Item1.RemovedDate.HasValue);
var hasRemove = Authorization.Has(Claims.User.Actions.RemoveFlags);
var hasEdit = Authorization.Has(Claims.User.Actions.EditFlags);
var hasUserFlagShow = Authorization.Has(Claims.Config.UserFlag.Show);
var activeAssignmentCount = Model.User.UserFlagAssignments == null ? 0 : Model.User.UserFlagAssignments.Count(a => !a.RemovedDate.HasValue);
var flagAssignments = Model.User.UserFlagAssignments.Select(a => Tuple.Create(a, UserFlagService.GetUserFlag(a.UserFlagId))).ToList();
#line default #line default
@@ -74,13 +67,13 @@ WriteLiteral(" class=\"UserPart\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 15 "..\..\Views\User\UserParts\_Flags.cshtml" #line 8 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 15 "..\..\Views\User\UserParts\_Flags.cshtml" #line 8 "..\..\Views\User\UserParts\_Flags.cshtml"
if (flagAssignments.Count > 0) if (flagAssignments.Count > 0)
{ {
@@ -110,13 +103,13 @@ WriteLiteral(" class=\"removed\"");
WriteLiteral(">Removed</th>\r\n </tr>\r\n"); WriteLiteral(">Removed</th>\r\n </tr>\r\n");
#line 24 "..\..\Views\User\UserParts\_Flags.cshtml" #line 17 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 24 "..\..\Views\User\UserParts\_Flags.cshtml" #line 17 "..\..\Views\User\UserParts\_Flags.cshtml"
foreach (var fa in flagAssignments.OrderByDescending(a => a.Item1.AddedDate)) foreach (var fa in flagAssignments.OrderByDescending(a => a.Item1.AddedDate))
{ {
@@ -128,7 +121,7 @@ WriteLiteral(" <tr");
WriteLiteral(" data-userflagassignmentid=\""); WriteLiteral(" data-userflagassignmentid=\"");
#line 26 "..\..\Views\User\UserParts\_Flags.cshtml" #line 19 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item1.Id); Write(fa.Item1.Id);
@@ -139,7 +132,7 @@ WriteLiteral("\"");
WriteLiteral(" data-flagassignmentaddeddate=\""); WriteLiteral(" data-flagassignmentaddeddate=\"");
#line 26 "..\..\Views\User\UserParts\_Flags.cshtml" #line 19 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item1.AddedDate.ToString("s")); Write(fa.Item1.AddedDate.ToString("s"));
@@ -147,14 +140,14 @@ WriteLiteral(" data-flagassignmentaddeddate=\"");
#line hidden #line hidden
WriteLiteral("\""); WriteLiteral("\"");
WriteAttribute("class", Tuple.Create(" class=\"", 1240), Tuple.Create("\"", 1303) WriteAttribute("class", Tuple.Create(" class=\"", 943), Tuple.Create("\"", 1006)
#line 26 "..\..\Views\User\UserParts\_Flags.cshtml" #line 19 "..\..\Views\User\UserParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 1248), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? "added" : "removed" , Tuple.Create(Tuple.Create("", 951), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? "added" : "removed"
#line default #line default
#line hidden #line hidden
, 1248), false) , 951), false)
); );
WriteLiteral(">\r\n <td"); WriteLiteral(">\r\n <td");
@@ -163,54 +156,54 @@ WriteLiteral(" class=\"name\"");
WriteLiteral(">\r\n <i"); WriteLiteral(">\r\n <i");
WriteAttribute("class", Tuple.Create(" class=\"", 1372), Tuple.Create("\"", 1439) WriteAttribute("class", Tuple.Create(" class=\"", 1075), Tuple.Create("\"", 1152)
, Tuple.Create(Tuple.Create("", 1380), Tuple.Create("fa", 1380), true) , Tuple.Create(Tuple.Create("", 1083), Tuple.Create("fa", 1083), true)
, Tuple.Create(Tuple.Create(" ", 1382), Tuple.Create("fa-", 1383), true) , Tuple.Create(Tuple.Create(" ", 1085), Tuple.Create("fa-", 1086), true)
#line 28 "..\..\Views\User\UserParts\_Flags.cshtml" #line 21 "..\..\Views\User\UserParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 1386), Tuple.Create<System.Object, System.Int32>(fa.Item2.Icon , Tuple.Create(Tuple.Create("", 1089), Tuple.Create<System.Object, System.Int32>(fa.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 1386), false) , 1089), false)
, Tuple.Create(Tuple.Create(" ", 1402), Tuple.Create("fa-fw", 1403), true) , Tuple.Create(Tuple.Create(" ", 1110), Tuple.Create("fa-fw", 1111), true)
, Tuple.Create(Tuple.Create(" ", 1408), Tuple.Create("fa-lg", 1409), true) , Tuple.Create(Tuple.Create(" ", 1116), Tuple.Create("fa-lg", 1117), true)
, Tuple.Create(Tuple.Create(" ", 1414), Tuple.Create("d-", 1415), true) , Tuple.Create(Tuple.Create(" ", 1122), Tuple.Create("d-", 1123), true)
#line 28 "..\..\Views\User\UserParts\_Flags.cshtml" #line 21 "..\..\Views\User\UserParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 1417), Tuple.Create<System.Object, System.Int32>(fa.Item2.IconColour , Tuple.Create(Tuple.Create("", 1125), Tuple.Create<System.Object, System.Int32>(fa.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 1417), false) , 1125), false)
); );
WriteLiteral("></i>\r\n"); WriteLiteral("></i>\r\n");
#line 29 "..\..\Views\User\UserParts\_Flags.cshtml" #line 22 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 29 "..\..\Views\User\UserParts\_Flags.cshtml" #line 22 "..\..\Views\User\UserParts\_Flags.cshtml"
if (hasUserFlagShow) if (Authorization.Has(Claims.Config.UserFlag.Show))
{ {
#line default #line default
#line hidden #line hidden
#line 31 "..\..\Views\User\UserParts\_Flags.cshtml" #line 24 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(Html.ActionLink(fa.Item2.Name, MVC.Config.UserFlag.Index(fa.Item2.Id))); Write(Html.ActionLink(fa.Item2.flag.Name, MVC.Config.UserFlag.Index(fa.Item2.flag.Id)));
#line default #line default
#line hidden #line hidden
#line 31 "..\..\Views\User\UserParts\_Flags.cshtml" #line 24 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
else else
{ {
@@ -219,15 +212,15 @@ WriteLiteral("></i>\r\n");
#line default #line default
#line hidden #line hidden
#line 35 "..\..\Views\User\UserParts\_Flags.cshtml" #line 28 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item2.Name); Write(fa.Item2.flag.Name);
#line default #line default
#line hidden #line hidden
#line 35 "..\..\Views\User\UserParts\_Flags.cshtml" #line 28 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -242,7 +235,7 @@ WriteLiteral(">\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 39 "..\..\Views\User\UserParts\_Flags.cshtml" #line 32 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.AddedDate, fa.Item1.AddedUser)); Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.AddedDate, fa.Item1.AddedUser));
@@ -251,13 +244,13 @@ WriteLiteral(" ");
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 40 "..\..\Views\User\UserParts\_Flags.cshtml" #line 33 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 40 "..\..\Views\User\UserParts\_Flags.cshtml" #line 33 "..\..\Views\User\UserParts\_Flags.cshtml"
if (fa.Item1.OnAssignmentExpressionResult != null) if (fa.Item1.OnAssignmentExpressionResult != null)
{ {
@@ -271,7 +264,7 @@ WriteLiteral(" class=\"expressionResult\"");
WriteLiteral(">"); WriteLiteral(">");
#line 42 "..\..\Views\User\UserParts\_Flags.cshtml" #line 35 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item1.OnAssignmentExpressionResult); Write(fa.Item1.OnAssignmentExpressionResult);
@@ -280,7 +273,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n"); WriteLiteral("</div>\r\n");
#line 43 "..\..\Views\User\UserParts\_Flags.cshtml" #line 36 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -293,14 +286,14 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 46 "..\..\Views\User\UserParts\_Flags.cshtml" #line 39 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 46 "..\..\Views\User\UserParts\_Flags.cshtml" #line 39 "..\..\Views\User\UserParts\_Flags.cshtml"
if (hasEdit) if (fa.Item2.permission.CanEdit())
{ {
@@ -319,7 +312,7 @@ WriteLiteral(" title=\"Edit Comments\"");
WriteLiteral("></i></div>\r\n"); WriteLiteral("></i></div>\r\n");
#line 49 "..\..\Views\User\UserParts\_Flags.cshtml" #line 42 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -328,7 +321,7 @@ WriteLiteral("></i></div>\r\n");
WriteLiteral(" "); WriteLiteral(" ");
#line 50 "..\..\Views\User\UserParts\_Flags.cshtml" #line 43 "..\..\Views\User\UserParts\_Flags.cshtml"
if (fa.Item1.Comments == null) if (fa.Item1.Comments == null)
{ {
@@ -342,7 +335,7 @@ WriteLiteral(" class=\"comments smallMessage\"");
WriteLiteral(">[no comments]</div>\r\n"); WriteLiteral(">[no comments]</div>\r\n");
#line 53 "..\..\Views\User\UserParts\_Flags.cshtml" #line 46 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
else else
{ {
@@ -357,7 +350,7 @@ WriteLiteral(" class=\"comments\"");
WriteLiteral(">"); WriteLiteral(">");
#line 56 "..\..\Views\User\UserParts\_Flags.cshtml" #line 49 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item1.Comments.ToHtmlComment()); Write(fa.Item1.Comments.ToHtmlComment());
@@ -372,7 +365,7 @@ WriteLiteral(" class=\"commentsRaw\"");
WriteLiteral(">"); WriteLiteral(">");
#line 57 "..\..\Views\User\UserParts\_Flags.cshtml" #line 50 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item1.Comments); Write(fa.Item1.Comments);
@@ -381,7 +374,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n"); WriteLiteral("</div>\r\n");
#line 58 "..\..\Views\User\UserParts\_Flags.cshtml" #line 51 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -389,27 +382,27 @@ WriteLiteral("</div>\r\n");
#line hidden #line hidden
WriteLiteral(" </td>\r\n <td"); WriteLiteral(" </td>\r\n <td");
WriteAttribute("class", Tuple.Create(" class=\"", 2954), Tuple.Create("\"", 3017) WriteAttribute("class", Tuple.Create(" class=\"", 2735), Tuple.Create("\"", 2798)
, Tuple.Create(Tuple.Create("", 2962), Tuple.Create("removed", 2962), true) , Tuple.Create(Tuple.Create("", 2743), Tuple.Create("removed", 2743), true)
#line 60 "..\..\Views\User\UserParts\_Flags.cshtml" #line 53 "..\..\Views\User\UserParts\_Flags.cshtml"
, Tuple.Create(Tuple.Create("", 2969), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? " na" : null , Tuple.Create(Tuple.Create("", 2750), Tuple.Create<System.Object, System.Int32>(!fa.Item1.RemovedDate.HasValue ? " na" : null
#line default #line default
#line hidden #line hidden
, 2969), false) , 2750), false)
); );
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 61 "..\..\Views\User\UserParts\_Flags.cshtml" #line 54 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 61 "..\..\Views\User\UserParts\_Flags.cshtml" #line 54 "..\..\Views\User\UserParts\_Flags.cshtml"
if (fa.Item1.RemovedDate.HasValue) if (fa.Item1.RemovedDate.HasValue)
{ {
@@ -417,14 +410,14 @@ WriteLiteral(">\r\n");
#line default #line default
#line hidden #line hidden
#line 63 "..\..\Views\User\UserParts\_Flags.cshtml" #line 56 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.RemovedDate.Value, fa.Item1.RemovedUser)); Write(CommonHelpers.FriendlyDateAndUser(fa.Item1.RemovedDate.Value, fa.Item1.RemovedUser));
#line default #line default
#line hidden #line hidden
#line 63 "..\..\Views\User\UserParts\_Flags.cshtml" #line 56 "..\..\Views\User\UserParts\_Flags.cshtml"
if (fa.Item1.OnUnassignmentExpressionResult != null) if (fa.Item1.OnUnassignmentExpressionResult != null)
{ {
@@ -439,7 +432,7 @@ WriteLiteral(" class=\"expressionResult\"");
WriteLiteral(">"); WriteLiteral(">");
#line 66 "..\..\Views\User\UserParts\_Flags.cshtml" #line 59 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(fa.Item1.OnUnassignmentExpressionResult); Write(fa.Item1.OnUnassignmentExpressionResult);
@@ -448,7 +441,7 @@ WriteLiteral(">");
WriteLiteral("</div>\r\n"); WriteLiteral("</div>\r\n");
#line 67 "..\..\Views\User\UserParts\_Flags.cshtml" #line 60 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
} }
else if (fa.Item1.CanRemove()) else if (fa.Item1.CanRemove())
@@ -466,7 +459,7 @@ WriteLiteral(" class=\"button small remove\"");
WriteLiteral(">Remove</a>\r\n"); WriteLiteral(">Remove</a>\r\n");
#line 72 "..\..\Views\User\UserParts\_Flags.cshtml" #line 65 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -475,7 +468,7 @@ WriteLiteral(">Remove</a>\r\n");
WriteLiteral(" </td>\r\n </tr>\r\n"); WriteLiteral(" </td>\r\n </tr>\r\n");
#line 75 "..\..\Views\User\UserParts\_Flags.cshtml" #line 68 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -494,15 +487,29 @@ WriteLiteral(" title=\"Remove this flag from the user?\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 78 "..\..\Views\User\UserParts\_Flags.cshtml" #line 71 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 78 "..\..\Views\User\UserParts\_Flags.cshtml" #line 71 "..\..\Views\User\UserParts\_Flags.cshtml"
using (Html.BeginForm(MVC.API.UserFlagAssignment.RemoveUser())) using (Html.BeginForm(MVC.API.UserFlagAssignment.RemoveUser()))
{ {
#line default
#line hidden
#line 73 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
#line 73 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
@@ -526,7 +533,7 @@ WriteLiteral(" class=\"fa fa-exclamation-triangle fa-lg\"");
WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n"); WriteLiteral("></i>&nbsp;Are you sure?\r\n </p>\r\n");
#line 84 "..\..\Views\User\UserParts\_Flags.cshtml" #line 78 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -545,15 +552,29 @@ WriteLiteral(" title=\"Edit the Comments\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 87 "..\..\Views\User\UserParts\_Flags.cshtml" #line 81 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
#line hidden #line hidden
#line 87 "..\..\Views\User\UserParts\_Flags.cshtml" #line 81 "..\..\Views\User\UserParts\_Flags.cshtml"
using (Html.BeginForm(MVC.API.UserFlagAssignment.UpdateComments())) using (Html.BeginForm(MVC.API.UserFlagAssignment.UpdateComments()))
{ {
#line default
#line hidden
#line 83 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
#line 83 "..\..\Views\User\UserParts\_Flags.cshtml"
#line default #line default
@@ -593,7 +614,7 @@ WriteLiteral(" class=\"block\"");
WriteLiteral("></textarea>\r\n </p>\r\n"); WriteLiteral("></textarea>\r\n </p>\r\n");
#line 95 "..\..\Views\User\UserParts\_Flags.cshtml" #line 90 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -651,7 +672,7 @@ WriteLiteral(">\r\n $(function () {\r\n var userFlags
";\r\n });\r\n </script>\r\n"); ";\r\n });\r\n </script>\r\n");
#line 174 "..\..\Views\User\UserParts\_Flags.cshtml" #line 169 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
else else
{ {
@@ -666,7 +687,7 @@ WriteLiteral(" class=\"none\"");
WriteLiteral(">This user has no associated flags</div>\r\n"); WriteLiteral(">This user has no associated flags</div>\r\n");
#line 178 "..\..\Views\User\UserParts\_Flags.cshtml" #line 173 "..\..\Views\User\UserParts\_Flags.cshtml"
} }
@@ -676,7 +697,7 @@ WriteLiteral(" <script>\r\n $(\'#UserDetailTabItems\').append(\'<li><a
"b-Flags\">Flags ["); "b-Flags\">Flags [");
#line 180 "..\..\Views\User\UserParts\_Flags.cshtml" #line 175 "..\..\Views\User\UserParts\_Flags.cshtml"
Write(activeAssignmentCount); Write(activeAssignmentCount);
+17 -16
View File
@@ -236,12 +236,13 @@
</script> </script>
} }
} }
@if (Model.User.CanAddUserFlags() && Model.AvailableUserFlags != null && Model.AvailableUserFlags.Count > 0) @if (Model.AvailableUserFlags != null && Model.AvailableUserFlags.Count > 0)
{ {
@Html.ActionLinkSmallButton("Add Flag", MVC.API.UserFlagAssignment.AddUser(), "User_Show_Details_Actions_AddFlag_Button") <button id="User_Show_Details_Actions_AddFlag_Button" type="button" class="button small">Add Flag</button>
<div id="User_Show_Details_Actions_AddFlag_Dialog" class="dialog" title="Add User Flag"> <div id="User_Show_Details_Actions_AddFlag_Dialog" class="dialog" title="Add User Flag">
@using (Html.BeginForm(MVC.API.UserFlagAssignment.AddUser())) @using (Html.BeginForm(MVC.API.UserFlagAssignment.AddUser()))
{ {
@Html.AntiForgeryToken()
<input id="User_Show_Details_Actions_AddFlag_Dialog_Id" type="hidden" name="id" /> <input id="User_Show_Details_Actions_AddFlag_Dialog_Id" type="hidden" name="id" />
<input id="User_Show_Details_Actions_AddFlag_Dialog_UserId" type="hidden" name="UserId" value="@Model.User.UserId" /> <input id="User_Show_Details_Actions_AddFlag_Dialog_UserId" type="hidden" name="UserId" value="@Model.User.UserId" />
<div class="flagPicker"> <div class="flagPicker">
@@ -265,7 +266,6 @@
$(function () { $(function () {
const button = $('#User_Show_Details_Actions_AddFlag_Button'); const button = $('#User_Show_Details_Actions_AddFlag_Button');
let buttonDialog = null; let buttonDialog = null;
const buttonLink = button.attr('href');
let flagPicker = null; let flagPicker = null;
let flagAddId = null; let flagAddId = null;
@@ -285,7 +285,7 @@
flagAddComments.focus().select(); flagAddComments.focus().select();
} }
button.attr('href', '#').click(function (e) { button.click(function (e) {
e.preventDefault(); e.preventDefault();
if (!buttonDialog) { if (!buttonDialog) {
@@ -302,10 +302,9 @@
}, },
"Add Flag": function () { "Add Flag": function () {
if (!!flagAddId.val()) { if (!!flagAddId.val()) {
const $this = $(this); buttonDialog
$this.dialog("disable"); .dialog("option", "buttons", null)
$this.dialog("option", "buttons", null); .find('form').submit();
buttonDialog.find('form').submit();
} else { } else {
alert('Select a User Flag'); alert('Select a User Flag');
} }
@@ -437,20 +436,22 @@
<span class="User_Show_AssignedDevices_CurrentAssignment_Assigned">@CommonHelpers.FriendlyDate(assignment.AssignedDate)</span> <span class="User_Show_AssignedDevices_CurrentAssignment_Assigned">@CommonHelpers.FriendlyDate(assignment.AssignedDate)</span>
</td> </td>
</tr> </tr>
@if (Authorization.Has(Claims.Device.ShowFlagAssignments) && @if (assignment.Device.DeviceFlagAssignments.CanShowAny())
assignment.Device.DeviceFlagAssignments.Any(a => a.RemovedDate.HasValue))
{ {
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div class="User_Show_Assigned_Devices_CurrentAssignment_Flags"> <div class="User_Show_Assigned_Devices_CurrentAssignment_Flags">
@foreach (var flag in assignment.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) @foreach (var flag in assignment.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
<span class="details"> {
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw d-@(flag.Item2.flag.IconColour)">
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span> <span class="details">
</span> <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
</i> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span>
</span>
</i>
}
} }
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
@@ -893,26 +893,22 @@ WriteLiteral(" ");
#line 239 "..\..\Views\User\UserParts\_Subject.cshtml" #line 239 "..\..\Views\User\UserParts\_Subject.cshtml"
if (Model.User.CanAddUserFlags() && Model.AvailableUserFlags != null && Model.AvailableUserFlags.Count > 0) if (Model.AvailableUserFlags != null && Model.AvailableUserFlags.Count > 0)
{ {
#line default
#line hidden
#line 241 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(Html.ActionLinkSmallButton("Add Flag", MVC.API.UserFlagAssignment.AddUser(), "User_Show_Details_Actions_AddFlag_Button"));
#line default #line default
#line hidden #line hidden
WriteLiteral(" <button");
#line 241 "..\..\Views\User\UserParts\_Subject.cshtml"
WriteLiteral(" id=\"User_Show_Details_Actions_AddFlag_Button\"");
WriteLiteral(" type=\"button\"");
WriteLiteral(" class=\"button small\"");
WriteLiteral(">Add Flag</button>\r\n");
#line default
#line hidden
WriteLiteral(" <div"); WriteLiteral(" <div");
WriteLiteral(" id=\"User_Show_Details_Actions_AddFlag_Dialog\""); WriteLiteral(" id=\"User_Show_Details_Actions_AddFlag_Dialog\"");
@@ -933,6 +929,20 @@ WriteLiteral(">\r\n");
#line 243 "..\..\Views\User\UserParts\_Subject.cshtml" #line 243 "..\..\Views\User\UserParts\_Subject.cshtml"
using (Html.BeginForm(MVC.API.UserFlagAssignment.AddUser())) using (Html.BeginForm(MVC.API.UserFlagAssignment.AddUser()))
{ {
#line default
#line hidden
#line 245 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(Html.AntiForgeryToken());
#line default
#line hidden
#line 245 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
@@ -955,14 +965,14 @@ WriteLiteral(" type=\"hidden\"");
WriteLiteral(" name=\"UserId\""); WriteLiteral(" name=\"UserId\"");
WriteAttribute("value", Tuple.Create(" value=\"", 16008), Tuple.Create("\"", 16034) WriteAttribute("value", Tuple.Create(" value=\"", 16023), Tuple.Create("\"", 16049)
#line 246 "..\..\Views\User\UserParts\_Subject.cshtml" #line 247 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 16016), Tuple.Create<System.Object, System.Int32>(Model.User.UserId , Tuple.Create(Tuple.Create("", 16031), Tuple.Create<System.Object, System.Int32>(Model.User.UserId
#line default #line default
#line hidden #line hidden
, 16016), false) , 16031), false)
); );
WriteLiteral(" />\r\n"); WriteLiteral(" />\r\n");
@@ -984,13 +994,13 @@ WriteLiteral(" autocomplete=\"off\"");
WriteLiteral(" />\r\n"); WriteLiteral(" />\r\n");
#line 249 "..\..\Views\User\UserParts\_Subject.cshtml" #line 250 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 249 "..\..\Views\User\UserParts\_Subject.cshtml" #line 250 "..\..\Views\User\UserParts\_Subject.cshtml"
foreach (var userFlag in Model.AvailableUserFlags.OrderBy(jq => jq.Name)) foreach (var userFlag in Model.AvailableUserFlags.OrderBy(jq => jq.Name))
{ {
@@ -1004,7 +1014,7 @@ WriteLiteral(" class=\"flag\"");
WriteLiteral(" data-userflagid=\""); WriteLiteral(" data-userflagid=\"");
#line 251 "..\..\Views\User\UserParts\_Subject.cshtml" #line 252 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(userFlag.Id); Write(userFlag.Id);
@@ -1015,7 +1025,7 @@ WriteLiteral("\"");
WriteLiteral(" data-userflagname=\""); WriteLiteral(" data-userflagname=\"");
#line 251 "..\..\Views\User\UserParts\_Subject.cshtml" #line 252 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(userFlag.Name); Write(userFlag.Name);
@@ -1025,32 +1035,32 @@ WriteLiteral("\"");
WriteLiteral(">\r\n <i"); WriteLiteral(">\r\n <i");
WriteAttribute("class", Tuple.Create(" class=\"", 16599), Tuple.Create("\"", 16666) WriteAttribute("class", Tuple.Create(" class=\"", 16614), Tuple.Create("\"", 16681)
, Tuple.Create(Tuple.Create("", 16607), Tuple.Create("fa", 16607), true) , Tuple.Create(Tuple.Create("", 16622), Tuple.Create("fa", 16622), true)
, Tuple.Create(Tuple.Create(" ", 16609), Tuple.Create("fa-", 16610), true) , Tuple.Create(Tuple.Create(" ", 16624), Tuple.Create("fa-", 16625), true)
#line 252 "..\..\Views\User\UserParts\_Subject.cshtml" #line 253 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 16613), Tuple.Create<System.Object, System.Int32>(userFlag.Icon , Tuple.Create(Tuple.Create("", 16628), Tuple.Create<System.Object, System.Int32>(userFlag.Icon
#line default #line default
#line hidden #line hidden
, 16613), false) , 16628), false)
, Tuple.Create(Tuple.Create(" ", 16629), Tuple.Create("fa-fw", 16630), true) , Tuple.Create(Tuple.Create(" ", 16644), Tuple.Create("fa-fw", 16645), true)
, Tuple.Create(Tuple.Create(" ", 16635), Tuple.Create("fa-lg", 16636), true) , Tuple.Create(Tuple.Create(" ", 16650), Tuple.Create("fa-lg", 16651), true)
, Tuple.Create(Tuple.Create(" ", 16641), Tuple.Create("d-", 16642), true) , Tuple.Create(Tuple.Create(" ", 16656), Tuple.Create("d-", 16657), true)
#line 252 "..\..\Views\User\UserParts\_Subject.cshtml" #line 253 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 16644), Tuple.Create<System.Object, System.Int32>(userFlag.IconColour , Tuple.Create(Tuple.Create("", 16659), Tuple.Create<System.Object, System.Int32>(userFlag.IconColour
#line default #line default
#line hidden #line hidden
, 16644), false) , 16659), false)
); );
WriteLiteral("></i>"); WriteLiteral("></i>");
#line 252 "..\..\Views\User\UserParts\_Subject.cshtml" #line 253 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(userFlag.Name); Write(userFlag.Name);
@@ -1059,7 +1069,7 @@ WriteLiteral("></i>");
WriteLiteral("\r\n </div>\r\n"); WriteLiteral("\r\n </div>\r\n");
#line 254 "..\..\Views\User\UserParts\_Subject.cshtml" #line 255 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1083,7 +1093,7 @@ WriteLiteral("></textarea>\r\n </div>\r\n
" </div>\r\n"); " </div>\r\n");
#line 262 "..\..\Views\User\UserParts\_Subject.cshtml" #line 263 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1097,72 +1107,69 @@ WriteLiteral(" type=\"text/javascript\"");
WriteLiteral(">\r\n $(function () {\r\n " + WriteLiteral(">\r\n $(function () {\r\n " +
" const button = $(\'#User_Show_Details_Actions_AddFlag_Button\');\r\n " + " const button = $(\'#User_Show_Details_Actions_AddFlag_Button\');\r\n " +
" let buttonDialog = null;\r\n " + " let buttonDialog = null;\r\n\r\n " +
" const buttonLink = button.attr(\'href\');\r\n\r\n " + " let flagPicker = null;\r\n let flagA" +
" let flagPicker = null;\r\n let flagAddI" + "ddId = null;\r\n let flagAddComments = null;\r\n " +
"d = null;\r\n let flagAddComments = null;\r\n " + " let details = null;\r\n\r\n " +
" let details = null;\r\n\r\n " + " function flagSelected() {\r\n " +
" function flagSelected() {\r\n co" + " const flag = $(this);\r\n\r\n flagPicker.chi" +
"nst flag = $(this);\r\n\r\n flagPicker.childr" + "ldren().removeClass(\'selected\');\r\n flag.a" +
"en().removeClass(\'selected\');\r\n flag.addC" + "ddClass(\'selected\');\r\n\r\n flagAddId.val(fl" +
"lass(\'selected\');\r\n\r\n flagAddId.val(flag." + "ag.attr(\'data-userflagid\'));\r\n\r\n details." +
"attr(\'data-userflagid\'));\r\n\r\n details.sho" + "show();\r\n\r\n flagAddComments.focus().selec" +
"w();\r\n\r\n flagAddComments.focus().select()" + "t();\r\n }\r\n\r\n " +
";\r\n }\r\n\r\n " + " button.click(function (e) {\r\n e.preven" +
"button.attr(\'href\', \'#\').click(function (e) {\r\n " + "tDefault();\r\n\r\n if (!buttonDialog) {\r\n " +
" e.preventDefault();\r\n\r\n if (!butto" + " buttonDialog = $(\'#User_Show_Details_Ac" +
"nDialog) {\r\n buttonDialog = $(\'#User_" + "tions_AddFlag_Dialog\');\r\n buttonDialo" +
"Show_Details_Actions_AddFlag_Dialog\');\r\n " + "g.dialog({\r\n width: 600,\r\n " +
" buttonDialog.dialog({\r\n width" + " height: 410,\r\n " +
": 600,\r\n height: 410,\r\n " + " resizable: false,\r\n " +
" resizable: false,\r\n " + " modal: true,\r\n autoOpen" +
" modal: true,\r\n " + ": false,\r\n buttons: {\r\n " +
" autoOpen: false,\r\n buttons" + " Cancel: function () {\r\n " +
": {\r\n Cancel: function () {\r\n" + " $(this).dialog(\"close\");\r\n " +
" $(this).dialog(\"close\");" + " },\r\n " +
"\r\n },\r\n " + " \"Add Flag\": function () {\r\n " +
" \"Add Flag\": function () {\r\n " + " if (!!flagAddId.val()) {\r\n " +
" if (!!flagAddId.val()) {\r\n " + " buttonDialog\r\n " +
" const $this = $(this);\r\n " + " .dialog(\"option\", \"buttons\", null)\r\n " +
" $this.dialog(\"disable\");\r\n " + " .find(\'form\').submit();\r\n " +
" $this.dialog(\"option\", \"buttons" + " } else {\r\n " +
"\", null);\r\n buttonDia" + " alert(\'Select a User Flag\');\r\n " +
"log.find(\'form\').submit();\r\n " + " }\r\n " +
" } else {\r\n alert(" + " }\r\n }\r\n " +
"\'Select a User Flag\');\r\n " + " });\r\n\r\n " +
"}\r\n }\r\n " + " flagAddId = $(\'#User_Show_Details_Actions_AddFlag_Dialog_Id\');\r\n " +
" }\r\n });\r\n\r\n" + " flagAddComments = buttonDialog.find(\'#User_Show_D" +
" flagAddId = $(\'#User_Show_Details_Ac" + "etails_Actions_AddFlag_Dialog_Comments\');\r\n " +
"tions_AddFlag_Dialog_Id\');\r\n flagAddC" + " flagPicker = buttonDialog.find(\'.flagPicker\');\r\n " +
"omments = buttonDialog.find(\'#User_Show_Details_Actions_AddFlag_Dialog_Comments\'" + " details = buttonDialog.find(\'.details\');\r\n\r\n " +
");\r\n flagPicker = buttonDialog.find(\'" + " $(\'#User_Show_Details_Actions_AddFlag_Dialog_Filter\')" +
".flagPicker\');\r\n details = buttonDial" + ".on(\'keyup\', function (e) {\r\n con" +
"og.find(\'.details\');\r\n\r\n $(\'#User_Sho" + "st filter = $(e.currentTarget).val().toLowerCase();\r\n " +
"w_Details_Actions_AddFlag_Dialog_Filter\').on(\'keyup\', function (e) {\r\n " + " if (filter) {\r\n " +
" const filter = $(e.currentTarget).val().to" + " flagPicker.children(\'div.flag\').each(function () {\r\n " +
"LowerCase();\r\n if (filter) {\r\n " + " const $this = $(this);\r\n " +
" flagPicker.children(\'div.flag\')" + " if ($this.attr(\'data-userflagname\').toLowerC" +
".each(function () {\r\n con" + "ase().indexOf(filter) >= 0) {\r\n " +
"st $this = $(this);\r\n if " + " $this.css(\'display\', \'block\');\r\n " +
"($this.attr(\'data-userflagname\').toLowerCase().indexOf(filter) >= 0) {\r\n " + " } else {\r\n " +
" $this.css(\'display\', \'block\'" + " $this.css(\'display\', \'none\');\r\n " +
");\r\n } else {\r\n " + " }\r\n });\r\n " +
" $this.css(\'display\', \'none\');\r" + " } else {\r\n " +
"\n }\r\n " + " flagPicker.children(\'div.flag\').each(function () { $(t" +
" });\r\n " + "his).css(\'display\', \'block\'); });\r\n " +
" } else {\r\n flagPicker.ch" + " }\r\n });\r\n\r\n " +
"ildren(\'div.flag\').each(function () { $(this).css(\'display\', \'block\'); });\r\n " + " flagPicker.on(\'click\', \'div.flag\', flagSelected);\r\n " +
" }\r\n " + " }\r\n\r\n $(\'" +
" });\r\n\r\n flagPicker.on(\'cli" + "#User_Show_Details_Actions_AddFlag_Dialog_Filter\').val(\'\');\r\n " +
"ck\', \'div.flag\', flagSelected);\r\n }\r\n\r\n " + " buttonDialog.dialog(\'open\');\r\n " +
" $(\'#User_Show_Details_Actions_AddFlag_Dial" + " return false;\r\n });\r\n " +
"og_Filter\').val(\'\');\r\n buttonDialog.dialo" + " });\r\n </script>\r\n");
"g(\'open\');\r\n return false;\r\n " +
" });\r\n });\r\n " +
" </script>\r\n");
#line 346 "..\..\Views\User\UserParts\_Subject.cshtml" #line 345 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1171,13 +1178,13 @@ WriteLiteral(">\r\n $(function () {\r\n
WriteLiteral(" </div>\r\n </div>\r\n </td>\r\n"); WriteLiteral(" </div>\r\n </div>\r\n </td>\r\n");
#line 350 "..\..\Views\User\UserParts\_Subject.cshtml" #line 349 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 350 "..\..\Views\User\UserParts\_Subject.cshtml" #line 349 "..\..\Views\User\UserParts\_Subject.cshtml"
if (Authorization.Has(Claims.User.ShowAssignments)) if (Authorization.Has(Claims.User.ShowAssignments))
{ {
@@ -1195,13 +1202,13 @@ WriteLiteral(" id=\"User_Show_AssignedDevices_Active\"");
WriteLiteral(">\r\n <h3>Current Device Assignments</h3>\r\n"); WriteLiteral(">\r\n <h3>Current Device Assignments</h3>\r\n");
#line 356 "..\..\Views\User\UserParts\_Subject.cshtml" #line 355 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 356 "..\..\Views\User\UserParts\_Subject.cshtml" #line 355 "..\..\Views\User\UserParts\_Subject.cshtml"
if (currentDeviceAssignments.Count > 0) if (currentDeviceAssignments.Count > 0)
{ {
foreach (var assignment in currentDeviceAssignments) foreach (var assignment in currentDeviceAssignments)
@@ -1217,7 +1224,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment clearfix\"");
WriteLiteral(" data-deviceserialnumber=\""); WriteLiteral(" data-deviceserialnumber=\"");
#line 360 "..\..\Views\User\UserParts\_Subject.cshtml" #line 359 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.DeviceSerialNumber); Write(assignment.DeviceSerialNumber);
@@ -1228,13 +1235,13 @@ WriteLiteral("\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 361 "..\..\Views\User\UserParts\_Subject.cshtml" #line 360 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 361 "..\..\Views\User\UserParts\_Subject.cshtml" #line 360 "..\..\Views\User\UserParts\_Subject.cshtml"
if (Authorization.Has(Claims.Device.Show)) if (Authorization.Has(Claims.Device.Show))
{ {
@@ -1243,14 +1250,14 @@ WriteLiteral(">\r\n");
#line hidden #line hidden
WriteLiteral(" <a"); WriteLiteral(" <a");
WriteAttribute("href", Tuple.Create(" href=\"", 23450), Tuple.Create("\"", 23517) WriteAttribute("href", Tuple.Create(" href=\"", 23264), Tuple.Create("\"", 23331)
#line 363 "..\..\Views\User\UserParts\_Subject.cshtml" #line 362 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 23457), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Device.Show(assignment.Device.SerialNumber)) , Tuple.Create(Tuple.Create("", 23271), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.Device.Show(assignment.Device.SerialNumber))
#line default #line default
#line hidden #line hidden
, 23457), false) , 23271), false)
); );
WriteLiteral(">\r\n <img"); WriteLiteral(">\r\n <img");
@@ -1259,20 +1266,20 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Image\"");
WriteLiteral(" alt=\"Model Image\""); WriteLiteral(" alt=\"Model Image\"");
WriteAttribute("src", Tuple.Create(" src=\"", 23649), Tuple.Create("\"", 23770) WriteAttribute("src", Tuple.Create(" src=\"", 23463), Tuple.Create("\"", 23584)
#line 364 "..\..\Views\User\UserParts\_Subject.cshtml" #line 363 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 23655), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.DeviceModel.Image(assignment.Device.DeviceModel.Id, assignment.Device.DeviceModel.ImageHash())) , Tuple.Create(Tuple.Create("", 23469), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.DeviceModel.Image(assignment.Device.DeviceModel.Id, assignment.Device.DeviceModel.ImageHash()))
#line default #line default
#line hidden #line hidden
, 23655), false) , 23469), false)
); );
WriteLiteral(" />\r\n </a>\r\n"); WriteLiteral(" />\r\n </a>\r\n");
#line 366 "..\..\Views\User\UserParts\_Subject.cshtml" #line 365 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
else else
{ {
@@ -1286,20 +1293,20 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Image\"");
WriteLiteral(" alt=\"Model Image\""); WriteLiteral(" alt=\"Model Image\"");
WriteAttribute("src", Tuple.Create(" src=\"", 24082), Tuple.Create("\"", 24203) WriteAttribute("src", Tuple.Create(" src=\"", 23896), Tuple.Create("\"", 24017)
#line 369 "..\..\Views\User\UserParts\_Subject.cshtml" #line 368 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 24088), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.DeviceModel.Image(assignment.Device.DeviceModel.Id, assignment.Device.DeviceModel.ImageHash())) , Tuple.Create(Tuple.Create("", 23902), Tuple.Create<System.Object, System.Int32>(Url.Action(MVC.API.DeviceModel.Image(assignment.Device.DeviceModel.Id, assignment.Device.DeviceModel.ImageHash()))
#line default #line default
#line hidden #line hidden
, 24088), false) , 23902), false)
); );
WriteLiteral(" />\r\n"); WriteLiteral(" />\r\n");
#line 370 "..\..\Views\User\UserParts\_Subject.cshtml" #line 369 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1327,13 +1334,13 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_SerialNumber\
WriteLiteral(" data-clipboard>\r\n"); WriteLiteral(" data-clipboard>\r\n");
#line 380 "..\..\Views\User\UserParts\_Subject.cshtml" #line 379 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 380 "..\..\Views\User\UserParts\_Subject.cshtml" #line 379 "..\..\Views\User\UserParts\_Subject.cshtml"
if (Authorization.Has(Claims.Device.Show)) if (Authorization.Has(Claims.Device.Show))
{ {
@@ -1341,14 +1348,14 @@ WriteLiteral(" data-clipboard>\r\n");
#line default #line default
#line hidden #line hidden
#line 382 "..\..\Views\User\UserParts\_Subject.cshtml" #line 381 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(Html.ActionLink(assignment.Device.SerialNumber, MVC.Device.Show(assignment.Device.SerialNumber))); Write(Html.ActionLink(assignment.Device.SerialNumber, MVC.Device.Show(assignment.Device.SerialNumber)));
#line default #line default
#line hidden #line hidden
#line 382 "..\..\Views\User\UserParts\_Subject.cshtml" #line 381 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
else else
@@ -1358,14 +1365,14 @@ WriteLiteral(" data-clipboard>\r\n");
#line default #line default
#line hidden #line hidden
#line 386 "..\..\Views\User\UserParts\_Subject.cshtml" #line 385 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.Device.SerialNumber); Write(assignment.Device.SerialNumber);
#line default #line default
#line hidden #line hidden
#line 386 "..\..\Views\User\UserParts\_Subject.cshtml" #line 385 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1375,13 +1382,13 @@ WriteLiteral(" data-clipboard>\r\n");
WriteLiteral(" </span>\r\n"); WriteLiteral(" </span>\r\n");
#line 389 "..\..\Views\User\UserParts\_Subject.cshtml" #line 388 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 389 "..\..\Views\User\UserParts\_Subject.cshtml" #line 388 "..\..\Views\User\UserParts\_Subject.cshtml"
if (!string.IsNullOrWhiteSpace(assignment.Device.ComputerName)) if (!string.IsNullOrWhiteSpace(assignment.Device.ComputerName))
{ {
@@ -1397,7 +1404,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_ComputerName\
WriteLiteral(" data-clipboard>"); WriteLiteral(" data-clipboard>");
#line 391 "..\..\Views\User\UserParts\_Subject.cshtml" #line 390 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.Device.ComputerName); Write(assignment.Device.ComputerName);
@@ -1408,7 +1415,7 @@ WriteLiteral("</span>)");
WriteLiteral("\r\n"); WriteLiteral("\r\n");
#line 392 "..\..\Views\User\UserParts\_Subject.cshtml" #line 391 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1418,13 +1425,13 @@ WriteLiteral(" </td>\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 395 "..\..\Views\User\UserParts\_Subject.cshtml" #line 394 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 395 "..\..\Views\User\UserParts\_Subject.cshtml" #line 394 "..\..\Views\User\UserParts\_Subject.cshtml"
if (!string.IsNullOrEmpty(assignment.Device.AssetNumber)) if (!string.IsNullOrEmpty(assignment.Device.AssetNumber))
{ {
@@ -1441,7 +1448,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Asset\"");
WriteLiteral(" data-clipboard>"); WriteLiteral(" data-clipboard>");
#line 400 "..\..\Views\User\UserParts\_Subject.cshtml" #line 399 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.Device.AssetNumber); Write(assignment.Device.AssetNumber);
@@ -1451,7 +1458,7 @@ WriteLiteral("</span>\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 403 "..\..\Views\User\UserParts\_Subject.cshtml" #line 402 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1460,7 +1467,7 @@ WriteLiteral("</span>\r\n
WriteLiteral(" "); WriteLiteral(" ");
#line 404 "..\..\Views\User\UserParts\_Subject.cshtml" #line 403 "..\..\Views\User\UserParts\_Subject.cshtml"
if (assignment.Device.DeviceModelId.HasValue) if (assignment.Device.DeviceModelId.HasValue)
{ {
@@ -1479,7 +1486,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Model\"");
WriteLiteral(">"); WriteLiteral(">");
#line 411 "..\..\Views\User\UserParts\_Subject.cshtml" #line 410 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.Device.DeviceModel.ToString()); Write(assignment.Device.DeviceModel.ToString());
@@ -1489,7 +1496,7 @@ WriteLiteral("</span>\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 414 "..\..\Views\User\UserParts\_Subject.cshtml" #line 413 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1507,7 +1514,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Profile\"");
WriteLiteral(">"); WriteLiteral(">");
#line 420 "..\..\Views\User\UserParts\_Subject.cshtml" #line 419 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.Device.DeviceProfile.ToString()); Write(assignment.Device.DeviceProfile.ToString());
@@ -1517,13 +1524,13 @@ WriteLiteral("</span>\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 423 "..\..\Views\User\UserParts\_Subject.cshtml" #line 422 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 423 "..\..\Views\User\UserParts\_Subject.cshtml" #line 422 "..\..\Views\User\UserParts\_Subject.cshtml"
if (assignment.Device.DeviceBatchId.HasValue) if (assignment.Device.DeviceBatchId.HasValue)
{ {
@@ -1542,7 +1549,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Batch\"");
WriteLiteral(">"); WriteLiteral(">");
#line 430 "..\..\Views\User\UserParts\_Subject.cshtml" #line 429 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(assignment.Device.DeviceBatch.ToString()); Write(assignment.Device.DeviceBatch.ToString());
@@ -1552,7 +1559,7 @@ WriteLiteral("</span>\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 433 "..\..\Views\User\UserParts\_Subject.cshtml" #line 432 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1568,7 +1575,7 @@ WriteLiteral(" class=\"User_Show_AssignedDevices_CurrentAssignment_Assigned\"");
WriteLiteral(">"); WriteLiteral(">");
#line 437 "..\..\Views\User\UserParts\_Subject.cshtml" #line 436 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(CommonHelpers.FriendlyDate(assignment.AssignedDate)); Write(CommonHelpers.FriendlyDate(assignment.AssignedDate));
@@ -1578,15 +1585,14 @@ WriteLiteral("</span>\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 440 "..\..\Views\User\UserParts\_Subject.cshtml" #line 439 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 440 "..\..\Views\User\UserParts\_Subject.cshtml" #line 439 "..\..\Views\User\UserParts\_Subject.cshtml"
if (Authorization.Has(Claims.Device.ShowFlagAssignments) && if (assignment.Device.DeviceFlagAssignments.CanShowAny())
assignment.Device.DeviceFlagAssignments.Any(a => a.RemovedDate.HasValue))
{ {
@@ -1604,50 +1610,52 @@ WriteLiteral(" class=\"User_Show_Assigned_Devices_CurrentAssignment_Flags\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 446 "..\..\Views\User\UserParts\_Subject.cshtml" #line 444 "..\..\Views\User\UserParts\_Subject.cshtml"
#line default #line default
#line hidden #line hidden
#line 446 "..\..\Views\User\UserParts\_Subject.cshtml" #line 444 "..\..\Views\User\UserParts\_Subject.cshtml"
foreach (var flag in assignment.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) foreach (var flag in assignment.Device.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId))))
{ {
if (flag.Item2.permission.CanShow())
{
#line default #line default
#line hidden #line hidden
WriteLiteral(" <i"); WriteLiteral(" <i");
WriteAttribute("class", Tuple.Create(" class=\"", 30837), Tuple.Create("\"", 30907) WriteAttribute("class", Tuple.Create(" class=\"", 30707), Tuple.Create("\"", 30787)
, Tuple.Create(Tuple.Create("", 30845), Tuple.Create("flag", 30845), true) , Tuple.Create(Tuple.Create("", 30715), Tuple.Create("flag", 30715), true)
, Tuple.Create(Tuple.Create(" ", 30849), Tuple.Create("fa", 30850), true) , Tuple.Create(Tuple.Create(" ", 30719), Tuple.Create("fa", 30720), true)
, Tuple.Create(Tuple.Create(" ", 30852), Tuple.Create("fa-", 30853), true) , Tuple.Create(Tuple.Create(" ", 30722), Tuple.Create("fa-", 30723), true)
#line 448 "..\..\Views\User\UserParts\_Subject.cshtml" #line 448 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 30856), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon , Tuple.Create(Tuple.Create("", 30726), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 30856), false) , 30726), false)
, Tuple.Create(Tuple.Create(" ", 30874), Tuple.Create("fa-fw", 30875), true) , Tuple.Create(Tuple.Create(" ", 30749), Tuple.Create("fa-fw", 30750), true)
, Tuple.Create(Tuple.Create(" ", 30880), Tuple.Create("d-", 30881), true) , Tuple.Create(Tuple.Create(" ", 30755), Tuple.Create("d-", 30756), true)
#line 448 "..\..\Views\User\UserParts\_Subject.cshtml" #line 448 "..\..\Views\User\UserParts\_Subject.cshtml"
, Tuple.Create(Tuple.Create("", 30883), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour , Tuple.Create(Tuple.Create("", 30758), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 30883), false) , 30758), false)
); );
WriteLiteral(">\r\n <s" + WriteLiteral(">\r\n " +
"pan"); " <span");
WriteLiteral(" class=\"details\""); WriteLiteral(" class=\"details\"");
WriteLiteral(">\r\n " + WriteLiteral(">\r\n " +
" <span"); " <span");
WriteLiteral(" class=\"name\""); WriteLiteral(" class=\"name\"");
@@ -1655,7 +1663,7 @@ WriteLiteral(">");
#line 450 "..\..\Views\User\UserParts\_Subject.cshtml" #line 450 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(flag.Item2.Name); Write(flag.Item2.flag.Name);
#line default #line default
@@ -1664,8 +1672,8 @@ WriteLiteral("</span>");
#line 450 "..\..\Views\User\UserParts\_Subject.cshtml" #line 450 "..\..\Views\User\UserParts\_Subject.cshtml"
if (flag.Item1.Comments != null) if (flag.Item1.Comments != null)
{ {
#line default #line default
#line hidden #line hidden
@@ -1677,7 +1685,7 @@ WriteLiteral(">");
#line 451 "..\..\Views\User\UserParts\_Subject.cshtml" #line 451 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(flag.Item1.Comments.ToHtmlComment()); Write(flag.Item1.Comments.ToHtmlComment());
#line default #line default
@@ -1686,7 +1694,7 @@ WriteLiteral("</span>");
#line 451 "..\..\Views\User\UserParts\_Subject.cshtml" #line 451 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
#line default #line default
#line hidden #line hidden
@@ -1698,17 +1706,18 @@ WriteLiteral(">");
#line 451 "..\..\Views\User\UserParts\_Subject.cshtml" #line 451 "..\..\Views\User\UserParts\_Subject.cshtml"
Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)); Write(CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId));
#line default #line default
#line hidden #line hidden
WriteLiteral("</span>\r\n " + WriteLiteral("</span>\r\n " +
" </span>\r\n " + " </span>\r\n " +
" </i>\r\n"); " </i>\r\n");
#line 454 "..\..\Views\User\UserParts\_Subject.cshtml" #line 454 "..\..\Views\User\UserParts\_Subject.cshtml"
}
} }
@@ -1761,7 +1770,7 @@ WriteLiteral(">\r\n
" </tr>\r\n"); " </tr>\r\n");
#line 488 "..\..\Views\User\UserParts\_Subject.cshtml" #line 489 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1772,7 +1781,7 @@ WriteLiteral(" </tbody>\r\n
" </div>\r\n"); " </div>\r\n");
#line 493 "..\..\Views\User\UserParts\_Subject.cshtml" #line 494 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
} }
else else
@@ -1788,7 +1797,7 @@ WriteLiteral(" class=\"smallMessage\"");
WriteLiteral(">No Current Device Assignments</span>\r\n"); WriteLiteral(">No Current Device Assignments</span>\r\n");
#line 498 "..\..\Views\User\UserParts\_Subject.cshtml" #line 499 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
@@ -1798,7 +1807,7 @@ WriteLiteral(" </div>\r\n </div>\r\n
"\r\n"); "\r\n");
#line 502 "..\..\Views\User\UserParts\_Subject.cshtml" #line 503 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
+9 -9
View File
@@ -42,22 +42,22 @@
{ {
@item.FriendlyId @item.FriendlyId
} }
@if (Authorization.Has(Claims.User.ShowFlagAssignments)) @if (item.UserFlagAssignments.CanShowAny())
{ {
@if (item.UserFlagAssignments != null && item.UserFlagAssignments.Count > 0) <div class="flags">
{ @foreach (var flag in item.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId))))
<div class="flags"> {
@foreach (var flag in item.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) if (flag.Item2.permission.CanShow())
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> <i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw d-@(flag.Item2.flag.IconColour)">
<span class="details"> <span class="details">
<span class="name">@flag.Item2.Name</span>@if (flag.Item1.Comments != null) <span class="name">@flag.Item2.flag.Name</span>@if (flag.Item1.Comments != null)
{<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUserId)</span>
</span> </span>
</i> </i>
} }
</div> }
} </div>
} }
</td> </td>
<td> <td>
+24 -35
View File
@@ -173,35 +173,29 @@ WriteLiteral(" ");
#line 45 "..\..\Views\User\_UserTable.cshtml" #line 45 "..\..\Views\User\_UserTable.cshtml"
if (Authorization.Has(Claims.User.ShowFlagAssignments)) if (item.UserFlagAssignments.CanShowAny())
{ {
#line default
#line hidden
#line 47 "..\..\Views\User\_UserTable.cshtml"
if (item.UserFlagAssignments != null && item.UserFlagAssignments.Count > 0)
{
#line default #line default
#line hidden #line hidden
WriteLiteral(" <div"); WriteLiteral(" <div");
WriteLiteral(" class=\"flags\""); WriteLiteral(" class=\"flags\"");
WriteLiteral(">\r\n"); WriteLiteral(">\r\n");
#line 50 "..\..\Views\User\_UserTable.cshtml" #line 48 "..\..\Views\User\_UserTable.cshtml"
#line default #line default
#line hidden #line hidden
#line 50 "..\..\Views\User\_UserTable.cshtml" #line 48 "..\..\Views\User\_UserTable.cshtml"
foreach (var flag in item.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId)))) foreach (var flag in item.UserFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, UserFlagService.GetUserFlag(f.UserFlagId))))
{
if (flag.Item2.permission.CanShow())
{ {
@@ -209,26 +203,26 @@ WriteLiteral(">\r\n");
#line hidden #line hidden
WriteLiteral(" <i"); WriteLiteral(" <i");
WriteAttribute("class", Tuple.Create(" class=\"", 2064), Tuple.Create("\"", 2134) WriteAttribute("class", Tuple.Create(" class=\"", 2015), Tuple.Create("\"", 2095)
, Tuple.Create(Tuple.Create("", 2072), Tuple.Create("flag", 2072), true) , Tuple.Create(Tuple.Create("", 2023), Tuple.Create("flag", 2023), true)
, Tuple.Create(Tuple.Create(" ", 2076), Tuple.Create("fa", 2077), true) , Tuple.Create(Tuple.Create(" ", 2027), Tuple.Create("fa", 2028), true)
, Tuple.Create(Tuple.Create(" ", 2079), Tuple.Create("fa-", 2080), true) , Tuple.Create(Tuple.Create(" ", 2030), Tuple.Create("fa-", 2031), true)
#line 52 "..\..\Views\User\_UserTable.cshtml" #line 52 "..\..\Views\User\_UserTable.cshtml"
, Tuple.Create(Tuple.Create("", 2083), Tuple.Create<System.Object, System.Int32>(flag.Item2.Icon , Tuple.Create(Tuple.Create("", 2034), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.Icon
#line default #line default
#line hidden #line hidden
, 2083), false) , 2034), false)
, Tuple.Create(Tuple.Create(" ", 2101), Tuple.Create("fa-fw", 2102), true) , Tuple.Create(Tuple.Create(" ", 2057), Tuple.Create("fa-fw", 2058), true)
, Tuple.Create(Tuple.Create(" ", 2107), Tuple.Create("d-", 2108), true) , Tuple.Create(Tuple.Create(" ", 2063), Tuple.Create("d-", 2064), true)
#line 52 "..\..\Views\User\_UserTable.cshtml" #line 52 "..\..\Views\User\_UserTable.cshtml"
, Tuple.Create(Tuple.Create("", 2110), Tuple.Create<System.Object, System.Int32>(flag.Item2.IconColour , Tuple.Create(Tuple.Create("", 2066), Tuple.Create<System.Object, System.Int32>(flag.Item2.flag.IconColour
#line default #line default
#line hidden #line hidden
, 2110), false) , 2066), false)
); );
WriteLiteral(">\r\n <span"); WriteLiteral(">\r\n <span");
@@ -243,7 +237,7 @@ WriteLiteral(">");
#line 54 "..\..\Views\User\_UserTable.cshtml" #line 54 "..\..\Views\User\_UserTable.cshtml"
Write(flag.Item2.Name); Write(flag.Item2.flag.Name);
#line default #line default
@@ -252,7 +246,7 @@ WriteLiteral("</span>");
#line 54 "..\..\Views\User\_UserTable.cshtml" #line 54 "..\..\Views\User\_UserTable.cshtml"
if (flag.Item1.Comments != null) if (flag.Item1.Comments != null)
{ {
#line default #line default
@@ -297,20 +291,15 @@ WriteLiteral("</span>\r\n </span>
#line 58 "..\..\Views\User\_UserTable.cshtml" #line 58 "..\..\Views\User\_UserTable.cshtml"
} }
}
#line default
#line hidden
WriteLiteral("\r\n </div>\r\n");
#line 60 "..\..\Views\User\_UserTable.cshtml"
}
#line default #line default
#line hidden #line hidden
WriteLiteral(" </div>\r\n");
#line 60 "..\..\Views\User\_UserTable.cshtml" #line 61 "..\..\Views\User\_UserTable.cshtml"
} }