VodVas

CleanCode_ExampleTask21-27.cs

Dec 18th, 2024 (edited)
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 9.91 KB | Legal | 0 0
  1. using System.Data;
  2. using System.Reflection;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5.  
  6. namespace PassportService
  7. {
  8.     internal class Program
  9.     {
  10.         static void Main()
  11.         {
  12.             string databasePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "db.sqlite");
  13.  
  14.             IPassportView view = new PassportView();
  15.  
  16.             FactoryPresenter presenterFactory = new FactoryPresenter();
  17.  
  18.             IPassportPresenter presenter = presenterFactory.CreatePresenter(view, databasePath);
  19.  
  20.             try
  21.             {
  22.                 view.Run();
  23.             }
  24.             finally
  25.             {
  26.                 if (presenter is PassportPresenter passportPresenter)
  27.                 {
  28.                     passportPresenter.Unsubscribe();
  29.                 }
  30.             }
  31.         }
  32.     }
  33.  
  34.     public enum PassportCheckResult
  35.     {
  36.         InvalidFormat,
  37.         AccessGranted,
  38.         AccessDenied,
  39.         NotFound
  40.     }
  41.  
  42.     public interface IPassportView
  43.     {
  44.         event EventHandler CheckPassportClicked;
  45.  
  46.         string PassportNumber { get; }
  47.  
  48.         void ShowMessage(string message);
  49.         void ShowError(string errorMessage);
  50.         void Run();
  51.     }
  52.  
  53.     public interface IPassportPresenter
  54.     {
  55.         void OnCheckPassportClicked(object sender, EventArgs eventArgs);
  56.     }
  57.  
  58.     public interface IPassportService
  59.     {
  60.         Citizen VerifyPassportAccess(Passport passport);
  61.     }
  62.  
  63.     public interface IDatabaseContext
  64.     {
  65.         Citizen GetCitizenByPassportHash(string passportHash);
  66.     }
  67.  
  68.     public interface IDatabase
  69.     {
  70.         DataTable ExecuteQuery(string query);
  71.     }
  72.  
  73.     public class PassportView : IPassportView
  74.     {
  75.         public event EventHandler CheckPassportClicked;
  76.  
  77.         public string PassportNumber { get; private set; }
  78.  
  79.         public void Run()
  80.         {
  81.             Console.WriteLine("Введите серию и номер паспорта:");
  82.  
  83.             PassportNumber = Console.ReadLine();
  84.  
  85.             CheckPassportClicked?.Invoke(this, EventArgs.Empty);
  86.         }
  87.  
  88.         public void ShowMessage(string message)
  89.         {
  90.             Console.WriteLine(message);
  91.         }
  92.  
  93.         public void ShowError(string errorMessage)
  94.         {
  95.             Console.WriteLine("Ошибка: " + errorMessage);
  96.         }
  97.     }
  98.  
  99.     public class FactoryPresenter
  100.     {
  101.         public IPassportPresenter CreatePresenter(IPassportView view, string databasePath)
  102.         {
  103.             var database = new Database(databasePath);
  104.             var databaseContext = new DatabaseContext(database);
  105.             var hashingService = new HashingService();
  106.             var service = new PassportService(databaseContext, hashingService);
  107.             var presenter = new PassportPresenter(view, service);
  108.  
  109.             return presenter;
  110.         }
  111.     }
  112.  
  113.     public class PassportPresenter : IPassportPresenter
  114.     {
  115.         private readonly IPassportView _view;
  116.         private readonly IPassportService _service;
  117.  
  118.         public PassportPresenter(IPassportView view, IPassportService service)
  119.         {
  120.             _view = view ?? throw new ArgumentNullException(nameof(view));
  121.             _service = service ?? throw new ArgumentNullException(nameof(service));
  122.  
  123.             _view.CheckPassportClicked += OnCheckPassportClicked;
  124.         }
  125.  
  126.         public void Unsubscribe()
  127.         {
  128.             _view.CheckPassportClicked -= OnCheckPassportClicked;
  129.         }
  130.  
  131.         public void OnCheckPassportClicked(object sender, EventArgs eventArgs)
  132.         {
  133.             try
  134.             {
  135.                 var passport = new Passport(_view.PassportNumber);
  136.  
  137.                 Citizen citizen = _service.VerifyPassportAccess(passport);
  138.  
  139.                 if (citizen != null)
  140.                 {
  141.                     if (citizen.HasAccess)
  142.                     {
  143.                         _view.ShowMessage($"По паспорту «{passport.Number}» доступ ПРЕДОСТАВЛЕН.");
  144.                     }
  145.                     else
  146.                     {
  147.                         _view.ShowMessage($"По паспорту «{passport.Number}» доступ НЕ ПРЕДОСТАВЛЕН.");
  148.                     }
  149.                 }
  150.                 else
  151.                 {
  152.                     _view.ShowMessage($"Паспорт «{passport.Number}» в списке НЕ НАЙДЕН.");
  153.                 }
  154.             }
  155.             catch (ArgumentException exception)
  156.             {
  157.                 _view.ShowError(exception.Message);
  158.             }
  159.             catch (FileNotFoundException)
  160.             {
  161.                 _view.ShowError("Файл базы данных не найден.");
  162.             }
  163.             catch (Exception)
  164.             {
  165.                 _view.ShowError("Произошла непредвиденная ошибка.");
  166.             }
  167.         }
  168.     }
  169.  
  170.     public class Passport
  171.     {
  172.         private const int PassportSymbolsLength = 10;
  173.  
  174.         public string Number { get; }
  175.  
  176.         public Passport(string passportNumber)
  177.         {
  178.             Number = CleanPassportNumber(passportNumber) ?? throw new ArgumentNullException(nameof(passportNumber));
  179.  
  180.             if (IsValidFormat(Number) == false)
  181.             {
  182.                 throw new ArgumentException("Неверный формат серии или номера паспорта.", nameof(passportNumber));
  183.             }
  184.         }
  185.  
  186.         private bool IsValidFormat(string passportNumber)
  187.         {
  188.             return string.IsNullOrWhiteSpace(passportNumber) == false && passportNumber.Length == PassportSymbolsLength;
  189.         }
  190.  
  191.         private string CleanPassportNumber(string passportNumber)
  192.         {
  193.             return passportNumber.Trim().Replace(" ", string.Empty);
  194.         }
  195.     }
  196.  
  197.     public class Citizen
  198.     {
  199.         public bool HasAccess { get; }
  200.  
  201.         public Citizen(bool hasAccess)
  202.         {
  203.             HasAccess = hasAccess;
  204.         }
  205.     }
  206.  
  207.     public class PassportService : IPassportService
  208.     {
  209.         private readonly IDatabaseContext _databaseContext;
  210.         private readonly HashingService _hashingService;
  211.  
  212.         public PassportService(IDatabaseContext databaseContext, HashingService hashingService)
  213.         {
  214.             _databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
  215.             _hashingService = hashingService ?? throw new ArgumentNullException(nameof(hashingService));
  216.         }
  217.  
  218.         public Citizen VerifyPassportAccess(Passport passport)
  219.         {
  220.             string hashedPassport = _hashingService.ComputeSha256Hash(passport.Number);
  221.  
  222.             Citizen citizen = _databaseContext.GetCitizenByPassportHash(hashedPassport);
  223.  
  224.             return citizen;
  225.         }
  226.     }
  227.  
  228.     public class HashingService
  229.     {
  230.         public string ComputeSha256Hash(string rawData)
  231.         {
  232.             if (rawData == null)
  233.             {
  234.                 throw new ArgumentNullException(nameof(rawData));
  235.             }
  236.  
  237.             using (SHA256 sha256Hash = SHA256.Create())
  238.             {
  239.                 byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(rawData));
  240.  
  241.                 StringBuilder builder = new StringBuilder();
  242.  
  243.                 foreach (byte @byte in bytes)
  244.                 {
  245.                     builder.Append(@byte.ToString("x2"));
  246.                 }
  247.  
  248.                 return builder.ToString();
  249.             }
  250.         }
  251.     }
  252.  
  253.     public class DatabaseContext : IDatabaseContext
  254.     {
  255.         private const string AccessColumnName = "access";
  256.         private const int ColumnNumber = 0;
  257.  
  258.         private readonly IDatabase _database;
  259.  
  260.         public DatabaseContext(IDatabase database)
  261.         {
  262.             _database = database ?? throw new ArgumentNullException(nameof(database));
  263.         }
  264.  
  265.         public Citizen GetCitizenByPassportHash(string passportHash)
  266.         {
  267.             string query = $"SELECT * FROM passports WHERE num='{passportHash}' LIMIT 1;";
  268.  
  269.             DataTable dataTable = _database.ExecuteQuery(query);
  270.  
  271.             if (dataTable.Rows.Count > 0)
  272.             {
  273.                 bool accessGranted = Convert.ToBoolean(dataTable.Rows[ColumnNumber][AccessColumnName]);
  274.  
  275.                 return new Citizen(accessGranted);
  276.             }
  277.             else
  278.             {
  279.                 return null;
  280.             }
  281.         }
  282.     }
  283.  
  284.     public class Database : IDatabase
  285.     {
  286.         private const int SqLiteErrorCode = 1;
  287.  
  288.         private readonly string _connectionString;
  289.  
  290.         public Database(string databasePath)
  291.         {
  292.             _connectionString = $"Data Source={databasePath ?? throw new ArgumentNullException(nameof(databasePath))}";
  293.         }
  294.  
  295.         public DataTable ExecuteQuery(string query)
  296.         {
  297.             try
  298.             {
  299.                 using (var connection = new System.Data.SQLite.SQLiteConnection(_connectionString))
  300.                 {
  301.                     connection.Open();
  302.  
  303.                     using (var command = new System.Data.SQLite.SQLiteCommand(query, connection))
  304.                     {
  305.                         using (var adapter = new System.Data.SQLite.SQLiteDataAdapter(command))
  306.                         {
  307.                             DataTable dataTable = new DataTable();
  308.  
  309.                             adapter.Fill(dataTable);
  310.  
  311.                             return dataTable;
  312.                         }
  313.                     }
  314.                 }
  315.             }
  316.             catch (System.Data.SQLite.SQLiteException exception)
  317.             {
  318.                 if (exception.ErrorCode == SqLiteErrorCode)
  319.                 {
  320.                     throw new FileNotFoundException("Файл базы данных не найден.", exception);
  321.                 }
  322.  
  323.                 throw new Exception("Ошибка работы с базой данных.", exception);
  324.             }
  325.         }
  326.     }
  327. }
Advertisement
Add Comment
Please, Sign In to add comment