diff --git a/.gitignore b/.gitignore
index acf7eab..f9cd75e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,28 +1,4 @@
# Mine
*.db*
-
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
+bin/
diff --git a/backend/.gitignore b/backend/.gitignore
new file mode 100644
index 0000000..93a464b
--- /dev/null
+++ b/backend/.gitignore
@@ -0,0 +1 @@
+static/
\ No newline at end of file
diff --git a/backend/db_ops/backup.go b/backend/db_ops/backup.go
new file mode 100644
index 0000000..95aa9dc
--- /dev/null
+++ b/backend/db_ops/backup.go
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package db_ops
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path/filepath"
+ "seif/params"
+ "sort"
+ "strings"
+ "time"
+)
+
+const bkpTimeFormat = "060102-150405"
+
+var bkpTimeGlob = strings.Repeat("?", len(bkpTimeFormat))
+
+const bkpFile = "seif_%s.db"
+const numFiles = 8
+
+func Backup() {
+ var bkpDir = filepath.Join(filepath.Dir(params.DbPath), "backups")
+ var err error
+
+ if _, err = os.Stat(bkpDir); errors.Is(err, os.ErrNotExist) {
+ if err = os.Mkdir(bkpDir, 0755); err != nil {
+ panic(err)
+ }
+ }
+
+ // Execute non-concurrently
+ params.Lock.Lock()
+ defer params.Lock.Unlock()
+
+ now := time.Now().Format(bkpTimeFormat)
+ fname := fmt.Sprintf(filepath.Join(bkpDir, bkpFile), now)
+ _, err = params.Db.Exec("VACUUM INTO ?", fname)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "backup: %s\n", err.Error())
+ return
+ }
+
+ // delete the backup files, except for the last n
+ list, err := filepath.Glob(fmt.Sprintf(filepath.Join(bkpDir, bkpFile), bkpTimeGlob))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "sched. task (pruning bkp files): %s\n", err.Error())
+ return
+ }
+
+ sort.Strings(list)
+ for i := 0; i < len(list)-numFiles; i++ {
+ os.Remove(list[i])
+ }
+}
diff --git a/backend/db_ops/create.go b/backend/db_ops/create.go
new file mode 100644
index 0000000..dac1e3c
--- /dev/null
+++ b/backend/db_ops/create.go
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package db_ops
+
+import (
+ "fmt"
+ "seif/params"
+ "seif/utils"
+)
+
+const DB_VERSION = 1
+
+const SQL_CREATE = `
+ CREATE TABLE SECRETS (
+ ID TEXT PRIMARY KEY,
+ IV TEXT,
+ SECRET TEXT,
+ SHA TEXT,
+ EXPIRY INTEGER,
+ TS TEXT
+ )`
+
+var SQL_CREATE_2 = fmt.Sprintf("CREATE VIEW VERSION AS SELECT %d AS VERSION", DB_VERSION)
+
+func InitDb() {
+ // Execute non-concurrently
+ params.Lock.Lock()
+ defer params.Lock.Unlock()
+
+ if _, err := params.Db.Exec(SQL_CREATE); err != nil {
+ utils.Abort("in creating db: %s", err)
+ }
+
+ if _, err := params.Db.Exec(SQL_CREATE_2); err != nil {
+ utils.Abort("in creating db: %s", err)
+ }
+}
diff --git a/backend/db_ops/maint.go b/backend/db_ops/maint.go
new file mode 100644
index 0000000..8a34963
--- /dev/null
+++ b/backend/db_ops/maint.go
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package db_ops
+
+import (
+ "fmt"
+ "os"
+ "seif/params"
+ "seif/utils"
+ "time"
+)
+
+const maint_period = 5 // min
+
+const SQL_MAINT = "DELETE FROM SECRETS WHERE TS < DATETIME('now', '-' || EXPIRY || ' days')"
+
+func maint(allowToPanic bool) {
+ // Execute non-concurrently
+ params.Lock.Lock()
+ defer params.Lock.Unlock()
+
+ if _, err := params.Db.Exec(SQL_MAINT); err != nil {
+ if allowToPanic {
+ utils.Abort("in doing cleanup: %s\n", err.Error())
+ } else {
+ fmt.Fprintf(os.Stderr, "in doing maintenance cleanup: %s\n", err.Error())
+ }
+ }
+
+ if _, err := params.Db.Exec("VACUUM"); err != nil {
+ if allowToPanic {
+ utils.Abort("in doing vacuum: %s\n", err.Error())
+ } else {
+ fmt.Fprintf(os.Stderr, "in doing maintenance vacuum: %s\n", err.Error())
+ }
+ }
+}
+
+func StartMaint() {
+ maint(true)
+ for range time.Tick((maint_period * time.Minute)) {
+ maint(false)
+ }
+}
diff --git a/backend/flags/flags.go b/backend/flags/flags.go
new file mode 100644
index 0000000..a415627
--- /dev/null
+++ b/backend/flags/flags.go
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package flags
+
+import (
+ "flag"
+ "seif/params"
+)
+
+func Parse() {
+ _db := flag.String("db", "./seif.db", "The path of the sqlite database")
+ _port := flag.Int("port", 34543, "Port")
+ _maxDays := flag.Int("max-days", 3, "Maximum retention days to allow")
+ _maxBytes := flag.Int("max-bytes", 1024, "Maximum size, in bytes, of a secret")
+
+ flag.Parse()
+
+ params.DbPath = *_db
+ params.Port = *_port
+ params.MaxDays = *_maxDays
+ params.MaxBytes = *_maxBytes
+}
diff --git a/backend/go.mod b/backend/go.mod
new file mode 100644
index 0000000..cc70a0b
--- /dev/null
+++ b/backend/go.mod
@@ -0,0 +1,32 @@
+module seif
+
+go 1.22
+
+require (
+ github.com/gofiber/fiber/v2 v2.52.2
+ modernc.org/sqlite v1.29.5
+)
+
+require (
+ github.com/andybalholm/brotli v1.1.0 // indirect
+ github.com/dustin/go-humanize v1.0.1 // indirect
+ github.com/google/uuid v1.6.0 // indirect
+ github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
+ github.com/klauspost/compress v1.17.7 // indirect
+ github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mattn/go-runewidth v0.0.15 // indirect
+ github.com/ncruces/go-strftime v0.1.9 // indirect
+ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
+ github.com/valyala/bytebufferpool v1.0.0 // indirect
+ github.com/valyala/fasthttp v1.52.0 // indirect
+ github.com/valyala/tcplisten v1.0.0 // indirect
+ golang.org/x/sys v0.18.0 // indirect
+ modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
+ modernc.org/libc v1.45.0 // indirect
+ modernc.org/mathutil v1.6.0 // indirect
+ modernc.org/memory v1.7.2 // indirect
+ modernc.org/strutil v1.2.0 // indirect
+ modernc.org/token v1.1.0 // indirect
+)
diff --git a/backend/go.sum b/backend/go.sum
new file mode 100644
index 0000000..367738f
--- /dev/null
+++ b/backend/go.sum
@@ -0,0 +1,72 @@
+github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
+github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo=
+github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
+github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
+github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
+github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
+github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
+github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0=
+github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
+github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
+github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
+golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
+golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
+golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
+modernc.org/cc/v4 v4.19.3 h1:vE9kmJqUcyvNOf8F2Hn8od14SOMq34BiqcZ2tMzLk5c=
+modernc.org/cc/v4 v4.19.3/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
+modernc.org/ccgo/v4 v4.11.0 h1:2uc2kRvZLC/oHylsrirRW6f1I4wljQST2BBbm+aKiXM=
+modernc.org/ccgo/v4 v4.11.0/go.mod h1:GwrfAtnU6PdZkCWD4XI8wB1T5Xj3fSw9lO/40H1ldys=
+modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
+modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
+modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
+modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
+modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
+modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
+modernc.org/libc v1.45.0 h1:qmAJZf9tYFqK/SFSFqpBc9uHWGsvoYWtRcMQdG+JEfM=
+modernc.org/libc v1.45.0/go.mod h1:YkRHLoN4L70OdO1cVmM83KZhRbRvsc3XogfVzbTXBwE=
+modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
+modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
+modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
+modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
+modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
+modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
+modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
+modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
+modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE=
+modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
+modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
+modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
+modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
+modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
diff --git a/backend/handlers/get_init_data/get_init_data.go b/backend/handlers/get_init_data/get_init_data.go
new file mode 100644
index 0000000..6765aae
--- /dev/null
+++ b/backend/handlers/get_init_data/get_init_data.go
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package get_init_data
+
+import (
+ "seif/params"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+type response struct {
+ Version string `json:"version"`
+ MaxDays int `json:"max_days"`
+}
+
+func GetInitData(c *fiber.Ctx) error {
+ c.JSON(response{Version: params.VERSION, MaxDays: params.MaxDays})
+ return c.SendStatus(fiber.StatusOK)
+}
diff --git a/backend/handlers/get_secret/get_secret.go b/backend/handlers/get_secret/get_secret.go
new file mode 100644
index 0000000..2ea633e
--- /dev/null
+++ b/backend/handlers/get_secret/get_secret.go
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package get_secret
+
+import (
+ "seif/db_ops"
+ "seif/params"
+ "seif/utils"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+type Secret struct {
+ IV string `json:"iv"`
+ Sec string `json:"secret"`
+ SHA string `json:"sha"`
+}
+
+type response struct {
+ Secret *Secret `json:"secret"`
+}
+
+const SQL = "DELETE FROM SECRETS WHERE ID = $1 RETURNING IV, SECRET, SHA"
+
+func GetSecret(c *fiber.Ctx) error {
+ id := c.Query("id", "")
+
+ defer func() { go db_ops.Backup() }()
+ params.Lock.Lock()
+ defer params.Lock.Unlock()
+
+ ret := response{}
+
+ rows, err := params.Db.Query(SQL, id)
+ if err != nil {
+ return utils.SendError(c, fiber.StatusInternalServerError, utils.FHE002, "secret", &err)
+ }
+ defer rows.Close()
+ if rows.Next() {
+ var secret Secret
+ err = rows.Scan(&secret.IV, &secret.Sec, &secret.SHA)
+ if err != nil {
+ return utils.SendError(c, fiber.StatusInternalServerError, utils.FHE001, "secret", &err)
+ }
+ ret.Secret = &secret
+ }
+ if err = rows.Err(); err != nil {
+ return utils.SendError(c, fiber.StatusInternalServerError, utils.FHE003, "secret", &err)
+ }
+
+ c.JSON(ret)
+ return c.SendStatus(fiber.StatusOK)
+}
diff --git a/backend/handlers/get_secret_status/getSecretStatus.go b/backend/handlers/get_secret_status/getSecretStatus.go
new file mode 100644
index 0000000..2d492d7
--- /dev/null
+++ b/backend/handlers/get_secret_status/getSecretStatus.go
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package get_secret_status
+
+import (
+ "seif/params"
+ "seif/utils"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+type response struct {
+ Pristine bool `json:"pristine"`
+}
+
+const SQL_GET_SECRET = "SELECT 1 FROM SECRETS WHERE ID = $1"
+
+func GetSecretStatus(c *fiber.Ctx) error {
+ id := c.Query("id", "")
+
+ params.Lock.Lock()
+ defer params.Lock.Unlock()
+
+ rows, err := params.Db.Query(SQL_GET_SECRET, id)
+ if err != nil {
+ return utils.SendError(c, fiber.StatusInternalServerError, utils.FHE001, "secret", &err)
+ }
+ defer rows.Close()
+ ret := rows.Next()
+ if err = rows.Err(); err != nil {
+ return utils.SendError(c, fiber.StatusInternalServerError, utils.FHE003, "secret", &err)
+ }
+
+ c.JSON(response{Pristine: ret})
+ return c.SendStatus(fiber.StatusOK)
+}
diff --git a/backend/handlers/put_secret/putSecret.go b/backend/handlers/put_secret/putSecret.go
new file mode 100644
index 0000000..9592a3c
--- /dev/null
+++ b/backend/handlers/put_secret/putSecret.go
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package put_secret
+
+import (
+ "crypto/rand"
+ "encoding/base64"
+ "fmt"
+ "seif/db_ops"
+ "seif/handlers/get_secret"
+ "seif/params"
+ "seif/utils"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+type request struct {
+ get_secret.Secret
+ Expiry int `json:"expiry"`
+}
+
+type response struct {
+ Id string `json:"id"`
+}
+
+const SQL = `
+ INSERT INTO SECRETS (ID, IV, SECRET, SHA, EXPIRY, TS)
+ VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP)
+ RETURNING ID`
+
+// generateRandomBase64 generates a 42-bit random value encoded in base64.
+func generate42bitRandomBase64() (string, error) {
+ // 42 bits = 5.25 bytes, but we need a whole number of bytes
+ b := make([]byte, 6) // Using 6 bytes (48 bits) to have a whole number greater than 42 bits
+ _, err := rand.Read(b)
+ if err != nil {
+ return "", err
+ }
+ // Mask the last 6 bits of the last byte to zero to ensure only 42 bits are random
+ b[5] &= 0xC0 // 0xC0 is 11000000 in binary, which sets the last 6 bits to zero
+
+ // Encode to base64
+ encoded := base64.URLEncoding.EncodeToString(b)
+ // Trim the result to the correct length: 7 characters for 42 bits
+ return encoded[:7], nil
+}
+
+func PutSecret(c *fiber.Ctx) error {
+ req := new(request)
+ if err := c.BodyParser(req); err != nil {
+ return utils.SendError(c, fiber.StatusBadRequest, utils.FHE004, "body", &err)
+ }
+
+ if len(req.Sec) > params.MaxBytes {
+ return utils.SendError(c, fiber.StatusBadRequest, utils.FHE005, "", nil)
+ }
+
+ if req.Expiry < 1 || req.Expiry > params.MaxDays {
+ return utils.SendError(c, fiber.StatusBadRequest, utils.FHE006, fmt.Sprint(params.MaxDays), nil)
+ }
+
+ id, err := generate42bitRandomBase64()
+ if err != nil {
+ return utils.SendError(c, fiber.StatusBadRequest, utils.FHE007, "", &err)
+ }
+
+ defer func() { go db_ops.Backup() }()
+ params.Lock.Lock()
+ defer params.Lock.Unlock()
+
+ _, err = params.Db.Exec(SQL, id, req.IV, req.Sec, req.SHA, req.Expiry)
+ if err != nil {
+ return utils.SendError(c, fiber.StatusInternalServerError, utils.FHE002, "secrets", &err)
+ }
+
+ c.JSON(response{Id: id})
+ return c.SendStatus(fiber.StatusOK)
+}
diff --git a/backend/main.go b/backend/main.go
new file mode 100644
index 0000000..f5bb74f
--- /dev/null
+++ b/backend/main.go
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package main
+
+import (
+ "database/sql"
+ "embed"
+ "fmt"
+ "net/http"
+ "seif/db_ops"
+ "seif/flags"
+ "seif/handlers/get_init_data"
+ "seif/handlers/get_secret"
+ "seif/handlers/get_secret_status"
+ "seif/handlers/put_secret"
+ "seif/params"
+ "seif/utils"
+
+ "github.com/gofiber/fiber/v2"
+ "github.com/gofiber/fiber/v2/middleware/filesystem"
+ "github.com/gofiber/fiber/v2/middleware/recover"
+ _ "modernc.org/sqlite"
+)
+
+//go:embed static/*
+var static embed.FS
+
+func main() {
+ flags.Parse()
+
+ dbIsNew := !utils.FileExists(params.DbPath)
+
+ // FIXME don't open a new connection for each operation
+ var err error
+ params.Db, err = sql.Open("sqlite", params.DbPath)
+ if err != nil {
+ panic(err)
+ }
+ defer params.Db.Close()
+
+ // Populates db
+ if dbIsNew {
+ db_ops.InitDb()
+ } else {
+ // check db version
+
+ row := params.Db.QueryRow("SELECT VERSION FROM VERSION")
+ var dbVersion int
+ if err := row.Scan(&dbVersion); err != nil {
+ panic(err)
+ }
+ if dbVersion != db_ops.DB_VERSION {
+ utils.Abort("DB version is %d but should be %d. Please upgrade the database or the application.", dbVersion, db_ops.DB_VERSION)
+ }
+
+ // Backup
+
+ db_ops.Backup()
+ }
+
+ // Maintenance
+
+ go db_ops.StartMaint()
+
+ // server
+
+ app := fiber.New(fiber.Config{ServerHeader: "seif v." + params.VERSION, AppName: "seif", DisableStartupMessage: true})
+
+ app.Use(recover.New())
+
+ app.Use("/", filesystem.New(filesystem.Config{
+ Root: http.FS(static),
+ PathPrefix: "static",
+ }))
+
+ app.Get("/api/getInitData", get_init_data.GetInitData)
+ app.Delete("/api/getSecret", get_secret.GetSecret)
+ app.Get("/api/getSecretStatus", get_secret_status.GetSecretStatus)
+ app.Put("/api/putSecret", put_secret.PutSecret)
+
+ fmt.Println(" - server on port", params.Port)
+ fmt.Printf(" - all ok. Please open http://localhost:%d\n", params.Port)
+ app.Listen(fmt.Sprintf(":%d", params.Port))
+}
diff --git a/backend/params/globals.go b/backend/params/globals.go
new file mode 100644
index 0000000..b933056
--- /dev/null
+++ b/backend/params/globals.go
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package params
+
+import (
+ "database/sql"
+ "fmt"
+ "sync"
+)
+
+const VERSION = "v0.0.0"
+
+// https://manytools.org/hacker-tools/ascii-banner/, profile "Small Slant"
+const banner = ` ____ _ ___
+ / __/__ (_) _/
+ _\ \/ -_) / _/
+/___/\__/_/_/`
+
+var Lock sync.Mutex
+
+var Db *sql.DB
+
+func init() {
+ fmt.Println(banner, VERSION)
+ fmt.Println()
+}
diff --git a/backend/params/params.go b/backend/params/params.go
new file mode 100644
index 0000000..7e5dfd6
--- /dev/null
+++ b/backend/params/params.go
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package params
+
+var DbPath string
+var Port int
+var MaxDays int
+var MaxBytes int
diff --git a/backend/utils/errors.go b/backend/utils/errors.go
new file mode 100644
index 0000000..eabf45b
--- /dev/null
+++ b/backend/utils/errors.go
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package utils
+
+var FHE001 = "cannot read from %s"
+var FHE002 = "cannot write to %s"
+var FHE003 = "residual error on resultset"
+var FHE004 = "%s is malformed"
+var FHE005 = "secret is too long"
+var FHE006 = "invalid expiry, must be between 1 and %s days"
+var FHE007 = "cannot generate random key"
diff --git a/backend/utils/utils.go b/backend/utils/utils.go
new file mode 100644
index 0000000..1006ebe
--- /dev/null
+++ b/backend/utils/utils.go
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024- Germano Rizzo
+ *
+ * This file is part of Seif.
+ *
+ * Seif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Seif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Seif. If not, see .
+ */
+package utils
+
+import (
+ "encoding/json"
+ "fmt"
+ "os"
+
+ "github.com/gofiber/fiber/v2"
+)
+
+func Abort(msg string, a ...any) {
+ fmt.Fprintf(os.Stderr, "FATAL: %s\n", fmt.Sprintf(msg, a...))
+ os.Exit(-1)
+}
+
+func FileExists(filePath string) bool {
+ _, err := os.Stat(filePath)
+ return !os.IsNotExist(err)
+}
+
+type errorr struct {
+ Code string `json:"code"`
+ Object string `json:"object"`
+ Error *string `json:"error"`
+}
+
+func SendError(c *fiber.Ctx, status int, errCode string, obj string, err *error) error {
+ var errString *string
+ if err != nil {
+ _errString := (*err).Error()
+ errString = &_errString
+ }
+ e := errorr{
+ Code: errCode,
+ Object: obj,
+ Error: errString,
+ }
+
+ str, _ := json.Marshal(e)
+ fmt.Fprintf(os.Stderr, "%s\n", str)
+ c.JSON(e)
+ return c.SendStatus(status)
+}
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000..a547bf3
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/index.html b/frontend/index.html
similarity index 100%
rename from index.html
rename to frontend/index.html
diff --git a/jsconfig.json b/frontend/jsconfig.json
similarity index 100%
rename from jsconfig.json
rename to frontend/jsconfig.json
diff --git a/package-lock.json b/frontend/package-lock.json
similarity index 87%
rename from package-lock.json
rename to frontend/package-lock.json
index fad2e23..26376a1 100644
--- a/package-lock.json
+++ b/frontend/package-lock.json
@@ -18,13 +18,13 @@
}
},
"node_modules/@ampproject/remapping": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
- "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"dependencies": {
- "@jridgewell/gen-mapping": "^0.3.0",
- "@jridgewell/trace-mapping": "^0.3.9"
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
@@ -383,32 +383,32 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dev": true,
"dependencies": {
- "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
+ "@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"engines": {
"node": ">=6.0.0"
@@ -421,9 +421,9 @@
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.19",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -431,9 +431,9 @@
}
},
"node_modules/@sveltejs/vite-plugin-svelte": {
- "version": "2.4.6",
- "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.4.6.tgz",
- "integrity": "sha512-zO79p0+DZnXPnF0ltIigWDx/ux7Ni+HRaFOw720Qeivc1azFUrJxTl0OryXVibYNx1hCboGia1NRV3x8RNv4cA==",
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.5.3.tgz",
+ "integrity": "sha512-erhNtXxE5/6xGZz/M9eXsmI7Pxa6MS7jyTy06zN3Ck++ldrppOnOlJwHHTsMC7DHDQdgUp4NAc4cDNQ9eGdB/w==",
"dev": true,
"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^1.0.4",
@@ -448,7 +448,7 @@
"node": "^14.18.0 || >= 16"
},
"peerDependencies": {
- "svelte": "^3.54.0 || ^4.0.0",
+ "svelte": "^3.54.0 || ^4.0.0 || ^5.0.0-next.0",
"vite": "^4.0.0"
}
},
@@ -470,15 +470,15 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz",
- "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
+ "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
"node_modules/acorn": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
- "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -497,9 +497,9 @@
}
},
"node_modules/axobject-query": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
- "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.0.0.tgz",
+ "integrity": "sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==",
"dev": true,
"dependencies": {
"dequal": "^2.0.3"
@@ -519,9 +519,9 @@
}
},
"node_modules/crypto-js": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz",
- "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw=="
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
+ "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"node_modules/css-tree": {
"version": "2.3.1",
@@ -656,9 +656,9 @@
"dev": true
},
"node_modules/magic-string": {
- "version": "0.30.3",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz",
- "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==",
+ "version": "0.30.8",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
+ "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -680,9 +680,9 @@
"dev": true
},
"node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"funding": [
{
@@ -715,9 +715,9 @@
"dev": true
},
"node_modules/postcss": {
- "version": "8.4.30",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz",
- "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==",
+ "version": "8.4.35",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz",
+ "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==",
"dev": true,
"funding": [
{
@@ -734,7 +734,7 @@
}
],
"dependencies": {
- "nanoid": "^3.3.6",
+ "nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
@@ -743,9 +743,9 @@
}
},
"node_modules/rollup": {
- "version": "3.29.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.2.tgz",
- "integrity": "sha512-CJouHoZ27v6siztc21eEQGo0kIcE5D1gVPA571ez0mMYb25LGYGKnVNXpEj5MGlepmDWGXNjDB5q7uNiPHC11A==",
+ "version": "3.29.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz",
+ "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
@@ -768,23 +768,24 @@
}
},
"node_modules/svelte": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.1.tgz",
- "integrity": "sha512-LpLqY2Jr7cRxkrTc796/AaaoMLF/1ax7cto8Ot76wrvKQhrPmZ0JgajiWPmg9mTSDqO16SSLiD17r9MsvAPTmw==",
+ "version": "4.2.12",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz",
+ "integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.1",
"@jridgewell/sourcemap-codec": "^1.4.15",
"@jridgewell/trace-mapping": "^0.3.18",
+ "@types/estree": "^1.0.1",
"acorn": "^8.9.0",
"aria-query": "^5.3.0",
- "axobject-query": "^3.2.1",
+ "axobject-query": "^4.0.0",
"code-red": "^1.0.3",
"css-tree": "^2.3.1",
"estree-walker": "^3.0.3",
"is-reference": "^3.0.1",
"locate-character": "^3.0.0",
- "magic-string": "^0.30.0",
+ "magic-string": "^0.30.4",
"periscopic": "^3.1.0"
},
"engines": {
@@ -804,18 +805,18 @@
}
},
"node_modules/sweetalert2": {
- "version": "11.7.28",
- "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.7.28.tgz",
- "integrity": "sha512-9895DVuYTDlV4Hx4IJablFKMdSqzwpy0PKycztbO4cXnOeVMmw55weOq4gcZAh3/tAyunCKjApFDrlSAcswwcA==",
+ "version": "11.10.6",
+ "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.6.tgz",
+ "integrity": "sha512-CINZPLZXZRSZqSOE7H7j1F7X8e8O1kLOiXPmtJn1DYxvXsKBr3d16d90+IcwTTs7dJww20h8r8QIxIwsLGX+6A==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/limonte"
}
},
"node_modules/vite": {
- "version": "4.4.9",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz",
- "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==",
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz",
+ "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==",
"dev": true,
"dependencies": {
"esbuild": "^0.18.10",
@@ -868,12 +869,12 @@
}
},
"node_modules/vitefu": {
- "version": "0.2.4",
- "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.4.tgz",
- "integrity": "sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==",
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz",
+ "integrity": "sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==",
"dev": true,
"peerDependencies": {
- "vite": "^3.0.0 || ^4.0.0"
+ "vite": "^3.0.0 || ^4.0.0 || ^5.0.0"
},
"peerDependenciesMeta": {
"vite": {
@@ -882,4 +883,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/package.json b/frontend/package.json
similarity index 100%
rename from package.json
rename to frontend/package.json
diff --git a/public/favicon.png b/frontend/public/favicon.png
similarity index 100%
rename from public/favicon.png
rename to frontend/public/favicon.png
diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte
new file mode 100644
index 0000000..c5483ff
--- /dev/null
+++ b/frontend/src/App.svelte
@@ -0,0 +1,233 @@
+
+
+{#if !!initData}
+
+
+
+
+
+
+ {#if token == ""}
+ {#if link == ""}
+
+ Input your secret here. It will be encrypted and saved to the
+ server, and an one-time link will be generated.
+
+
+
+
+
+ Expires after
+
+
+
+ days
+
+
+
+
+ {:else}
+
+
+
+
+
+
+
+
+
+
+ Note: if the user inputs the wrong key, the secret will not be
+ revealed but it will be "used" all the same, and the link will
+ be invalid.
+
+ {/if}
+ {:else if contents == ""}
+
+
+
+ {:else}
+
+ {/if}
+
+
+
+
+{/if}
diff --git a/src/ClipboardableField.svelte b/frontend/src/ClipboardableField.svelte
similarity index 61%
rename from src/ClipboardableField.svelte
rename to frontend/src/ClipboardableField.svelte
index 748c29e..a345937 100644
--- a/src/ClipboardableField.svelte
+++ b/frontend/src/ClipboardableField.svelte
@@ -1,4 +1,22 @@
diff --git a/src/app.css b/frontend/src/app.css
similarity index 100%
rename from src/app.css
rename to frontend/src/app.css
diff --git a/src/main.js b/frontend/src/main.js
similarity index 100%
rename from src/main.js
rename to frontend/src/main.js
diff --git a/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
similarity index 100%
rename from src/vite-env.d.ts
rename to frontend/src/vite-env.d.ts
diff --git a/svelte.config.js b/frontend/svelte.config.js
similarity index 100%
rename from svelte.config.js
rename to frontend/svelte.config.js
diff --git a/vite.config.js b/frontend/vite.config.js
similarity index 73%
rename from vite.config.js
rename to frontend/vite.config.js
index 8cdd22b..346a773 100644
--- a/vite.config.js
+++ b/frontend/vite.config.js
@@ -4,7 +4,9 @@ import { svelte } from '@sveltejs/vite-plugin-svelte'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()],
- // build: {
+ build: {
+ outDir: '../backend/static',
+ emptyOutDir: true,
// sourcemap: true,
- // },
+ },
})
diff --git a/seif.yaml b/seif.yaml
deleted file mode 100644
index 405b787..0000000
--- a/seif.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-storedStatements:
- - id: S1
- # 10 random HEX digits = 2^40 possible values
- sql: INSERT INTO SECRETS(ID, IV, SECRET, SHA, EXPIRY, TS) VALUES (LOWER(SUBSTRING(PRINTF('%X', RANDOM()), 1, 10)), :iv, :secret, :sha, :expiry, CURRENT_TIMESTAMP) RETURNING ID
- - id: S2
- sql: SELECT 1 FROM SECRETS WHERE ID = :id
- - id: S3
- sql: DELETE FROM SECRETS WHERE ID = :id RETURNING IV, SECRET, SHA
-useOnlyStoredStatements: true
-macros:
- - id: INIT
- statements:
- - CREATE TABLE SECRETS (
- ID TEXT PRIMARY KEY,
- IV TEXT,
- SECRET TEXT,
- SHA TEXT,
- EXPIRY INTEGER,
- TS TEXT)
- execution:
- onCreate: true
- - id: CLEANUP
- statements:
- - DELETE FROM SECRETS WHERE TS < DATETIME('now', '-' || EXPIRY || ' days')
- execution:
- period: 5 # every 5 minutes
diff --git a/src/App.svelte b/src/App.svelte
deleted file mode 100644
index a1f1c8f..0000000
--- a/src/App.svelte
+++ /dev/null
@@ -1,234 +0,0 @@
-
-
-
-
-
-
-
-
- {#if token == ""}
- {#if link == ""}
-
- Input your secret here. It will be encrypted and saved to the
- server, and an one-time link will be generated.
-
-
-
-
-
- Expires after
-
-
-
- days
-
-
-
-
- {:else}
-
-
-
-
-
-
-
-
-
-
- Note: if the user inputs the wrong key, the secret will not be
- revealed but it will be "used" all the same, and the link will be
- invalid.
-