Multiple fixes and added article get endpoint for authors

This commit is contained in:
2022-02-02 16:00:56 +01:00
parent 6a6283f781
commit 3c8fd32345
11 changed files with 141 additions and 20 deletions

4
.env
View File

@@ -2,8 +2,8 @@ SERVER_PORT=8080
# the global address of your webserver (protocol://domain[:port]). make sure this DOES NOT has a trailing slash # the global address of your webserver (protocol://domain[:port]). make sure this DOES NOT has a trailing slash
ADDRESS=http://localhost:8080 ADDRESS=http://localhost:8080
# the path you serve on. must be at least a slash # the path you serve on
Path=/ SUBPATH=
DATABASE_FILE=database.sqlite3 DATABASE_FILE=database.sqlite3
FRONTEND_DIR=./frontend/ FRONTEND_DIR=./frontend/

View File

@@ -12,21 +12,75 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
"strconv"
"strings" "strings"
"time" "time"
) )
func Article(w http.ResponseWriter, r *http.Request) { func Article(w http.ResponseWriter, r *http.Request) {
switch r.Method { switch r.Method {
case http.MethodGet:
assetsGet(w, r)
case http.MethodPost: case http.MethodPost:
assetsPost(w, r) articlePost(w, r)
case http.MethodDelete: case http.MethodDelete:
assetsDelete(w, r) articleDelete(w, r)
case http.MethodPatch:
articlePatch(w, r)
} }
} }
type getResponse struct {
Title string `json:"title"`
Summary string `json:"summary"`
Authors []int `json:"authors"`
Image string `json:"image"`
Tags []string `json:"tags"`
Link string `json:"link"`
Content string `json:"content"`
}
func articleGet(w http.ResponseWriter, r *http.Request) {
authorId, ok := authorizedSession(r)
if !ok {
w.WriteHeader(http.StatusUnauthorized)
return
}
rawId := r.URL.Query().Get("id")
if rawId == "" {
ApiError{Message: "no id was given", Code: http.StatusBadRequest}.Send(w)
return
}
id, err := strconv.Atoi(rawId)
if err != nil {
ApiError{"invalid 'id' parameter", http.StatusUnprocessableEntity}.Send(w)
return
}
if !database.Exists(database.GetDB().Table("article_author"), "author_id=?", authorId) {
w.WriteHeader(http.StatusUnauthorized)
return
}
var article database.Article
if database.GetDB().Table("article").First(&article, id).RowsAffected == 0 {
ApiError{Message: "no such id", Code: http.StatusNotFound}.Send(w)
return
}
resp := getResponse{
Title: article.Title,
Summary: article.Summary,
Image: article.Image,
Link: article.Link,
Content: base64.StdEncoding.EncodeToString([]byte(article.Markdown)),
}
database.GetDB().Table("article_author").Select("author_id").Where("article_id", article.Id).Find(&resp.Authors)
database.GetDB().Table("article_tag").Select("tag").Where("article_id", article.Id).Find(&resp.Tags)
json.NewEncoder(w).Encode(resp)
}
type uploadPayload struct { type uploadPayload struct {
Title string `json:"title"` Title string `json:"title"`
Summary string `json:"summary"` Summary string `json:"summary"`
@@ -102,7 +156,7 @@ func articlePost(w http.ResponseWriter, r *http.Request) {
} else { } else {
articleSummary.Tags = []string{} articleSummary.Tags = []string{}
} }
articleSummary.Link = path.Join(config.Path, "article", url.PathEscape(articleSummary.Link)) articleSummary.Link = path.Join("/", config.SubPath, "article", url.PathEscape(articleSummary.Link))
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(articleSummary) json.NewEncoder(w).Encode(articleSummary)
@@ -216,7 +270,7 @@ func articlePatch(w http.ResponseWriter, r *http.Request) {
} else { } else {
articleSummary.Tags = []string{} articleSummary.Tags = []string{}
} }
articleSummary.Link = path.Join(config.Path, "article", url.PathEscape(articleSummary.Link)) articleSummary.Link = path.Join("/", config.SubPath, "article", url.PathEscape(articleSummary.Link))
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(articleSummary) json.NewEncoder(w).Encode(articleSummary)

