Bugfix on UI elements when no secret is found. Add copy secret button on successful retrieval. Include deployment information and updated example files.
This commit is contained in:
parent
c3a3374e45
commit
ee8686bc83
43
Purr.cabal
43
Purr.cabal
@ -68,7 +68,7 @@ library
|
|||||||
, wai-middleware-static >=0.5
|
, wai-middleware-static >=0.5
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
||||||
executable Purr-exe
|
executable Purr-musl
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
other-modules:
|
other-modules:
|
||||||
Paths_Purr
|
Paths_Purr
|
||||||
@ -82,46 +82,7 @@ executable Purr-exe
|
|||||||
GeneralizedNewtypeDeriving
|
GeneralizedNewtypeDeriving
|
||||||
OverloadedStrings
|
OverloadedStrings
|
||||||
ScopedTypeVariables
|
ScopedTypeVariables
|
||||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N -static -optl-static -optl-pthread -fPIC
|
||||||
build-depends:
|
|
||||||
Purr
|
|
||||||
, base >=4.7
|
|
||||||
, base64-bytestring >=1.2.0.0
|
|
||||||
, blaze-html >=0.9.1.0
|
|
||||||
, bytestring >=0.10.12.1
|
|
||||||
, containers >=0.6.4.1
|
|
||||||
, crypto-simple >=0.1.0.0
|
|
||||||
, dhall >=1.40 && <1.41.2
|
|
||||||
, http-types >=0.12.3
|
|
||||||
, iso8601-time >=0.1.5
|
|
||||||
, mtl >=2.2.2
|
|
||||||
, random >=1.2
|
|
||||||
, scotty ==0.12
|
|
||||||
, shakespeare >=2.0.20
|
|
||||||
, split >=0.2.3.4
|
|
||||||
, sqlite-simple >=0.4.18.0
|
|
||||||
, text >=1.2.5.0
|
|
||||||
, time >=1.9
|
|
||||||
, wai-extra >=3.1.12.1
|
|
||||||
, wai-middleware-static >=0.5
|
|
||||||
default-language: Haskell2010
|
|
||||||
|
|
||||||
test-suite Purr-test
|
|
||||||
type: exitcode-stdio-1.0
|
|
||||||
main-is: Spec.hs
|
|
||||||
other-modules:
|
|
||||||
Paths_Purr
|
|
||||||
hs-source-dirs:
|
|
||||||
test
|
|
||||||
default-extensions:
|
|
||||||
ConstraintKinds
|
|
||||||
DeriveGeneric
|
|
||||||
FlexibleContexts
|
|
||||||
FlexibleInstances
|
|
||||||
GeneralizedNewtypeDeriving
|
|
||||||
OverloadedStrings
|
|
||||||
ScopedTypeVariables
|
|
||||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
|
||||||
build-depends:
|
build-depends:
|
||||||
Purr
|
Purr
|
||||||
, base >=4.7
|
, base >=4.7
|
||||||
|
30
README
30
README
@ -4,6 +4,12 @@ purr
|
|||||||
https://purr.eversole.co
|
https://purr.eversole.co
|
||||||
a work-in-progress web application offering customizable password generation and time-limited sharing of secrets.
|
a work-in-progress web application offering customizable password generation and time-limited sharing of secrets.
|
||||||
|
|
||||||
|
TECH STACK
|
||||||
|
|
||||||
|
- Haskell and Scotty backend
|
||||||
|
- HTMX frontend
|
||||||
|
- SQLite database
|
||||||
|
|
||||||
GOALS
|
GOALS
|
||||||
|
|
||||||
- Generate sufficiently memorable but secure passwords for use with accounts that don't offer better authentication methods.
|
- Generate sufficiently memorable but secure passwords for use with accounts that don't offer better authentication methods.
|
||||||
@ -14,16 +20,28 @@ GOALS
|
|||||||
|
|
||||||
WHY TRUST YOU?
|
WHY TRUST YOU?
|
||||||
|
|
||||||
You shouldn't. This is free and open-source software which you can run on your own hardware. Instructions for deployment are coming SOON™.
|
You shouldn't. This is free and open-source software which you can run on your own hardware.
|
||||||
|
|
||||||
TECH STACK
|
DEPLOYMENT
|
||||||
|
|
||||||
- Haskell and Scotty backend
|
purr is intended to run in a docker container.
|
||||||
- HTMX frontend
|
This repo's Stack project is configured to use a musl-based docker container for builds.
|
||||||
- SQLite database
|
Assuming your working directory is inside of this repository:
|
||||||
|
|
||||||
|
1. Copy "examples/config.dhall" to ./config.dhall - configure this file appropriately.
|
||||||
|
- Use `openssl rand -hex 10` to generate an encryption key for "dbKey"
|
||||||
|
2. Copy "examples/Dockerfile" to ./Dockerfile
|
||||||
|
3. If using default database file location, run: `mkdir ./data; touch ./data/Purr.sqlite`
|
||||||
|
4. Run `chmod +x build-docker`
|
||||||
|
5. Run `./build-docker $IMAGE_NAME` to complete the initial Stack build and create the container
|
||||||
|
6. Orchestrate the container as desired
|
||||||
|
- docker run -d -v "$(pwd -P)/data/Purr.sqlite:/app/data/Purr.sqlite" \
|
||||||
|
-v "$(pwd -P)/config.dhall:/app/config.dhall" \
|
||||||
|
-p 5195:3000 purr
|
||||||
|
|- An example docker-stack.yml is provided: `docker stack deploy -c docker-stack.yml purr`
|
||||||
|
|
||||||
DEVELOPMENT & SUPPORT
|
DEVELOPMENT & SUPPORT
|
||||||
|
|
||||||
Please send me an email for support.
|
Please send me an email for support or to provide patches.
|
||||||
|
|
||||||
Copyright 2022 James Eversole (james@eversole.co)
|
Copyright 2022 James Eversole (james@eversole.co)
|
||||||
|
12
build-docker
Executable file
12
build-docker
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
# Date: 12/27/2022
|
||||||
|
# Author: James Eversole
|
||||||
|
# ISC License
|
||||||
|
# This script completes a stack build and then builds a docker image
|
||||||
|
# containing Purr. The image name is the first argument to the script.
|
||||||
|
|
||||||
|
IMAGE_NAME=${1:-"purr"}
|
||||||
|
|
||||||
|
stack build --copy-bins
|
||||||
|
docker build . -t $IMAGE_NAME
|
@ -1,11 +1,10 @@
|
|||||||
FROM haskell:9.0.2
|
FROM alpine:3.17.0
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ADD . /app
|
ADD ./views /app/views
|
||||||
|
ADD ./src /app/src
|
||||||
RUN stack setup
|
ADD ./bin/Purr-musl /app/Purr-musl
|
||||||
RUN stack build --copy-bins --local-bin-path ./
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
CMD ./Purr-exe
|
ENTRYPOINT ["/app/Purr-musl"]
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
version: '3.1'
|
version: '3.1'
|
||||||
|
|
||||||
# Default Docker Stack/Compose configuration for Purr.
|
|
||||||
# You will need to change all instances of "REPLACEME" with the appropriate details.
|
|
||||||
# Additionally, you may want to update the host port definitions for each service.
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
purr:
|
purr:
|
||||||
image: purr
|
image: purr
|
||||||
@ -13,6 +9,7 @@ services:
|
|||||||
- webnet
|
- webnet
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/Purr.sqlite:/app/data/Purr.sqlite
|
- ./data/Purr.sqlite:/app/data/Purr.sqlite
|
||||||
|
- ./config.dhall:/app/config.dhall
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
webnet:
|
webnet:
|
||||||
|
30
package.yaml
30
package.yaml
@ -52,23 +52,31 @@ library:
|
|||||||
source-dirs: src
|
source-dirs: src
|
||||||
|
|
||||||
executables:
|
executables:
|
||||||
Purr-exe:
|
Purr-musl:
|
||||||
main: Main.hs
|
main: Main.hs
|
||||||
source-dirs: app
|
source-dirs: app
|
||||||
ghc-options:
|
ghc-options:
|
||||||
- -threaded
|
- -threaded
|
||||||
- -rtsopts
|
- -rtsopts
|
||||||
- -with-rtsopts=-N
|
- -with-rtsopts=-N
|
||||||
|
- -static
|
||||||
|
- -optl-static
|
||||||
|
- -optl-pthread
|
||||||
|
- -fPIC
|
||||||
dependencies:
|
dependencies:
|
||||||
- Purr
|
- Purr
|
||||||
|
|
||||||
tests:
|
#tests:
|
||||||
Purr-test:
|
# Purr-test:
|
||||||
main: Spec.hs
|
# main: Spec.hs
|
||||||
source-dirs: test
|
# source-dirs: test
|
||||||
ghc-options:
|
# ghc-options:
|
||||||
- -threaded
|
# - -threaded
|
||||||
- -rtsopts
|
# - -rtsopts
|
||||||
- -with-rtsopts=-N
|
# - -with-rtsopts=-N
|
||||||
dependencies:
|
# - -static
|
||||||
- Purr
|
# - -optl-static
|
||||||
|
# - -optl-pthread
|
||||||
|
# - -fPIC
|
||||||
|
# dependencies:
|
||||||
|
# - Purr
|
||||||
|
50
stack.yaml
50
stack.yaml
@ -1,54 +1,23 @@
|
|||||||
# This file was automatically generated by 'stack init'
|
# This file was automatically generated by 'stack init'
|
||||||
#
|
#
|
||||||
# Some commonly used options have been documented as comments in this file.
|
|
||||||
# For advanced use and comprehensive documentation of the format, please see:
|
|
||||||
# https://docs.haskellstack.org/en/stable/yaml_configuration/
|
|
||||||
|
|
||||||
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
|
|
||||||
# A snapshot resolver dictates the compiler version and the set of packages
|
|
||||||
# to be used for project dependencies. For example:
|
|
||||||
#
|
|
||||||
# resolver: lts-3.5
|
|
||||||
# resolver: nightly-2015-09-21
|
|
||||||
# resolver: ghc-7.10.2
|
|
||||||
#
|
|
||||||
# The location of a snapshot can be provided as a file or url. Stack assumes
|
|
||||||
# a snapshot provided as a file might change, whereas a url resource does not.
|
|
||||||
#
|
|
||||||
# resolver: ./custom-snapshot.yaml
|
|
||||||
# resolver: https://example.com/snapshots/2018-01-01.yaml
|
|
||||||
resolver:
|
resolver:
|
||||||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/13.yaml
|
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/13.yaml
|
||||||
|
|
||||||
# User packages to be built.
|
# User packages to be built.
|
||||||
# Various formats can be used as shown in the example below.
|
|
||||||
#
|
|
||||||
# packages:
|
|
||||||
# - some-directory
|
|
||||||
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
|
|
||||||
# subdirs:
|
|
||||||
# - auto-update
|
|
||||||
# - wai
|
|
||||||
packages:
|
packages:
|
||||||
- .
|
- .
|
||||||
# Dependency packages to be pulled from upstream that are not in the resolver.
|
|
||||||
# These entries can reference officially published versions as well as
|
|
||||||
# forks / in-progress versions pinned to a git hash. For example:
|
|
||||||
#
|
#
|
||||||
extra-deps:
|
extra-deps:
|
||||||
- crypto-simple-0.1.0.0@sha256:5c0e1e04a814d903743d7543245951a91a46817230fdf478fadca57116805fc1,1502
|
- crypto-simple-0.1.0.0@sha256:5c0e1e04a814d903743d7543245951a91a46817230fdf478fadca57116805fc1,1502
|
||||||
|
|
||||||
|
docker:
|
||||||
|
enable: true
|
||||||
|
image: "utdemir/ghc-musl:v24-ghc902"
|
||||||
|
|
||||||
|
local-bin-path:
|
||||||
|
./bin
|
||||||
#ghc-options:
|
#ghc-options:
|
||||||
|
|
||||||
# Override default flag values for local packages and extra-deps
|
|
||||||
# flags: {}
|
|
||||||
|
|
||||||
# Extra package databases containing global packages
|
|
||||||
# extra-package-dbs: []
|
|
||||||
|
|
||||||
# Control whether we use the GHC we find on the path
|
|
||||||
# system-ghc: true
|
|
||||||
#
|
|
||||||
# Require a specific version of stack, using version ranges
|
# Require a specific version of stack, using version ranges
|
||||||
# require-stack-version: -any # Default
|
# require-stack-version: -any # Default
|
||||||
# require-stack-version: ">=2.7"
|
# require-stack-version: ">=2.7"
|
||||||
@ -56,10 +25,3 @@ extra-deps:
|
|||||||
# Override the architecture used by stack, especially useful on Windows
|
# Override the architecture used by stack, especially useful on Windows
|
||||||
# arch: i386
|
# arch: i386
|
||||||
# arch: x86_64
|
# arch: x86_64
|
||||||
#
|
|
||||||
# Extra directories used by stack for building
|
|
||||||
# extra-include-dirs: [/path/to/dir]
|
|
||||||
# extra-lib-dirs: [/path/to/dir]
|
|
||||||
#
|
|
||||||
# Allow a newer minor version of GHC than the snapshot specifies
|
|
||||||
# compiler-check: newer-minor
|
|
||||||
|
@ -172,9 +172,17 @@ input[type=number]
|
|||||||
box-shadow: 8px 8px 12px #ccc
|
box-shadow: 8px 8px 12px #ccc
|
||||||
|
|
||||||
.pwResult
|
.pwResult
|
||||||
|
margin: 0.25em 0 0.75em 0
|
||||||
font-size: 1.5em
|
font-size: 1.5em
|
||||||
color: #f0f6f0
|
color: #f0f6f0
|
||||||
|
|
||||||
|
.pwResultCopy
|
||||||
|
width: 1px
|
||||||
|
overflow: hidden
|
||||||
|
display: inline-block
|
||||||
|
height: 1px
|
||||||
|
color: rgba(255,255,255,0)
|
||||||
|
|
||||||
.shareNew
|
.shareNew
|
||||||
padding: 0.5em 0.5em 0.5em 1.5em
|
padding: 0.5em 0.5em 0.5em 1.5em
|
||||||
background-color: #{colorTwo}
|
background-color: #{colorTwo}
|
||||||
|
@ -5,6 +5,7 @@ $doctype 5
|
|||||||
<title>purr
|
<title>purr
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous">
|
<script src="https://unpkg.com/htmx.org@1.7.0" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous">
|
||||||
|
<script src="/copySecret.js" integrity="sha384-jB3mpB1WyAo8ToD7oWm/LjXBnEImM/8GB7tjExykwuNErwdPHa9mihHlVJRtV+bt">
|
||||||
<link rel="stylesheet" href="/style.css">
|
<link rel="stylesheet" href="/style.css">
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
10
views/public/copySecret.js
Normal file
10
views/public/copySecret.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
function copySecret(secret) {
|
||||||
|
var tempText = document.createElement('input');
|
||||||
|
tempText.style = 'position: absolute; left: -1000px; top: -1000px';
|
||||||
|
tempText.value = secret;
|
||||||
|
document.body.appendChild(tempText);
|
||||||
|
tempText.select();
|
||||||
|
document.execCommand('copy');
|
||||||
|
document.body.removeChild(tempText);
|
||||||
|
document.getElementById('copyButton').innerHTML = "- secret copied -";
|
||||||
|
}
|
@ -2,5 +2,7 @@
|
|||||||
$maybe pw <- password
|
$maybe pw <- password
|
||||||
<p .resLink>secret found at <a href="/pw/#{link}">/pw/#{link}</a>:
|
<p .resLink>secret found at <a href="/pw/#{link}">/pw/#{link}</a>:
|
||||||
<h3 .pwResult>#{pw}
|
<h3 .pwResult>#{pw}
|
||||||
|
<button #copyButton .mainButton onclick="copySecret('#{pw}')">copy secret</button>
|
||||||
$nothing
|
$nothing
|
||||||
<h3 .pwResult>no secret found at <a href="/pw/#{link}">/pw/#{link}</a>
|
<p .resLink>no secret found at
|
||||||
|
<br /><a href="/pw/#{link}">/pw/#{link}</a>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user