Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
5dff12ea70 | |||
e332dc63e8 | |||
a18e9bcc88 | |||
4b43edf54a | |||
e3aa2dd5ff | |||
98a03c25e6 | |||
7f618e7e45 | |||
84a7be4549 | |||
b2bad5f64c | |||
41f55c0920 | |||
edbf8a8ecf | |||
4852804581 | |||
22b1c35b3e | |||
d1e9ffd89b | |||
9c675ba48c | |||
ef3d3d5bde | |||
7e835af3f2 | |||
f153102978 | |||
5944c784ba | |||
2aa186450a | |||
70b53106ea | |||
b958189b0c | |||
acd488aab0 | |||
5378b7a820 | |||
1bb5d3ecb0 | |||
0d79e9c85e | |||
70382a63ed | |||
b3886cc6fc | |||
cfe525f274 | |||
96e8ec4b67 | |||
7a3397f978 | |||
dc212d7441 | |||
6e04594b4d | |||
b6834aa829 | |||
093a6c5c2b | |||
407d220552 | |||
bf8593080b | |||
d63d529d2b | |||
c4f545d1e8 | |||
b94588ead4 | |||
96657b89d2 | |||
d05b090252 | |||
d262a37db6 | |||
a66e8033df | |||
95ba8d1fed | |||
f93be44449 | |||
f73aa1bcf8 | |||
6e25bb697f | |||
5a105a7b29 | |||
c8dfeaec12 | |||
bf2c95bfb6 | |||
4aef5a1b04 | |||
7520b6b1da |
@@ -1 +1,2 @@
|
||||
target
|
||||
target
|
||||
node_modules
|
1
.gitattributes
vendored
@@ -1,2 +1 @@
|
||||
*.afdesign filter=lfs diff=lfs merge=lfs -text
|
||||
*.svg filter=lfs diff=lfs merge=lfs -text
|
||||
|
12
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: cupcakearmy
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
2
.github/workflows/docker.yml
vendored
@@ -22,6 +22,7 @@ jobs:
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
@@ -31,6 +32,7 @@ jobs:
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
# platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
- name: Image digest
|
||||
|
18
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
text:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Install
|
||||
run: |
|
||||
docker-compose build
|
||||
npm ci
|
||||
- name: Test
|
||||
run: npm run test:run
|
81
CHANGELOG.md
@@ -5,6 +5,87 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.1.0] - 2021-05-16
|
||||
|
||||
### Security
|
||||
|
||||
- Using hash `#` instead of path
|
||||
|
||||
## [1.0.11] - 2021-05-08
|
||||
|
||||
### Added
|
||||
|
||||
- loading text
|
||||
- description for created notes about availability
|
||||
|
||||
### Changed
|
||||
|
||||
- iterations from 100 to 100k
|
||||
|
||||
### Fixed
|
||||
|
||||
- time based view bug
|
||||
|
||||
## [1.0.10] - 2021-05-08
|
||||
|
||||
### Fixed
|
||||
|
||||
- API endpoint was not reachable
|
||||
|
||||
## [1.0.9] - 2021-05-07
|
||||
|
||||
## Changed
|
||||
|
||||
- Removed a dependency
|
||||
|
||||
## [1.0.8] - 2021-05-05
|
||||
|
||||
### Added
|
||||
|
||||
- Manual theme override option
|
||||
|
||||
### Fixed
|
||||
|
||||
- Removed Arm builds for now
|
||||
- iOS style bugs
|
||||
|
||||
## [1.0.7] - 2021-05-04
|
||||
|
||||
### Added
|
||||
|
||||
- Arm images
|
||||
|
||||
## [1.0.6] - 2021-05-04
|
||||
|
||||
### Added
|
||||
|
||||
- Always use encryption with random passwords included links
|
||||
|
||||
## [1.0.5] - 2021-05-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Typos
|
||||
|
||||
## [1.0.4] - 2021-05-02
|
||||
|
||||
### Added
|
||||
|
||||
- From scratch docker image
|
||||
|
||||
## [1.0.3] - 2021-05-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- Higher default text area
|
||||
- Mobile touchups
|
||||
|
||||
## [1.0.2] - 2021-05-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- SVG Icons
|
||||
|
||||
## [1.0.1] - 2021-05-02
|
||||
|
||||
### Added
|
||||
|
@@ -1,7 +1,7 @@
|
||||
FROM node:16-alpine as CLIENT
|
||||
|
||||
WORKDIR /tmp
|
||||
COPY ./client .
|
||||
COPY ./client ./
|
||||
|
||||
RUN npm ci
|
||||
RUN npm run build
|
||||
@@ -10,12 +10,12 @@ FROM rust:1.51-alpine as RUST
|
||||
|
||||
WORKDIR /tmp
|
||||
RUN apk add libc-dev openssl-dev alpine-sdk
|
||||
COPY ./Cargo* .
|
||||
COPY ./Cargo* ./
|
||||
COPY ./src ./src
|
||||
|
||||
RUN cargo build --release
|
||||
|
||||
FROM alpine
|
||||
FROM scratch
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=RUST /tmp/target/release/cryptgeon .
|
||||
@@ -23,4 +23,6 @@ COPY --from=CLIENT /tmp/build ./client/build
|
||||
|
||||
ENV MEMCACHE=memcached:11211
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
ENTRYPOINT [ "/app/cryptgeon" ]
|
19
README.md
@@ -1,10 +1,14 @@
|
||||
<p align="center">
|
||||
<img src="./design/github.svg">
|
||||
<img src="./design/Github.png">
|
||||
</p>
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## About?
|
||||
|
||||
_cryptgeon_ is an secure, open source sharing note service inspired by [_PrivNote_](https://privnote.com)
|
||||
_cryptgeon_ is a secure, open source sharing note service inspired by [_PrivNote_](https://privnote.com)
|
||||
|
||||
## Demo
|
||||
|
||||
@@ -12,9 +16,10 @@ Check out the demo and see for yourself https://cryptgeon.nicco.io.
|
||||
|
||||
## Features
|
||||
|
||||
- view and time constrains
|
||||
- server cannot decrypt contents due to client side encryption
|
||||
- view and time constraints
|
||||
- in memory, no persistence
|
||||
- in browser encryption → server cannot decrypt contents
|
||||
- obligatory dark mode support
|
||||
|
||||
## How does it work?
|
||||
|
||||
@@ -22,11 +27,11 @@ each note has a 512bit generated <i>id</i> that is used to retrieve the note. da
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||

|
||||
|
||||
## Deployment
|
||||
|
||||
Docker is the easiest way.
|
||||
Docker is the easiest way. There is the [official image here](https://hub.docker.com/r/cupcakearmy/cryptgeon).
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
@@ -40,6 +45,8 @@ services:
|
||||
|
||||
app:
|
||||
image: cupcakearmy/cryptgeon:latest
|
||||
depends_on:
|
||||
- memcache
|
||||
ports:
|
||||
- 80:5000
|
||||
```
|
||||
|
1
client/.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/.svelte
|
||||
/.svelte-kit
|
||||
/build
|
||||
/functions
|
||||
|
147
client/package-lock.json
generated
@@ -1,15 +1,11 @@
|
||||
{
|
||||
"name": "cryptgeon",
|
||||
"version": "0.0.1",
|
||||
"name": "client",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "cryptgeon",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@fontsource/fira-mono": "^4.2.2",
|
||||
"axios": "^0.21.1",
|
||||
"copy-to-clipboard": "^3.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -25,8 +21,7 @@
|
||||
"node_modules/@fontsource/fira-mono": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/fira-mono/-/fira-mono-4.2.2.tgz",
|
||||
"integrity": "sha512-t2WRThg+eLkQNQCtPG2sCCq40lz3xeb7nsL7P8l4+wfSRbdLQXAY5IebMftI2YEZR4MRRhdgrg0p5fi/2yXypA==",
|
||||
"license": "MIT"
|
||||
"integrity": "sha512-t2WRThg+eLkQNQCtPG2sCCq40lz3xeb7nsL7P8l4+wfSRbdLQXAY5IebMftI2YEZR4MRRhdgrg0p5fi/2yXypA=="
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "4.1.0",
|
||||
@@ -45,15 +40,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-static": {
|
||||
"version": "1.0.0-next.7",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-1.0.0-next.7.tgz",
|
||||
"integrity": "sha512-kIghJ2PoAPW6x8r5f+q8JTeB0EmBtl0Jl7wDB2HfsBCcdtNmdRqVgMcpfhSstpz1VGVDOuaU8rGlHL+XBAMMKQ==",
|
||||
"version": "1.0.0-next.8",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-1.0.0-next.8.tgz",
|
||||
"integrity": "sha512-goE3v68y+pn+fayPDJCCQ7W1QQpSMl86pZS9RvjuG64+TEI/PGsZwYR1RRgvwIiDqu33wBEHj+3ZYHEpJO/gwg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
"version": "1.0.0-next.94",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.94.tgz",
|
||||
"integrity": "sha512-2HkW+LqijRAHjKzKur3uLNblV8Ea1Vsju7LPVNYfMarJAk/mJrLTTm+29Qw6VSgaQsezlKfrgv3i+ZwgxZM1BQ==",
|
||||
"version": "1.0.0-next.101",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.101.tgz",
|
||||
"integrity": "sha512-SwUImLhFmyaDsq7LKRJXPJRIOPa06SWENG7heko5FTRRLMpI/UDFcijjT2ln0Fp+AL9XfSbTHO8QrOflCMbfiQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.9",
|
||||
@@ -67,7 +62,7 @@
|
||||
"node": ">= 12.17.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"svelte": "^3.32.1",
|
||||
"svelte": "^3.34.0",
|
||||
"vite": "^2.2.3"
|
||||
}
|
||||
},
|
||||
@@ -95,9 +90,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "15.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz",
|
||||
"integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==",
|
||||
"version": "15.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz",
|
||||
"integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/pug": {
|
||||
@@ -130,14 +125,6 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
@@ -237,25 +224,6 @@
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.0.tgz",
|
||||
"integrity": "sha512-0vRwd7RKQBTt+mgu87mtYeofLFZpTas2S9zY+jIeuLJMNvudIgF52nr19q40HOwH5RrhWIPuj9puybzSJiRrVg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
@@ -370,9 +338,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.2.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
|
||||
"integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==",
|
||||
"version": "8.2.14",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz",
|
||||
"integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"colorette": "^1.2.2",
|
||||
@@ -416,9 +384,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.46.0.tgz",
|
||||
"integrity": "sha512-qPGoUBNl+Z8uNu0z7pD3WPTABWRbcOwIrO/5ccDJzmrtzn0LVf6Lj91+L5CcWhXl6iWf23FQ6m8Jkl2CmN1O7Q==",
|
||||
"version": "2.47.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.47.0.tgz",
|
||||
"integrity": "sha512-rqBjgq9hQfW0vRmz+0S062ORRNJXvwRpzxhFXORvar/maZqY6za3rgQ/p1Glg+j1hnc1GtYyQCPiAei95uTElg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
@@ -488,9 +456,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte": {
|
||||
"version": "3.38.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.1.tgz",
|
||||
"integrity": "sha512-N3XLAyfzqrFxwRLevBeW7Dke9ZlHRVGSIed5abo4Drvj+zvd2OyWpFa1x4nQUc8Lnvt4Kcn8/5le1peRDybNqg==",
|
||||
"version": "3.38.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.2.tgz",
|
||||
"integrity": "sha512-q5Dq0/QHh4BLJyEVWGe7Cej5NWs040LWjMbicBGZ+3qpFWJ1YObRmUDZKbbovddLC9WW7THTj3kYbTOFmU9fbg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
@@ -506,9 +474,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-preprocess": {
|
||||
"version": "4.7.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.7.2.tgz",
|
||||
"integrity": "sha512-EToG+08rEsA33btv+C5g2qnRArwpTc5AoU0QBB3ZEkYagxAb2yPNsy0qsmtvbJOTBMy6o3oyijDdl3DMpMvpEg==",
|
||||
"version": "4.7.3",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.7.3.tgz",
|
||||
"integrity": "sha512-Zx1/xLeGOIBlZMGPRCaXtlMe4ZA0faato5Dc3CosEqwu75MIEPuOstdkH6cy+RYTUYynoxzNaDxkPX4DbrPwRA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
@@ -594,9 +562,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.2.3.tgz",
|
||||
"integrity": "sha512-PtjyBL4GtACM+uT5q5hi2+AlMBbb6YI2b2bam6QI8ZdZt4FezseF0yZHQx0G+b3po9jIJ/GS5N9gc5Yq9Rue7g==",
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.2.4.tgz",
|
||||
"integrity": "sha512-vnIwSNci+phFMp6krhy+FbYzKL0R67Sdt9mVZ96S27AewrApSJjTqncJcalk8sf60BgcbW4+1C6DFIWkxquO9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.9.3",
|
||||
@@ -632,15 +600,15 @@
|
||||
}
|
||||
},
|
||||
"@sveltejs/adapter-static": {
|
||||
"version": "1.0.0-next.7",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-1.0.0-next.7.tgz",
|
||||
"integrity": "sha512-kIghJ2PoAPW6x8r5f+q8JTeB0EmBtl0Jl7wDB2HfsBCcdtNmdRqVgMcpfhSstpz1VGVDOuaU8rGlHL+XBAMMKQ==",
|
||||
"version": "1.0.0-next.8",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-1.0.0-next.8.tgz",
|
||||
"integrity": "sha512-goE3v68y+pn+fayPDJCCQ7W1QQpSMl86pZS9RvjuG64+TEI/PGsZwYR1RRgvwIiDqu33wBEHj+3ZYHEpJO/gwg==",
|
||||
"dev": true
|
||||
},
|
||||
"@sveltejs/kit": {
|
||||
"version": "1.0.0-next.94",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.94.tgz",
|
||||
"integrity": "sha512-2HkW+LqijRAHjKzKur3uLNblV8Ea1Vsju7LPVNYfMarJAk/mJrLTTm+29Qw6VSgaQsezlKfrgv3i+ZwgxZM1BQ==",
|
||||
"version": "1.0.0-next.101",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.101.tgz",
|
||||
"integrity": "sha512-SwUImLhFmyaDsq7LKRJXPJRIOPa06SWENG7heko5FTRRLMpI/UDFcijjT2ln0Fp+AL9XfSbTHO8QrOflCMbfiQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.9",
|
||||
@@ -665,9 +633,9 @@
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "15.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz",
|
||||
"integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==",
|
||||
"version": "15.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.2.tgz",
|
||||
"integrity": "sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/pug": {
|
||||
@@ -694,14 +662,6 @@
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.21.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
|
||||
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
@@ -774,11 +734,6 @@
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.0.tgz",
|
||||
"integrity": "sha512-0vRwd7RKQBTt+mgu87mtYeofLFZpTas2S9zY+jIeuLJMNvudIgF52nr19q40HOwH5RrhWIPuj9puybzSJiRrVg=="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
@@ -859,9 +814,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.2.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz",
|
||||
"integrity": "sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==",
|
||||
"version": "8.2.14",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz",
|
||||
"integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colorette": "^1.2.2",
|
||||
@@ -894,9 +849,9 @@
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.46.0.tgz",
|
||||
"integrity": "sha512-qPGoUBNl+Z8uNu0z7pD3WPTABWRbcOwIrO/5ccDJzmrtzn0LVf6Lj91+L5CcWhXl6iWf23FQ6m8Jkl2CmN1O7Q==",
|
||||
"version": "2.47.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.47.0.tgz",
|
||||
"integrity": "sha512-rqBjgq9hQfW0vRmz+0S062ORRNJXvwRpzxhFXORvar/maZqY6za3rgQ/p1Glg+j1hnc1GtYyQCPiAei95uTElg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.3.1"
|
||||
@@ -942,9 +897,9 @@
|
||||
}
|
||||
},
|
||||
"svelte": {
|
||||
"version": "3.38.1",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.1.tgz",
|
||||
"integrity": "sha512-N3XLAyfzqrFxwRLevBeW7Dke9ZlHRVGSIed5abo4Drvj+zvd2OyWpFa1x4nQUc8Lnvt4Kcn8/5le1peRDybNqg==",
|
||||
"version": "3.38.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.38.2.tgz",
|
||||
"integrity": "sha512-q5Dq0/QHh4BLJyEVWGe7Cej5NWs040LWjMbicBGZ+3qpFWJ1YObRmUDZKbbovddLC9WW7THTj3kYbTOFmU9fbg==",
|
||||
"dev": true
|
||||
},
|
||||
"svelte-hmr": {
|
||||
@@ -955,9 +910,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"svelte-preprocess": {
|
||||
"version": "4.7.2",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.7.2.tgz",
|
||||
"integrity": "sha512-EToG+08rEsA33btv+C5g2qnRArwpTc5AoU0QBB3ZEkYagxAb2yPNsy0qsmtvbJOTBMy6o3oyijDdl3DMpMvpEg==",
|
||||
"version": "4.7.3",
|
||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.7.3.tgz",
|
||||
"integrity": "sha512-Zx1/xLeGOIBlZMGPRCaXtlMe4ZA0faato5Dc3CosEqwu75MIEPuOstdkH6cy+RYTUYynoxzNaDxkPX4DbrPwRA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/pug": "^2.0.4",
|
||||
@@ -984,9 +939,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"vite": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.2.3.tgz",
|
||||
"integrity": "sha512-PtjyBL4GtACM+uT5q5hi2+AlMBbb6YI2b2bam6QI8ZdZt4FezseF0yZHQx0G+b3po9jIJ/GS5N9gc5Yq9Rue7g==",
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.2.4.tgz",
|
||||
"integrity": "sha512-vnIwSNci+phFMp6krhy+FbYzKL0R67Sdt9mVZ96S27AewrApSJjTqncJcalk8sf60BgcbW4+1C6DFIWkxquO9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esbuild": "^0.9.3",
|
||||
|
@@ -18,7 +18,6 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@fontsource/fira-mono": "^4.2.2",
|
||||
"axios": "^0.21.1",
|
||||
"copy-to-clipboard": "^3.3.1"
|
||||
}
|
||||
}
|
||||
|
@@ -7,29 +7,46 @@
|
||||
:root {
|
||||
font-family: 'Fira Mono', monospace;
|
||||
|
||||
--ui-bg-0: #fefefe;
|
||||
--ui-bg-0-85: #fefefed9;
|
||||
--ui-bg-1: #eee;
|
||||
--ui-bg-2: #e2e2e2;
|
||||
--ui-text-0: #111;
|
||||
--ui-text-1: #222;
|
||||
--ui-bg-0: #111;
|
||||
--ui-bg-0-85: #111111d9;
|
||||
--ui-bg-1: #333;
|
||||
--ui-bg-2: #444;
|
||||
--ui-text-0: #fefefe;
|
||||
--ui-text-1: #eee;
|
||||
--ui-clr-primary: hsl(186, 65%, 55%);
|
||||
--ui-clr-error: hsl(357, 77%, 51%);
|
||||
|
||||
--ui-anim: all 150ms ease;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--ui-bg-0: #111;
|
||||
--ui-bg-0-85: #111111d9;
|
||||
--ui-bg-1: #222;
|
||||
--ui-bg-2: #282828;
|
||||
--ui-text-0: #fefefe;
|
||||
--ui-text-1: #eee;
|
||||
--ui-bg-0: #fefefe;
|
||||
--ui-bg-0-85: #fefefed9;
|
||||
--ui-bg-1: #eee;
|
||||
--ui-bg-2: #e2e2e2;
|
||||
--ui-text-0: #111;
|
||||
--ui-text-1: #333;
|
||||
}
|
||||
}
|
||||
|
||||
:root[theme='dark'] {
|
||||
--ui-bg-0: #111 !important;
|
||||
--ui-bg-0-85: #111111d9 !important;
|
||||
--ui-bg-1: #333 !important;
|
||||
--ui-bg-2: #444 !important;
|
||||
--ui-text-0: #fefefe !important;
|
||||
--ui-text-1: #eee !important;
|
||||
}
|
||||
:root[theme='light'] {
|
||||
--ui-bg-0: #fefefe !important;
|
||||
--ui-bg-0-85: #fefefed9 !important;
|
||||
--ui-bg-1: #eee !important;
|
||||
--ui-bg-2: #e2e2e2 !important;
|
||||
--ui-text-0: #111 !important;
|
||||
--ui-text-1: #333 !important;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: var(--ui-clr-error);
|
||||
}
|
||||
@@ -61,6 +78,8 @@ input,
|
||||
textarea,
|
||||
button {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
border-radius: 0;
|
||||
transition: var(--ui-anim);
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
|
@@ -1,37 +1,50 @@
|
||||
import axios from 'axios'
|
||||
import { dev } from '$app/env'
|
||||
|
||||
const base = axios.create({ baseURL: dev ? 'http://localhost:5000' : undefined })
|
||||
|
||||
export type Note = {
|
||||
contents: string
|
||||
password: boolean
|
||||
views?: number
|
||||
expiration?: number
|
||||
}
|
||||
export type NoteInfo = Pick<Note, 'password'>
|
||||
export type NoteInfo = {}
|
||||
export type NotePublic = Pick<Note, 'contents'>
|
||||
|
||||
type CallOptions = {
|
||||
url: string
|
||||
method: string
|
||||
body?: any
|
||||
}
|
||||
const base = dev ? 'http://localhost:5000/api/' : '/api/'
|
||||
async function call(options: CallOptions) {
|
||||
return fetch(base + options.url, {
|
||||
method: options.method,
|
||||
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}).then((r) => r.json())
|
||||
}
|
||||
|
||||
export async function create(note: Note) {
|
||||
const { data } = await base({
|
||||
url: '/api/notes',
|
||||
const data = await call({
|
||||
url: 'notes',
|
||||
method: 'post',
|
||||
data: note,
|
||||
body: note,
|
||||
})
|
||||
return data as { id: string }
|
||||
}
|
||||
|
||||
export async function get(id: string) {
|
||||
const { data } = await base({
|
||||
url: `/api/notes/${id}`,
|
||||
const data = await call({
|
||||
url: `notes/${id}`,
|
||||
method: 'delete',
|
||||
})
|
||||
return data as NotePublic
|
||||
}
|
||||
|
||||
export async function info(id: string) {
|
||||
const { data } = await base({
|
||||
url: `/api/notes/${id}`,
|
||||
const data = await call({
|
||||
url: `notes/${id}`,
|
||||
method: 'get',
|
||||
})
|
||||
return data as NoteInfo
|
||||
|
@@ -36,7 +36,7 @@ export function getKeyFromString(password: string) {
|
||||
}
|
||||
|
||||
export async function getDerivedForKey(key: CryptoKey, salt: ArrayBuffer) {
|
||||
const iterations = 1_000
|
||||
const iterations = 100_000
|
||||
return window.crypto.subtle.deriveKey(
|
||||
{
|
||||
name: 'PBKDF2',
|
||||
|
@@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
export let icon: string
|
||||
export let icon: string = ''
|
||||
export let href: string = ''
|
||||
|
||||
$: src = `/icons/${icon}.svg`
|
||||
$: src = href || `/icons/${icon}.svg`
|
||||
|
||||
let html = null
|
||||
|
||||
|
@@ -13,15 +13,20 @@
|
||||
<style>
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 8rem;
|
||||
min-height: calc(100vh - 30rem);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 2px solid var(--ui-bg-1);
|
||||
resize: vertical;
|
||||
outline: none;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 30rem) {
|
||||
textarea {
|
||||
min-height: calc(100vh - 25rem);
|
||||
}
|
||||
}
|
||||
|
||||
textarea:hover,
|
||||
textarea:focus {
|
||||
border-color: var(--ui-clr-primary);
|
||||
|
62
client/src/lib/ui/ThemeToggle.svelte
Normal file
@@ -0,0 +1,62 @@
|
||||
<script lang="ts" context="module">
|
||||
import { writable } from 'svelte/store'
|
||||
|
||||
export enum Theme {
|
||||
Dark = 'dark',
|
||||
Light = 'light',
|
||||
Auto = 'auto',
|
||||
}
|
||||
|
||||
const NextTheme = {
|
||||
[Theme.Auto]: Theme.Light,
|
||||
[Theme.Light]: Theme.Dark,
|
||||
[Theme.Dark]: Theme.Auto,
|
||||
}
|
||||
|
||||
function init(): Theme {
|
||||
if (typeof window !== 'undefined') {
|
||||
const saved = window.localStorage.getItem('theme') as Theme
|
||||
if (Object.values(Theme).includes(saved)) return saved
|
||||
}
|
||||
return Theme.Auto
|
||||
}
|
||||
|
||||
export const theme = writable<Theme>(init())
|
||||
|
||||
theme.subscribe((theme) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem('theme', theme)
|
||||
const html = window.document.getElementsByTagName('html')[0]
|
||||
html.setAttribute('theme', theme)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import Icon from '$lib/ui/Icon.svelte'
|
||||
|
||||
function change() {
|
||||
theme.update((current) => NextTheme[current])
|
||||
}
|
||||
</script>
|
||||
|
||||
<div on:click={change}>
|
||||
<Icon class="icon" icon="contrast-sharp" />
|
||||
{$theme}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div :global(.icon) {
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Note } from '$lib/api'
|
||||
import { create } from '$lib/api'
|
||||
import { getKeyFromString, encrypt } from '$lib/crypto'
|
||||
import { getKeyFromString, encrypt, Hex, getRandomBytes } from '$lib/crypto'
|
||||
|
||||
import Button from '$lib/ui/Button.svelte'
|
||||
import Switch from '$lib/ui/Switch.svelte'
|
||||
@@ -10,11 +10,9 @@
|
||||
|
||||
let note: Note = {
|
||||
contents: '',
|
||||
password: false,
|
||||
views: 1,
|
||||
expiration: 60,
|
||||
}
|
||||
let password: string = ''
|
||||
let result: { password: string; id: string } | null = null
|
||||
let advanced = false
|
||||
let type = false
|
||||
@@ -37,25 +35,23 @@
|
||||
try {
|
||||
error = null
|
||||
loading = true
|
||||
const password = Hex.encode(getRandomBytes(32))
|
||||
const key = await getKeyFromString(password)
|
||||
const data: Note = {
|
||||
contents: note.contents,
|
||||
password: !!password,
|
||||
contents: await encrypt(note.contents, key),
|
||||
}
|
||||
// @ts-ignore
|
||||
if (type) data.expiration = parseInt(note.expiration)
|
||||
// @ts-ignore
|
||||
else data.views = parseInt(note.views)
|
||||
if (data.password) {
|
||||
const key = await getKeyFromString(password)
|
||||
data.contents = await encrypt(data.contents, key)
|
||||
}
|
||||
|
||||
const response = await create(data)
|
||||
result = {
|
||||
password: password,
|
||||
id: response.id,
|
||||
}
|
||||
} catch {
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
error = 'could not create note.'
|
||||
} finally {
|
||||
loading = false
|
||||
@@ -68,28 +64,52 @@
|
||||
</script>
|
||||
|
||||
{#if result}
|
||||
{#if result.password}
|
||||
<TextInput type="password" readonly value={result.password} copy />
|
||||
<br />
|
||||
{/if}
|
||||
<TextInput type="text" readonly value="{window.location.origin}/note/{result.id}" copy />
|
||||
<TextInput
|
||||
type="text"
|
||||
readonly
|
||||
label="share link"
|
||||
value="{window.location.origin}/note/{result.id}#{result.password}"
|
||||
copy
|
||||
data-testid="note-share-link"
|
||||
/>
|
||||
<br />
|
||||
<Button on:click={reset}>new</Button>
|
||||
<p>
|
||||
<b>availability:</b>
|
||||
<br />
|
||||
the note is not guaranteed to be stored as everything is kept in ram, if it fills up the oldest notes
|
||||
will be removed.
|
||||
<br />
|
||||
(you probably will be fine, just be warned.)
|
||||
</p>
|
||||
<br />
|
||||
<Button on:click={reset}>new note</Button>
|
||||
{:else}
|
||||
<form on:submit|preventDefault={submit}>
|
||||
<fieldset disabled={loading}>
|
||||
<TextArea label="note" bind:value={note.contents} placeholder="..." />
|
||||
<TextArea
|
||||
label="note"
|
||||
bind:value={note.contents}
|
||||
placeholder="..."
|
||||
data-testid="input-note"
|
||||
/>
|
||||
|
||||
<div class="bottom">
|
||||
<Switch label="advanced" bind:value={advanced} />
|
||||
<Button type="submit">create</Button>
|
||||
<Button type="submit" data-testid="button-create">create</Button>
|
||||
</div>
|
||||
|
||||
{#if error}
|
||||
<div class="error-text">{error}</div>
|
||||
{/if}
|
||||
|
||||
<p><br />{message}</p>
|
||||
<p>
|
||||
<br />
|
||||
{#if loading}
|
||||
loading...
|
||||
{:else}
|
||||
{message}
|
||||
{/if}
|
||||
</p>
|
||||
|
||||
<div class="advanced" class:hidden={!advanced}>
|
||||
<br />
|
||||
@@ -112,15 +132,6 @@
|
||||
max={360}
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<TextInput
|
||||
type="password"
|
||||
label="password"
|
||||
placeholder="optional"
|
||||
bind:value={password}
|
||||
copy
|
||||
random
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
37
client/src/lib/views/Footer.svelte
Normal file
@@ -0,0 +1,37 @@
|
||||
<script lang="ts">
|
||||
import Icon from '$lib/ui/Icon.svelte'
|
||||
import ThemeToggle from '$lib/ui/ThemeToggle.svelte'
|
||||
</script>
|
||||
|
||||
<footer>
|
||||
<ThemeToggle />
|
||||
<nav>
|
||||
<a href="/">/home</a>
|
||||
<a href="/about">/about</a>
|
||||
<a href="https://github.com/cupcakearmy/cryptgeon" target="_blank" rel="noopener">/code</a>
|
||||
</nav>
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
background-color: var(--ui-bg-0-85);
|
||||
}
|
||||
|
||||
a {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
107
client/src/lib/views/Header.svelte
Normal file
@@ -0,0 +1,107 @@
|
||||
<header>
|
||||
<a href="/">
|
||||
<svg
|
||||
width="100%"
|
||||
height="100%"
|
||||
viewBox="0 0 450 200"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:space="preserve"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
|
||||
><g id="Logo"
|
||||
><clipPath id="_clip1"><rect x="6.336" y="3.225" width="193.55" height="193.55" /></clipPath
|
||||
><g clip-path="url(#_clip1)"
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M173.425,43.296c-2.087,-0 -3.78,1.693 -3.78,3.78c-0,2.087 1.693,3.78 3.78,3.78c2.087,0 3.78,-1.693 3.78,-3.78c0,-2.087 -1.693,-3.78 -3.78,-3.78Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M103.112,134.023c-2.087,-0 -3.781,1.693 -3.781,3.78c0,2.087 1.694,3.78 3.781,3.78c2.086,0 3.78,-1.693 3.78,-3.78c-0,-2.087 -1.694,-3.78 -3.78,-3.78Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M156.036,96.22c-2.088,-0 -3.781,1.692 -3.781,3.78c0,18.76 -15.262,34.023 -34.022,34.023c-2.088,-0 -3.781,1.692 -3.781,3.78c0,2.088 1.693,3.78 3.781,3.78c22.929,0 41.583,-18.654 41.583,-41.583c-0,-2.088 -1.693,-3.78 -3.78,-3.78Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M199.488,60.507l-9.515,-19.026c-4.102,-8.207 -12.35,-13.306 -21.527,-13.306c-7.479,-0 -14.626,3.547 -19.154,9.498l-10.679,12.016c-2.846,-4.047 -7.021,-7.049 -11.83,-8.421l-19.102,-5.459c-14.623,-4.178 -28.92,-15.441 -39.227,-30.901c-0.924,-1.386 -2.646,-2.003 -4.241,-1.521c-1.594,0.483 -2.684,1.953 -2.684,3.618l-0,20.372c-0,9.468 1.417,18.804 4.219,27.813c-2.936,0.73 -5.896,1.34 -8.843,1.816c-5.772,0.936 -11.653,1.411 -17.48,1.411l-29.308,-0c-1.374,-0 -2.64,0.746 -3.307,1.948c-0.666,1.202 -0.627,2.671 0.101,3.836l22.637,36.219c9.672,15.473 26.329,25.183 44.578,25.983l-36.36,41.158c-5.602,5.728 -3.655,15.315 3.746,18.396l20.017,9.887c0.089,0.044 0.179,0.084 0.271,0.121c5.79,2.313 12.389,-0.496 14.726,-6.279l13.969,-32.982l27.738,0c31.966,0 58.972,-25.967 58.972,-56.704l0,-22.682c0,-6.253 5.088,-11.341 11.341,-11.341l7.56,0c1.311,0 2.528,-0.678 3.216,-1.793c0.689,-1.114 0.752,-2.506 0.166,-3.677Zm-130.399,-42.236c10.418,12.203 23.307,21.034 36.515,24.808l19.103,5.459c3.726,1.063 6.866,3.624 8.666,7.048l-10.048,11.307l-17.652,-10.591c-7.646,-4.588 -16.746,-6.412 -25.776,-4.951c-2.838,0.46 -4.649,1.038 -6.877,1.759c-2.609,-8.332 -3.931,-16.971 -3.931,-25.733l0,-9.106Zm119.457,40.146c-10.422,-0 -18.901,8.479 -18.901,18.901l-0,22.682c-0,26.639 -23.544,49.144 -51.412,49.144l-30.243,-0c-10.77,-0 -20.451,5.983 -25.265,15.615l-0.797,1.596c-0.934,1.867 -0.177,4.137 1.691,5.071c1.867,0.934 4.138,0.176 5.071,-1.691c0.44,-0.586 3.306,-9.102 13.21,-12.125l-12.349,29.159c-0.01,0.024 -0.02,0.047 -0.029,0.071c-0.75,1.877 -2.864,2.851 -4.8,2.148c-21.279,-10.506 -19.997,-9.888 -20.252,-9.99c-2.526,-1.01 -3.191,-4.259 -1.267,-6.182c0.13,-0.131 8.026,-9.078 41.009,-46.411c13.867,-0.617 26.841,-6.319 36.694,-16.172c1.476,-1.476 1.476,-3.87 0,-5.346c-1.476,-1.477 -3.87,-1.476 -5.346,-0c-16.827,16.828 -36.803,13.634 -39.028,14.014c-16.603,0 -31.771,-8.407 -40.573,-22.488l-2.417,-3.868l2.729,1.065c17.307,6.753 38.919,4.347 53.816,-5.586c1.737,-1.158 2.207,-3.505 1.049,-5.242c-1.159,-1.737 -3.505,-2.207 -5.243,-1.048c-13.085,8.724 -31.922,10.666 -46.875,4.832l-12.185,-4.753l-9.896,-15.836l22.488,0c6.231,0 12.519,-0.507 18.689,-1.507c12.711,-2.055 18.051,-4.855 22.992,-5.655c7.182,-1.163 14.516,0.274 20.678,3.97l29.625,17.775c1.789,1.074 4.112,0.494 5.186,-1.296c1.075,-1.79 0.495,-4.113 -1.295,-5.187l-5.378,-3.226c26.56,-29.893 25.14,-28.272 25.32,-28.511c3.101,-4.136 8.038,-6.605 13.204,-6.605c6.294,0 11.951,3.497 14.764,9.127l6.779,13.555l-1.443,-0Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
></g
|
||||
><g
|
||||
><path
|
||||
d="M222.664,114.692c0.85,-0 1.274,0.586 1.274,1.759c0,1.174 -0.242,2.347 -0.728,3.52c-0.485,1.173 -1.183,2.326 -2.093,3.459c-0.91,1.132 -2.185,2.063 -3.823,2.791c-1.639,0.728 -3.489,1.092 -5.552,1.092c-4.531,0 -8.081,-1.143 -10.65,-3.428c-2.569,-2.286 -3.853,-5.644 -3.853,-10.073c-0,-4.43 1.133,-7.889 3.398,-10.377c2.265,-2.488 5.158,-3.732 8.677,-3.732c2.549,0 4.41,0.678 5.583,2.033c1.173,1.355 1.76,2.964 1.76,4.824c-0,1.012 -0.304,1.821 -0.91,2.428c-0.607,0.606 -1.194,0.91 -1.76,0.91c-1.052,-0 -1.74,-0.243 -2.063,-0.728c0.242,-0.607 0.364,-1.477 0.364,-2.61c-0,-1.132 -0.385,-2.164 -1.153,-3.094c-0.769,-0.931 -1.699,-1.396 -2.792,-1.396c-1.901,0 -3.266,0.93 -4.095,2.791c-0.83,1.861 -1.244,4.784 -1.244,8.769c-0,3.984 0.778,6.867 2.336,8.647c1.557,1.78 3.732,2.67 6.523,2.67c2.791,-0 5.138,-0.86 7.039,-2.579c1.901,-1.72 2.852,-4.157 2.852,-7.312c0.04,-0.243 0.344,-0.364 0.91,-0.364Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M227.337,116.815l-0,9.649c-0.405,0.566 -1.113,0.849 -2.124,0.849c-1.012,0 -1.821,-0.313 -2.428,-0.94c-0.606,-0.627 -0.91,-1.548 -0.91,-2.761l0,-23.059c0.405,-0.566 1.113,-0.85 2.124,-0.85c1.011,0 1.821,0.314 2.427,0.941c0.607,0.627 0.911,1.547 0.911,2.761l-0,4.612c2.022,-5.017 4.814,-7.525 8.373,-7.525c2.549,0 4.41,0.678 5.583,2.033c1.173,1.355 1.76,2.963 1.76,4.824c-0,1.012 -0.304,1.821 -0.91,2.427c-0.607,0.607 -1.194,0.911 -1.76,0.911c-1.052,-0 -1.74,-0.243 -2.063,-0.728c0.242,-0.607 0.364,-1.477 0.364,-2.61c-0,-1.132 -0.384,-2.164 -1.153,-3.094c-0.769,-0.931 -1.699,-1.396 -2.791,-1.396c-1.902,-0 -3.611,1.729 -5.128,5.188c-1.517,3.459 -2.275,6.382 -2.275,8.768Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M245.419,103.405c0,-1.214 0.304,-2.134 0.911,-2.761c0.606,-0.627 1.375,-0.941 2.306,-0.941c0.93,0 1.678,0.284 2.245,0.85l-0,17.415c-0,4.814 1.213,7.221 3.641,7.221c2.184,0 3.974,-1.153 5.37,-3.458c1.395,-2.306 2.093,-6.19 2.093,-11.651l0,-6.675c0,-1.214 0.304,-2.134 0.91,-2.761c0.607,-0.627 1.376,-0.941 2.306,-0.941c0.931,0 1.679,0.284 2.246,0.85l-0,30.826c0.485,-0.041 1.254,-0.061 2.305,-0.061c1.052,0 1.578,0.445 1.578,1.335l-0.364,0.91c-1.537,0 -2.71,0.021 -3.519,0.061l-0,3.034c-0,4.167 -0.941,7.454 -2.822,9.861c-1.881,2.407 -4.399,3.61 -7.555,3.61c-1.861,0 -3.509,-0.556 -4.945,-1.669c-1.436,-1.112 -2.155,-2.862 -2.155,-5.248c0,-3.075 1.093,-5.522 3.277,-7.343c2.185,-1.82 5.097,-3.095 8.738,-3.823l0,-9.466c-1.699,3.156 -4.429,4.733 -8.192,4.733c-2.589,0 -4.632,-0.829 -6.128,-2.488c-1.497,-1.658 -2.246,-4.045 -2.246,-7.16l0,-14.26Zm7.646,39.989c0,1.416 0.385,2.498 1.153,3.246c0.769,0.748 1.699,1.123 2.791,1.123c1.093,-0 1.983,-0.324 2.67,-0.971c1.538,-1.376 2.306,-5.522 2.306,-12.44c-5.946,1.335 -8.92,4.349 -8.92,9.042Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M298.576,104.861c1.335,2.306 2.002,5.411 2.002,9.315c0,3.904 -0.981,7.059 -2.943,9.466c-1.962,2.407 -4.52,3.611 -7.676,3.611c-1.861,-0 -3.509,-0.648 -4.945,-1.942c-1.436,-1.295 -2.155,-3.358 -2.155,-6.19c0,-6.634 3.297,-11.59 9.891,-14.866c-1.051,-1.457 -2.518,-2.185 -4.399,-2.185c-1.881,0 -3.671,0.93 -5.37,2.791c-1.699,1.861 -2.549,4.653 -2.549,8.374l0,36.105c-0.404,0.567 -1.112,0.85 -2.124,0.85c-1.011,-0 -1.82,-0.314 -2.427,-0.941c-0.607,-0.627 -0.91,-1.547 -0.91,-2.761l-0,-45.935c0.405,-0.566 1.112,-0.85 2.124,-0.85c1.011,0 1.82,0.314 2.427,0.941c0.607,0.627 0.91,1.547 0.91,2.761l0,1.335c2.104,-3.358 4.885,-5.037 8.344,-5.037c3.459,0 6.159,0.971 8.101,2.913c4.247,-1.375 9.001,-2.063 14.26,-2.063c1.092,-0 1.638,0.445 1.638,1.335l-0.364,0.91c-4.895,0 -9.507,0.688 -13.835,2.063Zm-8.738,20.025c3.317,-0 4.976,-3.297 4.976,-9.891c-0,-3.479 -0.284,-6.21 -0.85,-8.192c-5.34,2.913 -8.01,7.08 -8.01,12.5c0,1.78 0.385,3.156 1.153,4.127c0.769,0.971 1.679,1.456 2.731,1.456Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M308.285,94.424c-0,-1.213 0.303,-2.134 0.91,-2.761c0.607,-0.627 1.375,-0.94 2.306,-0.94c0.93,-0 1.679,0.283 2.245,0.849l0,8.981l8.313,-0c0.85,-0 1.406,0.162 1.669,0.485c0.263,0.324 0.394,0.87 0.394,1.639l-10.376,-0l0,15.291c0,2.225 0.637,3.945 1.911,5.158c1.275,1.214 2.741,1.821 4.4,1.821c2.508,-0 4.349,-0.931 5.522,-2.792c1.173,-1.861 1.76,-4.874 1.76,-9.041c0.08,-0.243 0.384,-0.364 0.91,-0.364c0.728,-0 1.092,1.072 1.092,3.216c-0,3.277 -0.819,5.987 -2.458,8.131c-1.638,2.144 -4.156,3.216 -7.554,3.216c-3.398,0 -6.089,-0.89 -8.071,-2.67c-1.982,-1.78 -2.973,-4.429 -2.973,-7.949l-0,-22.27Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M345.543,101.463c0.526,-1.173 1.365,-1.76 2.518,-1.76c1.153,0 2.013,0.284 2.579,0.85l-0,30.826c0.485,-0.041 1.254,-0.061 2.306,-0.061c1.052,0 1.578,0.445 1.578,1.335l-0.365,0.91c-1.537,0 -2.71,0.021 -3.519,0.061l-0,3.155c-0.041,4.167 -1.001,7.434 -2.882,9.8c-1.882,2.367 -4.38,3.55 -7.494,3.55c-1.861,0 -3.51,-0.556 -4.946,-1.669c-1.436,-1.112 -2.154,-2.862 -2.154,-5.248c-0,-3.075 1.092,-5.522 3.277,-7.343c2.184,-1.82 5.097,-3.095 8.738,-3.823l-0,-8.92c-1.699,2.792 -4.046,4.187 -7.039,4.187c-7.08,0 -10.619,-4.632 -10.619,-13.896c-0,-4.692 1.102,-8.151 3.307,-10.376c2.204,-2.225 5.127,-3.338 8.768,-3.338c2.791,0 4.774,0.587 5.947,1.76Zm-0.364,12.986l-0,-4.308c-0,-2.873 -0.486,-4.936 -1.457,-6.19c-0.971,-1.254 -2.093,-1.881 -3.367,-1.881c-1.275,0 -2.276,0.121 -3.004,0.364c-0.728,0.243 -1.436,0.748 -2.124,1.517c-1.295,1.456 -1.942,4.612 -1.942,9.466c0,3.196 0.283,5.684 0.85,7.464c0.566,1.78 1.213,2.903 1.942,3.368c0.728,0.465 1.749,0.698 3.064,0.698c1.315,-0 2.65,-0.84 4.005,-2.519c1.355,-1.678 2.033,-4.338 2.033,-7.979Zm-0,22.209l-0,-2.306c-5.947,1.335 -8.92,4.349 -8.92,9.042c-0,1.416 0.384,2.498 1.153,3.246c0.768,0.748 1.678,1.123 2.73,1.123c1.699,-0 2.963,-0.789 3.793,-2.367c0.829,-1.578 1.244,-4.49 1.244,-8.738Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M381.891,113.478c0.849,-0 1.274,0.647 1.274,1.942c-0,2.993 -1.042,5.724 -3.125,8.192c-2.084,2.467 -5.249,3.701 -9.497,3.701c-4.247,0 -7.656,-1.143 -10.224,-3.428c-2.569,-2.286 -3.854,-5.644 -3.854,-10.073c0,-4.43 1.133,-7.889 3.398,-10.377c2.266,-2.488 5.158,-3.732 8.678,-3.732c2.548,0 4.409,0.678 5.582,2.033c1.174,1.355 1.76,2.964 1.76,4.824c0,3.034 -1.264,5.553 -3.792,7.555c-2.529,2.003 -5.755,3.004 -9.679,3.004c0.364,2.589 1.305,4.541 2.822,5.856c1.517,1.314 3.519,1.972 6.007,1.972c2.488,-0 4.733,-0.941 6.736,-2.822c2.002,-1.881 3.003,-4.642 3.003,-8.283c0.041,-0.243 0.344,-0.364 0.911,-0.364Zm-19.661,0.85l-0,0.546c2.508,-0.324 4.682,-1.113 6.523,-2.367c1.841,-1.254 2.761,-3.115 2.761,-5.583c0,-1.577 -0.344,-2.781 -1.031,-3.61c-0.688,-0.829 -1.659,-1.244 -2.913,-1.244c-1.901,0 -3.267,0.93 -4.096,2.791c-0.829,1.861 -1.244,5.017 -1.244,9.467Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M393.359,99.703c3.601,0 6.534,1.194 8.799,3.581c2.265,2.386 3.398,5.633 3.398,9.739c0,4.106 -1.062,7.514 -3.186,10.225c-2.124,2.71 -4.965,4.065 -8.525,4.065c-3.56,0 -6.524,-1.224 -8.89,-3.671c-2.367,-2.447 -3.55,-5.846 -3.55,-10.194c0,-4.349 1.102,-7.727 3.307,-10.134c2.205,-2.407 5.087,-3.611 8.647,-3.611Zm0.061,2.367c-1.092,0 -2.033,0.273 -2.822,0.819c-0.789,0.546 -1.183,1.325 -1.183,2.336c-0,2.589 1.011,5.067 3.034,7.434c2.023,2.366 4.43,3.934 7.221,4.703c0.081,-1.538 0.121,-2.852 0.121,-3.945c0,-4.207 -0.445,-7.15 -1.335,-8.829c-0.89,-1.679 -2.568,-2.518 -5.036,-2.518Zm-6.25,11.347c-0,4.127 0.516,7.08 1.547,8.86c1.032,1.78 2.721,2.67 5.067,2.67c1.618,-0 2.862,-0.415 3.732,-1.244c0.87,-0.83 1.466,-2.175 1.79,-4.036c-2.63,-0.566 -5.047,-1.759 -7.251,-3.58c-2.205,-1.82 -3.813,-3.843 -4.825,-6.068c-0.04,0.688 -0.06,1.821 -0.06,3.398Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/><path
|
||||
d="M442.571,112.75c0.729,-0 1.093,1.072 1.093,3.216c-0,3.438 -0.739,6.189 -2.215,8.252c-1.477,2.064 -3.631,3.095 -6.463,3.095c-2.832,0 -5.006,-0.971 -6.523,-2.912c-1.517,-1.942 -2.275,-4.693 -2.275,-8.253l-0,-7.1c-0,-4.814 -1.214,-7.221 -3.641,-7.221c-2.144,0 -3.904,1.093 -5.28,3.277c-1.375,2.185 -2.063,5.846 -2.063,10.983l0,10.377c-0.404,0.566 -1.112,0.849 -2.124,0.849c-1.011,0 -1.82,-0.313 -2.427,-0.94c-0.607,-0.627 -0.91,-1.548 -0.91,-2.761l0,-23.059c0.405,-0.566 1.173,-0.85 2.306,-0.85c2.103,0 3.155,1.517 3.155,4.552c1.699,-3.035 4.39,-4.552 8.071,-4.552c2.629,0 4.723,0.83 6.28,2.488c1.558,1.659 2.337,4.046 2.337,7.161l-0,8.616c-0,2.306 0.364,4.046 1.092,5.219c0.728,1.173 1.81,1.76 3.246,1.76c1.436,-0 2.7,-0.9 3.793,-2.701c1.092,-1.8 1.638,-4.844 1.638,-9.132c0.041,-0.243 0.344,-0.364 0.91,-0.364Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
></svg
|
||||
>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
a {
|
||||
border: none;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
margin-top: 4rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 30rem) {
|
||||
header {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
header svg {
|
||||
max-height: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
header svg {
|
||||
width: 100%;
|
||||
max-width: 16rem;
|
||||
transform: translateX(-1rem);
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
BIN
client/src/lib/views/Header/Logo.svg
(Stored with Git LFS)
@@ -1,74 +0,0 @@
|
||||
<script lang="ts">
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<a href="/">
|
||||
<svg
|
||||
width="100%"
|
||||
height="100%"
|
||||
viewBox="0 0 475 200"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xml:space="preserve"
|
||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"
|
||||
fill="currentColor"
|
||||
><g id="Logo"
|
||||
><clipPath id="_clip1"><rect x="4.516" y="3.225" width="193.55" height="193.55" /></clipPath
|
||||
><g clip-path="url(#_clip1)"
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M171.604,43.296c-2.087,-0 -3.78,1.693 -3.78,3.78c-0,2.087 1.693,3.78 3.78,3.78c2.087,0 3.78,-1.693 3.78,-3.78c0,-2.087 -1.693,-3.78 -3.78,-3.78Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M101.291,134.023c-2.087,-0 -3.78,1.693 -3.78,3.78c-0,2.087 1.693,3.78 3.78,3.78c2.087,0 3.78,-1.693 3.78,-3.78c0,-2.087 -1.693,-3.78 -3.78,-3.78Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M154.215,96.22c-2.088,-0 -3.78,1.692 -3.78,3.78c-0,18.76 -15.263,34.023 -34.023,34.023c-2.088,-0 -3.78,1.692 -3.78,3.78c-0,2.088 1.692,3.78 3.78,3.78c22.929,0 41.583,-18.654 41.583,-41.583c0,-2.088 -1.692,-3.78 -3.78,-3.78Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
><g
|
||||
><g
|
||||
><path
|
||||
d="M197.667,60.507l-9.515,-19.026c-4.101,-8.207 -12.349,-13.306 -21.526,-13.306c-7.48,-0 -14.627,3.547 -19.155,9.498l-10.678,12.016c-2.847,-4.047 -7.021,-7.049 -11.831,-8.421l-19.102,-5.459c-14.623,-4.178 -28.92,-15.441 -39.227,-30.901c-0.924,-1.386 -2.646,-2.003 -4.24,-1.521c-1.595,0.483 -2.685,1.953 -2.685,3.618l-0,20.372c-0,9.468 1.418,18.804 4.219,27.813c-2.936,0.73 -5.896,1.34 -8.842,1.816c-5.773,0.936 -11.654,1.411 -17.48,1.411l-29.309,-0c-1.374,-0 -2.64,0.746 -3.306,1.948c-0.666,1.202 -0.628,2.671 0.101,3.836l22.636,36.219c9.672,15.473 26.33,25.183 44.578,25.983l-36.36,41.158c-5.602,5.728 -3.654,15.315 3.746,18.396l20.018,9.887c0.088,0.044 0.179,0.084 0.271,0.121c5.789,2.313 12.389,-0.496 14.725,-6.279l13.969,-32.982l27.738,0c31.966,0 58.972,-25.967 58.972,-56.704l0,-22.682c0,-6.253 5.088,-11.341 11.341,-11.341l7.561,0c1.31,0 2.527,-0.678 3.216,-1.793c0.688,-1.114 0.751,-2.506 0.165,-3.677Zm-130.399,-42.236c10.418,12.203 23.307,21.034 36.515,24.808l19.104,5.459c3.725,1.063 6.865,3.624 8.666,7.048l-10.049,11.307l-17.652,-10.591c-7.646,-4.588 -16.746,-6.412 -25.776,-4.951c-2.837,0.46 -4.648,1.038 -6.877,1.759c-2.609,-8.332 -3.931,-16.971 -3.931,-25.733l0,-9.106Zm119.457,40.146c-10.422,-0 -18.901,8.479 -18.901,18.901l-0,22.682c-0,26.639 -23.544,49.144 -51.412,49.144l-30.242,-0c-10.771,-0 -20.452,5.983 -25.265,15.615l-0.798,1.596c-0.934,1.867 -0.177,4.137 1.691,5.071c1.867,0.934 4.138,0.176 5.072,-1.691c0.44,-0.586 3.306,-9.102 13.21,-12.125l-12.349,29.159c-0.01,0.024 -0.02,0.047 -0.03,0.071c-0.75,1.877 -2.864,2.851 -4.8,2.148c-21.279,-10.506 -19.997,-9.888 -20.252,-9.99c-2.526,-1.01 -3.191,-4.259 -1.267,-6.182c0.131,-0.131 8.026,-9.078 41.009,-46.411c13.867,-0.617 26.842,-6.319 36.694,-16.172c1.477,-1.476 1.477,-3.87 0,-5.346c-1.476,-1.477 -3.869,-1.476 -5.346,-0c-16.827,16.828 -36.803,13.634 -39.027,14.014c-16.604,0 -31.772,-8.407 -40.574,-22.488l-2.417,-3.868l2.729,1.065c17.308,6.753 38.919,4.347 53.817,-5.586c1.737,-1.158 2.206,-3.505 1.048,-5.242c-1.158,-1.737 -3.505,-2.207 -5.243,-1.048c-13.085,8.724 -31.922,10.666 -46.874,4.832l-12.185,-4.753l-9.896,-15.836l22.488,0c6.23,0 12.518,-0.507 18.688,-1.507c12.711,-2.055 18.051,-4.855 22.993,-5.655c7.181,-1.163 14.516,0.274 20.677,3.97l29.625,17.775c1.79,1.074 4.112,0.494 5.187,-1.296c1.074,-1.79 0.494,-4.113 -1.296,-5.187l-5.377,-3.226c26.559,-29.893 25.139,-28.272 25.319,-28.511c3.102,-4.136 8.038,-6.605 13.205,-6.605c6.293,0 11.95,3.497 14.764,9.127l6.779,13.555l-1.444,-0Z"
|
||||
style="fill-rule:nonzero;"
|
||||
/></g
|
||||
></g
|
||||
></g
|
||||
><text
|
||||
x="195.418px"
|
||||
y="127.131px"
|
||||
style="font-family:'Sofia-Regular', 'Sofia';font-size:60.681px;">cryptogeon</text
|
||||
></g
|
||||
></svg
|
||||
>
|
||||
</a>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
a {
|
||||
border: none;
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
margin-top: calc(min(15vh, 6rem));
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
header svg {
|
||||
width: 100%;
|
||||
max-width: 16rem;
|
||||
transform: translateX(-1rem);
|
||||
}
|
||||
</style>
|
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import Footer from '$lib/views/Footer.svelte'
|
||||
import Header from '$lib/views/Header.svelte'
|
||||
|
||||
import '../app.css'
|
||||
import Header from '$lib/views/Header/index.svelte'
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -12,16 +14,9 @@
|
||||
<slot />
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<a href="/">/home</a>
|
||||
<a href="/about">/about</a>
|
||||
<a href="https://github.com/cupcakearmy/cryptgeon" target="_blank" rel="noopener">/code</a>
|
||||
</footer>
|
||||
<Footer />
|
||||
|
||||
<style>
|
||||
a {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
main {
|
||||
padding: 1rem;
|
||||
padding-bottom: 4rem;
|
||||
@@ -29,17 +24,4 @@
|
||||
max-width: 35rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
background-color: var(--ui-bg-0-85);
|
||||
}
|
||||
</style>
|
||||
|
@@ -13,7 +13,7 @@
|
||||
<h1>About</h1>
|
||||
|
||||
<p>
|
||||
<i>cryptgeon</i> is an secure, open source sharing note service inspired by
|
||||
<i>cryptgeon</i> is a secure, open source sharing note service inspired by
|
||||
<a href="https://privnote.com"><i>PrivNote</i></a>.
|
||||
</p>
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
<b>▶ Features</b>
|
||||
<ul>
|
||||
<li>view and time constrains</li>
|
||||
<li>server cannot decrypt contents due to client side encryption</li>
|
||||
<li>view and time constraints</li>
|
||||
<li>in memory, no persistence</li>
|
||||
<li>in browser encryption → server cannot decrypt contents</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
@@ -7,18 +7,17 @@
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import copy from 'copy-to-clipboard'
|
||||
|
||||
import type { NotePublic } from '$lib/api'
|
||||
import { info, get } from '$lib/api'
|
||||
import { decrypt, getKeyFromString } from '$lib/crypto'
|
||||
import Button from '$lib/ui/Button.svelte'
|
||||
import TextInput from '$lib/ui/TextInput.svelte'
|
||||
import copy from 'copy-to-clipboard'
|
||||
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
export let id: string
|
||||
let needPassword = false
|
||||
let password: string = ''
|
||||
|
||||
let password: string
|
||||
let note: NotePublic | null = null
|
||||
let exists = false
|
||||
|
||||
@@ -29,8 +28,9 @@
|
||||
try {
|
||||
loading = true
|
||||
error = null
|
||||
const data = await info(id)
|
||||
needPassword = data.password
|
||||
password = window.location.hash.slice(1)
|
||||
console.log(password)
|
||||
await info(id)
|
||||
exists = true
|
||||
} catch {
|
||||
exists = false
|
||||
@@ -40,49 +40,52 @@
|
||||
})
|
||||
|
||||
async function show() {
|
||||
const data = note || (await get(id)) // Don't get the content twice on wrong password.
|
||||
if (needPassword) {
|
||||
try {
|
||||
const key = await getKeyFromString(password)
|
||||
data.contents = await decrypt(data.contents, key)
|
||||
error = false
|
||||
} catch {
|
||||
error = true
|
||||
}
|
||||
try {
|
||||
error = false
|
||||
loading = true
|
||||
const data = note || (await get(id)) // Don't get the content twice on wrong password.
|
||||
const key = await getKeyFromString(password)
|
||||
data.contents = await decrypt(data.contents, key)
|
||||
note = data
|
||||
} catch {
|
||||
error = true
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
note = data
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !loading}
|
||||
{#if !exists}
|
||||
<p class="error-text">note was not found or was already deleted.</p>
|
||||
<p class="error-text" data-testid="note-not-found">
|
||||
note was not found or was already deleted.
|
||||
</p>
|
||||
{:else if note && !error}
|
||||
<p class="error-text">you will not get the chance to see the note again.</p>
|
||||
<div class="note">
|
||||
<div class="note" data-testid="note-result">
|
||||
{note.contents}
|
||||
</div>
|
||||
<br />
|
||||
<Button on:click={() => copy(note.contents)}>copy to clipboard</Button>
|
||||
{:else}
|
||||
<form on:submit|preventDefault={show}>
|
||||
<p>click below to show and delete the note if the counter has reached it's limit</p>
|
||||
{#if needPassword}
|
||||
<TextInput type="password" label="password" bind:value={password} />
|
||||
<br />
|
||||
{/if}
|
||||
<Button type="submit">show note</Button>
|
||||
{#if error}
|
||||
<br />
|
||||
<p class="error-text">
|
||||
wrong password. could not decipher.
|
||||
<fieldset>
|
||||
<p>click below to show and delete the note if the counter has reached it's limit</p>
|
||||
<Button type="submit" data-testid="button-show">show note</Button>
|
||||
{#if error}
|
||||
<br />
|
||||
note already destroyed. try again without reloading the page.
|
||||
</p>
|
||||
{/if}
|
||||
<p class="error-text">
|
||||
wrong password. could not decipher. probably a broken link. note was destroyed.
|
||||
<br />
|
||||
</p>
|
||||
{/if}
|
||||
</fieldset>
|
||||
</form>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if loading}
|
||||
<p>loading...</p>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.note {
|
||||
|
1
client/static/icons/contrast-sharp.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns='http://www.w3.org/2000/svg' class='ionicon' viewBox='0 0 512 512'><title>Contrast</title><path d='M256 32C132.29 32 32 132.29 32 256s100.29 224 224 224 224-100.29 224-224S379.71 32 256 32zM128.72 383.28A180 180 0 01256 76v360a178.82 178.82 0 01-127.28-52.72z'/></svg>
|
After Width: | Height: | Size: 279 B |
BIN
client/static/icons/copy-sharp.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 313 B |
BIN
client/static/icons/dice-sharp.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 728 B |
BIN
client/static/icons/eye-off-sharp.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 720 B |
BIN
client/static/icons/eye-sharp.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 474 B |
BIN
client/static/icons/lock-closed-sharp.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 128 B After Width: | Height: | Size: 275 B |
@@ -1,17 +0,0 @@
|
||||
const preprocess = require('svelte-preprocess')
|
||||
const adapter = require('@sveltejs/adapter-static')
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
module.exports = {
|
||||
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||
// for more information about preprocessors
|
||||
preprocess: preprocess(),
|
||||
|
||||
kit: {
|
||||
adapter: adapter({
|
||||
fallback: 'index.html',
|
||||
}),
|
||||
// hydrate the <div id="svelte"> element in src/app.html
|
||||
target: '#svelte',
|
||||
},
|
||||
}
|
13
client/svelte.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import preprocess from 'svelte-preprocess'
|
||||
import adapter from '@sveltejs/adapter-static'
|
||||
|
||||
export default {
|
||||
preprocess: preprocess(),
|
||||
|
||||
kit: {
|
||||
adapter: adapter({
|
||||
fallback: 'index.html',
|
||||
}),
|
||||
target: '#svelte',
|
||||
},
|
||||
}
|
5
cypress.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"fixturesFolder": false,
|
||||
"pluginsFile": false,
|
||||
"supportFile": false
|
||||
}
|
2
cypress/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
screenshots
|
||||
videos
|
41
cypress/integration/main.spec.js
Normal file
@@ -0,0 +1,41 @@
|
||||
function createNote(options = {}) {
|
||||
Object.assign(options, {
|
||||
text: `Revaluation battle selfish derive suicide revaluation society love superiority salvation spirit virtues revaluation. Aversion sexuality play burying mountains intentions battle reason strong burying war insofar inexpedient war. Fearful intentions selfish madness suicide.`,
|
||||
})
|
||||
cy.visit('http://localhost:5000')
|
||||
const text = options.text
|
||||
cy.get('[data-testid=input-note]').type(text)
|
||||
cy.get('[data-testid=button-create]').click()
|
||||
cy.wait(500)
|
||||
return cy
|
||||
.get('[data-testid=note-share-link]')
|
||||
.invoke('val')
|
||||
.then((link) => {
|
||||
return [link, text]
|
||||
})
|
||||
}
|
||||
|
||||
describe('Basics', () => {
|
||||
it('Share note', () => {
|
||||
createNote().then(([link, text]) => {
|
||||
cy.visit(link)
|
||||
cy.get('[data-testid=button-show]').click()
|
||||
cy.wait(250)
|
||||
cy.get('[data-testid=note-result]').should('have.text', text)
|
||||
})
|
||||
})
|
||||
|
||||
it('Check destroyed', () => {
|
||||
createNote().then(([link, text]) => {
|
||||
// Check the first time
|
||||
cy.visit(link)
|
||||
cy.get('[data-testid=button-show]').click()
|
||||
cy.wait(250)
|
||||
cy.get('[data-testid=note-result]').should('have.text', text)
|
||||
|
||||
// Should not exists anymore
|
||||
cy.visit(link)
|
||||
cy.get('[data-testid=note-not-found]').should('exist')
|
||||
})
|
||||
})
|
||||
})
|
BIN
design/Github.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
design/Logo.afdesign
(Stored with Git LFS)
BIN
design/Logo.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 129 B After Width: | Height: | Size: 12 KiB |
BIN
design/Screens.afdesign
(Stored with Git LFS)
Normal file
BIN
design/Screens.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
design/dove.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 129 B After Width: | Height: | Size: 3.3 KiB |
BIN
design/github.svg
(Stored with Git LFS)
Before Width: | Height: | Size: 60 KiB |
@@ -12,5 +12,7 @@ services:
|
||||
|
||||
app:
|
||||
build: .
|
||||
depends_on:
|
||||
- memcached
|
||||
ports:
|
||||
- 80:5000
|
||||
- 5000:5000
|
||||
|
4572
package-lock.json
generated
@@ -3,9 +3,14 @@
|
||||
"dev:docker": "docker-compose up memcached",
|
||||
"dev:backend": "cargo watch -x 'run --bin cryptgeon'",
|
||||
"dev:front": "npm --prefix client run dev",
|
||||
"dev": "run-p dev:*"
|
||||
"dev": "run-p dev:*",
|
||||
"test:server": "docker-compose up --build",
|
||||
"test:cypress": "cypress run --headless",
|
||||
"test:run": "start-server-and-test test:server http://localhost:5000 test:cypress"
|
||||
},
|
||||
"devDependencies": {
|
||||
"npm-run-all": "^4.1.5"
|
||||
"cypress": "^7.2.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"start-server-and-test": "^1.12.1"
|
||||
}
|
||||
}
|
||||
|
@@ -5,15 +5,12 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct Note {
|
||||
pub contents: String,
|
||||
pub password: bool,
|
||||
pub views: Option<u8>,
|
||||
pub expiration: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct NoteInfo {
|
||||
pub password: bool,
|
||||
}
|
||||
pub struct NoteInfo {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct NotePublic {
|
||||
|
@@ -23,11 +23,7 @@ async fn one(path: web::Path<NotePath>) -> impl Responder {
|
||||
let note = store::get(&p.id);
|
||||
match note {
|
||||
None => return HttpResponse::NotFound().finish(),
|
||||
Some(note) => {
|
||||
return HttpResponse::Ok().json(NoteInfo {
|
||||
password: note.password,
|
||||
})
|
||||
}
|
||||
Some(_) => return HttpResponse::Ok().json(NoteInfo {}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +56,8 @@ async fn create(note: web::Json<Note>) -> impl Responder {
|
||||
if e > 360 {
|
||||
return bad_req;
|
||||
}
|
||||
n.expiration = Some(now() + (e * 60))
|
||||
let expiration = now() + (e * 60);
|
||||
n.expiration = Some(expiration);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -93,8 +90,8 @@ async fn delete(path: web::Path<NotePath>) -> impl Responder {
|
||||
}
|
||||
match changed.expiration {
|
||||
Some(e) => {
|
||||
if e > now() {
|
||||
store::del(&p.id.clone());
|
||||
store::del(&p.id.clone());
|
||||
if e < now() {
|
||||
return HttpResponse::BadRequest().finish();
|
||||
}
|
||||
}
|
||||
@@ -114,7 +111,4 @@ pub fn init(cfg: &mut web::ServiceConfig) {
|
||||
.service(delete)
|
||||
.service(one),
|
||||
);
|
||||
// cfg.service(create);
|
||||
// cfg.service(delete);
|
||||
// cfg.service(one);
|
||||
}
|
||||
|