index page, not logged in
try logging in, but user not exist
create a new account
new account created, redirect to log in
register duplicate driver license will be rejected.
server search mongodb first, only add new user
user added to mongodb
logged in, sign out
sign out page, view ballots redirect to index page
logged out
package main
import (
"context"
"fmt"
"html/template"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/sessions"
"golang.org/x/crypto/bcrypt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type auth struct {
Username string
Password []byte
Status string
}
var templates *template.Template
var store = sessions.NewCookieStore([]byte("secret"))
func indexGetHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
registeredUser, _ := session.Values["username"]
registeredHashedPassword, _ := session.Values["password"]
status, _ := session.Values["status"]
if registeredUser == nil || registeredHashedPassword == nil || status == nil {
templates.ExecuteTemplate(w, "index.html", nil)
return
}
templates.ExecuteTemplate(w, "index.html",
auth{Username: registeredUser.(string),
Password: registeredHashedPassword.([]byte), Status: status.(string)})
}
func loginGetHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
registeredUser, _ := session.Values["username"]
//registeredHashedPassword, _ := session.Values["password"]
status, _ := session.Values["status"]
if registeredUser == nil || status == nil {
templates.ExecuteTemplate(w, "login.html", nil)
return
}
templates.ExecuteTemplate(w, "login.html",
auth{Username: registeredUser.(string),
Status: status.(string)})
}
func loginPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.PostForm.Get("username")
password := r.PostForm.Get("password")
var userAuth auth
userAuth = findUser(username)
if userAuth.Status != "voter found" {
templates.ExecuteTemplate(w, "login.html",
auth{Status: "voter not exist"})
return
}
err := bcrypt.CompareHashAndPassword(userAuth.Password, []byte(password))
if err != nil || username != userAuth.Username {
templates.ExecuteTemplate(w, "login.html",
auth{Status: "username password mismatch"})
return
}
session, _ := store.Get(r, "session")
session.Values["username"] = username
session.Values["password"] = userAuth.Password
session.Values["status"] = "logged in as " + username
session.Save(r, w)
http.Redirect(w, r, "/", 302)
}
func logoutGetHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
session.Values["username"] = nil
session.Values["password"] = nil
session.Values["status"] = nil
session.Save(r, w)
templates.ExecuteTemplate(w, "logout.html", nil)
}
func registerGetHandler(w http.ResponseWriter, r *http.Request) {
templates.ExecuteTemplate(w, "register.html", nil)
}
func registerPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
username := r.PostForm.Get("username")
password := r.PostForm.Get("password")
cost := bcrypt.DefaultCost
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), cost)
if err != nil {
templates.ExecuteTemplate(w, "register.html", auth{Status: "password not accepted"})
return
}
status := addUser(username, hashedPassword)
session, _ := store.Get(r, "session")
session.Values["username"] = username
session.Values["status"] = status
session.Save(r, w)
http.Redirect(w, r, "/login", 302)
}
func addUser(user string, password []byte) string {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb+srv://bob:password@cluster0.yvyo2.mongodb.net/test?retryWrites=true&w=majority"))
if err != nil {
log.Fatal(err)
}
ctx, _ := context.WithTimeout(context.Background(), 100*time.Second)
err = client.Connect(ctx)
if err != nil {
return "error connecting to database"
}
defer client.Disconnect(ctx)
electionDatabase := client.Database("sample_election")
votersCollection := electionDatabase.Collection("voters")
//check if voter exist
var userAuth auth
userAuth = findUser(user)
if userAuth.Status == "voter found" {
return "You are registered already, please log in."
}
address, err := votersCollection.InsertOne(ctx, bson.D{
{"user", user},
{"password", password},
})
if err != nil {
return "error adding new voter"
}
fmt.Println("inserted", user, "@ ", address)
return "new volter profile created"
}
func findUser(user string) auth {
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb+srv://bob:password@cluster0.yvyo2.mongodb.net/test?retryWrites=true&w=majority"))
if err != nil {
log.Fatal(err)
}
ctx, _ := context.WithTimeout(context.Background(), 100*time.Second)
err = client.Connect(ctx)
if err != nil {
return auth{Status: "error connecting to database"}
}
defer client.Disconnect(ctx)
electionDatabase := client.Database("sample_election")
votersCollection := electionDatabase.Collection("voters")
filterCursor, err := votersCollection.Find(ctx, bson.M{"user": user})
defer filterCursor.Close(ctx)
if err != nil {
return auth{Status: "voter not found"}
}
var userAuth bson.M
var userLiscense string
var userPassword []byte
filterCursor.Next(ctx)
if err = filterCursor.Decode(&userAuth); err != nil {
return auth{Status: "error connecting to database 2"}
}
for k, v := range userAuth {
if k == "user" {
userLiscense = v.(string)
}
if k == "password" {
userPassword = v.(primitive.Binary).Data
//fmt.Println(reflect.TypeOf(v))
}
}
return auth{Username: userLiscense, Password: userPassword, Status: "voter found"}
}
func main() {
templates = template.Must(template.ParseGlob("templates/*.html"))
r := mux.NewRouter()
r.HandleFunc("/", indexGetHandler).Methods("GET")
//r.HandleFunc("/", indexPostHandler).Methods("POST")
r.HandleFunc("/login", loginGetHandler).Methods("GET")
r.HandleFunc("/login", loginPostHandler).Methods("POST")
r.HandleFunc("/logout", logoutGetHandler).Methods("GET")
r.HandleFunc("/register", registerGetHandler).Methods("GET")
r.HandleFunc("/register", registerPostHandler).Methods("POST")
fs := http.FileServer(http.Dir("./static/"))
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))
http.Handle("/", r)
http.ListenAndServe(":8000", nil)
}
------------------------------------
//index.html
<html>
<head>
<title> Templates</title>
<link rel="stylesheet" type="text/css" href="/static/index.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<div style="text-align: center;">
<h1>World Election of Year 3000 </h1>
</div>
{{if .Username}}
<div>I ({{.Username}}) vote for</div>
<div><a href="/logout">sign out</a></div>
{{else}}
<div>Please <a href="/login">log in</a></div>
{{end}}
<!--
<form method="POST">
<textarea name="textarea1"></textarea>
<div>
<button type="submit">Post Comment</button>
</div>
</form>
-->
<div>status: {{.Status}}</div><br />
</body>
</html>
-------------------------------
//login.html
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Log In</h1>
<form method="POST">
<div> Driver's Liscense: <input name="username"></div><br />
<div></div>Password: <input name="password"></div><br />
<div> <a href="/register">create new account</a></div><br /><br />
<div> <button type="submit">Login</button></div>
</form>
<div>status: {{.Status}}</div><br />
</body>
</html>
---------------------------------
//register.html
<html>
<head>
<title>Register</title>
</head>
<body>
<h1>Registration</h1>
<form method="POST">
<div> Driver's Liscense: <input name="username"></div><br />
<div><input type="button" onclick="inputClick(); this.value=' ✔'" value='voter validation'></input>
</div><br />
<div></div>Password: <input name="password"></div><br /><br />
<div> <button type="submit" id="button1" disabled>Register</button></div><br />
</form>
<div>status: {{.Status}}</div><br />
</body>
<script>
function inputClick() {
document.getElementById('button1').disabled = false;
}
</script>
</html>
reference:
mongodb insert
mongodb query
No comments:
Post a Comment