diff --git a/PWManager.Application/Abstractions/Interfaces/IDeleteDataContext.cs b/PWManager.Application/Abstractions/Interfaces/IDeleteDataContext.cs new file mode 100644 index 0000000..2c55dbf --- /dev/null +++ b/PWManager.Application/Abstractions/Interfaces/IDeleteDataContext.cs @@ -0,0 +1,6 @@ +namespace PWManager.Application.Abstractions.Interfaces; + +public interface IDeleteDataContext { + + void DeleteDataContext(); +} \ No newline at end of file diff --git a/PWManager.Application/Exceptions/MessageStrings.cs b/PWManager.Application/Exceptions/MessageStrings.cs index e0cf453..0a9017d 100644 --- a/PWManager.Application/Exceptions/MessageStrings.cs +++ b/PWManager.Application/Exceptions/MessageStrings.cs @@ -13,6 +13,8 @@ public static class MessageStrings { public const string FAILED_ADDING_ACCOUNT = "Failed adding the account!"; public static string AccountAlreadyExist(string input) => $"Account with identifier '{input}' does already exist in your group!"; public const string NO_ACTIVE_GROUP = "No active group found. Are you in a session?"; + public const string NO_ACTIVE_USER = "No active user found. Are you in a session?"; + // ---------------------------------------- // GROUP SERVICE @@ -36,6 +38,7 @@ public static class MessageStrings { // Config File Handler public const string READ_FILE_ERROR = "The config file could not be read."; public const string WRITE_FILE_ERROR = "The config file could not be written."; + public const string DELETE_FILE_ERROR = "The config file could not be deleted."; public const string PATH_ERROR = "An unknown error occured! Could not determine execution path!"; public const string DIRECTORY_ERROR = "An unknown error occured! Execution path is not a directory!"; // ---------------------------------------- @@ -43,4 +46,7 @@ public static class MessageStrings { // PasswordBuilder public const string MIN_LENGTH_TO_SMALL = "MinLength cannot be smaller than 0"; public const string MAX_LENGTH_TO_SMALL = "MaxLength cannot be smaller than MinLength"; + + // DataContext + public const string CANNOT_DELETE_DATABASE = "Cannot delete the database!"; } diff --git a/PWManager.CLI/Abstractions/ConfigFileHandler.cs b/PWManager.CLI/Abstractions/ConfigFileHandler.cs index 3ff3079..8112118 100644 --- a/PWManager.CLI/Abstractions/ConfigFileHandler.cs +++ b/PWManager.CLI/Abstractions/ConfigFileHandler.cs @@ -3,6 +3,10 @@ namespace PWManager.CLI.Abstractions { public static class ConfigFileHandler { + + public static bool DefaultFileExists() { + return File.Exists(Path.Combine(GetPath(), "last.txt")); + } public static string ReadDefaultFile() { var defaultFilePath = GetPath(); @@ -23,6 +27,16 @@ public static void WriteDefaultFile(string username, string path) { } } + public static void DeleteDefaultFile() { + var defaultFilePath = Path.Combine(GetPath(), "last.txt"); + try { + File.Delete(defaultFilePath); + } + catch (IOException) { + throw new UserFeedbackException(MessageStrings.DELETE_FILE_ERROR); + } + } + private static string GetPath() { var assembly = Assembly.GetEntryAssembly(); if (assembly is null) { diff --git a/PWManager.CLI/Controllers/DeleteDatabaseController.cs b/PWManager.CLI/Controllers/DeleteDatabaseController.cs new file mode 100644 index 0000000..678eb26 --- /dev/null +++ b/PWManager.CLI/Controllers/DeleteDatabaseController.cs @@ -0,0 +1,58 @@ +using PWManager.Application.Abstractions.Interfaces; +using PWManager.Application.Context; +using PWManager.Application.Exceptions; +using PWManager.Application.Services.Interfaces; +using PWManager.CLI.Abstractions; +using PWManager.CLI.Attributes; +using PWManager.CLI.Enums; +using PWManager.CLI.Interfaces; + +namespace PWManager.CLI.Controllers; + +[SessionOnly] +public class DeleteDatabaseController : IController { + + private readonly IDeleteDataContext _dataContextDeleter; + private readonly ILoginService _loginService; + private readonly IUserEnvironment _userEnv; + + public DeleteDatabaseController(IDeleteDataContext dataContextDeleter, ILoginService loginService, IUserEnvironment userEnv) { + _dataContextDeleter = dataContextDeleter; + _loginService = loginService; + _userEnv = userEnv; + } + + public ExitCondition Handle(string[] args) { + + if (!ConfirmPassword()) { + return ExitCondition.CONTINUE; + } + + try { + _dataContextDeleter.DeleteDataContext(); + } + catch(UserFeedbackException ex) { + PromptHelper.PrintColoredText(ConsoleColor.Red, ex.Message); + return ExitCondition.EXIT; + } + + try { + ConfigFileHandler.DeleteDefaultFile(); + } + catch (UserFeedbackException ex) { + PromptHelper.PrintColoredText(ConsoleColor.Red, ex.Message); + } + + PromptHelper.PrintColoredText(ConsoleColor.Cyan, UIstrings.DATABASE_DELETED); + + return ExitCondition.EXIT; + } + + private bool ConfirmPassword() { + if (_userEnv.CurrentUser is null) { + throw new ApplicationException(MessageStrings.NO_ACTIVE_USER); + } + var username = _userEnv.CurrentUser.UserName; + return PromptHelper.ConfirmDeletion(UIstrings.YOUR_DATABASE, (pw) => _loginService.CheckPassword(username, pw)); + } +} \ No newline at end of file diff --git a/PWManager.CLI/Controllers/LoginController.cs b/PWManager.CLI/Controllers/LoginController.cs index b37a288..dec8466 100644 --- a/PWManager.CLI/Controllers/LoginController.cs +++ b/PWManager.CLI/Controllers/LoginController.cs @@ -22,12 +22,24 @@ public LoginController(ILoginService loginService) { public ExitCondition Handle(string[] args) { (var username, var path) = ParseArgs(args); - var lastUser = ConfigFileHandler.ReadDefaultFile(); - if (String.IsNullOrWhiteSpace(username)) { - username = lastUser.Split('\n')[0]; + if (!ConfigFileHandler.DefaultFileExists()) { + if (string.IsNullOrWhiteSpace(username)) { + username = AskForInput(UIstrings.ENTER_USERNAME); + } + + if (string.IsNullOrWhiteSpace(path)) { + path = AskForInput(UIstrings.ENTER_PATH); + } } - if (String.IsNullOrWhiteSpace(path)) { - path = lastUser.Split('\n')[1]; + else { + var lastUser = ConfigFileHandler.ReadDefaultFile(); + if (String.IsNullOrWhiteSpace(username)) { + username = lastUser.Split('\n')[0]; + } + + if (String.IsNullOrWhiteSpace(path)) { + path = lastUser.Split('\n')[1]; + } } var succ = PromptHelper.InputPassword((p) => _loginService.Login(username, p, path)); diff --git a/PWManager.CLI/ExtensionMethods/RunnerExtensions.cs b/PWManager.CLI/ExtensionMethods/RunnerExtensions.cs index e7ea755..b380c4d 100644 --- a/PWManager.CLI/ExtensionMethods/RunnerExtensions.cs +++ b/PWManager.CLI/ExtensionMethods/RunnerExtensions.cs @@ -14,6 +14,7 @@ public static void AddControllers(this IServiceCollection services) { services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); } @@ -26,6 +27,7 @@ public static void MapControllers(this ConsoleRunner runner) { runner.MapCommand(AvailableCommands.NEW); runner.MapCommand(AvailableCommands.GROUP); runner.MapCommand(AvailableCommands.GET); + runner.MapCommand(AvailableCommands.DELETE_DATABASE); runner.MapCommand(AvailableCommands.SETTINGS); runner.MapCommand(AvailableCommands.QUIT); } diff --git a/PWManager.CLI/UIstrings.cs b/PWManager.CLI/UIstrings.cs index fae1ff4..019ca30 100644 --- a/PWManager.CLI/UIstrings.cs +++ b/PWManager.CLI/UIstrings.cs @@ -123,6 +123,12 @@ internal static class UIstrings { public const string NO_ACCOUNTS_AVAILABLE = "There are no accounts in this group!"; // ---------------------------------------- + // DELETE DATABASE Controller + public const string YOUR_DATABASE = "your database?"; + public const string DATABASE_DELETED = "Your database was deleted successfully!"; + + // ---------------------------------------- + // SETTINGS Controller public const string MAIN_GROUP_CHANGE = "Which group will be your new main group?"; public static string ConfirmOfMainGroupChangedTo(string input) => $"Main group set to '{input}'"; diff --git a/PWManager.Data/DataContext.cs b/PWManager.Data/DataContext.cs index a0d5d0e..2f06588 100644 --- a/PWManager.Data/DataContext.cs +++ b/PWManager.Data/DataContext.cs @@ -1,10 +1,11 @@ using PWManager.Application.Abstractions.Interfaces; +using PWManager.Application.Exceptions; using PWManager.Data.Abstraction.Interfaces; using PWManager.Data.Persistance; namespace PWManager.Data; -public class DataContext : IDataContextInitializer, IHaveDataContext { +public class DataContext : IDataContextInitializer, IHaveDataContext, IDeleteDataContext { private ApplicationDbContext? _dbContext; private const string DatabaseFileName = "pwdb.scuml"; @@ -18,10 +19,28 @@ public void InitDataContext(string path) { return; } _dbContext = new ApplicationDbContext(Path.Combine(path, DatabaseFileName)); - + _dbContext.Database.EnsureCreated(); } + private void CloseDatabase() { + if (_dbContext is null) { + return; + } + _dbContext.Dispose(); + _dbContext = null; + } + + public void DeleteDataContext() { + if (_dbContext is null) { + return; + } + + _dbContext.Database.EnsureDeleted(); + + CloseDatabase(); + } + ApplicationDbContext IHaveDataContext.GetDbContext() { if (_dbContext is null) { throw new ApplicationException("Data Context was not initialized!"); diff --git a/PWManager.Data/DependencyInjection.cs b/PWManager.Data/DependencyInjection.cs index d82e2a2..33d47ca 100644 --- a/PWManager.Data/DependencyInjection.cs +++ b/PWManager.Data/DependencyInjection.cs @@ -18,7 +18,7 @@ public static IServiceCollection AddDataServices(this IServiceCollection service var dataContext = new DataContext(); HaveDataContextFactory.Initialize(dataContext); services.AddSingleton(dataContext); - + services.AddSingleton(dataContext); services.AddTransient(); services.AddTransient(); diff --git a/PWManager.Data/Persistance/ApplicationDbContext.cs b/PWManager.Data/Persistance/ApplicationDbContext.cs index a36e462..9d9b189 100644 --- a/PWManager.Data/Persistance/ApplicationDbContext.cs +++ b/PWManager.Data/Persistance/ApplicationDbContext.cs @@ -12,7 +12,11 @@ internal class ApplicationDbContext : DbContext { public DbSet Settings { get; set; } public DbSet Users { get; set; } + + public string Path { get; private set; } + public ApplicationDbContext(string dbPath) : base(CreateOptionsBuilder(dbPath)) { + Path = dbPath; } private static DbContextOptions CreateOptionsBuilder(string path) { diff --git a/PWManager.Data/Repositories/SettingsRepository.cs b/PWManager.Data/Repositories/SettingsRepository.cs index 896eda9..6669dcf 100644 --- a/PWManager.Data/Repositories/SettingsRepository.cs +++ b/PWManager.Data/Repositories/SettingsRepository.cs @@ -36,16 +36,20 @@ public Settings GetSettings() { var userId = _environment.CurrentUser.Id; var settingsList = _dbContext.Settings.Where(e => e.UserId == userId).AsNoTracking().ToList(); var settingsModel = settingsList.Any() ? settingsList.First() : null; - if (settingsModel is null) { - settingsModel = new SettingsModel { - UserId = _environment.CurrentUser.Id, - Id = Guid.NewGuid().ToString(), - MainGroupIdentifier = _cryptService.Encrypt("main") - }; - _dbContext.Settings.Add(settingsModel); - _dbContext.SaveChanges(); + if (settingsModel is not null) { + return SettingsModelToEntity(settingsModel); } + settingsModel = new SettingsModel { + UserId = _environment.CurrentUser.Id, + Id = Guid.NewGuid().ToString(), + MainGroupIdentifier = _cryptService.Encrypt("main"), + AccountTimeOutDuration = TimeSpan.FromMinutes(5), + ClipboardTimeOutDuration = TimeSpan.FromMinutes(1), + }; + _dbContext.Settings.Add(settingsModel); + _dbContext.SaveChanges(); + return SettingsModelToEntity(settingsModel); }