purr

password generation and secret sharing
Log | Files | Refs | README | LICENSE

commit 1be99a44ffcb03b7d611a08dfc69b5d43d934510
parent 910859bce6bdb37e9724c61211f5d510a43bed2b
Author: James Eversole <james@eversole.co>
Date:   Fri,  5 Aug 2022 19:43:39 -0500

Add favicon. Significantly modify layout and presentation of site by including flexbox for main content. Remove logo from index. Code whitespace updates on Sharing-SQLite

Diffstat:
Msrc/Feature/Sharing/SQLite.hs | 21++++++++++-----------
Mviews/cassius/style.cassius | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mviews/gen.hamlet | 52+++++++++++++++++++++++++---------------------------
Mviews/index.hamlet | 66+++++++++++++++++++++++++++++++++---------------------------------
Aviews/public/favicon.ico | 0
Mviews/pw.hamlet | 6+++---
6 files changed, 135 insertions(+), 99 deletions(-)

diff --git a/src/Feature/Sharing/SQLite.hs b/src/Feature/Sharing/SQLite.hs @@ -49,23 +49,22 @@ readEncryptedSecret key sec = do if (delete) then return Nothing else return (ET.decodeLatin1 <$> decKey) - where - incViews :: [SecretEntry] -> String -> IO () - incViews [] _ = return () - incViews (sec : _) db = do - conn <- liftIO $ open db - liftIO $ execute conn - "UPDATE pws SET views = views + 1 WHERE link = ?" (Only (link sec)) - liftIO $ close conn + where + incViews :: [SecretEntry] -> String -> IO () + incViews [] _ = return () + incViews (sec : _) db = do + conn <- liftIO $ open db + liftIO $ execute conn + "UPDATE pws SET views = views + 1 WHERE link = ?" (Only (link sec)) + liftIO $ close conn -- Returns True if deletion occurs, informing the caller to not provide -- the successfully retrieved secret to the requestor. deleteExpiredSecret :: [SecretEntry] -> String -> IO Bool -deleteExpiredSecret [] _ = return False +deleteExpiredSecret [] _ = return False deleteExpiredSecret (sec : _) db = do time <- liftIO $ epochTime - if ((date sec) + ((life sec) * 86400) < time) || - (views sec >= maxViews sec) + if ((date sec) + ((life sec) * 86400) < time) || (views sec >= maxViews sec) then deleteSec sec db else return False where diff --git a/views/cassius/style.cassius b/views/cassius/style.cassius @@ -9,24 +9,40 @@ html color: #{colorOne} body - font-size: 20px - text-align: left + margin: 3% 10% 0 10% + font-size: 20px + text-align: left h2 font-family: monaco, Consolas, monospace text-transform: uppercase +h3 + margin: 0.25em 0 0.25em 0 + p margin: 0.4em 0 0.4em 0 a color: #{colorThree} +.title + margin: 0 auto 0 auto + font-size: 2em + color: #{colorThree} + +.titleLink + all: unset + cursor: pointer + +.title h1 + margin: 0.1em 0 0.1em 0 + .htmx-indicator display: none ::placeholder - color: #{colorOne} + color: #{colorOne} opacity: 1 .logo @@ -36,7 +52,10 @@ a text-align: center .content - margin: 0 15% 0 15% + display: flex + +.column + flex: 50% .emptyReq height: 1% @@ -49,10 +68,19 @@ a border-style: none text-decoration: none +.genButton + width: 40% + margin: 0 0 0.25em 0 + padding: 0.75em 1.75em + background-color: #{colorThree} + color: #{colorTwo} + border-style: none + text-decoration: none + .mainInput font-weight: 400 font-size: 1em - width: 50% + max-width: 50% outline: none color: #{colorOne} background: #{colorTwo} @@ -102,49 +130,60 @@ a color: #{colorThree} opacity: 0.5 -.pwResult - font-size: 1.5em +.genResult color: #{colorFour} -.pwUtils - width: 75% - -.generators - margin: 5% 0 0 0 +.pwResult + margin: 0 0 1em 0 + font-size: 1.5em + color: #{colorFour} .shareNew margin-bottom: 2em -.title - font-size: 2em - color: #{colorOne} - text-decoration: none +.requestNew + margin-top: 1em -.titleLink - all: unset - cursor: pointer +.requestedPw + max-width: 85% -.title h1 - margin: 0.1em 0 0.3em 0 +.resLink + font-size: 0.75em + +.validForm + margin: 0.5em 0 0 0 @media only screen and (max-width : 768px) body text-align: center - font-size: 16px + font-size: 16px + + .content + display: block + + .mainButton + width: 80% + + .genButton + width: 80% .mainInput - width: 95% + width: 95% + max-width: 100% text-align: center .numberInput width: 25% .title - margin: 8% auto 2% auto + margin: 8% auto 2% auto font-size: 3em .title h1 margin-bottom: 0 + + .requestedPw + max-width: 100% - .pwUtils + .shareUtils width: 100% diff --git a/views/gen.hamlet b/views/gen.hamlet @@ -1,43 +1,41 @@ -<div #generators .generators> +<div #generators .column> <h2>Generators - <p>Generated password: - <h3>#{genPw} - <button .mainButton + <h3 .genResult>#{genPw} + <button .genButton hx-get="/gen" hx-target="#generators" hx-swap="outerHTML" /> - Generate New Password + Generate New <br /> - <button .mainButton + <button .genButton hx-post="/new" hx-target="#requestedPw" hx-swap="outerHTML" hx-include="[id='generators']" *{hsGeneratedSharing} /> - Share Generated Password + Share Password <img class="htmx-indicator" src="/loading.svg" /> - <br /> - Valid for: - <br /> - - <input .numberInput - name="newSecDuration" - type="number" - min="1" - max="90" - value="20" - onkeyup="if (value < 1 || value > 90) { value = 0 }" - /> days - <input .numberInput - name="newSecViews" - type="number" - min="1" - max="60" - value="20" - onkeyup="if (value < 1 || value > 60) { value = 0 }" - /> views + <div .validForm> + Valid for: + <br /> + <input .numberInput + name="newSecDuration" + type="number" + min="1" + max="90" + value="20" + onkeyup="if (value < 1 || value > 90) { value = 0 }" + /> days + <input .numberInput + name="newSecViews" + type="number" + min="1" + max="60" + value="20" + onkeyup="if (value < 1 || value > 60) { value = 0 }" + /> views diff --git a/views/index.hamlet b/views/index.hamlet @@ -9,15 +9,13 @@ $doctype 5 <body> - <div #logo .logo> - <img src="/purrlogo.png"> + <div #title .title> + <h1> + <a #titleLink .titleLink href="/">Purr <div #content .content> - <div #title .title> - <h1> - <a #titleLink .titleLink href="/">Purr - <div #pwUtils .pwUtils> + <div #shareUtils .column> <h2>Sharing Tools $if (link == "/") <div #requestedPw .requestedPw> @@ -33,31 +31,32 @@ $doctype 5 Loading... <img class="htmx-indicator" src="/loading.svg" /> <div #shareNew .shareNew> + <h3>Share New Secret <p> <input .mainInput name="newSec" type="text" placeholder="Enter a Secret to Share" /> - <br /> - Valid for: - <br /> - <input .numberInput - name="newSecDuration" - type="number" - min="1" - max="90" - value="20" - onkeyup="if (value < 1 || value > 90) { value = 0 }" - /> days - <input .numberInput - name="newSecViews" - type="number" - min="1" - max="60" - value="20" - onkeyup="if (value < 1 || value > 60) { value = 0 }" - /> views + <div .validForm> + Valid for: + <br /> + <input .numberInput + name="newSecDuration" + type="number" + min="1" + max="90" + value="20" + onkeyup="if (value < 1 || value > 90) { value = 0 }" + /> days + <input .numberInput + name="newSecViews" + type="number" + min="1" + max="60" + value="20" + onkeyup="if (value < 1 || value > 60) { value = 0 }" + /> views <button .mainButton hx-post="/new" hx-target="#requestedPw" @@ -68,6 +67,7 @@ $doctype 5 <img class="htmx-indicator" src="/loading.svg" /> <div #requestNew .requestNew> + <h3>Lookup <p> <input .mainInput name="userLink" @@ -83,11 +83,11 @@ $doctype 5 Get Secret <img class="htmx-indicator" src="/loading.svg" /> - <div #generators .generators> - <h2>Generators - <button .mainButton - hx-get="/gen" - hx-target="#generators" - hx-swap="outerHTML" - /> - Generate Password + <div #generators .column> + <h2>Generators + <button .mainButton + hx-get="/gen" + hx-target="#generators" + hx-swap="outerHTML" + /> + Load Generators diff --git a/views/public/favicon.ico b/views/public/favicon.ico Binary files differ. diff --git a/views/pw.hamlet b/views/pw.hamlet @@ -1,7 +1,7 @@ <div #requestedPw .requestedPw> $maybe pw <- password - <p>Here's the secret found at <a href="/pw/#{link}">/pw/#{link}</a>: + <p .resLink>Here's the secret found at <a href="/pw/#{link}">/pw/#{link}</a>: <h3 .pwResult>#{pw} - <hr /> + <hr /> $nothing - <h3>No secret found at <a href="/pw/#{link}">/pw/#{link}</a> + <h3 .pwResult>No secret found at <a href="/pw/#{link}">/pw/#{link}</a>