This commit's a little on the technical side, but don't worry. I have some interesting features coming up!

Added BypassGet() to the topic and user caches.
Moved 13 more queries to the query generator.
The query generator now supports simple insert queries.
Removed the pointless console logging for reply and topic deletions. We have modlogs for that.
The MySQL files now have build tags to make it easy for you to disable them for other database engines. Those will be coming after the query generator is done.
Moved a bunch of inline queries into more appropriate locations.
Rewrote _process_where and DB_Where to better handle joins.

Atom's continuing it's pointless crusade against trailing tabs.
This commit is contained in:
Azareal 2017-06-06 15:41:06 +01:00
parent 93d00b0337
commit 07a10ae9f4
10 changed files with 449 additions and 211 deletions

View File

@ -15,6 +15,7 @@ type DataStore interface {
Get(id int) (interface{}, error) Get(id int) (interface{}, error)
GetUnsafe(id int) (interface{}, error) GetUnsafe(id int) (interface{}, error)
CascadeGet(id int) (interface{}, error) CascadeGet(id int) (interface{}, error)
BypassGet(id int) (interface{}, error)
Set(item interface{}) error Set(item interface{}) error
Add(item interface{}) error Add(item interface{}) error
AddUnsafe(item interface{}) error AddUnsafe(item interface{}) error

View File

@ -1,4 +1,5 @@
/* This file was generated by Gosora's Query Generator */ /* This file was generated by Gosora's Query Generator */
// +build !pgsql !sqlite !mssql
package main package main
import "log" import "log"
@ -15,7 +16,20 @@ var get_settings_stmt *sql.Stmt
var get_setting_stmt *sql.Stmt var get_setting_stmt *sql.Stmt
var get_full_setting_stmt *sql.Stmt var get_full_setting_stmt *sql.Stmt
var is_plugin_active_stmt *sql.Stmt var is_plugin_active_stmt *sql.Stmt
var get_users_stmt *sql.Stmt
var is_theme_default_stmt *sql.Stmt
var get_modlogs_stmt *sql.Stmt
var get_reply_tid_stmt *sql.Stmt
var get_topic_fid_stmt *sql.Stmt
var get_user_reply_uid_stmt *sql.Stmt
var has_liked_topic_stmt *sql.Stmt
var get_topic_list_stmt *sql.Stmt var get_topic_list_stmt *sql.Stmt
var get_topic_user_stmt *sql.Stmt
var get_topic_by_reply_stmt *sql.Stmt
var get_topic_replies_stmt *sql.Stmt
var get_forum_topics_stmt *sql.Stmt
var get_profile_replies_stmt *sql.Stmt
var create_topic_stmt *sql.Stmt
func gen_mysql() (err error) { func gen_mysql() (err error) {
if debug { if debug {
@ -88,11 +102,89 @@ func gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing get_users statement.")
get_users_stmt, err = db.Prepare("SELECT `uid`,`name`,`group`,`active`,`is_super_admin`,`avatar` FROM users")
if err != nil {
return err
}
log.Print("Preparing is_theme_default statement.")
is_theme_default_stmt, err = db.Prepare("SELECT `default` FROM themes WHERE `uname` = ?")
if err != nil {
return err
}
log.Print("Preparing get_modlogs statement.")
get_modlogs_stmt, err = db.Prepare("SELECT `action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt` FROM moderation_logs")
if err != nil {
return err
}
log.Print("Preparing get_reply_tid statement.")
get_reply_tid_stmt, err = db.Prepare("SELECT `tid` FROM replies WHERE `rid` = ?")
if err != nil {
return err
}
log.Print("Preparing get_topic_fid statement.")
get_topic_fid_stmt, err = db.Prepare("SELECT `parentID` FROM topics WHERE `tid` = ?")
if err != nil {
return err
}
log.Print("Preparing get_user_reply_uid statement.")
get_user_reply_uid_stmt, err = db.Prepare("SELECT `uid` FROM users_replies WHERE `rid` = ?")
if err != nil {
return err
}
log.Print("Preparing has_liked_topic statement.")
has_liked_topic_stmt, err = db.Prepare("SELECT `targetItem` FROM likes WHERE `sentBy` = ? AND `targetItem` = ? AND `targetType` = 'topics'")
if err != nil {
return err
}
log.Print("Preparing get_topic_list statement.") log.Print("Preparing get_topic_list statement.")
get_topic_list_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`createdAt`,`topics`.`parentID`,`users`.`name`,`users`.`avatar` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC") get_topic_list_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`createdAt`,`topics`.`parentID`,`users`.`name`,`users`.`avatar` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing get_topic_user statement.")
get_topic_user_stmt, err = db.Prepare("SELECT `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` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` WHERE `tid` = ?")
if err != nil {
return err
}
log.Print("Preparing get_topic_by_reply statement.")
get_topic_by_reply_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`createdAt`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`parentID`,`topics`.`ipaddress`,`topics`.`postCount`,`topics`.`likeCount` FROM replies LEFT JOIN topics ON `replies`.`tid`=`topics`.`tid` WHERE `rid` = ?")
if err != nil {
return err
}
log.Print("Preparing get_topic_replies statement.")
get_topic_replies_stmt, err = db.Prepare("SELECT `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` FROM replies LEFT JOIN users ON `replies`.`createdBy`=`users`.`uid` WHERE `tid` = ?")
if err != nil {
return err
}
log.Print("Preparing get_forum_topics statement.")
get_forum_topics_stmt, err = db.Prepare("SELECT `topics`.`tid`,`topics`.`title`,`topics`.`content`,`topics`.`createdBy`,`topics`.`is_closed`,`topics`.`sticky`,`topics`.`createdAt`,`topics`.`lastReplyAt`,`topics`.`parentID`,`users`.`name`,`users`.`avatar` FROM topics LEFT JOIN users ON `topics`.`createdBy`=`users`.`uid` WHERE `topics`.`parentID` = ? ORDER BY topics.sticky DESC,topics.lastReplyAt DESC,topics.createdBy DESC")
if err != nil {
return err
}
log.Print("Preparing get_profile_replies statement.")
get_profile_replies_stmt, err = db.Prepare("SELECT `users_replies`.`rid`,`users_replies`.`content`,`users_replies`.`createdBy`,`users_replies`.`createdAt`,`users_replies`.`lastEdit`,`users_replies`.`lastEditBy`,`users`.`avatar`,`users`.`name`,`users`.`group` FROM users_replies LEFT JOIN users ON `users_replies`.`createdBy`=`users`.`uid` WHERE `users_replies`.`uid` = ?")
if err != nil {
return err
}
log.Print("Preparing create_topic statement.")
create_topic_stmt, err = db.Prepare("INSERT INTO topics(`parentID`,`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,?,NOW(),NOW(),?,?,?)")
if err != nil {
return err
}
return nil return nil
} }

View File

@ -1,7 +1,7 @@
package main package main
import ( import (
"log" // "log"
// "fmt" // "fmt"
"strconv" "strconv"
"net" "net"
@ -152,13 +152,15 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) {
InternalError(err,w,r) InternalError(err,w,r)
return return
} }
// Might need soft-delete before we can do an action reply for this
/*_, err = create_action_reply_stmt.Exec(tid,"delete",ipaddress,user.ID) /*_, err = create_action_reply_stmt.Exec(tid,"delete",ipaddress,user.ID)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
}*/ }*/
log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") //log.Print("Topic #" + strconv.Itoa(tid) + " was deleted by User #" + strconv.Itoa(user.ID))
http.Redirect(w,r,"/",http.StatusSeeOther) http.Redirect(w,r,"/",http.StatusSeeOther)
wcount := word_count(content) wcount := word_count(content)
@ -208,7 +210,6 @@ func route_stick_topic(w http.ResponseWriter, r *http.Request) {
InternalError(err,w,r) InternalError(err,w,r)
return return
} }
//topic.Sticky = true
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil { if err != nil {
@ -264,7 +265,6 @@ func route_unstick_topic(w http.ResponseWriter, r *http.Request) {
InternalError(err,w,r) InternalError(err,w,r)
return return
} }
//topic.Sticky = false
ipaddress, _, err := net.SplitHostPort(r.RemoteAddr) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil { if err != nil {
@ -316,14 +316,14 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) {
// Get the Reply ID.. // Get the Reply ID..
var tid int var tid int
err = db.QueryRow("select tid from replies where rid = ?", rid).Scan(&tid) err = get_reply_tid_stmt.QueryRow(rid).Scan(&tid)
if err != nil { if err != nil {
InternalErrorJSQ(err,w,r,is_js) InternalErrorJSQ(err,w,r,is_js)
return return
} }
var fid int var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js)
return return
@ -377,7 +377,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
} }
var fid int var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js)
return return
@ -400,7 +400,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
InternalErrorJSQ(err,w,r,is_js) InternalErrorJSQ(err,w,r,is_js)
return return
} }
log.Print("The reply '" + strconv.Itoa(rid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") //log.Print("Reply #" + strconv.Itoa(rid) + " was deleted by User #" + strconv.Itoa(user.ID))
if is_js == "0" { if is_js == "0" {
//http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) //http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
} else { } else {
@ -460,7 +460,7 @@ func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request) {
// Get the Reply ID.. // Get the Reply ID..
var uid int var uid int
err = db.QueryRow("select uid from users_replies where rid = ?", rid).Scan(&uid) err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid)
if err != nil { if err != nil {
InternalErrorJSQ(err,w,r,is_js) InternalErrorJSQ(err,w,r,is_js)
return return
@ -508,7 +508,7 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
} }
var uid int var uid int
err = db.QueryRow("select uid from users_replies where rid = ?", rid).Scan(&uid) err = get_user_reply_uid_stmt.QueryRow(rid).Scan(&uid)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js) LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js)
return return
@ -527,7 +527,7 @@ func route_profile_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
InternalErrorJSQ(err,w,r,is_js) InternalErrorJSQ(err,w,r,is_js)
return return
} }
log.Print("The reply '" + strconv.Itoa(rid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") //log.Print("The profile post '" + strconv.Itoa(rid) + "' was deleted by User #" + strconv.Itoa(user.ID))
if is_js == "0" { if is_js == "0" {
//http.Redirect(w,r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) //http.Redirect(w,r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther)

View File

@ -1,4 +1,5 @@
/* Copyright Azareal 2016 - 2017 */ /* Copyright Azareal 2016 - 2017 */
// +build !pgsql !sqlite !mssql
package main package main
import "database/sql" import "database/sql"
@ -12,13 +13,8 @@ var db *sql.DB
var db_version string var db_version string
var db_collation string = "utf8mb4_general_ci" var db_collation string = "utf8mb4_general_ci"
var get_topic_user_stmt *sql.Stmt var get_topic_replies_offset_stmt *sql.Stmt // I'll need to rewrite this one to stop it hard-coding the per page setting before moving it to the query generator
var get_topic_by_reply_stmt *sql.Stmt
var get_topic_replies_stmt *sql.Stmt
var get_topic_replies_offset_stmt *sql.Stmt
var get_forum_topics_stmt *sql.Stmt
var get_forum_topics_offset_stmt *sql.Stmt var get_forum_topics_offset_stmt *sql.Stmt
var create_topic_stmt *sql.Stmt
var create_report_stmt *sql.Stmt var create_report_stmt *sql.Stmt
var create_reply_stmt *sql.Stmt var create_reply_stmt *sql.Stmt
var create_action_reply_stmt *sql.Stmt var create_action_reply_stmt *sql.Stmt
@ -88,6 +84,10 @@ var add_theme_stmt *sql.Stmt
var update_theme_stmt *sql.Stmt var update_theme_stmt *sql.Stmt
var add_modlog_entry_stmt *sql.Stmt var add_modlog_entry_stmt *sql.Stmt
var add_adminlog_entry_stmt *sql.Stmt var add_adminlog_entry_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
func init_database() (err error) { func init_database() (err error) {
if(dbpassword != ""){ if(dbpassword != ""){
@ -118,48 +118,18 @@ func init_database() (err error) {
return err return err
} }
log.Print("Preparing get_topic_user statement.")
get_topic_user_stmt, err = db.Prepare("select 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 from topics left join users ON topics.createdBy = users.uid where tid = ?")
if err != nil {
return err
}
log.Print("Preparing get_topic_by_reply statement.")
get_topic_by_reply_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount from replies left join topics on replies.tid = topics.tid where rid = ?")
if err != nil {
return err
}
log.Print("Preparing get_topic_replies statement.")
get_topic_replies_stmt, err = db.Prepare("select 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 from replies left join users ON replies.createdBy = users.uid where tid = ?")
if err != nil {
return err
}
log.Print("Preparing get_topic_replies_offset statement.") log.Print("Preparing get_topic_replies_offset statement.")
get_topic_replies_offset_stmt, err = db.Prepare("select 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 from replies left join users on replies.createdBy = users.uid where tid = ? limit ?, " + strconv.Itoa(items_per_page)) get_topic_replies_offset_stmt, err = db.Prepare("select 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 from replies left join users on replies.createdBy = users.uid where tid = ? limit ?, " + strconv.Itoa(items_per_page))
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing get_forum_topics statement.")
get_forum_topics_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid where topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc")
if err != nil {
return err
}
log.Print("Preparing get_forum_topics_offset statement.") log.Print("Preparing get_forum_topics_offset statement.")
get_forum_topics_offset_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.postCount, topics.likeCount, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid WHERE topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC limit ?, " + strconv.Itoa(items_per_page)) get_forum_topics_offset_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, topics.postCount, topics.likeCount, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid WHERE topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC limit ?, " + strconv.Itoa(items_per_page))
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing create_topic statement.")
create_topic_stmt, err = db.Prepare("insert into topics(parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy) VALUES(?,?,?,?,NOW(),NOW(),?,?,?)")
if err != nil {
return err
}
log.Print("Preparing create_report statement.") log.Print("Preparing create_report statement.")
create_report_stmt, err = db.Prepare("INSERT INTO topics(title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class) VALUES(?,?,?,NOW(),NOW(),?,?,1,'report')") create_report_stmt, err = db.Prepare("INSERT INTO topics(title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class) VALUES(?,?,?,NOW(),NOW(),?,?,1,'report')")
if err != nil { if err != nil {
@ -560,6 +530,30 @@ func init_database() (err error) {
return err return err
} }
log.Print("Preparing todays_post_count statement.")
todays_post_count_stmt, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (now() - interval 1 day) and now()")
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 (now() - interval 1 day) and now()")
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 (now() - interval 1 day) and now() 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 (now() - interval 1 day) and now()")
if err != nil {
return err
}
log.Print("Loading the usergroups.") log.Print("Loading the usergroups.")
groups = append(groups, Group{ID:0,Name:"System"}) groups = append(groups, Group{ID:0,Name:"System"})

View File

@ -81,7 +81,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){
} }
var postCount int var postCount int
err = db.QueryRow("select count(*) from replies where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&postCount) err = todays_post_count_stmt.QueryRow().Scan(&postCount)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -98,7 +98,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){
} }
var topicCount int var topicCount int
err = db.QueryRow("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&topicCount) err = todays_topic_count_stmt.QueryRow().Scan(&topicCount)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -115,7 +115,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){
} }
var reportCount int var reportCount int
err = db.QueryRow("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now() and parentID = 1").Scan(&reportCount) err = todays_report_count_stmt.QueryRow().Scan(&reportCount)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -123,7 +123,7 @@ func route_panel(w http.ResponseWriter, r *http.Request){
var reportInterval string = "week" var reportInterval string = "week"
var newUserCount int var newUserCount int
err = db.QueryRow("select count(*) from users where createdAt BETWEEN (now() - interval 1 day) and now()").Scan(&newUserCount) err = todays_newuser_count_stmt.QueryRow().Scan(&newUserCount)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -770,7 +770,7 @@ func route_panel_plugins_deactivate(w http.ResponseWriter, r *http.Request, unam
} }
var active bool var active bool
err := db.QueryRow("select active from plugins where uname = ?", uname).Scan(&active) err := is_plugin_active_stmt.QueryRow(uname).Scan(&active)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
LocalError("The plugin you're trying to deactivate isn't active",w,r,user) LocalError("The plugin you're trying to deactivate isn't active",w,r,user)
return return
@ -807,7 +807,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request){
} }
var userList []interface{} var userList []interface{}
rows, err := db.Query("select `uid`,`name`,`group`,`active`,`is_super_admin`,`avatar` from users") rows, err := get_users_stmt.Query()
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -1481,7 +1481,7 @@ func route_panel_themes_default(w http.ResponseWriter, r *http.Request, uname st
} }
var isDefault bool var isDefault bool
err := db.QueryRow("select `default` from `themes` where `uname` = ?", uname).Scan(&isDefault) err := is_theme_default_stmt.QueryRow(uname).Scan(&isDefault)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -1542,7 +1542,7 @@ func route_panel_logs_mod(w http.ResponseWriter, r *http.Request){
return return
} }
rows, err := db.Query("select action, elementID, elementType, ipaddress, actorID, doneAt from moderation_logs") rows, err := get_modlogs_stmt.Query()
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return

