Another mooostly technical commit, don't worry we'll be getting to the fun stuff soon!

The query statements now use camelCase instead of undercase.
Added more documentation.
Renamed a few config variables.
The length counters in the MemoryUserStore and MemoryTopicStore are now atomic.
Added the Flush method to the UserCache and TopicCache.
Made more visual improvements to Tempra Conflux.
The avatar block vanished from the opening posts for topics for some reason, I added it back.
Added more tests.

And many more changes...
This commit is contained in:
Azareal 2017-09-18 18:03:52 +01:00
parent 2557eb935b
commit 217e7abab3
40 changed files with 1163 additions and 1024 deletions

View File

@ -122,7 +122,7 @@ func buildAlert(asid int, event string, elementType string, actorID int, targetU
} }
func notifyWatchers(asid int64) { func notifyWatchers(asid int64) {
rows, err := get_watchers_stmt.Query(asid) rows, err := getWatchersStmt.Query(asid)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
log.Fatal(err.Error()) log.Fatal(err.Error())
return return
@ -147,7 +147,7 @@ func notifyWatchers(asid int64) {
var actorID, targetUserID, elementID int var actorID, targetUserID, elementID int
var event, elementType string var event, elementType string
err = get_activity_entry_stmt.QueryRow(asid).Scan(&actorID, &targetUserID, &event, &elementType, &elementID) err = getActivityEntryStmt.QueryRow(asid).Scan(&actorID, &targetUserID, &event, &elementType, &elementID)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
log.Fatal(err.Error()) log.Fatal(err.Error())
return return

View File

@ -162,7 +162,7 @@ func (auth *DefaultAuth) CreateSession(uid int) (session string, err error) {
return "", err return "", err
} }
_, err = update_session_stmt.Exec(session, uid) _, err = updateSessionStmt.Exec(session, uid)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -11,7 +11,7 @@ const CACHE_SQL int = 2
// ErrCacheDesync is thrown whenever a piece of data, for instance, a user is out of sync with the database. Currently unused. // ErrCacheDesync is thrown whenever a piece of data, for instance, a user is out of sync with the database. Currently unused.
var ErrCacheDesync = errors.New("The cache is out of sync with the database.") // TODO: A cross-server synchronisation mechanism var ErrCacheDesync = errors.New("The cache is out of sync with the database.") // TODO: A cross-server synchronisation mechanism
// ErrStoreCapacityOverflow is thrown whenever a datastore reaches it's maximum hard capacity. I'm not sure *if* this one is used, at the moment. Probably. // ErrStoreCapacityOverflow is thrown whenever a datastore reaches it's maximum hard capacity. I'm not sure if this error is actually used.
var ErrStoreCapacityOverflow = errors.New("This datastore has reached it's maximum capacity.") var ErrStoreCapacityOverflow = errors.New("This datastore has reached it's maximum capacity.")
// nolint // nolint
@ -22,6 +22,7 @@ type DataStore interface {
//GetGlobalCount() //GetGlobalCount()
} }
// nolint
type DataCache interface { type DataCache interface {
CacheGet(id int) (interface{}, error) CacheGet(id int) (interface{}, error)
CacheGetUnsafe(id int) (interface{}, error) CacheGetUnsafe(id int) (interface{}, error)

View File

@ -29,16 +29,16 @@ func init() {
config.TopicCacheCapacity = 200 // The max number of topics held in memory config.TopicCacheCapacity = 200 // The max number of topics held in memory
// Email // Email
config.SmtpServer = "" config.SMTPServer = ""
config.SmtpUsername = "" config.SMTPUsername = ""
config.SmtpPassword = "" config.SMTPPassword = ""
config.SmtpPort = "25" config.SMTPPort = "25"
// Misc // Misc
config.DefaultRoute = routeTopics config.DefaultRoute = routeTopics
config.DefaultGroup = 3 // Should be a setting in the database config.DefaultGroup = 3 // Should be a setting in the database
config.ActivationGroup = 5 // Should be a setting in the database config.ActivationGroup = 5 // Should be a setting in the database
config.StaffCss = "staff_post" config.StaffCSS = "staff_post"
config.UncategorisedForumVisible = true config.UncategorisedForumVisible = true
config.MinifyTemplates = false config.MinifyTemplates = false
config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features

View File

@ -11,8 +11,8 @@ import "runtime/debug"
var errorBufferMutex sync.RWMutex var errorBufferMutex sync.RWMutex
var errorBuffer []error var errorBuffer []error
//var notfound_count_per_second int //var notfoundCountPerSecond int
//var noperms_count_per_second int //var nopermsCountPerSecond int
var errorInternal []byte var errorInternal []byte
var errorNotfound []byte var errorNotfound []byte
@ -83,6 +83,24 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) {
log.Fatal(err) log.Fatal(err)
} }
// ? - Where is this used? Is it actually used? Should we use it more?
// LoginRequired is an error shown to the end-user when they try to access an area which requires them to login
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) {
w.WriteHeader(401)
pi := Page{"Local Error", user, hvars, tList, "You need to login to do that."}
if preRenderHooks["pre_render_error"] != nil {
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
return
}
}
var b bytes.Buffer
err := templates.ExecuteTemplate(&b, "error.html", pi)
if err != nil {
LogError(err)
}
fmt.Fprintln(w, b.String())
}
func PreError(errmsg string, w http.ResponseWriter, r *http.Request) { func PreError(errmsg string, w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500) w.WriteHeader(500)
user := User{ID: 0, Group: 6, Perms: GuestPerms} user := User{ID: 0, Group: 6, Perms: GuestPerms}
@ -100,38 +118,6 @@ func PreError(errmsg string, w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, b.String()) fmt.Fprintln(w, b.String())
} }
func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) {
w.WriteHeader(500)
pi := Page{"Local Error", user, hvars, tList, errmsg}
if preRenderHooks["pre_render_error"] != nil {
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
return
}
}
var b bytes.Buffer
err := templates.ExecuteTemplate(&b, "error.html", pi)
if err != nil {
LogError(err)
}
fmt.Fprintln(w, b.String())
}
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) {
w.WriteHeader(401)
pi := Page{"Local Error", user, hvars, tList, "You need to login to do that."}
if preRenderHooks["pre_render_error"] != nil {
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
return
}
}
var b bytes.Buffer
err := templates.ExecuteTemplate(&b, "error.html", pi)
if err != nil {
LogError(err)
}
fmt.Fprintln(w, b.String())
}
func PreErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) { func PreErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) {
w.WriteHeader(500) w.WriteHeader(500)
_, _ = w.Write([]byte(`{"errmsg":"` + errmsg + `"}`)) _, _ = w.Write([]byte(`{"errmsg":"` + errmsg + `"}`))
@ -158,6 +144,23 @@ func PreErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, isJs boo
} }
} }
// LocalError is an error shown to the end-user when something goes wrong and it's not the software's fault
func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) {
w.WriteHeader(500)
pi := Page{"Local Error", user, hvars, tList, errmsg}
if preRenderHooks["pre_render_error"] != nil {
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
return
}
}
var b bytes.Buffer
err := templates.ExecuteTemplate(&b, "error.html", pi)
if err != nil {
LogError(err)
}
fmt.Fprintln(w, b.String())
}
func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user User, isJs bool) { func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user User, isJs bool) {
w.WriteHeader(500) w.WriteHeader(500)
if !isJs { if !isJs {
@ -183,6 +186,7 @@ func LocalErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{'errmsg': '` + errmsg + `'}`)) _, _ = w.Write([]byte(`{'errmsg': '` + errmsg + `'}`))
} }
// NoPermissions is an error shown to the end-user when they try to access an area which they aren't authorised to access
func NoPermissions(w http.ResponseWriter, r *http.Request, user User) { func NoPermissions(w http.ResponseWriter, r *http.Request, user User) {
w.WriteHeader(403) w.WriteHeader(403)
pi := Page{"Local Error", user, hvars, tList, "You don't have permission to do that."} pi := Page{"Local Error", user, hvars, tList, "You don't have permission to do that."}
@ -220,6 +224,7 @@ func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bo
} }
} }
// ? - Is this actually used? Should it be used? A ban in Gosora should be more of a permission revocation to stop them posting rather than something which spits up an error page, right?
func Banned(w http.ResponseWriter, r *http.Request, user User) { func Banned(w http.ResponseWriter, r *http.Request, user User) {
w.WriteHeader(403) w.WriteHeader(403)
pi := Page{"Banned", user, hvars, tList, "You have been banned from this site."} pi := Page{"Banned", user, hvars, tList, "You have been banned from this site."}
@ -237,6 +242,7 @@ func Banned(w http.ResponseWriter, r *http.Request, user User) {
} }
// nolint // nolint
// BannedJSQ is the version of the banned error page which handles both JavaScript requests and normal page loads
func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) { func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) {
w.WriteHeader(403) w.WriteHeader(403)
if !isJs { if !isJs {

View File

@ -79,6 +79,8 @@ var preRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User
"pre_render_security_error": nil, "pre_render_security_error": nil,
} }
// ? - Should we make this an interface which plugins implement instead?
// Plugin is a struct holding the metadata for a plugin, along with a few of it's primary handlers.
type Plugin struct { type Plugin struct {
UName string UName string
Name string Name string
@ -100,8 +102,9 @@ type Plugin struct {
Hooks map[string]int Hooks map[string]int
} }
// LoadPlugins polls the database to see which plugins have been activated and which have been installed
func LoadPlugins() error { func LoadPlugins() error {
rows, err := get_plugins_stmt.Query() rows, err := getPluginsStmt.Query()
if err != nil { if err != nil {
return err return err
} }

View File

@ -24,7 +24,7 @@ type SFile struct {
FormattedModTime string FormattedModTime string
} }
type CssData struct { type CSSData struct {
ComingSoon string ComingSoon string
} }

View File

@ -106,7 +106,7 @@ func (mfs *MemoryForumStore) LoadForums() error {
addForum(&Forum{0, buildForumURL(nameToSlug("Uncategorised"), 0), "Uncategorised", "", config.UncategorisedForumVisible, "all", 0, "", 0, "", "", 0, "", 0, ""}) addForum(&Forum{0, buildForumURL(nameToSlug("Uncategorised"), 0), "Uncategorised", "", config.UncategorisedForumVisible, "all", 0, "", 0, "", "", 0, "", 0, ""})
rows, err := get_forums_stmt.Query() rows, err := getForumsStmt.Query()
if err != nil { if err != nil {
return err return err
} }
@ -290,7 +290,7 @@ func (mfs *MemoryForumStore) IncrementTopicCount(id int) error {
if err != nil { if err != nil {
return err return err
} }
_, err = add_topics_to_forum_stmt.Exec(1, id) _, err = addTopicsToForumStmt.Exec(1, id)
if err != nil { if err != nil {
return err return err
} }
@ -303,7 +303,7 @@ func (mfs *MemoryForumStore) DecrementTopicCount(id int) error {
if err != nil { if err != nil {
return err return err
} }
_, err = remove_topics_from_forum_stmt.Exec(1, id) _, err = removeTopicsFromForumStmt.Exec(1, id)
if err != nil { if err != nil {
return err return err
} }
@ -318,7 +318,7 @@ func (mfs *MemoryForumStore) UpdateLastTopic(topicName string, tid int, username
return err return err
} }
_, err = update_forum_cache_stmt.Exec(topicName, tid, username, uid, fid) _, err = updateForumCacheStmt.Exec(topicName, tid, username, uid, fid)
if err != nil { if err != nil {
return err return err
} }
@ -334,7 +334,7 @@ func (mfs *MemoryForumStore) UpdateLastTopic(topicName string, tid int, username
func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) { func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) {
forumCreateMutex.Lock() forumCreateMutex.Lock()
res, err := create_forum_stmt.Exec(forumName, forumDesc, active, preset) res, err := createForumStmt.Exec(forumName, forumDesc, active, preset)
if err != nil { if err != nil {
return 0, err return 0, err
} }

File diff suppressed because it is too large Load Diff

View File

@ -7,45 +7,45 @@ import "log"
import "database/sql" import "database/sql"
// nolint // nolint
var add_replies_to_topic_stmt *sql.Stmt var addRepliesToTopicStmt *sql.Stmt
var remove_replies_from_topic_stmt *sql.Stmt var removeRepliesFromTopicStmt *sql.Stmt
var add_topics_to_forum_stmt *sql.Stmt var addTopicsToForumStmt *sql.Stmt
var remove_topics_from_forum_stmt *sql.Stmt var removeTopicsFromForumStmt *sql.Stmt
var update_forum_cache_stmt *sql.Stmt var updateForumCacheStmt *sql.Stmt
var add_likes_to_topic_stmt *sql.Stmt var addLikesToTopicStmt *sql.Stmt
var add_likes_to_reply_stmt *sql.Stmt var addLikesToReplyStmt *sql.Stmt
var edit_topic_stmt *sql.Stmt var editTopicStmt *sql.Stmt
var edit_reply_stmt *sql.Stmt var editReplyStmt *sql.Stmt
var stick_topic_stmt *sql.Stmt var stickTopicStmt *sql.Stmt
var unstick_topic_stmt *sql.Stmt var unstickTopicStmt *sql.Stmt
var update_last_ip_stmt *sql.Stmt var updateLastIPStmt *sql.Stmt
var update_session_stmt *sql.Stmt var updateSessionStmt *sql.Stmt
var set_password_stmt *sql.Stmt var setPasswordStmt *sql.Stmt
var set_avatar_stmt *sql.Stmt var setAvatarStmt *sql.Stmt
var set_username_stmt *sql.Stmt var setUsernameStmt *sql.Stmt
var change_group_stmt *sql.Stmt var changeGroupStmt *sql.Stmt
var activate_user_stmt *sql.Stmt var activateUserStmt *sql.Stmt
var update_user_level_stmt *sql.Stmt var updateUserLevelStmt *sql.Stmt
var increment_user_score_stmt *sql.Stmt var incrementUserScoreStmt *sql.Stmt
var increment_user_posts_stmt *sql.Stmt var incrementUserPostsStmt *sql.Stmt
var increment_user_bigposts_stmt *sql.Stmt var incrementUserBigpostsStmt *sql.Stmt
var increment_user_megaposts_stmt *sql.Stmt var incrementUserMegapostsStmt *sql.Stmt
var increment_user_topics_stmt *sql.Stmt var incrementUserTopicsStmt *sql.Stmt
var edit_profile_reply_stmt *sql.Stmt var editProfileReplyStmt *sql.Stmt
var update_forum_stmt *sql.Stmt var updateForumStmt *sql.Stmt
var update_setting_stmt *sql.Stmt var updateSettingStmt *sql.Stmt
var update_plugin_stmt *sql.Stmt var updatePluginStmt *sql.Stmt
var update_plugin_install_stmt *sql.Stmt var updatePluginInstallStmt *sql.Stmt
var update_theme_stmt *sql.Stmt var updateThemeStmt *sql.Stmt
var update_user_stmt *sql.Stmt var updateUserStmt *sql.Stmt
var update_group_perms_stmt *sql.Stmt var updateGroupPermsStmt *sql.Stmt
var update_group_rank_stmt *sql.Stmt var updateGroupRankStmt *sql.Stmt
var update_group_stmt *sql.Stmt var updateGroupStmt *sql.Stmt
var update_email_stmt *sql.Stmt var updateEmailStmt *sql.Stmt
var verify_email_stmt *sql.Stmt var verifyEmailStmt *sql.Stmt
var set_temp_group_stmt *sql.Stmt var setTempGroupStmt *sql.Stmt
var update_word_filter_stmt *sql.Stmt var updateWordFilterStmt *sql.Stmt
var bump_sync_stmt *sql.Stmt var bumpSyncStmt *sql.Stmt
// nolint // nolint
func _gen_pgsql() (err error) { func _gen_pgsql() (err error) {
@ -53,236 +53,236 @@ func _gen_pgsql() (err error) {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
log.Print("Preparing add_replies_to_topic statement.") log.Print("Preparing addRepliesToTopic statement.")
add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyBy` = ?,`lastReplyAt` = LOCALTIMESTAMP() WHERE `tid` = ?") addRepliesToTopicStmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyBy` = ?,`lastReplyAt` = LOCALTIMESTAMP() WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing remove_replies_from_topic statement.") log.Print("Preparing removeRepliesFromTopic statement.")
remove_replies_from_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` - ? WHERE `tid` = ?") removeRepliesFromTopicStmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` - ? WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing add_topics_to_forum statement.") log.Print("Preparing addTopicsToForum statement.")
add_topics_to_forum_stmt, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` + ? WHERE `fid` = ?") addTopicsToForumStmt, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` + ? WHERE `fid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing remove_topics_from_forum statement.") log.Print("Preparing removeTopicsFromForum statement.")
remove_topics_from_forum_stmt, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` - ? WHERE `fid` = ?") removeTopicsFromForumStmt, err = db.Prepare("UPDATE `forums` SET `topicCount` = `topicCount` - ? WHERE `fid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_forum_cache statement.") log.Print("Preparing updateForumCache statement.")
update_forum_cache_stmt, err = db.Prepare("UPDATE `forums` SET `lastTopic` = ?,`lastTopicID` = ?,`lastReplyer` = ?,`lastReplyerID` = ?,`lastTopicTime` = LOCALTIMESTAMP() WHERE `fid` = ?") updateForumCacheStmt, err = db.Prepare("UPDATE `forums` SET `lastTopic` = ?,`lastTopicID` = ?,`lastReplyer` = ?,`lastReplyerID` = ?,`lastTopicTime` = LOCALTIMESTAMP() WHERE `fid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing add_likes_to_topic statement.") log.Print("Preparing addLikesToTopic statement.")
add_likes_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?") addLikesToTopicStmt, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing add_likes_to_reply statement.") log.Print("Preparing addLikesToReply statement.")
add_likes_to_reply_stmt, err = db.Prepare("UPDATE `replies` SET `likeCount` = `likeCount` + ? WHERE `rid` = ?") addLikesToReplyStmt, err = db.Prepare("UPDATE `replies` SET `likeCount` = `likeCount` + ? WHERE `rid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing edit_topic statement.") log.Print("Preparing editTopic statement.")
edit_topic_stmt, err = db.Prepare("UPDATE `topics` SET `title` = ?,`content` = ?,`parsed_content` = ?,`is_closed` = ? WHERE `tid` = ?") editTopicStmt, err = db.Prepare("UPDATE `topics` SET `title` = ?,`content` = ?,`parsed_content` = ?,`is_closed` = ? WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing edit_reply statement.") log.Print("Preparing editReply statement.")
edit_reply_stmt, err = db.Prepare("UPDATE `replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?") editReplyStmt, err = db.Prepare("UPDATE `replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing stick_topic statement.") log.Print("Preparing stickTopic statement.")
stick_topic_stmt, err = db.Prepare("UPDATE `topics` SET `sticky` = 1 WHERE `tid` = ?") stickTopicStmt, err = db.Prepare("UPDATE `topics` SET `sticky` = 1 WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing unstick_topic statement.") log.Print("Preparing unstickTopic statement.")
unstick_topic_stmt, err = db.Prepare("UPDATE `topics` SET `sticky` = 0 WHERE `tid` = ?") unstickTopicStmt, err = db.Prepare("UPDATE `topics` SET `sticky` = 0 WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_last_ip statement.") log.Print("Preparing updateLastIP statement.")
update_last_ip_stmt, err = db.Prepare("UPDATE `users` SET `last_ip` = ? WHERE `uid` = ?") updateLastIPStmt, err = db.Prepare("UPDATE `users` SET `last_ip` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_session statement.") log.Print("Preparing updateSession statement.")
update_session_stmt, err = db.Prepare("UPDATE `users` SET `session` = ? WHERE `uid` = ?") updateSessionStmt, err = db.Prepare("UPDATE `users` SET `session` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing set_password statement.") log.Print("Preparing setPassword statement.")
set_password_stmt, err = db.Prepare("UPDATE `users` SET `password` = ?,`salt` = ? WHERE `uid` = ?") setPasswordStmt, err = db.Prepare("UPDATE `users` SET `password` = ?,`salt` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing set_avatar statement.") log.Print("Preparing setAvatar statement.")
set_avatar_stmt, err = db.Prepare("UPDATE `users` SET `avatar` = ? WHERE `uid` = ?") setAvatarStmt, err = db.Prepare("UPDATE `users` SET `avatar` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing set_username statement.") log.Print("Preparing setUsername statement.")
set_username_stmt, err = db.Prepare("UPDATE `users` SET `name` = ? WHERE `uid` = ?") setUsernameStmt, err = db.Prepare("UPDATE `users` SET `name` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing change_group statement.") log.Print("Preparing changeGroup statement.")
change_group_stmt, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?") changeGroupStmt, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing activate_user statement.") log.Print("Preparing activateUser statement.")
activate_user_stmt, err = db.Prepare("UPDATE `users` SET `active` = 1 WHERE `uid` = ?") activateUserStmt, err = db.Prepare("UPDATE `users` SET `active` = 1 WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_user_level statement.") log.Print("Preparing updateUserLevel statement.")
update_user_level_stmt, err = db.Prepare("UPDATE `users` SET `level` = ? WHERE `uid` = ?") updateUserLevelStmt, err = db.Prepare("UPDATE `users` SET `level` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing increment_user_score statement.") log.Print("Preparing incrementUserScore statement.")
increment_user_score_stmt, err = db.Prepare("UPDATE `users` SET `score` = `score` + ? WHERE `uid` = ?") incrementUserScoreStmt, err = db.Prepare("UPDATE `users` SET `score` = `score` + ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing increment_user_posts statement.") log.Print("Preparing incrementUserPosts statement.")
increment_user_posts_stmt, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ? WHERE `uid` = ?") incrementUserPostsStmt, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing increment_user_bigposts statement.") log.Print("Preparing incrementUserBigposts statement.")
increment_user_bigposts_stmt, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ? WHERE `uid` = ?") incrementUserBigpostsStmt, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing increment_user_megaposts statement.") log.Print("Preparing incrementUserMegaposts statement.")
increment_user_megaposts_stmt, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ?,`megaposts` = `megaposts` + ? WHERE `uid` = ?") incrementUserMegapostsStmt, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ?,`megaposts` = `megaposts` + ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing increment_user_topics statement.") log.Print("Preparing incrementUserTopics statement.")
increment_user_topics_stmt, err = db.Prepare("UPDATE `users` SET `topics` = `topics` + ? WHERE `uid` = ?") incrementUserTopicsStmt, err = db.Prepare("UPDATE `users` SET `topics` = `topics` + ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing edit_profile_reply statement.") log.Print("Preparing editProfileReply statement.")
edit_profile_reply_stmt, err = db.Prepare("UPDATE `users_replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?") editProfileReplyStmt, err = db.Prepare("UPDATE `users_replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_forum statement.") log.Print("Preparing updateForum statement.")
update_forum_stmt, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?") updateForumStmt, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_setting statement.") log.Print("Preparing updateSetting statement.")
update_setting_stmt, err = db.Prepare("UPDATE `settings` SET `content` = ? WHERE `name` = ?") updateSettingStmt, err = db.Prepare("UPDATE `settings` SET `content` = ? WHERE `name` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_plugin statement.") log.Print("Preparing updatePlugin statement.")
update_plugin_stmt, err = db.Prepare("UPDATE `plugins` SET `active` = ? WHERE `uname` = ?") updatePluginStmt, err = db.Prepare("UPDATE `plugins` SET `active` = ? WHERE `uname` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_plugin_install statement.") log.Print("Preparing updatePluginInstall statement.")
update_plugin_install_stmt, err = db.Prepare("UPDATE `plugins` SET `installed` = ? WHERE `uname` = ?") updatePluginInstallStmt, err = db.Prepare("UPDATE `plugins` SET `installed` = ? WHERE `uname` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_theme statement.") log.Print("Preparing updateTheme statement.")
update_theme_stmt, err = db.Prepare("UPDATE `themes` SET `default` = ? WHERE `uname` = ?") updateThemeStmt, err = db.Prepare("UPDATE `themes` SET `default` = ? WHERE `uname` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_user statement.") log.Print("Preparing updateUser statement.")
update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ?") updateUserStmt, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_group_perms statement.") log.Print("Preparing updateGroupPerms statement.")
update_group_perms_stmt, err = db.Prepare("UPDATE `users_groups` SET `permissions` = ? WHERE `gid` = ?") updateGroupPermsStmt, err = db.Prepare("UPDATE `users_groups` SET `permissions` = ? WHERE `gid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_group_rank statement.") log.Print("Preparing updateGroupRank statement.")
update_group_rank_stmt, err = db.Prepare("UPDATE `users_groups` SET `is_admin` = ?,`is_mod` = ?,`is_banned` = ? WHERE `gid` = ?") updateGroupRankStmt, err = db.Prepare("UPDATE `users_groups` SET `is_admin` = ?,`is_mod` = ?,`is_banned` = ? WHERE `gid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_group statement.") log.Print("Preparing updateGroup statement.")
update_group_stmt, err = db.Prepare("UPDATE `users_groups` SET `name` = ?,`tag` = ? WHERE `gid` = ?") updateGroupStmt, err = db.Prepare("UPDATE `users_groups` SET `name` = ?,`tag` = ? WHERE `gid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_email statement.") log.Print("Preparing updateEmail statement.")
update_email_stmt, err = db.Prepare("UPDATE `emails` SET `email` = ?,`uid` = ?,`validated` = ?,`token` = ? WHERE `email` = ?") updateEmailStmt, err = db.Prepare("UPDATE `emails` SET `email` = ?,`uid` = ?,`validated` = ?,`token` = ? WHERE `email` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing verify_email statement.") log.Print("Preparing verifyEmail statement.")
verify_email_stmt, err = db.Prepare("UPDATE `emails` SET `validated` = 1,`token` = '' WHERE `email` = ?") verifyEmailStmt, err = db.Prepare("UPDATE `emails` SET `validated` = 1,`token` = '' WHERE `email` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing set_temp_group statement.") log.Print("Preparing setTempGroup statement.")
set_temp_group_stmt, err = db.Prepare("UPDATE `users` SET `temp_group` = ? WHERE `uid` = ?") setTempGroupStmt, err = db.Prepare("UPDATE `users` SET `temp_group` = ? WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing update_word_filter statement.") log.Print("Preparing updateWordFilter statement.")
update_word_filter_stmt, err = db.Prepare("UPDATE `word_filters` SET `find` = ?,`replacement` = ? WHERE `wfid` = ?") updateWordFilterStmt, err = db.Prepare("UPDATE `word_filters` SET `find` = ?,`replacement` = ? WHERE `wfid` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing bump_sync statement.") log.Print("Preparing bumpSync statement.")
bump_sync_stmt, err = db.Prepare("UPDATE `sync` SET `last_update` = LOCALTIMESTAMP()") bumpSyncStmt, err = db.Prepare("UPDATE `sync` SET `last_update` = LOCALTIMESTAMP()")
if err != nil { if err != nil {
return err return err
} }

