From a475ba56480c9e4150df92d2c27ba629416db7a5 Mon Sep 17 00:00:00 2001 From: yanvoi Date: Sat, 25 May 2024 22:27:14 +0200 Subject: [PATCH] improve the app further --- HasswordManager.cabal | 3 +++ app/Main.hs | 41 ++++++++++++++++++++++++++++++++++++++--- package.yaml | 1 + src/Database.hs | 12 ++++++------ src/UserInterface.hs | 28 +++++++++++++++++----------- src/Utils.hs | 6 ++++++ 6 files changed, 71 insertions(+), 20 deletions(-) diff --git a/HasswordManager.cabal b/HasswordManager.cabal index e132257..299d087 100644 --- a/HasswordManager.cabal +++ b/HasswordManager.cabal @@ -46,6 +46,7 @@ library , sqlite-simple , text , utf8-string + , containers default-language: Haskell2010 executable HasswordManager-exe @@ -68,6 +69,7 @@ executable HasswordManager-exe , sqlite-simple , text , utf8-string + , containers default-language: Haskell2010 test-suite HasswordManager-test @@ -91,4 +93,5 @@ test-suite HasswordManager-test , sqlite-simple , text , utf8-string + , containers default-language: Haskell2010 diff --git a/app/Main.hs b/app/Main.hs index 8232de4..639c3b3 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -5,6 +5,7 @@ import Data.ByteString.UTF8 (fromString, toString) import Database.SQLite.Simple import System.Hclip import qualified Data.Text as T +import qualified Data.Map as Map import qualified UserInterface as Ui import qualified Database as Db @@ -113,10 +114,10 @@ application_loop conn mpass = do add_entry conn mpass application_loop conn mpass Ut.DeleteEntry -> do - return () + delete_entry conn application_loop conn mpass Ut.UpdateEntry -> do - return () + update_entry conn mpass application_loop conn mpass Ut.ChangeMasterPassword -> do return () @@ -127,10 +128,13 @@ application_loop conn mpass = do Ut.Exit -> do return () -list_all_entries :: Connection -> IO () +list_all_entries :: Connection -> IO (Map.Map Int (String, String)) list_all_entries conn = do + Ut.clear_screen entries <- Db.get_all_entries conn Ui.print_entries entries + let entries_map = Ut.map_entries entries + return entries_map add_entry :: Connection -> String -> IO () add_entry conn mpass = do @@ -149,3 +153,34 @@ add_entry conn mpass = do putStrLn "Please Enter the password:" password <- Ut.get_password Db.add_entry conn (T.pack service) (T.pack login) (T.pack (toString (Cr.encrypt' (fromString mpass) (fromString password)))) + +update_entry :: Connection -> String -> IO () +update_entry conn mpass = do + Ut.clear_screen + entries <- list_all_entries conn + chosen_entry <- Ui.choose_entry_to_update + let result = Map.lookup chosen_entry entries + case result of + Just (service, login) -> do + putStrLn "Please Enter the new password:" + password <- Ut.get_password + Db.update_entry conn (T.pack service) (T.pack login) (T.pack (toString (Cr.encrypt' (fromString mpass) (fromString password)))) + Nothing -> do + Ut.set_red + putStrLn "Invalid entry ID!!!" + Ut.reset_color + return () + +delete_entry :: Connection -> IO () +delete_entry conn = do + entries <- list_all_entries conn + chosen_entry <- Ui.choose_entry_to_delete + let result = Map.lookup chosen_entry entries + case result of + Just (service, login) -> do + Db.delete_entry conn (T.pack service) (T.pack login) + Nothing -> do + Ut.set_red + putStrLn "Invalid entry ID!!!" + Ut.reset_color + return () diff --git a/package.yaml b/package.yaml index 21230af..c3e9d65 100644 --- a/package.yaml +++ b/package.yaml @@ -20,6 +20,7 @@ extra-source-files: description: Please see the README on GitHub at dependencies: +- containers - text - sqlite-simple - hashable diff --git a/src/Database.hs b/src/Database.hs index a300917..530110e 100644 --- a/src/Database.hs +++ b/src/Database.hs @@ -60,9 +60,9 @@ add_entry :: Connection -> T.Text -> T.Text -> T.Text -> IO () add_entry conn service login password = do execute conn "INSERT INTO entries (entryService, entryLogin, entryPassword) VALUES (?,?,?)" (service, login, password) -update_entry :: Connection -> Int -> T.Text -> IO () -update_entry conn id new_password = do - execute conn "UPDATE entries SET entryPassword = ? WHERE entryId = ?" (new_password, id) +update_entry :: Connection -> T.Text -> T.Text -> T.Text -> IO () +update_entry conn service login new_password = do + execute conn "UPDATE entries SET entryPassword = ? WHERE entryService = ? AND entryLogin = ?" (new_password, service, login) get_entry :: Connection -> Int -> IO (Maybe Entry) get_entry conn id = do @@ -74,9 +74,9 @@ get_entry conn id = do get_all_entries :: Connection -> IO [Entry] get_all_entries conn = query_ conn "SELECT * from entries" -delete_entry :: Connection -> Int -> IO () -delete_entry conn id = do - execute conn "DELETE FROM entries WHERE entryId = ?" (Only id) +delete_entry :: Connection -> T.Text -> T.Text -> IO () +delete_entry conn service login = do + execute conn "DELETE FROM entries WHERE entryService = ? AND entryLogin = ?" (service, login) entry_already_exists :: Connection -> T.Text -> T.Text -> IO Bool entry_already_exists conn service login = do diff --git a/src/UserInterface.hs b/src/UserInterface.hs index a93f9b9..5e93503 100644 --- a/src/UserInterface.hs +++ b/src/UserInterface.hs @@ -1,18 +1,24 @@ -module UserInterface - ( print_entries - ) where +module UserInterface where import qualified Database as Db print_entries :: [Db.Entry] -> IO () print_entries entries = do putStrLn "Entries:" - mapM_ print_entry entries + mapM_ print_entry (zip [1..] entries) -print_entry :: Db.Entry -> IO () -print_entry entry = do - putStrLn $ "ID: " ++ show (Db.entryId entry) - putStrLn $ "Service: " ++ show (Db.entryService entry) - putStrLn $ "Login: " ++ show (Db.entryLogin entry) - putStrLn $ "Password: *****" - putStrLn "" +print_entry :: (Int, Db.Entry) -> IO () +print_entry (num, entry) = do + putStrLn $ show num ++ " " ++ show (Db.entryService entry) ++ " " ++ show (Db.entryLogin entry) ++ " " ++ "********" + +choose_entry_to_update :: IO Int +choose_entry_to_update = do + putStrLn "Please choose the entry ID to update:" + entry_id <- getLine + return (read entry_id :: Int) + +choose_entry_to_delete :: IO Int +choose_entry_to_delete = do + putStrLn "Please choose the entry ID to delete:" + entry_id <- getLine + return (read entry_id :: Int) diff --git a/src/Utils.hs b/src/Utils.hs index 225137a..1f758ab 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -3,6 +3,9 @@ module Utils where import System.Console.ANSI import System.IO import Control.Exception +import qualified Data.Map as Map + +import qualified Database as Db data MasterPasswordValidationCases = Empty | TooShort | DoNotMatch | NotValid | Valid String deriving (Show) @@ -39,3 +42,6 @@ get_password :: IO String get_password = do pass <- hide_pass getLine return pass + +map_entries :: [Db.Entry] -> Map.Map Int (String, String) +map_entries = Map.fromList . zip [1..] . map (\entry -> (show $ Db.entryService entry, show $ Db.entryLogin entry))