feature/id-for-hmtl-headers #3
							
								
								
									
										28
									
								
								cmd/backend/files.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								cmd/backend/files.go
									
									
									
									
									
										Normal 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()
 | 
			
		||||
}
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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"])
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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")
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@
 | 
			
		||||
 | 
			
		||||
    <footer class="text-center text-gray-500 my-8">
 | 
			
		||||
        <p>© 2024 Jason Streifling. Alle Rechte vorbehalten.</p>
 | 
			
		||||
        <p>v0.11.0 - <strong>Alpha: Drastische Änderungen und Fehler vorbehalten.</strong></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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user