diff --git a/database/initialization.go b/database/initialization.go
index fca7d948..512a69c6 100644
--- a/database/initialization.go
+++ b/database/initialization.go
@@ -5,6 +5,7 @@ import (
"github.com/kabukky/journey/database/migration"
"github.com/kabukky/journey/filenames"
"github.com/kabukky/journey/helpers"
+ "github.com/kabukky/journey/structure"
_ "github.com/mattn/go-sqlite3"
"github.com/twinj/uuid"
"time"
@@ -147,5 +148,97 @@ func Initialize() error {
if err != nil {
return err
}
+ err = checkBlogSettings()
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// Function to check and insert any missing blog settings into the database (settings could be missing if migrating from Ghost).
+func checkBlogSettings() error {
+ tempBlog := structure.Blog{}
+ // Check for title
+ row := readDB.QueryRow(stmtRetrieveBlog, "title")
+ err := row.Scan(&tempBlog.Title)
+ if err != nil {
+ // Insert title
+ err = insertSettingString("title", "My Blog", "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for description
+ row = readDB.QueryRow(stmtRetrieveBlog, "description")
+ err = row.Scan(&tempBlog.Description)
+ if err != nil {
+ // Insert description
+ err = insertSettingString("description", "Just another Blog", "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for email
+ var email []byte
+ row = readDB.QueryRow(stmtRetrieveBlog, "email")
+ err = row.Scan(&email)
+ if err != nil {
+ // Insert email
+ err = insertSettingString("email", "", "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for logo
+ row = readDB.QueryRow(stmtRetrieveBlog, "logo")
+ err = row.Scan(&tempBlog.Logo)
+ if err != nil {
+ // Insert logo
+ err = insertSettingString("logo", "/public/images/blog-logo.jpg", "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for cover
+ row = readDB.QueryRow(stmtRetrieveBlog, "cover")
+ err = row.Scan(&tempBlog.Cover)
+ if err != nil {
+ // Insert cover
+ err = insertSettingString("cover", "/public/images/blog-cover.jpg", "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for postsPerPage
+ row = readDB.QueryRow(stmtRetrieveBlog, "postsPerPage")
+ err = row.Scan(&tempBlog.PostsPerPage)
+ if err != nil {
+ // Insert postsPerPage
+ err = insertSettingInt64("postsPerPage", 5, "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for activeTheme
+ row = readDB.QueryRow(stmtRetrieveBlog, "activeTheme")
+ err = row.Scan(&tempBlog.ActiveTheme)
+ if err != nil {
+ // Insert activeTheme
+ err = insertSettingString("activeTheme", "promenade", "theme", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
+ // Check for navigation
+ var navigation []byte
+ row = readDB.QueryRow(stmtRetrieveBlog, "navigation")
+ err = row.Scan(&navigation)
+ if err != nil {
+ // Insert navigation
+ err = insertSettingString("navigation", "[{\"label\":\"Home\", \"url\":\"/\"}]", "blog", time.Now(), 1)
+ if err != nil {
+ return err
+ }
+ }
return nil
}
diff --git a/database/insertion.go b/database/insertion.go
index f6cd7402..1db1b7e6 100644
--- a/database/insertion.go
+++ b/database/insertion.go
@@ -11,6 +11,7 @@ const stmtInsertUser = "INSERT INTO users (id, uuid, name, slug, password, email
const stmtInsertRoleUser = "INSERT INTO roles_users (id, role_id, user_id) VALUES (?, ?, ?)"
const stmtInsertTag = "INSERT INTO tags (id, uuid, name, slug, created_at, created_by, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
const stmtInsertPostTag = "INSERT INTO posts_tags (id, post_id, tag_id) VALUES (?, ?, ?)"
+const stmtInsertSetting = "INSERT INTO settings (id, uuid, key, value, type, created_at, created_by, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
func InsertPost(title []byte, slug string, markdown []byte, html []byte, featured bool, isPage bool, published bool, image []byte, created_at time.Time, created_by int64) (int64, error) {
@@ -106,3 +107,31 @@ func InsertPostTag(post_id int64, tag_id int64) error {
}
return writeDB.Commit()
}
+
+func insertSettingString(key string, value string, setting_type string, created_at time.Time, created_by int64) error {
+ writeDB, err := readDB.Begin()
+ if err != nil {
+ writeDB.Rollback()
+ return err
+ }
+ _, err = writeDB.Exec(stmtInsertSetting, nil, uuid.Formatter(uuid.NewV4(), uuid.CleanHyphen), key, value, setting_type, created_at, created_by, created_at, created_by)
+ if err != nil {
+ writeDB.Rollback()
+ return err
+ }
+ return writeDB.Commit()
+}
+
+func insertSettingInt64(key string, value int64, setting_type string, created_at time.Time, created_by int64) error {
+ writeDB, err := readDB.Begin()
+ if err != nil {
+ writeDB.Rollback()
+ return err
+ }
+ _, err = writeDB.Exec(stmtInsertSetting, nil, uuid.Formatter(uuid.NewV4(), uuid.CleanHyphen), key, value, setting_type, created_at, created_by, created_at, created_by)
+ if err != nil {
+ writeDB.Rollback()
+ return err
+ }
+ return writeDB.Commit()
+}
diff --git a/database/update.go b/database/update.go
index 41e98f4f..53f5ee59 100644
--- a/database/update.go
+++ b/database/update.go
@@ -7,7 +7,7 @@ import (
const stmtUpdatePost = "UPDATE posts SET title = ?, slug = ?, markdown = ?, html = ?, featured = ?, page = ?, status = ?, image = ?, updated_at = ?, updated_by = ? WHERE id = ?"
const stmtUpdatePostPublished = "UPDATE posts SET title = ?, slug = ?, markdown = ?, html = ?, featured = ?, page = ?, status = ?, image = ?, updated_at = ?, updated_by = ?, published_at = ?, published_by = ? WHERE id = ?"
const stmtUpdateSettings = "UPDATE settings SET value = ?, updated_at = ?, updated_by = ? WHERE key = ?"
-const stmtUpdateUser = "UPDATE users SET email = ?, image = ?, cover = ?, bio = ?, website = ?, location = ?, updated_at = ?, updated_by = ? WHERE id = ?"
+const stmtUpdateUser = "UPDATE users SET name = ?, slug = ?, email = ?, image = ?, cover = ?, bio = ?, website = ?, location = ?, updated_at = ?, updated_by = ? WHERE id = ?"
const stmtUpdateLastLogin = "UPDATE users SET last_login = ? WHERE id = ?"
const stmtUpdateUserPassword = "UPDATE users SET password = ?, updated_at = ?, updated_by = ? WHERE id = ?"
@@ -103,13 +103,13 @@ func UpdateActiveTheme(activeTheme string, updated_at time.Time, updated_by int6
return writeDB.Commit()
}
-func UpdateUser(id int64, email []byte, image []byte, cover []byte, bio []byte, website []byte, location []byte, updated_at time.Time, updated_by int64) error {
+func UpdateUser(id int64, name []byte, slug string, email []byte, image []byte, cover []byte, bio []byte, website []byte, location []byte, updated_at time.Time, updated_by int64) error {
writeDB, err := readDB.Begin()
if err != nil {
writeDB.Rollback()
return err
}
- _, err = writeDB.Exec(stmtUpdateUser, email, image, cover, bio, website, location, updated_at, updated_by, id)
+ _, err = writeDB.Exec(stmtUpdateUser, name, slug, email, image, cover, bio, website, location, updated_at, updated_by, id)
if err != nil {
writeDB.Rollback()
return err
diff --git a/server/admin.go b/server/admin.go
index a16af771..99db4032 100644
--- a/server/admin.go
+++ b/server/admin.go
@@ -52,6 +52,7 @@ type JsonBlog struct {
type JsonUser struct {
Id int64
Name string
+ Slug string
Email string
Image string
Cover string
@@ -86,15 +87,7 @@ func postLoginHandler(w http.ResponseWriter, r *http.Request, _ map[string]strin
password := r.FormValue("password")
if name != "" && password != "" {
if authentication.LoginIsCorrect(name, password) {
- authentication.SetSession(name, w)
- userId, err := getUserId(name)
- if err != nil {
- log.Println("Couldn't get id of logged in user:", err)
- }
- err = database.UpdateLastLogin(time.Now(), userId)
- if err != nil {
- log.Println("Couldn't update last login date of a user:", err)
- }
+ logInUser(name, w)
} else {
log.Println("Failed login attempt for user " + name)
}
@@ -597,13 +590,13 @@ func getApiUserHandler(w http.ResponseWriter, r *http.Request, params map[string
http.Error(w, "You don't have permission to access this data.", http.StatusForbidden)
return
}
- author, err := database.RetrieveUser(userIdToGet)
+ user, err := database.RetrieveUser(userIdToGet)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- authorJson := JsonUser{Id: author.Id, Name: string(author.Name), Email: string(author.Email), Image: string(author.Image), Cover: string(author.Cover), Bio: string(author.Bio), Website: string(author.Website), Location: string(author.Location)}
- json, err := json.Marshal(authorJson)
+ userJson := userToJson(user)
+ json, err := json.Marshal(userJson)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -633,19 +626,34 @@ func patchApiUserHandler(w http.ResponseWriter, r *http.Request, _ map[string]st
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- // Make sure user id is over 0 and E-Mail is included.
+ // Make sure user id is over 0
if json.Id < 1 {
http.Error(w, "Wrong user id.", http.StatusInternalServerError)
return
- } else if json.Email == "" {
- http.Error(w, "Email needs to be included.", http.StatusInternalServerError)
- return
} else if userId != json.Id { // Make sure the authenticated user is only changing his/her own data. TODO: Make sure the user is admin when multiple users have been introduced
http.Error(w, "You don't have permission to change this data.", http.StatusInternalServerError)
return
}
- author := structure.User{Id: json.Id, Email: []byte(json.Email), Image: []byte(json.Image), Cover: []byte(json.Cover), Bio: []byte(json.Bio), Website: []byte(json.Website), Location: []byte(json.Location)}
- err = methods.UpdateUser(&author, userId)
+ // Get old user data to compare
+ tempUser, err := database.RetrieveUser(json.Id)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ // Make sure user email is provided
+ if json.Email == "" {
+ json.Email = string(tempUser.Email)
+ }
+ // Make sure user name is provided
+ if json.Name == "" {
+ json.Name = string(tempUser.Name)
+ }
+ // Make sure user slug is provided
+ if json.Slug == "" {
+ json.Slug = tempUser.Slug
+ }
+ user := structure.User{Id: json.Id, Name: []byte(json.Name), Slug: json.Slug, Email: []byte(json.Email), Image: []byte(json.Image), Cover: []byte(json.Cover), Bio: []byte(json.Bio), Website: []byte(json.Website), Location: []byte(json.Location)}
+ err = methods.UpdateUser(&user, userId)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@@ -656,12 +664,16 @@ func patchApiUserHandler(w http.ResponseWriter, r *http.Request, _ map[string]st
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
- err = database.UpdateUserPassword(author.Id, encryptedPassword, time.Now(), json.Id)
+ err = database.UpdateUserPassword(user.Id, encryptedPassword, time.Now(), json.Id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
+ // Check if the user name was changed. If so, update the session cookie to the new user name.
+ if json.Name != string(tempUser.Name) {
+ logInUser(json.Name, w)
+ }
w.WriteHeader(http.StatusOK)
w.Write([]byte("User settings updated!"))
return
@@ -703,6 +715,18 @@ func getUserId(userName string) (int64, error) {
return user.Id, nil
}
+func logInUser(name string, w http.ResponseWriter) {
+ authentication.SetSession(name, w)
+ userId, err := getUserId(name)
+ if err != nil {
+ log.Println("Couldn't get id of logged in user:", err)
+ }
+ err = database.UpdateLastLogin(time.Now(), userId)
+ if err != nil {
+ log.Println("Couldn't update last login date of a user:", err)
+ }
+}
+
func postsToJson(posts []structure.Post) *[]JsonPost {
jsonPosts := make([]JsonPost, len(posts))
for index, _ := range posts {
@@ -745,6 +769,20 @@ func blogToJson(blog *structure.Blog) *JsonBlog {
return &jsonBlog
}
+func userToJson(user *structure.User) *JsonUser {
+ var jsonUser JsonUser
+ jsonUser.Id = user.Id
+ jsonUser.Name = string(user.Name)
+ jsonUser.Slug = user.Slug
+ jsonUser.Email = string(user.Email)
+ jsonUser.Image = string(user.Image)
+ jsonUser.Cover = string(user.Cover)
+ jsonUser.Bio = string(user.Bio)
+ jsonUser.Website = string(user.Website)
+ jsonUser.Location = string(user.Location)
+ return &jsonUser
+}
+
func InitializeAdmin(router *httptreemux.TreeMux) {
// For admin panel
router.GET("/admin/", adminHandler)
diff --git a/structure/methods/user.go b/structure/methods/user.go
index 7a40d101..d0b33ad7 100644
--- a/structure/methods/user.go
+++ b/structure/methods/user.go
@@ -19,7 +19,7 @@ func SaveUser(u *structure.User, hashedPassword string, createdBy int64) error {
}
func UpdateUser(u *structure.User, updatedById int64) error {
- err := database.UpdateUser(u.Id, u.Email, u.Image, u.Cover, u.Bio, u.Website, u.Location, time.Now(), updatedById)
+ err := database.UpdateUser(u.Id, u.Name, u.Slug, u.Email, u.Image, u.Cover, u.Bio, u.Website, u.Location, time.Now(), updatedById)
if err != nil {
return err
}
diff --git a/templates/rss.go b/templates/rss.go
index e34f6050..cedecab4 100644
--- a/templates/rss.go
+++ b/templates/rss.go
@@ -5,27 +5,30 @@ import (
"github.com/gorilla/feeds"
"github.com/kabukky/journey/database"
"github.com/kabukky/journey/structure"
+ "github.com/kabukky/journey/structure/methods"
"net/http"
"time"
)
func ShowIndexRss(writer http.ResponseWriter) error {
+ // Read lock global blog
+ methods.Blog.RLock()
+ defer methods.Blog.RUnlock()
// 15 posts in rss for now
posts, err := database.RetrievePostsForIndex(15, 0)
if err != nil {
return err
}
- blog, err := database.RetrieveBlog()
- if err != nil {
- return err
- }
- blogData := &structure.RequestData{Posts: posts, Blog: blog}
+ blogData := &structure.RequestData{Posts: posts, Blog: methods.Blog}
feed := createFeed(blogData)
err = feed.WriteRss(writer)
return err
}
func ShowTagRss(writer http.ResponseWriter, slug string) error {
+ // Read lock global blog
+ methods.Blog.RLock()
+ defer methods.Blog.RUnlock()
tag, err := database.RetrieveTagBySlug(slug)
if err != nil {
return err
@@ -35,17 +38,16 @@ func ShowTagRss(writer http.ResponseWriter, slug string) error {
if err != nil {
return err
}
- blog, err := database.RetrieveBlog()
- if err != nil {
- return err
- }
- blogData := &structure.RequestData{Posts: posts, Blog: blog}
+ blogData := &structure.RequestData{Posts: posts, Blog: methods.Blog}
feed := createFeed(blogData)
err = feed.WriteRss(writer)
return err
}
func ShowAuthorRss(writer http.ResponseWriter, slug string) error {
+ // Read lock global blog
+ methods.Blog.RLock()
+ defer methods.Blog.RUnlock()
author, err := database.RetrieveUserBySlug(slug)
if err != nil {
return err
@@ -55,11 +57,7 @@ func ShowAuthorRss(writer http.ResponseWriter, slug string) error {
if err != nil {
return err
}
- blog, err := database.RetrieveBlog()
- if err != nil {
- return err
- }
- blogData := &structure.RequestData{Posts: posts, Blog: blog}
+ blogData := &structure.RequestData{Posts: posts, Blog: methods.Blog}
feed := createFeed(blogData)
err = feed.WriteRss(writer)
return err
@@ -68,8 +66,8 @@ func ShowAuthorRss(writer http.ResponseWriter, slug string) error {
func createFeed(values *structure.RequestData) *feeds.Feed {
now := time.Now()
feed := &feeds.Feed{
- Title: string(makeCdata(values.Blog.Title)),
- Description: string(makeCdata(values.Blog.Description)),
+ Title: string(values.Blog.Title),
+ Description: string(values.Blog.Description),
Link: &feeds.Link{Href: string(values.Blog.Url)},
Created: now,
}
@@ -81,8 +79,8 @@ func createFeed(values *structure.RequestData) *feeds.Feed {
buffer.WriteString("/")
buffer.WriteString(values.Posts[i].Slug)
feed.Items = append(feed.Items, &feeds.Item{
- Title: string(makeCdata(values.Posts[i].Title)),
- Description: string(makeCdata(values.Posts[i].Html)),
+ Title: string(values.Posts[i].Title),
+ Description: string(values.Posts[i].Html),
Link: &feeds.Link{Href: buffer.String()},
Id: string(values.Posts[i].Uuid),
Author: &feeds.Author{Name: string(values.Posts[i].Author.Name), Email: ""},
@@ -93,11 +91,3 @@ func createFeed(values *structure.RequestData) *feeds.Feed {
return feed
}
-
-func makeCdata(input []byte) []byte {
- var buffer bytes.Buffer
- buffer.WriteString("")
- return buffer.Bytes()
-}