Merge branch 'develop'

This commit is contained in:
Lars Hoogestraat 2019-03-27 18:36:22 +01:00
commit 145b0e6884
21 changed files with 72 additions and 68 deletions

View File

@ -32,6 +32,7 @@ package:
cp -r examples/ ${TMP}/
cp -r templates/ ${TMP}/
cp -r assets/ ${TMP}/
cp README.md ${TMP}/
cd ${TMP} && tar -czvf ../releases/$(BINARYNAME)_$(BUILD_VERSION).tar.gz * && cd -
vet:

View File

@ -11,24 +11,27 @@ Prerequisites
Configuration
--------
* create a "custom" folder in
* create a "custom" folder in the app directory
* copy go-blog.conf into custom/ folder
* edit custom/go-blog.conf to your needs
* create a user for running this application
* see "examples/systemd" for creating a service
### SQLite setup ###
Create the initial database:
Create the initial database (switch to folder clt/):
./init_database -sqlite /path/to/your/sqlite/database
Change the config file to point to the correct sqlite database
~~~
sqlite_file = /path/to/your/sqlite/database
~~~
### Create user with administration rights ###
Create your first administrator account with createuser:
Create your first administrator account with createuser (switch to folder clt/):
~~~
./createuser -admin -sqlite /path/to/your/sqlite/database -username test -email test@example.com -displayname "Hello World" -password secret1234

View File

