Compare commits

..

43 Commits

Author SHA1 Message Date
bc4d8fa37e Merge branch 'devel' 2024-09-28 13:59:34 +02:00
1368593c75 Move file handling to backend/files.go 2024-09-28 13:55:25 +02:00
e4bef7006c Abstract sessions.Session with b.session 2024-09-28 13:44:25 +02:00
afa1b65563 Moved getSession to frontend/sessions.go 2024-09-28 13:22:53 +02:00
a9bef63174 Change version number 2024-09-28 13:15:00 +02:00
4d944ef65a Delete unused SaveArticle() 2024-09-28 13:12:46 +02:00
d2b21e7405 Merge branch 'devel' 2024-09-28 12:36:46 +02:00
4bd255a7c4 Strictly require title for issue 2024-09-28 12:34:41 +02:00
2743899b65 Changed version number and disclaimer 2024-09-28 12:19:18 +02:00
e3c192359f Merge branch 'devel' 2024-09-11 18:15:31 +02:00
46532e4c85 Merge branch 'devel' 2024-09-11 18:15:07 +02:00
c722135a56 Merge branch 'devel' 2024-09-11 17:18:42 +02:00
887fa863bc Merge branch 'devel' 2024-09-10 19:43:22 +02:00
74d71cfb6a Merge branch 'devel' 2024-09-09 22:03:43 +02:00
ca7e7cddd3 Merge branch 'devel' 2024-09-08 16:22:59 +02:00
94431a2aa9 Merge branch 'devel' 2024-09-08 16:21:38 +02:00
5b1f20c5bc Merge branch 'devel' 2024-09-08 13:36:22 +02:00
d0c566f8df Merge branch 'devel' 2024-09-01 21:14:05 +02:00
5e586aa49a Merge branch 'devel' 2024-09-01 18:51:33 +02:00
66b2743d3d Merge branch 'devel' 2024-09-01 18:48:26 +02:00
3723b2b5e6 Merge branch 'devel' 2024-09-01 18:18:18 +02:00
ce788bfd50 Merge branch 'devel' 2024-09-01 12:54:12 +02:00
230a6278cc Merge branch 'devel' 2024-09-01 12:49:30 +02:00
42d6e0c198 Merge branch 'devel' 2024-08-31 12:17:41 +02:00
e1af2979af Merge branch 'devel' 2024-08-31 11:27:15 +02:00
f6dedc6f10 Merge branch 'devel' 2024-08-31 01:43:53 +02:00
cdf0a49550 Merge branch 'devel' 2024-08-31 01:38:28 +02:00
c3c0650210 Merge branch 'devel' 2024-08-31 01:00:55 +02:00
d077f700d8 Merge branch 'devel' 2024-08-31 00:36:48 +02:00
ec752b1c66 Merge branch 'devel' 2024-08-30 23:43:12 +02:00
46aef4f12f Merge branch 'devel' 2024-08-25 10:51:35 +02:00
1b29e328cf Merge branch 'devel' 2024-08-25 06:38:55 +02:00
e50cb819f3 Merge branch 'devel' 2024-08-23 21:45:30 +02:00
c32e38ca10 Merge branch 'devel' 2024-08-23 20:57:11 +02:00
d7c8c7a43a Merge branch 'devel' 2024-08-18 17:31:00 +02:00
1cd3edc90c Merge branch 'devel' 2024-08-18 12:06:29 +02:00
0e768c9f61 Merge branch 'devel' 2024-08-08 21:27:07 +02:00
1fcd775cc5 Merge branch 'devel' 2024-08-08 21:14:24 +02:00
203a1ed147 Implemented EasyMDE 2024-08-08 21:13:25 +02:00
ef1914ee5c Implemented article preview 2024-08-08 21:13:25 +02:00
084b101e31 Register f.ArticlePreviewHtmlData in init() 2024-08-08 21:13:25 +02:00
b2db128aa9 Shorten lines by referencing frontend as f and backend as b 2024-08-08 21:13:25 +02:00
081e880fb6 Change structure of code tor frontend and backend one 2024-08-08 21:13:25 +02:00
9 changed files with 69 additions and 162 deletions

28
cmd/backend/files.go Normal file
View File

