laatzen/LaaProductionWeb/LaaProductionWeb.Services/SoftwareService.cs
2023-06-02 15:49:59 +02:00

390 lines
16 KiB
C#

namespace LaaProductionWeb.Services
{
using LaaProductionWeb.Data.Interfaces;
using LaaProductionWeb.Services.Interfaces;
using LaaProductionWeb.Services.Models.Software;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
public class SoftwareService : ISoftwareService
{
private readonly ISqlClient sqlClient;
public SoftwareService(ISqlClient sqlClient)
=> this.sqlClient = sqlClient;
public void AddFunction(short appId, string name)
=> this.sqlClient
.CreateCommand($@"
INSERT INTO [SoftwareFunctions] (
[AppId]
, [Function])
VALUES (@{nameof(appId)}
, @{nameof(name)})")
.AddParameter(nameof(appId), appId)
.AddParameter(nameof(name), name)
.ExecuteNonQuery();
public int ApplicationId(string name)
=> this.sqlClient
.CreateCommand($@"
SELECT TOP 1 [AppId]
FROM [VersionSoftwareAccess]
WHERE [SoftwareAccess_Program] = @{nameof(name)}")
.AddParameter(nameof(name), name)
.FirstOrDefault(x => x.GetSmallint());
public void DeleteFunction(int funcId)
{
this.sqlClient
.CreateCommand($@"
DELETE FROM [SoftwareFunctions]
WHERE [Id] = @{nameof(funcId)}")
.AddParameter(nameof(funcId), funcId)
.ExecuteNonQuery();
this.sqlClient
.CreateCommand($@"
DELETE FROM [UsersFunctions]
WHERE [SoftwareFunctionId] = @{nameof(funcId)}")
.AddParameter(nameof(funcId), funcId)
.ExecuteNonQuery();
}
public short FindAndUpdateSoftware(string name, IEnumerable<string> functions)
{
var appId = this.sqlClient
.CreateCommand($@"
SELECT TOP 1 [AppId]
, MAX([SoftwareAccess_VaildTo]) OVER (PARTITION BY [AppId])
FROM [VersionSoftwareAccess]
WHERE [SoftwareAccess_Program] = @{nameof(name)}
AND [SoftwareAccess_VaildTo] > GETDATE()")
.AddParameter(nameof(name), name)
.FirstOrDefault(x => x.GetSmallint());
if (appId > 0 && functions != null && functions.Any())
{
foreach (var function in functions)
{
if (Regex.IsMatch(function, "[a-zA-Z_]+"))
{
this.AddFunction(appId, function);
}
}
}
return appId;
}
public IEnumerable<SoftwareFunction> GetAllSoftwareFunctions()
=> this.sqlClient
.CreateCommand($@"
SELECT [Id]
, [AppId]
, [Function]
FROM [SoftwareFunctions]")
.ExecuteReader(f => new SoftwareFunction
{
Id = f.GetInt(),
AppId = f.GetSmallint(),
Function = f.GetString()
});
public IEnumerable<SoftwareFunction> GetSoftwareFunctions(short appId)
=> this.sqlClient
.CreateCommand($@"
SELECT [Id]
, [AppId]
, [Function]
FROM [SoftwareFunctions]
WHERE [AppId] = @{nameof(appId)}")
.AddParameter(nameof(appId), appId)
.ExecuteReader(f => new SoftwareFunction
{
Id = f.GetInt(),
AppId = f.GetSmallint(),
Function = f.GetString()
});
public IEnumerable<string> GetSoftwareFunctions(short appId, short userId)
=> this.sqlClient
.CreateCommand($@"
SELECT [SF].[Function] AS [Function]
FROM [UsersFunctions] AS [UF]
JOIN [SoftwareFunctions] AS [SF]
ON [SF].[Id] = [UF].[SoftwareFunctionId]
WHERE [UF].[UserId] = @{nameof(userId)}
AND [SF].[AppId] = @{nameof(appId)}")
.AddParameter(nameof(appId), appId)
.AddParameter(nameof(userId), userId)
.ExecuteReader(x => x.GetString());
public SoftwareOverview GetSoftwareOverview(short appId)
=> this.sqlClient
.CreateCommand($@"
SELECT [vsa].[AppID]
, [vsa].[SoftwareAccess_Program]
, COUNT([vsa].[AppID])
, (SELECT COUNT(1)
FROM [SoftwareFunctions]
WHERE [AppId] = [vsa].[AppID]) AS [CountF]
FROM [VersionSoftwareAccess] AS [vsa]
WHERE [vsa].[AppID] = @{nameof(appId)}
GROUP BY [vsa].[AppID]
, [vsa].[SoftwareAccess_Program]")
.AddParameter(nameof(appId), appId)
.FirstOrDefault(x => new SoftwareOverview
{
AppId = x.GetSmallint(),
Name = x.GetString(),
Versions = x.GetInt(),
Functions = x.GetInt()
});
public IEnumerable<Software> GetSoftwareVersions(short appId)
=> this.sqlClient
.CreateCommand($@"
SELECT [SoftwareAccess_ID]
, [AppID]
, [SoftwareAccess_Program]
, [SoftwareAccess_MajorVersion]
, [SoftwareAccess_MinorVersion]
, [SoftwareAccess_BuildVersion]
, [SoftwareAccess_VaildTo]
, [SoftwareAccess_Desc]
FROM [VersionSoftwareAccess]
WHERE [AppId] = @{nameof(appId)}
ORDER BY [SoftwareAccess_VaildTo] DESC
, [SoftwareAccess_MajorVersion] DESC
, [SoftwareAccess_MinorVersion] DESC
, [SoftwareAccess_BuildVersion] DESC")
.AddParameter(nameof(appId), appId)
.ExecuteReader(x => new Software
{
Id = x.GetInt(),
AppId = x.GetSmallint(),
FullName = x.GetString(),
MajorV = x.GetInt(),
MinorV = x.GetInt(),
BuildV = x.GetInt(),
ValidTo = x.GetDate(),
Description = x.GetString()
});
public IEnumerable<SoftwareOverview> GetSoftwares()
=> this.sqlClient
.CreateCommand(@"
SELECT [VSA].[AppId] AS [AppId]
, [VSA].[SoftwareAccess_Program] AS [Program]
, COUNT([VSA].[AppId]) AS [Versions]
, (SELECT COUNT(1)
FROM [SoftwareFunctions]
WHERE [AppId] = [VSA].[AppID]) AS [Functions]
FROM [VersionSoftwareAccess] AS [VSA]
GROUP BY [VSA].[AppId]
, [VSA].[SoftwareAccess_Program]")
.ExecuteReader(x => new SoftwareOverview
{
AppId = x.GetSmallint(),
Name = x.GetString(),
Versions = x.GetInt(),
Functions = x.GetInt(),
});
public IEnumerable<SoftwareUser> GetUsers(string username = null)
=> this.sqlClient
.CreateCommand($@"
SELECT [U].[MitarbeiterNr]
, [U].[Vorname]
, [U].[Name]
, [U].[Benutzername]
, COUNT([UF].[UserId])
, CAST(CASE WHEN [U].[PasswordHash] IS NULL THEN 0 ELSE 1 END AS BIT)
FROM [Mitarbeiter] AS [U]
LEFT JOIN [UsersFunctions] AS [UF]
ON [UF].[UserId] = [U].[MitarbeiterNr]
WHERE [U].[Vorname] LIKE @{nameof(username)}
OR [U].[Name] LIKE @{nameof(username)}
OR [U].[Benutzername] LIKE @{nameof(username)}
GROUP BY [U].[MitarbeiterNr]
, [U].[Vorname]
, [U].[Name]
, [U].[Benutzername]
, [U].[PasswordHash]
ORDER BY [U].[Vorname]
, [U].[Name]
, [U].[Benutzername]")
.AddParameter(nameof(username), $"%{username}%")
.ExecuteReader(x => new SoftwareUser
{
Id = x.GetSmallint(),
FirstName = x.GetString(),
LastName = x.GetString(),
Username = x.GetString(),
FunctionsCount = x.GetInt(),
HasPassword = x.GetBool()
});
public IEnumerable<SoftwareUser> GetUsersWithFunctions(int userId = -1, string username = null)
=> this.sqlClient
.CreateCommand($@"
SELECT [U].[MitarbeiterNr]
, [U].[Vorname]
, [U].[Name]
, [U].[Benutzername]
, COUNT([UF].[UserId])
, CAST(CASE WHEN [U].[PasswordHash] IS NULL THEN 0 ELSE 1 END AS BIT)
, (SELECT CAST([SoftwareFunctionId] * -1 AS VARCHAR(MAX))
FROM [UsersFunctions]
WHERE [UserId] = [UF].[UserId]
ORDER BY [SoftwareFunctionId]
FOR XML PATH (''))
FROM [Mitarbeiter] AS [U]
LEFT JOIN [UsersFunctions] AS [UF]
ON [UF].[UserId] = [U].[MitarbeiterNr]
WHERE [U].[Vorname] LIKE @{nameof(username)}
OR [U].[Name] LIKE @{nameof(username)}
OR [U].[Benutzername] LIKE @{nameof(username)}
OR [U].[MitarbeiterNr] = @{nameof(userId)}
GROUP BY [U].[MitarbeiterNr]
, [U].[Vorname]
, [U].[Name]
, [U].[Benutzername]
, [U].[PasswordHash]
, [UF].[UserId]
ORDER BY [U].[Vorname]
, [U].[Name]
, [U].[Benutzername]")
.AddParameter(nameof(username), $"%{username}%")
.AddParameter(nameof(userId), userId)
.ExecuteReader(x => new SoftwareUser
{
Id = x.GetSmallint(),
FirstName = x.GetString(),
LastName = x.GetString(),
Username = x.GetString(),
FunctionsCount = x.GetInt(),
HasPassword = x.GetBool(),
Functions = x.GetString()
});
public void UpdateFunction(int funcId, string name)
=> this.sqlClient
.CreateCommand($@"
UPDATE [SoftwareFunctions]
SET [Function] = @{nameof(name)}
WHERE [Id] = @{nameof(funcId)}")
.AddParameter(nameof(funcId), funcId)
.AddParameter(nameof(name), name)
.ExecuteNonQuery();
public void UpdatePasswordHashes()
{
var pwdUsers = this.sqlClient
.CreateCommand($@"
SELECT [MitarbeiterNr]
, [Kennwort]
FROM [Mitarbeiter]
WHERE [Kennwort] IS NOT NULL
AND [PasswordHash] IS NULL")
.ExecuteReader(x => new KeyValuePair<short, string>(
key: x.GetSmallint(),
value: x.GetString()));
var sha256 = SHA256.Create();
foreach (var kvp in pwdUsers)
{
var userId = kvp.Key;
var password = sha256.ComputeHash(kvp.Value);
this.sqlClient
.CreateCommand($@"
UPDATE [Mitarbeiter]
SET [PasswordHash] = @{nameof(password)}
WHERE [MitarbeiterNr] = @{nameof(userId)}")
.AddParameter(nameof(userId), userId)
.AddParameter(nameof(password), password)
.ExecuteNonQuery();
}
}
public int ResetPassword(short userId)
=> this.sqlClient
.CreateCommand($@"
UPDATE [Mitarbeiter]
SET [PasswordHash] = NULL
WHERE [MitarbeiterNr] = @{nameof(userId)}")
.AddParameter(nameof(userId), userId)
.ExecuteNonQuery();
public int ResetPassword(short userId, string password)
{
password = SHA256.Create().ComputeHash(password);
return this.sqlClient
.CreateCommand($@"
UPDATE [Mitarbeiter]
SET [PasswordHash] = @{nameof(password)}
WHERE [MitarbeiterNr] = @{nameof(userId)}")
.AddParameter(nameof(userId), userId)
.AddParameter(nameof(password), password)
.ExecuteNonQuery();
}
public void UpdateUsersFunctions(Action<UserFunctions> mapper)
{
var model = new UserFunctions();
mapper(model);
var userId = model.UserId;
this.sqlClient
.CreateCommand($@"DELETE FROM [UsersFunctions] WHERE [UserId] = @{nameof(userId)}")
.AddParameter(nameof(userId), userId)
.ExecuteNonQuery();
foreach (var funcId in model.Functions ?? Array.Empty<int>())
{
this.sqlClient
.CreateCommand($@"
INSERT
INTO [UsersFunctions] ([UserId] ,[SoftwareFunctionId])
VALUES (@{nameof(userId)}, @{nameof(funcId)})")
.AddParameter(nameof(userId), userId)
.AddParameter(nameof(funcId), funcId)
.ExecuteNonQuery();
}
}
public void UpdateUsersFunctions(Action<FunctionUsers> mapper)
{
var model = new FunctionUsers();
mapper(model);
var funcId = model.FunctionId;
this.sqlClient
.CreateCommand($@"DELETE FROM [UsersFunctions] WHERE [SoftwareFunctionId] = @{nameof(funcId)}")
.AddParameter(nameof(funcId), funcId)
.ExecuteNonQuery();
foreach (var userId in model.Users ?? Array.Empty<short>())
{
this.sqlClient
.CreateCommand($@"
INSERT
INTO [UsersFunctions] ([UserId] ,[SoftwareFunctionId])
VALUES (@{nameof(userId)}, @{nameof(funcId)})")
.AddParameter(nameof(userId), userId)
.AddParameter(nameof(funcId), funcId)
.ExecuteNonQuery();
}
}
}
}