Add account editing form.
このコミットが含まれているのは:
コミット
87df8cc3f3
142
main.go
142
main.go
|
@ -3,9 +3,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "bufio"
|
import "bufio"
|
||||||
|
import "errors"
|
||||||
import "github.com/gorilla/mux"
|
import "github.com/gorilla/mux"
|
||||||
import "golang.org/x/crypto/bcrypt"
|
import "golang.org/x/crypto/bcrypt"
|
||||||
import "html/template"
|
import "html/template"
|
||||||
|
import "io/ioutil"
|
||||||
import "log"
|
import "log"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "os"
|
import "os"
|
||||||
|
@ -60,25 +62,51 @@ func execTemplate(w http.ResponseWriter, file string, input string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
func login(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||||
execTemplate(w, "index.html", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func signUpFormHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
execTemplate(w, "signupform.html", "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func signUpHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
name := r.FormValue("name")
|
name := r.FormValue("name")
|
||||||
pw := r.FormValue("password")
|
pw := r.FormValue("password")
|
||||||
pw2 := r.FormValue("password2")
|
loginValid := false
|
||||||
|
file, err := os.Open(loginsFile)
|
||||||
|
defer file.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Can't open file for reading", err)
|
||||||
|
}
|
||||||
|
scanner := bufio.NewScanner(bufio.NewReader(file))
|
||||||
|
for {
|
||||||
|
if !scanner.Scan() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
line := scanner.Text()
|
||||||
|
tokens := strings.Split(line, " ")
|
||||||
|
if len(tokens) == 3 {
|
||||||
|
if 0 == strings.Compare(tokens[0], name) &&
|
||||||
|
nil == bcrypt.CompareHashAndPassword(
|
||||||
|
[]byte(tokens[1]), []byte(pw)) {
|
||||||
|
loginValid = true
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !loginValid {
|
||||||
|
execTemplate(w, "error.html", "Bad login.")
|
||||||
|
return name, errors.New("")
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func accountLine(w http.ResponseWriter, r *http.Request,
|
||||||
|
checkDupl bool) (string, error) {
|
||||||
|
name := r.FormValue("name")
|
||||||
|
pw := r.FormValue("new_password")
|
||||||
|
pw2 := r.FormValue("new_password2")
|
||||||
mail := r.FormValue("mail")
|
mail := r.FormValue("mail")
|
||||||
if 0 != strings.Compare(pw, pw2) || 0 == strings.Compare("name", "") ||
|
if 0 != strings.Compare(pw, pw2) || 0 == strings.Compare("name", "") ||
|
||||||
0 == strings.Compare(pw, "") || !onlyLegalRunes(name) ||
|
0 == strings.Compare(pw, "") || !onlyLegalRunes(name) ||
|
||||||
len(name) > 140 {
|
len(name) > 140 {
|
||||||
execTemplate(w, "error.html", "Invalid values.")
|
execTemplate(w, "error.html", "Invalid values.")
|
||||||
return
|
return "", errors.New("")
|
||||||
}
|
}
|
||||||
|
if checkDupl {
|
||||||
fileRead, err := os.Open(loginsFile)
|
fileRead, err := os.Open(loginsFile)
|
||||||
defer fileRead.Close()
|
defer fileRead.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -93,15 +121,73 @@ func signUpHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
tokens := strings.Split(line, " ")
|
tokens := strings.Split(line, " ")
|
||||||
if 0 == strings.Compare(name, tokens[0]) {
|
if 0 == strings.Compare(name, tokens[0]) {
|
||||||
execTemplate(w, "error.html", "Username taken.")
|
execTemplate(w, "error.html", "Username taken.")
|
||||||
return
|
return "", errors.New("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
|
hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Can't generate password hash", err)
|
log.Fatal("Can't generate password hash", err)
|
||||||
}
|
}
|
||||||
new_line := name + " " + string(hash) + " " + mail + "\n"
|
return name + " " + string(hash) + " " + mail + "\n", nil
|
||||||
appendToFile(loginsFile, new_line)
|
}
|
||||||
|
|
||||||
|
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
execTemplate(w, "index.html", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signUpFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
execTemplate(w, "signupform.html", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func signUpHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
newLine, err := accountLine(w, r, true)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appendToFile(loginsFile, newLine)
|
||||||
|
execTemplate(w, "feedset.html", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func accountFormHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
execTemplate(w, "accountform.html", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func accountPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
name, err := login(w, r)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newLine, err := accountLine(w, r, false)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
text, err := ioutil.ReadFile(loginsFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Can't read file", err)
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(text), "\n")
|
||||||
|
for i, line := range lines {
|
||||||
|
tokens := strings.Split(line, " ")
|
||||||
|
if 0 == strings.Compare(name, tokens[0]) {
|
||||||
|
lines[i] = newLine
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text = []byte(strings.Join(lines, "\n"))
|
||||||
|
tmpFile := "tmp_" + loginsFile
|
||||||
|
if err := ioutil.WriteFile(tmpFile, []byte(text), 0600); err != nil {
|
||||||
|
log.Fatal("Trouble writing file", err)
|
||||||
|
}
|
||||||
|
if err := os.Rename(loginsFile, "_"+loginsFile); err != nil {
|
||||||
|
log.Fatal("Trouble moving file", err)
|
||||||
|
}
|
||||||
|
if err := os.Rename(tmpFile, loginsFile); err != nil {
|
||||||
|
log.Fatal("Trouble moving file", err)
|
||||||
|
}
|
||||||
|
if err := os.Remove("_" + loginsFile); err != nil {
|
||||||
|
log.Fatal("Trouble removing file", err)
|
||||||
|
}
|
||||||
execTemplate(w, "signup.html", "")
|
execTemplate(w, "signup.html", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,32 +217,8 @@ func listHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func twtxtPostHandler(w http.ResponseWriter, r *http.Request) {
|
func twtxtPostHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
name := r.FormValue("name")
|
name, err := login(w, r)
|
||||||
pw := r.FormValue("password")
|
|
||||||
loginValid := false
|
|
||||||
file, err := os.Open(loginsFile)
|
|
||||||
defer file.Close()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Can't open file for reading", err)
|
|
||||||
}
|
|
||||||
scanner := bufio.NewScanner(bufio.NewReader(file))
|
|
||||||
for {
|
|
||||||
if !scanner.Scan() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
line := scanner.Text()
|
|
||||||
tokens := strings.Split(line, " ")
|
|
||||||
if len(tokens) == 3 {
|
|
||||||
if 0 == strings.Compare(tokens[0], name) &&
|
|
||||||
nil == bcrypt.CompareHashAndPassword(
|
|
||||||
[]byte(tokens[1]), []byte(pw)) {
|
|
||||||
loginValid = true
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !loginValid {
|
|
||||||
execTemplate(w, "error.html", "Bad login.")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
text := r.FormValue("twt")
|
text := r.FormValue("twt")
|
||||||
|
@ -216,6 +278,8 @@ func main() {
|
||||||
router.HandleFunc("/", indexHandler)
|
router.HandleFunc("/", indexHandler)
|
||||||
router.HandleFunc("/twtxt", listHandler).Methods("GET")
|
router.HandleFunc("/twtxt", listHandler).Methods("GET")
|
||||||
router.HandleFunc("/twtxt/", listHandler)
|
router.HandleFunc("/twtxt/", listHandler)
|
||||||
|
router.HandleFunc("/account", accountFormHandler).Methods("GET")
|
||||||
|
router.HandleFunc("/account", accountPostHandler).Methods("POST")
|
||||||
router.HandleFunc("/signup", signUpFormHandler).Methods("GET")
|
router.HandleFunc("/signup", signUpFormHandler).Methods("GET")
|
||||||
router.HandleFunc("/signup", signUpHandler).Methods("POST")
|
router.HandleFunc("/signup", signUpHandler).Methods("POST")
|
||||||
router.HandleFunc("/twtxt", twtxtPostHandler).Methods("POST")
|
router.HandleFunc("/twtxt", twtxtPostHandler).Methods("POST")
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<html>
|
||||||
|
<h1>edit account</h1>
|
||||||
|
<form method="POST" action="/account">
|
||||||
|
E-mail: <input type="text" name="mail" /><br />
|
||||||
|
New password: <input type="password" name="new_password" /><br />
|
||||||
|
New password (repeat): <input type="password" name="new_password2" /><br />
|
||||||
|
<br />
|
||||||
|
Name: <input type="text" name="name" /><br />
|
||||||
|
Old password: <input type="password" name="password" /><br />
|
||||||
|
<input type="submit" value="update" />
|
||||||
|
</form>
|
||||||
|
<hr />
|
||||||
|
<p>This project is licensed under the <a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a>, source code <a href="https://github.com/plomlompom/htwtxt">here</a>.</p>
|
||||||
|
</html>
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<h1>sign up</h1>
|
<h1>feed setup</h1>
|
||||||
<p>
|
<p>
|
||||||
Feed creation successful.
|
Feed successfully set.
|
||||||
<a href="/">Return to twtxt input form.</a>
|
<a href="/">Return to twtxt input form.</a>
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
|
@ -7,7 +7,8 @@
|
||||||
<input type="submit" value="twt" />
|
<input type="submit" value="twt" />
|
||||||
</form>
|
</form>
|
||||||
No feed yet? <a href="/signup">Create one!</a><br />
|
No feed yet? <a href="/signup">Create one!</a><br />
|
||||||
Also, check out <a href="/twtxt">other people's feeds</a> …
|
Also, check out <a href="/twtxt">other people's feeds</a> …<br />
|
||||||
|
Or <a href="/account">edit your account settings</a>.
|
||||||
<hr />
|
<hr />
|
||||||
<p>This project is licensed under the <a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a>, source code <a href="https://github.com/plomlompom/htwtxt">here</a>.</p>
|
<p>This project is licensed under the <a href="http://www.gnu.org/licenses/agpl-3.0.html">AGPLv3</a>, source code <a href="https://github.com/plomlompom/htwtxt">here</a>.</p>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
<h1>sign up</h1>
|
<h1>sign up</h1>
|
||||||
<form method="POST" action="/signup">
|
<form method="POST" action="/signup">
|
||||||
Name: <input type="text" name="name" /> (only up to 140 legal chars: A-Z, a-z, 0-1, _)<br />
|
Name: <input type="text" name="name" /> (only up to 140 legal chars: A-Z, a-z, 0-1, _)<br />
|
||||||
Password: <input type="password" name="password" /><br />
|
Password: <input type="password" name="new_password" /><br />
|
||||||
Password (repeat): <input type="password" name="password2" /><br />
|
Password (repeat): <input type="password" name="new_password2" /><br />
|
||||||
E-Mail: <input type="text" name="mail" /> (optional; stored internally to reach and/or identify you when there's trouble with your feed, you want to reset your password, etc.; in any such communication, communicating from an address provided here is a necessary condition for you to be treated as the owner of your feed)<br />
|
E-mail: <input type="text" name="mail" /> (optional; stored internally to reach and/or identify you when there's trouble with your feed, you want to reset your password, etc.; in any such communication, communicating from an address provided here is a necessary condition for you to be treated as the owner of your feed)<br />
|
||||||
<input type="submit" value="create" />
|
<input type="submit" value="create" />
|
||||||
</form>
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
読み込み中…
新しいイシューから参照