@ -0,0 +1,28 @@
package backend
import (
"fmt"
"io"
"os"
)
func CopyFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("error opening source file: %v", err)
}
defer srcFile.Close()
dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return fmt.Errorf("error opening destination file: %v", err)
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return fmt.Errorf("error copying file: %v", err)
}
return dstFile.Sync()
}

View File

@ -10,7 +10,10 @@ import (
"github.com/gorilla/sessions"
)
type CookieStore struct{ sessions.CookieStore }
type (
CookieStore struct{ sessions.CookieStore }
Session struct{ sessions.Session }
)
func NewKey() ([]byte, error) {
key := make([]byte, 32)

View File

@ -33,27 +33,6 @@ type EditorHTMLData struct {
Tags []*b.Tag
}
func copyFile(src, dst string) error {
srcFile, err := os.Open(src)
if err != nil {
return fmt.Errorf("error opening source file: %v", err)
}
defer srcFile.Close()
dstFile, err := os.Create(dst)
if err != nil {
return fmt.Errorf("error opening destination file: %v", err)
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return fmt.Errorf("error copying file: %v", err)
}
return dstFile.Sync()
}
func WriteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, err := getSession(w, r, c, s)
@ -61,14 +40,13 @@ func WriteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
return
}
data := new(EditorHTMLData)
data := &EditorHTMLData{Action: "submit"}
if session.Values["article"] == nil {
data = &EditorHTMLData{Article: new(b.Article)}
} else {
data = session.Values["article"].(*EditorHTMLData)
}
// data.Mode = EditMode
data.Tags, err = db.GetTagList()
if err != nil {
@ -77,8 +55,6 @@ func WriteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
return
}
data.Action = "submit"
tmpl, err := template.ParseFiles(c.WebDir + "/templates/editor.html")
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data)
}
@ -696,7 +672,7 @@ func AllowEditArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc
return
}
if err = copyFile(fmt.Sprint(c.ArticleDir, "/", oldID, ".md"), fmt.Sprint(c.ArticleDir, "/", newID, ".md")); err != nil {
if err = b.CopyFile(fmt.Sprint(c.ArticleDir, "/", oldID, ".md"), fmt.Sprint(c.ArticleDir, "/", newID, ".md")); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@ -762,94 +738,3 @@ func EditArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data)
}
}
func SaveArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
session, err := getSession(w, r, c, s)
if err != nil {
return
}
session.Values["article"] = nil
if err = session.Save(r, w); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
article := &b.Article{
Title: r.PostFormValue("article-title"),
Description: r.PostFormValue("article-description"),
Published: false,
Rejected: false,
AuthorID: session.Values["id"].(int64),
IsInIssue: r.PostFormValue("issue") == "on",
AutoGenerated: false,
}
oldID, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Println(oldID)
if oldID != 0 {
if err = db.DeleteArticle(oldID); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err = os.Remove(fmt.Sprint(c.ArticleDir, "/", oldID, ".md")); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
article.ID, err = db.AddArticle(article)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
articleAbsName := fmt.Sprint(c.ArticleDir, "/", article.ID, ".md")
if err = os.WriteFile(articleAbsName, []byte(r.PostFormValue("article-content")), 0644); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
article.Link = fmt.Sprint(c.Domain, "/article/serve/", article.ID)
if err = db.UpdateAttributes(&b.Attribute{Table: "articles", ID: article.ID, AttName: "link", Value: article.Link}); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
r.ParseForm()
tags := make([]int64, 0)
for _, tag := range r.Form["tags"] {
tagID, err := strconv.ParseInt(tag, 10, 64)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tags = append(tags, tagID)
}
if err = db.WriteArticleTags(article.ID, tags); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html")
tmpl = template.Must(tmpl, err)
tmpl.ExecuteTemplate(w, "page-content", session.Values["role"])
}
}

View File

