Added a database engine neutral database.go file for the start-up queries.

Added SimpleCount to the query generator.
Moved more queries to the query generator.
Added the get_user_reply function for profile comments.
IP Addresses are now tracked for profile comments.
Added SimpleInsert, SimpleUpdate, SimpleDelete, and Purge to the inline query builder.
This commit is contained in:
Azareal 2017-06-14 08:09:44 +01:00
parent 93b4b269ed
commit fe2eabedd0
14 changed files with 485 additions and 299 deletions

255
database.go Normal file
View File

@ -0,0 +1,255 @@
package main
import "log"
import "fmt"
import "strconv"
import "encoding/json"
func init_database() (err error) {
// Engine specific code
err = _init_database()
if err != nil {
return err
}
log.Print("Loading the usergroups.")
groups = append(groups, Group{ID:0,Name:"System"})
rows, err := get_groups_stmt.Query()
if err != nil {
return err
}
defer rows.Close()
i := 1
for ;rows.Next();i++ {
group := Group{ID: 0,}
err := rows.Scan(&group.ID, &group.Name, &group.PermissionsText, &group.Is_Mod, &group.Is_Admin, &group.Is_Banned, &group.Tag)
if err != nil {
return err
}
// Ugh, you really shouldn't physically delete these items, it makes a big mess of things
if group.ID != i {
log.Print("Stop physically deleting groups. You are messing up the IDs. Use the Group Manager or delete_group() instead x.x")
fill_group_id_gap(i, group.ID)
}
err = json.Unmarshal(group.PermissionsText, &group.Perms)
if err != nil {
return err
}
if debug {
log.Print(group.Name + ": ")
fmt.Printf("%+v\n", group.Perms)
}
group.Perms.ExtData = make(map[string]bool)
groups = append(groups, group)
}
err = rows.Err()
if err != nil {
return err
}
groupCapCount = i
log.Print("Binding the Not Loggedin Group")
GuestPerms = groups[6].Perms
log.Print("Loading the forums.")
log.Print("Adding the uncategorised forum")
forums = append(forums, Forum{0,"Uncategorised","",uncategorised_forum_visible,"all",0,"",0,"",0,""})
//rows, err = db.Query("SELECT fid, name, active, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums")
//rows, err = db.Query("select `fid`, `name`, `desc`, `active`, `preset`, `topicCount`, `lastTopic`, `lastTopicID`, `lastReplyer`, `lastReplyerID`, `lastTopicTime` from forums order by fid asc")
rows, err = get_forums_stmt.Query()
if err != nil {
return err
}
defer rows.Close()
i = 1
for ;rows.Next();i++ {
forum := Forum{ID:0,Name:"",Active:true,Preset:"all"}
err := rows.Scan(&forum.ID, &forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.TopicCount, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime)
if err != nil {
return err
}
// Ugh, you really shouldn't physically delete these items, it makes a big mess of things
if forum.ID != i {
log.Print("Stop physically deleting forums. You are messing up the IDs. Use the Forum Manager or delete_forum() instead x.x")
fill_forum_id_gap(i, forum.ID)
}
if forum.Name == "" {
if debug {
log.Print("Adding a placeholder forum")
}
} else {
log.Print("Adding the " + forum.Name + " forum")
}
forums = append(forums,forum)
}
err = rows.Err()
if err != nil {
return err
}
forumCapCount = i
//log.Print("Adding the reports forum")
//forums[-1] = Forum{-1,"Reports",false,0,"",0,"",0,""}
log.Print("Loading the forum permissions")
rows, err = get_forums_permissions_stmt.Query()
if err != nil {
return err
}
defer rows.Close()
if debug {
log.Print("Adding the forum permissions")
}
// Temporarily store the forum perms in a map before transferring it to a much faster and thread-safe slice
forum_perms = make(map[int]map[int]ForumPerms)
for rows.Next() {
var gid, fid int
var perms []byte
var pperms ForumPerms
err := rows.Scan(&gid, &fid, &perms)
if err != nil {
return err
}
err = json.Unmarshal(perms, &pperms)
if err != nil {
return err
}
pperms.ExtData = make(map[string]bool)
pperms.Overrides = true
_, ok := forum_perms[gid]
if !ok {
forum_perms[gid] = make(map[int]ForumPerms)
}
forum_perms[gid][fid] = pperms
}
for gid, _ := range groups {
if debug {
log.Print("Adding the forum permissions for Group #" + strconv.Itoa(gid) + " - " + groups[gid].Name)
}
//groups[gid].Forums = append(groups[gid].Forums,BlankForumPerms) // GID 0. I sometimes wish MySQL's AUTO_INCREMENT would start at zero
for fid, _ := range forums {
forum_perm, ok := forum_perms[gid][fid]
if ok {
// Override group perms
//log.Print("Overriding permissions for forum #" + strconv.Itoa(fid))
groups[gid].Forums = append(groups[gid].Forums,forum_perm)
} else {
// Inherit from Group
//log.Print("Inheriting from default for forum #" + strconv.Itoa(fid))
forum_perm = BlankForumPerms
groups[gid].Forums = append(groups[gid].Forums,forum_perm)
}
if forum_perm.Overrides {
if forum_perm.ViewTopic {
groups[gid].CanSee = append(groups[gid].CanSee, fid)
}
} else if groups[gid].Perms.ViewTopic {
groups[gid].CanSee = append(groups[gid].CanSee, fid)
}
}
//fmt.Printf("%+v\n", groups[gid].CanSee)
//fmt.Printf("%+v\n", groups[gid].Forums)
//fmt.Println(len(groups[gid].CanSee))
//fmt.Println(len(groups[gid].Forums))
}
log.Print("Loading the settings.")
rows, err = get_full_settings_stmt.Query()
if err != nil {
return err
}
defer rows.Close()
var sname, scontent, stype, sconstraints string
for rows.Next() {
err := rows.Scan(&sname, &scontent, &stype, &sconstraints)
if err != nil {
return err
}
errmsg := parseSetting(sname, scontent, stype, sconstraints)
if errmsg != "" {
return err
}
}
err = rows.Err()
if err != nil {
return err
}
log.Print("Loading the plugins.")
rows, err = get_plugins_stmt.Query()
if err != nil {
return err
}
defer rows.Close()
var uname string
var active bool
for rows.Next() {
err := rows.Scan(&uname, &active)
if err != nil {
return err
}
// Was the plugin deleted at some point?
plugin, ok := plugins[uname]
if !ok {
continue
}
plugin.Active = active
plugins[uname] = plugin
}
err = rows.Err()
if err != nil {
return err
}
log.Print("Loading the themes.")
rows, err = get_themes_stmt.Query()
if err != nil {
return err
}
defer rows.Close()
var defaultThemeSwitch bool
for rows.Next() {
err := rows.Scan(&uname, &defaultThemeSwitch)
if err != nil {
return err
}
// Was the theme deleted at some point?
theme, ok := themes[uname]
if !ok {
continue
}
if defaultThemeSwitch {
log.Print("Loading the theme '" + theme.Name + "'")
theme.Active = true
defaultTheme = uname
add_theme_static_files(uname)
map_theme_templates(theme)
} else {
theme.Active = false
}
themes[uname] = theme
}
err = rows.Err()
if err != nil {
return err
}
return nil
}

