index page shows current vote count, press on the search button
redirected to record page, sample random vote data was inserted in mongodb
register as 123 and vote for human, human count increase by 1
123's vote is recorded
//tutorial.go
package main
import (
"bytes"
"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
Ballot string
Status string
Count1 int
Count2 int
}
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"]
ballot, _ := session.Values["ballot"]
status, _ := session.Values["status"]
count1 := countBallot("human")
count2 := countBallot("humanoid")
if registeredUser == nil || registeredHashedPassword == nil || status == nil {
templates.ExecuteTemplate(w, "index.html", auth{Count1: count1, Count2: count2})
return
}
if ballot == nil {
ballot = ""
}
templates.ExecuteTemplate(w, "index.html",
auth{Username: registeredUser.(string), Ballot: ballot.(string),
Password: registeredHashedPassword.([]byte), Status: status.(string),
Count1: count1, Count2: count2})
}
func indexPostHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
ballot := r.PostForm.Get("ballot")
session, _ := store.Get(r, "session")
username, _ := session.Values["username"]
password, _ := session.Values["password"]
if username == nil || password == nil {
http.Redirect(w, r, "/login", 302)
return
}
var updateStatus = updateUser(username.(string), password.([]byte), ballot)
session.Values["status"] = updateStatus
if updateStatus == "update successful" {
session.Values["ballot"] = ballot
}
session.Save(r, w)
http.Redirect(w, r, "/", 302)
}
func ballotGetHandler(w http.ResponseWriter, r *http.Request) {
ballot := queryAll()
templates.ExecuteTemplate(w, "ballot.html", ballot)
}
func loginGetHandler(w http.ResponseWriter, r *http.Request) {
session, _ := store.Get(r, "session")
registeredUser, _ := session.Values["username"]
userBallot, _ := session.Values["ballot"]
//registeredHashedPassword, _ := session.Values["password"]
status, _ := session.Values["status"]
if userBallot == nil {
userBallot = ""
}
if registeredUser == nil || status == nil {
templates.ExecuteTemplate(w, "login.html", nil)
return
}
templates.ExecuteTemplate(w, "login.html",
auth{Username: registeredUser.(string), Ballot: userBallot.(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["ballot"] = userAuth.Ballot
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.Values["ballot"] = 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},
{"ballot", ""},
})
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
var userBallot string
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 == "ballot" {
userBallot = v.(string)
}
if k == "password" {
userPassword = v.(primitive.Binary).Data
//fmt.Println(reflect.TypeOf(v))
}
}
return auth{Username: userLiscense, Password: userPassword, Ballot: userBallot, Status: "voter found"}
}
func updateUser(registeredUser string, registeredHashedPassword []byte, ballot string) string {
var userAuth auth
userAuth = findUser(registeredUser)
if userAuth.Status != "voter found" {
return "not registered"
}
if bytes.Compare(userAuth.Password, registeredHashedPassword) != 0 || registeredUser != userAuth.Username {
return "wrong credential"
}
client, err := mongo.NewClient(options.Client().ApplyURI("mongodb+srv://bob:password@cluster0.yvyo2.mongodb.net/test?retryWrites=true&w=majority"))
if err != nil {
return "database not exist"
}
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")
userUpdate, err := votersCollection.UpdateOne(
ctx,
bson.M{"user": userAuth.Username},
bson.M{"$set": bson.M{"ballot": ballot}})
if err != nil {
return "update failed"
}
fmt.Println(userUpdate.ModifiedCount, " updated")
return "update successful"
}
func countBallot(ballot string) int {
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 {
log.Fatal(err)
}
defer client.Disconnect(ctx)
electionDatabase := client.Database("sample_election")
votersCollection := electionDatabase.Collection("voters")
filterCursor, err := votersCollection.Find(ctx, bson.M{"ballot": ballot})
defer filterCursor.Close(ctx)
if err != nil {
log.Fatal(err)
}
var countFiltered []bson.M
if err = filterCursor.All(ctx, &countFiltered); err != nil {
log.Fatal(err)
}
return len(countFiltered)
}
func queryAll() map[string]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 {
log.Fatal(err)
}
defer client.Disconnect(ctx)
electionDatabase := client.Database("sample_election")
votersCollection := electionDatabase.Collection("voters")
cursor, err := votersCollection.Find(ctx, bson.M{})
if err != nil {
log.Fatal(err)
}
defer cursor.Close(ctx)
profileArray := make(map[string]string)
for cursor.Next(ctx) {
var profile bson.M
if err = cursor.Decode(&profile); err != nil {
log.Fatal(err)
}
profileArray[profile["user"].(string)] = profile["ballot"].(string)
}
return profileArray
}
func main() {
templates = template.Must(template.ParseGlob("templates/*.html"))
r := mux.NewRouter()
r.HandleFunc("/", indexGetHandler).Methods("GET")
r.HandleFunc("/", indexPostHandler).Methods("POST")
r.HandleFunc("/ballot", ballotGetHandler).Methods("GET")
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)
}
------------------------------------
//simulator.go
package main
import (
"context"
"fmt"
"log"
"math/rand"
"strconv"
"time"
"golang.org/x/crypto/bcrypt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
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 {
log.Fatal(err)
}
defer client.Disconnect(ctx)
electionDatabase := client.Database("sample_election")
votersCollection := electionDatabase.Collection("voters")
cost := bcrypt.DefaultCost
hashedPassword, err := bcrypt.GenerateFromPassword([]byte("abc"), cost)
for i := 0; i < 100; i++ {
var ballot = ""
randomN := rand.Intn(100)
if randomN > 50 {
ballot = "humanoid"
} else {
ballot = "human"
}
address, err := votersCollection.InsertOne(ctx, bson.D{
{"user", strconv.Itoa(i)},
{"password", hashedPassword},
{"ballot", ballot},
})
if err != nil {
log.Fatal(err)
}
fmt.Println("inserted", strconv.Itoa(i), "@ ", address)
}
}
--------------------------------
//index.html
<html>
<head>
<title> Ballot</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>
<h3>I ({{.Username}}) vote for <i>{{.Ballot}}</i>
<span style="float: right;"><a href="/logout">sign out</a></span></h3>
</div>
{{else}}
<div>
<h3>Please <a href="/login">log in</a></h3>
</div>
{{end}}
<div>
<h3>Current Counts: human ({{.Count1}}) vs humanoid ({{.Count2}})
<a href="/ballot" style="border: 1px solid black; background-color: beige;">
<i class="fa fa-search"></i></a>
</h3>
</div>
<form method="POST">
<input type="hidden" value="" id="input1" name="ballot">
<div class="row">
<div class="column">
<h2>Human</h2>
<img src="/static/human.jpg" alt="Human" style="width:90%;" onclick="humanClick()">
</div>
<div class="column">
<h2>Humanoid</h2>
<img src="/static/humanoid.jpg" alt="Humanoid" style="width:90%;" onclick="humanoidClick()">
</div>
</div>
<button type="submit" style="display: none;" id="button1"></button>
</form>
<div>
<h3>status: {{.Status}}</h3>
</div><br />
</body>
<script>
function humanClick() {
document.getElementById("input1").value = "human"
document.getElementById("button1").click()
}
function humanoidClick() {
document.getElementById("input1").value = "humanoid"
document.getElementById("button1").click()
}
</script>
</html>
----------------------------------
//ballot.html
<html>
<head>
<title>Ballot Record</title>
<link rel="stylesheet" type="text/css" href="/static/index.css">
</head>
<body>
<h1>Ballot Record</h1>
<h3><a href="/">back</a></h3>
<table>
<tr>
<th>Driver's license</th>
<th>Ballot</th>
</tr>
{{range $key, $val := .}}
<tr>
<td>{{$key}}</td>
<td>{{$val}}</td>
</tr>
{{end}}
</table>
</body>
</html>
reference:
mangodb query
go template
go map
No comments:
Post a Comment