Updated the codebeat and codeclimate config files.
Renamed the pre_render_view_forum hook to pre_render_forum. Renamed the pre_render_ips hook to pre_render_ip_search. Renamed routeTopicCreate to CreateTopic and moved it into /routes/topic.go Moved three routes into /routes/user.go Renamed routeIps to IPSearch and moved it into /routes/moderate.go Moved the IP Search logic out of the route and into the DefaultIPSearcher. Added InQ() to the select builders and replaced three hand-rolled queries with it. De-duplicated some pagination logic.
This commit is contained in:
parent
2997135e80
commit
8252c481df
|
@ -1,3 +1,4 @@
|
|||
/public/chartist/**
|
||||
/public/trumbowyg/**
|
||||
/public/jquery-emojiarea/**
|
||||
/public/font-awesome-4.7.0/**
|
||||
|
@ -17,3 +18,4 @@ template_profile.go
|
|||
gen_mysql.go
|
||||
gen_mssql.go
|
||||
gen_pgsql.go
|
||||
gen_router.go
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
exclude_patterns:
|
||||
- "gen_*"
|
||||
- "schema/*"
|
||||
- "public/chartist/*"
|
||||
- "public/trumbowyg/*"
|
||||
- "public/jquery-emojiarea/*"
|
||||
- "public/font-awesome-4.7.0/*"
|
||||
- "public/jquery-3.1.1.min.js"
|
||||
- "public/EQCSS.min.js"
|
||||
- "public/EQCSS.js"
|
||||
- "template_list.go"
|
||||
- "template_forum.go"
|
||||
- "template_forums.go"
|
||||
- "template_topic.go"
|
||||
- "template_topic_alt.go"
|
||||
- "template_topics.go"
|
||||
- "template_profile.go"
|
|
@ -75,7 +75,7 @@ var PreRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User
|
|||
"pre_render": nil,
|
||||
|
||||
"pre_render_forum_list": nil,
|
||||
"pre_render_view_forum": nil,
|
||||
"pre_render_forum": nil,
|
||||
"pre_render_topic_list": nil,
|
||||
"pre_render_view_topic": nil,
|
||||
"pre_render_profile": nil,
|
||||
|
@ -90,7 +90,7 @@ var PreRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User
|
|||
"pre_render_login": nil,
|
||||
"pre_render_register": nil,
|
||||
"pre_render_ban": nil,
|
||||
"pre_render_ips": nil,
|
||||
"pre_render_ip_search": nil,
|
||||
|
||||
"pre_render_panel_dashboard": nil,
|
||||
"pre_render_panel_forums": nil,
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var IPSearch IPSearcher
|
||||
|
||||
type IPSearcher interface {
|
||||
Lookup(ip string) (uids []int, err error)
|
||||
}
|
||||
|
||||
type DefaultIPSearcher struct {
|
||||
searchUsers *sql.Stmt
|
||||
searchReplies *sql.Stmt
|
||||
searchTopics *sql.Stmt
|
||||
}
|
||||
|
||||
// NewDefaultIPSearcher gives you a new instance of DefaultIPSearcher
|
||||
func NewDefaultIPSearcher() (*DefaultIPSearcher, error) {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
return &DefaultIPSearcher{
|
||||
searchUsers: acc.Select("users").Columns("uid").Where("last_ip = ?").Prepare(),
|
||||
searchTopics: acc.Select("users").Columns("uid").InQ("uid", acc.Select("topics").Columns("createdBy").Where("ipaddress = ?")).Prepare(),
|
||||
searchReplies: acc.Select("users").Columns("uid").InQ("uid", acc.Select("replies").Columns("createdBy").Where("ipaddress = ?")).Prepare(),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (searcher *DefaultIPSearcher) Lookup(ip string) (uids []int, err error) {
|
||||
var uid int
|
||||
var reqUserList = make(map[int]bool)
|
||||
|
||||
var runQuery = func(stmt *sql.Stmt) error {
|
||||
rows, err := stmt.Query(ip)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
err = runQuery(searcher.searchUsers)
|
||||
if err != nil {
|
||||
return uids, err
|
||||
}
|
||||
|
||||
err = runQuery(searcher.searchTopics)
|
||||
if err != nil {
|
||||
return uids, err
|
||||
}
|
||||
|
||||
err = runQuery(searcher.searchReplies)
|
||||
if err != nil {
|
||||
return uids, err
|
||||
}
|
||||
|
||||
// Convert the user ID map to a slice, then bulk load the users
|
||||
uids = make([]int, len(reqUserList))
|
||||
var i int
|
||||
for userID := range reqUserList {
|
||||
uids[i] = userID
|
||||
i++
|
||||
}
|
||||
|
||||
return uids, nil
|
||||
}
|
|
@ -64,9 +64,6 @@ type Stmts struct {
|
|||
todaysTopicCount *sql.Stmt
|
||||
todaysReportCount *sql.Stmt
|
||||
todaysNewUserCount *sql.Stmt
|
||||
findUsersByIPUsers *sql.Stmt
|
||||
findUsersByIPTopics *sql.Stmt
|
||||
findUsersByIPReplies *sql.Stmt
|
||||
|
||||
Mocks bool
|
||||
}
|
||||
|
|
|
@ -66,9 +66,6 @@ type Stmts struct {
|
|||
todaysTopicCount *sql.Stmt
|
||||
todaysReportCount *sql.Stmt
|
||||
todaysNewUserCount *sql.Stmt
|
||||
findUsersByIPUsers *sql.Stmt
|
||||
findUsersByIPTopics *sql.Stmt
|
||||
findUsersByIPReplies *sql.Stmt
|
||||
|
||||
Mocks bool
|
||||
}
|
||||
|
|
|
@ -28,9 +28,6 @@ type Stmts struct {
|
|||
todaysTopicCount *sql.Stmt
|
||||
todaysReportCount *sql.Stmt
|
||||
todaysNewUserCount *sql.Stmt
|
||||
findUsersByIPUsers *sql.Stmt
|
||||
findUsersByIPTopics *sql.Stmt
|
||||
findUsersByIPReplies *sql.Stmt
|
||||
|
||||
Mocks bool
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ var RouteMap = map[string]interface{}{
|
|||
"routeShowAttachment": routeShowAttachment,
|
||||
"routeWebsockets": routeWebsockets,
|
||||
"routeReportSubmit": routeReportSubmit,
|
||||
"routeTopicCreate": routeTopicCreate,
|
||||
"routes.CreateTopic": routes.CreateTopic,
|
||||
"routeTopics": routeTopics,
|
||||
"routePanelForums": routePanelForums,
|
||||
"routePanelForumsCreateSubmit": routePanelForumsCreateSubmit,
|
||||
|
@ -79,11 +79,11 @@ var RouteMap = map[string]interface{}{
|
|||
"routeAccountEditEmail": routeAccountEditEmail,
|
||||
"routeAccountEditEmailTokenSubmit": routeAccountEditEmailTokenSubmit,
|
||||
"routeProfile": routeProfile,
|
||||
"routeBanSubmit": routeBanSubmit,
|
||||
"routeUnban": routeUnban,
|
||||
"routeActivate": routeActivate,
|
||||
"routeIps": routeIps,
|
||||
"routeTopicCreateSubmit": routeTopicCreateSubmit,
|
||||
"routes.BanUserSubmit": routes.BanUserSubmit,
|
||||
"routes.UnbanUser": routes.UnbanUser,
|
||||
"routes.ActivateUser": routes.ActivateUser,
|
||||
"routes.IPSearch": routes.IPSearch,
|
||||
"routeCreateTopicSubmit": routeCreateTopicSubmit,
|
||||
"routes.EditTopicSubmit": routes.EditTopicSubmit,
|
||||
"routes.DeleteTopicSubmit": routes.DeleteTopicSubmit,
|
||||
"routes.StickTopicSubmit": routes.StickTopicSubmit,
|
||||
|
@ -120,7 +120,7 @@ var routeMapEnum = map[string]int{
|
|||
"routeShowAttachment": 6,
|
||||
"routeWebsockets": 7,
|
||||
"routeReportSubmit": 8,
|
||||
"routeTopicCreate": 9,
|
||||
"routes.CreateTopic": 9,
|
||||
"routeTopics": 10,
|
||||
"routePanelForums": 11,
|
||||
"routePanelForumsCreateSubmit": 12,
|
||||
|
@ -174,11 +174,11 @@ var routeMapEnum = map[string]int{
|
|||
"routeAccountEditEmail": 60,
|
||||
"routeAccountEditEmailTokenSubmit": 61,
|
||||
"routeProfile": 62,
|
||||
"routeBanSubmit": 63,
|
||||
"routeUnban": 64,
|
||||
"routeActivate": 65,
|
||||
"routeIps": 66,
|
||||
"routeTopicCreateSubmit": 67,
|
||||
"routes.BanUserSubmit": 63,
|
||||
"routes.UnbanUser": 64,
|
||||
"routes.ActivateUser": 65,
|
||||
"routes.IPSearch": 66,
|
||||
"routeCreateTopicSubmit": 67,
|
||||
"routes.EditTopicSubmit": 68,
|
||||
"routes.DeleteTopicSubmit": 69,
|
||||
"routes.StickTopicSubmit": 70,
|
||||
|
@ -213,7 +213,7 @@ var reverseRouteMapEnum = map[int]string{
|
|||
6: "routeShowAttachment",
|
||||
7: "routeWebsockets",
|
||||
8: "routeReportSubmit",
|
||||
9: "routeTopicCreate",
|
||||
9: "routes.CreateTopic",
|
||||
10: "routeTopics",
|
||||
11: "routePanelForums",
|
||||
12: "routePanelForumsCreateSubmit",
|
||||
|
@ -267,11 +267,11 @@ var reverseRouteMapEnum = map[int]string{
|
|||
60: "routeAccountEditEmail",
|
||||
61: "routeAccountEditEmailTokenSubmit",
|
||||
62: "routeProfile",
|
||||
63: "routeBanSubmit",
|
||||
64: "routeUnban",
|
||||
65: "routeActivate",
|
||||
66: "routeIps",
|
||||
67: "routeTopicCreateSubmit",
|
||||
63: "routes.BanUserSubmit",
|
||||
64: "routes.UnbanUser",
|
||||
65: "routes.ActivateUser",
|
||||
66: "routes.IPSearch",
|
||||
67: "routeCreateTopicSubmit",
|
||||
68: "routes.EditTopicSubmit",
|
||||
69: "routes.DeleteTopicSubmit",
|
||||
70: "routes.StickTopicSubmit",
|
||||
|
@ -657,7 +657,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
common.RouteViewCounter.Bump(9)
|
||||
err = routeTopicCreate(w,req,user,extraData)
|
||||
err = routes.CreateTopic(w,req,user,extraData)
|
||||
default:
|
||||
common.RouteViewCounter.Bump(10)
|
||||
err = routeTopics(w,req,user)
|
||||
|
@ -1083,7 +1083,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
common.RouteViewCounter.Bump(63)
|
||||
err = routeBanSubmit(w,req,user,extraData)
|
||||
err = routes.BanUserSubmit(w,req,user,extraData)
|
||||
case "/users/unban/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
|
@ -1098,7 +1098,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
common.RouteViewCounter.Bump(64)
|
||||
err = routeUnban(w,req,user,extraData)
|
||||
err = routes.UnbanUser(w,req,user,extraData)
|
||||
case "/users/activate/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
|
@ -1113,7 +1113,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
common.RouteViewCounter.Bump(65)
|
||||
err = routeActivate(w,req,user,extraData)
|
||||
err = routes.ActivateUser(w,req,user,extraData)
|
||||
case "/users/ips/":
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
|
@ -1122,7 +1122,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
common.RouteViewCounter.Bump(66)
|
||||
err = routeIps(w,req,user)
|
||||
err = routes.IPSearch(w,req,user)
|
||||
}
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
|
@ -1143,7 +1143,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
|
||||
common.RouteViewCounter.Bump(67)
|
||||
err = routeTopicCreateSubmit(w,req,user)
|
||||
err = routeCreateTopicSubmit(w,req,user)
|
||||
case "/topic/edit/submit/":
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
|
|
5
main.go
5
main.go
|
@ -80,6 +80,11 @@ func afterDBInit() (err error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
common.IPSearch, err = common.NewDefaultIPSearcher()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
common.GlobalViewCounter, err = common.NewGlobalViewCounter()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
105
member_routes.go
105
member_routes.go
|
@ -16,110 +16,7 @@ import (
|
|||
"./common"
|
||||
)
|
||||
|
||||
// Experimenting
|
||||
/*func memberRenderTemplate(tmplName string, themeName string, w http.ResponseWriter, r *http.Request, user common.User, pi interface{}) common.RouteError {
|
||||
if common.PreRenderHooks["pre_render_"+tmplName] != nil {
|
||||
if common.RunPreRenderHook("pre_render_"+tmplName, w, r, &user, pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
err := common.RunThemeTemplate(themeName, tmplName, pi, w)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}*/
|
||||
|
||||
// ? - Should we add a new permission or permission zone (like per-forum permissions) specifically for profile comment creation
|
||||
// ? - Should we allow banned users to make reports? How should we handle report abuse?
|
||||
// TODO: Add a permission to stop certain users from using custom avatars
|
||||
// ? - Log username changes and put restrictions on this?
|
||||
func routeTopicCreate(w http.ResponseWriter, r *http.Request, user common.User, sfid string) common.RouteError {
|
||||
var fid int
|
||||
var err error
|
||||
if sfid != "" {
|
||||
fid, err = strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return common.LocalError("You didn't provide a valid number for the forum ID.", w, r, user)
|
||||
}
|
||||
}
|
||||
if fid == 0 {
|
||||
fid = common.Config.DefaultForum
|
||||
}
|
||||
|
||||
headerVars, ferr := common.ForumUserCheck(w, r, &user, fid)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.CreateTopic {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
headerVars.Zone = "create_topic"
|
||||
|
||||
// Lock this to the forum being linked?
|
||||
// Should we always put it in strictmode when it's linked from another forum? Well, the user might end up changing their mind on what forum they want to post in and it would be a hassle, if they had to switch pages, even if it is a single click for many (exc. mobile)
|
||||
var strictmode bool
|
||||
if common.Vhooks["topic_create_pre_loop"] != nil {
|
||||
common.RunVhook("topic_create_pre_loop", w, r, fid, &headerVars, &user, &strictmode)
|
||||
}
|
||||
|
||||
// TODO: Re-add support for plugin_guilds
|
||||
var forumList []common.Forum
|
||||
var canSee []int
|
||||
if user.IsSuperAdmin {
|
||||
canSee, err = common.Forums.GetAllVisibleIDs()
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
} else {
|
||||
group, err := common.Groups.Get(user.Group)
|
||||
if err != nil {
|
||||
// TODO: Refactor this
|
||||
common.LocalError("Something weird happened behind the scenes", w, r, user)
|
||||
log.Printf("Group #%d doesn't exist, but it's set on common.User #%d", user.Group, user.ID)
|
||||
return nil
|
||||
}
|
||||
canSee = group.CanSee
|
||||
}
|
||||
|
||||
// TODO: plugin_superadmin needs to be able to override this loop. Skip flag on topic_create_pre_loop?
|
||||
for _, ffid := range canSee {
|
||||
// TODO: Surely, there's a better way of doing this. I've added it in for now to support plugin_guilds, but we really need to clean this up
|
||||
if strictmode && ffid != fid {
|
||||
continue
|
||||
}
|
||||
|
||||
// Do a bulk forum fetch, just in case it's the SqlForumStore?
|
||||
forum := common.Forums.DirtyGet(ffid)
|
||||
if forum.Name != "" && forum.Active {
|
||||
fcopy := forum.Copy()
|
||||
if common.Hooks["topic_create_frow_assign"] != nil {
|
||||
// TODO: Add the skip feature to all the other row based hooks?
|
||||
if common.RunHook("topic_create_frow_assign", &fcopy).(bool) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
forumList = append(forumList, fcopy)
|
||||
}
|
||||
}
|
||||
|
||||
ctpage := common.CreateTopicPage{"Create Topic", user, headerVars, forumList, fid}
|
||||
if common.PreRenderHooks["pre_render_create_topic"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_create_topic", w, r, &user, &ctpage) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
err = common.RunThemeTemplate(headerVars.Theme.Name, "create_topic", ctpage, w)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// POST functions. Authorised users only.
|
||||
func routeTopicCreateSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
func routeCreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
// TODO: Reduce this to 1MB for attachments for each file?
|
||||
if r.ContentLength > int64(common.Config.MaxRequestSize) {
|
||||
size, unit := common.ConvertByteUnit(float64(common.Config.MaxRequestSize))
|
||||
|
|
29
mssql.go
29
mssql.go
|
@ -75,56 +75,41 @@ func initMSSQL() (err error) {
|
|||
}
|
||||
|
||||
// TODO: Is there a less noisy way of doing this for tests?
|
||||
log.Print("Preparing get_activity_feed_by_watcher statement.")
|
||||
log.Print("Preparing getActivityFeedByWatcher statement.")
|
||||
getActivityFeedByWatcherStmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM [activity_stream_matches] INNER JOIN [activity_stream] ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE [watcher] = ? ORDER BY activity_stream.asid ASC OFFSET 0 ROWS FETCH NEXT 8 ROWS ONLY")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing get_activity_count_by_watcher statement.")
|
||||
log.Print("Preparing getActivityCountByWatcher statement.")
|
||||
getActivityCountByWatcherStmt, err = db.Prepare("SELECT count(*) FROM [activity_stream_matches] INNER JOIN [activity_stream] ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE [watcher] = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_post_count statement.")
|
||||
log.Print("Preparing todaysPostCount statement.")
|
||||
todaysPostCountStmt, err = db.Prepare("select count(*) from replies where createdAt >= DATEADD(DAY, -1, GETUTCDATE())")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_topic_count statement.")
|
||||
log.Print("Preparing todaysTopicCount statement.")
|
||||
todaysTopicCountStmt, err = db.Prepare("select count(*) from topics where createdAt >= DATEADD(DAY, -1, GETUTCDATE())")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_report_count statement.")
|
||||
log.Print("Preparing todaysReportCount statement.")
|
||||
todaysReportCountStmt, err = db.Prepare("select count(*) from topics where createdAt >= DATEADD(DAY, -1, GETUTCDATE()) and parentID = 1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_newuser_count statement.")
|
||||
log.Print("Preparing todaysNewUserCount statement.")
|
||||
todaysNewUserCountStmt, err = db.Prepare("select count(*) from users where createdAt >= DATEADD(DAY, -1, GETUTCDATE())")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ? - Why is this a custom query? Are we planning a union or something?
|
||||
log.Print("Preparing find_users_by_ip_users statement.")
|
||||
findUsersByIPUsersStmt, err = db.Prepare("select uid from users where last_ip = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing find_users_by_ip_topics statement.")
|
||||
findUsersByIPTopicsStmt, err = db.Prepare("select uid from users where uid in(select createdBy from topics where ipaddress = ?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing find_users_by_ip_replies statement.")
|
||||
findUsersByIPRepliesStmt, err = db.Prepare("select uid from users where uid in(select createdBy from replies where ipaddress = ?)")
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
|
28
mysql.go
28
mysql.go
|
@ -69,55 +69,41 @@ func initMySQL() (err error) {
|
|||
}
|
||||
|
||||
// TODO: Is there a less noisy way of doing this for tests?
|
||||
log.Print("Preparing get_activity_feed_by_watcher statement.")
|
||||
log.Print("Preparing getActivityFeedByWatcher statement.")
|
||||
stmts.getActivityFeedByWatcher, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing get_activity_count_by_watcher statement.")
|
||||
log.Print("Preparing getActivityCountByWatcher statement.")
|
||||
stmts.getActivityCountByWatcher, err = db.Prepare("SELECT count(*) FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_post_count statement.")
|
||||
log.Print("Preparing todaysPostCount statement.")
|
||||
stmts.todaysPostCount, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_topic_count statement.")
|
||||
log.Print("Preparing todaysTopicCount statement.")
|
||||
stmts.todaysTopicCount, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_report_count statement.")
|
||||
log.Print("Preparing todaysReportCount statement.")
|
||||
stmts.todaysReportCount, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp() and parentID = 1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing todays_newuser_count statement.")
|
||||
log.Print("Preparing todaysNewUserCount statement.")
|
||||
stmts.todaysNewUserCount, err = db.Prepare("select count(*) from users where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing find_users_by_ip_users statement.")
|
||||
stmts.findUsersByIPUsers, err = db.Prepare("select uid from users where last_ip = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing find_users_by_ip_topics statement.")
|
||||
stmts.findUsersByIPTopics, err = db.Prepare("select uid from users where uid in(select createdBy from topics where ipaddress = ?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing find_users_by_ip_replies statement.")
|
||||
stmts.findUsersByIPReplies, err = db.Prepare("select uid from users where uid in(select createdBy from replies where ipaddress = ?)")
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func initGuilds() (err error) {
|
|||
common.Plugins["guilds"].AddHook("intercept_build_widgets", guilds.Widgets)
|
||||
common.Plugins["guilds"].AddHook("trow_assign", guilds.TrowAssign)
|
||||
common.Plugins["guilds"].AddHook("topic_create_pre_loop", guilds.TopicCreatePreLoop)
|
||||
common.Plugins["guilds"].AddHook("pre_render_view_forum", guilds.PreRenderViewForum)
|
||||
common.Plugins["guilds"].AddHook("pre_render_forum", guilds.PreRenderViewForum)
|
||||
common.Plugins["guilds"].AddHook("simple_forum_check_pre_perms", guilds.ForumCheck)
|
||||
common.Plugins["guilds"].AddHook("forum_check_pre_perms", guilds.ForumCheck)
|
||||
// TODO: Auto-grant this perm to admins upon installation?
|
||||
|
@ -61,7 +61,7 @@ func deactivateGuilds() {
|
|||
common.Plugins["guilds"].RemoveHook("intercept_build_widgets", guilds.Widgets)
|
||||
common.Plugins["guilds"].RemoveHook("trow_assign", guilds.TrowAssign)
|
||||
common.Plugins["guilds"].RemoveHook("topic_create_pre_loop", guilds.TopicCreatePreLoop)
|
||||
common.Plugins["guilds"].RemoveHook("pre_render_view_forum", guilds.PreRenderViewForum)
|
||||
common.Plugins["guilds"].RemoveHook("pre_render_forum", guilds.PreRenderViewForum)
|
||||
common.Plugins["guilds"].RemoveHook("simple_forum_check_pre_perms", guilds.ForumCheck)
|
||||
common.Plugins["guilds"].RemoveHook("forum_check_pre_perms", guilds.ForumCheck)
|
||||
common.DeregisterPluginPerm("CreateGuild")
|
||||
|
|
|
@ -47,6 +47,8 @@ type accSelectBuilder struct {
|
|||
orderby string
|
||||
limit string
|
||||
dateCutoff *dateCutoff // We might want to do this in a slightly less hacky way
|
||||
inChain *accSelectBuilder
|
||||
inColumn string
|
||||
|
||||
build *Accumulator
|
||||
}
|
||||
|
@ -61,6 +63,12 @@ func (selectItem *accSelectBuilder) Where(where string) *accSelectBuilder {
|
|||
return selectItem
|
||||
}
|
||||
|
||||
func (selectItem *accSelectBuilder) InQ(column string, subBuilder *accSelectBuilder) *accSelectBuilder {
|
||||
selectItem.inChain = subBuilder
|
||||
selectItem.inColumn = column
|
||||
return selectItem
|
||||
}
|
||||
|
||||
func (selectItem *accSelectBuilder) DateCutoff(column string, quantity int, unit string) *accSelectBuilder {
|
||||
selectItem.dateCutoff = &dateCutoff{column, quantity, unit}
|
||||
return selectItem
|
||||
|
@ -78,7 +86,7 @@ func (selectItem *accSelectBuilder) Limit(limit string) *accSelectBuilder {
|
|||
|
||||
func (selectItem *accSelectBuilder) Prepare() *sql.Stmt {
|
||||
// TODO: Phase out the procedural API and use the adapter's OO API? The OO API might need a bit more work before we do that and it needs to be rolled out to MSSQL.
|
||||
if selectItem.dateCutoff != nil {
|
||||
if selectItem.dateCutoff != nil || selectItem.inChain != nil {
|
||||
selectBuilder := selectItem.build.GetAdapter().Builder().Select().FromAcc(selectItem)
|
||||
return selectItem.build.prepare(selectItem.build.GetAdapter().ComplexSelect(selectBuilder))
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@ func (build *Accumulator) Update(table string) *accUpdateBuilder {
|
|||
}
|
||||
|
||||
func (build *Accumulator) Select(table string) *accSelectBuilder {
|
||||
return &accSelectBuilder{table, "", "", "", "", nil, build}
|
||||
return &accSelectBuilder{table, "", "", "", "", nil, nil, "", build}
|
||||
}
|
||||
|
||||
func (build *Accumulator) Insert(table string) *accInsertBuilder {
|
||||
|
|
|
@ -12,7 +12,7 @@ type prebuilder struct {
|
|||
|
||||
func (build *prebuilder) Select(nlist ...string) *selectPrebuilder {
|
||||
name := optString(nlist, "_builder")
|
||||
return &selectPrebuilder{name, "", "", "", "", "", nil, build.adapter}
|
||||
return &selectPrebuilder{name, "", "", "", "", "", nil, nil, "", build.adapter}
|
||||
}
|
||||
|
||||
func (build *prebuilder) Insert(nlist ...string) *insertPrebuilder {
|
||||
|
@ -96,6 +96,8 @@ type selectPrebuilder struct {
|
|||
orderby string
|
||||
limit string
|
||||
dateCutoff *dateCutoff
|
||||
inChain *selectPrebuilder
|
||||
inColumn string // for inChain
|
||||
|
||||
build Adapter
|
||||
}
|
||||
|
@ -115,6 +117,11 @@ func (selectItem *selectPrebuilder) Where(where string) *selectPrebuilder {
|
|||
return selectItem
|
||||
}
|
||||
|
||||
func (selectItem *selectPrebuilder) InQ(subBuilder *selectPrebuilder) *selectPrebuilder {
|
||||
selectItem.inChain = subBuilder
|
||||
return selectItem
|
||||
}
|
||||
|
||||
func (selectItem *selectPrebuilder) Orderby(orderby string) *selectPrebuilder {
|
||||
selectItem.orderby = orderby
|
||||
return selectItem
|
||||
|
@ -130,9 +137,14 @@ func (selectItem *selectPrebuilder) FromAcc(accBuilder *accSelectBuilder) *selec
|
|||
selectItem.table = accBuilder.table
|
||||
selectItem.columns = accBuilder.columns
|
||||
selectItem.where = accBuilder.where
|
||||
selectItem.dateCutoff = accBuilder.dateCutoff
|
||||
selectItem.orderby = accBuilder.orderby
|
||||
selectItem.limit = accBuilder.limit
|
||||
|
||||
selectItem.dateCutoff = accBuilder.dateCutoff
|
||||
if accBuilder.inChain != nil {
|
||||
selectItem.inChain = &selectPrebuilder{"__builder", accBuilder.inChain.table, accBuilder.inChain.columns, accBuilder.inChain.where, accBuilder.inChain.orderby, accBuilder.inChain.limit, accBuilder.inChain.dateCutoff, nil, "", selectItem.build}
|
||||
selectItem.inColumn = accBuilder.inColumn
|
||||
}
|
||||
return selectItem
|
||||
}
|
||||
|
||||
|
|
|
@ -1114,9 +1114,6 @@ type Stmts struct {
|
|||
todaysTopicCount *sql.Stmt
|
||||
todaysReportCount *sql.Stmt
|
||||
todaysNewUserCount *sql.Stmt
|
||||
findUsersByIPUsers *sql.Stmt
|
||||
findUsersByIPTopics *sql.Stmt
|
||||
findUsersByIPReplies *sql.Stmt
|
||||
|
||||
Mocks bool
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
package qgen
|
||||
|
||||
//import "fmt"
|
||||
import "strings"
|
||||
import "strconv"
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Registry = append(Registry,
|
||||
|
@ -399,7 +401,7 @@ func (adapter *MysqlAdapter) SimpleSelect(name string, table string, columns str
|
|||
return querystr, nil
|
||||
}
|
||||
|
||||
func (adapter *MysqlAdapter) ComplexSelect(preBuilder *selectPrebuilder) (string, error) {
|
||||
func (adapter *MysqlAdapter) ComplexSelect(preBuilder *selectPrebuilder) (out string, err error) {
|
||||
if preBuilder.name == "" {
|
||||
return "", errors.New("You need a name for this statement")
|
||||
}
|
||||
|
@ -418,9 +420,19 @@ func (adapter *MysqlAdapter) ComplexSelect(preBuilder *selectPrebuilder) (string
|
|||
}
|
||||
querystr = querystr[0 : len(querystr)-1]
|
||||
|
||||
whereStr, err := adapter.buildFlexiWhere(preBuilder.where, preBuilder.dateCutoff)
|
||||
if err != nil {
|
||||
return querystr, err
|
||||
var whereStr string
|
||||
// TODO: Let callers have a Where() and a InQ()
|
||||
if preBuilder.inChain != nil {
|
||||
whereStr, err = adapter.ComplexSelect(preBuilder.inChain)
|
||||
if err != nil {
|
||||
return querystr, err
|
||||
}
|
||||
whereStr = " WHERE `" + preBuilder.inColumn + "` IN(" + whereStr + ")"
|
||||
} else {
|
||||
whereStr, err = adapter.buildFlexiWhere(preBuilder.where, preBuilder.dateCutoff)
|
||||
if err != nil {
|
||||
return querystr, err
|
||||
}
|
||||
}
|
||||
|
||||
querystr += " FROM `" + preBuilder.table + "`" + whereStr + adapter.buildOrderby(preBuilder.orderby) + adapter.buildLimit(preBuilder.limit)
|
||||
|
@ -664,9 +676,6 @@ type Stmts struct {
|
|||
todaysTopicCount *sql.Stmt
|
||||
todaysReportCount *sql.Stmt
|
||||
todaysNewUserCount *sql.Stmt
|
||||
findUsersByIPUsers *sql.Stmt
|
||||
findUsersByIPTopics *sql.Stmt
|
||||
findUsersByIPReplies *sql.Stmt
|
||||
|
||||
Mocks bool
|
||||
}
|
||||
|
|
|
@ -375,9 +375,6 @@ type Stmts struct {
|
|||
todaysTopicCount *sql.Stmt
|
||||
todaysReportCount *sql.Stmt
|
||||
todaysNewUserCount *sql.Stmt
|
||||
findUsersByIPUsers *sql.Stmt
|
||||
findUsersByIPTopics *sql.Stmt
|
||||
findUsersByIPReplies *sql.Stmt
|
||||
|
||||
Mocks bool
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func routes() {
|
|||
|
||||
topicGroup := newRouteGroup("/topics/",
|
||||
View("routeTopics", "/topics/"),
|
||||
MemberView("routeTopicCreate", "/topics/create/", "extraData"),
|
||||
MemberView("routes.CreateTopic", "/topics/create/", "extraData"),
|
||||
)
|
||||
addRouteGroup(topicGroup)
|
||||
|
||||
|
@ -53,10 +53,10 @@ func buildUserRoutes() {
|
|||
// TODO: Auto test and manual test these routes
|
||||
userGroup = newRouteGroup("/users/")
|
||||
userGroup.Routes(
|
||||
Action("routeBanSubmit", "/users/ban/submit/", "extraData"),
|
||||
Action("routeUnban", "/users/unban/", "extraData"),
|
||||
Action("routeActivate", "/users/activate/", "extraData"),
|
||||
MemberView("routeIps", "/users/ips/"), // TODO: .Perms("ViewIPs")?
|
||||
Action("routes.BanUserSubmit", "/users/ban/submit/", "extraData"),
|
||||
Action("routes.UnbanUser", "/users/unban/", "extraData"),
|
||||
Action("routes.ActivateUser", "/users/activate/", "extraData"),
|
||||
MemberView("routes.IPSearch", "/users/ips/"), // TODO: .Perms("ViewIPs")?
|
||||
)
|
||||
addRouteGroup(userGroup)
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func buildTopicRoutes() {
|
|||
topicGroup := newRouteGroup("/topic/")
|
||||
topicGroup.Routes(
|
||||
View("routeTopicID", "/topic/", "extraData"),
|
||||
Action("routeTopicCreateSubmit", "/topic/create/submit/"),
|
||||
Action("routeCreateTopicSubmit", "/topic/create/submit/"),
|
||||
Action("routes.EditTopicSubmit", "/topic/edit/submit/", "extraData"),
|
||||
Action("routes.DeleteTopicSubmit", "/topic/delete/submit/").LitBefore("req.URL.Path += extraData"),
|
||||
Action("routes.StickTopicSubmit", "/topic/stick/submit/", "extraData"),
|
||||
|
|
34
routes.go
34
routes.go
|
@ -291,18 +291,8 @@ func routeForum(w http.ResponseWriter, r *http.Request, user common.User, sfid s
|
|||
}
|
||||
headerVars.Zone = "view_forum"
|
||||
|
||||
// Calculate the offset
|
||||
var offset int
|
||||
// TODO: Does forum.TopicCount take the deleted items into consideration for guests?
|
||||
lastPage := (forum.TopicCount / common.Config.ItemsPerPage) + 1
|
||||
if page > 1 {
|
||||
offset = (common.Config.ItemsPerPage * page) - common.Config.ItemsPerPage
|
||||
} else if page == -1 {
|
||||
page = lastPage
|
||||
offset = (common.Config.ItemsPerPage * page) - common.Config.ItemsPerPage
|
||||
} else {
|
||||
page = 1
|
||||
}
|
||||
// TODO: Does forum.TopicCount take the deleted items into consideration for guests? We don't have soft-delete yet, only hard-delete
|
||||
offset, page, lastPage := common.PageOffset(forum.TopicCount, page, common.Config.ItemsPerPage)
|
||||
|
||||
// TODO: Move this to *Forum
|
||||
rows, err := stmts.getForumTopicsOffset.Query(fid, offset, common.Config.ItemsPerPage)
|
||||
|
@ -358,8 +348,8 @@ func routeForum(w http.ResponseWriter, r *http.Request, user common.User, sfid s
|
|||
}
|
||||
|
||||
pi := common.ForumPage{forum.Name, user, headerVars, topicList, forum, page, lastPage}
|
||||
if common.PreRenderHooks["pre_render_view_forum"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_view_forum", w, r, &user, &pi) {
|
||||
if common.PreRenderHooks["pre_render_forum"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_forum", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -430,10 +420,9 @@ func routeForums(w http.ResponseWriter, r *http.Request, user common.User) commo
|
|||
|
||||
func routeTopicID(w http.ResponseWriter, r *http.Request, user common.User, urlBit string) common.RouteError {
|
||||
var err error
|
||||
var page, offset int
|
||||
var replyList []common.ReplyUser
|
||||
|
||||
page, _ = strconv.Atoi(r.FormValue("page"))
|
||||
page, _ := strconv.Atoi(r.FormValue("page"))
|
||||
|
||||
// SEO URLs...
|
||||
// TODO: Make a shared function for this
|
||||
|
@ -496,16 +485,7 @@ func routeTopicID(w http.ResponseWriter, r *http.Request, user common.User, urlB
|
|||
}
|
||||
|
||||
// Calculate the offset
|
||||
lastPage := (topic.PostCount / common.Config.ItemsPerPage) + 1
|
||||
if page > 1 {
|
||||
offset = (common.Config.ItemsPerPage * page) - common.Config.ItemsPerPage
|
||||
} else if page == -1 {
|
||||
page = lastPage
|
||||
offset = (common.Config.ItemsPerPage * page) - common.Config.ItemsPerPage
|
||||
} else {
|
||||
page = 1
|
||||
}
|
||||
|
||||
offset, page, lastPage := common.PageOffset(topic.PostCount, page, common.Config.ItemsPerPage)
|
||||
tpage := common.TopicPage{topic.Title, user, headerVars, replyList, topic, page, lastPage}
|
||||
|
||||
// Get the replies..
|
||||
|
@ -918,7 +898,6 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user common.User) common.R
|
|||
if err != nil {
|
||||
return common.PreErrorJS("Invalid asid", w, r)
|
||||
}
|
||||
|
||||
_, err = stmts.deleteActivityStreamMatch.Exec(user.ID, asid)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
|
@ -957,7 +936,6 @@ func routeAPI(w http.ResponseWriter, r *http.Request, user common.User) common.R
|
|||
}
|
||||
msglist += res + ","
|
||||
}
|
||||
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return common.InternalErrorJS(err, w, r)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package routes
|
||||
|
||||
import (
|
||||
"html"
|
||||
"net/http"
|
||||
|
||||
"../common"
|
||||
)
|
||||
|
||||
func IPSearch(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, ferr := common.UserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
// TODO: How should we handle the permissions if we extend this into an alt detector of sorts?
|
||||
if !user.Perms.ViewIPs {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
// TODO: Reject IP Addresses with illegal characters
|
||||
var ip = html.EscapeString(r.FormValue("ip"))
|
||||
uids, err := common.IPSearch.Lookup(ip)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: What if a user is deleted via the Control Panel? We'll cross that bridge when we come to it, although we might lean towards blanking the account and removing the related data rather than purging it
|
||||
userList, err := common.Users.BulkGetMap(uids)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
pi := common.IPSearchPage{common.GetTitlePhrase("ip-search"), user, headerVars, userList, ip}
|
||||
if common.PreRenderHooks["pre_render_ip_search"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_ip_search", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = common.Templates.ExecuteTemplate(w, "ip-search.html", pi)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
This file is here so that Git will include this folder in the repository.
|
125
routes/topic.go
125
routes/topic.go
|
@ -12,6 +12,93 @@ import (
|
|||
|
||||
var successJSONBytes = []byte(`{"success":"1"}`)
|
||||
|
||||
// ? - Should we add a new permission or permission zone (like per-forum permissions) specifically for profile comment creation
|
||||
// ? - Should we allow banned users to make reports? How should we handle report abuse?
|
||||
// TODO: Add a permission to stop certain users from using custom avatars
|
||||
// ? - Log username changes and put restrictions on this?
|
||||
func CreateTopic(w http.ResponseWriter, r *http.Request, user common.User, sfid string) common.RouteError {
|
||||
var fid int
|
||||
var err error
|
||||
if sfid != "" {
|
||||
fid, err = strconv.Atoi(sfid)
|
||||
if err != nil {
|
||||
return common.LocalError("You didn't provide a valid number for the forum ID.", w, r, user)
|
||||
}
|
||||
}
|
||||
if fid == 0 {
|
||||
fid = common.Config.DefaultForum
|
||||
}
|
||||
|
||||
headerVars, ferr := common.ForumUserCheck(w, r, &user, fid)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.CreateTopic {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
headerVars.Zone = "create_topic"
|
||||
|
||||
// Lock this to the forum being linked?
|
||||
// Should we always put it in strictmode when it's linked from another forum? Well, the user might end up changing their mind on what forum they want to post in and it would be a hassle, if they had to switch pages, even if it is a single click for many (exc. mobile)
|
||||
var strictmode bool
|
||||
if common.Vhooks["topic_create_pre_loop"] != nil {
|
||||
common.RunVhook("topic_create_pre_loop", w, r, fid, &headerVars, &user, &strictmode)
|
||||
}
|
||||
|
||||
// TODO: Re-add support for plugin_guilds
|
||||
var forumList []common.Forum
|
||||
var canSee []int
|
||||
if user.IsSuperAdmin {
|
||||
canSee, err = common.Forums.GetAllVisibleIDs()
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
} else {
|
||||
group, err := common.Groups.Get(user.Group)
|
||||
if err != nil {
|
||||
// TODO: Refactor this
|
||||
common.LocalError("Something weird happened behind the scenes", w, r, user)
|
||||
log.Printf("Group #%d doesn't exist, but it's set on common.User #%d", user.Group, user.ID)
|
||||
return nil
|
||||
}
|
||||
canSee = group.CanSee
|
||||
}
|
||||
|
||||
// TODO: plugin_superadmin needs to be able to override this loop. Skip flag on topic_create_pre_loop?
|
||||
for _, ffid := range canSee {
|
||||
// TODO: Surely, there's a better way of doing this. I've added it in for now to support plugin_guilds, but we really need to clean this up
|
||||
if strictmode && ffid != fid {
|
||||
continue
|
||||
}
|
||||
|
||||
// Do a bulk forum fetch, just in case it's the SqlForumStore?
|
||||
forum := common.Forums.DirtyGet(ffid)
|
||||
if forum.Name != "" && forum.Active {
|
||||
fcopy := forum.Copy()
|
||||
if common.Hooks["topic_create_frow_assign"] != nil {
|
||||
// TODO: Add the skip feature to all the other row based hooks?
|
||||
if common.RunHook("topic_create_frow_assign", &fcopy).(bool) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
forumList = append(forumList, fcopy)
|
||||
}
|
||||
}
|
||||
|
||||
ctpage := common.CreateTopicPage{"Create Topic", user, headerVars, forumList, fid}
|
||||
if common.PreRenderHooks["pre_render_create_topic"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_create_topic", w, r, &user, &ctpage) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
err = common.RunThemeTemplate(headerVars.Theme.Name, "create_topic", ctpage, w)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
||||
// TODO: Disable stat updates in posts handled by plugin_guilds
|
||||
func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
|
||||
|
@ -149,11 +236,7 @@ func StickTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User,
|
|||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = common.ModLogs.Create("stick", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("stick", user.LastIP, user)
|
||||
err = addTopicAction("stick", topic, user)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -188,11 +271,7 @@ func UnstickTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User
|
|||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = common.ModLogs.Create("unstick", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("unstick", user.LastIP, user)
|
||||
err = addTopicAction("unstick", topic, user)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -247,11 +326,7 @@ func LockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) c
|
|||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
err = common.ModLogs.Create("lock", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
err = topic.CreateActionReply("lock", user.LastIP, user)
|
||||
err = addTopicAction("lock", topic, user)
|
||||
if err != nil {
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
@ -290,11 +365,7 @@ func UnlockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User,
|
|||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = common.ModLogs.Create("unlock", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("unlock", user.LastIP, user)
|
||||
err = addTopicAction("unlock", topic, user)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
@ -354,11 +425,7 @@ func MoveTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, s
|
|||
}
|
||||
|
||||
// TODO: Log more data so we can list the destination forum in the action post?
|
||||
err = common.ModLogs.Create("move", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return common.InternalErrorJS(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("move", user.LastIP, user)
|
||||
err = addTopicAction("move", topic, user)
|
||||
if err != nil {
|
||||
return common.InternalErrorJS(err, w, r)
|
||||
}
|
||||
|
@ -369,3 +436,11 @@ func MoveTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, s
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addTopicAction(action string, topic *common.Topic, user common.User) error {
|
||||
err := common.ModLogs.Create(action, topic.ID, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return topic.CreateActionReply(action, user.LastIP, user)
|
||||
}
|
||||
|
|
|
@ -1,108 +1,15 @@
|
|||
package main
|
||||
package routes
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"./common"
|
||||
"../common"
|
||||
)
|
||||
|
||||
func routeIps(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, ferr := common.UserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewIPs {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
var ip = r.FormValue("ip")
|
||||
var uid int
|
||||
var reqUserList = make(map[int]bool)
|
||||
|
||||
rows, err := stmts.findUsersByIPUsers.Query(ip)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&uid)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
rows2, err := stmts.findUsersByIPTopics.Query(ip)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows2.Close()
|
||||
|
||||
for rows2.Next() {
|
||||
err := rows2.Scan(&uid)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
err = rows2.Err()
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
rows3, err := stmts.findUsersByIPReplies.Query(ip)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows3.Close()
|
||||
|
||||
for rows3.Next() {
|
||||
err := rows3.Scan(&uid)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
err = rows3.Err()
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// Convert the user ID map to a slice, then bulk load the users
|
||||
var idSlice = make([]int, len(reqUserList))
|
||||
var i int
|
||||
for userID := range reqUserList {
|
||||
idSlice[i] = userID
|
||||
i++
|
||||
}
|
||||
|
||||
// TODO: What if a user is deleted via the Control Panel?
|
||||
userList, err := common.Users.BulkGetMap(idSlice)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
pi := common.IPSearchPage{common.GetTitlePhrase("ip-search"), user, headerVars, userList, ip}
|
||||
if common.PreRenderHooks["pre_render_ips"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_ips", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = common.Templates.ExecuteTemplate(w, "ip-search.html", pi)
|
||||
if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeBanSubmit(w http.ResponseWriter, r *http.Request, user common.User, suid string) common.RouteError {
|
||||
func BanUserSubmit(w http.ResponseWriter, r *http.Request, user common.User, suid string) common.RouteError {
|
||||
if !user.Perms.BanUsers {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
@ -116,7 +23,7 @@ func routeBanSubmit(w http.ResponseWriter, r *http.Request, user common.User, su
|
|||
}
|
||||
|
||||
targetUser, err := common.Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
return common.LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
|
@ -160,7 +67,7 @@ func routeBanSubmit(w http.ResponseWriter, r *http.Request, user common.User, su
|
|||
}
|
||||
|
||||
err = targetUser.Ban(duration, user.ID)
|
||||
if err == ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
return common.LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
|
@ -175,7 +82,7 @@ func routeBanSubmit(w http.ResponseWriter, r *http.Request, user common.User, su
|
|||
return nil
|
||||
}
|
||||
|
||||
func routeUnban(w http.ResponseWriter, r *http.Request, user common.User, suid string) common.RouteError {
|
||||
func UnbanUser(w http.ResponseWriter, r *http.Request, user common.User, suid string) common.RouteError {
|
||||
if !user.Perms.BanUsers {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
@ -186,7 +93,7 @@ func routeUnban(w http.ResponseWriter, r *http.Request, user common.User, suid s
|
|||
}
|
||||
|
||||
targetUser, err := common.Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
return common.LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
|
@ -199,7 +106,7 @@ func routeUnban(w http.ResponseWriter, r *http.Request, user common.User, suid s
|
|||
err = targetUser.Unban()
|
||||
if err == common.ErrNoTempGroup {
|
||||
return common.LocalError("The user you're trying to unban is not banned", w, r, user)
|
||||
} else if err == ErrNoRows {
|
||||
} else if err == sql.ErrNoRows {
|
||||
return common.LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
||||
|
@ -214,7 +121,7 @@ func routeUnban(w http.ResponseWriter, r *http.Request, user common.User, suid s
|
|||
return nil
|
||||
}
|
||||
|
||||
func routeActivate(w http.ResponseWriter, r *http.Request, user common.User, suid string) common.RouteError {
|
||||
func ActivateUser(w http.ResponseWriter, r *http.Request, user common.User, suid string) common.RouteError {
|
||||
if !user.Perms.ActivateUsers {
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
@ -225,7 +132,7 @@ func routeActivate(w http.ResponseWriter, r *http.Request, user common.User, sui
|
|||
}
|
||||
|
||||
targetUser, err := common.Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
if err == sql.ErrNoRows {
|
||||
return common.LocalError("The account you're trying to activate no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return common.InternalError(err, w, r)
|
Loading…
Reference in New Issue