Created
October 23, 2017 16:17
-
-
Save monirz/aa1be66fb4e2ac121f4ed525ca55b76c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"log" | |
"net/http" | |
"strconv" | |
"time" | |
"golang.org/x/crypto/bcrypt" | |
jwt "github.com/dgrijalva/jwt-go" | |
_ "github.com/go-sql-driver/mysql" | |
"github.com/jmoiron/sqlx" | |
) | |
type User struct { | |
ID int64 | |
UserName string | |
Email string | |
Password string | |
CreatedAt time.Time | |
UpdatedAt time.Time | |
} | |
var db *sqlx.DB | |
func init() { | |
var err error | |
db, err = sqlx.Connect("mysql", "root:123456@/api?parseTime=true") | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
func main() { | |
http.HandleFunc("/register", usersHandler) | |
http.HandleFunc("/login", loginHandler) | |
http.HandleFunc("/get-token", getTokenHandler) | |
h := http.HandlerFunc(savePost) | |
http.Handle("/posts", middlewareToken(h)) | |
http.ListenAndServe(":8089", nil) | |
} | |
func getTokenHandler(w http.ResponseWriter, r *http.Request) { | |
token := jwt.New(jwt.SigningMethodHS256) | |
var mySigningKey = []byte("secret") | |
/* Sign the token with our secret */ | |
tokenString, _ := token.SignedString(mySigningKey) | |
/* Finally, write the token to the browser window */ | |
w.Write([]byte(tokenString)) | |
} | |
func getToken() string { | |
token := jwt.New(jwt.SigningMethodHS256) | |
var mySigningKey = []byte("secret") | |
/* Sign the token with our secret */ | |
tokenString, _ := token.SignedString(mySigningKey) | |
/* Finally, write the token to the browser window */ | |
return tokenString | |
} | |
func usersHandler(w http.ResponseWriter, r *http.Request) { | |
if r.Method != "POST" { | |
http.NotFound(w, r) | |
return | |
} | |
r.ParseForm() | |
required := []string{"user_name", "email", "password"} | |
requiredError := validate(r, required) | |
if len(requiredError) > 0 { | |
b, err := json.Marshal(requiredError) | |
if err != nil { | |
log.Fatal(err) | |
} | |
w.Header().Set("Content-Type", "application/json") | |
w.Write([]byte(b)) | |
return | |
} | |
userName := r.FormValue("user_name") | |
email := r.FormValue("email") | |
password := r.FormValue("password") | |
if isEmailExist(email) { | |
w.Write([]byte("email already registered")) | |
return | |
} | |
passwordHash, err := hashPassword(password) | |
if err != nil { | |
fmt.Println(err) | |
return | |
} | |
_, err = db.Exec("insert into users (user_name, email, password)values(?, ?, ?)", userName, email, passwordHash) | |
if err != nil { | |
log.Printf("%v", err) | |
return | |
} | |
} | |
func postHandler(w http.ResponseWriter, r *http.Request) { | |
switch r.Method { | |
case "POST": | |
savePost(w, r) | |
case "GET": | |
} | |
} | |
func savePost(w http.ResponseWriter, r *http.Request) { | |
required := []string{"user_id", "title", "body"} | |
requiredError := validate(r, required) | |
if len(requiredError) > 0 { | |
b, err := json.Marshal(requiredError) | |
if err != nil { | |
log.Printf("%v", err) | |
return | |
} | |
w.Write(b) | |
return | |
} | |
userIDStr := r.FormValue("user_id") | |
userID, err := strconv.ParseInt(userIDStr, 10, 64) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
title := r.FormValue("title") | |
body := r.FormValue("body") | |
_, err = db.Exec("insert into posts(user_id, title, body)values(?, ?, ?)", userID, title, body) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
} | |
func isValidPostID(id int64) { | |
} | |
func getPost(w http.ResponseWriter, r *http.Request) { | |
} | |
func loginHandler(w http.ResponseWriter, r *http.Request) { | |
if r.Method != "POST" { | |
http.NotFound(w, r) | |
return | |
} | |
// required := []string{"email", "password"} | |
// | |
// requiredError := validate(r, required) | |
// | |
// if len(requiredError) > 0 { | |
// | |
// b, err := json.Marshal(requiredError) | |
// | |
// if err != nil { | |
// log.Println(err) | |
// return | |
// } | |
// w.Write(b) | |
// return | |
// } | |
email := r.FormValue("email") | |
password := r.FormValue("password") | |
if user, ok := isValidUser(email, password); ok { | |
token := getToken() | |
fmt.Println("user id ", user.ID) | |
saveToken(token, user.ID) | |
str := `{"success": "log in successful","access_token": "` + token + `" }` | |
w.Header().Set("Content-Type", "application/json") | |
w.Write([]byte(str)) | |
return | |
} | |
w.Write([]byte("login failed")) | |
} | |
func saveToken(token string, userID int64) { | |
_, err := db.Exec("update users set token =? where id =? ", token, userID) | |
if err != nil { | |
log.Println(err) | |
} | |
} | |
func isValidUser(email string, password string) (*User, bool) { | |
user := User{} | |
err := db.Get(&user, "select id, email, password from users where email =?", email) | |
if err != nil { | |
fmt.Println(err) | |
return nil, false | |
} | |
hash := user.Password | |
if checkPasswordHash(hash, password) { | |
return &user, true | |
} | |
return nil, false | |
} | |
func hashPassword(password string) (string, error) { | |
b, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) | |
return string(b), err | |
} | |
func checkPasswordHash(hash string, password string) bool { | |
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) | |
return err == nil | |
} | |
func isEmailExist(email string) bool { | |
user := User{} | |
err := db.Get(&user, "select email from users where email =?", email) | |
if err != nil { | |
return false | |
} | |
if len(user.Email) > 0 { | |
return true | |
} | |
return false | |
} | |
func saveUsers(w http.ResponseWriter, r *http.Request) { | |
} | |
func getUsers(w http.ResponseWriter, r *http.Request) { | |
} | |
func createTable(tableName string) { | |
schemaSQL := ` | |
create table users( | |
id bigint not null auto_increment, | |
user_name varchar(255), | |
email varchar(255) not null, | |
password varchar(100) not null, | |
created_at timestamp, | |
updated_at timestamp, | |
primary key (id) | |
) | |
` | |
result, err := db.Exec(schemaSQL) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Println(result) | |
schemaSQL = ` | |
create table posts( | |
id bigint not null auto_increment, | |
title varchar(255) , | |
body varchar(255), | |
user_id bigint not null, | |
primary key (id), | |
FOREIGN KEY(user_id) REFERENCES users(id) | |
) | |
` | |
result, err = db.Exec(schemaSQL) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Println(result) | |
schemaSQL = ` | |
create table comments( | |
id bigint not null auto_increment, | |
body varchar(255), | |
user_id bigint not null, | |
post_id bigint not null, | |
primary key (id), | |
FOREIGN KEY(user_id) REFERENCES users(id), | |
FOREIGN KEY(post_id) REFERENCES posts(id) | |
) | |
` | |
result, err = db.Exec(schemaSQL) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Println(result.RowsAffected()) | |
} | |
func middlewareToken(next http.Handler) http.Handler { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
required := []string{"user_id", "access_token"} | |
requiredError := validate(r, required) | |
if len(requiredError) > 0 { | |
b, err := json.Marshal(requiredError) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
w.Write([]byte(b)) | |
return | |
} | |
userIDStr := r.FormValue("user_id") | |
userID, err := strconv.ParseInt(userIDStr, 10, 64) | |
if err != nil { | |
log.Println(err) | |
return | |
} | |
token := r.FormValue("access_token") | |
if !verifyToken(userID, token) { | |
w.Write([]byte("unauthorised access")) | |
return | |
} | |
next.ServeHTTP(w, r) | |
}) | |
} | |
func verifyToken(userID int64, token string) bool { | |
user := User{} | |
err := db.Get(&user, "select id from users where id=? and token=?", userID, token) | |
if err != nil { | |
log.Println(err) | |
return false | |
} | |
if user.ID == userID { | |
return true | |
} | |
return false | |
} | |
func validate(r *http.Request, required []string) map[string]string { | |
// data := make(map[string]interface{}) | |
r.ParseForm() | |
params := r.Form | |
requiredError := make(map[string]string) | |
for _, v := range required { | |
if _, ok := params[v]; ok { | |
continue | |
} | |
requiredError[v] = v + " field is required" | |
} | |
return requiredError | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment