Compare commits
	
		
			5 Commits
		
	
	
		
			4da9792b0f
			...
			88776337e4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 88776337e4 | |||
| f8691eb180 | |||
| 60e09175da | |||
| 13a6039490 | |||
| d953b4135c | 
| @@ -12,7 +12,6 @@ args_bin = [ | |||||||
|     "-domain localhost", |     "-domain localhost", | ||||||
|     "-feed tmp/cpolis.atom", |     "-feed tmp/cpolis.atom", | ||||||
|     "-firebase tmp/firebase.json", |     "-firebase tmp/firebase.json", | ||||||
|     "-gob tmp/cpolis.gob", |  | ||||||
|     "-img-width 256", |     "-img-width 256", | ||||||
|     "-link https://distrikt-ni-st.de", |     "-link https://distrikt-ni-st.de", | ||||||
|     "-log tmp/cpolis.log", |     "-log tmp/cpolis.log", | ||||||
|   | |||||||
| @@ -12,48 +12,48 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| type Config struct { | type Config struct { | ||||||
| 	AESKeyFile      string | 	AESKeyFile        string | ||||||
| 	ArticleDir      string | 	ArticleDir        string | ||||||
| 	AtomFile        string | 	AtomFile          string | ||||||
| 	ConfigFile      string | 	ConfigFile        string | ||||||
| 	DBName          string | 	DBName            string | ||||||
| 	Description     string | 	Description       string | ||||||
| 	Domain          string | 	Domain            string | ||||||
| 	FirebaseKey     string | 	FirebaseKey       string | ||||||
| 	GOBKeyFile      string | 	Link              string | ||||||
| 	Link            string | 	LogFile           string | ||||||
| 	LogFile         string | 	PDFDir            string | ||||||
| 	PDFDir          string | 	PicsDir           string | ||||||
| 	PicsDir         string | 	Port              string | ||||||
| 	Port            string | 	Title             string | ||||||
| 	Title           string | 	Version           string | ||||||
| 	Version         string | 	WebDir            string | ||||||
| 	WebDir          string | 	CookieExpiryHours int | ||||||
| 	MaxBannerHeight int | 	MaxBannerHeight   int | ||||||
| 	MaxBannerWidth  int | 	MaxBannerWidth    int | ||||||
| 	MaxImgHeight    int | 	MaxImgHeight      int | ||||||
| 	MaxImgWidth     int | 	MaxImgWidth       int | ||||||
| } | } | ||||||
|  |  | ||||||
| func newConfig() *Config { | func newConfig() *Config { | ||||||
| 	return &Config{ | 	return &Config{ | ||||||
| 		AESKeyFile:      "/var/www/cpolis/aes.key", | 		AESKeyFile:        "/var/www/cpolis/aes.key", | ||||||
| 		ArticleDir:      "/var/www/cpolis/articles", | 		ArticleDir:        "/var/www/cpolis/articles", | ||||||
| 		AtomFile:        "/var/www/cpolis/cpolis.atom", | 		AtomFile:          "/var/www/cpolis/cpolis.atom", | ||||||
| 		ConfigFile:      "/etc/cpolis/config.toml", | 		ConfigFile:        "/etc/cpolis/config.toml", | ||||||
| 		DBName:          "cpolis", | 		CookieExpiryHours: 24 * 30, | ||||||
| 		FirebaseKey:     "/var/www/cpolis/serviceAccountKey.json", | 		DBName:            "cpolis", | ||||||
| 		GOBKeyFile:      "/var/www/cpolis/gob.key", | 		FirebaseKey:       "/var/www/cpolis/serviceAccountKey.json", | ||||||
| 		LogFile:         "/var/log/cpolis.log", | 		LogFile:           "/var/log/cpolis.log", | ||||||
| 		MaxBannerHeight: 1080, | 		MaxBannerHeight:   1080, | ||||||
| 		MaxBannerWidth:  1920, | 		MaxBannerWidth:    1920, | ||||||
| 		MaxImgHeight:    1080, | 		MaxImgHeight:      1080, | ||||||
| 		MaxImgWidth:     1920, | 		MaxImgWidth:       1920, | ||||||
| 		PDFDir:          "/var/www/cpolis/pdfs", | 		PDFDir:            "/var/www/cpolis/pdfs", | ||||||
| 		PicsDir:         "/var/www/cpolis/pics", | 		PicsDir:           "/var/www/cpolis/pics", | ||||||
| 		Port:            ":8080", | 		Port:              ":8080", | ||||||
| 		Version:         "v0.15.0", | 		Version:           "v0.15.0", | ||||||
| 		WebDir:          "/var/www/cpolis/web", | 		WebDir:            "/var/www/cpolis/web", | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -116,13 +116,13 @@ func (c *Config) handleCliArgs() error { | |||||||
| 	flag.StringVar(&c.Description, "desc", c.Description, "channel description") | 	flag.StringVar(&c.Description, "desc", c.Description, "channel description") | ||||||
| 	flag.StringVar(&c.Domain, "domain", c.Domain, "domain name") | 	flag.StringVar(&c.Domain, "domain", c.Domain, "domain name") | ||||||
| 	flag.StringVar(&c.FirebaseKey, "firebase", c.FirebaseKey, "Firebase service account key file") | 	flag.StringVar(&c.FirebaseKey, "firebase", c.FirebaseKey, "Firebase service account key file") | ||||||
| 	flag.StringVar(&c.GOBKeyFile, "gob", c.GOBKeyFile, "gob key file") |  | ||||||
| 	flag.StringVar(&c.Link, "link", c.Link, "channel Link") | 	flag.StringVar(&c.Link, "link", c.Link, "channel Link") | ||||||
| 	flag.StringVar(&c.LogFile, "log", c.LogFile, "log file") | 	flag.StringVar(&c.LogFile, "log", c.LogFile, "log file") | ||||||
| 	flag.StringVar(&c.PDFDir, "pdfs", c.PDFDir, "pdf directory") | 	flag.StringVar(&c.PDFDir, "pdfs", c.PDFDir, "pdf directory") | ||||||
| 	flag.StringVar(&c.PicsDir, "pics", c.PicsDir, "pictures directory") | 	flag.StringVar(&c.PicsDir, "pics", c.PicsDir, "pictures directory") | ||||||
| 	flag.StringVar(&c.Title, "title", c.Title, "channel title") | 	flag.StringVar(&c.Title, "title", c.Title, "channel title") | ||||||
| 	flag.StringVar(&c.WebDir, "web", c.WebDir, "web directory") | 	flag.StringVar(&c.WebDir, "web", c.WebDir, "web directory") | ||||||
|  | 	flag.IntVar(&c.CookieExpiryHours, "cookie-expiry-hours", c.CookieExpiryHours, "cookies expire after this amount of hours") | ||||||
| 	flag.IntVar(&c.MaxBannerHeight, "banner-height", c.MaxBannerHeight, "maximum banner height") | 	flag.IntVar(&c.MaxBannerHeight, "banner-height", c.MaxBannerHeight, "maximum banner height") | ||||||
| 	flag.IntVar(&c.MaxBannerWidth, "banner-width", c.MaxBannerWidth, "maximum banner width") | 	flag.IntVar(&c.MaxBannerWidth, "banner-width", c.MaxBannerWidth, "maximum banner width") | ||||||
| 	flag.IntVar(&c.MaxImgHeight, "img-height", c.MaxImgHeight, "maximum image height") | 	flag.IntVar(&c.MaxImgHeight, "img-height", c.MaxImgHeight, "maximum image height") | ||||||
| @@ -179,6 +179,10 @@ func (c *Config) setupConfig(cliConfig *Config) error { | |||||||
| 		return fmt.Errorf("error setting up file: %v", err) | 		return fmt.Errorf("error setting up file: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if cliConfig.CookieExpiryHours != defaultConfig.CookieExpiryHours { | ||||||
|  | 		c.CookieExpiryHours = cliConfig.CookieExpiryHours | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if cliConfig.DBName != defaultConfig.DBName { | 	if cliConfig.DBName != defaultConfig.DBName { | ||||||
| 		c.DBName = cliConfig.DBName | 		c.DBName = cliConfig.DBName | ||||||
| 	} | 	} | ||||||
| @@ -203,14 +207,6 @@ func (c *Config) setupConfig(cliConfig *Config) error { | |||||||
| 		return fmt.Errorf("error setting up file: %v", err) | 		return fmt.Errorf("error setting up file: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if cliConfig.GOBKeyFile != defaultConfig.GOBKeyFile { |  | ||||||
| 		c.GOBKeyFile = cliConfig.GOBKeyFile |  | ||||||
| 	} |  | ||||||
| 	c.GOBKeyFile, err = mkFile(c.GOBKeyFile, 0600, 0700) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("error setting up file: %v", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if cliConfig.Link != defaultConfig.Link { | 	if cliConfig.Link != defaultConfig.Link { | ||||||
| 		c.Link = cliConfig.Link | 		c.Link = cliConfig.Link | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -1,63 +0,0 @@ | |||||||
| package backend |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"crypto/rand" |  | ||||||
| 	"encoding/gob" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
|  |  | ||||||
| 	"github.com/gorilla/sessions" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type ( |  | ||||||
| 	CookieStore struct{ sessions.CookieStore } |  | ||||||
| 	Session     struct{ sessions.Session } |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func NewKey() ([]byte, error) { |  | ||||||
| 	key := make([]byte, 32) |  | ||||||
|  |  | ||||||
| 	if _, err := io.ReadFull(rand.Reader, key); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("error generating key: %v", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return key, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func SaveKey(key []byte, filename string) error { |  | ||||||
| 	file, err := os.Create(filename) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return fmt.Errorf("error creating key file: %v", err) |  | ||||||
| 	} |  | ||||||
| 	defer file.Close() |  | ||||||
| 	file.Chmod(0600) |  | ||||||
|  |  | ||||||
| 	if err = gob.NewEncoder(file).Encode(key); err != nil { |  | ||||||
| 		return fmt.Errorf("error ecoding key: %v", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func LoadKey(filename string) ([]byte, error) { |  | ||||||
| 	file, err := os.Open(filename) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, fmt.Errorf("error opening key file: %v", err) |  | ||||||
| 	} |  | ||||||
| 	defer file.Close() |  | ||||||
|  |  | ||||||
| 	key := make([]byte, 32) |  | ||||||
| 	if err = gob.NewDecoder(file).Decode(&key); err != nil { |  | ||||||
| 		return nil, fmt.Errorf("error decoding key: %v", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return key, nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func NewCookieStore(key []byte) *CookieStore { |  | ||||||
| 	store := sessions.NewCookieStore(key) |  | ||||||
| 	store.Options.Secure = true |  | ||||||
| 	store.Options.HttpOnly = true |  | ||||||
| 	return &CookieStore{*store} |  | ||||||
| } |  | ||||||
| @@ -9,9 +9,9 @@ import ( | |||||||
| 	f "streifling.com/jason/cpolis/cmd/frontend" | 	f "streifling.com/jason/cpolis/cmd/frontend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func ServeImage(c *b.Config, s *b.CookieStore) http.HandlerFunc { | func ServeImage(c *b.Config, s map[string]*f.Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := f.GetSession(w, r, c, s); err != nil { | 		if _, err := f.ManageSession(w, r, c, s); err != nil { | ||||||
| 			if !tokenIsVerified(w, r, c) { | 			if !tokenIsVerified(w, r, c) { | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -45,33 +45,27 @@ type EditorHTMLData struct { | |||||||
| 	Contributors []*b.User | 	Contributors []*b.User | ||||||
| } | } | ||||||
|  |  | ||||||
| func WriteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func WriteArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		var data *EditorHTMLData |  | ||||||
| 		if session.Values["article"] == nil { |  | ||||||
| 			data = &EditorHTMLData{Action: "submit", Article: new(b.Article), ArticleUsers: make(map[string]*ArticleUser)} |  | ||||||
| 		} else { |  | ||||||
| 			data = session.Values["article"].(*EditorHTMLData) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		users, err := db.GetAllUsers(c) | 		users, err := db.GetAllUsers(c) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		data := &EditorHTMLData{Action: "submit", Article: new(b.Article), ArticleUsers: make(map[string]*ArticleUser)} | ||||||
| 		for _, user := range users { | 		for _, user := range users { | ||||||
| 			data.ArticleUsers[fmt.Sprint(user.LastName, user.FirstName, user.ID)] = &ArticleUser{User: user, ArticleRole: None} | 			data.ArticleUsers[fmt.Sprint(user.LastName, user.FirstName, user.ID)] = &ArticleUser{User: user, ArticleRole: None} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		creator, err := db.GetUser(c, session.Values["id"].(int64)) | 		creator, err := db.GetUser(c, session.User.ID) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| @@ -97,19 +91,11 @@ func WriteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func SubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func SubmitArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		session.Values["article"] = nil |  | ||||||
| 		if err = session.Save(r, w); err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -117,7 +103,7 @@ func SubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 			Title:         r.PostFormValue("article-title"), | 			Title:         r.PostFormValue("article-title"), | ||||||
| 			BannerLink:    r.PostFormValue("article-banner-url"), | 			BannerLink:    r.PostFormValue("article-banner-url"), | ||||||
| 			Summary:       r.PostFormValue("article-summary"), | 			Summary:       r.PostFormValue("article-summary"), | ||||||
| 			CreatorID:     session.Values["id"].(int64), | 			CreatorID:     session.User.ID, | ||||||
| 			Published:     false, | 			Published:     false, | ||||||
| 			Rejected:      false, | 			Rejected:      false, | ||||||
| 			IsInIssue:     r.PostFormValue("issue") == "on", | 			IsInIssue:     r.PostFormValue("issue") == "on", | ||||||
| @@ -215,7 +201,7 @@ func SubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -227,12 +213,11 @@ func SubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ResubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func ResubmitArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -240,7 +225,7 @@ func ResubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 			Title:      r.PostFormValue("article-title"), | 			Title:      r.PostFormValue("article-title"), | ||||||
| 			BannerLink: r.PostFormValue("article-banner-url"), | 			BannerLink: r.PostFormValue("article-banner-url"), | ||||||
| 			Summary:    r.PostFormValue("article-summary"), | 			Summary:    r.PostFormValue("article-summary"), | ||||||
| 			CreatorID:  session.Values["id"].(int64), | 			CreatorID:  session.User.ID, | ||||||
| 			IsInIssue:  r.PostFormValue("issue") == "on", | 			IsInIssue:  r.PostFormValue("issue") == "on", | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -346,7 +331,7 @@ func ResubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -358,11 +343,10 @@ func ResubmitArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ShowUnpublishedUnrejectedAndPublishedRejectedArticles(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func ShowUnpublishedUnrejectedAndPublishedRejectedArticles(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -402,12 +386,11 @@ func ShowUnpublishedUnrejectedAndPublishedRejectedArticles(c *b.Config, db *b.DB | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ShowRejectedArticles(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func ShowRejectedArticles(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -425,7 +408,7 @@ func ShowRejectedArticles(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerF | |||||||
|  |  | ||||||
| 		data.MyIDs = make(map[int64]bool) | 		data.MyIDs = make(map[int64]bool) | ||||||
| 		for _, article := range data.RejectedArticles { | 		for _, article := range data.RejectedArticles { | ||||||
| 			if article.CreatorID == session.Values["id"].(int64) { | 			if article.CreatorID == session.User.ID { | ||||||
| 				data.MyIDs[article.ID] = true | 				data.MyIDs[article.ID] = true | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @@ -440,12 +423,11 @@ func ShowRejectedArticles(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerF | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ReviewRejectedArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func ReviewRejectedArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -513,7 +495,7 @@ func ReviewRejectedArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.Handler | |||||||
| 			data.ArticleUsers[fmt.Sprint(contributor.LastName, contributor.FirstName, contributor.ID)].ArticleRole = Contributor | 			data.ArticleUsers[fmt.Sprint(contributor.LastName, contributor.FirstName, contributor.ID)].ArticleRole = Contributor | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		creator, err := db.GetUser(c, session.Values["id"].(int64)) | 		creator, err := db.GetUser(c, session.User.ID) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| @@ -545,12 +527,11 @@ func ReviewRejectedArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.Handler | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func PublishArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func PublishArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -624,7 +605,7 @@ func PublishArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -636,12 +617,11 @@ func PublishArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func RejectArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func RejectArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -659,7 +639,7 @@ func RejectArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -671,11 +651,10 @@ func RejectArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ShowCurrentIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func ShowCurrentIssue(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -695,11 +674,10 @@ func ShowCurrentIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ShowPublishedArticles(c *b.Config, db *b.DB, s *b.CookieStore, action string) http.HandlerFunc { | func ShowPublishedArticles(c *b.Config, db *b.DB, s map[string]*Session, action string) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -732,11 +710,10 @@ func ShowPublishedArticles(c *b.Config, db *b.DB, s *b.CookieStore, action strin | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ReviewArticle(c *b.Config, db *b.DB, s *b.CookieStore, action, title, button string) http.HandlerFunc { | func ReviewArticle(c *b.Config, db *b.DB, s map[string]*Session, action, title, button string) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -827,12 +804,11 @@ func ReviewArticle(c *b.Config, db *b.DB, s *b.CookieStore, action, title, butto | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func DeleteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func DeleteArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -868,7 +844,7 @@ func DeleteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -880,12 +856,11 @@ func DeleteArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func AllowEditArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func AllowEditArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -962,7 +937,7 @@ func AllowEditArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl := template.Must(template.ParseFiles(c.WebDir + "/templates/hub.html")) | 		tmpl := template.Must(template.ParseFiles(c.WebDir + "/templates/hub.html")) | ||||||
| 		if err = tmpl.ExecuteTemplate(w, "page-content", data); err != nil { | 		if err = tmpl.ExecuteTemplate(w, "page-content", data); err != nil { | ||||||
| @@ -973,11 +948,10 @@ func AllowEditArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func EditArticle(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func EditArticle(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										99
									
								
								cmd/frontend/homepage.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								cmd/frontend/homepage.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | package frontend | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"html/template" | ||||||
|  | 	"log" | ||||||
|  | 	"net/http" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	b "streifling.com/jason/cpolis/cmd/backend" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func HomePage(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		numRows, err := db.CountEntries("users") | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Fatalln(err) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		data := new(struct { | ||||||
|  | 			*UserHTMLData | ||||||
|  | 			Version string | ||||||
|  | 		}) | ||||||
|  | 		data.UserHTMLData = &UserHTMLData{User: new(b.User)} | ||||||
|  | 		data.Version = c.Version | ||||||
|  |  | ||||||
|  | 		files := make([]string, 2) | ||||||
|  | 		files[0] = c.WebDir + "/templates/index.html" | ||||||
|  | 		if numRows == 0 { | ||||||
|  | 			data.Role = b.NonExistent | ||||||
|  | 			data.Title = "Erster Benutzer (Administrator)" | ||||||
|  | 			data.ButtonText = "Anlegen" | ||||||
|  | 			data.URL = "/user/add-first" | ||||||
|  |  | ||||||
|  | 			files[1] = c.WebDir + "/templates/edit-user.html" | ||||||
|  | 			tmpl, err := template.ParseFiles(files...) | ||||||
|  | 			if err = template.Must(tmpl, err).Execute(w, data); err != nil { | ||||||
|  | 				log.Println(err) | ||||||
|  | 				http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			cookie, err := r.Cookie("cpolis_session") | ||||||
|  | 			if err != nil { | ||||||
|  | 				files[1] = c.WebDir + "/templates/login.html" | ||||||
|  | 				tmpl, err := template.ParseFiles(files...) | ||||||
|  | 				if err = template.Must(tmpl, err).Execute(w, data); err != nil { | ||||||
|  | 					log.Println(err) | ||||||
|  | 					http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			session, ok := s[cookie.Value] | ||||||
|  | 			if !ok { | ||||||
|  | 				cookie.Expires = time.Now() | ||||||
|  | 				http.SetCookie(w, cookie) | ||||||
|  |  | ||||||
|  | 				files[1] = c.WebDir + "/templates/login.html" | ||||||
|  | 				tmpl, err := template.ParseFiles(files...) | ||||||
|  | 				if err = template.Must(tmpl, err).Execute(w, data); err != nil { | ||||||
|  | 					log.Println(err) | ||||||
|  | 					http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			data.Role = session.User.Role | ||||||
|  | 			files[1] = c.WebDir + "/templates/hub.html" | ||||||
|  | 			tmpl, err := template.ParseFiles(files...) | ||||||
|  | 			if err = template.Must(tmpl, err).Execute(w, data); err != nil { | ||||||
|  | 				log.Println(err) | ||||||
|  | 				http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ShowHub(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
|  | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 		session, err := ManageSession(w, r, c, s) | ||||||
|  | 		if err != nil { | ||||||
|  | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		data := new(struct{ Role int }) | ||||||
|  | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
|  | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
|  | 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data); err != nil { | ||||||
|  | 			log.Println(err) | ||||||
|  | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -9,11 +9,10 @@ import ( | |||||||
| 	b "streifling.com/jason/cpolis/cmd/backend" | 	b "streifling.com/jason/cpolis/cmd/backend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func UploadEasyMDEImage(c *b.Config, s *b.CookieStore) http.HandlerFunc { | func UploadEasyMDEImage(c *b.Config, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -42,11 +41,10 @@ func UploadEasyMDEImage(c *b.Config, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func UploadImage(c *b.Config, s *b.CookieStore, fileKey, htmlFile, htmlTemplate string) http.HandlerFunc { | func UploadImage(c *b.Config, s map[string]*Session, fileKey, htmlFile, htmlTemplate string) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,19 +11,11 @@ import ( | |||||||
| 	b "streifling.com/jason/cpolis/cmd/backend" | 	b "streifling.com/jason/cpolis/cmd/backend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func PublishLatestIssue(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		session.Values["article"] = nil |  | ||||||
| 		if err = session.Save(r, w); err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -49,14 +41,7 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		authorIDs := make([]int64, 1) | 		authorIDs := make([]int64, 1) | ||||||
| 		var ok bool | 		authorIDs[0] = session.User.ID | ||||||
|  |  | ||||||
| 		if authorIDs[0], ok = session.Values["id"].(int64); !ok { |  | ||||||
| 			msg := "fälschlicherweise session.Values[\"id\"].(int64) für authorIDs[0] angenommen" |  | ||||||
| 			log.Println(msg) |  | ||||||
| 			http.Error(w, msg, http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if err = db.WriteArticleAuthors(article.ID, authorIDs); err != nil { | 		if err = db.WriteArticleAuthors(article.ID, authorIDs); err != nil { | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| @@ -101,15 +86,8 @@ func PublishLatestIssue(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFun | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		session.Values["issue-image"] = nil |  | ||||||
| 		if err = session.Save(r, w); err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
|   | |||||||
| @@ -10,11 +10,10 @@ import ( | |||||||
| 	b "streifling.com/jason/cpolis/cmd/backend" | 	b "streifling.com/jason/cpolis/cmd/backend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func UploadPDF(c *b.Config, s *b.CookieStore) http.HandlerFunc { | func UploadPDF(c *b.Config, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,115 +1,102 @@ | |||||||
| package frontend | package frontend | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"html/template" | 	"html/template" | ||||||
| 	"log" | 	"log" | ||||||
| 	"net/http" | 	"net/http" | ||||||
|  | 	"time" | ||||||
|  |  | ||||||
|  | 	"github.com/google/uuid" | ||||||
| 	b "streifling.com/jason/cpolis/cmd/backend" | 	b "streifling.com/jason/cpolis/cmd/backend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func saveSession(w http.ResponseWriter, r *http.Request, s *b.CookieStore, u *b.User) error { | type Session struct { | ||||||
| 	session, err := s.Get(r, "cookie") | 	ctx    context.Context | ||||||
| 	if err != nil { | 	cancel context.CancelFunc | ||||||
| 		return fmt.Errorf("error getting session: %v", err) | 	cookie *http.Cookie | ||||||
| 	} | 	User   *b.User | ||||||
|  |  | ||||||
| 	session.Values["authenticated"] = true |  | ||||||
| 	session.Values["id"] = u.ID |  | ||||||
| 	session.Values["name"] = u.FirstName + u.LastName |  | ||||||
| 	session.Values["role"] = u.Role |  | ||||||
| 	if err := session.Save(r, w); err != nil { |  | ||||||
| 		return fmt.Errorf("error saving session: %v", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // GetSession is used for verifying that the user is logged in and returns their session and an error. | func newSession(w http.ResponseWriter, c *b.Config, sessionExpiryChan chan<- string, user *b.User) *Session { | ||||||
| func GetSession(w http.ResponseWriter, r *http.Request, c *b.Config, s *b.CookieStore) (*b.Session, error) { | 	sessionID := uuid.New().String() | ||||||
| 	msg := "Keine gültige Session. Bitte erneut anmelden." | 	expires := time.Now().Add(time.Hour * time.Duration(c.CookieExpiryHours)) | ||||||
|  | 	ctx, cancel := context.WithDeadline(context.Background(), expires) | ||||||
|  |  | ||||||
|  | 	session := &Session{ | ||||||
|  | 		ctx:    ctx, | ||||||
|  | 		cancel: cancel, | ||||||
|  | 		cookie: &http.Cookie{ | ||||||
|  | 			Name:     "cpolis_session", | ||||||
|  | 			Value:    sessionID, | ||||||
|  | 			Expires:  expires, | ||||||
|  | 			Path:     "/", | ||||||
|  | 			HttpOnly: true, | ||||||
|  | 			Secure:   true, | ||||||
|  | 			SameSite: http.SameSiteStrictMode, | ||||||
|  | 		}, | ||||||
|  | 		User: user, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	go func() { | ||||||
|  | 		<-session.ctx.Done() | ||||||
|  | 		sessionExpiryChan <- session.cookie.Value | ||||||
|  | 		session.cookie.Expires = time.Now() | ||||||
|  | 		http.SetCookie(w, session.cookie) | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	return session | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func StartSessions() (map[string]*Session, chan string) { | ||||||
|  | 	sessions := make(map[string]*Session) | ||||||
|  | 	sessionExpiryChan := make(chan string) | ||||||
|  |  | ||||||
|  | 	go func() { | ||||||
|  | 		for sessionID := range sessionExpiryChan { | ||||||
|  | 			delete(sessions, sessionID) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  |  | ||||||
|  | 	return sessions, sessionExpiryChan | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ManageSession is used for verifying that the user is logged in and returns | ||||||
|  | // their session and an error. It also handles cases where the user is not | ||||||
|  | // logged in. | ||||||
|  | func ManageSession(w http.ResponseWriter, r *http.Request, c *b.Config, s map[string]*Session) (*Session, error) { | ||||||
| 	tmpl, tmplErr := template.ParseFiles(c.WebDir+"/templates/index.html", c.WebDir+"/templates/login.html") | 	tmpl, tmplErr := template.ParseFiles(c.WebDir+"/templates/index.html", c.WebDir+"/templates/login.html") | ||||||
|  |  | ||||||
| 	tmpSession, err := s.Get(r, "cookie") | 	cookie, err := r.Cookie("cpolis_session") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", msg); err != nil { | 		if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", nil); err != nil { | ||||||
| 			return nil, fmt.Errorf("error executing template: %v", err) | 			return nil, fmt.Errorf("error executing template: %v", err) | ||||||
| 		} | 		} | ||||||
| 		return nil, fmt.Errorf("error getting session: %v", err) |  | ||||||
|  | 		return nil, errors.New("no cookie set") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	session := &b.Session{Session: *tmpSession} | 	session, ok := s[cookie.Value] | ||||||
| 	if session.IsNew { | 	if !ok { | ||||||
| 		if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", msg); err != nil { | 		cookie.Expires = time.Now() | ||||||
|  | 		http.SetCookie(w, cookie) | ||||||
|  |  | ||||||
|  | 		if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", nil); err != nil { | ||||||
| 			return nil, fmt.Errorf("error executing template: %v", err) | 			return nil, fmt.Errorf("error executing template: %v", err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		return nil, errors.New("session does not exist") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	session.cookie.Expires = time.Now().Add(time.Hour * time.Duration(c.CookieExpiryHours)) | ||||||
|  | 	http.SetCookie(w, session.cookie) | ||||||
|  |  | ||||||
| 	return session, nil | 	return session, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func HomePage(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func Login(c *b.Config, db *b.DB, s map[string]*Session, sessionExpiryChan chan string) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { |  | ||||||
| 		numRows, err := db.CountEntries("users") |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalln(err) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		data := new(struct { |  | ||||||
| 			*UserHTMLData |  | ||||||
| 			Version string |  | ||||||
| 		}) |  | ||||||
| 		data.UserHTMLData = &UserHTMLData{User: new(b.User)} |  | ||||||
| 		data.Version = c.Version |  | ||||||
|  |  | ||||||
| 		files := make([]string, 2) |  | ||||||
| 		files[0] = c.WebDir + "/templates/index.html" |  | ||||||
| 		if numRows == 0 { |  | ||||||
| 			data.Role = b.NonExistent |  | ||||||
| 			data.Title = "Erster Benutzer (Administrator)" |  | ||||||
| 			data.ButtonText = "Anlegen" |  | ||||||
| 			data.URL = "/user/add-first" |  | ||||||
|  |  | ||||||
| 			files[1] = c.WebDir + "/templates/edit-user.html" |  | ||||||
| 			tmpl, err := template.ParseFiles(files...) |  | ||||||
| 			if err = template.Must(tmpl, err).Execute(w, data); err != nil { |  | ||||||
| 				log.Println(err) |  | ||||||
| 				http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			session, err := s.Get(r, "cookie") |  | ||||||
| 			if err != nil { |  | ||||||
| 				log.Println(err) |  | ||||||
| 				http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if auth, ok := session.Values["authenticated"].(bool); auth && ok { |  | ||||||
| 				data.Role = session.Values["role"].(int) |  | ||||||
| 				files[1] = c.WebDir + "/templates/hub.html" |  | ||||||
| 				tmpl, err := template.ParseFiles(files...) |  | ||||||
| 				if err = template.Must(tmpl, err).Execute(w, data); err != nil { |  | ||||||
| 					log.Println(err) |  | ||||||
| 					http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				data.Role = b.Author |  | ||||||
| 				files[1] = c.WebDir + "/templates/login.html" |  | ||||||
| 				tmpl, err := template.ParseFiles(files...) |  | ||||||
| 				if err = template.Must(tmpl, err).Execute(w, data); err != nil { |  | ||||||
| 					log.Println(err) |  | ||||||
| 					http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func Login(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { |  | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		userName := r.PostFormValue("username") | 		userName := r.PostFormValue("username") | ||||||
| 		password := r.PostFormValue("password") | 		password := r.PostFormValue("password") | ||||||
| @@ -133,11 +120,9 @@ func Login(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := saveSession(w, r, s, user); err != nil { | 		session := newSession(w, c, sessionExpiryChan, user) | ||||||
| 			log.Println(err) | 		s[session.cookie.Value] = session | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 		http.SetCookie(w, session.cookie) | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", user); err != nil { | 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", user); err != nil { | ||||||
| @@ -148,52 +133,32 @@ func Login(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func Logout(c *b.Config, s *b.CookieStore) http.HandlerFunc { | func Logout(c *b.Config, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		tmpl, tmplErr := template.ParseFiles(c.WebDir + "/templates/login.html") | ||||||
|  |  | ||||||
|  | 		cookie, err := r.Cookie("cpolis_session") | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", nil); err != nil { | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 				log.Println(err) | ||||||
| 			return | 				http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  | 		cookie.Expires = time.Now() | ||||||
|  | 		http.SetCookie(w, cookie) | ||||||
|  |  | ||||||
| 		session.Options.MaxAge = -1 | 		session, ok := s[cookie.Value] | ||||||
| 		if err = session.Save(r, w); err != nil { | 		if !ok { | ||||||
| 			log.Println(err) | 			if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", nil); err != nil { | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 				log.Println(err) | ||||||
| 			return | 				http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
|  | 		session.cancel() | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/login.html") | 		if err = template.Must(tmpl, tmplErr).ExecuteTemplate(w, "page-content", nil); err != nil { | ||||||
| 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", nil); err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func ShowHub(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 { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		session.Values["article"] = nil |  | ||||||
| 		if err = session.Save(r, w); err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) |  | ||||||
| 		data.Role = session.Values["role"].(int) |  | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") |  | ||||||
| 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data); err != nil { |  | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| 			return | 			return | ||||||
|   | |||||||
| @@ -8,11 +8,10 @@ import ( | |||||||
| 	b "streifling.com/jason/cpolis/cmd/backend" | 	b "streifling.com/jason/cpolis/cmd/backend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func CreateTag(c *b.Config, s *b.CookieStore) http.HandlerFunc { | func CreateTag(c *b.Config, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -25,12 +24,11 @@ func CreateTag(c *b.Config, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func AddTag(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func AddTag(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -42,7 +40,7 @@ func AddTag(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		db.AddTag(tag) | 		db.AddTag(tag) | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
|   | |||||||
| @@ -43,11 +43,10 @@ func sortUsersByName(users []*b.User) { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func CreateUser(c *b.Config, s *b.CookieStore) http.HandlerFunc { | func CreateUser(c *b.Config, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -67,12 +66,11 @@ func CreateUser(c *b.Config, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func AddUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func AddUser(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -134,7 +132,7 @@ func AddUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -146,16 +144,15 @@ func AddUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func EditSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func EditSelf(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		user, err := db.GetUser(c, session.Values["id"].(int64)) | 		user, err := db.GetUser(c, session.User.ID) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| @@ -179,17 +176,16 @@ func EditSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func UpdateSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func UpdateSelf(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		user := &b.User{ | 		user := &b.User{ | ||||||
| 			ID:             session.Values["id"].(int64), | 			ID:             session.User.ID, | ||||||
| 			UserName:       r.PostFormValue("username"), | 			UserName:       r.PostFormValue("username"), | ||||||
| 			FirstName:      r.PostFormValue("first-name"), | 			FirstName:      r.PostFormValue("first-name"), | ||||||
| 			LastName:       r.PostFormValue("last-name"), | 			LastName:       r.PostFormValue("last-name"), | ||||||
| @@ -244,7 +240,7 @@ func UpdateSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
| @@ -256,7 +252,7 @@ func UpdateSelf(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func AddFirstUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func AddFirstUser(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		var err error | 		var err error | ||||||
| 		user := &b.User{ | 		user := &b.User{ | ||||||
| @@ -303,12 +299,6 @@ func AddFirstUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := saveSession(w, r, s, user); err != nil { |  | ||||||
| 			log.Println(err) |  | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if _, err := db.AddIssue(); err != nil { | 		if _, err := db.AddIssue(); err != nil { | ||||||
| 			log.Println(err) | 			log.Println(err) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| @@ -327,12 +317,11 @@ func AddFirstUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func ShowAllUsers(c *b.Config, db *b.DB, s *b.CookieStore, action string) http.HandlerFunc { | func ShowAllUsers(c *b.Config, db *b.DB, s map[string]*Session, action string) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -348,7 +337,7 @@ func ShowAllUsers(c *b.Config, db *b.DB, s *b.CookieStore, action string) http.H | |||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) | 			http.Error(w, err.Error(), http.StatusInternalServerError) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 		delete(data.Users, session.Values["id"].(int64)) | 		delete(data.Users, session.User.ID) | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/show-all-users.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/show-all-users.html") | ||||||
| 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data); err != nil { | 		if err = template.Must(tmpl, err).ExecuteTemplate(w, "page-content", data); err != nil { | ||||||
| @@ -359,11 +348,10 @@ func ShowAllUsers(c *b.Config, db *b.DB, s *b.CookieStore, action string) http.H | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func EditUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func EditUser(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		if _, err := GetSession(w, r, c, s); err != nil { | 		if _, err := ManageSession(w, r, c, s); err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -398,12 +386,11 @@ func EditUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func UpdateUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func UpdateUser(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -473,7 +460,7 @@ func UpdateUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl := template.Must(template.ParseFiles(c.WebDir + "/templates/hub.html")) | 		tmpl := template.Must(template.ParseFiles(c.WebDir + "/templates/hub.html")) | ||||||
| 		if err = tmpl.ExecuteTemplate(w, "page-content", data); err != nil { | 		if err = tmpl.ExecuteTemplate(w, "page-content", data); err != nil { | ||||||
| @@ -484,12 +471,11 @@ func UpdateUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func DeleteUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | func DeleteUser(c *b.Config, db *b.DB, s map[string]*Session) http.HandlerFunc { | ||||||
| 	return func(w http.ResponseWriter, r *http.Request) { | 	return func(w http.ResponseWriter, r *http.Request) { | ||||||
| 		session, err := GetSession(w, r, c, s) | 		session, err := ManageSession(w, r, c, s) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Println(err) | 			http.Error(w, "Die Session ist abgelaufen. Bitte erneut anmelden.", http.StatusUnauthorized) | ||||||
| 			http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -507,7 +493,7 @@ func DeleteUser(c *b.Config, db *b.DB, s *b.CookieStore) http.HandlerFunc { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		data := new(struct{ Role int }) | 		data := new(struct{ Role int }) | ||||||
| 		data.Role = session.Values["role"].(int) | 		data.Role = session.User.Role | ||||||
|  |  | ||||||
| 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | 		tmpl, err := template.ParseFiles(c.WebDir + "/templates/hub.html") | ||||||
| 		tmpl = template.Must(tmpl, err) | 		tmpl = template.Must(tmpl, err) | ||||||
|   | |||||||
							
								
								
									
										98
									
								
								cmd/main.go
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								cmd/main.go
									
									
									
									
									
								
							| @@ -1,7 +1,6 @@ | |||||||
| package main | package main | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"encoding/gob" |  | ||||||
| 	"log" | 	"log" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| @@ -11,10 +10,6 @@ import ( | |||||||
| 	f "streifling.com/jason/cpolis/cmd/frontend" | 	f "streifling.com/jason/cpolis/cmd/frontend" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { |  | ||||||
| 	gob.Register(b.User{}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func main() { | func main() { | ||||||
| 	config, err := b.HandleConfig() | 	config, err := b.HandleConfig() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -34,68 +29,59 @@ func main() { | |||||||
| 	} | 	} | ||||||
| 	defer db.Close() | 	defer db.Close() | ||||||
|  |  | ||||||
| 	key, err := b.LoadKey(config.GOBKeyFile) | 	sessions, sessionExpiryChan := f.StartSessions() | ||||||
| 	if err != nil { | 	defer close(sessionExpiryChan) | ||||||
| 		key, err = b.NewKey() |  | ||||||
| 		if err != nil { |  | ||||||
| 			log.Fatalln(err) |  | ||||||
| 		} |  | ||||||
| 		if err = b.SaveKey(key, config.GOBKeyFile); err != nil { |  | ||||||
| 			log.Fatalln(err) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	store := b.NewCookieStore(key) |  | ||||||
|  |  | ||||||
| 	mux := http.NewServeMux() | 	mux := http.NewServeMux() | ||||||
| 	mux.Handle("/web/static/", http.StripPrefix("/web/static/", | 	mux.Handle("/web/static/", http.StripPrefix("/web/static/", | ||||||
| 		http.FileServer(http.Dir(config.WebDir+"/static/")))) | 		http.FileServer(http.Dir(config.WebDir+"/static/")))) | ||||||
| 	mux.HandleFunc("/", f.HomePage(config, db, store)) | 	mux.HandleFunc("/", f.HomePage(config, db, sessions)) | ||||||
|  |  | ||||||
| 	mux.HandleFunc("GET /article/allow-edit/{id}", f.AllowEditArticle(config, db, store)) | 	mux.HandleFunc("GET /article/allow-edit/{id}", f.AllowEditArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/all-published/review-edit", f.ShowPublishedArticles(config, db, store, "review-edit")) | 	mux.HandleFunc("GET /article/all-published/review-edit", f.ShowPublishedArticles(config, db, sessions, "review-edit")) | ||||||
| 	mux.HandleFunc("GET /article/all-published/delete", f.ShowPublishedArticles(config, db, store, "review-delete")) | 	mux.HandleFunc("GET /article/all-published/delete", f.ShowPublishedArticles(config, db, sessions, "review-delete")) | ||||||
| 	mux.HandleFunc("GET /article/all-rejected", f.ShowRejectedArticles(config, db, store)) | 	mux.HandleFunc("GET /article/all-rejected", f.ShowRejectedArticles(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/all-unpublished-unrejected-and-published-rejected", f.ShowUnpublishedUnrejectedAndPublishedRejectedArticles(config, db, store)) | 	mux.HandleFunc("GET /article/all-unpublished-unrejected-and-published-rejected", f.ShowUnpublishedUnrejectedAndPublishedRejectedArticles(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/delete/{id}", f.DeleteArticle(config, db, store)) | 	mux.HandleFunc("GET /article/delete/{id}", f.DeleteArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/edit/{id}", f.EditArticle(config, db, store)) | 	mux.HandleFunc("GET /article/edit/{id}", f.EditArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/publish/{id}", f.PublishArticle(config, db, store)) | 	mux.HandleFunc("GET /article/publish/{id}", f.PublishArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/reject/{id}", f.RejectArticle(config, db, store)) | 	mux.HandleFunc("GET /article/reject/{id}", f.RejectArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/review-delete/{id}", f.ReviewArticle(config, db, store, "delete", "Artikel löschen", "Löschen")) | 	mux.HandleFunc("GET /article/review-delete/{id}", f.ReviewArticle(config, db, sessions, "delete", "Artikel löschen", "Löschen")) | ||||||
| 	mux.HandleFunc("GET /article/review-edit/{id}", f.ReviewArticle(config, db, store, "allow-edit", "Artikel bearbeiten", "Bearbeiten erlauben")) | 	mux.HandleFunc("GET /article/review-edit/{id}", f.ReviewArticle(config, db, sessions, "allow-edit", "Artikel bearbeiten", "Bearbeiten erlauben")) | ||||||
| 	mux.HandleFunc("GET /article/review-rejected/{id}", f.ReviewRejectedArticle(config, db, store)) | 	mux.HandleFunc("GET /article/review-rejected/{id}", f.ReviewRejectedArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /article/review-unpublished/{id}", f.ReviewArticle(config, db, store, "publish", "Artikel veröffentlichen", "Veröffentlichen")) | 	mux.HandleFunc("GET /article/review-unpublished/{id}", f.ReviewArticle(config, db, sessions, "publish", "Artikel veröffentlichen", "Veröffentlichen")) | ||||||
| 	mux.HandleFunc("GET /article/serve/{id}", c.ServeArticle(config, db)) | 	mux.HandleFunc("GET /article/serve/{id}", c.ServeArticle(config, db)) | ||||||
| 	mux.HandleFunc("GET /article/serve/{id}/clicks", c.ServeClicks(db)) | 	mux.HandleFunc("GET /article/serve/{id}/clicks", c.ServeClicks(db)) | ||||||
| 	mux.HandleFunc("GET /article/write", f.WriteArticle(config, db, store)) | 	mux.HandleFunc("GET /article/write", f.WriteArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /atom/serve", c.ServeAtomFeed(config)) | 	mux.HandleFunc("GET /atom/serve", c.ServeAtomFeed(config)) | ||||||
| 	mux.HandleFunc("GET /hub", f.ShowHub(config, db, store)) | 	mux.HandleFunc("GET /hub", f.ShowHub(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /image/serve/{pic}", c.ServeImage(config, store)) | 	mux.HandleFunc("GET /image/serve/{pic}", c.ServeImage(config, sessions)) | ||||||
| 	mux.HandleFunc("GET /issue/this", f.ShowCurrentIssue(config, db, store)) | 	mux.HandleFunc("GET /issue/this", f.ShowCurrentIssue(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /logout", f.Logout(config, store)) | 	mux.HandleFunc("GET /logout", f.Logout(config, sessions)) | ||||||
| 	mux.HandleFunc("GET /pdf/get-list", c.ServePDFList(config)) | 	mux.HandleFunc("GET /pdf/get-list", c.ServePDFList(config)) | ||||||
| 	mux.HandleFunc("GET /pdf/serve/{id}", c.ServePDF(config)) | 	mux.HandleFunc("GET /pdf/serve/{id}", c.ServePDF(config)) | ||||||
| 	mux.HandleFunc("GET /tag/create", f.CreateTag(config, store)) | 	mux.HandleFunc("GET /tag/create", f.CreateTag(config, sessions)) | ||||||
| 	mux.HandleFunc("GET /user/create", f.CreateUser(config, store)) | 	mux.HandleFunc("GET /user/create", f.CreateUser(config, sessions)) | ||||||
| 	mux.HandleFunc("GET /user/delete/{id}", f.DeleteUser(config, db, store)) | 	mux.HandleFunc("GET /user/delete/{id}", f.DeleteUser(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /user/edit/{id}", f.EditUser(config, db, store)) | 	mux.HandleFunc("GET /user/edit/{id}", f.EditUser(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /user/edit/self", f.EditSelf(config, db, store)) | 	mux.HandleFunc("GET /user/edit/self", f.EditSelf(config, db, sessions)) | ||||||
| 	mux.HandleFunc("GET /user/show-all/delete", f.ShowAllUsers(config, db, store, "delete")) | 	mux.HandleFunc("GET /user/show-all/delete", f.ShowAllUsers(config, db, sessions, "delete")) | ||||||
| 	mux.HandleFunc("GET /user/show-all/edit", f.ShowAllUsers(config, db, store, "edit")) | 	mux.HandleFunc("GET /user/show-all/edit", f.ShowAllUsers(config, db, sessions, "edit")) | ||||||
|  |  | ||||||
| 	mux.HandleFunc("POST /article/resubmit/{id}", f.ResubmitArticle(config, db, store)) | 	mux.HandleFunc("POST /article/resubmit/{id}", f.ResubmitArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /article/submit", f.SubmitArticle(config, db, store)) | 	mux.HandleFunc("POST /article/submit", f.SubmitArticle(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /article/upload-banner", f.UploadImage(config, store, "article-banner", "editor.html", "article-banner-template")) | 	mux.HandleFunc("POST /article/upload-banner", f.UploadImage(config, sessions, "article-banner", "editor.html", "article-banner-template")) | ||||||
| 	mux.HandleFunc("POST /article/upload-image", f.UploadEasyMDEImage(config, store)) | 	mux.HandleFunc("POST /article/upload-image", f.UploadEasyMDEImage(config, sessions)) | ||||||
| 	mux.HandleFunc("POST /issue/publish", f.PublishLatestIssue(config, db, store)) | 	mux.HandleFunc("POST /issue/publish", f.PublishLatestIssue(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /issue/upload-banner", f.UploadImage(config, store, "issue-banner", "current-issue.html", "issue-banner-template")) | 	mux.HandleFunc("POST /issue/upload-banner", f.UploadImage(config, sessions, "issue-banner", "current-issue.html", "issue-banner-template")) | ||||||
| 	mux.HandleFunc("POST /login", f.Login(config, db, store)) | 	mux.HandleFunc("POST /login", f.Login(config, db, sessions, sessionExpiryChan)) | ||||||
| 	mux.HandleFunc("POST /pdf/upload", f.UploadPDF(config, store)) | 	mux.HandleFunc("POST /pdf/upload", f.UploadPDF(config, sessions)) | ||||||
| 	mux.HandleFunc("POST /tag/add", f.AddTag(config, db, store)) | 	mux.HandleFunc("POST /tag/add", f.AddTag(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /user/add", f.AddUser(config, db, store)) | 	mux.HandleFunc("POST /user/add", f.AddUser(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /user/add-first", f.AddFirstUser(config, db, store)) | 	mux.HandleFunc("POST /user/add-first", f.AddFirstUser(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /user/update/{id}", f.UpdateUser(config, db, store)) | 	mux.HandleFunc("POST /user/update/{id}", f.UpdateUser(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /user/update/self", f.UpdateSelf(config, db, store)) | 	mux.HandleFunc("POST /user/update/self", f.UpdateSelf(config, db, sessions)) | ||||||
| 	mux.HandleFunc("POST /user/upload-profile-pic", f.UploadImage(config, store, "upload-profile-pic", "edit-user.html", "profile-pic-template")) | 	mux.HandleFunc("POST /user/upload-profile-pic", f.UploadImage(config, sessions, "upload-profile-pic", "edit-user.html", "profile-pic-template")) | ||||||
|  |  | ||||||
| 	log.Fatalln(http.ListenAndServe(config.Port, mux)) | 	log.Fatalln(http.ListenAndServe(config.Port, mux)) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							| @@ -10,7 +10,6 @@ require ( | |||||||
| 	github.com/disintegration/imaging v1.6.2 | 	github.com/disintegration/imaging v1.6.2 | ||||||
| 	github.com/go-sql-driver/mysql v1.8.1 | 	github.com/go-sql-driver/mysql v1.8.1 | ||||||
| 	github.com/google/uuid v1.6.0 | 	github.com/google/uuid v1.6.0 | ||||||
| 	github.com/gorilla/sessions v1.4.0 |  | ||||||
| 	github.com/microcosm-cc/bluemonday v1.0.27 | 	github.com/microcosm-cc/bluemonday v1.0.27 | ||||||
| 	github.com/yuin/goldmark v1.7.8 | 	github.com/yuin/goldmark v1.7.8 | ||||||
| 	golang.org/x/crypto v0.32.0 | 	golang.org/x/crypto v0.32.0 | ||||||
| @@ -49,7 +48,6 @@ require ( | |||||||
| 	github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect | 	github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect | ||||||
| 	github.com/googleapis/gax-go/v2 v2.14.1 // indirect | 	github.com/googleapis/gax-go/v2 v2.14.1 // indirect | ||||||
| 	github.com/gorilla/css v1.0.1 // indirect | 	github.com/gorilla/css v1.0.1 // indirect | ||||||
| 	github.com/gorilla/securecookie v1.1.2 // indirect |  | ||||||
| 	github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect | 	github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect | ||||||
| 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect | 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect | ||||||
| 	go.opentelemetry.io/contrib/detectors/gcp v1.33.0 // indirect | 	go.opentelemetry.io/contrib/detectors/gcp v1.33.0 // indirect | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
									
									
									
									
								
							| @@ -80,8 +80,6 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6 | |||||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= | ||||||
| github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||||||
| github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= |  | ||||||
| github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= |  | ||||||
| github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= | github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= | ||||||
| github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= | github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= | ||||||
| github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= | github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= | ||||||
| @@ -94,10 +92,6 @@ github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrk | |||||||
| github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= | github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= | ||||||
| github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= | github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= | ||||||
| github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= | github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= | ||||||
| github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= |  | ||||||
| github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= |  | ||||||
| github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= |  | ||||||
| github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= |  | ||||||
| github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= | github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= | ||||||
| github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= | github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= | ||||||
| github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= | github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user