Listing & adding entries now works
This commit is contained in:
parent
d34a957780
commit
7d4c37debe
@ -41,6 +41,7 @@ library
|
||||
, ansi-terminal
|
||||
, base >=4.7 && <5
|
||||
, bytestring
|
||||
, cipher-aes
|
||||
, hashable
|
||||
, sqlite-simple
|
||||
, text
|
||||
@ -62,6 +63,7 @@ executable HasswordManager-exe
|
||||
, ansi-terminal
|
||||
, base >=4.7 && <5
|
||||
, bytestring
|
||||
, cipher-aes
|
||||
, hashable
|
||||
, sqlite-simple
|
||||
, text
|
||||
@ -84,6 +86,7 @@ test-suite HasswordManager-test
|
||||
, ansi-terminal
|
||||
, base >=4.7 && <5
|
||||
, bytestring
|
||||
, cipher-aes
|
||||
, hashable
|
||||
, sqlite-simple
|
||||
, text
|
||||
|
95
app/Main.hs
95
app/Main.hs
@ -1,9 +1,10 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Main (main) where
|
||||
|
||||
import Data.ByteString.UTF8 (fromString)
|
||||
import Data.ByteString.UTF8 (fromString, toString)
|
||||
import Database.SQLite.Simple
|
||||
import System.Hclip
|
||||
import qualified Data.Text as T
|
||||
|
||||
import qualified UserInterface as Ui
|
||||
import qualified Database as Db
|
||||
@ -13,18 +14,19 @@ import qualified Utils as Ut
|
||||
main :: IO ()
|
||||
main = do
|
||||
conn <- Db.init_connection
|
||||
|
||||
Ut.clear_screen
|
||||
putStrLn "Welcome to Hassword Manager!!!"
|
||||
welcome_screen conn
|
||||
|
||||
setup_application conn
|
||||
mpass <- open_hassword_book conn
|
||||
putStrLn mpass
|
||||
setClipboard mpass
|
||||
-- application_loop conn
|
||||
application_loop conn mpass
|
||||
|
||||
Db.close_connection conn
|
||||
|
||||
welcome_screen :: Connection -> IO ()
|
||||
welcome_screen conn = do
|
||||
|
||||
setup_application :: Connection -> IO ()
|
||||
setup_application conn = do
|
||||
first <- Db.is_it_first_app_usage conn
|
||||
if first
|
||||
then do
|
||||
@ -66,8 +68,8 @@ open_hassword_book :: Connection -> IO (String)
|
||||
open_hassword_book conn = do
|
||||
putStrLn "Please Enter your MASTER PASSWORD:"
|
||||
mpass <- Ut.get_password
|
||||
res <- Db.check_if_mpass_valid conn (Cr.hash' $ fromString mpass)
|
||||
if res
|
||||
mpass_valid <- Db.check_if_mpass_valid conn (Cr.hash' $ fromString mpass)
|
||||
if mpass_valid
|
||||
then
|
||||
return mpass
|
||||
else do
|
||||
@ -76,7 +78,74 @@ open_hassword_book conn = do
|
||||
Ut.reset_color
|
||||
open_hassword_book conn
|
||||
|
||||
application_loop :: Connection -> IO ()
|
||||
application_loop conn = do
|
||||
putStrLn "What would you like to do?"
|
||||
application_loop conn
|
||||
get_action_choice :: IO (Ut.ActionChoice)
|
||||
get_action_choice = do
|
||||
putStrLn "\nWhat would you like to do?"
|
||||
putStrLn "1. List all entries"
|
||||
putStrLn "2. Copy entry password"
|
||||
putStrLn "3. Add a new entry"
|
||||
putStrLn "4. Delete an entry"
|
||||
putStrLn "5. Update an entry"
|
||||
putStrLn "6. Change Master Password"
|
||||
putStrLn "7. Close the application"
|
||||
choice <- getLine
|
||||
case choice of
|
||||
"1" -> return Ut.ListAllEntries
|
||||
"2" -> return Ut.CopyEntryPassword
|
||||
"3" -> return Ut.AddNewEntry
|
||||
"4" -> return Ut.DeleteEntry
|
||||
"5" -> return Ut.UpdateEntry
|
||||
"6" -> return Ut.ChangeMasterPassword
|
||||
"7" -> return Ut.Exit
|
||||
_ -> return Ut.InvalidAction
|
||||
|
||||
application_loop :: Connection -> String -> IO ()
|
||||
application_loop conn mpass = do
|
||||
choice <- get_action_choice
|
||||
case choice of
|
||||
Ut.ListAllEntries -> do
|
||||
list_all_entries conn
|
||||
application_loop conn mpass
|
||||
Ut.CopyEntryPassword -> do
|
||||
return ()
|
||||
application_loop conn mpass
|
||||
Ut.AddNewEntry -> do
|
||||
add_entry conn mpass
|
||||
application_loop conn mpass
|
||||
Ut.DeleteEntry -> do
|
||||
return ()
|
||||
application_loop conn mpass
|
||||
Ut.UpdateEntry -> do
|
||||
return ()
|
||||
application_loop conn mpass
|
||||
Ut.ChangeMasterPassword -> do
|
||||
return ()
|
||||
application_loop conn mpass
|
||||
Ut.InvalidAction -> do
|
||||
putStrLn "Invalid choice!!!"
|
||||
application_loop conn mpass
|
||||
Ut.Exit -> do
|
||||
return ()
|
||||
|
||||
list_all_entries :: Connection -> IO ()
|
||||
list_all_entries conn = do
|
||||
entries <- Db.get_all_entries conn
|
||||
Ui.print_entries entries
|
||||
|
||||
add_entry :: Connection -> String -> IO ()
|
||||
add_entry conn mpass = do
|
||||
putStrLn "Please Enter the service name:"
|
||||
service <- getLine
|
||||
putStrLn "Please Enter the login:"
|
||||
login <- getLine
|
||||
entry_exists <- Db.entry_already_exists conn (T.pack service) (T.pack login)
|
||||
if entry_exists
|
||||
then do
|
||||
Ut.set_red
|
||||
putStrLn "Entry already exists!!!"
|
||||
Ut.reset_color
|
||||
return ()
|
||||
else 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))))
|
||||
|
@ -27,6 +27,7 @@ dependencies:
|
||||
- utf8-string
|
||||
- ansi-terminal
|
||||
- Hclip
|
||||
- cipher-aes
|
||||
- base >= 4.7 && < 5
|
||||
|
||||
ghc-options:
|
||||
|
@ -1,15 +1,28 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Crypto (
|
||||
-- encode,
|
||||
-- decode,
|
||||
encrypt',
|
||||
decrypt',
|
||||
hash'
|
||||
) where
|
||||
|
||||
import Data.ByteString (ByteString)
|
||||
import Data.Hashable
|
||||
import Crypto.Cipher.AES
|
||||
|
||||
pepper :: ByteString
|
||||
pepper = "pepper"
|
||||
|
||||
hash' :: ByteString -> Int
|
||||
hash' = hashWithSalt 0 . mappend pepper
|
||||
|
||||
encrypt' :: ByteString -> ByteString -> ByteString
|
||||
encrypt' key plain_text = plain_text
|
||||
|
||||
decrypt' :: ByteString -> ByteString -> ByteString
|
||||
decrypt' key cypher_text = cypher_text
|
||||
|
||||
-- encrypt' :: ByteString -> ByteString -> ByteString
|
||||
-- encrypt' = encryptECB . initAES
|
||||
|
||||
-- decrypt' :: ByteString -> ByteString -> ByteString
|
||||
-- decrypt' = decryptECB . initAES
|
||||
|
@ -1,29 +1,22 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Database (
|
||||
Entry(..),
|
||||
init_connection,
|
||||
close_connection,
|
||||
check_if_mpass_valid,
|
||||
insert_new_mpass,
|
||||
is_it_first_app_usage
|
||||
) where
|
||||
module Database where
|
||||
|
||||
import Control.Applicative
|
||||
import qualified Data.Text as T
|
||||
import Database.SQLite.Simple
|
||||
|
||||
data Entry = Entry { entryId :: Int, entryLogin :: T.Text, entryPassword :: T.Text } deriving (Show)
|
||||
data Entry = Entry { entryId :: Int, entryService :: T.Text, entryLogin :: T.Text, entryPassword :: T.Text } deriving (Show)
|
||||
data Mpass = Mpass { mpassId :: Int, hash :: Int } deriving (Show)
|
||||
|
||||
|
||||
instance FromRow Entry where
|
||||
fromRow = Entry <$> field <*> field <*> field
|
||||
fromRow = Entry <$> field <*> field <*> field <*> field
|
||||
|
||||
instance FromRow Mpass where
|
||||
fromRow = Mpass <$> field <*> field
|
||||
|
||||
instance ToRow Entry where
|
||||
toRow (Entry id_ login password) = toRow (id_, login, password)
|
||||
toRow (Entry id_ service login password) = toRow (id_, service, login, password)
|
||||
|
||||
instance ToRow Mpass where
|
||||
toRow (Mpass id_ hash) = toRow (id_, hash)
|
||||
@ -41,9 +34,9 @@ close_connection conn = close conn
|
||||
|
||||
create_db :: Connection -> IO ()
|
||||
create_db conn = do
|
||||
execute_ conn "CREATE TABLE IF NOT EXISTS hasswords (entryId INTEGER PRIMARY KEY, entryLogin TEXT, entryPassword TEXT)"
|
||||
execute_ conn "CREATE TABLE IF NOT EXISTS mpass (mpassId INTEGER PRIMARY KEY, hash INTEGER)"
|
||||
-- execute conn "INSERT INTO hassword (entryId, entryLogin, entryPassword) VALUES (?,?,?)" (Entry 1 "admin" "admin")
|
||||
execute_ conn "CREATE TABLE IF NOT EXISTS entries (entryId INTEGER PRIMARY KEY AUTOINCREMENT, entryService TEXT, entryLogin TEXT, entryPassword TEXT)"
|
||||
execute_ conn "CREATE TABLE IF NOT EXISTS mpass (mpassId INTEGER PRIMARY KEY AUTOINCREMENT, hash INTEGER)"
|
||||
-- execute conn "INSERT INTO entries (entryId, entryLogin, entryPassword) VALUES (?,?,?)" (Entry 1 "admin" "admin")
|
||||
-- rowId <- lastInsertRowId conn
|
||||
-- r <- query_ conn "SELECT * from hassword" :: IO [Entry]
|
||||
-- mapM_ print r
|
||||
@ -56,9 +49,36 @@ is_it_first_app_usage conn = do
|
||||
insert_new_mpass :: Connection -> Int -> IO ()
|
||||
insert_new_mpass conn hash = do
|
||||
execute_ conn "DELETE FROM mpass"
|
||||
execute conn "INSERT INTO mpass (mpassId, hash) VALUES (?,?)" (Mpass 1 hash)
|
||||
execute conn "INSERT INTO mpass (hash) VALUES (?)" (Only hash)
|
||||
|
||||
check_if_mpass_valid :: Connection -> Int -> IO Bool
|
||||
check_if_mpass_valid conn hash = do
|
||||
r <- query conn "SELECT * from mpass WHERE hash = ?" (Only hash) :: IO [Mpass]
|
||||
return $ length r == 1
|
||||
|
||||
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)
|
||||
|
||||
get_entry :: Connection -> Int -> IO (Maybe Entry)
|
||||
get_entry conn id = do
|
||||
r <- query conn "SELECT * from entries WHERE entryId = ?" (Only id) :: IO [Entry]
|
||||
return $ case r of
|
||||
[] -> Nothing
|
||||
[entry] -> Just entry
|
||||
|
||||
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)
|
||||
|
||||
entry_already_exists :: Connection -> T.Text -> T.Text -> IO Bool
|
||||
entry_already_exists conn service login = do
|
||||
r <- query conn "SELECT * from entries WHERE entryService = ? AND entryLogin = ?" (service, login) :: IO [Entry]
|
||||
return $ length r == 1
|
||||
|
@ -1,6 +1,18 @@
|
||||
module UserInterface
|
||||
( someFunc
|
||||
( print_entries
|
||||
) where
|
||||
|
||||
someFunc :: IO ()
|
||||
someFunc = putStrLn "someFunc"
|
||||
import qualified Database as Db
|
||||
|
||||
print_entries :: [Db.Entry] -> IO ()
|
||||
print_entries entries = do
|
||||
putStrLn "Entries:"
|
||||
mapM_ print_entry 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 ""
|
||||
|
@ -6,6 +6,8 @@ import Control.Exception
|
||||
|
||||
data MasterPasswordValidationCases = Empty | TooShort | DoNotMatch | NotValid | Valid String deriving (Show)
|
||||
|
||||
data ActionChoice = ListAllEntries | CopyEntryPassword | AddNewEntry | DeleteEntry | UpdateEntry | ChangeMasterPassword | Exit | InvalidAction deriving (Show)
|
||||
|
||||
validate_password :: String -> String -> MasterPasswordValidationCases
|
||||
validate_password p1 p2
|
||||
| p1 /= p2 = DoNotMatch
|
||||
|
Loading…
Reference in New Issue
Block a user