View File

@ -1,7 +1,7 @@
/* WIP Under Construction */ /* WIP Under Construction */
package main package main
//import "fmt" import "fmt"
import "strings" import "strings"
import "log" import "log"
import "os" import "os"
@ -17,10 +17,18 @@ type DB_Column struct
Type string // function or column Type string // function or column
} }
type DB_Field struct
{
Name string
Type string
}
type DB_Where struct type DB_Where struct
{ {
Left string LeftTable string
Right string LeftColumn string
RightTable string
RightColumn string
Operator string Operator string
LeftType string LeftType string
RightType string RightType string
@ -42,8 +50,8 @@ type DB_Order struct
type DB_Adapter interface { type DB_Adapter interface {
get_name() string get_name() string
simple_insert(string,string,string,[]string,[]bool) error simple_insert(string,string,string,string) error
//simple_replace(string,string,[]string,[]string,[]bool) error //simple_replace(string,string,[]string,string) error
simple_update() error simple_update() error
simple_select(string,string,string,string,string/*,int,int*/) error simple_select(string,string,string,string,string/*,int,int*/) error
simple_left_join(string,string,string,string,string,string,string/*,int,int*/) error simple_left_join(string,string,string,string,string,string,string/*,int,int*/) error
@ -76,6 +84,7 @@ func write_statements(adapter DB_Adapter) error {
adapter.simple_select("username_exists","users","name","name = ?","") adapter.simple_select("username_exists","users","name","name = ?","")
adapter.simple_select("get_settings","settings","name, content, type","","") adapter.simple_select("get_settings","settings","name, content, type","","")
adapter.simple_select("get_setting","settings","content, type","name = ?","") adapter.simple_select("get_setting","settings","content, type","name = ?","")
@ -84,9 +93,37 @@ func write_statements(adapter DB_Adapter) error {
adapter.simple_select("is_plugin_active","plugins","active","uname = ?","") adapter.simple_select("is_plugin_active","plugins","active","uname = ?","")
adapter.simple_select("get_users","users","uid, name, group, active, is_super_admin, avatar","","")
adapter.simple_select("is_theme_default","themes","default","uname = ?","")
adapter.simple_select("get_modlogs","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","","")
adapter.simple_select("get_reply_tid","replies","tid","rid = ?","")
adapter.simple_select("get_topic_fid","topics","parentID","tid = ?","")
adapter.simple_select("get_user_reply_uid","users_replies","uid","rid = ?","")
adapter.simple_select("has_liked_topic","likes","targetItem","sentBy = ? and targetItem = ? and targetType = 'topics'","")
/*"select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'replies'"*/
adapter.simple_left_join("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.simple_left_join("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.simple_left_join("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.simple_left_join("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","replies.tid = topics.tid","rid = ?","")
adapter.simple_left_join("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.simple_left_join("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.simple_left_join("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.simple_insert("create_topic","topics","parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy","?,?,?,?,NOW(),NOW(),?,?,?")
return nil return nil
} }
@ -175,16 +212,73 @@ func _process_where(wherestr string) (where []DB_Where) {
// TO-DO: Subparse the contents of a function and spit out a DB_Function struct // TO-DO: Subparse the contents of a function and spit out a DB_Function struct
var outwhere DB_Where var outwhere DB_Where
var parseOffset int var parseOffset int
outwhere.Left, parseOffset = _get_identifier(segment, parseOffset) var left, right string
left, parseOffset = _get_identifier(segment, parseOffset)
outwhere.Operator, parseOffset = _get_operator(segment, parseOffset + 1) outwhere.Operator, parseOffset = _get_operator(segment, parseOffset + 1)
outwhere.Right, parseOffset = _get_identifier(segment, parseOffset + 1) right, parseOffset = _get_identifier(segment, parseOffset + 1)
outwhere.LeftType = _get_identifier_type(outwhere.Left) outwhere.LeftType = _get_identifier_type(left)
outwhere.RightType = _get_identifier_type(outwhere.Right) outwhere.RightType = _get_identifier_type(right)
left_operand := strings.Split(left,".")
right_operand := strings.Split(right,".")
if len(left_operand) == 2 {
outwhere.LeftTable = strings.TrimSpace(left_operand[0])
outwhere.LeftColumn = strings.TrimSpace(left_operand[1])
} else {
outwhere.LeftColumn = strings.TrimSpace(left_operand[0])
}
if len(right_operand) == 2 {
outwhere.RightTable = strings.TrimSpace(right_operand[0])
outwhere.RightColumn = strings.TrimSpace(right_operand[1])
} else {
outwhere.RightColumn = strings.TrimSpace(right_operand[0])
}
where = append(where,outwhere) where = append(where,outwhere)
} }
return where return where
} }
func _process_fields(fieldstr string) (fields []DB_Field) {
fmt.Println("_Entering _process_fields")
if fieldstr == "" {
return fields
}
var buffer string
var last_item int
fieldstr += ","
for i := 0; i < len(fieldstr); i++ {
if fieldstr[i] == '(' {
var pre_i int
pre_i = i
i = _skip_function_call(fieldstr,i-1)
fmt.Println("msg prior to i",fieldstr[0:i])
fmt.Println("len(fieldstr)",len(fieldstr))
fmt.Println("pre_i",pre_i)
fmt.Println("last_item",last_item)
fmt.Println("pre_i",string(fieldstr[pre_i]))
fmt.Println("last_item",string(fieldstr[last_item]))
fmt.Println("fieldstr[pre_i:i+1]",fieldstr[pre_i:i+1])
fmt.Println("fieldstr[last_item:i+1]",fieldstr[last_item:i+1])
fields = append(fields,DB_Field{Name:fieldstr[last_item:i+1],Type:_get_identifier_type(fieldstr[last_item:i+1])})
buffer = ""
last_item = i + 2
} else if fieldstr[i] == ',' && buffer != "" {
fields = append(fields,DB_Field{Name:buffer,Type:_get_identifier_type(buffer)})
buffer = ""
last_item = i + 1
} else if (fieldstr[i] > 32) && fieldstr[i] != ',' && fieldstr[i] != ')' {
buffer += string(fieldstr[i])
}
}
fmt.Println("fields",fields)
return fields
}
func _get_identifier_type(identifier string) string { func _get_identifier_type(identifier string) string {
if ('a' <= identifier[0] && identifier[0] <= 'z') || ('A' <= identifier[0] && identifier[0] <= 'Z') { if ('a' <= identifier[0] && identifier[0] <= 'z') || ('A' <= identifier[0] && identifier[0] <= 'Z') {
if identifier[len(identifier) - 1] == ')' { if identifier[len(identifier) - 1] == ')' {
@ -229,19 +323,23 @@ func _get_operator(segment string, startOffset int) (out string, i int) {
return strings.TrimSpace(segment[startOffset:]), (i - 1) return strings.TrimSpace(segment[startOffset:]), (i - 1)
} }
func _skip_function_call(segment string, i int) int { func _skip_function_call(data string, index int) int {
var brace_count int = 1 var brace_count int
for ; i < len(segment); i++ { for ;index < len(data); index++{
if segment[i] == '(' { char := data[index]
if char == '(' {
fmt.Println("Enter brace")
brace_count++ brace_count++
} else if segment[i] == ')' { } else if char == ')' {
brace_count-- brace_count--
} fmt.Println("Exit brace")
if brace_count == 0 { if brace_count == 0 {
return i fmt.Println("Exit function segment")
return index
}
} }
} }
return i return index
} }
func write_file(name string, content string) (err error) { func write_file(name string, content string) (err error) {

View File

@ -20,7 +20,7 @@ func (adapter *Mysql_Adapter) get_name() string {
return adapter.Name return adapter.Name
} }
func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns string, fields []string, quoteWhat []bool) error { func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns string, fields string) error {
if name == "" { if name == "" {
return errors.New("You need a name for this statement") return errors.New("You need a name for this statement")
} }
@ -34,28 +34,23 @@ func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns s
return errors.New("No input data found for simple_insert") return errors.New("No input data found for simple_insert")
} }
// Slice up the user friendly strings into something easier to process
var colslice []string = strings.Split(strings.TrimSpace(columns),",")
var noquotes bool = (len(quoteWhat) == 0)
var querystr string = "INSERT INTO " + table + "(" var querystr string = "INSERT INTO " + table + "("
// Escape the column names, just in case we've used a reserved keyword // Escape the column names, just in case we've used a reserved keyword
// TO-DO: Subparse the columns to allow functions and AS keywords for _, column := range _process_columns(columns) {
for _, column := range colslice { if column.Type == "function" {
querystr += "`" + column + "`," querystr += column.Left + ","
} else {
querystr += "`" + column.Left + "`,"
}
} }
// Remove the trailing comma // Remove the trailing comma
querystr = querystr[0:len(querystr) - 1] querystr = querystr[0:len(querystr) - 1]
querystr += ") VALUES (" querystr += ") VALUES ("
for fid, field := range fields { for _, field := range _process_fields(fields) {
if !noquotes && quoteWhat[fid] { querystr += field.Name + ","
querystr += "'" + field + "',"
} else {
querystr += field + ","
}
} }
querystr = querystr[0:len(querystr) - 1] querystr = querystr[0:len(querystr) - 1]
@ -93,20 +88,24 @@ func (adapter *Mysql_Adapter) simple_select(name string, table string, columns s
querystr += " FROM " + table querystr += " FROM " + table
if len(where) != 0 { if len(where) != 0 {
querystr += " WHERE" querystr += " " + "WHERE"
//fmt.Println("where",where)
//fmt.Println("_process_where(where)",_process_where(where))
for _, loc := range _process_where(where) { for _, loc := range _process_where(where) {
var lquote, rquote string var left, right string
if loc.LeftType == "column" { if loc.LeftType == "column" {
lquote = "`" left = "`" + loc.LeftColumn + "`"
} else {
left = loc.LeftColumn
} }
if loc.RightType == "column" { if loc.RightType == "column" {
rquote = "`" right = "`" + loc.RightColumn + "`"
} else {
right = loc.RightColumn
} }
querystr += " " + lquote + loc.Left + lquote + " " + loc.Operator + " " + rquote + loc.Right + rquote + " AND "
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
} }
// Remove the trailing AND
querystr = querystr[0:len(querystr) - 4] querystr = querystr[0:len(querystr) - 4]
} }
@ -172,16 +171,27 @@ func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table
if len(where) != 0 { if len(where) != 0 {
querystr += " " + "WHERE" querystr += " " + "WHERE"
for _, loc := range _process_where(where) { for _, loc := range _process_where(where) {
var lquote, rquote string var left, right string
if loc.LeftType == "column" {
lquote = "`" if loc.LeftTable != "" {
left = "`" + loc.LeftTable + "`.`" + loc.LeftColumn + "`"
} else if loc.LeftType == "column" {
left = "`" + loc.LeftColumn + "`"
} else {
left = loc.LeftColumn
} }
if loc.RightType == "column" {
rquote = "`" if loc.RightTable != "" {
right = "`" + loc.RightTable + "`.`" + loc.RightColumn + "`"
} else if loc.RightType == "column" {
right = "`" + loc.RightColumn + "`"
} else {
right = loc.RightColumn
} }
querystr += " " + lquote + loc.Left + lquote + " " + loc.Operator + " " + rquote + loc.Right + rquote + " AND "
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
} }
querystr = querystr[0:len(querystr) - 3] querystr = querystr[0:len(querystr) - 4]
} }
if len(orderby) != 0 { if len(orderby) != 0 {
@ -198,6 +208,7 @@ func (adapter *Mysql_Adapter) simple_left_join(name string, table1 string, table
func (adapter *Mysql_Adapter) write() error { func (adapter *Mysql_Adapter) write() error {
out := `/* This file was generated by Gosora's Query Generator */ out := `/* This file was generated by Gosora's Query Generator */
// +build !pgsql !sqlite !mssql
package main package main
import "log" import "log"

View File

@ -487,7 +487,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){
} }
// Get the replies.. // Get the replies..
rows, err := db.Query("select users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group from users_replies left join users ON users_replies.createdBy = users.uid where users_replies.uid = ?", puser.ID) rows, err := get_profile_replies_stmt.Query(puser.ID)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -765,9 +765,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) {
return return
} }
var words int var words, fid, createdBy int
var fid int
var createdBy int
err = db.QueryRow("select parentID, words, createdBy from topics where tid = ?", tid).Scan(&fid,&words,&createdBy) err = db.QueryRow("select parentID, words, createdBy from topics where tid = ?", tid).Scan(&fid,&words,&createdBy)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
PreError("The requested topic doesn't exist.",w,r) PreError("The requested topic doesn't exist.",w,r)
@ -786,7 +784,7 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) {
return return
} }
err = db.QueryRow("select targetItem from likes where sentBy = ? and targetItem = ? and targetType = 'topics'", user.ID, tid).Scan(&tid) err = has_liked_topic_stmt.QueryRow(user.ID, tid).Scan(&tid)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -866,9 +864,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
var tid int var tid, words, createdBy int
var words int
var createdBy int
err = db.QueryRow("select tid, words, createdBy from replies where rid = ?", rid).Scan(&tid, &words, &createdBy) err = db.QueryRow("select tid, words, createdBy from replies where rid = ?", rid).Scan(&tid, &words, &createdBy)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
PreError("You can't like something which doesn't exist!",w,r) PreError("You can't like something which doesn't exist!",w,r)
@ -879,7 +875,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
} }
var fid int var fid int
err = db.QueryRow("select parentID from topics where tid = ?", tid).Scan(&fid) err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
PreError("The parent topic doesn't exist.",w,r) PreError("The parent topic doesn't exist.",w,r)
return return

View File

@ -91,6 +91,7 @@ type TopicStore interface {
Get(id int) (*Topic, error) Get(id int) (*Topic, error)
GetUnsafe(id int) (*Topic, error) GetUnsafe(id int) (*Topic, error)
CascadeGet(id int) (*Topic, error) CascadeGet(id int) (*Topic, error)
BypassGet(id int) (*Topic, error)
Set(item *Topic) error Set(item *Topic) error
Add(item *Topic) error Add(item *Topic) error
AddUnsafe(item *Topic) error AddUnsafe(item *Topic) error
@ -146,6 +147,12 @@ func (sts *StaticTopicStore) CascadeGet(id int) (*Topic, error) {
return topic, err return topic, err
} }
func (sts *StaticTopicStore) BypassGet(id int) (*Topic, error) {
topic := &Topic{ID:id}
err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount)
return topic, err
}
func (sts *StaticTopicStore) Load(id int) error { func (sts *StaticTopicStore) Load(id int) error {
topic := &Topic{ID:id} topic := &Topic{ID:id}
err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount)
@ -254,6 +261,12 @@ func (sus *SqlTopicStore) CascadeGet(id int) (*Topic, error) {
return &topic, err return &topic, err
} }
func (sts *SqlTopicStore) BypassGet(id int) (*Topic, error) {
topic := &Topic{ID:id}
err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount)
return topic, err
}
func (sus *SqlTopicStore) Load(id int) error { func (sus *SqlTopicStore) Load(id int) error {
topic := Topic{ID:id} topic := Topic{ID:id}
err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) err := get_topic_stmt.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount)

33
user.go
View File

@ -54,6 +54,7 @@ type UserStore interface {
Get(id int) (*User, error) Get(id int) (*User, error)
GetUnsafe(id int) (*User, error) GetUnsafe(id int) (*User, error)
CascadeGet(id int) (*User, error) CascadeGet(id int) (*User, error)
BypassGet(id int) (*User, error)
Set(item *User) error Set(item *User) error
Add(item *User) error Add(item *User) error
AddUnsafe(item *User) error AddUnsafe(item *User) error
@ -120,6 +121,22 @@ func (sts *StaticUserStore) CascadeGet(id int) (*User, error) {
return user, err return user, err
} }
func (sts *StaticUserStore) BypassGet(id int) (*User, error) {
user := &User{ID:id,Loggedin:true}
err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(user)
return user, err
}
func (sts *StaticUserStore) Load(id int) error { func (sts *StaticUserStore) Load(id int) error {
user := &User{ID:id,Loggedin:true} user := &User{ID:id,Loggedin:true}
err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP) err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
@ -275,6 +292,22 @@ func (sus *SqlUserStore) CascadeGet(id int) (*User, error) {
return &user, err return &user, err
} }
func (sus *SqlUserStore) BypassGet(id int) (*User, error) {
user := User{ID:id,Loggedin:true}
err := get_full_user_stmt.QueryRow(id).Scan(&user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.Last_IP)
if user.Avatar != "" {
if user.Avatar[0] == '.' {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
}
} else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1)
}
user.Tag = groups[user.Group].Tag
init_user_perms(&user)
return &user, err
}
func (sus *SqlUserStore) Load(id int) error { func (sus *SqlUserStore) Load(id int) error {
user := &User{ID:id} user := &User{ID:id}
// Simplify this into a quick check whether the user exists // Simplify this into a quick check whether the user exists