@ -2,7 +2,6 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//Inititializes the database schema
package main
import (

View File

@ -15,7 +15,7 @@ type SQLiteConfig struct {
File string
}
//Open receives handle for sqlite database; validates if opening the connection
//Open receives handle for sqlite database, returns an error if connection failed
func (d SQLiteConfig) Open() (*sql.DB, error) {
db, err := sql.Open("sqlite3", d.File)
@ -26,8 +26,8 @@ func (d SQLiteConfig) Open() (*sql.DB, error) {
return db, nil
}
//InitTables creates the tables
func InitTables(db *sql.DB) error {
if _, err := db.Exec("CREATE TABLE user " +
"(" +
"id INTEGER PRIMARY KEY, " +

View File

@ -10,21 +10,21 @@ import (
)
//Error enriches the original go error type with
//DisplayMsg the description for the displaying message; shown to the user
//HTTPStatus is returned as response code in the middleware.AppHandler
//Error the error if available which is logged internally
//DisplayMsg the description for the displaying message
//HTTPStatus the HTTP status code
//Err the internal error it should not be shown to the user
type Error struct {
DisplayMsg string `json:"display_message"`
HTTPStatus int `json:"status"`
Err error `json:"-"`
}
//New convenient function to returns a new error
//New returns a new error
func New(httpStatus int, displayMsg string, err error) *Error {
return &Error{DisplayMsg: displayMsg, Err: err, HTTPStatus: httpStatus}
}
//PermissionDenied returns a permission denied message with code 403 to the user on a specific action and subject.
//PermissionDenied returns a permission denied message with code 403.
//The following display message is returned: "You are not allowed to [action] the [subject]."
func PermissionDenied(action, subject string, err error) *Error {
return &Error{
@ -34,8 +34,8 @@ func PermissionDenied(action, subject string, err error) *Error {
}
}
//NotFound returns a not found message with code 404 on a resource.
//The following display message is returned: "The %s was not found."
//NotFound returns a not found message with code 404.
//The following display message is returned: "The [res] was not found."
func NotFound(res string, err error) *Error {
return &Error{
HTTPStatus: http.StatusNotFound,
@ -45,12 +45,12 @@ func NotFound(res string, err error) *Error {
}
//ValueTooLong returns the following display message with code 422.
//Display message: "The value of [param] is too long. Maximum %d characters are allowed."
func ValueTooLong(param string, nChars int) *Error {
//Display message: "The value of [param] is too long. Maximum [nchars] characters are allowed."
func ValueTooLong(param string, nchars int) *Error {
return &Error{
HTTPStatus: http.StatusUnprocessableEntity,
Err: fmt.Errorf("the value of field %s is too long (%d characters are allowed.)", param, nChars),
DisplayMsg: fmt.Sprintf("The value of %s is too long. Maximum %d characters are allowed.", param, nChars),
Err: fmt.Errorf("the value of field %s is too long (%d characters are allowed.)", param, nchars),
DisplayMsg: fmt.Sprintf("The value of %s is too long. Maximum %d characters are allowed.", param, nchars),
}
}

View File

@ -22,7 +22,7 @@ var Log = logrus.New()
// error
// fatal
// panic
func InitLogger(file io.Writer, level string) {
func InitLogger(w io.Writer, level string) {
level = strings.ToLower(level)
switch level {
@ -43,6 +43,6 @@ func InitLogger(file io.Writer, level string) {
Log.Level = logrus.InfoLevel
}
Log.Out = file
Log.Out = w
Log.Formatter = &logrus.TextFormatter{FullTimestamp: true, DisableColors: true}
}

View File

@ -25,6 +25,7 @@ func (m Mail) validate() error {
return nil
}
//NewMailService returns a new Service with specified config
func NewMailService(subjectPrefix, from string, smtpConfig SMTPConfig) Service {
s := Service{
SubjectPrefix: subjectPrefix,

View File

@ -4,6 +4,7 @@ import (
"bytes"
"database/sql"
"errors"
"fmt"
"net/http"
"time"
@ -26,7 +27,7 @@ func AdminProfileHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *h
}
}
//AdminProfilePostHandler handles the updating of the user profile
//AdminProfilePostHandler handles the updating of the user profile which is currently logged in
func AdminProfilePostHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
ctxUser, _ := middleware.User(r)
ctxUser.PlainPassword = []byte(r.FormValue("current_password"))
@ -63,7 +64,7 @@ func AdminProfilePostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
return &middleware.Template{
Name: tplAdminProfile,
Active: "profile",
Err: httperror.New(http.StatusUnprocessableEntity, "Please check your retyped password", errors.New("the password did not match the retyped one")),
Err: httperror.New(http.StatusUnprocessableEntity, "The passwords entered do not match.", errors.New("the password entered did not match")),
Data: map[string]interface{}{
"user": u,
},
@ -103,13 +104,14 @@ func AdminProfilePostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
return &middleware.Template{
RedirectPath: "admin/user/profile",
Active: "profile",
SuccessMsg: "Your profile update was successful",
SuccessMsg: "Your profile was successfully updated.",
Data: map[string]interface{}{
"user": u,
},
}
}
//ActivateAccountHandler shows the form to activate an account.
func ActivateAccountHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
hash := getVar(r, "hash")
@ -119,7 +121,7 @@ func ActivateAccountHandler(ctx *middleware.AppContext, w http.ResponseWriter, r
if err == sql.ErrNoRows {
return &middleware.Template{
Name: tplAdminLogin,
Err: httperror.New(http.StatusNotFound, "Could not find an invitation", errors.New("the invitation was not found")),
Err: httperror.New(http.StatusNotFound, "Can't find an invitation.", fmt.Errorf("the invitation with hash %s was not found", hash)),
}
}
@ -137,8 +139,9 @@ func ActivateAccountHandler(ctx *middleware.AppContext, w http.ResponseWriter, r
}
}
//ActivateAccountPostHandler activates an user account
func ActivateAccountPostHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
// Delete any cookies if user is logged in
// Delete any cookies if an user is logged in
ctx.SessionService.Remove(w, r)
password := r.FormValue("password")
@ -148,7 +151,7 @@ func ActivateAccountPostHandler(ctx *middleware.AppContext, w http.ResponseWrite
if !bytes.Equal([]byte(password), []byte(repassword)) {
return &middleware.Template{
Name: tplAdminActivateAccount,
Err: httperror.New(http.StatusUnprocessableEntity, "Please check your retyped password", errors.New("the password did not match the retyped one")),
Err: httperror.New(http.StatusUnprocessableEntity, "The passwords entered do not match.", errors.New("the password entered did not match")),
Data: map[string]interface{}{
"hash": hash,
},
@ -161,7 +164,7 @@ func ActivateAccountPostHandler(ctx *middleware.AppContext, w http.ResponseWrite
if err == sql.ErrNoRows {
return &middleware.Template{
Name: tplAdminLogin,
Err: httperror.New(http.StatusNotFound, "Could not find the invitation", errors.New("the invitation was not found")),
Err: httperror.New(http.StatusNotFound, "Can't find an invitation.", fmt.Errorf("the invitation with hash %s was not found", hash)),
}
}
@ -197,7 +200,7 @@ func ActivateAccountPostHandler(ctx *middleware.AppContext, w http.ResponseWrite
}
}
//ResetPasswordHandler returns the form for the resetting the password
//ResetPasswordHandler returns the form for resetting the password
func ResetPasswordHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
hash := getVar(r, "hash")
@ -207,7 +210,7 @@ func ResetPasswordHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *
if err == sql.ErrNoRows {
return &middleware.Template{
Name: tplAdminForgotPassword,
Err: httperror.New(http.StatusNotFound, "The token was not found. Fill out the form to receive another token", errors.New("the token was not found")),
Err: httperror.New(http.StatusNotFound, "The token was not found. Please fill out the form to receive another token.", errors.New("the token to reset the password was not found")),
}
}
return &middleware.Template{
@ -251,7 +254,7 @@ func ResetPasswordPostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
if password != repassword {
return &middleware.Template{
Name: tplAdminResetPassword,
Err: httperror.New(http.StatusUnprocessableEntity, "The passwords do not match", errors.New("the passwords did not match")),
Err: httperror.New(http.StatusUnprocessableEntity, "The passwords entered do not match.", errors.New("the password entered did not match")),
}
}
@ -276,7 +279,7 @@ func ResetPasswordPostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
return &middleware.Template{
RedirectPath: "admin",
SuccessMsg: "Your password reset was successful. Please enter your login information.",
SuccessMsg: "Your password reset was successful.",
}
}

View File

@ -17,7 +17,7 @@ import (
)
//GetArticleHandler returns a specific article
//Parameters in the url form 2016/03/my-headline are used for obtaining the article
//Parameters in the url form 2016/3/my-headline are used for obtaining the article
func GetArticleHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
year := getVar(r, "year")
month := getVar(r, "month")
@ -577,18 +577,18 @@ func AdminArticlePublishHandler(ctx *middleware.AppContext, w http.ResponseWrite
if a.Published {
action = models.Action{
ID: "unpublishSite",
ID: "unpublishArticle",
ActionURL: fmt.Sprintf("/admin/article/publish/%d", a.ID),
BackLinkURL: "/admin/articles",
Description: fmt.Sprintf("%s %s?", "Do you want to unpublish the article ", a.Headline),
Description: fmt.Sprintf("%s %s?", "Do you want to unpublish the article", a.Headline),
Title: "Confirm unpublishing of article",
}
} else {
action = models.Action{
ID: "publishSite",
ID: "publishArticle",
ActionURL: fmt.Sprintf("/admin/article/publish/%d", a.ID),
BackLinkURL: "/admin/articles",
Description: fmt.Sprintf("%s %s?", "Do you want to publish the article ", a.Headline),
Description: fmt.Sprintf("%s %s?", "Do you want to publish the article", a.Headline),
Title: "Confirm publishing of article",
}
}
@ -627,7 +627,7 @@ func AdminArticlePublishPostHandler(ctx *middleware.AppContext, w http.ResponseW
return &middleware.Template{
RedirectPath: "admin/articles",
Active: "articles",
SuccessMsg: "Article successfully published",
SuccessMsg: "Article successfully published.",
}
}
@ -661,7 +661,7 @@ func AdminArticleDeleteHandler(ctx *middleware.AppContext, w http.ResponseWriter
ID: "deleteArticle",
ActionURL: fmt.Sprintf("/admin/article/delete/%d", a.ID),
BackLinkURL: "/admin/articles",
Description: fmt.Sprintf("%s %s?", "Do you want to delete the article", a.Headline),
Description: fmt.Sprintf("%s %s?", "Do you want to delete the article ", a.Headline),
Title: "Confirm removal of article",
}
@ -700,7 +700,7 @@ func AdminArticleDeletePostHandler(ctx *middleware.AppContext, w http.ResponseWr
return &middleware.Template{
Active: "articles",
RedirectPath: "admin/articles",
SuccessMsg: "Article successfully deleted",
SuccessMsg: "Article successfully deleted.",
}
}

View File

@ -92,7 +92,7 @@ func AdminCategoryNewPostHandler(ctx *middleware.AppContext, w http.ResponseWrit
return &middleware.Template{
RedirectPath: "admin/categories",
Active: "categories",
SuccessMsg: "Category successfully saved",
SuccessMsg: "Category successfully saved.",
Data: map[string]interface{}{
"categoryID": id,
},
@ -164,7 +164,7 @@ func AdminCategoryEditPostHandler(ctx *middleware.AppContext, w http.ResponseWri
return &middleware.Template{
RedirectPath: "admin/categories",
Active: "categories",
SuccessMsg: "Category successfully updated",
SuccessMsg: "Category successfully updated.",
}
}

View File

@ -60,7 +60,7 @@ func (fh FileHandler) FileGetHandler(w http.ResponseWriter, r *http.Request) {
http.ServeContent(w, r, loc, f.LastModified, rf)
}
//AdminListFilesHandler returns the template which lists alle uploaded files belonging to a user, admins will see all files
//AdminListFilesHandler returns the template which lists all uploaded files belonging to a user, admins will see all files
func AdminListFilesHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
u, _ := middleware.User(r)
@ -138,7 +138,7 @@ func AdminToggleInlineFilePostHandler(ctx *middleware.AppContext, w http.Respons
return &middleware.Template{
Active: "files",
RedirectPath: "/admin/files",
SuccessMsg: "File successfully updated",
SuccessMsg: "File successfully updated.",
}
}
@ -168,7 +168,7 @@ func AdminUploadFilePostHandler(ctx *middleware.AppContext, w http.ResponseWrite
return &middleware.Template{
RedirectPath: "/admin/files",
SuccessMsg: "Successfully uploaded file",
SuccessMsg: "Successfully uploaded file.",
Active: "files",
}
}
@ -226,7 +226,7 @@ func AdminUploadDeleteHandler(ctx *middleware.AppContext, w http.ResponseWriter,
action := models.Action{
ID: "deleteFile",
ActionURL: fmt.Sprintf("/admin/file/delete/%d", f.ID),
Description: fmt.Sprintf("%s %s?", "Do you want to delete the file ", f.UniqueName),
Description: fmt.Sprintf("%s %s?", "Do you want to delete the file", f.UniqueName),
Title: "Confirm removal of file",
}
@ -260,7 +260,7 @@ func AdminUploadDeletePostHandler(ctx *middleware.AppContext, w http.ResponseWri
warnMsg := ""
if err != nil {
if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOENT {
warnMsg = "File removed from database, but was not found in filesystem anymore"
warnMsg = "File removed from database, but was not found in filesystem anymore."
} else {
return &middleware.Template{
RedirectPath: "/admin/files",
@ -273,7 +273,7 @@ func AdminUploadDeletePostHandler(ctx *middleware.AppContext, w http.ResponseWri
return &middleware.Template{
Active: "files",
RedirectPath: "admin/files",
SuccessMsg: "File successfully deleted",
SuccessMsg: "File successfully deleted.",
WarnMsg: warnMsg,
}
}

View File

@ -79,7 +79,7 @@ func LogoutHandler(ctx *middleware.AppContext, rw http.ResponseWriter, r *http.R
return &middleware.Template{
RedirectPath: "admin",
SuccessMsg: "Successfully logged out",
SuccessMsg: "Successfully logged out.",
}
}

View File

@ -15,7 +15,7 @@ import (
"git.hoogi.eu/go-blog/models"
)
//SiteHandler returns the site template only published sites are considered
//GetSiteHandler returns the site template - only published sites are considered
func GetSiteHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
site, err := ctx.SiteService.GetByLink(getVar(r, "site"), models.OnlyPublished)
@ -40,7 +40,7 @@ func GetSiteHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.R
}
}
//SiteHandler returns the site template only published sites are considered
//AdminGetSiteHandler returns the template containing the sites
func AdminGetSiteHandler(ctx *middleware.AppContext, w http.ResponseWriter, r *http.Request) *middleware.Template {
reqVar := getVar(r, "siteID")
@ -240,7 +240,7 @@ func AdminSiteEditPostHandler(ctx *middleware.AppContext, w http.ResponseWriter,
return &middleware.Template{
RedirectPath: "admin/sites",
Active: "sites",
SuccessMsg: "Successfully edited site " + s.Title,
SuccessMsg: fmt.Sprintf("%s %s.", "Successfully edited site", s.Title),
}
}
@ -282,7 +282,7 @@ func AdminSiteOrderHandler(ctx *middleware.AppContext, w http.ResponseWriter, r
return &middleware.Template{
RedirectPath: "admin/sites",
Active: "sites",
SuccessMsg: "Site successfully reordered",
SuccessMsg: "Site successfully reordered.",
}
}
@ -316,7 +316,7 @@ func AdminSitePublishHandler(ctx *middleware.AppContext, w http.ResponseWriter,
ID: "unpublishSite",
ActionURL: fmt.Sprintf("/admin/site/publish/%d", s.ID),
BackLinkURL: "/admin/sites",
Description: fmt.Sprintf("%s %s?", "Do you want to unpublish the site ", s.Title),
Description: fmt.Sprintf("%s %s?", "Do you want to unpublish the site", s.Title),
Title: "Confirm unpublishing of site",
}
} else {
@ -324,7 +324,7 @@ func AdminSitePublishHandler(ctx *middleware.AppContext, w http.ResponseWriter,
ID: "publishSite",
ActionURL: fmt.Sprintf("/admin/site/publish/%d", s.ID),
BackLinkURL: "/admin/sites",
Description: fmt.Sprintf("%s %s?", "Do you want to publish the site ", s.Title),
Description: fmt.Sprintf("%s %s?", "Do you want to publish the site", s.Title),
Title: "Confirm publishing of site",
}
}
@ -363,7 +363,7 @@ func AdminSitePublishPostHandler(ctx *middleware.AppContext, w http.ResponseWrit
return &middleware.Template{
RedirectPath: "admin/sites",
Active: "sites",
SuccessMsg: "Site successfully published",
SuccessMsg: "Site successfully published.",
}
}
@ -434,7 +434,7 @@ func AdminSiteDeletePostHandler(ctx *middleware.AppContext, w http.ResponseWrite
return &middleware.Template{
RedirectPath: "admin/sites",
Active: "sites",
SuccessMsg: "Site successfully deleted",
SuccessMsg: "Site successfully deleted.",
}
}

View File

@ -233,7 +233,7 @@ func AdminUserDeleteHandler(ctx *middleware.AppContext, w http.ResponseWriter, r
RedirectPath: "admin/users",
Active: "users",
Err: httperror.New(http.StatusUnprocessableEntity,
"Could not remove administrator. No Administrator would remain.",
"Could not remove administrator. No administrator would remain.",
fmt.Errorf("could not remove administrator %s no administrator would remain", user.Username)),
}
}

View File

@ -44,7 +44,7 @@ func AdminUserInviteNewPostHandler(ctx *middleware.AppContext, w http.ResponseWr
return &middleware.Template{
RedirectPath: "admin/users",
Active: "users",
SuccessMsg: "Successfully invited user " + ui.Email,
SuccessMsg: fmt.Sprintf("%s %s. ", "Successfully invited user ", ui.Email),
Data: map[string]interface{}{
"inviteID": inviteID,
"hash": ui.Hash,
@ -78,7 +78,7 @@ func AdminUserInviteResendPostHandler(ctx *middleware.AppContext, w http.Respons
return &middleware.Template{
RedirectPath: "admin/users",
Active: "users",
SuccessMsg: "Successfully invited user " + ui.Email,
SuccessMsg: fmt.Sprintf("%s %s. ", "Successfully invited user ", ui.Email),
Data: map[string]interface{}{
"inviteID": inviteID,
"hash": ui.Hash,

6
go.sum
View File

@ -19,6 +19,7 @@ github.com/justinas/alice v0.0.0-20171023064455-03f45bd4b7da h1:5y58+OCjoHCYB818
github.com/justinas/alice v0.0.0-20171023064455-03f45bd4b7da/go.mod h1:oLH0CmIaxCGXD67VKGR5AacGXZSMznlmeqM8RzPrcY8=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
@ -34,18 +35,15 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.0 h1:yKenngtzGh+cUSSh6GWbxW2abRqhYUSR/t/6+2QqNvE=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc h1:F5tKCVGp+MUAHhKp5MZtGqAlGX3+oCsiL1Q629FL90M=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576 h1:aUX/1G2gFSs4AsJJg2cL3HuoRhCSCz733FE5GUSuaT4=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

View File

@ -12,7 +12,7 @@ import (
"git.hoogi.eu/session"
)
//AppContext contains the services, session store, templates
//AppContext contains the services, session store, templates, ...
type AppContext struct {
SessionService *session.SessionService
ArticleService models.ArticleService

View File

@ -14,8 +14,6 @@ import (
)
// JSONHandler marshals JSON and writes to the http response
// Currently just used for keeping the session alive (if writing or editing an article or site)
// see controllers/json/session.go
type JSONHandler struct {
AppCtx *AppContext
Handler JHandler

View File

@ -63,7 +63,7 @@ func NotFound(ctx *AppContext, rw http.ResponseWriter, r *http.Request) *Templat
}
}
//FuncMap some functions for use in templates
//FuncMap some function that can be used in templates
func FuncMap(ss models.SiteService, settings *settings.Settings) template.FuncMap {
return template.FuncMap{
"GetMetadata": func(data map[string]interface{}) template.HTML {

View File

@ -54,5 +54,6 @@ func (fn XMLHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
x = bytes.Replace(x, []byte("&lt;"), []byte("&#x3c;"), -1) // <
x = bytes.Replace(x, []byte("&gt;"), []byte("&#x3e;"), -1) // >
}
rw.Write(x)
}

View File

@ -7,7 +7,7 @@ package models
// Action this type is used for YES/NO actions see template/admin/action.html
// Title is shown in the headline
// ActionURL defines where the form should be sent
// BackLinkURL defines where to go back
// BackLinkURL defines where to go back (if clicking on cancel)
// WarnMsg defines an optional warning which is shown above the description
// Description describes what action the user has to decide
type Action struct {