2020-11-13 18:45:42 +00:00
package user
import (
2021-07-10 19:04:21 +00:00
"net/http"
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
2021-07-02 08:20:03 +00:00
"github.com/bouncepaw/mycorrhiza/cfg"
2021-04-19 16:39:25 +00:00
"golang.org/x/crypto/bcrypt"
2020-11-13 18:45:42 +00:00
)
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-07-02 08:20:03 +00:00
Name string ` json:"name" `
Group string ` json:"group" `
Password string ` json:"hashed_password" `
RegisteredAt time . Time ` json:"registered_on" `
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-06-29 15:10:48 +00:00
var groups = [ ] string {
"anon" ,
"editor" ,
"trusted" ,
"moderator" ,
"admin" ,
}
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-06-29 15:10:48 +00:00
func ValidGroup ( group string ) bool {
for _ , grp := range groups {
if grp == group {
return true
}
}
return false
}
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 {
2021-07-02 08:20:03 +00:00
if ! cfg . UseAuth {
2021-01-09 20:49:48 +00:00
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-07-02 08:20:03 +00:00
err := bcrypt . CompareHashAndPassword ( [ ] byte ( user . Password ) , [ ] byte ( password ) )
return err == nil
2020-11-14 10:39:18 +00:00
}
2021-07-10 19:04:21 +00:00
// ShowLockMaybe redirects to the lock page if the user is anon and the wiki has been configured to use the lock. It returns true if the user was redirected.
func ( user * User ) ShowLockMaybe ( w http . ResponseWriter , rq * http . Request ) bool {
if cfg . Locked && user . Group == "anon" {
http . Redirect ( w , rq , "/lock" , http . StatusSeeOther )
return true
}
return false
}