2016-12-07 09:34:09 +00:00
|
|
|
package main
|
|
|
|
|
2017-05-11 13:04:43 +00:00
|
|
|
import (
|
2017-06-16 10:41:30 +00:00
|
|
|
//"log"
|
|
|
|
//"fmt"
|
2017-10-30 09:57:08 +00:00
|
|
|
"encoding/json"
|
2017-09-03 04:50:31 +00:00
|
|
|
"html"
|
2017-10-30 09:57:08 +00:00
|
|
|
"log"
|
2017-05-11 13:04:43 +00:00
|
|
|
"net/http"
|
2017-09-03 04:50:31 +00:00
|
|
|
"strconv"
|
|
|
|
"time"
|
2017-11-11 04:06:16 +00:00
|
|
|
|
|
|
|
"./common"
|
2017-05-11 13:04:43 +00:00
|
|
|
)
|
2016-12-07 09:34:09 +00:00
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
2017-11-02 04:12:51 +00:00
|
|
|
// TODO: Disable stat updates in posts handled by plugin_guilds
|
2017-11-23 05:37:08 +00:00
|
|
|
// TODO: Make sure this route is member only
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeEditTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
err := r.ParseForm()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("Bad Form", w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
isJs := (r.PostFormValue("js") == "1")
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-22 02:21:17 +00:00
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/edit/submit/"):])
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The provided TopicID is not a valid number.", w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
topic, err := common.Topics.Get(tid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The topic you tried to edit doesn't exist.", w, r, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-02-05 16:36:54 +00:00
|
|
|
if !user.Perms.ViewTopic || !user.Perms.EditTopic {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
topicName := r.PostFormValue("topic_name")
|
|
|
|
topicContent := html.EscapeString(r.PostFormValue("topic_content"))
|
2017-09-28 22:16:34 +00:00
|
|
|
err = topic.Update(topicName, topicContent)
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.Forums.UpdateLastTopic(topic.ID, user.ID, topic.ParentID)
|
2017-09-22 02:21:17 +00:00
|
|
|
if err != nil && err != ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-04-02 13:00:40 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
if !isJs {
|
|
|
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
2016-12-07 09:34:09 +00:00
|
|
|
} else {
|
2017-09-03 04:50:31 +00:00
|
|
|
_, _ = w.Write(successJSONBytes)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
// TODO: Add support for soft-deletion and add a permission for hard delete in addition to the usual
|
2017-11-02 04:12:51 +00:00
|
|
|
// TODO: Disable stat updates in posts handled by plugin_guilds
|
2017-11-23 05:37:08 +00:00
|
|
|
// TODO: Make sure this route is member only
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeDeleteTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2017-10-30 09:57:08 +00:00
|
|
|
// TODO: Move this to some sort of middleware
|
|
|
|
var tids []int
|
|
|
|
var isJs = false
|
2017-11-23 05:37:08 +00:00
|
|
|
if common.ReqIsJson(r) {
|
2017-10-30 09:57:08 +00:00
|
|
|
if r.Body == nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("No request body", w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
//log.Print("r.Body: ", r.Body)
|
|
|
|
err := json.NewDecoder(r.Body).Decode(&tids)
|
|
|
|
if err != nil {
|
|
|
|
//log.Print("parse err: ", err)
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("We weren't able to parse your data", w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
isJs = true
|
|
|
|
} else {
|
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
tids = append(tids, tid)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
if len(tids) == 0 {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJSQ("You haven't provided any IDs", w, r, user, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
for _, tid := range tids {
|
2017-11-11 04:06:16 +00:00
|
|
|
topic, err := common.Topics.Get(tid)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The topic you tried to delete doesn't exist.", w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
|
|
|
}
|
|
|
|
if !user.Perms.ViewTopic || !user.Perms.DeleteTopic {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
// We might be able to handle this err better
|
|
|
|
err = topic.Delete()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("delete", tid, "topic", user.LastIP, user.ID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
// ? - We might need to add soft-delete before we can do an action reply for this
|
2017-11-05 09:55:34 +00:00
|
|
|
/*_, err = stmts.createActionReply.Exec(tid,"delete",ipaddress,user.ID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err,w,r,isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}*/
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
log.Printf("Topic #%d was deleted by common.User #%d", tid, user.ID)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeStickTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
topic, err := common.Topics.Get(tid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The topic you tried to pin doesn't exist.", w, r)
|
2017-01-31 05:13:38 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-02-05 16:36:54 +00:00
|
|
|
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-22 02:21:17 +00:00
|
|
|
err = topic.Stick()
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("stick", tid, "topic", user.LastIP, user.ID)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-11-10 00:16:15 +00:00
|
|
|
err = topic.CreateActionReply("stick", user.LastIP, user)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
topic, err := common.Topics.Get(tid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The topic you tried to unpin doesn't exist.", w, r)
|
2017-01-31 05:13:38 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-02-05 16:36:54 +00:00
|
|
|
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-22 02:21:17 +00:00
|
|
|
err = topic.Unstick()
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("unstick", tid, "topic", user.LastIP, user.ID)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-11-10 00:16:15 +00:00
|
|
|
err = topic.CreateActionReply("unstick", user.LastIP, user)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
|
2017-09-22 02:21:17 +00:00
|
|
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeLockTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2017-10-30 09:57:08 +00:00
|
|
|
// TODO: Move this to some sort of middleware
|
|
|
|
var tids []int
|
|
|
|
var isJs = false
|
2017-11-23 05:37:08 +00:00
|
|
|
if common.ReqIsJson(r) {
|
2017-10-30 09:57:08 +00:00
|
|
|
if r.Body == nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("No request body", w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
err := json.NewDecoder(r.Body).Decode(&tids)
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("We weren't able to parse your data", w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
isJs = true
|
|
|
|
} else {
|
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/lock/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
tids = append(tids, tid)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
if len(tids) == 0 {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJSQ("You haven't provided any IDs", w, r, user, isJs)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
for _, tid := range tids {
|
2017-11-11 04:06:16 +00:00
|
|
|
topic, err := common.Topics.Get(tid)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The topic you tried to lock doesn't exist.", w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-09-22 02:21:17 +00:00
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
|
|
|
}
|
|
|
|
if !user.Perms.ViewTopic || !user.Perms.CloseTopic {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-09-22 02:21:17 +00:00
|
|
|
|
2017-10-30 09:57:08 +00:00
|
|
|
err = topic.Lock()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("lock", tid, "topic", user.LastIP, user.ID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-11-10 00:16:15 +00:00
|
|
|
err = topic.CreateActionReply("lock", user.LastIP, user)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
|
|
|
|
if len(tids) == 1 {
|
|
|
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tids[0]), http.StatusSeeOther)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeUnlockTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2017-09-22 02:21:17 +00:00
|
|
|
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unlock/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
topic, err := common.Topics.Get(tid)
|
2017-09-22 02:21:17 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("The topic you tried to unlock doesn't exist.", w, r)
|
2017-09-22 02:21:17 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
if !user.Perms.ViewTopic || !user.Perms.CloseTopic {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err = topic.Unlock()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("unlock", tid, "topic", user.LastIP, user.ID)
|
2017-09-22 02:21:17 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-22 02:21:17 +00:00
|
|
|
}
|
2017-11-10 00:16:15 +00:00
|
|
|
err = topic.CreateActionReply("unlock", user.LastIP, user)
|
2017-09-22 02:21:17 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-02-16 06:47:55 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-02 04:12:51 +00:00
|
|
|
// TODO: Disable stat updates in posts handled by plugin_guilds
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
err := r.ParseForm()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("Bad Form", w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
isJs := (r.PostFormValue("js") == "1")
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 09:34:09 +00:00
|
|
|
rid, err := strconv.Atoi(r.URL.Path[len("/reply/edit/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 09:34:09 +00:00
|
|
|
// Get the Reply ID..
|
|
|
|
var tid int
|
2017-11-05 09:55:34 +00:00
|
|
|
err = stmts.getReplyTID.QueryRow(rid).Scan(&tid)
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-01-31 05:13:38 +00:00
|
|
|
var fid int
|
2017-11-05 09:55:34 +00:00
|
|
|
err = stmts.getTopicFID.QueryRow(tid).Scan(&fid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, fid)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-02-05 16:36:54 +00:00
|
|
|
if !user.Perms.ViewTopic || !user.Perms.EditReply {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
content := html.EscapeString(common.PreparseMessage(r.PostFormValue("edit_item")))
|
|
|
|
_, err = stmts.editReply.Exec(content, common.ParseMessage(content, fid, "forums"), rid)
|
Added Quick Topic.
Added Attachments.
Added Attachment Media Embeds.
Renamed a load of *Store and *Cache methods to reduce the amount of unneccesary typing.
Added petabytes as a unit and cleaned up a few of the friendly units.
Refactored the username change logic to make it easier to maintain.
Refactored the avatar change logic to make it easier to maintain.
Shadow now uses CSS Variables for most of it's colours. We have plans to transpile this to support older browsers later on!
Snuck some CSS Variables into Tempra Conflux.
Added the GroupCache interface to MemoryGroupStore.
Added the Length method to MemoryGroupStore.
Added support for a site short name.
Added the UploadFiles permission.
Renamed more functions.
Fixed the background for the left gutter on the postbit for Tempra Simple and Shadow.
Added support for if statements operating on int8, int16, int32, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64 for the template compiler.
Added support for if statements operating on slices and maps for the template compiler.
Fixed a security exploit in reply editing.
Fixed a bug in the URL detector in the parser where it couldn't find URLs with non-standard ports.
Fixed buttons having blue outlines on focus on Shadow.
Refactored the topic creation logic to make it easier to maintain.
Made a few responsive fixes, but there's still more to do in the following commits!
2017-10-05 10:20:28 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
Added Quick Topic.
Added Attachments.
Added Attachment Media Embeds.
Renamed a load of *Store and *Cache methods to reduce the amount of unneccesary typing.
Added petabytes as a unit and cleaned up a few of the friendly units.
Refactored the username change logic to make it easier to maintain.
Refactored the avatar change logic to make it easier to maintain.
Shadow now uses CSS Variables for most of it's colours. We have plans to transpile this to support older browsers later on!
Snuck some CSS Variables into Tempra Conflux.
Added the GroupCache interface to MemoryGroupStore.
Added the Length method to MemoryGroupStore.
Added support for a site short name.
Added the UploadFiles permission.
Renamed more functions.
Fixed the background for the left gutter on the postbit for Tempra Simple and Shadow.
Added support for if statements operating on int8, int16, int32, int32, int64, uint, uint8, uint16, uint32, uint64, float32, and float64 for the template compiler.
Added support for if statements operating on slices and maps for the template compiler.
Fixed a security exploit in reply editing.
Fixed a bug in the URL detector in the parser where it couldn't find URLs with non-standard ports.
Fixed buttons having blue outlines on focus on Shadow.
Refactored the topic creation logic to make it easier to maintain.
Made a few responsive fixes, but there's still more to do in the following commits!
2017-10-05 10:20:28 +00:00
|
|
|
}
|
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
if !isJs {
|
|
|
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther)
|
2016-12-07 09:34:09 +00:00
|
|
|
} else {
|
2017-09-03 04:50:31 +00:00
|
|
|
w.Write(successJSONBytes)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-10-12 03:24:14 +00:00
|
|
|
// TODO: Refactor this
|
2017-11-02 04:12:51 +00:00
|
|
|
// TODO: Disable stat updates in posts handled by plugin_guilds
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
err := r.ParseForm()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreError("Bad Form", w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
isJs := (r.PostFormValue("isJs") == "1")
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 09:34:09 +00:00
|
|
|
rid, err := strconv.Atoi(r.URL.Path[len("/reply/delete/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
reply, err := common.Rstore.Get(rid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The reply you tried to delete doesn't exist.", w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-01-31 05:13:38 +00:00
|
|
|
var fid int
|
2017-11-05 09:55:34 +00:00
|
|
|
err = stmts.getTopicFID.QueryRow(reply.ParentID).Scan(&fid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Add hooks to make use of headerLite
|
2017-11-11 04:06:16 +00:00
|
|
|
_, ferr := common.SimpleForumUserCheck(w, r, &user, fid)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-02-05 16:36:54 +00:00
|
|
|
if !user.Perms.ViewTopic || !user.Perms.DeleteReply {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2017-01-31 05:13:38 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-10-12 03:24:14 +00:00
|
|
|
err = reply.Delete()
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-10-12 03:24:14 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
//log.Printf("Reply #%d was deleted by common.User #%d", rid, user.ID)
|
2017-09-03 04:50:31 +00:00
|
|
|
if !isJs {
|
2016-12-07 09:34:09 +00:00
|
|
|
//http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
|
|
|
} else {
|
2017-09-03 04:50:31 +00:00
|
|
|
w.Write(successJSONBytes)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
replyCreator, err := common.Users.Get(reply.CreatedBy)
|
2017-09-10 16:57:22 +00:00
|
|
|
if err == nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
wcount := common.WordCount(reply.Content)
|
|
|
|
err = replyCreator.DecreasePostStats(wcount, false)
|
2017-09-10 16:57:22 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-09-10 16:57:22 +00:00
|
|
|
}
|
|
|
|
} else if err != ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-01-12 02:55:08 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("delete", reply.ParentID, "reply", user.LastIP, user.ID)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2017-02-15 10:49:30 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
err := r.ParseForm()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("Bad Form", w, r, user)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
isJs := (r.PostFormValue("js") == "1")
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 09:34:09 +00:00
|
|
|
rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/edit/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 13:46:14 +00:00
|
|
|
// Get the Reply ID..
|
|
|
|
var uid int
|
2017-11-05 09:55:34 +00:00
|
|
|
err = stmts.getUserReplyUID.QueryRow(rid).Scan(&uid)
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-21 02:30:32 +00:00
|
|
|
if user.ID != uid && !user.Perms.EditReply {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2016-12-07 13:46:14 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
content := html.EscapeString(common.PreparseMessage(r.PostFormValue("edit_item")))
|
|
|
|
_, err = stmts.editProfileReply.Exec(content, common.ParseMessage(content, 0, ""), rid)
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
if !isJs {
|
|
|
|
http.Redirect(w, r, "/user/"+strconv.Itoa(uid)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther)
|
2016-12-07 09:34:09 +00:00
|
|
|
} else {
|
2017-09-03 04:50:31 +00:00
|
|
|
w.Write(successJSONBytes)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-07 09:34:09 +00:00
|
|
|
err := r.ParseForm()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("Bad Form", w, r, user)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
isJs := (r.PostFormValue("isJs") == "1")
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 09:34:09 +00:00
|
|
|
rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/delete/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-07 09:34:09 +00:00
|
|
|
var uid int
|
2017-11-05 09:55:34 +00:00
|
|
|
err = stmts.getUserReplyUID.QueryRow(rid).Scan(&uid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 13:46:14 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-21 02:30:32 +00:00
|
|
|
if user.ID != uid && !user.Perms.DeleteReply {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissionsJSQ(w, r, user, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-05 09:55:34 +00:00
|
|
|
_, err = stmts.deleteProfileReply.Exec(rid)
|
2016-12-07 09:34:09 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJSQ(err, w, r, isJs)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-11-11 04:06:16 +00:00
|
|
|
//log.Printf("The profile post '%d' was deleted by common.User #%d", rid, user.ID)
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
if !isJs {
|
2016-12-07 09:34:09 +00:00
|
|
|
//http.Redirect(w,r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther)
|
|
|
|
} else {
|
2017-09-03 04:50:31 +00:00
|
|
|
w.Write(successJSONBytes)
|
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeIps(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
|
|
|
headerVars, ferr := common.UserCheck(w, r, &user)
|
2017-10-30 09:57:08 +00:00
|
|
|
if ferr != nil {
|
|
|
|
return ferr
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
if !user.Perms.ViewIPs {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
2017-10-12 03:24:14 +00:00
|
|
|
var ip = r.FormValue("ip")
|
2017-09-03 04:50:31 +00:00
|
|
|
var uid int
|
2017-09-10 16:57:22 +00:00
|
|
|
var reqUserList = make(map[int]bool)
|
2017-09-03 04:50:31 +00:00
|
|
|
|
2017-11-05 09:55:34 +00:00
|
|
|
rows, err := stmts.findUsersByIPUsers.Query(ip)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
for rows.Next() {
|
|
|
|
err := rows.Scan(&uid)
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
reqUserList[uid] = true
|
|
|
|
}
|
|
|
|
err = rows.Err()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 09:55:34 +00:00
|
|
|
rows2, err := stmts.findUsersByIPTopics.Query(ip)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
defer rows2.Close()
|
|
|
|
|
|
|
|
for rows2.Next() {
|
|
|
|
err := rows2.Scan(&uid)
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
reqUserList[uid] = true
|
|
|
|
}
|
|
|
|
err = rows2.Err()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 09:55:34 +00:00
|
|
|
rows3, err := stmts.findUsersByIPReplies.Query(ip)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
defer rows3.Close()
|
|
|
|
|
|
|
|
for rows3.Next() {
|
|
|
|
err := rows3.Scan(&uid)
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
reqUserList[uid] = true
|
|
|
|
}
|
|
|
|
err = rows3.Err()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the user ID map to a slice, then bulk load the users
|
2017-09-10 16:57:22 +00:00
|
|
|
var idSlice = make([]int, len(reqUserList))
|
2017-09-03 04:50:31 +00:00
|
|
|
var i int
|
|
|
|
for userID := range reqUserList {
|
|
|
|
idSlice[i] = userID
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: What if a user is deleted via the Control Panel?
|
2017-11-11 04:06:16 +00:00
|
|
|
userList, err := common.Users.BulkGetMap(idSlice)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
pi := common.IPSearchPage{common.GetTitlePhrase("ip-search"), user, headerVars, userList, ip}
|
2017-11-11 04:06:16 +00:00
|
|
|
if common.PreRenderHooks["pre_render_ips"] != nil {
|
|
|
|
if common.RunPreRenderHook("pre_render_ips", w, r, &user, &pi) {
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-11 04:06:16 +00:00
|
|
|
err = common.Templates.ExecuteTemplate(w, "ip-search.html", pi)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeBanSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-21 02:30:32 +00:00
|
|
|
if !user.Perms.BanUsers {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-08 14:11:18 +00:00
|
|
|
uid, err := strconv.Atoi(r.URL.Path[len("/users/ban/submit/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The provided common.User ID is not a valid number.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-11-23 05:37:08 +00:00
|
|
|
if uid == -2 {
|
|
|
|
return common.LocalError("Why don't you like Merlin?", w, r, user)
|
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
targetUser, err := common.Users.Get(uid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-10-31 07:26:44 +00:00
|
|
|
// TODO: Is there a difference between IsMod and IsSuperMod? Should we delete the redundant one?
|
2017-11-23 05:37:08 +00:00
|
|
|
if targetUser.IsMod {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("You may not ban another staff member.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
|
|
|
if uid == user.ID {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("Why are you trying to ban yourself? Stop that.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
if targetUser.IsBanned {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The user you're trying to unban is already banned.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
durationDays, err := strconv.Atoi(r.FormValue("ban-duration-days"))
|
2017-08-27 09:33:45 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("You can only use whole numbers for the number of days", w, r, user)
|
2017-08-27 09:33:45 +00:00
|
|
|
}
|
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
durationWeeks, err := strconv.Atoi(r.FormValue("ban-duration-weeks"))
|
2017-08-27 09:33:45 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("You can only use whole numbers for the number of weeks", w, r, user)
|
2017-08-27 09:33:45 +00:00
|
|
|
}
|
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
durationMonths, err := strconv.Atoi(r.FormValue("ban-duration-months"))
|
2016-12-08 14:11:18 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("You can only use whole numbers for the number of months", w, r, user)
|
2017-08-27 09:33:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var duration time.Duration
|
2017-09-03 04:50:31 +00:00
|
|
|
if durationDays > 1 && durationWeeks > 1 && durationMonths > 1 {
|
2017-08-27 09:33:45 +00:00
|
|
|
duration, _ = time.ParseDuration("0")
|
|
|
|
} else {
|
|
|
|
var seconds int
|
2017-11-11 04:06:16 +00:00
|
|
|
seconds += durationDays * common.Day
|
|
|
|
seconds += durationWeeks * common.Week
|
|
|
|
seconds += durationMonths * common.Month
|
2017-08-27 09:33:45 +00:00
|
|
|
duration, _ = time.ParseDuration(strconv.Itoa(seconds) + "s")
|
|
|
|
}
|
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
err = targetUser.Ban(duration, user.ID)
|
2017-08-27 09:33:45 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
2017-08-27 09:33:45 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("ban", uid, "user", user.LastIP, user.ID)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeUnban(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-21 02:30:32 +00:00
|
|
|
if !user.Perms.BanUsers {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-08 14:11:18 +00:00
|
|
|
uid, err := strconv.Atoi(r.URL.Path[len("/users/unban/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The provided common.User ID is not a valid number.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
targetUser, err := common.Users.Get(uid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
if !targetUser.IsBanned {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The user you're trying to unban isn't banned.", w, r, user)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-08-27 09:33:45 +00:00
|
|
|
err = targetUser.Unban()
|
2017-11-11 04:06:16 +00:00
|
|
|
if err == common.ErrNoTempGroup {
|
|
|
|
return common.LocalError("The user you're trying to unban is not banned", w, r, user)
|
2017-10-21 00:27:47 +00:00
|
|
|
} else if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
2017-08-27 09:33:45 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("unban", uid, "user", user.LastIP, user.ID)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-08 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeActivate(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2016-12-21 02:30:32 +00:00
|
|
|
if !user.Perms.ActivateUsers {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.NoPermissions(w, r, user)
|
2016-12-18 12:56:06 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2016-12-18 12:56:06 +00:00
|
|
|
uid, err := strconv.Atoi(r.URL.Path[len("/users/activate/"):])
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The provided common.User ID is not a valid number.", w, r, user)
|
2016-12-18 12:56:06 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
targetUser, err := common.Users.Get(uid)
|
2017-06-28 12:05:26 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The account you're trying to activate no longer exists.", w, r, user)
|
2016-12-18 12:56:06 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-18 12:56:06 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-09-22 02:21:17 +00:00
|
|
|
if targetUser.Active {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalError("The account you're trying to activate has already been activated.", w, r, user)
|
2016-12-18 12:56:06 +00:00
|
|
|
}
|
2017-09-22 02:21:17 +00:00
|
|
|
err = targetUser.Activate()
|
2016-12-21 02:30:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2016-12-21 02:30:32 +00:00
|
|
|
}
|
2017-06-06 14:41:06 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.ModLogs.Create("activate", targetUser.ID, "user", user.LastIP, user.ID)
|
2017-04-06 17:37:32 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-04-06 17:37:32 +00:00
|
|
|
}
|
2017-09-22 02:21:17 +00:00
|
|
|
http.Redirect(w, r, "/user/"+strconv.Itoa(targetUser.ID), http.StatusSeeOther)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2016-12-18 12:56:06 +00:00
|
|
|
}
|