rename go packages

This commit is contained in:
1e99 2025-05-21 17:15:55 +02:00
parent a48e22ba5f
commit fc04b6c9cd
9 changed files with 133 additions and 133 deletions

28
main.go
View file

@ -10,15 +10,15 @@ import (
"strconv" "strconv"
"time" "time"
"git.1e99.eu/1e99/passed/routes" "git.1e99.eu/1e99/passed/password"
"git.1e99.eu/1e99/passed/storage" "git.1e99.eu/1e99/passed/route"
) )
//go:embed static/* //go:embed static/*
var embedFS embed.FS var embedFS embed.FS
func run() error { func run() error {
store, err := newStore() storage, err := newStorage()
if err != nil { if err != nil {
return err return err
} }
@ -39,12 +39,12 @@ func run() error {
handler := http.Handler(mux) handler := http.Handler(mux)
mux.Handle("GET /", http.FileServerFS(staticFS)) mux.Handle("GET /", http.FileServerFS(staticFS))
mux.Handle("POST /api/password", routes.CreatePassword(store, maxPasswordLength)) mux.Handle("POST /api/password", route.CreatePassword(storage, maxPasswordLength))
mux.Handle("GET /api/password/{id}", routes.GetPassword(store)) mux.Handle("GET /api/password/{id}", route.GetPassword(storage))
mux.Handle("HEAD /api/password/{id}", routes.HasPassword(store)) mux.Handle("HEAD /api/password/{id}", route.HasPassword(storage))
if logRequests { if logRequests {
handler = routes.Logger(handler) handler = route.Logger(handler)
} }
log.Printf("Listening on %s.", address) log.Printf("Listening on %s.", address)
@ -76,15 +76,15 @@ func newStaticFS() (sfs fs.FS, err error) {
} }
} }
func newStore() (store storage.Store, err error) { func newStorage() (storage password.Storage, err error) {
var storeType string var storageType string
var clearInterval int var clearInterval int
env("PASSED_STORE_TYPE", &storeType, "ram") env("PASSED_STORE_TYPE", &storageType, "ram")
env("PASSED_STORE_CLEAR_INTERVAL", &clearInterval, "30") env("PASSED_STORE_CLEAR_INTERVAL", &clearInterval, "30")
switch storeType { switch storageType {
case "ram": case "ram":
store = storage.NewRamStore() storage = password.NewRamStorage()
case "dir", "directory": case "dir", "directory":
var path string var path string
env("PASSED_STORE_DIR_PATH", &path, "passwords") env("PASSED_STORE_DIR_PATH", &path, "passwords")
@ -94,7 +94,7 @@ func newStore() (store storage.Store, err error) {
return return
} }
store = storage.NewDirStore(path) storage = password.NewDirStorage(path)
default: default:
err = errors.New("unknown storage type") err = errors.New("unknown storage type")
return return
@ -105,7 +105,7 @@ func newStore() (store storage.Store, err error) {
for { for {
<-ticker <-ticker
err := store.ClearExpired() err := storage.ClearExpired()
if err != nil { if err != nil {
log.Printf("Failed to clear expired passwords: %s", err) log.Printf("Failed to clear expired passwords: %s", err)
continue continue

View file

@ -1,4 +1,4 @@
package storage package password
import ( import (
"encoding/gob" "encoding/gob"
@ -7,12 +7,12 @@ import (
"time" "time"
) )
func NewDirStore(path string) Store { func NewDirStorage(path string) Storage {
store := &dir{ storage := &dir{
path: path, path: path,
} }
return store return storage
} }
type dir struct { type dir struct {
@ -24,10 +24,10 @@ type dirEntry struct {
ExpiresAt time.Time ExpiresAt time.Time
} }
func (store *dir) Create(password []byte, expiresAt time.Time) (string, error) { func (s *dir) Create(password []byte, expiresAt time.Time) (string, error) {
for range 1000 { for range 1000 {
id := generateId(24) id := generateId(24)
path := store.getPath(id) path := s.getPath(id)
file, err := os.OpenFile( file, err := os.OpenFile(
path, path,
@ -59,8 +59,8 @@ func (store *dir) Create(password []byte, expiresAt time.Time) (string, error) {
return "", ErrFull return "", ErrFull
} }
func (store *dir) Get(id string) ([]byte, error) { func (s *dir) Get(id string) ([]byte, error) {
entry, err := store.getEntry(id) entry, err := s.getEntry(id)
switch { switch {
case os.IsNotExist(err): case os.IsNotExist(err):
return nil, ErrNotFound return nil, ErrNotFound
@ -71,8 +71,8 @@ func (store *dir) Get(id string) ([]byte, error) {
return entry.Password, nil return entry.Password, nil
} }
func (store *dir) Delete(id string) error { func (s *dir) Delete(id string) error {
path := store.getPath(id) path := s.getPath(id)
err := os.Remove(path) err := os.Remove(path)
if err != nil { if err != nil {
return nil return nil
@ -81,23 +81,23 @@ func (store *dir) Delete(id string) error {
return nil return nil
} }
func (store *dir) ClearExpired() error { func (s *dir) ClearExpired() error {
now := time.Now() now := time.Now()
entries, err := os.ReadDir(store.path) entries, err := os.ReadDir(s.path)
if err != nil { if err != nil {
return err return err
} }
for _, file := range entries { for _, file := range entries {
id := file.Name() id := file.Name()
entry, err := store.getEntry(id) entry, err := s.getEntry(id)
if err != nil { if err != nil {
return err return err
} }
if now.After(entry.ExpiresAt) { if now.After(entry.ExpiresAt) {
err = store.Delete(id) err = s.Delete(id)
if err != nil { if err != nil {
return err return err
} }
@ -107,8 +107,8 @@ func (store *dir) ClearExpired() error {
return nil return nil
} }
func (store *dir) getEntry(id string) (dirEntry, error) { func (s *dir) getEntry(id string) (dirEntry, error) {
path := store.getPath(id) path := s.getPath(id)
file, err := os.OpenFile( file, err := os.OpenFile(
path, path,
os.O_RDONLY, os.O_RDONLY,
@ -129,6 +129,6 @@ func (store *dir) getEntry(id string) (dirEntry, error) {
return entry, nil return entry, nil
} }
func (store *dir) getPath(id string) string { func (s *dir) getPath(id string) string {
return path.Join(store.path, id) return path.Join(s.path, id)
} }

81
password/ram.go Normal file
View file

@ -0,0 +1,81 @@
package password
import (
"sync"
"time"
)
func NewRamStorage() Storage {
storage := &ram{
passwords: make(map[string]ramEntry),
lock: sync.Mutex{},
}
return storage
}
type ram struct {
passwords map[string]ramEntry
lock sync.Mutex
}
type ramEntry struct {
Password []byte
ExpiresAt time.Time
}
func (s *ram) Create(password []byte, expiresAt time.Time) (string, error) {
s.lock.Lock()
defer s.lock.Unlock()
for range 1000 {
id := generateId(24)
_, found := s.passwords[id]
if found {
continue
}
s.passwords[id] = ramEntry{
Password: password,
ExpiresAt: expiresAt,
}
return id, nil
}
return "", ErrFull
}
func (s *ram) Get(id string) ([]byte, error) {
s.lock.Lock()
defer s.lock.Unlock()
password, found := s.passwords[id]
if !found {
return nil, ErrNotFound
}
return password.Password, nil
}
func (s *ram) Delete(id string) error {
delete(s.passwords, id)
return nil
}
func (s *ram) ClearExpired() error {
s.lock.Lock()
defer s.lock.Unlock()
time := time.Now()
for id, password := range s.passwords {
if time.After(password.ExpiresAt) {
err := s.Delete(id)
if err != nil {
return err
}
}
}
return nil
}

View file

@ -1,4 +1,4 @@
package storage package password
import ( import (
"errors" "errors"
@ -11,7 +11,7 @@ var (
ErrFull = errors.New("storage is filled") ErrFull = errors.New("storage is filled")
) )
type Store interface { type Storage interface {
Create(password []byte, expiresAt time.Time) (string, error) Create(password []byte, expiresAt time.Time) (string, error)
Get(id string) ([]byte, error) Get(id string) ([]byte, error)
Delete(id string) error Delete(id string) error

View file

@ -1,14 +1,14 @@
package routes package route
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"time" "time"
"git.1e99.eu/1e99/passed/storage" "git.1e99.eu/1e99/passed/password"
) )
func CreatePassword(store storage.Store, maxLength int) http.HandlerFunc { func CreatePassword(storage password.Storage, maxLength int) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
var reqBody struct { var reqBody struct {
// Go automatically decodes byte arrays using Base64 // Go automatically decodes byte arrays using Base64
@ -37,12 +37,12 @@ func CreatePassword(store storage.Store, maxLength int) http.HandlerFunc {
return return
} }
id, err := store.Create( id, err := storage.Create(
reqBody.Password, reqBody.Password,
time.Now().Add(expiresIn), time.Now().Add(expiresIn),
) )
switch { switch {
case err == storage.ErrFull: case err == password.ErrFull:
http.Error(res, "Insufficient storage", http.StatusInsufficientStorage) http.Error(res, "Insufficient storage", http.StatusInsufficientStorage)
return return
case err != nil: case err != nil:

View file

@ -1,18 +1,18 @@
package routes package route
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"git.1e99.eu/1e99/passed/storage" "git.1e99.eu/1e99/passed/password"
) )
func GetPassword(store storage.Store) http.HandlerFunc { func GetPassword(storage password.Storage) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
id := req.PathValue("id") id := req.PathValue("id")
password, err := store.Get(id) passwd, err := storage.Get(id)
switch { switch {
case err == storage.ErrNotFound: case err == password.ErrNotFound:
http.Error(res, "Password not found", http.StatusNotFound) http.Error(res, "Password not found", http.StatusNotFound)
return return
case err != nil: case err != nil:
@ -20,7 +20,7 @@ func GetPassword(store storage.Store) http.HandlerFunc {
return return
} }
err = store.Delete(id) err = storage.Delete(id)
if err != nil { if err != nil {
http.Error(res, "", http.StatusInternalServerError) http.Error(res, "", http.StatusInternalServerError)
return return
@ -30,7 +30,7 @@ func GetPassword(store storage.Store) http.HandlerFunc {
// Go automatically encodes byte arrays using Base64 // Go automatically encodes byte arrays using Base64
Password []byte `json:"password"` Password []byte `json:"password"`
}{ }{
Password: password, Password: passwd,
} }
err = json.NewEncoder(res).Encode(&resBody) err = json.NewEncoder(res).Encode(&resBody)
if err != nil { if err != nil {

View file

@ -1,17 +1,17 @@
package routes package route
import ( import (
"net/http" "net/http"
"git.1e99.eu/1e99/passed/storage" "git.1e99.eu/1e99/passed/password"
) )
func HasPassword(store storage.Store) http.HandlerFunc { func HasPassword(storage password.Storage) http.HandlerFunc {
return func(res http.ResponseWriter, req *http.Request) { return func(res http.ResponseWriter, req *http.Request) {
id := req.PathValue("id") id := req.PathValue("id")
_, err := store.Get(id) _, err := storage.Get(id)
switch { switch {
case err == storage.ErrNotFound: case err == password.ErrNotFound:
http.Error(res, "", http.StatusNotFound) http.Error(res, "", http.StatusNotFound)
return return
case err != nil: case err != nil:

View file

@ -1,4 +1,4 @@
package routes package route
import ( import (
"log" "log"

View file

@ -1,81 +0,0 @@
package storage
import (
"sync"
"time"
)
func NewRamStore() Store {
store := &ram{
passwords: make(map[string]ramEntry),
lock: sync.Mutex{},
}
return store
}
type ram struct {
passwords map[string]ramEntry
lock sync.Mutex
}
type ramEntry struct {
Password []byte
ExpiresAt time.Time
}
func (store *ram) Create(password []byte, expiresAt time.Time) (string, error) {
store.lock.Lock()
defer store.lock.Unlock()
for range 1000 {
id := generateId(24)
_, found := store.passwords[id]
if found {
continue
}
store.passwords[id] = ramEntry{
Password: password,
ExpiresAt: expiresAt,
}
return id, nil
}
return "", ErrFull
}
func (store *ram) Get(id string) ([]byte, error) {
store.lock.Lock()
defer store.lock.Unlock()
password, found := store.passwords[id]
if !found {
return nil, ErrNotFound
}
return password.Password, nil
}
func (store *ram) Delete(id string) error {
delete(store.passwords, id)
return nil
}
func (store *ram) ClearExpired() error {
store.lock.Lock()
defer store.lock.Unlock()
time := time.Now()
for id, password := range store.passwords {
if time.After(password.ExpiresAt) {
err := store.Delete(id)
if err != nil {
return err
}
}
}
return nil
}