Add backend
This commit is contained in:
parent
312a8fb017
commit
9ddd929a0b
|
@ -0,0 +1,189 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"magmise/models"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
}
|
||||
|
||||
// "/user/:username"
|
||||
func (u User) Get(w http.ResponseWriter, r *http.Request) {
|
||||
username := chi.URLParam(r, "username")
|
||||
if username == "" {
|
||||
http.Error(w, "Missing user id", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
user := models.User{Username: username}
|
||||
if user.Read() != nil {
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(user); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
// "/user/{userid}"
|
||||
func (t User) Create(w http.ResponseWriter, r *http.Request) {
|
||||
username := chi.URLParam(r, "username")
|
||||
if username == "" {
|
||||
http.Error(w, "Missing username", http.StatusNotFound)
|
||||
}
|
||||
user := models.User{Username: username, Password: "a"}
|
||||
if user.Create() != nil {
|
||||
http.Error(w, "failed to create user", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// // /users/application/:status/
|
||||
// func (t User) Getusers(w http.ResponseWriter, r *http.Request) {
|
||||
// status := vestigo.Param(r, "status")
|
||||
// offset, err := strconv.ParseInt(vestigo.Param(r, "offset"), 0, 32)
|
||||
// if err != nil {
|
||||
// offset = 0
|
||||
// }
|
||||
|
||||
// limit, err := strconv.ParseInt(vestigo.Param(r, "limit"), 0, 32)
|
||||
// if err != nil {
|
||||
// limit = 100
|
||||
// }
|
||||
|
||||
// var user models.User
|
||||
// switch status {
|
||||
// case "open", "closed":
|
||||
// user = models.User{Status: status}
|
||||
// case "all":
|
||||
// user = models.User{}
|
||||
// default:
|
||||
// http.Error(w, "Missing status", http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
|
||||
// users, err := user.ReadAll(int(offset), int(limit))
|
||||
// if err != nil {
|
||||
// http.Error(w, "Not found", http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
// if err := json.NewEncoder(w).Encode(users); err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// w.Header().Add("Content-Type", "application/json")
|
||||
// }
|
||||
|
||||
// // "/user/application/:userid"
|
||||
// func (t User) Updateuser(w http.ResponseWriter, r *http.Request) {
|
||||
// userid := vestigo.Param(r, "userid")
|
||||
// if userid == "" {
|
||||
// http.Error(w, "Missing user or discord id", http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
// log.Println(r.Body)
|
||||
// var user models.User
|
||||
// if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// log.Println(user)
|
||||
// if err := user.Update(); err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // "/user/application/:userid"
|
||||
// func (t User) Deleteuser(w http.ResponseWriter, r *http.Request) {
|
||||
// userid := vestigo.Param(r, "userid")
|
||||
// if userid == "" {
|
||||
// http.Error(w, "Missing user or discord id", http.StatusNotFound)
|
||||
// }
|
||||
// user := models.User{userId: userid}
|
||||
|
||||
// if user.Delete() != nil {
|
||||
// http.Error(w, "failed to delete user", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // /user/:discordid/users/application/:status/
|
||||
// func (t User) GetUserusers(w http.ResponseWriter, r *http.Request) {
|
||||
// discordid, _ := strconv.ParseInt(vestigo.Param(r, "discordid"), 0, 64)
|
||||
// status := vestigo.Param(r, "status")
|
||||
// offset, err := strconv.ParseInt(vestigo.Param(r, "offset"), 0, 32)
|
||||
// if err != nil {
|
||||
// offset = 0
|
||||
// }
|
||||
|
||||
// limit, err := strconv.ParseInt(vestigo.Param(r, "limit"), 0, 32)
|
||||
// if err != nil {
|
||||
// limit = 100
|
||||
// }
|
||||
|
||||
// log.Println(discordid, status)
|
||||
// var user models.User
|
||||
// switch status {
|
||||
// case "open", "closed":
|
||||
// user = models.User{DiscordId: discordid, Status: status}
|
||||
// case "all":
|
||||
// user = models.User{DiscordId: discordid}
|
||||
// default:
|
||||
// http.Error(w, "Missing status", http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
|
||||
// users, err := user.ReadAll(int(offset), int(limit))
|
||||
// if err != nil {
|
||||
// http.Error(w, "Not found", http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
// if err := json.NewEncoder(w).Encode(users); err != nil {
|
||||
// http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// w.Header().Add("Content-Type", "application/json")
|
||||
// }
|
||||
|
||||
// // "/answer/application/:userid/:modalid"
|
||||
|
||||
// func (t User) AddAnswer(w http.ResponseWriter, r *http.Request) {
|
||||
// userid := vestigo.Param(r, "userid")
|
||||
// modalid := vestigo.Param(r, "modalid")
|
||||
// if userid == "" {
|
||||
// http.Error(w, "Missing user or discord id", http.StatusNotFound)
|
||||
// return
|
||||
// }
|
||||
// b, err := ioutil.ReadAll(r.Body)
|
||||
// if err != nil {
|
||||
// http.Error(w, "Missing body", http.StatusNotFound)
|
||||
// }
|
||||
// user := models.User{userId: userid}
|
||||
// if user.Read() != nil {
|
||||
// http.Error(w, "Failed to read user", http.StatusInternalServerError)
|
||||
// }
|
||||
// for _, answer := range user.Answers {
|
||||
// if answer.ModalId == modalid {
|
||||
// answer.Response = string(b)
|
||||
// if answer.Update() != nil {
|
||||
// http.Error(w, "Failed to update answer", http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// answer := models.Answer{ModalId: modalid, Response: string(b)}
|
||||
// user.Answers = append(user.Answers, answer)
|
||||
// if user.Update() != nil {
|
||||
// http.Error(w, "Failed to update user", http.StatusInternalServerError)
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,23 @@
|
|||
module magmise
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/go-chi/chi/v5 v5.0.7
|
||||
github.com/go-redis/redis/v8 v8.11.5
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/husobee/vestigo v1.1.1
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
||||
gorm.io/driver/sqlite v1.3.6
|
||||
gorm.io/gorm v1.23.8
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.12 // indirect
|
||||
github.com/stretchr/testify v1.8.0 // indirect
|
||||
)
|
|
@ -0,0 +1,51 @@
|
|||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/husobee/vestigo v1.1.1 h1:bsReVP78YhmHUn/nQ4AxIEfObmWMSLGLGXP1OwgFa9s=
|
||||
github.com/husobee/vestigo v1.1.1/go.mod h1:JigD7C8lzUfpo1uzqYgefpyZLswrtJbAQxMw7ds7YCE=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/mattn/go-sqlite3 v1.14.12 h1:TJ1bhYJPV44phC+IMu1u2K/i5RriLTPe+yc68XDJ1Z0=
|
||||
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/sqlite v1.3.6 h1:Fi8xNYCUplOqWiPa3/GuCeowRNBRGTf62DEmhMDHeQQ=
|
||||
gorm.io/driver/sqlite v1.3.6/go.mod h1:Sg1/pvnKtbQ7jLXxfZa+jSHvoX8hoZA8cn4xllOMTgE=
|
||||
gorm.io/gorm v1.23.4/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||
gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE=
|
||||
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"magmise/controllers"
|
||||
"magmise/models"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
models.Init()
|
||||
var user controllers.User
|
||||
r := chi.NewRouter()
|
||||
r.Use(middleware.Logger)
|
||||
r.Handle("/*", http.FileServer(http.Dir("/api/www")))
|
||||
r.Get("/user/{username}", user.Get)
|
||||
r.Post("/user/{username}", user.Create)
|
||||
http.ListenAndServe(":8080", r)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/golang-jwt/jwt"
|
||||
)
|
||||
|
||||
var secret = []byte(os.Getenv("SECRET"))
|
||||
|
||||
func Auth(f http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
// get token
|
||||
authheader, ok := r.Header["Authorization"]
|
||||
if !ok {
|
||||
http.Error(w, "Missing token", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
tokenString := strings.Split(authheader[0], " ")[1]
|
||||
|
||||
//parse token
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return secret, nil
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, "Bad token", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// check if path is allowed
|
||||
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid && r.URL.Path == claims["path"] {
|
||||
log.Println(r.URL.Path)
|
||||
f(w, r)
|
||||
} else {
|
||||
log.Println(err)
|
||||
http.Error(w, "Forbidden", http.StatusUnauthorized)
|
||||
}
|
||||
// it's all good
|
||||
}
|
||||
}
|
||||
|
||||
func GenerateToken(path string) {
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||
"path": path,
|
||||
})
|
||||
tokenString, err := token.SignedString(secret)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(tokenString)
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func BasicAuth(f http.HandlerFunc) http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
username, password, ok := r.BasicAuth()
|
||||
hash, err := HashPassword(os.Getenv("PASSWORD"))
|
||||
if err == nil && ok {
|
||||
if username == os.Getenv("USERNAME") && CheckPasswordHash(password, hash) {
|
||||
f(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`)
|
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
||||
})
|
||||
}
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPasswordHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var db *gorm.DB
|
||||
|
||||
func Init() {
|
||||
if _, err := os.Stat("/data/database.db"); errors.Is(err, os.ErrNotExist) {
|
||||
log.Printf("Creating sqlite database")
|
||||
_, err := os.Create("/data/database.db")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
var err error
|
||||
|
||||
db, err = gorm.Open(sqlite.Open("/data/database.db"), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Println("Failed to connect to db")
|
||||
}
|
||||
migrate()
|
||||
}
|
||||
|
||||
func DB() *gorm.DB {
|
||||
if db == nil {
|
||||
Init()
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func create(d interface{}) error {
|
||||
return DB().Create(&d).Error
|
||||
}
|
||||
|
||||
func read(d *interface{}) error {
|
||||
return DB().First(d, d).Error
|
||||
}
|
||||
|
||||
func readAll(d interface{}, offset, limit int) ([]interface{}, error) {
|
||||
var data []interface{}
|
||||
err := DB().Offset(offset).Limit(limit).Where(&d).Find(&data).Error
|
||||
return data, err
|
||||
}
|
||||
|
||||
func update(d interface{}, where string, f interface{}) error {
|
||||
return DB().Model(d).Where(where+" = ?", f).Updates(d).Error
|
||||
}
|
||||
|
||||
func delete(d interface{}) error {
|
||||
|
||||
return DB().Delete(d).Error
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package models
|
||||
|
||||
import "fmt"
|
||||
|
||||
func migrate() {
|
||||
DB().AutoMigrate(&User{})
|
||||
|
||||
fmt.Println("Migrated")
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
gorm.Model
|
||||
Username string `json:"username" gorm:"uniqueIndex, column: username"`
|
||||
Password string
|
||||
}
|
||||
|
||||
func (u User) Create() error {
|
||||
return DB().Create(&u).Error
|
||||
}
|
||||
|
||||
func (u *User) Read() error {
|
||||
return DB().First(u, u).Error
|
||||
}
|
||||
|
||||
func (u User) ReadAll(offset, limit int) ([]User, error) {
|
||||
var Users []User
|
||||
err := DB().Offset(offset).Limit(limit).Where(&u).Find(&Users).Error
|
||||
return Users, err
|
||||
}
|
||||
|
||||
func (u *User) Update() error {
|
||||
return DB().Model(u).Where("username = ?", u.Username).Updates(u).Error
|
||||
}
|
||||
|
||||
func (u *User) Delete() error {
|
||||
|
||||
return DB().Where("username = ?", u.Username).Delete(u).Error
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
package controllers_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"magmise/controllers"
|
||||
"magmise/models"
|
||||
"magmise/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// "/user/{username}"
|
||||
func TestGetUser(t *testing.T) {
|
||||
setup := test.Setup(t, "get user")
|
||||
defer setup()
|
||||
|
||||
var user controllers.User
|
||||
w := test.Request(t, user.Get, "GET", "/user/{username}", `{}`, map[string]string{"username": "fred"})
|
||||
|
||||
var usermodel models.User
|
||||
if json.Unmarshal(w.Body.Bytes(), &usermodel) != nil {
|
||||
t.Fail()
|
||||
}
|
||||
if usermodel.Username != "fred" {
|
||||
t.Fatal(usermodel)
|
||||
}
|
||||
t.Log(usermodel)
|
||||
}
|
||||
|
||||
// // "/user/application/:userid/:discordid"
|
||||
// func TestCreateuser(t *testing.T) {
|
||||
// setup := test.Setup(t)
|
||||
// defer setup()
|
||||
|
||||
// var user controllers.User
|
||||
// handler := http.HandlerFunc(user.Createuser)
|
||||
// r, err := http.NewRequest("POST", "/user/application/:userid/:discordid", nil)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// q := r.URL.Query()
|
||||
// q.Add(":userid", "6")
|
||||
// q.Add(":discordid", "6")
|
||||
// r.URL.RawQuery = q.Encode()
|
||||
// w := httptest.NewRecorder()
|
||||
// handler(w, r)
|
||||
// if w.Code != 200 {
|
||||
// t.Fail()
|
||||
// }
|
||||
// }
|
||||
|
||||
// // PATCH "/user/application/:userid"
|
||||
// func TestUpdateuser(t *testing.T) {
|
||||
// setup := test.Setup(t)
|
||||
// defer setup()
|
||||
// t.Log("Test Updateuser")
|
||||
// usermodel := models.User{userId: "1", Status: "closed"}
|
||||
// userjson, err := json.Marshal(usermodel)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// var user controllers.Userco
|
||||
// handler := http.HandlerFunc(user.Updateuser)
|
||||
// r, err := http.NewRequest("PATCH", "/user/application/:userid", bytes.NewBuffer(userjson))
|
||||
// r.Header.Set("Content-Type", "application/json; charset=UTF-8")
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// q := r.URL.Query()
|
||||
// q.Add(":userid", "1")
|
||||
// r.URL.RawQuery = q.Encode()
|
||||
// w := httptest.NewRecorder()
|
||||
// handler(w, r)
|
||||
// if w.Code != 200 {
|
||||
// t.Log(w.Body)
|
||||
// t.Fatal(w.Code)
|
||||
// }
|
||||
// usermodel.Read()
|
||||
// if usermodel.Status != "closed" {
|
||||
|
||||
// t.Fail()
|
||||
// }
|
||||
// }
|
||||
|
||||
// // "/user/application/:userid"
|
||||
// func TestDeleteuser(t *testing.T) {
|
||||
// setup := test.Setup(t)
|
||||
// defer setup()
|
||||
|
||||
// var user controllers.User
|
||||
// handler := http.HandlerFunc(user.Deleteuser)
|
||||
// r, err := http.NewRequest("POST", "/user/application/:userid", nil)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// q := r.URL.Query()
|
||||
// q.Add(":userid", "1")
|
||||
|
||||
// r.URL.RawQuery = q.Encode()
|
||||
// w := httptest.NewRecorder()
|
||||
// handler(w, r)
|
||||
// if w.Code != 200 {
|
||||
// t.Fail()
|
||||
// }
|
||||
// }
|
||||
|
||||
// // /user/:discordid/users/application/:status/
|
||||
// func TestGetUserusers(t *testing.T) {
|
||||
// setup := test.Setup(t)
|
||||
// defer setup()
|
||||
|
||||
// handler := http.HandlerFunc(controllers.User{}.GetUserusers)
|
||||
// r, err := http.NewRequest("GET", "/user/:discordid/users/application/:status/", nil)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// q := r.URL.Query()
|
||||
// q.Add(":discordid", "1")
|
||||
// q.Add(":status", "all")
|
||||
// q.Add(":limit", "100")
|
||||
// r.URL.RawQuery = q.Encode()
|
||||
// w := httptest.NewRecorder()
|
||||
// handler(w, r)
|
||||
// if w.Code != 200 {
|
||||
// t.Fail()
|
||||
// }
|
||||
// var users []models.User
|
||||
// if json.Unmarshal(w.Body.Bytes(), &users) != nil {
|
||||
// t.Fatal("Failed unmarshal")
|
||||
// }
|
||||
|
||||
// for _, user := range users {
|
||||
// t.Log(user)
|
||||
// t.Log("\n")
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // /users/application/:status/
|
||||
// func TestGetusers(t *testing.T) {
|
||||
// setup := test.Setup(t)
|
||||
// defer setup()
|
||||
|
||||
// handler := http.HandlerFunc(controllers.User{}.GetUserusers)
|
||||
// r, err := http.NewRequest("GET", "/users/application/:status/", nil)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// q := r.URL.Query()
|
||||
// q.Add(":status", "all")
|
||||
// q.Add(":limit", "100")
|
||||
// r.URL.RawQuery = q.Encode()
|
||||
// w := httptest.NewRecorder()
|
||||
// handler(w, r)
|
||||
// if w.Code != 200 {
|
||||
// t.Fail()
|
||||
// }
|
||||
// var users []models.User
|
||||
// if json.Unmarshal(w.Body.Bytes(), &users) != nil {
|
||||
// t.Fatal("Failed unmarshal")
|
||||
// }
|
||||
|
||||
// for _, user := range users {
|
||||
// t.Log(user)
|
||||
// t.Log("\n")
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// // "/answer/application/:userid/"
|
||||
// func TestAddAnswer(t *testing.T) {
|
||||
// setup := test.Setup(t)
|
||||
// defer setup()
|
||||
|
||||
// var user controllers.User
|
||||
// handler := http.HandlerFunc(user.AddAnswer)
|
||||
// r, err := http.NewRequest("POST", "/answer/application/:userid/", bytes.NewBufferString("Hello world"))
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
// q := r.URL.Query()
|
||||
// q.Add(":userid", "1")
|
||||
// r.URL.RawQuery = q.Encode()
|
||||
// w := httptest.NewRecorder()
|
||||
// handler(w, r)
|
||||
// if w.Code != 200 {
|
||||
// t.Fatal("Failed to add answer", w.Code)
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,18 @@
|
|||
package middleware_test
|
||||
|
||||
import (
|
||||
"magmise/middleware"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCheckPasswordHash(t *testing.T) {
|
||||
password := "password"
|
||||
hash, _ := middleware.HashPassword(password)
|
||||
if middleware.CheckPasswordHash(password, hash) == false {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicAuth(t *testing.T) {
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package models_test
|
||||
|
||||
import (
|
||||
"magmise/models"
|
||||
"magmise/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// func TestUserCreate(t *testing.T) {
|
||||
// cleanup := test.Setup(t, "user create")
|
||||
// defer cleanup()
|
||||
// user := models.User{Username: "Bob", Password: "a"}
|
||||
// if user.Create() != nil {
|
||||
// t.Fail()
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestUserRead(t *testing.T) {
|
||||
cleanup := test.Setup(t, "user read")
|
||||
defer cleanup()
|
||||
user := models.User{Username: "fred"}
|
||||
if user.Read() != nil {
|
||||
t.Fatal("Faied to read application user")
|
||||
}
|
||||
|
||||
if user.Password != "a" {
|
||||
t.Log(user)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserReadAll(t *testing.T) {
|
||||
cleanup := test.Setup(t, "user readall")
|
||||
defer cleanup()
|
||||
user := models.User{}
|
||||
users, err := user.ReadAll(0, 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if users[0].Username != "fred" {
|
||||
t.Log(users)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestUserUpdate(t *testing.T) {
|
||||
cleanup := test.Setup(t, "user update")
|
||||
defer cleanup()
|
||||
user := models.User{Username: "fred"}
|
||||
user.Read()
|
||||
user.Password = "b"
|
||||
if user.Update() != nil {
|
||||
t.Fail()
|
||||
}
|
||||
user.Read()
|
||||
if user.Password != "b" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserDelete(t *testing.T) {
|
||||
cleanup := test.Setup(t, "user delete")
|
||||
defer cleanup()
|
||||
user := models.User{Username: "fred"}
|
||||
if err := user.Delete(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if user.Read() == nil {
|
||||
t.Fatal(user)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"magmise/models"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
func Setup(t *testing.T, name string) func() {
|
||||
t.Log("Setup " + name)
|
||||
models.Init()
|
||||
//models.DB().Exec("DROP TABLE ticketapplication_answers")
|
||||
models.DB().Migrator().DropTable(models.User{})
|
||||
models.DB().AutoMigrate(models.User{})
|
||||
|
||||
models.User{Username: "fred", Password: "a"}.Create()
|
||||
return func() {
|
||||
t.Log("Cleanup " + name)
|
||||
models.DB().Migrator().DropTable(models.User{})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func Request(t *testing.T, model http.HandlerFunc, method, path, _json string, urlparams map[string]string) *httptest.ResponseRecorder {
|
||||
handler := http.HandlerFunc(model)
|
||||
r, err := http.NewRequest("GET", "/user/{username}", bytes.NewBufferString(_json))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rctx := chi.NewRouteContext()
|
||||
for key, value := range urlparams {
|
||||
rctx.URLParams.Add(key, value)
|
||||
}
|
||||
|
||||
r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, rctx))
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
handler(w, r)
|
||||
if w.Code != 200 {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
return w
|
||||
}
|
Loading…
Reference in New Issue