2020-11-13 18:45:42 +00:00
|
|
|
package user
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
2020-11-14 10:39:18 +00:00
|
|
|
"net/http"
|
|
|
|
"time"
|
2020-11-13 18:45:42 +00:00
|
|
|
|
|
|
|
"github.com/bouncepaw/mycorrhiza/util"
|
|
|
|
)
|
|
|
|
|
2020-11-16 15:26:03 +00:00
|
|
|
func (u *User) OrAnon() *User {
|
|
|
|
if u == nil {
|
|
|
|
return &User{}
|
|
|
|
}
|
|
|
|
return u
|
|
|
|
}
|
|
|
|
|
2020-11-14 13:03:06 +00:00
|
|
|
func LogoutFromRequest(w http.ResponseWriter, rq *http.Request) {
|
|
|
|
cookieFromUser, err := rq.Cookie("mycorrhiza_token")
|
|
|
|
if err == nil {
|
|
|
|
http.SetCookie(w, cookie("token", "", time.Unix(0, 0)))
|
|
|
|
terminateSession(cookieFromUser.Value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (us *FixedUserStorage) userByToken(token string) *User {
|
|
|
|
if user, ok := us.Tokens[token]; ok {
|
|
|
|
return user
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-14 14:46:04 +00:00
|
|
|
func (us *FixedUserStorage) userByName(username string) *User {
|
|
|
|
for _, user := range us.Users {
|
|
|
|
if user.Name == username {
|
|
|
|
return user
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-14 13:03:06 +00:00
|
|
|
func FromRequest(rq *http.Request) *User {
|
|
|
|
cookie, err := rq.Cookie("mycorrhiza_token")
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return UserStorage.userByToken(cookie.Value)
|
|
|
|
}
|
|
|
|
|
2020-11-14 10:39:18 +00:00
|
|
|
func LoginDataHTTP(w http.ResponseWriter, rq *http.Request, username, password string) string {
|
|
|
|
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
|
|
|
if !HasUsername(username) {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
log.Println("Unknown username", username, "was entered")
|
|
|
|
return "unknown username"
|
|
|
|
}
|
|
|
|
if !CredentialsOK(username, password) {
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
log.Println("A wrong password was entered for username", username)
|
|
|
|
return "wrong password"
|
|
|
|
}
|
|
|
|
token, err := AddSession(username)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
|
|
return err.Error()
|
|
|
|
}
|
|
|
|
http.SetCookie(w, cookie("token", token, time.Now().Add(14*24*time.Hour)))
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddSession saves a session for `username` and returns a token to use.
|
|
|
|
func AddSession(username string) (string, error) {
|
|
|
|
token, err := util.RandomString(16)
|
|
|
|
if err == nil {
|
2020-11-14 13:03:06 +00:00
|
|
|
for _, user := range UserStorage.Users {
|
|
|
|
if user.Name == username {
|
|
|
|
UserStorage.Tokens[token] = user
|
2020-11-14 14:46:04 +00:00
|
|
|
go dumpTokens()
|
2020-11-14 13:03:06 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-14 10:39:18 +00:00
|
|
|
log.Println("New token for", username, "is", token)
|
|
|
|
}
|
|
|
|
return token, err
|
|
|
|
}
|
|
|
|
|
2020-11-14 13:03:06 +00:00
|
|
|
func terminateSession(token string) {
|
|
|
|
delete(UserStorage.Tokens, token)
|
2020-11-14 14:46:04 +00:00
|
|
|
go dumpTokens()
|
2020-11-14 13:03:06 +00:00
|
|
|
}
|
|
|
|
|
2020-11-14 10:39:18 +00:00
|
|
|
func HasUsername(username string) bool {
|
|
|
|
for _, user := range UserStorage.Users {
|
|
|
|
if user.Name == username {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func CredentialsOK(username, password string) bool {
|
|
|
|
for _, user := range UserStorage.Users {
|
|
|
|
if user.Name == username && user.Password == password {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-11-13 18:45:42 +00:00
|
|
|
type FixedUserStorage struct {
|
2020-11-14 10:39:18 +00:00
|
|
|
Users []*User
|
2020-11-14 13:03:06 +00:00
|
|
|
Tokens map[string]*User
|
2020-11-13 18:45:42 +00:00
|
|
|
}
|
|
|
|
|
2020-11-14 13:03:06 +00:00
|
|
|
var UserStorage = FixedUserStorage{Tokens: make(map[string]*User)}
|
2020-11-13 18:45:42 +00:00
|
|
|
|
|
|
|
// AuthUsed shows if a method of authentication is used. You should set it by yourself.
|
|
|
|
var AuthUsed bool
|
|
|
|
|
|
|
|
// User is a user.
|
|
|
|
type User struct {
|
|
|
|
// Name is a username. It must follow hypha naming rules.
|
|
|
|
Name string `json:"name"`
|
|
|
|
// Group the user is part of.
|
|
|
|
Group UserGroup `json:"-"`
|
|
|
|
GroupString string `json:"group"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
|
|
|
|
2020-11-14 10:39:18 +00:00
|
|
|
// A handy cookie constructor
|
|
|
|
func cookie(name_suffix, val string, t time.Time) *http.Cookie {
|
|
|
|
return &http.Cookie{
|
|
|
|
Name: "mycorrhiza_" + name_suffix,
|
|
|
|
Value: val,
|
|
|
|
Expires: t,
|
|
|
|
Path: "/",
|
|
|
|
}
|
|
|
|
}
|