diff --git a/Api/JsonSerialization/VerifyJson.go b/Api/JsonSerialization/VerifyJson.go
index 862e7c8..3a3ae78 100644
--- a/Api/JsonSerialization/VerifyJson.go
+++ b/Api/JsonSerialization/VerifyJson.go
@@ -55,6 +55,7 @@ func CanConvert(t reflect.Type, v reflect.Value) bool {
f float64
srcInt bool
)
+
isPtr = t.Kind() == reflect.Ptr
isStruct = t.Kind() == reflect.Struct
isArray = t.Kind() == reflect.Array
diff --git a/Api/Posts.go b/Api/Posts.go
index 77f37a4..074a536 100644
--- a/Api/Posts.go
+++ b/Api/Posts.go
@@ -2,70 +2,16 @@ package Api
import (
"encoding/json"
- "io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
- "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/Auth"
- "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
"git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Util"
)
-func getPosts(w http.ResponseWriter, r *http.Request) {
- var (
- posts []Models.Post
- returnJson []byte
- values url.Values
- page, pageSize int
- search string
- err error
- )
-
- values = r.URL.Query()
-
- page, err = strconv.Atoi(values.Get("page"))
- if err != nil {
- log.Println("Could not parse page url argument")
- Util.JsonReturn(w, 500, "An error occured")
- return
- }
-
- pageSize, err = strconv.Atoi(values.Get("pageSize"))
- if err != nil {
- log.Println("Could not parse pageSize url argument")
- Util.JsonReturn(w, 500, "An error occured")
- return
- }
-
- search = values.Get("search")
-
- posts, err = Database.GetPosts(page, pageSize, search)
- if err != nil {
- log.Printf("An error occured: %s\n", err.Error())
- Util.JsonReturn(w, 500, "An error occured")
- return
- }
-
- if len(posts) == 0 {
- Util.JsonReturn(w, 404, "No more data")
- return
- }
-
- returnJson, err = json.MarshalIndent(posts, "", " ")
- if err != nil {
- Util.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
@@ -91,71 +37,48 @@ func getFrontPagePosts(w http.ResponseWriter, r *http.Request) {
w.Write(returnJson)
}
-func getPost(w http.ResponseWriter, r *http.Request) {
+func getPostsPublic(w http.ResponseWriter, r *http.Request) {
var (
- postData Models.Post
- returnJson []byte
- err error
+ posts []Models.Post
+ returnJson []byte
+ values url.Values
+ page, pageSize int
+ search string
+ err error
)
- postData, err = Util.GetPostById(w, r)
- if err != nil {
- return
- }
+ values = r.URL.Query()
- returnJson, err = json.MarshalIndent(postData, "", " ")
+ page, err = strconv.Atoi(values.Get("page"))
if err != nil {
+ log.Println("Could not parse page url argument")
Util.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
- )
-
- _, err = Auth.CheckCookie(r)
+ pageSize, err = strconv.Atoi(values.Get("pageSize"))
if err != nil {
- w.WriteHeader(http.StatusUnauthorized)
+ log.Println("Could not parse pageSize url argument")
+ Util.JsonReturn(w, 500, "An error occured")
return
}
- requestBody, err = ioutil.ReadAll(r.Body)
+ search = values.Get("search")
+
+ posts, err = Database.GetPostsPublic(page, pageSize, search)
if err != nil {
- log.Printf("Error encountered reading POST body: %s\n", err.Error())
+ log.Printf("An error occured: %s\n", err.Error())
Util.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())
- Util.JsonReturn(w, 405, "Invalid data")
+ if len(posts) == 0 {
+ Util.JsonReturn(w, 404, "No more data")
return
}
- err = Database.CreatePost(&postData)
- if err != nil {
- Util.JsonReturn(w, 405, "Invalid data")
- }
-
- returnJson, err = json.MarshalIndent(postData, "", " ")
+ returnJson, err = json.MarshalIndent(posts, "", " ")
if err != nil {
- log.Printf("An error occured: %s\n", err.Error())
Util.JsonReturn(w, 500, "An error occured")
return
}
@@ -165,52 +88,28 @@ func createPost(w http.ResponseWriter, r *http.Request) {
w.Write(returnJson)
}
-func updatePost(w http.ResponseWriter, r *http.Request) {
+func getPostPublic(w http.ResponseWriter, r *http.Request) {
var (
- postData Models.Post
- requestBody []byte
- returnJson []byte
- id string
- err error
+ postData Models.Post
+ returnJson []byte
+ id string
+ err error
)
- _, err = Auth.CheckCookie(r)
- if err != nil {
- w.WriteHeader(http.StatusUnauthorized)
- return
- }
-
id, err = Util.GetPostId(r)
if err != nil {
- log.Printf("Error encountered getting id\n")
- Util.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())
Util.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())
- Util.JsonReturn(w, 405, "Invalid data")
- return
- }
-
- postData, err = Database.UpdatePost(id, &postData)
+ postData, err = Database.GetPostByIdPublic(id)
if err != nil {
- log.Printf("An error occured: %s\n", err.Error())
- Util.JsonReturn(w, 500, "An error occured")
+ Util.JsonReturn(w, 404, "Not found")
return
}
returnJson, err = json.MarshalIndent(postData, "", " ")
if err != nil {
- log.Printf("An error occured: %s\n", err.Error())
Util.JsonReturn(w, 500, "An error occured")
return
}
@@ -219,31 +118,3 @@ func updatePost(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write(returnJson)
}
-
-func deletePost(w http.ResponseWriter, r *http.Request) {
- var (
- postData Models.Post
- err error
- )
-
- _, err = Auth.CheckCookie(r)
- if err != nil {
- w.WriteHeader(http.StatusUnauthorized)
- return
- }
-
- postData, err = Util.GetPostById(w, r)
- if err != nil {
- return
- }
-
- err = Database.DeletePost(&postData)
- if err != nil {
- log.Printf("An error occured: %s\n", err.Error())
- Util.JsonReturn(w, 500, "An error occured")
- return
- }
-
- // Return updated json
- w.WriteHeader(http.StatusOK)
-}
diff --git a/Api/PostsAdmin.go b/Api/PostsAdmin.go
new file mode 100644
index 0000000..68c3734
--- /dev/null
+++ b/Api/PostsAdmin.go
@@ -0,0 +1,283 @@
+package Api
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "net/url"
+ "strconv"
+ "time"
+
+ "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/Auth"
+ "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Api/JsonSerialization"
+ "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Database"
+ "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
+ "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Util"
+)
+
+func getPosts(w http.ResponseWriter, r *http.Request) {
+ var (
+ posts []Models.Post
+ returnJson []byte
+ values url.Values
+ page, pageSize int
+ search string
+ err error
+ )
+
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ values = r.URL.Query()
+
+ page, err = strconv.Atoi(values.Get("page"))
+ if err != nil {
+ log.Println("Could not parse page url argument")
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ pageSize, err = strconv.Atoi(values.Get("pageSize"))
+ if err != nil {
+ log.Println("Could not parse pageSize url argument")
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ search = values.Get("search")
+
+ posts, err = Database.GetPosts(page, pageSize, search)
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ if len(posts) == 0 {
+ Util.JsonReturn(w, 404, "No more data")
+ return
+ }
+
+ returnJson, err = json.MarshalIndent(posts, "", " ")
+ if err != nil {
+ Util.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
+ )
+
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ postData, err = Util.GetPostById(w, r)
+ if err != nil {
+ return
+ }
+
+ returnJson, err = json.MarshalIndent(postData, "", " ")
+ if err != nil {
+ Util.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
+ )
+
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ requestBody, err = ioutil.ReadAll(r.Body)
+ if err != nil {
+ log.Printf("Error encountered reading POST body: %s\n", err.Error())
+ Util.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())
+ Util.JsonReturn(w, 405, "Invalid data")
+ return
+ }
+
+ err = Database.CreatePost(&postData)
+ if err != nil {
+ Util.JsonReturn(w, 405, "Invalid data")
+ }
+
+ returnJson, err = json.MarshalIndent(postData, "", " ")
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.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
+ id string
+ err error
+ )
+
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ id, err = Util.GetPostId(r)
+ if err != nil {
+ log.Printf("Error encountered getting id\n")
+ Util.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())
+ Util.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())
+ Util.JsonReturn(w, 405, "Invalid data")
+ return
+ }
+
+ postData, err = Database.UpdatePost(id, &postData)
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ returnJson, err = json.MarshalIndent(postData, "", " ")
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ // Return updated json
+ w.WriteHeader(http.StatusOK)
+ w.Write(returnJson)
+}
+
+func publishPost(w http.ResponseWriter, r *http.Request) {
+ var (
+ now time.Time = time.Now()
+ postData Models.Post
+ returnJson []byte
+ err error
+ )
+
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ postData, err = Util.GetPostById(w, r)
+ if err != nil {
+ log.Printf("Error encountered getting id\n")
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ if postData.PublishedAt == nil {
+ postData.PublishedAt = &now
+ } else {
+ postData.PublishedAt = nil
+ }
+
+ postData, err = Database.UpdatePost(postData.ID.String(), &postData)
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ returnJson, err = json.MarshalIndent(postData, "", " ")
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.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
+ )
+
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
+ postData, err = Util.GetPostById(w, r)
+ if err != nil {
+ return
+ }
+
+ err = Database.DeletePost(&postData)
+ if err != nil {
+ log.Printf("An error occured: %s\n", err.Error())
+ Util.JsonReturn(w, 500, "An error occured")
+ return
+ }
+
+ // Return updated json
+ w.WriteHeader(http.StatusOK)
+}
diff --git a/Api/Routes.go b/Api/Routes.go
index 316db2c..edee089 100644
--- a/Api/Routes.go
+++ b/Api/Routes.go
@@ -17,17 +17,21 @@ func InitApiEndpoints(router *mux.Router) {
api = router.PathPrefix("/api/v1/").Subrouter()
+ api.HandleFunc("/posts/front-page", getFrontPagePosts).Methods("GET")
+ api.HandleFunc("/post", getPostsPublic).Methods("GET")
+ api.HandleFunc("/post/{postID}", getPostPublic).Methods("GET")
+
// Define routes for posts api
- api.HandleFunc("/post", getPosts).Methods("GET")
- api.HandleFunc("/post", createPost).Methods("POST")
- api.HandleFunc("/post/{postID}", getPost).Methods("GET")
- api.HandleFunc("/post/{postID}", updatePost).Methods("PUT")
- api.HandleFunc("/post/{postID}", deletePost).Methods("DELETE")
+ api.HandleFunc("/admin/post", getPosts).Methods("GET")
+ api.HandleFunc("/admin/post/{postID}", getPost).Methods("GET")
- api.HandleFunc("/frontPagePosts", getFrontPagePosts).Methods("GET")
+ api.HandleFunc("/admin/post", createPost).Methods("POST")
+ api.HandleFunc("/admin/post/{postID}", updatePost).Methods("PUT")
+ api.HandleFunc("/admin/post/{postID}", deletePost).Methods("DELETE")
+ api.HandleFunc("/admin/post/{postID}/publish", publishPost).Methods("GET")
- api.HandleFunc("/post/{postID}/image", createPostImage).Methods("POST")
- api.HandleFunc("/post/{postID}/image/{imageID}", deletePostImage).Methods("DELETE")
+ api.HandleFunc("/admin/post/{postID}/image", createPostImage).Methods("POST")
+ api.HandleFunc("/admin/post/{postID}/image/{imageID}", deletePostImage).Methods("DELETE")
// Define routes for users api
api.HandleFunc("/admin/user", getUsers).Methods("GET")
diff --git a/Api/Users.go b/Api/Users.go
index e84a9e4..d12eda1 100644
--- a/Api/Users.go
+++ b/Api/Users.go
@@ -109,6 +109,12 @@ func createUser(w http.ResponseWriter, r *http.Request) {
err error
)
+ _, err = Auth.CheckCookie(r)
+ if err != nil {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+
requestBody, err = ioutil.ReadAll(r.Body)
if err != nil {
log.Printf("Error encountered reading POST body: %s\n", err.Error())
diff --git a/Database/Posts.go b/Database/Posts.go
index 2e5a360..453a585 100644
--- a/Database/Posts.go
+++ b/Database/Posts.go
@@ -9,7 +9,22 @@ import (
"gorm.io/gorm/clause"
)
-func GetPosts(page, pageSize int, search string) ([]Models.Post, error) {
+func GetFrontPagePosts() ([]Models.Post, error) {
+ var (
+ posts []Models.Post
+ err error
+ )
+
+ err = DB.Where("front_page = ?", true).
+ Where("published_at IS NOT NULL").
+ Order("order asc").
+ Find(&posts).
+ Error
+
+ return posts, err
+}
+
+func GetPostsPublic(page, pageSize int, search string) ([]Models.Post, error) {
var (
posts []Models.Post
query *gorm.DB
@@ -30,6 +45,7 @@ func GetPosts(page, pageSize int, search string) ([]Models.Post, error) {
query = DB.Model(Models.Post{}).
Preload(clause.Associations).
+ Where("published_at IS NOT NULL").
Offset(offset).
Limit(pageSize).
Order("created_at desc")
@@ -47,65 +63,16 @@ func GetPosts(page, pageSize int, search string) ([]Models.Post, 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) {
+func GetPostByIdPublic(id string) (Models.Post, error) {
var (
postData Models.Post
err error
)
err = DB.Preload(clause.Associations).
+ Where("published_at IS NOT NULL").
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
- )
-
- DB.Model(postData).
- Where("id = ?", id).
- Association("PostLinks").
- Replace(postData.PostLinks)
-
- 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
-}
diff --git a/Database/PostsAdmin.go b/Database/PostsAdmin.go
new file mode 100644
index 0000000..3715bc7
--- /dev/null
+++ b/Database/PostsAdmin.go
@@ -0,0 +1,97 @@
+package Database
+
+import (
+ "fmt"
+
+ "git.tovijaeschke.xyz/tovi/SuddenImpactRecords/Models"
+
+ "gorm.io/gorm"
+ "gorm.io/gorm/clause"
+)
+
+func GetPosts(page, pageSize int, search string) ([]Models.Post, error) {
+ var (
+ posts []Models.Post
+ query *gorm.DB
+ offset int
+ err error
+ )
+
+ switch {
+ case pageSize > 100:
+ pageSize = 100
+ case pageSize <= 0:
+ pageSize = 10
+ }
+
+ offset = page * pageSize
+
+ search = fmt.Sprintf("%%%s%%", search)
+
+ query = DB.Model(Models.Post{}).
+ Preload(clause.Associations).
+ Offset(offset).
+ Limit(pageSize).
+ Order("created_at desc")
+
+ if search != "%%" {
+ query = query.
+ Where("title LIKE ?", search).
+ Or("content LIKE ?", search)
+ }
+
+ err = query.
+ 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
+ )
+
+ DB.Model(postData).
+ Where("id = ?", id).
+ Association("PostLinks").
+ Replace(postData.PostLinks)
+
+ 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
+}
diff --git a/Frontend/vue/src/assets/css/admin.css b/Frontend/vue/src/assets/css/admin.css
index 2e7812f..674c6e3 100644
--- a/Frontend/vue/src/assets/css/admin.css
+++ b/Frontend/vue/src/assets/css/admin.css
@@ -118,3 +118,18 @@ label[role=alert] {
background-color: #e9ecef;
opacity: 1;
}
+
+.editor-form .input-group {
+ display: inline-block;
+ width: unset;
+ padding-right: 0.3rem;
+}
+
+.ProseMirror {
+ outline: 0;
+ height: 100%;
+}
+
+.ProseMirror p:last-child {
+ margin-bottom: 0;
+}
diff --git a/Frontend/vue/src/components/admin/components/editor/AdminEditor.vue b/Frontend/vue/src/components/admin/components/editor/AdminEditor.vue
new file mode 100644
index 0000000..e4807b7
--- /dev/null
+++ b/Frontend/vue/src/components/admin/components/editor/AdminEditor.vue
@@ -0,0 +1,204 @@
+
+