diff --git a/README.md b/README.md index 61674b8..ec4ebc9 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ You shouldn't! This is [free and open-source software](https://git.eversole.co/J ## Project Goals 1. Provide a minimal and clean interface for generating and sharing passwords. 2. Maintain a clean and organized codebase that can be extended to include more utilities than originally anticipated. -3. Aim for graceful degradation when JavaScript isn't enabled. ## Development & Support Please send me an [email](mailto:james@eversole.co) or join the [Support Chat](openpgp4fpr://FEB27223219E8DB3203225350462EA0901FE08F7#a=james%40eversole.co&g=Purr%20Support&x=RbVs8iQCVnf&i=-FuzUDK_RM1&s=KgeGtFFJtkq) in [DeltaChat](https://delta.chat)! diff --git a/src/Core/SQLite.hs b/src/Core/SQLite.hs index cdc5aff..081cf85 100644 --- a/src/Core/SQLite.hs +++ b/src/Core/SQLite.hs @@ -15,7 +15,10 @@ main db = do "CREATE TABLE IF NOT EXISTS pws\ \ (link TEXT PRIMARY KEY,\ \ secret TEXT,\ - \ date DATETIME DEFAULT CURRENT_TIMESTAMP)" + \ date DATETIME DEFAULT CURRENT_TIMESTAMP,\ + \ life INT,\ + \ views INT,\ + \ maxViews INT)" close conn dbPath :: PurrAction String diff --git a/src/Feature/Generation/wordlist.txt b/src/Feature/Generation/wordlist.txt index b1dafc2..4c058c8 100644 --- a/src/Feature/Generation/wordlist.txt +++ b/src/Feature/Generation/wordlist.txt @@ -175,7 +175,6 @@ bread break breast breath -breed brick bridge brief @@ -820,9 +819,7 @@ media medium meet melt -member memory -mental menu mere merely @@ -1035,7 +1032,6 @@ profit prompt proof proper -proud prove public pull diff --git a/src/Feature/Sharing/HTTP.hs b/src/Feature/Sharing/HTTP.hs index bba9711..0a9b96d 100644 --- a/src/Feature/Sharing/HTTP.hs +++ b/src/Feature/Sharing/HTTP.hs @@ -26,10 +26,12 @@ routes = do post "/pw" $ do reqId <- param "userLink" res <- findByLink reqId - html $ renderPw reqId (secret <$> res) + html $ renderPw reqId res post "/new" $ do reqSecret <- param "newSec" + reqDur <- param "newSecDuration" + reqViews <- param "newSecViews" link <- genLink - insertNewSecret reqSecret (T.pack link) + insertNewSecret reqSecret reqDur (T.pack link) reqViews html $ renderPw link (Just reqSecret) diff --git a/src/Feature/Sharing/SQLite.hs b/src/Feature/Sharing/SQLite.hs index 86869d8..fc7afb5 100644 --- a/src/Feature/Sharing/SQLite.hs +++ b/src/Feature/Sharing/SQLite.hs @@ -9,7 +9,6 @@ import Crypto.Simple.CBC (encrypt, decrypt) import Data.Maybe (listToMaybe) import Data.Time.Clock.POSIX (getPOSIXTime) import Database.SQLite.Simple -import Database.SQLite.Simple.FromRow import qualified Data.ByteString.Base64 as B64 import qualified Data.ByteString.Char8 as B @@ -17,28 +16,44 @@ import qualified Data.Text as T import qualified Data.Text.Encoding as ET import qualified Data.Text.Lazy as LT -findByLink :: String -> PurrAction (Maybe SecretEntry) +findByLink :: String -> PurrAction (Maybe T.Text) findByLink link = do - db <- dbPath - conn <- liftIO $ open db - res <- liftIO $ query conn "SELECT * from pws WHERE link = ?" (Only link) + db <- dbPath + key <- encKey + conn <- liftIO $ open db + res <- liftIO $ query conn "SELECT * from pws WHERE link = ?" (Only link) liftIO $ close conn - return $ listToMaybe res + readEncryptedSecret key res -insertNewSecret :: T.Text -> T.Text -> PurrAction () -insertNewSecret sec link = do +insertNewSecret :: T.Text -> Integer -> T.Text -> Integer -> PurrAction () +insertNewSecret sec life link maxViews = do db <- dbPath key <- encKey - encSec <- liftIO $ encrypt (B.pack key) (ET.encodeUtf8 sec) + encSec <- liftIO $ encryptSecret key sec conn <- liftIO $ open db time <- liftIO $ epochTime - liftIO $ execute conn - "INSERT INTO pws (link, secret, date) VALUES (?, ?, ?)" - (SecretEntry link (encodeSecret encSec) time) - liftIO $ close conn + liftIO $ execute conn + "INSERT INTO pws (link, secret, date, life, views, maxViews) VALUES (?, ?, ?, ?, ?, ?)" + (SecretEntry link (encodeSecret encSec) time life 0 maxViews) + liftIO $ close conn -epochTime :: IO Integer -epochTime = fmap round getPOSIXTime +readEncryptedSecret :: String -> [SecretEntry] -> PurrAction (Maybe T.Text) +readEncryptedSecret key sec = do + decKey <- liftIO + (sequence $ decryptSecret key <$> decodeSecret <$> listToMaybe sec) + return (ET.decodeLatin1 <$> decKey) encodeSecret :: B.ByteString -> T.Text encodeSecret b = ET.decodeUtf8 $ B64.encode b + +decodeSecret :: SecretEntry -> B.ByteString +decodeSecret s = B64.decodeLenient $ ET.encodeUtf8 (secret s) + +encryptSecret :: String -> T.Text -> IO B.ByteString +encryptSecret k s = encrypt (B.pack k) (ET.encodeUtf8 s) + +decryptSecret :: String -> B.ByteString -> IO B.ByteString +decryptSecret k b = decrypt (B.pack k) b + +epochTime :: IO Integer +epochTime = fmap round getPOSIXTime diff --git a/src/Feature/Sharing/Types.hs b/src/Feature/Sharing/Types.hs index c144cab..ae7db64 100644 --- a/src/Feature/Sharing/Types.hs +++ b/src/Feature/Sharing/Types.hs @@ -10,9 +10,12 @@ import Database.SQLite.Simple.FromRow import qualified Data.Text as T data SecretEntry = SecretEntry - { link :: T.Text - , secret :: T.Text - , date :: Integer + { link :: T.Text + , secret :: T.Text + , date :: Integer + , life :: Integer + , views :: Integer + , maxViews :: Integer } deriving (Show, Generic) instance FromRow SecretEntry where diff --git a/views/cassius/style.cassius b/views/cassius/style.cassius index f0d894c..a9a7f00 100644 --- a/views/cassius/style.cassius +++ b/views/cassius/style.cassius @@ -56,7 +56,7 @@ a outline: none color: #{colorOne} background: #{colorTwo} - margin: 0.5em 0 + margin: 0.5em 0 1em 0 border-style: none none solid none padding: 0.4em 0 box-sizing: border-box @@ -75,6 +75,33 @@ a color: #{colorThree} opacity: 0.5 +.numberInput + text-align: center + font-weight: 400 + font-size: 1em + width: 10% + outline: none + color: #{colorOne} + background: #{colorTwo} + margin: 0.5em 0 + border-style: none none solid none + padding: 0.4em 0 + box-sizing: border-box + -webkit-box-sizing: border-box + -moz-box-sizing: border-box + -webkit-transition: all 0.1s ease-in-out + -moz-transition: all 0.1s ease-in-out + -ms-transition: all 0.1s ease-in-out + -o-transition: all 0.1s ease-in-out + transition: all 0.1s ease-in-out + +.numberInput:focus + border-bottom: 0.2em solid #{colorThree}; + +.numberInput:focus::placeholder + color: #{colorThree} + opacity: 0.5 + .pwResult font-size: 1.5em color: #{colorFour} @@ -109,6 +136,9 @@ a width: 95% text-align: center + .numberInput + width: 25% + .title margin: 8% auto 2% auto font-size: 3em diff --git a/views/index.hamlet b/views/index.hamlet index 56f1a7d..4665cb3 100644 --- a/views/index.hamlet +++ b/views/index.hamlet @@ -36,14 +36,33 @@ $doctype 5

+
+ Valid for: +
+ days + views