login password authorization complete
This commit is contained in:
parent
30c71fdc19
commit
ff8f3c2f45
5 changed files with 150 additions and 7 deletions
1
go.mod
1
go.mod
|
|
@ -5,4 +5,5 @@ go 1.23.2
|
||||||
require (
|
require (
|
||||||
github.com/mattn/go-sqlite3 v1.14.24
|
github.com/mattn/go-sqlite3 v1.14.24
|
||||||
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4
|
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4
|
||||||
|
golang.org/x/crypto v0.29.0
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -6,3 +6,5 @@ github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBW
|
||||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4 h1:qk1XyC6UGfPa51PGmsTQJavyhfMLScqw97pEV3sFClI=
|
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4 h1:qk1XyC6UGfPa51PGmsTQJavyhfMLScqw97pEV3sFClI=
|
||||||
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4/go.mod h1:X6iKjXCleSyo/LZzKZ9zDF/ZB2L9gC36I5gLMf32w3M=
|
github.com/umpc/go-sortedmap v0.0.0-20180422175548-64ab94c482f4/go.mod h1:X6iKjXCleSyo/LZzKZ9zDF/ZB2L9gC36I5gLMf32w3M=
|
||||||
|
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||||
|
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||||
|
|
|
||||||
135
main.go
135
main.go
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -8,25 +9,37 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"text/template"
|
"text/template"
|
||||||
"wargh/db"
|
"wargh/db"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var DB *sql.DB
|
||||||
var templates *template.Template
|
var templates *template.Template
|
||||||
|
|
||||||
|
type UserSession struct {
|
||||||
|
Id int
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessions map[string]UserSession
|
||||||
|
|
||||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == "GET" {
|
if r.Method == "GET" {
|
||||||
//templates.Lookup("index.html").Execute(w, nil)
|
templates.Lookup("index.html").Execute(w, nil)
|
||||||
redirectError(w, r, ERROR_TEST)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ERROR_UNKNOWN = 0
|
ERROR_UNKNOWN = 0
|
||||||
ERROR_TEST = 1
|
ERROR_INVALID_INPUT = 1
|
||||||
|
ERROR_INVALID_LOGIN_PASSWORD = 2
|
||||||
|
ERROR_UNAUTHORIZED = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
var ERROR_TEXT = []string{
|
var ERROR_TEXT = []string{
|
||||||
"Unknown error",
|
"Unknown error",
|
||||||
"Test error",
|
"Invalid input",
|
||||||
|
"Invalid login or password",
|
||||||
|
"Unathorized",
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorHandler(w http.ResponseWriter, r *http.Request) {
|
func errorHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
@ -53,13 +66,121 @@ func redirectError(w http.ResponseWriter, r *http.Request, errorCode int) {
|
||||||
http.Redirect(w, r, fmt.Sprintf("/error?error=%d", errorCode), http.StatusSeeOther)
|
http.Redirect(w, r, fmt.Sprintf("/error?error=%d", errorCode), http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isFirstUser() (bool, error) {
|
||||||
|
row := DB.QueryRow("SELECT COUNT(id) FROM `user`;")
|
||||||
|
if row.Err() != nil {
|
||||||
|
return false, row.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int
|
||||||
|
err := row.Scan(&count)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count == 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createUser(login string, password string) (int, error) {
|
||||||
|
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = DB.Exec("INSERT INTO `user` (login, password) VALUES (?,?);", login, bytes)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
row := DB.QueryRow("SELECT id FROM `user` WHERE login = ?;", login)
|
||||||
|
if row.Err() != nil {
|
||||||
|
return 0, row.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
var id int
|
||||||
|
row.Scan(&id)
|
||||||
|
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "GET" {
|
||||||
|
templates.Lookup("login.html").Execute(w, nil)
|
||||||
|
} else if r.Method == "POST" {
|
||||||
|
err := r.ParseForm()
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
|
||||||
|
redirectError(w, r, ERROR_UNKNOWN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loginParam := r.Form.Get("login")
|
||||||
|
passwordParam := r.Form.Get("password")
|
||||||
|
if loginParam == "" || passwordParam == "" {
|
||||||
|
redirectError(w, r, ERROR_INVALID_INPUT)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isFirst, err := isFirstUser()
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
|
||||||
|
redirectError(w, r, ERROR_UNKNOWN)
|
||||||
|
}
|
||||||
|
|
||||||
|
if isFirst {
|
||||||
|
id, err := createUser(loginParam, passwordParam)
|
||||||
|
if err != nil {
|
||||||
|
log.Print(err)
|
||||||
|
} else {
|
||||||
|
log.Printf("created user %d\n", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create session
|
||||||
|
} else {
|
||||||
|
// try authorize
|
||||||
|
row := DB.QueryRow("SELECT id,password FROM `user` WHERE login = ?;", loginParam)
|
||||||
|
if row.Err() != nil {
|
||||||
|
if row.Err().Error() == sql.ErrNoRows.Error() {
|
||||||
|
redirectError(w, r, ERROR_INVALID_LOGIN_PASSWORD)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
log.Print(err)
|
||||||
|
|
||||||
|
redirectError(w, r, ERROR_UNKNOWN)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var id int
|
||||||
|
password := make([]byte, 8)
|
||||||
|
|
||||||
|
err = row.Scan(&id, &password)
|
||||||
|
if err != nil {
|
||||||
|
// can't scan blob? fatal error
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bcrypt.CompareHashAndPassword(password, []byte(passwordParam)) != nil {
|
||||||
|
redirectError(w, r, ERROR_INVALID_LOGIN_PASSWORD)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create session
|
||||||
|
log.Printf("user %d authorized!\n", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
db.Init(&db.DBConfig{
|
db.Init(&db.DBConfig{
|
||||||
DBPath: "wargh.db",
|
DBPath: "wargh.db",
|
||||||
MigrationsPath: "migrations",
|
MigrationsPath: "migrations",
|
||||||
})
|
})
|
||||||
|
|
||||||
DB, err := db.Open()
|
var err error
|
||||||
|
DB, err = db.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
@ -69,6 +190,7 @@ func main() {
|
||||||
templates, err = template.New("templates").ParseFiles(
|
templates, err = template.New("templates").ParseFiles(
|
||||||
"templates/index.html",
|
"templates/index.html",
|
||||||
"templates/error.html",
|
"templates/error.html",
|
||||||
|
"templates/login.html",
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
@ -76,6 +198,7 @@ func main() {
|
||||||
|
|
||||||
http.HandleFunc("/", indexHandler)
|
http.HandleFunc("/", indexHandler)
|
||||||
http.HandleFunc("/error", errorHandler)
|
http.HandleFunc("/error", errorHandler)
|
||||||
|
http.HandleFunc("/login", loginHandler)
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
CREATE TABLE user (
|
CREATE TABLE user (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
login TEXT NOT NULL UNIQUE,
|
login TEXT NOT NULL UNIQUE,
|
||||||
password TEXT NOT NULL
|
password BLOB NOT NULL
|
||||||
);
|
);
|
||||||
|
|
|
||||||
17
templates/login.html
Normal file
17
templates/login.html
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>wargh - login</title>
|
||||||
|
</head>
|
||||||
|
<bodY>
|
||||||
|
<form action="login" method="POST">
|
||||||
|
<label for="login"><b>Login</b></label>
|
||||||
|
<input type="text" placeholder="Enter login" name="login" required>
|
||||||
|
|
||||||
|
<label for="password"><b>Password</b></label>
|
||||||
|
<input type="password" placeholder="Enter password" name="password" required>
|
||||||
|
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
</bodY>
|
||||||
|
</html>
|
||||||
Loading…
Add table
Reference in a new issue