View File

@ -8,12 +8,19 @@ import "database/sql"
var get_user_stmt *sql.Stmt var get_user_stmt *sql.Stmt
var get_reply_stmt *sql.Stmt var get_reply_stmt *sql.Stmt
var get_user_reply_stmt *sql.Stmt
var login_stmt *sql.Stmt var login_stmt *sql.Stmt
var get_password_stmt *sql.Stmt var get_password_stmt *sql.Stmt
var username_exists_stmt *sql.Stmt var username_exists_stmt *sql.Stmt
var get_settings_stmt *sql.Stmt 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 get_full_settings_stmt *sql.Stmt
var get_groups_stmt *sql.Stmt
var get_forums_stmt *sql.Stmt
var get_forums_permissions_stmt *sql.Stmt
var get_plugins_stmt *sql.Stmt
var get_themes_stmt *sql.Stmt
var is_plugin_active_stmt *sql.Stmt var is_plugin_active_stmt *sql.Stmt
var get_users_stmt *sql.Stmt var get_users_stmt *sql.Stmt
var is_theme_default_stmt *sql.Stmt var is_theme_default_stmt *sql.Stmt
@ -91,10 +98,13 @@ var update_user_stmt *sql.Stmt
var update_group_perms_stmt *sql.Stmt var update_group_perms_stmt *sql.Stmt
var update_group_rank_stmt *sql.Stmt var update_group_rank_stmt *sql.Stmt
var update_group_stmt *sql.Stmt var update_group_stmt *sql.Stmt
var update_email_stmt *sql.Stmt
var verify_email_stmt *sql.Stmt
var delete_reply_stmt *sql.Stmt var delete_reply_stmt *sql.Stmt
var delete_topic_stmt *sql.Stmt var delete_topic_stmt *sql.Stmt
var delete_profile_reply_stmt *sql.Stmt var delete_profile_reply_stmt *sql.Stmt
var delete_forum_perms_by_forum_stmt *sql.Stmt var delete_forum_perms_by_forum_stmt *sql.Stmt
var report_exists_stmt *sql.Stmt
func gen_mysql() (err error) { func gen_mysql() (err error) {
if debug { if debug {
@ -108,7 +118,13 @@ func gen_mysql() (err error) {
} }
log.Print("Preparing get_reply statement.") log.Print("Preparing get_reply statement.")
get_reply_stmt, err = db.Prepare("SELECT `content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress`,`likeCount` FROM `replies` WHERE `rid` = ?") get_reply_stmt, err = db.Prepare("SELECT `tid`,`content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress`,`likeCount` FROM `replies` WHERE `rid` = ?")
if err != nil {
return err
}
log.Print("Preparing get_user_reply statement.")
get_user_reply_stmt, err = db.Prepare("SELECT `uid`,`content`,`createdBy`,`createdAt`,`lastEdit`,`lastEditBy`,`ipaddress` FROM `users_replies` WHERE `rid` = ?")
if err != nil { if err != nil {
return err return err
} }
@ -149,6 +165,42 @@ func gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing get_full_settings statement.")
get_full_settings_stmt, err = db.Prepare("SELECT `name`,`content`,`type`,`constraints` FROM `settings`")
if err != nil {
return err
}
log.Print("Preparing get_groups statement.")
get_groups_stmt, err = db.Prepare("SELECT `gid`,`name`,`permissions`,`is_mod`,`is_admin`,`is_banned`,`tag` FROM `users_groups`")
if err != nil {
return err
}
log.Print("Preparing get_forums statement.")
get_forums_stmt, err = db.Prepare("SELECT `fid`,`name`,`desc`,`active`,`preset`,`topicCount`,`lastTopic`,`lastTopicID`,`lastReplyer`,`lastReplyerID`,`lastTopicTime` FROM `forums` ORDER BY fid ASC")
if err != nil {
return err
}
log.Print("Preparing get_forums_permissions statement.")
get_forums_permissions_stmt, err = db.Prepare("SELECT `gid`,`fid`,`permissions` FROM `forums_permissions` ORDER BY gid ASC,fid ASC")
if err != nil {
return err
}
log.Print("Preparing get_plugins statement.")
get_plugins_stmt, err = db.Prepare("SELECT `uname`,`active` FROM `plugins`")
if err != nil {
return err
}
log.Print("Preparing get_themes statement.")
get_themes_stmt, err = db.Prepare("SELECT `uname`,`default` FROM `themes`")
if err != nil {
return err
}
log.Print("Preparing is_plugin_active statement.") log.Print("Preparing is_plugin_active statement.")
is_plugin_active_stmt, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?") is_plugin_active_stmt, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?")
if err != nil { if err != nil {
@ -228,7 +280,7 @@ func gen_mysql() (err error) {
} }
log.Print("Preparing get_emails_by_user statement.") log.Print("Preparing get_emails_by_user statement.")
get_emails_by_user_stmt, err = db.Prepare("SELECT `email`,`validated` FROM `emails` WHERE `uid` = ?") get_emails_by_user_stmt, err = db.Prepare("SELECT `email`,`validated`,`token` FROM `emails` WHERE `uid` = ?")
if err != nil { if err != nil {
return err return err
} }
@ -342,7 +394,7 @@ func gen_mysql() (err error) {
} }
log.Print("Preparing create_profile_reply statement.") log.Print("Preparing create_profile_reply statement.")
create_profile_reply_stmt, err = db.Prepare("INSERT INTO `users_replies`(`uid`,`content`,`parsed_content`,`createdAt`,`createdBy`) VALUES (?,?,?,NOW(),?)") create_profile_reply_stmt, err = db.Prepare("INSERT INTO `users_replies`(`uid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`ipaddress`) VALUES (?,?,?,NOW(),?,?)")
if err != nil { if err != nil {
return err return err
} }
@ -611,6 +663,18 @@ func gen_mysql() (err error) {
return err return err
} }
log.Print("Preparing update_email statement.")
update_email_stmt, 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` = '1' WHERE `email` = ? ")
if err != nil {
return err
}
log.Print("Preparing delete_reply statement.") log.Print("Preparing delete_reply statement.")
delete_reply_stmt, err = db.Prepare("DELETE FROM `replies` WHERE `rid` = ?") delete_reply_stmt, err = db.Prepare("DELETE FROM `replies` WHERE `rid` = ?")
if err != nil { if err != nil {
@ -634,6 +698,12 @@ func gen_mysql() (err error) {
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing report_exists statement.")
report_exists_stmt, err = db.Prepare("SELECT COUNT(*) AS `count` FROM `topics` WHERE `data` = ? AND `data` != '' AND `parentID` = 1")
if err != nil {
return err
}
return nil return nil
} }

View File

@ -365,9 +365,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
var tid, createdBy int reply, err := get_reply(rid)
var content string
err = db.QueryRow("select tid, content, createdBy from replies where rid = ?", rid).Scan(&tid, &content, &createdBy)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
PreErrorJSQ("The reply you tried to delete doesn't exist.",w,r,is_js) PreErrorJSQ("The reply you tried to delete doesn't exist.",w,r,is_js)
return return
@ -377,7 +375,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
} }
var fid int var fid int
err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) err = get_topic_fid_stmt.QueryRow(reply.ParentID).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
@ -407,13 +405,13 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
w.Write(success_json_bytes) w.Write(success_json_bytes)
} }
wcount := word_count(content) wcount := word_count(reply.Content)
err = decrease_post_user_stats(wcount, createdBy, false, user) err = decrease_post_user_stats(wcount, reply.CreatedBy, false, user)
if err != nil { if err != nil {
InternalErrorJSQ(err,w,r,is_js) InternalErrorJSQ(err,w,r,is_js)
return return
} }
_, err = remove_replies_from_topic_stmt.Exec(1,tid) _, err = remove_replies_from_topic_stmt.Exec(1,reply.ParentID)
if err != nil { if err != nil {
InternalErrorJSQ(err,w,r,is_js) InternalErrorJSQ(err,w,r,is_js)
} }
@ -423,13 +421,13 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) {
LocalError("Bad IP",w,r,user) LocalError("Bad IP",w,r,user)
return return
} }
err = addModLog("delete",tid,"reply",ipaddress,user.ID) err = addModLog("delete",reply.ParentID,"reply",ipaddress,user.ID)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
} }
err = topics.Load(tid) err = topics.Load(reply.ParentID)
if err != nil { if err != nil {
LocalError("This topic no longer exists!",w,r,user) LocalError("This topic no longer exists!",w,r,user)
return return

261
mysql.go
View File

@ -3,9 +3,7 @@
package main package main
import "log" import "log"
import "fmt"
import "strconv" import "strconv"
import "encoding/json"
import "database/sql" import "database/sql"
import _ "github.com/go-sql-driver/mysql" import _ "github.com/go-sql-driver/mysql"
import "./query_gen/lib" import "./query_gen/lib"
@ -19,7 +17,6 @@ var get_forum_topics_offset_stmt *sql.Stmt
var notify_watchers_stmt *sql.Stmt var notify_watchers_stmt *sql.Stmt
var get_activity_feed_by_watcher_stmt *sql.Stmt var get_activity_feed_by_watcher_stmt *sql.Stmt
var get_activity_count_by_watcher_stmt *sql.Stmt var get_activity_count_by_watcher_stmt *sql.Stmt
var update_email_stmt, verify_email_stmt *sql.Stmt
var forum_entry_exists_stmt *sql.Stmt var forum_entry_exists_stmt *sql.Stmt
var group_entry_exists_stmt *sql.Stmt var group_entry_exists_stmt *sql.Stmt
@ -31,9 +28,8 @@ var todays_post_count_stmt *sql.Stmt
var todays_topic_count_stmt *sql.Stmt var todays_topic_count_stmt *sql.Stmt
var todays_report_count_stmt *sql.Stmt var todays_report_count_stmt *sql.Stmt
var todays_newuser_count_stmt *sql.Stmt var todays_newuser_count_stmt *sql.Stmt
var report_exists_stmt *sql.Stmt
func init_database() (err error) { func _init_database() (err error) {
if(dbpassword != ""){ if(dbpassword != ""){
dbpassword = ":" + dbpassword dbpassword = ":" + dbpassword
} }
@ -99,18 +95,6 @@ func init_database() (err error) {
return err return err
} }
log.Print("Preparing update_email statement.")
update_email_stmt, 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 = ?")
if err != nil {
return err
}
log.Print("Preparing forum_entry_exists statement.") log.Print("Preparing forum_entry_exists statement.")
forum_entry_exists_stmt, err = db.Prepare("SELECT `fid` FROM `forums` WHERE `name` = '' order by fid asc limit 1") forum_entry_exists_stmt, err = db.Prepare("SELECT `fid` FROM `forums` WHERE `name` = '' order by fid asc limit 1")
if err != nil { if err != nil {
@ -165,248 +149,5 @@ func init_database() (err error) {
return err return err
} }
log.Print("Preparing report_exists statement.")
report_exists_stmt, err = db.Prepare("select count(*) as count from topics where data = ? and data != '' and parentID = 1")
if err != nil {
return err
}
log.Print("Loading the usergroups.")
groups = append(groups, Group{ID:0,Name:"System"})
rows, err := db.Query("select gid,name,permissions,is_mod,is_admin,is_banned,tag from users_groups")
if err != nil {
return err
}
defer rows.Close()
i := 1
for ;rows.Next();i++ {
group := Group{ID: 0,}
err := rows.Scan(&group.ID, &group.Name, &group.PermissionsText, &group.Is_Mod, &group.Is_Admin, &group.Is_Banned, &group.Tag)
if err != nil {
return err
}
// Ugh, you really shouldn't physically delete these items, it makes a big mess of things
if group.ID != i {
log.Print("Stop physically deleting groups. You are messing up the IDs. Use the Group Manager or delete_group() instead x.x")
fill_group_id_gap(i, group.ID)
}
err = json.Unmarshal(group.PermissionsText, &group.Perms)
if err != nil {
return err
}
if debug {
log.Print(group.Name + ": ")
fmt.Printf("%+v\n", group.Perms)
}
group.Perms.ExtData = make(map[string]bool)
groups = append(groups, group)
}
err = rows.Err()
if err != nil {
return err
}
groupCapCount = i
log.Print("Binding the Not Loggedin Group")
GuestPerms = groups[6].Perms
log.Print("Loading the forums.")
log.Print("Adding the uncategorised forum")
forums = append(forums, Forum{0,"Uncategorised","",uncategorised_forum_visible,"all",0,"",0,"",0,""})
//rows, err = db.Query("SELECT fid, name, active, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime FROM forums")
rows, err = db.Query("select `fid`, `name`, `desc`, `active`, `preset`, `topicCount`, `lastTopic`, `lastTopicID`, `lastReplyer`, `lastReplyerID`, `lastTopicTime` from forums order by fid asc")
if err != nil {
return err
}
defer rows.Close()
i = 1
for ;rows.Next();i++ {
forum := Forum{ID:0,Name:"",Active:true,Preset:"all"}
err := rows.Scan(&forum.ID, &forum.Name, &forum.Desc, &forum.Active, &forum.Preset, &forum.TopicCount, &forum.LastTopic, &forum.LastTopicID, &forum.LastReplyer, &forum.LastReplyerID, &forum.LastTopicTime)
if err != nil {
return err
}
// Ugh, you really shouldn't physically delete these items, it makes a big mess of things
if forum.ID != i {
log.Print("Stop physically deleting forums. You are messing up the IDs. Use the Forum Manager or delete_forum() instead x.x")
fill_forum_id_gap(i, forum.ID)
}
if forum.Name == "" {
if debug {
log.Print("Adding a placeholder forum")
}
} else {
log.Print("Adding the " + forum.Name + " forum")
}
forums = append(forums,forum)
}
err = rows.Err()
if err != nil {
return err
}
forumCapCount = i
//log.Print("Adding the reports forum")
//forums[-1] = Forum{-1,"Reports",false,0,"",0,"",0,""}
log.Print("Loading the forum permissions")
rows, err = db.Query("select gid, fid, permissions from forums_permissions order by gid asc, fid asc")
if err != nil {
return err
}
defer rows.Close()
if debug {
log.Print("Adding the forum permissions")
}
// Temporarily store the forum perms in a map before transferring it to a much faster slice
forum_perms = make(map[int]map[int]ForumPerms)
for rows.Next() {
var gid, fid int
var perms []byte
var pperms ForumPerms
err := rows.Scan(&gid, &fid, &perms)
if err != nil {
return err
}
err = json.Unmarshal(perms, &pperms)
if err != nil {
return err
}
pperms.ExtData = make(map[string]bool)
pperms.Overrides = true
_, ok := forum_perms[gid]
if !ok {
forum_perms[gid] = make(map[int]ForumPerms)
}
forum_perms[gid][fid] = pperms
}
for gid, _ := range groups {
if debug {
log.Print("Adding the forum permissions for Group #" + strconv.Itoa(gid) + " - " + groups[gid].Name)
}
//groups[gid].Forums = append(groups[gid].Forums,BlankForumPerms) // GID 0. I sometimes wish MySQL's AUTO_INCREMENT would start at zero
for fid, _ := range forums {
forum_perm, ok := forum_perms[gid][fid]
if ok {
// Override group perms
//log.Print("Overriding permissions for forum #" + strconv.Itoa(fid))
groups[gid].Forums = append(groups[gid].Forums,forum_perm)
} else {
// Inherit from Group
//log.Print("Inheriting from default for forum #" + strconv.Itoa(fid))
forum_perm = BlankForumPerms
groups[gid].Forums = append(groups[gid].Forums,forum_perm)
}
if forum_perm.Overrides {
if forum_perm.ViewTopic {
groups[gid].CanSee = append(groups[gid].CanSee, fid)
}
} else if groups[gid].Perms.ViewTopic {
groups[gid].CanSee = append(groups[gid].CanSee, fid)
}
}
//fmt.Printf("%+v\n", groups[gid].CanSee)
//fmt.Printf("%+v\n", groups[gid].Forums)
//fmt.Println(len(groups[gid].CanSee))
//fmt.Println(len(groups[gid].Forums))
}
log.Print("Loading the settings.")
rows, err = db.Query("select name, content, type, constraints from settings")
if err != nil {
return err
}
defer rows.Close()
var sname, scontent, stype, sconstraints string
for rows.Next() {
err := rows.Scan(&sname, &scontent, &stype, &sconstraints)
if err != nil {
return err
}
errmsg := parseSetting(sname, scontent, stype, sconstraints)
if errmsg != "" {
return err
}
}
err = rows.Err()
if err != nil {
return err
}
log.Print("Loading the plugins.")
rows, err = db.Query("select uname, active from plugins")
if err != nil {
return err
}
defer rows.Close()
var uname string
var active bool
for rows.Next() {
err := rows.Scan(&uname, &active)
if err != nil {
return err
}
// Was the plugin deleted at some point?
plugin, ok := plugins[uname]
if !ok {
continue
}
plugin.Active = active
plugins[uname] = plugin
}
err = rows.Err()
if err != nil {
return err
}
log.Print("Loading the themes.")
rows, err = db.Query("select `uname`, `default` from `themes`")
if err != nil {
return err
}
defer rows.Close()
var defaultThemeSwitch bool
for rows.Next() {
err := rows.Scan(&uname, &defaultThemeSwitch)
if err != nil {
return err
}
// Was the theme deleted at some point?
theme, ok := themes[uname]
if !ok {
continue
}
if defaultThemeSwitch {
log.Print("Loading the theme '" + theme.Name + "'")
theme.Active = true
defaultTheme = uname
add_theme_static_files(uname)
map_theme_templates(theme)
} else {
theme.Active = false
}
themes[uname] = theme
}
err = rows.Err()
if err != nil {
return err
}
return nil return nil
} }

View File

@ -119,6 +119,7 @@ CREATE TABLE `users_replies`(
`createdBy` int not null, `createdBy` int not null,
`lastEdit` int not null, `lastEdit` int not null,
`lastEditBy` int not null, `lastEditBy` int not null,
`ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null,
primary key(`rid`) primary key(`rid`)
) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;

