diff --git a/database.go b/database.go new file mode 100644 index 00000000..16e72def --- /dev/null +++ b/database.go @@ -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 +} diff --git a/gen_mysql.go b/gen_mysql.go index 983ccd84..3e3b4c6b 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -8,12 +8,19 @@ import "database/sql" var get_user_stmt *sql.Stmt var get_reply_stmt *sql.Stmt +var get_user_reply_stmt *sql.Stmt var login_stmt *sql.Stmt var get_password_stmt *sql.Stmt var username_exists_stmt *sql.Stmt var get_settings_stmt *sql.Stmt var get_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 get_users_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_rank_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_topic_stmt *sql.Stmt var delete_profile_reply_stmt *sql.Stmt var delete_forum_perms_by_forum_stmt *sql.Stmt +var report_exists_stmt *sql.Stmt func gen_mysql() (err error) { if debug { @@ -108,7 +118,13 @@ func gen_mysql() (err error) { } 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 { return err } @@ -149,6 +165,42 @@ func gen_mysql() (err error) { 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.") is_plugin_active_stmt, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?") if err != nil { @@ -228,7 +280,7 @@ func gen_mysql() (err error) { } 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 { return err } @@ -342,7 +394,7 @@ func gen_mysql() (err error) { } 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 { return err } @@ -611,6 +663,18 @@ func gen_mysql() (err error) { 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.") delete_reply_stmt, err = db.Prepare("DELETE FROM `replies` WHERE `rid` = ?") if err != nil { @@ -634,6 +698,12 @@ func gen_mysql() (err error) { if err != nil { 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 } diff --git a/mod_routes.go b/mod_routes.go index 89909868..ef4942ff 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -365,9 +365,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { return } - var tid, createdBy int - var content string - err = db.QueryRow("select tid, content, createdBy from replies where rid = ?", rid).Scan(&tid, &content, &createdBy) + reply, err := get_reply(rid) if err == sql.ErrNoRows { PreErrorJSQ("The reply you tried to delete doesn't exist.",w,r,is_js) return @@ -377,7 +375,7 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { } 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 { PreErrorJSQ("The parent topic doesn't exist.",w,r,is_js) return @@ -407,13 +405,13 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { w.Write(success_json_bytes) } - wcount := word_count(content) - err = decrease_post_user_stats(wcount, createdBy, false, user) + wcount := word_count(reply.Content) + err = decrease_post_user_stats(wcount, reply.CreatedBy, false, user) if err != nil { InternalErrorJSQ(err,w,r,is_js) return } - _, err = remove_replies_from_topic_stmt.Exec(1,tid) + _, err = remove_replies_from_topic_stmt.Exec(1,reply.ParentID) if err != nil { 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) return } - err = addModLog("delete",tid,"reply",ipaddress,user.ID) + err = addModLog("delete",reply.ParentID,"reply",ipaddress,user.ID) if err != nil { InternalError(err,w,r) return } - err = topics.Load(tid) + err = topics.Load(reply.ParentID) if err != nil { LocalError("This topic no longer exists!",w,r,user) return diff --git a/mysql.go b/mysql.go index f42225f8..24eb58a9 100644 --- a/mysql.go +++ b/mysql.go @@ -3,9 +3,7 @@ package main import "log" -import "fmt" import "strconv" -import "encoding/json" import "database/sql" import _ "github.com/go-sql-driver/mysql" import "./query_gen/lib" @@ -19,7 +17,6 @@ var get_forum_topics_offset_stmt *sql.Stmt var notify_watchers_stmt *sql.Stmt var get_activity_feed_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 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_report_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 != ""){ dbpassword = ":" + dbpassword } @@ -99,18 +95,6 @@ func init_database() (err error) { 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.") forum_entry_exists_stmt, err = db.Prepare("SELECT `fid` FROM `forums` WHERE `name` = '' order by fid asc limit 1") if err != nil { @@ -165,248 +149,5 @@ func init_database() (err error) { 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 } diff --git a/mysql.sql b/mysql.sql index 8db95612..a14e92c5 100644 --- a/mysql.sql +++ b/mysql.sql @@ -119,6 +119,7 @@ CREATE TABLE `users_replies`( `createdBy` int not null, `lastEdit` int not null, `lastEditBy` int not null, + `ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null, primary key(`rid`) ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; diff --git a/permissions.go b/permissions.go index e0b6f546..27f2e091 100644 --- a/permissions.go +++ b/permissions.go @@ -90,7 +90,7 @@ type Perms struct CloseTopic bool //CloseOwnTopic bool - ExtData interface{} + ExtData map[string]bool } /* 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": return AllForumPerms, true case "no_access": - return ForumPerms{Overrides: true}, true + return ForumPerms{Overrides: true,ExtData: make(map[string]bool)}, true case "default": return BlankForumPerms, true //case "custom": return fperms, false diff --git a/query_gen/lib/builder.go b/query_gen/lib/builder.go index cb592138..571c2a8a 100644 --- a/query_gen/lib/builder.go +++ b/query_gen/lib/builder.go @@ -35,3 +35,36 @@ func (build *builder) SimpleSelect(table string, columns string, where string, o } 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) +} diff --git a/query_gen/lib/mysql.go b/query_gen/lib/mysql.go index 4b5c13ac..51bc281d 100644 --- a/query_gen/lib/mysql.go +++ b/query_gen/lib/mysql.go @@ -441,6 +441,42 @@ func (adapter *Mysql_Adapter) SimpleInnerJoin(name string, table1 string, table2 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 { var stmts, body string diff --git a/query_gen/lib/querygen.go b/query_gen/lib/querygen.go index e367f981..ec97d593 100644 --- a/query_gen/lib/querygen.go +++ b/query_gen/lib/querygen.go @@ -66,6 +66,7 @@ type DB_Adapter interface { SimpleSelect(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) + SimpleCount(string,string,string/*,int,int*/) (string, error) Write() error // TO-DO: Add a simple query builder diff --git a/query_gen/main.go b/query_gen/main.go index b38b01a2..7c3861c9 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -42,6 +42,10 @@ func write_statements(adapter qgen.DB_Adapter) error { if err != nil { return err } + err = write_simple_counts(adapter) + if err != nil { + return err + } return nil } @@ -51,7 +55,9 @@ func write_selects(adapter qgen.DB_Adapter) error { // 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 = ?","") @@ -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_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("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_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 = ?","") @@ -144,7 +162,7 @@ func write_inserts(adapter qgen.DB_Adapter) error { 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") @@ -244,6 +262,10 @@ func write_updates(adapter qgen.DB_Adapter) error { 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 } @@ -258,4 +280,10 @@ func write_deletes(adapter qgen.DB_Adapter) error { adapter.SimpleDelete("delete_forum_perms_by_forum","forums_permissions","fid = ?") return nil -} \ No newline at end of file +} + +func write_simple_counts(adapter qgen.DB_Adapter) error { + adapter.SimpleCount("report_exists","topics","data = ? and data != '' and parentID = 1") + + return nil +} diff --git a/reply.go b/reply.go index 6590239c..aa007749 100644 --- a/reply.go +++ b/reply.go @@ -47,6 +47,12 @@ type ReplyShort struct func get_reply(id int) (*ReplyShort, error) { 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 } diff --git a/routes.go b/routes.go index eccb5b8d..3fdd28d0 100644 --- a/routes.go +++ b/routes.go @@ -877,8 +877,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - var tid, words, createdBy int - err = db.QueryRow("select tid, words, createdBy from replies where rid = ?", rid).Scan(&tid, &words, &createdBy) + reply, err := get_reply(rid) if err == sql.ErrNoRows { PreError("You can't like something which doesn't exist!",w,r) return @@ -888,7 +887,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { } 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 { PreError("The parent topic doesn't exist.",w,r) return @@ -906,7 +905,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - if createdBy == user.ID { + if reply.CreatedBy == user.ID { LocalError("You can't like your own replies",w,r,user) return } @@ -920,7 +919,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - _, err = users.CascadeGet(createdBy) + _, err = users.CascadeGet(reply.CreatedBy) if err != nil && err != sql.ErrNoRows { LocalError("The target user doesn't exist",w,r,user) return @@ -942,7 +941,7 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { 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 { InternalError(err,w,r) return @@ -953,16 +952,16 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - _, err = notify_one_stmt.Exec(createdBy,lastId) + _, err = notify_one_stmt.Exec(reply.CreatedBy,lastId) if err != nil { InternalError(err,w,r) return } // 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) { @@ -986,7 +985,13 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { 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 { InternalError(err,w,r) return @@ -1038,10 +1043,9 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string item_type := r.FormValue("type") var fid int = 1 - var tid int var title, content string 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 { LocalError("We were unable to find the reported post",w,r,user) return @@ -1050,7 +1054,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string return } - topic, err := topics.CascadeGet(tid) + topic, err := topics.CascadeGet(reply.ParentID) if err == sql.ErrNoRows { LocalError("We weren't able to find the topic the reported post is supposed to be in",w,r,user) return @@ -1060,9 +1064,9 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string } 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" { - 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 { LocalError("We weren't able to find the reported post",w,r,user) return @@ -1071,7 +1075,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string 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 { LocalError("We weren't able to find the profile the reported post is supposed to be on",w,r,user) return @@ -1080,7 +1084,7 @@ func route_report_submit(w http.ResponseWriter, r *http.Request, sitem_id string return } 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" { err = get_topic_basic_stmt.QueryRow(item_id).Scan(&title,&content) if err == sql.ErrNoRows { @@ -1396,7 +1400,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request) { defer rows.Close() for rows.Next() { - err := rows.Scan(&email.Email, &email.Validated) + err := rows.Scan(&email.Email, &email.Validated, &email.Token) if err != nil { 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} targetEmail := Email{UserID: user.ID} 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 { InternalError(err,w,r) return diff --git a/user.go b/user.go index 6c1e14ab..3fd1d222 100644 --- a/user.go +++ b/user.go @@ -94,6 +94,12 @@ func SimpleForumSessionCheck(w http.ResponseWriter, r *http.Request, fid int) (u user.Perms.DeleteReply = fperms.DeleteReply user.Perms.PinTopic = fperms.PinTopic user.Perms.CloseTopic = fperms.CloseTopic + + if len(fperms.ExtData) != 0 { + for name, perm := range fperms.ExtData { + user.Perms.ExtData[name] = perm + } + } } 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.PinTopic = fperms.PinTopic 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 { 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) return *user, false } + user.Last_IP = host } return *user, true } diff --git a/user_store.go b/user_store.go index da70ccd1..95ca6662 100644 --- a/user_store.go +++ b/user_store.go @@ -196,7 +196,7 @@ func (sus *StaticUserStore) GetCapacity() int { //} type SqlUserStore struct { - get *sql.Stmt + get *sql.Stmt } func NewSqlUserStore() *SqlUserStore {