forked from jriou/coller
feat: Rename password by encryption key
Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
parent
634326190c
commit
8e1dd686d3
16 changed files with 118 additions and 117 deletions
|
@ -11,7 +11,7 @@ type Config struct {
|
|||
DatabaseType string `json:"database_type"`
|
||||
DatabaseDsn string `json:"database_dsn"`
|
||||
NodeID int64 `json:"node_id"`
|
||||
PasswordLength int `json:"password_length"`
|
||||
EncryptionKeyLength int `json:"encryption_key_length"`
|
||||
ExpirationInterval int `json:"expiration_interval"`
|
||||
ListenAddress string `json:"listen_address"`
|
||||
ListenPort int `json:"listen_port"`
|
||||
|
@ -33,14 +33,14 @@ type Config struct {
|
|||
|
||||
func NewConfig() *Config {
|
||||
return &Config{
|
||||
Title: "Coller",
|
||||
DatabaseType: "sqlite",
|
||||
DatabaseDsn: "collerd.db",
|
||||
NodeID: 1,
|
||||
PasswordLength: 16,
|
||||
ExpirationInterval: 60, // 1 minute
|
||||
ListenAddress: "0.0.0.0",
|
||||
ListenPort: 8080,
|
||||
Title: "Coller",
|
||||
DatabaseType: "sqlite",
|
||||
DatabaseDsn: "collerd.db",
|
||||
NodeID: 1,
|
||||
EncryptionKeyLength: 16,
|
||||
ExpirationInterval: 60, // 1 minute
|
||||
ListenAddress: "0.0.0.0",
|
||||
ListenPort: 8080,
|
||||
Expirations: []int{
|
||||
300, // 5 minutes
|
||||
3600, // 1 hour
|
||||
|
@ -92,8 +92,8 @@ func (c *Config) Check() error {
|
|||
return fmt.Errorf("node id must be between 0 and 1023")
|
||||
}
|
||||
|
||||
if c.PasswordLength < internal.MIN_PASSWORD_LENGTH || c.PasswordLength > internal.MAX_PASSWORD_LENGTH {
|
||||
return fmt.Errorf("password length must be between %d and %d", internal.MIN_PASSWORD_LENGTH, internal.MAX_PASSWORD_LENGTH)
|
||||
if c.EncryptionKeyLength < internal.MIN_ENCRYPTION_KEY_LENGTH || c.EncryptionKeyLength > internal.MAX_ENCRYPTION_KEY_LENGTH {
|
||||
return fmt.Errorf("encryption key length must be between %d and %d", internal.MIN_ENCRYPTION_KEY_LENGTH, internal.MAX_ENCRYPTION_KEY_LENGTH)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ func (d *Database) Get(id string) (*Note, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (d *Database) Create(content []byte, password string, encrypted bool, expiration int, deleteAfterRead bool, language string) (note *Note, err error) {
|
||||
func (d *Database) Create(content []byte, encryptionKey string, encrypted bool, expiration int, deleteAfterRead bool, language string) (note *Note, err error) {
|
||||
if expiration == 0 {
|
||||
expiration = d.expiration
|
||||
}
|
||||
|
@ -148,11 +148,11 @@ func (d *Database) Create(content []byte, password string, encrypted bool, expir
|
|||
DeleteAfterRead: deleteAfterRead,
|
||||
Language: language,
|
||||
}
|
||||
if password != "" {
|
||||
if err = internal.ValidatePassword(password); err != nil {
|
||||
if encryptionKey != "" {
|
||||
if err = internal.ValidateEncryptionKey(encryptionKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
note.Content, err = internal.Encrypt(note.Content, password)
|
||||
note.Content, err = internal.Encrypt(note.Content, encryptionKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ type CreateNoteHandler struct {
|
|||
|
||||
type CreateNotePayload struct {
|
||||
Content string `json:"content"`
|
||||
Password string `json:"password"`
|
||||
EncryptionKey string `json:"encryption_key"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
Expiration int `json:"expiration"`
|
||||
DeleteAfterRead bool `json:"delete_after_read"`
|
||||
|
@ -54,7 +54,7 @@ func (h *CreateNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
note, err := h.db.Create(content, body.Password, body.Encrypted, body.Expiration, body.DeleteAfterRead, body.Language)
|
||||
note, err := h.db.Create(content, body.EncryptionKey, body.Encrypted, body.Expiration, body.DeleteAfterRead, body.Language)
|
||||
if err != nil {
|
||||
WriteError(w, "could not create note", err)
|
||||
return
|
||||
|
@ -99,7 +99,7 @@ func (h *GetProtectedNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
password := vars["password"]
|
||||
encryptionKey := vars["encryptionKey"]
|
||||
|
||||
note, err := h.db.Get(id)
|
||||
|
||||
|
@ -111,8 +111,8 @@ func (h *GetProtectedNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
|||
return
|
||||
}
|
||||
|
||||
if password != "" && note.Encrypted {
|
||||
note.Content, err = internal.Decrypt(note.Content, password)
|
||||
if encryptionKey != "" && note.Encrypted {
|
||||
note.Content, err = internal.Decrypt(note.Content, encryptionKey)
|
||||
if err != nil {
|
||||
WriteError(w, "could not decrypt note", err)
|
||||
return
|
||||
|
|
|
@ -109,15 +109,15 @@ func (h *CreateNoteWithFormHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
|||
}
|
||||
|
||||
h.logger.Debug("checking inputs")
|
||||
noPassword := r.FormValue("no-password")
|
||||
password := r.FormValue("password")
|
||||
noEncryption := r.FormValue("no-encryption")
|
||||
encryptionKey := r.FormValue("encryption-key")
|
||||
expiration := r.FormValue("expiration")
|
||||
deleteAfterRead := r.FormValue("delete-after-read")
|
||||
language := r.FormValue("language")
|
||||
|
||||
if password == "" && noPassword == "" {
|
||||
h.logger.Debug("generating password")
|
||||
password = internal.GenerateChars(passwordLength)
|
||||
if encryptionKey == "" && noEncryption == "" {
|
||||
h.logger.Debug("generating encryption key")
|
||||
encryptionKey = internal.GenerateChars(encryptionKeyLength)
|
||||
}
|
||||
|
||||
h.logger.Debug("computing expiration")
|
||||
|
@ -129,7 +129,7 @@ func (h *CreateNoteWithFormHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
|||
}
|
||||
|
||||
h.logger.Debug("saving note to the database")
|
||||
note, err := h.db.Create(content, password, password != "", expirationInt, deleteAfterRead != "", language)
|
||||
note, err := h.db.Create(content, encryptionKey, encryptionKey != "", expirationInt, deleteAfterRead != "", language)
|
||||
if err != nil {
|
||||
h.PageData.Err = err
|
||||
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||
|
@ -143,8 +143,8 @@ func (h *CreateNoteWithFormHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
|||
}
|
||||
|
||||
h.PageData.URL = fmt.Sprintf("%s%s/%s", scheme, r.Host, note.ID)
|
||||
if password != "" {
|
||||
h.PageData.URL += "/" + password
|
||||
if encryptionKey != "" {
|
||||
h.PageData.URL += "/" + encryptionKey
|
||||
}
|
||||
|
||||
h.logger.Debug("rendering page")
|
||||
|
@ -197,7 +197,7 @@ func (h *GetProtectedWebNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
|
|||
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
password := vars["password"]
|
||||
encryptionKey := vars["encryptionKey"]
|
||||
|
||||
note, err := h.db.Get(id)
|
||||
|
||||
|
@ -213,8 +213,8 @@ func (h *GetProtectedWebNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Re
|
|||
return
|
||||
}
|
||||
|
||||
if password != "" && note.Encrypted {
|
||||
note.Content, err = internal.Decrypt(note.Content, password)
|
||||
if encryptionKey != "" && note.Encrypted {
|
||||
note.Content, err = internal.Decrypt(note.Content, encryptionKey)
|
||||
if err != nil {
|
||||
h.PageData.Err = fmt.Errorf("could not decrypt note: %v", err)
|
||||
h.Templates.ExecuteTemplate(w, templateName, h.PageData)
|
||||
|
|
|
@ -16,10 +16,10 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
passwordLength = internal.MIN_PASSWORD_LENGTH
|
||||
supportedOSes = []string{"linux", "darwin"}
|
||||
supportedArches = []string{"amd64", "arm64"}
|
||||
supportedClients = []string{"coller", "copier"}
|
||||
encryptionKeyLength = internal.MIN_ENCRYPTION_KEY_LENGTH
|
||||
supportedOSes = []string{"linux", "darwin"}
|
||||
supportedArches = []string{"amd64", "arm64"}
|
||||
supportedClients = []string{"coller", "copier"}
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
|
@ -41,8 +41,8 @@ func NewServer(logger *slog.Logger, db *Database, config *Config, version string
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *Server) SetPasswordLength(length int) {
|
||||
passwordLength = length
|
||||
func (s *Server) SetEncryptionKeyLength(length int) {
|
||||
encryptionKeyLength = length
|
||||
}
|
||||
|
||||
func (s *Server) SetMetrics(metrics *Metrics) {
|
||||
|
@ -100,7 +100,7 @@ func (s *Server) Start() error {
|
|||
|
||||
// API
|
||||
r.Path("/api/note").Handler(&CreateNoteHandler{logger: s.logger, db: s.db, maxUploadSize: s.config.MaxUploadSize}).Methods("POST")
|
||||
r.Path("/{id:[a-zA-Z0-9]+}/{password:[a-zA-Z0-9]+}").Handler(&GetProtectedNoteHandler{logger: s.logger, db: s.db}).Methods("GET")
|
||||
r.Path("/{id:[a-zA-Z0-9]+}/{encryptionKey:[a-zA-Z0-9]+}").Handler(&GetProtectedNoteHandler{logger: s.logger, db: s.db}).Methods("GET")
|
||||
r.Path("/{id:[a-zA-Z0-9]+}").Handler(&GetNoteHandler{logger: s.logger, db: s.db}).Methods("GET")
|
||||
|
||||
// Web pages
|
||||
|
@ -150,7 +150,7 @@ func (s *Server) Start() error {
|
|||
logger: s.logger,
|
||||
db: s.db,
|
||||
}
|
||||
r.Path("/{id:[a-zA-Z0-9]+}/{password:[a-zA-Z0-9]+}.html").Handler(protectedWebNoteHandler).Methods("GET")
|
||||
r.Path("/{id:[a-zA-Z0-9]+}/{encryptionKey:[a-zA-Z0-9]+}.html").Handler(protectedWebNoteHandler).Methods("GET")
|
||||
|
||||
webNoteHandler := &GetWebNoteHandler{
|
||||
Templates: templates,
|
||||
|
|
|
@ -14,17 +14,17 @@
|
|||
<div class="container text-center justify-content-center w-75 mb-4">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-1">
|
||||
<label class="col-form-label col-form-label-sm" for="password">Password</label>
|
||||
<label class="col-form-label col-form-label-sm" for="encryption-key">Encryption key</label>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input type="password" pattern="^[a-zA-Z0-9]{16,256}$"
|
||||
title="Letters and numbers with length from 16 to 256" class="form-control" id="password"
|
||||
name="password">
|
||||
title="Letters and numbers with length from 16 to 256" class="form-control" id="encryption-key"
|
||||
name="encryption-key">
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<input type="checkbox" class="form-check-input" for="no-password" id="no-password"
|
||||
value="no-password" name="no-password">
|
||||
<label class="col-form-label col-form-label-sm" for="no-password">No password</label>
|
||||
<input type="checkbox" class="form-check-input" for="no-encryption-key" id="no-encryption-key"
|
||||
value="no-encryption-key" name="no-encryption-key">
|
||||
<label class="col-form-label col-form-label-sm" for="no-encryption-key">No encryption</label>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<input type="checkbox" class="form-check-input" for="delete-after-read" id="delete-after-read"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue