feature: flag permissions

feature: flag permissions
This commit is contained in:
Gary Sharp committed 2025-07-31 19:03:33 +10:00
1 parent 7deead494b
commit be7ee4cae8
72 files changed
+5334 -1853

No files matched your search

+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");
}
}
}
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Target" xml:space="preserve">
<value>H4sIAAAAAAAEAO1925Ict47g+0bsPyj6aXciRi3JsiyfkGdCbkl2ayS1TrdsP3akqtjdOc7KLGdmyerza/uwn7S/sGReeQF4S+alSvVwfNRFEARAJAiSIPD//s//ffGfXzfJgy8kL+Is/enk8cNHJw9IusrWcXr708muvPn35yf/+R//83+8eL3efH3wewv3HYOjPdPip5O7stz+4/S0WN2RTVQ83MSrPCuym/LhKtucRuvs9MmjRz+ePn58SiiKE4rrwYMXl7u0jDek+oP+eZalK7Itd1HyPluTpGh+py1XFdYHH6INKbbRivx08iouVtnDV1EZPbwk26yIyyy/P3nwMokjSswVSW5OHmyf/uO3glyVeZbeXm2jMo6ST/dbQttvoqQgDen/2D61pf7RE0b9aZSmWUnRZakX9ycdX5Sz11QC5T0jq+LupxMqhJv4dpdX+M9LIoDTDv9F7oUf6E8f82xL8vL+ktw0SK5W9JeTB6dmSIpOhntxKo/R9RPRM6rpH2VOteTkwZv4K1m/I+ltedcJ+H30tf3lOVWV39KY6hTtU+Y72vphlyTR54R04KfaUStSJx7z9yjZuXJK/6kZtv6bH/XFaa8EWtV4la12G5KWn8hmm0Ql8dGM87X7dLM+ThL4brDcX5Filcfb+htzGvvJ94MH91HvZ0MHfRMnJclff93mpCjc2XZVOpWAi/QXkhJqd8isRJxvtllevizLaHXHlH0BxNBFJH+TRLeXu4QUk1NBRy5Lkr7J8k079s9ZlpAo9fiqvsQrUryL0z/J+pc8220n54bJclYCzotf4/WapM6y/BB9iW+rVVnC+Db7fLX7XHkWJw8uSVLBFHfxtvZDHspm+1ro8CbPNpdZAph3Hu76KtvlK2aUMgvgT1F+S0rPVaZHFGZ9AcHoIGyESVajJ4MXBI5ap5G/n28ZfPzInWtUw3trPLKWt4prpeXtJ2HLRW39zjJq01OKE2FDBEK5wMFUJjSwrjzQvv/ckR0yB20rRjXUrpALAnnQWVkQhErWpiFSboZoVGA8SESlqKHNRJeRJnt3X9Sb6b3987T87glgNui++oput0nrL64/Mg8lT1lfUnFh54hUu3zNcDbL+VgW0mbss6wo20FfkVW8iZKTBx9z+q/mGOX5yYOrVcTQQWJ0s1uVsDQmq2q/Vm2cbLNgOMRoIcAen5reQxpudBX/yMJAD/gq69k4qC/S9zv6fvB39D5KdzfRqtzlJHf27QYPXn9Xc4xar5BOIz8dOvArchPtkvIj/VruooK8YsdIrQmj//4UbzxQ1p+anzF0IPqPKM+jtLynrV/itbOuhJLdJdlGcT4ZESH82YGLA2xcDSuJGxs66q+FFVCmmW9FljEBJIBP5nUkT/I4Sj7sNp+ZzjifuAu93U4mB29/XxYFKb3GHvzJvctWUfBDYHujFsZDZZjojzdxQsxLuQ2yn6NydReErFfZJopT94ONoeKlKhXfpmTNjgOnH/1dVJQfSPl3lv/5LrvN0hCr4Mskyf7+LY125R3zuFbMC3ud5lnnW/ge2p7lhOEy0WiFqyIoMSOzFWKFL4wPsco2m7g65w9DHo/xkkQFZ0PqlUVuLoauxKYdmsMyBi+44ErnRmNjhjRUNhDX3bIsEyoBIEuuDOV3WFcZOg2xVTtOqtCMECrCuJLJ2zHd1ItwytzzzdjkCzB+s8+61mg2BodRhGzEoxIOgiGChmH99OIVKaM40TFQQ6CEC80IwSKMH6H9ybmO2B4KJVgBQYhW4TyPyekv8U21jGnPbHowlHQVBjsiVwGDHeo2+Op25ftjP2PfXdXm972xS2O7702EREUJgiHShGG9L01MHFzLkMgC1wLo17gOKsBZXbvmHdBpHfvvBBeC8ib0LstLr6HnuwcdfjrZnPpc5LdRGheV8r9cr1lMyqD9Fzsx2dFZZ391AV0hgyHsBBsXdKzPO8aVcBxZfdhSY+GMnhdalFBSy6As2sj5dXqT5fUBVSvusyz9wr6zzD0IBEaOs+mLuDpdZHuTl69erlbZLh2MkXcf2alK8nK9iQcLoNn10okoqB27JPEmuiV0xaw2hsyCH0DIEi+5WQnh/KP29Nk1HG34zQVHxMtdSVeEuD+Qn56aP+KcJNQUN2v8hIQMOM923mLDrhK2ER/gKtX77W/bURruMdhertk5XbvtNolnuBjtuGj32hNLkS2jY14qMvz/3EWNGg06Sa8cxHA3Bu095+9REq/p4honOi1yweg3lwGCbtNil4c5161QRemKzPZhNMwEmZiOm7lmpt+vTzzwN+3YaZwH2ZZYnH6rXbCDcBkS8SxQcL9jsAqd3UmoBHotXAOAXMHAusN+pIffyZiRGdvbCf1MhPXwegkckq9ndzdu5XR9Iqu78FfTtu/ASBraa7Ua+T1dvzxC0gKMzFbOoow228Hesudy5uGthri5DGHoNHbDYBptGWo/Bgdu+i4mVlpISz468EGmsCLNw/K1JsHV+s1kSl7FxTaJ7j32wMOd5Ktd7mHFho/7S/yFpLNw/PEuS4lXlNzwlwivN3TzIN1K2A7uHk2FWgqm57qr+b79WrYOUpPiv8ntrt5aFX1gcEFFGJBEqRkkU4bxcyy9YzX0oSYaYLu4DTBUZfD1fIVNvpzvflQWh77FdTFr33KbRKvCgfoAgIA6AcH5qLD2Ir7CKkJJwuQbYaEKEIMX2fqLDbfUwpHV4yY7mWnx9klCEeCO3z3JSoBBp8iyYvqyhi5Y0NcELWje39JhbtrnCQA/7u+P+3vH42opE0HYnEg2FPwapevEQ2VDDUxtCclJuvJIgxGIApbtbamrhOO+AVotsL1FkHMaaQDogAYBMdGqPZLR7nPkdGYWdKt9UPqV3CEGPhT4AKft4t7JZ92u8egeD4Ld2l1afePquvBDg07/5pBjYOCqMe9rs9/SyJIZN3tk+fYk2PEAfEJrc6DgdvIx1rMUK/qlkHqvb/9t9vmQXPQZs1+NaYZss9VNbzAutnSu1jPuUWoCwrw4/bolK6p1Z0lWhAkAqjGNIx378UNwwg4F+51M6+28j9LoljBj1LT7xNX8SpL1UPJ6TPMJu6fBMxPA8LuVmoRLEq3v32R0F1Tu8jSMaEWccwu5piLU42se43yc/RHFJR2Iyrha5le8Ag13wAxJ7q67diWBHPtZ8Uf4NlfPyZRhyyGnHUKWNnvWIKdO+ygTSegi3AoF2cBrbp+gCx0/CsSVHZ0pGUycLLEVnC8JxHXKxCUWJVMGE8kUW0EyJRA/zeIXKJRUCFQkV4UASQbA/MiGjb+BAawTxAoMq2EK6eDLnmj7jYzJ4DBLIpSWGQnUw6Ka4gUEEGYQJKrFRihZqAThcZ1uSP/FQwAUCm0QgSKAB33vsluUMtoG0NT8ClHTNo2TNbdZ6KCEuU0Tmiu3bfcg7D0po+4VAEafAAQQqbRDlKpAnuS2r0l01LYwCLF8M0arAONJ6ocstaGWA0MIliAwmmWwQcnmWv9x8rOkfU9v7uzGm3znyid3yFcNrEsKzNAjxsOMB6CMHYP3j5f7x8v94+X+pJf71ao/3McHDD+yCwhyqy+iRzZPNnf6CNgoV/riWLobfT2kgYmw9/n8Xui43i5lvZ0zL9RE1R80hsl+Zw98KfDWP5RV6rEjRkkF0BMZ5uFXfYZw/H6X8v3O7jv6pFDz+VT1R12A5sunYKE+TIYX+ST5JoykYJ9he2x2YN9ixdbQDzLAN/1yvQ4VO8cwzWQeqrGbL3vy7CCXZJN9CXMd3qCa5w68GXwuMV69e/n66zbOSRFCkh/zuMo4J0TNtN9d3zjEhFeo9OX1WuMFF9frWvHSej2Ix7n20EsMwLSDlxzWcaithTASxkHC5HUAWiJ7KFdSuQ/RSKwAC5PLgWgJ5uGCLJyHtGp+cD8vDfDkcM6d4/nKo6DNUIbZoGdZQrXUWdjDZV0lkmpXgmHZ9gKtAPIqtfv832RVnq8nSIQ25CLKvbwrZpcGxXRxC2CIdRKlUV1Kfc2meM3uYT4bp9zVggbw5d9lRXGRv4pYauUQPtRrlvzat7BWgHBaX8M73Bf9dBfndIGiP5xFu4J08+KbnFrG57GUDReoTMQfd64v+J8FSMNcpqQoSMH+LJpENMQ5Fc1wYfy8y2+TKL//dEduSvrN32XrixtqD3JXmQTIB9T8yepkXRESpMjYxyyJV+RDxjJwD1dfEdtVOY9BEKkIL6WznKK4JFtWuyJz5O7pYO4uyYq6/vklWe9WRAxAt6Th+WAaLso7ktO1h9CvsvLQ8zJ2/jgD3LLT6by4adNKD38GFMWbN1m+uaKrWZh3RRzCeY5q6szCc2U07oMAxifA53zDPQgS8CvxSEn74HhJT+zoBbppqFegzbyoXUL4zF305F65zK+/sjOIKAl+tmDlXzeDv8tub8MsaC1G3w80HE/sQjYhFuVIg371LsHEyHcCBu8O+TD4yOK9+jbOi85mVCZjqBfZ1Ceienh2x+R6Sf7axYGS/WO451meZWqsLtm8ES+Dx49RPAqLDO88HLYO6EW+pi5PFAd6zA2gXQJ/3i5dSCpCuegK0rnc9C9Z9cRsReJAN8QSyrluircRta75LF5TO3g4r6nFOJ/X1FIwktekWx1tXzvpcWifQem6Ym6YdX/nS2hsCfUVBHZXbd3PRwT+N9vY+urLft/fifu2mw/zXV9X3pGl15Z1tLuWc6SXDeNY10F825xGoERoziSMfZw51p5P6PgFFklbbsGuWl6BHjacQt08np6HfaxqQffgbTHjVMxyfkhBKi13QzffcwZS7n046GFFZIZjY6Y8aHNVDrxIexvz+uuWXTVTO3lJil0yfXjrRdqm95yHHGOhC5fqFjW8scIF+wnMpovB+hTpCF2Vw5LewNGvwCjgxkIHZ0P6eCGxwGBIZKwe0oYLU5ysmQ93Nqy5cGNi+AVc90EekBt1jPU99FhfprWzFvVlBCygtjDspCzGPZmckI8k38TV0MXbLine truncated
</data>
</root>
+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; }
} }
} }
+16 -8
View File
@@ -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,7 +575,8 @@ 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;
@@ -796,8 +802,10 @@ namespace Disco.Services.Authorization
return c; return c;
} }
public static RoleClaims ComputerAccountClaims() { public static RoleClaims ComputerAccountClaims()
return new RoleClaims() { {
return new RoleClaims()
{
ComputerAccount = true ComputerAccount = true
}; };
} }
+16 -8
View File
@@ -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,7 +127,8 @@ 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);#>
@@ -130,8 +136,10 @@ namespace Disco.Services.Authorization
return c; return c;
} }
public static RoleClaims ComputerAccountClaims() { public static RoleClaims ComputerAccountClaims()
return new RoleClaims() { {
return new RoleClaims()
{
ComputerAccount = true ComputerAccount = true
}; };
} }
+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");
@@ -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");
@@ -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\"");
@@ -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,7 +39,8 @@
</th> </th>
<td> <td>
@if (canConfig) @if (canConfig)
{@Html.EditorFor(model => model.DeviceFlag.Name) {
@Html.EditorFor(model => model.DeviceFlag.Name)
@AjaxHelpers.AjaxSave() @AjaxHelpers.AjaxSave()
@AjaxHelpers.AjaxLoader() @AjaxHelpers.AjaxLoader()
<script type="text/javascript"> <script type="text/javascript">
@@ -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:
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;
+1 -1
View File
@@ -1 +1 @@
.tableData{border:solid 1px #f4f4f4;border-collapse:collapse;}.tableData>tbody>tr>td{border:solid 1px #f4f4f4;background-color:#fff;}.tableData>tbody>tr:nth-child(odd)>td{background-color:hsl(0,0%,98.5%);}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#f4f4f4;border:solid 1px #f4f4f4;}.tableData>tbody>tr:hover>td{background-color:hsl(0,0%,97.5%);}.tableData>tfoot>tr>th,.tableData>tfoot>tr>td{background-color:#f4f4f4;}.tableDataDark{border:solid 1px #d8d8d8;border-collapse:collapse;}.tableDataDark td{border:solid 1px #d8d8d8;background-color:#fff;}.tableDataDark th{background-color:#eee;border:solid 1px #d8d8d8;}.tableDataContainer{background-color:#fff;}.tableDataVertical{border:solid 1px #f4f4f4;border-collapse:collapse;}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#f4f4f4;margin:0;padding:0;}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right;}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa;}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right;}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right;}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer;}.subtleUntilHover{-moz-opacity:.3;opacity:.3;}.subtleUntilHover:hover{-moz-opacity:1;opacity:1;}#updateAvailableContainer{float:right;border:1px dashed #ddd;background-color:#fff;font-size:.6em;line-height:1em;padding:10px 10px 4px 70px;text-align:right;height:50px;}#updateAvailableContainer i{position:absolute;display:block;height:64px;width:64px;vertical-align:middle;margin-left:-70px;font-size:50px;color:#e51400;}#updateAvailableContainer button{font-size:12px;margin-top:8px;}.Config_HideAdvanced .Config_HideAdvanced_Item{display:none;}.Config_LinkedGroup_Instance{margin:4px 0 8px 4px;padding:4px 0 4px 6px;border-left:4px solid #ccc;background-color:#fff;}.Config_LinkedGroup_Instance div.code{margin-left:2px;}#Config_LinkedGroup_Dialog h3{margin-bottom:6px;}#Config_LinkedGroup_Dialog table.input{margin-top:12px;}#Config_LinkedGroup_Dialog table.input th{text-align:right;}#expressionEditor #expressionEditorExceptionContainer{display:none;border:1px dashed #ff9696;background-color:#ffd8d8;margin:10px 0;padding:10px;}#expressionEditor #expressionEditorContainer{border:1px solid #1e6dab;background-color:#f4f4f4;height:100px;}.expressionTree span.dynatree-node span.dynatree-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAQCAYAAACm53kpAAAGFklEQVRYw+WVe1BUVRzHvwE+QE0ZLF1Y3gTGSxIl4rk85KHFe0cUiIc8IjNx8gUmLJAFpbIKKJmmCSOi4q48zAe6LqAoioiIMlpOqYWxKCroWFNzO2eXXRdYCBqmf/rNfPece+6598738/ud3wJjHPV8WNwphoSO+L+F3HznWaTVbcGDsYQggkhjJPucWIhcGYYP5xnAKnkh0n1skcGxRobzLGx0MsYmR2MUO5qBMzEAiXhvxmLZU94tq/rJqzUV3q08zL+ei/lt+fC9sRt+N0vh334U/rdOYMEtMRnPqzL/4CxSu46jQFIJgSoI93FfZ7Tmi1FsVoSitWuwhv1Pe51ZcO0+g0BHNkqYH7BVrueXsPlhDYou7cYhrh2OOCzCdhQg7SWAcCYK4X/GIPyPBHBfJIP7fAWCe1chuGc9Qp5kIfhRDgIfbkHQo0IESnaCI74yKPNnkNZ5HPldxLxEiEuSw7i7fgl65BCo+Soc2zkaCHLzZSgLpeM2bBsWAscSM90McID5GTuy41BKzfdexOYn51Ao+R5lvwpR9bsAP65chr0z+TijqgLWw7dtI/zatsoy315GVA2/WyJp1uVyr7k6oOxT5ea7BGgk5u+pMt+N7pCRQtiP/VbUdA1qPLrxNLgFrR/T6wLsMlRscj+bpZAdn+tph5SeBvDi/HGYQjCfjObHtdj+8CRKOwQQ/XIIVyT78GhRFAQ6n6NJ9hKrZeGKF3IZdXDIefO/PQH2l7UQUD8FLnXaZG060Uy8c14PnAYjsJwa6Xb5me86KSv7LpL5riEyT8334FmSCOK8T7D6mrLZjhaEpacjFKzxoTAOWE2W1KhZUgFBj9ETRp+juozmFXQ9D3ksBYBIJgJOe32o+S4xPp1riKqGPdho+BrKKQQWxtXe3IMm8SbcFeWi8zMuJDPsIdLNxg3Z1y2TImUTRk1m/tiEoA78NlDwJOZd6gxg/r6/HAA1WZSCJ5IqCKVlL8BVah4Gvny5TuF0/kDzI6mADcgQfIEcfjOuLXmKZ/H0eTImilGfFI3Yo2SLuhSAV5MfNX9hH1Kpeeh4rHEwQnXjN/hWG69WMBfxk/F0dKpD84W1If4y0oJQ3Q779Xno6AMQG0vMvwKTwHUwWpgJQ/+vpIbJolzSa11XMdhuF5QBKEPoKsc9OioaHwXQVwE7satOlXma+RqhLPseC0gFsNVDYeCQRO/xkCkUQLjtJYTemFa0xcUjsTwa0S1kyzjoe7rRvW5u0Hcxw3d2s2BEr+cYw5VCaNqOFu1x6B0PtWJomyTLvzvRHxFTQ3FPdmUekaAq44MqwE1sTPTGQADKEPp1/T4AcgjUvCHIO0YYPGSVC1FRWI1qfg5y8w6hPGkpEk6kI6MuDnH9ADA8aFApHj54UB3qk0M9zUijM42yRgTDxiSdE6q/ZLYoWTnj0rmhTyH0vfaQD5RBn1MBPfeTJPu10HNpgFVK2EAAcgj9FpQA0JCaj68tQbyIPfD8C0sRFvcBQlnWCAHbdqnsCGyYRyAIjqKyoAKVW2MQ25yJzLoVSGkk82sc8ncO9nz3QQB4PDUsJz0soH0KFt+ZIVU0Yzo0AFPuR4OyLW16jaTpndaDH2l6nPNmcK63gHOjFWanRaoCMCiUAVDT1HwWkwiPYzUDIQxdBTzbLGQLDqCsiGZ9LdY1RCPmeglKLKUb9H1dZUmMipKKIUdZPldWFPPmsABId9eESbCiB8DQuxAGpAL0PA7A85yptAJoD6AVMFoAyuaXX8+Wzu2/ZkZ6FHKRa0ErIRZLmyMR2c4H31ZxU9+n/xE4SP7FSBNHkGgaQm6wwG03RsRNG8Qxs4cHYNsyCd6npsLrog6czr1Osq0Lb9LxXepMiMzhdcGSyBauDXNGBYBKlfkRVoA88pFvswQRt7OQZd/vRh8ARaa5zHjVFfBs7vAAqHldZwuwA21gnjAPs9e64C2eNxy+fBeOeSFw2hGu0EgBKJe/077Gf2t+2DAKfLtfBTCMpkJHGB3wGANkMJbIYWyGB0ANjVajCWp6rM3T0Ji2ifxUQV2rQqHxU4i0KomqoKHZN06sGhrAfxVjbX4M4m/gZza+uQwOHQAAAABJRU5ErkJggg==);background-position-y:0;}.expressionTree span.dynatree-node.object span.dynatree-icon{background-position-x:0;}.expressionTree span.dynatree-node.parameter span.dynatree-icon{background-position-x:-16px;}.expressionTree span.dynatree-node.function span.dynatree-icon{background-position-x:-32px;}.expressionTree span.dynatreeLine truncated .tableData{border:solid 1px #f4f4f4;border-collapse:collapse;}.tableData>tbody>tr>td{border:solid 1px #f4f4f4;background-color:#fff;}.tableData>tbody>tr:nth-child(odd)>td{background-color:hsl(0,0%,98.5%);}.tableData>thead>tr>th,.tableData>tbody>tr>th{background-color:#f4f4f4;border:solid 1px #f4f4f4;}.tableData>tbody>tr:hover>td{background-color:hsl(0,0%,97.5%);}.tableData>tfoot>tr>th,.tableData>tfoot>tr>td{background-color:#f4f4f4;}.tableDataDark{border:solid 1px #d8d8d8;border-collapse:collapse;}.tableDataDark td{border:solid 1px #d8d8d8;background-color:#fff;}.tableDataDark th{background-color:#eee;border:solid 1px #d8d8d8;}.tableDataContainer{background-color:#fff;}.tableDataVertical{border:solid 1px #f4f4f4;border-collapse:collapse;}.tableDataVertical>tbody>tr:nth-child(odd){background-color:#f4f4f4;margin:0;padding:0;}.tableDataVertical>tbody>tr>th.name{width:170px;text-align:right;}.tableDataVertical table.sub>tbody>tr:not(:first-child)>th,.tableDataVertical table.sub>tbody>tr:not(:first-child)>td{border-top:1px dashed #aaa;}.tableDataVertical table.sub>tbody>tr>th{font-weight:normal;text-align:right;}.tableDataVertical table.sub>tbody>tr>th.name{text-align:right;}.icon16{display:inline-block;height:16px;width:16px;margin-left:2px;cursor:pointer;}.subtleUntilHover{-moz-opacity:.3;opacity:.3;}.subtleUntilHover:hover{-moz-opacity:1;opacity:1;}#updateAvailableContainer{float:right;border:1px dashed #ddd;background-color:#fff;font-size:.6em;line-height:1em;padding:10px 10px 4px 70px;text-align:right;height:50px;}#updateAvailableContainer i{position:absolute;display:block;height:64px;width:64px;vertical-align:middle;margin-left:-70px;font-size:50px;color:#e51400;}#updateAvailableContainer button{font-size:12px;margin-top:8px;}.Config_HideAdvanced .Config_HideAdvanced_Item{display:none;}.Config_LinkedGroup_Instance{margin:4px 0 8px 4px;padding:4px 0 4px 6px;border-left:4px solid #ccc;background-color:#fff;}.Config_LinkedGroup_Instance div.code{margin-left:2px;}#Config_LinkedGroup_Dialog h3{margin-bottom:6px;}#Config_LinkedGroup_Dialog table.input{margin-top:12px;}#Config_LinkedGroup_Dialog table.input th{text-align:right;}#expressionEditor #expressionEditorExceptionContainer{display:none;border:1px dashed #ff9696;background-color:#ffd8d8;margin:10px 0;padding:10px;}#expressionEditor #expressionEditorContainer{border:1px solid #1e6dab;background-color:#f4f4f4;height:100px;}.expressionTree span.dynatree-node span.dynatree-icon{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAQCAYAAACm53kpAAAGFklEQVRYw+WVe1BUVRzHvwE+QE0ZLF1Y3gTGSxIl4rk85KHFe0cUiIc8IjNx8gUmLJAFpbIKKJmmCSOi4q48zAe6LqAoioiIMlpOqYWxKCroWFNzO2eXXRdYCBqmf/rNfPece+6598738/ud3wJjHPV8WNwphoSO+L+F3HznWaTVbcGDsYQggkhjJPucWIhcGYYP5xnAKnkh0n1skcGxRobzLGx0MsYmR2MUO5qBMzEAiXhvxmLZU94tq/rJqzUV3q08zL+ei/lt+fC9sRt+N0vh334U/rdOYMEtMRnPqzL/4CxSu46jQFIJgSoI93FfZ7Tmi1FsVoSitWuwhv1Pe51ZcO0+g0BHNkqYH7BVrueXsPlhDYou7cYhrh2OOCzCdhQg7SWAcCYK4X/GIPyPBHBfJIP7fAWCe1chuGc9Qp5kIfhRDgIfbkHQo0IESnaCI74yKPNnkNZ5HPldxLxEiEuSw7i7fgl65BCo+Soc2zkaCHLzZSgLpeM2bBsWAscSM90McID5GTuy41BKzfdexOYn51Ao+R5lvwpR9bsAP65chr0z+TijqgLWw7dtI/zatsoy315GVA2/WyJp1uVyr7k6oOxT5ea7BGgk5u+pMt+N7pCRQtiP/VbUdA1qPLrxNLgFrR/T6wLsMlRscj+bpZAdn+tph5SeBvDi/HGYQjCfjObHtdj+8CRKOwQQ/XIIVyT78GhRFAQ6n6NJ9hKrZeGKF3IZdXDIefO/PQH2l7UQUD8FLnXaZG060Uy8c14PnAYjsJwa6Xb5me86KSv7LpL5riEyT8334FmSCOK8T7D6mrLZjhaEpacjFKzxoTAOWE2W1KhZUgFBj9ETRp+juozmFXQ9D3ksBYBIJgJOe32o+S4xPp1riKqGPdho+BrKKQQWxtXe3IMm8SbcFeWi8zMuJDPsIdLNxg3Z1y2TImUTRk1m/tiEoA78NlDwJOZd6gxg/r6/HAA1WZSCJ5IqCKVlL8BVah4Gvny5TuF0/kDzI6mADcgQfIEcfjOuLXmKZ/H0eTImilGfFI3Yo2SLuhSAV5MfNX9hH1Kpeeh4rHEwQnXjN/hWG69WMBfxk/F0dKpD84W1If4y0oJQ3Q779Xno6AMQG0vMvwKTwHUwWpgJQ/+vpIbJolzSa11XMdhuF5QBKEPoKsc9OioaHwXQVwE7satOlXma+RqhLPseC0gFsNVDYeCQRO/xkCkUQLjtJYTemFa0xcUjsTwa0S1kyzjoe7rRvW5u0Hcxw3d2s2BEr+cYw5VCaNqOFu1x6B0PtWJomyTLvzvRHxFTQ3FPdmUekaAq44MqwE1sTPTGQADKEPp1/T4AcgjUvCHIO0YYPGSVC1FRWI1qfg5y8w6hPGkpEk6kI6MuDnH9ADA8aFApHj54UB3qk0M9zUijM42yRgTDxiSdE6q/ZLYoWTnj0rmhTyH0vfaQD5RBn1MBPfeTJPu10HNpgFVK2EAAcgj9FpQA0JCaj68tQbyIPfD8C0sRFvcBQlnWCAHbdqnsCGyYRyAIjqKyoAKVW2MQ25yJzLoVSGkk82sc8ncO9nz3QQB4PDUsJz0soH0KFt+ZIVU0Yzo0AFPuR4OyLW16jaTpndaDH2l6nPNmcK63gHOjFWanRaoCMCiUAVDT1HwWkwiPYzUDIQxdBTzbLGQLDqCsiGZ9LdY1RCPmeglKLKUb9H1dZUmMipKKIUdZPldWFPPmsABId9eESbCiB8DQuxAGpAL0PA7A85yptAJoD6AVMFoAyuaXX8+Wzu2/ZkZ6FHKRa0ErIRZLmyMR2c4H31ZxU9+n/xE4SP7FSBNHkGgaQm6wwG03RsRNG8Qxs4cHYNsyCd6npsLrog6czr1Osq0Lb9LxXepMiMzhdcGSyBauDXNGBYBKlfkRVoA88pFvswQRt7OQZd/vRh8ARaa5zHjVFfBs7vAAqHldZwuwA21gnjAPs9e64C2eNxy+fBeOeSFw2hGu0EgBKJe/077Gf2t+2DAKfLtfBTCMpkJHGB3wGANkMJbIYWyGB0ANjVajCWp6rM3T0Ji2ifxUQV2rQqHxU4i0KomqoKHZN06sGhrAfxVjbX4M4m/gZza+uQwOHQAAAABJRU5ErkJggg==);background-position-y:0;}.expressionTree span.dynatree-node.object span.dynatree-icon{background-position-x:0;}.expressionTree span.dynatree-node.parameter span.dynatree-icon{background-position-x:-16px;}.expressionTree span.dynatree-node.function span.dynatree-icon{background-position-x:-32px;}.expressionTree span.dynatreeLine truncated
+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,53 +156,53 @@ 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,14 +212,14 @@ 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,17 +487,31 @@ 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
#line hidden #line hidden
WriteLiteral(" <input"); WriteLiteral(" <input");
@@ -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,17 +552,31 @@ 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
#line hidden #line hidden
WriteLiteral(" <input"); WriteLiteral(" <input");
@@ -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,18 +239,21 @@
<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())
{
<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>
} }
}
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$('#Device_Show_User_Flags') $('#Device_Show_User_Flags')
@@ -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
+7 -4
View File
@@ -19,18 +19,21 @@
}); });
</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())
{
<i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw fa-lg 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.AddedUser)</span> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)</span>
</span> </span>
</i> </i>
} }
}
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
@@ -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)
} }
+49 -46
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,33 +144,35 @@ 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");
@@ -184,8 +186,8 @@ 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,7 +195,7 @@ 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)
{ {
@@ -206,7 +208,7 @@ 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());
@@ -215,7 +217,7 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 30 "..\..\Views\Device\Show.cshtml" #line 32 "..\..\Views\Device\Show.cshtml"
} }
#line default #line default
@@ -227,7 +229,7 @@ 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));
@@ -236,7 +238,8 @@ WriteLiteral(">");
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"
} }
+6 -6
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"> <div class="flags">
@foreach (var flag in item.DeviceFlagAssignments.Where(f => !f.RemovedDate.HasValue).Select(f => Tuple.Create(f, DeviceFlagService.GetDeviceFlag(f.DeviceFlagId)))) @foreach (var flag in item.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())
{
<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>
@@ -175,15 +175,7 @@ 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)
{ {
@@ -196,14 +188,22 @@ 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
@@ -302,17 +302,18 @@ WriteLiteral("</span>\r\n </span>
#line default #line default
#line hidden #line hidden
WriteLiteral("\r\n </div>\r\n");
#line 48 "..\..\Views\Device\_DeviceTable.cshtml"
#line 50 "..\..\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"
+12 -8
View File
@@ -256,20 +256,21 @@
</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())
{
<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>
} }
}
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$('#Job_Show_Device_Flags') $('#Job_Show_Device_Flags')
@@ -506,18 +507,21 @@
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())
{
<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>
} }
}
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$('#Job_Show_User_Flags') $('#Job_Show_User_Flags')
File diff suppressed because it is too large. Load diff
+7 -4
View File
@@ -13,18 +13,21 @@
} }
} }
<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())
{
<i class="flag fa fa-@(flag.Item2.flag.Icon) fa-fw fa-lg 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.AddedUser)</span> {<span class="comments">@flag.Item1.Comments.ToHtmlComment()</span>}<span class="added">@CommonHelpers.FriendlyDateAndUser(flag.Item1.AddedDate, flag.Item1.AddedUser)</span>
</span> </span>
</i> </i>
} }
}
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
@@ -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)
} }
+46 -43
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,33 +113,35 @@ 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");
@@ -153,8 +155,8 @@ 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,7 +164,7 @@ 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)
{ {
@@ -175,7 +177,7 @@ 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());
@@ -184,7 +186,7 @@ WriteLiteral(">");
WriteLiteral("</span>"); WriteLiteral("</span>");
#line 24 "..\..\Views\User\Show.cshtml" #line 26 "..\..\Views\User\Show.cshtml"
} }
#line default #line default
@@ -196,7 +198,7 @@ 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));
@@ -205,7 +207,8 @@ WriteLiteral(">");
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,53 +156,53 @@ 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,14 +212,14 @@ 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,17 +487,31 @@ 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
#line hidden #line hidden
WriteLiteral(" <input"); WriteLiteral(" <input");
@@ -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,17 +552,31 @@ 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
#line hidden #line hidden
WriteLiteral(" <input"); WriteLiteral(" <input");
@@ -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);
+13 -12
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,21 +436,23 @@
<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())
{
<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>
} }
}
<script type="text/javascript"> <script type="text/javascript">
$(function () { $(function () {
$('.User_Show_Assigned_Devices_CurrentAssignment_Flags') $('.User_Show_Assigned_Devices_CurrentAssignment_Flags')
@@ -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 default
#line hidden #line hidden
WriteLiteral(" <button");
#line 241 "..\..\Views\User\UserParts\_Subject.cshtml" WriteLiteral(" id=\"User_Show_Details_Actions_AddFlag_Button\"");
Write(Html.ActionLinkSmallButton("Add Flag", MVC.API.UserFlagAssignment.AddUser(), "User_Show_Details_Actions_AddFlag_Button"));
WriteLiteral(" type=\"button\"");
#line default WriteLiteral(" class=\"button small\"");
#line hidden
#line 241 "..\..\Views\User\UserParts\_Subject.cshtml" 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\"");
@@ -935,6 +931,20 @@ WriteLiteral(">\r\n");
{ {
#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
#line hidden #line hidden
WriteLiteral(" <input"); WriteLiteral(" <input");
@@ -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 co" + " function flagSelected() {\r\n " +
"nst flag = $(this);\r\n\r\n flagPicker.childr" + " const flag = $(this);\r\n\r\n flagPicker.chi" +
"en().removeClass(\'selected\');\r\n flag.addC" + "ldren().removeClass(\'selected\');\r\n flag.a" +
"lass(\'selected\');\r\n\r\n flagAddId.val(flag." + "ddClass(\'selected\');\r\n\r\n flagAddId.val(fl" +
"attr(\'data-userflagid\'));\r\n\r\n details.sho" + "ag.attr(\'data-userflagid\'));\r\n\r\n details." +
"w();\r\n\r\n flagAddComments.focus().select()" + "show();\r\n\r\n flagAddComments.focus().selec" +
";\r\n }\r\n\r\n " + "t();\r\n }\r\n\r\n " +
"button.attr(\'href\', \'#\').click(function (e) {\r\n " + " button.click(function (e) {\r\n e.preven" +
" e.preventDefault();\r\n\r\n if (!butto" + "tDefault();\r\n\r\n if (!buttonDialog) {\r\n " +
"nDialog) {\r\n buttonDialog = $(\'#User_" + " buttonDialog = $(\'#User_Show_Details_Ac" +
"Show_Details_Actions_AddFlag_Dialog\');\r\n " + "tions_AddFlag_Dialog\');\r\n buttonDialo" +
" buttonDialog.dialog({\r\n width" + "g.dialog({\r\n width: 600,\r\n " +
": 600,\r\n height: 410,\r\n " + " height: 410,\r\n " +
" resizable: false,\r\n " + " resizable: false,\r\n " +
" modal: true,\r\n " + " modal: true,\r\n autoOpen" +
" autoOpen: false,\r\n buttons" + ": false,\r\n buttons: {\r\n " +
": {\r\n Cancel: function () {\r\n" + " Cancel: function () {\r\n " +
" $(this).dialog(\"close\");" + " $(this).dialog(\"close\");\r\n " +
"\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 " +
" const $this = $(this);\r\n " + " buttonDialog\r\n " +
" $this.dialog(\"disable\");\r\n " + " .dialog(\"option\", \"buttons\", null)\r\n " +
" $this.dialog(\"option\", \"buttons" + " .find(\'form\').submit();\r\n " +
"\", null);\r\n buttonDia" + " } else {\r\n " +
"log.find(\'form\').submit();\r\n " + " alert(\'Select a User Flag\');\r\n " +
" } else {\r\n alert(" +
"\'Select a User Flag\');\r\n " +
"}\r\n }\r\n " +
" }\r\n });\r\n\r\n" +
" flagAddId = $(\'#User_Show_Details_Ac" +
"tions_AddFlag_Dialog_Id\');\r\n flagAddC" +
"omments = buttonDialog.find(\'#User_Show_Details_Actions_AddFlag_Dialog_Comments\'" +
");\r\n flagPicker = buttonDialog.find(\'" +
".flagPicker\');\r\n details = buttonDial" +
"og.find(\'.details\');\r\n\r\n $(\'#User_Sho" +
"w_Details_Actions_AddFlag_Dialog_Filter\').on(\'keyup\', function (e) {\r\n " +
" const filter = $(e.currentTarget).val().to" +
"LowerCase();\r\n if (filter) {\r\n " +
" flagPicker.children(\'div.flag\')" +
".each(function () {\r\n con" +
"st $this = $(this);\r\n if " +
"($this.attr(\'data-userflagname\').toLowerCase().indexOf(filter) >= 0) {\r\n " +
" $this.css(\'display\', \'block\'" +
");\r\n } else {\r\n " +
" $this.css(\'display\', \'none\');\r" +
"\n }\r\n " +
" });\r\n " +
" } else {\r\n flagPicker.ch" +
"ildren(\'div.flag\').each(function () { $(this).css(\'display\', \'block\'); });\r\n " +
" }\r\n " + " }\r\n " +
" });\r\n\r\n flagPicker.on(\'cli" + " }\r\n }\r\n " +
"ck\', \'div.flag\', flagSelected);\r\n }\r\n\r\n " + " });\r\n\r\n " +
" $(\'#User_Show_Details_Actions_AddFlag_Dial" + " flagAddId = $(\'#User_Show_Details_Actions_AddFlag_Dialog_Id\');\r\n " +
"og_Filter\').val(\'\');\r\n buttonDialog.dialo" + " flagAddComments = buttonDialog.find(\'#User_Show_D" +
"g(\'open\');\r\n return false;\r\n " + "etails_Actions_AddFlag_Dialog_Comments\');\r\n " +
" });\r\n });\r\n " + " flagPicker = buttonDialog.find(\'.flagPicker\');\r\n " +
" </script>\r\n"); " details = buttonDialog.find(\'.details\');\r\n\r\n " +
" $(\'#User_Show_Details_Actions_AddFlag_Dialog_Filter\')" +
".on(\'keyup\', function (e) {\r\n con" +
"st filter = $(e.currentTarget).val().toLowerCase();\r\n " +
" if (filter) {\r\n " +
" flagPicker.children(\'div.flag\').each(function () {\r\n " +
" const $this = $(this);\r\n " +
" if ($this.attr(\'data-userflagname\').toLowerC" +
"ase().indexOf(filter) >= 0) {\r\n " +
" $this.css(\'display\', \'block\');\r\n " +
" } else {\r\n " +
" $this.css(\'display\', \'none\');\r\n " +
" }\r\n });\r\n " +
" } else {\r\n " +
" flagPicker.children(\'div.flag\').each(function () { $(t" +
"his).css(\'display\', \'block\'); });\r\n " +
" }\r\n });\r\n\r\n " +
" flagPicker.on(\'click\', \'div.flag\', flagSelected);\r\n " +
" }\r\n\r\n $(\'" +
"#User_Show_Details_Actions_AddFlag_Dialog_Filter\').val(\'\');\r\n " +
" buttonDialog.dialog(\'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,45 +1610,47 @@ 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\"");
@@ -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
@@ -1710,6 +1718,7 @@ WriteLiteral("</span>\r\n
#line 454 "..\..\Views\User\UserParts\_Subject.cshtml" #line 454 "..\..\Views\User\UserParts\_Subject.cshtml"
} }
}
#line default #line default
@@ -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"
} }
+6 -6
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"> <div class="flags">
@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))))
{ {
<i class="flag fa fa-@(flag.Item2.Icon) fa-fw d-@(flag.Item2.IconColour)"> if (flag.Item2.permission.CanShow())
{
<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>
+19 -30
View File
@@ -173,15 +173,7 @@ 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)
{ {
@@ -194,41 +186,43 @@ 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())
{
#line default #line default
#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
@@ -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"
} }