2017-09-03 04:50:31 +00:00
|
|
|
/*
|
|
|
|
*
|
2017-09-13 15:09:13 +00:00
|
|
|
* Gosora Route Handlers
|
|
|
|
* Copyright Azareal 2016 - 2018
|
2017-09-03 04:50:31 +00:00
|
|
|
*
|
|
|
|
*/
|
2016-12-02 07:38:54 +00:00
|
|
|
package main
|
|
|
|
|
2017-05-11 13:04:43 +00:00
|
|
|
import (
|
2017-09-03 04:50:31 +00:00
|
|
|
"html"
|
2017-12-24 07:38:46 +00:00
|
|
|
"log"
|
2017-05-11 13:04:43 +00:00
|
|
|
"net/http"
|
2017-09-03 04:50:31 +00:00
|
|
|
"strconv"
|
2017-06-19 08:06:54 +00:00
|
|
|
|
2017-11-10 03:33:11 +00:00
|
|
|
"./common"
|
2017-05-11 13:04:43 +00:00
|
|
|
)
|
2017-04-05 14:05:37 +00:00
|
|
|
|
2016-12-02 07:38:54 +00:00
|
|
|
// A blank list to fill out that parameter in Page for routes which don't use it
|
2016-12-18 12:56:06 +00:00
|
|
|
var tList []interface{}
|
2017-09-03 04:50:31 +00:00
|
|
|
|
|
|
|
//var nList []string
|
|
|
|
var successJSONBytes = []byte(`{"success":"1"}`)
|
2016-12-02 07:38:54 +00:00
|
|
|
|
2017-09-18 17:03:52 +00:00
|
|
|
// HTTPSRedirect is a connection handler which redirects all HTTP requests to HTTPS
|
2017-09-10 16:57:22 +00:00
|
|
|
type HTTPSRedirect struct {
|
2017-08-13 11:22:34 +00:00
|
|
|
}
|
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
2017-12-22 03:32:23 +00:00
|
|
|
w.Header().Set("Connection", "close")
|
2017-08-13 11:22:34 +00:00
|
|
|
dest := "https://" + req.Host + req.URL.Path
|
|
|
|
if len(req.URL.RawQuery) > 0 {
|
|
|
|
dest += "?" + req.URL.RawQuery
|
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
http.Redirect(w, req, dest, http.StatusTemporaryRedirect)
|
2017-08-13 11:22:34 +00:00
|
|
|
}
|
|
|
|
|
2017-12-24 22:08:35 +00:00
|
|
|
// Temporary stubs for view tracking
|
|
|
|
func routeDynamic() {
|
|
|
|
}
|
|
|
|
func routeUploads() {
|
|
|
|
}
|
2018-01-26 05:53:34 +00:00
|
|
|
func BadRoute() {
|
|
|
|
}
|
2017-12-24 22:08:35 +00:00
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeForums(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
|
2016-12-16 10:37:42 +00:00
|
|
|
}
|
2017-11-29 02:34:02 +00:00
|
|
|
headerVars.Zone = "forums"
|
2017-12-27 23:38:37 +00:00
|
|
|
headerVars.MetaDesc = headerVars.Settings["meta_desc"].(string)
|
2017-05-29 14:52:37 +00:00
|
|
|
|
2017-02-06 04:52:19 +00:00
|
|
|
var err error
|
2017-11-11 04:06:16 +00:00
|
|
|
var forumList []common.Forum
|
2017-07-12 11:05:18 +00:00
|
|
|
var canSee []int
|
2017-09-03 04:50:31 +00:00
|
|
|
if user.IsSuperAdmin {
|
2017-11-23 05:37:08 +00:00
|
|
|
canSee, err = common.Forums.GetAllVisibleIDs()
|
2017-07-12 11:05:18 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-07-12 11:05:18 +00:00
|
|
|
}
|
|
|
|
} else {
|
2017-11-23 05:37:08 +00:00
|
|
|
group, err := common.Groups.Get(user.Group)
|
2017-09-15 22:20:01 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
log.Printf("Group #%d doesn't exist despite being used by common.User #%d", user.Group, user.ID)
|
|
|
|
return common.LocalError("Something weird happened", w, r, user)
|
2017-09-15 22:20:01 +00:00
|
|
|
}
|
2017-07-12 11:05:18 +00:00
|
|
|
canSee = group.CanSee
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, fid := range canSee {
|
2017-09-28 22:16:34 +00:00
|
|
|
// Avoid data races by copying the struct into something we can freely mold without worrying about breaking something somewhere else
|
2017-11-23 05:37:08 +00:00
|
|
|
var forum = common.Forums.DirtyGet(fid).Copy()
|
2017-09-24 00:49:41 +00:00
|
|
|
if forum.ParentID == 0 && forum.Name != "" && forum.Active {
|
2017-02-06 04:52:19 +00:00
|
|
|
if forum.LastTopicID != 0 {
|
2017-09-28 22:16:34 +00:00
|
|
|
if forum.LastTopic.ID != 0 && forum.LastReplyer.ID != 0 {
|
2017-11-11 04:06:16 +00:00
|
|
|
forum.LastTopicTime = common.RelativeTime(forum.LastTopic.LastReplyAt)
|
2017-09-28 22:16:34 +00:00
|
|
|
} else {
|
|
|
|
forum.LastTopicTime = ""
|
2017-02-06 04:52:19 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
forum.LastTopicTime = ""
|
|
|
|
}
|
2018-02-19 04:26:01 +00:00
|
|
|
common.RunHook("forums_frow_assign", &forum)
|
2017-02-06 04:52:19 +00:00
|
|
|
forumList = append(forumList, forum)
|
2016-12-03 13:45:08 +00:00
|
|
|
}
|
|
|
|
}
|
2017-05-29 14:52:37 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
pi := common.ForumsPage{common.GetTitlePhrase("forums"), user, headerVars, forumList}
|
2018-02-19 04:26:01 +00:00
|
|
|
if common.RunPreRenderHook("pre_render_forum_list", w, r, &user, &pi) {
|
|
|
|
return nil
|
2017-07-12 11:05:18 +00:00
|
|
|
}
|
2017-11-23 05:37:08 +00:00
|
|
|
err = common.RunThemeTemplate(headerVars.Theme.Name, "forums", pi, w)
|
2017-10-30 09:57:08 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalError(err, w, r)
|
2017-10-30 09:57:08 +00:00
|
|
|
}
|
|
|
|
return nil
|
2016-12-07 09:34:09 +00:00
|
|
|
}
|
|
|
|
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Set the cookie domain
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeChangeTheme(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2017-09-10 17:39:16 +00:00
|
|
|
//headerLite, _ := SimpleUserCheck(w, r, &user)
|
2017-09-10 16:57:22 +00:00
|
|
|
// TODO: Rename isJs to something else, just in case we rewrite the JS side in WebAssembly?
|
|
|
|
isJs := (r.PostFormValue("isJs") == "1")
|
|
|
|
newTheme := html.EscapeString(r.PostFormValue("newTheme"))
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
theme, ok := common.Themes[newTheme]
|
2017-09-10 16:57:22 +00:00
|
|
|
if !ok || theme.HideFromThemes {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJSQ("That theme doesn't exist", w, r, user, isJs)
|
2017-09-10 16:57:22 +00:00
|
|
|
}
|
|
|
|
|
2017-11-11 04:06:16 +00:00
|
|
|
cookie := http.Cookie{Name: "current_theme", Value: newTheme, Path: "/", MaxAge: common.Year}
|
2017-09-10 16:57:22 +00:00
|
|
|
http.SetCookie(w, &cookie)
|
|
|
|
|
|
|
|
if !isJs {
|
|
|
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
|
|
|
} else {
|
|
|
|
_, _ = w.Write(successJSONBytes)
|
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-09-10 16:57:22 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
// TODO: Refactor this
|
2017-09-10 16:57:22 +00:00
|
|
|
var phraseLoginAlerts = []byte(`{"msgs":[{"msg":"Login to see your alerts","path":"/accounts/login"}]}`)
|
2017-09-03 04:50:31 +00:00
|
|
|
|
2017-11-23 05:37:08 +00:00
|
|
|
// TODO: Refactor this endpoint
|
2017-11-11 04:06:16 +00:00
|
|
|
func routeAPI(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
2017-11-23 05:37:08 +00:00
|
|
|
// TODO: Don't make this too JSON dependent so that we can swap in newer more efficient formats
|
2017-09-03 04:50:31 +00:00
|
|
|
w.Header().Set("Content-Type", "application/json")
|
2017-02-28 09:27:28 +00:00
|
|
|
err := r.ParseForm()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("Bad Form", w, r)
|
2017-02-28 09:27:28 +00:00
|
|
|
}
|
2017-05-29 14:52:37 +00:00
|
|
|
|
2017-02-28 09:27:28 +00:00
|
|
|
action := r.FormValue("action")
|
|
|
|
if action != "get" && action != "set" {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("Invalid Action", w, r)
|
2017-02-28 09:27:28 +00:00
|
|
|
}
|
2017-05-29 14:52:37 +00:00
|
|
|
|
2017-02-28 09:27:28 +00:00
|
|
|
module := r.FormValue("module")
|
2017-09-03 04:50:31 +00:00
|
|
|
switch module {
|
|
|
|
case "dismiss-alert":
|
|
|
|
asid, err := strconv.Atoi(r.FormValue("asid"))
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("Invalid asid", w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
2017-11-05 09:55:34 +00:00
|
|
|
_, err = stmts.deleteActivityStreamMatch.Exec(user.ID, asid)
|
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
|
|
|
}
|
|
|
|
case "alerts": // A feed of events tailored for a specific user
|
|
|
|
if !user.Loggedin {
|
2017-09-10 16:57:22 +00:00
|
|
|
w.Write(phraseLoginAlerts)
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
2017-05-29 14:52:37 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
var msglist, event, elementType string
|
|
|
|
var asid, actorID, targetUserID, elementID int
|
|
|
|
var msgCount int
|
2017-06-10 07:58:15 +00:00
|
|
|
|
2017-11-05 09:55:34 +00:00
|
|
|
err = stmts.getActivityCountByWatcher.QueryRow(user.ID).Scan(&msgCount)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err == ErrNoRows {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("Couldn't find the parent topic", w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
} else if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJS(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 09:55:34 +00:00
|
|
|
rows, err := stmts.getActivityFeedByWatcher.Query(user.ID)
|
2017-09-03 04:50:31 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJS(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
defer rows.Close()
|
2017-05-29 14:52:37 +00:00
|
|
|
|
2017-09-03 04:50:31 +00:00
|
|
|
for rows.Next() {
|
|
|
|
err = rows.Scan(&asid, &actorID, &targetUserID, &event, &elementType, &elementID)
|
2017-02-28 09:27:28 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJS(err, w, r)
|
2017-02-28 09:27:28 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
res, err := buildAlert(asid, event, elementType, actorID, targetUserID, elementID, user)
|
2017-02-28 09:27:28 +00:00
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.LocalErrorJS(err.Error(), w, r)
|
2017-02-28 09:27:28 +00:00
|
|
|
}
|
2017-09-03 04:50:31 +00:00
|
|
|
msglist += res + ","
|
|
|
|
}
|
|
|
|
err = rows.Err()
|
|
|
|
if err != nil {
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.InternalErrorJS(err, w, r)
|
2017-09-03 04:50:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(msglist) != 0 {
|
|
|
|
msglist = msglist[0 : len(msglist)-1]
|
|
|
|
}
|
|
|
|
_, _ = w.Write([]byte(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`))
|
|
|
|
default:
|
2017-11-11 04:06:16 +00:00
|
|
|
return common.PreErrorJS("Invalid Module", w, r)
|
2017-02-28 09:27:28 +00:00
|
|
|
}
|
2017-10-30 09:57:08 +00:00
|
|
|
return nil
|
2017-02-28 09:27:28 +00:00
|
|
|
}
|