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:
James Eversole 2022-12-27 12:25:14 -06:00
parent c3a3374e45
commit ee8686bc83
11 changed files with 91 additions and 113 deletions

View File

@ -68,7 +68,7 @@ library
, wai-middleware-static >=0.5
default-language: Haskell2010
executable Purr-exe
executable Purr-musl
main-is: Main.hs
other-modules:
Paths_Purr
@ -82,46 +82,7 @@ executable Purr-exe
GeneralizedNewtypeDeriving
OverloadedStrings
ScopedTypeVariables
ghc-options: -threaded -rtsopts -with-rtsopts=-N
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
ghc-options: -threaded -rtsopts -with-rtsopts=-N -static -optl-static -optl-pthread -fPIC
build-depends:
Purr
, base >=4.7

30
README
View File

@ -4,6 +4,12 @@ purr
https://purr.eversole.co
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
- 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?
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
- HTMX frontend
- SQLite database
purr is intended to run in a docker container.
This repo's Stack project is configured to use a musl-based docker container for builds.
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
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)

12
build-docker Executable file
View 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

View File

@ -1,11 +1,10 @@
FROM haskell:9.0.2
FROM alpine:3.17.0
WORKDIR /app
ADD . /app
RUN stack setup
RUN stack build --copy-bins --local-bin-path ./
ADD ./views /app/views
ADD ./src /app/src
ADD ./bin/Purr-musl /app/Purr-musl
EXPOSE 3000
CMD ./Purr-exe
ENTRYPOINT ["/app/Purr-musl"]

View File

@ -1,9 +1,5 @@
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:
purr:
image: purr
@ -13,6 +9,7 @@ services:
- webnet
volumes:
- ./data/Purr.sqlite:/app/data/Purr.sqlite
- ./config.dhall:/app/config.dhall
networks:
webnet:

View File

@ -52,23 +52,31 @@ library:
source-dirs: src
executables:
Purr-exe:
Purr-musl:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
- -static
- -optl-static
- -optl-pthread
- -fPIC
dependencies:
- Purr
tests:
Purr-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- Purr
#tests:
# Purr-test:
# main: Spec.hs
# source-dirs: test
# ghc-options:
# - -threaded
# - -rtsopts
# - -with-rtsopts=-N
# - -static
# - -optl-static
# - -optl-pthread
# - -fPIC
# dependencies:
# - Purr

View File

@ -1,54 +1,23 @@
# 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:
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/13.yaml
# 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:
- .
# 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:
- crypto-simple-0.1.0.0@sha256:5c0e1e04a814d903743d7543245951a91a46817230fdf478fadca57116805fc1,1502
docker:
enable: true
image: "utdemir/ghc-musl:v24-ghc902"
local-bin-path:
./bin
#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-stack-version: -any # Default
# require-stack-version: ">=2.7"
@ -56,10 +25,3 @@ extra-deps:
# Override the architecture used by stack, especially useful on Windows
# arch: i386
# 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

View File

@ -172,9 +172,17 @@ input[type=number]
box-shadow: 8px 8px 12px #ccc
.pwResult
margin: 0.25em 0 0.75em 0
font-size: 1.5em
color: #f0f6f0
.pwResultCopy
width: 1px
overflow: hidden
display: inline-block
height: 1px
color: rgba(255,255,255,0)
.shareNew
padding: 0.5em 0.5em 0.5em 1.5em
background-color: #{colorTwo}

View File

@ -5,6 +5,7 @@ $doctype 5
<title>purr
<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="/copySecret.js" integrity="sha384-jB3mpB1WyAo8ToD7oWm/LjXBnEImM/8GB7tjExykwuNErwdPHa9mihHlVJRtV+bt">
<link rel="stylesheet" href="/style.css">
<body>

View 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 -";
}

View File

@ -2,5 +2,7 @@
$maybe pw <- password
<p .resLink>secret found at <a href="/pw/#{link}">/pw/#{link}</a>:
<h3 .pwResult>#{pw}
<button #copyButton .mainButton onclick="copySecret('#{pw}')">copy secret</button>
$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>