View File

@@ -10,6 +10,71 @@ import (
"time" "time"
) )
func TestArticleGet(t *testing.T) {
if err := initTestDatabase("upload_get_test.sqlite3"); err != nil {
t.Fatal(err)
}
database.GetDB().Table("article").Create([]map[string]interface{}{
{
"title": "Get test",
"summary": "",
"created": time.Now().Unix(),
"link": "get-test",
"markdown": "Testing ._.",
"html": "<p>Testing ._.<p>",
},
})
database.GetDB().Table("author").Create([]map[string]interface{}{
{
"name": "admin",
"password": "",
"information": "admin",
},
})
database.GetDB().Table("article_author").Create([]map[string]interface{}{
{
"article_id": 1,
"author_id": 1,
},
})
server := httptest.NewServer(http.HandlerFunc(articleGet))
checkTestInformation(t, server.URL, []testInformation{
{
Method: http.MethodGet,
Code: http.StatusUnauthorized,
},
{
Method: http.MethodGet,
Cookie: map[string]string{
"session_id": initSession(),
},
ResultBody: map[string]interface{}{
"message": "no id was given",
},
Code: http.StatusBadRequest,
},
{
Method: http.MethodGet,
Query: map[string]interface{}{
"id": 1,
},
Cookie: map[string]string{
"session_id": initSession(),
},
ResultBody: getResponse{
Title: "Get test",
Authors: []int{1},
Tags: []string{},
Link: "get-test",
Content: base64.StdEncoding.EncodeToString([]byte("Testing ._.")),
},
Code: http.StatusOK,
},
})
}
func TestArticlePost(t *testing.T) { func TestArticlePost(t *testing.T) {
if err := initTestDatabase("upload_post_test.sqlite3"); err != nil { if err := initTestDatabase("upload_post_test.sqlite3"); err != nil {
t.Fatal(err) t.Fatal(err)

View File

@@ -58,7 +58,7 @@ func assetsGet(w http.ResponseWriter, r *http.Request) {
request.Find(&assets) request.Find(&assets)
for _, asset := range assets { for _, asset := range assets {
asset.Link = path.Join(config.Path, "assets", asset.Link) asset.Link = path.Join("/", config.SubPath, "assets", asset.Link)
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
@@ -101,7 +101,7 @@ func assetsPost(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(schema.Asset{ json.NewEncoder(w).Encode(schema.Asset{
Id: tmpDatabaseSchema.Id, Id: tmpDatabaseSchema.Id,
Name: tmpDatabaseSchema.Name, Name: tmpDatabaseSchema.Name,
Link: path.Join(config.Path, "assets", tmpDatabaseSchema.Link), Link: path.Join("/", config.SubPath, "assets", tmpDatabaseSchema.Link),
}) })
} }
} }

View File

@@ -35,7 +35,7 @@ func Recent(w http.ResponseWriter, r *http.Request) {
database.GetDB().Table("author").Where("id IN (?)", database.GetDB().Table("article_author").Select("author_id").Where("article_id = ?", summary.Id)).Find(&summary.Authors) database.GetDB().Table("author").Where("id IN (?)", database.GetDB().Table("article_author").Select("author_id").Where("article_id = ?", summary.Id)).Find(&summary.Authors)
summary.Tags = []string{} summary.Tags = []string{}
database.GetDB().Table("article_tag").Select("tag").Where("article_id = ?", summary.Id).Find(&summary.Tags) database.GetDB().Table("article_tag").Select("tag").Where("article_id = ?", summary.Id).Find(&summary.Tags)
summary.Link = path.Join(config.Path, "article", summary.Link) summary.Link = path.Join("/", config.SubPath, "article", summary.Link)
articleSummaries[i] = summary articleSummaries[i] = summary
} }

View File

@@ -72,7 +72,7 @@ func Search(w http.ResponseWriter, r *http.Request) {
database.GetDB().Table("author").Where("id IN (?)", database.GetDB().Table("article_author").Select("author_id").Where("article_id = ?", summary.Id)).Find(&summary.Authors) database.GetDB().Table("author").Where("id IN (?)", database.GetDB().Table("article_author").Select("author_id").Where("article_id = ?", summary.Id)).Find(&summary.Authors)
summary.Tags = []string{} summary.Tags = []string{}
database.GetDB().Table("article_tag").Select("tag").Where("article_id = ?", summary.Id).Find(&summary.Tags) database.GetDB().Table("article_tag").Select("tag").Where("article_id = ?", summary.Id).Find(&summary.Tags)
summary.Link = path.Join(config.Path, "article", summary.Link) summary.Link = path.Join("/", config.SubPath, "article", summary.Link)
articleSummaries[i] = summary articleSummaries[i] = summary
} }

View File

@@ -12,7 +12,7 @@ func Tags(w http.ResponseWriter, r *http.Request) {
request := database.GetDB().Table("article_tag") request := database.GetDB().Table("article_tag")
if query.Has("name") { if query.Has("name") {
request.Where("name LIKE ?", "%"+query.Get("name")+"%") request.Where("tag LIKE ?", "%"+query.Get("name")+"%")
} }
if query.Has("limit") { if query.Has("limit") {
limit, err := strconv.Atoi(query.Get("limit")) limit, err := strconv.Atoi(query.Get("limit"))

View File

@@ -9,7 +9,7 @@ var (
ServerPort string ServerPort string
Address string Address string
Path string SubPath string
DatabaseFile string DatabaseFile string
FrontendDir string FrontendDir string
@@ -21,7 +21,7 @@ func init() {
ServerPort = os.Getenv("SERVER_PORT") ServerPort = os.Getenv("SERVER_PORT")
Address = os.Getenv("ADDRESS") Address = os.Getenv("ADDRESS")
Path = os.Getenv("Path") SubPath = os.Getenv("SUBPATH")
DatabaseFile = os.Getenv("DATABASE_FILE") DatabaseFile = os.Getenv("DATABASE_FILE")
FrontendDir = os.Getenv("FRONTEND_DIR") FrontendDir = os.Getenv("FRONTEND_DIR")

View File

@@ -9,6 +9,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
"html/template" "html/template"
"net/http" "net/http"
"path"
"path/filepath" "path/filepath"
) )
@@ -17,8 +18,8 @@ func main() {
r.StrictSlash(true) r.StrictSlash(true)
var subrouter *mux.Router var subrouter *mux.Router
if config.Path != "/" { if config.SubPath != "" {
subrouter = r.PathPrefix(config.Path).Subrouter() subrouter = r.PathPrefix(config.SubPath).Subrouter()
} else { } else {
subrouter = r subrouter = r
} }
@@ -69,7 +70,7 @@ func setupFrontend(r *mux.Router) {
r.Path("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.Path("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
landingpage.Execute(w, struct { landingpage.Execute(w, struct {
BasePath string BasePath string
}{BasePath: config.Address + config.Path}) }{BasePath: config.Address + path.Join("/", config.SubPath)})
}) })
r.NotFoundHandler = http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.NotFoundHandler = http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@@ -5,6 +5,7 @@ import (
"TheAdversary/database" "TheAdversary/database"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"net/http" "net/http"
"path"
"path/filepath" "path/filepath"
"text/template" "text/template"
"time" "time"
@@ -40,7 +41,7 @@ func Article(w http.ResponseWriter, r *http.Request) {
ta := tmplArticle{ ta := tmplArticle{
Title: article.Title, Title: article.Title,
BasePath: config.Address + config.Path, BasePath: config.Address + path.Join("/", config.SubPath),
Summary: article.Summary, Summary: article.Summary,
Image: article.Image, Image: article.Image,
Authors: authors, Authors: authors,

View File

@@ -9,7 +9,7 @@ import (
) )
func ServePath(w http.ResponseWriter, r *http.Request) { func ServePath(w http.ResponseWriter, r *http.Request) {
path := filepath.Join(config.FrontendDir, strings.TrimPrefix(r.URL.Path, config.Path)) path := filepath.Join(config.FrontendDir, strings.TrimPrefix(r.URL.Path, config.SubPath))
if _, err := os.Stat(path); os.IsNotExist(err) { if _, err := os.Stat(path); os.IsNotExist(err) {
Error404(w, r) Error404(w, r)
} else { } else {