Add auth-managed proxy UI improvements
This commit is contained in:
@ -1,15 +1,24 @@
|
||||
package noodle
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.mills.io/bitcask/v2"
|
||||
)
|
||||
|
||||
var ErrUserNotFound = errors.New("user not found")
|
||||
var ErrLastAdminRemoval = errors.New("cannot remove the last admin")
|
||||
|
||||
type Database struct {
|
||||
connection *bitcask.Bitcask
|
||||
Handle *bitcask.Collection
|
||||
Users *bitcask.Collection
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewDatabase(path string) *Database {
|
||||
@ -20,6 +29,7 @@ func NewDatabase(path string) *Database {
|
||||
return &Database{
|
||||
connection: db,
|
||||
Handle: db.Collection("noodles"),
|
||||
Users: db.Collection("users"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,6 +43,9 @@ func (db *Database) MakeID() string {
|
||||
}
|
||||
|
||||
func (db *Database) GetAll() []Noodle {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []Noodle
|
||||
if err := db.Handle.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
@ -42,6 +55,9 @@ func (db *Database) GetAll() []Noodle {
|
||||
}
|
||||
|
||||
func (db *Database) GetAllGeneric() []interface{} {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []interface{}
|
||||
if err := db.Handle.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
@ -51,6 +67,9 @@ func (db *Database) GetAllGeneric() []interface{} {
|
||||
}
|
||||
|
||||
func (db *Database) Get(id string) Noodle {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var item Noodle
|
||||
log.Printf("Looking up noodle key='%s'", id)
|
||||
log.Printf("key='%s' exists=%t", id, db.Handle.Has(id))
|
||||
@ -62,6 +81,9 @@ func (db *Database) Get(id string) Noodle {
|
||||
}
|
||||
|
||||
func (db *Database) Add(item Noodle) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
if err := db.Handle.Add(item.Id, item); err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
@ -70,6 +92,9 @@ func (db *Database) Add(item Noodle) error {
|
||||
}
|
||||
|
||||
func (db *Database) Update(item Noodle) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
if err := db.Handle.Add(item.Id, item); err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
@ -78,6 +103,9 @@ func (db *Database) Update(item Noodle) error {
|
||||
}
|
||||
|
||||
func (db *Database) Delete(id string) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
if err := db.Handle.Delete(id); err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
@ -88,3 +116,248 @@ func (db *Database) Delete(id string) error {
|
||||
func (db *Database) Close() error {
|
||||
return db.connection.Close()
|
||||
}
|
||||
|
||||
func (db *Database) GetAllUsers() []User {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []User
|
||||
if err := db.Users.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (db *Database) GetUserByUsername(username string) (User, error) {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []User
|
||||
if err := db.Users.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
for _, user := range data {
|
||||
if user.Username == username {
|
||||
return user, nil
|
||||
}
|
||||
}
|
||||
|
||||
return User{}, ErrUserNotFound
|
||||
}
|
||||
|
||||
func (db *Database) AddUser(user User) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []User
|
||||
if err := db.Users.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
}
|
||||
for _, existing := range data {
|
||||
if existing.Username == user.Username {
|
||||
return fmt.Errorf("user %q already exists", user.Username)
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.Users.Add(user.Id, user); err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) UpdateUser(user User) error {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
if err := db.Users.Add(user.Id, user); err != nil {
|
||||
log.Print(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) SetUserRole(username, role string) (User, error) {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []User
|
||||
if err := db.Users.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
var target User
|
||||
found := false
|
||||
adminCount := 0
|
||||
for _, user := range data {
|
||||
if user.Role == UserRoleAdmin {
|
||||
adminCount++
|
||||
}
|
||||
if user.Username == username {
|
||||
target = user
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return User{}, ErrUserNotFound
|
||||
}
|
||||
if target.Role == UserRoleAdmin && role != UserRoleAdmin && adminCount <= 1 {
|
||||
return User{}, ErrLastAdminRemoval
|
||||
}
|
||||
|
||||
target.Role = role
|
||||
if err := db.Users.Add(target.Id, target); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (db *Database) SetUserPassword(username, passwordHash string) (User, error) {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []User
|
||||
if err := db.Users.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
for _, user := range data {
|
||||
if user.Username != username {
|
||||
continue
|
||||
}
|
||||
user.PasswordHash = passwordHash
|
||||
if err := db.Users.Add(user.Id, user); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
return User{}, ErrUserNotFound
|
||||
}
|
||||
|
||||
func (db *Database) DeleteUser(username string) (User, error) {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var data []User
|
||||
if err := db.Users.List(&data); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
|
||||
var target User
|
||||
found := false
|
||||
adminCount := 0
|
||||
for _, user := range data {
|
||||
if user.Role == UserRoleAdmin {
|
||||
adminCount++
|
||||
}
|
||||
if user.Username == username {
|
||||
target = user
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return User{}, ErrUserNotFound
|
||||
}
|
||||
if target.Role == UserRoleAdmin && adminCount <= 1 {
|
||||
return User{}, ErrLastAdminRemoval
|
||||
}
|
||||
|
||||
if err := db.Users.Delete(target.Id); err != nil {
|
||||
log.Print(err)
|
||||
return User{}, err
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
|
||||
func (db *Database) SetIsUp(id string, isUp bool) (Noodle, error) {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var item Noodle
|
||||
if err := db.Handle.Get(id, &item); err != nil {
|
||||
log.Print(err)
|
||||
return Noodle{}, err
|
||||
}
|
||||
|
||||
item.IsUp = isUp
|
||||
if err := db.Handle.Add(item.Id, item); err != nil {
|
||||
log.Print(err)
|
||||
return Noodle{}, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (db *Database) DeleteByID(id string) (Noodle, error) {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var item Noodle
|
||||
if err := db.Handle.Get(id, &item); err != nil {
|
||||
log.Print(err)
|
||||
return Noodle{}, err
|
||||
}
|
||||
|
||||
if err := db.Handle.Delete(id); err != nil {
|
||||
log.Print(err)
|
||||
return Noodle{}, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (db *Database) TickExpirations() []Noodle {
|
||||
db.mu.Lock()
|
||||
defer db.mu.Unlock()
|
||||
|
||||
var noodles []Noodle
|
||||
if err := db.Handle.List(&noodles); err != nil {
|
||||
log.Print(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var stopped []Noodle
|
||||
for _, item := range noodles {
|
||||
if !item.IsUp {
|
||||
continue
|
||||
}
|
||||
|
||||
if item.Expiration <= 0 {
|
||||
item.IsUp = false
|
||||
stopped = append(stopped, item)
|
||||
if err := db.Handle.Delete(item.Id); err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
item.Expiration -= time.Second
|
||||
if item.Expiration <= 0 {
|
||||
item.Expiration = 0
|
||||
item.IsUp = false
|
||||
stopped = append(stopped, item)
|
||||
if err := db.Handle.Delete(item.Id); err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if err := db.Handle.Add(item.Id, item); err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
return stopped
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user