2020-11-13 18:45:42 +00:00
|
|
|
package user
|
|
|
|
|
|
|
|
import (
|
2021-01-09 20:49:48 +00:00
|
|
|
"sync"
|
2021-06-29 10:34:36 +00:00
|
|
|
"time"
|
2021-04-19 16:39:25 +00:00
|
|
|
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
2020-11-13 18:45:42 +00:00
|
|
|
)
|
|
|
|
|
2021-04-12 17:40:43 +00:00
|
|
|
// UserSource shows where is the user data gotten from.
|
|
|
|
type UserSource int
|
|
|
|
|
|
|
|
const (
|
|
|
|
SourceUnknown UserSource = iota
|
|
|
|
// SourceFixed is used with users that are predefined using fixed auth
|
|
|
|
SourceFixed
|
|
|
|
// SourceRegistration is used with users that are registered through the register form
|
|
|
|
SourceRegistration
|
|
|
|
)
|
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
// User is a user.
|
|
|
|
type User struct {
|
|
|
|
// Name is a username. It must follow hypha naming rules.
|
2021-04-12 17:40:43 +00:00
|
|
|
Name string `json:"name"`
|
|
|
|
Group string `json:"group"`
|
|
|
|
Password string `json:"password"` // for fixed
|
|
|
|
HashedPassword string `json:"hashed_password"` // for registered
|
2021-06-29 10:34:36 +00:00
|
|
|
RegisteredAt time.Time `json:"registered_on"`
|
2021-04-12 17:40:43 +00:00
|
|
|
Source UserSource `json:"-"`
|
2021-01-09 20:49:48 +00:00
|
|
|
sync.RWMutex
|
2021-04-19 16:39:25 +00:00
|
|
|
|
|
|
|
// A note about why HashedPassword is string and not []byte. The reason is
|
|
|
|
// simple: golang's json marshals []byte as slice of numbers, which is not
|
|
|
|
// acceptable.
|
2020-11-14 13:03:06 +00:00
|
|
|
}
|
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
// Route — Right (more is more right)
|
|
|
|
var minimalRights = map[string]int{
|
2021-01-23 19:00:58 +00:00
|
|
|
"edit": 1,
|
|
|
|
"upload-binary": 1,
|
|
|
|
"upload-text": 1,
|
|
|
|
"rename-ask": 2,
|
|
|
|
"rename-confirm": 2,
|
|
|
|
"unattach-ask": 2,
|
|
|
|
"unattach-confirm": 2,
|
|
|
|
"update-header-links": 3,
|
|
|
|
"delete-ask": 3,
|
|
|
|
"delete-confirm": 3,
|
|
|
|
"reindex": 4,
|
2021-03-14 15:01:32 +00:00
|
|
|
"admin": 4,
|
2021-02-18 14:50:37 +00:00
|
|
|
"admin/shutdown": 4,
|
2020-11-14 14:46:04 +00:00
|
|
|
}
|
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
// Group — Right
|
|
|
|
var groupRight = map[string]int{
|
|
|
|
"anon": 0,
|
|
|
|
"editor": 1,
|
|
|
|
"trusted": 2,
|
|
|
|
"moderator": 3,
|
|
|
|
"admin": 4,
|
2020-11-14 13:03:06 +00:00
|
|
|
}
|
|
|
|
|
2021-01-24 07:30:14 +00:00
|
|
|
func EmptyUser() *User {
|
2021-01-09 20:49:48 +00:00
|
|
|
return &User{
|
|
|
|
Name: "anon",
|
|
|
|
Group: "anon",
|
|
|
|
Password: "",
|
2020-11-14 10:39:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
func (user *User) CanProceed(route string) bool {
|
|
|
|
if !AuthUsed {
|
|
|
|
return true
|
2020-11-14 10:39:18 +00:00
|
|
|
}
|
2020-11-14 13:03:06 +00:00
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
user.RLock()
|
|
|
|
defer user.RUnlock()
|
2020-11-14 10:39:18 +00:00
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
right, _ := groupRight[user.Group]
|
|
|
|
minimalRight, _ := minimalRights[route]
|
|
|
|
if right >= minimalRight {
|
|
|
|
return true
|
2020-11-14 10:39:18 +00:00
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2021-01-09 20:49:48 +00:00
|
|
|
func (user *User) isCorrectPassword(password string) bool {
|
|
|
|
user.RLock()
|
|
|
|
defer user.RUnlock()
|
2020-11-13 18:45:42 +00:00
|
|
|
|
2021-04-12 17:40:43 +00:00
|
|
|
switch user.Source {
|
|
|
|
case SourceFixed:
|
|
|
|
return password == user.Password
|
|
|
|
case SourceRegistration:
|
|
|
|
err := bcrypt.CompareHashAndPassword([]byte(user.HashedPassword), []byte(password))
|
|
|
|
return err == nil
|
|
|
|
}
|
|
|
|
return false
|
2020-11-14 10:39:18 +00:00
|
|
|
}
|