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) {
rows, err := get_watchers_stmt.Query(asid)
rows, err := getWatchersStmt.Query(asid)
if err != nil && err != ErrNoRows {
log.Fatal(err.Error())
return
@ -147,7 +147,7 @@ func notifyWatchers(asid int64) {
var actorID, targetUserID, elementID int
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 {
log.Fatal(err.Error())
return

View File

@ -162,7 +162,7 @@ func (auth *DefaultAuth) CreateSession(uid int) (session string, err error) {
return "", err
}
_, err = update_session_stmt.Exec(session, uid)
_, err = updateSessionStmt.Exec(session, uid)
if err != nil {
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.
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.")
// nolint
@ -22,6 +22,7 @@ type DataStore interface {
//GetGlobalCount()
}
// nolint
type DataCache interface {
CacheGet(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
// Email
config.SmtpServer = ""
config.SmtpUsername = ""
config.SmtpPassword = ""
config.SmtpPort = "25"
config.SMTPServer = ""
config.SMTPUsername = ""
config.SMTPPassword = ""
config.SMTPPort = "25"
// Misc
config.DefaultRoute = routeTopics
config.DefaultGroup = 3 // 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.MinifyTemplates = false
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 errorBuffer []error
//var notfound_count_per_second int
//var noperms_count_per_second int
//var notfoundCountPerSecond int
//var nopermsCountPerSecond int
var errorInternal []byte
var errorNotfound []byte
@ -83,6 +83,24 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) {
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) {
w.WriteHeader(500)
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())
}
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) {
w.WriteHeader(500)
_, _ = 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) {
w.WriteHeader(500)
if !isJs {
@ -183,6 +186,7 @@ func LocalErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) {
_, _ = 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) {
w.WriteHeader(403)
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) {
w.WriteHeader(403)
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
// 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) {
w.WriteHeader(403)
if !isJs {

View File

@ -79,6 +79,8 @@ var preRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User
"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 {
UName string
Name string
@ -100,8 +102,9 @@ type Plugin struct {
Hooks map[string]int
}
// LoadPlugins polls the database to see which plugins have been activated and which have been installed
func LoadPlugins() error {
rows, err := get_plugins_stmt.Query()
rows, err := getPluginsStmt.Query()
if err != nil {
return err
}

View File

@ -24,7 +24,7 @@ type SFile struct {
FormattedModTime string
}
type CssData struct {
type CSSData struct {
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, ""})
rows, err := get_forums_stmt.Query()
rows, err := getForumsStmt.Query()
if err != nil {
return err
}
@ -290,7 +290,7 @@ func (mfs *MemoryForumStore) IncrementTopicCount(id int) error {
if err != nil {
return err
}
_, err = add_topics_to_forum_stmt.Exec(1, id)
_, err = addTopicsToForumStmt.Exec(1, id)
if err != nil {
return err
}
@ -303,7 +303,7 @@ func (mfs *MemoryForumStore) DecrementTopicCount(id int) error {
if err != nil {
return err
}
_, err = remove_topics_from_forum_stmt.Exec(1, id)
_, err = removeTopicsFromForumStmt.Exec(1, id)
if err != nil {
return err
}
@ -318,7 +318,7 @@ func (mfs *MemoryForumStore) UpdateLastTopic(topicName string, tid int, username
return err
}
_, err = update_forum_cache_stmt.Exec(topicName, tid, username, uid, fid)
_, err = updateForumCacheStmt.Exec(topicName, tid, username, uid, fid)
if err != nil {
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) {
forumCreateMutex.Lock()
res, err := create_forum_stmt.Exec(forumName, forumDesc, active, preset)
res, err := createForumStmt.Exec(forumName, forumDesc, active, preset)
if err != nil {
return 0, err
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -506,7 +506,7 @@ func BenchmarkQueryPreparedTopicParallel(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
var tu TopicUser
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 {
b.Fatal("No rows found!")
return

View File

@ -35,7 +35,7 @@ func NewMemoryGroupStore() *MemoryGroupStore {
func (mgs *MemoryGroupStore) LoadGroups() error {
mgs.groups = []*Group{&Group{ID: 0, Name: "Unknown"}}
rows, err := get_groups_stmt.Query()
rows, err := getGroupsStmt.Query()
if err != nil {
return err
}
@ -113,7 +113,7 @@ func (mgs *MemoryGroupStore) Create(groupName string, tag string, isAdmin bool,
defer groupCreateMutex.Unlock()
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 {
return 0, err
}
@ -163,7 +163,7 @@ func (mgs *MemoryGroupStore) Create(groupName string, tag string, isAdmin bool,
return gid, err
}
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 {
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
// Email
config.SmtpServer = ""
config.SmtpUsername = ""
config.SmtpPassword = ""
config.SmtpPort = "25"
config.SMTPServer = ""
config.SMTPUsername = ""
config.SMTPPassword = ""
config.SMTPPort = "25"
// Misc
config.DefaultRoute = routeTopics
config.DefaultGroup = 3 // 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.MinifyTemplates = true
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)
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 {
InternalError(err, w)
return
@ -145,7 +145,7 @@ func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = add_subscription_stmt.Exec(user.ID, lastID, "topic")
_, err = addSubscriptionStmt.Exec(user.ID, lastID, "topic")
if err != nil {
InternalError(err, w)
return
@ -203,13 +203,13 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) {
}
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 {
InternalError(err, w)
return
}
_, err = add_replies_to_topic_stmt.Exec(1, user.ID, tid)
_, err = addRepliesToTopicStmt.Exec(1, user.ID, tid)
if err != nil {
InternalError(err, w)
return
@ -220,7 +220,7 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) {
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 {
InternalError(err, w)
return
@ -231,7 +231,7 @@ func routeCreateReply(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = notify_watchers_stmt.Exec(lastID)
_, err = notifyWatchersStmt.Exec(lastID)
if err != nil {
InternalError(err, w)
return
@ -297,7 +297,7 @@ func routeLikeTopic(w http.ResponseWriter, r *http.Request, user User) {
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 {
InternalError(err, w)
return
@ -316,19 +316,19 @@ func routeLikeTopic(w http.ResponseWriter, r *http.Request, user User) {
}
score := 1
_, err = create_like_stmt.Exec(score, tid, "topics", user.ID)
_, err = createLikeStmt.Exec(score, tid, "topics", user.ID)
if err != nil {
InternalError(err, w)
return
}
_, err = add_likes_to_topic_stmt.Exec(1, tid)
_, err = addLikesToTopicStmt.Exec(1, tid)
if err != nil {
InternalError(err, w)
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 {
InternalError(err, w)
return
@ -339,7 +339,7 @@ func routeLikeTopic(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = notify_one_stmt.Exec(topic.CreatedBy, lastID)
_, err = notifyOneStmt.Exec(topic.CreatedBy, lastID)
if err != nil {
InternalError(err, w)
return
@ -384,7 +384,7 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
}
var fid int
err = get_topic_fid_stmt.QueryRow(reply.ParentID).Scan(&fid)
err = getTopicFIDStmt.QueryRow(reply.ParentID).Scan(&fid)
if err == ErrNoRows {
PreError("The parent topic doesn't exist.", w, r)
return
@ -408,7 +408,7 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
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 {
InternalError(err, w)
return
@ -427,19 +427,19 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
}
score := 1
_, err = create_like_stmt.Exec(score, rid, "replies", user.ID)
_, err = createLikeStmt.Exec(score, rid, "replies", user.ID)
if err != nil {
InternalError(err, w)
return
}
_, err = add_likes_to_reply_stmt.Exec(1, rid)
_, err = addLikesToReplyStmt.Exec(1, rid)
if err != nil {
InternalError(err, w)
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 {
InternalError(err, w)
return
@ -450,7 +450,7 @@ func routeReplyLikeSubmit(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = notify_one_stmt.Exec(reply.CreatedBy, lastID)
_, err = notifyOneStmt.Exec(reply.CreatedBy, lastID)
if err != nil {
InternalError(err, w)
return
@ -485,14 +485,14 @@ func routeProfileReplyCreate(w http.ResponseWriter, r *http.Request, user User)
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 {
InternalError(err, w)
return
}
var userName string
err = get_user_name_stmt.QueryRow(uid).Scan(&userName)
err = getUserNameStmt.QueryRow(uid).Scan(&userName)
if err == ErrNoRows {
LocalError("The profile you're trying to post on doesn't exist.", w, r, user)
return
@ -565,7 +565,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
return
}
err = get_user_name_stmt.QueryRow(userReply.ParentID).Scan(&title)
err = getUserNameStmt.QueryRow(userReply.ParentID).Scan(&title)
if err == ErrNoRows {
LocalError("We weren't able to find the profile the reported post is supposed to be on", w, r, user)
return
@ -576,7 +576,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
title = "Profile: " + title
content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID)
} else if itemType == "topic" {
err = get_topic_basic_stmt.QueryRow(itemID).Scan(&title, &content)
err = getTopicBasicStmt.QueryRow(itemID).Scan(&title, &content)
if err == ErrNoRows {
NotFound(w, r)
return
@ -597,7 +597,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
}
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 {
InternalError(err, w)
return
@ -615,7 +615,8 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
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 {
InternalError(err, w)
return
@ -627,7 +628,7 @@ func routeReportSubmit(w http.ResponseWriter, r *http.Request, user User, sitemI
return
}
_, err = add_topics_to_forum_stmt.Exec(1, fid)
_, err = addTopicsToForumStmt.Exec(1, fid)
if err != nil {
InternalError(err, w)
return
@ -681,7 +682,7 @@ func routeAccountOwnEditCriticalSubmit(w http.ResponseWriter, r *http.Request, u
newPassword := r.PostFormValue("account-new-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 {
LocalError("Your account no longer exists.", w, r, user)
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 {
InternalError(err, w)
return
@ -867,7 +868,7 @@ func routeAccountOwnEditUsernameSubmit(w http.ResponseWriter, r *http.Request, u
}
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 {
LocalError("Unable to change the username. Does someone else already have this name?", w, r, user)
return
@ -903,7 +904,7 @@ func routeAccountOwnEditEmail(w http.ResponseWriter, r *http.Request, user User)
email := Email{UserID: user.ID}
var emailList []interface{}
rows, err := get_emails_by_user_stmt.Query(user.ID)
rows, err := getEmailsByUserStmt.Query(user.ID)
if err != nil {
log.Fatal(err)
}
@ -960,7 +961,7 @@ func routeAccountOwnEditEmailTokenSubmit(w http.ResponseWriter, r *http.Request,
email := Email{UserID: user.ID}
targetEmail := Email{UserID: user.ID}
var emailList []interface{}
rows, err := get_emails_by_user_stmt.Query(user.ID)
rows, err := getEmailsByUserStmt.Query(user.ID)
if err != nil {
InternalError(err, w)
return
@ -997,7 +998,7 @@ func routeAccountOwnEditEmailTokenSubmit(w http.ResponseWriter, r *http.Request,
return
}
_, err = verify_email_stmt.Exec(user.Email)
_, err = verifyEmailStmt.Exec(user.Email)
if err != nil {
InternalError(err, w)
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 headerVars.Settings["activation_type"] == 2 {
_, err = activate_user_stmt.Exec(user.ID)
_, err = activateUserStmt.Exec(user.ID)
if err != nil {
InternalError(err, w)
return

View File

@ -4,6 +4,7 @@ import "strconv"
import "testing"
// 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) {
if !gloinited {
err := gloinit()
@ -16,6 +17,7 @@ func TestUserStore(t *testing.T) {
}
users = NewMemoryUserStore(config.UserCacheCapacity)
users.(UserCache).Flush()
userStoreTest(t)
users = NewSQLUserStore()
userStoreTest(t)
@ -23,6 +25,12 @@ func TestUserStore(t *testing.T) {
func userStoreTest(t *testing.T) {
var user *User
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)
if err == nil {
@ -31,6 +39,10 @@ func userStoreTest(t *testing.T) {
t.Fatal(err)
}
if hasCache && ucache.GetLength() != 0 {
t.Error("There shouldn't be anything in the user cache")
}
_, err = users.Get(0)
if err == nil {
t.Error("UID #0 shouldn't exist")
@ -38,6 +50,10 @@ func userStoreTest(t *testing.T) {
t.Fatal(err)
}
if hasCache && ucache.GetLength() != 0 {
t.Error("There shouldn't be anything in the user cache")
}
user, err = users.Get(1)
if err == ErrNoRows {
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.")
}
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?
var userList map[int]*User
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")
}
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})
if len(userList) > 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})
if len(userList) == 0 {
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.")
}
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)
if ok {
t.Error("UID #-1 shouldn't exist")
@ -93,6 +167,13 @@ func userStoreTest(t *testing.T) {
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()
if count <= 0 {
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"))
// 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 {
InternalErrorJSQ(err, w, r, isJs)
return
@ -78,12 +78,12 @@ func routeEditTopic(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w)
return
}
_, err = create_action_reply_stmt.Exec(tid, action, ipaddress, user.ID)
_, err = createActionReplyStmt.Exec(tid, action, ipaddress, user.ID)
if err != nil {
InternalError(err, w)
return
}
_, err = add_replies_to_topic_stmt.Exec(1, user.ID, tid)
_, err = addRepliesToTopicStmt.Exec(1, user.ID, tid)
if err != nil {
InternalError(err, w)
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
/*_, err = create_action_reply_stmt.Exec(tid,"delete",ipaddress,user.ID)
/*_, err = createActionReplyStmt.Exec(tid,"delete",ipaddress,user.ID)
if err != nil {
InternalError(err,w)
return
@ -194,7 +194,8 @@ func routeStickTopic(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = stick_topic_stmt.Exec(tid)
// TODO: Move this into the TopicStore?
_, err = stickTopicStmt.Exec(tid)
if err != nil {
InternalError(err, w)
return
@ -210,7 +211,7 @@ func routeStickTopic(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w)
return
}
_, err = create_action_reply_stmt.Exec(tid, "stick", ipaddress, user.ID)
_, err = createActionReplyStmt.Exec(tid, "stick", ipaddress, user.ID)
if err != nil {
InternalError(err, w)
return
@ -250,7 +251,7 @@ func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = unstick_topic_stmt.Exec(tid)
_, err = unstickTopicStmt.Exec(tid)
if err != nil {
InternalError(err, w)
return
@ -266,7 +267,7 @@ func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w)
return
}
_, err = create_action_reply_stmt.Exec(tid, "unstick", ipaddress, user.ID)
_, err = createActionReplyStmt.Exec(tid, "unstick", ipaddress, user.ID)
if err != nil {
InternalError(err, w)
return
@ -297,7 +298,7 @@ func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) {
}
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 {
InternalErrorJSQ(err, w, r, isJs)
return
@ -305,14 +306,14 @@ func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) {
// Get the Reply ID..
var tid int
err = get_reply_tid_stmt.QueryRow(rid).Scan(&tid)
err = getReplyTIDStmt.QueryRow(rid).Scan(&tid)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
}
var fid int
err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid)
err = getTopicFIDStmt.QueryRow(tid).Scan(&fid)
if err == ErrNoRows {
PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
return
@ -363,7 +364,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) {
}
var fid int
err = get_topic_fid_stmt.QueryRow(reply.ParentID).Scan(&fid)
err = getTopicFIDStmt.QueryRow(reply.ParentID).Scan(&fid)
if err == ErrNoRows {
PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
return
@ -382,7 +383,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = delete_reply_stmt.Exec(rid)
_, err = deleteReplyStmt.Exec(rid)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
@ -406,7 +407,7 @@ func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) {
InternalErrorJSQ(err, w, r, isJs)
return
}
_, err = remove_replies_from_topic_stmt.Exec(1, reply.ParentID)
_, err = removeRepliesFromTopicStmt.Exec(1, reply.ParentID)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
}
@ -445,7 +446,7 @@ func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user Us
// Get the Reply ID..
var uid int
err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid)
err = getUserReplyUIDStmt.QueryRow(rid).Scan(&uid)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
@ -457,7 +458,7 @@ func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user Us
}
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 {
InternalErrorJSQ(err, w, r, isJs)
return
@ -485,7 +486,7 @@ func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user
}
var uid int
err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid)
err = getUserReplyUIDStmt.QueryRow(rid).Scan(&uid)
if err == ErrNoRows {
LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs)
return
@ -499,7 +500,7 @@ func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user
return
}
_, err = delete_profile_reply_stmt.Exec(rid)
_, err = deleteProfileReplyStmt.Exec(rid)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
@ -527,7 +528,7 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) {
var uid int
var reqUserList = make(map[int]bool)
rows, err := find_users_by_ip_users_stmt.Query(ip)
rows, err := findUsersByIPUsersStmt.Query(ip)
if err != nil {
InternalError(err, w)
return
@ -548,7 +549,7 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) {
return
}
rows2, err := find_users_by_ip_topics_stmt.Query(ip)
rows2, err := findUsersByIPTopicsStmt.Query(ip)
if err != nil {
InternalError(err, w)
return
@ -569,7 +570,7 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) {
return
}
rows3, err := find_users_by_ip_replies_stmt.Query(ip)
rows3, err := findUsersByIPRepliesStmt.Query(ip)
if err != nil {
InternalError(err, w)
return
@ -821,7 +822,7 @@ func routeActivate(w http.ResponseWriter, r *http.Request, user User) {
}
var active bool
err = get_user_active_stmt.QueryRow(uid).Scan(&active)
err = getUserActiveStmt.QueryRow(uid).Scan(&active)
if err == ErrNoRows {
LocalError("The account you're trying to activate no longer exists.", w, r, user)
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)
return
}
_, err = activate_user_stmt.Exec(uid)
_, err = activateUserStmt.Exec(uid)
if err != nil {
InternalError(err, w)
return
}
_, err = change_group_stmt.Exec(config.DefaultGroup, uid)
_, err = changeGroupStmt.Exec(config.DefaultGroup, uid)
if err != nil {
InternalError(err, w)
return

View File

@ -1,6 +1,11 @@
// +build !pgsql !sqlite !mssql
/* Copyright Azareal 2016 - 2018 */
/*
*
* Gosora MySQL Interface
* Copyright Azareal 2016 - 2018
*
*/
package main
import "log"
@ -11,15 +16,15 @@ import _ "github.com/go-sql-driver/mysql"
import "./query_gen/lib"
var dbCollation = "utf8mb4_general_ci"
var get_activity_feed_by_watcher_stmt *sql.Stmt
var get_activity_count_by_watcher_stmt *sql.Stmt
var todays_post_count_stmt *sql.Stmt
var todays_topic_count_stmt *sql.Stmt
var todays_report_count_stmt *sql.Stmt
var todays_newuser_count_stmt *sql.Stmt
var find_users_by_ip_users_stmt *sql.Stmt
var find_users_by_ip_topics_stmt *sql.Stmt
var find_users_by_ip_replies_stmt *sql.Stmt
var getActivityFeedByWatcherStmt *sql.Stmt
var getActivityCountByWatcherStmt *sql.Stmt
var todaysPostCountStmt *sql.Stmt
var todaysTopicCountStmt *sql.Stmt
var todaysReportCountStmt *sql.Stmt
var todaysNewUserCountStmt *sql.Stmt
var findUsersByIPUsersStmt *sql.Stmt
var findUsersByIPTopicsStmt *sql.Stmt
var findUsersByIPRepliesStmt *sql.Stmt
func init() {
dbAdapter = "mysql"
@ -68,54 +73,54 @@ func _initDatabase() (err error) {
// TODO: Is there a less noisy way of doing this for tests?
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 {
return err
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
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
}

View File

@ -60,7 +60,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
}
var postCount int
err = todays_post_count_stmt.QueryRow().Scan(&postCount)
err = todaysPostCountStmt.QueryRow().Scan(&postCount)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -77,7 +77,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
}
var topicCount int
err = todays_topic_count_stmt.QueryRow().Scan(&topicCount)
err = todaysTopicCountStmt.QueryRow().Scan(&topicCount)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -94,7 +94,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
}
var reportCount int
err = todays_report_count_stmt.QueryRow().Scan(&reportCount)
err = todaysReportCountStmt.QueryRow().Scan(&reportCount)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -102,7 +102,7 @@ func routePanel(w http.ResponseWriter, r *http.Request, user User) {
var reportInterval = "week"
var newUserCount int
err = todays_newuser_count_stmt.QueryRow().Scan(&newUserCount)
err = todaysNewUserCountStmt.QueryRow().Scan(&newUserCount)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -440,7 +440,7 @@ func routePanelForumsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
}
forumUpdateMutex.Lock()
_, err = update_forum_stmt.Exec(forumName, forumDesc, active, forumPreset, fid)
_, err = updateForumStmt.Exec(forumName, forumDesc, active, forumPreset, fid)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
@ -531,13 +531,13 @@ func routePanelForumsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
return
}
_, err = add_forum_perms_to_group_stmt.Exec(gid, fid, permPreset, perms)
_, err = addForumPermsToGroupStmt.Exec(gid, fid, permPreset, perms)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
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 {
InternalErrorJSQ(err, w, r, isJs)
return
@ -564,7 +564,7 @@ func routePanelSettings(w http.ResponseWriter, r *http.Request, user User) {
//log.Print("headerVars.Settings",headerVars.Settings)
var settingList = make(map[string]interface{})
rows, err := get_settings_stmt.Query()
rows, err := getSettingsStmt.Query()
if err != nil {
InternalError(err, w)
return
@ -628,7 +628,7 @@ func routePanelSetting(w http.ResponseWriter, r *http.Request, user User, 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 {
LocalError("The setting you want to edit doesn't exist.", w, r, user)
return
@ -691,7 +691,7 @@ func routePanelSettingEdit(w http.ResponseWriter, r *http.Request, user User, sn
var stype, sconstraints string
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 {
LocalError("The setting you want to edit doesn't exist.", w, r, user)
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 {
InternalError(err, w)
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
replacement := strings.TrimSpace(r.PostFormValue("replacement"))
res, err := create_word_filter_stmt.Exec(find, replacement)
res, err := createWordFilterStmt.Exec(find, replacement)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
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
replacement := strings.TrimSpace(r.PostFormValue("replacement"))
_, err = update_word_filter_stmt.Exec(find, replacement, id)
_, err = updateWordFilterStmt.Exec(find, replacement, id)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
@ -881,7 +882,7 @@ func routePanelWordFiltersDeleteSubmit(w http.ResponseWriter, r *http.Request, u
return
}
_, err = delete_word_filter_stmt.Exec(id)
_, err = deleteWordFilterStmt.Exec(id)
if err != nil {
InternalErrorJSQ(err, w, r, isJs)
return
@ -950,7 +951,7 @@ func routePanelPluginsActivate(w http.ResponseWriter, r *http.Request, user User
}
var active bool
err := is_plugin_active_stmt.QueryRow(uname).Scan(&active)
err := isPluginActiveStmt.QueryRow(uname).Scan(&active)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -972,15 +973,15 @@ func routePanelPluginsActivate(w http.ResponseWriter, r *http.Request, user User
LocalError("The plugin is already active", w, r, user)
return
}
//log.Print("update_plugin")
_, err = update_plugin_stmt.Exec(1, uname)
//log.Print("updatePlugin")
_, err = updatePluginStmt.Exec(1, uname)
if err != nil {
InternalError(err, w)
return
}
} else {
//log.Print("add_plugin")
_, err := add_plugin_stmt.Exec(uname, 1, 0)
//log.Print("addPlugin")
_, err := addPluginStmt.Exec(uname, 1, 0)
if err != nil {
InternalError(err, w)
return
@ -1021,7 +1022,7 @@ func routePanelPluginsDeactivate(w http.ResponseWriter, r *http.Request, user Us
}
var active bool
err := is_plugin_active_stmt.QueryRow(uname).Scan(&active)
err := isPluginActiveStmt.QueryRow(uname).Scan(&active)
if err == ErrNoRows {
LocalError("The plugin you're trying to deactivate isn't active", w, r, user)
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)
return
}
_, err = update_plugin_stmt.Exec(0, uname)
_, err = updatePluginStmt.Exec(0, uname)
if err != nil {
InternalError(err, w)
return
@ -1078,7 +1079,7 @@ func routePanelPluginsInstall(w http.ResponseWriter, r *http.Request, user User,
}
var active bool
err := is_plugin_active_stmt.QueryRow(uname).Scan(&active)
err := isPluginActiveStmt.QueryRow(uname).Scan(&active)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -1102,18 +1103,18 @@ func routePanelPluginsInstall(w http.ResponseWriter, r *http.Request, user User,
}
if hasPlugin {
_, err = update_plugin_install_stmt.Exec(1, uname)
_, err = updatePluginInstallStmt.Exec(1, uname)
if err != nil {
InternalError(err, w)
return
}
_, err = update_plugin_stmt.Exec(1, uname)
_, err = updatePluginStmt.Exec(1, uname)
if err != nil {
InternalError(err, w)
return
}
} else {
_, err := add_plugin_stmt.Exec(uname, 1, 1)
_, err := addPluginStmt.Exec(uname, 1, 1)
if err != nil {
InternalError(err, w)
return
@ -1144,7 +1145,7 @@ func routePanelUsers(w http.ResponseWriter, r *http.Request, user User) {
offset, page, lastPage := pageOffset(stats.Users, page, perPage)
var userList []User
rows, err := get_users_offset_stmt.Query(offset, perPage)
rows, err := getUsersOffsetStmt.Query(offset, perPage)
if err != nil {
InternalError(err, w)
return
@ -1335,7 +1336,7 @@ func routePanelUsersEditSubmit(w http.ResponseWriter, r *http.Request, user User
return
}
_, err = update_user_stmt.Exec(newname, newemail, newgroup, targetUser.ID)
_, err = updateUserStmt.Exec(newname, newemail, newgroup, targetUser.ID)
if err != nil {
InternalError(err, w)
return
@ -1636,7 +1637,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
return
}
_, err = update_group_rank_stmt.Exec(1, 1, 0, gid)
_, err = updateGroupRankStmt.Exec(1, 1, 0, gid)
if err != nil {
InternalError(err, w)
return
@ -1650,7 +1651,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
return
}
_, err = update_group_rank_stmt.Exec(0, 1, 0, gid)
_, err = updateGroupRankStmt.Exec(0, 1, 0, gid)
if err != nil {
InternalError(err, w)
return
@ -1659,7 +1660,7 @@ func routePanelGroupsEditSubmit(w http.ResponseWriter, r *http.Request, user Use
group.IsMod = true
group.IsBanned = false
case "Banned":
_, err = update_group_rank_stmt.Exec(0, 0, 1, gid)
_, err = updateGroupRankStmt.Exec(0, 0, 1, gid)
if err != nil {
InternalError(err, w)
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)
return
case "Member":
_, err = update_group_rank_stmt.Exec(0, 0, 0, gid)
_, err = updateGroupRankStmt.Exec(0, 0, 0, gid)
if err != nil {
InternalError(err, w)
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 {
InternalError(err, w)
return
@ -1760,7 +1761,7 @@ func routePanelGroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, use
return
}
_, err = update_group_perms_stmt.Exec(pjson, gid)
_, err = updateGroupPermsStmt.Exec(pjson, gid)
if err != nil {
InternalError(err, w)
return
@ -1886,7 +1887,7 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user Use
var isDefault bool
log.Print("uname", uname)
err := is_theme_default_stmt.QueryRow(uname).Scan(&isDefault)
err := isThemeDefaultStmt.QueryRow(uname).Scan(&isDefault)
if err != nil && err != ErrNoRows {
InternalError(err, w)
return
@ -1899,13 +1900,13 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user Use
LocalError("The theme is already active", w, r, user)
return
}
_, err = update_theme_stmt.Exec(1, uname)
_, err = updateThemeStmt.Exec(1, uname)
if err != nil {
InternalError(err, w)
return
}
} else {
_, err := add_theme_stmt.Exec(uname, 1)
_, err := addThemeStmt.Exec(uname, 1)
if err != nil {
InternalError(err, w)
return
@ -1915,7 +1916,7 @@ func routePanelThemesSetDefault(w http.ResponseWriter, r *http.Request, user Use
// TODO: Make this less racey
changeDefaultThemeMutex.Lock()
defaultTheme := defaultThemeBox.Load().(string)
_, err = update_theme_stmt.Exec(0, defaultTheme)
_, err = updateThemeStmt.Exec(0, defaultTheme)
if err != nil {
InternalError(err, w)
return
@ -1948,7 +1949,7 @@ func routePanelLogsMod(w http.ResponseWriter, r *http.Request, user User) {
}
var logCount int
err := modlog_count_stmt.QueryRow().Scan(&logCount)
err := modlogCountStmt.QueryRow().Scan(&logCount)
if err != nil {
InternalError(err, w)
return
@ -1958,7 +1959,7 @@ func routePanelLogsMod(w http.ResponseWriter, r *http.Request, user User) {
perPage := 10
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 {
InternalError(err, w)
return

View File

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

View File

@ -816,10 +816,10 @@ func (adapter *Mysql_Adapter) Write() error {
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 :(
if stmt.Type != "create-table" {
stmts += "var " + name + "_stmt *sql.Stmt\n"
stmts += "var " + name + "Stmt *sql.Stmt\n"
body += `
log.Print("Preparing ` + name + ` statement.")
` + name + `_stmt, err = db.Prepare("` + stmt.Contents + `")
` + name + `Stmt, err = db.Prepare("` + stmt.Contents + `")
if err != nil {
return err
}

View File

@ -306,10 +306,10 @@ func (adapter *Pgsql_Adapter) Write() error {
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 :(
if stmt.Type != "create-table" {
stmts += "var " + name + "_stmt *sql.Stmt\n"
stmts += "var " + name + "Stmt *sql.Stmt\n"
body += `
log.Print("Preparing ` + name + ` statement.")
` + name + `_stmt, err = db.Prepare("` + stmt.Contents + `")
` + name + `Stmt, err = db.Prepare("` + stmt.Contents + `")
if err != nil {
return err
}

View File

@ -195,286 +195,284 @@ func seed_tables(adapter qgen.DB_Adapter) error {
// nolint
func write_selects(adapter qgen.DB_Adapter) error {
// 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
}
// nolint
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
}
// nolint
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
}
// nolint
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
}
// nolint
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
}
// nolint
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
}
// nolint
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("delete_activity_stream_match", "activity_stream_matches", "watcher = ? AND asid = ?")
adapter.SimpleDelete("deleteActivityStreamMatch", "activity_stream_matches", "watcher = ? AND asid = ?")
//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
}
// nolint
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
}
// nolint
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_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_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_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
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_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) {
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
}
func getUserReply(id int) (*ReplyShort, error) {
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
}

View File

@ -33,6 +33,7 @@ func init() {
hvars = &HeaderVars{Site: site}
}
// HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS
type HTTPSRedirect struct {
}
@ -307,7 +308,7 @@ func routeForum(w http.ResponseWriter, r *http.Request, user User, sfid string)
} else {
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 {
InternalError(err, w)
return
@ -461,6 +462,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
return
}
topic.ClassName = ""
//log.Printf("topic: %+v\n", topic)
headerVars, ok := ForumUserCheck(w, r, &user, topic.ParentID)
if !ok {
@ -490,7 +492,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
topic.Tag = postGroup.Tag
if postGroup.IsMod || postGroup.IsAdmin {
topic.ClassName = config.StaffCss
topic.ClassName = config.StaffCSS
}
/*if headerVars.Settings["url_tags"] == false {
@ -509,6 +511,15 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
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
lastPage := (topic.PostCount / config.ItemsPerPage) + 1
if page > 1 {
@ -521,7 +532,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
}
// 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 {
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
@ -551,11 +562,12 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user User) {
}
if postGroup.IsMod || postGroup.IsAdmin {
replyItem.ClassName = config.StaffCss
replyItem.ClassName = config.StaffCSS
} else {
replyItem.ClassName = ""
}
// TODO: Make a function for this? Build a more sophisticated noavatar handling system?
if replyItem.Avatar != "" {
if replyItem.Avatar[0] == '.' {
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..
rows, err := get_profile_replies_stmt.Query(puser.ID)
rows, err := getProfileRepliesStmt.Query(puser.ID)
if err != nil {
InternalError(err, w)
return
@ -687,7 +699,7 @@ func routeProfile(w http.ResponseWriter, r *http.Request, user User) {
replyLines = strings.Count(replyContent, "\n")
if group.IsMod || group.IsAdmin {
replyClassName = config.StaffCss
replyClassName = config.StaffCSS
} else {
replyClassName = ""
}
@ -893,7 +905,7 @@ func routeRegisterSubmit(w http.ResponseWriter, r *http.Request, user User) {
InternalError(err, w)
return
}
_, err = add_email_stmt.Exec(email, uid, 0, token)
_, err = addEmailStmt.Exec(email, uid, 0, token)
if err != nil {
InternalError(err, w)
return
@ -981,7 +993,7 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = delete_activity_stream_match_stmt.Exec(user.ID, asid)
_, err = deleteActivityStreamMatchStmt.Exec(user.ID, asid)
if err != nil {
InternalError(err, w)
return
@ -996,7 +1008,7 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user User) {
var asid, actorID, targetUserID, elementID 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 {
PreErrorJS("Couldn't find the parent topic", w, r)
return
@ -1005,7 +1017,7 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user User) {
return
}
rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID)
rows, err := getActivityFeedByWatcherStmt.Query(user.ID)
if err != nil {
InternalErrorJS(err, w, r)
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 {
InternalError(err, w)
return headerVars, stats, false
@ -307,7 +307,7 @@ func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
return *user, false
}
if host != user.LastIP {
_, err = update_last_ip_stmt.Exec(host, user.ID)
_, err = updateLastIPStmt.Exec(host, user.ID)
if err != nil {
InternalError(err, w)
return *user, false

View File

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

10
site.go
View File

@ -35,15 +35,15 @@ type Config struct {
UserCacheCapacity int
TopicCacheCapacity int
SmtpServer string
SmtpUsername string
SmtpPassword string
SmtpPort string
SMTPServer string
SMTPUsername string
SMTPPassword string
SMTPPort string
DefaultRoute func(http.ResponseWriter, *http.Request, User)
DefaultGroup 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
MinifyTemplates bool
MultiServer bool

View File

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

View File

@ -349,14 +349,14 @@ var topic_alt_40 = []byte(`
var topic_alt_41 = []byte(`?session=`)
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_44 = []byte(`</a>`)
var topic_alt_43 = []byte(`<a class="action_button action_button_right like_count hide_on_micro">`)
var topic_alt_44 = []byte(` up</a>`)
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_47 = []byte(`<a class="action_button action_button_right hide_on_micro">`)
var topic_alt_48 = []byte(` up</a>`)
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(`</a>`)
var topic_alt_49 = []byte(`
</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_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_78 = []byte(`</a>`)
var topic_alt_77 = []byte(`<a class="action_button action_button_right like_count hide_on_micro">`)
var topic_alt_78 = []byte(` up</a>`)
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_81 = []byte(`<a class="action_button action_button_right hide_on_micro">`)
var topic_alt_82 = []byte(` up</a>`)
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(`</a>`)
var topic_alt_83 = []byte(`
</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([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
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([]byte(tmpl_topic_alt_vars.Topic.CreatedAt))
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([]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_49)
@ -239,18 +239,18 @@ w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_alt_75)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
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([]byte(item.CreatedAt))
w.Write(topic_alt_80)
if item.LikeCount > 0 {
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
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_83)

View File

@ -40,10 +40,10 @@
{{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}}
<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}}
<a class="action_button action_button_right hide_on_mobile">{{.Topic.CreatedAt}}</a>
{{if .Topic.LikeCount}}<a class="action_button action_button_right hide_on_micro">{{.Topic.LikeCount}} up</a>{{end}}
{{if .Topic.LikeCount}}<a class="action_button action_button_right like_count 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 style="clear:both;"></div>
</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.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>
{{if $.CurrentUser.Perms.ViewIPs}}<a href="#" title="IP Address" class="action_button action_button_right ip_item hide_on_mobile">{{.IPAddress}}</a>{{end}}
{{end}}
<a class="action_button action_button_right hide_on_mobile">{{.CreatedAt}}</a>
{{if .LikeCount}}<a class="action_button action_button_right hide_on_micro">{{.LikeCount}} up</a>{{end}}
{{if .LikeCount}}<a class="action_button action_button_right like_count 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>
{{end}}
</div>

View File

@ -69,7 +69,7 @@ type ThemeResource struct {
func LoadThemes() error {
changeDefaultThemeMutex.Lock()
rows, err := get_themes_stmt.Query()
rows, err := getThemesStmt.Query()
if err != nil {
return err
}
@ -189,7 +189,7 @@ func addThemeStaticFiles(theme Theme) error {
var pieces = strings.Split(path, "/")
var filename = pieces[len(pieces)-1]
//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 {
return err
}

View File

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

View File

@ -118,7 +118,7 @@ func getTopicuser(tid int) (TopicUser, error) {
}
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.UserLink = buildProfileURL(nameToSlug(tu.CreatedByName), tu.CreatedBy)
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) {
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)
return &topic, err
}

View File

@ -10,6 +10,7 @@ import (
"database/sql"
"log"
"sync"
"sync/atomic"
"./query_gen/lib"
)
@ -17,6 +18,7 @@ import (
// TODO: Add the watchdog goroutine
// TODO: Add BulkGetMap
// 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
type TopicStore interface {
@ -25,18 +27,22 @@ type TopicStore interface {
BypassGet(id int) (*Topic, error)
Delete(id int) error
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
}
type TopicCache interface {
CacheGet(id int) (*Topic, error)
GetUnsafe(id int) (*Topic, error)
CacheGetUnsafe(id int) (*Topic, error)
CacheSet(item *Topic) error
CacheAdd(item *Topic) error
CacheAddUnsafe(item *Topic) error
CacheRemove(id int) error
CacheRemoveUnsafe(id int) error
Flush()
GetLength() int
SetCapacity(capacity int)
GetCapacity() int
@ -44,11 +50,12 @@ type TopicCache interface {
type MemoryTopicStore struct {
items map[int]*Topic
length int
length int64 // sync/atomic only lets us operate on int32s and int64s
capacity int
get *sql.Stmt
exists *sql.Stmt
topicCount *sql.Stmt
delete *sql.Stmt
sync.RWMutex
}
@ -66,72 +73,78 @@ func NewMemoryTopicStore(capacity int) *MemoryTopicStore {
if err != nil {
log.Fatal(err)
}
deleteStmt, err := qgen.Builder.SimpleDelete("topics", "tid = ?")
if err != nil {
log.Fatal(err)
}
return &MemoryTopicStore{
items: make(map[int]*Topic),
capacity: capacity,
get: getStmt,
exists: existsStmt,
topicCount: topicCountStmt,
delete: deleteStmt,
}
}
func (sts *MemoryTopicStore) CacheGet(id int) (*Topic, error) {
sts.RLock()
item, ok := sts.items[id]
sts.RUnlock()
func (mts *MemoryTopicStore) CacheGet(id int) (*Topic, error) {
mts.RLock()
item, ok := mts.items[id]
mts.RUnlock()
if ok {
return item, nil
}
return item, ErrNoRows
}
func (sts *MemoryTopicStore) CacheGetUnsafe(id int) (*Topic, error) {
item, ok := sts.items[id]
func (mts *MemoryTopicStore) CacheGetUnsafe(id int) (*Topic, error) {
item, ok := mts.items[id]
if ok {
return item, nil
}
return item, ErrNoRows
}
func (sts *MemoryTopicStore) Get(id int) (*Topic, error) {
sts.RLock()
topic, ok := sts.items[id]
sts.RUnlock()
func (mts *MemoryTopicStore) Get(id int) (*Topic, error) {
mts.RLock()
topic, ok := mts.items[id]
mts.RUnlock()
if ok {
return topic, nil
}
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 {
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
_ = sts.CacheAdd(topic)
_ = mts.CacheAdd(topic)
}
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}
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)
return topic, err
}
func (sts *MemoryTopicStore) Reload(id int) error {
func (mts *MemoryTopicStore) Reload(id int) error {
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 {
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
_ = sts.CacheSet(topic)
_ = mts.CacheSet(topic)
} else {
_ = sts.CacheRemove(id)
_ = mts.CacheRemove(id)
}
return err
}
// TODO: Use a transaction here
func (sts *MemoryTopicStore) Delete(id int) error {
topic, err := sts.Get(id)
func (mts *MemoryTopicStore) Delete(id int) error {
topic, err := mts.Get(id)
if err != nil {
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
}
sts.Lock()
sts.CacheRemoveUnsafe(id)
_, err = delete_topic_stmt.Exec(id)
if err != nil {
sts.Unlock()
mts.Lock()
mts.CacheRemoveUnsafe(id)
_, err = mts.delete.Exec(id)
mts.Unlock()
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 {
return sts.exists.QueryRow(id).Scan(&id) == nil
}
func (sts *MemoryTopicStore) CacheSet(item *Topic) error {
sts.Lock()
_, ok := sts.items[item.ID]
func (mts *MemoryTopicStore) CacheSet(item *Topic) error {
mts.Lock()
_, ok := mts.items[item.ID]
if ok {
sts.items[item.ID] = item
} else if sts.length >= sts.capacity {
sts.Unlock()
mts.items[item.ID] = item
} else if int(mts.length) >= mts.capacity {
mts.Unlock()
return ErrStoreCapacityOverflow
} else {
sts.items[item.ID] = item
sts.length++
mts.items[item.ID] = item
atomic.AddInt64(&mts.length, 1)
}
sts.Unlock()
mts.Unlock()
return nil
}
func (sts *MemoryTopicStore) CacheAdd(item *Topic) error {
if sts.length >= sts.capacity {
func (mts *MemoryTopicStore) CacheAdd(item *Topic) error {
if int(mts.length) >= mts.capacity {
return ErrStoreCapacityOverflow
}
sts.Lock()
sts.items[item.ID] = item
sts.Unlock()
sts.length++
mts.Lock()
mts.items[item.ID] = item
mts.Unlock()
atomic.AddInt64(&mts.length, 1)
return nil
}
// TODO: Make these length increments thread-safe. Ditto for the other DataStores
func (sts *MemoryTopicStore) CacheAddUnsafe(item *Topic) error {
if sts.length >= sts.capacity {
func (mts *MemoryTopicStore) CacheAddUnsafe(item *Topic) error {
if int(mts.length) >= mts.capacity {
return ErrStoreCapacityOverflow
}
sts.items[item.ID] = item
sts.length++
mts.items[item.ID] = item
atomic.AddInt64(&mts.length, 1)
return nil
}
// TODO: Make these length decrements thread-safe. Ditto for the other DataStores
func (sts *MemoryTopicStore) CacheRemove(id int) error {
sts.Lock()
delete(sts.items, id)
sts.Unlock()
sts.length--
func (mts *MemoryTopicStore) CacheRemove(id int) error {
mts.Lock()
delete(mts.items, id)
mts.Unlock()
atomic.AddInt64(&mts.length, -1)
return nil
}
func (sts *MemoryTopicStore) CacheRemoveUnsafe(id int) error {
delete(sts.items, id)
sts.length--
func (mts *MemoryTopicStore) CacheRemoveUnsafe(id int) error {
delete(mts.items, id)
atomic.AddInt64(&mts.length, -1)
return nil
}
// ? - 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...
return nil
}
func (sts *MemoryTopicStore) GetLength() int {
return sts.length
func (mts *MemoryTopicStore) Flush() {
mts.Lock()
mts.items = make(map[int]*Topic)
mts.length = 0
mts.Unlock()
}
func (sts *MemoryTopicStore) SetCapacity(capacity int) {
sts.capacity = capacity
func (mts *MemoryTopicStore) GetLength() int {
return int(mts.length)
}
func (sts *MemoryTopicStore) GetCapacity() int {
return sts.capacity
func (mts *MemoryTopicStore) SetCapacity(capacity int) {
mts.capacity = capacity
}
func (mts *MemoryTopicStore) GetCapacity() int {
return mts.capacity
}
// Return the total number of topics on these forums
func (sts *MemoryTopicStore) GetGlobalCount() int {
func (mts *MemoryTopicStore) GetGlobalCount() int {
var tcount int
err := sts.topicCount.QueryRow().Scan(&tcount)
err := mts.topicCount.QueryRow().Scan(&tcount)
if err != nil {
LogError(err)
}
@ -252,6 +267,7 @@ type SQLTopicStore struct {
get *sql.Stmt
exists *sql.Stmt
topicCount *sql.Stmt
delete *sql.Stmt
}
func NewSQLTopicStore() *SQLTopicStore {
@ -267,10 +283,15 @@ func NewSQLTopicStore() *SQLTopicStore {
if err != nil {
log.Fatal(err)
}
deleteStmt, err := qgen.Builder.SimpleDelete("topics", "tid = ?")
if err != nil {
log.Fatal(err)
}
return &SQLTopicStore{
get: getStmt,
exists: existsStmt,
topicCount: topicCountStmt,
delete: deleteStmt,
}
}
@ -281,6 +302,7 @@ func (sts *SQLTopicStore) Get(id int) (*Topic, error) {
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) {
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)
@ -288,6 +310,7 @@ func (sts *SQLTopicStore) BypassGet(id int) (*Topic, error) {
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 {
return sts.exists.QueryRow(id).Scan(&id)
}
@ -319,10 +342,11 @@ func (sts *SQLTopicStore) Delete(id int) error {
return err
}
_, err = delete_topic_stmt.Exec(id)
_, err = sts.delete.Exec(id)
return err
}
// ? - What're we going to do about this?
func (sts *SQLTopicStore) AddLastTopic(item *Topic, fid int) error {
// Coming Soon...
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)
_, err := replace_schedule_group_stmt.Exec(user.ID, gid, issuedBy, revertAt, temporary)
_, err := replaceScheduleGroupStmt.Exec(user.ID, gid, issuedBy, revertAt, temporary)
if err != nil {
return err
}
_, err = set_temp_group_stmt.Exec(gid, user.ID)
_, err = setTempGroupStmt.Exec(gid, user.ID)
if err != nil {
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
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 {
return err
}
_, err = set_temp_group_stmt.Exec(0, user.ID)
_, err = setTempGroupStmt.Exec(0, user.ID)
if err != nil {
return err
}
@ -135,7 +135,7 @@ func SetPassword(uid int, password string) error {
if err != nil {
return err
}
_, err = set_password_stmt.Exec(hashedPassword, salt, uid)
_, err = setPasswordStmt.Exec(hashedPassword, salt, uid)
return err
}
@ -172,7 +172,7 @@ func (user *User) increasePostStats(wcount int, topic bool) error {
var mod int
baseScore := 1
if topic {
_, err := increment_user_topics_stmt.Exec(1, user.ID)
_, err := incrementUserTopicsStmt.Exec(1, user.ID)
if err != nil {
return err
}
@ -181,31 +181,31 @@ func (user *User) increasePostStats(wcount int, topic bool) error {
settings := settingBox.Load().(SettingBox)
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 {
return err
}
mod = 4
} 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 {
return err
}
mod = 1
} else {
_, err := increment_user_posts_stmt.Exec(1, user.ID)
_, err := incrementUserPostsStmt.Exec(1, user.ID)
if err != nil {
return err
}
}
_, err := increment_user_score_stmt.Exec(baseScore+mod, user.ID)
_, err := incrementUserScoreStmt.Exec(baseScore+mod, user.ID)
if err != nil {
return err
}
//log.Print(user.Score + base_score + mod)
//log.Print(getLevel(user.Score + base_score + mod))
// 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
}
@ -214,7 +214,7 @@ func (user *User) decreasePostStats(wcount int, topic bool) error {
var mod int
baseScore := -1
if topic {
_, err := increment_user_topics_stmt.Exec(-1, user.ID)
_, err := incrementUserTopicsStmt.Exec(-1, user.ID)
if err != nil {
return err
}
@ -223,29 +223,29 @@ func (user *User) decreasePostStats(wcount int, topic bool) error {
settings := settingBox.Load().(SettingBox)
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 {
return err
}
mod = 4
} 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 {
return err
}
mod = 1
} else {
_, err := increment_user_posts_stmt.Exec(-1, user.ID)
_, err := incrementUserPostsStmt.Exec(-1, user.ID)
if err != nil {
return err
}
}
_, err := increment_user_score_stmt.Exec(baseScore-mod, user.ID)
_, err := incrementUserScoreStmt.Exec(baseScore-mod, user.ID)
if err != nil {
return err
}
// 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
}

View File

@ -7,6 +7,7 @@ import (
"strconv"
"strings"
"sync"
"sync/atomic"
"./query_gen/lib"
"golang.org/x/crypto/bcrypt"
@ -36,6 +37,7 @@ type UserCache interface {
CacheAddUnsafe(item *User) error
CacheRemove(id int) error
CacheRemoveUnsafe(id int) error
Flush()
GetLength() int
SetCapacity(capacity int)
GetCapacity() int
@ -43,7 +45,7 @@ type UserCache interface {
type MemoryUserStore struct {
items map[int]*User
length int
length int64
capacity int
get *sql.Stmt
exists *sql.Stmt
@ -93,34 +95,34 @@ func NewMemoryUserStore(capacity int) *MemoryUserStore {
}
}
func (sus *MemoryUserStore) CacheGet(id int) (*User, error) {
sus.RLock()
item, ok := sus.items[id]
sus.RUnlock()
func (mus *MemoryUserStore) CacheGet(id int) (*User, error) {
mus.RLock()
item, ok := mus.items[id]
mus.RUnlock()
if ok {
return item, nil
}
return item, ErrNoRows
}
func (sus *MemoryUserStore) CacheGetUnsafe(id int) (*User, error) {
item, ok := sus.items[id]
func (mus *MemoryUserStore) CacheGetUnsafe(id int) (*User, error) {
item, ok := mus.items[id]
if ok {
return item, nil
}
return item, ErrNoRows
}
func (sus *MemoryUserStore) Get(id int) (*User, error) {
sus.RLock()
user, ok := sus.items[id]
sus.RUnlock()
func (mus *MemoryUserStore) Get(id int) (*User, error) {
mus.RLock()
user, ok := mus.items[id]
mus.RUnlock()
if ok {
return user, nil
}
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[0] == '.' {
@ -133,25 +135,25 @@ func (sus *MemoryUserStore) Get(id int) (*User, error) {
user.Tag = gstore.DirtyGet(user.Group).Tag
initUserPerms(user)
if err == nil {
sus.CacheSet(user)
mus.CacheSet(user)
}
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
func (sus *MemoryUserStore) bulkGet(ids []int) (list []*User) {
func (mus *MemoryUserStore) bulkGet(ids []int) (list []*User) {
list = make([]*User, len(ids))
sus.RLock()
mus.RLock()
for i, id := range ids {
list[i] = sus.items[id]
list[i] = mus.items[id]
}
sus.RUnlock()
mus.RUnlock()
return list
}
// 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?
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)
list = make(map[int]*User)
if idCount == 0 {
@ -159,7 +161,7 @@ func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
}
var stillHere []int
sliceList := sus.bulkGet(ids)
sliceList := mus.bulkGet(ids)
for i, sliceItem := range sliceList {
if sliceItem != nil {
list[sliceItem.ID] = sliceItem
@ -212,7 +214,7 @@ func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
initUserPerms(user)
// Add it to the cache...
_ = sus.CacheSet(user)
_ = mus.CacheSet(user)
// Add it to the list to be returned
list[user.ID] = user
@ -246,9 +248,9 @@ func (sus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
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}
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[0] == '.' {
@ -263,11 +265,11 @@ func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
return user, err
}
func (sus *MemoryUserStore) Reload(id int) error {
func (mus *MemoryUserStore) Reload(id int) error {
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 {
sus.CacheRemove(id)
mus.CacheRemove(id)
return err
}
@ -281,68 +283,68 @@ func (sus *MemoryUserStore) Reload(id int) error {
user.Link = buildProfileURL(nameToSlug(user.Name), id)
user.Tag = gstore.DirtyGet(user.Group).Tag
initUserPerms(user)
_ = sus.CacheSet(user)
_ = mus.CacheSet(user)
return nil
}
func (sus *MemoryUserStore) Exists(id int) bool {
return sus.exists.QueryRow(id).Scan(&id) == nil
func (mus *MemoryUserStore) Exists(id int) bool {
return mus.exists.QueryRow(id).Scan(&id) == nil
}
func (sus *MemoryUserStore) CacheSet(item *User) error {
sus.Lock()
user, ok := sus.items[item.ID]
func (mus *MemoryUserStore) CacheSet(item *User) error {
mus.Lock()
user, ok := mus.items[item.ID]
if ok {
sus.Unlock()
mus.Unlock()
*user = *item
} else if sus.length >= sus.capacity {
sus.Unlock()
} else if int(mus.length) >= mus.capacity {
mus.Unlock()
return ErrStoreCapacityOverflow
} else {
sus.items[item.ID] = item
sus.Unlock()
sus.length++
mus.items[item.ID] = item
mus.Unlock()
atomic.AddInt64(&mus.length, 1)
}
return nil
}
func (sus *MemoryUserStore) CacheAdd(item *User) error {
if sus.length >= sus.capacity {
func (mus *MemoryUserStore) CacheAdd(item *User) error {
if int(mus.length) >= mus.capacity {
return ErrStoreCapacityOverflow
}
sus.Lock()
sus.items[item.ID] = item
sus.Unlock()
sus.length++
mus.Lock()
mus.items[item.ID] = item
mus.Unlock()
atomic.AddInt64(&mus.length, 1)
return nil
}
func (sus *MemoryUserStore) CacheAddUnsafe(item *User) error {
if sus.length >= sus.capacity {
func (mus *MemoryUserStore) CacheAddUnsafe(item *User) error {
if int(mus.length) >= mus.capacity {
return ErrStoreCapacityOverflow
}
sus.items[item.ID] = item
sus.length++
mus.items[item.ID] = item
atomic.AddInt64(&mus.length, 1)
return nil
}
func (sus *MemoryUserStore) CacheRemove(id int) error {
sus.Lock()
delete(sus.items, id)
sus.Unlock()
sus.length--
func (mus *MemoryUserStore) CacheRemove(id int) error {
mus.Lock()
delete(mus.items, id)
mus.Unlock()
atomic.AddInt64(&mus.length, -1)
return nil
}
func (sus *MemoryUserStore) CacheRemoveUnsafe(id int) error {
delete(sus.items, id)
sus.length--
func (mus *MemoryUserStore) CacheRemoveUnsafe(id int) error {
delete(mus.items, id)
atomic.AddInt64(&mus.length, -1)
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..?
err := sus.usernameExists.QueryRow(username).Scan(&username)
err := mus.usernameExists.QueryRow(username).Scan(&username)
if err != ErrNoRows {
return 0, errAccountExists
}
@ -357,7 +359,7 @@ func (sus *MemoryUserStore) Create(username string, password string, email strin
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 {
return 0, err
}
@ -366,22 +368,29 @@ func (sus *MemoryUserStore) Create(username string, password string, email strin
return int(lastID), err
}
func (sus *MemoryUserStore) GetLength() int {
return sus.length
func (mus *MemoryUserStore) Flush() {
mus.Lock()
mus.items = make(map[int]*User)
mus.length = 0
mus.Unlock()
}
func (sus *MemoryUserStore) SetCapacity(capacity int) {
sus.capacity = capacity
func (mus *MemoryUserStore) GetLength() int {
return int(mus.length)
}
func (sus *MemoryUserStore) GetCapacity() int {
return sus.capacity
func (mus *MemoryUserStore) SetCapacity(capacity int) {
mus.capacity = capacity
}
func (mus *MemoryUserStore) GetCapacity() int {
return mus.capacity
}
// Return the total number of users registered on the forums
func (sus *MemoryUserStore) GetGlobalCount() int {
func (mus *MemoryUserStore) GetGlobalCount() int {
var ucount int
err := sus.userCount.QueryRow().Scan(&ucount)
err := mus.userCount.QueryRow().Scan(&ucount)
if err != nil {
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}
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[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?
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 uidList []interface{}
for _, id := range ids {
@ -497,9 +506,9 @@ func (sus *SQLUserStore) BulkGetMap(ids []int) (list map[int]*User, err error) {
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}
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[0] == '.' {
@ -514,17 +523,17 @@ func (sus *SQLUserStore) BypassGet(id int) (*User, error) {
return &user, err
}
func (sus *SQLUserStore) Reload(id int) error {
return sus.exists.QueryRow(id).Scan(&id)
func (mus *SQLUserStore) Reload(id int) error {
return mus.exists.QueryRow(id).Scan(&id)
}
func (sus *SQLUserStore) Exists(id int) bool {
return sus.exists.QueryRow(id).Scan(&id) == nil
func (mus *SQLUserStore) Exists(id int) bool {
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..?
err := sus.usernameExists.QueryRow(username).Scan(&username)
err := mus.usernameExists.QueryRow(username).Scan(&username)
if err != ErrNoRows {
return 0, errAccountExists
}
@ -539,7 +548,7 @@ func (sus *SQLUserStore) Create(username string, password string, email string,
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 {
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
func (sus *SQLUserStore) GetGlobalCount() int {
func (mus *SQLUserStore) GetGlobalCount() int {
var ucount int
err := sus.userCount.QueryRow().Scan(&ucount)
err := mus.userCount.QueryRow().Scan(&ucount)
if err != nil {
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"
con, err := smtp.Dial(config.SmtpServer + ":" + config.SmtpPort)
con, err := smtp.Dial(config.SMTPServer + ":" + config.SMTPPort)
if err != nil {
return
}
if config.SmtpUsername != "" {
auth := smtp.PlainAuth("", config.SmtpUsername, config.SmtpPassword, config.SmtpServer)
if config.SMTPUsername != "" {
auth := smtp.PlainAuth("", config.SMTPUsername, config.SMTPPassword, config.SMTPServer)
err = con.Auth(auth)
if err != nil {
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) {
_, err = add_modlog_entry_stmt.Exec(action, elementID, elementType, ipaddress, actorID)
_, err = addModlogEntryStmt.Exec(action, elementID, elementType, ipaddress, actorID)
return err
}
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
}

View File

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

View File

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