View File

@ -90,7 +90,7 @@ type Perms struct
CloseTopic bool CloseTopic bool
//CloseOwnTopic bool //CloseOwnTopic bool
ExtData interface{} ExtData map[string]bool
} }
/* Inherit from group permissions for ones we don't have */ /* Inherit from group permissions for ones we don't have */
@ -405,7 +405,7 @@ func group_forum_preset_to_forum_perms(preset string) (fperms ForumPerms, change
case "can_moderate": case "can_moderate":
return AllForumPerms, true return AllForumPerms, true
case "no_access": case "no_access":
return ForumPerms{Overrides: true}, true return ForumPerms{Overrides: true,ExtData: make(map[string]bool)}, true
case "default": case "default":
return BlankForumPerms, true return BlankForumPerms, true
//case "custom": return fperms, false //case "custom": return fperms, false

View File

@ -35,3 +35,36 @@ func (build *builder) SimpleSelect(table string, columns string, where string, o
} }
return build.conn.Prepare(res) return build.conn.Prepare(res)
} }
func (build *builder) SimpleInsert(table string, columns string, fields string) (stmt *sql.Stmt, err error) {
res, err := build.adapter.SimpleInsert("_builder", table, columns, fields)
if err != nil {
return stmt, err
}
return build.conn.Prepare(res)
}
func (build *builder) SimpleUpdate(table string, set string, where string) (stmt *sql.Stmt, err error) {
res, err := build.adapter.SimpleUpdate("_builder", table, set, where)
if err != nil {
return stmt, err
}
return build.conn.Prepare(res)
}
func (build *builder) SimpleDelete(table string, where string) (stmt *sql.Stmt, err error) {
res, err := build.adapter.SimpleDelete("_builder", table, where)
if err != nil {
return stmt, err
}
return build.conn.Prepare(res)
}
// I don't know why you need this, but here it is x.x
func (build *builder) Purge(table string) (stmt *sql.Stmt, err error) {
res, err := build.adapter.Purge("_builder", table)
if err != nil {
return stmt, err
}
return build.conn.Prepare(res)
}

