@ -0,0 +1,76 @@ | |||
package JsonSerialization | |||
import ( | |||
"encoding/json" | |||
"errors" | |||
"fmt" | |||
"strings" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" | |||
schema "github.com/Kangaroux/go-map-schema" | |||
) | |||
func DeserializePost(data []byte, allowMissing []string, allowAllMissing bool) (Models.Post, error) { | |||
var ( | |||
postData Models.Post = Models.Post{} | |||
jsonStructureTest map[string]interface{} = make(map[string]interface{}) | |||
jsonStructureTestResults *schema.CompareResults | |||
field schema.FieldMissing | |||
allowed string | |||
missingFields []string | |||
i int | |||
err error | |||
) | |||
// Verify the JSON has the correct structure | |||
json.Unmarshal(data, &jsonStructureTest) | |||
jsonStructureTestResults, err = schema.CompareMapToStruct( | |||
&postData, | |||
jsonStructureTest, | |||
&schema.CompareOpts{ | |||
ConvertibleFunc: CanConvert, | |||
TypeNameFunc: schema.DetailedTypeName, | |||
}) | |||
if err != nil { | |||
return postData, err | |||
} | |||
if len(jsonStructureTestResults.MismatchedFields) > 0 { | |||
return postData, errors.New(fmt.Sprintf( | |||
"MismatchedFields found when deserializing data: %s", | |||
jsonStructureTestResults.Errors().Error(), | |||
)) | |||
} | |||
// Remove allowed missing fields from MissingFields | |||
for _, allowed = range allowMissing { | |||
for i, field = range jsonStructureTestResults.MissingFields { | |||
if allowed == field.String() { | |||
jsonStructureTestResults.MissingFields = append( | |||
jsonStructureTestResults.MissingFields[:i], | |||
jsonStructureTestResults.MissingFields[i+1:]..., | |||
) | |||
} | |||
} | |||
} | |||
if !allowAllMissing && len(jsonStructureTestResults.MissingFields) > 0 { | |||
for _, field = range jsonStructureTestResults.MissingFields { | |||
missingFields = append(missingFields, field.String()) | |||
} | |||
return postData, errors.New(fmt.Sprintf( | |||
"MissingFields found when deserializing data: %s", | |||
strings.Join(missingFields, ", "), | |||
)) | |||
} | |||
// Deserialize the JSON into the struct | |||
err = json.Unmarshal(data, &postData) | |||
if err != nil { | |||
return postData, err | |||
} | |||
return postData, err | |||
} |
@ -0,0 +1,87 @@ | |||
package JsonSerialization | |||
import ( | |||
"math" | |||
"reflect" | |||
) | |||
// isIntegerType returns whether the type is an integer and if it's unsigned. | |||
// See: https://github.com/Kangaroux/go-map-schema/blob/master/schema.go#L328 | |||
func isIntegerType(t reflect.Type) (yes bool, unsigned bool) { | |||
switch t.Kind() { | |||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | |||
yes = true | |||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |||
yes = true | |||
unsigned = true | |||
} | |||
return | |||
} | |||
// isFloatType returns true if the type is a floating point. Note that this doesn't | |||
// care about the value -- unmarshaling the number "0" gives a float, not an int. | |||
// See: https://github.com/Kangaroux/go-map-schema/blob/master/schema.go#L319 | |||
func isFloatType(t reflect.Type) (yes bool) { | |||
switch t.Kind() { | |||
case reflect.Float32, reflect.Float64: | |||
yes = true | |||
} | |||
return | |||
} | |||
// CanConvert returns whether value v is convertible to type t. | |||
// | |||
// If t is a pointer and v is not nil, it checks if v is convertible to the type that | |||
// t points to. | |||
// Modified due to not handling slices (DefaultCanConvert fails on PhotoUrls and Tags) | |||
// See: https://github.com/Kangaroux/go-map-schema/blob/master/schema.go#L191 | |||
func CanConvert(t reflect.Type, v reflect.Value) bool { | |||
isPtr := t.Kind() == reflect.Ptr | |||
isStruct := t.Kind() == reflect.Struct | |||
dstType := t | |||
// Check if v is a nil value. | |||
if !v.IsValid() || (v.CanAddr() && v.IsNil()) { | |||
return isPtr | |||
} | |||
// If the dst is a pointer, check if we can convert to the type it's pointing to. | |||
if isPtr { | |||
dstType = t.Elem() | |||
isStruct = t.Elem().Kind() == reflect.Struct | |||
} | |||
// If the dst is a struct, we should check its nested fields. | |||
if isStruct { | |||
return v.Kind() == reflect.Map | |||
} | |||
if t.Kind() == reflect.Slice { | |||
return v.Kind() == reflect.Slice | |||
} | |||
if !v.Type().ConvertibleTo(dstType) { | |||
return false | |||
} | |||
// Handle converting to an integer type. | |||
if dstInt, unsigned := isIntegerType(dstType); dstInt { | |||
if isFloatType(v.Type()) { | |||
f := v.Float() | |||
if math.Trunc(f) != f { | |||
return false | |||
} else if unsigned && f < 0 { | |||
return false | |||
} | |||
} else if srcInt, _ := isIntegerType(v.Type()); srcInt { | |||
if unsigned && v.Int() < 0 { | |||
return false | |||
} | |||
} | |||
} | |||
return true | |||
} |
@ -0,0 +1,257 @@ | |||
package Api | |||
import ( | |||
"encoding/json" | |||
"errors" | |||
"io/ioutil" | |||
"log" | |||
"net/http" | |||
"net/url" | |||
"strconv" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" | |||
"github.com/gorilla/mux" | |||
) | |||
func getPostById(w http.ResponseWriter, r *http.Request) (Models.Post, error) { | |||
var ( | |||
postData Models.Post | |||
urlVars map[string]string | |||
id string | |||
ok bool | |||
err error | |||
) | |||
urlVars = mux.Vars(r) | |||
id, ok = urlVars["postID"] | |||
if !ok { | |||
log.Printf("Error encountered getting id\n") | |||
JsonReturn(w, 500, "An error occured") | |||
return postData, errors.New("Could not get id") | |||
} | |||
postData, err = Database.GetPostById(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 | |||
} | |||
func getPosts(w http.ResponseWriter, r *http.Request) { | |||
var ( | |||
posts []Models.Post | |||
returnJson []byte | |||
values url.Values | |||
page, pageSize int | |||
err error | |||
) | |||
values = r.URL.Query() | |||
page, err = strconv.Atoi(values.Get("page")) | |||
if err != nil { | |||
log.Println("Could not parse page url argument") | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
page, err = strconv.Atoi(values.Get("pageSize")) | |||
if err != nil { | |||
log.Println("Could not parse pageSize url argument") | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
posts, err = Database.GetPosts(page, pageSize) | |||
if err != nil { | |||
log.Printf("An error occured: %s\n", err.Error()) | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
returnJson, err = json.MarshalIndent(posts, "", " ") | |||
if err != nil { | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
// Return updated json | |||
w.WriteHeader(http.StatusOK) | |||
w.Write(returnJson) | |||
} | |||
func getFrontPagePosts(w http.ResponseWriter, r *http.Request) { | |||
var ( | |||
posts []Models.Post | |||
returnJson []byte | |||
err error | |||
) | |||
posts, err = Database.GetFrontPagePosts() | |||
if err != nil { | |||
log.Printf("An error occured: %s\n", err.Error()) | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
returnJson, err = json.MarshalIndent(posts, "", " ") | |||
if err != nil { | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
// Return updated json | |||
w.WriteHeader(http.StatusOK) | |||
w.Write(returnJson) | |||
} | |||
func getPost(w http.ResponseWriter, r *http.Request) { | |||
var ( | |||
postData Models.Post | |||
returnJson []byte | |||
err error | |||
) | |||
postData, err = getPostById(w, r) | |||
if err != nil { | |||
return | |||
} | |||
returnJson, err = json.MarshalIndent(postData, "", " ") | |||
if err != nil { | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
// Return updated json | |||
w.WriteHeader(http.StatusOK) | |||
w.Write(returnJson) | |||
} | |||
func createPost(w http.ResponseWriter, r *http.Request) { | |||
var ( | |||
requestBody []byte | |||
postData Models.Post | |||
returnJson []byte | |||
err error | |||
) | |||
// TODO: Add auth | |||
log.Printf("Posts handler recieved %s request", r.Method) | |||
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 | |||
} | |||
postData, err = JsonSerialization.DeserializePost(requestBody, []string{ | |||
"id", | |||
"links", | |||
"images", | |||
"videos", | |||
"audios", | |||
}, false) | |||
if err != nil { | |||
log.Printf("Invalid data provided to posts API: %s\n", err.Error()) | |||
JsonReturn(w, 405, "Invalid data") | |||
return | |||
} | |||
err = Database.CreatePost(&postData) | |||
if err != nil { | |||
JsonReturn(w, 405, "Invalid data") | |||
} | |||
returnJson, err = json.MarshalIndent(postData, "", " ") | |||
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 updatePost(w http.ResponseWriter, r *http.Request) { | |||
var ( | |||
postData Models.Post | |||
requestBody []byte | |||
returnJson []byte | |||
urlVars map[string]string | |||
id string | |||
ok bool | |||
err error | |||
) | |||
urlVars = mux.Vars(r) | |||
id, ok = urlVars["postID"] | |||
if !ok { | |||
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 | |||
} | |||
postData, err = JsonSerialization.DeserializePost(requestBody, []string{}, true) | |||
if err != nil { | |||
log.Printf("Invalid data provided to posts API: %s\n", err.Error()) | |||
JsonReturn(w, 405, "Invalid data") | |||
return | |||
} | |||
postData, err = Database.UpdatePost(id, &postData) | |||
if err != nil { | |||
log.Printf("An error occured: %s\n", err.Error()) | |||
JsonReturn(w, 500, "An error occured") | |||
return | |||
} | |||
returnJson, err = json.MarshalIndent(postData, "", " ") | |||
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 deletePost(w http.ResponseWriter, r *http.Request) { | |||
var ( | |||
postData Models.Post | |||
err error | |||
) | |||
postData, err = getPostById(w, r) | |||
if err != nil { | |||
return | |||
} | |||
err = Database.DeletePost(&postData) | |||
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) | |||
} |
@ -0,0 +1,289 @@ | |||
package Api | |||
import ( | |||
"encoding/json" | |||
"fmt" | |||
"io/ioutil" | |||
"log" | |||
"net/http" | |||
"net/http/httptest" | |||
"strings" | |||
"testing" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" | |||
"github.com/gorilla/mux" | |||
) | |||
func Test_getPosts(t *testing.T) { | |||
log.SetOutput(ioutil.Discard) | |||
Database.Init() | |||
r := mux.NewRouter() | |||
r.HandleFunc("/post", getPosts).Methods("GET") | |||
ts := httptest.NewServer(r) | |||
defer ts.Close() | |||
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://google.com/", | |||
}, | |||
}, | |||
} | |||
Database.CreatePost(&postData) | |||
defer Database.DB.Unscoped().Delete(&postData) | |||
} | |||
res, err := http.Get(ts.URL + "/post?page=1&pageSize=10") | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
if res.StatusCode != http.StatusOK { | |||
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) | |||
} | |||
getPostsData := new([]Models.Post) | |||
err = json.NewDecoder(res.Body).Decode(getPostsData) | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
if len(*getPostsData) != 10 { | |||
t.Errorf("Expected 10, recieved %d", len(*getPostsData)) | |||
} | |||
} | |||
func Test_getPost(t *testing.T) { | |||
log.SetOutput(ioutil.Discard) | |||
Database.Init() | |||
r := mux.NewRouter() | |||
r.HandleFunc("/post/{postID}", getPost).Methods("GET") | |||
ts := httptest.NewServer(r) | |||
defer ts.Close() | |||
postData := Models.Post{ | |||
Title: "Test post", | |||
Content: "Test content", | |||
FrontPage: true, | |||
Order: 1, | |||
PostLinks: []Models.PostLink{ | |||
{ | |||
Type: "Facebook", | |||
Link: "http://google.com/", | |||
}, | |||
}, | |||
} | |||
Database.CreatePost(&postData) | |||
res, err := http.Get(fmt.Sprintf( | |||
"%s/post/%s", | |||
ts.URL, | |||
postData.ID, | |||
)) | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
if res.StatusCode != http.StatusOK { | |||
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) | |||
} | |||
getPostData := new(Models.Post) | |||
err = json.NewDecoder(res.Body).Decode(getPostData) | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
Database.DB.Unscoped().Delete(&postData) | |||
} | |||
func Test_createPost(t *testing.T) { | |||
log.SetOutput(ioutil.Discard) | |||
Database.Init() | |||
r := mux.NewRouter() | |||
r.HandleFunc("/post", createPost).Methods("POST") | |||
ts := httptest.NewServer(r) | |||
defer ts.Close() | |||
postJson := ` | |||
{ | |||
"title": "Test post", | |||
"content": "Test content", | |||
"front_page": true, | |||
"order": 1, | |||
"links": [{ | |||
"type": "Facebook", | |||
"link": "http://google.com/" | |||
}] | |||
} | |||
` | |||
res, err := http.Post(ts.URL+"/post", "application/json", strings.NewReader(postJson)) | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
if res.StatusCode != http.StatusOK { | |||
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) | |||
} | |||
postData := new(Models.Post) | |||
err = json.NewDecoder(res.Body).Decode(postData) | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
if postData.Title != "Test post" { | |||
t.Errorf("Expected title \"Test post\", recieved \"%s\"", postData.Title) | |||
} | |||
if postData.Content != "Test content" { | |||
t.Errorf("Expected content \"Test content\", recieved \"%s\"", postData.Content) | |||
} | |||
Database.DB.Unscoped().Delete(&postData) | |||
} | |||
func Test_deletePost(t *testing.T) { | |||
log.SetOutput(ioutil.Discard) | |||
Database.Init() | |||
r := mux.NewRouter() | |||
r.HandleFunc("/post/{postID}", deletePost).Methods("DELETE") | |||
ts := httptest.NewServer(r) | |||
defer ts.Close() | |||
postData := Models.Post{ | |||
Title: "Test post", | |||
Content: "Test content", | |||
FrontPage: true, | |||
Order: 1, | |||
PostLinks: []Models.PostLink{ | |||
{ | |||
Type: "Facebook", | |||
Link: "http://google.com/", | |||
}, | |||
}, | |||
} | |||
Database.CreatePost(&postData) | |||
req, err := http.NewRequest("DELETE", fmt.Sprintf( | |||
"%s/post/%s", | |||
ts.URL, | |||
postData.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() | |||
if res.StatusCode != http.StatusOK { | |||
t.Errorf("Expected %d, recieved %d", http.StatusOK, res.StatusCode) | |||
} | |||
Database.DB.Unscoped().Delete(&postData) | |||
} | |||
func Test_updatePost(t *testing.T) { | |||
log.SetOutput(ioutil.Discard) | |||
Database.Init() | |||
r := mux.NewRouter() | |||
r.HandleFunc("/post/{postID}", updatePost).Methods("PUT") | |||
ts := httptest.NewServer(r) | |||
defer ts.Close() | |||
postData := Models.Post{ | |||
Title: "Test post", | |||
Content: "Test content", | |||
FrontPage: true, | |||
Order: 1, | |||
PostLinks: []Models.PostLink{ | |||
{ | |||
Type: "Facebook", | |||
Link: "http://google.com/", | |||
}, | |||
}, | |||
} | |||
Database.CreatePost(&postData) | |||
postJson := ` | |||
{ | |||
"content": "New test content", | |||
"front_page": false, | |||
"order": 2 | |||
} | |||
` | |||
req, err := http.NewRequest("PUT", fmt.Sprintf( | |||
"%s/post/%s", | |||
ts.URL, | |||
postData.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) | |||
} | |||
updatePostData := new(Models.Post) | |||
err = json.NewDecoder(res.Body).Decode(updatePostData) | |||
if err != nil { | |||
t.Errorf("Expected nil, recieved %s", err.Error()) | |||
} | |||
if updatePostData.Content != "New test content" { | |||
t.Errorf("Expected \"New test content\", recieved %s", updatePostData.Content) | |||
} | |||
if updatePostData.FrontPage != false { | |||
t.Errorf("Expected false, recieved %t", updatePostData.FrontPage) | |||
} | |||
if updatePostData.Order != 2 { | |||
t.Errorf("Expected 2, recieved %d", updatePostData.Order) | |||
} | |||
Database.DB.Unscoped().Delete(&postData) | |||
} |
@ -0,0 +1,28 @@ | |||
package Api | |||
import ( | |||
"encoding/json" | |||
"log" | |||
"net/http" | |||
) | |||
func JsonReturn(w http.ResponseWriter, code int, msg string) { | |||
var ( | |||
responseJsonMap map[string]interface{} | |||
responseJson []byte | |||
err error | |||
) | |||
responseJsonMap = make(map[string]interface{}) | |||
w.WriteHeader(code) | |||
responseJsonMap["code"] = code | |||
responseJsonMap["message"] = msg | |||
responseJson, err = json.MarshalIndent(responseJsonMap, "", " ") | |||
if err != nil { | |||
log.Printf("Error occured creating response: %s\n", err.Error()) | |||
} | |||
w.Write(responseJson) | |||
} |
@ -0,0 +1,29 @@ | |||
package Api | |||
import ( | |||
"log" | |||
"github.com/gorilla/mux" | |||
) | |||
func InitApiEndpoints() *mux.Router { | |||
var ( | |||
router *mux.Router | |||
) | |||
log.Println("Initializing API routes...") | |||
router = mux.NewRouter() | |||
// Define routes for posts api | |||
router.HandleFunc("/post", getPosts).Methods("GET") | |||
router.HandleFunc("/frontPagePosts", getFrontPagePosts).Methods("GET") | |||
router.HandleFunc("/post", createPost).Methods("POST") | |||
router.HandleFunc("/post/{postID}", createPost).Methods("GET") | |||
router.HandleFunc("/post/{postID}", updatePost).Methods("PUT") | |||
router.HandleFunc("/post/{postID}", deletePost).Methods("DELETE") | |||
//router.PathPrefix("/").Handler(http.StripPrefix("/images/", http.FileServer(http.Dir("./uploads")))) | |||
return router | |||
} |
@ -0,0 +1,90 @@ | |||
package Database | |||
import ( | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models" | |||
"gorm.io/gorm" | |||
"gorm.io/gorm/clause" | |||
) | |||
func GetPosts(page, pageSize int) ([]Models.Post, error) { | |||
var ( | |||
posts []Models.Post | |||
err error | |||
) | |||
if page == 0 { | |||
page = 1 | |||
} | |||
switch { | |||
case pageSize > 100: | |||
pageSize = 100 | |||
case pageSize <= 0: | |||
pageSize = 10 | |||
} | |||
err = DB.Offset(page). | |||
Limit(pageSize). | |||
Find(&posts). | |||
Error | |||
return posts, err | |||
} | |||
func GetFrontPagePosts() ([]Models.Post, error) { | |||
var ( | |||
posts []Models.Post | |||
err error | |||
) | |||
err = DB.Where("front_page = ?", true). | |||
Order("order asc"). | |||
Find(&posts). | |||
Error | |||
return posts, err | |||
} | |||
func GetPostById(id string) (Models.Post, error) { | |||
var ( | |||
postData Models.Post | |||
err error | |||
) | |||
err = DB.Preload(clause.Associations). | |||
First(&postData, "id = ?", id). | |||
Error | |||
return postData, err | |||
} | |||
func CreatePost(postData *Models.Post) error { | |||
return DB.Session(&gorm.Session{FullSaveAssociations: true}). | |||
Create(postData). | |||
Error | |||
} | |||
func UpdatePost(id string, postData *Models.Post) (Models.Post, error) { | |||
var ( | |||
err error | |||
) | |||
err = DB.Model(&Models.Post{}). | |||
Select("*"). | |||
Omit("id", "created_at", "updated_at", "deleted_at"). | |||
Where("id = ?", id). | |||
Updates(postData). | |||
Error | |||
if err != nil { | |||
return Models.Post{}, err | |||
} | |||
return GetPostById(id) | |||
} | |||
func DeletePost(postData *Models.Post) error { | |||
return DB.Session(&gorm.Session{FullSaveAssociations: true}). | |||
Delete(postData). | |||
Error | |||
} |
@ -0,0 +1,53 @@ | |||
package Models | |||
import ( | |||
"github.com/gofrs/uuid" | |||
) | |||
type Post struct { | |||
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"` | |||
PostLinks []PostLink `json:"links"` | |||
PostImages []PostImage `json:"images"` | |||
PostVideos []PostVideo `json:"videos"` | |||
PostAudios []PostAudio `json:"audios"` | |||
} | |||
type PostLinkType string | |||
const ( | |||
POST_LINK_FACEBOOK PostLinkType = "Facebook" | |||
POST_LINK_INSTAGRAM PostLinkType = "Instagram" | |||
POST_LINK_YOUTUBE PostLinkType = "YouTube" | |||
POST_LINK_SPOTIFY PostLinkType = "Spotify" | |||
POST_LINK_OTHER PostLinkType = "Other" | |||
) | |||
type PostLink struct { | |||
Base | |||
PostID uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;" json:"post_id"` | |||
Link string `gorm:"not null" json:"link"` | |||
Type PostLinkType `gorm:"not null" json:"type"` | |||
} | |||
type PostImage struct { | |||
Base | |||
PostID uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;" json:"post_id"` | |||
Filepath string `gorm:"not null" json:"filepath"` | |||
} | |||
type PostVideo struct { | |||
Base | |||
PostID uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;" json:"post_id"` | |||
Filepath string `gorm:"not null" json:"filepath"` | |||
} | |||
type PostAudio struct { | |||
Base | |||
PostID uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;" json:"post_id"` | |||
Filepath string `gorm:"not null" json:"filepath"` | |||
} |
@ -1 +0,0 @@ | |||
package database |
@ -1,11 +1,24 @@ | |||
package main | |||
import ( | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/database" | |||
"net/http" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api" | |||
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database" | |||
"github.com/gorilla/mux" | |||
) | |||
func main() { | |||
var () | |||
var ( | |||
router *mux.Router | |||
) | |||
Database.Init() | |||
router = Api.InitApiEndpoints() | |||
database.Init() | |||
// TODO: Run this within goroutine when running vue application | |||
// Start and listen to requests | |||
http.ListenAndServe(":8080", router) | |||
} |
@ -1,48 +0,0 @@ | |||
package models | |||
import ( | |||
"github.com/gofrs/uuid" | |||
) | |||
type Post struct { | |||
Base | |||
Title string `gorm:"not null"` | |||
Content string `gorm:"not null"` | |||
FrontPage bool `gorm:"not null"` | |||
Order int `gorm:"not null"` | |||
} | |||
type PostLinkType string | |||
const ( | |||
POST_LINK_FACEBOOK PostLinkType = "Facebook" | |||
POST_LINK_INSTAGRAM PostLinkType = "Instagram" | |||
POST_LINK_YOUTUBE PostLinkType = "YouTube" | |||
POST_LINK_SPOTIFY PostLinkType = "Spotify" | |||
POST_LINK_OTHER PostLinkType = "Other" | |||
) | |||
type PostLink struct { | |||
Base | |||
PostId uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;"` | |||
Link string `gorm:"not null"` | |||
Type PostLinkType `gorm:"not null"` | |||
} | |||
type PostImage struct { | |||
Base | |||
PostId uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;"` | |||
Filepath string `gorm:"not null"` | |||
} | |||
type PostVideo struct { | |||
Base | |||
PostId uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;"` | |||
Filepath string `gorm:"not null"` | |||
} | |||
type PostAudio struct { | |||
Base | |||
PostId uuid.UUID `gorm:"type:uuid;column:post_foreign_key;not null;"` | |||
Filepath string `gorm:"not null"` | |||
} |