Last active
February 3, 2016 17:23
-
-
Save ernado/f1500a4e8f10c381f4ee 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 ( | |
"database/sql" | |
"fmt" | |
"log" | |
"net/http" | |
"strconv" | |
"time" | |
"github.com/dgrijalva/jwt-go" | |
"github.com/gin-gonic/gin" | |
_ "github.com/go-sql-driver/mysql" | |
"github.com/gorilla/websocket" | |
"gopkg.in/gorp.v1" | |
"net/url" | |
) | |
var database *sql.DB | |
type User struct { | |
Id int64 `db:"id" json:"id"` | |
Email string `db:"email" json:"email"` | |
Username string `db:"username" json:"username"` | |
Password string `db:"password" json:"password"` | |
Sex int64 `db:"sex" json:"sex"` | |
Age int64 `db:"age" json:"age"` | |
} | |
type Login struct { | |
Email string `json:"email" binding:"required"` | |
Password string `json:"password" binding:"required"` | |
} | |
type Check struct { | |
Email string `json:"email" binding:"required"` | |
} | |
var ( | |
validUser = User{Id: 1, Email: "Vas", Username: "Sav"} | |
mySigningKey = "USEHERE" | |
) | |
var dbmap = initDb() | |
func initDb() *gorp.DbMap { | |
db, err := sql.Open("mysql", "root:root:root123456@/myapi") | |
checkErr(err, "sql.Open failed") | |
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}} | |
dbmap.AddTableWithName(User{}, "User").SetKeys(true, "Id") | |
err = dbmap.CreateTablesIfNotExists() | |
checkErr(err, "Create tables failed") | |
return dbmap | |
} | |
func checkErr(err error, msg string) { | |
if err != nil { | |
log.Fatalln(msg, err) | |
} | |
} | |
//var myconn string | |
//websocket | |
var connections map[*websocket.Conn]bool | |
var destinations map[string]*websocket.Conn | |
func wsHandler(w http.ResponseWriter, r *http.Request) { | |
// Taken from gorilla's website | |
conn, err := websocket.Upgrade(w, r, nil, 1024, 1024) | |
if _, ok := err.(websocket.HandshakeError); ok { | |
http.Error(w, "Not a websocket handshake", 400) | |
return | |
} else if err != nil { | |
log.Println(err) | |
return | |
} | |
log.Println("Succesfully upgraded connection") | |
connections[conn] = true | |
for { | |
// Blocks until a message is read | |
_, msg, err := conn.ReadMessage() | |
if err != nil { | |
delete(connections, conn) | |
conn.Close() | |
return | |
//log.Println(err) | |
} | |
log.Println(string(msg)) | |
sendAll(msg,conn) | |
} | |
} | |
func sendAll(msg []byte, myconn *websocket.Conn) { | |
for conn := range connections { | |
if myconn != conn { | |
if err := conn.WriteMessage(websocket.TextMessage, msg); err != nil { | |
delete(connections, conn) | |
conn.Close() | |
} | |
} | |
} | |
} | |
func wsHandlerChat(w http.ResponseWriter, r *http.Request) { | |
// Taken from gorilla's website | |
query := r.URL.Query() | |
// ws?origin=A&destination=B для юзера A | |
// ws?origin=B&destination=A для юзера B | |
originID := query.Get("origin") | |
destinationID := query.Get("destination") | |
conn, err := websocket.Upgrade(w, r, nil, 1024, 1024) | |
if _, ok := err.(websocket.HandshakeError); ok { | |
http.Error(w, "Not a websocket handshake", 400) | |
return | |
} else if err != nil { | |
log.Println(err) | |
return | |
} | |
destinations[originID] = conn | |
log.Println("Succesfully upgraded connection") | |
connections[conn] = true | |
for { | |
// Blocks until a message is read | |
_, msg, err := conn.ReadMessage() | |
if err != nil { | |
delete(destinations, originID) | |
delete(connections, conn) | |
conn.Close() | |
return | |
//log.Println(err) | |
} | |
log.Println(string(msg)) | |
connDestination, ok := destinations[destinationID] | |
if !ok { | |
log.Println("destination", destinationID, "not found") | |
continue | |
} | |
if err := connDestination.WriteMessage(websocket.TextMessage, msg); err != nil { | |
delete(connections, connDestination) | |
delete(destinations, destinationID) | |
conn.Close() | |
} | |
} | |
} | |
//end websocket | |
func main() { | |
r := gin.Default() | |
r.GET("/ws", func(c *gin.Context) { | |
wsHandler(c.Writer, c.Request) | |
}) | |
r.GET("/ws/chat", func(c *gin.Context) { | |
wsHandlerChat(c.Writer, c.Request) | |
}) | |
connections = make(map[*websocket.Conn]bool) | |
destinations = make(map[string]*websocket.Conn) | |
v1 := r.Group("api/v1") | |
{ | |
v1.GET("/users", GetUsers) | |
v1.GET("/users/:id", GetUser) | |
v1.GET("/chat/:origin/:destination", GetChat) | |
//v1.GET("/users/email", GetPassword) | |
v1.POST("/users", PostUser) | |
v1.PUT("/users/:id", UpdateUser) | |
v1.DELETE("/users/:id", DeleteUser) | |
} | |
//func to return fogot password | |
r.Use(func(c *gin.Context) { | |
// Run this on all requests | |
// Should be moved to a proper middleware | |
c.Writer.Header().Set("Access-Control-Allow-Origin", "*") | |
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") | |
c.Next() | |
}) | |
r.OPTIONS("/*cors", func(c *gin.Context) { | |
// Empty 200 response | |
}) | |
r.POST("/users/token", func(c *gin.Context) { | |
var login Login | |
val := c.Bind(&login) | |
dbb, err := sql.Open("mysql", "root:root123456@/myapi") | |
if err != nil { | |
} | |
database = dbb | |
var email string | |
var password string | |
sql := "Select email,password from User where email='" + login.Email + "'" | |
q := database.QueryRow(sql).Scan(&email, &password) | |
if q != nil { | |
//log.Fatal(q) | |
} | |
fmt.Println(email) | |
fmt.Println(password) | |
if val != nil { | |
c.JSON(200, gin.H{"code": 401, "msg": "Both name & password are required"}) | |
return | |
} | |
if login.Email == email && login.Password == password { | |
// if login.Firstname == dbmap.Select("Select firstname from User where id=1") { | |
token := jwt.New(jwt.SigningMethodHS256) | |
// Headers | |
token.Header["alg"] = "HS256" | |
token.Header["typ"] = "JWT" | |
// Claims | |
token.Claims["name"] = login.Email | |
token.Claims["mail"] = login.Password | |
token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() | |
tokenString, err := token.SignedString([]byte(mySigningKey)) | |
if err != nil { | |
c.JSON(200, gin.H{"code": 500, "msg": "Server error!"}) | |
return | |
} | |
c.JSON(200, gin.H{"code": 200, "msg": "OK", "jwt": tokenString}) | |
} else { | |
c.JSON(200, gin.H{"code": 400, "msg": "Error username or password!"}) | |
} | |
}) | |
//check | |
r.POST("/users/email", func(c *gin.Context) { | |
var check Check | |
val := c.Bind(&check) | |
dbb, err := sql.Open("mysql", "root:root123456@/myapi") | |
if err != nil { | |
} | |
database = dbb | |
var email string | |
var password string | |
sql := "Select email,password from User where email='" + check.Email + "'" | |
q := database.QueryRow(sql).Scan(&email, &password) | |
if q != nil { | |
// log.Fatal(q) | |
} | |
fmt.Println(email) | |
fmt.Println(password) | |
if val != nil { | |
// c.JSON(200, gin.H{"code": 401, "msg": "Both name & password are required"}) | |
//return | |
} | |
if check.Email == email { | |
//if 1==1 { | |
c.JSON(200, gin.H{"code": 200, "msg": "OK", "Your Password": password}) | |
} else { | |
c.JSON(200, gin.H{"code": 400, "msg": "Error Mail!"}) | |
} | |
}) | |
r.Run(":8080") | |
} | |
func GetUsers(c *gin.Context) { | |
var users []User | |
_, err := dbmap.Select(&users, "SELECT * FROM User;") | |
if err == nil { | |
c.JSON(200, users) | |
} else { | |
c.JSON(404, gin.H{"error": "no user(s) into the table"}) | |
} | |
// curl -i http://localhost:8080/api/v1/users | |
} | |
func GetUser(c *gin.Context) { | |
id := c.Params.ByName("id") | |
var user User | |
err := dbmap.SelectOne(&user, "SELECT * FROM User WHERE id=? LIMIT 1;", id) | |
if err == nil { | |
user_id, _ := strconv.ParseInt(id, 0, 64) | |
content := &User{ | |
Id: user_id, | |
Email: user.Email, | |
Username: user.Username, | |
Password: user.Password, | |
Sex: user.Sex, | |
Age: user.Age, | |
} | |
c.JSON(200, content) | |
} else { | |
c.JSON(404, gin.H{"error": "user not found"}) | |
} | |
// curl -i http://localhost:8080/api/v1/users/1 | |
} | |
func GetChat(c *gin.Context) { | |
originID := c.Params.ByName("origin") | |
destinationID := c.Params.ByName("destination") | |
wsURL := new(url.URL) | |
query := wsURL.Query() | |
query.Add("origin", originID) | |
query.Add("destination", destinationID) | |
wsURL.Path = "/ws/chat" | |
wsURL.RawQuery = query.Encode() | |
c.JSON(200, gin.H{"websocket_url": wsURL.String()}) | |
// curl -i http://localhost:8080/api/v1/chat/1/2 | |
} | |
func PostUser(c *gin.Context) { | |
var user User | |
c.Bind(&user) | |
log.Println(user) | |
if user.Email != "" && user.Username != "" { | |
if insert, _ := dbmap.Exec(`INSERT INTO User (email, username, password, sex, age) VALUES (?, ?, ?, ?, ?)`, user.Email, user.Username, user.Password, user.Sex, user.Age); insert != nil { | |
user_id, err := insert.LastInsertId() | |
if err == nil { | |
content := &User{ | |
Id: user_id, | |
Email: user.Email, | |
Username: user.Username, | |
Password: user.Password, | |
Sex: user.Sex, | |
Age: user.Age, | |
} | |
c.JSON(201, content) | |
} else { | |
checkErr(err, "Insert failed") | |
} | |
} | |
} else { | |
c.JSON(400, gin.H{"error": "fields are empty"}) | |
} | |
// curl -i -X POST -H "Content-Type: application/json" -d "{ \"firstname\": \"Thea\", \"lastname\": \"Queen\" }" http://localhost:8080/api/v1/users | |
} | |
func UpdateUser(c *gin.Context) { | |
id := c.Params.ByName("id") | |
var user User | |
err := dbmap.SelectOne(&user, "SELECT * FROM User WHERE id=?;", id) | |
if err == nil { | |
var json User | |
c.Bind(&json) | |
user_id, _ := strconv.ParseInt(id, 0, 64) | |
user := User{ | |
Id: user_id, | |
Email: user.Email, | |
Username: user.Username, | |
Password: user.Password, | |
Sex: user.Sex, | |
Age: user.Age, | |
} | |
if user.Email != "" && user.Username != "" { | |
_, err = dbmap.Update(&user) | |
if err == nil { | |
c.JSON(200, user) | |
} else { | |
checkErr(err, "Updated failed") | |
} | |
} else { | |
c.JSON(400, gin.H{"error": "fields are empty"}) | |
} | |
} else { | |
c.JSON(404, gin.H{"error": "user not found"}) | |
} | |
// curl -i -X PUT -H "Content-Type: application/json" -d "{ \"firstname\": \"Thea\", \"lastname\": \"Merlyn\" }" http://localhost:8080/api/v1/users/1 | |
} | |
func DeleteUser(c *gin.Context) { | |
id := c.Params.ByName("id") | |
var user User | |
err := dbmap.SelectOne(&user, "SELECT * FROM User WHERE id=?;", id) | |
if err == nil { | |
_, err = dbmap.Delete(&user) | |
if err == nil { | |
c.JSON(200, gin.H{"id #" + id: "deleted"}) | |
} else { | |
checkErr(err, "Delete failed") | |
} | |
} else { | |
c.JSON(404, gin.H{"error": "user not found"}) | |
} | |
// curl -i -X DELETE http://localhost:8080/api/v1/users/1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment