Users cleanup, ver. 2.24.1382

This commit is contained in:
Milan Hanajik 2019-12-03 20:57:37 +01:00
parent 531b5d29ae
commit 88a7de450a
53 changed files with 574 additions and 583 deletions

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2013-2017 Sensus Metering Systems
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
///
using System;
@ -8,17 +8,15 @@ namespace Config.Entities
public class Group
{
public virtual int Id { get; protected set; }
public virtual int Gid { get; set; }
public virtual string Name { get; set; }
public virtual Users.Entities.GID GID { get; set; }
public Group()
{
}
public Group(int gid, string name)
public Group(Users.Entities.GID gid)
{
Gid = gid;
Name = name;
GID = gid;
}
}
}

View File

@ -16,6 +16,7 @@ namespace Config.Entities
public virtual string Password { get; set; }
public virtual string Password2 { get; set; }
public virtual string Password3 { get; set; }
public virtual string Password4 { get; set; }
public virtual DateTime LastPwChange { get; set; }
public virtual IList<Group> Groups { get; set; } //User can be a member of a list of groups

View File

@ -147,13 +147,13 @@ namespace Config
///
/// Prepare all groups
///
var testers = new Config.Entities.Group((int)Users.Grp.GID.Testers, Strings.Tester);
var testingSpecialists = new Config.Entities.Group((int)Users.Grp.GID.TestingSpecialists, Strings.Testing_Specialist);
var headOfLab = new Config.Entities.Group((int)Users.Grp.GID.HeadOfLab, Strings.Head_of_Lab);
var maintenanceSpecialists = new Config.Entities.Group((int)Users.Grp.GID.MaintenanceSpecialists, Strings.Maintenance_Specialist);
var metrologists = new Config.Entities.Group((int)Users.Grp.GID.Metrologists, Strings.Metrologist);
var calibrationSpecialists = new Config.Entities.Group((int)Users.Grp.GID.CalibrationSpecialists, Strings.Calibration_Specialist);
var administrators = new Config.Entities.Group((int)Users.Grp.GID.Administrators, Strings.Administrator);
var testers = new Config.Entities.Group(Users.Entities.GID.Testers);
var testingSpecialists = new Config.Entities.Group(Users.Entities.GID.TestingSpecialists);
var headOfLab = new Config.Entities.Group(Users.Entities.GID.HeadOfLab);
var maintenanceSpecialists = new Config.Entities.Group(Users.Entities.GID.MaintenanceSpecialists);
var metrologists = new Config.Entities.Group(Users.Entities.GID.Metrologists);
var calibrationSpecialists = new Config.Entities.Group(Users.Entities.GID.CalibrationSpecialists);
var administrators = new Config.Entities.Group(Users.Entities.GID.Administrators);
/// Create the user 'admin' add his groups
var admin = new Config.Entities.User

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2013-2015 Sensus Metering Systems
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
///
using FluentNHibernate.Mapping;
@ -10,8 +10,7 @@ namespace Config.Mappings
public GroupMap()
{
Id(x => x.Id);
Map(x => x.Gid);
Map(x => x.Name);
Map(x => x.GID).Column("Name"); ;
}
}
}

View File

@ -12,12 +12,11 @@ namespace Config.Mappings
Id(x => x.Id);
Map(x => x.UserName).Column("Name");
Map(x => x.Number);
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
Map(x => x.Tag);
#endif
Map(x => x.Password);
Map(x => x.Password2);
Map(x => x.Password3);
Map(x => x.Password4);
Map(x => x.FullName).Column("Description");
Map(x => x.LastPwChange);
HasMany(x => x.Groups)

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.24.1369.0")]
[assembly: AssemblyFileVersion("2.24.1369.0")]
[assembly: AssemblyVersion("2.24.1382.0")]
[assembly: AssemblyFileVersion("2.24.1382.0")]

View File

@ -117,27 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>Administrator</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>Kalibriertechniker</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>Laborleiter</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>Wartungstechniker</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>Messtechniker</value>
</data>
<data name="Tester" xml:space="preserve">
<value>Prüfer</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>Prüftechniker</value>
</data>
<data name="Failed" xml:space="preserve">
<value>NiO</value>
</data>

View File

@ -117,27 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>Administrateur</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>Spécialiste en calibration</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>Chef de laboratoire</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>Spécialiste en maintenance</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>Métrologue</value>
</data>
<data name="Tester" xml:space="preserve">
<value>Testeur</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>Spécialiste d'essais</value>
</data>
<data name="Failed" xml:space="preserve">
<value>Échoué</value>
</data>

View File

@ -117,27 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>Amministratore</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>esperto in calibrazione</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>capo di laboratorio</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>esperto di manutenzione</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>metrologo</value>
</data>
<data name="Tester" xml:space="preserve">
<value>tester</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>esperto di prove </value>
</data>
<data name="Failed" xml:space="preserve">
<value>NOK</value>
</data>

View File

@ -117,27 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>Administrator</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>Specjalista ds. kalibracji</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>Kierownik Laboratorium</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>Konserwator</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>Metrolog</value>
</data>
<data name="Tester" xml:space="preserve">
<value>Pracownik przeprowadzający testy</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>Specjalista ds. testów</value>
</data>
<data name="Failed" xml:space="preserve">
<value>Niepowodzenie</value>
</data>

View File

@ -117,27 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>Administrator</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>Calibration Specialist</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>Head of Lab</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>Maintenance Specialist</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>Metrologist</value>
</data>
<data name="Tester" xml:space="preserve">
<value>Tester</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>Testing Specialist</value>
</data>
<data name="Failed" xml:space="preserve">
<value>NOK</value>
</data>

View File

@ -117,27 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>Администратор</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>Специалист по калибровке</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>Руководитель лаборатории</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>Специалист по техобслуживанию</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>Метролог</value>
</data>
<data name="Tester" xml:space="preserve">
<value>Контролер</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>Специалист по тестированию</value>
</data>
<data name="Failed" xml:space="preserve">
<value>NOK</value>
</data>

View File

