- Created backend structure with Go, including main application logic and API endpoints. - Added Docker support for both development and production environments. - Introduced frontend using Nuxt 3 with Tailwind CSS for styling. - Included configuration files for Docker and environment variables. - Established basic documentation for contributing, development, and deployment processes. - Set up .gitignore and .dockerignore files to manage ignored files in the repository.
176 lines
3.8 KiB
Go
176 lines
3.8 KiB
Go
package app
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"net/http"
|
|
"time"
|
|
|
|
"go.etcd.io/bbolt"
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
func (a *App) index(rw http.ResponseWriter, req *http.Request) {
|
|
s := a.getSession(req)
|
|
if s == nil {
|
|
http.Redirect(rw, req, "/login", 302)
|
|
return
|
|
}
|
|
|
|
tokens := []string{}
|
|
prefix := "http://example.com"
|
|
a.db.View(func(tx *bbolt.Tx) error {
|
|
b := tx.Bucket([]byte("users"))
|
|
if b == nil {
|
|
return nil
|
|
}
|
|
uRaw := b.Get([]byte(s.Username))
|
|
if uRaw == nil {
|
|
return nil
|
|
}
|
|
u := User{}
|
|
json.Unmarshal(uRaw, &u)
|
|
tokens = u.Tokens
|
|
|
|
config := tx.Bucket([]byte("config"))
|
|
if config != nil {
|
|
prefix = string(config.Get([]byte("prefix")))
|
|
}
|
|
return nil
|
|
})
|
|
|
|
a.ExecuteTemplate(rw, "index.tmpl", struct {
|
|
Page Page
|
|
Session *Session
|
|
UploadTokens []string
|
|
Prefix string
|
|
}{
|
|
Page: a.getPage(req),
|
|
Session: s,
|
|
UploadTokens: tokens,
|
|
Prefix: prefix,
|
|
})
|
|
}
|
|
|
|
func (a *App) login(rw http.ResponseWriter, req *http.Request) {
|
|
if req.Method == "POST" {
|
|
u := a.getUser(req.FormValue("user"), req.FormValue("pass"))
|
|
if u != nil {
|
|
session := make([]byte, 32)
|
|
rand.Read(session)
|
|
http.SetCookie(rw, &http.Cookie{
|
|
Name: "session",
|
|
Expires: time.Now().Add(time.Hour * 24 * 7),
|
|
Value: hex.EncodeToString(session),
|
|
})
|
|
s := &Session{
|
|
ID: hex.EncodeToString(session),
|
|
Username: req.FormValue("user"),
|
|
TempAdmin: u.Auths.Has("tempadmin"),
|
|
}
|
|
a.saveSession(s)
|
|
http.Redirect(rw, req, "/", 302)
|
|
return
|
|
}
|
|
}
|
|
a.ExecuteTemplate(rw, "login.tmpl", struct {
|
|
Page Page
|
|
}{
|
|
Page: a.getPage(req),
|
|
})
|
|
}
|
|
|
|
func (a *App) logout(rw http.ResponseWriter, req *http.Request) {
|
|
s := a.getSession(req)
|
|
if s != nil {
|
|
a.deleteSession(s)
|
|
}
|
|
http.Redirect(rw, req, "/login", 302)
|
|
return
|
|
}
|
|
|
|
func (a *App) generateToken(rw http.ResponseWriter, req *http.Request) {
|
|
s := a.getSession(req)
|
|
if s == nil || !s.Auths.Has(AUTH_UPLOAD) {
|
|
http.Redirect(rw, req, "/", 302)
|
|
return
|
|
}
|
|
tokenRaw := make([]byte, 16)
|
|
_, err := rand.Read(tokenRaw)
|
|
if err != nil {
|
|
rw.WriteHeader(500)
|
|
return
|
|
}
|
|
token := hex.EncodeToString(tokenRaw)
|
|
a.db.Update(func(tx *bbolt.Tx) error {
|
|
ub, err := tx.CreateBucketIfNotExists([]byte("users"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
uRaw := ub.Get([]byte(s.Username))
|
|
if uRaw == nil {
|
|
return nil
|
|
}
|
|
u := User{}
|
|
err = json.Unmarshal(uRaw, &u)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
u.Tokens = append(u.Tokens, token)
|
|
buf, err := json.Marshal(u)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ub.Put([]byte(s.Username), buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
b, err := tx.CreateBucketIfNotExists([]byte("tokens"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return b.Put([]byte(token), []byte(s.Username))
|
|
})
|
|
http.Redirect(rw, req, "/", 302)
|
|
}
|
|
|
|
func (a *App) changePassword(rw http.ResponseWriter, req *http.Request) {
|
|
s := a.getSession(req)
|
|
if s == nil {
|
|
http.Redirect(rw, req, "/", 302)
|
|
return
|
|
}
|
|
|
|
if req.Method == "POST" {
|
|
req.ParseForm()
|
|
password := req.FormValue("pass")
|
|
a.db.Update(func(tx *bbolt.Tx) error {
|
|
users, err := tx.CreateBucketIfNotExists([]byte("users"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
u := User{}
|
|
raw := users.Get([]byte(s.Username))
|
|
if raw != nil {
|
|
json.Unmarshal(raw, &u)
|
|
}
|
|
if password != "" {
|
|
u.Pass, _ = bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
}
|
|
raw, _ = json.Marshal(u)
|
|
users.Put([]byte(s.Username), raw)
|
|
return nil
|
|
})
|
|
http.Redirect(rw, req, "/", 302)
|
|
}
|
|
|
|
a.ExecuteTemplate(rw, "password.tmpl", struct {
|
|
Page Page
|
|
Session *Session
|
|
}{
|
|
Page: a.getPage(req),
|
|
Session: s,
|
|
})
|
|
}
|