1
0
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:
bouncepaw 2021-04-19 21:39:25 +05:00
parent 68ab5df3f1
commit aee2f23b5e
6 changed files with 75 additions and 8 deletions

View File

@ -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)
}
}
}

View File

@ -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")

View File

@ -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)

View File

@ -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 {

View File

@ -82,5 +82,5 @@ func ReadConfigFile(path string) {
FixedCredentialsPath = cfg.FixedAuthCredentialsPath
UseRegistration = cfg.UseRegistration
RegistrationCredentialsPath = cfg.RegistrationCredentialsPath
LimitRegistration = cfg.LimitRegistration
LimitRegistration = int(cfg.LimitRegistration)
}

View File

@ -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))
}