@ -1,128 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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.
Version 1.3
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">1.3</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1">this is my long string</data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
[base64 mime encoded serialized .NET Framework object]
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
[base64 mime encoded string representing a byte array form of the .NET Framework object]
</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.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:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<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" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</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>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Administrator" xml:space="preserve">
<value>管理员</value>
</data>
<data name="Calibration_Specialist" xml:space="preserve">
<value>校准专员</value>
</data>
<data name="Failed" xml:space="preserve">
<value>NOK</value>
</data>
<data name="Head_of_Lab" xml:space="preserve">
<value>实验室负责人</value>
</data>
<data name="Maintenance_Specialist" xml:space="preserve">
<value>维护专员</value>
</data>
<data name="Metrologist" xml:space="preserve">
<value>计量者</value>
</data>
<data name="Passed" xml:space="preserve">
<value>好</value>
</data>
<data name="Tester" xml:space="preserve">
<value>测试仪</value>
</data>
<data name="Testing_Specialist" xml:space="preserve">
<value>测试专员</value>
</data>
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="Error" xml:space="preserve">
<value>错误 Error</value>
</data>
<data name="Failed" xml:space="preserve">
<value>NOK</value>
</data>
<data name="Passed" xml:space="preserve">
<value>好</value>
</data>
</root>

View File

@ -42,7 +42,7 @@ namespace TBF.BenchControl
Flags = CfgUpdateFlags.None;
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { global::Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { global::Users.Entities.GID.Metrologists };
sharedButtons.MoreButtonTop = ComponentCfgCtrlHeight - 45;
sharedButtons.OptionalButtons = SharedButtons.Buttons.None;
sharedButtons.Unlocked += Unlock;

View File

@ -24,7 +24,7 @@ namespace TBF.BenchControl.Elde.CoverTest
readonly ulong mask; /// derived from bitPosition in the constructor
readonly ulong target;
readonly string message;
readonly Users.Grp.GID[] bypassLevel;
readonly Users.Entities.GID[] bypassLevel;
public CoverTest()
{

View File

@ -22,7 +22,7 @@ namespace TBF.BenchControl.Elde.CoverTest
public int BitPosition;
public bool Invert;
public string Message;
public Users.Grp.GID[] BypassLevel;
public Users.Entities.GID[] BypassLevel;
/// Private parameterless constructor invoked by all other (public) constructors
CoverTestCfg()
@ -35,7 +35,7 @@ namespace TBF.BenchControl.Elde.CoverTest
Invert = false;
Message = Strings.Close_the_cover;
BypassLevel = new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists };
BypassLevel = new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists };
}
public CoverTestCfg(IComponentFactory factory)

View File

@ -46,7 +46,7 @@ namespace TBF.BenchControl.Elde.CoverTest
}
}
for (Users.Grp.GID gid = 0; gid < Users.Grp.GID.NrOfGroups; gid++)
for (Users.Entities.GID gid = 0; gid < Users.Entities.GID.NrOfGroups; gid++)
{
bypassLevelComboBox.Items.Add(gid.ToString());
}
@ -94,11 +94,11 @@ namespace TBF.BenchControl.Elde.CoverTest
config.Message = messageTextBox.Text;
config.BypassLevel = null;
for (Users.Grp.GID gid = 0; gid < Users.Grp.GID.NrOfGroups; gid++)
for (Users.Entities.GID gid = 0; gid < Users.Entities.GID.NrOfGroups; gid++)
{
if (bypassLevelComboBox.Text == gid.ToString())
{
config.BypassLevel = new Users.Grp.GID[] { gid };
config.BypassLevel = new Users.Entities.GID[] { gid };
break;
}
}

View File

@ -18,9 +18,9 @@ namespace TBF.BenchControl.Elde.CoverTest
public bool Completed { get { return completed; } }
bool completed;
Users.Grp.GID[] bypassLevel;
Users.Entities.GID[] bypassLevel;
public CoverTestForm(string message, Users.Grp.GID[] bypassLevel, ILog bypassLog)
public CoverTestForm(string message, Users.Entities.GID[] bypassLevel, ILog bypassLog)
{
InitializeComponent();
ControlBox = false;

View File

@ -46,7 +46,7 @@ namespace TBF.BenchControl.TestMethods.Endurance
InitializeComponent();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.Metrologists };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add |
SharedButtons.Buttons.Remove |
SharedButtons.Buttons.Up |

View File

@ -8,6 +8,7 @@ using System.Windows.Forms;
using log4net;
using Config.Entities;
using Users;
using Users.Entities;
using TBF.Resources;
using TBF.UI.Shared;
@ -254,12 +255,12 @@ namespace TBF
try
{
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
Grp.GID[] reqGrpMembership = new Grp.GID[] { Grp.GID.Testers, Grp.GID.TestingSpecialists, Grp.GID.Metrologists, Grp.GID.HeadOfLab };
GID[] reqGrpMembership = new Grp.GID[] { Grp.GID.Testers, Grp.GID.TestingSpecialists, Grp.GID.Metrologists, Grp.GID.HeadOfLab };
#else
Grp.GID[] reqGrpMembership = null;
GID[] reqGrpMembership = null;
#endif
bool authorized = false;
Users.Entities.AuthorizedAs authorizedAs = Users.Entities.AuthorizedAs.PowerUser;
AuthorizedAs authorizedAs = Users.Entities.AuthorizedAs.PowerUser;
if (Users.Entities.User.IsPowerUser(loginDlgBench.Alias, loginDlgBench.Password))
{

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("2.24.1369.0")]
[assembly: AssemblyFileVersion("2.24.1369.0")]
[assembly: AssemblyVersion("2.24.1382.0")]
[assembly: AssemblyFileVersion("2.24.1382.0")]

View File

@ -69,7 +69,7 @@ namespace TBF.UI.Bench.Components
selectComponentTypeDlg = new SelectComponentClassDlg();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.Metrologists };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add |
SharedButtons.Buttons.Remove |

View File

@ -26,11 +26,7 @@ namespace TBF.UI.Bench.Metrology
InitializeComponent();
/// SharedDlgButtons configuration
#if KEMPNO_50
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.MetrologicalAuthority };
#else
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists };
#endif
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.Metrologists, Users.Entities.GID.MetrologicalAuthority };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove;
sharedButtons.Unlocked += unlockButton_Click;
sharedButtons.OKClicked += okButton_Click;

View File

@ -51,7 +51,7 @@ namespace TBF.UI.Bench.Paths
InitializeComponent();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.Metrologists };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove |
SharedButtons.Buttons.Up | SharedButtons.Buttons.Down;
sharedButtons.Unlocked += Unlocked;

View File

