bashhub-server/internal/server.go
2020-02-07 11:14:22 -05:00

207 lines
6 KiB
Go

package internal
import (
"crypto/sha256"
"fmt"
"log"
"net/http"
"strconv"
"strings"
"time"
jwt_lib "github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
)
type User struct {
ID uint `gorm:"primary_key"`
Username string `form:"Username" json:"Username" xml:"Username" gorm:"type:varchar(200);unique_index"`
Email string `form:"email" json:"email" xml:"email"`
Password string `form:"password" json:"password" xml:"password"`
Mac *string `form:"mac" json:"mac" xml:"mac"`
RegistrationCode *string `form:"registrationCode" json:"registrationCode" xml:"registrationCode"`
Token string
}
type Query struct {
Uuid string `form:"uuid" json:"uuid" xml:"uuid"`
Command string `form:"command" json:"command" xml:"command"`
Created int64 `form:"created" json:"created" xml:"created"`
}
type SystemQuery struct {
ID uint `form:"id" json:"id" xml:"id" gorm:"primary_key"`
Created int64
Updated int64
Mac string `form:"mac" json:"mac" xml:"mac"`
Hostname *string `form:"hostname" json:"hostname" xml:"hostname"`
Name *string `form:"name" json:"name" xml:"name"`
ClientVersion *string `form:"clientVersion" json:"clientVersion" xml:"clientVersion"`
}
type Command struct {
ProcessId int `form:"processId" json:"processId" xml:"processId"`
ProcessStartTime int64 `form:"processStartTime" json:"processStartTime" xml:"processStartTime"`
Uuid string `form:"uuid" json:"uuid" xml:"uuid"`
Command string `form:"command" json:"command" xml:"command"`
Created int64 `form:"created" json:"created" xml:"created"`
Path string `form:"path" json:"path" xml:"path"`
ExitStatus int `form:"exitStatus" json:"exitStatus" xml:"exitStatus"`
User User `gorm:"association_foreignkey:ID"`
UserId uint
Token string `gorm:"-"`
Limit int `gorm:"-"`
Unique bool `gorm:"-"`
}
// {"mac": "83779604164095", "hostname": "yay.local", "name": "yay.local", "clientVersion": "1.2.0"}
//{"name":"Home","mac":"83779604164095","userId":"5b5d53b6e4b02a6c4914bec8","hostname":"yay.local","clientVersion":"1.2.0","id":"5b5d53c8e4b02a6c4914bec9","created":1532842952382,"updated":1581032237766}
type System struct {
ID uint `form:"id" json:"id" xml:"id" gorm:"primary_key"`
Created int64
Updated int64
Mac string `form:"mac" json:"mac" xml:"mac"`
Hostname *string `form:"hostname" json:"hostname" xml:"hostname"`
Name *string `form:"name" json:"name" xml:"name"`
ClientVersion *string `form:"clientVersion" json:"clientVersion" xml:"clientVersion"`
User User `gorm:"association_foreignkey:ID"`
UserId uint `form:"userId" json:"userId" xml:"userId"`
Token string `gorm:"-"`
}
func auth() gin.HandlerFunc {
return func(c *gin.Context) {
var user User
err := func() error {
user.Token = strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
if user.tokenExists() {
return nil
} else {
return fmt.Errorf("token doesn't exist")
}
}()
if err != nil {
c.AbortWithError(401, err)
}
}
}
func Run() {
DbInit()
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.POST("/api/v1/login", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user.Password = fmt.Sprintf("%v", sha256.Sum256([]byte(user.Password)))
if !user.userExists() {
c.String(401, "Bad credentials")
return
}
token := jwt_lib.New(jwt_lib.GetSigningMethod("HS256"))
token.Claims = jwt_lib.MapClaims{
"Id": user.Username,
"exp": time.Now().Add(time.Hour * 20000).Unix(),
}
// Sign and get the complete encoded token as a string
tokenString, err := token.SignedString([]byte(user.Password))
if err != nil {
c.JSON(500, gin.H{"message": "Could not generate token"})
}
user.Token = tokenString
user.updateToken()
c.JSON(200, gin.H{"accessToken": tokenString})
})
r.POST("/api/v1/user", func(c *gin.Context) {
var user User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if user.Email == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "email required"})
return
}
user.Password = fmt.Sprintf("%v", sha256.Sum256([]byte(user.Password)))
user.userCreate()
})
r.Use(auth())
r.GET("/api/v1/command/search", func(c *gin.Context) {
var command Command
command.Token = strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
command.Limit = 100
if c.Query("limit") != "" {
if num, err := strconv.Atoi(c.Query("limit")); err != nil {
command.Limit = num
}
}
if c.Query("unique") == "true" {
command.Unique = true
}else {
command.Unique = false
}
result := command.commandGet()
c.IndentedJSON(http.StatusOK, result)
})
r.POST("/api/v1/command", func(c *gin.Context) {
var command Command
if err := c.ShouldBindJSON(&command); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
command.Token = strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
command.commandInsert()
})
r.POST("/api/v1/system", func(c *gin.Context) {
var system System
err := c.Bind(&system)
if err != nil {
log.Fatal(err)
}
system.Token = strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
system.systemInsert()
c.AbortWithStatus(201)
})
r.GET("/api/v1/system", func(c *gin.Context) {
var system System
system.Token = strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
system.Mac = c.Query("mac")
if system.Mac == "" {
c.AbortWithStatus(http.StatusBadRequest)
return
}
result, err := system.systemGet()
if err != nil {
c.AbortWithStatus(404)
return
}
c.IndentedJSON(http.StatusOK, result)
})
r.Run()
}