Browse Source

Add user_id to post model

Add update and delete cruds to user API
pull/2/head
Tovi Jaeschke-Rogers 3 years ago
parent
commit
4cb80bbb3a
13 changed files with 533 additions and 170 deletions
  1. +22
    -0
      Api/Auth/Passwords.go
  2. +5
    -0
      Api/JsonSerialization/VerifyJson.go
  3. +1
    -16
      Api/PostImages_test.go
  4. +3
    -7
      Api/Posts.go
  5. +55
    -94
      Api/Posts_test.go
  6. +7
    -2
      Api/Routes.go
  7. +51
    -0
      Api/UserHelper.go
  8. +102
    -1
      Api/Users.go
  9. +193
    -29
      Api/Users_test.go
  10. +36
    -15
      Database/Init.go
  11. +52
    -1
      Database/Users.go
  12. +5
    -4
      Models/Posts.go
  13. +1
    -1
      Models/Users.go

+ 22
- 0
Api/Auth/Passwords.go View File

@ -0,0 +1,22 @@
package Auth
import (
"golang.org/x/crypto/bcrypt"
)
func HashPassword(password string) (string, error) {
var (
bytes []byte
err error
)
bytes, err = bcrypt.GenerateFromPassword([]byte(password), 14)
return string(bytes), err
}
func CheckPasswordHash(password, hash string) bool {
var (
err error
)
err = bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}

+ 5
- 0
Api/JsonSerialization/VerifyJson.go View File