View File

@ -506,7 +506,7 @@ func BenchmarkQueryPreparedTopicParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
var tu TopicUser var tu TopicUser
for pb.Next() { for pb.Next() {
err := get_topic_user_stmt.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) err := getTopicUserStmt.QueryRow(1).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
if err == ErrNoRows { if err == ErrNoRows {
b.Fatal("No rows found!") b.Fatal("No rows found!")
return return

View File

@ -35,7 +35,7 @@ func NewMemoryGroupStore() *MemoryGroupStore {
func (mgs *MemoryGroupStore) LoadGroups() error { func (mgs *MemoryGroupStore) LoadGroups() error {
mgs.groups = []*Group{&Group{ID: 0, Name: "Unknown"}} mgs.groups = []*Group{&Group{ID: 0, Name: "Unknown"}}
rows, err := get_groups_stmt.Query() rows, err := getGroupsStmt.Query()
if err != nil { if err != nil {
return err return err
} }
@ -113,7 +113,7 @@ func (mgs *MemoryGroupStore) Create(groupName string, tag string, isAdmin bool,
defer groupCreateMutex.Unlock() defer groupCreateMutex.Unlock()
var permstr = "{}" var permstr = "{}"
res, err := create_group_stmt.Exec(groupName, tag, isAdmin, isMod, isBanned, permstr) res, err := createGroupStmt.Exec(groupName, tag, isAdmin, isMod, isBanned, permstr)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -163,7 +163,7 @@ func (mgs *MemoryGroupStore) Create(groupName string, tag string, isAdmin bool,
return gid, err return gid, err
} }
perms := string(permstr) perms := string(permstr)
_, err = add_forum_perms_to_group_stmt.Exec(gid, forum.ID, forum.Preset, perms) _, err = addForumPermsToGroupStmt.Exec(gid, forum.ID, forum.Preset, perms)
if err != nil { if err != nil {
return gid, err return gid, err
} }

View File

@ -173,16 +173,16 @@ config.UserCacheCapacity = 120 // The max number of users held in memory
config.TopicCacheCapacity = 200 // The max number of topics held in memory config.TopicCacheCapacity = 200 // The max number of topics held in memory
// Email // Email
config.SmtpServer = "" config.SMTPServer = ""
config.SmtpUsername = "" config.SMTPUsername = ""
config.SmtpPassword = "" config.SMTPPassword = ""
config.SmtpPort = "25" config.SMTPPort = "25"
// Misc // Misc
config.DefaultRoute = routeTopics config.DefaultRoute = routeTopics
config.DefaultGroup = 3 // Should be a setting in the database config.DefaultGroup = 3 // Should be a setting in the database
config.ActivationGroup = 5 // Should be a setting in the database config.ActivationGroup = 5 // Should be a setting in the database
config.StaffCss = "staff_post" config.StaffCSS = "staff_post"
config.UncategorisedForumVisible = true config.UncategorisedForumVisible = true
config.MinifyTemplates = true config.MinifyTemplates = true
config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features

View File

@ -128,7 +128,7 @@ func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user User) {
} }
wcount := wordCount(content) wcount := wordCount(content)
res, err := create_topic_stmt.Exec(fid, topicName, content, parseMessage(content), user.ID, ipaddress, wcount, user.ID) res, err := createTopicStmt.Exec(fid, topicName, content, parseMessage(content), user.ID, ipaddress, wcount, user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -145,7 +145,7 @@ func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = add_subscription_stmt.Exec(user.ID, lastID, "topic") _, err = addSubscriptionStmt.Exec(user.ID, lastID, "topic")
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -203,13 +203,13 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) {
} }
wcount := wordCount(content) wcount := wordCount(content)
_, err = create_reply_stmt.Exec(tid, content, parseMessage(content), ipaddress, wcount, user.ID) _, err = createReplyStmt.Exec(tid, content, parseMessage(content), ipaddress, wcount, user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = add_replies_to_topic_stmt.Exec(1, user.ID, tid) _, err = addRepliesToTopicStmt.Exec(1, user.ID, tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -220,7 +220,7 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
res, err := add_activity_stmt.Exec(user.ID, topic.CreatedBy, "reply", "topic", tid) res, err := addActivityStmt.Exec(user.ID, topic.CreatedBy, "reply", "topic", tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -231,7 +231,7 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = notify_watchers_stmt.Exec(lastID) _, err = notifyWatchersStmt.Exec(lastID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -297,7 +297,7 @@ func routeLikeTopic(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
err = has_liked_topic_stmt.QueryRow(user.ID, tid).Scan(&tid) err = hasLikedTopicStmt.QueryRow(user.ID, tid).Scan(&tid)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -316,19 +316,19 @@ func routeLikeTopic(w http.ResponseWriter, r *http.Request, user User) {
} }
score := 1 score := 1
_, err = create_like_stmt.Exec(score, tid, "topics", user.ID) _, err = createLikeStmt.Exec(score, tid, "topics", user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = add_likes_to_topic_stmt.Exec(1, tid) _, err = addLikesToTopicStmt.Exec(1, tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
res, err := add_activity_stmt.Exec(user.ID, topic.CreatedBy, "like", "topic", tid) res, err := addActivityStmt.Exec(user.ID, topic.CreatedBy, "like", "topic", tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -339,7 +339,7 @@ func routeLikeTopic(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = notify_one_stmt.Exec(topic.CreatedBy, lastID) _, err = notifyOneStmt.Exec(topic.CreatedBy, lastID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -384,7 +384,7 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
} }
var fid int var fid int
err = get_topic_fid_stmt.QueryRow(reply.ParentID).Scan(&fid) err = getTopicFIDStmt.QueryRow(reply.ParentID).Scan(&fid)
if err == ErrNoRows { if err == ErrNoRows {
PreError("The parent topic doesn't exist.", w, r) PreError("The parent topic doesn't exist.", w, r)
return return
@ -408,7 +408,7 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
err = has_liked_reply_stmt.QueryRow(user.ID, rid).Scan(&rid) err = hasLikedReplyStmt.QueryRow(user.ID, rid).Scan(&rid)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -427,19 +427,19 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
} }
score := 1 score := 1
_, err = create_like_stmt.Exec(score, rid, "replies", user.ID) _, err = createLikeStmt.Exec(score, rid, "replies", user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = add_likes_to_reply_stmt.Exec(1, rid) _, err = addLikesToReplyStmt.Exec(1, rid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
res, err := add_activity_stmt.Exec(user.ID, reply.CreatedBy, "like", "post", rid) res, err := addActivityStmt.Exec(user.ID, reply.CreatedBy, "like", "post", rid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -450,7 +450,7 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = notify_one_stmt.Exec(reply.CreatedBy, lastID) _, err = notifyOneStmt.Exec(reply.CreatedBy, lastID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -485,14 +485,14 @@ func routeProfileReplyCreate(w http.ResponseWriter, r *http.Request, user User)
return return
} }
_, err = create_profile_reply_stmt.Exec(uid, html.EscapeString(preparseMessage(r.PostFormValue("reply-content"))), parseMessage(html.EscapeString(preparseMessage(r.PostFormValue("reply-content")))), user.ID, ipaddress) _, err = createProfileReplyStmt.Exec(uid, html.EscapeString(preparseMessage(r.PostFormValue("reply-content"))), parseMessage(html.EscapeString(preparseMessage(r.PostFormValue("reply-content")))), user.ID, ipaddress)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
var userName string var userName string
err = get_user_name_stmt.QueryRow(uid).Scan(&userName) err = getUserNameStmt.QueryRow(uid).Scan(&userName)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("The profile you're trying to post on doesn't exist.", w, r, user) LocalError("The profile you're trying to post on doesn't exist.", w, r, user)
return return
@ -565,7 +565,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
return return
} }
err = get_user_name_stmt.QueryRow(userReply.ParentID).Scan(&title) err = getUserNameStmt.QueryRow(userReply.ParentID).Scan(&title)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("We weren't able to find the profile the reported post is supposed to be on", w, r, user) LocalError("We weren't able to find the profile the reported post is supposed to be on", w, r, user)
return return
@ -576,7 +576,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
title = "Profile: " + title title = "Profile: " + title
content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID) content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID)
} else if itemType == "topic" { } else if itemType == "topic" {
err = get_topic_basic_stmt.QueryRow(itemID).Scan(&title, &content) err = getTopicBasicStmt.QueryRow(itemID).Scan(&title, &content)
if err == ErrNoRows { if err == ErrNoRows {
NotFound(w, r) NotFound(w, r)
return return
@ -597,7 +597,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
} }
var count int var count int
rows, err := report_exists_stmt.Query(itemType + "_" + strconv.Itoa(itemID)) rows, err := reportExistsStmt.Query(itemType + "_" + strconv.Itoa(itemID))
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -615,7 +615,8 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
return return
} }
res, err := create_report_stmt.Exec(title, content, parseMessage(content), user.ID, itemType+"_"+strconv.Itoa(itemID)) // ? - Can we do this via the TopicStore?
res, err := createReportStmt.Exec(title, content, parseMessage(content), user.ID, itemType+"_"+strconv.Itoa(itemID))
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -627,7 +628,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
return return
} }
_, err = add_topics_to_forum_stmt.Exec(1, fid) _, err = addTopicsToForumStmt.Exec(1, fid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -681,7 +682,7 @@ func routeAccountOwnEditCriticalSubmit(w http.ResponseWriter, r *http.Request, u
newPassword := r.PostFormValue("account-new-password") newPassword := r.PostFormValue("account-new-password")
confirmPassword := r.PostFormValue("account-confirm-password") confirmPassword := r.PostFormValue("account-confirm-password")
err = get_password_stmt.QueryRow(user.ID).Scan(&realPassword, &salt) err = getPasswordStmt.QueryRow(user.ID).Scan(&realPassword, &salt)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("Your account no longer exists.", w, r, user) LocalError("Your account no longer exists.", w, r, user)
return return
@ -811,7 +812,7 @@ func routeAccountOwnEditAvatarSubmit(w http.ResponseWriter, r *http.Request, use
} }
} }
_, err = set_avatar_stmt.Exec("."+ext, strconv.Itoa(user.ID)) _, err = setAvatarStmt.Exec("."+ext, strconv.Itoa(user.ID))
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -867,7 +868,7 @@ func routeAccountOwnEditUsernameSubmit(w http.ResponseWriter, r *http.Request, u
} }
newUsername := html.EscapeString(r.PostFormValue("account-new-username")) newUsername := html.EscapeString(r.PostFormValue("account-new-username"))
_, err = set_username_stmt.Exec(newUsername, strconv.Itoa(user.ID)) _, err = setUsernameStmt.Exec(newUsername, strconv.Itoa(user.ID))
if err != nil { if err != nil {
LocalError("Unable to change the username. Does someone else already have this name?", w, r, user) LocalError("Unable to change the username. Does someone else already have this name?", w, r, user)
return return
@ -903,7 +904,7 @@ func routeAccountOwnEditEmail(w http.ResponseWriter, r *http.Request, user User)
email := Email{UserID: user.ID} email := Email{UserID: user.ID}
var emailList []interface{} var emailList []interface{}
rows, err := get_emails_by_user_stmt.Query(user.ID) rows, err := getEmailsByUserStmt.Query(user.ID)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -960,7 +961,7 @@ func routeAccountOwnEditEmailTokenSubmit(w http.ResponseWriter, r *http.Request,
email := Email{UserID: user.ID} email := Email{UserID: user.ID}
targetEmail := Email{UserID: user.ID} targetEmail := Email{UserID: user.ID}
var emailList []interface{} var emailList []interface{}
rows, err := get_emails_by_user_stmt.Query(user.ID) rows, err := getEmailsByUserStmt.Query(user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -997,7 +998,7 @@ func routeAccountOwnEditEmailTokenSubmit(w http.ResponseWriter, r *http.Request,
return return
} }
_, err = verify_email_stmt.Exec(user.Email) _, err = verifyEmailStmt.Exec(user.Email)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1005,7 +1006,7 @@ func routeAccountOwnEditEmailTokenSubmit(w http.ResponseWriter, r *http.Request,
// If Email Activation is on, then activate the account while we're here // If Email Activation is on, then activate the account while we're here
if headerVars.Settings["activation_type"] == 2 { if headerVars.Settings["activation_type"] == 2 {
_, err = activate_user_stmt.Exec(user.ID) _, err = activateUserStmt.Exec(user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return

View File

@ -4,6 +4,7 @@ import "strconv"
import "testing" import "testing"
// TODO: Generate a test database to work with rather than a live one // TODO: Generate a test database to work with rather than a live one
// TODO: We might need to refactor TestUserStore soon, as it's getting fairly complex
func TestUserStore(t *testing.T) { func TestUserStore(t *testing.T) {
if !gloinited { if !gloinited {
err := gloinit() err := gloinit()
@ -16,6 +17,7 @@ func TestUserStore(t *testing.T) {
} }
users = NewMemoryUserStore(config.UserCacheCapacity) users = NewMemoryUserStore(config.UserCacheCapacity)
users.(UserCache).Flush()
userStoreTest(t) userStoreTest(t)
users = NewSQLUserStore() users = NewSQLUserStore()
userStoreTest(t) userStoreTest(t)
@ -23,6 +25,12 @@ func TestUserStore(t *testing.T) {
func userStoreTest(t *testing.T) { func userStoreTest(t *testing.T) {
var user *User var user *User
var err error var err error
var length int
ucache, hasCache := users.(UserCache)
if hasCache && ucache.GetLength() != 0 {
t.Error("Initial ucache length isn't zero")
}
_, err = users.Get(-1) _, err = users.Get(-1)
if err == nil { if err == nil {
@ -31,6 +39,10 @@ func userStoreTest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if hasCache && ucache.GetLength() != 0 {
t.Error("There shouldn't be anything in the user cache")
}
_, err = users.Get(0) _, err = users.Get(0)
if err == nil { if err == nil {
t.Error("UID #0 shouldn't exist") t.Error("UID #0 shouldn't exist")
@ -38,6 +50,10 @@ func userStoreTest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if hasCache && ucache.GetLength() != 0 {
t.Error("There shouldn't be anything in the user cache")
}
user, err = users.Get(1) user, err = users.Get(1)
if err == ErrNoRows { if err == ErrNoRows {
t.Error("Couldn't find UID #1") t.Error("Couldn't find UID #1")
@ -49,6 +65,30 @@ func userStoreTest(t *testing.T) {
t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.") t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.")
} }
if hasCache {
length = ucache.GetLength()
if length != 1 {
t.Error("User cache length should be 1, not " + strconv.Itoa(length))
}
user, err = ucache.CacheGet(1)
if err == ErrNoRows {
t.Error("Couldn't find UID #1 in the cache")
} else if err != nil {
t.Fatal(err)
}
if user.ID != 1 {
t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.")
}
ucache.Flush()
length = ucache.GetLength()
if length != 0 {
t.Error("User cache length should be 0, not " + strconv.Itoa(length))
}
}
// TODO: Lock onto the specific error type. Is this even possible without sacrificing the detailed information in the error message? // TODO: Lock onto the specific error type. Is this even possible without sacrificing the detailed information in the error message?
var userList map[int]*User var userList map[int]*User
userList, _ = users.BulkGetMap([]int{-1}) userList, _ = users.BulkGetMap([]int{-1})
@ -56,11 +96,25 @@ func userStoreTest(t *testing.T) {
t.Error("There shouldn't be any results for UID #-1") t.Error("There shouldn't be any results for UID #-1")
} }
if hasCache {
length = ucache.GetLength()
if length != 0 {
t.Error("User cache length should be 0, not " + strconv.Itoa(length))
}
}
userList, _ = users.BulkGetMap([]int{0}) userList, _ = users.BulkGetMap([]int{0})
if len(userList) > 0 { if len(userList) > 0 {
t.Error("There shouldn't be any results for UID #0") t.Error("There shouldn't be any results for UID #0")
} }
if hasCache {
length = ucache.GetLength()
if length != 0 {
t.Error("User cache length should be 0, not " + strconv.Itoa(length))
}
}
userList, _ = users.BulkGetMap([]int{1}) userList, _ = users.BulkGetMap([]int{1})
if len(userList) == 0 { if len(userList) == 0 {
t.Error("The returned map is empty for UID #1") t.Error("The returned map is empty for UID #1")
@ -78,6 +132,26 @@ func userStoreTest(t *testing.T) {
t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.") t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.")
} }
if hasCache {
length = ucache.GetLength()
if length != 1 {
t.Error("User cache length should be 1, not " + strconv.Itoa(length))
}
user, err = ucache.CacheGet(1)
if err == ErrNoRows {
t.Error("Couldn't find UID #1 in the cache")
} else if err != nil {
t.Fatal(err)
}
if user.ID != 1 {
t.Error("user.ID does not match the requested UID. Got '" + strconv.Itoa(user.ID) + "' instead.")
}
ucache.Flush()
}
ok = users.Exists(-1) ok = users.Exists(-1)
if ok { if ok {
t.Error("UID #-1 shouldn't exist") t.Error("UID #-1 shouldn't exist")
@ -93,6 +167,13 @@ func userStoreTest(t *testing.T) {
t.Error("UID #1 should exist") t.Error("UID #1 should exist")
} }
if hasCache {
length = ucache.GetLength()
if length != 0 {
t.Error("User cache length should be 0, not " + strconv.Itoa(length))
}
}
count := users.GetGlobalCount() count := users.GetGlobalCount()
if count <= 0 { if count <= 0 {
t.Error("The number of users should be bigger than zero") t.Error("The number of users should be bigger than zero")

View File

@ -53,7 +53,7 @@ func routeEditTopic(w http.ResponseWriter, r *http.Request, user User) {
topicContent := html.EscapeString(r.PostFormValue("topic_content")) topicContent := html.EscapeString(r.PostFormValue("topic_content"))
// TODO: Move this bit to the TopicStore // TODO: Move this bit to the TopicStore
_, err = edit_topic_stmt.Exec(topicName, preparseMessage(topicContent), parseMessage(html.EscapeString(preparseMessage(topicContent))), isClosed, tid) _, err = editTopicStmt.Exec(topicName, preparseMessage(topicContent), parseMessage(html.EscapeString(preparseMessage(topicContent))), isClosed, tid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -78,12 +78,12 @@ func routeEditTopic(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = create_action_reply_stmt.Exec(tid, action, ipaddress, user.ID) _, err = createActionReplyStmt.Exec(tid, action, ipaddress, user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = add_replies_to_topic_stmt.Exec(1, user.ID, tid) _, err = addRepliesToTopicStmt.Exec(1, user.ID, tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -158,7 +158,7 @@ func routeDeleteTopic(w http.ResponseWriter, r *http.Request, user User) {
} }
// ? - We might need to add soft-delete before we can do an action reply for this // ? - We might need to add soft-delete before we can do an action reply for this
/*_, err = create_action_reply_stmt.Exec(tid,"delete",ipaddress,user.ID) /*_, err = createActionReplyStmt.Exec(tid,"delete",ipaddress,user.ID)
if err != nil { if err != nil {
InternalError(err,w) InternalError(err,w)
return return
@ -194,7 +194,8 @@ func routeStickTopic(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = stick_topic_stmt.Exec(tid) // TODO: Move this into the TopicStore?
_, err = stickTopicStmt.Exec(tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -210,7 +211,7 @@ func routeStickTopic(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = create_action_reply_stmt.Exec(tid, "stick", ipaddress, user.ID) _, err = createActionReplyStmt.Exec(tid, "stick", ipaddress, user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -250,7 +251,7 @@ func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = unstick_topic_stmt.Exec(tid) _, err = unstickTopicStmt.Exec(tid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -266,7 +267,7 @@ func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = create_action_reply_stmt.Exec(tid, "unstick", ipaddress, user.ID) _, err = createActionReplyStmt.Exec(tid, "unstick", ipaddress, user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -297,7 +298,7 @@ func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) {
} }
content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item"))) content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item")))
_, err = edit_reply_stmt.Exec(content, parseMessage(content), rid) _, err = editReplyStmt.Exec(content, parseMessage(content), rid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -305,14 +306,14 @@ func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) {
// Get the Reply ID.. // Get the Reply ID..
var tid int var tid int
err = get_reply_tid_stmt.QueryRow(rid).Scan(&tid) err = getReplyTIDStmt.QueryRow(rid).Scan(&tid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
} }
var fid int var fid int
err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) err = getTopicFIDStmt.QueryRow(tid).Scan(&fid)
if err == ErrNoRows { if err == ErrNoRows {
PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs) PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
return return
@ -363,7 +364,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) {
} }
var fid int var fid int
err = get_topic_fid_stmt.QueryRow(reply.ParentID).Scan(&fid) err = getTopicFIDStmt.QueryRow(reply.ParentID).Scan(&fid)
if err == ErrNoRows { if err == ErrNoRows {
PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs) PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
return return
@ -382,7 +383,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = delete_reply_stmt.Exec(rid) _, err = deleteReplyStmt.Exec(rid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -406,7 +407,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
} }
_, err = remove_replies_from_topic_stmt.Exec(1, reply.ParentID) _, err = removeRepliesFromTopicStmt.Exec(1, reply.ParentID)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
} }
@ -445,7 +446,7 @@ func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user Us
// Get the Reply ID.. // Get the Reply ID..
var uid int var uid int
err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid) err = getUserReplyUIDStmt.QueryRow(rid).Scan(&uid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -457,7 +458,7 @@ func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user Us
} }
content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item"))) content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item")))
_, err = edit_profile_reply_stmt.Exec(content, parseMessage(content), rid) _, err = editProfileReplyStmt.Exec(content, parseMessage(content), rid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -485,7 +486,7 @@ func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user
} }
var uid int var uid int
err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid) err = getUserReplyUIDStmt.QueryRow(rid).Scan(&uid)
if err == ErrNoRows { if err == ErrNoRows {
LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs) LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs)
return return
@ -499,7 +500,7 @@ func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user
return return
} }
_, err = delete_profile_reply_stmt.Exec(rid) _, err = deleteProfileReplyStmt.Exec(rid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -527,7 +528,7 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) {
var uid int var uid int
var reqUserList = make(map[int]bool) var reqUserList = make(map[int]bool)
rows, err := find_users_by_ip_users_stmt.Query(ip) rows, err := findUsersByIPUsersStmt.Query(ip)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -548,7 +549,7 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
rows2, err := find_users_by_ip_topics_stmt.Query(ip) rows2, err := findUsersByIPTopicsStmt.Query(ip)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -569,7 +570,7 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
rows3, err := find_users_by_ip_replies_stmt.Query(ip) rows3, err := findUsersByIPRepliesStmt.Query(ip)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -821,7 +822,7 @@ func routeActivate(w http.ResponseWriter, r *http.Request, user User) {
} }
var active bool var active bool
err = get_user_active_stmt.QueryRow(uid).Scan(&active) err = getUserActiveStmt.QueryRow(uid).Scan(&active)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("The account you're trying to activate no longer exists.", w, r, user) LocalError("The account you're trying to activate no longer exists.", w, r, user)
return return
@ -834,13 +835,13 @@ func routeActivate(w http.ResponseWriter, r *http.Request, user User) {
LocalError("The account you're trying to activate has already been activated.", w, r, user) LocalError("The account you're trying to activate has already been activated.", w, r, user)
return return
} }
_, err = activate_user_stmt.Exec(uid) _, err = activateUserStmt.Exec(uid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = change_group_stmt.Exec(config.DefaultGroup, uid) _, err = changeGroupStmt.Exec(config.DefaultGroup, uid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return

View File

@ -1,6 +1,11 @@
// +build !pgsql !sqlite !mssql // +build !pgsql !sqlite !mssql
/* Copyright Azareal 2016 - 2018 */ /*
*
* Gosora MySQL Interface
* Copyright Azareal 2016 - 2018
*
*/
package main package main
import "log" import "log"
@ -11,15 +16,15 @@ import _ "github.com/go-sql-driver/mysql"
import "./query_gen/lib" import "./query_gen/lib"
var dbCollation = "utf8mb4_general_ci" var dbCollation = "utf8mb4_general_ci"
var get_activity_feed_by_watcher_stmt *sql.Stmt var getActivityFeedByWatcherStmt *sql.Stmt
var get_activity_count_by_watcher_stmt *sql.Stmt var getActivityCountByWatcherStmt *sql.Stmt
var todays_post_count_stmt *sql.Stmt var todaysPostCountStmt *sql.Stmt
var todays_topic_count_stmt *sql.Stmt var todaysTopicCountStmt *sql.Stmt
var todays_report_count_stmt *sql.Stmt var todaysReportCountStmt *sql.Stmt
var todays_newuser_count_stmt *sql.Stmt var todaysNewUserCountStmt *sql.Stmt
var find_users_by_ip_users_stmt *sql.Stmt var findUsersByIPUsersStmt *sql.Stmt
var find_users_by_ip_topics_stmt *sql.Stmt var findUsersByIPTopicsStmt *sql.Stmt
var find_users_by_ip_replies_stmt *sql.Stmt var findUsersByIPRepliesStmt *sql.Stmt
func init() { func init() {
dbAdapter = "mysql" dbAdapter = "mysql"
@ -68,54 +73,54 @@ func _initDatabase() (err error) {
// TODO: Is there a less noisy way of doing this for tests? // TODO: Is there a less noisy way of doing this for tests?
log.Print("Preparing get_activity_feed_by_watcher statement.") log.Print("Preparing get_activity_feed_by_watcher statement.")
get_activity_feed_by_watcher_stmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8") getActivityFeedByWatcherStmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing get_activity_count_by_watcher statement.") log.Print("Preparing get_activity_count_by_watcher statement.")
get_activity_count_by_watcher_stmt, err = db.Prepare("SELECT count(*) FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ?") getActivityCountByWatcherStmt, err = db.Prepare("SELECT count(*) FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_post_count statement.") log.Print("Preparing todays_post_count statement.")
todays_post_count_stmt, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()") todaysPostCountStmt, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_topic_count statement.") log.Print("Preparing todays_topic_count statement.")
todays_topic_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()") todaysTopicCountStmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_report_count statement.") log.Print("Preparing todays_report_count statement.")
todays_report_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp() and parentID = 1") todaysReportCountStmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp() and parentID = 1")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_newuser_count statement.") log.Print("Preparing todays_newuser_count statement.")
todays_newuser_count_stmt, err = db.Prepare("select count(*) from users where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()") todaysNewUserCountStmt, err = db.Prepare("select count(*) from users where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing find_users_by_ip_users statement.") log.Print("Preparing find_users_by_ip_users statement.")
find_users_by_ip_users_stmt, err = db.Prepare("select uid from users where last_ip = ?") findUsersByIPUsersStmt, err = db.Prepare("select uid from users where last_ip = ?")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing find_users_by_ip_topics statement.") log.Print("Preparing find_users_by_ip_topics statement.")
find_users_by_ip_topics_stmt, err = db.Prepare("select uid from users where uid in(select createdBy from topics where ipaddress = ?)") findUsersByIPTopicsStmt, err = db.Prepare("select uid from users where uid in(select createdBy from topics where ipaddress = ?)")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing find_users_by_ip_replies statement.") log.Print("Preparing find_users_by_ip_replies statement.")
find_users_by_ip_replies_stmt, err = db.Prepare("select uid from users where uid in(select createdBy from replies where ipaddress = ?)") findUsersByIPRepliesStmt, err = db.Prepare("select uid from users where uid in(select createdBy from replies where ipaddress = ?)")
return err return err
} }

View File

@ -60,7 +60,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
} }
var postCount int var postCount int
err = todays_post_count_stmt.QueryRow().Scan(&postCount) err = todaysPostCountStmt.QueryRow().Scan(&postCount)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -77,7 +77,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
} }
var topicCount int var topicCount int
err = todays_topic_count_stmt.QueryRow().Scan(&topicCount) err = todaysTopicCountStmt.QueryRow().Scan(&topicCount)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -94,7 +94,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
} }
var reportCount int var reportCount int
err = todays_report_count_stmt.QueryRow().Scan(&reportCount) err = todaysReportCountStmt.QueryRow().Scan(&reportCount)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -102,7 +102,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
var reportInterval = "week" var reportInterval = "week"
var newUserCount int var newUserCount int
err = todays_newuser_count_stmt.QueryRow().Scan(&newUserCount) err = todaysNewUserCountStmt.QueryRow().Scan(&newUserCount)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -440,7 +440,7 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
} }
forumUpdateMutex.Lock() forumUpdateMutex.Lock()
_, err = update_forum_stmt.Exec(forumName, forumDesc, active, forumPreset, fid) _, err = updateForumStmt.Exec(forumName, forumDesc, active, forumPreset, fid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -531,13 +531,13 @@ func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
return return
} }
_, err = add_forum_perms_to_group_stmt.Exec(gid, fid, permPreset, perms) _, err = addForumPermsToGroupStmt.Exec(gid, fid, permPreset, perms)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
} }
_, err = update_forum_stmt.Exec(forum.Name, forum.Desc, forum.Active, "", fid) _, err = updateForumStmt.Exec(forum.Name, forum.Desc, forum.Active, "", fid)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -564,7 +564,7 @@ func routePanelSettings(w http.ResponseWriter, r *http.Request, user User) {
//log.Print("headerVars.Settings",headerVars.Settings) //log.Print("headerVars.Settings",headerVars.Settings)
var settingList = make(map[string]interface{}) var settingList = make(map[string]interface{})
rows, err := get_settings_stmt.Query() rows, err := getSettingsStmt.Query()
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -628,7 +628,7 @@ func routePanelSetting(w http.ResponseWriter, r *http.Request, user User, sname
} }
setting := Setting{sname, "", "", ""} setting := Setting{sname, "", "", ""}
err := get_setting_stmt.QueryRow(setting.Name).Scan(&setting.Content, &setting.Type) err := getSettingStmt.QueryRow(setting.Name).Scan(&setting.Content, &setting.Type)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("The setting you want to edit doesn't exist.", w, r, user) LocalError("The setting you want to edit doesn't exist.", w, r, user)
return return
@ -691,7 +691,7 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user User, sn
var stype, sconstraints string var stype, sconstraints string
scontent := r.PostFormValue("setting-value") scontent := r.PostFormValue("setting-value")
err = get_full_setting_stmt.QueryRow(sname).Scan(&sname, &stype, &sconstraints) err = getFullSettingStmt.QueryRow(sname).Scan(&sname, &stype, &sconstraints)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("The setting you want to edit doesn't exist.", w, r, user) LocalError("The setting you want to edit doesn't exist.", w, r, user)
return return
@ -708,7 +708,8 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user User, sn
} }
} }
_, err = update_setting_stmt.Exec(scontent, sname) // TODO: Make this a method or function?
_, err = updateSettingStmt.Exec(scontent, sname)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -773,7 +774,7 @@ func routePanelWordFiltersCreate(w http.ResponseWriter, r *http.Request, user Us
// Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement // Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement
replacement := strings.TrimSpace(r.PostFormValue("replacement")) replacement := strings.TrimSpace(r.PostFormValue("replacement"))
res, err := create_word_filter_stmt.Exec(find, replacement) res, err := createWordFilterStmt.Exec(find, replacement)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -845,7 +846,7 @@ func routePanelWordFiltersEditSubmit(w http.ResponseWriter, r *http.Request, use
// Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement // Unlike with find, it's okay if we leave this blank, as this means that the admin wants to remove the word entirely with no replacement
replacement := strings.TrimSpace(r.PostFormValue("replacement")) replacement := strings.TrimSpace(r.PostFormValue("replacement"))
_, err = update_word_filter_stmt.Exec(find, replacement, id) _, err = updateWordFilterStmt.Exec(find, replacement, id)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -881,7 +882,7 @@ func routePanelWordFiltersDeleteSubmit(w http.ResponseWriter, r *http.Request, u
return return
} }
_, err = delete_word_filter_stmt.Exec(id) _, err = deleteWordFilterStmt.Exec(id)
if err != nil { if err != nil {
InternalErrorJSQ(err, w, r, isJs) InternalErrorJSQ(err, w, r, isJs)
return return
@ -950,7 +951,7 @@ func routePanelPluginsActivate(w http.ResponseWriter, r *http.Request, user User
} }
var active bool var active bool
err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) err := isPluginActiveStmt.QueryRow(uname).Scan(&active)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -972,15 +973,15 @@ func routePanelPluginsActivate(w http.ResponseWriter, r *http.Request, user User
LocalError("The plugin is already active", w, r, user) LocalError("The plugin is already active", w, r, user)
return return
} }
//log.Print("update_plugin") //log.Print("updatePlugin")
_, err = update_plugin_stmt.Exec(1, uname) _, err = updatePluginStmt.Exec(1, uname)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
} else { } else {
//log.Print("add_plugin") //log.Print("addPlugin")
_, err := add_plugin_stmt.Exec(uname, 1, 0) _, err := addPluginStmt.Exec(uname, 1, 0)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1021,7 +1022,7 @@ func routePanelPluginsDeactivate(w http.ResponseWriter, r *http.Request, user Us
} }
var active bool var active bool
err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) err := isPluginActiveStmt.QueryRow(uname).Scan(&active)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("The plugin you're trying to deactivate isn't active", w, r, user) LocalError("The plugin you're trying to deactivate isn't active", w, r, user)
return return
@ -1034,7 +1035,7 @@ func routePanelPluginsDeactivate(w http.ResponseWriter, r *http.Request, user Us
LocalError("The plugin you're trying to deactivate isn't active", w, r, user) LocalError("The plugin you're trying to deactivate isn't active", w, r, user)
return return
} }
_, err = update_plugin_stmt.Exec(0, uname) _, err = updatePluginStmt.Exec(0, uname)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1078,7 +1079,7 @@ func routePanelPluginsInstall(w http.ResponseWriter, r *http.Request, user User,
} }
var active bool var active bool
err := is_plugin_active_stmt.QueryRow(uname).Scan(&active) err := isPluginActiveStmt.QueryRow(uname).Scan(&active)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -1102,18 +1103,18 @@ func routePanelPluginsInstall(w http.ResponseWriter, r *http.Request, user User,
} }
if hasPlugin { if hasPlugin {
_, err = update_plugin_install_stmt.Exec(1, uname) _, err = updatePluginInstallStmt.Exec(1, uname)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = update_plugin_stmt.Exec(1, uname) _, err = updatePluginStmt.Exec(1, uname)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
} else { } else {
_, err := add_plugin_stmt.Exec(uname, 1, 1) _, err := addPluginStmt.Exec(uname, 1, 1)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1144,7 +1145,7 @@ func routePanelUsers(w http.ResponseWriter, r *http.Request, user User) {
offset, page, lastPage := pageOffset(stats.Users, page, perPage) offset, page, lastPage := pageOffset(stats.Users, page, perPage)
var userList []User var userList []User
rows, err := get_users_offset_stmt.Query(offset, perPage) rows, err := getUsersOffsetStmt.Query(offset, perPage)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1335,7 +1336,7 @@ func routePanelUsersEditSubmit(w http.ResponseWriter, r *http.Request, user User
return return
} }
_, err = update_user_stmt.Exec(newname, newemail, newgroup, targetUser.ID) _, err = updateUserStmt.Exec(newname, newemail, newgroup, targetUser.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1636,7 +1637,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
return return
} }
_, err = update_group_rank_stmt.Exec(1, 1, 0, gid) _, err = updateGroupRankStmt.Exec(1, 1, 0, gid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1650,7 +1651,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
return return
} }
_, err = update_group_rank_stmt.Exec(0, 1, 0, gid) _, err = updateGroupRankStmt.Exec(0, 1, 0, gid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1659,7 +1660,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
group.IsMod = true group.IsMod = true
group.IsBanned = false group.IsBanned = false
case "Banned": case "Banned":
_, err = update_group_rank_stmt.Exec(0, 0, 1, gid) _, err = updateGroupRankStmt.Exec(0, 0, 1, gid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1671,7 +1672,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
LocalError("You can't designate a group as a guest group.", w, r, user) LocalError("You can't designate a group as a guest group.", w, r, user)
return return
case "Member": case "Member":
_, err = update_group_rank_stmt.Exec(0, 0, 0, gid) _, err = updateGroupRankStmt.Exec(0, 0, 0, gid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1685,7 +1686,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
} }
} }
_, err = update_group_stmt.Exec(gname, gtag, gid) _, err = updateGroupStmt.Exec(gname, gtag, gid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1760,7 +1761,7 @@ func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
return return
} }
_, err = update_group_perms_stmt.Exec(pjson, gid) _, err = updateGroupPermsStmt.Exec(pjson, gid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1886,7 +1887,7 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user Use
var isDefault bool var isDefault bool
log.Print("uname", uname) log.Print("uname", uname)
err := is_theme_default_stmt.QueryRow(uname).Scan(&isDefault) err := isThemeDefaultStmt.QueryRow(uname).Scan(&isDefault)
if err != nil && err != ErrNoRows { if err != nil && err != ErrNoRows {
InternalError(err, w) InternalError(err, w)
return return
@ -1899,13 +1900,13 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user Use
LocalError("The theme is already active", w, r, user) LocalError("The theme is already active", w, r, user)
return return
} }
_, err = update_theme_stmt.Exec(1, uname) _, err = updateThemeStmt.Exec(1, uname)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
} }
} else { } else {
_, err := add_theme_stmt.Exec(uname, 1) _, err := addThemeStmt.Exec(uname, 1)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1915,7 +1916,7 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user Use
// TODO: Make this less racey // TODO: Make this less racey
changeDefaultThemeMutex.Lock() changeDefaultThemeMutex.Lock()
defaultTheme := defaultThemeBox.Load().(string) defaultTheme := defaultThemeBox.Load().(string)
_, err = update_theme_stmt.Exec(0, defaultTheme) _, err = updateThemeStmt.Exec(0, defaultTheme)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1948,7 +1949,7 @@ func routePanelLogsMod(w http.ResponseWriter, r *http.Request, user User) {
} }
var logCount int var logCount int
err := modlog_count_stmt.QueryRow().Scan(&logCount) err := modlogCountStmt.QueryRow().Scan(&logCount)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -1958,7 +1959,7 @@ func routePanelLogsMod(w http.ResponseWriter, r *http.Request, user User) {
perPage := 10 perPage := 10
offset, page, lastPage := pageOffset(logCount, page, perPage) offset, page, lastPage := pageOffset(logCount, page, perPage)
rows, err := get_modlogs_offset_stmt.Query(offset, perPage) rows, err := getModlogsOffsetStmt.Query(offset, perPage)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return

View File

@ -254,7 +254,7 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
permUpdateMutex.Lock() permUpdateMutex.Lock()
defer permUpdateMutex.Unlock() defer permUpdateMutex.Unlock()
_, err := delete_forum_perms_by_forum_stmt.Exec(fid) _, err := deleteForumPermsByForumStmt.Exec(fid)
if err != nil { if err != nil {
return err return err
} }
@ -263,7 +263,7 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
if err != nil { if err != nil {
return err return err
} }
_, err = add_forum_perms_to_forum_admins_stmt.Exec(fid, "", perms) _, err = addForumPermsToForumAdminsStmt.Exec(fid, "", perms)
if err != nil { if err != nil {
return err return err
} }
@ -272,7 +272,7 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
if err != nil { if err != nil {
return err return err
} }
_, err = add_forum_perms_to_forum_staff_stmt.Exec(fid, "", perms) _, err = addForumPermsToForumStaffStmt.Exec(fid, "", perms)
if err != nil { if err != nil {
return err return err
} }
@ -281,7 +281,7 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
if err != nil { if err != nil {
return err return err
} }
_, err = add_forum_perms_to_forum_members_stmt.Exec(fid, "", perms) _, err = addForumPermsToForumMembersStmt.Exec(fid, "", perms)
if err != nil { if err != nil {
return err return err
} }
@ -290,7 +290,7 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
if err != nil { if err != nil {
return err return err
} }
_, err = add_forum_perms_to_group_stmt.Exec(6, fid, "", perms) _, err = addForumPermsToGroupStmt.Exec(6, fid, "", perms)
if err != nil { if err != nil {
return err return err
} }
@ -380,13 +380,14 @@ func rebuildForumPermissions(fid int) error {
return nil return nil
} }
// ? - We could have buildForumPermissions and rebuildForumPermissions call a third function containing common logic?
func buildForumPermissions() error { func buildForumPermissions() error {
forums, err := fstore.GetAll() forums, err := fstore.GetAll()
if err != nil { if err != nil {
return err return err
} }
rows, err := get_forums_permissions_stmt.Query() rows, err := getForumsPermissionsStmt.Query()
if err != nil { if err != nil {
return err return err
} }

View File

@ -816,10 +816,10 @@ func (adapter *Mysql_Adapter) Write() error {
stmt := adapter.Buffer[name] stmt := adapter.Buffer[name]
// TODO: Add support for create-table? Table creation might be a little complex for Go to do outside a SQL file :( // TODO: Add support for create-table? Table creation might be a little complex for Go to do outside a SQL file :(
if stmt.Type != "create-table" { if stmt.Type != "create-table" {
stmts += "var " + name + "_stmt *sql.Stmt\n" stmts += "var " + name + "Stmt *sql.Stmt\n"
body += ` body += `
log.Print("Preparing ` + name + ` statement.") log.Print("Preparing ` + name + ` statement.")
` + name + `_stmt, err = db.Prepare("` + stmt.Contents + `") ` + name + `Stmt, err = db.Prepare("` + stmt.Contents + `")
if err != nil { if err != nil {
return err return err
} }

View File

@ -306,10 +306,10 @@ func (adapter *Pgsql_Adapter) Write() error {
stmt := adapter.Buffer[name] stmt := adapter.Buffer[name]
// TODO: Add support for create-table? Table creation might be a little complex for Go to do outside a SQL file :( // TODO: Add support for create-table? Table creation might be a little complex for Go to do outside a SQL file :(
if stmt.Type != "create-table" { if stmt.Type != "create-table" {
stmts += "var " + name + "_stmt *sql.Stmt\n" stmts += "var " + name + "Stmt *sql.Stmt\n"
body += ` body += `
log.Print("Preparing ` + name + ` statement.") log.Print("Preparing ` + name + ` statement.")
` + name + `_stmt, err = db.Prepare("` + stmt.Contents + `") ` + name + `Stmt, err = db.Prepare("` + stmt.Contents + `")
if err != nil { if err != nil {
return err return err
} }

View File

@ -195,286 +195,284 @@ func seed_tables(adapter qgen.DB_Adapter) error {
// nolint // nolint
func write_selects(adapter qgen.DB_Adapter) error { func write_selects(adapter qgen.DB_Adapter) error {
// url_prefix and url_name will be removed from this query in a later commit // url_prefix and url_name will be removed from this query in a later commit
adapter.SimpleSelect("get_user", "users", "name, group, is_super_admin, avatar, message, url_prefix, url_name, level", "uid = ?", "", "") adapter.SimpleSelect("getUser", "users", "name, group, is_super_admin, avatar, message, url_prefix, url_name, level", "uid = ?", "", "")
// Looking for get_topic? Your statement is in another castle // Looking for getTopic? Your statement is in another castle
adapter.SimpleSelect("get_reply", "replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", "") adapter.SimpleSelect("getReply", "replies", "tid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount", "rid = ?", "", "")
adapter.SimpleSelect("get_user_reply", "users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", "") adapter.SimpleSelect("getUserReply", "users_replies", "uid, content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress", "rid = ?", "", "")
adapter.SimpleSelect("get_password", "users", "password,salt", "uid = ?", "", "") adapter.SimpleSelect("getPassword", "users", "password,salt", "uid = ?", "", "")
adapter.SimpleSelect("get_settings", "settings", "name, content, type", "", "", "") adapter.SimpleSelect("getSettings", "settings", "name, content, type", "", "", "")
adapter.SimpleSelect("get_setting", "settings", "content, type", "name = ?", "", "") adapter.SimpleSelect("getSetting", "settings", "content, type", "name = ?", "", "")
adapter.SimpleSelect("get_full_setting", "settings", "name, type, constraints", "name = ?", "", "") adapter.SimpleSelect("getFullSetting", "settings", "name, type, constraints", "name = ?", "", "")
adapter.SimpleSelect("get_full_settings", "settings", "name, content, type, constraints", "", "", "") adapter.SimpleSelect("getFullSettings", "settings", "name, content, type, constraints", "", "", "")
adapter.SimpleSelect("get_groups", "users_groups", "gid, name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "", "", "") adapter.SimpleSelect("getGroups", "users_groups", "gid, name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "", "", "")
adapter.SimpleSelect("get_forums", "forums", "fid, name, desc, active, preset, parentID, parentType, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime", "", "fid ASC", "") adapter.SimpleSelect("getForums", "forums", "fid, name, desc, active, preset, parentID, parentType, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime", "", "fid ASC", "")
adapter.SimpleSelect("get_forums_permissions", "forums_permissions", "gid, fid, permissions", "", "gid ASC, fid ASC", "") adapter.SimpleSelect("getForumsPermissions", "forums_permissions", "gid, fid, permissions", "", "gid ASC, fid ASC", "")
adapter.SimpleSelect("get_plugins", "plugins", "uname, active, installed", "", "", "") adapter.SimpleSelect("getPlugins", "plugins", "uname, active, installed", "", "", "")
adapter.SimpleSelect("get_themes", "themes", "uname, default", "", "", "") adapter.SimpleSelect("getThemes", "themes", "uname, default", "", "", "")
adapter.SimpleSelect("get_widgets", "widgets", "position, side, type, active, location, data", "", "position ASC", "") adapter.SimpleSelect("getWidgets", "widgets", "position, side, type, active, location, data", "", "position ASC", "")
adapter.SimpleSelect("is_plugin_active", "plugins", "active", "uname = ?", "", "") adapter.SimpleSelect("isPluginActive", "plugins", "active", "uname = ?", "", "")
//adapter.SimpleSelect("is_plugin_installed","plugins","installed","uname = ?","","") //adapter.SimpleSelect("isPluginInstalled","plugins","installed","uname = ?","","")
adapter.SimpleSelect("get_users", "users", "uid, name, group, active, is_super_admin, avatar", "", "", "") adapter.SimpleSelect("getUsers", "users", "uid, name, group, active, is_super_admin, avatar", "", "", "")
adapter.SimpleSelect("get_users_offset", "users", "uid, name, group, active, is_super_admin, avatar", "", "", "?,?") adapter.SimpleSelect("getUsersOffset", "users", "uid, name, group, active, is_super_admin, avatar", "", "", "?,?")
adapter.SimpleSelect("get_word_filters", "word_filters", "wfid, find, replacement", "", "", "") adapter.SimpleSelect("getWordFilters", "word_filters", "wfid, find, replacement", "", "", "")
adapter.SimpleSelect("is_theme_default", "themes", "default", "uname = ?", "", "") adapter.SimpleSelect("isThemeDefault", "themes", "default", "uname = ?", "", "")
adapter.SimpleSelect("get_modlogs", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "", "", "") adapter.SimpleSelect("getModlogs", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "", "", "")
adapter.SimpleSelect("get_modlogs_offset", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "", "", "?,?") adapter.SimpleSelect("getModlogsOffset", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "", "", "?,?")
adapter.SimpleSelect("get_reply_tid", "replies", "tid", "rid = ?", "", "") adapter.SimpleSelect("getReplyTID", "replies", "tid", "rid = ?", "", "")
adapter.SimpleSelect("get_topic_fid", "topics", "parentID", "tid = ?", "", "") adapter.SimpleSelect("getTopicFID", "topics", "parentID", "tid = ?", "", "")
adapter.SimpleSelect("get_user_reply_uid", "users_replies", "uid", "rid = ?", "", "") adapter.SimpleSelect("getUserReplyUID", "users_replies", "uid", "rid = ?", "", "")
adapter.SimpleSelect("has_liked_topic", "likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'topics'", "", "") adapter.SimpleSelect("hasLikedTopic", "likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'topics'", "", "")
adapter.SimpleSelect("has_liked_reply", "likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'replies'", "", "") adapter.SimpleSelect("hasLikedReply", "likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'replies'", "", "")
adapter.SimpleSelect("get_user_name", "users", "name", "uid = ?", "", "") adapter.SimpleSelect("getUserName", "users", "name", "uid = ?", "", "")
adapter.SimpleSelect("get_user_active", "users", "active", "uid = ?", "", "") adapter.SimpleSelect("getUserActive", "users", "active", "uid = ?", "", "")
adapter.SimpleSelect("get_emails_by_user", "emails", "email, validated, token", "uid = ?", "", "") adapter.SimpleSelect("getEmailsByUser", "emails", "email, validated, token", "uid = ?", "", "")
adapter.SimpleSelect("get_topic_basic", "topics", "title, content", "tid = ?", "", "") adapter.SimpleSelect("getTopicBasic", "topics", "title, content", "tid = ?", "", "")
adapter.SimpleSelect("get_activity_entry", "activity_stream", "actor, targetUser, event, elementType, elementID", "asid = ?", "", "") adapter.SimpleSelect("getActivityEntry", "activity_stream", "actor, targetUser, event, elementType, elementID", "asid = ?", "", "")
adapter.SimpleSelect("forum_entry_exists", "forums", "fid", "name = ''", "fid ASC", "0,1") adapter.SimpleSelect("forumEntryExists", "forums", "fid", "name = ''", "fid ASC", "0,1")
adapter.SimpleSelect("group_entry_exists", "users_groups", "gid", "name = ''", "gid ASC", "0,1") adapter.SimpleSelect("groupEntryExists", "users_groups", "gid", "name = ''", "gid ASC", "0,1")
adapter.SimpleSelect("get_forum_topics_offset", "topics", "tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount", "parentID = ?", "sticky DESC, lastReplyAt DESC, createdBy DESC", "?,?") adapter.SimpleSelect("getForumTopicsOffset", "topics", "tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount", "parentID = ?", "sticky DESC, lastReplyAt DESC, createdBy DESC", "?,?")
adapter.SimpleSelect("get_expired_scheduled_groups", "users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", "") adapter.SimpleSelect("getExpiredScheduledGroups", "users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", "")
adapter.SimpleSelect("get_sync", "sync", "last_update", "", "", "") adapter.SimpleSelect("getSync", "sync", "last_update", "", "", "")
return nil return nil
} }
// nolint // nolint
func write_left_joins(adapter qgen.DB_Adapter) error { func write_left_joins(adapter qgen.DB_Adapter) error {
adapter.SimpleLeftJoin("get_topic_replies_offset", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType", "replies.createdBy = users.uid", "tid = ?", "", "?,?") adapter.SimpleLeftJoin("getTopicRepliesOffset", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress, replies.likeCount, replies.actionType", "replies.createdBy = users.uid", "tid = ?", "", "?,?")
adapter.SimpleLeftJoin("get_topic_list", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC", "") adapter.SimpleLeftJoin("getTopicList", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC", "")
adapter.SimpleLeftJoin("get_topic_user", "topics", "users", "topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level", "topics.createdBy = users.uid", "tid = ?", "", "") adapter.SimpleLeftJoin("getTopicUser", "topics", "users", "topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level", "topics.createdBy = users.uid", "tid = ?", "", "")
adapter.SimpleLeftJoin("get_topic_by_reply", "replies", "topics", "topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, topics.data", "replies.tid = topics.tid", "rid = ?", "", "") adapter.SimpleLeftJoin("getTopicByReply", "replies", "topics", "topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, topics.data", "replies.tid = topics.tid", "rid = ?", "", "")
adapter.SimpleLeftJoin("get_topic_replies", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress", "replies.createdBy = users.uid", "tid = ?", "", "") adapter.SimpleLeftJoin("getTopicReplies", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress", "replies.createdBy = users.uid", "tid = ?", "", "")
adapter.SimpleLeftJoin("get_forum_topics", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "topics.parentID = ?", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc", "") adapter.SimpleLeftJoin("getForumTopics", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "topics.parentID = ?", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc", "")
adapter.SimpleLeftJoin("get_profile_replies", "users_replies", "users", "users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group", "users_replies.createdBy = users.uid", "users_replies.uid = ?", "", "") adapter.SimpleLeftJoin("getProfileReplies", "users_replies", "users", "users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group", "users_replies.createdBy = users.uid", "users_replies.uid = ?", "", "")
return nil return nil
} }
// nolint // nolint
func write_inner_joins(adapter qgen.DB_Adapter) error { func write_inner_joins(adapter qgen.DB_Adapter) error {
adapter.SimpleInnerJoin("get_watchers", "activity_stream", "activity_subscriptions", "activity_subscriptions.user", "activity_subscriptions.targetType = activity_stream.elementType AND activity_subscriptions.targetID = activity_stream.elementID AND activity_subscriptions.user != activity_stream.actor", "asid = ?", "", "") adapter.SimpleInnerJoin("getWatchers", "activity_stream", "activity_subscriptions", "activity_subscriptions.user", "activity_subscriptions.targetType = activity_stream.elementType AND activity_subscriptions.targetID = activity_stream.elementID AND activity_subscriptions.user != activity_stream.actor", "asid = ?", "", "")
return nil return nil
} }
// nolint // nolint
func write_inserts(adapter qgen.DB_Adapter) error { func write_inserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("create_topic", "topics", "parentID,title,content,parsed_content,createdAt,lastReplyAt,lastReplyBy,ipaddress,words,createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?") adapter.SimpleInsert("createTopic", "topics", "parentID,title,content,parsed_content,createdAt,lastReplyAt,lastReplyBy,ipaddress,words,createdBy", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?")
adapter.SimpleInsert("create_report", "topics", "title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,1,'report'") adapter.SimpleInsert("createReport", "topics", "title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,1,'report'")
adapter.SimpleInsert("create_reply", "replies", "tid,content,parsed_content,createdAt,ipaddress,words,createdBy", "?,?,?,UTC_TIMESTAMP(),?,?,?") adapter.SimpleInsert("createReply", "replies", "tid,content,parsed_content,createdAt,ipaddress,words,createdBy", "?,?,?,UTC_TIMESTAMP(),?,?,?")
adapter.SimpleInsert("create_action_reply", "replies", "tid,actionType,ipaddress,createdBy", "?,?,?,?") adapter.SimpleInsert("createActionReply", "replies", "tid,actionType,ipaddress,createdBy", "?,?,?,?")
adapter.SimpleInsert("create_like", "likes", "weight, targetItem, targetType, sentBy", "?,?,?,?") adapter.SimpleInsert("createLike", "likes", "weight, targetItem, targetType, sentBy", "?,?,?,?")
adapter.SimpleInsert("add_activity", "activity_stream", "actor,targetUser,event,elementType,elementID", "?,?,?,?,?") adapter.SimpleInsert("addActivity", "activity_stream", "actor,targetUser,event,elementType,elementID", "?,?,?,?,?")
adapter.SimpleInsert("notify_one", "activity_stream_matches", "watcher,asid", "?,?") adapter.SimpleInsert("notifyOne", "activity_stream_matches", "watcher,asid", "?,?")
adapter.SimpleInsert("add_email", "emails", "email, uid, validated, token", "?,?,?,?") adapter.SimpleInsert("addEmail", "emails", "email, uid, validated, token", "?,?,?,?")
adapter.SimpleInsert("create_profile_reply", "users_replies", "uid, content, parsed_content, createdAt, createdBy, ipaddress", "?,?,?,UTC_TIMESTAMP(),?,?") adapter.SimpleInsert("createProfileReply", "users_replies", "uid, content, parsed_content, createdAt, createdBy, ipaddress", "?,?,?,UTC_TIMESTAMP(),?,?")
adapter.SimpleInsert("add_subscription", "activity_subscriptions", "user,targetID,targetType,level", "?,?,?,2") adapter.SimpleInsert("addSubscription", "activity_subscriptions", "user,targetID,targetType,level", "?,?,?,2")
adapter.SimpleInsert("create_forum", "forums", "name, desc, active, preset", "?,?,?,?") adapter.SimpleInsert("createForum", "forums", "name, desc, active, preset", "?,?,?,?")
adapter.SimpleInsert("add_forum_perms_to_forum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?") adapter.SimpleInsert("addForumPermsToForum", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?")
adapter.SimpleInsert("add_plugin", "plugins", "uname, active, installed", "?,?,?") adapter.SimpleInsert("addPlugin", "plugins", "uname, active, installed", "?,?,?")
adapter.SimpleInsert("add_theme", "themes", "uname,default", "?,?") adapter.SimpleInsert("addTheme", "themes", "uname,default", "?,?")
adapter.SimpleInsert("create_group", "users_groups", "name, tag, is_admin, is_mod, is_banned, permissions", "?,?,?,?,?,?") adapter.SimpleInsert("createGroup", "users_groups", "name, tag, is_admin, is_mod, is_banned, permissions", "?,?,?,?,?,?")
adapter.SimpleInsert("add_modlog_entry", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()") adapter.SimpleInsert("addModlogEntry", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()")
adapter.SimpleInsert("add_adminlog_entry", "administration_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()") adapter.SimpleInsert("addAdminlogEntry", "administration_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()")
adapter.SimpleInsert("create_word_filter", "word_filters", "find, replacement", "?,?") adapter.SimpleInsert("createWordFilter", "word_filters", "find, replacement", "?,?")
return nil return nil
} }
// nolint // nolint
func write_replaces(adapter qgen.DB_Adapter) error { func write_replaces(adapter qgen.DB_Adapter) error {
adapter.SimpleReplace("add_forum_perms_to_group", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?") adapter.SimpleReplace("addForumPermsToGroup", "forums_permissions", "gid,fid,preset,permissions", "?,?,?,?")
adapter.SimpleReplace("replace_schedule_group", "users_groups_scheduler", "uid, set_group, issued_by, issued_at, revert_at, temporary", "?,?,?,UTC_TIMESTAMP(),?,?") adapter.SimpleReplace("replaceScheduleGroup", "users_groups_scheduler", "uid, set_group, issued_by, issued_at, revert_at, temporary", "?,?,?,UTC_TIMESTAMP(),?,?")
return nil return nil
} }
// nolint // nolint
func write_updates(adapter qgen.DB_Adapter) error { func write_updates(adapter qgen.DB_Adapter) error {
adapter.SimpleUpdate("add_replies_to_topic", "topics", "postCount = postCount + ?, lastReplyBy = ?, lastReplyAt = UTC_TIMESTAMP()", "tid = ?") adapter.SimpleUpdate("addRepliesToTopic", "topics", "postCount = postCount + ?, lastReplyBy = ?, lastReplyAt = UTC_TIMESTAMP()", "tid = ?")
adapter.SimpleUpdate("remove_replies_from_topic", "topics", "postCount = postCount - ?", "tid = ?") adapter.SimpleUpdate("removeRepliesFromTopic", "topics", "postCount = postCount - ?", "tid = ?")
adapter.SimpleUpdate("add_topics_to_forum", "forums", "topicCount = topicCount + ?", "fid = ?") adapter.SimpleUpdate("addTopicsToForum", "forums", "topicCount = topicCount + ?", "fid = ?")
adapter.SimpleUpdate("remove_topics_from_forum", "forums", "topicCount = topicCount - ?", "fid = ?") adapter.SimpleUpdate("removeTopicsFromForum", "forums", "topicCount = topicCount - ?", "fid = ?")
adapter.SimpleUpdate("update_forum_cache", "forums", "lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = UTC_TIMESTAMP()", "fid = ?") adapter.SimpleUpdate("updateForumCache", "forums", "lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = UTC_TIMESTAMP()", "fid = ?")
adapter.SimpleUpdate("add_likes_to_topic", "topics", "likeCount = likeCount + ?", "tid = ?") adapter.SimpleUpdate("addLikesToTopic", "topics", "likeCount = likeCount + ?", "tid = ?")
adapter.SimpleUpdate("add_likes_to_reply", "replies", "likeCount = likeCount + ?", "rid = ?") adapter.SimpleUpdate("addLikesToReply", "replies", "likeCount = likeCount + ?", "rid = ?")
adapter.SimpleUpdate("edit_topic", "topics", "title = ?, content = ?, parsed_content = ?, is_closed = ?", "tid = ?") adapter.SimpleUpdate("editTopic", "topics", "title = ?, content = ?, parsed_content = ?, is_closed = ?", "tid = ?")
adapter.SimpleUpdate("edit_reply", "replies", "content = ?, parsed_content = ?", "rid = ?") adapter.SimpleUpdate("editReply", "replies", "content = ?, parsed_content = ?", "rid = ?")
adapter.SimpleUpdate("stick_topic", "topics", "sticky = 1", "tid = ?") adapter.SimpleUpdate("stickTopic", "topics", "sticky = 1", "tid = ?")
adapter.SimpleUpdate("unstick_topic", "topics", "sticky = 0", "tid = ?") adapter.SimpleUpdate("unstickTopic", "topics", "sticky = 0", "tid = ?")
adapter.SimpleUpdate("update_last_ip", "users", "last_ip = ?", "uid = ?") adapter.SimpleUpdate("updateLastIP", "users", "last_ip = ?", "uid = ?")
adapter.SimpleUpdate("update_session", "users", "session = ?", "uid = ?") adapter.SimpleUpdate("updateSession", "users", "session = ?", "uid = ?")
adapter.SimpleUpdate("set_password", "users", "password = ?, salt = ?", "uid = ?") adapter.SimpleUpdate("setPassword", "users", "password = ?, salt = ?", "uid = ?")
adapter.SimpleUpdate("set_avatar", "users", "avatar = ?", "uid = ?") adapter.SimpleUpdate("setAvatar", "users", "avatar = ?", "uid = ?")
adapter.SimpleUpdate("set_username", "users", "name = ?", "uid = ?") adapter.SimpleUpdate("setUsername", "users", "name = ?", "uid = ?")
adapter.SimpleUpdate("change_group", "users", "group = ?", "uid = ?") adapter.SimpleUpdate("changeGroup", "users", "group = ?", "uid = ?")
adapter.SimpleUpdate("activate_user", "users", "active = 1", "uid = ?") adapter.SimpleUpdate("activateUser", "users", "active = 1", "uid = ?")
adapter.SimpleUpdate("update_user_level", "users", "level = ?", "uid = ?") adapter.SimpleUpdate("updateUserLevel", "users", "level = ?", "uid = ?")
adapter.SimpleUpdate("increment_user_score", "users", "score = score + ?", "uid = ?") adapter.SimpleUpdate("incrementUserScore", "users", "score = score + ?", "uid = ?")
adapter.SimpleUpdate("increment_user_posts", "users", "posts = posts + ?", "uid = ?") adapter.SimpleUpdate("incrementUserPosts", "users", "posts = posts + ?", "uid = ?")
adapter.SimpleUpdate("increment_user_bigposts", "users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?") adapter.SimpleUpdate("incrementUserBigposts", "users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?")
adapter.SimpleUpdate("increment_user_megaposts", "users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?") adapter.SimpleUpdate("incrementUserMegaposts", "users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?")
adapter.SimpleUpdate("increment_user_topics", "users", "topics = topics + ?", "uid = ?") adapter.SimpleUpdate("incrementUserTopics", "users", "topics = topics + ?", "uid = ?")
adapter.SimpleUpdate("edit_profile_reply", "users_replies", "content = ?, parsed_content = ?", "rid = ?") adapter.SimpleUpdate("editProfileReply", "users_replies", "content = ?, parsed_content = ?", "rid = ?")
adapter.SimpleUpdate("update_forum", "forums", "name = ?, desc = ?, active = ?, preset = ?", "fid = ?") adapter.SimpleUpdate("updateForum", "forums", "name = ?, desc = ?, active = ?, preset = ?", "fid = ?")
adapter.SimpleUpdate("update_setting", "settings", "content = ?", "name = ?") adapter.SimpleUpdate("updateSetting", "settings", "content = ?", "name = ?")
adapter.SimpleUpdate("update_plugin", "plugins", "active = ?", "uname = ?") adapter.SimpleUpdate("updatePlugin", "plugins", "active = ?", "uname = ?")
adapter.SimpleUpdate("update_plugin_install", "plugins", "installed = ?", "uname = ?") adapter.SimpleUpdate("updatePluginInstall", "plugins", "installed = ?", "uname = ?")
adapter.SimpleUpdate("update_theme", "themes", "default = ?", "uname = ?") adapter.SimpleUpdate("updateTheme", "themes", "default = ?", "uname = ?")
adapter.SimpleUpdate("update_user", "users", "name = ?, email = ?, group = ?", "uid = ?") adapter.SimpleUpdate("updateUser", "users", "name = ?, email = ?, group = ?", "uid = ?")
adapter.SimpleUpdate("update_group_perms", "users_groups", "permissions = ?", "gid = ?") adapter.SimpleUpdate("updateGroupPerms", "users_groups", "permissions = ?", "gid = ?")
adapter.SimpleUpdate("update_group_rank", "users_groups", "is_admin = ?, is_mod = ?, is_banned = ?", "gid = ?") adapter.SimpleUpdate("updateGroupRank", "users_groups", "is_admin = ?, is_mod = ?, is_banned = ?", "gid = ?")
adapter.SimpleUpdate("update_group", "users_groups", "name = ?, tag = ?", "gid = ?") adapter.SimpleUpdate("updateGroup", "users_groups", "name = ?, tag = ?", "gid = ?")
adapter.SimpleUpdate("update_email", "emails", "email = ?, uid = ?, validated = ?, token = ?", "email = ?") adapter.SimpleUpdate("updateEmail", "emails", "email = ?, uid = ?, validated = ?, token = ?", "email = ?")
adapter.SimpleUpdate("verify_email", "emails", "validated = 1, token = ''", "email = ?") // Need to fix this: Empty string isn't working, it gets set to 1 instead x.x -- Has this been fixed? adapter.SimpleUpdate("verifyEmail", "emails", "validated = 1, token = ''", "email = ?") // Need to fix this: Empty string isn't working, it gets set to 1 instead x.x -- Has this been fixed?
adapter.SimpleUpdate("set_temp_group", "users", "temp_group = ?", "uid = ?") adapter.SimpleUpdate("setTempGroup", "users", "temp_group = ?", "uid = ?")
adapter.SimpleUpdate("update_word_filter", "word_filters", "find = ?, replacement = ?", "wfid = ?") adapter.SimpleUpdate("updateWordFilter", "word_filters", "find = ?, replacement = ?", "wfid = ?")
adapter.SimpleUpdate("bump_sync", "sync", "last_update = UTC_TIMESTAMP()", "") adapter.SimpleUpdate("bumpSync", "sync", "last_update = UTC_TIMESTAMP()", "")
return nil return nil
} }
// nolint // nolint
func write_deletes(adapter qgen.DB_Adapter) error { func write_deletes(adapter qgen.DB_Adapter) error {
adapter.SimpleDelete("delete_reply", "replies", "rid = ?") adapter.SimpleDelete("deleteReply", "replies", "rid = ?")
adapter.SimpleDelete("delete_topic", "topics", "tid = ?") adapter.SimpleDelete("deleteProfileReply", "users_replies", "rid = ?")
adapter.SimpleDelete("delete_profile_reply", "users_replies", "rid = ?") adapter.SimpleDelete("deleteForumPermsByForum", "forums_permissions", "fid = ?")
adapter.SimpleDelete("delete_forum_perms_by_forum", "forums_permissions", "fid = ?") adapter.SimpleDelete("deleteActivityStreamMatch", "activity_stream_matches", "watcher = ? AND asid = ?")
adapter.SimpleDelete("delete_activity_stream_match", "activity_stream_matches", "watcher = ? AND asid = ?")
//adapter.SimpleDelete("delete_activity_stream_matches_by_watcher","activity_stream_matches","watcher = ?") //adapter.SimpleDelete("delete_activity_stream_matches_by_watcher","activity_stream_matches","watcher = ?")
adapter.SimpleDelete("delete_word_filter", "word_filters", "wfid = ?") adapter.SimpleDelete("deleteWordFilter", "word_filters", "wfid = ?")
return nil return nil
} }
// nolint // nolint
func write_simple_counts(adapter qgen.DB_Adapter) error { func write_simple_counts(adapter qgen.DB_Adapter) error {
adapter.SimpleCount("report_exists", "topics", "data = ? AND data != '' AND parentID = 1", "") adapter.SimpleCount("reportExists", "topics", "data = ? AND data != '' AND parentID = 1", "")
adapter.SimpleCount("group_count", "users_groups", "", "") adapter.SimpleCount("groupCount", "users_groups", "", "")
adapter.SimpleCount("modlog_count", "moderation_logs", "", "") adapter.SimpleCount("modlogCount", "moderation_logs", "", "")
return nil return nil
} }
// nolint // nolint
func write_insert_selects(adapter qgen.DB_Adapter) error { func write_insert_selects(adapter qgen.DB_Adapter) error {
adapter.SimpleInsertSelect("add_forum_perms_to_forum_admins", adapter.SimpleInsertSelect("addForumPermsToForumAdmins",
qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""}, qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""},
qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 1", "", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 1", "", ""},
) )
adapter.SimpleInsertSelect("add_forum_perms_to_forum_staff", adapter.SimpleInsertSelect("addForumPermsToForumStaff",
qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""}, qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""},
qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 1", "", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 1", "", ""},
) )
adapter.SimpleInsertSelect("add_forum_perms_to_forum_members", adapter.SimpleInsertSelect("addForumPermsToForumMembers",
qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""}, qgen.DB_Insert{"forums_permissions", "gid,fid,preset,permissions", ""},
qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""}, qgen.DB_Select{"users_groups", "gid, ? AS fid, ? AS preset, ? AS permissions", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""},
) )
@ -489,7 +487,7 @@ func write_insert_left_joins(adapter qgen.DB_Adapter) error {
// nolint // nolint
func write_insert_inner_joins(adapter qgen.DB_Adapter) error { func write_insert_inner_joins(adapter qgen.DB_Adapter) error {
adapter.SimpleInsertInnerJoin("notify_watchers", adapter.SimpleInsertInnerJoin("notifyWatchers",
qgen.DB_Insert{"activity_stream_matches", "watcher, asid", ""}, qgen.DB_Insert{"activity_stream_matches", "watcher, asid", ""},
qgen.DB_Join{"activity_stream", "activity_subscriptions", "activity_subscriptions.user, activity_stream.asid", "activity_subscriptions.targetType = activity_stream.elementType AND activity_subscriptions.targetID = activity_stream.elementID AND activity_subscriptions.user != activity_stream.actor", "asid = ?", "", ""}, qgen.DB_Join{"activity_stream", "activity_subscriptions", "activity_subscriptions.user, activity_stream.asid", "activity_subscriptions.targetType = activity_stream.elementType AND activity_subscriptions.targetID = activity_stream.elementID AND activity_subscriptions.user != activity_stream.actor", "asid = ?", "", ""},
) )

View File

@ -53,12 +53,12 @@ type ReplyShort struct {
func getReply(id int) (*ReplyShort, error) { func getReply(id int) (*ReplyShort, error) {
reply := ReplyShort{ID: id} reply := ReplyShort{ID: id}
err := get_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress, &reply.LikeCount) err := getReplyStmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress, &reply.LikeCount)
return &reply, err return &reply, err
} }
func getUserReply(id int) (*ReplyShort, error) { func getUserReply(id int) (*ReplyShort, error) {
reply := ReplyShort{ID: id} reply := ReplyShort{ID: id}
err := get_user_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress) err := getUserReplyStmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IPAddress)
return &reply, err return &reply, err
} }

View File

@ -33,6 +33,7 @@ func init() {
hvars = &HeaderVars{Site: site} hvars = &HeaderVars{Site: site}
} }
// HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS
type HTTPSRedirect struct { type HTTPSRedirect struct {
} }
@ -307,7 +308,7 @@ func routeForum(w http.ResponseWriter, r *http.Request, user User, sfid string)
} else { } else {
page = 1 page = 1
} }
rows, err := get_forum_topics_offset_stmt.Query(fid, offset, config.ItemsPerPage) rows, err := getForumTopicsOffsetStmt.Query(fid, offset, config.ItemsPerPage)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -461,6 +462,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
topic.ClassName = "" topic.ClassName = ""
//log.Printf("topic: %+v\n", topic)
headerVars, ok := ForumUserCheck(w, r, &user, topic.ParentID) headerVars, ok := ForumUserCheck(w, r, &user, topic.ParentID)
if !ok { if !ok {
@ -490,7 +492,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
topic.Tag = postGroup.Tag topic.Tag = postGroup.Tag
if postGroup.IsMod || postGroup.IsAdmin { if postGroup.IsMod || postGroup.IsAdmin {
topic.ClassName = config.StaffCss topic.ClassName = config.StaffCSS
} }
/*if headerVars.Settings["url_tags"] == false { /*if headerVars.Settings["url_tags"] == false {
@ -509,6 +511,15 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
topic.CreatedAt = "" topic.CreatedAt = ""
} }
// TODO: Make a function for this? Build a more sophisticated noavatar handling system?
if topic.Avatar != "" {
if topic.Avatar[0] == '.' {
topic.Avatar = "/uploads/avatar_" + strconv.Itoa(topic.CreatedBy) + topic.Avatar
}
} else {
topic.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(topic.CreatedBy), 1)
}
// Calculate the offset // Calculate the offset
lastPage := (topic.PostCount / config.ItemsPerPage) + 1 lastPage := (topic.PostCount / config.ItemsPerPage) + 1
if page > 1 { if page > 1 {
@ -521,7 +532,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
} }
// Get the replies.. // Get the replies..
rows, err := get_topic_replies_offset_stmt.Query(topic.ID, offset, config.ItemsPerPage) rows, err := getTopicRepliesOffsetStmt.Query(topic.ID, offset, config.ItemsPerPage)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.", w, r, user) LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.", w, r, user)
return return
@ -551,11 +562,12 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
} }
if postGroup.IsMod || postGroup.IsAdmin { if postGroup.IsMod || postGroup.IsAdmin {
replyItem.ClassName = config.StaffCss replyItem.ClassName = config.StaffCSS
} else { } else {
replyItem.ClassName = "" replyItem.ClassName = ""
} }
// TODO: Make a function for this? Build a more sophisticated noavatar handling system?
if replyItem.Avatar != "" { if replyItem.Avatar != "" {
if replyItem.Avatar[0] == '.' { if replyItem.Avatar[0] == '.' {
replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar
@ -665,7 +677,7 @@ func routeProfile(w http.ResponseWriter, r *http.Request, user User) {
} }
// Get the replies.. // Get the replies..
rows, err := get_profile_replies_stmt.Query(puser.ID) rows, err := getProfileRepliesStmt.Query(puser.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -687,7 +699,7 @@ func routeProfile(w http.ResponseWriter, r *http.Request, user User) {
replyLines = strings.Count(replyContent, "\n") replyLines = strings.Count(replyContent, "\n")
if group.IsMod || group.IsAdmin { if group.IsMod || group.IsAdmin {
replyClassName = config.StaffCss replyClassName = config.StaffCSS
} else { } else {
replyClassName = "" replyClassName = ""
} }
@ -893,7 +905,7 @@ func routeRegisterSubmit(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w) InternalError(err, w)
return return
} }
_, err = add_email_stmt.Exec(email, uid, 0, token) _, err = addEmailStmt.Exec(email, uid, 0, token)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -981,7 +993,7 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = delete_activity_stream_match_stmt.Exec(user.ID, asid) _, err = deleteActivityStreamMatchStmt.Exec(user.ID, asid)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return return
@ -996,7 +1008,7 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user User) {
var asid, actorID, targetUserID, elementID int var asid, actorID, targetUserID, elementID int
var msgCount int var msgCount int
err = get_activity_count_by_watcher_stmt.QueryRow(user.ID).Scan(&msgCount) err = getActivityCountByWatcherStmt.QueryRow(user.ID).Scan(&msgCount)
if err == ErrNoRows { if err == ErrNoRows {
PreErrorJS("Couldn't find the parent topic", w, r) PreErrorJS("Couldn't find the parent topic", w, r)
return return
@ -1005,7 +1017,7 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID) rows, err := getActivityFeedByWatcherStmt.Query(user.ID)
if err != nil { if err != nil {
InternalErrorJS(err, w, r) InternalErrorJS(err, w, r)
return return

View File

@ -180,7 +180,7 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerV
} }
} }
err = group_count_stmt.QueryRow().Scan(&stats.Groups) err = groupCountStmt.QueryRow().Scan(&stats.Groups)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return headerVars, stats, false return headerVars, stats, false
@ -307,7 +307,7 @@ func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
return *user, false return *user, false
} }
if host != user.LastIP { if host != user.LastIP {
_, err = update_last_ip_stmt.Exec(host, user.ID) _, err = updateLastIPStmt.Exec(host, user.ID)
if err != nil { if err != nil {
InternalError(err, w) InternalError(err, w)
return *user, false return *user, false

View File

@ -27,7 +27,7 @@ func init() {
} }
func LoadSettings() error { func LoadSettings() error {
rows, err := get_full_settings_stmt.Query() rows, err := getFullSettingsStmt.Query()
if err != nil { if err != nil {
return err return err
} }

10
site.go
View File

@ -35,15 +35,15 @@ type Config struct {
UserCacheCapacity int UserCacheCapacity int
TopicCacheCapacity int TopicCacheCapacity int
SmtpServer string SMTPServer string
SmtpUsername string SMTPUsername string
SmtpPassword string SMTPPassword string
SmtpPort string SMTPPort string
DefaultRoute func(http.ResponseWriter, *http.Request, User) DefaultRoute func(http.ResponseWriter, *http.Request, User)
DefaultGroup int DefaultGroup int
ActivationGroup int ActivationGroup int
StaffCss string // ? - Move this into the settings table? Might be better to implement this as Group CSS StaffCSS string // ? - Move this into the settings table? Might be better to implement this as Group CSS
UncategorisedForumVisible bool UncategorisedForumVisible bool
MinifyTemplates bool MinifyTemplates bool
MultiServer bool MultiServer bool

View File

@ -15,7 +15,7 @@ func init() {
} }
func handleExpiredScheduledGroups() error { func handleExpiredScheduledGroups() error {
rows, err := get_expired_scheduled_groups_stmt.Query() rows, err := getExpiredScheduledGroupsStmt.Query()
if err != nil { if err != nil {
return err return err
} }
@ -27,11 +27,11 @@ func handleExpiredScheduledGroups() error {
if err != nil { if err != nil {
return err return err
} }
_, err = replace_schedule_group_stmt.Exec(uid, 0, 0, time.Now(), false) _, err = replaceScheduleGroupStmt.Exec(uid, 0, 0, time.Now(), false)
if err != nil { if err != nil {
return err return err
} }
_, err = set_temp_group_stmt.Exec(0, uid) _, err = setTempGroupStmt.Exec(0, uid)
if err != nil { if err != nil {
return err return err
} }
@ -43,13 +43,12 @@ func handleExpiredScheduledGroups() error {
func handleServerSync() error { func handleServerSync() error {
var lastUpdate time.Time var lastUpdate time.Time
var lastUpdateStr string var lastUpdateStr string
err := get_sync_stmt.QueryRow().Scan(&lastUpdateStr) err := getSyncStmt.QueryRow().Scan(&lastUpdateStr)
if err != nil { if err != nil {
return err return err
} }
layout := "2006-01-02 15:04:05" lastUpdate, err = time.Parse("2006-01-02 15:04:05", lastUpdateStr)
lastUpdate, err = time.Parse(layout, lastUpdateStr)
if err != nil { if err != nil {
return err return err
} }

View File

@ -349,14 +349,14 @@ var topic_alt_40 = []byte(`
var topic_alt_41 = []byte(`?session=`) var topic_alt_41 = []byte(`?session=`)
var topic_alt_42 = []byte(`&type=topic" class="action_button report_item">Report</a> var topic_alt_42 = []byte(`&type=topic" class="action_button report_item">Report</a>
`) `)
var topic_alt_43 = []byte(`<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">`) var topic_alt_43 = []byte(`<a class="action_button action_button_right like_count hide_on_micro">`)
var topic_alt_44 = []byte(`</a>`) var topic_alt_44 = []byte(` up</a>`)
var topic_alt_45 = []byte(` var topic_alt_45 = []byte(`
<a class="action_button action_button_right hide_on_mobile">`) <a class="action_button action_button_right created_at hide_on_mobile">`)
var topic_alt_46 = []byte(`</a> var topic_alt_46 = []byte(`</a>
`) `)
var topic_alt_47 = []byte(`<a class="action_button action_button_right hide_on_micro">`) var topic_alt_47 = []byte(`<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">`)
var topic_alt_48 = []byte(` up</a>`) var topic_alt_48 = []byte(`</a>`)
var topic_alt_49 = []byte(` var topic_alt_49 = []byte(`
</div> </div>
</div><div style="clear:both;"></div> </div><div style="clear:both;"></div>
@ -405,14 +405,14 @@ var topic_alt_74 = []byte(`
var topic_alt_75 = []byte(`?session=`) var topic_alt_75 = []byte(`?session=`)
var topic_alt_76 = []byte(`&type=reply" class="action_button report_item">Report</a> var topic_alt_76 = []byte(`&type=reply" class="action_button report_item">Report</a>
`) `)
var topic_alt_77 = []byte(`<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">`) var topic_alt_77 = []byte(`<a class="action_button action_button_right like_count hide_on_micro">`)
var topic_alt_78 = []byte(`</a>`) var topic_alt_78 = []byte(` up</a>`)
var topic_alt_79 = []byte(` var topic_alt_79 = []byte(`
<a class="action_button action_button_right hide_on_mobile">`) <a class="action_button action_button_right created_at hide_on_mobile">`)
var topic_alt_80 = []byte(`</a> var topic_alt_80 = []byte(`</a>
`) `)
var topic_alt_81 = []byte(`<a class="action_button action_button_right hide_on_micro">`) var topic_alt_81 = []byte(`<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">`)
var topic_alt_82 = []byte(` up</a>`) var topic_alt_82 = []byte(`</a>`)
var topic_alt_83 = []byte(` var topic_alt_83 = []byte(`
</div> </div>
`) `)

View File

@ -166,18 +166,18 @@ w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
w.Write(topic_alt_41) w.Write(topic_alt_41)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
w.Write(topic_alt_42) w.Write(topic_alt_42)
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
w.Write(topic_alt_43)
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
w.Write(topic_alt_44)
} }
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
w.Write(topic_alt_43)
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
w.Write(topic_alt_44)
} }
w.Write(topic_alt_45) w.Write(topic_alt_45)
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedAt)) w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedAt))
w.Write(topic_alt_46) w.Write(topic_alt_46)
if tmpl_topic_alt_vars.Topic.LikeCount > 0 { if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
w.Write(topic_alt_47) w.Write(topic_alt_47)
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount))) w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
w.Write(topic_alt_48) w.Write(topic_alt_48)
} }
w.Write(topic_alt_49) w.Write(topic_alt_49)
@ -239,18 +239,18 @@ w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_alt_75) w.Write(topic_alt_75)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
w.Write(topic_alt_76) w.Write(topic_alt_76)
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
w.Write(topic_alt_77)
w.Write([]byte(item.IPAddress))
w.Write(topic_alt_78)
} }
if item.LikeCount > 0 {
w.Write(topic_alt_77)
w.Write([]byte(strconv.Itoa(item.LikeCount)))
w.Write(topic_alt_78)
} }
w.Write(topic_alt_79) w.Write(topic_alt_79)
w.Write([]byte(item.CreatedAt)) w.Write([]byte(item.CreatedAt))
w.Write(topic_alt_80) w.Write(topic_alt_80)
if item.LikeCount > 0 { if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
w.Write(topic_alt_81) w.Write(topic_alt_81)
w.Write([]byte(strconv.Itoa(item.LikeCount))) w.Write([]byte(item.IPAddress))
w.Write(topic_alt_82) w.Write(topic_alt_82)
} }
w.Write(topic_alt_83) w.Write(topic_alt_83)

View File

@ -40,10 +40,10 @@
{{if .CurrentUser.Perms.PinTopic}} {{if .CurrentUser.Perms.PinTopic}}
{{if .Topic.Sticky}}<a href='/topic/unstick/submit/{{.Topic.ID}}' class="action_button">Unpin</a>{{else}}<a href='/topic/stick/submit/{{.Topic.ID}}' class="action_button">Pin</a>{{end}}{{end}} {{if .Topic.Sticky}}<a href='/topic/unstick/submit/{{.Topic.ID}}' class="action_button">Unpin</a>{{else}}<a href='/topic/stick/submit/{{.Topic.ID}}' class="action_button">Pin</a>{{end}}{{end}}
<a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item">Report</a> <a href="/report/submit/{{.Topic.ID}}?session={{.CurrentUser.Session}}&type=topic" class="action_button report_item">Report</a>
{{if .CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.Topic.IPAddress}}</a>{{end}}
{{end}} {{end}}
<a class="action_button action_button_right hide_on_mobile">{{.Topic.CreatedAt}}</a> {{if .Topic.LikeCount}}<a class="action_button action_button_right like_count hide_on_micro">{{.Topic.LikeCount}} up</a>{{end}}
{{if .Topic.LikeCount}}<a class="action_button action_button_right hide_on_micro">{{.Topic.LikeCount}} up</a>{{end}} <a class="action_button action_button_right created_at hide_on_mobile">{{.Topic.CreatedAt}}</a>
{{if .CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.Topic.IPAddress}}</a>{{end}}
</div> </div>
</div><div style="clear:both;"></div> </div><div style="clear:both;"></div>
</article> </article>
@ -66,10 +66,10 @@
{{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}" class="action_button edit_item">Edit</a>{{end}} {{if $.CurrentUser.Perms.EditReply}}<a href="/reply/edit/submit/{{.ID}}" class="action_button edit_item">Edit</a>{{end}}
{{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}" class="action_button delete_item">Delete</a>{{end}} {{if $.CurrentUser.Perms.DeleteReply}}<a href="/reply/delete/submit/{{.ID}}" class="action_button delete_item">Delete</a>{{end}}
<a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item">Report</a> <a href="/report/submit/{{.ID}}?session={{$.CurrentUser.Session}}&type=reply" class="action_button report_item">Report</a>
{{if $.CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.IPAddress}}</a>{{end}}
{{end}} {{end}}
<a class="action_button action_button_right hide_on_mobile">{{.CreatedAt}}</a> {{if .LikeCount}}<a class="action_button action_button_right like_count hide_on_micro">{{.LikeCount}} up</a>{{end}}
{{if .LikeCount}}<a class="action_button action_button_right hide_on_micro">{{.LikeCount}} up</a>{{end}} <a class="action_button action_button_right created_at hide_on_mobile">{{.CreatedAt}}</a>
{{if $.CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.IPAddress}}</a>{{end}}
</div> </div>
{{end}} {{end}}
</div> </div>

View File

@ -69,7 +69,7 @@ type ThemeResource struct {
func LoadThemes() error { func LoadThemes() error {
changeDefaultThemeMutex.Lock() changeDefaultThemeMutex.Lock()
rows, err := get_themes_stmt.Query() rows, err := getThemesStmt.Query()
if err != nil { if err != nil {
return err return err
} }
@ -189,7 +189,7 @@ func addThemeStaticFiles(theme Theme) error {
var pieces = strings.Split(path, "/") var pieces = strings.Split(path, "/")
var filename = pieces[len(pieces)-1] var filename = pieces[len(pieces)-1]
//log.Print("filename ", filename) //log.Print("filename ", filename)
err = theme.ResourceTemplates.ExecuteTemplate(&b, filename, CssData{ComingSoon: "We don't have any data to pass you yet!"}) err = theme.ResourceTemplates.ExecuteTemplate(&b, filename, CSSData{ComingSoon: "We don't have any data to pass you yet!"})
if err != nil { if err != nil {
return err return err
} }

View File

@ -498,17 +498,14 @@ button.username {
/* Tempra Conflux */ /* Tempra Conflux */
.user_content { .user_content {
padding: 5px; padding: 7px;
margin-top: 2px; margin-top: 2px;
margin-bottom: 0; margin-bottom: 0;
background: white; background: white;
min-height: 145px; min-height: 145.30px;
padding-bottom: 0; padding-bottom: 0;
width: 100%; width: 100%;
} }
.user_content.nobuttons {
min-height: 168px;
}
.button_container { .button_container {
border-top: solid 1px #eaeaea; border-top: solid 1px #eaeaea;
@ -517,24 +514,27 @@ button.username {
padding: 0; padding: 0;
margin: 0; margin: 0;
margin-top: 3px; margin-top: 3px;
display: block; display: flex;
height: 20px; flex-direction: row;
} }
.action_button { .action_button {
display: block; display: block;
float: left;
border-right: solid 1px #eaeaea; border-right: solid 1px #eaeaea;
color: #505050; color: #505050;
font-size: 13px; font-size: 13px;
padding-top: 2px; padding-top: 2px;
padding-bottom: 2px; padding-bottom: 1.5px;
padding-left: 5px; padding-left: 7px;
padding-right: 5px; padding-right: 7px;
} }
.action_button_right { .action_button_right {
float: right;
border-left: solid 1px #eaeaea; border-left: solid 1px #eaeaea;
border-right: none;
}
.button_container .report_item {
margin-right: auto;
} }
.like_label:before { content: "😀"; } .like_label:before { content: "😀"; }
@ -645,12 +645,12 @@ button.username {
.content_container { .content_container {
background: white; background: white;
margin-left: 137px; margin-left: 138px;
min-height: 128px; min-height: 128px;
margin-bottom: 0; margin-bottom: 0;
margin-right: 3px; margin-right: 3px;
/*box-shadow: 0 1px 2px rgba(0,0,0,.1);*/ /*box-shadow: 0 1px 2px rgba(0,0,0,.1);*/
border-bottom: 1px inset hsl(0,0%,80%); border-bottom: 1.5px inset hsl(0,0%,80%);
} }
.action_item .userinfo { display: none; } .action_item .userinfo { display: none; }
@ -681,8 +681,12 @@ button.username {
text-decoration: none; text-decoration: none;
color: #505050; color: #505050;
} }
.prev_button { left: 14px; } .prev_button {
.next_button { right: 14px; } left: 14px;
}
.next_button {
right: 14px;
}
.head_tag_upshift { .head_tag_upshift {
float: right; float: right;
@ -737,13 +741,13 @@ button.username {
/* Firefox specific CSS */ /* Firefox specific CSS */
@supports (-moz-appearance: none) { @supports (-moz-appearance: none) {
.footer, .rowmenu, #profile_right_lane .topic_reply_form { .footer, .rowmenu, #profile_right_lane .topic_reply_form, .content_container {
border-bottom: 2px inset hsl(0,0%,40%); border-bottom: 2px inset hsl(0,0%,40%);
} }
} }
/* Edge... We can't get the exact shade here, because of how they implemented it x.x */ /* Edge... We can't get the exact shade here, because of how they implemented it x.x */
@supports (-ms-ime-align:auto) { @supports (-ms-ime-align:auto) {
.footer, .rowmenu, #profile_right_lane .topic_reply_form { .footer, .rowmenu, #profile_right_lane .topic_reply_form, .content_container {
border-bottom: 1.5px inset hsl(0,0%,100%); border-bottom: 1.5px inset hsl(0,0%,100%);
} }
} }

View File

@ -118,7 +118,7 @@ func getTopicuser(tid int) (TopicUser, error) {
} }
tu := TopicUser{ID: tid} tu := TopicUser{ID: tid}
err := get_topic_user_stmt.QueryRow(tid).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level) err := getTopicUserStmt.QueryRow(tid).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
tu.Link = buildTopicURL(nameToSlug(tu.Title), tu.ID) tu.Link = buildTopicURL(nameToSlug(tu.Title), tu.ID)
tu.UserLink = buildProfileURL(nameToSlug(tu.CreatedByName), tu.CreatedBy) tu.UserLink = buildProfileURL(nameToSlug(tu.CreatedByName), tu.CreatedBy)
tu.Tag = gstore.DirtyGet(tu.Group).Tag tu.Tag = gstore.DirtyGet(tu.Group).Tag
@ -160,7 +160,7 @@ func copyTopicToTopicuser(topic *Topic, user *User) (tu TopicUser) {
func getTopicByReply(rid int) (*Topic, error) { func getTopicByReply(rid int) (*Topic, error) {
topic := Topic{ID: 0} topic := Topic{ID: 0}
err := get_topic_by_reply_stmt.QueryRow(rid).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data) err := getTopicByReplyStmt.QueryRow(rid).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
topic.Link = buildTopicURL(nameToSlug(topic.Title), topic.ID) topic.Link = buildTopicURL(nameToSlug(topic.Title), topic.ID)
return &topic, err return &topic, err
} }

View File

@ -10,6 +10,7 @@ import (
"database/sql" "database/sql"
"log" "log"
"sync" "sync"
"sync/atomic"
"./query_gen/lib" "./query_gen/lib"
) )
@ -17,6 +18,7 @@ import (
// TODO: Add the watchdog goroutine // TODO: Add the watchdog goroutine
// TODO: Add BulkGetMap // TODO: Add BulkGetMap
// TODO: Add some sort of update method // TODO: Add some sort of update method
// ? - Should we add stick, lock, unstick, and unlock methods? These might be better on the Topics not the TopicStore
var topics TopicStore var topics TopicStore
type TopicStore interface { type TopicStore interface {
@ -25,18 +27,22 @@ type TopicStore interface {
BypassGet(id int) (*Topic, error) BypassGet(id int) (*Topic, error)
Delete(id int) error Delete(id int) error
Exists(id int) bool Exists(id int) bool
AddLastTopic(item *Topic, fid int) error AddLastTopic(item *Topic, fid int) error // unimplemented
// TODO: Implement these two methods
//GetReplies() ([]*Reply, error)
//GetRepliesRange(lower int, higher int) ([]*Reply, error)
GetGlobalCount() int GetGlobalCount() int
} }
type TopicCache interface { type TopicCache interface {
CacheGet(id int) (*Topic, error) CacheGet(id int) (*Topic, error)
GetUnsafe(id int) (*Topic, error) CacheGetUnsafe(id int) (*Topic, error)
CacheSet(item *Topic) error CacheSet(item *Topic) error
CacheAdd(item *Topic) error CacheAdd(item *Topic) error
CacheAddUnsafe(item *Topic) error CacheAddUnsafe(item *Topic) error
CacheRemove(id int) error CacheRemove(id int) error
CacheRemoveUnsafe(id int) error CacheRemoveUnsafe(id int) error
Flush()
GetLength() int GetLength() int
SetCapacity(capacity int) SetCapacity(capacity int)
GetCapacity() int GetCapacity() int
@ -44,11 +50,12 @@ type TopicCache interface {
type MemoryTopicStore struct { type MemoryTopicStore struct {
items map[int]*Topic items map[int]*Topic
length int length int64 // sync/atomic only lets us operate on int32s and int64s
capacity int capacity int
get *sql.Stmt get *sql.Stmt
exists *sql.Stmt exists *sql.Stmt
topicCount *sql.Stmt topicCount *sql.Stmt
delete *sql.Stmt
sync.RWMutex sync.RWMutex
} }
@ -66,72 +73,78 @@ func NewMemoryTopicStore(capacity int) *MemoryTopicStore {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
deleteStmt, err := qgen.Builder.SimpleDelete("topics", "tid = ?")
if err != nil {
log.Fatal(err)
}
return &MemoryTopicStore{ return &MemoryTopicStore{
items: make(map[int]*Topic), items: make(map[int]*Topic),
capacity: capacity, capacity: capacity,
get: getStmt, get: getStmt,
exists: existsStmt, exists: existsStmt,
topicCount: topicCountStmt, topicCount: topicCountStmt,
delete: deleteStmt,
} }
} }
func (sts *MemoryTopicStore) CacheGet(id int) (*Topic, error) { func (mts *MemoryTopicStore) CacheGet(id int) (*Topic, error) {
sts.RLock() mts.RLock()
item, ok := sts.items[id] item, ok := mts.items[id]
sts.RUnlock() mts.RUnlock()
if ok { if ok {
return item, nil return item, nil
} }
return item, ErrNoRows return item, ErrNoRows
} }
func (sts *MemoryTopicStore) CacheGetUnsafe(id int) (*Topic, error) { func (mts *MemoryTopicStore) CacheGetUnsafe(id int) (*Topic, error) {
item, ok := sts.items[id] item, ok := mts.items[id]
if ok { if ok {
return item, nil return item, nil
} }
return item, ErrNoRows return item, ErrNoRows
} }
func (sts *MemoryTopicStore) Get(id int) (*Topic, error) { func (mts *MemoryTopicStore) Get(id int) (*Topic, error) {
sts.RLock() mts.RLock()
topic, ok := sts.items[id] topic, ok := mts.items[id]
sts.RUnlock() mts.RUnlock()
if ok { if ok {
return topic, nil return topic, nil
} }
topic = &Topic{ID: id} topic = &Topic{ID: id}
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data) err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
if err == nil { if err == nil {
topic.Link = buildTopicURL(nameToSlug(topic.Title), id) topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
_ = sts.CacheAdd(topic) _ = mts.CacheAdd(topic)
} }
return topic, err return topic, err
} }
func (sts *MemoryTopicStore) BypassGet(id int) (*Topic, error) { // BypassGet will always bypass the cache and pull the topic directly from the database
func (mts *MemoryTopicStore) BypassGet(id int) (*Topic, error) {
topic := &Topic{ID: id} topic := &Topic{ID: id}
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data) err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
topic.Link = buildTopicURL(nameToSlug(topic.Title), id) topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
return topic, err return topic, err
} }
func (sts *MemoryTopicStore) Reload(id int) error { func (mts *MemoryTopicStore) Reload(id int) error {
topic := &Topic{ID: id} topic := &Topic{ID: id}
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data) err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
if err == nil { if err == nil {
topic.Link = buildTopicURL(nameToSlug(topic.Title), id) topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
_ = sts.CacheSet(topic) _ = mts.CacheSet(topic)
} else { } else {
_ = sts.CacheRemove(id) _ = mts.CacheRemove(id)
} }
return err return err
} }
// TODO: Use a transaction here // TODO: Use a transaction here
func (sts *MemoryTopicStore) Delete(id int) error { func (mts *MemoryTopicStore) Delete(id int) error {
topic, err := sts.Get(id) topic, err := mts.Get(id)
if err != nil { if err != nil {
return nil // Already gone, maybe we should check for other errors here return nil // Already gone, maybe we should check for other errors here
} }
@ -152,96 +165,98 @@ func (sts *MemoryTopicStore) Delete(id int) error {
return err return err
} }
sts.Lock() mts.Lock()
sts.CacheRemoveUnsafe(id) mts.CacheRemoveUnsafe(id)
_, err = delete_topic_stmt.Exec(id) _, err = mts.delete.Exec(id)
if err != nil { mts.Unlock()
sts.Unlock()
return err return err
} }
sts.Unlock()
return nil func (mts *MemoryTopicStore) Exists(id int) bool {
return mts.exists.QueryRow(id).Scan(&id) == nil
} }
func (sts *MemoryTopicStore) Exists(id int) bool { func (mts *MemoryTopicStore) CacheSet(item *Topic) error {
return sts.exists.QueryRow(id).Scan(&id) == nil mts.Lock()
} _, ok := mts.items[item.ID]
func (sts *MemoryTopicStore) CacheSet(item *Topic) error {
sts.Lock()
_, ok := sts.items[item.ID]
if ok { if ok {
sts.items[item.ID] = item mts.items[item.ID] = item
} else if sts.length >= sts.capacity { } else if int(mts.length) >= mts.capacity {
sts.Unlock() mts.Unlock()
return ErrStoreCapacityOverflow return ErrStoreCapacityOverflow
} else { } else {
sts.items[item.ID] = item mts.items[item.ID] = item
sts.length++ atomic.AddInt64(&mts.length, 1)
} }
sts.Unlock() mts.Unlock()
return nil return nil
} }
func (sts *MemoryTopicStore) CacheAdd(item *Topic) error { func (mts *MemoryTopicStore) CacheAdd(item *Topic) error {
if sts.length >= sts.capacity { if int(mts.length) >= mts.capacity {
return ErrStoreCapacityOverflow return ErrStoreCapacityOverflow
} }
sts.Lock() mts.Lock()
sts.items[item.ID] = item mts.items[item.ID] = item
sts.Unlock() mts.Unlock()
sts.length++ atomic.AddInt64(&mts.length, 1)
return nil return nil
} }
// TODO: Make these length increments thread-safe. Ditto for the other DataStores // TODO: Make these length increments thread-safe. Ditto for the other DataStores
func (sts *MemoryTopicStore) CacheAddUnsafe(item *Topic) error { func (mts *MemoryTopicStore) CacheAddUnsafe(item *Topic) error {
if sts.length >= sts.capacity { if int(mts.length) >= mts.capacity {
return ErrStoreCapacityOverflow return ErrStoreCapacityOverflow
} }
sts.items[item.ID] = item mts.items[item.ID] = item
sts.length++ atomic.AddInt64(&mts.length, 1)
return nil return nil
} }
// TODO: Make these length decrements thread-safe. Ditto for the other DataStores // TODO: Make these length decrements thread-safe. Ditto for the other DataStores
func (sts *MemoryTopicStore) CacheRemove(id int) error { func (mts *MemoryTopicStore) CacheRemove(id int) error {
sts.Lock() mts.Lock()
delete(sts.items, id) delete(mts.items, id)
sts.Unlock() mts.Unlock()
sts.length-- atomic.AddInt64(&mts.length, -1)
return nil return nil
} }
func (sts *MemoryTopicStore) CacheRemoveUnsafe(id int) error { func (mts *MemoryTopicStore) CacheRemoveUnsafe(id int) error {
delete(sts.items, id) delete(mts.items, id)
sts.length-- atomic.AddInt64(&mts.length, -1)
return nil return nil
} }
// ? - What is this? Do we need it? Should it be in the main store interface? // ? - What is this? Do we need it? Should it be in the main store interface?
func (sts *MemoryTopicStore) AddLastTopic(item *Topic, fid int) error { func (mts *MemoryTopicStore) AddLastTopic(item *Topic, fid int) error {
// Coming Soon... // Coming Soon...
return nil return nil
} }
func (sts *MemoryTopicStore) GetLength() int { func (mts *MemoryTopicStore) Flush() {
return sts.length mts.Lock()
mts.items = make(map[int]*Topic)
mts.length = 0
mts.Unlock()
} }
func (sts *MemoryTopicStore) SetCapacity(capacity int) { func (mts *MemoryTopicStore) GetLength() int {
sts.capacity = capacity return int(mts.length)
} }
func (sts *MemoryTopicStore) GetCapacity() int { func (mts *MemoryTopicStore) SetCapacity(capacity int) {
return sts.capacity mts.capacity = capacity
}
func (mts *MemoryTopicStore) GetCapacity() int {
return mts.capacity
} }
// Return the total number of topics on these forums // Return the total number of topics on these forums
func (sts *MemoryTopicStore) GetGlobalCount() int { func (mts *MemoryTopicStore) GetGlobalCount() int {
var tcount int var tcount int
err := sts.topicCount.QueryRow().Scan(&tcount) err := mts.topicCount.QueryRow().Scan(&tcount)
if err != nil { if err != nil {
LogError(err) LogError(err)
} }
@ -252,6 +267,7 @@ type SQLTopicStore struct {
get *sql.Stmt get *sql.Stmt
exists *sql.Stmt exists *sql.Stmt
topicCount *sql.Stmt topicCount *sql.Stmt
delete *sql.Stmt
} }
func NewSQLTopicStore() *SQLTopicStore { func NewSQLTopicStore() *SQLTopicStore {
@ -267,10 +283,15 @@ func NewSQLTopicStore() *SQLTopicStore {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
deleteStmt, err := qgen.Builder.SimpleDelete("topics", "tid = ?")
if err != nil {
log.Fatal(err)
}
return &SQLTopicStore{ return &SQLTopicStore{
get: getStmt, get: getStmt,
exists: existsStmt, exists: existsStmt,
topicCount: topicCountStmt, topicCount: topicCountStmt,
delete: deleteStmt,
} }
} }
@ -281,6 +302,7 @@ func (sts *SQLTopicStore) Get(id int) (*Topic, error) {
return &topic, err return &topic, err
} }
// BypassGet is an alias of Get(), as we don't have a cache for SQLTopicStore
func (sts *SQLTopicStore) BypassGet(id int) (*Topic, error) { func (sts *SQLTopicStore) BypassGet(id int) (*Topic, error) {
topic := &Topic{ID: id} topic := &Topic{ID: id}
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data) err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
@ -288,6 +310,7 @@ func (sts *SQLTopicStore) BypassGet(id int) (*Topic, error) {
return topic, err return topic, err
} }
// Reload uses a similar query to Exists(), as we don't have any entries to reload, and the secondary benefit of calling Reload() is seeing if the item you're trying to reload exists
func (sts *SQLTopicStore) Reload(id int) error { func (sts *SQLTopicStore) Reload(id int) error {
return sts.exists.QueryRow(id).Scan(&id) return sts.exists.QueryRow(id).Scan(&id)
} }
@ -319,10 +342,11 @@ func (sts *SQLTopicStore) Delete(id int) error {
return err return err
} }
_, err = delete_topic_stmt.Exec(id) _, err = sts.delete.Exec(id)
return err return err
} }
// ? - What're we going to do about this?
func (sts *SQLTopicStore) AddLastTopic(item *Topic, fid int) error { func (sts *SQLTopicStore) AddLastTopic(item *Topic, fid int) error {
// Coming Soon... // Coming Soon...
return nil return nil

34
user.go
View File

@ -79,11 +79,11 @@ func (user *User) ScheduleGroupUpdate(gid int, issuedBy int, duration time.Durat
} }
revertAt := time.Now().Add(duration) revertAt := time.Now().Add(duration)
_, err := replace_schedule_group_stmt.Exec(user.ID, gid, issuedBy, revertAt, temporary) _, err := replaceScheduleGroupStmt.Exec(user.ID, gid, issuedBy, revertAt, temporary)
if err != nil { if err != nil {
return err return err
} }
_, err = set_temp_group_stmt.Exec(gid, user.ID) _, err = setTempGroupStmt.Exec(gid, user.ID)
if err != nil { if err != nil {
return err return err
} }
@ -92,11 +92,11 @@ func (user *User) ScheduleGroupUpdate(gid int, issuedBy int, duration time.Durat
// TODO: Use a transaction to avoid race conditions // TODO: Use a transaction to avoid race conditions
func (user *User) RevertGroupUpdate() error { func (user *User) RevertGroupUpdate() error {
_, err := replace_schedule_group_stmt.Exec(user.ID, 0, 0, time.Now(), false) _, err := replaceScheduleGroupStmt.Exec(user.ID, 0, 0, time.Now(), false)
if err != nil { if err != nil {
return err return err
} }
_, err = set_temp_group_stmt.Exec(0, user.ID) _, err = setTempGroupStmt.Exec(0, user.ID)
if err != nil { if err != nil {
return err return err
} }
@ -135,7 +135,7 @@ func SetPassword(uid int, password string) error {
if err != nil { if err != nil {
return err return err
} }
_, err = set_password_stmt.Exec(hashedPassword, salt, uid) _, err = setPasswordStmt.Exec(hashedPassword, salt, uid)
return err return err
} }
@ -172,7 +172,7 @@ func (user *User) increasePostStats(wcount int, topic bool) error {
var mod int var mod int
baseScore := 1 baseScore := 1
if topic { if topic {
_, err := increment_user_topics_stmt.Exec(1, user.ID) _, err := incrementUserTopicsStmt.Exec(1, user.ID)
if err != nil { if err != nil {
return err return err
} }
@ -181,31 +181,31 @@ func (user *User) increasePostStats(wcount int, topic bool) error {
settings := settingBox.Load().(SettingBox) settings := settingBox.Load().(SettingBox)
if wcount >= settings["megapost_min_words"].(int) { if wcount >= settings["megapost_min_words"].(int) {
_, err := increment_user_megaposts_stmt.Exec(1, 1, 1, user.ID) _, err := incrementUserMegapostsStmt.Exec(1, 1, 1, user.ID)
if err != nil { if err != nil {
return err return err
} }
mod = 4 mod = 4
} else if wcount >= settings["bigpost_min_words"].(int) { } else if wcount >= settings["bigpost_min_words"].(int) {
_, err := increment_user_bigposts_stmt.Exec(1, 1, user.ID) _, err := incrementUserBigpostsStmt.Exec(1, 1, user.ID)
if err != nil { if err != nil {
return err return err
} }
mod = 1 mod = 1
} else { } else {
_, err := increment_user_posts_stmt.Exec(1, user.ID) _, err := incrementUserPostsStmt.Exec(1, user.ID)
if err != nil { if err != nil {
return err return err
} }
} }
_, err := increment_user_score_stmt.Exec(baseScore+mod, user.ID) _, err := incrementUserScoreStmt.Exec(baseScore+mod, user.ID)
if err != nil { if err != nil {
return err return err
} }
//log.Print(user.Score + base_score + mod) //log.Print(user.Score + base_score + mod)
//log.Print(getLevel(user.Score + base_score + mod)) //log.Print(getLevel(user.Score + base_score + mod))
// TODO: Use a transaction to prevent level desyncs? // TODO: Use a transaction to prevent level desyncs?
_, err = update_user_level_stmt.Exec(getLevel(user.Score+baseScore+mod), user.ID) _, err = updateUserLevelStmt.Exec(getLevel(user.Score+baseScore+mod), user.ID)
return err return err
} }
@ -214,7 +214,7 @@ func (user *User) decreasePostStats(wcount int, topic bool) error {
var mod int var mod int
baseScore := -1 baseScore := -1
if topic { if topic {
_, err := increment_user_topics_stmt.Exec(-1, user.ID) _, err := incrementUserTopicsStmt.Exec(-1, user.ID)
if err != nil { if err != nil {
return err return err
} }
@ -223,29 +223,29 @@ func (user *User) decreasePostStats(wcount int, topic bool) error {
settings := settingBox.Load().(SettingBox) settings := settingBox.Load().(SettingBox)
if wcount >= settings["megapost_min_words"].(int) { if wcount >= settings["megapost_min_words"].(int) {
_, err := increment_user_megaposts_stmt.Exec(-1, -1, -1, user.ID) _, err := incrementUserMegapostsStmt.Exec(-1, -1, -1, user.ID)
if err != nil { if err != nil {
return err return err
} }
mod = 4 mod = 4
} else if wcount >= settings["bigpost_min_words"].(int) { } else if wcount >= settings["bigpost_min_words"].(int) {
_, err := increment_user_bigposts_stmt.Exec(-1, -1, user.ID) _, err := incrementUserBigpostsStmt.Exec(-1, -1, user.ID)
if err != nil { if err != nil {
return err return err
} }
mod = 1 mod = 1
} else { } else {
_, err := increment_user_posts_stmt.Exec(-1, user.ID) _, err := incrementUserPostsStmt.Exec(-1, user.ID)
if err != nil { if err != nil {
return err return err
} }
} }
_, err := increment_user_score_stmt.Exec(baseScore-mod, user.ID) _, err := incrementUserScoreStmt.Exec(baseScore-mod, user.ID)
if err != nil { if err != nil {
return err return err
} }
// TODO: Use a transaction to prevent level desyncs? // TODO: Use a transaction to prevent level desyncs?
_, err = update_user_level_stmt.Exec(getLevel(user.Score-baseScore-mod), user.ID) _, err = updateUserLevelStmt.Exec(getLevel(user.Score-baseScore-mod), user.ID)
return err return err
} }

View File

@ -7,6 +7,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"./query_gen/lib" "./query_gen/lib"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -36,6 +37,7 @@ type UserCache interface {
CacheAddUnsafe(item *User) error CacheAddUnsafe(item *User) error
CacheRemove(id int) error CacheRemove(id int) error
CacheRemoveUnsafe(id int) error CacheRemoveUnsafe(id int) error
Flush()
GetLength() int GetLength() int
SetCapacity(capacity int) SetCapacity(capacity int)
GetCapacity() int GetCapacity() int
@ -43,7 +45,7 @@ type UserCache interface {
type MemoryUserStore struct { type MemoryUserStore struct {
items map[int]*User items map[int]*User
length int length int64
capacity int capacity int
get *sql.Stmt get *sql.Stmt
exists *sql.Stmt exists *sql.Stmt
@ -93,34 +95,34 @@ func NewMemoryUserStore(capacity int) *MemoryUserStore {
} }
} }
func (sus *MemoryUserStore) CacheGet(id int) (*User, error) { func (mus *MemoryUserStore) CacheGet(id int) (*User, error) {
sus.RLock() mus.RLock()
item, ok := sus.items[id] item, ok := mus.items[id]
sus.RUnlock() mus.RUnlock()
if ok { if ok {
return item, nil return item, nil
} }
return item, ErrNoRows return item, ErrNoRows
} }
func (sus *MemoryUserStore) CacheGetUnsafe(id int) (*User, error) { func (mus *MemoryUserStore) CacheGetUnsafe(id int) (*User, error) {
item, ok := sus.items[id] item, ok := mus.items[id]
if ok { if ok {
return item, nil return item, nil
} }
return item, ErrNoRows return item, ErrNoRows
} }
func (sus *MemoryUserStore) Get(id int) (*User, error) { func (mus *MemoryUserStore) Get(id int) (*User, error) {
sus.RLock() mus.RLock()
user, ok := sus.items[id] user, ok := mus.items[id]
sus.RUnlock() mus.RUnlock()
if ok { if ok {
return user, nil return user, nil
} }
user = &User{ID: id, Loggedin: true} user = &User{ID: id, Loggedin: true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup) err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
if user.Avatar != "" { if user.Avatar != "" {
if user.Avatar[0] == '.' { if user.Avatar[0] == '.' {
@ -133,25 +135,25 @@ func (sus *MemoryUserStore) Get(id int) (*User, error) {
user.Tag = gstore.DirtyGet(user.Group).Tag user.Tag = gstore.DirtyGet(user.Group).Tag
initUserPerms(user) initUserPerms(user)
if err == nil { if err == nil {
sus.CacheSet(user) mus.CacheSet(user)
} }
return user, err return user, err
} }
// WARNING: We did a little hack to make this as thin and quick as possible to reduce lock contention, use the * Cascade* methods instead for normal use // WARNING: We did a little hack to make this as thin and quick as possible to reduce lock contention, use the * Cascade* methods instead for normal use
func (sus *MemoryUserStore) bulkGet(ids []int) (list []*User) { func (mus *MemoryUserStore) bulkGet(ids []int) (list []*User) {
list = make([]*User, len(ids)) list = make([]*User, len(ids))
sus.RLock() mus.RLock()
for i, id := range ids { for i, id := range ids {
list[i] = sus.items[id] list[i] = mus.items[id]
} }
sus.RUnlock() mus.RUnlock()
return list return list
} }
// TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts? // TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts?
// TODO: ID of 0 should always error? // TODO: ID of 0 should always error?
func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) { func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) {
var idCount = len(ids) var idCount = len(ids)
list = make(map[int]*User) list = make(map[int]*User)
if idCount == 0 { if idCount == 0 {
@ -159,7 +161,7 @@ func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
} }
var stillHere []int var stillHere []int
sliceList := sus.bulkGet(ids) sliceList := mus.bulkGet(ids)
for i, sliceItem := range sliceList { for i, sliceItem := range sliceList {
if sliceItem != nil { if sliceItem != nil {
list[sliceItem.ID] = sliceItem list[sliceItem.ID] = sliceItem
@ -212,7 +214,7 @@ func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
initUserPerms(user) initUserPerms(user)
// Add it to the cache... // Add it to the cache...
_ = sus.CacheSet(user) _ = mus.CacheSet(user)
// Add it to the list to be returned // Add it to the list to be returned
list[user.ID] = user list[user.ID] = user
@ -246,9 +248,9 @@ func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
return list, nil return list, nil
} }
func (sus *MemoryUserStore) BypassGet(id int) (*User, error) { func (mus *MemoryUserStore) BypassGet(id int) (*User, error) {
user := &User{ID: id, Loggedin: true} user := &User{ID: id, Loggedin: true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup) err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
if user.Avatar != "" { if user.Avatar != "" {
if user.Avatar[0] == '.' { if user.Avatar[0] == '.' {
@ -263,11 +265,11 @@ func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
return user, err return user, err
} }
func (sus *MemoryUserStore) Reload(id int) error { func (mus *MemoryUserStore) Reload(id int) error {
user := &User{ID: id, Loggedin: true} user := &User{ID: id, Loggedin: true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup) err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
if err != nil { if err != nil {
sus.CacheRemove(id) mus.CacheRemove(id)
return err return err
} }
@ -281,68 +283,68 @@ func (sus *MemoryUserStore) Reload(id int) error {
user.Link = buildProfileURL(nameToSlug(user.Name), id) user.Link = buildProfileURL(nameToSlug(user.Name), id)
user.Tag = gstore.DirtyGet(user.Group).Tag user.Tag = gstore.DirtyGet(user.Group).Tag
initUserPerms(user) initUserPerms(user)
_ = sus.CacheSet(user) _ = mus.CacheSet(user)
return nil return nil
} }
func (sus *MemoryUserStore) Exists(id int) bool { func (mus *MemoryUserStore) Exists(id int) bool {
return sus.exists.QueryRow(id).Scan(&id) == nil return mus.exists.QueryRow(id).Scan(&id) == nil
} }
func (sus *MemoryUserStore) CacheSet(item *User) error { func (mus *MemoryUserStore) CacheSet(item *User) error {
sus.Lock() mus.Lock()
user, ok := sus.items[item.ID] user, ok := mus.items[item.ID]
if ok { if ok {
sus.Unlock() mus.Unlock()
*user = *item *user = *item
} else if sus.length >= sus.capacity { } else if int(mus.length) >= mus.capacity {
sus.Unlock() mus.Unlock()
return ErrStoreCapacityOverflow return ErrStoreCapacityOverflow
} else { } else {
sus.items[item.ID] = item mus.items[item.ID] = item
sus.Unlock() mus.Unlock()
sus.length++ atomic.AddInt64(&mus.length, 1)
} }
return nil return nil
} }
func (sus *MemoryUserStore) CacheAdd(item *User) error { func (mus *MemoryUserStore) CacheAdd(item *User) error {
if sus.length >= sus.capacity { if int(mus.length) >= mus.capacity {
return ErrStoreCapacityOverflow return ErrStoreCapacityOverflow
} }
sus.Lock() mus.Lock()
sus.items[item.ID] = item mus.items[item.ID] = item
sus.Unlock() mus.Unlock()
sus.length++ atomic.AddInt64(&mus.length, 1)
return nil return nil
} }
func (sus *MemoryUserStore) CacheAddUnsafe(item *User) error { func (mus *MemoryUserStore) CacheAddUnsafe(item *User) error {
if sus.length >= sus.capacity { if int(mus.length) >= mus.capacity {
return ErrStoreCapacityOverflow return ErrStoreCapacityOverflow
} }
sus.items[item.ID] = item mus.items[item.ID] = item
sus.length++ atomic.AddInt64(&mus.length, 1)
return nil return nil
} }
func (sus *MemoryUserStore) CacheRemove(id int) error { func (mus *MemoryUserStore) CacheRemove(id int) error {
sus.Lock() mus.Lock()
delete(sus.items, id) delete(mus.items, id)
sus.Unlock() mus.Unlock()
sus.length-- atomic.AddInt64(&mus.length, -1)
return nil return nil
} }
func (sus *MemoryUserStore) CacheRemoveUnsafe(id int) error { func (mus *MemoryUserStore) CacheRemoveUnsafe(id int) error {
delete(sus.items, id) delete(mus.items, id)
sus.length-- atomic.AddInt64(&mus.length, -1)
return nil return nil
} }
func (sus *MemoryUserStore) Create(username string, password string, email string, group int, active int) (int, error) { func (mus *MemoryUserStore) Create(username string, password string, email string, group int, active int) (int, error) {
// Is this username already taken..? // Is this username already taken..?
err := sus.usernameExists.QueryRow(username).Scan(&username) err := mus.usernameExists.QueryRow(username).Scan(&username)
if err != ErrNoRows { if err != ErrNoRows {
return 0, errAccountExists return 0, errAccountExists
} }
@ -357,7 +359,7 @@ func (sus *MemoryUserStore) Create(username string, password string, email strin
return 0, err return 0, err
} }
res, err := sus.register.Exec(username, email, string(hashedPassword), salt, group, active) res, err := mus.register.Exec(username, email, string(hashedPassword), salt, group, active)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -366,22 +368,29 @@ func (sus *MemoryUserStore) Create(username string, password string, email strin
return int(lastID), err return int(lastID), err
} }
func (sus *MemoryUserStore) GetLength() int { func (mus *MemoryUserStore) Flush() {
return sus.length mus.Lock()
mus.items = make(map[int]*User)
mus.length = 0
mus.Unlock()
} }
func (sus *MemoryUserStore) SetCapacity(capacity int) { func (mus *MemoryUserStore) GetLength() int {
sus.capacity = capacity return int(mus.length)
} }
func (sus *MemoryUserStore) GetCapacity() int { func (mus *MemoryUserStore) SetCapacity(capacity int) {
return sus.capacity mus.capacity = capacity
}
func (mus *MemoryUserStore) GetCapacity() int {
return mus.capacity
} }
// Return the total number of users registered on the forums // Return the total number of users registered on the forums
func (sus *MemoryUserStore) GetGlobalCount() int { func (mus *MemoryUserStore) GetGlobalCount() int {
var ucount int var ucount int
err := sus.userCount.QueryRow().Scan(&ucount) err := mus.userCount.QueryRow().Scan(&ucount)
if err != nil { if err != nil {
LogError(err) LogError(err)
} }
@ -433,9 +442,9 @@ func NewSQLUserStore() *SQLUserStore {
} }
} }
func (sus *SQLUserStore) Get(id int) (*User, error) { func (mus *SQLUserStore) Get(id int) (*User, error) {
user := User{ID: id, Loggedin: true} user := User{ID: id, Loggedin: true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup) err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
if user.Avatar != "" { if user.Avatar != "" {
if user.Avatar[0] == '.' { if user.Avatar[0] == '.' {
@ -451,7 +460,7 @@ func (sus *SQLUserStore) Get(id int) (*User, error) {
} }
// TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts? // TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts?
func (sus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) { func (mus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) {
var qlist string var qlist string
var uidList []interface{} var uidList []interface{}
for _, id := range ids { for _, id := range ids {
@ -497,9 +506,9 @@ func (sus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) {
return list, nil return list, nil
} }
func (sus *SQLUserStore) BypassGet(id int) (*User, error) { func (mus *SQLUserStore) BypassGet(id int) (*User, error) {
user := User{ID: id, Loggedin: true} user := User{ID: id, Loggedin: true}
err := sus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup) err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
if user.Avatar != "" { if user.Avatar != "" {
if user.Avatar[0] == '.' { if user.Avatar[0] == '.' {
@ -514,17 +523,17 @@ func (sus *SQLUserStore) BypassGet(id int) (*User, error) {
return &user, err return &user, err
} }
func (sus *SQLUserStore) Reload(id int) error { func (mus *SQLUserStore) Reload(id int) error {
return sus.exists.QueryRow(id).Scan(&id) return mus.exists.QueryRow(id).Scan(&id)
} }
func (sus *SQLUserStore) Exists(id int) bool { func (mus *SQLUserStore) Exists(id int) bool {
return sus.exists.QueryRow(id).Scan(&id) == nil return mus.exists.QueryRow(id).Scan(&id) == nil
} }
func (sus *SQLUserStore) Create(username string, password string, email string, group int, active int) (int, error) { func (mus *SQLUserStore) Create(username string, password string, email string, group int, active int) (int, error) {
// Is this username already taken..? // Is this username already taken..?
err := sus.usernameExists.QueryRow(username).Scan(&username) err := mus.usernameExists.QueryRow(username).Scan(&username)
if err != ErrNoRows { if err != ErrNoRows {
return 0, errAccountExists return 0, errAccountExists
} }
@ -539,7 +548,7 @@ func (sus *SQLUserStore) Create(username string, password string, email string,
return 0, err return 0, err
} }
res, err := sus.register.Exec(username, email, string(hashedPassword), salt, group, active) res, err := mus.register.Exec(username, email, string(hashedPassword), salt, group, active)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -549,9 +558,9 @@ func (sus *SQLUserStore) Create(username string, password string, email string,
} }
// Return the total number of users registered on the forums // Return the total number of users registered on the forums
func (sus *SQLUserStore) GetGlobalCount() int { func (mus *SQLUserStore) GetGlobalCount() int {
var ucount int var ucount int
err := sus.userCount.QueryRow().Scan(&ucount) err := mus.userCount.QueryRow().Scan(&ucount)
if err != nil { if err != nil {
LogError(err) LogError(err)
} }

View File

@ -189,13 +189,13 @@ func SendEmail(email string, subject string, msg string) (res bool) {
} }
body := "Subject: " + subject + "\n\n" + msg + "\n" body := "Subject: " + subject + "\n\n" + msg + "\n"
con, err := smtp.Dial(config.SmtpServer + ":" + config.SmtpPort) con, err := smtp.Dial(config.SMTPServer + ":" + config.SMTPPort)
if err != nil { if err != nil {
return return
} }
if config.SmtpUsername != "" { if config.SMTPUsername != "" {
auth := smtp.PlainAuth("", config.SmtpUsername, config.SmtpPassword, config.SmtpServer) auth := smtp.PlainAuth("", config.SMTPUsername, config.SMTPPassword, config.SMTPServer)
err = con.Auth(auth) err = con.Auth(auth)
if err != nil { if err != nil {
return return
@ -394,11 +394,11 @@ func buildSlug(slug string, id int) string {
} }
func addModLog(action string, elementID int, elementType string, ipaddress string, actorID int) (err error) { func addModLog(action string, elementID int, elementType string, ipaddress string, actorID int) (err error) {
_, err = add_modlog_entry_stmt.Exec(action, elementID, elementType, ipaddress, actorID) _, err = addModlogEntryStmt.Exec(action, elementID, elementType, ipaddress, actorID)
return err return err
} }
func addAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) (err error) { func addAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) (err error) {
_, err = add_adminlog_entry_stmt.Exec(action, elementID, elementType, ipaddress, actorID) _, err = addAdminlogEntryStmt.Exec(action, elementID, elementType, ipaddress, actorID)
return err return err
} }

View File

@ -41,7 +41,7 @@ type NameTextPair struct {
} }
func initWidgets() error { func initWidgets() error {
rows, err := get_widgets_stmt.Query() rows, err := getWidgetsStmt.Query()
if err != nil { if err != nil {
return err return err
} }

View File

@ -16,7 +16,7 @@ func init() {
} }
func LoadWordFilters() error { func LoadWordFilters() error {
rows, err := get_word_filters_stmt.Query() rows, err := getWordFiltersStmt.Query()
if err != nil { if err != nil {
return err return err
} }