@ -50,7 +50,7 @@ namespace TBF.UI.Bench.TestProfiles
InitializeComponent();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.WaterMeterAuthority };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.MetrologicalAuthority };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove |
SharedButtons.Buttons.Up | SharedButtons.Buttons.Down;
@ -87,7 +87,7 @@ namespace TBF.UI.Bench.TestProfiles
this.usedNames = usedNames;
this.openUnlocked = openUnlocked;
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.WaterMeterAuthority };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.MetrologicalAuthority };
}
private void TestProfileDlg_Load(object sender, EventArgs e)

View File

@ -25,7 +25,8 @@ namespace TBF.UI.Bench.TestProfiles
InitializeComponent();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.MetrologicalAuthority };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove |
SharedButtons.Buttons.Up | SharedButtons.Buttons.Down |
SharedButtons.Buttons.Edit | SharedButtons.Buttons.Copy |

View File

@ -67,7 +67,7 @@ namespace TBF.UI.Bench.Transitions
InitializeComponent();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.Metrologists };
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove |
SharedButtons.Buttons.Up | SharedButtons.Buttons.Down |
SharedButtons.Buttons.Export | SharedButtons.Buttons.Import |

View File

@ -27,9 +27,9 @@ namespace TBF.UI.Bench.Uncertainties
/// SharedDlgButtons configuration
#if KEMPNO_50
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.MetrologicalAuthority };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.MetrologicalAuthority };
#else
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.Metrologists };
#endif
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove;
sharedButtons.Unlocked += unlockButton_Click;

View File

@ -114,10 +114,10 @@ namespace TBF.UI
graphsToolStripMenuItem.Text = Strings.Graphs;
#endif
usersTSMenuItem.Visible = Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.Administrators) ||
Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.HeadOfLab);
usersTSMenuItem.Visible = Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.Administrators) ||
Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.HeadOfLab);
upgradeTSMenuItem.Visible = Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.Administrators) && Users.GlobalData.CurrentUser.IsPowerUser();
upgradeTSMenuItem.Visible = Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.Administrators) && Users.GlobalData.CurrentUser.IsPowerUser();
#if IPERL
iPerlHeadsToolStripMenuItem.Visible = true;
@ -806,9 +806,9 @@ namespace TBF.UI
private void statusStrip1_DoubleClick(object sender, EventArgs e)
{
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
Users.Grp.GID[] reqGrpMembership = new Users.Grp.GID[] { Users.Grp.GID.Testers, Users.Grp.GID.TestingSpecialists, Users.Grp.GID.Metrologists, Users.Grp.GID.HeadOfLab };
Users.Entities.GID[] reqGrpMembership = new Users.Entities.GID[] { Users.Entities.GID.Testers, Users.Entities.GID.TestingSpecialists, Users.Entities.GID.Metrologists, Users.Entities.GID.HeadOfLab };
#else
Users.Grp.GID[] reqGrpMembership = null;
Users.Entities.GID[] reqGrpMembership = null;
#endif
if (new Users.Forms.LoginDlg(reqGrpMembership).ShowDialog() == DialogResult.OK)
@ -819,12 +819,12 @@ namespace TBF.UI
private void clearCountersToolStripMenuItem_Click(object sender, EventArgs e)
{
Users.Grp.GID[] reqGrpMembership = new Users.Grp.GID[]
Users.Entities.GID[] reqGrpMembership = new Users.Entities.GID[]
{
Users.Grp.GID.TestingSpecialists,
Users.Grp.GID.Metrologists,
Users.Grp.GID.HeadOfLab,
Users.Grp.GID.Administrators,
Users.Entities.GID.TestingSpecialists,
Users.Entities.GID.Metrologists,
Users.Entities.GID.HeadOfLab,
Users.Entities.GID.Administrators,
};
if (new Users.Forms.LoginDlg(reqGrpMembership).ShowDialog() == DialogResult.OK)

View File

@ -67,9 +67,9 @@ namespace TBF.UI.Procedures
/// SharedDlgButtons configuration
#if KEMPNO_50 || KRAKOW_50
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.WaterMeterAuthority };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists, Users.Entities.GID.WaterMeterAuthority };
#else
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists, Users.Entities.GID.Metrologists };
#endif
#if TURA_SPECIAL || TURA_IPERL || TURA_IPERL_NEW
@ -119,11 +119,11 @@ namespace TBF.UI.Procedures
this.openUnlocked = openUnlocked;
#if KEMPNO_50 || KRAKOW_50
sharedButtons.RequiredGroupMembership = procedure.Protected ? new Users.Grp.GID[] { Users.Grp.GID.WaterMeterAuthority }
: new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.WaterMeterAuthority };
sharedButtons.RequiredGroupMembership = procedure.Protected ? new Users.Entities.GID[] { Users.Entities.GID.WaterMeterAuthority }
: new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists, Users.Entities.GID.WaterMeterAuthority };
#else
sharedButtons.RequiredGroupMembership = procedure.Protected ? new Users.Grp.GID[] { Users.Grp.GID.Metrologists }
: new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = procedure.Protected ? new Users.Entities.GID[] { Users.Entities.GID.Metrologists }
: new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists, Users.Entities.GID.Metrologists };
#endif
using (NHibernate.ISession session = Config.FluentCommon.CreateSession(Users.Entities.DBKind.Config))
{
@ -1829,7 +1829,7 @@ namespace TBF.UI.Procedures
procNameTextBox.Enabled = true;
descriptionTextBox.Enabled = true;
watermetersTextBox.Enabled = true;
protectedCheckBox.Enabled = Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.Metrologists);
protectedCheckBox.Enabled = Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.Metrologists);
mustBeCompleteCheckBox.Enabled = true;
manualControlDisabledCheckBox.Enabled = true;
dataEntryComboBox.Enabled = true;

View File

@ -26,7 +26,7 @@ namespace TBF.UI.Procedures
InitializeComponent();
/// SharedDlgButtons configuration
sharedButtons.RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.Metrologists };
sharedButtons.RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists, Users.Entities.GID.Metrologists };
#if TEST_PROFILES
sharedButtons.OptionalButtons = SharedButtons.Buttons.Add | SharedButtons.Buttons.Remove |

View File

@ -106,7 +106,7 @@ namespace TBF.UI.ResultsMI
else if (mode == PreviousResultsMode.Fix)
{
/// Access only to thise who manage production tracing
Users.Grp.GID[] rqrdGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.TraceabilityManagement };
Users.Entities.GID[] rqrdGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.TraceabilityManagement };
if ((new Users.Forms.LoginDlg(Users.GlobalData.CurrentUser.UserName, rqrdGroupMembership)).ShowDialog() != DialogResult.OK)
{

View File

@ -15,7 +15,7 @@ namespace TBF.UI.ResultsMI
/// <summary>
/// Required access rights to make changes with this form
/// </summary>
static readonly Users.Grp.GID[] RequiredGroupMembership = new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists, Users.Grp.GID.Metrologists };
static readonly Users.Entities.GID[] RequiredGroupMembership = new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists, Users.Entities.GID.Metrologists };
public bool Unlocked; /// true = changes enabled