@ -40,6 +40,7 @@ func isFloatType(t reflect.Type) (yes bool) {
func CanConvert(t reflect.Type, v reflect.Value) bool { func CanConvert(t reflect.Type, v reflect.Value) bool {
isPtr := t.Kind() == reflect.Ptr isPtr := t.Kind() == reflect.Ptr
isStruct := t.Kind() == reflect.Struct isStruct := t.Kind() == reflect.Struct
isArray := t.Kind() == reflect.Array
dstType := t dstType := t
// Check if v is a nil value. // Check if v is a nil value.
@ -58,6 +59,10 @@ func CanConvert(t reflect.Type, v reflect.Value) bool {
return v.Kind() == reflect.Map return v.Kind() == reflect.Map
} }
if isArray {
return v.Kind() == reflect.String
}
if t.Kind() == reflect.Slice { if t.Kind() == reflect.Slice {
return v.Kind() == reflect.Slice return v.Kind() == reflect.Slice
} }


+ 1
- 16
Api/PostImages_test.go View File

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -22,7 +21,6 @@ import (
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"gorm.io/gorm"
) )
func init() { func init() {
@ -34,8 +32,7 @@ func init() {
panic(err) panic(err)
} }
log.SetOutput(ioutil.Discard)
Database.Init()
Database.InitTest()
r = mux.NewRouter() r = mux.NewRouter()
} }
@ -181,12 +178,6 @@ func Test_createPostImages(t *testing.T) {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
} }
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks", "PostImages").
Delete(&postData)
if len(updatePostData.PostImages) != 1 { if len(updatePostData.PostImages) != 1 {
t.Errorf("Expected len(updatePostData.PostImages) == 1, recieved %d", len(updatePostData.PostImages)) t.Errorf("Expected len(updatePostData.PostImages) == 1, recieved %d", len(updatePostData.PostImages))
} }
@ -243,12 +234,6 @@ func Test_deletePostImages(t *testing.T) {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
} }
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks", "PostImages").
Delete(&postData)
req, err := http.NewRequest("DELETE", fmt.Sprintf( req, err := http.NewRequest("DELETE", fmt.Sprintf(
"%s/post/%s/image/%s", "%s/post/%s/image/%s",
ts.URL, ts.URL,


+ 3
- 7
Api/Posts.go View File

@ -11,8 +11,6 @@ import (
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"github.com/gorilla/mux"
) )
func getPosts(w http.ResponseWriter, r *http.Request) { func getPosts(w http.ResponseWriter, r *http.Request) {
@ -131,6 +129,7 @@ func createPost(w http.ResponseWriter, r *http.Request) {
"audios", "audios",
}, false) }, false)
if err != nil { if err != nil {
panic(err)
log.Printf("Invalid data provided to posts API: %s\n", err.Error()) log.Printf("Invalid data provided to posts API: %s\n", err.Error())
JsonReturn(w, 405, "Invalid data") JsonReturn(w, 405, "Invalid data")
return return
@ -158,15 +157,12 @@ func updatePost(w http.ResponseWriter, r *http.Request) {
postData Models.Post postData Models.Post
requestBody []byte requestBody []byte
returnJson []byte returnJson []byte
urlVars map[string]string
id string id string
ok bool
err error err error
) )
urlVars = mux.Vars(r)
id, ok = urlVars["postID"]
if !ok {
id, err = getPostId(r)
if err != nil {
log.Printf("Error encountered getting id\n") log.Printf("Error encountered getting id\n")
JsonReturn(w, 500, "An error occured") JsonReturn(w, 500, "An error occured")
return return


+ 55
- 94
Api/Posts_test.go View File

@ -3,8 +3,6 @@ package Api
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"log"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
@ -17,7 +15,6 @@ import (
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"gorm.io/gorm"
) )
var ( var (
@ -33,12 +30,34 @@ func init() {
panic(err) panic(err)
} }
log.SetOutput(ioutil.Discard)
Database.Init()
Database.InitTest()
r = mux.NewRouter() r = mux.NewRouter()
} }
func createTestPost() (Models.Post, error) {
userData, err := createTestUser(true)
postData := Models.Post{
UserID: userData.ID,
Title: "Test post",
Content: "Test content",
FrontPage: true,
Order: 1,
PostLinks: []Models.PostLink{
{
Type: "Facebook",
Link: "http://facebook.com/",
},
},
}
err = Database.CreatePost(&postData)
return postData, err
}
func Test_getPosts(t *testing.T) { func Test_getPosts(t *testing.T) {
t.Log("Testing getPosts...") t.Log("Testing getPosts...")
@ -49,29 +68,7 @@ func Test_getPosts(t *testing.T) {
var err error var err error
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
postData := Models.Post{
Title: "Test post",
Content: "Test content",
FrontPage: true,
Order: i,
PostLinks: []Models.PostLink{
{
Type: "Facebook",
Link: "http://facebook.com/",
},
},
}
err = Database.CreatePost(&postData)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks").
Delete(&postData)
createTestPost()
} }
res, err := http.Get(ts.URL + "/post?page=1&pageSize=10") res, err := http.Get(ts.URL + "/post?page=1&pageSize=10")
@ -103,30 +100,12 @@ func Test_getPost(t *testing.T) {
defer ts.Close() defer ts.Close()
postData := Models.Post{
Title: "Test post",
Content: "Test content",
FrontPage: true,
Order: 1,
PostLinks: []Models.PostLink{
{
Type: "Facebook",
Link: "http://facebook.com/",
},
},
}
err := Database.CreatePost(&postData)
postData, err := createTestPost()
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
} }
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks").
Delete(&postData)
res, err := http.Get(fmt.Sprintf( res, err := http.Get(fmt.Sprintf(
"%s/post/%s", "%s/post/%s",
ts.URL, ts.URL,
@ -135,16 +114,36 @@ func Test_getPost(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
} }
if res.StatusCode != http.StatusOK { if res.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode)
t.FailNow()
} }
getPostData := new(Models.Post) getPostData := new(Models.Post)
err = json.NewDecoder(res.Body).Decode(getPostData) err = json.NewDecoder(res.Body).Decode(getPostData)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
}
if getPostData.Title != "Test post" {
t.Errorf("Expected title \"Test post\", recieved %s", getPostData.Title)
t.FailNow()
} }
if getPostData.Content != "Test content" {
t.Errorf("Expected content \"Test content\", recieved %s", getPostData.Content)
t.FailNow()
}
if len(getPostData.PostLinks) != 1 {
t.Errorf("Expected len(PostLinks) == 1, recieved %d", len(getPostData.PostLinks))
t.FailNow()
}
} }
func Test_createPost(t *testing.T) { func Test_createPost(t *testing.T) {
@ -156,8 +155,11 @@ func Test_createPost(t *testing.T) {
defer ts.Close() defer ts.Close()
userData, err := createTestUser(true)
postJson := ` postJson := `
{ {
"user_id": "%s",
"title": "Test post", "title": "Test post",
"content": "Test content", "content": "Test content",
"front_page": true, "front_page": true,
@ -169,6 +171,8 @@ func Test_createPost(t *testing.T) {
} }
` `
postJson = fmt.Sprintf(postJson, userData.ID.String())
res, err := http.Post(ts.URL+"/post", "application/json", strings.NewReader(postJson)) res, err := http.Post(ts.URL+"/post", "application/json", strings.NewReader(postJson))
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
@ -183,12 +187,6 @@ func Test_createPost(t *testing.T) {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
} }
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks").
Delete(&postData)
if postData.Title != "Test post" { if postData.Title != "Test post" {
t.Errorf("Expected title \"Test post\", recieved \"%s\"", postData.Title) t.Errorf("Expected title \"Test post\", recieved \"%s\"", postData.Title)
} }
@ -206,30 +204,12 @@ func Test_deletePost(t *testing.T) {
defer ts.Close() defer ts.Close()
postData := Models.Post{
Title: "Test post",
Content: "Test content",
FrontPage: true,
Order: 1,
PostLinks: []Models.PostLink{
{
Type: "Facebook",
Link: "http://facebook.com/",
},
},
}
err := Database.CreatePost(&postData)
postData, err := createTestPost()
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
} }
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks").
Delete(&postData)
req, err := http.NewRequest("DELETE", fmt.Sprintf( req, err := http.NewRequest("DELETE", fmt.Sprintf(
"%s/post/%s", "%s/post/%s",
ts.URL, ts.URL,
@ -262,20 +242,7 @@ func Test_updatePost(t *testing.T) {
defer ts.Close() defer ts.Close()
postData := Models.Post{
Title: "Test post",
Content: "Test content",
FrontPage: true,
Order: 1,
PostLinks: []Models.PostLink{
{
Type: "Facebook",
Link: "http://facebook.com/",
},
},
}
err := Database.CreatePost(&postData)
postData, err := createTestPost()
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
} }
@ -315,12 +282,6 @@ func Test_updatePost(t *testing.T) {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
} }
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Select("PostLinks").
Delete(&postData)
if updatePostData.Content != "New test content" { if updatePostData.Content != "New test content" {
t.Errorf("Expected \"New test content\", recieved %s", updatePostData.Content) t.Errorf("Expected \"New test content\", recieved %s", updatePostData.Content)
} }


+ 7
- 2
Api/Routes.go View File

@ -17,17 +17,22 @@ func InitApiEndpoints() *mux.Router {
// Define routes for posts api // Define routes for posts api
router.HandleFunc("/post", getPosts).Methods("GET") router.HandleFunc("/post", getPosts).Methods("GET")
router.HandleFunc("/frontPagePosts", getFrontPagePosts).Methods("GET")
router.HandleFunc("/post", createPost).Methods("POST") router.HandleFunc("/post", createPost).Methods("POST")
router.HandleFunc("/post/{postID}", createPost).Methods("GET")
router.HandleFunc("/post/{postID}", getPost).Methods("GET")
router.HandleFunc("/post/{postID}", updatePost).Methods("PUT") router.HandleFunc("/post/{postID}", updatePost).Methods("PUT")
router.HandleFunc("/post/{postID}", deletePost).Methods("DELETE") router.HandleFunc("/post/{postID}", deletePost).Methods("DELETE")
router.HandleFunc("/frontPagePosts", getFrontPagePosts).Methods("GET")
router.HandleFunc("/post/{postID}/image", createPostImage).Methods("POST") router.HandleFunc("/post/{postID}/image", createPostImage).Methods("POST")
router.HandleFunc("/post/{postID}/image/{imageID}", deletePostImage).Methods("DELETE") router.HandleFunc("/post/{postID}/image/{imageID}", deletePostImage).Methods("DELETE")
// Define routes for users api // Define routes for users api
router.HandleFunc("/user", getUsers).Methods("GET")
router.HandleFunc("/user", createUser).Methods("POST") router.HandleFunc("/user", createUser).Methods("POST")
router.HandleFunc("/user/{userID}", getUser).Methods("GET")
router.HandleFunc("/user/{userID}", updatePost).Methods("PUT")
router.HandleFunc("/user/{userID}", deletePost).Methods("DELETE")
//router.PathPrefix("/").Handler(http.StripPrefix("/images/", http.FileServer(http.Dir("./uploads")))) //router.PathPrefix("/").Handler(http.StripPrefix("/images/", http.FileServer(http.Dir("./uploads"))))


+ 51
- 0
Api/UserHelper.go View File

@ -0,0 +1,51 @@
package Api
import (
"errors"
"log"
"net/http"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"github.com/gorilla/mux"
)
func getUserId(r *http.Request) (string, error) {
var (
urlVars map[string]string
id string
ok bool
)
urlVars = mux.Vars(r)
id, ok = urlVars["userID"]
if !ok {
return id, errors.New("Could not get id")
}
return id, nil
}
func getUserById(w http.ResponseWriter, r *http.Request) (Models.User, error) {
var (
postData Models.User
id string
err error
)
id, err = getUserId(r)
if err != nil {
log.Printf("Error encountered getting id\n")
JsonReturn(w, 500, "An error occured")
return postData, err
}
postData, err = Database.GetUserById(id)
if err != nil {
log.Printf("Could not find pet with id %s\n", id)
JsonReturn(w, 404, "Not found")
return postData, err
}
return postData, nil
}

+ 102
- 1
Api/Users.go View File

@ -8,6 +8,7 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/Auth"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
@ -56,6 +57,29 @@ func getUsers(w http.ResponseWriter, r *http.Request) {
w.Write(returnJson) w.Write(returnJson)
} }
func getUser(w http.ResponseWriter, r *http.Request) {
var (
userData Models.User
returnJson []byte
err error
)
userData, err = getUserById(w, r)
if err != nil {
return
}
returnJson, err = json.MarshalIndent(userData, "", " ")
if err != nil {
JsonReturn(w, 500, "An error occured")
return
}
// Return updated json
w.WriteHeader(http.StatusOK)
w.Write(returnJson)
}
func createUser(w http.ResponseWriter, r *http.Request) { func createUser(w http.ResponseWriter, r *http.Request) {
var ( var (
userData Models.User userData Models.User
@ -87,16 +111,93 @@ func createUser(w http.ResponseWriter, r *http.Request) {
} }
if userData.Password != userData.ConfirmPassword { if userData.Password != userData.ConfirmPassword {
JsonReturn(w, 500, "invalid_password")
JsonReturn(w, 405, "invalid_password")
return
}
userData.Password, err = Auth.HashPassword(userData.Password)
if err != nil {
JsonReturn(w, 500, "An error occured")
return return
} }
err = Database.CreateUser(&userData) err = Database.CreateUser(&userData)
if err != nil { if err != nil {
JsonReturn(w, 500, "An error occured")
return
}
// Return updated json
w.WriteHeader(http.StatusOK)
}
func updateUser(w http.ResponseWriter, r *http.Request) {
var (
userData Models.User
requestBody []byte
returnJson []byte
id string
err error
)
id, err = getUserId(r)
if err != nil {
log.Printf("Error encountered getting id\n")
JsonReturn(w, 500, "An error occured")
return
}
requestBody, err = ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("Error encountered reading POST body: %s\n", err.Error())
JsonReturn(w, 500, "An error occured")
return
}
userData, err = JsonSerialization.DeserializeUser(requestBody, []string{}, true)
if err != nil {
log.Printf("Invalid data provided to users API: %s\n", err.Error())
JsonReturn(w, 405, "Invalid data") JsonReturn(w, 405, "Invalid data")
return return
} }
err = Database.UpdateUser(id, &userData)
if err != nil {
log.Printf("An error occured: %s\n", err.Error())
JsonReturn(w, 500, "An error occured")
return
}
returnJson, err = json.MarshalIndent(userData, "", " ")
if err != nil {
log.Printf("An error occured: %s\n", err.Error())
JsonReturn(w, 500, "An error occured")
return
}
// Return updated json
w.WriteHeader(http.StatusOK)
w.Write(returnJson)
}
func deleteUser(w http.ResponseWriter, r *http.Request) {
var (
userData Models.User
err error
)
userData, err = getUserById(w, r)
if err != nil {
return
}
err = Database.DeleteUser(&userData)
if err != nil {
log.Printf("An error occured: %s\n", err.Error())
JsonReturn(w, 500, "An error occured")
return
}
// Return updated json // Return updated json
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }

+ 193
- 29
Api/Users_test.go View File

@ -3,8 +3,6 @@ package Api
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"log"
"math/rand" "math/rand"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -13,11 +11,12 @@ import (
"runtime" "runtime"
"strings" "strings"
"testing" "testing"
"time"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/Auth"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"gorm.io/gorm"
) )
func init() { func init() {
@ -29,15 +28,14 @@ func init() {
panic(err) panic(err)
} }
log.SetOutput(ioutil.Discard)
Database.Init()
Database.InitTest()
r = mux.NewRouter() r = mux.NewRouter()
} }
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
func RandStringRunes(n int) string {
func randString(n int) string {
b := make([]rune, n) b := make([]rune, n)
for i := range b { for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))] b[i] = letterRunes[rand.Intn(len(letterRunes))]
@ -45,6 +43,84 @@ func RandStringRunes(n int) string {
return string(b) return string(b)
} }
func createTestUser(random bool) (Models.User, error) {
now := time.Now()
email := "email@email.com"
if random {
email = fmt.Sprintf("%s@email.com", randString(16))
}
password, err := Auth.HashPassword("password")
if err != nil {
return Models.User{}, err
}
userData := Models.User{
Email: email,
Password: password,
LastLogin: &now,
FirstName: "Hugh",
LastName: "Mann",
}
err = Database.CreateUser(&userData)
return userData, err
}
func Test_getUser(t *testing.T) {
t.Log("Testing getPost...")
r.HandleFunc("/user/{userID}", getUser).Methods("GET")
ts := httptest.NewServer(r)
defer ts.Close()
userData, err := createTestUser(false)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
}
res, err := http.Get(fmt.Sprintf(
"%s/user/%s",
ts.URL,
userData.ID,
))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
}
if res.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode)
t.FailNow()
}
getUserData := new(Models.User)
err = json.NewDecoder(res.Body).Decode(getUserData)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
}
if getUserData.Email != "email@email.com" {
t.Errorf("Expected email \"email@email.com\", recieved %s", getUserData.Email)
t.FailNow()
}
if getUserData.FirstName != "Hugh" {
t.Errorf("Expected email \"Hugh\", recieved %s", getUserData.FirstName)
t.FailNow()
}
if getUserData.LastName != "Mann" {
t.Errorf("Expected email \"Mann\", recieved %s", getUserData.LastName)
t.FailNow()
}
}
func Test_getUsers(t *testing.T) { func Test_getUsers(t *testing.T) {
t.Log("Testing getUsers...") t.Log("Testing getUsers...")
@ -55,43 +131,30 @@ func Test_getUsers(t *testing.T) {
var err error var err error
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
userData := Models.User{
Email: fmt.Sprintf(
"%s@email.com",
RandStringRunes(16),
),
Password: "password",
ConfirmPassword: "password",
}
err = Database.CreateUser(&userData)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
defer Database.DB.
Session(&gorm.Session{FullSaveAssociations: true}).
Unscoped().
Delete(&userData)
createTestUser(true)
} }
res, err := http.Get(ts.URL + "/user?page=1&pageSize=10") res, err := http.Get(ts.URL + "/user?page=1&pageSize=10")
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
} }
if res.StatusCode != http.StatusOK { if res.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode)
t.FailNow()
} }
getUsersData := new([]Models.User) getUsersData := new([]Models.User)
err = json.NewDecoder(res.Body).Decode(getUsersData) err = json.NewDecoder(res.Body).Decode(getUsersData)
if err != nil { if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error()) t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
} }
if len(*getUsersData) != 10 { if len(*getUsersData) != 10 {
t.Errorf("Expected 10, recieved %d", len(*getUsersData)) t.Errorf("Expected 10, recieved %d", len(*getUsersData))
t.FailNow()
} }
} }
@ -104,15 +167,18 @@ func Test_createUser(t *testing.T) {
defer ts.Close() defer ts.Close()
email := fmt.Sprintf("%s@email.com", randString(16))
postJson := ` postJson := `
{ {
"email": "email@email.com",
"email": "%s",
"password": "password", "password": "password",
"confirm_password": "password", "confirm_password": "password",
"first_name": "Hugh", "first_name": "Hugh",
"last_name": "Mann" "last_name": "Mann"
} }
` `
postJson = fmt.Sprintf(postJson, email)
res, err := http.Post(ts.URL+"/user", "application/json", strings.NewReader(postJson)) res, err := http.Post(ts.URL+"/user", "application/json", strings.NewReader(postJson))
if err != nil { if err != nil {
@ -124,9 +190,107 @@ func Test_createUser(t *testing.T) {
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode)
return return
} }
}
func Test_updateUser(t *testing.T) {
t.Log("Testing updateUser...")
r.HandleFunc("/user/{userID}", updateUser).Methods("PUT")
ts := httptest.NewServer(r)
defer ts.Close()
userData, err := createTestUser(true)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
email := fmt.Sprintf("%s@email.com", randString(16))
postJson := `
{
"email": "%s",
"first_name": "first",
"last_name": "last"
}
`
postJson = fmt.Sprintf(postJson, email)
req, err := http.NewRequest("PUT", fmt.Sprintf(
"%s/user/%s",
ts.URL,
userData.ID,
), strings.NewReader(postJson))
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
// Fetch Request
res, err := http.DefaultClient.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode)
}
updateUserData := new(Models.User)
err = json.NewDecoder(res.Body).Decode(updateUserData)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
if updateUserData.Email != email {
t.Errorf("Expected email \"%s\", recieved %s", email, updateUserData.Email)
}
if updateUserData.FirstName != "first" {
t.Errorf("Expected FirstName \"first\", recieved %s", updateUserData.FirstName)
}
if updateUserData.LastName != "last" {
t.Errorf("Expected LastName \"last\", recieved %s", updateUserData.LastName)
}
}
func Test_deleteUser(t *testing.T) {
t.Log("Testing deleteUser...")
r.HandleFunc("/user/{userID}", deleteUser).Methods("DELETE")
ts := httptest.NewServer(r)
defer ts.Close()
userData, err := createTestUser(true)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
t.FailNow()
}
req, err := http.NewRequest("DELETE", fmt.Sprintf(
"%s/user/%s",
ts.URL,
userData.ID,
), nil)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
}
// Fetch Request
res, err := http.DefaultClient.Do(req)
if err != nil {
t.Errorf("Expected nil, recieved %s", err.Error())
return
}
defer res.Body.Close()
Database.DB.Model(Models.User{}).
Select("count(*) > 0").
Where("email = ?", "email@email.com").
Delete(Models.User{})
if res.StatusCode != http.StatusOK {
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode)
}
} }

+ 36
- 15
Database/Init.go View File

@ -10,14 +10,30 @@ import (
) )
const dbUrl = "postgres://postgres:@localhost:5432/sudden_impact_records" const dbUrl = "postgres://postgres:@localhost:5432/sudden_impact_records"
const dbTestUrl = "postgres://postgres:@localhost:5432/sudden_impact_records_test"
var ( var (
DB *gorm.DB DB *gorm.DB
) )
func GetModels() []interface{} {
return []interface{}{
&Models.User{},
&Models.PostImage{},
&Models.PostVideo{},
&Models.PostAudio{},
&Models.PostLink{},
&Models.Post{},
&Models.SubscriptionEmailAttachment{},
&Models.SubscriptionEmail{},
&Models.Subscription{},
}
}
func Init() { func Init() {
var ( var (
err error
model interface{}
err error
) )
log.Println("Initializing database...") log.Println("Initializing database...")
@ -28,22 +44,27 @@ func Init() {
log.Fatalln(err) log.Fatalln(err)
} }
log.Println("Running AutoMigrate on Post tables...")
log.Println("Running AutoMigrate...")
for _, model = range GetModels() {
DB.AutoMigrate(model)
}
}
// Post tables
DB.AutoMigrate(&Models.PostImage{})
DB.AutoMigrate(&Models.PostVideo{})
DB.AutoMigrate(&Models.PostAudio{})
DB.AutoMigrate(&Models.PostLink{})
DB.AutoMigrate(&Models.Post{})
func InitTest() {
var (
model interface{}
err error
)
log.Println("Running AutoMigrate on Subscription tables...")
DB, err = gorm.Open(postgres.Open(dbTestUrl), &gorm.Config{})
// Email subscription tables
DB.AutoMigrate(&Models.SubscriptionEmailAttachment{})
DB.AutoMigrate(&Models.SubscriptionEmail{})
DB.AutoMigrate(&Models.Subscription{})
if err != nil {
log.Fatalln(err)
}
log.Println("Running AutoMigrate on User tables...")
DB.AutoMigrate(&Models.User{})
for _, model = range GetModels() {
DB.Migrator().DropTable(model)
DB.AutoMigrate(model)
}
} }

+ 52
- 1
Database/Users.go View File

@ -6,11 +6,28 @@ import (
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause"
) )
func GetUserById(id string) (Models.User, error) {
var (
userData Models.User
err error
)
err = DB.Preload(clause.Associations).
First(&userData, "id = ?", id).
Error
userData.Password = ""
return userData, err
}
func GetUsers(page, pageSize int) ([]Models.User, error) { func GetUsers(page, pageSize int) ([]Models.User, error) {
var ( var (
users []Models.User users []Models.User
i int
err error err error
) )
@ -30,6 +47,10 @@ func GetUsers(page, pageSize int) ([]Models.User, error) {
Find(&users). Find(&users).
Error Error
for i, _ = range users {
users[i].Password = ""
}
return users, err return users, err
} }
@ -57,7 +78,37 @@ func CheckUniqueEmail(email string) error {
} }
func CreateUser(userData *Models.User) error { func CreateUser(userData *Models.User) error {
return DB.Session(&gorm.Session{FullSaveAssociations: true}).
var (
err error
)
err = DB.Session(&gorm.Session{FullSaveAssociations: true}).
Create(userData). Create(userData).
Error Error
userData.Password = ""
return err
}
func UpdateUser(id string, userData *Models.User) error {
var (
err error
)
err = DB.Model(&Models.Post{}).
Select("*").
Omit("id", "created_at", "updated_at", "deleted_at").
Where("id = ?", id).
Updates(userData).
Error
userData.Password = ""
return err
}
func DeleteUser(userData *Models.User) error {
return DB.Session(&gorm.Session{FullSaveAssociations: true}).
Delete(userData).
Error
} }

+ 5
- 4
Models/Posts.go View File

@ -6,10 +6,11 @@ import (
type Post struct { type Post struct {
Base Base
Title string `gorm:"not null" json:"title"`
Content string `gorm:"not null" json:"content"`
FrontPage bool `gorm:"not null;type:boolean" json:"front_page"`
Order int `gorm:"not null" json:"order"`
UserID uuid.UUID `gorm:"type:uuid;column:user_id;not null;" json:"user_id"`
Title string `gorm:"not null" json:"title"`
Content string `gorm:"not null" json:"content"`
FrontPage bool `gorm:"not null;type:boolean" json:"front_page"`
Order int `gorm:"not null" json:"order"`
PostLinks []PostLink `json:"links"` PostLinks []PostLink `json:"links"`
PostImages []PostImage `json:"images"` PostImages []PostImage `json:"images"`


+ 1
- 1
Models/Users.go View File

@ -7,7 +7,7 @@ import (
type User struct { type User struct {
Base Base
Email string `gorm:"not null;unique" json:"email"` Email string `gorm:"not null;unique" json:"email"`
Password string `gorm:"not null" json:"password"`
Password string `gorm:"not null" json:"password,omitempty"`
ConfirmPassword string `gorm:"-" json:"confirm_password"` ConfirmPassword string `gorm:"-" json:"confirm_password"`
LastLogin *time.Time `json:"last_login"` LastLogin *time.Time `json:"last_login"`
FirstName string `gorm:"not null" json:"first_name"` FirstName string `gorm:"not null" json:"first_name"`


Loading…
Cancel
Save