Add --adduser flag to add users manually as a site operator.
このコミットが含まれているのは:
コミット
fbec273fb9
20
README.md
20
README.md
|
@ -10,18 +10,20 @@ space.
|
|||
|
||||
## Features (or lack thereof)
|
||||
|
||||
- users may register accounts mapped to individual twtxt feeds they may write to
|
||||
- user accounts may be registered, mapped to individual twtxt feeds they can
|
||||
write to
|
||||
- no sessions, no cookies: few POST-writable resources (feeds, account data)
|
||||
expect user credential parameters, which to store between requests is up to
|
||||
the user / browser
|
||||
expect user credential parameters, which to store between requests if desired
|
||||
is up to the user / browser
|
||||
- account registration may be open to the public, or closed (with the site
|
||||
operator adding new accounts manually)
|
||||
- users may register e-mail addresses and optional security questions to allow
|
||||
for password reset (if enabled by site operator)
|
||||
- account registration may be closed or open to the public
|
||||
- HTTPS / TLS support (if paths to key and certificate files are provided)
|
||||
|
||||
## Online demo
|
||||
|
||||
A demo instance with frequent downtimes can be tested at
|
||||
A demo instance with frequent downtimes and open sign-up can be tested at
|
||||
http://test.plomlompom.com:8000 (don't expect any of its feeds' URLs to be
|
||||
stable; it's just for testing, and data frequently gets deleted).
|
||||
|
||||
|
@ -76,10 +78,12 @@ This is [a common privilege problem](http://stackoverflow.com/q/413807) and
|
|||
|
||||
sudo setcap 'cap_net_bind_service=+ep' $GOPATH/bin/htwtxt
|
||||
|
||||
### Public sign-up
|
||||
### Public or closed sign-up
|
||||
|
||||
By default, sign up / account creation is not open to the public. The `--signup`
|
||||
flag must be set explicitely to change that.
|
||||
By default, sign up / account creation is not open to the web-browsing public.
|
||||
The `--signup` flag must be set explicitely to change that. Alternatively, new
|
||||
accounts can be added by starting the program with the `--adduser` flag,
|
||||
followed by an argument of the form `NAME:PASSWORD`.
|
||||
|
||||
### Set site owner contact info
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ func signUpHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
name := r.FormValue("name")
|
||||
if "" == name || !onlyLegalRunes(name) || len(name) > 140 {
|
||||
if !nameIsLegal(name) {
|
||||
execTemplate(w, "error.html", "Illegal name.")
|
||||
return
|
||||
}
|
||||
|
|
65
main.go
65
main.go
|
@ -117,19 +117,31 @@ func login(w http.ResponseWriter, r *http.Request) (string, error) {
|
|||
return name, nil
|
||||
}
|
||||
|
||||
func nameIsLegal(name string) bool {
|
||||
return !("" == name || !onlyLegalRunes(name) || len(name) > 140)
|
||||
}
|
||||
|
||||
func passwordIsLegal(password string) bool {
|
||||
return !("" == password)
|
||||
}
|
||||
|
||||
func hashFromPw(pw string) string {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
log.Fatal("Can't generate hash", err)
|
||||
}
|
||||
return string(hash)
|
||||
}
|
||||
|
||||
func newPassword(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||
pw := r.FormValue("new_password")
|
||||
pw2 := r.FormValue("new_password2")
|
||||
if 0 != strings.Compare(pw, pw2) {
|
||||
return "", errors.New("Password values did not match")
|
||||
} else if "" == pw {
|
||||
} else if !passwordIsLegal(pw) {
|
||||
return "", errors.New("Illegal password.")
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
log.Fatal("Can't generate password hash", err)
|
||||
}
|
||||
return string(hash), nil
|
||||
return hashFromPw(pw), nil
|
||||
}
|
||||
|
||||
func newMailAddress(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||
|
@ -152,12 +164,7 @@ func newSecurityQuestion(w http.ResponseWriter, r *http.Request) (string,
|
|||
} else if "" == secanswer {
|
||||
return "", "", errors.New("Illegal security question answer.")
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(secanswer),
|
||||
bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
log.Fatal("Can't generate security question answer hash", err)
|
||||
}
|
||||
return secquestion, string(hash), nil
|
||||
return secquestion, hashFromPw(secanswer), nil
|
||||
}
|
||||
|
||||
func changeLoginField(w http.ResponseWriter, r *http.Request,
|
||||
|
@ -203,11 +210,14 @@ func nameMyself(ssl bool, port int) string {
|
|||
return "http" + s + "://" + ip + ":" + strconv.Itoa(port)
|
||||
}
|
||||
|
||||
func readOptions() (string, int, string, int) {
|
||||
func readOptions() (string, int, string, int, string) {
|
||||
var mailpw string
|
||||
var mailport int
|
||||
var mailserver string
|
||||
var port int
|
||||
var newLogin string
|
||||
flag.StringVar(&newLogin, "adduser", "", "instead of starting as "+
|
||||
"server, add user with login NAME:PASSWORD")
|
||||
flag.IntVar(&port, "port", 8000, "port to serve")
|
||||
flag.StringVar(&keyPath, "key", "", "SSL key file")
|
||||
flag.StringVar(&certPath, "cert", "", "SSL certificate file")
|
||||
|
@ -244,13 +254,38 @@ func readOptions() (string, int, string, int) {
|
|||
mailpw = string(bytePassword)
|
||||
fmt.Println("")
|
||||
}
|
||||
return mailserver, mailport, mailpw, port
|
||||
return mailserver, mailport, mailpw, port, newLogin
|
||||
}
|
||||
|
||||
func addUser(login string) {
|
||||
fields := strings.Split(login, ":")
|
||||
if len(fields) != 2 {
|
||||
log.Fatal("Malformed adduser string, must be NAME:PASSWORD")
|
||||
}
|
||||
name := fields[0]
|
||||
password := fields[1]
|
||||
if !nameIsLegal(name) {
|
||||
log.Fatal("Malformed adduser NAME argument.")
|
||||
}
|
||||
if !passwordIsLegal(password) {
|
||||
log.Fatal("Malformed adduser PASSWORD argument.")
|
||||
}
|
||||
if _, err := getFromFileEntryFor(loginsPath, name, 5); err == nil {
|
||||
log.Fatal("Username already taken.")
|
||||
}
|
||||
hash := hashFromPw(password)
|
||||
appendToFile(loginsPath, name+"\t"+hash+"\t\t\t")
|
||||
fmt.Println("Added user.")
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
mailserver, mailport, mailpw, port := readOptions()
|
||||
mailserver, mailport, mailpw, port, newLogin := readOptions()
|
||||
initFilesAndDirs()
|
||||
if "" != newLogin {
|
||||
addUser(newLogin)
|
||||
return
|
||||
}
|
||||
myself = nameMyself("" != keyPath, port)
|
||||
templ, err = template.New("main").ParseGlob(templPath + "/*.html")
|
||||
if err != nil {
|
||||
|
|
読み込み中…
新しいイシューから参照