View File

@ -268,9 +268,9 @@ namespace TBF.UI.Shared
{
#if TURA_IPERL || TURA_IPERL_NEW
/// Prevent 'Stop draining' by password
if (drain1Highlighted && !Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.TestingSpecialists))
if (drain1Highlighted && !Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.TestingSpecialists))
{
if ((new Users.Forms.LoginDlg(new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists })).ShowDialog() != DialogResult.OK)
if ((new Users.Forms.LoginDlg(new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists })).ShowDialog() != DialogResult.OK)
return;
if (Program.MainWnd != null) Program.MainWnd.UpdateUser();
@ -285,9 +285,9 @@ namespace TBF.UI.Shared
{
#if TURA_IPERL || TURA_IPERL_NEW
/// Prevent 'Stop draining' by password
if (drain1Highlighted && !Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.TestingSpecialists))
if (drain1Highlighted && !Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.TestingSpecialists))
{
if ((new Users.Forms.LoginDlg(new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists })).ShowDialog() != DialogResult.OK)
if ((new Users.Forms.LoginDlg(new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists })).ShowDialog() != DialogResult.OK)
return;
if (Program.MainWnd != null) Program.MainWnd.UpdateUser();
@ -302,9 +302,9 @@ namespace TBF.UI.Shared
{
#if TURA_IPERL || TURA_IPERL_NEW
/// Prevent 'Stop draining' by password
if (drain1Highlighted && !Users.GlobalData.CurrentUser.IsMemberOf(Users.Grp.GID.TestingSpecialists))
if (drain1Highlighted && !Users.GlobalData.CurrentUser.IsMemberOf(Users.Entities.GID.TestingSpecialists))
{
if ((new Users.Forms.LoginDlg(new Users.Grp.GID[] { Users.Grp.GID.TestingSpecialists })).ShowDialog() != DialogResult.OK)
if ((new Users.Forms.LoginDlg(new Users.Entities.GID[] { Users.Entities.GID.TestingSpecialists })).ShowDialog() != DialogResult.OK)
return;
if (Program.MainWnd != null) Program.MainWnd.UpdateUser();

View File

@ -72,7 +72,7 @@ namespace TBF.UI.Shared
Middle,
}
public Users.Grp.GID[] RequiredGroupMembership;
public Users.Entities.GID[] RequiredGroupMembership;
Users.Entities.User originalUser;

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2017 Sensus Metering Systems
/// Copyright (c) 2017-2019 Sensus Slovensko a.s.
///
using System;
@ -37,4 +37,22 @@ namespace Users.Entities
RemoteUser,
Count
}
/// <summary>
/// GID-s of user groups, each user is member of one or more groups.
/// </summary>
public enum GID
{
Testers,
TestingSpecialists,
HeadOfLab,
MaintenanceSpecialists,
Metrologists,
CalibrationSpecialists,
Administrators, /// application / network / database administrator
TraceabilityManagement,
MetrologicalAuthority,
WaterMeterAuthority,
NrOfGroups, /// Number of groups (this is not a GroupID)
}
}

View File

@ -1,25 +1,43 @@
///
/// Copyright (c) 2016-2017 Sensus Metering Systems
/// Copyright (c) 2016-2019 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using Users.Resources;
namespace Users.Entities
{
public class Group
{
public virtual int Id { get; protected set; }
public virtual int Gid { get; set; }
public virtual string Name { get; set; }
public virtual GID GID { get; set; }
public Group()
{
}
public Group(int gid, string name)
public Group(GID gid)
{
Gid = gid;
Name = name;
GID = gid;
}
public static string Gid2Str(GID gid)
{
switch (gid)
{
case GID.Testers: return Strings.tester;
case GID.TestingSpecialists: return Strings.specialist;
case GID.HeadOfLab: return Strings.head_of_lab;
case GID.MaintenanceSpecialists: return Strings.maintenance;
case GID.Metrologists: return Strings.metrologist;
case GID.CalibrationSpecialists: return Strings.calibration_specialist;
case GID.Administrators: return Strings.administrator;
case GID.TraceabilityManagement: return Strings.production_tracing_administrator;
case GID.MetrologicalAuthority: return Strings.metrological_authority;
case GID.WaterMeterAuthority: return Strings.water_meter_authority;
default:
return (gid >= 0 && gid < GID.NrOfGroups) ? gid.ToString() : Strings.invalid;
}
}
}
}

View File

@ -23,6 +23,7 @@ namespace Users.Entities
public virtual string Password { get; set; }
public virtual string Password2 { get; set; }
public virtual string Password3 { get; set; }
public virtual string Password4 { get; set; }
public virtual DateTime LastPwChange { get; set; }
public virtual IList<Group> Groups { get; set; } //User can be a member of a list of groups
@ -80,29 +81,21 @@ namespace Users.Entities
/// </summary>
/// <param name="groupId">Group GID</param>
/// <returns>true is user is a member of the specified group</returns>
public virtual bool IsMemberOf(Grp.GID groupId)
public virtual bool IsMemberOf(GID groupId)
{
if (groupId == Grp.GID.None || powerUser)
if (powerUser)
{
return true;
}
else if (groupId >= 0 && (int)groupId < Grp.Count)
else if ((groupId >= 0) && (groupId < GID.NrOfGroups) && (Groups != null))
{
// for all group elements in User.groups
for (int i = 0; i < Groups.Count; ++i)
foreach (var g in Groups)
{
// element GID = parameter GroupId ?
if (((Group)Groups[i]).Gid == (int)groupId)
{
return true;
}
if (g.GID == groupId) return true;
}
return false;
}
else
{
return false;
}
return false;
}
/// <summary>
@ -111,25 +104,22 @@ namespace Users.Entities
/// </summary>
/// <param name="groupIds">An array of group GID-s or null (no membership required)</param>
/// <returns>true if user is a member of any of specified groups</returns>
public virtual bool IsMemberOf(Grp.GID[] groupIds)
public virtual bool IsMemberOf(GID[] groupIds)
{
if (groupIds == null || powerUser)
{
return true;
}
foreach (var groupId in groupIds)
foreach (var gid in groupIds)
{
if (groupId >= 0 && (int)groupId < Grp.Count)
if (gid >= 0 && gid < GID.NrOfGroups)
{
// for all group elements in User.groups
for (int i = 0; i < Groups.Count; ++i)
/// for all group elements in User.Groups
foreach (var grp in Groups)
{
// element GID = parameter GroupId ?
if (((Group)Groups[i]).Gid == (int)groupId)
{
return true;
}
/// element GID = parameter GroupId ?
if (grp.GID == gid) return true;
}
}
}
@ -176,7 +166,7 @@ namespace Users.Entities
/// <returns></ returns>
bool IsPasswordExpired()
{
if (IsPowerUser() || IsMemberOf(Grp.GID.Administrators) || GlobalData.PasswdExpirationPeriodDays == 0)
if (IsPowerUser() || IsMemberOf(GID.Administrators) || GlobalData.PasswdExpirationPeriodDays == 0)
{
/// Password cannot expirate for this user or this feature is disabled in Backup and Security options
return false;
@ -192,6 +182,7 @@ namespace Users.Entities
/// <param name="password">Password</param>
public virtual void SetPassword(string password)
{
Password4 = Password3;
Password3 = Password2;
Password2 = Password;
Password = EncryptedPassword(password);
@ -231,7 +222,7 @@ namespace Users.Entities
/// <param name="password">Password</param>
/// <param name="requiredGrupMembership"></param>
/// <returns>true = authorized</returns>
public virtual bool Authorize(string userName, string password, Grp.GID[] requiredGroupMembership)
public virtual bool Authorize(string userName, string password, GID[] requiredGroupMembership)
{
if (IsPowerUser(userName, password))
{
@ -262,7 +253,7 @@ namespace Users.Entities
/// <param name="password">Password</param>
/// <param name="requiredGrupMembership"></param>
/// <returns>true = authorized</returns>
public virtual bool AuthorizeNumber(int number, string password, Grp.GID[] requiredGroupMembership)
public virtual bool AuthorizeNumber(int number, string password, GID[] requiredGroupMembership)
{
if (Number != number)
{
@ -284,7 +275,7 @@ namespace Users.Entities
/// <param name="password"></param>
/// <param name="requiredGrupMembership"></param>
/// <returns>true = authorized</returns>
public virtual bool AuthorizeFullName(string fullName, string password, Grp.GID[] requiredGroupMembership)
public virtual bool AuthorizeFullName(string fullName, string password, GID[] requiredGroupMembership)
{
if (FullName.ToLower() != fullName.ToLower())
{
@ -301,7 +292,7 @@ namespace Users.Entities
/// <param name="password">Password</param>
/// <param name="requiredGroupMembership">Required group membership</param>
/// <returns>true = authorized</returns>
bool CompleteAuthorization(string password, Grp.GID[] requiredGroupMembership)
bool CompleteAuthorization(string password, GID[] requiredGroupMembership)
{
if (!IsMemberOf(requiredGroupMembership) || !IsCorrectPassword(password))
{
@ -336,7 +327,7 @@ namespace Users.Entities
/// <param name="tag">Tag (RFID, NFC, ... s/n)</param>
/// <param name="requiredGrupMembership"></param>
/// <returns>true = authorized</returns>
public virtual bool AuthorizeTag(string tag, Grp.GID[] requiredGroupMembership)
public virtual bool AuthorizeTag(string tag, GID[] requiredGroupMembership)
{
if (Tag != tag)
{
@ -384,12 +375,7 @@ namespace Users.Entities
DB.DbType = dbSettings.DbType;
DB.ConnectionString = dbSettings.ConnectionString;
IList<User> listOfUsers = DB.CreateSession()
.CreateQuery("FROM User WHERE LOWER(UserName) = :username") /// Note: QueryOver<User>().Where(x => x.UserName.ToLower() == ... does not work
.SetParameter("username", userName.ToLower())
.List<User>();
return (listOfUsers.Count > 0) ? listOfUsers[0] : null;
return LoadUserByName(userName);
}
/// <summary>
@ -399,11 +385,10 @@ namespace Users.Entities
/// <returns>reference to a 'User' (if it exists) or null</returns>
public static User LoadUserByName(string userName)
{
string upperCaseUserName = userName.ToUpper();
IList<User> listOfUsers = DB.CreateSession()
.CreateQuery("FROM User WHERE LOWER(UserName) = :username") /// Note: QueryOver<User>().Where(x => x.UserName.ToLower() == ... does not work
.SetParameter("username", userName.ToLower())
.List<User>();
.QueryOver<User>()
.Where(x => (x.UserName == userName))
.List();
return (listOfUsers.Count > 0) ? listOfUsers[0] : null;
}
@ -420,12 +405,7 @@ namespace Users.Entities
DB.DbType = dbSettings.DbType;
DB.ConnectionString = dbSettings.ConnectionString;
IList<User> listOfUsers = DB.CreateSession()
.CreateQuery("FROM User WHERE LOWER(Description) = :fullname") /// Note: QueryOver<User>().Where(x => x.FullName.ToLower() == ... does not work
.SetParameter("fullname", fullName.ToLower())
.List<User>();
return (listOfUsers.Count > 0) ? listOfUsers[0] : null;
return LoadUserByFullName(fullName);
}
/// <summary>
@ -436,9 +416,9 @@ namespace Users.Entities
public static User LoadUserByFullName(string fullName)
{
IList<User> listOfUsers = DB.CreateSession()
.CreateQuery("FROM User WHERE LOWER(Description) = :fullname") /// Note: QueryOver<User>().Where(x => x.FullName.ToLower() == ... does not work
.SetParameter("fullname", fullName.ToLower())
.List<User>();
.QueryOver<User>()
.Where(x => (x.FullName == fullName))
.List();
return (listOfUsers.Count > 0) ? listOfUsers[0] : null;
}
@ -455,12 +435,7 @@ namespace Users.Entities
DB.DbType = dbSettings.DbType;
DB.ConnectionString = dbSettings.ConnectionString;
IList<User> listOfUsers = DB.CreateSession()
.QueryOver<User>()
.Where(x => (x.Number == number))
.List();
return (listOfUsers.Count > 0) ? listOfUsers[0] : null;
return LoadUserByNumber(number);
}
/// <summary>
@ -490,12 +465,7 @@ namespace Users.Entities
DB.DbType = dbSettings.DbType;
DB.ConnectionString = dbSettings.ConnectionString;
IList<User> listOfUsers = DB.CreateSession()
.QueryOver<User>()
.Where(x => (x.Tag == tag))
.List();
return (listOfUsers.Count > 0) ? listOfUsers[0] : null;
return LoadUserByTag(tag);
}
/// <summary>

View File

@ -17,6 +17,9 @@ namespace Users.Forms
{
NHibernate.ISession session;
User user;
GID[] displayedGIDs;
bool[] oriGroupMember; /// index is gid, size is Grp.Count
@ -29,15 +32,18 @@ namespace Users.Forms
{
InitializeComponent();
this.toolTip1.SetToolTip(this.txtName, string.Format(Strings.max_0_alphanum_chars, 20));
oriGroupMember = new bool[Grp.Count];
oriGroupMember = new bool[(displayedGIDs != null) ? displayedGIDs.Length : 0];
okBtn.Enabled = false;
}
public EditSelectedUser(NHibernate.ISession session, User user)
public EditSelectedUser(NHibernate.ISession session, User user, GID[] displayedGIDs)
: this()
{
this.session = session;
this.user = user;
this.displayedGIDs = displayedGIDs;
oriGroupMember = new bool[(displayedGIDs != null) ? displayedGIDs.Length : 0];
}
private void EditSelectedUser_Load(object sender, EventArgs e)
@ -55,7 +61,6 @@ namespace Users.Forms
smartCardReader = null; /// null = No smart card reader detected
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
try
{
card = new CardNative();
@ -100,7 +105,6 @@ namespace Users.Forms
{
smartCardReader = null;
}
#endif
}
void Localize()
@ -120,13 +124,12 @@ namespace Users.Forms
public void ShowGroups()
{
checkedListBoxGroups.Items.Clear();
for (int i= 0; i < Grp.Count; i++)
for (int i= 0; i < displayedGIDs.Length; i++)
{
Group group = Grp.FromId((Grp.GID)i);
GID gid = displayedGIDs[i];
bool boolIsMember = oriGroupMember[i] = user.IsMemberOf((Grp.GID)group.Gid);
checkedListBoxGroups.Items.Add(Grp.Gid2Str(i));
bool boolIsMember = oriGroupMember[i] = user.IsMemberOf(gid);
checkedListBoxGroups.Items.Add(Group.Gid2Str(gid));
checkedListBoxGroups.SetItemCheckState(i, boolIsMember ? CheckState.Checked : CheckState.Unchecked);
}
}
@ -188,15 +191,17 @@ namespace Users.Forms
/// Groups
IList<Group> groups = user.Groups; /// = session.QueryOver<Group>().Where(x => (x.User.Id == user.Id)).List();
for (int gid = 0; gid < Grp.Count; gid++)
for (int i = 0; i < displayedGIDs.Length; i++ )
{
bool newIsMember = checkedListBoxGroups.GetItemChecked(gid);
GID gid = displayedGIDs[i];
bool newIsMember = checkedListBoxGroups.GetItemChecked(i);
if (!newIsMember && oriGroupMember[gid])
if (!newIsMember && oriGroupMember[i])
{
for (int j = 0; j < user.Groups.Count; j++)
{
if (user.Groups[j].Gid == gid)
Group grp = user.Groups[j];
if (grp.GID == gid)
{
session.Delete(user.Groups[j]);
user.Groups.RemoveAt(j);
@ -204,9 +209,9 @@ namespace Users.Forms
}
}
}
else if (newIsMember && !oriGroupMember[gid])
else if (newIsMember && !oriGroupMember[i])
{
Group newGroup = new Group(gid, ((Grp.GID)gid).ToString());
Group newGroup = new Group(gid);
user.Groups.Add(newGroup);
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Windows.Forms;
using GemCard;
using Users.Entities;
using Users.Resources;
using System.Drawing;
@ -18,7 +19,7 @@ namespace Users.Forms
// Private fields
string user;
string password;
Grp.GID[] requiredGroupMembership;
GID[] requiredGroupMembership;
bool noDatabase;
Color oriBackColor;
@ -61,7 +62,7 @@ namespace Users.Forms
/// <summary>
/// Constructor when a specific group membership is required.
/// </summary>
public LoginDlg(Grp.GID[] requiredGroupMembership)
public LoginDlg(GID[] requiredGroupMembership)
: this()
{
this.requiredGroupMembership = requiredGroupMembership;
@ -75,7 +76,7 @@ namespace Users.Forms
/// <summary>
/// Constructor with a predefined user when a specific group membership is required.
/// </summary>
public LoginDlg(string predefinedUser, Grp.GID[] requiredGroupMembership)
public LoginDlg(string predefinedUser, GID[] requiredGroupMembership)
: this()
{
user = predefinedUser;

View File

@ -26,6 +26,39 @@ namespace Users.Forms
const int NameSurnameColumn = 2;
static GID[] DisplayedGIDs = new GID[]
{
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
GID.Testers,
GID.TestingSpecialists,
GID.HeadOfLab,
GID.MaintenanceSpecialists,
GID.Metrologists,
GID.CalibrationSpecialists,
GID.Administrators,
GID.TraceabilityManagement,
#elif KEMPNO_50 || KRAKOW_50 || TORUN_50 || WARSAW_END
GID.Testers,
GID.TestingSpecialists,
GID.HeadOfLab,
GID.MaintenanceSpecialists,
GID.Metrologists,
GID.CalibrationSpecialists,
GID.Administrators,
GID.MetrologicalAuthority,
GID.WaterMeterAuthority,
#else
GID.Testers,
GID.TestingSpecialists,
GID.HeadOfLab,
GID.MaintenanceSpecialists,
GID.Metrologists,
GID.CalibrationSpecialists,
GID.Administrators,
#endif
};
public string TitleExtension;
@ -61,9 +94,7 @@ namespace Users.Forms
listViewUsers.Columns.Add(Strings.User_name, 100); /// column 0
listViewUsers.Columns.Add(Strings.User_code, 70); /// column 1: UserNumberColumn
listViewUsers.Columns.Add(Strings.Full_name, 150); /// column 2: NameSurnameColumn
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
listViewUsers.Columns.Add(Strings.Tag, 110);
#endif
listViewUsers.Columns.Add(Strings.Groups, 370);
try
@ -87,38 +118,19 @@ namespace Users.Forms
{
string grps = string.Empty;
///
#if TURA_IPERL || TURA_IPERL_NEW
foreach (var gid in new Grp.GID[] { Grp.GID.TraceabilityManagement,
Grp.GID.Administrators,
Grp.GID.HeadOfLab,
Grp.GID.Metrologists,
Grp.GID.CalibrationSpecialists,
Grp.GID.TestingSpecialists,
Grp.GID.MaintenanceSpecialists,
Grp.GID.Testers })
#else
foreach (var gid in new Grp.GID[] { Grp.GID.Administrators,
Grp.GID.HeadOfLab,
Grp.GID.Metrologists,
Grp.GID.CalibrationSpecialists,
Grp.GID.TestingSpecialists,
Grp.GID.MaintenanceSpecialists,
Grp.GID.Testers })
#endif
foreach (var gid in DisplayedGIDs)
{
if (u.IsMemberOf(gid))
{
if (!string.IsNullOrEmpty(grps)) grps += ", ";
grps += Grp.Gid2Str(gid);
grps += Group.Gid2Str(gid);
}
}
ListViewItem item = new ListViewItem(u.UserName);
item.SubItems.Add(u.Number.ToString());
item.SubItems.Add(u.FullName);
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
item.SubItems.Add(string.IsNullOrEmpty(u.Tag) ? string.Empty : u.Tag);
#endif
item.SubItems.Add(grps);
item.Tag = u;
this.listViewUsers.Items.Add(item);
@ -197,7 +209,7 @@ namespace Users.Forms
{
if (listViewUsers.SelectedItems.Count == 1 && listViewUsers.SelectedItems[0].Tag is User)
{
new Forms.EditSelectedUser(session, (User)listViewUsers.SelectedItems[0].Tag).ShowDialog();
new Forms.EditSelectedUser(session, (User)listViewUsers.SelectedItems[0].Tag, DisplayedGIDs).ShowDialog();
ListUsers();
}
}
@ -210,7 +222,7 @@ namespace Users.Forms
private void addButton_Click(object sender, EventArgs e)
{
User newUser = new User();
if (new Forms.EditSelectedUser(session, newUser).ShowDialog() == DialogResult.OK)
if (new Forms.EditSelectedUser(session, newUser, DisplayedGIDs).ShowDialog() == DialogResult.OK)
{
listOfUsers.Add(newUser);
}
@ -285,7 +297,7 @@ namespace Users.Forms
newUsers.Add(newUser);
foreach (var group in user.Groups)
{
Group newGroup = new Group(group.Gid, group.Name);
Group newGroup = new Group(group.GID);
newUser.AddGroup(newGroup);
}

View File

@ -1,4 +1,7 @@
using System;
///
/// Copyright (c) 2016-2019 Sensus Slovensko a.s.
///
using System;
namespace Users
{

View File

@ -1,129 +0,0 @@
///
/// Copyright (c) 2013-2019 Sensus Slovensko a.s.
///
using System;
using System.Collections.Generic;
using System.Text;
using NHibernate;
using FluentNHibernate;
using Users.Entities;
using Users.Resources;
namespace Users
{
/// <summary>
/// Enum Grp.GID specifies GID-s of user groups.
/// An instance of this class represenst a group, which contains a list of its members (users).
/// Static private array 'groups' of this class, accesible through indexer, contains all groups.
/// </summary>
public class Grp
{
/// <summary>
/// GID-s of user groups, each user is member of one or more groups.
/// </summary>
public enum GID
{
// The first NrOfGroups items are GroupID-s (0..NrOfGroups-1)
Testers = 0,
TestingSpecialists,
HeadOfLab,
MaintenanceSpecialists,
Metrologists,
CalibrationSpecialists,
Administrators, // application / network / database administrator
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
TraceabilityManagement,
#endif
MetrologicalAuthority,
WaterMeterAuthority,
NrOfGroups, // Number of groups (this is not a GroupID)
None, // Not a GroupID, can be used to indicate no group membership is required
Invalid = -1, // Not a GroupID, indicates a variable has not been properly set so far
}
public static string Gid2Str(int gid)
{
return Gid2Str((GID)gid);
}
public static string Gid2Str(GID gid)
{
switch (gid)
{
case GID.Testers: return Strings.tester;
case GID.TestingSpecialists: return Strings.specialist;
case GID.HeadOfLab: return Strings.head_of_lab;
case GID.MaintenanceSpecialists: return Strings.maintenance;
case GID.Metrologists: return Strings.metrologist;
case GID.CalibrationSpecialists: return Strings.calibration_specialist;
case GID.Administrators: return Strings.administrator;
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
case GID.TraceabilityManagement: return Strings.production_tracing_administrator;
#endif
case GID.MetrologicalAuthority: return Strings.metrological_authority;
case GID.WaterMeterAuthority: return Strings.water_meter_authority;
default: return Strings.invalid;
}
}
/// <summary>
/// Number of groups.
/// </summary>
public const int Count = (int)GID.NrOfGroups;
// Static array of all groups.
static Grp[] groups;
/// <summary>
/// Static constructor, creates all groups with no members.
/// </summary>
static Grp()
{
groups = new Grp[Count];
for (int i = 0; i < Count; i++)
{
groups[i] = new Grp((GID)i);
}
}
/// <summary>
/// Returns a Group from Id.
/// </summary>
/// <param name="id">Group Gid</param>
/// <returns>Entities.Group object reference</returns>
public static Entities.Group FromId(GID gid)
{
int i = (int)gid;
if (i >= 0 && i < Count)
{
return groups[i].group;
}
else
{
return null;
}
}
///////////////////// ^ static ^ ///////////////////// v instance v /////////////////////
/// Public properties
public GID Gid { get { return (GID)group.Gid; } }
public string Name { get { return group.Name; } set { group.Name = value; } }
/// Private fields
Entities.Group group;
/// <summary>
/// Instance constructor.
/// </summary>
/// <param name="id"></param>
public Grp(GID gid)
{
group = new Entities.Group();
this.group.Gid = (int)gid;
this.group.Name = gid.ToString();
}
}
}

View File

@ -1,5 +1,5 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
/// Copyright (c) 2016-2019 Sensus Slovensko a.s.
///
using FluentNHibernate.Mapping;
@ -10,8 +10,7 @@ namespace Users.Mappings
public GroupMap()
{
Id(x => x.Id);
Map(x => x.Gid);
Map(x => x.Name);
Map(x => x.GID).Column("Name"); ;
}
}
}

View File

@ -12,12 +12,11 @@ namespace Users.Mappings
Id(x => x.Id);
Map(x => x.UserName).Column("Name");
Map(x => x.Number);
#if TURA_IPERL || TURA_IPERL_NEW || TURA_SPECIAL
Map(x => x.Tag);
#endif
Map(x => x.Password);
Map(x => x.Password2);
Map(x => x.Password3);
Map(x => x.Password4);
Map(x => x.FullName).Column("Description");
Map(x => x.LastPwChange);
HasMany(x => x.Groups)

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.24.1368.0")]
[assembly: AssemblyFileVersion("2.24.1368.0")]
[assembly: AssemblyVersion("2.24.1382.0")]
[assembly: AssemblyFileVersion("2.24.1382.0")]

View File

@ -192,4 +192,25 @@
<data name="Warning" xml:space="preserve">
<value>Warnung</value>
</data>
<data name="administrator" xml:space="preserve">
<value>Administrator</value>
</data>
<data name="calibration_specialist" xml:space="preserve">
<value>Kalibriertechniker</value>
</data>
<data name="head_of_lab" xml:space="preserve">
<value>Laborleiter</value>
</data>
<data name="maintenance" xml:space="preserve">
<value>Wartungstechniker</value>
</data>
<data name="metrologist" xml:space="preserve">
<value>Messtechniker</value>
</data>
<data name="specialist" xml:space="preserve">
<value>Prüftechniker</value>
</data>
<data name="tester" xml:space="preserve">
<value>Prüfer</value>
</data>
</root>

View File

@ -205,25 +205,25 @@
<value>Enregistrement ou mise à jour utilisateur a échoué</value>
</data>
<data name="administrator" xml:space="preserve">
<value>administrateur</value>
<value>Administrateur</value>
</data>
<data name="calibration_specialist" xml:space="preserve">
<value>spécialiste étalonnages</value>
<value>Spécialiste en calibration</value>
</data>
<data name="head_of_lab" xml:space="preserve">
<value>chef laboratoire</value>
<value>Chef de laboratoire</value>
</data>
<data name="maintenance" xml:space="preserve">
<value>entretien</value>
<value>Spécialiste en maintenance</value>
</data>
<data name="metrologist" xml:space="preserve">
<value>métrologue</value>
<value>Métrologue</value>
</data>
<data name="specialist" xml:space="preserve">
<value>spécialiste</value>
<value>Spécialiste d'essais</value>
</data>
<data name="tester" xml:space="preserve">
<value>testeur</value>
<value>Testeur</value>
</data>
<data name="invalid" xml:space="preserve">
<value>invalide</value>

View File

@ -0,0 +1,141 @@
<?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="administrator" xml:space="preserve">
<value>Amministratore</value>
</data>
<data name="calibration_specialist" xml:space="preserve">
<value>esperto in calibrazione</value>
</data>
<data name="head_of_lab" xml:space="preserve">
<value>capo di laboratorio</value>
</data>
<data name="maintenance" xml:space="preserve">
<value>esperto di manutenzione</value>
</data>
<data name="metrologist" xml:space="preserve">
<value>metrologo</value>
</data>
<data name="specialist" xml:space="preserve">
<value>esperto di prove</value>
</data>
<data name="tester" xml:space="preserve">
<value>tester</value>
</data>
</root>

View File

@ -183,4 +183,25 @@
<data name="CloseBtnText" xml:space="preserve">
<value>Zamknij</value>
</data>
<data name="administrator" xml:space="preserve">
<value>Administrator</value>
</data>
<data name="calibration_specialist" xml:space="preserve">
<value>Specjalista ds. kalibracji</value>
</data>
<data name="head_of_lab" xml:space="preserve">
<value>Kierownik Laboratorium</value>
</data>
<data name="maintenance" xml:space="preserve">
<value>Konserwator</value>
</data>
<data name="metrologist" xml:space="preserve">
<value>Metrolog</value>
</data>
<data name="specialist" xml:space="preserve">
<value>Specjalista ds. testów</value>
</data>
<data name="tester" xml:space="preserve">
<value>Pracownik przeprowadzający testy</value>
</data>
</root>

View File

@ -183,4 +183,25 @@
<data name="CloseBtnText" xml:space="preserve">
<value>Закрыть</value>
</data>
<data name="administrator" xml:space="preserve">
<value>Администратор</value>
</data>
<data name="calibration_specialist" xml:space="preserve">
<value>Специалист по калибровке</value>
</data>
<data name="head_of_lab" xml:space="preserve">
<value>Руководитель лаборатории</value>
</data>
<data name="maintenance" xml:space="preserve">
<value>Специалист по техобслуживанию</value>
</data>
<data name="metrologist" xml:space="preserve">
<value>Метролог</value>
</data>
<data name="specialist" xml:space="preserve">
<value>Специалист по тестированию</value>
</data>
<data name="tester" xml:space="preserve">
<value>Контролер</value>
</data>
</root>

View File

@ -183,4 +183,25 @@
<data name="CloseBtnText" xml:space="preserve">
<value>关闭 Close</value>
</data>
<data name="administrator" xml:space="preserve">
<value>管理员</value>
</data>
<data name="calibration_specialist" xml:space="preserve">
<value>校准专员</value>
</data>
<data name="head_of_lab" xml:space="preserve">
<value>实验室负责人</value>
</data>
<data name="maintenance" xml:space="preserve">
<value>维护专员</value>
</data>
<data name="metrologist" xml:space="preserve">
<value>计量者</value>
</data>
<data name="specialist" xml:space="preserve">
<value>测试专员</value>
</data>
<data name="tester" xml:space="preserve">
<value>测试仪</value>
</data>
</root>

View File

@ -91,7 +91,6 @@
<Compile Include="Forms\LoginDlg.designer.cs">
<DependentUpon>LoginDlg.cs</DependentUpon>
</Compile>
<Compile Include="Grp.cs" />
<Compile Include="Mappings\GroupMap.cs" />
<Compile Include="Mappings\UserMap.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@ -123,6 +122,7 @@
<EmbeddedResource Include="Resources\Strings.cs.resx" />
<EmbeddedResource Include="Resources\Strings.de.resx" />
<EmbeddedResource Include="Resources\Strings.fr.resx" />
<EmbeddedResource Include="Resources\Strings.it.resx" />
<EmbeddedResource Include="Resources\Strings.pl.resx" />
<EmbeddedResource Include="Resources\Strings.resx">
<Generator>ResXFileCodeGenerator</Generator>