Skip to content

Instantly share code, notes, and snippets.

@monirz
Created October 23, 2017 16:17
Show Gist options
  • Save monirz/aa1be66fb4e2ac121f4ed525ca55b76c to your computer and use it in GitHub Desktop.
Save monirz/aa1be66fb4e2ac121f4ed525ca55b76c to your computer and use it in GitHub Desktop.
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