mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-03-13 23:18:17 +00:00
You can now register, but the new account is not saved on disk
This commit is contained in:
parent
68ab5df3f1
commit
aee2f23b5e
16
http_auth.go
16
http_auth.go
@ -20,9 +20,7 @@ func init() {
|
||||
|
||||
func handlerRegister(w http.ResponseWriter, rq *http.Request) {
|
||||
log.Println(rq.URL)
|
||||
if util.UseRegistration {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
if !util.UseRegistration {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
if rq.Method == http.MethodGet {
|
||||
@ -35,7 +33,17 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) {
|
||||
),
|
||||
)
|
||||
} else if rq.Method == http.MethodPost {
|
||||
io.WriteString(w, "Not implemented")
|
||||
var (
|
||||
username = rq.PostFormValue("username")
|
||||
password = rq.PostFormValue("password")
|
||||
err = user.Register(username, password)
|
||||
)
|
||||
if err != nil {
|
||||
io.WriteString(w, err.Error())
|
||||
} else {
|
||||
user.LoginDataHTTP(w, rq, username, password)
|
||||
http.Redirect(w, rq, "/"+rq.URL.RawQuery, http.StatusSeeOther)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
32
user/net.go
32
user/net.go
@ -1,11 +1,14 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// CanProceed returns `true` if the user in `rq` has enough rights to access `route`.
|
||||
@ -31,6 +34,35 @@ func LogoutFromRequest(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Register registers the given user. If it fails, a non-nil error is returned.
|
||||
func Register(username, password string) error {
|
||||
username = util.CanonicalName(username)
|
||||
log.Println("Attempt to register user", username)
|
||||
switch {
|
||||
case CountRegistered() >= util.LimitRegistration && util.LimitRegistration > 0:
|
||||
i := strconv.Itoa(util.LimitRegistration)
|
||||
log.Println("Limit reached: " + i)
|
||||
return errors.New("Reached the limit of registered users: " + i)
|
||||
case HasUsername(username):
|
||||
log.Println("Username taken")
|
||||
return errors.New("Username " + username + " is taken already.")
|
||||
case !util.IsPossibleUsername(username):
|
||||
log.Println("Illegal username:", username)
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u := User{
|
||||
Name: username,
|
||||
Group: "editor",
|
||||
HashedPassword: string(hash),
|
||||
Source: SourceRegistration,
|
||||
}
|
||||
users.Store(username, &u)
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoginDataHTTP logs such user in and returns string representation of an error if there is any.
|
||||
func LoginDataHTTP(w http.ResponseWriter, rq *http.Request, username, password string) string {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
|
@ -1,8 +1,9 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// UserSource shows where is the user data gotten from.
|
||||
@ -25,6 +26,10 @@ type User struct {
|
||||
HashedPassword string `json:"hashed_password"` // for registered
|
||||
Source UserSource `json:"-"`
|
||||
sync.RWMutex
|
||||
|
||||
// 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.
|
||||
}
|
||||
|
||||
// Route — Right (more is more right)
|
||||
|
@ -30,6 +30,17 @@ func ListUsersWithGroup(group string) []string {
|
||||
return usersWithTheGroup
|
||||
}
|
||||
|
||||
func CountRegistered() int {
|
||||
i := 0
|
||||
users.Range(func(k, v interface{}) bool {
|
||||
if v.(*User).Source == SourceRegistration {
|
||||
i++
|
||||
}
|
||||
return true
|
||||
})
|
||||
return i
|
||||
}
|
||||
|
||||
func Count() int {
|
||||
i := 0
|
||||
users.Range(func(k, v interface{}) bool {
|
||||
|
@ -82,5 +82,5 @@ func ReadConfigFile(path string) {
|
||||
FixedCredentialsPath = cfg.FixedAuthCredentialsPath
|
||||
UseRegistration = cfg.UseRegistration
|
||||
RegistrationCredentialsPath = cfg.RegistrationCredentialsPath
|
||||
LimitRegistration = cfg.LimitRegistration
|
||||
LimitRegistration = int(cfg.LimitRegistration)
|
||||
}
|
||||
|
15
util/util.go
15
util/util.go
@ -29,7 +29,7 @@ var (
|
||||
FixedCredentialsPath string
|
||||
UseRegistration bool
|
||||
RegistrationCredentialsPath string
|
||||
LimitRegistration uint64
|
||||
LimitRegistration int
|
||||
)
|
||||
|
||||
// LettersNumbersOnly keeps letters and numbers only in the given string.
|
||||
@ -94,13 +94,24 @@ func BeautifulName(uglyName string) string {
|
||||
|
||||
// CanonicalName makes sure the `name` is canonical. A name is canonical if it is lowercase and all spaces are replaced with underscores.
|
||||
func CanonicalName(name string) string {
|
||||
return strings.ToLower(strings.ReplaceAll(name, " ", "_"))
|
||||
return strings.ToLower(
|
||||
strings.ReplaceAll(
|
||||
strings.TrimRight(
|
||||
strings.TrimLeft(name, "_"),
|
||||
"_",
|
||||
), " ", "_"))
|
||||
}
|
||||
|
||||
// HyphaPattern is a pattern which all hyphae must match.
|
||||
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"\'&%{}]+`)
|
||||
|
||||
var UsernamePattern = regexp.MustCompile(`[^?!:#@><*|"\'&%{}/]+`)
|
||||
|
||||
// IsCanonicalName checks if the `name` is canonical.
|
||||
func IsCanonicalName(name string) bool {
|
||||
return HyphaPattern.MatchString(name)
|
||||
}
|
||||
|
||||
func IsPossibleUsername(username string) bool {
|
||||
return UsernamePattern.MatchString(strings.TrimSpace(username))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user