View File

@ -441,6 +441,42 @@ func (adapter *Mysql_Adapter) SimpleInnerJoin(name string, table1 string, table2
return querystr, nil return querystr, nil
} }
func (adapter *Mysql_Adapter) SimpleCount(name string, table string, where string/*, offset int, maxCount int*/) (string, error) {
if name == "" {
return "", errors.New("You need a name for this statement")
}
if table == "" {
return "", errors.New("You need a name for this table")
}
var querystr string = "SELECT COUNT(*) AS `count` FROM `" + table + "`"
if len(where) != 0 {
querystr += " WHERE"
for _, loc := range _process_where(where) {
var left, right string
if loc.LeftType == "column" {
left = "`" + loc.LeftColumn + "`"
} else {
left = loc.LeftColumn
}
if loc.RightType == "column" {
right = "`" + loc.RightColumn + "`"
} else {
right = loc.RightColumn
}
querystr += " " + left + " " + loc.Operator + " " + right + " AND "
}
querystr = querystr[0:len(querystr) - 4]
}
querystr = strings.TrimSpace(querystr)
adapter.push_statement(name,querystr)
return querystr, nil
}
func (adapter *Mysql_Adapter) Write() error { func (adapter *Mysql_Adapter) Write() error {
var stmts, body string var stmts, body string

View File

@ -66,6 +66,7 @@ type DB_Adapter interface {
SimpleSelect(string,string,string,string,string/*,int,int*/) (string, error) SimpleSelect(string,string,string,string,string/*,int,int*/) (string, error)
SimpleLeftJoin(string,string,string,string,string,string,string/*,int,int*/) (string, error) SimpleLeftJoin(string,string,string,string,string,string,string/*,int,int*/) (string, error)
SimpleInnerJoin(string,string,string,string,string,string,string/*,int,int*/) (string, error) SimpleInnerJoin(string,string,string,string,string,string,string/*,int,int*/) (string, error)
SimpleCount(string,string,string/*,int,int*/) (string, error)
Write() error Write() error
// TO-DO: Add a simple query builder // TO-DO: Add a simple query builder

View File

@ -42,6 +42,10 @@ func write_statements(adapter qgen.DB_Adapter) error {
if err != nil { if err != nil {
return err return err
} }
err = write_simple_counts(adapter)
if err != nil {
return err
}
return nil return nil
} }
@ -51,7 +55,9 @@ func write_selects(adapter qgen.DB_Adapter) error {
// Looking for get_topic? Your statement is in another castle // Looking for get_topic? Your statement is in another castle
adapter.SimpleSelect("get_reply","replies","content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount","rid = ?","") adapter.SimpleSelect("get_reply","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("login","users","uid, name, password, salt","name = ?","") adapter.SimpleSelect("login","users","uid, name, password, salt","name = ?","")
@ -66,6 +72,18 @@ func write_selects(adapter qgen.DB_Adapter) error {
adapter.SimpleSelect("get_full_setting","settings","name, type, constraints","name = ?","") adapter.SimpleSelect("get_full_setting","settings","name, type, constraints","name = ?","")
adapter.SimpleSelect("get_full_settings","settings","name, content, type, constraints","","")
adapter.SimpleSelect("get_groups","users_groups","gid, name, permissions, is_mod, is_admin, is_banned, tag","","")
adapter.SimpleSelect("get_forums","forums","fid, name, desc, active, preset, topicCount, lastTopic, lastTopicID, lastReplyer, lastReplyerID, lastTopicTime","","fid ASC")
adapter.SimpleSelect("get_forums_permissions","forums_permissions","gid, fid, permissions","","gid ASC, fid ASC")
adapter.SimpleSelect("get_plugins","plugins","uname, active","","")
adapter.SimpleSelect("get_themes","themes","uname, default","","")
adapter.SimpleSelect("is_plugin_active","plugins","active","uname = ?","") adapter.SimpleSelect("is_plugin_active","plugins","active","uname = ?","")
adapter.SimpleSelect("get_users","users","uid, name, group, active, is_super_admin, avatar","","") adapter.SimpleSelect("get_users","users","uid, name, group, active, is_super_admin, avatar","","")
@ -92,7 +110,7 @@ func write_selects(adapter qgen.DB_Adapter) error {
adapter.SimpleSelect("get_user_group","users","group","uid = ?","") adapter.SimpleSelect("get_user_group","users","group","uid = ?","")
adapter.SimpleSelect("get_emails_by_user","emails","email, validated","uid = ?","") adapter.SimpleSelect("get_emails_by_user","emails","email, validated, token","uid = ?","")
adapter.SimpleSelect("get_topic_basic","topics","title, content","tid = ?","") adapter.SimpleSelect("get_topic_basic","topics","title, content","tid = ?","")
@ -144,7 +162,7 @@ func write_inserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("add_email","emails","email, uid, validated, token","?,?,?,?") adapter.SimpleInsert("add_email","emails","email, uid, validated, token","?,?,?,?")
adapter.SimpleInsert("create_profile_reply","users_replies","uid,content,parsed_content,createdAt,createdBy","?,?,?,NOW(),?") adapter.SimpleInsert("create_profile_reply","users_replies","uid, content, parsed_content, createdAt, createdBy, ipaddress","?,?,?,NOW(),?,?")
adapter.SimpleInsert("add_subscription","activity_subscriptions","user,targetID,targetType,level","?,?,?,2") adapter.SimpleInsert("add_subscription","activity_subscriptions","user,targetID,targetType,level","?,?,?,2")
@ -244,6 +262,10 @@ func write_updates(adapter qgen.DB_Adapter) error {
adapter.SimpleUpdate("update_group","users_groups","name = ?, tag = ?","gid = ?") adapter.SimpleUpdate("update_group","users_groups","name = ?, tag = ?","gid = ?")
adapter.SimpleUpdate("update_email","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
return nil return nil
} }
@ -258,4 +280,10 @@ func write_deletes(adapter qgen.DB_Adapter) error {
adapter.SimpleDelete("delete_forum_perms_by_forum","forums_permissions","fid = ?") adapter.SimpleDelete("delete_forum_perms_by_forum","forums_permissions","fid = ?")
return nil return nil
} }
func write_simple_counts(adapter qgen.DB_Adapter) error {
adapter.SimpleCount("report_exists","topics","data = ? and data != '' and parentID = 1")
return nil
}

View File

@ -47,6 +47,12 @@ type ReplyShort struct
func get_reply(id int) (*ReplyShort, error) { func get_reply(id int) (*ReplyShort, error) {
reply := ReplyShort{ID:id} reply := ReplyShort{ID:id}
err := get_reply_stmt.QueryRow(id).Scan(&reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IpAddress, &reply.LikeCount) err := get_reply_stmt.QueryRow(id).Scan(&reply.ParentID, &reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IpAddress, &reply.LikeCount)
return &reply, err
}
func get_user_reply(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)
return &reply, err return &reply, err
} }

View File

@ -877,8 +877,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
var tid, words, createdBy int reply, err := get_reply(rid)
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)
return return
@ -888,7 +887,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
} }
var fid int var fid int
err = get_topic_fid_stmt.QueryRow(tid).Scan(&fid) err = get_topic_fid_stmt.QueryRow(reply.ParentID).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
@ -906,7 +905,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
if createdBy == user.ID { if reply.CreatedBy == user.ID {
LocalError("You can't like your own replies",w,r,user) LocalError("You can't like your own replies",w,r,user)
return return
} }
@ -920,7 +919,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
_, err = users.CascadeGet(createdBy) _, err = users.CascadeGet(reply.CreatedBy)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
LocalError("The target user doesn't exist",w,r,user) LocalError("The target user doesn't exist",w,r,user)
return return
@ -942,7 +941,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
res, err := add_activity_stmt.Exec(user.ID,createdBy,"like","post",rid) res, err := add_activity_stmt.Exec(user.ID,reply.CreatedBy,"like","post",rid)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -953,16 +952,16 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) {
return return
} }
_, err = notify_one_stmt.Exec(createdBy,lastId) _, err = notify_one_stmt.Exec(reply.CreatedBy,lastId)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
} }
// Live alerts, if the poster is online and WebSockets is enabled // Live alerts, if the poster is online and WebSockets is enabled
_ = ws_hub.push_alert(createdBy,"like","post",user.ID,createdBy,rid) _ = ws_hub.push_alert(reply.CreatedBy,"like","post",user.ID,reply.CreatedBy,rid)
http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) http.Redirect(w,r,"/topic/" + strconv.Itoa(reply.ParentID),http.StatusSeeOther)
} }
func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { func route_profile_reply_create(w http.ResponseWriter, r *http.Request) {
@ -986,7 +985,13 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) {
return return
} }
_, err = create_profile_reply_stmt.Exec(uid,html.EscapeString(preparse_message(r.PostFormValue("reply-content"))),parse_message(html.EscapeString(preparse_message(r.PostFormValue("reply-content")))),user.ID) ipaddress, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
LocalError("Bad IP",w,r,user)
return
}
_, err = create_profile_reply_stmt.Exec(uid,html.EscapeString(preparse_message(r.PostFormValue("reply-content"))),parse_message(html.EscapeString(preparse_message(r.PostFormValue("reply-content")))),user.ID,ipaddress)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -1038,10 +1043,9 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string
item_type := r.FormValue("type") item_type := r.FormValue("type")
var fid int = 1 var fid int = 1
var tid int
var title, content string var title, content string
if item_type == "reply" { if item_type == "reply" {
err = db.QueryRow("select tid, content from replies where rid = ?", item_id).Scan(&tid, &content) reply, err := get_reply(item_id)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
LocalError("We were unable to find the reported post",w,r,user) LocalError("We were unable to find the reported post",w,r,user)
return return
@ -1050,7 +1054,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string
return return
} }
topic, err := topics.CascadeGet(tid) topic, err := topics.CascadeGet(reply.ParentID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
LocalError("We weren't able to find the topic the reported post is supposed to be in",w,r,user) LocalError("We weren't able to find the topic the reported post is supposed to be in",w,r,user)
return return
@ -1060,9 +1064,9 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string
} }
title = "Reply: " + topic.Title title = "Reply: " + topic.Title
content = content + "\n\nOriginal Post: #rid-" + strconv.Itoa(item_id) content = reply.Content + "\n\nOriginal Post: #rid-" + strconv.Itoa(item_id)
} else if item_type == "user-reply" { } else if item_type == "user-reply" {
err = db.QueryRow("select uid, content from users_replies where rid = ?", item_id).Scan(&tid, &content) user_reply, err := get_user_reply(item_id)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
LocalError("We weren't able to find the reported post",w,r,user) LocalError("We weren't able to find the reported post",w,r,user)
return return
@ -1071,7 +1075,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string
return return
} }
err = get_user_name_stmt.QueryRow(tid).Scan(&title) err = get_user_name_stmt.QueryRow(user_reply.ParentID).Scan(&title)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
LocalError("We weren't able to find the profile the reported post is supposed to be on",w,r,user) LocalError("We weren't able to find the profile the reported post is supposed to be on",w,r,user)
return return
@ -1080,7 +1084,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string
return return
} }
title = "Profile: " + title title = "Profile: " + title
content = content + "\n\nOriginal Post: @" + strconv.Itoa(tid) content = user_reply.Content + "\n\nOriginal Post: @" + strconv.Itoa(user_reply.ParentID)
} else if item_type == "topic" { } else if item_type == "topic" {
err = get_topic_basic_stmt.QueryRow(item_id).Scan(&title,&content) err = get_topic_basic_stmt.QueryRow(item_id).Scan(&title,&content)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
@ -1396,7 +1400,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) {
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
err := rows.Scan(&email.Email, &email.Validated) err := rows.Scan(&email.Email, &email.Validated, &email.Token)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -1441,7 +1445,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re
email := Email{UserID: user.ID} email := Email{UserID: user.ID}
targetEmail := Email{UserID: user.ID} targetEmail := Email{UserID: user.ID}
var emailList []interface{} var emailList []interface{}
rows, err := db.Query("select email, validated, token from emails where uid = ?", user.ID) rows, err := get_emails_by_user_stmt.Query(user.ID)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return

13
user.go
View File

@ -94,6 +94,12 @@ func SimpleForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (u
user.Perms.DeleteReply = fperms.DeleteReply user.Perms.DeleteReply = fperms.DeleteReply
user.Perms.PinTopic = fperms.PinTopic user.Perms.PinTopic = fperms.PinTopic
user.Perms.CloseTopic = fperms.CloseTopic user.Perms.CloseTopic = fperms.CloseTopic
if len(fperms.ExtData) != 0 {
for name, perm := range fperms.ExtData {
user.Perms.ExtData[name] = perm
}
}
} }
return user, success return user, success
} }
@ -118,6 +124,12 @@ func ForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (user Us
user.Perms.DeleteReply = fperms.DeleteReply user.Perms.DeleteReply = fperms.DeleteReply
user.Perms.PinTopic = fperms.PinTopic user.Perms.PinTopic = fperms.PinTopic
user.Perms.CloseTopic = fperms.CloseTopic user.Perms.CloseTopic = fperms.CloseTopic
if len(fperms.ExtData) != 0 {
for name, perm := range fperms.ExtData {
user.Perms.ExtData[name] = perm
}
}
} }
if user.Is_Banned { if user.Is_Banned {
noticeList = append(noticeList,"Your account has been suspended. Some of your permissions may have been revoked.") noticeList = append(noticeList,"Your account has been suspended. Some of your permissions may have been revoked.")
@ -178,6 +190,7 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (User,bool) {
InternalError(err,w,r) InternalError(err,w,r)
return *user, false return *user, false
} }
user.Last_IP = host
} }
return *user, true return *user, true
} }

View File

@ -196,7 +196,7 @@ func (sus *StaticUserStore) GetCapacity() int {
//} //}
type SqlUserStore struct { type SqlUserStore struct {
get *sql.Stmt get *sql.Stmt
} }
func NewSqlUserStore() *SqlUserStore { func NewSqlUserStore() *SqlUserStore {