@ -30,6 +30,14 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun
return
}
title := r.PostFormValue("issue-title")
if len(title) == 0 {
err = fmt.Errorf("error: no title for issue specified")
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if session.Values["issue-image"] == nil {
err := "error: Image required"
log.Println(err)
@ -55,14 +63,11 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun
return
}
imgSize := imgInfo.Size()
mimeType := mime.TypeByExtension(filepath.Ext(imgAbsName))
article := &b.Article{
Title: r.PostFormValue("issue-title"),
Title: title,
EncURL: fmt.Sprint(c.Domain, "/image/serve/", imgFileName),
EncLength: int(imgSize),
EncType: mimeType,
EncLength: int(imgInfo.Size()),
EncType: mime.TypeByExtension(filepath.Ext(imgAbsName)),
Published: true,
Rejected: false,
Created: time.Now(),

View File

@ -1,6 +1,7 @@
package frontend
import (
"errors"
"fmt"
"html/template"
"log"
@ -26,6 +27,26 @@ func saveSession(w http.ResponseWriter, r *http.Request, s *b.CookieStore, u *b.
return nil
}
// getSession is used for verifying that the user is logged in and returns their session and an error.
func getSession(w http.ResponseWriter, r *http.Request, c *b.Config, s *b.CookieStore) (*b.Session, error) {
msg := "Keine gültige Session. Bitte erneut anmelden."
tmpl, tmplErr := template.ParseFiles(c.WebDir+"/templates/index.html", c.WebDir+"/templates/login.html")
tmpSession, err := s.Get(r, "cookie")
if err != nil {
template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", msg)
return nil, err
}
session := &b.Session{Session: *tmpSession}
if session.IsNew {
template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", msg)
return session, errors.New("error: no existing session")
}
return session, nil
}
func HomePage(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
numRows, err := db.CountEntries("users")

View File

@ -1,29 +0,0 @@
package frontend
import (
"errors"
"html/template"
"net/http"
"github.com/gorilla/sessions"
b "streifling.com/jason/cpolis/cmd/backend"
)
// getSession is used for verifying that the user is logged in and returns their session and an error.
func getSession(w http.ResponseWriter, r *http.Request, c *b.Config, s *b.CookieStore) (*sessions.Session, error) {
msg := "Keine gültige Session. Bitte erneut anmelden."
tmpl, tmplErr := template.ParseFiles(c.WebDir+"/templates/index.html", c.WebDir+"/templates/login.html")
session, err := s.Get(r, "cookie")
if err != nil {
template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", msg)
return nil, err
}
if session.IsNew {
template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", msg)
return session, errors.New("error: no existing session")
}
return session, nil
}

View File

@ -62,7 +62,6 @@ func main() {
mux.HandleFunc("GET /article/review-edit/{id}", f.ReviewArticle(config, db, store, "allow-edit", "Artikel bearbeiten", "Bearbeiten erlauben"))
mux.HandleFunc("GET /article/review-rejected/{id}", f.ReviewRejectedArticle(config, db, store))
mux.HandleFunc("GET /article/review-unpublished/{id}", f.ReviewArticle(config, db, store, "publish", "Artikel veröffentlichen", "Veröffentlichen"))
mux.HandleFunc("GET /article/save/{id}", f.SaveArticle(config, db, store))
mux.HandleFunc("GET /article/serve/{id}", c.ServeArticle(config, db))
mux.HandleFunc("GET /article/write", f.WriteArticle(config, db, store))
mux.HandleFunc("GET /hub", f.ShowHub(config, db, store))

View File

@ -18,7 +18,7 @@
<div>
<h3>Titelseite</h3>
<div class="grid grid-cols-2 gap-4 items-center">
<input class="h-full" name="issue-title" placeholder="Titel" type="text" />
<input class="h-full" name="issue-title" placeholder="Titel" required type="text" />
<label class="btn text-center" for="image-upload">Bild hochladen</label>
<input class="hidden" id="image-upload" name="issue-image" type="file" required
hx-post="/issue/upload-image" />

View File

@ -34,13 +34,8 @@
</main>
<footer class="text-center text-gray-500 my-8">
<p>
&copy; 2024 Jason Streifling. Alle Rechte vorbehalten.
</p>
<p>
v0.10.3 - <strong>Hinweis:</strong> Diese Software befindet sich noch in der Entwicklung und kann Fehler
enthalten.
</p>
<p>&copy; 2024 Jason Streifling. Alle Rechte vorbehalten.</p>
<p>v0.11.1 - <strong>Alpha: Drastische Änderungen und Fehler vorbehalten.</strong></p>
</footer>
<script src="https://unpkg.com/htmx.org@2.0.2"></script>