Finished moving the files into the subpackage, this should open more doors to us.
Moved more queries out of the global stmt holder. Refactored several things.
This commit is contained in:
parent
10e681f15f
commit
f30ea7a9bb
28
alerts.go
28
alerts.go
@ -6,10 +6,14 @@
|
||||
*/
|
||||
package main
|
||||
|
||||
import "log"
|
||||
import "strings"
|
||||
import "strconv"
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
// These notes are for me, don't worry about it too much ^_^
|
||||
/*
|
||||
@ -26,10 +30,10 @@ import "errors"
|
||||
"{x}{created a new topic}{topic}"
|
||||
*/
|
||||
|
||||
func buildAlert(asid int, event string, elementType string, actorID int, targetUserID int, elementID int, user User /* The current user */) (string, error) {
|
||||
var targetUser *User
|
||||
func buildAlert(asid int, event string, elementType string, actorID int, targetUserID int, elementID int, user common.User /* The current user */) (string, error) {
|
||||
var targetUser *common.User
|
||||
|
||||
actor, err := users.Get(actorID)
|
||||
actor, err := common.Users.Get(actorID)
|
||||
if err != nil {
|
||||
return "", errors.New("Unable to find the actor")
|
||||
}
|
||||
@ -52,7 +56,7 @@ func buildAlert(asid int, event string, elementType string, actorID int, targetU
|
||||
case "forum":
|
||||
if event == "reply" {
|
||||
act = "created a new topic"
|
||||
topic, err := topics.Get(elementID)
|
||||
topic, err := common.Topics.Get(elementID)
|
||||
if err != nil {
|
||||
return "", errors.New("Unable to find the linked topic")
|
||||
}
|
||||
@ -64,7 +68,7 @@ func buildAlert(asid int, event string, elementType string, actorID int, targetU
|
||||
act = "did something in a forum"
|
||||
}
|
||||
case "topic":
|
||||
topic, err := topics.Get(elementID)
|
||||
topic, err := common.Topics.Get(elementID)
|
||||
if err != nil {
|
||||
return "", errors.New("Unable to find the linked topic")
|
||||
}
|
||||
@ -75,7 +79,7 @@ func buildAlert(asid int, event string, elementType string, actorID int, targetU
|
||||
postAct = " your topic"
|
||||
}
|
||||
case "user":
|
||||
targetUser, err = users.Get(elementID)
|
||||
targetUser, err = common.Users.Get(elementID)
|
||||
if err != nil {
|
||||
return "", errors.New("Unable to find the target user")
|
||||
}
|
||||
@ -83,7 +87,9 @@ func buildAlert(asid int, event string, elementType string, actorID int, targetU
|
||||
endFrag = "'s profile"
|
||||
url = targetUser.Link
|
||||
case "post":
|
||||
topic, err := getTopicByReply(elementID)
|
||||
reply := common.BlankReply()
|
||||
reply.ID = elementID
|
||||
topic, err := reply.Topic()
|
||||
if err != nil {
|
||||
return "", errors.New("Unable to find the linked reply or parent topic")
|
||||
}
|
||||
|
@ -4,18 +4,17 @@
|
||||
* Copyright Azareal 2017 - 2018
|
||||
*
|
||||
*/
|
||||
package main
|
||||
package common
|
||||
|
||||
import "log"
|
||||
import "errors"
|
||||
import "strconv"
|
||||
import "net/http"
|
||||
import "database/sql"
|
||||
|
||||
import "./query_gen/lib"
|
||||
import "golang.org/x/crypto/bcrypt"
|
||||
import "../query_gen/lib"
|
||||
|
||||
var auth Auth
|
||||
var Auth AuthInt
|
||||
|
||||
// ErrMismatchedHashAndPassword is thrown whenever a hash doesn't match it's unhashed password
|
||||
var ErrMismatchedHashAndPassword = bcrypt.ErrMismatchedHashAndPassword
|
||||
@ -27,8 +26,8 @@ var ErrWrongPassword = errors.New("That's not the correct password.")
|
||||
var ErrSecretError = errors.New("There was a glitch in the system. Please contact your local administrator.")
|
||||
var ErrNoUserByName = errors.New("We couldn't find an account with that username.")
|
||||
|
||||
// Auth is the main authentication interface.
|
||||
type Auth interface {
|
||||
// AuthInt is the main authentication interface.
|
||||
type AuthInt interface {
|
||||
Authenticate(username string, password string) (uid int, err error)
|
||||
Logout(w http.ResponseWriter, uid int)
|
||||
ForceLogout(uid int) error
|
||||
@ -40,24 +39,19 @@ type Auth interface {
|
||||
|
||||
// DefaultAuth is the default authenticator used by Gosora, may be swapped with an alternate authenticator in some situations. E.g. To support LDAP.
|
||||
type DefaultAuth struct {
|
||||
login *sql.Stmt
|
||||
logout *sql.Stmt
|
||||
login *sql.Stmt
|
||||
logout *sql.Stmt
|
||||
updateSession *sql.Stmt
|
||||
}
|
||||
|
||||
// NewDefaultAuth is a factory for spitting out DefaultAuths
|
||||
func NewDefaultAuth() *DefaultAuth {
|
||||
loginStmt, err := qgen.Builder.SimpleSelect("users", "uid, password, salt", "name = ?", "", "")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
logoutStmt, err := qgen.Builder.SimpleUpdate("users", "session = ''", "uid = ?")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
func NewDefaultAuth() (*DefaultAuth, error) {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
return &DefaultAuth{
|
||||
login: loginStmt,
|
||||
logout: logoutStmt,
|
||||
}
|
||||
login: acc.SimpleSelect("users", "uid, password, salt", "name = ?", "", ""),
|
||||
logout: acc.SimpleUpdate("users", "session = ''", "uid = ?"),
|
||||
updateSession: acc.SimpleUpdate("users", "session = ?", "uid = ?"),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
// Authenticate checks if a specific username and password is valid and returns the UID for the corresponding user, if so. Otherwise, a user safe error.
|
||||
@ -97,7 +91,7 @@ func (auth *DefaultAuth) ForceLogout(uid int) error {
|
||||
}
|
||||
|
||||
// Flush the user out of the cache
|
||||
ucache, ok := users.(UserCache)
|
||||
ucache, ok := Users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(uid)
|
||||
}
|
||||
@ -107,18 +101,18 @@ func (auth *DefaultAuth) ForceLogout(uid int) error {
|
||||
|
||||
// Logout logs you out of the computer you requested the logout for, but not the other computers you're logged in with
|
||||
func (auth *DefaultAuth) Logout(w http.ResponseWriter, _ int) {
|
||||
cookie := http.Cookie{Name: "uid", Value: "", Path: "/", MaxAge: year}
|
||||
cookie := http.Cookie{Name: "uid", Value: "", Path: "/", MaxAge: Year}
|
||||
http.SetCookie(w, &cookie)
|
||||
cookie = http.Cookie{Name: "session", Value: "", Path: "/", MaxAge: year}
|
||||
cookie = http.Cookie{Name: "session", Value: "", Path: "/", MaxAge: Year}
|
||||
http.SetCookie(w, &cookie)
|
||||
}
|
||||
|
||||
// TODO: Set the cookie domain
|
||||
// SetCookies sets the two cookies required for the current user to be recognised as a specific user in future requests
|
||||
func (auth *DefaultAuth) SetCookies(w http.ResponseWriter, uid int, session string) {
|
||||
cookie := http.Cookie{Name: "uid", Value: strconv.Itoa(uid), Path: "/", MaxAge: year}
|
||||
cookie := http.Cookie{Name: "uid", Value: strconv.Itoa(uid), Path: "/", MaxAge: Year}
|
||||
http.SetCookie(w, &cookie)
|
||||
cookie = http.Cookie{Name: "session", Value: session, Path: "/", MaxAge: year}
|
||||
cookie = http.Cookie{Name: "session", Value: session, Path: "/", MaxAge: Year}
|
||||
http.SetCookie(w, &cookie)
|
||||
}
|
||||
|
||||
@ -144,20 +138,20 @@ func (auth *DefaultAuth) GetCookies(r *http.Request) (uid int, session string, e
|
||||
func (auth *DefaultAuth) SessionCheck(w http.ResponseWriter, r *http.Request) (user *User, halt bool) {
|
||||
uid, session, err := auth.GetCookies(r)
|
||||
if err != nil {
|
||||
return &guestUser, false
|
||||
return &GuestUser, false
|
||||
}
|
||||
|
||||
// Is this session valid..?
|
||||
user, err = users.Get(uid)
|
||||
user, err = Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
return &guestUser, false
|
||||
return &GuestUser, false
|
||||
} else if err != nil {
|
||||
InternalError(err, w, r)
|
||||
return &guestUser, true
|
||||
return &GuestUser, true
|
||||
}
|
||||
|
||||
if user.Session == "" || session != user.Session {
|
||||
return &guestUser, false
|
||||
return &GuestUser, false
|
||||
}
|
||||
|
||||
return user, false
|
||||
@ -165,18 +159,18 @@ func (auth *DefaultAuth) SessionCheck(w http.ResponseWriter, r *http.Request) (u
|
||||
|
||||
// CreateSession generates a new session to allow a remote client to stay logged in as a specific user
|
||||
func (auth *DefaultAuth) CreateSession(uid int) (session string, err error) {
|
||||
session, err = GenerateSafeString(sessionLength)
|
||||
session, err = GenerateSafeString(SessionLength)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, err = stmts.updateSession.Exec(session, uid)
|
||||
_, err = auth.updateSession.Exec(session, uid)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Flush the user data from the cache
|
||||
ucache, ok := users.(UserCache)
|
||||
ucache, ok := Users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(uid)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package common
|
||||
|
||||
import "errors"
|
||||
|
||||
@ -17,10 +17,10 @@ var ErrStoreCapacityOverflow = errors.New("This datastore has reached it's maxim
|
||||
|
||||
// nolint
|
||||
type DataStore interface {
|
||||
Load(id int) error
|
||||
DirtyGet(id int) interface{}
|
||||
Get(id int) (interface{}, error)
|
||||
BypassGet(id int) (interface{}, error)
|
||||
//GetGlobalCount()
|
||||
//GlobalCount()
|
||||
}
|
||||
|
||||
// nolint
|
||||
@ -32,6 +32,9 @@ type DataCache interface {
|
||||
CacheAddUnsafe(item interface{}) error
|
||||
CacheRemove(id int) error
|
||||
CacheRemoveUnsafe(id int) error
|
||||
GetLength() int
|
||||
Reload(id int) error
|
||||
Flush()
|
||||
Length() int
|
||||
SetCapacity(capacity int)
|
||||
GetCapacity() int
|
||||
}
|
@ -2,5 +2,78 @@ package common
|
||||
|
||||
import "database/sql"
|
||||
|
||||
// nolint I don't want to write comments for each of these o.o
|
||||
const Hour int = 60 * 60
|
||||
const Day int = Hour * 24
|
||||
const Week int = Day * 7
|
||||
const Month int = Day * 30
|
||||
const Year int = Day * 365
|
||||
const Kilobyte int = 1024
|
||||
const Megabyte int = Kilobyte * 1024
|
||||
const Gigabyte int = Megabyte * 1024
|
||||
const Terabyte int = Gigabyte * 1024
|
||||
const Petabyte int = Terabyte * 1024
|
||||
|
||||
const SaltLength int = 32
|
||||
const SessionLength int = 80
|
||||
|
||||
var TmplPtrMap = make(map[string]interface{})
|
||||
|
||||
// ErrNoRows is an alias of sql.ErrNoRows, just in case we end up with non-database/sql datastores
|
||||
var ErrNoRows = sql.ErrNoRows
|
||||
|
||||
// ? - Make this more customisable?
|
||||
var ExternalSites = map[string]string{
|
||||
"YT": "https://www.youtube.com/",
|
||||
}
|
||||
|
||||
type StringList []string
|
||||
|
||||
// ? - Should we allow users to upload .php or .go files? It could cause security issues. We could store them with a mangled extension to render them inert
|
||||
// TODO: Let admins manage this from the Control Panel
|
||||
var AllowedFileExts = StringList{
|
||||
"png", "jpg", "jpeg", "svg", "bmp", "gif", "tif", "webp", "apng", // images
|
||||
|
||||
"txt", "xml", "json", "yaml", "toml", "ini", "md", "html", "rtf", "js", "py", "rb", "css", "scss", "less", "eqcss", "pcss", "java", "ts", "cs", "c", "cc", "cpp", "cxx", "C", "c++", "h", "hh", "hpp", "hxx", "h++", "rs", "rlib", "htaccess", "gitignore", // text
|
||||
|
||||
"mp3", "mp4", "avi", "wmv", "webm", // video
|
||||
|
||||
"otf", "woff2", "woff", "ttf", "eot", // fonts
|
||||
}
|
||||
var ImageFileExts = StringList{
|
||||
"png", "jpg", "jpeg", "svg", "bmp", "gif", "tif", "webp", "apng",
|
||||
}
|
||||
var ArchiveFileExts = StringList{
|
||||
"bz2", "zip", "gz", "7z", "tar", "cab",
|
||||
}
|
||||
var ExecutableFileExts = StringList{
|
||||
"exe", "jar", "phar", "shar", "iso",
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func (slice StringList) Contains(needle string) bool {
|
||||
for _, item := range slice {
|
||||
if item == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type DBInits []func() error
|
||||
|
||||
var DbInits DBInits
|
||||
|
||||
func (inits DBInits) Run() error {
|
||||
for _, init := range inits {
|
||||
err := init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (inits DBInits) Add(init ...func() error) {
|
||||
inits = append(inits, init...)
|
||||
}
|
||||
|
73
common/email.go
Normal file
73
common/email.go
Normal file
@ -0,0 +1,73 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/smtp"
|
||||
)
|
||||
|
||||
type Email struct {
|
||||
UserID int
|
||||
Email string
|
||||
Validated bool
|
||||
Primary bool
|
||||
Token string
|
||||
}
|
||||
|
||||
func SendValidationEmail(username string, email string, token string) bool {
|
||||
var schema = "http"
|
||||
if Site.EnableSsl {
|
||||
schema += "s"
|
||||
}
|
||||
|
||||
// TODO: Move these to the phrase system
|
||||
subject := "Validate Your Email @ " + Site.Name
|
||||
msg := "Dear " + username + ", following your registration on our forums, we ask you to validate your email, so that we can confirm that this email actually belongs to you.\n\nClick on the following link to do so. " + schema + "://" + Site.URL + "/user/edit/token/" + token + "\n\nIf you haven't created an account here, then please feel free to ignore this email.\nWe're sorry for the inconvenience this may have caused."
|
||||
return SendEmail(email, subject, msg)
|
||||
}
|
||||
|
||||
// TODO: Refactor this
|
||||
func SendEmail(email string, subject string, msg string) bool {
|
||||
// This hook is useful for plugin_sendmail or for testing tools. Possibly to hook it into some sort of mail server?
|
||||
if Vhooks["email_send_intercept"] != nil {
|
||||
return Vhooks["email_send_intercept"](email, subject, msg).(bool)
|
||||
}
|
||||
body := "Subject: " + subject + "\n\n" + msg + "\n"
|
||||
|
||||
con, err := smtp.Dial(Config.SMTPServer + ":" + Config.SMTPPort)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if Config.SMTPUsername != "" {
|
||||
auth := smtp.PlainAuth("", Config.SMTPUsername, Config.SMTPPassword, Config.SMTPServer)
|
||||
err = con.Auth(auth)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
err = con.Mail(Site.Email)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
err = con.Rcpt(email)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
emailData, err := con.Data()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = fmt.Fprintf(emailData, body)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
err = emailData.Close()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
err = con.Quit()
|
||||
return err == nil
|
||||
}
|
@ -21,7 +21,7 @@ var tList []interface{}
|
||||
type RouteError interface {
|
||||
Type() string
|
||||
Error() string
|
||||
Json() bool
|
||||
JSON() bool
|
||||
Handled() bool
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ func (err *RouteErrorImpl) Error() string {
|
||||
}
|
||||
|
||||
// Respond with JSON?
|
||||
func (err *RouteErrorImpl) Json() bool {
|
||||
func (err *RouteErrorImpl) JSON() bool {
|
||||
return err.json
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ func InternalError(err error, w http.ResponseWriter, r *http.Request) RouteError
|
||||
// TODO: Centralise the user struct somewhere else
|
||||
user := User{0, "guest", "Guest", "", 0, false, false, false, false, false, false, GuestPerms, nil, "", false, "", "", "", "", "", 0, 0, "0.0.0.0.0", 0}
|
||||
pi := Page{"Internal Server Error", user, DefaultHeaderVar(), tList, "A problem has occurred in the system."}
|
||||
err = templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err = Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
@ -119,33 +119,16 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteErr
|
||||
return HandledRouteError()
|
||||
}
|
||||
|
||||
// ? - Where is this used? Should we use it more?
|
||||
// LoginRequired is an error shown to the end-user when they try to access an area which requires them to login
|
||||
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(401)
|
||||
pi := Page{"Local Error", user, DefaultHeaderVar(), tList, "You need to login to do that."}
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
return HandledRouteError()
|
||||
}
|
||||
|
||||
func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError {
|
||||
w.WriteHeader(500)
|
||||
user := User{ID: 0, Group: 6, Perms: GuestPerms}
|
||||
pi := Page{"Error", user, DefaultHeaderVar(), tList, errmsg}
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
if PreRenderHooks["pre_render_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -169,12 +152,12 @@ func PreErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, isJs boo
|
||||
func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(500)
|
||||
pi := Page{"Local Error", user, DefaultHeaderVar(), tList, errmsg}
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
if PreRenderHooks["pre_render_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -200,12 +183,12 @@ func NoPermissions(w http.ResponseWriter, r *http.Request, user User) RouteError
|
||||
w.WriteHeader(403)
|
||||
pi := Page{"Local Error", user, DefaultHeaderVar(), tList, "You don't have permission to do that."}
|
||||
// TODO: What to do about this hook?
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
if PreRenderHooks["pre_render_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -229,12 +212,12 @@ func NoPermissionsJS(w http.ResponseWriter, r *http.Request, user User) RouteErr
|
||||
func Banned(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(403)
|
||||
pi := Page{"Banned", user, DefaultHeaderVar(), tList, "You have been banned from this site."}
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
if PreRenderHooks["pre_render_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -258,21 +241,33 @@ func BannedJS(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
|
||||
// nolint
|
||||
func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) RouteError {
|
||||
w.WriteHeader(401)
|
||||
if !isJs {
|
||||
pi := Page{"Local Error", user, DefaultHeaderVar(), tList, "You need to login to do that."}
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
} else {
|
||||
_, _ = w.Write([]byte(`{"errmsg":"You need to login to do that."}`))
|
||||
return LoginRequired(w, r, user)
|
||||
}
|
||||
return LoginRequiredJS(w, r, user)
|
||||
}
|
||||
|
||||
// ? - Where is this used? Should we use it more?
|
||||
// LoginRequired is an error shown to the end-user when they try to access an area which requires them to login
|
||||
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(401)
|
||||
pi := Page{"Local Error", user, DefaultHeaderVar(), tList, "You need to login to do that."}
|
||||
if PreRenderHooks["pre_render_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
return HandledRouteError()
|
||||
}
|
||||
|
||||
// nolint
|
||||
func LoginRequiredJS(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(401)
|
||||
_, _ = w.Write([]byte(`{"errmsg":"You need to login to do that."}`))
|
||||
return HandledRouteError()
|
||||
}
|
||||
|
||||
@ -281,12 +276,12 @@ func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bo
|
||||
func SecurityError(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(403)
|
||||
pi := Page{"Security Error", user, DefaultHeaderVar(), tList, "There was a security issue with your request."}
|
||||
if preRenderHooks["pre_render_security_error"] != nil {
|
||||
if runPreRenderHook("pre_render_security_error", w, r, &user, &pi) {
|
||||
if PreRenderHooks["pre_render_security_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_security_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -301,7 +296,7 @@ func NotFound(w http.ResponseWriter, r *http.Request) RouteError {
|
||||
// TODO: Centralise the user struct somewhere else
|
||||
user := User{0, "guest", "Guest", "", 0, false, false, false, false, false, false, GuestPerms, nil, "", false, "", "", "", "", "", 0, 0, "0.0.0.0.0", 0}
|
||||
pi := Page{"Not Found", user, DefaultHeaderVar(), tList, "The requested page doesn't exist."}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -312,12 +307,12 @@ func NotFound(w http.ResponseWriter, r *http.Request) RouteError {
|
||||
func CustomError(errmsg string, errcode int, errtitle string, w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
w.WriteHeader(errcode)
|
||||
pi := Page{errtitle, user, DefaultHeaderVar(), tList, errmsg}
|
||||
if preRenderHooks["pre_render_error"] != nil {
|
||||
if runPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
if PreRenderHooks["pre_render_error"] != nil {
|
||||
if RunPreRenderHook("pre_render_error", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := templates.ExecuteTemplate(w, "error.html", pi)
|
||||
err := Templates.ExecuteTemplate(w, "error.html", pi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ type PluginList map[string]*Plugin
|
||||
var Plugins PluginList = make(map[string]*Plugin)
|
||||
|
||||
// Hooks with a single argument. Is this redundant? Might be useful for inlining, as variadics aren't inlined? Are closures even inlined to begin with?
|
||||
var hooks = map[string][]func(interface{}) interface{}{
|
||||
var Hooks = map[string][]func(interface{}) interface{}{
|
||||
"forums_frow_assign": nil,
|
||||
"topic_create_frow_assign": nil,
|
||||
}
|
||||
|
||||
// Hooks with a variable number of arguments
|
||||
var vhooks = map[string]func(...interface{}) interface{}{
|
||||
var Vhooks = map[string]func(...interface{}) interface{}{
|
||||
"intercept_build_widgets": nil,
|
||||
"forum_trow_assign": nil,
|
||||
"topics_topic_row_assign": nil,
|
||||
@ -35,7 +35,7 @@ var vhooks = map[string]func(...interface{}) interface{}{
|
||||
}
|
||||
|
||||
// Hooks with a variable number of arguments and return values for skipping the parent function and propagating an error upwards
|
||||
var vhookSkippable = map[string]func(...interface{}) (bool, RouteError){
|
||||
var VhookSkippable = map[string]func(...interface{}) (bool, RouteError){
|
||||
"simple_forum_check_pre_perms": nil,
|
||||
"forum_check_pre_perms": nil,
|
||||
}
|
||||
@ -65,13 +65,13 @@ var messageHooks = map[string][]func(Message, PageInt, ...interface{}) interface
|
||||
}
|
||||
|
||||
// Hooks which take in and spit out a string. This is usually used for parser components
|
||||
var sshooks = map[string][]func(string) string{
|
||||
var Sshooks = map[string][]func(string) string{
|
||||
"preparse_preassign": nil,
|
||||
"parse_assign": nil,
|
||||
}
|
||||
|
||||
// The hooks which run before the template is rendered for a route
|
||||
var preRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User, interface{}) bool{
|
||||
var PreRenderHooks = map[string][]func(http.ResponseWriter, *http.Request, *User, interface{}) bool{
|
||||
"pre_render": nil,
|
||||
|
||||
"pre_render_forum_list": nil,
|
||||
@ -137,7 +137,7 @@ type Plugin struct {
|
||||
Data interface{} // Usually used for hosting the VMs / reusable elements of non-native plugins
|
||||
}
|
||||
|
||||
func initExtend() (err error) {
|
||||
func InitExtend() (err error) {
|
||||
err = InitPluginLangs()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -145,7 +145,7 @@ func initExtend() (err error) {
|
||||
return Plugins.Load()
|
||||
}
|
||||
|
||||
// LoadPlugins polls the database to see which plugins have been activated and which have been installed
|
||||
// Load polls the database to see which plugins have been activated and which have been installed
|
||||
func (plugins PluginList) Load() error {
|
||||
getPlugins, err := qgen.Builder.SimpleSelect("plugins", "uname, active, installed", "", "", "")
|
||||
if err != nil {
|
||||
@ -206,37 +206,37 @@ func NewPlugin(uname string, name string, author string, url string, settings st
|
||||
func (plugin *Plugin) AddHook(name string, handler interface{}) {
|
||||
switch h := handler.(type) {
|
||||
case func(interface{}) interface{}:
|
||||
if len(hooks[name]) == 0 {
|
||||
if len(Hooks[name]) == 0 {
|
||||
var hookSlice []func(interface{}) interface{}
|
||||
hookSlice = append(hookSlice, h)
|
||||
hooks[name] = hookSlice
|
||||
Hooks[name] = hookSlice
|
||||
} else {
|
||||
hooks[name] = append(hooks[name], h)
|
||||
Hooks[name] = append(Hooks[name], h)
|
||||
}
|
||||
plugin.Hooks[name] = len(hooks[name])
|
||||
plugin.Hooks[name] = len(Hooks[name])
|
||||
case func(string) string:
|
||||
if len(sshooks[name]) == 0 {
|
||||
if len(Sshooks[name]) == 0 {
|
||||
var hookSlice []func(string) string
|
||||
hookSlice = append(hookSlice, h)
|
||||
sshooks[name] = hookSlice
|
||||
Sshooks[name] = hookSlice
|
||||
} else {
|
||||
sshooks[name] = append(sshooks[name], h)
|
||||
Sshooks[name] = append(Sshooks[name], h)
|
||||
}
|
||||
plugin.Hooks[name] = len(sshooks[name])
|
||||
plugin.Hooks[name] = len(Sshooks[name])
|
||||
case func(http.ResponseWriter, *http.Request, *User, interface{}) bool:
|
||||
if len(preRenderHooks[name]) == 0 {
|
||||
if len(PreRenderHooks[name]) == 0 {
|
||||
var hookSlice []func(http.ResponseWriter, *http.Request, *User, interface{}) bool
|
||||
hookSlice = append(hookSlice, h)
|
||||
preRenderHooks[name] = hookSlice
|
||||
PreRenderHooks[name] = hookSlice
|
||||
} else {
|
||||
preRenderHooks[name] = append(preRenderHooks[name], h)
|
||||
PreRenderHooks[name] = append(PreRenderHooks[name], h)
|
||||
}
|
||||
plugin.Hooks[name] = len(preRenderHooks[name])
|
||||
plugin.Hooks[name] = len(PreRenderHooks[name])
|
||||
case func(...interface{}) interface{}:
|
||||
vhooks[name] = h
|
||||
Vhooks[name] = h
|
||||
plugin.Hooks[name] = 0
|
||||
case func(...interface{}) (bool, RouteError):
|
||||
vhookSkippable[name] = h
|
||||
VhookSkippable[name] = h
|
||||
plugin.Hooks[name] = 0
|
||||
default:
|
||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||
@ -248,35 +248,35 @@ func (plugin *Plugin) RemoveHook(name string, handler interface{}) {
|
||||
switch handler.(type) {
|
||||
case func(interface{}) interface{}:
|
||||
key := plugin.Hooks[name]
|
||||
hook := hooks[name]
|
||||
hook := Hooks[name]
|
||||
if len(hook) == 1 {
|
||||
hook = []func(interface{}) interface{}{}
|
||||
} else {
|
||||
hook = append(hook[:key], hook[key+1:]...)
|
||||
}
|
||||
hooks[name] = hook
|
||||
Hooks[name] = hook
|
||||
case func(string) string:
|
||||
key := plugin.Hooks[name]
|
||||
hook := sshooks[name]
|
||||
hook := Sshooks[name]
|
||||
if len(hook) == 1 {
|
||||
hook = []func(string) string{}
|
||||
} else {
|
||||
hook = append(hook[:key], hook[key+1:]...)
|
||||
}
|
||||
sshooks[name] = hook
|
||||
Sshooks[name] = hook
|
||||
case func(http.ResponseWriter, *http.Request, *User, interface{}) bool:
|
||||
key := plugin.Hooks[name]
|
||||
hook := preRenderHooks[name]
|
||||
hook := PreRenderHooks[name]
|
||||
if len(hook) == 1 {
|
||||
hook = []func(http.ResponseWriter, *http.Request, *User, interface{}) bool{}
|
||||
} else {
|
||||
hook = append(hook[:key], hook[key+1:]...)
|
||||
}
|
||||
preRenderHooks[name] = hook
|
||||
PreRenderHooks[name] = hook
|
||||
case func(...interface{}) interface{}:
|
||||
delete(vhooks, name)
|
||||
delete(Vhooks, name)
|
||||
case func(...interface{}) (bool, RouteError):
|
||||
delete(vhookSkippable, name)
|
||||
delete(VhookSkippable, name)
|
||||
default:
|
||||
panic("I don't recognise this kind of handler!") // Should this be an error for the plugin instead of a panic()?
|
||||
}
|
||||
@ -285,18 +285,18 @@ func (plugin *Plugin) RemoveHook(name string, handler interface{}) {
|
||||
|
||||
var pluginsInited = false
|
||||
|
||||
func initPlugins() {
|
||||
func InitPlugins() {
|
||||
for name, body := range Plugins {
|
||||
log.Print("Added plugin " + name)
|
||||
log.Printf("Added plugin %s", name)
|
||||
if body.Active {
|
||||
log.Print("Initialised plugin " + name)
|
||||
log.Printf("Initialised plugin %s", name)
|
||||
if Plugins[name].Init != nil {
|
||||
err := Plugins[name].Init()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
} else {
|
||||
log.Print("Plugin " + name + " doesn't have an initialiser.")
|
||||
log.Printf("Plugin %s doesn't have an initialiser.", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -304,49 +304,49 @@ func initPlugins() {
|
||||
}
|
||||
|
||||
// ? - Are the following functions racey?
|
||||
func runHook(name string, data interface{}) interface{} {
|
||||
for _, hook := range hooks[name] {
|
||||
func RunHook(name string, data interface{}) interface{} {
|
||||
for _, hook := range Hooks[name] {
|
||||
data = hook(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func runHookNoreturn(name string, data interface{}) {
|
||||
for _, hook := range hooks[name] {
|
||||
func RunHookNoreturn(name string, data interface{}) {
|
||||
for _, hook := range Hooks[name] {
|
||||
_ = hook(data)
|
||||
}
|
||||
}
|
||||
|
||||
func runVhook(name string, data ...interface{}) interface{} {
|
||||
return vhooks[name](data...)
|
||||
func RunVhook(name string, data ...interface{}) interface{} {
|
||||
return Vhooks[name](data...)
|
||||
}
|
||||
|
||||
func runVhookSkippable(name string, data ...interface{}) (bool, RouteError) {
|
||||
return vhookSkippable[name](data...)
|
||||
func RunVhookSkippable(name string, data ...interface{}) (bool, RouteError) {
|
||||
return VhookSkippable[name](data...)
|
||||
}
|
||||
|
||||
func runVhookNoreturn(name string, data ...interface{}) {
|
||||
_ = vhooks[name](data...)
|
||||
func RunVhookNoreturn(name string, data ...interface{}) {
|
||||
_ = Vhooks[name](data...)
|
||||
}
|
||||
|
||||
// Trying to get a teeny bit of type-safety where-ever possible, especially for such a critical set of hooks
|
||||
func runSshook(name string, data string) string {
|
||||
for _, hook := range sshooks[name] {
|
||||
func RunSshook(name string, data string) string {
|
||||
for _, hook := range Sshooks[name] {
|
||||
data = hook(data)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func runPreRenderHook(name string, w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) {
|
||||
func RunPreRenderHook(name string, w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) {
|
||||
// This hook runs on ALL pre_render hooks
|
||||
for _, hook := range preRenderHooks["pre_render"] {
|
||||
for _, hook := range PreRenderHooks["pre_render"] {
|
||||
if hook(w, r, user, data) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// The actual pre_render hook
|
||||
for _, hook := range preRenderHooks[name] {
|
||||
for _, hook := range PreRenderHooks[name] {
|
||||
if hook(w, r, user, data) {
|
||||
return true
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -13,6 +13,10 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type SFileList map[string]SFile
|
||||
|
||||
var StaticFiles SFileList = make(map[string]SFile)
|
||||
|
||||
type SFile struct {
|
||||
Data []byte
|
||||
GzipData []byte
|
||||
@ -28,7 +32,7 @@ type CSSData struct {
|
||||
ComingSoon string
|
||||
}
|
||||
|
||||
func initStaticFiles() error {
|
||||
func (list SFileList) Init() error {
|
||||
return filepath.Walk("./public", func(path string, f os.FileInfo, err error) error {
|
||||
if f.IsDir() {
|
||||
return nil
|
||||
@ -44,16 +48,16 @@ func initStaticFiles() error {
|
||||
var ext = filepath.Ext("/public/" + path)
|
||||
gzipData := compressBytesGzip(data)
|
||||
|
||||
staticFiles["/static/"+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}
|
||||
list["/static/"+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}
|
||||
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Added the '" + path + "' static file.")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func addStaticFile(path string, prefix string) error {
|
||||
func (list SFileList) Add(path string, prefix string) error {
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -71,10 +75,10 @@ func addStaticFile(path string, prefix string) error {
|
||||
path = strings.TrimPrefix(path, prefix)
|
||||
gzipData := compressBytesGzip(data)
|
||||
|
||||
staticFiles["/static"+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}
|
||||
list["/static"+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}
|
||||
|
||||
if dev.DebugMode {
|
||||
log.Print("Added the '" + path + "' static file")
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Added the '%s' static file", path)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -2,12 +2,15 @@ package common
|
||||
|
||||
//import "fmt"
|
||||
import (
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"../query_gen/lib"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
// TODO: Do we really need this?
|
||||
type ForumAdmin struct {
|
||||
ID int
|
||||
Name string
|
||||
@ -44,11 +47,25 @@ type ForumSimple struct {
|
||||
Preset string
|
||||
}
|
||||
|
||||
type ForumStmts struct {
|
||||
update *sql.Stmt
|
||||
}
|
||||
|
||||
var forumStmts ForumStmts
|
||||
|
||||
func init() {
|
||||
DbInits.Add(func() error {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
forumStmts = ForumStmts{
|
||||
update: acc.SimpleUpdate("forums", "name = ?, desc = ?, active = ?, preset = ?", "fid = ?"),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}
|
||||
|
||||
// Copy gives you a non-pointer concurrency safe copy of the forum
|
||||
func (forum *Forum) Copy() (fcopy Forum) {
|
||||
//forum.LastLock.RLock()
|
||||
fcopy = *forum
|
||||
//forum.LastLock.RUnlock()
|
||||
return fcopy
|
||||
}
|
||||
|
||||
@ -58,17 +75,17 @@ func (forum *Forum) Update(name string, desc string, active bool, preset string)
|
||||
name = forum.Name
|
||||
}
|
||||
preset = strings.TrimSpace(preset)
|
||||
_, err := stmts.updateForum.Exec(name, desc, active, preset, forum.ID)
|
||||
_, err := forumStmts.update.Exec(name, desc, active, preset, forum.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if forum.Preset != preset || preset == "custom" || preset == "" {
|
||||
err = permmapToQuery(presetToPermmap(preset), forum.ID)
|
||||
err = PermmapToQuery(PresetToPermmap(preset), forum.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_ = fstore.Reload(forum.ID)
|
||||
_ = Fstore.Reload(forum.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -91,13 +108,13 @@ func makeDummyForum(fid int, link string, name string, desc string, active bool,
|
||||
return &Forum{ID: fid, Link: link, Name: name, Desc: desc, Active: active, Preset: preset, ParentID: parentID, ParentType: parentType, TopicCount: topicCount}
|
||||
}
|
||||
|
||||
func buildForumURL(slug string, fid int) string {
|
||||
func BuildForumURL(slug string, fid int) string {
|
||||
if slug == "" {
|
||||
return "/forum/" + strconv.Itoa(fid)
|
||||
}
|
||||
return "/forum/" + slug + "." + strconv.Itoa(fid)
|
||||
}
|
||||
|
||||
func getForumURLPrefix() string {
|
||||
func GetForumURLPrefix() string {
|
||||
return "/forum/"
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var fpstore ForumPermsStore
|
||||
var Fpstore ForumPermsStore
|
||||
|
||||
type ForumPermsStore interface {
|
||||
Init() error
|
||||
@ -40,11 +40,11 @@ func NewMemoryForumPermsStore() (*MemoryForumPermsStore, error) {
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) Init() error {
|
||||
fids, err := fstore.GetAllIDs()
|
||||
fids, err := Fstore.GetAllIDs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Print("fids: ", fids)
|
||||
}
|
||||
|
||||
@ -54,9 +54,9 @@ func (fps *MemoryForumPermsStore) Init() error {
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Adding the forum permissions")
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Print("forumPerms[gid][fid]")
|
||||
}
|
||||
}
|
||||
@ -72,7 +72,7 @@ func (fps *MemoryForumPermsStore) Init() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Print("perms: ", string(perms))
|
||||
}
|
||||
err = json.Unmarshal(perms, &pperms)
|
||||
@ -86,7 +86,7 @@ func (fps *MemoryForumPermsStore) Init() error {
|
||||
forumPerms[gid] = make(map[int]ForumPerms)
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Print("gid: ", gid)
|
||||
log.Print("fid: ", fid)
|
||||
log.Printf("perms: %+v\n", pperms)
|
||||
@ -99,10 +99,10 @@ func (fps *MemoryForumPermsStore) Init() error {
|
||||
|
||||
// TODO: Need a more thread-safe way of doing this. Possibly with sync.Map?
|
||||
func (fps *MemoryForumPermsStore) Reload(fid int) error {
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Reloading the forum permissions for forum #%d", fid)
|
||||
}
|
||||
fids, err := fstore.GetAllIDs()
|
||||
fids, err := Fstore.GetAllIDs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -138,20 +138,20 @@ func (fps *MemoryForumPermsStore) Reload(fid int) error {
|
||||
}
|
||||
|
||||
func (fps *MemoryForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[int]ForumPerms, fids []int) error {
|
||||
groups, err := gstore.GetAll()
|
||||
groups, err := Gstore.GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Updating the forum permissions for Group #%d", group.ID)
|
||||
}
|
||||
group.Forums = []ForumPerms{BlankForumPerms}
|
||||
group.CanSee = []int{}
|
||||
fps.cascadePermSetToGroup(forumPerms, group, fids)
|
||||
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Printf("group.CanSee (length %d): %+v \n", len(group.CanSee), group.CanSee)
|
||||
log.Printf("group.Forums (length %d): %+v\n", len(group.Forums), group.Forums)
|
||||
}
|
||||
@ -161,12 +161,12 @@ func (fps *MemoryForumPermsStore) cascadePermSetToGroups(forumPerms map[int]map[
|
||||
|
||||
func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[int]ForumPerms, group *Group, fids []int) {
|
||||
for _, fid := range fids {
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Printf("Forum #%+v\n", fid)
|
||||
}
|
||||
forumPerm, ok := forumPerms[group.ID][fid]
|
||||
if ok {
|
||||
//log.Print("Overriding permissions for forum #%d",fid)
|
||||
//log.Printf("Overriding permissions for forum #%d",fid)
|
||||
group.Forums = append(group.Forums, forumPerm)
|
||||
} else {
|
||||
//log.Printf("Inheriting from group defaults for forum #%d",fid)
|
||||
@ -181,7 +181,7 @@ func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[i
|
||||
group.CanSee = append(group.CanSee, fid)
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if Dev.SuperDebug {
|
||||
log.Print("group.ID: ", group.ID)
|
||||
log.Printf("forumPerm: %+v\n", forumPerm)
|
||||
log.Print("group.CanSee: ", group.CanSee)
|
||||
@ -191,7 +191,7 @@ func (fps *MemoryForumPermsStore) cascadePermSetToGroup(forumPerms map[int]map[i
|
||||
|
||||
func (fps *MemoryForumPermsStore) Get(fid int, gid int) (fperms ForumPerms, err error) {
|
||||
// TODO: Add a hook here and have plugin_guilds use it
|
||||
group, err := gstore.Get(gid)
|
||||
group, err := Gstore.Get(gid)
|
||||
if err != nil {
|
||||
return fperms, ErrNoRows
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ import (
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var forumUpdateMutex sync.Mutex
|
||||
var ForumUpdateMutex sync.Mutex
|
||||
var forumCreateMutex sync.Mutex
|
||||
var forumPerms map[int]map[int]ForumPerms // [gid][fid]Perms // TODO: Add an abstraction around this and make it more thread-safe
|
||||
var fstore ForumStore
|
||||
var Fstore ForumStore
|
||||
|
||||
// ForumStore is an interface for accessing the forums and the metadata stored on them
|
||||
type ForumStore interface {
|
||||
@ -110,26 +110,16 @@ func (mfs *MemoryForumStore) LoadForums() error {
|
||||
}
|
||||
|
||||
if forum.Name == "" {
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Adding a placeholder forum")
|
||||
}
|
||||
} else {
|
||||
log.Printf("Adding the %s forum", forum.Name)
|
||||
log.Printf("Adding the '%s' forum", forum.Name)
|
||||
}
|
||||
|
||||
forum.Link = buildForumURL(nameToSlug(forum.Name), forum.ID)
|
||||
|
||||
topic, err := topics.Get(forum.LastTopicID)
|
||||
if err != nil {
|
||||
topic = getDummyTopic()
|
||||
}
|
||||
user, err := users.Get(forum.LastReplyerID)
|
||||
if err != nil {
|
||||
user = getDummyUser()
|
||||
}
|
||||
forum.LastTopic = topic
|
||||
forum.LastReplyer = user
|
||||
//forum.SetLast(topic, user)
|
||||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
|
||||
addForum(forum)
|
||||
}
|
||||
@ -178,19 +168,9 @@ func (mfs *MemoryForumStore) Get(id int) (*Forum, error) {
|
||||
return forum, err
|
||||
}
|
||||
|
||||
forum.Link = buildForumURL(nameToSlug(forum.Name), forum.ID)
|
||||
|
||||
topic, err := topics.Get(forum.LastTopicID)
|
||||
if err != nil {
|
||||
topic = getDummyTopic()
|
||||
}
|
||||
user, err := users.Get(forum.LastReplyerID)
|
||||
if err != nil {
|
||||
user = getDummyUser()
|
||||
}
|
||||
forum.LastTopic = topic
|
||||
forum.LastReplyer = user
|
||||
//forum.SetLast(topic, user)
|
||||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
|
||||
mfs.CacheSet(forum)
|
||||
return forum, err
|
||||
@ -205,19 +185,9 @@ func (mfs *MemoryForumStore) BypassGet(id int) (*Forum, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
forum.Link = buildForumURL(nameToSlug(forum.Name), forum.ID)
|
||||
|
||||
topic, err := topics.Get(forum.LastTopicID)
|
||||
if err != nil {
|
||||
topic = getDummyTopic()
|
||||
}
|
||||
user, err := users.Get(forum.LastReplyerID)
|
||||
if err != nil {
|
||||
user = getDummyUser()
|
||||
}
|
||||
forum.LastTopic = topic
|
||||
forum.LastReplyer = user
|
||||
//forum.SetLast(topic, user)
|
||||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
|
||||
return forum, err
|
||||
}
|
||||
@ -228,19 +198,9 @@ func (mfs *MemoryForumStore) Reload(id int) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
forum.Link = buildForumURL(nameToSlug(forum.Name), forum.ID)
|
||||
|
||||
topic, err := topics.Get(forum.LastTopicID)
|
||||
if err != nil {
|
||||
topic = getDummyTopic()
|
||||
}
|
||||
user, err := users.Get(forum.LastReplyerID)
|
||||
if err != nil {
|
||||
user = getDummyUser()
|
||||
}
|
||||
forum.LastTopic = topic
|
||||
forum.LastReplyer = user
|
||||
//forum.SetLast(topic, user)
|
||||
forum.Link = BuildForumURL(NameToSlug(forum.Name), forum.ID)
|
||||
forum.LastTopic = Topics.DirtyGet(forum.LastTopicID)
|
||||
forum.LastReplyer = Users.DirtyGet(forum.LastReplyerID)
|
||||
|
||||
mfs.CacheSet(forum)
|
||||
return nil
|
||||
@ -372,7 +332,7 @@ func (mfs *MemoryForumStore) Create(forumName string, forumDesc string, active b
|
||||
return 0, err
|
||||
}
|
||||
|
||||
permmapToQuery(presetToPermmap(preset), fid)
|
||||
PermmapToQuery(PresetToPermmap(preset), fid)
|
||||
forumCreateMutex.Unlock()
|
||||
return fid, nil
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
package common
|
||||
|
||||
import "database/sql"
|
||||
import "../query_gen/lib"
|
||||
|
||||
var blankGroup = Group{ID: 0, Name: ""}
|
||||
|
||||
type GroupAdmin struct {
|
||||
@ -27,13 +30,29 @@ type Group struct {
|
||||
CanSee []int // The IDs of the forums this group can see
|
||||
}
|
||||
|
||||
type GroupStmts struct {
|
||||
updateGroupRank *sql.Stmt
|
||||
}
|
||||
|
||||
var groupStmts GroupStmts
|
||||
|
||||
func init() {
|
||||
DbInits.Add(func() error {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
groupStmts = GroupStmts{
|
||||
updateGroupRank: acc.SimpleUpdate("users_groups", "is_admin = ?, is_mod = ?, is_banned = ?", "gid = ?"),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}
|
||||
|
||||
func (group *Group) ChangeRank(isAdmin bool, isMod bool, isBanned bool) (err error) {
|
||||
_, err = stmts.updateGroupRank.Exec(isAdmin, isMod, isBanned, group.ID)
|
||||
_, err = groupStmts.updateGroupRank.Exec(isAdmin, isMod, isBanned, group.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gstore.Reload(group.ID)
|
||||
Gstore.Reload(group.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var gstore GroupStore
|
||||
var Gstore GroupStore
|
||||
|
||||
// ? - We could fallback onto the database when an item can't be found in the cache?
|
||||
type GroupStore interface {
|
||||
@ -38,6 +38,7 @@ type MemoryGroupStore struct {
|
||||
groupCount int
|
||||
getAll *sql.Stmt
|
||||
get *sql.Stmt
|
||||
count *sql.Stmt
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
@ -49,6 +50,7 @@ func NewMemoryGroupStore() (*MemoryGroupStore, error) {
|
||||
groupCount: 0,
|
||||
getAll: acc.SimpleSelect("users_groups", "gid, name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "", "", ""),
|
||||
get: acc.SimpleSelect("users_groups", "name, permissions, plugin_perms, is_mod, is_admin, is_banned, tag", "gid = ?", "", ""),
|
||||
count: acc.SimpleCount("users_groups", "", ""),
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
@ -84,7 +86,7 @@ func (mgs *MemoryGroupStore) LoadGroups() error {
|
||||
}
|
||||
mgs.groupCount = i
|
||||
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Binding the Not Loggedin Group")
|
||||
}
|
||||
GuestPerms = mgs.dirtyGetUnsafe(6).Perms
|
||||
@ -146,7 +148,7 @@ func (mgs *MemoryGroupStore) Reload(id int) error {
|
||||
}
|
||||
mgs.CacheSet(group)
|
||||
|
||||
err = rebuildGroupPermissions(id)
|
||||
err = RebuildGroupPermissions(id)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
@ -160,7 +162,7 @@ func (mgs *MemoryGroupStore) initGroup(group *Group) error {
|
||||
log.Print("bad group perms: ", group.PermissionsText)
|
||||
return err
|
||||
}
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Printf(group.Name+": %+v\n", group.Perms)
|
||||
}
|
||||
|
||||
@ -170,7 +172,7 @@ func (mgs *MemoryGroupStore) initGroup(group *Group) error {
|
||||
log.Print("bad group plugin perms: ", group.PluginPermsText)
|
||||
return err
|
||||
}
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Printf(group.Name+": %+v\n", group.PluginPerms)
|
||||
}
|
||||
|
||||
@ -200,7 +202,7 @@ func (mgs *MemoryGroupStore) Exists(gid int) bool {
|
||||
// ? Allow two groups with the same name?
|
||||
func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod bool, isBanned bool) (gid int, err error) {
|
||||
var permstr = "{}"
|
||||
tx, err := db.Begin()
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -226,20 +228,20 @@ func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod
|
||||
var blankIntList []int
|
||||
var pluginPerms = make(map[string]bool)
|
||||
var pluginPermsBytes = []byte("{}")
|
||||
if vhooks["create_group_preappend"] != nil {
|
||||
runVhook("create_group_preappend", &pluginPerms, &pluginPermsBytes)
|
||||
if Vhooks["create_group_preappend"] != nil {
|
||||
RunVhook("create_group_preappend", &pluginPerms, &pluginPermsBytes)
|
||||
}
|
||||
|
||||
// Generate the forum permissions based on the presets...
|
||||
fdata, err := fstore.GetAll()
|
||||
fdata, err := Fstore.GetAll()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var presetSet = make(map[int]string)
|
||||
var permSet = make(map[int]ForumPerms)
|
||||
permUpdateMutex.Lock()
|
||||
defer permUpdateMutex.Unlock()
|
||||
PermUpdateMutex.Lock()
|
||||
defer PermUpdateMutex.Unlock()
|
||||
for _, forum := range fdata {
|
||||
var thePreset string
|
||||
if isAdmin {
|
||||
@ -252,7 +254,7 @@ func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod
|
||||
thePreset = "members"
|
||||
}
|
||||
|
||||
permmap := presetToPermmap(forum.Preset)
|
||||
permmap := PresetToPermmap(forum.Preset)
|
||||
permItem := permmap[thePreset]
|
||||
permItem.Overrides = true
|
||||
|
||||
@ -260,7 +262,7 @@ func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod
|
||||
presetSet[forum.ID] = forum.Preset
|
||||
}
|
||||
|
||||
err = replaceForumPermsForGroupTx(tx, gid, presetSet, permSet)
|
||||
err = ReplaceForumPermsForGroupTx(tx, gid, presetSet, permSet)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -281,7 +283,7 @@ func (mgs *MemoryGroupStore) Create(name string, tag string, isAdmin bool, isMod
|
||||
mgs.Unlock()
|
||||
|
||||
for _, forum := range fdata {
|
||||
err = fpstore.Reload(forum.ID)
|
||||
err = Fpstore.Reload(forum.ID)
|
||||
if err != nil {
|
||||
return gid, err
|
||||
}
|
||||
@ -344,8 +346,10 @@ func (mgs *MemoryGroupStore) Length() int {
|
||||
return mgs.groupCount
|
||||
}
|
||||
|
||||
func (mgs *MemoryGroupStore) GlobalCount() int {
|
||||
mgs.RLock()
|
||||
defer mgs.RUnlock()
|
||||
return mgs.groupCount
|
||||
func (mgs *MemoryGroupStore) GlobalCount() (count int) {
|
||||
err := mgs.count.QueryRow().Scan(&count)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Copyright Azareal 2016 - 2018
|
||||
*
|
||||
*/
|
||||
package main
|
||||
package common
|
||||
|
||||
import (
|
||||
"errors"
|
@ -11,7 +11,7 @@ type HeaderVars struct {
|
||||
Scripts []string
|
||||
Stylesheets []string
|
||||
Widgets PageWidgets
|
||||
Site *Site
|
||||
Site *site
|
||||
Settings map[string]interface{}
|
||||
Themes map[string]Theme // TODO: Use a slice containing every theme instead of the main map for speed
|
||||
ThemeName string
|
||||
@ -21,7 +21,7 @@ type HeaderVars struct {
|
||||
|
||||
// TODO: Add this to routes which don't use templates. E.g. Json APIs.
|
||||
type HeaderLite struct {
|
||||
Site *Site
|
||||
Site *site
|
||||
Settings SettingMap
|
||||
ExtData ExtData
|
||||
}
|
||||
@ -34,7 +34,7 @@ type PageWidgets struct {
|
||||
// TODO: Add a ExtDataHolder interface with methods for manipulating the contents?
|
||||
// ? - Could we use a sync.Map instead?
|
||||
type ExtData struct {
|
||||
items map[string]interface{} // Key: pluginname
|
||||
Items map[string]interface{} // Key: pluginname
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ type PanelEditGroupPermsPage struct {
|
||||
GlobalPerms []NameLangToggle
|
||||
}
|
||||
|
||||
type backupItem struct {
|
||||
type BackupItem struct {
|
||||
SQLURL string
|
||||
|
||||
// TODO: Add an easier to parse format here for Gosora to be able to more easily reimport portions of the dump and to strip unnecessary data (e.g. table defs and parsed post data)
|
||||
@ -239,10 +239,10 @@ type PanelBackupPage struct {
|
||||
CurrentUser User
|
||||
Header *HeaderVars
|
||||
Stats PanelStats
|
||||
Backups []backupItem
|
||||
Backups []BackupItem
|
||||
}
|
||||
|
||||
type logItem struct {
|
||||
type LogItem struct {
|
||||
Action template.HTML
|
||||
IPAddress string
|
||||
DoneAt string
|
||||
@ -253,7 +253,7 @@ type PanelLogsPage struct {
|
||||
CurrentUser User
|
||||
Header *HeaderVars
|
||||
Stats PanelStats
|
||||
Logs []logItem
|
||||
Logs []LogItem
|
||||
PageList []int
|
||||
Page int
|
||||
LastPage int
|
||||
@ -282,5 +282,5 @@ type AreYouSure struct {
|
||||
// This is mostly for errors.go, please create *HeaderVars on the spot instead of relying on this or the atomic store underlying it, if possible
|
||||
// TODO: Write a test for this
|
||||
func DefaultHeaderVar() *HeaderVars {
|
||||
return &HeaderVars{Site: site, ThemeName: fallbackTheme}
|
||||
return &HeaderVars{Site: Site, ThemeName: fallbackTheme}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package common
|
||||
|
||||
import (
|
||||
//"fmt"
|
||||
@ -9,19 +9,19 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var spaceGap = []byte(" ")
|
||||
var SpaceGap = []byte(" ")
|
||||
var httpProtBytes = []byte("http://")
|
||||
var invalidURL = []byte("<span style='color: red;'>[Invalid URL]</span>")
|
||||
var invalidTopic = []byte("<span style='color: red;'>[Invalid Topic]</span>")
|
||||
var invalidProfile = []byte("<span style='color: red;'>[Invalid Profile]</span>")
|
||||
var invalidForum = []byte("<span style='color: red;'>[Invalid Forum]</span>")
|
||||
var InvalidURL = []byte("<span style='color: red;'>[Invalid URL]</span>")
|
||||
var InvalidTopic = []byte("<span style='color: red;'>[Invalid Topic]</span>")
|
||||
var InvalidProfile = []byte("<span style='color: red;'>[Invalid Profile]</span>")
|
||||
var InvalidForum = []byte("<span style='color: red;'>[Invalid Forum]</span>")
|
||||
var unknownMedia = []byte("<span style='color: red;'>[Unknown Media]</span>")
|
||||
var urlOpen = []byte("<a href='")
|
||||
var urlOpen2 = []byte("'>")
|
||||
var UrlOpen = []byte("<a href='")
|
||||
var UrlOpen2 = []byte("'>")
|
||||
var bytesSinglequote = []byte("'")
|
||||
var bytesGreaterthan = []byte(">")
|
||||
var urlMention = []byte(" class='mention'")
|
||||
var urlClose = []byte("</a>")
|
||||
var UrlClose = []byte("</a>")
|
||||
var imageOpen = []byte("<a href=\"")
|
||||
var imageOpen2 = []byte("\"><img src='")
|
||||
var imageClose = []byte("' class='postImage' /></a>")
|
||||
@ -164,16 +164,16 @@ func shortcodeToUnicode(msg string) string {
|
||||
return msg
|
||||
}
|
||||
|
||||
func preparseMessage(msg string) string {
|
||||
if sshooks["preparse_preassign"] != nil {
|
||||
msg = runSshook("preparse_preassign", msg)
|
||||
func PreparseMessage(msg string) string {
|
||||
if Sshooks["preparse_preassign"] != nil {
|
||||
msg = RunSshook("preparse_preassign", msg)
|
||||
}
|
||||
return shortcodeToUnicode(msg)
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
// TODO: We need a lot more hooks here. E.g. To add custom media types and handlers.
|
||||
func parseMessage(msg string, sectionID int, sectionType string /*, user User*/) string {
|
||||
func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/) string {
|
||||
msg = strings.Replace(msg, ":)", "😀", -1)
|
||||
msg = strings.Replace(msg, ":(", "😞", -1)
|
||||
msg = strings.Replace(msg, ":D", "😃", -1)
|
||||
@ -185,7 +185,7 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
//msg = url_reg.ReplaceAllString(msg,"<a href=\"$2$3//$4\" rel=\"nofollow\">$2$3//$4</a>")
|
||||
|
||||
// Word filter list. E.g. Swear words and other things the admins don't like
|
||||
wordFilters := wordFilterBox.Load().(WordFilterBox)
|
||||
wordFilters := WordFilterBox.Load().(WordFilterMap)
|
||||
for _, filter := range wordFilters {
|
||||
msg = strings.Replace(msg, filter.Find, filter.Replacement, -1)
|
||||
}
|
||||
@ -194,7 +194,7 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
//log.Print("Parser Loop!")
|
||||
var msgbytes = []byte(msg)
|
||||
var outbytes []byte
|
||||
msgbytes = append(msgbytes, spaceGap...)
|
||||
msgbytes = append(msgbytes, SpaceGap...)
|
||||
//log.Printf("string(msgbytes) %+v\n", `"`+string(msgbytes)+`"`)
|
||||
var lastItem = 0
|
||||
var i = 0
|
||||
@ -215,23 +215,23 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
outbytes = append(outbytes, msgbytes[lastItem:i]...)
|
||||
i += 5
|
||||
start := i
|
||||
tid, intLen := coerceIntBytes(msgbytes[start:])
|
||||
tid, intLen := CoerceIntBytes(msgbytes[start:])
|
||||
i += intLen
|
||||
|
||||
topic, err := topics.Get(tid)
|
||||
if err != nil || !fstore.Exists(topic.ParentID) {
|
||||
outbytes = append(outbytes, invalidTopic...)
|
||||
topic, err := Topics.Get(tid)
|
||||
if err != nil || !Fstore.Exists(topic.ParentID) {
|
||||
outbytes = append(outbytes, InvalidTopic...)
|
||||
lastItem = i
|
||||
continue
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
var urlBit = []byte(buildTopicURL("", tid))
|
||||
outbytes = append(outbytes, UrlOpen...)
|
||||
var urlBit = []byte(BuildTopicURL("", tid))
|
||||
outbytes = append(outbytes, urlBit...)
|
||||
outbytes = append(outbytes, urlOpen2...)
|
||||
outbytes = append(outbytes, UrlOpen2...)
|
||||
var tidBit = []byte("#tid-" + strconv.Itoa(tid))
|
||||
outbytes = append(outbytes, tidBit...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, UrlClose...)
|
||||
lastItem = i
|
||||
|
||||
//log.Print("string(msgbytes): ",string(msgbytes))
|
||||
@ -244,44 +244,46 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
outbytes = append(outbytes, msgbytes[lastItem:i]...)
|
||||
i += 5
|
||||
start := i
|
||||
rid, intLen := coerceIntBytes(msgbytes[start:])
|
||||
rid, intLen := CoerceIntBytes(msgbytes[start:])
|
||||
i += intLen
|
||||
|
||||
topic, err := getTopicByReply(rid)
|
||||
if err != nil || !fstore.Exists(topic.ParentID) {
|
||||
outbytes = append(outbytes, invalidTopic...)
|
||||
reply := BlankReply()
|
||||
reply.ID = rid
|
||||
topic, err := reply.Topic()
|
||||
if err != nil || !Fstore.Exists(topic.ParentID) {
|
||||
outbytes = append(outbytes, InvalidTopic...)
|
||||
lastItem = i
|
||||
continue
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
var urlBit = []byte(buildTopicURL("", topic.ID))
|
||||
outbytes = append(outbytes, UrlOpen...)
|
||||
var urlBit = []byte(BuildTopicURL("", topic.ID))
|
||||
outbytes = append(outbytes, urlBit...)
|
||||
outbytes = append(outbytes, urlOpen2...)
|
||||
outbytes = append(outbytes, UrlOpen2...)
|
||||
var ridBit = []byte("#rid-" + strconv.Itoa(rid))
|
||||
outbytes = append(outbytes, ridBit...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, UrlClose...)
|
||||
lastItem = i
|
||||
} else if bytes.Equal(msgbytes[i+1:i+5], []byte("fid-")) {
|
||||
outbytes = append(outbytes, msgbytes[lastItem:i]...)
|
||||
i += 5
|
||||
start := i
|
||||
fid, intLen := coerceIntBytes(msgbytes[start:])
|
||||
fid, intLen := CoerceIntBytes(msgbytes[start:])
|
||||
i += intLen
|
||||
|
||||
if !fstore.Exists(fid) {
|
||||
outbytes = append(outbytes, invalidForum...)
|
||||
if !Fstore.Exists(fid) {
|
||||
outbytes = append(outbytes, InvalidForum...)
|
||||
lastItem = i
|
||||
continue
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
var urlBit = []byte(buildForumURL("", fid))
|
||||
outbytes = append(outbytes, UrlOpen...)
|
||||
var urlBit = []byte(BuildForumURL("", fid))
|
||||
outbytes = append(outbytes, urlBit...)
|
||||
outbytes = append(outbytes, urlOpen2...)
|
||||
outbytes = append(outbytes, UrlOpen2...)
|
||||
var fidBit = []byte("#fid-" + strconv.Itoa(fid))
|
||||
outbytes = append(outbytes, fidBit...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, UrlClose...)
|
||||
lastItem = i
|
||||
} else {
|
||||
// TODO: Forum Shortcode Link
|
||||
@ -291,17 +293,17 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
outbytes = append(outbytes, msgbytes[lastItem:i]...)
|
||||
i++
|
||||
start := i
|
||||
uid, intLen := coerceIntBytes(msgbytes[start:])
|
||||
uid, intLen := CoerceIntBytes(msgbytes[start:])
|
||||
i += intLen
|
||||
|
||||
menUser, err := users.Get(uid)
|
||||
menUser, err := Users.Get(uid)
|
||||
if err != nil {
|
||||
outbytes = append(outbytes, invalidProfile...)
|
||||
outbytes = append(outbytes, InvalidProfile...)
|
||||
lastItem = i
|
||||
continue
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
outbytes = append(outbytes, UrlOpen...)
|
||||
var urlBit = []byte(menUser.Link)
|
||||
outbytes = append(outbytes, urlBit...)
|
||||
outbytes = append(outbytes, bytesSinglequote...)
|
||||
@ -309,7 +311,7 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
outbytes = append(outbytes, bytesGreaterthan...)
|
||||
var uidBit = []byte("@" + menUser.Name)
|
||||
outbytes = append(outbytes, uidBit...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, UrlClose...)
|
||||
lastItem = i
|
||||
|
||||
//log.Print(string(msgbytes))
|
||||
@ -338,21 +340,21 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
|
||||
//log.Print("Normal URL")
|
||||
outbytes = append(outbytes, msgbytes[lastItem:i]...)
|
||||
urlLen := partialURLBytesLen(msgbytes[i:])
|
||||
urlLen := PartialURLBytesLen(msgbytes[i:])
|
||||
if msgbytes[i+urlLen] > 32 { // space and invisibles
|
||||
//log.Print("INVALID URL")
|
||||
//log.Print("msgbytes[i+urlLen]: ", msgbytes[i+urlLen])
|
||||
//log.Print("string(msgbytes[i+urlLen]): ", string(msgbytes[i+urlLen]))
|
||||
//log.Print("msgbytes[i:i+urlLen]: ", msgbytes[i:i+urlLen])
|
||||
//log.Print("string(msgbytes[i:i+urlLen]): ", string(msgbytes[i:i+urlLen]))
|
||||
outbytes = append(outbytes, invalidURL...)
|
||||
outbytes = append(outbytes, InvalidURL...)
|
||||
i += urlLen
|
||||
continue
|
||||
}
|
||||
|
||||
media, ok := parseMediaBytes(msgbytes[i : i+urlLen])
|
||||
if !ok {
|
||||
outbytes = append(outbytes, invalidURL...)
|
||||
outbytes = append(outbytes, InvalidURL...)
|
||||
i += urlLen
|
||||
continue
|
||||
}
|
||||
@ -386,23 +388,23 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
continue
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
outbytes = append(outbytes, UrlOpen...)
|
||||
outbytes = append(outbytes, msgbytes[i:i+urlLen]...)
|
||||
outbytes = append(outbytes, urlOpen2...)
|
||||
outbytes = append(outbytes, UrlOpen2...)
|
||||
outbytes = append(outbytes, msgbytes[i:i+urlLen]...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, UrlClose...)
|
||||
i += urlLen
|
||||
lastItem = i
|
||||
} else if msgbytes[i] == '/' && msgbytes[i+1] == '/' {
|
||||
outbytes = append(outbytes, msgbytes[lastItem:i]...)
|
||||
urlLen := partialURLBytesLen(msgbytes[i:])
|
||||
urlLen := PartialURLBytesLen(msgbytes[i:])
|
||||
if msgbytes[i+urlLen] > 32 { // space and invisibles
|
||||
//log.Print("INVALID URL")
|
||||
//log.Print("msgbytes[i+urlLen]: ", msgbytes[i+urlLen])
|
||||
//log.Print("string(msgbytes[i+urlLen]): ", string(msgbytes[i+urlLen]))
|
||||
//log.Print("msgbytes[i:i+urlLen]: ", msgbytes[i:i+urlLen])
|
||||
//log.Print("string(msgbytes[i:i+urlLen]): ", string(msgbytes[i:i+urlLen]))
|
||||
outbytes = append(outbytes, invalidURL...)
|
||||
outbytes = append(outbytes, InvalidURL...)
|
||||
i += urlLen
|
||||
continue
|
||||
}
|
||||
@ -412,7 +414,7 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
//log.Print("string(msgbytes[i:i+urlLen]): ", string(msgbytes[i:i+urlLen]))
|
||||
media, ok := parseMediaBytes(msgbytes[i : i+urlLen])
|
||||
if !ok {
|
||||
outbytes = append(outbytes, invalidURL...)
|
||||
outbytes = append(outbytes, InvalidURL...)
|
||||
i += urlLen
|
||||
continue
|
||||
}
|
||||
@ -446,11 +448,11 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
continue
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
outbytes = append(outbytes, UrlOpen...)
|
||||
outbytes = append(outbytes, msgbytes[i:i+urlLen]...)
|
||||
outbytes = append(outbytes, urlOpen2...)
|
||||
outbytes = append(outbytes, UrlOpen2...)
|
||||
outbytes = append(outbytes, msgbytes[i:i+urlLen]...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, UrlClose...)
|
||||
i += urlLen
|
||||
lastItem = i
|
||||
}
|
||||
@ -474,25 +476,12 @@ func parseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
||||
//log.Print("msg",`"`+msg+`"`)
|
||||
|
||||
msg = strings.Replace(msg, "\n", "<br>", -1)
|
||||
if sshooks["parse_assign"] != nil {
|
||||
msg = runSshook("parse_assign", msg)
|
||||
if Sshooks["parse_assign"] != nil {
|
||||
msg = RunSshook("parse_assign", msg)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
/*func regexParseMessage(msg string) string {
|
||||
msg = strings.Replace(msg, ":)", "😀", -1)
|
||||
msg = strings.Replace(msg, ":D", "😃", -1)
|
||||
msg = strings.Replace(msg, ":P", "😛", -1)
|
||||
msg = urlReg.ReplaceAllString(msg, "<a href=\"$2$3//$4\" rel=\"nofollow\">$2$3//$4</a>")
|
||||
msg = strings.Replace(msg, "\n", "<br>", -1)
|
||||
if sshooks["parse_assign"] != nil {
|
||||
msg = runSshook("parse_assign", msg)
|
||||
}
|
||||
return msg
|
||||
}*/
|
||||
|
||||
// 6, 7, 8, 6, 2, 7
|
||||
// ftp://, http://, https:// git://, //, mailto: (not a URL, just here for length comparison purposes)
|
||||
// TODO: Write a test for this
|
||||
@ -541,7 +530,7 @@ func validatedURLBytes(data []byte) (url []byte) {
|
||||
// ? - There should only be one : and that's only if the URL is on a non-standard port. Same for ?s.
|
||||
for ; datalen > i; i++ {
|
||||
if data[i] != '\\' && data[i] != '_' && data[i] != ':' && data[i] != '?' && data[i] != '&' && data[i] != '=' && data[i] != ';' && data[i] != '@' && !(data[i] > 44 && data[i] < 58) && !(data[i] > 64 && data[i] < 91) && !(data[i] > 96 && data[i] < 123) {
|
||||
return invalidURL
|
||||
return InvalidURL
|
||||
}
|
||||
}
|
||||
|
||||
@ -550,7 +539,7 @@ func validatedURLBytes(data []byte) (url []byte) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func partialURLBytes(data []byte) (url []byte) {
|
||||
func PartialURLBytes(data []byte) (url []byte) {
|
||||
datalen := len(data)
|
||||
i := 0
|
||||
end := datalen - 1
|
||||
@ -579,7 +568,7 @@ func partialURLBytes(data []byte) (url []byte) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func partialURLBytesLen(data []byte) int {
|
||||
func PartialURLBytesLen(data []byte) int {
|
||||
datalen := len(data)
|
||||
i := 0
|
||||
|
||||
@ -632,13 +621,12 @@ func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) {
|
||||
query := url.Query()
|
||||
//log.Printf("query %+v\n", query)
|
||||
|
||||
var samesite = hostname == "localhost" || hostname == site.URL
|
||||
var samesite = hostname == "localhost" || hostname == Site.URL
|
||||
if samesite {
|
||||
//log.Print("samesite")
|
||||
hostname = strings.Split(site.URL, ":")[0]
|
||||
hostname = strings.Split(Site.URL, ":")[0]
|
||||
// ?- Test this as I'm not sure it'll do what it should. If someone's running SSL on port 80 or non-SSL on port 443 then... Well... They're in far worse trouble than this...
|
||||
port = site.Port
|
||||
if scheme == "" && site.EnableSsl {
|
||||
port = Site.Port
|
||||
if scheme == "" && Site.EnableSsl {
|
||||
scheme = "https"
|
||||
}
|
||||
}
|
||||
@ -684,7 +672,7 @@ func parseMediaBytes(data []byte) (media MediaEmbed, ok bool) {
|
||||
extarr := strings.Split(lastFrag, ".")
|
||||
if len(extarr) >= 2 {
|
||||
ext := extarr[len(extarr)-1]
|
||||
if imageFileExts.Contains(ext) {
|
||||
if ImageFileExts.Contains(ext) {
|
||||
media.Type = "image"
|
||||
var sport string
|
||||
if port != "443" && port != "80" {
|
||||
@ -704,7 +692,7 @@ func parseURL(data []byte) (*url.URL, error) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func coerceIntBytes(data []byte) (res int, length int) {
|
||||
func CoerceIntBytes(data []byte) (res int, length int) {
|
||||
if !(data[0] > 47 && data[0] < 58) {
|
||||
return 0, 1
|
||||
}
|
||||
@ -728,7 +716,7 @@ func coerceIntBytes(data []byte) (res int, length int) {
|
||||
}
|
||||
|
||||
// TODO: Write tests for this
|
||||
func paginate(count int, perPage int, maxPages int) []int {
|
||||
func Paginate(count int, perPage int, maxPages int) []int {
|
||||
if count < perPage {
|
||||
return []int{1}
|
||||
}
|
||||
@ -745,7 +733,7 @@ func paginate(count int, perPage int, maxPages int) []int {
|
||||
}
|
||||
|
||||
// TODO: Write tests for this
|
||||
func pageOffset(count int, page int, perPage int) (int, int, int) {
|
||||
func PageOffset(count int, page int, perPage int) (int, int, int) {
|
||||
var offset int
|
||||
lastPage := (count / perPage) + 1
|
||||
if page > 1 {
|
@ -5,18 +5,24 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
// TODO: Refactor the perms system
|
||||
|
||||
var permUpdateMutex sync.Mutex
|
||||
var PermUpdateMutex sync.Mutex
|
||||
var BlankPerms Perms
|
||||
var BlankForumPerms ForumPerms
|
||||
var GuestPerms Perms
|
||||
var ReadForumPerms ForumPerms
|
||||
var ReadReplyForumPerms ForumPerms
|
||||
var ReadWriteForumPerms ForumPerms
|
||||
|
||||
// AllPerms is a set of global permissions with everything set to true
|
||||
var AllPerms Perms
|
||||
|
||||
// AllForumPerms is a set of forum local permissions with everything set to true
|
||||
var AllForumPerms ForumPerms
|
||||
var AllPluginPerms = make(map[string]bool)
|
||||
|
||||
@ -216,15 +222,15 @@ func init() {
|
||||
ExtData: make(map[string]bool),
|
||||
}
|
||||
|
||||
guestUser.Perms = GuestPerms
|
||||
GuestUser.Perms = GuestPerms
|
||||
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Guest Perms: %+v\n", GuestPerms)
|
||||
log.Printf("All Perms: %+v\n", AllPerms)
|
||||
}
|
||||
}
|
||||
|
||||
func presetToPermmap(preset string) (out map[string]ForumPerms) {
|
||||
func PresetToPermmap(preset string) (out map[string]ForumPerms) {
|
||||
out = make(map[string]ForumPerms)
|
||||
switch preset {
|
||||
case "all":
|
||||
@ -266,8 +272,8 @@ func presetToPermmap(preset string) (out map[string]ForumPerms) {
|
||||
return out
|
||||
}
|
||||
|
||||
func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
|
||||
tx, err := db.Begin()
|
||||
func PermmapToQuery(permmap map[string]ForumPerms, fid int) error {
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -337,7 +343,7 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
|
||||
|
||||
// 6 is the ID of the Not Loggedin Group
|
||||
// TODO: Use a shared variable rather than a literal for the group ID
|
||||
err = replaceForumPermsForGroupTx(tx, 6, map[int]string{fid: ""}, map[int]ForumPerms{fid: permmap["guests"]})
|
||||
err = ReplaceForumPermsForGroupTx(tx, 6, map[int]string{fid: ""}, map[int]ForumPerms{fid: permmap["guests"]})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -347,25 +353,25 @@ func permmapToQuery(permmap map[string]ForumPerms, fid int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
permUpdateMutex.Lock()
|
||||
defer permUpdateMutex.Unlock()
|
||||
return fpstore.Reload(fid)
|
||||
PermUpdateMutex.Lock()
|
||||
defer PermUpdateMutex.Unlock()
|
||||
return Fpstore.Reload(fid)
|
||||
}
|
||||
|
||||
func replaceForumPermsForGroup(gid int, presetSet map[int]string, permSets map[int]ForumPerms) error {
|
||||
tx, err := db.Begin()
|
||||
func ReplaceForumPermsForGroup(gid int, presetSet map[int]string, permSets map[int]ForumPerms) error {
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
err = replaceForumPermsForGroupTx(tx, gid, presetSet, permSets)
|
||||
err = ReplaceForumPermsForGroupTx(tx, gid, presetSet, permSets)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func replaceForumPermsForGroupTx(tx *sql.Tx, gid int, presetSets map[int]string, permSets map[int]ForumPerms) error {
|
||||
func ReplaceForumPermsForGroupTx(tx *sql.Tx, gid int, presetSets map[int]string, permSets map[int]ForumPerms) error {
|
||||
deleteForumPermsForGroupTx, err := qgen.Builder.SimpleDeleteTx(tx, "forums_permissions", "gid = ? AND fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -394,7 +400,7 @@ func replaceForumPermsForGroupTx(tx *sql.Tx, gid int, presetSets map[int]string,
|
||||
}
|
||||
|
||||
// TODO: Refactor this and write tests for it
|
||||
func forumPermsToGroupForumPreset(fperms ForumPerms) string {
|
||||
func ForumPermsToGroupForumPreset(fperms ForumPerms) string {
|
||||
if !fperms.Overrides {
|
||||
return "default"
|
||||
}
|
||||
@ -422,7 +428,7 @@ func forumPermsToGroupForumPreset(fperms ForumPerms) string {
|
||||
return "custom"
|
||||
}
|
||||
|
||||
func groupForumPresetToForumPerms(preset string) (fperms ForumPerms, changed bool) {
|
||||
func GroupForumPresetToForumPerms(preset string) (fperms ForumPerms, changed bool) {
|
||||
switch preset {
|
||||
case "read_only":
|
||||
return ReadForumPerms, true
|
||||
@ -439,7 +445,7 @@ func groupForumPresetToForumPerms(preset string) (fperms ForumPerms, changed boo
|
||||
return fperms, false
|
||||
}
|
||||
|
||||
func stripInvalidGroupForumPreset(preset string) string {
|
||||
func StripInvalidGroupForumPreset(preset string) string {
|
||||
switch preset {
|
||||
case "read_only", "can_post", "can_moderate", "no_access", "default", "custom":
|
||||
return preset
|
||||
@ -447,7 +453,7 @@ func stripInvalidGroupForumPreset(preset string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func stripInvalidPreset(preset string) string {
|
||||
func StripInvalidPreset(preset string) string {
|
||||
switch preset {
|
||||
case "all", "announce", "members", "staff", "admins", "archive", "custom":
|
||||
return preset
|
||||
@ -457,7 +463,7 @@ func stripInvalidPreset(preset string) string {
|
||||
}
|
||||
|
||||
// TODO: Move this into the phrase system?
|
||||
func presetToLang(preset string) string {
|
||||
func PresetToLang(preset string) string {
|
||||
phrases := GetAllPermPresets()
|
||||
phrase, ok := phrases[preset]
|
||||
if !ok {
|
||||
@ -467,10 +473,18 @@ func presetToLang(preset string) string {
|
||||
}
|
||||
|
||||
// TODO: Is this racey?
|
||||
func rebuildGroupPermissions(gid int) error {
|
||||
// TODO: Test this along with the rest of the perms system
|
||||
func RebuildGroupPermissions(gid int) error {
|
||||
var permstr []byte
|
||||
log.Print("Reloading a group")
|
||||
err := db.QueryRow("select permissions from users_groups where gid = ?", gid).Scan(&permstr)
|
||||
|
||||
// TODO: Avoid re-initting this all the time
|
||||
getGroupPerms, err := qgen.Builder.SimpleSelect("users_groups", "permissions", "gid = ?", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = getGroupPerms.QueryRow(gid).Scan(&permstr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -483,7 +497,7 @@ func rebuildGroupPermissions(gid int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
group, err := gstore.Get(gid)
|
||||
group, err := Gstore.Get(gid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -491,7 +505,7 @@ func rebuildGroupPermissions(gid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func overridePerms(perms *Perms, status bool) {
|
||||
func OverridePerms(perms *Perms, status bool) {
|
||||
if status {
|
||||
*perms = AllPerms
|
||||
} else {
|
||||
@ -500,7 +514,7 @@ func overridePerms(perms *Perms, status bool) {
|
||||
}
|
||||
|
||||
// TODO: We need a better way of overriding forum perms rather than setting them one by one
|
||||
func overrideForumPerms(perms *Perms, status bool) {
|
||||
func OverrideForumPerms(perms *Perms, status bool) {
|
||||
perms.ViewTopic = status
|
||||
perms.LikeItem = status
|
||||
perms.CreateTopic = status
|
||||
@ -513,10 +527,10 @@ func overrideForumPerms(perms *Perms, status bool) {
|
||||
perms.CloseTopic = status
|
||||
}
|
||||
|
||||
func registerPluginPerm(name string) {
|
||||
func RegisterPluginPerm(name string) {
|
||||
AllPluginPerms[name] = true
|
||||
}
|
||||
|
||||
func deregisterPluginPerm(name string) {
|
||||
func DeregisterPluginPerm(name string) {
|
||||
delete(AllPluginPerms, name)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Copyright Azareal 2017 - 2018
|
||||
*
|
||||
*/
|
||||
package main
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@ -20,7 +20,7 @@ import (
|
||||
// TODO: Let the admin edit phrases from inside the Control Panel? How should we persist these? Should we create a copy of the langpack or edit the primaries? Use the changeLangpack mutex for this?
|
||||
// nolint Be quiet megacheck, this *is* used
|
||||
var currentLangPack atomic.Value
|
||||
var langpackCount int // TODO: Use atomics for this
|
||||
var langPackCount int // TODO: Use atomics for this
|
||||
|
||||
// TODO: We'll be implementing the level phrases in the software proper very very soon!
|
||||
type LevelPhrases struct {
|
||||
@ -44,10 +44,9 @@ type LanguagePack struct {
|
||||
}
|
||||
|
||||
// TODO: Add the ability to edit language JSON files from the Control Panel and automatically scan the files for changes
|
||||
////var langpacks = map[string]*LanguagePack
|
||||
var langpacks sync.Map // nolint it is used
|
||||
var langPacks sync.Map // nolint it is used
|
||||
|
||||
func initPhrases() error {
|
||||
func InitPhrases() error {
|
||||
log.Print("Loading the language packs")
|
||||
err := filepath.Walk("./langs", func(path string, f os.FileInfo, err error) error {
|
||||
if f.IsDir() {
|
||||
@ -61,8 +60,8 @@ func initPhrases() error {
|
||||
|
||||
var ext = filepath.Ext("/langs/" + path)
|
||||
if ext != ".json" {
|
||||
if dev.DebugMode {
|
||||
log.Print("Found a " + ext + "in /langs/")
|
||||
if Dev.DebugMode {
|
||||
log.Printf("Found a '%s' in /langs/", ext)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -74,8 +73,8 @@ func initPhrases() error {
|
||||
}
|
||||
|
||||
log.Print("Adding the '" + langPack.Name + "' language pack")
|
||||
langpacks.Store(langPack.Name, &langPack)
|
||||
langpackCount++
|
||||
langPacks.Store(langPack.Name, &langPack)
|
||||
langPackCount++
|
||||
|
||||
return nil
|
||||
})
|
||||
@ -83,13 +82,13 @@ func initPhrases() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if langpackCount == 0 {
|
||||
if langPackCount == 0 {
|
||||
return errors.New("You don't have any language packs")
|
||||
}
|
||||
|
||||
langPack, ok := langpacks.Load(site.Language)
|
||||
langPack, ok := langPacks.Load(Site.Language)
|
||||
if !ok {
|
||||
return errors.New("Couldn't find the " + site.Language + " language pack")
|
||||
return errors.New("Couldn't find the " + Site.Language + " language pack")
|
||||
}
|
||||
currentLangPack.Store(langPack)
|
||||
return nil
|
||||
@ -167,7 +166,7 @@ func DeletePhrase() {
|
||||
// TODO: Use atomics to store the pointer of the current active langpack?
|
||||
// nolint
|
||||
func ChangeLanguagePack(name string) (exists bool) {
|
||||
pack, ok := langpacks.Load(name)
|
||||
pack, ok := langPacks.Load(name)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
@ -89,7 +89,7 @@ func InitPluginLangs() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
plugins[plugin.UName] = pplugin
|
||||
Plugins[plugin.UName] = pplugin
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package common
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var prstore ProfileReplyStore
|
||||
var Prstore ProfileReplyStore
|
||||
|
||||
type ProfileReplyStore interface {
|
||||
Get(id int) (*Reply, error)
|
||||
@ -33,7 +35,7 @@ func (store *SQLProfileReplyStore) Get(id int) (*Reply, error) {
|
||||
}
|
||||
|
||||
func (store *SQLProfileReplyStore) Create(profileID int, content string, createdBy int, ipaddress string) (id int, err error) {
|
||||
res, err := store.create.Exec(profileID, content, parseMessage(content, 0, ""), createdBy, ipaddress)
|
||||
res, err := store.create.Exec(profileID, content, ParseMessage(content, 0, ""), createdBy, ipaddress)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -7,8 +7,11 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
type ReplyUser struct {
|
||||
@ -56,12 +59,37 @@ type Reply struct {
|
||||
}
|
||||
|
||||
var ErrAlreadyLiked = errors.New("You already liked this!")
|
||||
var replyStmts ReplyStmts
|
||||
|
||||
type ReplyStmts struct {
|
||||
isLiked *sql.Stmt
|
||||
createLike *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
addLikesToReply *sql.Stmt
|
||||
removeRepliesFromTopic *sql.Stmt
|
||||
getParent *sql.Stmt
|
||||
}
|
||||
|
||||
func init() {
|
||||
DbInits.Add(func() error {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
replyStmts = ReplyStmts{
|
||||
isLiked: acc.SimpleSelect("likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'replies'", "", ""),
|
||||
createLike: acc.SimpleInsert("likes", "weight, targetItem, targetType, sentBy", "?,?,?,?"),
|
||||
delete: acc.SimpleDelete("replies", "rid = ?"),
|
||||
addLikesToReply: acc.SimpleUpdate("replies", "likeCount = likeCount + ?", "rid = ?"),
|
||||
removeRepliesFromTopic: acc.SimpleUpdate("topics", "postCount = postCount - ?", "tid = ?"),
|
||||
getParent: acc.SimpleLeftJoin("replies", "topics", "topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, topics.data", "replies.tid = topics.tid", "rid = ?", "", ""),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Write tests for this
|
||||
// TODO: Wrap these queries in a transaction to make sure the state is consistent
|
||||
func (reply *Reply) Like(uid int) (err error) {
|
||||
var rid int // unused, just here to avoid mutating reply.ID
|
||||
err = stmts.hasLikedReply.QueryRow(uid, reply.ID).Scan(&rid)
|
||||
err = replyStmts.isLiked.QueryRow(uid, reply.ID).Scan(&rid)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return err
|
||||
} else if err != ErrNoRows {
|
||||
@ -69,29 +97,41 @@ func (reply *Reply) Like(uid int) (err error) {
|
||||
}
|
||||
|
||||
score := 1
|
||||
_, err = stmts.createLike.Exec(score, reply.ID, "replies", uid)
|
||||
_, err = replyStmts.createLike.Exec(score, reply.ID, "replies", uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmts.addLikesToReply.Exec(1, reply.ID)
|
||||
_, err = replyStmts.addLikesToReply.Exec(1, reply.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Write tests for this
|
||||
func (reply *Reply) Delete() error {
|
||||
_, err := stmts.deleteReply.Exec(reply.ID)
|
||||
_, err := replyStmts.delete.Exec(reply.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmts.removeRepliesFromTopic.Exec(1, reply.ParentID)
|
||||
tcache, ok := topics.(TopicCache)
|
||||
// TODO: Move this bit to *Topic
|
||||
_, err = replyStmts.removeRepliesFromTopic.Exec(1, reply.ParentID)
|
||||
tcache, ok := Topics.(TopicCache)
|
||||
if ok {
|
||||
tcache.CacheRemove(reply.ParentID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (reply *Reply) Topic() (*Topic, error) {
|
||||
topic := Topic{ID: 0}
|
||||
err := replyStmts.getParent.QueryRow(reply.ID).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), topic.ID)
|
||||
return &topic, err
|
||||
}
|
||||
|
||||
// Copy gives you a non-pointer concurrency safe copy of the reply
|
||||
func (reply *Reply) Copy() Reply {
|
||||
return *reply
|
||||
}
|
||||
|
||||
func BlankReply() *Reply {
|
||||
return &Reply{ID: 0}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package common
|
||||
import "database/sql"
|
||||
import "../query_gen/lib"
|
||||
|
||||
var rstore ReplyStore
|
||||
var Rstore ReplyStore
|
||||
|
||||
type ReplyStore interface {
|
||||
Get(id int) (*Reply, error)
|
||||
@ -31,8 +31,8 @@ func (store *SQLReplyStore) Get(id int) (*Reply, error) {
|
||||
|
||||
// TODO: Write a test for this
|
||||
func (store *SQLReplyStore) Create(topic *Topic, content string, ipaddress string, uid int) (id int, err error) {
|
||||
wcount := wordCount(content)
|
||||
res, err := store.create.Exec(topic.ID, content, parseMessage(content, topic.ParentID, "forums"), ipaddress, wcount, uid)
|
||||
wcount := WordCount(content)
|
||||
res, err := store.create.Exec(topic.ID, content, ParseMessage(content, topic.ParentID, "forums"), ipaddress, wcount, uid)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package common
|
||||
|
||||
import (
|
||||
"html"
|
||||
@ -7,8 +7,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
// nolint
|
||||
@ -16,28 +14,28 @@ var PreRoute func(http.ResponseWriter, *http.Request) (User, bool) = preRoute
|
||||
|
||||
// TODO: Come up with a better middleware solution
|
||||
// nolint We need these types so people can tell what they are without scrolling to the bottom of the file
|
||||
var PanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*common.HeaderVars, common.PanelStats, RouteError) = panelUserCheck
|
||||
var SimplePanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*common.HeaderLite, RouteError) = simplePanelUserCheck
|
||||
var SimpleForumUserCheck func(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerLite *common.HeaderLite, err RouteError) = simpleForumUserCheck
|
||||
var ForumUserCheck func(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerVars *common.HeaderVars, err RouteError) = forumUserCheck
|
||||
var MemberCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerVars *common.HeaderVars, err RouteError) = memberCheck
|
||||
var UserCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerVars *common.HeaderVars, err RouteError) = userCheck
|
||||
var UserCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerVars *common.HeaderVars, err RouteError) = userCheck
|
||||
var PanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*HeaderVars, PanelStats, RouteError) = panelUserCheck
|
||||
var SimplePanelUserCheck func(http.ResponseWriter, *http.Request, *User) (*HeaderLite, RouteError) = simplePanelUserCheck
|
||||
var SimpleForumUserCheck func(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerLite *HeaderLite, err RouteError) = simpleForumUserCheck
|
||||
var ForumUserCheck func(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerVars *HeaderVars, err RouteError) = forumUserCheck
|
||||
var MemberCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerVars *HeaderVars, err RouteError) = memberCheck
|
||||
var SimpleUserCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerLite *HeaderLite, err RouteError) = simpleUserCheck
|
||||
var UserCheck func(w http.ResponseWriter, r *http.Request, user *User) (headerVars *HeaderVars, err RouteError) = userCheck
|
||||
|
||||
// TODO: Support for left sidebars and sidebars on both sides
|
||||
// http.Request is for context.Context middleware. Mostly for plugin_guilds right now
|
||||
func BuildWidgets(zone string, data interface{}, headerVars *common.HeaderVars, r *http.Request) {
|
||||
if vhooks["intercept_build_widgets"] != nil {
|
||||
if runVhook("intercept_build_widgets", zone, data, headerVars, r).(bool) {
|
||||
func BuildWidgets(zone string, data interface{}, headerVars *HeaderVars, r *http.Request) {
|
||||
if Vhooks["intercept_build_widgets"] != nil {
|
||||
if RunVhook("intercept_build_widgets", zone, data, headerVars, r).(bool) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//log.Print("themes[headerVars.ThemeName].Sidebars",themes[headerVars.ThemeName].Sidebars)
|
||||
if themes[headerVars.ThemeName].Sidebars == "right" {
|
||||
if len(docks.RightSidebar) != 0 {
|
||||
//log.Print("Themes[headerVars.ThemeName].Sidebars", Themes[headerVars.ThemeName].Sidebars)
|
||||
if Themes[headerVars.ThemeName].Sidebars == "right" {
|
||||
if len(Docks.RightSidebar) != 0 {
|
||||
var sbody string
|
||||
for _, widget := range docks.RightSidebar {
|
||||
for _, widget := range Docks.RightSidebar {
|
||||
if widget.Enabled {
|
||||
if widget.Location == "global" || widget.Location == zone {
|
||||
sbody += widget.Body
|
||||
@ -49,21 +47,21 @@ func BuildWidgets(zone string, data interface{}, headerVars *common.HeaderVars,
|
||||
}
|
||||
}
|
||||
|
||||
func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerLite *common.HeaderLite, rerr RouteError) {
|
||||
if !fstore.Exists(fid) {
|
||||
func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerLite *HeaderLite, rerr RouteError) {
|
||||
if !Fstore.Exists(fid) {
|
||||
return nil, PreError("The target forum doesn't exist.", w, r)
|
||||
}
|
||||
|
||||
// Is there a better way of doing the skip AND the success flag on this hook like multiple returns?
|
||||
if vhookSkippable["simple_forum_check_pre_perms"] != nil {
|
||||
if VhookSkippable["simple_forum_check_pre_perms"] != nil {
|
||||
var skip bool
|
||||
skip, rerr = runVhookSkippable("simple_forum_check_pre_perms", w, r, user, &fid, &headerLite)
|
||||
skip, rerr = RunVhookSkippable("simple_forum_check_pre_perms", w, r, user, &fid, &headerLite)
|
||||
if skip || rerr != nil {
|
||||
return headerLite, rerr
|
||||
}
|
||||
}
|
||||
|
||||
fperms, err := fpstore.Get(fid, user.Group)
|
||||
fperms, err := Fpstore.Get(fid, user.Group)
|
||||
if err != nil {
|
||||
// TODO: Refactor this
|
||||
log.Printf("Unable to get the forum perms for Group #%d for User #%d", user.Group, user.ID)
|
||||
@ -73,24 +71,24 @@ func simpleForumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fi
|
||||
return headerLite, nil
|
||||
}
|
||||
|
||||
func forumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerVars *common.HeaderVars, rerr RouteError) {
|
||||
func forumUserCheck(w http.ResponseWriter, r *http.Request, user *User, fid int) (headerVars *HeaderVars, rerr RouteError) {
|
||||
headerVars, rerr = UserCheck(w, r, user)
|
||||
if rerr != nil {
|
||||
return headerVars, rerr
|
||||
}
|
||||
if !fstore.Exists(fid) {
|
||||
if !Fstore.Exists(fid) {
|
||||
return headerVars, NotFound(w, r)
|
||||
}
|
||||
|
||||
if vhookSkippable["forum_check_pre_perms"] != nil {
|
||||
if VhookSkippable["forum_check_pre_perms"] != nil {
|
||||
var skip bool
|
||||
skip, rerr = runVhookSkippable("forum_check_pre_perms", w, r, user, &fid, &headerVars)
|
||||
skip, rerr = RunVhookSkippable("forum_check_pre_perms", w, r, user, &fid, &headerVars)
|
||||
if skip || rerr != nil {
|
||||
return headerVars, rerr
|
||||
}
|
||||
}
|
||||
|
||||
fperms, err := fpstore.Get(fid, user.Group)
|
||||
fperms, err := Fpstore.Get(fid, user.Group)
|
||||
if err != nil {
|
||||
// TODO: Refactor this
|
||||
log.Printf("Unable to get the forum perms for Group #%d for User #%d", user.Group, user.ID)
|
||||
@ -126,29 +124,29 @@ func cascadeForumPerms(fperms ForumPerms, user *User) {
|
||||
|
||||
// Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with
|
||||
// TODO: Do a panel specific theme?
|
||||
func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *common.HeaderVars, stats common.PanelStats, rerr RouteError) {
|
||||
var themeName = defaultThemeBox.Load().(string)
|
||||
func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *HeaderVars, stats PanelStats, rerr RouteError) {
|
||||
var themeName = DefaultThemeBox.Load().(string)
|
||||
|
||||
cookie, err := r.Cookie("current_theme")
|
||||
if err == nil {
|
||||
cookie := html.EscapeString(cookie.Value)
|
||||
theme, ok := themes[cookie]
|
||||
theme, ok := Themes[cookie]
|
||||
if ok && !theme.HideFromThemes {
|
||||
themeName = cookie
|
||||
}
|
||||
}
|
||||
|
||||
headerVars = &HeaderVars{
|
||||
Site: site,
|
||||
Settings: settingBox.Load().(SettingBox),
|
||||
Themes: themes,
|
||||
Site: Site,
|
||||
Settings: SettingBox.Load().(SettingMap),
|
||||
Themes: Themes,
|
||||
ThemeName: themeName,
|
||||
}
|
||||
// TODO: We should probably initialise headerVars.ExtData
|
||||
|
||||
headerVars.Stylesheets = append(headerVars.Stylesheets, headerVars.ThemeName+"/panel.css")
|
||||
if len(themes[headerVars.ThemeName].Resources) > 0 {
|
||||
rlist := themes[headerVars.ThemeName].Resources
|
||||
if len(Themes[headerVars.ThemeName].Resources) > 0 {
|
||||
rlist := Themes[headerVars.ThemeName].Resources
|
||||
for _, resource := range rlist {
|
||||
if resource.Location == "global" || resource.Location == "panel" {
|
||||
extarr := strings.Split(resource.Name, ".")
|
||||
@ -162,16 +160,12 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerV
|
||||
}
|
||||
}
|
||||
|
||||
err = stmts.groupCount.QueryRow().Scan(&stats.Groups)
|
||||
if err != nil {
|
||||
return headerVars, stats, InternalError(err, w, r)
|
||||
}
|
||||
|
||||
stats.Users = users.GlobalCount()
|
||||
stats.Forums = fstore.GlobalCount() // TODO: Stop it from showing the blanked forums
|
||||
stats.Users = Users.GlobalCount()
|
||||
stats.Groups = Gstore.GlobalCount()
|
||||
stats.Forums = Fstore.GlobalCount() // TODO: Stop it from showing the blanked forums
|
||||
stats.Settings = len(headerVars.Settings)
|
||||
stats.WordFilters = len(wordFilterBox.Load().(WordFilterBox))
|
||||
stats.Themes = len(themes)
|
||||
stats.WordFilters = len(WordFilterBox.Load().(WordFilterMap))
|
||||
stats.Themes = len(Themes)
|
||||
stats.Reports = 0 // TODO: Do the report count. Only show open threads?
|
||||
|
||||
pusher, ok := w.(http.Pusher)
|
||||
@ -188,15 +182,15 @@ func panelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerV
|
||||
return headerVars, stats, nil
|
||||
}
|
||||
|
||||
func simplePanelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerLite *common.HeaderLite, rerr RouteError) {
|
||||
func simplePanelUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerLite *HeaderLite, rerr RouteError) {
|
||||
return &HeaderLite{
|
||||
Site: site,
|
||||
Settings: settingBox.Load().(SettingBox),
|
||||
Site: Site,
|
||||
Settings: SettingBox.Load().(SettingMap),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TODO: Add this to the member routes
|
||||
func memberCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *common.HeaderVars, rerr RouteError) {
|
||||
func memberCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *HeaderVars, rerr RouteError) {
|
||||
headerVars, rerr = UserCheck(w, r, user)
|
||||
if !user.Loggedin {
|
||||
return headerVars, NoPermissions(w, r, *user)
|
||||
@ -205,31 +199,31 @@ func memberCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars
|
||||
}
|
||||
|
||||
// SimpleUserCheck is back from the grave, yay :D
|
||||
func simpleUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerLite *common.HeaderLite, rerr RouteError) {
|
||||
func simpleUserCheck(w http.ResponseWriter, r *http.Request, user *User) (headerLite *HeaderLite, rerr RouteError) {
|
||||
headerLite = &HeaderLite{
|
||||
Site: site,
|
||||
Settings: settingBox.Load().(SettingBox),
|
||||
Site: Site,
|
||||
Settings: SettingBox.Load().(SettingMap),
|
||||
}
|
||||
return headerLite, nil
|
||||
}
|
||||
|
||||
// TODO: Add the ability for admins to restrict certain themes to certain groups?
|
||||
func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *common.HeaderVars, rerr RouteError) {
|
||||
var themeName = defaultThemeBox.Load().(string)
|
||||
func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *HeaderVars, rerr RouteError) {
|
||||
var themeName = DefaultThemeBox.Load().(string)
|
||||
|
||||
cookie, err := r.Cookie("current_theme")
|
||||
if err == nil {
|
||||
cookie := html.EscapeString(cookie.Value)
|
||||
theme, ok := themes[cookie]
|
||||
theme, ok := Themes[cookie]
|
||||
if ok && !theme.HideFromThemes {
|
||||
themeName = cookie
|
||||
}
|
||||
}
|
||||
|
||||
headerVars = &HeaderVars{
|
||||
Site: site,
|
||||
Settings: settingBox.Load().(SettingBox),
|
||||
Themes: themes,
|
||||
Site: Site,
|
||||
Settings: SettingBox.Load().(SettingMap),
|
||||
Themes: Themes,
|
||||
ThemeName: themeName,
|
||||
}
|
||||
|
||||
@ -237,8 +231,8 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *
|
||||
headerVars.NoticeList = append(headerVars.NoticeList, "Your account has been suspended. Some of your permissions may have been revoked.")
|
||||
}
|
||||
|
||||
if len(themes[headerVars.ThemeName].Resources) > 0 {
|
||||
rlist := themes[headerVars.ThemeName].Resources
|
||||
if len(Themes[headerVars.ThemeName].Resources) > 0 {
|
||||
rlist := Themes[headerVars.ThemeName].Resources
|
||||
for _, resource := range rlist {
|
||||
if resource.Location == "global" || resource.Location == "frontend" {
|
||||
extarr := strings.Split(resource.Name, ".")
|
||||
@ -266,27 +260,28 @@ func userCheck(w http.ResponseWriter, r *http.Request, user *User) (headerVars *
|
||||
}
|
||||
|
||||
func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
|
||||
user, halt := auth.SessionCheck(w, r)
|
||||
user, halt := Auth.SessionCheck(w, r)
|
||||
if halt {
|
||||
return *user, false
|
||||
}
|
||||
if user == &guestUser {
|
||||
if user == &GuestUser {
|
||||
return *user, true
|
||||
}
|
||||
|
||||
var usercpy = *user
|
||||
var usercpy *User
|
||||
*usercpy = *user
|
||||
|
||||
// TODO: WIP. Refactor this to eliminate the unnecessary query
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
PreError("Bad IP", w, r)
|
||||
return usercpy, false
|
||||
return *usercpy, false
|
||||
}
|
||||
if host != usercpy.LastIP {
|
||||
_, err = stmts.updateLastIP.Exec(host, usercpy.ID)
|
||||
err = usercpy.UpdateIP(host)
|
||||
if err != nil {
|
||||
InternalError(err, w, r)
|
||||
return usercpy, false
|
||||
return *usercpy, false
|
||||
}
|
||||
usercpy.LastIP = host
|
||||
}
|
||||
@ -296,7 +291,7 @@ func preRoute(w http.ResponseWriter, r *http.Request) (User, bool) {
|
||||
//h.Set("X-XSS-Protection", "1")
|
||||
// TODO: Set the content policy header
|
||||
|
||||
return usercpy, true
|
||||
return *usercpy, true
|
||||
}
|
||||
|
||||
// SuperModeOnly makes sure that only super mods or higher can access the panel routes
|
@ -3,6 +3,7 @@ package common
|
||||
import "strconv"
|
||||
import "strings"
|
||||
import "sync/atomic"
|
||||
import "../query_gen/lib"
|
||||
|
||||
// SettingMap is a map type specifically for holding the various settings admins set to toggle features on and off or to otherwise alter Gosora's behaviour from the Control Panel
|
||||
type SettingMap map[string]interface{}
|
||||
@ -27,7 +28,12 @@ func init() {
|
||||
}
|
||||
|
||||
func LoadSettings() error {
|
||||
rows, err := stmts.getFullSettings.Query()
|
||||
// TODO: Stop doing this inline
|
||||
getFullSettings, err := qgen.Builder.SimpleSelect("settings", "name, content, type, constraints", "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := getFullSettings.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -6,24 +6,31 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
var site = &Site{Name: "Magical Fairy Land", Language: "english"}
|
||||
var dbConfig = DBConfig{Host: "localhost"}
|
||||
var config Config
|
||||
var dev DevConfig
|
||||
// Site holds the basic settings which should be tweaked when setting up a site, we might move them to the settings table at some point
|
||||
var Site = &site{Name: "Magical Fairy Land", Language: "english"}
|
||||
|
||||
type Site struct {
|
||||
// DbConfig holds the database configuration
|
||||
var DbConfig = dbConfig{Host: "localhost"}
|
||||
|
||||
// Config holds the more technical settings
|
||||
var Config config
|
||||
|
||||
// Dev holds build flags and other things which should only be modified during developers or to gather additional test data
|
||||
var Dev devConfig
|
||||
|
||||
type site struct {
|
||||
ShortName string
|
||||
Name string // ? - Move this into the settings table? Should we make a second version of this for the abbreviation shown in the navbar?
|
||||
Email string // ? - Move this into the settings table?
|
||||
Name string
|
||||
Email string
|
||||
URL string
|
||||
Port string
|
||||
EnableSsl bool
|
||||
EnableEmails bool
|
||||
HasProxy bool
|
||||
Language string // ? - Move this into the settings table?
|
||||
Language string
|
||||
}
|
||||
|
||||
type DBConfig struct {
|
||||
type dbConfig struct {
|
||||
// Production database
|
||||
Host string
|
||||
Username string
|
||||
@ -39,7 +46,7 @@ type DBConfig struct {
|
||||
TestPort string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
type config struct {
|
||||
SslPrivkey string
|
||||
SslFullchain string
|
||||
|
||||
@ -65,7 +72,7 @@ type Config struct {
|
||||
ItemsPerPage int // ? - Move this into the settings table?
|
||||
}
|
||||
|
||||
type DevConfig struct {
|
||||
type devConfig struct {
|
||||
DebugMode bool
|
||||
SuperDebug bool
|
||||
TemplateDebug bool
|
||||
@ -73,35 +80,35 @@ type DevConfig struct {
|
||||
TestDB bool
|
||||
}
|
||||
|
||||
func processConfig() error {
|
||||
config.Noavatar = strings.Replace(config.Noavatar, "{site_url}", site.URL, -1)
|
||||
if site.Port != "80" && site.Port != "443" {
|
||||
site.URL = strings.TrimSuffix(site.URL, "/")
|
||||
site.URL = strings.TrimSuffix(site.URL, "\\")
|
||||
site.URL = strings.TrimSuffix(site.URL, ":")
|
||||
site.URL = site.URL + ":" + site.Port
|
||||
func ProcessConfig() error {
|
||||
Config.Noavatar = strings.Replace(Config.Noavatar, "{site_url}", Site.URL, -1)
|
||||
if Site.Port != "80" && Site.Port != "443" {
|
||||
Site.URL = strings.TrimSuffix(Site.URL, "/")
|
||||
Site.URL = strings.TrimSuffix(Site.URL, "\\")
|
||||
Site.URL = strings.TrimSuffix(Site.URL, ":")
|
||||
Site.URL = Site.URL + ":" + Site.Port
|
||||
}
|
||||
// We need this in here rather than verifyConfig as switchToTestDB() currently overwrites the values it verifies
|
||||
if dbConfig.TestDbname == dbConfig.Dbname {
|
||||
if DbConfig.TestDbname == DbConfig.Dbname {
|
||||
return errors.New("Your test database can't have the same name as your production database")
|
||||
}
|
||||
if dev.TestDB {
|
||||
switchToTestDB()
|
||||
if Dev.TestDB {
|
||||
SwitchToTestDB()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyConfig() error {
|
||||
if !fstore.Exists(config.DefaultForum) {
|
||||
func VerifyConfig() error {
|
||||
if !Fstore.Exists(Config.DefaultForum) {
|
||||
return errors.New("Invalid default forum")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func switchToTestDB() {
|
||||
dbConfig.Host = dbConfig.TestHost
|
||||
dbConfig.Username = dbConfig.TestUsername
|
||||
dbConfig.Password = dbConfig.TestPassword
|
||||
dbConfig.Dbname = dbConfig.TestDbname
|
||||
dbConfig.Port = dbConfig.TestPort
|
||||
func SwitchToTestDB() {
|
||||
DbConfig.Host = DbConfig.TestHost
|
||||
DbConfig.Username = DbConfig.TestUsername
|
||||
DbConfig.Password = DbConfig.TestPassword
|
||||
DbConfig.Dbname = DbConfig.TestDbname
|
||||
DbConfig.Port = DbConfig.TestPort
|
||||
}
|
||||
|
@ -4,11 +4,13 @@
|
||||
* Copyright Azareal 2017 - 2018
|
||||
*
|
||||
*/
|
||||
package main
|
||||
package common
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
var lastSync time.Time
|
||||
@ -17,8 +19,12 @@ func init() {
|
||||
lastSync = time.Now()
|
||||
}
|
||||
|
||||
func handleExpiredScheduledGroups() error {
|
||||
rows, err := stmts.getExpiredScheduledGroups.Query()
|
||||
func HandleExpiredScheduledGroups() error {
|
||||
getExpiredScheduledGroups, err := qgen.Builder.SimpleSelect("users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := getExpiredScheduledGroups.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -32,7 +38,7 @@ func handleExpiredScheduledGroups() error {
|
||||
}
|
||||
|
||||
// Sneaky way of initialising a *User, please use the methods on the UserStore instead
|
||||
user := getDummyUser()
|
||||
user := BlankUser()
|
||||
user.ID = uid
|
||||
err = user.RevertGroupUpdate()
|
||||
if err != nil {
|
||||
@ -42,16 +48,20 @@ func handleExpiredScheduledGroups() error {
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func handleServerSync() error {
|
||||
func HandleServerSync() error {
|
||||
var lastUpdate time.Time
|
||||
err := stmts.getSync.QueryRow().Scan(&lastUpdate)
|
||||
getSync, err := qgen.Builder.SimpleSelect("sync", "last_update", "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = getSync.QueryRow().Scan(&lastUpdate)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if lastUpdate.After(lastSync) {
|
||||
// TODO: A more granular sync
|
||||
err = fstore.LoadForums()
|
||||
err = Fstore.LoadForums()
|
||||
if err != nil {
|
||||
log.Print("Unable to reload the forums")
|
||||
return err
|
@ -5,10 +5,12 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"./templates"
|
||||
)
|
||||
|
||||
var templates = template.New("")
|
||||
var prebuildTmplList []func(*User, *HeaderVars) CTmpl
|
||||
var Templates = template.New("")
|
||||
var PrebuildTmplList []func(User, *HeaderVars) CTmpl
|
||||
|
||||
type CTmpl struct {
|
||||
Name string
|
||||
@ -20,11 +22,11 @@ type CTmpl struct {
|
||||
|
||||
// nolint
|
||||
func interpreted_topic_template(pi TopicPage, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap["topic"]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["topic"]
|
||||
if !ok {
|
||||
mapping = "topic"
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
|
||||
// nolint
|
||||
@ -33,64 +35,66 @@ var template_topic_alt_handle func(TopicPage, http.ResponseWriter) error = inter
|
||||
|
||||
// nolint
|
||||
var template_topics_handle func(TopicsPage, http.ResponseWriter) error = func(pi TopicsPage, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap["topics"]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["topics"]
|
||||
if !ok {
|
||||
mapping = "topics"
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
|
||||
// nolint
|
||||
var template_forum_handle func(ForumPage, http.ResponseWriter) error = func(pi ForumPage, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap["forum"]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["forum"]
|
||||
if !ok {
|
||||
mapping = "forum"
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
|
||||
// nolint
|
||||
var template_forums_handle func(ForumsPage, http.ResponseWriter) error = func(pi ForumsPage, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap["forums"]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["forums"]
|
||||
if !ok {
|
||||
mapping = "forums"
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
|
||||
// nolint
|
||||
var template_profile_handle func(ProfilePage, http.ResponseWriter) error = func(pi ProfilePage, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap["profile"]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["profile"]
|
||||
if !ok {
|
||||
mapping = "profile"
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
|
||||
// nolint
|
||||
var template_create_topic_handle func(CreateTopicPage, http.ResponseWriter) error = func(pi CreateTopicPage, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap["create-topic"]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap["create-topic"]
|
||||
if !ok {
|
||||
mapping = "create-topic"
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
|
||||
// ? - Add template hooks?
|
||||
func compileTemplates() error {
|
||||
var c CTemplateSet
|
||||
var c tmpl.CTemplateSet
|
||||
c.Minify(Config.MinifyTemplates)
|
||||
c.SuperDebug(Dev.TemplateDebug)
|
||||
|
||||
// Schemas to train the template compiler on what to expect
|
||||
// TODO: Add support for interface{}s
|
||||
user := User{62, buildProfileURL("fake-user", 62), "Fake User", "compiler@localhost", 0, false, false, false, false, false, false, GuestPerms, make(map[string]bool), "", false, "", "", "", "", "", 0, 0, "0.0.0.0.0", 0}
|
||||
user := User{62, BuildProfileURL("fake-user", 62), "Fake User", "compiler@localhost", 0, false, false, false, false, false, false, GuestPerms, make(map[string]bool), "", false, "", "", "", "", "", 0, 0, "0.0.0.0.0", 0}
|
||||
// TODO: Do a more accurate level calculation for this?
|
||||
user2 := User{1, buildProfileURL("admin-alice", 1), "Admin Alice", "alice@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, "", "", "", "", "", 58, 1000, "127.0.0.1", 0}
|
||||
user3 := User{2, buildProfileURL("admin-fred", 62), "Admin Fred", "fred@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, "", "", "", "", "", 42, 900, "::1", 0}
|
||||
user2 := User{1, BuildProfileURL("admin-alice", 1), "Admin Alice", "alice@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, "", "", "", "", "", 58, 1000, "127.0.0.1", 0}
|
||||
user3 := User{2, BuildProfileURL("admin-fred", 62), "Admin Fred", "fred@localhost", 1, true, true, true, true, false, false, AllPerms, make(map[string]bool), "", true, "", "", "", "", "", 42, 900, "::1", 0}
|
||||
headerVars := &HeaderVars{
|
||||
Site: site,
|
||||
Settings: settingBox.Load().(SettingBox),
|
||||
Themes: themes,
|
||||
ThemeName: defaultThemeBox.Load().(string),
|
||||
Site: Site,
|
||||
Settings: SettingBox.Load().(SettingMap),
|
||||
Themes: Themes,
|
||||
ThemeName: DefaultThemeBox.Load().(string),
|
||||
NoticeList: []string{"test"},
|
||||
Stylesheets: []string{"panel"},
|
||||
Scripts: []string{"whatever"},
|
||||
@ -102,31 +106,31 @@ func compileTemplates() error {
|
||||
log.Print("Compiling the templates")
|
||||
|
||||
var now = time.Now()
|
||||
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, relativeTime(now), now, relativeTime(now), 0, "", "127.0.0.1", 0, 1, "classname", "weird-data", buildProfileURL("fake-user", 62), "Fake User", config.DefaultGroup, "", 0, "", "", "", "", "", 58, false}
|
||||
topic := TopicUser{1, "blah", "Blah", "Hey there!", 0, false, false, now, RelativeTime(now), now, RelativeTime(now), 0, "", "127.0.0.1", 0, 1, "classname", "weird-data", BuildProfileURL("fake-user", 62), "Fake User", Config.DefaultGroup, "", 0, "", "", "", "", "", 58, false}
|
||||
var replyList []ReplyUser
|
||||
replyList = append(replyList, ReplyUser{0, 0, "Yo!", "Yo!", 0, "alice", "Alice", config.DefaultGroup, now, relativeTime(now), 0, 0, "", "", 0, "", "", "", "", 0, "127.0.0.1", false, 1, "", ""})
|
||||
replyList = append(replyList, ReplyUser{0, 0, "Yo!", "Yo!", 0, "alice", "Alice", Config.DefaultGroup, now, RelativeTime(now), 0, 0, "", "", 0, "", "", "", "", 0, "127.0.0.1", false, 1, "", ""})
|
||||
|
||||
var varList = make(map[string]VarItem)
|
||||
var varList = make(map[string]tmpl.VarItem)
|
||||
tpage := TopicPage{"Title", user, headerVars, replyList, topic, 1, 1}
|
||||
topicIDTmpl, err := c.compileTemplate("topic.html", "templates/", "TopicPage", tpage, varList)
|
||||
topicIDTmpl, err := c.Compile("topic.html", "templates/", "TopicPage", tpage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
topicIDAltTmpl, err := c.compileTemplate("topic_alt.html", "templates/", "TopicPage", tpage, varList)
|
||||
topicIDAltTmpl, err := c.Compile("topic_alt.html", "templates/", "TopicPage", tpage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
varList = make(map[string]VarItem)
|
||||
varList = make(map[string]tmpl.VarItem)
|
||||
ppage := ProfilePage{"User 526", user, headerVars, replyList, user}
|
||||
profileTmpl, err := c.compileTemplate("profile.html", "templates/", "ProfilePage", ppage, varList)
|
||||
profileTmpl, err := c.Compile("profile.html", "templates/", "ProfilePage", ppage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Use a dummy forum list to avoid o(n) problems
|
||||
var forumList []Forum
|
||||
forums, err := fstore.GetAll()
|
||||
forums, err := Fstore.GetAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -135,17 +139,17 @@ func compileTemplates() error {
|
||||
//log.Printf("*forum %+v\n", *forum)
|
||||
forumList = append(forumList, *forum)
|
||||
}
|
||||
varList = make(map[string]VarItem)
|
||||
varList = make(map[string]tmpl.VarItem)
|
||||
forumsPage := ForumsPage{"Forum List", user, headerVars, forumList}
|
||||
forumsTmpl, err := c.compileTemplate("forums.html", "templates/", "ForumsPage", forumsPage, varList)
|
||||
forumsTmpl, err := c.Compile("forums.html", "templates/", "ForumsPage", forumsPage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var topicsList []*TopicsRow
|
||||
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, "Date", time.Now(), "Date", user3.ID, 1, "", "127.0.0.1", 0, 1, "classname", "", &user2, "", 0, &user3, "General", "/forum/general.2"})
|
||||
topicsPage := TopicsPage{"Topic List", user, headerVars, topicsList, forumList, config.DefaultForum}
|
||||
topicsTmpl, err := c.compileTemplate("topics.html", "templates/", "TopicsPage", topicsPage, varList)
|
||||
topicsPage := TopicsPage{"Topic List", user, headerVars, topicsList, forumList, Config.DefaultForum}
|
||||
topicsTmpl, err := c.Compile("topics.html", "templates/", "TopicsPage", topicsPage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -154,20 +158,20 @@ func compileTemplates() error {
|
||||
//topicList = append(topicList,TopicUser{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",1,"","127.0.0.1",0,1,"classname","","admin-fred","Admin Fred",config.DefaultGroup,"",0,"","","","",58,false})
|
||||
forumItem := makeDummyForum(1, "general-forum.1", "General Forum", "Where the general stuff happens", true, "all", 0, "", 0)
|
||||
forumPage := ForumPage{"General Forum", user, headerVars, topicsList, forumItem, 1, 1}
|
||||
forumTmpl, err := c.compileTemplate("forum.html", "templates/", "ForumPage", forumPage, varList)
|
||||
forumTmpl, err := c.Compile("forum.html", "templates/", "ForumPage", forumPage, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Let plugins register their own templates
|
||||
for _, tmplfunc := range prebuildTmplList {
|
||||
tmpl := tmplfunc(user, headerVars)
|
||||
varList = make(map[string]VarItem)
|
||||
compiledTmpl, err := c.compileTemplate(tmpl.Filename, tmpl.Path, tmpl.StructName, tmpl.Data, varList)
|
||||
for _, tmplfunc := range PrebuildTmplList {
|
||||
tmplItem := tmplfunc(user, headerVars)
|
||||
varList = make(map[string]tmpl.VarItem)
|
||||
compiledTmpl, err := c.Compile(tmplItem.Filename, tmplItem.Path, tmplItem.StructName, tmplItem.Data, varList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go writeTemplate(tmpl.Name, compiledTmpl)
|
||||
go writeTemplate(tmplItem.Name, compiledTmpl)
|
||||
}
|
||||
|
||||
log.Print("Writing the templates")
|
||||
@ -194,8 +198,8 @@ func writeTemplate(name string, content string) {
|
||||
}
|
||||
}
|
||||
|
||||
func initTemplates() {
|
||||
if dev.DebugMode {
|
||||
func InitTemplates() {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Initialising the template system")
|
||||
}
|
||||
compileTemplates()
|
||||
@ -259,10 +263,10 @@ func initTemplates() {
|
||||
}
|
||||
|
||||
// The interpreted templates...
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Loading the template files...")
|
||||
}
|
||||
templates.Funcs(fmap)
|
||||
template.Must(templates.ParseGlob("templates/*"))
|
||||
template.Must(templates.ParseGlob("pages/*"))
|
||||
Templates.Funcs(fmap)
|
||||
template.Must(Templates.ParseGlob("templates/*"))
|
||||
template.Must(Templates.ParseGlob("pages/*"))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package tmpl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -14,8 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// TODO: Turn this file into a library
|
||||
var ctemplates []string
|
||||
var tmplPtrMap = make(map[string]interface{})
|
||||
var cTemplates []string
|
||||
var textOverlapList = make(map[string]int)
|
||||
|
||||
// nolint
|
||||
@ -47,11 +46,26 @@ type CTemplateSet struct {
|
||||
nextNode parse.NodeType
|
||||
//tempVars map[string]string
|
||||
doImports bool
|
||||
minify bool
|
||||
debug bool
|
||||
superDebug bool
|
||||
expectsInt interface{}
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) compileTemplate(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string, err error) {
|
||||
if dev.DebugMode {
|
||||
func (c *CTemplateSet) Minify(on bool) {
|
||||
c.minify = on
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) Debug(on bool) {
|
||||
c.debug = on
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) SuperDebug(on bool) {
|
||||
c.superDebug = on
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) Compile(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string, err error) {
|
||||
if c.debug {
|
||||
fmt.Println("Compiling template '" + name + "'")
|
||||
}
|
||||
|
||||
@ -75,6 +89,7 @@ func (c *CTemplateSet) compileTemplate(name string, dir string, expects string,
|
||||
|
||||
c.importMap = map[string]string{
|
||||
"net/http": "net/http",
|
||||
"./common": "./common",
|
||||
}
|
||||
c.varList = varList
|
||||
//c.pVarList = ""
|
||||
@ -89,7 +104,7 @@ func (c *CTemplateSet) compileTemplate(name string, dir string, expects string,
|
||||
}
|
||||
|
||||
content := string(res)
|
||||
if config.MinifyTemplates {
|
||||
if c.minify {
|
||||
content = minify(content)
|
||||
}
|
||||
|
||||
@ -133,7 +148,7 @@ func (c *CTemplateSet) compileTemplate(name string, dir string, expects string,
|
||||
|
||||
fout := "// +build !no_templategen\n\n// Code generated by Gosora. More below:\n/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */\n"
|
||||
fout += "package main\n" + importList + c.pVarList + "\n"
|
||||
fout += "// nolint\nfunc init() {\n\ttemplate_" + fname + "_handle = template_" + fname + "\n\t//o_template_" + fname + "_handle = template_" + fname + "\n\tctemplates = append(ctemplates,\"" + fname + "\")\n\ttmplPtrMap[\"" + fname + "\"] = &template_" + fname + "_handle\n\ttmplPtrMap[\"o_" + fname + "\"] = template_" + fname + "\n}\n\n"
|
||||
fout += "// nolint\nfunc init() {\n\ttemplate_" + fname + "_handle = template_" + fname + "\n\t//o_template_" + fname + "_handle = template_" + fname + "\n\tctemplates = append(ctemplates,\"" + fname + "\")\n\tTmplPtrMap[\"" + fname + "\"] = &template_" + fname + "_handle\n\tcommon.TmplPtrMap[\"o_" + fname + "\"] = template_" + fname + "\n}\n\n"
|
||||
fout += "// nolint\nfunc template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w http.ResponseWriter) error {\n" + varString + out + "\treturn nil\n}\n"
|
||||
|
||||
fout = strings.Replace(fout, `))
|
||||
@ -143,7 +158,7 @@ w.Write([]byte(`, " + ", -1)
|
||||
//whitespaceWrites := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`)
|
||||
//fout = whitespaceWrites.ReplaceAllString(fout,"")
|
||||
|
||||
if dev.DebugMode {
|
||||
if c.debug {
|
||||
for index, count := range c.stats {
|
||||
fmt.Println(index+": ", strconv.Itoa(count))
|
||||
}
|
||||
@ -160,9 +175,7 @@ func (c *CTemplateSet) rootIterate(tree *parse.Tree, varholder string, holdrefle
|
||||
c.log(tree.Root)
|
||||
treeLength := len(tree.Root.Nodes)
|
||||
for index, node := range tree.Root.Nodes {
|
||||
if dev.TemplateDebug {
|
||||
fmt.Println("Node:", node.String())
|
||||
}
|
||||
c.log("Node:", node.String())
|
||||
c.previousNode = c.currentNode
|
||||
c.currentNode = node.Type()
|
||||
if treeLength != (index + 1) {
|
||||
@ -245,9 +258,7 @@ func (c *CTemplateSet) compileRangeNode(varholder string, holdreflect reflect.Va
|
||||
|
||||
var outVal reflect.Value
|
||||
for _, cmd := range node.Pipe.Cmds {
|
||||
if dev.TemplateDebug {
|
||||
fmt.Println("Range Bit:", cmd)
|
||||
}
|
||||
c.log("Range Bit:", cmd)
|
||||
out, outVal = c.compileReflectSwitch(varholder, holdreflect, templateName, cmd)
|
||||
}
|
||||
c.log("Returned:", out)
|
||||
@ -259,7 +270,7 @@ func (c *CTemplateSet) compileRangeNode(varholder string, holdreflect reflect.Va
|
||||
for _, key := range outVal.MapKeys() {
|
||||
item = outVal.MapIndex(key)
|
||||
}
|
||||
if dev.DebugMode {
|
||||
if c.debug {
|
||||
fmt.Println("Range item:", item)
|
||||
}
|
||||
if !item.IsValid() {
|
||||
@ -317,11 +328,11 @@ func (c *CTemplateSet) compileSubswitch(varholder string, holdreflect reflect.Va
|
||||
}
|
||||
|
||||
if !cur.IsValid() {
|
||||
if dev.DebugMode {
|
||||
if c.debug {
|
||||
fmt.Println("Debug Data:")
|
||||
fmt.Println("Holdreflect:", holdreflect)
|
||||
fmt.Println("Holdreflect.Kind():", holdreflect.Kind())
|
||||
if !dev.TemplateDebug {
|
||||
if !c.superDebug {
|
||||
fmt.Println("cur.Kind():", cur.Kind().String())
|
||||
}
|
||||
fmt.Println("")
|
||||
@ -382,7 +393,7 @@ func (c *CTemplateSet) compileVarswitch(varholder string, holdreflect reflect.Va
|
||||
firstWord := node.Args[0]
|
||||
switch n := firstWord.(type) {
|
||||
case *parse.FieldNode:
|
||||
if dev.TemplateDebug {
|
||||
if c.superDebug {
|
||||
fmt.Println("Field Node:", n.Ident)
|
||||
for _, id := range n.Ident {
|
||||
fmt.Println("Field Bit:", id)
|
||||
@ -564,7 +575,7 @@ func (c *CTemplateSet) compileReflectSwitch(varholder string, holdreflect reflec
|
||||
firstWord := node.Args[0]
|
||||
switch n := firstWord.(type) {
|
||||
case *parse.FieldNode:
|
||||
if dev.TemplateDebug {
|
||||
if c.superDebug {
|
||||
fmt.Println("Field Node:", n.Ident)
|
||||
for _, id := range n.Ident {
|
||||
fmt.Println("Field Bit:", id)
|
||||
@ -771,7 +782,7 @@ func (c *CTemplateSet) compileSubtemplate(pvarholder string, pholdreflect reflec
|
||||
}
|
||||
|
||||
content := string(res)
|
||||
if config.MinifyTemplates {
|
||||
if c.minify {
|
||||
content = minify(content)
|
||||
}
|
||||
|
||||
@ -795,7 +806,7 @@ func (c *CTemplateSet) compileSubtemplate(pvarholder string, pholdreflect reflec
|
||||
}
|
||||
|
||||
func (c *CTemplateSet) log(args ...interface{}) {
|
||||
if dev.TemplateDebug {
|
||||
if c.superDebug {
|
||||
fmt.Println(args...)
|
||||
}
|
||||
}
|
@ -17,13 +17,15 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"text/template"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
type ThemeList map[string]Theme
|
||||
|
||||
//var themes ThemeList = make(map[string]Theme)
|
||||
var Themes ThemeList = make(map[string]Theme)
|
||||
var DefaultThemeBox atomic.Value
|
||||
var changeDefaultThemeMutex sync.Mutex
|
||||
var ChangeDefaultThemeMutex sync.Mutex
|
||||
|
||||
// TODO: Use this when the default theme doesn't exist
|
||||
var fallbackTheme = "shadow"
|
||||
@ -73,14 +75,19 @@ type ThemeResource struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
defaultThemeBox.Store(fallbackTheme)
|
||||
DefaultThemeBox.Store(fallbackTheme)
|
||||
}
|
||||
|
||||
// TODO: Make the initThemes and LoadThemes functions less confusing
|
||||
// ? - Delete themes which no longer exist in the themes folder from the database?
|
||||
func LoadThemeActiveStatus() error {
|
||||
changeDefaultThemeMutex.Lock()
|
||||
rows, err := stmts.getThemes.Query()
|
||||
func (themes ThemeList) LoadActiveStatus() error {
|
||||
getThemes, err := qgen.Builder.SimpleSelect("themes", "uname, default", "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ChangeDefaultThemeMutex.Lock()
|
||||
rows, err := getThemes.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -103,8 +110,8 @@ func LoadThemeActiveStatus() error {
|
||||
if defaultThemeSwitch {
|
||||
log.Print("Loading the default theme '" + theme.Name + "'")
|
||||
theme.Active = true
|
||||
defaultThemeBox.Store(theme.Name)
|
||||
mapThemeTemplates(theme)
|
||||
DefaultThemeBox.Store(theme.Name)
|
||||
MapThemeTemplates(theme)
|
||||
} else {
|
||||
log.Print("Loading the theme '" + theme.Name + "'")
|
||||
theme.Active = false
|
||||
@ -112,11 +119,11 @@ func LoadThemeActiveStatus() error {
|
||||
|
||||
themes[uname] = theme
|
||||
}
|
||||
changeDefaultThemeMutex.Unlock()
|
||||
ChangeDefaultThemeMutex.Unlock()
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func initThemes() error {
|
||||
func InitThemes() error {
|
||||
themeFiles, err := ioutil.ReadDir("./themes")
|
||||
if err != nil {
|
||||
return err
|
||||
@ -156,10 +163,10 @@ func initThemes() error {
|
||||
}
|
||||
|
||||
if theme.FullImage != "" {
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Adding theme image")
|
||||
}
|
||||
err = addStaticFile("./themes/"+themeName+"/"+theme.FullImage, "./themes/"+themeName)
|
||||
err = StaticFiles.Add("./themes/"+themeName+"/"+theme.FullImage, "./themes/"+themeName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -170,7 +177,7 @@ func initThemes() error {
|
||||
if theme.Templates != nil {
|
||||
for _, themeTmpl := range theme.Templates {
|
||||
theme.TemplatesMap[themeTmpl.Name] = themeTmpl.Source
|
||||
theme.TmplPtr[themeTmpl.Name] = tmplPtrMap["o_"+themeTmpl.Source]
|
||||
theme.TmplPtr[themeTmpl.Name] = TmplPtrMap["o_"+themeTmpl.Source]
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,20 +185,20 @@ func initThemes() error {
|
||||
template.Must(theme.ResourceTemplates.ParseGlob("./themes/" + theme.Name + "/public/*.css"))
|
||||
|
||||
// It should be safe for us to load the files for all the themes in memory, as-long as the admin hasn't setup a ridiculous number of themes
|
||||
err = addThemeStaticFiles(theme)
|
||||
err = AddThemeStaticFiles(theme)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
themes[theme.Name] = theme
|
||||
Themes[theme.Name] = theme
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addThemeStaticFiles(theme Theme) error {
|
||||
func AddThemeStaticFiles(theme Theme) error {
|
||||
// TODO: Use a function instead of a closure to make this more testable? What about a function call inside the closure to take the theme variable into account?
|
||||
return filepath.Walk("./themes/"+theme.Name+"/public", func(path string, f os.FileInfo, err error) error {
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Attempting to add static file '" + path + "' for default theme '" + theme.Name + "'")
|
||||
}
|
||||
if err != nil {
|
||||
@ -224,16 +231,16 @@ func addThemeStaticFiles(theme Theme) error {
|
||||
|
||||
path = strings.TrimPrefix(path, "themes/"+theme.Name+"/public")
|
||||
gzipData := compressBytesGzip(data)
|
||||
staticFiles["/static/"+theme.Name+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}
|
||||
StaticFiles["/static/"+theme.Name+path] = SFile{data, gzipData, 0, int64(len(data)), int64(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)}
|
||||
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("Added the '/" + theme.Name + path + "' static file for theme " + theme.Name + ".")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func mapThemeTemplates(theme Theme) {
|
||||
func MapThemeTemplates(theme Theme) {
|
||||
if theme.Templates != nil {
|
||||
for _, themeTmpl := range theme.Templates {
|
||||
if themeTmpl.Name == "" {
|
||||
@ -245,11 +252,11 @@ func mapThemeTemplates(theme Theme) {
|
||||
|
||||
// `go generate` is one possibility for letting plugins inject custom page structs, but it would simply add another step of compilation. It might be simpler than the current build process from the perspective of the administrator?
|
||||
|
||||
destTmplPtr, ok := tmplPtrMap[themeTmpl.Name]
|
||||
destTmplPtr, ok := TmplPtrMap[themeTmpl.Name]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
sourceTmplPtr, ok := tmplPtrMap[themeTmpl.Source]
|
||||
sourceTmplPtr, ok := TmplPtrMap[themeTmpl.Source]
|
||||
if !ok {
|
||||
log.Fatal("The source template doesn't exist!")
|
||||
}
|
||||
@ -325,20 +332,20 @@ func mapThemeTemplates(theme Theme) {
|
||||
}
|
||||
}
|
||||
|
||||
func resetTemplateOverrides() {
|
||||
func ResetTemplateOverrides() {
|
||||
log.Print("Resetting the template overrides")
|
||||
|
||||
for name := range overridenTemplates {
|
||||
log.Print("Resetting '" + name + "' template override")
|
||||
|
||||
originPointer, ok := tmplPtrMap["o_"+name]
|
||||
originPointer, ok := TmplPtrMap["o_"+name]
|
||||
if !ok {
|
||||
//log.Fatal("The origin template doesn't exist!")
|
||||
log.Print("The origin template doesn't exist!")
|
||||
return
|
||||
}
|
||||
|
||||
destTmplPtr, ok := tmplPtrMap[name]
|
||||
destTmplPtr, ok := TmplPtrMap[name]
|
||||
if !ok {
|
||||
//log.Fatal("The destination template doesn't exist!")
|
||||
log.Print("The destination template doesn't exist!")
|
||||
@ -447,11 +454,11 @@ func RunThemeTemplate(theme string, template string, pi interface{}, w http.Resp
|
||||
case func(Page, http.ResponseWriter) error:
|
||||
return tmplO(pi.(Page), w)
|
||||
case string:
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap[template]
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap[template]
|
||||
if !ok {
|
||||
mapping = template
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
default:
|
||||
log.Print("theme ", theme)
|
||||
log.Print("template ", template)
|
||||
@ -474,11 +481,11 @@ func RunThemeTemplate(theme string, template string, pi interface{}, w http.Resp
|
||||
|
||||
// GetThemeTemplate attempts to get the template for a specific theme, otherwise it falls back on the default template pointer, which if absent will fallback onto the template interpreter
|
||||
func GetThemeTemplate(theme string, template string) interface{} {
|
||||
tmpl, ok := themes[theme].TmplPtr[template]
|
||||
tmpl, ok := Themes[theme].TmplPtr[template]
|
||||
if ok {
|
||||
return tmpl
|
||||
}
|
||||
tmpl, ok = tmplPtrMap[template]
|
||||
tmpl, ok = TmplPtrMap[template]
|
||||
if ok {
|
||||
return tmpl
|
||||
}
|
||||
@ -487,19 +494,19 @@ func GetThemeTemplate(theme string, template string) interface{} {
|
||||
|
||||
// CreateThemeTemplate creates a theme template on the current default theme
|
||||
func CreateThemeTemplate(theme string, name string) {
|
||||
themes[theme].TmplPtr[name] = func(pi Page, w http.ResponseWriter) error {
|
||||
mapping, ok := themes[defaultThemeBox.Load().(string)].TemplatesMap[name]
|
||||
Themes[theme].TmplPtr[name] = func(pi Page, w http.ResponseWriter) error {
|
||||
mapping, ok := Themes[DefaultThemeBox.Load().(string)].TemplatesMap[name]
|
||||
if !ok {
|
||||
mapping = name
|
||||
}
|
||||
return templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
return Templates.ExecuteTemplate(w, mapping+".html", pi)
|
||||
}
|
||||
}
|
||||
|
||||
func GetDefaultThemeName() string {
|
||||
return defaultThemeBox.Load().(string)
|
||||
return DefaultThemeBox.Load().(string)
|
||||
}
|
||||
|
||||
func SetDefaultThemeName(name string) {
|
||||
defaultThemeBox.Store(name)
|
||||
DefaultThemeBox.Store(name)
|
||||
}
|
||||
|
116
common/topic.go
116
common/topic.go
@ -6,12 +6,14 @@
|
||||
*/
|
||||
package common
|
||||
|
||||
//import "fmt"
|
||||
import (
|
||||
"database/sql"
|
||||
"html"
|
||||
"html/template"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
// This is also in reply.go
|
||||
@ -105,10 +107,49 @@ type TopicsRow struct {
|
||||
ForumLink string
|
||||
}
|
||||
|
||||
type TopicStmts struct {
|
||||
addRepliesToTopic *sql.Stmt
|
||||
lock *sql.Stmt
|
||||
unlock *sql.Stmt
|
||||
stick *sql.Stmt
|
||||
unstick *sql.Stmt
|
||||
hasLikedTopic *sql.Stmt
|
||||
createLike *sql.Stmt
|
||||
addLikesToTopic *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
edit *sql.Stmt
|
||||
createActionReply *sql.Stmt
|
||||
|
||||
getTopicUser *sql.Stmt // TODO: Can we get rid of this?
|
||||
}
|
||||
|
||||
var topicStmts TopicStmts
|
||||
|
||||
func init() {
|
||||
DbInits.Add(func() error {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
topicStmts = TopicStmts{
|
||||
addRepliesToTopic: acc.SimpleUpdate("topics", "postCount = postCount + ?, lastReplyBy = ?, lastReplyAt = UTC_TIMESTAMP()", "tid = ?"),
|
||||
lock: acc.SimpleUpdate("topics", "is_closed = 1", "tid = ?"),
|
||||
unlock: acc.SimpleUpdate("topics", "is_closed = 0", "tid = ?"),
|
||||
stick: acc.SimpleUpdate("topics", "sticky = 1", "tid = ?"),
|
||||
unstick: acc.SimpleUpdate("topics", "sticky = 0", "tid = ?"),
|
||||
hasLikedTopic: acc.SimpleSelect("likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'topics'", "", ""),
|
||||
createLike: acc.SimpleInsert("likes", "weight, targetItem, targetType, sentBy", "?,?,?,?"),
|
||||
addLikesToTopic: acc.SimpleUpdate("topics", "likeCount = likeCount + ?", "tid = ?"),
|
||||
delete: acc.SimpleDelete("topics", "tid = ?"),
|
||||
edit: acc.SimpleUpdate("topics", "title = ?, content = ?, parsed_content = ?", "tid = ?"),
|
||||
createActionReply: acc.SimpleInsert("replies", "tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''"),
|
||||
getTopicUser: acc.SimpleLeftJoin("topics", "users", "topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level", "topics.createdBy = users.uid", "tid = ?", "", ""),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}
|
||||
|
||||
// Flush the topic out of the cache
|
||||
// ? - We do a CacheRemove() here instead of mutating the pointer to avoid creating a race condition
|
||||
func (topic *Topic) cacheRemove() {
|
||||
tcache, ok := topics.(TopicCache)
|
||||
tcache, ok := Topics.(TopicCache)
|
||||
if ok {
|
||||
tcache.CacheRemove(topic.ID)
|
||||
}
|
||||
@ -116,32 +157,32 @@ func (topic *Topic) cacheRemove() {
|
||||
|
||||
// TODO: Write a test for this
|
||||
func (topic *Topic) AddReply(uid int) (err error) {
|
||||
_, err = stmts.addRepliesToTopic.Exec(1, uid, topic.ID)
|
||||
_, err = topicStmts.addRepliesToTopic.Exec(1, uid, topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (topic *Topic) Lock() (err error) {
|
||||
_, err = stmts.lockTopic.Exec(topic.ID)
|
||||
_, err = topicStmts.lock.Exec(topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (topic *Topic) Unlock() (err error) {
|
||||
_, err = stmts.unlockTopic.Exec(topic.ID)
|
||||
_, err = topicStmts.unlock.Exec(topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: We might want more consistent terminology rather than using stick in some places and pin in others. If you don't understand the difference, there is none, they are one and the same.
|
||||
func (topic *Topic) Stick() (err error) {
|
||||
_, err = stmts.stickTopic.Exec(topic.ID)
|
||||
_, err = topicStmts.stick.Exec(topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (topic *Topic) Unstick() (err error) {
|
||||
_, err = stmts.unstickTopic.Exec(topic.ID)
|
||||
_, err = topicStmts.unstick.Exec(topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
@ -150,19 +191,19 @@ func (topic *Topic) Unstick() (err error) {
|
||||
// TODO: Use a transaction for this
|
||||
func (topic *Topic) Like(score int, uid int) (err error) {
|
||||
var tid int // Unused
|
||||
err = stmts.hasLikedTopic.QueryRow(uid, topic.ID).Scan(&tid)
|
||||
err = topicStmts.hasLikedTopic.QueryRow(uid, topic.ID).Scan(&tid)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return err
|
||||
} else if err != ErrNoRows {
|
||||
return ErrAlreadyLiked
|
||||
}
|
||||
|
||||
_, err = stmts.createLike.Exec(score, tid, "topics", uid)
|
||||
_, err = topicStmts.createLike.Exec(score, tid, "topics", uid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = stmts.addLikesToTopic.Exec(1, tid)
|
||||
_, err = topicStmts.addLikesToTopic.Exec(1, tid)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
@ -174,10 +215,10 @@ func (topic *Topic) Unlike(uid int) error {
|
||||
|
||||
// TODO: Use a transaction here
|
||||
func (topic *Topic) Delete() error {
|
||||
topicCreator, err := users.Get(topic.CreatedBy)
|
||||
topicCreator, err := Users.Get(topic.CreatedBy)
|
||||
if err == nil {
|
||||
wcount := wordCount(topic.Content)
|
||||
err = topicCreator.decreasePostStats(wcount, true)
|
||||
wcount := WordCount(topic.Content)
|
||||
err = topicCreator.DecreasePostStats(wcount, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -185,31 +226,31 @@ func (topic *Topic) Delete() error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = fstore.RemoveTopic(topic.ParentID)
|
||||
err = Fstore.RemoveTopic(topic.ParentID)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = stmts.deleteTopic.Exec(topic.ID)
|
||||
_, err = topicStmts.delete.Exec(topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (topic *Topic) Update(name string, content string) error {
|
||||
content = preparseMessage(content)
|
||||
parsed_content := parseMessage(html.EscapeString(content), topic.ParentID, "forums")
|
||||
|
||||
_, err := stmts.editTopic.Exec(name, content, parsed_content, topic.ID)
|
||||
content = PreparseMessage(content)
|
||||
parsedContent := ParseMessage(html.EscapeString(content), topic.ParentID, "forums")
|
||||
_, err := topicStmts.edit.Exec(name, content, parsedContent, topic.ID)
|
||||
topic.cacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Have this go through the ReplyStore?
|
||||
func (topic *Topic) CreateActionReply(action string, ipaddress string, user User) (err error) {
|
||||
_, err = stmts.createActionReply.Exec(topic.ID, action, ipaddress, user.ID)
|
||||
_, err = topicStmts.createActionReply.Exec(topic.ID, action, ipaddress, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmts.addRepliesToTopic.Exec(1, user.ID, topic.ID)
|
||||
_, err = topicStmts.addRepliesToTopic.Exec(1, user.ID, topic.ID)
|
||||
topic.cacheRemove()
|
||||
// ? - Update the last topic cache for the parent forum?
|
||||
return err
|
||||
@ -221,13 +262,13 @@ func (topic *Topic) Copy() Topic {
|
||||
}
|
||||
|
||||
// TODO: Refactor the caller to take a Topic and a User rather than a combined TopicUser
|
||||
func getTopicUser(tid int) (TopicUser, error) {
|
||||
tcache, tok := topics.(TopicCache)
|
||||
ucache, uok := users.(UserCache)
|
||||
func GetTopicUser(tid int) (TopicUser, error) {
|
||||
tcache, tok := Topics.(TopicCache)
|
||||
ucache, uok := Users.(UserCache)
|
||||
if tok && uok {
|
||||
topic, err := tcache.CacheGet(tid)
|
||||
if err == nil {
|
||||
user, err := users.Get(topic.CreatedBy)
|
||||
user, err := Users.Get(topic.CreatedBy)
|
||||
if err != nil {
|
||||
return TopicUser{ID: tid}, err
|
||||
}
|
||||
@ -235,11 +276,11 @@ func getTopicUser(tid int) (TopicUser, error) {
|
||||
// We might be better off just passing separate topic and user structs to the caller?
|
||||
return copyTopicToTopicUser(topic, user), nil
|
||||
} else if ucache.Length() < ucache.GetCapacity() {
|
||||
topic, err = topics.Get(tid)
|
||||
topic, err = Topics.Get(tid)
|
||||
if err != nil {
|
||||
return TopicUser{ID: tid}, err
|
||||
}
|
||||
user, err := users.Get(topic.CreatedBy)
|
||||
user, err := Users.Get(topic.CreatedBy)
|
||||
if err != nil {
|
||||
return TopicUser{ID: tid}, err
|
||||
}
|
||||
@ -248,14 +289,14 @@ func getTopicUser(tid int) (TopicUser, error) {
|
||||
}
|
||||
|
||||
tu := TopicUser{ID: tid}
|
||||
err := stmts.getTopicUser.QueryRow(tid).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
|
||||
tu.Link = buildTopicURL(nameToSlug(tu.Title), tu.ID)
|
||||
tu.UserLink = buildProfileURL(nameToSlug(tu.CreatedByName), tu.CreatedBy)
|
||||
tu.Tag = gstore.DirtyGet(tu.Group).Tag
|
||||
err := topicStmts.getTopicUser.QueryRow(tid).Scan(&tu.Title, &tu.Content, &tu.CreatedBy, &tu.CreatedAt, &tu.IsClosed, &tu.Sticky, &tu.ParentID, &tu.IPAddress, &tu.PostCount, &tu.LikeCount, &tu.CreatedByName, &tu.Avatar, &tu.Group, &tu.URLPrefix, &tu.URLName, &tu.Level)
|
||||
tu.Link = BuildTopicURL(NameToSlug(tu.Title), tu.ID)
|
||||
tu.UserLink = BuildProfileURL(NameToSlug(tu.CreatedByName), tu.CreatedBy)
|
||||
tu.Tag = Gstore.DirtyGet(tu.Group).Tag
|
||||
|
||||
if tok {
|
||||
theTopic := Topic{ID: tu.ID, Link: tu.Link, Title: tu.Title, Content: tu.Content, CreatedBy: tu.CreatedBy, IsClosed: tu.IsClosed, Sticky: tu.Sticky, CreatedAt: tu.CreatedAt, LastReplyAt: tu.LastReplyAt, ParentID: tu.ParentID, IPAddress: tu.IPAddress, PostCount: tu.PostCount, LikeCount: tu.LikeCount}
|
||||
//log.Printf("the_topic: %+v\n", theTopic)
|
||||
//log.Printf("theTopic: %+v\n", theTopic)
|
||||
_ = tcache.CacheAdd(&theTopic)
|
||||
}
|
||||
return tu, err
|
||||
@ -289,18 +330,11 @@ func copyTopicToTopicUser(topic *Topic, user *User) (tu TopicUser) {
|
||||
}
|
||||
|
||||
// For use in tests and for generating blank topics for forums which don't have a last poster
|
||||
func getDummyTopic() *Topic {
|
||||
func BlankTopic() *Topic {
|
||||
return &Topic{ID: 0, Title: ""}
|
||||
}
|
||||
|
||||
func getTopicByReply(rid int) (*Topic, error) {
|
||||
topic := Topic{ID: 0}
|
||||
err := stmts.getTopicByReply.QueryRow(rid).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
topic.Link = buildTopicURL(nameToSlug(topic.Title), topic.ID)
|
||||
return &topic, err
|
||||
}
|
||||
|
||||
func buildTopicURL(slug string, tid int) string {
|
||||
func BuildTopicURL(slug string, tid int) string {
|
||||
if slug == "" {
|
||||
return "/topic/" + strconv.Itoa(tid)
|
||||
}
|
||||
|
@ -20,11 +20,12 @@ import (
|
||||
// TODO: Add BulkGetMap
|
||||
// TODO: Add some sort of update method
|
||||
// ? - Should we add stick, lock, unstick, and unlock methods? These might be better on the Topics not the TopicStore
|
||||
var topics TopicStore
|
||||
var Topics TopicStore
|
||||
var ErrNoTitle = errors.New("This message is missing a title")
|
||||
var ErrNoBody = errors.New("This message is missing a body")
|
||||
|
||||
type TopicStore interface {
|
||||
DirtyGet(id int) *Topic
|
||||
Get(id int) (*Topic, error)
|
||||
BypassGet(id int) (*Topic, error)
|
||||
Exists(id int) bool
|
||||
@ -93,6 +94,24 @@ func (mts *MemoryTopicStore) CacheGetUnsafe(id int) (*Topic, error) {
|
||||
return item, ErrNoRows
|
||||
}
|
||||
|
||||
func (mts *MemoryTopicStore) DirtyGet(id int) *Topic {
|
||||
mts.RLock()
|
||||
topic, ok := mts.items[id]
|
||||
mts.RUnlock()
|
||||
if ok {
|
||||
return topic
|
||||
}
|
||||
|
||||
topic = &Topic{ID: id}
|
||||
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
if err == nil {
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
_ = mts.CacheAdd(topic)
|
||||
return topic
|
||||
}
|
||||
return BlankTopic()
|
||||
}
|
||||
|
||||
func (mts *MemoryTopicStore) Get(id int) (*Topic, error) {
|
||||
mts.RLock()
|
||||
topic, ok := mts.items[id]
|
||||
@ -104,7 +123,7 @@ func (mts *MemoryTopicStore) Get(id int) (*Topic, error) {
|
||||
topic = &Topic{ID: id}
|
||||
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
if err == nil {
|
||||
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
_ = mts.CacheAdd(topic)
|
||||
}
|
||||
return topic, err
|
||||
@ -114,7 +133,7 @@ func (mts *MemoryTopicStore) Get(id int) (*Topic, error) {
|
||||
func (mts *MemoryTopicStore) BypassGet(id int) (*Topic, error) {
|
||||
topic := &Topic{ID: id}
|
||||
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
return topic, err
|
||||
}
|
||||
|
||||
@ -122,7 +141,7 @@ func (mts *MemoryTopicStore) Reload(id int) error {
|
||||
topic := &Topic{ID: id}
|
||||
err := mts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
if err == nil {
|
||||
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
_ = mts.CacheSet(topic)
|
||||
} else {
|
||||
_ = mts.CacheRemove(id)
|
||||
@ -141,12 +160,12 @@ func (mts *MemoryTopicStore) Create(fid int, topicName string, content string, u
|
||||
}
|
||||
|
||||
content = strings.TrimSpace(content)
|
||||
parsedContent := parseMessage(content, fid, "forums")
|
||||
parsedContent := ParseMessage(content, fid, "forums")
|
||||
if strings.TrimSpace(parsedContent) == "" {
|
||||
return 0, ErrNoBody
|
||||
}
|
||||
|
||||
wcount := wordCount(content)
|
||||
wcount := WordCount(content)
|
||||
// TODO: Move this statement into the topic store
|
||||
res, err := mts.create.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid)
|
||||
if err != nil {
|
||||
@ -158,8 +177,7 @@ func (mts *MemoryTopicStore) Create(fid int, topicName string, content string, u
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = fstore.AddTopic(int(lastID), uid, fid)
|
||||
return int(lastID), err
|
||||
return int(lastID), Fstore.AddTopic(int(lastID), uid, fid)
|
||||
}
|
||||
|
||||
func (mts *MemoryTopicStore) CacheSet(item *Topic) error {
|
||||
@ -268,10 +286,20 @@ func NewSQLTopicStore() (*SQLTopicStore, error) {
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (sts *SQLTopicStore) DirtyGet(id int) *Topic {
|
||||
topic := &Topic{ID: id}
|
||||
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
if err != nil {
|
||||
return BlankTopic()
|
||||
}
|
||||
return topic
|
||||
}
|
||||
|
||||
func (sts *SQLTopicStore) Get(id int) (*Topic, error) {
|
||||
topic := Topic{ID: id}
|
||||
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
return &topic, err
|
||||
}
|
||||
|
||||
@ -279,7 +307,7 @@ func (sts *SQLTopicStore) Get(id int) (*Topic, error) {
|
||||
func (sts *SQLTopicStore) BypassGet(id int) (*Topic, error) {
|
||||
topic := &Topic{ID: id}
|
||||
err := sts.get.QueryRow(id).Scan(&topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.LastReplyAt, &topic.IsClosed, &topic.Sticky, &topic.ParentID, &topic.IPAddress, &topic.PostCount, &topic.LikeCount, &topic.Data)
|
||||
topic.Link = buildTopicURL(nameToSlug(topic.Title), id)
|
||||
topic.Link = BuildTopicURL(NameToSlug(topic.Title), id)
|
||||
return topic, err
|
||||
}
|
||||
|
||||
@ -294,12 +322,12 @@ func (sts *SQLTopicStore) Create(fid int, topicName string, content string, uid
|
||||
}
|
||||
|
||||
content = strings.TrimSpace(content)
|
||||
parsedContent := parseMessage(content, fid, "forums")
|
||||
parsedContent := ParseMessage(content, fid, "forums")
|
||||
if strings.TrimSpace(parsedContent) == "" {
|
||||
return 0, ErrNoBody
|
||||
}
|
||||
|
||||
wcount := wordCount(content)
|
||||
wcount := WordCount(content)
|
||||
// TODO: Move this statement into the topic store
|
||||
res, err := sts.create.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid)
|
||||
if err != nil {
|
||||
@ -311,8 +339,7 @@ func (sts *SQLTopicStore) Create(fid int, topicName string, content string, uid
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = fstore.AddTopic(int(lastID), uid, fid)
|
||||
return int(lastID), err
|
||||
return int(lastID), Fstore.AddTopic(int(lastID), uid, fid)
|
||||
}
|
||||
|
||||
// ? - What're we going to do about this?
|
||||
|
183
common/user.go
183
common/user.go
@ -15,12 +15,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"../query_gen/lib"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// TODO: Replace any literals with this
|
||||
var BanGroup = 4
|
||||
|
||||
// GuestUser is an instance of user which holds guest data to avoid having to initialise a guest every time
|
||||
var GuestUser = User{ID: 0, Link: "#", Group: 6, Perms: GuestPerms}
|
||||
|
||||
//func(real_password string, password string, salt string) (err error)
|
||||
@ -57,12 +59,48 @@ type User struct {
|
||||
TempGroup int
|
||||
}
|
||||
|
||||
type Email struct {
|
||||
UserID int
|
||||
Email string
|
||||
Validated bool
|
||||
Primary bool
|
||||
Token string
|
||||
type UserStmts struct {
|
||||
activate *sql.Stmt
|
||||
changeGroup *sql.Stmt
|
||||
delete *sql.Stmt
|
||||
setAvatar *sql.Stmt
|
||||
setUsername *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
incrementTopics *sql.Stmt
|
||||
updateLevel *sql.Stmt
|
||||
incrementScore *sql.Stmt
|
||||
incrementPosts *sql.Stmt
|
||||
incrementBigposts *sql.Stmt
|
||||
incrementMegaposts *sql.Stmt
|
||||
updateLastIP *sql.Stmt
|
||||
|
||||
setPassword *sql.Stmt
|
||||
}
|
||||
|
||||
var userStmts UserStmts
|
||||
|
||||
func init() {
|
||||
DbInits.Add(func() error {
|
||||
acc := qgen.Builder.Accumulator()
|
||||
userStmts = UserStmts{
|
||||
activate: acc.SimpleUpdate("users", "active = 1", "uid = ?"),
|
||||
changeGroup: acc.SimpleUpdate("users", "group = ?", "uid = ?"),
|
||||
delete: acc.SimpleDelete("users", "uid = ?"),
|
||||
setAvatar: acc.SimpleUpdate("users", "avatar = ?", "uid = ?"),
|
||||
setUsername: acc.SimpleUpdate("users", "name = ?", "uid = ?"),
|
||||
updateGroup: acc.SimpleUpdate("users", "group = ?", "uid = ?"),
|
||||
incrementTopics: acc.SimpleUpdate("users", "topics = topics + ?", "uid = ?"),
|
||||
updateLevel: acc.SimpleUpdate("users", "level = ?", "uid = ?"),
|
||||
incrementScore: acc.SimpleUpdate("users", "score = score + ?", "uid = ?"),
|
||||
incrementPosts: acc.SimpleUpdate("users", "posts = posts + ?", "uid = ?"),
|
||||
incrementBigposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?"),
|
||||
incrementMegaposts: acc.SimpleUpdate("users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?"),
|
||||
updateLastIP: acc.SimpleUpdate("users", "last_ip = ?", "uid = ?"),
|
||||
|
||||
setPassword: acc.SimpleUpdate("users", "password = ?, salt = ?", "uid = ?"),
|
||||
}
|
||||
return acc.FirstError()
|
||||
})
|
||||
}
|
||||
|
||||
func (user *User) Init() {
|
||||
@ -71,15 +109,22 @@ func (user *User) Init() {
|
||||
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
|
||||
}
|
||||
} else {
|
||||
user.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(user.ID), 1)
|
||||
user.Avatar = strings.Replace(Config.Noavatar, "{id}", strconv.Itoa(user.ID), 1)
|
||||
}
|
||||
user.Link = BuildProfileURL(NameToSlug(user.Name), user.ID)
|
||||
user.Tag = Gstore.DirtyGet(user.Group).Tag
|
||||
user.InitPerms()
|
||||
}
|
||||
|
||||
func (user *User) CacheRemove() {
|
||||
ucache, ok := Users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
user.Link = buildProfileURL(nameToSlug(user.Name), user.ID)
|
||||
user.Tag = gstore.DirtyGet(user.Group).Tag
|
||||
user.initPerms()
|
||||
}
|
||||
|
||||
func (user *User) Ban(duration time.Duration, issuedBy int) error {
|
||||
return user.ScheduleGroupUpdate(banGroup, issuedBy, duration)
|
||||
return user.ScheduleGroupUpdate(BanGroup, issuedBy, duration)
|
||||
}
|
||||
|
||||
func (user *User) Unban() error {
|
||||
@ -112,7 +157,7 @@ func (user *User) ScheduleGroupUpdate(gid int, issuedBy int, duration time.Durat
|
||||
}
|
||||
revertAt := time.Now().Add(duration)
|
||||
|
||||
tx, err := db.Begin()
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -138,15 +183,12 @@ func (user *User) ScheduleGroupUpdate(gid int, issuedBy int, duration time.Durat
|
||||
}
|
||||
err = tx.Commit()
|
||||
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) RevertGroupUpdate() error {
|
||||
tx, err := db.Begin()
|
||||
tx, err := qgen.Builder.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -163,25 +205,19 @@ func (user *User) RevertGroupUpdate() error {
|
||||
}
|
||||
err = tx.Commit()
|
||||
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Use a transaction here
|
||||
// ? - Add a Deactivate method? Not really needed, if someone's been bad you could do a ban, I guess it might be useful, if someone says that email x isn't actually owned by the user in question?
|
||||
func (user *User) Activate() (err error) {
|
||||
_, err = stmts.activateUser.Exec(user.ID)
|
||||
_, err = userStmts.activate.Exec(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmts.changeGroup.Exec(config.DefaultGroup, user.ID)
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
_, err = userStmts.changeGroup.Exec(Config.DefaultGroup, user.ID)
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
@ -189,111 +225,105 @@ func (user *User) Activate() (err error) {
|
||||
// TODO: Delete this user's content too?
|
||||
// TODO: Expose this to the admin?
|
||||
func (user *User) Delete() error {
|
||||
_, err := stmts.deleteUser.Exec(user.ID)
|
||||
_, err := userStmts.delete.Exec(user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) ChangeName(username string) (err error) {
|
||||
_, err = stmts.setUsername.Exec(username, user.ID)
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
_, err = userStmts.setUsername.Exec(username, user.ID)
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) ChangeAvatar(avatar string) (err error) {
|
||||
_, err = stmts.setAvatar.Exec(avatar, user.ID)
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
_, err = userStmts.setAvatar.Exec(avatar, user.ID)
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) ChangeGroup(group int) (err error) {
|
||||
_, err = stmts.updateUserGroup.Exec(group, user.ID)
|
||||
ucache, ok := users.(UserCache)
|
||||
if ok {
|
||||
ucache.CacheRemove(user.ID)
|
||||
}
|
||||
_, err = userStmts.updateGroup.Exec(group, user.ID)
|
||||
user.CacheRemove()
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) increasePostStats(wcount int, topic bool) (err error) {
|
||||
// ! Only updates the database not the *User for safety reasons
|
||||
func (user *User) UpdateIP(host string) error {
|
||||
_, err := userStmts.updateLastIP.Exec(host, user.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) IncreasePostStats(wcount int, topic bool) (err error) {
|
||||
var mod int
|
||||
baseScore := 1
|
||||
if topic {
|
||||
_, err = stmts.incrementUserTopics.Exec(1, user.ID)
|
||||
_, err = userStmts.incrementTopics.Exec(1, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
baseScore = 2
|
||||
}
|
||||
|
||||
settings := settingBox.Load().(SettingBox)
|
||||
settings := SettingBox.Load().(SettingMap)
|
||||
if wcount >= settings["megapost_min_words"].(int) {
|
||||
_, err = stmts.incrementUserMegaposts.Exec(1, 1, 1, user.ID)
|
||||
_, err = userStmts.incrementMegaposts.Exec(1, 1, 1, user.ID)
|
||||
mod = 4
|
||||
} else if wcount >= settings["bigpost_min_words"].(int) {
|
||||
_, err = stmts.incrementUserBigposts.Exec(1, 1, user.ID)
|
||||
_, err = userStmts.incrementBigposts.Exec(1, 1, user.ID)
|
||||
mod = 1
|
||||
} else {
|
||||
_, err = stmts.incrementUserPosts.Exec(1, user.ID)
|
||||
_, err = userStmts.incrementPosts.Exec(1, user.ID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = stmts.incrementUserScore.Exec(baseScore+mod, user.ID)
|
||||
_, err = userStmts.incrementScore.Exec(baseScore+mod, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//log.Print(user.Score + base_score + mod)
|
||||
//log.Print(getLevel(user.Score + base_score + mod))
|
||||
// TODO: Use a transaction to prevent level desyncs?
|
||||
_, err = stmts.updateUserLevel.Exec(getLevel(user.Score+baseScore+mod), user.ID)
|
||||
_, err = userStmts.updateLevel.Exec(GetLevel(user.Score+baseScore+mod), user.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (user *User) decreasePostStats(wcount int, topic bool) (err error) {
|
||||
func (user *User) DecreasePostStats(wcount int, topic bool) (err error) {
|
||||
var mod int
|
||||
baseScore := -1
|
||||
if topic {
|
||||
_, err = stmts.incrementUserTopics.Exec(-1, user.ID)
|
||||
_, err = userStmts.incrementTopics.Exec(-1, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
baseScore = -2
|
||||
}
|
||||
|
||||
settings := settingBox.Load().(SettingBox)
|
||||
settings := SettingBox.Load().(SettingMap)
|
||||
if wcount >= settings["megapost_min_words"].(int) {
|
||||
_, err = stmts.incrementUserMegaposts.Exec(-1, -1, -1, user.ID)
|
||||
_, err = userStmts.incrementMegaposts.Exec(-1, -1, -1, user.ID)
|
||||
mod = 4
|
||||
} else if wcount >= settings["bigpost_min_words"].(int) {
|
||||
_, err = stmts.incrementUserBigposts.Exec(-1, -1, user.ID)
|
||||
_, err = userStmts.incrementBigposts.Exec(-1, -1, user.ID)
|
||||
mod = 1
|
||||
} else {
|
||||
_, err = stmts.incrementUserPosts.Exec(-1, user.ID)
|
||||
_, err = userStmts.incrementPosts.Exec(-1, user.ID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = stmts.incrementUserScore.Exec(baseScore-mod, user.ID)
|
||||
_, err = userStmts.incrementScore.Exec(baseScore-mod, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: Use a transaction to prevent level desyncs?
|
||||
_, err = stmts.updateUserLevel.Exec(getLevel(user.Score-baseScore-mod), user.ID)
|
||||
_, err = userStmts.updateLevel.Exec(GetLevel(user.Score-baseScore-mod), user.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -303,12 +333,12 @@ func (user *User) Copy() User {
|
||||
}
|
||||
|
||||
// TODO: Write unit tests for this
|
||||
func (user *User) initPerms() {
|
||||
func (user *User) InitPerms() {
|
||||
if user.TempGroup != 0 {
|
||||
user.Group = user.TempGroup
|
||||
}
|
||||
|
||||
group := gstore.DirtyGet(user.Group)
|
||||
group := Gstore.DirtyGet(user.Group)
|
||||
if user.IsSuperAdmin {
|
||||
user.Perms = AllPerms
|
||||
user.PluginPerms = AllPluginPerms
|
||||
@ -332,7 +362,7 @@ func BcryptCheckPassword(realPassword string, password string, salt string) (err
|
||||
|
||||
// Investigate. Do we need the extra salt?
|
||||
func BcryptGeneratePassword(password string) (hashedPassword string, salt string, err error) {
|
||||
salt, err = GenerateSafeString(saltLength)
|
||||
salt, err = GenerateSafeString(SaltLength)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
@ -353,27 +383,16 @@ func BcryptGeneratePasswordNoSalt(password string) (hash string, err error) {
|
||||
return string(hashedPassword), nil
|
||||
}
|
||||
|
||||
// TODO: Move this to *User
|
||||
func SetPassword(uid int, password string) error {
|
||||
hashedPassword, salt, err := GeneratePassword(password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = stmts.setPassword.Exec(hashedPassword, salt, uid)
|
||||
_, err = userStmts.setPassword.Exec(hashedPassword, salt, uid)
|
||||
return err
|
||||
}
|
||||
|
||||
func SendValidationEmail(username string, email string, token string) bool {
|
||||
var schema = "http"
|
||||
if site.EnableSsl {
|
||||
schema += "s"
|
||||
}
|
||||
|
||||
// TODO: Move these to the phrase system
|
||||
subject := "Validate Your Email @ " + site.Name
|
||||
msg := "Dear " + username + ", following your registration on our forums, we ask you to validate your email, so that we can confirm that this email actually belongs to you.\n\nClick on the following link to do so. " + schema + "://" + site.URL + "/user/edit/token/" + token + "\n\nIf you haven't created an account here, then please feel free to ignore this email.\nWe're sorry for the inconvenience this may have caused."
|
||||
return SendEmail(email, subject, msg)
|
||||
}
|
||||
|
||||
// TODO: Write units tests for this
|
||||
func wordsToScore(wcount int, topic bool) (score int) {
|
||||
if topic {
|
||||
@ -382,7 +401,7 @@ func wordsToScore(wcount int, topic bool) (score int) {
|
||||
score = 1
|
||||
}
|
||||
|
||||
settings := settingBox.Load().(SettingBox)
|
||||
settings := SettingBox.Load().(SettingMap)
|
||||
if wcount >= settings["megapost_min_words"].(int) {
|
||||
score += 4
|
||||
} else if wcount >= settings["bigpost_min_words"].(int) {
|
||||
@ -392,12 +411,12 @@ func wordsToScore(wcount int, topic bool) (score int) {
|
||||
}
|
||||
|
||||
// For use in tests and to help generate dummy users for forums which don't have last posters
|
||||
func getDummyUser() *User {
|
||||
func BlankUser() *User {
|
||||
return &User{ID: 0, Name: ""}
|
||||
}
|
||||
|
||||
// TODO: Write unit tests for this
|
||||
func buildProfileURL(slug string, uid int) string {
|
||||
func BuildProfileURL(slug string, uid int) string {
|
||||
if slug == "" {
|
||||
return "/user/" + strconv.Itoa(uid)
|
||||
}
|
||||
|
@ -8,15 +8,17 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"../query_gen/lib"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// TODO: Add the watchdog goroutine
|
||||
// TODO: Add some sort of update method
|
||||
var users UserStore
|
||||
var errAccountExists = errors.New("this username is already in use")
|
||||
var Users UserStore
|
||||
var ErrAccountExists = errors.New("this username is already in use")
|
||||
|
||||
type UserStore interface {
|
||||
DirtyGet(id int) *User
|
||||
Get(id int) (*User, error)
|
||||
Exists(id int) bool
|
||||
//BulkGet(ids []int) ([]*User, error)
|
||||
@ -86,6 +88,25 @@ func (mus *MemoryUserStore) CacheGetUnsafe(id int) (*User, error) {
|
||||
return item, ErrNoRows
|
||||
}
|
||||
|
||||
func (mus *MemoryUserStore) DirtyGet(id int) *User {
|
||||
mus.RLock()
|
||||
user, ok := mus.items[id]
|
||||
mus.RUnlock()
|
||||
if ok {
|
||||
return user
|
||||
}
|
||||
|
||||
user = &User{ID: id, Loggedin: true}
|
||||
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
||||
|
||||
user.Init()
|
||||
if err == nil {
|
||||
mus.CacheSet(user)
|
||||
return user
|
||||
}
|
||||
return BlankUser()
|
||||
}
|
||||
|
||||
func (mus *MemoryUserStore) Get(id int) (*User, error) {
|
||||
mus.RLock()
|
||||
user, ok := mus.items[id]
|
||||
@ -188,7 +209,7 @@ func (mus *MemoryUserStore) BulkGetMap(ids []int) (list map[int]*User, err error
|
||||
|
||||
// We probably don't need this, but it might be useful in case of bugs in BulkCascadeGetMap
|
||||
if sidList == "" {
|
||||
if dev.DebugMode {
|
||||
if Dev.DebugMode {
|
||||
log.Print("This data is sampled later in the BulkCascadeGetMap function, so it might miss the cached IDs")
|
||||
log.Print("idCount", idCount)
|
||||
log.Print("ids", ids)
|
||||
@ -298,10 +319,10 @@ func (mus *MemoryUserStore) Create(username string, password string, email strin
|
||||
// Is this username already taken..?
|
||||
err := mus.usernameExists.QueryRow(username).Scan(&username)
|
||||
if err != ErrNoRows {
|
||||
return 0, errAccountExists
|
||||
return 0, ErrAccountExists
|
||||
}
|
||||
|
||||
salt, err := GenerateSafeString(saltLength)
|
||||
salt, err := GenerateSafeString(SaltLength)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -370,6 +391,17 @@ func NewSQLUserStore() (*SQLUserStore, error) {
|
||||
}, acc.FirstError()
|
||||
}
|
||||
|
||||
func (mus *SQLUserStore) DirtyGet(id int) *User {
|
||||
user := &User{ID: id, Loggedin: true}
|
||||
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
||||
|
||||
user.Init()
|
||||
if err != nil {
|
||||
return BlankUser()
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
func (mus *SQLUserStore) Get(id int) (*User, error) {
|
||||
user := &User{ID: id, Loggedin: true}
|
||||
err := mus.get.QueryRow(id).Scan(&user.Name, &user.Group, &user.IsSuperAdmin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score, &user.LastIP, &user.TempGroup)
|
||||
@ -436,10 +468,10 @@ func (mus *SQLUserStore) Create(username string, password string, email string,
|
||||
// Is this username already taken..?
|
||||
err := mus.usernameExists.QueryRow(username).Scan(&username)
|
||||
if err != ErrNoRows {
|
||||
return 0, errAccountExists
|
||||
return 0, ErrAccountExists
|
||||
}
|
||||
|
||||
salt, err := GenerateSafeString(saltLength)
|
||||
salt, err := GenerateSafeString(SaltLength)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
127
common/utils.go
127
common/utils.go
@ -12,12 +12,13 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/smtp"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"../query_gen/lib"
|
||||
)
|
||||
|
||||
// Version stores a Gosora version
|
||||
@ -53,7 +54,7 @@ func GenerateSafeString(length int) (string, error) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func relativeTimeFromString(in string) (string, error) {
|
||||
func RelativeTimeFromString(in string) (string, error) {
|
||||
if in == "" {
|
||||
return "", nil
|
||||
}
|
||||
@ -63,11 +64,11 @@ func relativeTimeFromString(in string) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return relativeTime(t), nil
|
||||
return RelativeTime(t), nil
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func relativeTime(t time.Time) string {
|
||||
func RelativeTime(t time.Time) string {
|
||||
diff := time.Since(t)
|
||||
hours := diff.Hours()
|
||||
seconds := diff.Seconds()
|
||||
@ -105,36 +106,36 @@ func relativeTime(t time.Time) string {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func convertByteUnit(bytes float64) (float64, string) {
|
||||
func ConvertByteUnit(bytes float64) (float64, string) {
|
||||
switch {
|
||||
case bytes >= float64(petabyte):
|
||||
return bytes / float64(petabyte), "PB"
|
||||
case bytes >= float64(terabyte):
|
||||
return bytes / float64(terabyte), "TB"
|
||||
case bytes >= float64(gigabyte):
|
||||
return bytes / float64(gigabyte), "GB"
|
||||
case bytes >= float64(megabyte):
|
||||
return bytes / float64(megabyte), "MB"
|
||||
case bytes >= float64(kilobyte):
|
||||
return bytes / float64(kilobyte), "KB"
|
||||
case bytes >= float64(Petabyte):
|
||||
return bytes / float64(Petabyte), "PB"
|
||||
case bytes >= float64(Terabyte):
|
||||
return bytes / float64(Terabyte), "TB"
|
||||
case bytes >= float64(Gigabyte):
|
||||
return bytes / float64(Gigabyte), "GB"
|
||||
case bytes >= float64(Megabyte):
|
||||
return bytes / float64(Megabyte), "MB"
|
||||
case bytes >= float64(Kilobyte):
|
||||
return bytes / float64(Kilobyte), "KB"
|
||||
default:
|
||||
return bytes, " bytes"
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func convertByteInUnit(bytes float64, unit string) (count float64) {
|
||||
func ConvertByteInUnit(bytes float64, unit string) (count float64) {
|
||||
switch unit {
|
||||
case "PB":
|
||||
count = bytes / float64(petabyte)
|
||||
count = bytes / float64(Petabyte)
|
||||
case "TB":
|
||||
count = bytes / float64(terabyte)
|
||||
count = bytes / float64(Terabyte)
|
||||
case "GB":
|
||||
count = bytes / float64(gigabyte)
|
||||
count = bytes / float64(Gigabyte)
|
||||
case "MB":
|
||||
count = bytes / float64(megabyte)
|
||||
count = bytes / float64(Megabyte)
|
||||
case "KB":
|
||||
count = bytes / float64(kilobyte)
|
||||
count = bytes / float64(Kilobyte)
|
||||
default:
|
||||
count = 0.1
|
||||
}
|
||||
@ -146,7 +147,7 @@ func convertByteInUnit(bytes float64, unit string) (count float64) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func convertUnit(num int) (int, string) {
|
||||
func ConvertUnit(num int) (int, string) {
|
||||
switch {
|
||||
case num >= 1000000000000:
|
||||
return num / 1000000000000, "T"
|
||||
@ -162,7 +163,7 @@ func convertUnit(num int) (int, string) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func convertFriendlyUnit(num int) (int, string) {
|
||||
func ConvertFriendlyUnit(num int) (int, string) {
|
||||
switch {
|
||||
case num >= 1000000000000000:
|
||||
return 0, " quadrillion"
|
||||
@ -179,7 +180,7 @@ func convertFriendlyUnit(num int) (int, string) {
|
||||
}
|
||||
}
|
||||
|
||||
func nameToSlug(name string) (slug string) {
|
||||
func NameToSlug(name string) (slug string) {
|
||||
name = strings.TrimSpace(name)
|
||||
name = strings.Replace(name, " ", " ", -1)
|
||||
|
||||
@ -199,58 +200,8 @@ func nameToSlug(name string) (slug string) {
|
||||
return slug
|
||||
}
|
||||
|
||||
// TODO: Refactor this
|
||||
func SendEmail(email string, subject string, msg string) bool {
|
||||
// This hook is useful for plugin_sendmail or for testing tools. Possibly to hook it into some sort of mail server?
|
||||
if vhooks["email_send_intercept"] != nil {
|
||||
return vhooks["email_send_intercept"](email, subject, msg).(bool)
|
||||
}
|
||||
body := "Subject: " + subject + "\n\n" + msg + "\n"
|
||||
|
||||
con, err := smtp.Dial(config.SMTPServer + ":" + config.SMTPPort)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if config.SMTPUsername != "" {
|
||||
auth := smtp.PlainAuth("", config.SMTPUsername, config.SMTPPassword, config.SMTPServer)
|
||||
err = con.Auth(auth)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
err = con.Mail(site.Email)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
err = con.Rcpt(email)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
emailData, err := con.Data()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = fmt.Fprintf(emailData, body)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
err = emailData.Close()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
err = con.Quit()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func weakPassword(password string) error {
|
||||
func WeakPassword(password string) error {
|
||||
if len(password) < 8 {
|
||||
return errors.New("your password needs to be at-least eight characters long")
|
||||
}
|
||||
@ -335,7 +286,7 @@ func Stripslashes(text string) string {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func wordCount(input string) (count int) {
|
||||
func WordCount(input string) (count int) {
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "" {
|
||||
return 0
|
||||
@ -355,7 +306,7 @@ func wordCount(input string) (count int) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func getLevel(score int) (level int) {
|
||||
func GetLevel(score int) (level int) {
|
||||
var base float64 = 25
|
||||
var current, prev float64
|
||||
var expFactor = 2.8
|
||||
@ -376,7 +327,7 @@ func getLevel(score int) (level int) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func getLevelScore(getLevel int) (score int) {
|
||||
func GetLevelScore(getLevel int) (score int) {
|
||||
var base float64 = 25
|
||||
var current, prev float64
|
||||
var level int
|
||||
@ -398,7 +349,7 @@ func getLevelScore(getLevel int) (score int) {
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func getLevels(maxLevel int) []float64 {
|
||||
func GetLevels(maxLevel int) []float64 {
|
||||
var base float64 = 25
|
||||
var current, prev float64 // = 0
|
||||
var expFactor = 2.8
|
||||
@ -417,7 +368,7 @@ func getLevels(maxLevel int) []float64 {
|
||||
return out
|
||||
}
|
||||
|
||||
func buildSlug(slug string, id int) string {
|
||||
func BuildSlug(slug string, id int) string {
|
||||
if slug == "" {
|
||||
return strconv.Itoa(id)
|
||||
}
|
||||
@ -425,13 +376,21 @@ func buildSlug(slug string, id int) string {
|
||||
}
|
||||
|
||||
// TODO: Make a store for this?
|
||||
func addModLog(action string, elementID int, elementType string, ipaddress string, actorID int) (err error) {
|
||||
_, err = stmts.addModlogEntry.Exec(action, elementID, elementType, ipaddress, actorID)
|
||||
func AddModLog(action string, elementID int, elementType string, ipaddress string, actorID int) (err error) {
|
||||
addModLogEntry, err := qgen.Builder.SimpleInsert("moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addModLogEntry.Exec(action, elementID, elementType, ipaddress, actorID)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Make a store for this?
|
||||
func addAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) (err error) {
|
||||
_, err = stmts.addAdminlogEntry.Exec(action, elementID, elementType, ipaddress, actorID)
|
||||
func AddAdminLog(action string, elementID string, elementType int, ipaddress string, actorID int) (err error) {
|
||||
addAdminLogEntry, err := qgen.Builder.SimpleInsert("administration_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = addAdminLogEntry.Exec(action, elementID, elementType, ipaddress, actorID)
|
||||
return err
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
/* Copyright Azareal 2017 - 2018 */
|
||||
package main
|
||||
package common
|
||||
|
||||
import "log"
|
||||
import "bytes"
|
||||
import "sync"
|
||||
import "encoding/json"
|
||||
import "../query_gen/lib"
|
||||
|
||||
//import "html/template"
|
||||
|
||||
var docks WidgetDocks
|
||||
var Docks WidgetDocks
|
||||
var widgetUpdateMutex sync.RWMutex
|
||||
|
||||
type WidgetDocks struct {
|
||||
@ -41,8 +40,12 @@ type NameTextPair struct {
|
||||
}
|
||||
|
||||
// TODO: Make a store for this?
|
||||
func initWidgets() error {
|
||||
rows, err := stmts.getWidgets.Query()
|
||||
func InitWidgets() error {
|
||||
getWidgets, err := qgen.Builder.SimpleSelect("widgets", "position, side, type, active, location, data", "", "position ASC", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := getWidgets.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -71,7 +74,7 @@ func initWidgets() error {
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
err = templates.ExecuteTemplate(&b, "widget_simple.html", tmp)
|
||||
err = Templates.ExecuteTemplate(&b, "widget_simple.html", tmp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -92,13 +95,13 @@ func initWidgets() error {
|
||||
}
|
||||
|
||||
widgetUpdateMutex.Lock()
|
||||
docks.LeftSidebar = leftWidgets
|
||||
docks.RightSidebar = rightWidgets
|
||||
Docks.LeftSidebar = leftWidgets
|
||||
Docks.RightSidebar = rightWidgets
|
||||
widgetUpdateMutex.Unlock()
|
||||
|
||||
if dev.SuperDebug {
|
||||
log.Print("docks.LeftSidebar", docks.LeftSidebar)
|
||||
log.Print("docks.RightSidebar", docks.RightSidebar)
|
||||
if Dev.SuperDebug {
|
||||
log.Print("Docks.LeftSidebar", Docks.LeftSidebar)
|
||||
log.Print("Docks.RightSidebar", Docks.RightSidebar)
|
||||
}
|
||||
|
||||
return nil
|
50
common/word_filters.go
Normal file
50
common/word_filters.go
Normal file
@ -0,0 +1,50 @@
|
||||
package common
|
||||
|
||||
import "sync/atomic"
|
||||
import "../query_gen/lib"
|
||||
|
||||
type WordFilter struct {
|
||||
ID int
|
||||
Find string
|
||||
Replacement string
|
||||
}
|
||||
type WordFilterMap map[int]WordFilter
|
||||
|
||||
var WordFilterBox atomic.Value // An atomic value holding a WordFilterBox
|
||||
|
||||
func init() {
|
||||
WordFilterBox.Store(WordFilterMap(make(map[int]WordFilter)))
|
||||
}
|
||||
|
||||
func LoadWordFilters() error {
|
||||
getWordFilters, err := qgen.Builder.SimpleSelect("word_filters", "wfid, find, replacement", "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rows, err := getWordFilters.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var wordFilters = WordFilterMap(make(map[int]WordFilter))
|
||||
var wfid int
|
||||
var find string
|
||||
var replacement string
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&wfid, &find, &replacement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wordFilters[wfid] = WordFilter{ID: wfid, Find: find, Replacement: replacement}
|
||||
}
|
||||
WordFilterBox.Store(wordFilters)
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func AddWordFilter(id int, find string, replacement string) {
|
||||
wordFilters := WordFilterBox.Load().(WordFilterMap)
|
||||
wordFilters[id] = WordFilter{ID: id, Find: find, Replacement: replacement}
|
||||
WordFilterBox.Store(wordFilters)
|
||||
}
|
66
database.go
66
database.go
@ -1,8 +1,11 @@
|
||||
package main
|
||||
|
||||
import "log"
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
import "database/sql"
|
||||
"./common"
|
||||
)
|
||||
|
||||
var stmts *Stmts
|
||||
|
||||
@ -15,7 +18,7 @@ var ErrNoRows = sql.ErrNoRows
|
||||
|
||||
var _initDatabase func() error
|
||||
|
||||
func initDatabase() (err error) {
|
||||
func InitDatabase() (err error) {
|
||||
stmts = &Stmts{Mocks: false}
|
||||
|
||||
// Engine specific code
|
||||
@ -25,70 +28,69 @@ func initDatabase() (err error) {
|
||||
}
|
||||
globs = &Globs{stmts}
|
||||
|
||||
log.Print("Loading the usergroups.")
|
||||
gstore, err = NewMemoryGroupStore()
|
||||
err = common.DbInits.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = gstore.LoadGroups()
|
||||
|
||||
log.Print("Loading the usergroups.")
|
||||
common.Gstore, err = common.NewMemoryGroupStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err2 := common.Gstore.LoadGroups()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
// We have to put this here, otherwise LoadForums() won't be able to get the last poster data when building it's forums
|
||||
log.Print("Initialising the user and topic stores")
|
||||
if config.CacheTopicUser == CACHE_STATIC {
|
||||
users, err = NewMemoryUserStore(config.UserCacheCapacity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
topics, err = NewMemoryTopicStore(config.TopicCacheCapacity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if common.Config.CacheTopicUser == common.CACHE_STATIC {
|
||||
common.Users, err = common.NewMemoryUserStore(common.Config.UserCacheCapacity)
|
||||
common.Topics, err2 = common.NewMemoryTopicStore(common.Config.TopicCacheCapacity)
|
||||
} else {
|
||||
users, err = NewSQLUserStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
topics, err = NewSQLTopicStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
common.Users, err = common.NewSQLUserStore()
|
||||
common.Topics, err2 = common.NewSQLTopicStore()
|
||||
}
|
||||
|
||||
log.Print("Loading the forums.")
|
||||
fstore, err = NewMemoryForumStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = fstore.LoadForums()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
log.Print("Loading the forums.")
|
||||
common.Fstore, err = common.NewMemoryForumStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = common.Fstore.LoadForums()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Loading the forum permissions.")
|
||||
fpstore, err = NewMemoryForumPermsStore()
|
||||
common.Fpstore, err = common.NewMemoryForumPermsStore()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = fpstore.Init()
|
||||
err = common.Fpstore.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Loading the settings.")
|
||||
err = LoadSettings()
|
||||
err = common.LoadSettings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Loading the plugins.")
|
||||
err = initExtend()
|
||||
err = common.InitExtend()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Loading the themes.")
|
||||
return LoadThemeActiveStatus()
|
||||
return common.Themes.LoadActiveStatus()
|
||||
}
|
||||
|
@ -14,6 +14,9 @@ import (
|
||||
"../../../common"
|
||||
)
|
||||
|
||||
// A blank list to fill out that parameter in Page for routes which don't use it
|
||||
var tList []interface{}
|
||||
|
||||
var ListStmt *sql.Stmt
|
||||
var MemberListStmt *sql.Stmt
|
||||
var MemberListJoinStmt *sql.Stmt
|
||||
@ -45,15 +48,15 @@ type Guild struct {
|
||||
MainForumID int
|
||||
MainForum *common.Forum
|
||||
Forums []*common.Forum
|
||||
ExtData ExtData
|
||||
ExtData common.ExtData
|
||||
}
|
||||
|
||||
type Page struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
CurrentUser common.User
|
||||
Header *common.HeaderVars
|
||||
ItemList []*TopicsRow
|
||||
Forum *commmon.Forum
|
||||
ItemList []*common.TopicsRow
|
||||
Forum *common.Forum
|
||||
Guild *Guild
|
||||
Page int
|
||||
LastPage int
|
||||
@ -62,16 +65,16 @@ type Page struct {
|
||||
// ListPage is a page struct for constructing a list of every guild
|
||||
type ListPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
Header *HeaderVars
|
||||
CurrentUser common.User
|
||||
Header *common.HeaderVars
|
||||
GuildList []*Guild
|
||||
}
|
||||
|
||||
type MemberListPage struct {
|
||||
Title string
|
||||
CurrentUser User
|
||||
Header *HeaderVars
|
||||
ItemList []GuildMember
|
||||
CurrentUser common.User
|
||||
Header *common.HeaderVars
|
||||
ItemList []Member
|
||||
Guild *Guild
|
||||
Page int
|
||||
LastPage int
|
||||
@ -86,15 +89,15 @@ type Member struct {
|
||||
JoinedAt string
|
||||
Offline bool // TODO: Need to track the online states of members when WebSockets are enabled
|
||||
|
||||
User User
|
||||
User common.User
|
||||
}
|
||||
|
||||
func PrebuildTmplList(user *User, headerVars *HeaderVars) CTmpl {
|
||||
func PrebuildTmplList(user common.User, headerVars *common.HeaderVars) common.CTmpl {
|
||||
var guildList = []*Guild{
|
||||
&Guild{
|
||||
ID: 1,
|
||||
Name: "lol",
|
||||
Link: guildsBuildGuildURL(nameToSlug("lol"), 1),
|
||||
Link: BuildGuildURL(common.NameToSlug("lol"), 1),
|
||||
Desc: "A group for people who like to laugh",
|
||||
Active: true,
|
||||
MemberCount: 1,
|
||||
@ -102,38 +105,38 @@ func PrebuildTmplList(user *User, headerVars *HeaderVars) CTmpl {
|
||||
CreatedAt: "date",
|
||||
LastUpdateTime: "date",
|
||||
MainForumID: 1,
|
||||
MainForum: fstore.DirtyGet(1),
|
||||
Forums: []*Forum{fstore.DirtyGet(1)},
|
||||
MainForum: common.Fstore.DirtyGet(1),
|
||||
Forums: []*common.Forum{common.Fstore.DirtyGet(1)},
|
||||
},
|
||||
}
|
||||
listPage := ListPage{"Guild List", user, headerVars, guildList}
|
||||
return CTmpl{"guilds-guild-list", "guilds_guild_list", "templates/", "guilds.ListPage", listPage}
|
||||
return common.CTmpl{"guilds-guild-list", "guilds_guild_list", "templates/", "guilds.ListPage", listPage}
|
||||
}
|
||||
|
||||
// TODO: Do this properly via the widget system
|
||||
func CommonAreaWidgets(headerVars *HeaderVars) {
|
||||
func CommonAreaWidgets(headerVars *common.HeaderVars) {
|
||||
// TODO: Hot Groups? Featured Groups? Official Groups?
|
||||
var b bytes.Buffer
|
||||
var menu = WidgetMenu{"Guilds", []WidgetMenuItem{
|
||||
WidgetMenuItem{"Create Guild", "/guild/create/", false},
|
||||
var menu = common.WidgetMenu{"Guilds", []common.WidgetMenuItem{
|
||||
common.WidgetMenuItem{"Create Guild", "/guild/create/", false},
|
||||
}}
|
||||
|
||||
err := templates.ExecuteTemplate(&b, "widget_menu.html", menu)
|
||||
err := common.Templates.ExecuteTemplate(&b, "widget_menu.html", menu)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
common.LogError(err)
|
||||
return
|
||||
}
|
||||
|
||||
if themes[headerVars.ThemeName].Sidebars == "left" {
|
||||
if common.Themes[headerVars.ThemeName].Sidebars == "left" {
|
||||
headerVars.Widgets.LeftSidebar = template.HTML(string(b.Bytes()))
|
||||
} else if themes[headerVars.ThemeName].Sidebars == "right" || themes[headerVars.ThemeName].Sidebars == "both" {
|
||||
} else if common.Themes[headerVars.ThemeName].Sidebars == "right" || common.Themes[headerVars.ThemeName].Sidebars == "both" {
|
||||
headerVars.Widgets.RightSidebar = template.HTML(string(b.Bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Do this properly via the widget system
|
||||
// TODO: Make a better more customisable group widget system
|
||||
func GuildWidgets(headerVars *HeaderVars, guildItem *Guild) (success bool) {
|
||||
func GuildWidgets(headerVars *common.HeaderVars, guildItem *Guild) (success bool) {
|
||||
return false // Disabled until the next commit
|
||||
|
||||
/*var b bytes.Buffer
|
||||
@ -144,7 +147,7 @@ func GuildWidgets(headerVars *HeaderVars, guildItem *Guild) (success bool) {
|
||||
|
||||
err := templates.ExecuteTemplate(&b, "widget_menu.html", menu)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
common.LogError(err)
|
||||
return false
|
||||
}
|
||||
|
||||
@ -162,16 +165,16 @@ func GuildWidgets(headerVars *HeaderVars, guildItem *Guild) (success bool) {
|
||||
Custom Pages
|
||||
*/
|
||||
|
||||
func routeGuildList(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
headerVars, ferr := UserCheck(w, r, &user)
|
||||
func RouteGuildList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, ferr := common.UserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
guildsCommonAreaWidgets(headerVars)
|
||||
CommonAreaWidgets(headerVars)
|
||||
|
||||
rows, err := guildsListStmt.Query()
|
||||
if err != nil && err != ErrNoRows {
|
||||
return InternalError(err, w, r)
|
||||
rows, err := ListStmt.Query()
|
||||
if err != nil && err != common.ErrNoRows {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
@ -180,31 +183,31 @@ func routeGuildList(w http.ResponseWriter, r *http.Request, user User) RouteErro
|
||||
guildItem := &Guild{ID: 0}
|
||||
err := rows.Scan(&guildItem.ID, &guildItem.Name, &guildItem.Desc, &guildItem.Active, &guildItem.Privacy, &guildItem.Joinable, &guildItem.Owner, &guildItem.MemberCount, &guildItem.CreatedAt, &guildItem.LastUpdateTime)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
guildItem.Link = guildsBuildGuildURL(nameToSlug(guildItem.Name), guildItem.ID)
|
||||
guildItem.Link = BuildGuildURL(common.NameToSlug(guildItem.Name), guildItem.ID)
|
||||
guildList = append(guildList, guildItem)
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
pi := GuildListPage{"Guild List", user, headerVars, guildList}
|
||||
err = RunThemeTemplate(headerVars.ThemeName, "guilds_guild_list", pi, w)
|
||||
pi := ListPage{"Guild List", user, headerVars, guildList}
|
||||
err = common.RunThemeTemplate(headerVars.ThemeName, "guilds_guild_list", pi, w)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetGuild(guildID int) (guildItem *Guild, err error) {
|
||||
guildItem = &Guild{ID: guildID}
|
||||
err = guildsGetGuildStmt.QueryRow(guildID).Scan(&guildItem.Name, &guildItem.Desc, &guildItem.Active, &guildItem.Privacy, &guildItem.Joinable, &guildItem.Owner, &guildItem.MemberCount, &guildItem.MainForumID, &guildItem.Backdrop, &guildItem.CreatedAt, &guildItem.LastUpdateTime)
|
||||
err = GetGuildStmt.QueryRow(guildID).Scan(&guildItem.Name, &guildItem.Desc, &guildItem.Active, &guildItem.Privacy, &guildItem.Joinable, &guildItem.Owner, &guildItem.MemberCount, &guildItem.MainForumID, &guildItem.Backdrop, &guildItem.CreatedAt, &guildItem.LastUpdateTime)
|
||||
return guildItem, err
|
||||
}
|
||||
|
||||
func middleViewGuild(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func MiddleViewGuild(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
// SEO URLs...
|
||||
halves := strings.Split(r.URL.Path[len("/guild/"):], ".")
|
||||
if len(halves) < 2 {
|
||||
@ -212,45 +215,48 @@ func middleViewGuild(w http.ResponseWriter, r *http.Request, user User) RouteErr
|
||||
}
|
||||
guildID, err := strconv.Atoi(halves[1])
|
||||
if err != nil {
|
||||
return PreError("Not a valid guild ID", w, r)
|
||||
return common.PreError("Not a valid guild ID", w, r)
|
||||
}
|
||||
|
||||
guildItem, err := guildsGetGuild(guildID)
|
||||
guildItem, err := GetGuild(guildID)
|
||||
if err != nil {
|
||||
return LocalError("Bad guild", w, r, user)
|
||||
return common.LocalError("Bad guild", w, r, user)
|
||||
}
|
||||
if !guildItem.Active {
|
||||
return NotFound(w, r)
|
||||
return common.NotFound(w, r)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
// TODO: Re-implement this
|
||||
// Re-route the request to routeForums
|
||||
var ctx = context.WithValue(r.Context(), "guilds_current_guild", guildItem)
|
||||
return routeForum(w, r.WithContext(ctx), user, strconv.Itoa(guildItem.MainForumID))
|
||||
//var ctx = context.WithValue(r.Context(), "guilds_current_guild", guildItem)
|
||||
//return routeForum(w, r.WithContext(ctx), user, strconv.Itoa(guildItem.MainForumID))
|
||||
}
|
||||
|
||||
func CreateGuild(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
headerVars, ferr := UserCheck(w, r, &user)
|
||||
func RouteCreateGuild(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, ferr := common.UserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
// TODO: Add an approval queue mode for group creation
|
||||
if !user.Loggedin || !user.PluginPerms["CreateGuild"] {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
guildsCommonAreaWidgets(headerVars)
|
||||
CommonAreaWidgets(headerVars)
|
||||
|
||||
pi := Page{"Create Guild", user, headerVars, tList, nil}
|
||||
err := templates.ExecuteTemplate(w, "guilds_create_guild.html", pi)
|
||||
pi := common.Page{"Create Guild", user, headerVars, tList, nil}
|
||||
err := common.Templates.ExecuteTemplate(w, "guilds_create_guild.html", pi)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateGuildSubmit(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func RouteCreateGuildSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
// TODO: Add an approval queue mode for group creation
|
||||
if !user.Loggedin || !user.PluginPerms["CreateGuild"] {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
var guildActive = true
|
||||
@ -271,37 +277,37 @@ func CreateGuildSubmit(w http.ResponseWriter, r *http.Request, user User) RouteE
|
||||
}
|
||||
|
||||
// Create the backing forum
|
||||
fid, err := fstore.Create(guildName, "", true, "")
|
||||
fid, err := common.Fstore.Create(guildName, "", true, "")
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
res, err := guildsCreateGuildStmt.Exec(guildName, guildDesc, guildActive, guildPrivacy, user.ID, fid)
|
||||
res, err := CreateGuildStmt.Exec(guildName, guildDesc, guildActive, guildPrivacy, user.ID, fid)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
lastID, err := res.LastInsertId()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// Add the main backing forum to the forum list
|
||||
err = guildsAttachForum(int(lastID), fid)
|
||||
err = AttachForum(int(lastID), fid)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
_, err = guildsAddMemberStmt.Exec(lastID, user.ID, 2)
|
||||
_, err = AddMemberStmt.Exec(lastID, user.ID, 2)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, guildsBuildGuildURL(nameToSlug(guildName), int(lastID)), http.StatusSeeOther)
|
||||
http.Redirect(w, r, BuildGuildURL(common.NameToSlug(guildName), int(lastID)), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func MemberList(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
headerVars, ferr := UserCheck(w, r, &user)
|
||||
func RouteMemberList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
headerVars, ferr := common.UserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
@ -313,40 +319,40 @@ func MemberList(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
}
|
||||
guildID, err := strconv.Atoi(halves[1])
|
||||
if err != nil {
|
||||
return PreError("Not a valid group ID", w, r)
|
||||
return common.PreError("Not a valid group ID", w, r)
|
||||
}
|
||||
|
||||
var guildItem = &Guild{ID: guildID}
|
||||
var mainForum int // Unused
|
||||
err = guildsGetGuildStmt.QueryRow(guildID).Scan(&guildItem.Name, &guildItem.Desc, &guildItem.Active, &guildItem.Privacy, &guildItem.Joinable, &guildItem.Owner, &guildItem.MemberCount, &mainForum, &guildItem.Backdrop, &guildItem.CreatedAt, &guildItem.LastUpdateTime)
|
||||
err = GetGuildStmt.QueryRow(guildID).Scan(&guildItem.Name, &guildItem.Desc, &guildItem.Active, &guildItem.Privacy, &guildItem.Joinable, &guildItem.Owner, &guildItem.MemberCount, &mainForum, &guildItem.Backdrop, &guildItem.CreatedAt, &guildItem.LastUpdateTime)
|
||||
if err != nil {
|
||||
return LocalError("Bad group", w, r, user)
|
||||
return common.LocalError("Bad group", w, r, user)
|
||||
}
|
||||
guildItem.Link = guildsBuildGuildURL(nameToSlug(guildItem.Name), guildItem.ID)
|
||||
guildItem.Link = BuildGuildURL(common.NameToSlug(guildItem.Name), guildItem.ID)
|
||||
|
||||
guildsGuildWidgets(headerVars, guildItem)
|
||||
GuildWidgets(headerVars, guildItem)
|
||||
|
||||
rows, err := guildsMemberListJoinStmt.Query(guildID)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return InternalError(err, w, r)
|
||||
rows, err := MemberListJoinStmt.Query(guildID)
|
||||
if err != nil && err != common.ErrNoRows {
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
var guildMembers []GuildMember
|
||||
var guildMembers []Member
|
||||
for rows.Next() {
|
||||
guildMember := GuildMember{PostCount: 0}
|
||||
guildMember := Member{PostCount: 0}
|
||||
err := rows.Scan(&guildMember.User.ID, &guildMember.Rank, &guildMember.PostCount, &guildMember.JoinedAt, &guildMember.User.Name, &guildMember.User.Avatar)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
guildMember.Link = buildProfileURL(nameToSlug(guildMember.User.Name), guildMember.User.ID)
|
||||
guildMember.Link = common.BuildProfileURL(common.NameToSlug(guildMember.User.Name), guildMember.User.ID)
|
||||
if guildMember.User.Avatar != "" {
|
||||
if guildMember.User.Avatar[0] == '.' {
|
||||
guildMember.User.Avatar = "/uploads/avatar_" + strconv.Itoa(guildMember.User.ID) + guildMember.User.Avatar
|
||||
}
|
||||
} else {
|
||||
guildMember.User.Avatar = strings.Replace(config.Noavatar, "{id}", strconv.Itoa(guildMember.User.ID), 1)
|
||||
guildMember.User.Avatar = strings.Replace(common.Config.Noavatar, "{id}", strconv.Itoa(guildMember.User.ID), 1)
|
||||
}
|
||||
guildMember.JoinedAt, _ = relativeTimeFromString(guildMember.JoinedAt)
|
||||
guildMember.JoinedAt, _ = common.RelativeTimeFromString(guildMember.JoinedAt)
|
||||
if guildItem.Owner == guildMember.User.ID {
|
||||
guildMember.RankString = "Owner"
|
||||
} else {
|
||||
@ -363,31 +369,31 @@ func MemberList(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
pi := GuildMemberListPage{"Guild Member List", user, headerVars, guildMembers, guildItem, 0, 0}
|
||||
pi := MemberListPage{"Guild Member List", user, headerVars, guildMembers, guildItem, 0, 0}
|
||||
// A plugin with plugins. Pluginception!
|
||||
if preRenderHooks["pre_render_guilds_member_list"] != nil {
|
||||
if runPreRenderHook("pre_render_guilds_member_list", w, r, &user, &pi) {
|
||||
if common.PreRenderHooks["pre_render_guilds_member_list"] != nil {
|
||||
if common.RunPreRenderHook("pre_render_guilds_member_list", w, r, &user, &pi) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err = RunThemeTemplate(headerVars.ThemeName, "guilds_member_list", pi, w)
|
||||
err = common.RunThemeTemplate(headerVars.ThemeName, "guilds_member_list", pi, w)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func AttachForum(guildID int, fid int) error {
|
||||
_, err := guildsAttachForumStmt.Exec(guildID, fid)
|
||||
_, err := AttachForumStmt.Exec(guildID, fid)
|
||||
return err
|
||||
}
|
||||
|
||||
func UnattachForum(fid int) error {
|
||||
_, err := guildsAttachForumStmt.Exec(fid)
|
||||
_, err := AttachForumStmt.Exec(fid)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -403,16 +409,16 @@ func BuildGuildURL(slug string, id int) string {
|
||||
*/
|
||||
|
||||
// TODO: Prebuild this template
|
||||
func PreRenderViewForum(w http.ResponseWriter, r *http.Request, user *User, data interface{}) (halt bool) {
|
||||
pi := data.(*ForumPage)
|
||||
if pi.Header.ExtData.items != nil {
|
||||
if guildData, ok := pi.Header.ExtData.items["guilds_current_group"]; ok {
|
||||
func PreRenderViewForum(w http.ResponseWriter, r *http.Request, user *common.User, data interface{}) (halt bool) {
|
||||
pi := data.(*common.ForumPage)
|
||||
if pi.Header.ExtData.Items != nil {
|
||||
if guildData, ok := pi.Header.ExtData.Items["guilds_current_group"]; ok {
|
||||
guildItem := guildData.(*Guild)
|
||||
|
||||
guildpi := GuildPage{pi.Title, pi.CurrentUser, pi.Header, pi.ItemList, pi.Forum, guildItem, pi.Page, pi.LastPage}
|
||||
err := templates.ExecuteTemplate(w, "guilds_view_guild.html", guildpi)
|
||||
guildpi := Page{pi.Title, pi.CurrentUser, pi.Header, pi.ItemList, pi.Forum, guildItem, pi.Page, pi.LastPage}
|
||||
err := common.Templates.ExecuteTemplate(w, "guilds_view_guild.html", guildpi)
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
common.LogError(err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@ -422,10 +428,10 @@ func PreRenderViewForum(w http.ResponseWriter, r *http.Request, user *User, data
|
||||
}
|
||||
|
||||
func TrowAssign(args ...interface{}) interface{} {
|
||||
var forum = args[1].(*Forum)
|
||||
var forum = args[1].(*common.Forum)
|
||||
if forum.ParentType == "guild" {
|
||||
var topicItem = args[0].(*TopicsRow)
|
||||
topicItem.ForumLink = "/guild/" + strings.TrimPrefix(topicItem.ForumLink, getForumURLPrefix())
|
||||
var topicItem = args[0].(*common.TopicsRow)
|
||||
topicItem.ForumLink = "/guild/" + strings.TrimPrefix(topicItem.ForumLink, common.GetForumURLPrefix())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -433,7 +439,7 @@ func TrowAssign(args ...interface{}) interface{} {
|
||||
// TODO: It would be nice, if you could select one of the boards in the group from that drop-down rather than just the one you got linked from
|
||||
func TopicCreatePreLoop(args ...interface{}) interface{} {
|
||||
var fid = args[2].(int)
|
||||
if fstore.DirtyGet(fid).ParentType == "guild" {
|
||||
if common.Fstore.DirtyGet(fid).ParentType == "guild" {
|
||||
var strictmode = args[5].(*bool)
|
||||
*strictmode = true
|
||||
}
|
||||
@ -443,27 +449,27 @@ func TopicCreatePreLoop(args ...interface{}) interface{} {
|
||||
// TODO: Add privacy options
|
||||
// TODO: Add support for multiple boards and add per-board simplified permissions
|
||||
// TODO: Take isJs into account for routes which expect JSON responses
|
||||
func ForumCheck(args ...interface{}) (skip bool, rerr RouteError) {
|
||||
func ForumCheck(args ...interface{}) (skip bool, rerr common.RouteError) {
|
||||
var r = args[1].(*http.Request)
|
||||
var fid = args[3].(*int)
|
||||
var forum = fstore.DirtyGet(*fid)
|
||||
var forum = common.Fstore.DirtyGet(*fid)
|
||||
|
||||
if forum.ParentType == "guild" {
|
||||
var err error
|
||||
var w = args[0].(http.ResponseWriter)
|
||||
guildItem, ok := r.Context().Value("guilds_current_group").(*Guild)
|
||||
if !ok {
|
||||
guildItem, err = guildsGetGuild(forum.ParentID)
|
||||
guildItem, err = GetGuild(forum.ParentID)
|
||||
if err != nil {
|
||||
return true, InternalError(errors.New("Unable to find the parent group for a forum"), w, r)
|
||||
return true, common.InternalError(errors.New("Unable to find the parent group for a forum"), w, r)
|
||||
}
|
||||
if !guildItem.Active {
|
||||
return true, NotFound(w, r)
|
||||
return true, common.NotFound(w, r)
|
||||
}
|
||||
r = r.WithContext(context.WithValue(r.Context(), "guilds_current_group", guildItem))
|
||||
}
|
||||
|
||||
var user = args[2].(*User)
|
||||
var user = args[2].(*common.User)
|
||||
var rank int
|
||||
var posts int
|
||||
var joinedAt string
|
||||
@ -472,32 +478,32 @@ func ForumCheck(args ...interface{}) (skip bool, rerr RouteError) {
|
||||
|
||||
// Clear the default group permissions
|
||||
// TODO: Do this more efficiently, doing it quick and dirty for now to get this out quickly
|
||||
overrideForumPerms(&user.Perms, false)
|
||||
common.OverrideForumPerms(&user.Perms, false)
|
||||
user.Perms.ViewTopic = true
|
||||
|
||||
err = guildsGetMemberStmt.QueryRow(guildItem.ID, user.ID).Scan(&rank, &posts, &joinedAt)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return true, InternalError(err, w, r)
|
||||
err = GetMemberStmt.QueryRow(guildItem.ID, user.ID).Scan(&rank, &posts, &joinedAt)
|
||||
if err != nil && err != common.ErrNoRows {
|
||||
return true, common.InternalError(err, w, r)
|
||||
} else if err != nil {
|
||||
// TODO: Should we let admins / guests into public groups?
|
||||
return true, LocalError("You're not part of this group!", w, r, *user)
|
||||
return true, common.LocalError("You're not part of this group!", w, r, *user)
|
||||
}
|
||||
|
||||
// TODO: Implement bans properly by adding the Local Ban API in the next commit
|
||||
// TODO: How does this even work? Refactor it along with the rest of this plugin!
|
||||
if rank < 0 {
|
||||
return true, LocalError("You've been banned from this group!", w, r, *user)
|
||||
return true, common.LocalError("You've been banned from this group!", w, r, *user)
|
||||
}
|
||||
|
||||
// Basic permissions for members, more complicated permissions coming in the next commit!
|
||||
if guildItem.Owner == user.ID {
|
||||
overrideForumPerms(&user.Perms, true)
|
||||
common.OverrideForumPerms(&user.Perms, true)
|
||||
} else if rank == 0 {
|
||||
user.Perms.LikeItem = true
|
||||
user.Perms.CreateTopic = true
|
||||
user.Perms.CreateReply = true
|
||||
} else {
|
||||
overrideForumPerms(&user.Perms, true)
|
||||
common.OverrideForumPerms(&user.Perms, true)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@ -509,28 +515,28 @@ func ForumCheck(args ...interface{}) (skip bool, rerr RouteError) {
|
||||
|
||||
func Widgets(args ...interface{}) interface{} {
|
||||
var zone = args[0].(string)
|
||||
var headerVars = args[2].(*HeaderVars)
|
||||
var headerVars = args[2].(*common.HeaderVars)
|
||||
var request = args[3].(*http.Request)
|
||||
|
||||
if zone != "view_forum" {
|
||||
return false
|
||||
}
|
||||
|
||||
var forum = args[1].(*Forum)
|
||||
var forum = args[1].(*common.Forum)
|
||||
if forum.ParentType == "guild" {
|
||||
// This is why I hate using contexts, all the daisy chains and interface casts x.x
|
||||
guildItem, ok := request.Context().Value("guilds_current_group").(*Guild)
|
||||
if !ok {
|
||||
LogError(errors.New("Unable to find a parent group in the context data"))
|
||||
common.LogError(errors.New("Unable to find a parent group in the context data"))
|
||||
return false
|
||||
}
|
||||
|
||||
if headerVars.ExtData.items == nil {
|
||||
headerVars.ExtData.items = make(map[string]interface{})
|
||||
if headerVars.ExtData.Items == nil {
|
||||
headerVars.ExtData.Items = make(map[string]interface{})
|
||||
}
|
||||
headerVars.ExtData.items["guilds_current_group"] = guildItem
|
||||
headerVars.ExtData.Items["guilds_current_group"] = guildItem
|
||||
|
||||
return guildsGuildWidgets(headerVars, guildItem)
|
||||
return GuildWidgets(headerVars, guildItem)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
363
gen_mssql.go
363
gen_mssql.go
@ -5,6 +5,7 @@ package main
|
||||
|
||||
import "log"
|
||||
import "database/sql"
|
||||
import "./common"
|
||||
|
||||
// nolint
|
||||
type Stmts struct {
|
||||
@ -12,21 +13,14 @@ type Stmts struct {
|
||||
getSettings *sql.Stmt
|
||||
getSetting *sql.Stmt
|
||||
getFullSetting *sql.Stmt
|
||||
getFullSettings *sql.Stmt
|
||||
getPlugins *sql.Stmt
|
||||
getThemes *sql.Stmt
|
||||
getWidgets *sql.Stmt
|
||||
isPluginActive *sql.Stmt
|
||||
getUsersOffset *sql.Stmt
|
||||
getWordFilters *sql.Stmt
|
||||
isThemeDefault *sql.Stmt
|
||||
getModlogs *sql.Stmt
|
||||
getModlogsOffset *sql.Stmt
|
||||
getReplyTID *sql.Stmt
|
||||
getTopicFID *sql.Stmt
|
||||
getUserReplyUID *sql.Stmt
|
||||
hasLikedTopic *sql.Stmt
|
||||
hasLikedReply *sql.Stmt
|
||||
getUserName *sql.Stmt
|
||||
getEmailsByUser *sql.Stmt
|
||||
getTopicBasic *sql.Stmt
|
||||
@ -34,20 +28,14 @@ type Stmts struct {
|
||||
forumEntryExists *sql.Stmt
|
||||
groupEntryExists *sql.Stmt
|
||||
getForumTopicsOffset *sql.Stmt
|
||||
getExpiredScheduledGroups *sql.Stmt
|
||||
getSync *sql.Stmt
|
||||
getAttachment *sql.Stmt
|
||||
getTopicRepliesOffset *sql.Stmt
|
||||
getTopicList *sql.Stmt
|
||||
getTopicUser *sql.Stmt
|
||||
getTopicByReply *sql.Stmt
|
||||
getTopicReplies *sql.Stmt
|
||||
getForumTopics *sql.Stmt
|
||||
getProfileReplies *sql.Stmt
|
||||
getWatchers *sql.Stmt
|
||||
createReport *sql.Stmt
|
||||
createActionReply *sql.Stmt
|
||||
createLike *sql.Stmt
|
||||
addActivity *sql.Stmt
|
||||
notifyOne *sql.Stmt
|
||||
addEmail *sql.Stmt
|
||||
@ -55,57 +43,27 @@ type Stmts struct {
|
||||
addForumPermsToForum *sql.Stmt
|
||||
addPlugin *sql.Stmt
|
||||
addTheme *sql.Stmt
|
||||
addModlogEntry *sql.Stmt
|
||||
addAdminlogEntry *sql.Stmt
|
||||
addAttachment *sql.Stmt
|
||||
createWordFilter *sql.Stmt
|
||||
addRepliesToTopic *sql.Stmt
|
||||
removeRepliesFromTopic *sql.Stmt
|
||||
addLikesToTopic *sql.Stmt
|
||||
addLikesToReply *sql.Stmt
|
||||
editTopic *sql.Stmt
|
||||
editReply *sql.Stmt
|
||||
stickTopic *sql.Stmt
|
||||
unstickTopic *sql.Stmt
|
||||
lockTopic *sql.Stmt
|
||||
unlockTopic *sql.Stmt
|
||||
updateLastIP *sql.Stmt
|
||||
updateSession *sql.Stmt
|
||||
setPassword *sql.Stmt
|
||||
setAvatar *sql.Stmt
|
||||
setUsername *sql.Stmt
|
||||
changeGroup *sql.Stmt
|
||||
activateUser *sql.Stmt
|
||||
updateUserLevel *sql.Stmt
|
||||
incrementUserScore *sql.Stmt
|
||||
incrementUserPosts *sql.Stmt
|
||||
incrementUserBigposts *sql.Stmt
|
||||
incrementUserMegaposts *sql.Stmt
|
||||
incrementUserTopics *sql.Stmt
|
||||
editProfileReply *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateSetting *sql.Stmt
|
||||
updatePlugin *sql.Stmt
|
||||
updatePluginInstall *sql.Stmt
|
||||
updateTheme *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateUser *sql.Stmt
|
||||
updateUserGroup *sql.Stmt
|
||||
updateGroupPerms *sql.Stmt
|
||||
updateGroupRank *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
updateEmail *sql.Stmt
|
||||
verifyEmail *sql.Stmt
|
||||
setTempGroup *sql.Stmt
|
||||
updateWordFilter *sql.Stmt
|
||||
bumpSync *sql.Stmt
|
||||
deleteUser *sql.Stmt
|
||||
deleteTopic *sql.Stmt
|
||||
deleteReply *sql.Stmt
|
||||
deleteProfileReply *sql.Stmt
|
||||
deleteActivityStreamMatch *sql.Stmt
|
||||
deleteWordFilter *sql.Stmt
|
||||
reportExists *sql.Stmt
|
||||
groupCount *sql.Stmt
|
||||
modlogCount *sql.Stmt
|
||||
notifyWatchers *sql.Stmt
|
||||
|
||||
@ -124,7 +82,7 @@ type Stmts struct {
|
||||
|
||||
// nolint
|
||||
func _gen_mssql() (err error) {
|
||||
if dev.DebugMode {
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Building the generated statements")
|
||||
}
|
||||
|
||||
@ -156,34 +114,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getFullSettings statement.")
|
||||
stmts.getFullSettings, err = db.Prepare("SELECT [name],[content],[type],[constraints] FROM [settings]")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [name],[content],[type],[constraints] FROM [settings]")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getPlugins statement.")
|
||||
stmts.getPlugins, err = db.Prepare("SELECT [uname],[active],[installed] FROM [plugins]")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [uname],[active],[installed] FROM [plugins]")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getThemes statement.")
|
||||
stmts.getThemes, err = db.Prepare("SELECT [uname],[default] FROM [themes]")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [uname],[default] FROM [themes]")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getWidgets statement.")
|
||||
stmts.getWidgets, err = db.Prepare("SELECT [position],[side],[type],[active],[location],[data] FROM [widgets] ORDER BY position ASC")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [position],[side],[type],[active],[location],[data] FROM [widgets] ORDER BY position ASC")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing isPluginActive statement.")
|
||||
stmts.isPluginActive, err = db.Prepare("SELECT [active] FROM [plugins] WHERE [uname] = ?1")
|
||||
if err != nil {
|
||||
@ -198,13 +128,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getWordFilters statement.")
|
||||
stmts.getWordFilters, err = db.Prepare("SELECT [wfid],[find],[replacement] FROM [word_filters]")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [wfid],[find],[replacement] FROM [word_filters]")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing isThemeDefault statement.")
|
||||
stmts.isThemeDefault, err = db.Prepare("SELECT [default] FROM [themes] WHERE [uname] = ?1")
|
||||
if err != nil {
|
||||
@ -247,20 +170,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing hasLikedTopic statement.")
|
||||
stmts.hasLikedTopic, err = db.Prepare("SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'topics'")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'topics'")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing hasLikedReply statement.")
|
||||
stmts.hasLikedReply, err = db.Prepare("SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'replies'")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [targetItem] FROM [likes] WHERE [sentBy] = ?1 AND [targetItem] = ?2 AND [targetType] = 'replies'")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getUserName statement.")
|
||||
stmts.getUserName, err = db.Prepare("SELECT [name] FROM [users] WHERE [uid] = ?1")
|
||||
if err != nil {
|
||||
@ -310,20 +219,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getExpiredScheduledGroups statement.")
|
||||
stmts.getExpiredScheduledGroups, err = db.Prepare("SELECT [uid] FROM [users_groups_scheduler] WHERE GETDATE() > [revert_at] AND [temporary] = 1")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [uid] FROM [users_groups_scheduler] WHERE GETDATE() > [revert_at] AND [temporary] = 1")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getSync statement.")
|
||||
stmts.getSync, err = db.Prepare("SELECT [last_update] FROM [sync]")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [last_update] FROM [sync]")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getAttachment statement.")
|
||||
stmts.getAttachment, err = db.Prepare("SELECT [sectionID],[sectionTable],[originID],[originTable],[uploadedBy],[path] FROM [attachments] WHERE [path] = ?1 AND [sectionID] = ?2 AND [sectionTable] = ?3")
|
||||
if err != nil {
|
||||
@ -345,20 +240,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getTopicUser statement.")
|
||||
stmts.getTopicUser, err = db.Prepare("SELECT [topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[users].[name],[users].[avatar],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] WHERE [tid] = ?1")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[users].[name],[users].[avatar],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level] FROM [topics] LEFT JOIN [users] ON [topics].[createdBy] = [users].[uid] WHERE [tid] = ?1")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getTopicByReply statement.")
|
||||
stmts.getTopicByReply, err = db.Prepare("SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[topics].[data] FROM [replies] LEFT JOIN [topics] ON [replies].[tid] = [topics].[tid] WHERE [rid] = ?1")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT [topics].[tid],[topics].[title],[topics].[content],[topics].[createdBy],[topics].[createdAt],[topics].[is_closed],[topics].[sticky],[topics].[parentID],[topics].[ipaddress],[topics].[postCount],[topics].[likeCount],[topics].[data] FROM [replies] LEFT JOIN [topics] ON [replies].[tid] = [topics].[tid] WHERE [rid] = ?1")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getTopicReplies statement.")
|
||||
stmts.getTopicReplies, err = db.Prepare("SELECT [replies].[rid],[replies].[content],[replies].[createdBy],[replies].[createdAt],[replies].[lastEdit],[replies].[lastEditBy],[users].[avatar],[users].[name],[users].[group],[users].[url_prefix],[users].[url_name],[users].[level],[replies].[ipaddress] FROM [replies] LEFT JOIN [users] ON [replies].[createdBy] = [users].[uid] WHERE [tid] = ?1")
|
||||
if err != nil {
|
||||
@ -394,20 +275,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing createActionReply statement.")
|
||||
stmts.createActionReply, err = db.Prepare("INSERT INTO [replies] ([tid],[actionType],[ipaddress],[createdBy],[createdAt],[lastUpdated],[content],[parsed_content]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),'','')")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","INSERT INTO [replies] ([tid],[actionType],[ipaddress],[createdBy],[createdAt],[lastUpdated],[content],[parsed_content]) VALUES (?,?,?,?,GETUTCDATE(),GETUTCDATE(),'','')")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing createLike statement.")
|
||||
stmts.createLike, err = db.Prepare("INSERT INTO [likes] ([weight],[targetItem],[targetType],[sentBy]) VALUES (?,?,?,?)")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","INSERT INTO [likes] ([weight],[targetItem],[targetType],[sentBy]) VALUES (?,?,?,?)")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addActivity statement.")
|
||||
stmts.addActivity, err = db.Prepare("INSERT INTO [activity_stream] ([actor],[targetUser],[event],[elementType],[elementID]) VALUES (?,?,?,?,?)")
|
||||
if err != nil {
|
||||
@ -457,20 +324,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addModlogEntry statement.")
|
||||
stmts.addModlogEntry, err = db.Prepare("INSERT INTO [moderation_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","INSERT INTO [moderation_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addAdminlogEntry statement.")
|
||||
stmts.addAdminlogEntry, err = db.Prepare("INSERT INTO [administration_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","INSERT INTO [administration_logs] ([action],[elementID],[elementType],[ipaddress],[actorID],[doneAt]) VALUES (?,?,?,?,?,GETUTCDATE())")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addAttachment statement.")
|
||||
stmts.addAttachment, err = db.Prepare("INSERT INTO [attachments] ([sectionID],[sectionTable],[originID],[originTable],[uploadedBy],[path]) VALUES (?,?,?,?,?,?)")
|
||||
if err != nil {
|
||||
@ -485,41 +338,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addRepliesToTopic statement.")
|
||||
stmts.addRepliesToTopic, err = db.Prepare("UPDATE [topics] SET [postCount] = [postCount] + ?,[lastReplyBy] = ?,[lastReplyAt] = GETUTCDATE() WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [postCount] = [postCount] + ?,[lastReplyBy] = ?,[lastReplyAt] = GETUTCDATE() WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing removeRepliesFromTopic statement.")
|
||||
stmts.removeRepliesFromTopic, err = db.Prepare("UPDATE [topics] SET [postCount] = [postCount] - ? WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [postCount] = [postCount] - ? WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addLikesToTopic statement.")
|
||||
stmts.addLikesToTopic, err = db.Prepare("UPDATE [topics] SET [likeCount] = [likeCount] + ? WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [likeCount] = [likeCount] + ? WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addLikesToReply statement.")
|
||||
stmts.addLikesToReply, err = db.Prepare("UPDATE [replies] SET [likeCount] = [likeCount] + ? WHERE [rid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [replies] SET [likeCount] = [likeCount] + ? WHERE [rid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editTopic statement.")
|
||||
stmts.editTopic, err = db.Prepare("UPDATE [topics] SET [title] = ?,[content] = ?,[parsed_content] = ? WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [title] = ?,[content] = ?,[parsed_content] = ? WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editReply statement.")
|
||||
stmts.editReply, err = db.Prepare("UPDATE [replies] SET [content] = ?,[parsed_content] = ? WHERE [rid] = ?")
|
||||
if err != nil {
|
||||
@ -527,125 +345,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing stickTopic statement.")
|
||||
stmts.stickTopic, err = db.Prepare("UPDATE [topics] SET [sticky] = 1 WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [sticky] = 1 WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing unstickTopic statement.")
|
||||
stmts.unstickTopic, err = db.Prepare("UPDATE [topics] SET [sticky] = 0 WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [sticky] = 0 WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing lockTopic statement.")
|
||||
stmts.lockTopic, err = db.Prepare("UPDATE [topics] SET [is_closed] = 1 WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [is_closed] = 1 WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing unlockTopic statement.")
|
||||
stmts.unlockTopic, err = db.Prepare("UPDATE [topics] SET [is_closed] = 0 WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [topics] SET [is_closed] = 0 WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateLastIP statement.")
|
||||
stmts.updateLastIP, err = db.Prepare("UPDATE [users] SET [last_ip] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [last_ip] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateSession statement.")
|
||||
stmts.updateSession, err = db.Prepare("UPDATE [users] SET [session] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [session] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setPassword statement.")
|
||||
stmts.setPassword, err = db.Prepare("UPDATE [users] SET [password] = ?,[salt] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [password] = ?,[salt] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setAvatar statement.")
|
||||
stmts.setAvatar, err = db.Prepare("UPDATE [users] SET [avatar] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [avatar] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setUsername statement.")
|
||||
stmts.setUsername, err = db.Prepare("UPDATE [users] SET [name] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [name] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing changeGroup statement.")
|
||||
stmts.changeGroup, err = db.Prepare("UPDATE [users] SET [group] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [group] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing activateUser statement.")
|
||||
stmts.activateUser, err = db.Prepare("UPDATE [users] SET [active] = 1 WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [active] = 1 WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUserLevel statement.")
|
||||
stmts.updateUserLevel, err = db.Prepare("UPDATE [users] SET [level] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [level] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserScore statement.")
|
||||
stmts.incrementUserScore, err = db.Prepare("UPDATE [users] SET [score] = [score] + ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [score] = [score] + ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserPosts statement.")
|
||||
stmts.incrementUserPosts, err = db.Prepare("UPDATE [users] SET [posts] = [posts] + ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [posts] = [posts] + ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserBigposts statement.")
|
||||
stmts.incrementUserBigposts, err = db.Prepare("UPDATE [users] SET [posts] = [posts] + ?,[bigposts] = [bigposts] + ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [posts] = [posts] + ?,[bigposts] = [bigposts] + ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserMegaposts statement.")
|
||||
stmts.incrementUserMegaposts, err = db.Prepare("UPDATE [users] SET [posts] = [posts] + ?,[bigposts] = [bigposts] + ?,[megaposts] = [megaposts] + ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [posts] = [posts] + ?,[bigposts] = [bigposts] + ?,[megaposts] = [megaposts] + ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserTopics statement.")
|
||||
stmts.incrementUserTopics, err = db.Prepare("UPDATE [users] SET [topics] = [topics] + ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [topics] = [topics] + ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editProfileReply statement.")
|
||||
stmts.editProfileReply, err = db.Prepare("UPDATE [users_replies] SET [content] = ?,[parsed_content] = ? WHERE [rid] = ?")
|
||||
if err != nil {
|
||||
@ -653,13 +352,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE [forums] SET [name] = ?,[desc] = ?,[active] = ?,[preset] = ? WHERE [fid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [forums] SET [name] = ?,[desc] = ?,[active] = ?,[preset] = ? WHERE [fid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateSetting statement.")
|
||||
stmts.updateSetting, err = db.Prepare("UPDATE [settings] SET [content] = ? WHERE [name] = ?")
|
||||
if err != nil {
|
||||
@ -688,6 +380,13 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE [forums] SET [name] = ?,[desc] = ?,[active] = ?,[preset] = ? WHERE [fid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [forums] SET [name] = ?,[desc] = ?,[active] = ?,[preset] = ? WHERE [fid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUser statement.")
|
||||
stmts.updateUser, err = db.Prepare("UPDATE [users] SET [name] = ?,[email] = ?,[group] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
@ -695,13 +394,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUserGroup statement.")
|
||||
stmts.updateUserGroup, err = db.Prepare("UPDATE [users] SET [group] = ? WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users] SET [group] = ? WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroupPerms statement.")
|
||||
stmts.updateGroupPerms, err = db.Prepare("UPDATE [users_groups] SET [permissions] = ? WHERE [gid] = ?")
|
||||
if err != nil {
|
||||
@ -709,13 +401,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroupRank statement.")
|
||||
stmts.updateGroupRank, err = db.Prepare("UPDATE [users_groups] SET [is_admin] = ?,[is_mod] = ?,[is_banned] = ? WHERE [gid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","UPDATE [users_groups] SET [is_admin] = ?,[is_mod] = ?,[is_banned] = ? WHERE [gid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroup statement.")
|
||||
stmts.updateGroup, err = db.Prepare("UPDATE [users_groups] SET [name] = ?,[tag] = ? WHERE [gid] = ?")
|
||||
if err != nil {
|
||||
@ -758,27 +443,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteUser statement.")
|
||||
stmts.deleteUser, err = db.Prepare("DELETE FROM [users] WHERE [uid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","DELETE FROM [users] WHERE [uid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteTopic statement.")
|
||||
stmts.deleteTopic, err = db.Prepare("DELETE FROM [topics] WHERE [tid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","DELETE FROM [topics] WHERE [tid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteReply statement.")
|
||||
stmts.deleteReply, err = db.Prepare("DELETE FROM [replies] WHERE [rid] = ?")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","DELETE FROM [replies] WHERE [rid] = ?")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteProfileReply statement.")
|
||||
stmts.deleteProfileReply, err = db.Prepare("DELETE FROM [users_replies] WHERE [rid] = ?")
|
||||
if err != nil {
|
||||
@ -807,13 +471,6 @@ func _gen_mssql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing groupCount statement.")
|
||||
stmts.groupCount, err = db.Prepare("SELECT COUNT(*) AS [count] FROM [users_groups]")
|
||||
if err != nil {
|
||||
log.Print("Bad Query: ","SELECT COUNT(*) AS [count] FROM [users_groups]")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing modlogCount statement.")
|
||||
stmts.modlogCount, err = db.Prepare("SELECT COUNT(*) AS [count] FROM [moderation_logs]")
|
||||
if err != nil {
|
||||
|
318
gen_mysql.go
318
gen_mysql.go
@ -6,6 +6,7 @@ package main
|
||||
|
||||
import "log"
|
||||
import "database/sql"
|
||||
import "./common"
|
||||
//import "./query_gen/lib"
|
||||
|
||||
// nolint
|
||||
@ -14,21 +15,14 @@ type Stmts struct {
|
||||
getSettings *sql.Stmt
|
||||
getSetting *sql.Stmt
|
||||
getFullSetting *sql.Stmt
|
||||
getFullSettings *sql.Stmt
|
||||
getPlugins *sql.Stmt
|
||||
getThemes *sql.Stmt
|
||||
getWidgets *sql.Stmt
|
||||
isPluginActive *sql.Stmt
|
||||
getUsersOffset *sql.Stmt
|
||||
getWordFilters *sql.Stmt
|
||||
isThemeDefault *sql.Stmt
|
||||
getModlogs *sql.Stmt
|
||||
getModlogsOffset *sql.Stmt
|
||||
getReplyTID *sql.Stmt
|
||||
getTopicFID *sql.Stmt
|
||||
getUserReplyUID *sql.Stmt
|
||||
hasLikedTopic *sql.Stmt
|
||||
hasLikedReply *sql.Stmt
|
||||
getUserName *sql.Stmt
|
||||
getEmailsByUser *sql.Stmt
|
||||
getTopicBasic *sql.Stmt
|
||||
@ -36,20 +30,14 @@ type Stmts struct {
|
||||
forumEntryExists *sql.Stmt
|
||||
groupEntryExists *sql.Stmt
|
||||
getForumTopicsOffset *sql.Stmt
|
||||
getExpiredScheduledGroups *sql.Stmt
|
||||
getSync *sql.Stmt
|
||||
getAttachment *sql.Stmt
|
||||
getTopicRepliesOffset *sql.Stmt
|
||||
getTopicList *sql.Stmt
|
||||
getTopicUser *sql.Stmt
|
||||
getTopicByReply *sql.Stmt
|
||||
getTopicReplies *sql.Stmt
|
||||
getForumTopics *sql.Stmt
|
||||
getProfileReplies *sql.Stmt
|
||||
getWatchers *sql.Stmt
|
||||
createReport *sql.Stmt
|
||||
createActionReply *sql.Stmt
|
||||
createLike *sql.Stmt
|
||||
addActivity *sql.Stmt
|
||||
notifyOne *sql.Stmt
|
||||
addEmail *sql.Stmt
|
||||
@ -57,57 +45,27 @@ type Stmts struct {
|
||||
addForumPermsToForum *sql.Stmt
|
||||
addPlugin *sql.Stmt
|
||||
addTheme *sql.Stmt
|
||||
addModlogEntry *sql.Stmt
|
||||
addAdminlogEntry *sql.Stmt
|
||||
addAttachment *sql.Stmt
|
||||
createWordFilter *sql.Stmt
|
||||
addRepliesToTopic *sql.Stmt
|
||||
removeRepliesFromTopic *sql.Stmt
|
||||
addLikesToTopic *sql.Stmt
|
||||
addLikesToReply *sql.Stmt
|
||||
editTopic *sql.Stmt
|
||||
editReply *sql.Stmt
|
||||
stickTopic *sql.Stmt
|
||||
unstickTopic *sql.Stmt
|
||||
lockTopic *sql.Stmt
|
||||
unlockTopic *sql.Stmt
|
||||
updateLastIP *sql.Stmt
|
||||
updateSession *sql.Stmt
|
||||
setPassword *sql.Stmt
|
||||
setAvatar *sql.Stmt
|
||||
setUsername *sql.Stmt
|
||||
changeGroup *sql.Stmt
|
||||
activateUser *sql.Stmt
|
||||
updateUserLevel *sql.Stmt
|
||||
incrementUserScore *sql.Stmt
|
||||
incrementUserPosts *sql.Stmt
|
||||
incrementUserBigposts *sql.Stmt
|
||||
incrementUserMegaposts *sql.Stmt
|
||||
incrementUserTopics *sql.Stmt
|
||||
editProfileReply *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateSetting *sql.Stmt
|
||||
updatePlugin *sql.Stmt
|
||||
updatePluginInstall *sql.Stmt
|
||||
updateTheme *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateUser *sql.Stmt
|
||||
updateUserGroup *sql.Stmt
|
||||
updateGroupPerms *sql.Stmt
|
||||
updateGroupRank *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
updateEmail *sql.Stmt
|
||||
verifyEmail *sql.Stmt
|
||||
setTempGroup *sql.Stmt
|
||||
updateWordFilter *sql.Stmt
|
||||
bumpSync *sql.Stmt
|
||||
deleteUser *sql.Stmt
|
||||
deleteTopic *sql.Stmt
|
||||
deleteReply *sql.Stmt
|
||||
deleteProfileReply *sql.Stmt
|
||||
deleteActivityStreamMatch *sql.Stmt
|
||||
deleteWordFilter *sql.Stmt
|
||||
reportExists *sql.Stmt
|
||||
groupCount *sql.Stmt
|
||||
modlogCount *sql.Stmt
|
||||
notifyWatchers *sql.Stmt
|
||||
|
||||
@ -126,7 +84,7 @@ type Stmts struct {
|
||||
|
||||
// nolint
|
||||
func _gen_mysql() (err error) {
|
||||
if dev.DebugMode {
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Building the generated statements")
|
||||
}
|
||||
|
||||
@ -154,30 +112,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getFullSettings statement.")
|
||||
stmts.getFullSettings, err = db.Prepare("SELECT `name`,`content`,`type`,`constraints` FROM `settings`")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getPlugins statement.")
|
||||
stmts.getPlugins, err = db.Prepare("SELECT `uname`,`active`,`installed` FROM `plugins`")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getThemes statement.")
|
||||
stmts.getThemes, err = db.Prepare("SELECT `uname`,`default` FROM `themes`")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getWidgets statement.")
|
||||
stmts.getWidgets, err = db.Prepare("SELECT `position`,`side`,`type`,`active`,`location`,`data` FROM `widgets` ORDER BY position ASC")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing isPluginActive statement.")
|
||||
stmts.isPluginActive, err = db.Prepare("SELECT `active` FROM `plugins` WHERE `uname` = ?")
|
||||
if err != nil {
|
||||
@ -190,12 +124,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getWordFilters statement.")
|
||||
stmts.getWordFilters, err = db.Prepare("SELECT `wfid`,`find`,`replacement` FROM `word_filters`")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing isThemeDefault statement.")
|
||||
stmts.isThemeDefault, err = db.Prepare("SELECT `default` FROM `themes` WHERE `uname` = ?")
|
||||
if err != nil {
|
||||
@ -232,18 +160,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing hasLikedTopic statement.")
|
||||
stmts.hasLikedTopic, err = db.Prepare("SELECT `targetItem` FROM `likes` WHERE `sentBy` = ? AND `targetItem` = ? AND `targetType` = 'topics'")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing hasLikedReply statement.")
|
||||
stmts.hasLikedReply, err = db.Prepare("SELECT `targetItem` FROM `likes` WHERE `sentBy` = ? AND `targetItem` = ? AND `targetType` = 'replies'")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getUserName statement.")
|
||||
stmts.getUserName, err = db.Prepare("SELECT `name` FROM `users` WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
@ -286,18 +202,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getExpiredScheduledGroups statement.")
|
||||
stmts.getExpiredScheduledGroups, err = db.Prepare("SELECT `uid` FROM `users_groups_scheduler` WHERE UTC_TIMESTAMP() > `revert_at` AND `temporary` = 1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getSync statement.")
|
||||
stmts.getSync, err = db.Prepare("SELECT `last_update` FROM `sync`")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getAttachment statement.")
|
||||
stmts.getAttachment, err = db.Prepare("SELECT `sectionID`,`sectionTable`,`originID`,`originTable`,`uploadedBy`,`path` FROM `attachments` WHERE `path` = ? AND `sectionID` = ? AND `sectionTable` = ?")
|
||||
if err != nil {
|
||||
@ -316,18 +220,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getTopicUser statement.")
|
||||
stmts.getTopicUser, err = db.Prepare("SELECT `topics`.`title`, `topics`.`content`, `topics`.`createdBy`, `topics`.`createdAt`, `topics`.`is_closed`, `topics`.`sticky`, `topics`.`parentID`, `topics`.`ipaddress`, `topics`.`postCount`, `topics`.`likeCount`, `users`.`name`, `users`.`avatar`, `users`.`group`, `users`.`url_prefix`, `users`.`url_name`, `users`.`level` FROM `topics` LEFT JOIN `users` ON `topics`.`createdBy` = `users`.`uid` WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getTopicByReply statement.")
|
||||
stmts.getTopicByReply, err = db.Prepare("SELECT `topics`.`tid`, `topics`.`title`, `topics`.`content`, `topics`.`createdBy`, `topics`.`createdAt`, `topics`.`is_closed`, `topics`.`sticky`, `topics`.`parentID`, `topics`.`ipaddress`, `topics`.`postCount`, `topics`.`likeCount`, `topics`.`data` FROM `replies` LEFT JOIN `topics` ON `replies`.`tid` = `topics`.`tid` WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing getTopicReplies statement.")
|
||||
stmts.getTopicReplies, err = db.Prepare("SELECT `replies`.`rid`, `replies`.`content`, `replies`.`createdBy`, `replies`.`createdAt`, `replies`.`lastEdit`, `replies`.`lastEditBy`, `users`.`avatar`, `users`.`name`, `users`.`group`, `users`.`url_prefix`, `users`.`url_name`, `users`.`level`, `replies`.`ipaddress` FROM `replies` LEFT JOIN `users` ON `replies`.`createdBy` = `users`.`uid` WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
@ -358,18 +250,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing createActionReply statement.")
|
||||
stmts.createActionReply, err = db.Prepare("INSERT INTO `replies`(`tid`,`actionType`,`ipaddress`,`createdBy`,`createdAt`,`lastUpdated`,`content`,`parsed_content`) VALUES (?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','')")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing createLike statement.")
|
||||
stmts.createLike, err = db.Prepare("INSERT INTO `likes`(`weight`,`targetItem`,`targetType`,`sentBy`) VALUES (?,?,?,?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addActivity statement.")
|
||||
stmts.addActivity, err = db.Prepare("INSERT INTO `activity_stream`(`actor`,`targetUser`,`event`,`elementType`,`elementID`) VALUES (?,?,?,?,?)")
|
||||
if err != nil {
|
||||
@ -412,18 +292,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addModlogEntry statement.")
|
||||
stmts.addModlogEntry, err = db.Prepare("INSERT INTO `moderation_logs`(`action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt`) VALUES (?,?,?,?,?,UTC_TIMESTAMP())")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addAdminlogEntry statement.")
|
||||
stmts.addAdminlogEntry, err = db.Prepare("INSERT INTO `administration_logs`(`action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt`) VALUES (?,?,?,?,?,UTC_TIMESTAMP())")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addAttachment statement.")
|
||||
stmts.addAttachment, err = db.Prepare("INSERT INTO `attachments`(`sectionID`,`sectionTable`,`originID`,`originTable`,`uploadedBy`,`path`) VALUES (?,?,?,?,?,?)")
|
||||
if err != nil {
|
||||
@ -436,156 +304,18 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addRepliesToTopic statement.")
|
||||
stmts.addRepliesToTopic, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyBy` = ?,`lastReplyAt` = UTC_TIMESTAMP() WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing removeRepliesFromTopic statement.")
|
||||
stmts.removeRepliesFromTopic, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` - ? WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addLikesToTopic statement.")
|
||||
stmts.addLikesToTopic, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addLikesToReply statement.")
|
||||
stmts.addLikesToReply, err = db.Prepare("UPDATE `replies` SET `likeCount` = `likeCount` + ? WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editTopic statement.")
|
||||
stmts.editTopic, err = db.Prepare("UPDATE `topics` SET `title` = ?,`content` = ?,`parsed_content` = ? WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editReply statement.")
|
||||
stmts.editReply, err = db.Prepare("UPDATE `replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing stickTopic statement.")
|
||||
stmts.stickTopic, err = db.Prepare("UPDATE `topics` SET `sticky` = 1 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing unstickTopic statement.")
|
||||
stmts.unstickTopic, err = db.Prepare("UPDATE `topics` SET `sticky` = 0 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing lockTopic statement.")
|
||||
stmts.lockTopic, err = db.Prepare("UPDATE `topics` SET `is_closed` = 1 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing unlockTopic statement.")
|
||||
stmts.unlockTopic, err = db.Prepare("UPDATE `topics` SET `is_closed` = 0 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateLastIP statement.")
|
||||
stmts.updateLastIP, err = db.Prepare("UPDATE `users` SET `last_ip` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateSession statement.")
|
||||
stmts.updateSession, err = db.Prepare("UPDATE `users` SET `session` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setPassword statement.")
|
||||
stmts.setPassword, err = db.Prepare("UPDATE `users` SET `password` = ?,`salt` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setAvatar statement.")
|
||||
stmts.setAvatar, err = db.Prepare("UPDATE `users` SET `avatar` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setUsername statement.")
|
||||
stmts.setUsername, err = db.Prepare("UPDATE `users` SET `name` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing changeGroup statement.")
|
||||
stmts.changeGroup, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing activateUser statement.")
|
||||
stmts.activateUser, err = db.Prepare("UPDATE `users` SET `active` = 1 WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUserLevel statement.")
|
||||
stmts.updateUserLevel, err = db.Prepare("UPDATE `users` SET `level` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserScore statement.")
|
||||
stmts.incrementUserScore, err = db.Prepare("UPDATE `users` SET `score` = `score` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserPosts statement.")
|
||||
stmts.incrementUserPosts, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserBigposts statement.")
|
||||
stmts.incrementUserBigposts, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserMegaposts statement.")
|
||||
stmts.incrementUserMegaposts, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ?,`megaposts` = `megaposts` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserTopics statement.")
|
||||
stmts.incrementUserTopics, err = db.Prepare("UPDATE `users` SET `topics` = `topics` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editProfileReply statement.")
|
||||
stmts.editProfileReply, err = db.Prepare("UPDATE `users_replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateSetting statement.")
|
||||
stmts.updateSetting, err = db.Prepare("UPDATE `settings` SET `content` = ? WHERE `name` = ?")
|
||||
if err != nil {
|
||||
@ -610,30 +340,24 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUser statement.")
|
||||
stmts.updateUser, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUserGroup statement.")
|
||||
stmts.updateUserGroup, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroupPerms statement.")
|
||||
stmts.updateGroupPerms, err = db.Prepare("UPDATE `users_groups` SET `permissions` = ? WHERE `gid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroupRank statement.")
|
||||
stmts.updateGroupRank, err = db.Prepare("UPDATE `users_groups` SET `is_admin` = ?,`is_mod` = ?,`is_banned` = ? WHERE `gid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroup statement.")
|
||||
stmts.updateGroup, err = db.Prepare("UPDATE `users_groups` SET `name` = ?,`tag` = ? WHERE `gid` = ?")
|
||||
if err != nil {
|
||||
@ -670,24 +394,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteUser statement.")
|
||||
stmts.deleteUser, err = db.Prepare("DELETE FROM `users` WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteTopic statement.")
|
||||
stmts.deleteTopic, err = db.Prepare("DELETE FROM `topics` WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteReply statement.")
|
||||
stmts.deleteReply, err = db.Prepare("DELETE FROM `replies` WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing deleteProfileReply statement.")
|
||||
stmts.deleteProfileReply, err = db.Prepare("DELETE FROM `users_replies` WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
@ -712,12 +418,6 @@ func _gen_mysql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing groupCount statement.")
|
||||
stmts.groupCount, err = db.Prepare("SELECT COUNT(*) AS `count` FROM `users_groups`")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing modlogCount statement.")
|
||||
stmts.modlogCount, err = db.Prepare("SELECT COUNT(*) AS `count` FROM `moderation_logs`")
|
||||
if err != nil {
|
||||
|
185
gen_pgsql.go
185
gen_pgsql.go
@ -5,42 +5,19 @@ package main
|
||||
|
||||
import "log"
|
||||
import "database/sql"
|
||||
import "./common"
|
||||
|
||||
// nolint
|
||||
type Stmts struct {
|
||||
addRepliesToTopic *sql.Stmt
|
||||
removeRepliesFromTopic *sql.Stmt
|
||||
addLikesToTopic *sql.Stmt
|
||||
addLikesToReply *sql.Stmt
|
||||
editTopic *sql.Stmt
|
||||
editReply *sql.Stmt
|
||||
stickTopic *sql.Stmt
|
||||
unstickTopic *sql.Stmt
|
||||
lockTopic *sql.Stmt
|
||||
unlockTopic *sql.Stmt
|
||||
updateLastIP *sql.Stmt
|
||||
updateSession *sql.Stmt
|
||||
setPassword *sql.Stmt
|
||||
setAvatar *sql.Stmt
|
||||
setUsername *sql.Stmt
|
||||
changeGroup *sql.Stmt
|
||||
activateUser *sql.Stmt
|
||||
updateUserLevel *sql.Stmt
|
||||
incrementUserScore *sql.Stmt
|
||||
incrementUserPosts *sql.Stmt
|
||||
incrementUserBigposts *sql.Stmt
|
||||
incrementUserMegaposts *sql.Stmt
|
||||
incrementUserTopics *sql.Stmt
|
||||
editProfileReply *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateSetting *sql.Stmt
|
||||
updatePlugin *sql.Stmt
|
||||
updatePluginInstall *sql.Stmt
|
||||
updateTheme *sql.Stmt
|
||||
updateForum *sql.Stmt
|
||||
updateUser *sql.Stmt
|
||||
updateUserGroup *sql.Stmt
|
||||
updateGroupPerms *sql.Stmt
|
||||
updateGroupRank *sql.Stmt
|
||||
updateGroup *sql.Stmt
|
||||
updateEmail *sql.Stmt
|
||||
verifyEmail *sql.Stmt
|
||||
@ -63,160 +40,22 @@ type Stmts struct {
|
||||
|
||||
// nolint
|
||||
func _gen_pgsql() (err error) {
|
||||
if dev.DebugMode {
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Building the generated statements")
|
||||
}
|
||||
|
||||
log.Print("Preparing addRepliesToTopic statement.")
|
||||
stmts.addRepliesToTopic, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyBy` = ?,`lastReplyAt` = LOCALTIMESTAMP() WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing removeRepliesFromTopic statement.")
|
||||
stmts.removeRepliesFromTopic, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` - ? WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addLikesToTopic statement.")
|
||||
stmts.addLikesToTopic, err = db.Prepare("UPDATE `topics` SET `likeCount` = `likeCount` + ? WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing addLikesToReply statement.")
|
||||
stmts.addLikesToReply, err = db.Prepare("UPDATE `replies` SET `likeCount` = `likeCount` + ? WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editTopic statement.")
|
||||
stmts.editTopic, err = db.Prepare("UPDATE `topics` SET `title` = ?,`content` = ?,`parsed_content` = ? WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editReply statement.")
|
||||
stmts.editReply, err = db.Prepare("UPDATE `replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing stickTopic statement.")
|
||||
stmts.stickTopic, err = db.Prepare("UPDATE `topics` SET `sticky` = 1 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing unstickTopic statement.")
|
||||
stmts.unstickTopic, err = db.Prepare("UPDATE `topics` SET `sticky` = 0 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing lockTopic statement.")
|
||||
stmts.lockTopic, err = db.Prepare("UPDATE `topics` SET `is_closed` = 1 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing unlockTopic statement.")
|
||||
stmts.unlockTopic, err = db.Prepare("UPDATE `topics` SET `is_closed` = 0 WHERE `tid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateLastIP statement.")
|
||||
stmts.updateLastIP, err = db.Prepare("UPDATE `users` SET `last_ip` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateSession statement.")
|
||||
stmts.updateSession, err = db.Prepare("UPDATE `users` SET `session` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setPassword statement.")
|
||||
stmts.setPassword, err = db.Prepare("UPDATE `users` SET `password` = ?,`salt` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setAvatar statement.")
|
||||
stmts.setAvatar, err = db.Prepare("UPDATE `users` SET `avatar` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing setUsername statement.")
|
||||
stmts.setUsername, err = db.Prepare("UPDATE `users` SET `name` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing changeGroup statement.")
|
||||
stmts.changeGroup, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing activateUser statement.")
|
||||
stmts.activateUser, err = db.Prepare("UPDATE `users` SET `active` = 1 WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUserLevel statement.")
|
||||
stmts.updateUserLevel, err = db.Prepare("UPDATE `users` SET `level` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserScore statement.")
|
||||
stmts.incrementUserScore, err = db.Prepare("UPDATE `users` SET `score` = `score` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserPosts statement.")
|
||||
stmts.incrementUserPosts, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserBigposts statement.")
|
||||
stmts.incrementUserBigposts, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserMegaposts statement.")
|
||||
stmts.incrementUserMegaposts, err = db.Prepare("UPDATE `users` SET `posts` = `posts` + ?,`bigposts` = `bigposts` + ?,`megaposts` = `megaposts` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing incrementUserTopics statement.")
|
||||
stmts.incrementUserTopics, err = db.Prepare("UPDATE `users` SET `topics` = `topics` + ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing editProfileReply statement.")
|
||||
stmts.editProfileReply, err = db.Prepare("UPDATE `users_replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateSetting statement.")
|
||||
stmts.updateSetting, err = db.Prepare("UPDATE `settings` SET `content` = ? WHERE `name` = ?")
|
||||
if err != nil {
|
||||
@ -241,30 +80,24 @@ func _gen_pgsql() (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateForum statement.")
|
||||
stmts.updateForum, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUser statement.")
|
||||
stmts.updateUser, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateUserGroup statement.")
|
||||
stmts.updateUserGroup, err = db.Prepare("UPDATE `users` SET `group` = ? WHERE `uid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroupPerms statement.")
|
||||
stmts.updateGroupPerms, err = db.Prepare("UPDATE `users_groups` SET `permissions` = ? WHERE `gid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroupRank statement.")
|
||||
stmts.updateGroupRank, err = db.Prepare("UPDATE `users_groups` SET `is_admin` = ?,`is_mod` = ?,`is_banned` = ? WHERE `gid` = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Preparing updateGroup statement.")
|
||||
stmts.updateGroup, err = db.Prepare("UPDATE `users_groups` SET `name` = ?,`tag` = ? WHERE `gid` = ?")
|
||||
if err != nil {
|
||||
|
@ -2,17 +2,21 @@
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
|
||||
import "log"
|
||||
import "strings"
|
||||
import "sync"
|
||||
import "errors"
|
||||
import "net/http"
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
var ErrNoRoute = errors.New("That route doesn't exist.")
|
||||
|
||||
type GenRouter struct {
|
||||
UploadHandler func(http.ResponseWriter, *http.Request)
|
||||
extra_routes map[string]func(http.ResponseWriter, *http.Request, User) RouteError
|
||||
extra_routes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
@ -20,26 +24,26 @@ type GenRouter struct {
|
||||
func NewGenRouter(uploads http.Handler) *GenRouter {
|
||||
return &GenRouter{
|
||||
UploadHandler: http.StripPrefix("/uploads/",uploads).ServeHTTP,
|
||||
extra_routes: make(map[string]func(http.ResponseWriter, *http.Request, User) RouteError),
|
||||
extra_routes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
|
||||
}
|
||||
}
|
||||
|
||||
func (router *GenRouter) handleError(err RouteError, w http.ResponseWriter, r *http.Request, user User) {
|
||||
func (router *GenRouter) handleError(err common.RouteError, w http.ResponseWriter, r *http.Request, user common.User) {
|
||||
if err.Handled() {
|
||||
return
|
||||
}
|
||||
|
||||
if err.Type() == "system" {
|
||||
InternalErrorJSQ(err,w,r,err.Json())
|
||||
common.InternalErrorJSQ(err, w, r, err.JSON())
|
||||
return
|
||||
}
|
||||
LocalErrorJSQ(err.Error(),w,r,user,err.Json())
|
||||
common.LocalErrorJSQ(err.Error(), w, r, user,err.JSON())
|
||||
}
|
||||
|
||||
func (router *GenRouter) Handle(_ string, _ http.Handler) {
|
||||
}
|
||||
|
||||
func (router *GenRouter) HandleFunc(pattern string, handle func(http.ResponseWriter, *http.Request, User) RouteError) {
|
||||
func (router *GenRouter) HandleFunc(pattern string, handle func(http.ResponseWriter, *http.Request, common.User) common.RouteError) {
|
||||
router.Lock()
|
||||
router.extra_routes[pattern] = handle
|
||||
router.Unlock()
|
||||
@ -52,7 +56,7 @@ func (router *GenRouter) RemoveFunc(pattern string) error {
|
||||
router.Unlock()
|
||||
return ErrNoRoute
|
||||
}
|
||||
delete(router.extra_routes,pattern)
|
||||
delete(router.extra_routes, pattern)
|
||||
router.Unlock()
|
||||
return nil
|
||||
}
|
||||
@ -75,7 +79,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if common.Dev.SuperDebug {
|
||||
log.Print("before routeStatic")
|
||||
log.Print("prefix: ", prefix)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
@ -85,25 +89,25 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
if prefix == "/static" {
|
||||
req.URL.Path += extra_data
|
||||
routeStatic(w,req)
|
||||
routeStatic(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if common.Dev.SuperDebug {
|
||||
log.Print("before PreRoute")
|
||||
}
|
||||
|
||||
// Deal with the session stuff, etc.
|
||||
user, ok := PreRoute(w,req)
|
||||
user, ok := common.PreRoute(w, req)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if common.Dev.SuperDebug {
|
||||
log.Print("after PreRoute")
|
||||
}
|
||||
|
||||
var err RouteError
|
||||
var err common.RouteError
|
||||
switch(prefix) {
|
||||
case "/api":
|
||||
err = routeAPI(w,req,user)
|
||||
@ -136,19 +140,19 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
router.handleError(err,w,req,user)
|
||||
}
|
||||
case "/report":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = NoBanned(w,req,user)
|
||||
err = common.NoBanned(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = NoSessionMismatch(w,req,user)
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -164,7 +168,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
case "/topics":
|
||||
switch(req.URL.Path) {
|
||||
case "/topics/create/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -178,7 +182,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
router.handleError(err,w,req,user)
|
||||
}
|
||||
case "/panel":
|
||||
err = SuperModOnly(w,req,user)
|
||||
err = common.SuperModOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -260,7 +264,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
case "/user":
|
||||
switch(req.URL.Path) {
|
||||
case "/user/edit/critical/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -268,13 +272,13 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditCritical(w,req,user)
|
||||
case "/user/edit/critical/submit/":
|
||||
err = NoSessionMismatch(w,req,user)
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
}
|
||||
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -282,7 +286,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditCriticalSubmit(w,req,user)
|
||||
case "/user/edit/avatar/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -290,7 +294,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditAvatar(w,req,user)
|
||||
case "/user/edit/avatar/submit/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -298,7 +302,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditAvatarSubmit(w,req,user)
|
||||
case "/user/edit/username/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -306,7 +310,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditUsername(w,req,user)
|
||||
case "/user/edit/username/submit/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -314,7 +318,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditUsernameSubmit(w,req,user)
|
||||
case "/user/edit/email/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -322,7 +326,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeAccountEditEmail(w,req,user)
|
||||
case "/user/edit/token/":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -337,7 +341,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
router.handleError(err,w,req,user)
|
||||
}
|
||||
case "/users":
|
||||
err = MemberOnly(w,req,user)
|
||||
err = common.MemberOnly(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -345,7 +349,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
switch(req.URL.Path) {
|
||||
case "/users/ban/submit/":
|
||||
err = NoSessionMismatch(w,req,user)
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -353,7 +357,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeBanSubmit(w,req,user)
|
||||
case "/users/unban/":
|
||||
err = NoSessionMismatch(w,req,user)
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -361,7 +365,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
err = routeUnban(w,req,user)
|
||||
case "/users/activate/":
|
||||
err = NoSessionMismatch(w,req,user)
|
||||
err = common.NoSessionMismatch(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -376,7 +380,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
case "/uploads":
|
||||
if extra_data == "" {
|
||||
NotFound(w,req)
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
}
|
||||
req.URL.Path += extra_data
|
||||
@ -395,10 +399,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
if extra_data != "" {
|
||||
NotFound(w,req)
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
}
|
||||
config.DefaultRoute(w,req,user)
|
||||
common.Config.DefaultRoute(w,req,user)
|
||||
default:
|
||||
// A fallback for the routes which haven't been converted to the new router yet or plugins
|
||||
router.RLock()
|
||||
@ -413,6 +417,6 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
return
|
||||
}
|
||||
NotFound(w,req)
|
||||
common.NotFound(w,req)
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"./common"
|
||||
"./install/install"
|
||||
//"runtime/pprof"
|
||||
//_ "github.com/go-sql-driver/mysql"
|
||||
@ -46,28 +47,28 @@ func ResetTables() (err error) {
|
||||
}
|
||||
|
||||
func gloinit() (err error) {
|
||||
dev.DebugMode = false
|
||||
common.Dev.DebugMode = false
|
||||
//nogrouplog = true
|
||||
startTime = time.Now()
|
||||
|
||||
err = processConfig()
|
||||
err = common.ProcessConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = initThemes()
|
||||
err = common.InitThemes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switchToTestDB()
|
||||
common.SwitchToTestDB()
|
||||
|
||||
var ok bool
|
||||
installAdapter, ok = install.Lookup(dbAdapter)
|
||||
if !ok {
|
||||
return errors.New("We couldn't find the adapter '" + dbAdapter + "'")
|
||||
}
|
||||
installAdapter.SetConfig(dbConfig.Host, dbConfig.Username, dbConfig.Password, dbConfig.Dbname, dbConfig.Port)
|
||||
installAdapter.SetConfig(common.DbConfig.Host, common.DbConfig.Username, common.DbConfig.Password, common.DbConfig.Dbname, common.DbConfig.Port)
|
||||
|
||||
err = ResetTables()
|
||||
if err != nil {
|
||||
|
@ -97,67 +97,69 @@ func main() {
|
||||
|
||||
configContents := []byte(`package main
|
||||
|
||||
import "./common"
|
||||
|
||||
func init() {
|
||||
// Site Info
|
||||
site.ShortName = "` + siteShortName + `" // This should be less than three letters to fit in the navbar
|
||||
site.Name = "` + siteName + `"
|
||||
site.Email = ""
|
||||
site.URL = "` + siteURL + `"
|
||||
site.Port = "` + serverPort + `"
|
||||
site.EnableSsl = false
|
||||
site.EnableEmails = false
|
||||
site.HasProxy = false // Cloudflare counts as this, if it's sitting in the middle
|
||||
config.SslPrivkey = ""
|
||||
config.SslFullchain = ""
|
||||
site.Language = "english"
|
||||
common.Site.ShortName = "` + siteShortName + `" // This should be less than three letters to fit in the navbar
|
||||
common.Site.Name = "` + siteName + `"
|
||||
common.Site.Email = ""
|
||||
common.Site.URL = "` + siteURL + `"
|
||||
common.Site.Port = "` + serverPort + `"
|
||||
common.Site.EnableSsl = false
|
||||
common.Site.EnableEmails = false
|
||||
common.Site.HasProxy = false // Cloudflare counts as this, if it's sitting in the middle
|
||||
common.Config.SslPrivkey = ""
|
||||
common.Config.SslFullchain = ""
|
||||
common.Site.Language = "english"
|
||||
|
||||
// Database details
|
||||
dbConfig.Host = "` + adap.DBHost() + `"
|
||||
dbConfig.Username = "` + adap.DBUsername() + `"
|
||||
dbConfig.Password = "` + adap.DBPassword() + `"
|
||||
dbConfig.Dbname = "` + adap.DBName() + `"
|
||||
dbConfig.Port = "` + adap.DBPort() + `" // You probably won't need to change this
|
||||
common.DbConfig.Host = "` + adap.DBHost() + `"
|
||||
common.DbConfig.Username = "` + adap.DBUsername() + `"
|
||||
common.DbConfig.Password = "` + adap.DBPassword() + `"
|
||||
common.DbConfig.Dbname = "` + adap.DBName() + `"
|
||||
common.DbConfig.Port = "` + adap.DBPort() + `" // You probably won't need to change this
|
||||
|
||||
// Test Database details
|
||||
dbConfig.TestHost = ""
|
||||
dbConfig.TestUsername = ""
|
||||
dbConfig.TestPassword = ""
|
||||
dbConfig.TestDbname = "" // The name of the test database, leave blank to disable. DON'T USE YOUR PRODUCTION DATABASE FOR THIS. LEAVE BLANK IF YOU DON'T KNOW WHAT THIS MEANS.
|
||||
dbConfig.TestPort = ""
|
||||
common.DbConfig.TestHost = ""
|
||||
common.DbConfig.TestUsername = ""
|
||||
common.DbConfig.TestPassword = ""
|
||||
common.DbConfig.TestDbname = "" // The name of the test database, leave blank to disable. DON'T USE YOUR PRODUCTION DATABASE FOR THIS. LEAVE BLANK IF YOU DON'T KNOW WHAT THIS MEANS.
|
||||
common.DbConfig.TestPort = ""
|
||||
|
||||
// Limiters
|
||||
config.MaxRequestSize = 5 * megabyte
|
||||
common.Config.MaxRequestSize = 5 * common.Megabyte
|
||||
|
||||
// Caching
|
||||
config.CacheTopicUser = CACHE_STATIC
|
||||
config.UserCacheCapacity = 120 // The max number of users held in memory
|
||||
config.TopicCacheCapacity = 200 // The max number of topics held in memory
|
||||
common.Config.CacheTopicUser = common.CACHE_STATIC
|
||||
common.Config.UserCacheCapacity = 120 // The max number of users held in memory
|
||||
common.Config.TopicCacheCapacity = 200 // The max number of topics held in memory
|
||||
|
||||
// Email
|
||||
config.SMTPServer = ""
|
||||
config.SMTPUsername = ""
|
||||
config.SMTPPassword = ""
|
||||
config.SMTPPort = "25"
|
||||
common.Config.SMTPServer = ""
|
||||
common.Config.SMTPUsername = ""
|
||||
common.Config.SMTPPassword = ""
|
||||
common.Config.SMTPPort = "25"
|
||||
|
||||
// Misc
|
||||
config.DefaultRoute = routeTopics
|
||||
config.DefaultGroup = 3 // Should be a setting in the database
|
||||
config.ActivationGroup = 5 // Should be a setting in the database
|
||||
config.StaffCSS = "staff_post"
|
||||
config.DefaultForum = 2
|
||||
config.MinifyTemplates = true
|
||||
config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features
|
||||
common.Config.DefaultRoute = routeTopics
|
||||
common.Config.DefaultGroup = 3 // Should be a setting in the database
|
||||
common.Config.ActivationGroup = 5 // Should be a setting in the database
|
||||
common.Config.StaffCSS = "staff_post"
|
||||
common.Config.DefaultForum = 2
|
||||
common.Config.MinifyTemplates = true
|
||||
common.Config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features
|
||||
|
||||
//config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png"
|
||||
config.Noavatar = "https://api.adorable.io/avatars/285/{id}@{site_url}.png"
|
||||
config.ItemsPerPage = 25
|
||||
//common.Config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png"
|
||||
common.Config.Noavatar = "https://api.adorable.io/avatars/285/{id}@{site_url}.png"
|
||||
common.Config.ItemsPerPage = 25
|
||||
|
||||
// Developer flags
|
||||
dev.DebugMode = true
|
||||
//dev.SuperDebug = true
|
||||
//dev.TemplateDebug = true
|
||||
//dev.Profiling = true
|
||||
//dev.TestDB = true
|
||||
common.Dev.DebugMode = true
|
||||
//common.Dev.SuperDebug = true
|
||||
//common.Dev.TemplateDebug = true
|
||||
//common.Dev.Profiling = true
|
||||
//common.Dev.TestDB = true
|
||||
}
|
||||
`)
|
||||
|
||||
|
116
main.go
116
main.go
@ -14,65 +14,12 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
//"runtime/pprof"
|
||||
"./common"
|
||||
)
|
||||
|
||||
var version = Version{Major: 0, Minor: 1, Patch: 0, Tag: "dev"}
|
||||
|
||||
const hour int = 60 * 60
|
||||
const day int = hour * 24
|
||||
const week int = day * 7
|
||||
const month int = day * 30
|
||||
const year int = day * 365
|
||||
const kilobyte int = 1024
|
||||
const megabyte int = kilobyte * 1024
|
||||
const gigabyte int = megabyte * 1024
|
||||
const terabyte int = gigabyte * 1024
|
||||
const petabyte int = terabyte * 1024
|
||||
const saltLength int = 32
|
||||
const sessionLength int = 80
|
||||
|
||||
var version = common.Version{Major: 0, Minor: 1, Patch: 0, Tag: "dev"}
|
||||
var router *GenRouter
|
||||
var startTime time.Time
|
||||
|
||||
// ? - Make this more customisable?
|
||||
var externalSites = map[string]string{
|
||||
"YT": "https://www.youtube.com/",
|
||||
}
|
||||
|
||||
type StringList []string
|
||||
|
||||
// ? - Should we allow users to upload .php or .go files? It could cause security issues. We could store them with a mangled extension to render them inert
|
||||
// TODO: Let admins manage this from the Control Panel
|
||||
var allowedFileExts = StringList{
|
||||
"png", "jpg", "jpeg", "svg", "bmp", "gif", "tif", "webp", "apng", // images
|
||||
|
||||
"txt", "xml", "json", "yaml", "toml", "ini", "md", "html", "rtf", "js", "py", "rb", "css", "scss", "less", "eqcss", "pcss", "java", "ts", "cs", "c", "cc", "cpp", "cxx", "C", "c++", "h", "hh", "hpp", "hxx", "h++", "rs", "rlib", "htaccess", "gitignore", // text
|
||||
|
||||
"mp3", "mp4", "avi", "wmv", "webm", // video
|
||||
|
||||
"otf", "woff2", "woff", "ttf", "eot", // fonts
|
||||
}
|
||||
var imageFileExts = StringList{
|
||||
"png", "jpg", "jpeg", "svg", "bmp", "gif", "tif", "webp", "apng",
|
||||
}
|
||||
var archiveFileExts = StringList{
|
||||
"bz2", "zip", "gz", "7z", "tar", "cab",
|
||||
}
|
||||
var executableFileExts = StringList{
|
||||
"exe", "jar", "phar", "shar", "iso",
|
||||
}
|
||||
|
||||
// TODO: Write a test for this
|
||||
func (slice StringList) Contains(needle string) bool {
|
||||
for _, item := range slice {
|
||||
if item == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var staticFiles = make(map[string]SFile)
|
||||
var logWriter = io.MultiWriter(os.Stderr)
|
||||
|
||||
// TODO: Wrap the globals in here so we can pass pointers to them to subpackages
|
||||
@ -128,58 +75,61 @@ func main() {
|
||||
startTime = time.Now()
|
||||
|
||||
log.Print("Processing configuration data")
|
||||
err = processConfig()
|
||||
err = common.ProcessConfig()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = initThemes()
|
||||
err = common.InitThemes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = initDatabase()
|
||||
err = InitDatabase()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
rstore, err = NewSQLReplyStore()
|
||||
common.Rstore, err = common.NewSQLReplyStore()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
prstore, err = NewSQLProfileReplyStore()
|
||||
common.Prstore, err = common.NewSQLProfileReplyStore()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
initTemplates()
|
||||
common.InitTemplates()
|
||||
|
||||
err = initPhrases()
|
||||
err = common.InitPhrases()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Loading the static files.")
|
||||
err = initStaticFiles()
|
||||
err = common.StaticFiles.Init()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Initialising the widgets")
|
||||
err = initWidgets()
|
||||
err = common.InitWidgets()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Print("Initialising the authentication system")
|
||||
auth = NewDefaultAuth()
|
||||
|
||||
err = LoadWordFilters()
|
||||
common.Auth, err = common.NewDefaultAuth()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = verifyConfig()
|
||||
err = common.LoadWordFilters()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = common.VerifyConfig()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -195,18 +145,18 @@ func main() {
|
||||
//log.Print("Running the second ticker")
|
||||
// TODO: Add a plugin hook here
|
||||
|
||||
err := handleExpiredScheduledGroups()
|
||||
err := common.HandleExpiredScheduledGroups()
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
common.LogError(err)
|
||||
}
|
||||
|
||||
// TODO: Handle delayed moderation tasks
|
||||
// TODO: Handle the daily clean-up. Move this to a 24 hour task?
|
||||
|
||||
// Sync with the database, if there are any changes
|
||||
err = handleServerSync()
|
||||
err = common.HandleServerSync()
|
||||
if err != nil {
|
||||
LogError(err)
|
||||
common.LogError(err)
|
||||
}
|
||||
|
||||
// TODO: Manage the TopicStore, UserStore, and ForumStore
|
||||
@ -264,7 +214,7 @@ func main() {
|
||||
router.HandleFunc("/ws/", routeWebsockets)
|
||||
|
||||
log.Print("Initialising the plugins")
|
||||
initPlugins()
|
||||
common.InitPlugins()
|
||||
|
||||
defer db.Close()
|
||||
|
||||
@ -274,17 +224,17 @@ func main() {
|
||||
|
||||
// TODO: Let users run *both* HTTP and HTTPS
|
||||
log.Print("Initialising the HTTP server")
|
||||
if !site.EnableSsl {
|
||||
if site.Port == "" {
|
||||
site.Port = "80"
|
||||
if !common.Site.EnableSsl {
|
||||
if common.Site.Port == "" {
|
||||
common.Site.Port = "80"
|
||||
}
|
||||
log.Print("Listening on port " + site.Port)
|
||||
err = http.ListenAndServe(":"+site.Port, router)
|
||||
log.Print("Listening on port " + common.Site.Port)
|
||||
err = http.ListenAndServe(":"+common.Site.Port, router)
|
||||
} else {
|
||||
if site.Port == "" {
|
||||
site.Port = "443"
|
||||
if common.Site.Port == "" {
|
||||
common.Site.Port = "443"
|
||||
}
|
||||
if site.Port == "80" || site.Port == "443" {
|
||||
if common.Site.Port == "80" || common.Site.Port == "443" {
|
||||
// We should also run the server on port 80
|
||||
// TODO: Redirect to port 443
|
||||
go func() {
|
||||
@ -295,8 +245,8 @@ func main() {
|
||||
}
|
||||
}()
|
||||
}
|
||||
log.Print("Listening on port " + site.Port)
|
||||
err = http.ListenAndServeTLS(":"+site.Port, config.SslFullchain, config.SslPrivkey, router)
|
||||
log.Printf("Listening on port %s", common.Site.Port)
|
||||
err = http.ListenAndServeTLS(":"+common.Site.Port, common.Config.SslFullchain, common.Config.SslPrivkey, router)
|
||||
}
|
||||
|
||||
// Why did the server stop?
|
||||
|
548
member_routes.go
548
member_routes.go
File diff suppressed because it is too large
Load Diff
130
misc_test.go
130
misc_test.go
@ -8,6 +8,8 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
func recordMustExist(t *testing.T, err error, errmsg string, args ...interface{}) {
|
||||
@ -47,22 +49,22 @@ func TestUserStore(t *testing.T) {
|
||||
userStoreTest(t, 3)
|
||||
}
|
||||
func userStoreTest(t *testing.T, newUserID int) {
|
||||
ucache, hasCache := users.(UserCache)
|
||||
ucache, hasCache := common.Users.(UserCache)
|
||||
// Go doesn't have short-circuiting, so this'll allow us to do one liner tests
|
||||
if !hasCache {
|
||||
ucache = &NullUserStore{}
|
||||
}
|
||||
expect(t, (!hasCache || ucache.Length() == 0), fmt.Sprintf("The initial ucache length should be zero, not %d", ucache.Length()))
|
||||
|
||||
_, err := users.Get(-1)
|
||||
_, err := common.Users.Get(-1)
|
||||
recordMustNotExist(t, err, "UID #-1 shouldn't exist")
|
||||
expect(t, !hasCache || ucache.Length() == 0, fmt.Sprintf("We found %d items in the user cache and it's supposed to be empty", ucache.Length()))
|
||||
|
||||
_, err = users.Get(0)
|
||||
_, err = common.Users.Get(0)
|
||||
recordMustNotExist(t, err, "UID #0 shouldn't exist")
|
||||
expect(t, !hasCache || ucache.Length() == 0, fmt.Sprintf("We found %d items in the user cache and it's supposed to be empty", ucache.Length()))
|
||||
|
||||
user, err := users.Get(1)
|
||||
user, err := common.Users.Get(1)
|
||||
recordMustExist(t, err, "Couldn't find UID #1")
|
||||
|
||||
expect(t, user.ID == 1, fmt.Sprintf("user.ID should be 1. Got '%d' instead.", user.ID))
|
||||
@ -74,7 +76,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expect(t, user.IsMod, "Admin should be a mod")
|
||||
expect(t, !user.IsBanned, "Admin should not be banned")
|
||||
|
||||
_, err = users.Get(newUserID)
|
||||
_, err = common.Users.Get(newUserID)
|
||||
recordMustNotExist(t, err, fmt.Sprintf("UID #%d shouldn't exist", newUserID))
|
||||
|
||||
if hasCache {
|
||||
@ -103,7 +105,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
|
||||
// TODO: Lock onto the specific error type. Is this even possible without sacrificing the detailed information in the error message?
|
||||
var userList map[int]*User
|
||||
userList, _ = users.BulkGetMap([]int{-1})
|
||||
userList, _ = common.Users.BulkGetMap([]int{-1})
|
||||
if len(userList) > 0 {
|
||||
t.Error("There shouldn't be any results for UID #-1")
|
||||
}
|
||||
@ -112,7 +114,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectIntToBeX(t, ucache.Length(), 0, "User cache length should be 0, not %d")
|
||||
}
|
||||
|
||||
userList, _ = users.BulkGetMap([]int{0})
|
||||
userList, _ = common.Users.BulkGetMap([]int{0})
|
||||
if len(userList) > 0 {
|
||||
t.Error("There shouldn't be any results for UID #0")
|
||||
}
|
||||
@ -121,7 +123,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectIntToBeX(t, ucache.Length(), 0, "User cache length should be 0, not %d")
|
||||
}
|
||||
|
||||
userList, _ = users.BulkGetMap([]int{1})
|
||||
userList, _ = common.Users.BulkGetMap([]int{1})
|
||||
if len(userList) == 0 {
|
||||
t.Error("The returned map is empty for UID #1")
|
||||
} else if len(userList) > 1 {
|
||||
@ -151,19 +153,19 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
|
||||
expect(t, !users.Exists(-1), "UID #-1 shouldn't exist")
|
||||
expect(t, !users.Exists(0), "UID #0 shouldn't exist")
|
||||
expect(t, users.Exists(1), "UID #1 should exist")
|
||||
expect(t, common.Users.Exists(1), "UID #1 should exist")
|
||||
expect(t, !users.Exists(newUserID), fmt.Sprintf("UID #%d shouldn't exist", newUserID))
|
||||
|
||||
expect(t, !hasCache || ucache.Length() == 0, fmt.Sprintf("User cache length should be 0, not %d", ucache.Length()))
|
||||
expectIntToBeX(t, users.GlobalCount(), 1, "The number of users should be one, not %d")
|
||||
expectIntToBeX(t, common.Users.GlobalCount(), 1, "The number of users should be one, not %d")
|
||||
|
||||
var awaitingActivation = 5
|
||||
uid, err := users.Create("Sam", "ReallyBadPassword", "sam@localhost.loc", awaitingActivation, false)
|
||||
uid, err := common.Users.Create("Sam", "ReallyBadPassword", "sam@localhost.loc", awaitingActivation, false)
|
||||
expectNilErr(t, err)
|
||||
expect(t, uid == newUserID, fmt.Sprintf("The UID of the new user should be %d", newUserID))
|
||||
expect(t, users.Exists(newUserID), fmt.Sprintf("UID #%d should exist", newUserID))
|
||||
expect(t, common.Users.Exists(newUserID), fmt.Sprintf("UID #%d should exist", newUserID))
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
if user.ID != newUserID {
|
||||
t.Errorf("The UID of the user record should be %d", newUserID)
|
||||
@ -195,7 +197,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
recordMustNotExist(t, err, "UID #%d shouldn't be in the cache", newUserID)
|
||||
}
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
|
||||
expect(t, user.ID == newUserID, fmt.Sprintf("The UID of the user record should be %d, not %d", newUserID, user.ID))
|
||||
@ -221,7 +223,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
recordMustNotExist(t, err, "UID #%d shouldn't be in the cache", newUserID)
|
||||
}
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
if user.ID != newUserID {
|
||||
t.Errorf("The UID of the user record should be %d", newUserID)
|
||||
@ -247,7 +249,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
recordMustNotExist(t, err, "UID #%d shouldn't be in the cache", newUserID)
|
||||
}
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
|
||||
@ -270,7 +272,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectNilErr(t, err)
|
||||
expect(t, user.Group == config.DefaultGroup, "Someone's mutated this pointer elsewhere")
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
var user2 *User = getDummyUser()
|
||||
@ -293,7 +295,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectNilErr(t, err)
|
||||
expect(t, user.Group == 1, "Someone's mutated this pointer elsewhere")
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
user2 = getDummyUser()
|
||||
@ -316,7 +318,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectNilErr(t, err)
|
||||
expect(t, user.Group == 2, "Someone's mutated this pointer elsewhere")
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
user2 = getDummyUser()
|
||||
@ -340,7 +342,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectNilErr(t, err)
|
||||
expect(t, user.Group == 3, "Someone's mutated this pointer elsewhere")
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
user2 = getDummyUser()
|
||||
@ -363,7 +365,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectNilErr(t, err)
|
||||
expect(t, user.Group == 4, "Someone's mutated this pointer elsewhere")
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
user2 = getDummyUser()
|
||||
@ -386,7 +388,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
expectNilErr(t, err)
|
||||
expect(t, user.Group == 5, "Someone's mutated this pointer elsewhere")
|
||||
|
||||
user, err = users.Get(newUserID)
|
||||
user, err = common.Users.Get(newUserID)
|
||||
recordMustExist(t, err, "Couldn't find UID #%d", newUserID)
|
||||
expectIntToBeX(t, user.ID, newUserID, "The UID of the user record should be %d")
|
||||
user2 = getDummyUser()
|
||||
@ -419,7 +421,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||
recordMustNotExist(t, err, "UID #%d shouldn't be in the cache", newUserID)
|
||||
}
|
||||
|
||||
_, err = users.Get(newUserID)
|
||||
_, err = common.Users.Get(newUserID)
|
||||
recordMustNotExist(t, err, "UID #%d shouldn't exist", newUserID)
|
||||
|
||||
// TODO: Add tests for the Cache* methods
|
||||
@ -515,13 +517,13 @@ func topicStoreTest(t *testing.T) {
|
||||
var topic *Topic
|
||||
var err error
|
||||
|
||||
_, err = topics.Get(-1)
|
||||
_, err = common.Topics.Get(-1)
|
||||
recordMustNotExist(t, err, "TID #-1 shouldn't exist")
|
||||
|
||||
_, err = topics.Get(0)
|
||||
_, err = common.Topics.Get(0)
|
||||
recordMustNotExist(t, err, "TID #0 shouldn't exist")
|
||||
|
||||
topic, err = topics.Get(1)
|
||||
topic, err = common.Topics.Get(1)
|
||||
recordMustExist(t, err, "Couldn't find TID #1")
|
||||
|
||||
if topic.ID != 1 {
|
||||
@ -530,22 +532,22 @@ func topicStoreTest(t *testing.T) {
|
||||
|
||||
// TODO: Add BulkGetMap() to the TopicStore
|
||||
|
||||
ok := topics.Exists(-1)
|
||||
ok := common.Topics.Exists(-1)
|
||||
if ok {
|
||||
t.Error("TID #-1 shouldn't exist")
|
||||
}
|
||||
|
||||
ok = topics.Exists(0)
|
||||
ok = common.Topics.Exists(0)
|
||||
if ok {
|
||||
t.Error("TID #0 shouldn't exist")
|
||||
}
|
||||
|
||||
ok = topics.Exists(1)
|
||||
ok = common.Topics.Exists(1)
|
||||
if !ok {
|
||||
t.Error("TID #1 should exist")
|
||||
}
|
||||
|
||||
count := topics.GlobalCount()
|
||||
count := common.Topics.GlobalCount()
|
||||
if count <= 0 {
|
||||
t.Error("The number of topics should be bigger than zero")
|
||||
t.Error("count", count)
|
||||
@ -620,11 +622,11 @@ func TestGroupStore(t *testing.T) {
|
||||
initPlugins()
|
||||
}
|
||||
|
||||
_, err := gstore.Get(-1)
|
||||
_, err := common.Gstore.Get(-1)
|
||||
recordMustNotExist(t, err, "GID #-1 shouldn't exist")
|
||||
|
||||
// TODO: Refactor the group store to remove GID #0
|
||||
group, err := gstore.Get(0)
|
||||
group, err := common.Gstore.Get(0)
|
||||
recordMustExist(t, err, "Couldn't find GID #0")
|
||||
|
||||
if group.ID != 0 {
|
||||
@ -632,31 +634,31 @@ func TestGroupStore(t *testing.T) {
|
||||
}
|
||||
expect(t, group.Name == "Unknown", fmt.Sprintf("GID #0 is named '%s' and not 'Unknown'", group.Name))
|
||||
|
||||
group, err = gstore.Get(1)
|
||||
group, err = common.Gstore.Get(1)
|
||||
recordMustExist(t, err, "Couldn't find GID #1")
|
||||
|
||||
if group.ID != 1 {
|
||||
t.Errorf("group.ID doesn't not match the requested GID. Got '%d' instead.'", group.ID)
|
||||
}
|
||||
|
||||
ok := gstore.Exists(-1)
|
||||
ok := common.Gstore.Exists(-1)
|
||||
expect(t, !ok, "GID #-1 shouldn't exist")
|
||||
|
||||
// 0 aka Unknown, for system posts and other oddities
|
||||
ok = gstore.Exists(0)
|
||||
ok = common.Gstore.Exists(0)
|
||||
expect(t, ok, "GID #0 should exist")
|
||||
|
||||
ok = gstore.Exists(1)
|
||||
ok = common.Gstore.Exists(1)
|
||||
expect(t, ok, "GID #1 should exist")
|
||||
|
||||
var isAdmin = true
|
||||
var isMod = true
|
||||
var isBanned = false
|
||||
gid, err := gstore.Create("Testing", "Test", isAdmin, isMod, isBanned)
|
||||
gid, err := common.Gstore.Create("Testing", "Test", isAdmin, isMod, isBanned)
|
||||
expectNilErr(t, err)
|
||||
expect(t, gstore.Exists(gid), "The group we just made doesn't exist")
|
||||
expect(t, common.Gstore.Exists(gid), "The group we just made doesn't exist")
|
||||
|
||||
group, err = gstore.Get(gid)
|
||||
group, err = common.Gstore.Get(gid)
|
||||
expectNilErr(t, err)
|
||||
expect(t, group.ID == gid, "The group ID should match the requested ID")
|
||||
expect(t, group.IsAdmin, "This should be an admin group")
|
||||
@ -666,11 +668,11 @@ func TestGroupStore(t *testing.T) {
|
||||
isAdmin = false
|
||||
isMod = true
|
||||
isBanned = true
|
||||
gid, err = gstore.Create("Testing 2", "Test", isAdmin, isMod, isBanned)
|
||||
gid, err = common.Gstore.Create("Testing 2", "Test", isAdmin, isMod, isBanned)
|
||||
expectNilErr(t, err)
|
||||
expect(t, gstore.Exists(gid), "The group we just made doesn't exist")
|
||||
expect(t, common.Gstore.Exists(gid), "The group we just made doesn't exist")
|
||||
|
||||
group, err = gstore.Get(gid)
|
||||
group, err = common.Gstore.Get(gid)
|
||||
expectNilErr(t, err)
|
||||
expect(t, group.ID == gid, "The group ID should match the requested ID")
|
||||
expect(t, !group.IsAdmin, "This should not be an admin group")
|
||||
@ -681,7 +683,7 @@ func TestGroupStore(t *testing.T) {
|
||||
err = group.ChangeRank(false, false, true)
|
||||
expectNilErr(t, err)
|
||||
|
||||
group, err = gstore.Get(gid)
|
||||
group, err = common.Gstore.Get(gid)
|
||||
expectNilErr(t, err)
|
||||
expect(t, group.ID == gid, "The group ID should match the requested ID")
|
||||
expect(t, !group.IsAdmin, "This shouldn't be an admin group")
|
||||
@ -691,7 +693,7 @@ func TestGroupStore(t *testing.T) {
|
||||
err = group.ChangeRank(true, true, true)
|
||||
expectNilErr(t, err)
|
||||
|
||||
group, err = gstore.Get(gid)
|
||||
group, err = common.Gstore.Get(gid)
|
||||
expectNilErr(t, err)
|
||||
expect(t, group.ID == gid, "The group ID should match the requested ID")
|
||||
expect(t, group.IsAdmin, "This should be an admin group")
|
||||
@ -701,7 +703,7 @@ func TestGroupStore(t *testing.T) {
|
||||
err = group.ChangeRank(false, true, true)
|
||||
expectNilErr(t, err)
|
||||
|
||||
group, err = gstore.Get(gid)
|
||||
group, err = common.Gstore.Get(gid)
|
||||
expectNilErr(t, err)
|
||||
expect(t, group.ID == gid, "The group ID should match the requested ID")
|
||||
expect(t, !group.IsAdmin, "This shouldn't be an admin group")
|
||||
@ -709,9 +711,9 @@ func TestGroupStore(t *testing.T) {
|
||||
expect(t, !group.IsBanned, "This shouldn't be a ban group")
|
||||
|
||||
// Make sure the data is static
|
||||
gstore.Reload(gid)
|
||||
common.Gstore.Reload(gid)
|
||||
|
||||
group, err = gstore.Get(gid)
|
||||
group, err = common.Gstore.Get(gid)
|
||||
expectNilErr(t, err)
|
||||
expect(t, group.ID == gid, "The group ID should match the requested ID")
|
||||
expect(t, !group.IsAdmin, "This shouldn't be an admin group")
|
||||
@ -731,13 +733,13 @@ func TestReplyStore(t *testing.T) {
|
||||
initPlugins()
|
||||
}
|
||||
|
||||
_, err := rstore.Get(-1)
|
||||
_, err := common.Rstore.Get(-1)
|
||||
recordMustNotExist(t, err, "RID #-1 shouldn't exist")
|
||||
|
||||
_, err = rstore.Get(0)
|
||||
_, err = common.Rstore.Get(0)
|
||||
recordMustNotExist(t, err, "RID #0 shouldn't exist")
|
||||
|
||||
reply, err := rstore.Get(1)
|
||||
reply, err := common.Rstore.Get(1)
|
||||
expectNilErr(t, err)
|
||||
expect(t, reply.ID == 1, fmt.Sprintf("RID #1 has the wrong ID. It should be 1 not %d", reply.ID))
|
||||
expect(t, reply.ParentID == 1, fmt.Sprintf("The parent topic of RID #1 should be 1 not %d", reply.ParentID))
|
||||
@ -745,18 +747,18 @@ func TestReplyStore(t *testing.T) {
|
||||
expect(t, reply.Content == "A reply!", fmt.Sprintf("The contents of RID #1 should be 'A reply!' not %s", reply.Content))
|
||||
expect(t, reply.IPAddress == "::1", fmt.Sprintf("The IPAddress of RID#1 should be '::1' not %s", reply.IPAddress))
|
||||
|
||||
_, err = rstore.Get(2)
|
||||
_, err = common.Rstore.Get(2)
|
||||
recordMustNotExist(t, err, "RID #2 shouldn't exist")
|
||||
|
||||
// TODO: Test Create and Get
|
||||
//Create(tid int, content string, ipaddress string, fid int, uid int) (id int, err error)
|
||||
topic, err := topics.Get(1)
|
||||
topic, err := common.Topics.Get(1)
|
||||
expectNilErr(t, err)
|
||||
rid, err := rstore.Create(topic, "Fofofo", "::1", 1)
|
||||
rid, err := common.Rstore.Create(topic, "Fofofo", "::1", 1)
|
||||
expectNilErr(t, err)
|
||||
expect(t, rid == 2, fmt.Sprintf("The next reply ID should be 2 not %d", rid))
|
||||
|
||||
reply, err = rstore.Get(2)
|
||||
reply, err = common.Rstore.Get(2)
|
||||
expectNilErr(t, err)
|
||||
expect(t, reply.ID == 2, fmt.Sprintf("RID #2 has the wrong ID. It should be 2 not %d", reply.ID))
|
||||
expect(t, reply.ParentID == 1, fmt.Sprintf("The parent topic of RID #2 should be 1 not %d", reply.ParentID))
|
||||
@ -773,21 +775,21 @@ func TestProfileReplyStore(t *testing.T) {
|
||||
initPlugins()
|
||||
}
|
||||
|
||||
_, err := prstore.Get(-1)
|
||||
_, err := common.Prstore.Get(-1)
|
||||
recordMustNotExist(t, err, "PRID #-1 shouldn't exist")
|
||||
|
||||
_, err = prstore.Get(0)
|
||||
_, err = common.Prstore.Get(0)
|
||||
recordMustNotExist(t, err, "PRID #0 shouldn't exist")
|
||||
|
||||
_, err = prstore.Get(1)
|
||||
_, err = common.Prstore.Get(1)
|
||||
recordMustNotExist(t, err, "PRID #1 shouldn't exist")
|
||||
|
||||
var profileID = 1
|
||||
prid, err := prstore.Create(profileID, "Haha", 1, "::1")
|
||||
prid, err := common.Prstore.Create(profileID, "Haha", 1, "::1")
|
||||
expect(t, err == nil, "Unable to create a profile reply")
|
||||
expect(t, prid == 1, "The first profile reply should have an ID of 1")
|
||||
|
||||
profileReply, err := prstore.Get(1)
|
||||
profileReply, err := common.Prstore.Get(1)
|
||||
expect(t, err == nil, "PRID #1 should exist")
|
||||
expect(t, profileReply.ID == 1, fmt.Sprintf("The profile reply should have an ID of 1 not %d", profileReply.ID))
|
||||
expect(t, profileReply.ParentID == 1, fmt.Sprintf("The parent ID of the profile reply should be 1 not %d", profileReply.ParentID))
|
||||
@ -826,7 +828,7 @@ func TestSlugs(t *testing.T) {
|
||||
|
||||
for _, item := range msgList {
|
||||
t.Log("Testing string '" + item.Msg + "'")
|
||||
res = nameToSlug(item.Msg)
|
||||
res = common.NameToSlug(item.Msg)
|
||||
if res != item.Expects {
|
||||
t.Error("Bad output:", "'"+res+"'")
|
||||
t.Error("Expected:", item.Expects)
|
||||
@ -846,7 +848,7 @@ func TestAuth(t *testing.T) {
|
||||
realPassword = "Madame Cassandra's Mystic Orb"
|
||||
t.Log("Set realPassword to '" + realPassword + "'")
|
||||
t.Log("Hashing the real password")
|
||||
hashedPassword, err = BcryptGeneratePasswordNoSalt(realPassword)
|
||||
hashedPassword, err = common.BcryptGeneratePasswordNoSalt(realPassword)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -854,7 +856,7 @@ func TestAuth(t *testing.T) {
|
||||
password = realPassword
|
||||
t.Log("Testing password '" + password + "'")
|
||||
t.Log("Testing salt '" + salt + "'")
|
||||
err = CheckPassword(hashedPassword, password, salt)
|
||||
err = common.CheckPassword(hashedPassword, password, salt)
|
||||
if err == ErrMismatchedHashAndPassword {
|
||||
t.Error("The two don't match")
|
||||
} else if err == ErrPasswordTooLong {
|
||||
@ -866,7 +868,7 @@ func TestAuth(t *testing.T) {
|
||||
password = "hahaha"
|
||||
t.Log("Testing password '" + password + "'")
|
||||
t.Log("Testing salt '" + salt + "'")
|
||||
err = CheckPassword(hashedPassword, password, salt)
|
||||
err = common.CheckPassword(hashedPassword, password, salt)
|
||||
if err == ErrPasswordTooLong {
|
||||
t.Error("CheckPassword thinks the password is too long")
|
||||
} else if err == nil {
|
||||
@ -876,7 +878,7 @@ func TestAuth(t *testing.T) {
|
||||
password = "Madame Cassandra's Mystic"
|
||||
t.Log("Testing password '" + password + "'")
|
||||
t.Log("Testing salt '" + salt + "'")
|
||||
err = CheckPassword(hashedPassword, password, salt)
|
||||
err = common.CheckPassword(hashedPassword, password, salt)
|
||||
if err == ErrPasswordTooLong {
|
||||
t.Error("CheckPassword thinks the password is too long")
|
||||
} else if err == nil {
|
||||
|
364
mod_routes.go
364
mod_routes.go
@ -9,48 +9,50 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
// 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 routeEditTopic(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeEditTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return PreError("Bad Form", w, r)
|
||||
return common.PreError("Bad Form", w, r)
|
||||
}
|
||||
isJs := (r.PostFormValue("js") == "1")
|
||||
|
||||
tid, err := strconv.Atoi(r.URL.Path[len("/topic/edit/submit/"):])
|
||||
if err != nil {
|
||||
return PreErrorJSQ("The provided TopicID is not a valid number.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The provided TopicID is not a valid number.", w, r, isJs)
|
||||
}
|
||||
|
||||
topic, err := topics.Get(tid)
|
||||
topic, err := common.Topics.Get(tid)
|
||||
if err == ErrNoRows {
|
||||
return PreErrorJSQ("The topic you tried to edit doesn't exist.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The topic you tried to edit doesn't exist.", w, r, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.EditTopic {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
topicName := r.PostFormValue("topic_name")
|
||||
topicContent := html.EscapeString(r.PostFormValue("topic_content"))
|
||||
err = topic.Update(topicName, topicContent)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
err = fstore.UpdateLastTopic(topic.ID, user.ID, topic.ParentID)
|
||||
err = common.Fstore.UpdateLastTopic(topic.ID, user.ID, topic.ParentID)
|
||||
if err != nil && err != ErrNoRows {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
if !isJs {
|
||||
@ -63,204 +65,204 @@ func routeEditTopic(w http.ResponseWriter, r *http.Request, user User) RouteErro
|
||||
|
||||
// TODO: Add support for soft-deletion and add a permission for hard delete in addition to the usual
|
||||
// TODO: Disable stat updates in posts handled by plugin_guilds
|
||||
func routeDeleteTopic(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeDeleteTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
// TODO: Move this to some sort of middleware
|
||||
var tids []int
|
||||
var isJs = false
|
||||
if r.Header.Get("Content-type") == "application/json" {
|
||||
if r.Body == nil {
|
||||
return PreErrorJS("No request body", w, r)
|
||||
return common.PreErrorJS("No request body", w, r)
|
||||
}
|
||||
//log.Print("r.Body: ", r.Body)
|
||||
err := json.NewDecoder(r.Body).Decode(&tids)
|
||||
if err != nil {
|
||||
//log.Print("parse err: ", err)
|
||||
return PreErrorJS("We weren't able to parse your data", w, r)
|
||||
return common.PreErrorJS("We weren't able to parse your data", w, r)
|
||||
}
|
||||
isJs = true
|
||||
} else {
|
||||
tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):])
|
||||
if err != nil {
|
||||
return PreError("The provided TopicID is not a valid number.", w, r)
|
||||
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
||||
}
|
||||
tids = append(tids, tid)
|
||||
}
|
||||
if len(tids) == 0 {
|
||||
return LocalErrorJSQ("You haven't provided any IDs", w, r, user, isJs)
|
||||
return common.LocalErrorJSQ("You haven't provided any IDs", w, r, user, isJs)
|
||||
}
|
||||
|
||||
for _, tid := range tids {
|
||||
topic, err := topics.Get(tid)
|
||||
topic, err := common.Topics.Get(tid)
|
||||
if err == ErrNoRows {
|
||||
return PreErrorJSQ("The topic you tried to delete doesn't exist.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The topic you tried to delete doesn't exist.", w, r, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.DeleteTopic {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
// We might be able to handle this err better
|
||||
err = topic.Delete()
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
err = addModLog("delete", tid, "topic", user.LastIP, user.ID)
|
||||
err = common.AddModLog("delete", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// ? - We might need to add soft-delete before we can do an action reply for this
|
||||
/*_, err = stmts.createActionReply.Exec(tid,"delete",ipaddress,user.ID)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err,w,r,isJs)
|
||||
return common.InternalErrorJSQ(err,w,r,isJs)
|
||||
}*/
|
||||
|
||||
log.Printf("Topic #%d was deleted by User #%d", tid, user.ID)
|
||||
log.Printf("Topic #%d was deleted by common.User #%d", tid, user.ID)
|
||||
}
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeStickTopic(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeStickTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):])
|
||||
if err != nil {
|
||||
return PreError("The provided TopicID is not a valid number.", w, r)
|
||||
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
||||
}
|
||||
|
||||
topic, err := topics.Get(tid)
|
||||
topic, err := common.Topics.Get(tid)
|
||||
if err == ErrNoRows {
|
||||
return PreError("The topic you tried to pin doesn't exist.", w, r)
|
||||
return common.PreError("The topic you tried to pin doesn't exist.", w, r)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
err = topic.Stick()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = addModLog("stick", tid, "topic", user.LastIP, user.ID)
|
||||
err = common.AddModLog("stick", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("stick", user.LastIP, user)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeUnstickTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):])
|
||||
if err != nil {
|
||||
return PreError("The provided TopicID is not a valid number.", w, r)
|
||||
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
||||
}
|
||||
|
||||
topic, err := topics.Get(tid)
|
||||
topic, err := common.Topics.Get(tid)
|
||||
if err == ErrNoRows {
|
||||
return PreError("The topic you tried to unpin doesn't exist.", w, r)
|
||||
return common.PreError("The topic you tried to unpin doesn't exist.", w, r)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
err = topic.Unstick()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = addModLog("unstick", tid, "topic", user.LastIP, user.ID)
|
||||
err = common.AddModLog("unstick", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("unstick", user.LastIP, user)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeLockTopic(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeLockTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
// TODO: Move this to some sort of middleware
|
||||
var tids []int
|
||||
var isJs = false
|
||||
if r.Header.Get("Content-type") == "application/json" {
|
||||
if r.Body == nil {
|
||||
return PreErrorJS("No request body", w, r)
|
||||
return common.PreErrorJS("No request body", w, r)
|
||||
}
|
||||
err := json.NewDecoder(r.Body).Decode(&tids)
|
||||
if err != nil {
|
||||
return PreErrorJS("We weren't able to parse your data", w, r)
|
||||
return common.PreErrorJS("We weren't able to parse your data", w, r)
|
||||
}
|
||||
isJs = true
|
||||
} else {
|
||||
tid, err := strconv.Atoi(r.URL.Path[len("/topic/lock/submit/"):])
|
||||
if err != nil {
|
||||
return PreError("The provided TopicID is not a valid number.", w, r)
|
||||
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
||||
}
|
||||
tids = append(tids, tid)
|
||||
}
|
||||
if len(tids) == 0 {
|
||||
return LocalErrorJSQ("You haven't provided any IDs", w, r, user, isJs)
|
||||
return common.LocalErrorJSQ("You haven't provided any IDs", w, r, user, isJs)
|
||||
}
|
||||
|
||||
for _, tid := range tids {
|
||||
topic, err := topics.Get(tid)
|
||||
topic, err := common.Topics.Get(tid)
|
||||
if err == ErrNoRows {
|
||||
return PreErrorJSQ("The topic you tried to lock doesn't exist.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The topic you tried to lock doesn't exist.", w, r, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.CloseTopic {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
err = topic.Lock()
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
err = addModLog("lock", tid, "topic", user.LastIP, user.ID)
|
||||
err = common.AddModLog("lock", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
err = topic.CreateActionReply("lock", user.LastIP, user)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,40 +272,40 @@ func routeLockTopic(w http.ResponseWriter, r *http.Request, user User) RouteErro
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeUnlockTopic(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeUnlockTopic(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
tid, err := strconv.Atoi(r.URL.Path[len("/topic/unlock/submit/"):])
|
||||
if err != nil {
|
||||
return PreError("The provided TopicID is not a valid number.", w, r)
|
||||
return common.PreError("The provided TopicID is not a valid number.", w, r)
|
||||
}
|
||||
|
||||
topic, err := topics.Get(tid)
|
||||
topic, err := common.Topics.Get(tid)
|
||||
if err == ErrNoRows {
|
||||
return PreError("The topic you tried to unlock doesn't exist.", w, r)
|
||||
return common.PreError("The topic you tried to unlock doesn't exist.", w, r)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.CloseTopic {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
err = topic.Unlock()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = addModLog("unlock", tid, "topic", user.LastIP, user.ID)
|
||||
err = common.AddModLog("unlock", tid, "topic", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
err = topic.CreateActionReply("unlock", user.LastIP, user)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
||||
@ -312,46 +314,46 @@ func routeUnlockTopic(w http.ResponseWriter, r *http.Request, user User) RouteEr
|
||||
|
||||
// TODO: Disable stat updates in posts handled by plugin_guilds
|
||||
// TODO: Update the stats after edits so that we don't under or over decrement stats during deletes
|
||||
func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return PreError("Bad Form", w, r)
|
||||
return common.PreError("Bad Form", w, r)
|
||||
}
|
||||
isJs := (r.PostFormValue("js") == "1")
|
||||
|
||||
rid, err := strconv.Atoi(r.URL.Path[len("/reply/edit/submit/"):])
|
||||
if err != nil {
|
||||
return PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
||||
}
|
||||
|
||||
// Get the Reply ID..
|
||||
var tid int
|
||||
err = stmts.getReplyTID.QueryRow(rid).Scan(&tid)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
var fid int
|
||||
err = stmts.getTopicFID.QueryRow(tid).Scan(&fid)
|
||||
if err == ErrNoRows {
|
||||
return PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, fid)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, fid)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.EditReply {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item")))
|
||||
_, err = stmts.editReply.Exec(content, parseMessage(content, fid, "forums"), rid)
|
||||
content := html.EscapeString(common.PreparseMessage(r.PostFormValue("edit_item")))
|
||||
_, err = stmts.editReply.Exec(content, common.ParseMessage(content, fid, "forums"), rid)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
if !isJs {
|
||||
@ -364,99 +366,99 @@ func routeReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) Rou
|
||||
|
||||
// TODO: Refactor this
|
||||
// TODO: Disable stat updates in posts handled by plugin_guilds
|
||||
func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return PreError("Bad Form", w, r)
|
||||
return common.PreError("Bad Form", w, r)
|
||||
}
|
||||
isJs := (r.PostFormValue("isJs") == "1")
|
||||
|
||||
rid, err := strconv.Atoi(r.URL.Path[len("/reply/delete/submit/"):])
|
||||
if err != nil {
|
||||
return PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The provided Reply ID is not a valid number.", w, r, isJs)
|
||||
}
|
||||
|
||||
reply, err := rstore.Get(rid)
|
||||
reply, err := common.Rstore.Get(rid)
|
||||
if err == ErrNoRows {
|
||||
return PreErrorJSQ("The reply you tried to delete doesn't exist.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The reply you tried to delete doesn't exist.", w, r, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
var fid int
|
||||
err = stmts.getTopicFID.QueryRow(reply.ParentID).Scan(&fid)
|
||||
if err == ErrNoRows {
|
||||
return PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
||||
return common.PreErrorJSQ("The parent topic doesn't exist.", w, r, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
// TODO: Add hooks to make use of headerLite
|
||||
_, ferr := SimpleForumUserCheck(w, r, &user, fid)
|
||||
_, ferr := common.SimpleForumUserCheck(w, r, &user, fid)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
}
|
||||
if !user.Perms.ViewTopic || !user.Perms.DeleteReply {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
err = reply.Delete()
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
//log.Printf("Reply #%d was deleted by User #%d", rid, user.ID)
|
||||
//log.Printf("Reply #%d was deleted by common.User #%d", rid, user.ID)
|
||||
if !isJs {
|
||||
//http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther)
|
||||
} else {
|
||||
w.Write(successJSONBytes)
|
||||
}
|
||||
|
||||
replyCreator, err := users.Get(reply.CreatedBy)
|
||||
replyCreator, err := common.Users.Get(reply.CreatedBy)
|
||||
if err == nil {
|
||||
wcount := wordCount(reply.Content)
|
||||
err = replyCreator.decreasePostStats(wcount, false)
|
||||
wcount := common.WordCount(reply.Content)
|
||||
err = replyCreator.DecreasePostStats(wcount, false)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
} else if err != ErrNoRows {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
err = addModLog("delete", reply.ParentID, "reply", user.LastIP, user.ID)
|
||||
err = common.AddModLog("delete", reply.ParentID, "reply", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return LocalError("Bad Form", w, r, user)
|
||||
return common.LocalError("Bad Form", w, r, user)
|
||||
}
|
||||
isJs := (r.PostFormValue("js") == "1")
|
||||
|
||||
rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/edit/submit/"):])
|
||||
if err != nil {
|
||||
return LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs)
|
||||
return common.LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs)
|
||||
}
|
||||
|
||||
// Get the Reply ID..
|
||||
var uid int
|
||||
err = stmts.getUserReplyUID.QueryRow(rid).Scan(&uid)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
if user.ID != uid && !user.Perms.EditReply {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
content := html.EscapeString(preparseMessage(r.PostFormValue("edit_item")))
|
||||
_, err = stmts.editProfileReply.Exec(content, parseMessage(content, 0, ""), rid)
|
||||
content := html.EscapeString(common.PreparseMessage(r.PostFormValue("edit_item")))
|
||||
_, err = stmts.editProfileReply.Exec(content, common.ParseMessage(content, 0, ""), rid)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
if !isJs {
|
||||
@ -467,35 +469,35 @@ func routeProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user Us
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
return LocalError("Bad Form", w, r, user)
|
||||
return common.LocalError("Bad Form", w, r, user)
|
||||
}
|
||||
isJs := (r.PostFormValue("isJs") == "1")
|
||||
|
||||
rid, err := strconv.Atoi(r.URL.Path[len("/profile/reply/delete/submit/"):])
|
||||
if err != nil {
|
||||
return LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs)
|
||||
return common.LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, user, isJs)
|
||||
}
|
||||
|
||||
var uid int
|
||||
err = stmts.getUserReplyUID.QueryRow(rid).Scan(&uid)
|
||||
if err == ErrNoRows {
|
||||
return LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs)
|
||||
return common.LocalErrorJSQ("The reply you tried to delete doesn't exist.", w, r, user, isJs)
|
||||
} else if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
|
||||
if user.ID != uid && !user.Perms.DeleteReply {
|
||||
return NoPermissionsJSQ(w, r, user, isJs)
|
||||
return common.NoPermissionsJSQ(w, r, user, isJs)
|
||||
}
|
||||
|
||||
_, err = stmts.deleteProfileReply.Exec(rid)
|
||||
if err != nil {
|
||||
return InternalErrorJSQ(err, w, r, isJs)
|
||||
return common.InternalErrorJSQ(err, w, r, isJs)
|
||||
}
|
||||
//log.Printf("The profile post '%d' was deleted by User #%d", rid, user.ID)
|
||||
//log.Printf("The profile post '%d' was deleted by common.User #%d", rid, user.ID)
|
||||
|
||||
if !isJs {
|
||||
//http.Redirect(w,r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther)
|
||||
@ -505,13 +507,13 @@ func routeProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeIps(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
headerVars, ferr := UserCheck(w, r, &user)
|
||||
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 NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
var ip = r.FormValue("ip")
|
||||
@ -520,56 +522,56 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
|
||||
rows, err := stmts.findUsersByIPUsers.Query(ip)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&uid)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
rows2, err := stmts.findUsersByIPTopics.Query(ip)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows2.Close()
|
||||
|
||||
for rows2.Next() {
|
||||
err := rows2.Scan(&uid)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
err = rows2.Err()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
rows3, err := stmts.findUsersByIPReplies.Query(ip)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
defer rows3.Close()
|
||||
|
||||
for rows3.Next() {
|
||||
err := rows3.Scan(&uid)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
reqUserList[uid] = true
|
||||
}
|
||||
err = rows3.Err()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// Convert the user ID map to a slice, then bulk load the users
|
||||
@ -581,68 +583,68 @@ func routeIps(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
}
|
||||
|
||||
// TODO: What if a user is deleted via the Control Panel?
|
||||
userList, err := users.BulkGetMap(idSlice)
|
||||
userList, err := common.Users.BulkGetMap(idSlice)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
pi := IPSearchPage{"IP Search", user, headerVars, userList, ip}
|
||||
if preRenderHooks["pre_render_ips"] != nil {
|
||||
if runPreRenderHook("pre_render_ips", w, r, &user, &pi) {
|
||||
pi := common.IPSearchPage{"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 = templates.ExecuteTemplate(w, "ip-search.html", pi)
|
||||
err = common.Templates.ExecuteTemplate(w, "ip-search.html", pi)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeBanSubmit(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeBanSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
if !user.Perms.BanUsers {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
uid, err := strconv.Atoi(r.URL.Path[len("/users/ban/submit/"):])
|
||||
if err != nil {
|
||||
return LocalError("The provided User ID is not a valid number.", w, r, user)
|
||||
return common.LocalError("The provided common.User ID is not a valid number.", w, r, user)
|
||||
}
|
||||
/*if uid == -2 {
|
||||
return LocalError("Stop trying to ban Merlin! Ban admin! Bad! No!",w,r,user)
|
||||
return common.LocalError("Stop trying to ban Merlin! Ban admin! Bad! No!",w,r,user)
|
||||
}*/
|
||||
|
||||
targetUser, err := users.Get(uid)
|
||||
targetUser, err := common.Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
return LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
||||
return common.LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
// TODO: Is there a difference between IsMod and IsSuperMod? Should we delete the redundant one?
|
||||
if targetUser.IsSuperAdmin || targetUser.IsAdmin || targetUser.IsMod {
|
||||
return LocalError("You may not ban another staff member.", w, r, user)
|
||||
return common.LocalError("You may not ban another staff member.", w, r, user)
|
||||
}
|
||||
if uid == user.ID {
|
||||
return LocalError("Why are you trying to ban yourself? Stop that.", w, r, user)
|
||||
return common.LocalError("Why are you trying to ban yourself? Stop that.", w, r, user)
|
||||
}
|
||||
if targetUser.IsBanned {
|
||||
return LocalError("The user you're trying to unban is already banned.", w, r, user)
|
||||
return common.LocalError("The user you're trying to unban is already banned.", w, r, user)
|
||||
}
|
||||
|
||||
durationDays, err := strconv.Atoi(r.FormValue("ban-duration-days"))
|
||||
if err != nil {
|
||||
return LocalError("You can only use whole numbers for the number of days", w, r, user)
|
||||
return common.LocalError("You can only use whole numbers for the number of days", w, r, user)
|
||||
}
|
||||
|
||||
durationWeeks, err := strconv.Atoi(r.FormValue("ban-duration-weeks"))
|
||||
if err != nil {
|
||||
return LocalError("You can only use whole numbers for the number of weeks", w, r, user)
|
||||
return common.LocalError("You can only use whole numbers for the number of weeks", w, r, user)
|
||||
}
|
||||
|
||||
durationMonths, err := strconv.Atoi(r.FormValue("ban-duration-months"))
|
||||
if err != nil {
|
||||
return LocalError("You can only use whole numbers for the number of months", w, r, user)
|
||||
return common.LocalError("You can only use whole numbers for the number of months", w, r, user)
|
||||
}
|
||||
|
||||
var duration time.Duration
|
||||
@ -650,95 +652,95 @@ func routeBanSubmit(w http.ResponseWriter, r *http.Request, user User) RouteErro
|
||||
duration, _ = time.ParseDuration("0")
|
||||
} else {
|
||||
var seconds int
|
||||
seconds += durationDays * day
|
||||
seconds += durationWeeks * week
|
||||
seconds += durationMonths * month
|
||||
seconds += durationDays * common.Day
|
||||
seconds += durationWeeks * common.Week
|
||||
seconds += durationMonths * common.Month
|
||||
duration, _ = time.ParseDuration(strconv.Itoa(seconds) + "s")
|
||||
}
|
||||
|
||||
err = targetUser.Ban(duration, user.ID)
|
||||
if err == ErrNoRows {
|
||||
return LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
||||
return common.LocalError("The user you're trying to ban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = addModLog("ban", uid, "user", user.LastIP, user.ID)
|
||||
err = common.AddModLog("ban", uid, "user", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeUnban(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeUnban(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
if !user.Perms.BanUsers {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
uid, err := strconv.Atoi(r.URL.Path[len("/users/unban/"):])
|
||||
if err != nil {
|
||||
return LocalError("The provided User ID is not a valid number.", w, r, user)
|
||||
return common.LocalError("The provided common.User ID is not a valid number.", w, r, user)
|
||||
}
|
||||
|
||||
targetUser, err := users.Get(uid)
|
||||
targetUser, err := common.Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
return LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
||||
return common.LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
if !targetUser.IsBanned {
|
||||
return LocalError("The user you're trying to unban isn't banned.", w, r, user)
|
||||
return common.LocalError("The user you're trying to unban isn't banned.", w, r, user)
|
||||
}
|
||||
|
||||
err = targetUser.Unban()
|
||||
if err == ErrNoTempGroup {
|
||||
return LocalError("The user you're trying to unban is not banned", w, r, user)
|
||||
if err == common.ErrNoTempGroup {
|
||||
return common.LocalError("The user you're trying to unban is not banned", w, r, user)
|
||||
} else if err == ErrNoRows {
|
||||
return LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
||||
return common.LocalError("The user you're trying to unban no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = addModLog("unban", uid, "user", user.LastIP, user.ID)
|
||||
err = common.AddModLog("unban", uid, "user", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)
|
||||
return nil
|
||||
}
|
||||
|
||||
func routeActivate(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeActivate(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
if !user.Perms.ActivateUsers {
|
||||
return NoPermissions(w, r, user)
|
||||
return common.NoPermissions(w, r, user)
|
||||
}
|
||||
|
||||
uid, err := strconv.Atoi(r.URL.Path[len("/users/activate/"):])
|
||||
if err != nil {
|
||||
return LocalError("The provided User ID is not a valid number.", w, r, user)
|
||||
return common.LocalError("The provided common.User ID is not a valid number.", w, r, user)
|
||||
}
|
||||
|
||||
targetUser, err := users.Get(uid)
|
||||
targetUser, err := common.Users.Get(uid)
|
||||
if err == ErrNoRows {
|
||||
return LocalError("The account you're trying to activate no longer exists.", w, r, user)
|
||||
return common.LocalError("The account you're trying to activate no longer exists.", w, r, user)
|
||||
} else if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
if targetUser.Active {
|
||||
return LocalError("The account you're trying to activate has already been activated.", w, r, user)
|
||||
return common.LocalError("The account you're trying to activate has already been activated.", w, r, user)
|
||||
}
|
||||
err = targetUser.Activate()
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
|
||||
err = addModLog("activate", targetUser.ID, "user", user.LastIP, user.ID)
|
||||
err = common.AddModLog("activate", targetUser.ID, "user", user.LastIP, user.ID)
|
||||
if err != nil {
|
||||
return InternalError(err, w, r)
|
||||
return common.InternalError(err, w, r)
|
||||
}
|
||||
http.Redirect(w, r, "/user/"+strconv.Itoa(targetUser.ID), http.StatusSeeOther)
|
||||
return nil
|
||||
|
20
mysql.go
20
mysql.go
@ -8,12 +8,16 @@
|
||||
*/
|
||||
package main
|
||||
|
||||
import "log"
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
//import "time"
|
||||
import "database/sql"
|
||||
import _ "github.com/go-sql-driver/mysql"
|
||||
import "./query_gen/lib"
|
||||
//import "time"
|
||||
|
||||
"./common"
|
||||
"./query_gen/lib"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var dbCollation = "utf8mb4_general_ci"
|
||||
|
||||
@ -24,13 +28,13 @@ func init() {
|
||||
|
||||
func initMySQL() (err error) {
|
||||
var _dbpassword string
|
||||
if dbConfig.Password != "" {
|
||||
_dbpassword = ":" + dbConfig.Password
|
||||
if common.DbConfig.Password != "" {
|
||||
_dbpassword = ":" + common.DbConfig.Password
|
||||
}
|
||||
|
||||
// TODO: Move this bit to the query gen lib
|
||||
// Open the database connection
|
||||
db, err = sql.Open("mysql", dbConfig.Username+_dbpassword+"@tcp("+dbConfig.Host+":"+dbConfig.Port+")/"+dbConfig.Dbname+"?collation="+dbCollation+"&parseTime=true")
|
||||
db, err = sql.Open("mysql", common.DbConfig.Username+_dbpassword+"@tcp("+common.DbConfig.Host+":"+common.DbConfig.Port+")/"+common.DbConfig.Dbname+"?collation="+dbCollation+"&parseTime=true")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
1058
panel_routes.go
1058
panel_routes.go
File diff suppressed because it is too large
Load Diff
@ -10,9 +10,11 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
var random *rand.Rand
|
||||
var bbcodeRandom *rand.Rand
|
||||
var bbcodeInvalidNumber []byte
|
||||
var bbcodeNoNegative []byte
|
||||
var bbcodeMissingTag []byte
|
||||
@ -27,12 +29,12 @@ var bbcodeQuotes *regexp.Regexp
|
||||
var bbcodeCode *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
plugins["bbcode"] = NewPlugin("bbcode", "BBCode", "Azareal", "http://github.com/Azareal", "", "", "", initBbcode, nil, deactivateBbcode, nil, nil)
|
||||
common.Plugins["bbcode"] = common.NewPlugin("bbcode", "BBCode", "Azareal", "http://github.com/Azareal", "", "", "", initBbcode, nil, deactivateBbcode, nil, nil)
|
||||
}
|
||||
|
||||
func initBbcode() error {
|
||||
//plugins["bbcode"].AddHook("parse_assign", bbcode_parse_without_code)
|
||||
plugins["bbcode"].AddHook("parse_assign", bbcodeFullParse)
|
||||
common.Plugins["bbcode"].AddHook("parse_assign", bbcodeFullParse)
|
||||
|
||||
bbcodeInvalidNumber = []byte("<span style='color: red;'>[Invalid Number]</span>")
|
||||
bbcodeNoNegative = []byte("<span style='color: red;'>[No Negative Numbers]</span>")
|
||||
@ -48,13 +50,12 @@ func initBbcode() error {
|
||||
bbcodeQuotes = regexp.MustCompile(`\[quote\](.*)\[/quote\]`)
|
||||
bbcodeCode = regexp.MustCompile(`\[code\](.*)\[/code\]`)
|
||||
|
||||
random = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
bbcodeRandom = rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func deactivateBbcode() {
|
||||
//plugins["bbcode"].RemoveHook("parse_assign", bbcode_parse_without_code)
|
||||
plugins["bbcode"].RemoveHook("parse_assign", bbcodeFullParse)
|
||||
common.Plugins["bbcode"].RemoveHook("parse_assign", bbcodeFullParse)
|
||||
}
|
||||
|
||||
func bbcodeRegexParse(msg string) string {
|
||||
@ -213,7 +214,7 @@ func bbcodeFullParse(msg string) string {
|
||||
var complexBbc bool
|
||||
|
||||
msgbytes := []byte(msg)
|
||||
msgbytes = append(msgbytes, spaceGap...)
|
||||
msgbytes = append(msgbytes, common.SpaceGap...)
|
||||
//log.Print("BBCode Simple Pre:","`"+string(msgbytes)+"`")
|
||||
//log.Print("----")
|
||||
|
||||
@ -306,7 +307,7 @@ func bbcodeFullParse(msg string) string {
|
||||
if hasS {
|
||||
msgbytes = append(bytes.TrimSpace(msgbytes), closeStrike...)
|
||||
}
|
||||
msgbytes = append(msgbytes, spaceGap...)
|
||||
msgbytes = append(msgbytes, common.SpaceGap...)
|
||||
}
|
||||
|
||||
if complexBbc {
|
||||
@ -357,21 +358,21 @@ func bbcodeParseURL(i int, start int, lastTag int, msgbytes []byte, outbytes []b
|
||||
start = i + 5
|
||||
outbytes = append(outbytes, msgbytes[lastTag:i]...)
|
||||
i = start
|
||||
i += partialURLBytesLen(msgbytes[start:])
|
||||
i += common.PartialURLBytesLen(msgbytes[start:])
|
||||
//log.Print("Partial Bytes: ", string(msgbytes[start:]))
|
||||
//log.Print("-----")
|
||||
if !bytes.Equal(msgbytes[i:i+6], []byte("[/url]")) {
|
||||
//log.Print("Invalid Bytes: ", string(msgbytes[i:i+6]))
|
||||
//log.Print("-----")
|
||||
outbytes = append(outbytes, invalidURL...)
|
||||
outbytes = append(outbytes, common.InvalidURL...)
|
||||
return i, start, lastTag, outbytes
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, urlOpen...)
|
||||
outbytes = append(outbytes, common.UrlOpen...)
|
||||
outbytes = append(outbytes, msgbytes[start:i]...)
|
||||
outbytes = append(outbytes, urlOpen2...)
|
||||
outbytes = append(outbytes, common.UrlOpen2...)
|
||||
outbytes = append(outbytes, msgbytes[start:i]...)
|
||||
outbytes = append(outbytes, urlClose...)
|
||||
outbytes = append(outbytes, common.UrlClose...)
|
||||
i += 6
|
||||
lastTag = i
|
||||
|
||||
@ -411,7 +412,7 @@ func bbcodeParseRand(i int, start int, lastTag int, msgbytes []byte, outbytes []
|
||||
if number == 0 {
|
||||
dat = []byte("0")
|
||||
} else {
|
||||
dat = []byte(strconv.FormatInt((random.Int63n(number)), 10))
|
||||
dat = []byte(strconv.FormatInt((bbcodeRandom.Int63n(number)), 10))
|
||||
}
|
||||
|
||||
outbytes = append(outbytes, dat...)
|
||||
|
100
plugin_guilds.go
100
plugin_guilds.go
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
//"fmt"
|
||||
|
||||
"./common"
|
||||
"./extend/guilds/lib"
|
||||
"./query_gen/lib"
|
||||
)
|
||||
@ -11,75 +12,58 @@ import (
|
||||
|
||||
// TODO: Add a plugin interface instead of having a bunch of argument to AddPlugin?
|
||||
func init() {
|
||||
plugins["guilds"] = NewPlugin("guilds", "Guilds", "Azareal", "http://github.com/Azareal", "", "", "", initGuilds, nil, deactivateGuilds, installGuilds, nil)
|
||||
common.Plugins["guilds"] = common.NewPlugin("guilds", "Guilds", "Azareal", "http://github.com/Azareal", "", "", "", initGuilds, nil, deactivateGuilds, installGuilds, nil)
|
||||
|
||||
// TODO: Is it possible to avoid doing this when the plugin isn't activated?
|
||||
prebuildTmplList = append(prebuildTmplList, guilds.PrebuildTmplList)
|
||||
common.PrebuildTmplList = append(common.PrebuildTmplList, guilds.PrebuildTmplList)
|
||||
}
|
||||
|
||||
func initGuilds() (err error) {
|
||||
plugins["guilds"].AddHook("intercept_build_widgets", guilds.Widgets)
|
||||
plugins["guilds"].AddHook("trow_assign", guilds.TrowAssign)
|
||||
plugins["guilds"].AddHook("topic_create_pre_loop", guilds.TopicCreatePreLoop)
|
||||
plugins["guilds"].AddHook("pre_render_view_forum", guilds.PreRenderViewForum)
|
||||
plugins["guilds"].AddHook("simple_forum_check_pre_perms", guilds.ForumCheck)
|
||||
plugins["guilds"].AddHook("forum_check_pre_perms", guilds.ForumCheck)
|
||||
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("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?
|
||||
registerPluginPerm("CreateGuild")
|
||||
router.HandleFunc("/guilds/", guilds.GuildList)
|
||||
router.HandleFunc("/guild/", guilds.ViewGuild)
|
||||
router.HandleFunc("/guild/create/", guilds.CreateGuild)
|
||||
router.HandleFunc("/guild/create/submit/", guilds.CreateGuildSubmit)
|
||||
router.HandleFunc("/guild/members/", guilds.MemberList)
|
||||
common.RegisterPluginPerm("CreateGuild")
|
||||
router.HandleFunc("/guilds/", guilds.RouteGuildList)
|
||||
router.HandleFunc("/guild/", guilds.MiddleViewGuild)
|
||||
router.HandleFunc("/guild/create/", guilds.RouteCreateGuild)
|
||||
router.HandleFunc("/guild/create/submit/", guilds.RouteCreateGuildSubmit)
|
||||
router.HandleFunc("/guild/members/", guilds.RouteMemberList)
|
||||
|
||||
guilds.ListStmt, err = qgen.Builder.SimpleSelect("guilds", "guildID, name, desc, active, privacy, joinable, owner, memberCount, createdAt, lastUpdateTime", "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.GetGuildStmt, err = qgen.Builder.SimpleSelect("guilds", "name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime", "guildID = ?", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.MemberListStmt, err = qgen.Builder.SimpleSelect("guilds_members", "guildID, uid, rank, posts, joinedAt", "", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.MemberListJoinStmt, err = qgen.Builder.SimpleLeftJoin("guilds_members", "users", "users.uid, guilds_members.rank, guilds_members.posts, guilds_members.joinedAt, users.name, users.avatar", "guilds_members.uid = users.uid", "guilds_members.guildID = ?", "guilds_members.rank DESC, guilds_members.joinedat ASC", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.GetMemberStmt, err = qgen.Builder.SimpleSelect("guilds_members", "rank, posts, joinedAt", "guildID = ? AND uid = ?", "", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.CreateGuildStmt, err = qgen.Builder.SimpleInsert("guilds", "name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime", "?,?,?,?,1,?,1,?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.AttachForumStmt, err = qgen.Builder.SimpleUpdate("forums", "parentID = ?, parentType = 'guild'", "fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.UnattachForumStmt, err = qgen.Builder.SimpleUpdate("forums", "parentID = 0, parentType = ''", "fid = ?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guilds.AddMemberStmt, err = qgen.Builder.SimpleInsert("guilds_members", "guildID, uid, rank, posts, joinedAt", "?,?,?,0,UTC_TIMESTAMP()")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
acc := qgen.Builder.Accumulator()
|
||||
|
||||
return nil
|
||||
guilds.ListStmt = acc.SimpleSelect("guilds", "guildID, name, desc, active, privacy, joinable, owner, memberCount, createdAt, lastUpdateTime", "", "", "")
|
||||
|
||||
guilds.GetGuildStmt = acc.SimpleSelect("guilds", "name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime", "guildID = ?", "", "")
|
||||
|
||||
guilds.MemberListStmt = acc.SimpleSelect("guilds_members", "guildID, uid, rank, posts, joinedAt", "", "", "")
|
||||
|
||||
guilds.MemberListJoinStmt = acc.SimpleLeftJoin("guilds_members", "users", "users.uid, guilds_members.rank, guilds_members.posts, guilds_members.joinedAt, users.name, users.avatar", "guilds_members.uid = users.uid", "guilds_members.guildID = ?", "guilds_members.rank DESC, guilds_members.joinedat ASC", "")
|
||||
|
||||
guilds.GetMemberStmt = acc.SimpleSelect("guilds_members", "rank, posts, joinedAt", "guildID = ? AND uid = ?", "", "")
|
||||
|
||||
guilds.CreateGuildStmt = acc.SimpleInsert("guilds", "name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime", "?,?,?,?,1,?,1,?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()")
|
||||
|
||||
guilds.AttachForumStmt = acc.SimpleUpdate("forums", "parentID = ?, parentType = 'guild'", "fid = ?")
|
||||
|
||||
guilds.UnattachForumStmt = acc.SimpleUpdate("forums", "parentID = 0, parentType = ''", "fid = ?")
|
||||
|
||||
guilds.AddMemberStmt = acc.SimpleInsert("guilds_members", "guildID, uid, rank, posts, joinedAt", "?,?,?,0,UTC_TIMESTAMP()")
|
||||
|
||||
return acc.FirstError()
|
||||
}
|
||||
|
||||
func deactivateGuilds() {
|
||||
plugins["guilds"].RemoveHook("intercept_build_widgets", guilds.Widgets)
|
||||
plugins["guilds"].RemoveHook("trow_assign", guilds.TrowAssign)
|
||||
plugins["guilds"].RemoveHook("topic_create_pre_loop", guilds.TopicCreatePreLoop)
|
||||
plugins["guilds"].RemoveHook("pre_render_view_forum", guilds.PreRenderViewForum)
|
||||
plugins["guilds"].RemoveHook("simple_forum_check_pre_perms", guilds.ForumCheck)
|
||||
plugins["guilds"].RemoveHook("forum_check_pre_perms", guilds.ForumCheck)
|
||||
deregisterPluginPerm("CreateGuild")
|
||||
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("simple_forum_check_pre_perms", guilds.ForumCheck)
|
||||
common.Plugins["guilds"].RemoveHook("forum_check_pre_perms", guilds.ForumCheck)
|
||||
common.DeregisterPluginPerm("CreateGuild")
|
||||
_ = router.RemoveFunc("/guilds/")
|
||||
_ = router.RemoveFunc("/guild/")
|
||||
_ = router.RemoveFunc("/guild/create/")
|
||||
|
@ -1,22 +1,24 @@
|
||||
package main
|
||||
|
||||
import "./common"
|
||||
|
||||
func init() {
|
||||
plugins["heythere"] = NewPlugin("heythere", "Hey There", "Azareal", "http://github.com/Azareal", "", "", "", initHeythere, nil, deactivateHeythere, nil, nil)
|
||||
common.Plugins["heythere"] = common.NewPlugin("heythere", "Hey There", "Azareal", "http://github.com/Azareal", "", "", "", initHeythere, nil, deactivateHeythere, nil, nil)
|
||||
}
|
||||
|
||||
// init_heythere is separate from init() as we don't want the plugin to run if the plugin is disabled
|
||||
func initHeythere() error {
|
||||
plugins["heythere"].AddHook("topic_reply_row_assign", heythereReply)
|
||||
common.Plugins["heythere"].AddHook("topic_reply_row_assign", heythereReply)
|
||||
return nil
|
||||
}
|
||||
|
||||
func deactivateHeythere() {
|
||||
plugins["heythere"].RemoveHook("topic_reply_row_assign", heythereReply)
|
||||
common.Plugins["heythere"].RemoveHook("topic_reply_row_assign", heythereReply)
|
||||
}
|
||||
|
||||
func heythereReply(data ...interface{}) interface{} {
|
||||
currentUser := data[0].(*TopicPage).CurrentUser
|
||||
reply := data[1].(*ReplyUser)
|
||||
currentUser := data[0].(*common.TopicPage).CurrentUser
|
||||
reply := data[1].(*common.ReplyUser)
|
||||
reply.Content = "Hey there, " + currentUser.Name + "!"
|
||||
reply.ContentHtml = "Hey there, " + currentUser.Name + "!"
|
||||
reply.Tag = "Auto"
|
||||
|
@ -4,6 +4,8 @@ package main
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
var markdownMaxDepth = 25 // How deep the parser will go when parsing Markdown strings
|
||||
@ -19,11 +21,11 @@ var markdownStrikeTagOpen []byte
|
||||
var markdownStrikeTagClose []byte
|
||||
|
||||
func init() {
|
||||
plugins["markdown"] = NewPlugin("markdown", "Markdown", "Azareal", "http://github.com/Azareal", "", "", "", initMarkdown, nil, deactivateMarkdown, nil, nil)
|
||||
common.Plugins["markdown"] = common.NewPlugin("markdown", "Markdown", "Azareal", "http://github.com/Azareal", "", "", "", initMarkdown, nil, deactivateMarkdown, nil, nil)
|
||||
}
|
||||
|
||||
func initMarkdown() error {
|
||||
plugins["markdown"].AddHook("parse_assign", markdownParse)
|
||||
common.Plugins["markdown"].AddHook("parse_assign", markdownParse)
|
||||
|
||||
markdownUnclosedElement = []byte("<span style='color: red;'>[Unclosed Element]</span>")
|
||||
|
||||
@ -39,7 +41,7 @@ func initMarkdown() error {
|
||||
}
|
||||
|
||||
func deactivateMarkdown() {
|
||||
plugins["markdown"].RemoveHook("parse_assign", markdownParse)
|
||||
common.Plugins["markdown"].RemoveHook("parse_assign", markdownParse)
|
||||
}
|
||||
|
||||
// An adapter for the parser, so that the parser can call itself recursively.
|
||||
|
@ -1,5 +1,7 @@
|
||||
package main
|
||||
|
||||
import "./common"
|
||||
|
||||
func init() {
|
||||
/*
|
||||
The UName field should match the name in the URL minus plugin_ and the file extension. The same name as the map index. Please choose a unique name which won't clash with any other plugins.
|
||||
@ -26,7 +28,7 @@ func init() {
|
||||
|
||||
That Uninstallation field which is currently unused is for not only deactivating this plugin, but for purging any data associated with it such a new tables or data produced by the end-user.
|
||||
*/
|
||||
plugins["skeleton"] = NewPlugin("skeleton", "Skeleton", "Azareal", "", "", "", "", initSkeleton, activateSkeleton, deactivateSkeleton, nil, nil)
|
||||
common.Plugins["skeleton"] = common.NewPlugin("skeleton", "Skeleton", "Azareal", "", "", "", "", initSkeleton, activateSkeleton, deactivateSkeleton, nil, nil)
|
||||
}
|
||||
|
||||
func initSkeleton() error { return nil }
|
||||
|
@ -37,6 +37,10 @@ func (build *builder) GetAdapter() DB_Adapter {
|
||||
return build.adapter
|
||||
}
|
||||
|
||||
func (build *builder) Begin() (*sql.Tx, error) {
|
||||
return build.conn.Begin()
|
||||
}
|
||||
|
||||
func (build *builder) Tx(handler func(*TransactionBuilder) error) error {
|
||||
tx, err := build.conn.Begin()
|
||||
if err != nil {
|
||||
@ -50,101 +54,60 @@ func (build *builder) Tx(handler func(*TransactionBuilder) error) error {
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (build *builder) SimpleSelect(table string, columns string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit)
|
||||
func (build *builder) prepare(res string, err error) (*sql.Stmt, error) {
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
return nil, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
}
|
||||
|
||||
func (build *builder) SimpleSelect(table string, columns string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
return build.prepare(build.adapter.SimpleSelect("_builder", table, columns, where, orderby, limit))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleCount(table string, where string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleCount("_builder", table, where, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleCount("_builder", table, where, limit))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleLeftJoin(table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleLeftJoin("_builder", table1, table2, columns, joiners, where, orderby, limit))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInnerJoin(table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleInnerJoin("_builder", table1, table2, columns, joiners, where, orderby, limit))
|
||||
}
|
||||
|
||||
func (build *builder) CreateTable(table string, charset string, collation string, columns []DB_Table_Column, keys []DB_Table_Key) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.CreateTable("_builder", table, charset, collation, columns, keys)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.CreateTable("_builder", table, charset, collation, columns, keys))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsert(table string, columns string, fields string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsert("_builder", table, columns, fields)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleInsert("_builder", table, columns, fields))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertSelect(ins DB_Insert, sel DB_Select) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsertSelect("_builder", ins, sel)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleInsertSelect("_builder", ins, sel))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertLeftJoin(ins DB_Insert, sel DB_Join) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsertLeftJoin("_builder", ins, sel)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleInsertLeftJoin("_builder", ins, sel))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleInsertInnerJoin(ins DB_Insert, sel DB_Join) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleInsertInnerJoin("_builder", ins, sel)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleInsertInnerJoin("_builder", ins, sel))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleUpdate(table string, set string, where string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleUpdate("_builder", table, set, where)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleUpdate("_builder", table, set, where))
|
||||
}
|
||||
|
||||
func (build *builder) SimpleDelete(table string, where string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.SimpleDelete("_builder", table, where)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.SimpleDelete("_builder", table, where))
|
||||
}
|
||||
|
||||
// I don't know why you need this, but here it is x.x
|
||||
func (build *builder) Purge(table string) (stmt *sql.Stmt, err error) {
|
||||
res, err := build.adapter.Purge("_builder", table)
|
||||
if err != nil {
|
||||
return stmt, err
|
||||
}
|
||||
return build.conn.Prepare(res)
|
||||
return build.prepare(build.adapter.Purge("_builder", table))
|
||||
}
|
||||
|
||||
// These ones support transactions
|
||||
|
@ -1098,6 +1098,7 @@ package main
|
||||
|
||||
import "log"
|
||||
import "database/sql"
|
||||
import "./common"
|
||||
|
||||
// nolint
|
||||
type Stmts struct {
|
||||
@ -1117,7 +1118,7 @@ type Stmts struct {
|
||||
|
||||
// nolint
|
||||
func _gen_mssql() (err error) {
|
||||
if dev.DebugMode {
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Building the generated statements")
|
||||
}
|
||||
` + body + `
|
||||
|
@ -590,6 +590,7 @@ package main
|
||||
|
||||
import "log"
|
||||
import "database/sql"
|
||||
import "./common"
|
||||
//import "./query_gen/lib"
|
||||
|
||||
// nolint
|
||||
@ -610,7 +611,7 @@ type Stmts struct {
|
||||
|
||||
// nolint
|
||||
func _gen_mysql() (err error) {
|
||||
if dev.DebugMode {
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Building the generated statements")
|
||||
}
|
||||
` + body + `
|
||||
|
@ -346,6 +346,7 @@ package main
|
||||
|
||||
import "log"
|
||||
import "database/sql"
|
||||
import "./common"
|
||||
|
||||
// nolint
|
||||
type Stmts struct {
|
||||
@ -365,7 +366,7 @@ type Stmts struct {
|
||||
|
||||
// nolint
|
||||
func _gen_pgsql() (err error) {
|
||||
if dev.DebugMode {
|
||||
if common.Dev.DebugMode {
|
||||
log.Print("Building the generated statements")
|
||||
}
|
||||
` + body + `
|
||||
|
@ -230,20 +230,12 @@ func writeSelects(adapter qgen.DB_Adapter) error {
|
||||
|
||||
adapter.SimpleSelect("getFullSetting", "settings", "name, type, constraints", "name = ?", "", "")
|
||||
|
||||
adapter.SimpleSelect("getFullSettings", "settings", "name, content, type, constraints", "", "", "")
|
||||
|
||||
adapter.SimpleSelect("getThemes", "themes", "uname, default", "", "", "")
|
||||
|
||||
adapter.SimpleSelect("getWidgets", "widgets", "position, side, type, active, location, data", "", "position ASC", "")
|
||||
|
||||
adapter.SimpleSelect("isPluginActive", "plugins", "active", "uname = ?", "", "")
|
||||
|
||||
//adapter.SimpleSelect("isPluginInstalled","plugins","installed","uname = ?","","")
|
||||
|
||||
adapter.SimpleSelect("getUsersOffset", "users", "uid, name, group, active, is_super_admin, avatar", "", "uid ASC", "?,?")
|
||||
|
||||
adapter.SimpleSelect("getWordFilters", "word_filters", "wfid, find, replacement", "", "", "")
|
||||
|
||||
adapter.SimpleSelect("isThemeDefault", "themes", "default", "uname = ?", "", "")
|
||||
|
||||
adapter.SimpleSelect("getModlogs", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "", "", "")
|
||||
@ -256,10 +248,6 @@ func writeSelects(adapter qgen.DB_Adapter) error {
|
||||
|
||||
adapter.SimpleSelect("getUserReplyUID", "users_replies", "uid", "rid = ?", "", "")
|
||||
|
||||
adapter.SimpleSelect("hasLikedTopic", "likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'topics'", "", "")
|
||||
|
||||
adapter.SimpleSelect("hasLikedReply", "likes", "targetItem", "sentBy = ? and targetItem = ? and targetType = 'replies'", "", "")
|
||||
|
||||
adapter.SimpleSelect("getUserName", "users", "name", "uid = ?", "", "")
|
||||
|
||||
adapter.SimpleSelect("getEmailsByUser", "emails", "email, validated, token", "uid = ?", "", "")
|
||||
@ -274,10 +262,6 @@ func writeSelects(adapter qgen.DB_Adapter) error {
|
||||
|
||||
adapter.SimpleSelect("getForumTopicsOffset", "topics", "tid, title, content, createdBy, is_closed, sticky, createdAt, lastReplyAt, lastReplyBy, parentID, postCount, likeCount", "parentID = ?", "sticky DESC, lastReplyAt DESC, createdBy DESC", "?,?")
|
||||
|
||||
adapter.SimpleSelect("getExpiredScheduledGroups", "users_groups_scheduler", "uid", "UTC_TIMESTAMP() > revert_at AND temporary = 1", "", "")
|
||||
|
||||
adapter.SimpleSelect("getSync", "sync", "last_update", "", "", "")
|
||||
|
||||
adapter.SimpleSelect("getAttachment", "attachments", "sectionID, sectionTable, originID, originTable, uploadedBy, path", "path = ? AND sectionID = ? AND sectionTable = ?", "", "")
|
||||
|
||||
return nil
|
||||
@ -288,11 +272,6 @@ func writeLeftJoins(adapter qgen.DB_Adapter) error {
|
||||
|
||||
adapter.SimpleLeftJoin("getTopicList", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC", "")
|
||||
|
||||
// TODO: Can we get rid of this?
|
||||
adapter.SimpleLeftJoin("getTopicUser", "topics", "users", "topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level", "topics.createdBy = users.uid", "tid = ?", "", "")
|
||||
|
||||
adapter.SimpleLeftJoin("getTopicByReply", "replies", "topics", "topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, topics.data", "replies.tid = topics.tid", "rid = ?", "", "")
|
||||
|
||||
adapter.SimpleLeftJoin("getTopicReplies", "replies", "users", "replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress", "replies.createdBy = users.uid", "tid = ?", "", "")
|
||||
|
||||
adapter.SimpleLeftJoin("getForumTopics", "topics", "users", "topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar", "topics.createdBy = users.uid", "topics.parentID = ?", "topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc", "")
|
||||
@ -314,10 +293,6 @@ func writeInnerJoins(adapter qgen.DB_Adapter) (err error) {
|
||||
func writeInserts(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleInsert("createReport", "topics", "title, content, parsed_content, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class", "?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,1,'report'")
|
||||
|
||||
adapter.SimpleInsert("createActionReply", "replies", "tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content", "?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''")
|
||||
|
||||
adapter.SimpleInsert("createLike", "likes", "weight, targetItem, targetType, sentBy", "?,?,?,?")
|
||||
|
||||
adapter.SimpleInsert("addActivity", "activity_stream", "actor, targetUser, event, elementType, elementID", "?,?,?,?,?")
|
||||
|
||||
adapter.SimpleInsert("notifyOne", "activity_stream_matches", "watcher, asid", "?,?")
|
||||
@ -332,10 +307,6 @@ func writeInserts(adapter qgen.DB_Adapter) error {
|
||||
|
||||
adapter.SimpleInsert("addTheme", "themes", "uname, default", "?,?")
|
||||
|
||||
adapter.SimpleInsert("addModlogEntry", "moderation_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()")
|
||||
|
||||
adapter.SimpleInsert("addAdminlogEntry", "administration_logs", "action, elementID, elementType, ipaddress, actorID, doneAt", "?,?,?,?,?,UTC_TIMESTAMP()")
|
||||
|
||||
adapter.SimpleInsert("addAttachment", "attachments", "sectionID, sectionTable, originID, originTable, uploadedBy, path", "?,?,?,?,?,?")
|
||||
|
||||
adapter.SimpleInsert("createWordFilter", "word_filters", "find, replacement", "?,?")
|
||||
@ -363,56 +334,10 @@ func writeReplaces(adapter qgen.DB_Adapter) (err error) {
|
||||
}*/
|
||||
|
||||
func writeUpdates(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleUpdate("addRepliesToTopic", "topics", "postCount = postCount + ?, lastReplyBy = ?, lastReplyAt = UTC_TIMESTAMP()", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("removeRepliesFromTopic", "topics", "postCount = postCount - ?", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("addLikesToTopic", "topics", "likeCount = likeCount + ?", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("addLikesToReply", "replies", "likeCount = likeCount + ?", "rid = ?")
|
||||
|
||||
adapter.SimpleUpdate("editTopic", "topics", "title = ?, content = ?, parsed_content = ?", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("editReply", "replies", "content = ?, parsed_content = ?", "rid = ?")
|
||||
|
||||
adapter.SimpleUpdate("stickTopic", "topics", "sticky = 1", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("unstickTopic", "topics", "sticky = 0", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("lockTopic", "topics", "is_closed = 1", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("unlockTopic", "topics", "is_closed = 0", "tid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateLastIP", "users", "last_ip = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateSession", "users", "session = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("setPassword", "users", "password = ?, salt = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("setAvatar", "users", "avatar = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("setUsername", "users", "name = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("changeGroup", "users", "group = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("activateUser", "users", "active = 1", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateUserLevel", "users", "level = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("incrementUserScore", "users", "score = score + ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("incrementUserPosts", "users", "posts = posts + ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("incrementUserBigposts", "users", "posts = posts + ?, bigposts = bigposts + ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("incrementUserMegaposts", "users", "posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("incrementUserTopics", "users", "topics = topics + ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("editProfileReply", "users_replies", "content = ?, parsed_content = ?", "rid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateForum", "forums", "name = ?, desc = ?, active = ?, preset = ?", "fid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateSetting", "settings", "content = ?", "name = ?")
|
||||
|
||||
adapter.SimpleUpdate("updatePlugin", "plugins", "active = ?", "uname = ?")
|
||||
@ -421,14 +346,12 @@ func writeUpdates(adapter qgen.DB_Adapter) error {
|
||||
|
||||
adapter.SimpleUpdate("updateTheme", "themes", "default = ?", "uname = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateForum", "forums", "name = ?, desc = ?, active = ?, preset = ?", "fid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateUser", "users", "name = ?, email = ?, group = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateUserGroup", "users", "group = ?", "uid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateGroupPerms", "users_groups", "permissions = ?", "gid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateGroupRank", "users_groups", "is_admin = ?, is_mod = ?, is_banned = ?", "gid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateGroup", "users_groups", "name = ?, tag = ?", "gid = ?")
|
||||
|
||||
adapter.SimpleUpdate("updateEmail", "emails", "email = ?, uid = ?, validated = ?, token = ?", "email = ?")
|
||||
@ -445,12 +368,6 @@ func writeUpdates(adapter qgen.DB_Adapter) error {
|
||||
}
|
||||
|
||||
func writeDeletes(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleDelete("deleteUser", "users", "uid = ?")
|
||||
|
||||
adapter.SimpleDelete("deleteTopic", "topics", "tid = ?")
|
||||
|
||||
adapter.SimpleDelete("deleteReply", "replies", "rid = ?")
|
||||
|
||||
adapter.SimpleDelete("deleteProfileReply", "users_replies", "rid = ?")
|
||||
|
||||
//adapter.SimpleDelete("deleteForumPermsByForum", "forums_permissions", "fid = ?")
|
||||
@ -466,8 +383,6 @@ func writeDeletes(adapter qgen.DB_Adapter) error {
|
||||
func writeSimpleCounts(adapter qgen.DB_Adapter) error {
|
||||
adapter.SimpleCount("reportExists", "topics", "data = ? AND data != '' AND parentID = 1", "")
|
||||
|
||||
adapter.SimpleCount("groupCount", "users_groups", "", "")
|
||||
|
||||
adapter.SimpleCount("modlogCount", "moderation_logs", "", "")
|
||||
|
||||
return nil
|
||||
|
12
router.go
12
router.go
@ -2,9 +2,13 @@
|
||||
package main
|
||||
|
||||
//import "fmt"
|
||||
import "strings"
|
||||
import "sync"
|
||||
import "net/http"
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
// TODO: Support the new handler signatures created by our efforts to move the PreRoute middleware into the generated router
|
||||
// nolint Stop linting the uselessness of this file, we never know when we might need this file again
|
||||
@ -59,5 +63,5 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
//log.Print("req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/')]",req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/')])
|
||||
NotFound(w, req)
|
||||
common.NotFound(w, req)
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ func main() {
|
||||
out += "\n\t\t\t\t\t" + runnable.Contents
|
||||
} else {
|
||||
out += `
|
||||
err = ` + runnable.Contents + `(w,req,user)
|
||||
err = common.` + runnable.Contents + `(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -65,7 +65,7 @@ func main() {
|
||||
out += "\t\t\t" + runnable.Contents
|
||||
} else {
|
||||
out += `
|
||||
err = ` + runnable.Contents + `(w,req,user)
|
||||
err = common.` + runnable.Contents + `(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -89,7 +89,7 @@ func main() {
|
||||
out += "\n\t\t\t\t\t" + runnable.Contents
|
||||
} else {
|
||||
out += `
|
||||
err = ` + runnable.Contents + `(w,req,user)
|
||||
err = common.` + runnable.Contents + `(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -113,7 +113,7 @@ func main() {
|
||||
out += "\n\t\t\t\t\t" + runnable.Contents
|
||||
} else {
|
||||
out += `
|
||||
err = ` + runnable.Contents + `(w,req,user)
|
||||
err = common.` + runnable.Contents + `(w,req,user)
|
||||
if err != nil {
|
||||
router.handleError(err,w,req,user)
|
||||
return
|
||||
@ -137,17 +137,21 @@ func main() {
|
||||
|
||||
fileData += `package main
|
||||
|
||||
import "log"
|
||||
import "strings"
|
||||
import "sync"
|
||||
import "errors"
|
||||
import "net/http"
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"./common"
|
||||
)
|
||||
|
||||
var ErrNoRoute = errors.New("That route doesn't exist.")
|
||||
|
||||
type GenRouter struct {
|
||||
UploadHandler func(http.ResponseWriter, *http.Request)
|
||||
extra_routes map[string]func(http.ResponseWriter, *http.Request, User) RouteError
|
||||
extra_routes map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
@ -155,26 +159,26 @@ type GenRouter struct {
|
||||
func NewGenRouter(uploads http.Handler) *GenRouter {
|
||||
return &GenRouter{
|
||||
UploadHandler: http.StripPrefix("/uploads/",uploads).ServeHTTP,
|
||||
extra_routes: make(map[string]func(http.ResponseWriter, *http.Request, User) RouteError),
|
||||
extra_routes: make(map[string]func(http.ResponseWriter, *http.Request, common.User) common.RouteError),
|
||||
}
|
||||
}
|
||||
|
||||
func (router *GenRouter) handleError(err RouteError, w http.ResponseWriter, r *http.Request, user User) {
|
||||
func (router *GenRouter) handleError(err common.RouteError, w http.ResponseWriter, r *http.Request, user common.User) {
|
||||
if err.Handled() {
|
||||
return
|
||||
}
|
||||
|
||||
if err.Type() == "system" {
|
||||
InternalErrorJSQ(err,w,r,err.Json())
|
||||
common.InternalErrorJSQ(err, w, r, err.JSON())
|
||||
return
|
||||
}
|
||||
LocalErrorJSQ(err.Error(),w,r,user,err.Json())
|
||||
common.LocalErrorJSQ(err.Error(), w, r, user,err.JSON())
|
||||
}
|
||||
|
||||
func (router *GenRouter) Handle(_ string, _ http.Handler) {
|
||||
}
|
||||
|
||||
func (router *GenRouter) HandleFunc(pattern string, handle func(http.ResponseWriter, *http.Request, User) RouteError) {
|
||||
func (router *GenRouter) HandleFunc(pattern string, handle func(http.ResponseWriter, *http.Request, common.User) common.RouteError) {
|
||||
router.Lock()
|
||||
router.extra_routes[pattern] = handle
|
||||
router.Unlock()
|
||||
@ -187,7 +191,7 @@ func (router *GenRouter) RemoveFunc(pattern string) error {
|
||||
router.Unlock()
|
||||
return ErrNoRoute
|
||||
}
|
||||
delete(router.extra_routes,pattern)
|
||||
delete(router.extra_routes, pattern)
|
||||
router.Unlock()
|
||||
return nil
|
||||
}
|
||||
@ -210,7 +214,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
req.URL.Path = req.URL.Path[:strings.LastIndexByte(req.URL.Path,'/') + 1]
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if common.Dev.SuperDebug {
|
||||
log.Print("before routeStatic")
|
||||
log.Print("prefix: ", prefix)
|
||||
log.Print("req.URL.Path: ", req.URL.Path)
|
||||
@ -220,29 +224,29 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
|
||||
if prefix == "/static" {
|
||||
req.URL.Path += extra_data
|
||||
routeStatic(w,req)
|
||||
routeStatic(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if common.Dev.SuperDebug {
|
||||
log.Print("before PreRoute")
|
||||
}
|
||||
|
||||
// Deal with the session stuff, etc.
|
||||
user, ok := PreRoute(w,req)
|
||||
user, ok := common.PreRoute(w, req)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if dev.SuperDebug {
|
||||
if common.Dev.SuperDebug {
|
||||
log.Print("after PreRoute")
|
||||
}
|
||||
|
||||
var err RouteError
|
||||
var err common.RouteError
|
||||
switch(prefix) {` + out + `
|
||||
case "/uploads":
|
||||
if extra_data == "" {
|
||||
NotFound(w,req)
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
}
|
||||
req.URL.Path += extra_data
|
||||
@ -261,10 +265,10 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
if extra_data != "" {
|
||||
NotFound(w,req)
|
||||
common.NotFound(w,req)
|
||||
return
|
||||
}
|
||||
config.DefaultRoute(w,req,user)
|
||||
common.Config.DefaultRoute(w,req,user)
|
||||
default:
|
||||
// A fallback for the routes which haven't been converted to the new router yet or plugins
|
||||
router.RLock()
|
||||
@ -279,7 +283,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
return
|
||||
}
|
||||
NotFound(w,req)
|
||||
common.NotFound(w,req)
|
||||
}
|
||||
}
|
||||
`
|
||||
|
@ -1,230 +0,0 @@
|
||||
// +build !no_templategen
|
||||
|
||||
// Code generated by Gosora. More below:
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "net/http"
|
||||
import "strconv"
|
||||
|
||||
// nolint
|
||||
func init() {
|
||||
template_forum_handle = template_forum
|
||||
//o_template_forum_handle = template_forum
|
||||
ctemplates = append(ctemplates,"forum")
|
||||
tmplPtrMap["forum"] = &template_forum_handle
|
||||
tmplPtrMap["o_forum"] = template_forum
|
||||
}
|
||||
|
||||
// nolint
|
||||
func template_forum(tmpl_forum_vars ForumPage, w http.ResponseWriter) error {
|
||||
w.Write(header_0)
|
||||
w.Write([]byte(tmpl_forum_vars.Title))
|
||||
w.Write(header_1)
|
||||
w.Write([]byte(tmpl_forum_vars.Header.Site.Name))
|
||||
w.Write(header_2)
|
||||
w.Write([]byte(tmpl_forum_vars.Header.ThemeName))
|
||||
w.Write(header_3)
|
||||
if len(tmpl_forum_vars.Header.Stylesheets) != 0 {
|
||||
for _, item := range tmpl_forum_vars.Header.Stylesheets {
|
||||
w.Write(header_4)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_5)
|
||||
}
|
||||
}
|
||||
w.Write(header_6)
|
||||
if len(tmpl_forum_vars.Header.Scripts) != 0 {
|
||||
for _, item := range tmpl_forum_vars.Header.Scripts {
|
||||
w.Write(header_7)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_8)
|
||||
}
|
||||
}
|
||||
w.Write(header_9)
|
||||
w.Write([]byte(tmpl_forum_vars.CurrentUser.Session))
|
||||
w.Write(header_10)
|
||||
w.Write([]byte(tmpl_forum_vars.Header.Site.URL))
|
||||
w.Write(header_11)
|
||||
if !tmpl_forum_vars.CurrentUser.IsSuperMod {
|
||||
w.Write(header_12)
|
||||
}
|
||||
w.Write(header_13)
|
||||
w.Write(menu_0)
|
||||
w.Write(menu_1)
|
||||
w.Write([]byte(tmpl_forum_vars.Header.Site.ShortName))
|
||||
w.Write(menu_2)
|
||||
if tmpl_forum_vars.CurrentUser.Loggedin {
|
||||
w.Write(menu_3)
|
||||
w.Write([]byte(tmpl_forum_vars.CurrentUser.Link))
|
||||
w.Write(menu_4)
|
||||
w.Write([]byte(tmpl_forum_vars.CurrentUser.Session))
|
||||
w.Write(menu_5)
|
||||
} else {
|
||||
w.Write(menu_6)
|
||||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_14)
|
||||
if tmpl_forum_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(header_15)
|
||||
}
|
||||
w.Write(header_16)
|
||||
if len(tmpl_forum_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_forum_vars.Header.NoticeList {
|
||||
w.Write(header_17)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_18)
|
||||
}
|
||||
}
|
||||
if tmpl_forum_vars.Page > 1 {
|
||||
w.Write(forum_0)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||
w.Write(forum_1)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Page - 1)))
|
||||
w.Write(forum_2)
|
||||
}
|
||||
if tmpl_forum_vars.LastPage != tmpl_forum_vars.Page {
|
||||
w.Write(forum_3)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||
w.Write(forum_4)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Page + 1)))
|
||||
w.Write(forum_5)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||
w.Write(forum_6)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Page + 1)))
|
||||
w.Write(forum_7)
|
||||
}
|
||||
w.Write(forum_8)
|
||||
if tmpl_forum_vars.CurrentUser.ID != 0 {
|
||||
w.Write(forum_9)
|
||||
}
|
||||
w.Write(forum_10)
|
||||
w.Write([]byte(tmpl_forum_vars.Title))
|
||||
w.Write(forum_11)
|
||||
if tmpl_forum_vars.CurrentUser.ID != 0 {
|
||||
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
|
||||
w.Write(forum_12)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||
w.Write(forum_13)
|
||||
w.Write(forum_14)
|
||||
} else {
|
||||
w.Write(forum_15)
|
||||
}
|
||||
w.Write(forum_16)
|
||||
}
|
||||
w.Write(forum_17)
|
||||
if tmpl_forum_vars.CurrentUser.ID != 0 {
|
||||
w.Write(forum_18)
|
||||
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
|
||||
w.Write(forum_19)
|
||||
if tmpl_forum_vars.CurrentUser.Avatar != "" {
|
||||
w.Write(forum_20)
|
||||
w.Write([]byte(tmpl_forum_vars.CurrentUser.Avatar))
|
||||
w.Write(forum_21)
|
||||
}
|
||||
w.Write(forum_22)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||
w.Write(forum_23)
|
||||
if tmpl_forum_vars.CurrentUser.Perms.UploadFiles {
|
||||
w.Write(forum_24)
|
||||
}
|
||||
w.Write(forum_25)
|
||||
}
|
||||
}
|
||||
w.Write(forum_26)
|
||||
if len(tmpl_forum_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_forum_vars.ItemList {
|
||||
w.Write(forum_27)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(forum_28)
|
||||
if item.Sticky {
|
||||
w.Write(forum_29)
|
||||
} else {
|
||||
if item.IsClosed {
|
||||
w.Write(forum_30)
|
||||
}
|
||||
}
|
||||
w.Write(forum_31)
|
||||
if item.Creator.Avatar != "" {
|
||||
w.Write(forum_32)
|
||||
w.Write([]byte(item.Creator.Link))
|
||||
w.Write(forum_33)
|
||||
w.Write([]byte(item.Creator.Avatar))
|
||||
w.Write(forum_34)
|
||||
}
|
||||
w.Write(forum_35)
|
||||
w.Write([]byte(item.Link))
|
||||
w.Write(forum_36)
|
||||
w.Write([]byte(item.Title))
|
||||
w.Write(forum_37)
|
||||
w.Write([]byte(item.Creator.Link))
|
||||
w.Write(forum_38)
|
||||
w.Write([]byte(item.Creator.Name))
|
||||
w.Write(forum_39)
|
||||
if item.IsClosed {
|
||||
w.Write(forum_40)
|
||||
}
|
||||
if item.Sticky {
|
||||
w.Write(forum_41)
|
||||
}
|
||||
w.Write(forum_42)
|
||||
w.Write([]byte(strconv.Itoa(item.PostCount)))
|
||||
w.Write(forum_43)
|
||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||
w.Write(forum_44)
|
||||
if item.Sticky {
|
||||
w.Write(forum_45)
|
||||
} else {
|
||||
if item.IsClosed {
|
||||
w.Write(forum_46)
|
||||
}
|
||||
}
|
||||
w.Write(forum_47)
|
||||
if item.LastUser.Avatar != "" {
|
||||
w.Write(forum_48)
|
||||
w.Write([]byte(item.LastUser.Link))
|
||||
w.Write(forum_49)
|
||||
w.Write([]byte(item.LastUser.Avatar))
|
||||
w.Write(forum_50)
|
||||
}
|
||||
w.Write(forum_51)
|
||||
w.Write([]byte(item.LastUser.Link))
|
||||
w.Write(forum_52)
|
||||
w.Write([]byte(item.LastUser.Name))
|
||||
w.Write(forum_53)
|
||||
w.Write([]byte(item.RelativeLastReplyAt))
|
||||
w.Write(forum_54)
|
||||
}
|
||||
} else {
|
||||
w.Write(forum_55)
|
||||
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
|
||||
w.Write(forum_56)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
|
||||
w.Write(forum_57)
|
||||
}
|
||||
w.Write(forum_58)
|
||||
}
|
||||
w.Write(forum_59)
|
||||
w.Write(footer_0)
|
||||
if len(tmpl_forum_vars.Header.Themes) != 0 {
|
||||
for _, item := range tmpl_forum_vars.Header.Themes {
|
||||
if !item.HideFromThemes {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(footer_2)
|
||||
if tmpl_forum_vars.Header.ThemeName == item.Name {
|
||||
w.Write(footer_3)
|
||||
}
|
||||
w.Write(footer_4)
|
||||
w.Write([]byte(item.FriendlyName))
|
||||
w.Write(footer_5)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(footer_6)
|
||||
if tmpl_forum_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(footer_7)
|
||||
w.Write([]byte(string(tmpl_forum_vars.Header.Widgets.RightSidebar)))
|
||||
w.Write(footer_8)
|
||||
}
|
||||
w.Write(footer_9)
|
||||
return nil
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
// +build !no_templategen
|
||||
|
||||
// Code generated by Gosora. More below:
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "net/http"
|
||||
|
||||
// nolint
|
||||
func init() {
|
||||
template_forums_handle = template_forums
|
||||
//o_template_forums_handle = template_forums
|
||||
ctemplates = append(ctemplates,"forums")
|
||||
tmplPtrMap["forums"] = &template_forums_handle
|
||||
tmplPtrMap["o_forums"] = template_forums
|
||||
}
|
||||
|
||||
// nolint
|
||||
func template_forums(tmpl_forums_vars ForumsPage, w http.ResponseWriter) error {
|
||||
w.Write(header_0)
|
||||
w.Write([]byte(tmpl_forums_vars.Title))
|
||||
w.Write(header_1)
|
||||
w.Write([]byte(tmpl_forums_vars.Header.Site.Name))
|
||||
w.Write(header_2)
|
||||
w.Write([]byte(tmpl_forums_vars.Header.ThemeName))
|
||||
w.Write(header_3)
|
||||
if len(tmpl_forums_vars.Header.Stylesheets) != 0 {
|
||||
for _, item := range tmpl_forums_vars.Header.Stylesheets {
|
||||
w.Write(header_4)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_5)
|
||||
}
|
||||
}
|
||||
w.Write(header_6)
|
||||
if len(tmpl_forums_vars.Header.Scripts) != 0 {
|
||||
for _, item := range tmpl_forums_vars.Header.Scripts {
|
||||
w.Write(header_7)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_8)
|
||||
}
|
||||
}
|
||||
w.Write(header_9)
|
||||
w.Write([]byte(tmpl_forums_vars.CurrentUser.Session))
|
||||
w.Write(header_10)
|
||||
w.Write([]byte(tmpl_forums_vars.Header.Site.URL))
|
||||
w.Write(header_11)
|
||||
if !tmpl_forums_vars.CurrentUser.IsSuperMod {
|
||||
w.Write(header_12)
|
||||
}
|
||||
w.Write(header_13)
|
||||
w.Write(menu_0)
|
||||
w.Write(menu_1)
|
||||
w.Write([]byte(tmpl_forums_vars.Header.Site.ShortName))
|
||||
w.Write(menu_2)
|
||||
if tmpl_forums_vars.CurrentUser.Loggedin {
|
||||
w.Write(menu_3)
|
||||
w.Write([]byte(tmpl_forums_vars.CurrentUser.Link))
|
||||
w.Write(menu_4)
|
||||
w.Write([]byte(tmpl_forums_vars.CurrentUser.Session))
|
||||
w.Write(menu_5)
|
||||
} else {
|
||||
w.Write(menu_6)
|
||||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_14)
|
||||
if tmpl_forums_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(header_15)
|
||||
}
|
||||
w.Write(header_16)
|
||||
if len(tmpl_forums_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_forums_vars.Header.NoticeList {
|
||||
w.Write(header_17)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_18)
|
||||
}
|
||||
}
|
||||
w.Write(forums_0)
|
||||
if len(tmpl_forums_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_forums_vars.ItemList {
|
||||
w.Write(forums_1)
|
||||
if item.Desc != "" || item.LastTopic.Title != "" {
|
||||
w.Write(forums_2)
|
||||
}
|
||||
w.Write(forums_3)
|
||||
w.Write([]byte(item.Link))
|
||||
w.Write(forums_4)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(forums_5)
|
||||
if item.Desc != "" {
|
||||
w.Write(forums_6)
|
||||
w.Write([]byte(item.Desc))
|
||||
w.Write(forums_7)
|
||||
} else {
|
||||
w.Write(forums_8)
|
||||
}
|
||||
w.Write(forums_9)
|
||||
if item.LastReplyer.Avatar != "" {
|
||||
w.Write(forums_10)
|
||||
w.Write([]byte(item.LastReplyer.Avatar))
|
||||
w.Write(forums_11)
|
||||
}
|
||||
w.Write(forums_12)
|
||||
w.Write([]byte(item.LastTopic.Link))
|
||||
w.Write(forums_13)
|
||||
if item.LastTopic.Title != "" {
|
||||
w.Write([]byte(item.LastTopic.Title))
|
||||
} else {
|
||||
w.Write(forums_14)
|
||||
}
|
||||
w.Write(forums_15)
|
||||
if item.LastTopicTime != "" {
|
||||
w.Write(forums_16)
|
||||
w.Write([]byte(item.LastTopicTime))
|
||||
w.Write(forums_17)
|
||||
}
|
||||
w.Write(forums_18)
|
||||
}
|
||||
} else {
|
||||
w.Write(forums_19)
|
||||
}
|
||||
w.Write(forums_20)
|
||||
w.Write(footer_0)
|
||||
if len(tmpl_forums_vars.Header.Themes) != 0 {
|
||||
for _, item := range tmpl_forums_vars.Header.Themes {
|
||||
if !item.HideFromThemes {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(footer_2)
|
||||
if tmpl_forums_vars.Header.ThemeName == item.Name {
|
||||
w.Write(footer_3)
|
||||
}
|
||||
w.Write(footer_4)
|
||||
w.Write([]byte(item.FriendlyName))
|
||||
w.Write(footer_5)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(footer_6)
|
||||
if tmpl_forums_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(footer_7)
|
||||
w.Write([]byte(string(tmpl_forums_vars.Header.Widgets.RightSidebar)))
|
||||
w.Write(footer_8)
|
||||
}
|
||||
w.Write(footer_9)
|
||||
return nil
|
||||
}
|
1022
template_list.go
1022
template_list.go
File diff suppressed because it is too large
Load Diff
@ -1,188 +0,0 @@
|
||||
// +build !no_templategen
|
||||
|
||||
// Code generated by Gosora. More below:
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "net/http"
|
||||
import "strconv"
|
||||
|
||||
// nolint
|
||||
func init() {
|
||||
template_profile_handle = template_profile
|
||||
//o_template_profile_handle = template_profile
|
||||
ctemplates = append(ctemplates,"profile")
|
||||
tmplPtrMap["profile"] = &template_profile_handle
|
||||
tmplPtrMap["o_profile"] = template_profile
|
||||
}
|
||||
|
||||
// nolint
|
||||
func template_profile(tmpl_profile_vars ProfilePage, w http.ResponseWriter) error {
|
||||
w.Write(header_0)
|
||||
w.Write([]byte(tmpl_profile_vars.Title))
|
||||
w.Write(header_1)
|
||||
w.Write([]byte(tmpl_profile_vars.Header.Site.Name))
|
||||
w.Write(header_2)
|
||||
w.Write([]byte(tmpl_profile_vars.Header.ThemeName))
|
||||
w.Write(header_3)
|
||||
if len(tmpl_profile_vars.Header.Stylesheets) != 0 {
|
||||
for _, item := range tmpl_profile_vars.Header.Stylesheets {
|
||||
w.Write(header_4)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_5)
|
||||
}
|
||||
}
|
||||
w.Write(header_6)
|
||||
if len(tmpl_profile_vars.Header.Scripts) != 0 {
|
||||
for _, item := range tmpl_profile_vars.Header.Scripts {
|
||||
w.Write(header_7)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_8)
|
||||
}
|
||||
}
|
||||
w.Write(header_9)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||
w.Write(header_10)
|
||||
w.Write([]byte(tmpl_profile_vars.Header.Site.URL))
|
||||
w.Write(header_11)
|
||||
if !tmpl_profile_vars.CurrentUser.IsSuperMod {
|
||||
w.Write(header_12)
|
||||
}
|
||||
w.Write(header_13)
|
||||
w.Write(menu_0)
|
||||
w.Write(menu_1)
|
||||
w.Write([]byte(tmpl_profile_vars.Header.Site.ShortName))
|
||||
w.Write(menu_2)
|
||||
if tmpl_profile_vars.CurrentUser.Loggedin {
|
||||
w.Write(menu_3)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Link))
|
||||
w.Write(menu_4)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||
w.Write(menu_5)
|
||||
} else {
|
||||
w.Write(menu_6)
|
||||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_14)
|
||||
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(header_15)
|
||||
}
|
||||
w.Write(header_16)
|
||||
if len(tmpl_profile_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_profile_vars.Header.NoticeList {
|
||||
w.Write(header_17)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_18)
|
||||
}
|
||||
}
|
||||
w.Write(profile_0)
|
||||
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Avatar))
|
||||
w.Write(profile_1)
|
||||
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Name))
|
||||
w.Write(profile_2)
|
||||
if tmpl_profile_vars.ProfileOwner.Tag != "" {
|
||||
w.Write(profile_3)
|
||||
w.Write([]byte(tmpl_profile_vars.ProfileOwner.Tag))
|
||||
w.Write(profile_4)
|
||||
}
|
||||
w.Write(profile_5)
|
||||
if tmpl_profile_vars.CurrentUser.IsSuperMod && !tmpl_profile_vars.ProfileOwner.IsSuperMod {
|
||||
w.Write(profile_6)
|
||||
if tmpl_profile_vars.ProfileOwner.IsBanned {
|
||||
w.Write(profile_7)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||
w.Write(profile_8)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||
w.Write(profile_9)
|
||||
} else {
|
||||
w.Write(profile_10)
|
||||
}
|
||||
w.Write(profile_11)
|
||||
}
|
||||
w.Write(profile_12)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||
w.Write(profile_13)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||
w.Write(profile_14)
|
||||
if tmpl_profile_vars.CurrentUser.Perms.BanUsers {
|
||||
w.Write(profile_15)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||
w.Write(profile_16)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||
w.Write(profile_17)
|
||||
w.Write(profile_18)
|
||||
}
|
||||
w.Write(profile_19)
|
||||
if len(tmpl_profile_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_profile_vars.ItemList {
|
||||
w.Write(profile_20)
|
||||
w.Write([]byte(item.ClassName))
|
||||
w.Write(profile_21)
|
||||
if item.Avatar != "" {
|
||||
w.Write(profile_22)
|
||||
w.Write([]byte(item.Avatar))
|
||||
w.Write(profile_23)
|
||||
if item.ContentLines <= 5 {
|
||||
w.Write(profile_24)
|
||||
}
|
||||
w.Write(profile_25)
|
||||
}
|
||||
w.Write(profile_26)
|
||||
w.Write([]byte(item.ContentHtml))
|
||||
w.Write(profile_27)
|
||||
w.Write([]byte(item.UserLink))
|
||||
w.Write(profile_28)
|
||||
w.Write([]byte(item.CreatedByName))
|
||||
w.Write(profile_29)
|
||||
if tmpl_profile_vars.CurrentUser.IsMod {
|
||||
w.Write(profile_30)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(profile_31)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(profile_32)
|
||||
}
|
||||
w.Write(profile_33)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(profile_34)
|
||||
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
|
||||
w.Write(profile_35)
|
||||
if item.Tag != "" {
|
||||
w.Write(profile_36)
|
||||
w.Write([]byte(item.Tag))
|
||||
w.Write(profile_37)
|
||||
}
|
||||
w.Write(profile_38)
|
||||
}
|
||||
}
|
||||
w.Write(profile_39)
|
||||
if !tmpl_profile_vars.CurrentUser.IsBanned {
|
||||
w.Write(profile_40)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
|
||||
w.Write(profile_41)
|
||||
}
|
||||
w.Write(profile_42)
|
||||
w.Write(profile_43)
|
||||
w.Write(footer_0)
|
||||
if len(tmpl_profile_vars.Header.Themes) != 0 {
|
||||
for _, item := range tmpl_profile_vars.Header.Themes {
|
||||
if !item.HideFromThemes {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(footer_2)
|
||||
if tmpl_profile_vars.Header.ThemeName == item.Name {
|
||||
w.Write(footer_3)
|
||||
}
|
||||
w.Write(footer_4)
|
||||
w.Write([]byte(item.FriendlyName))
|
||||
w.Write(footer_5)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(footer_6)
|
||||
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(footer_7)
|
||||
w.Write([]byte(string(tmpl_profile_vars.Header.Widgets.RightSidebar)))
|
||||
w.Write(footer_8)
|
||||
}
|
||||
w.Write(footer_9)
|
||||
return nil
|
||||
}
|
@ -1,323 +0,0 @@
|
||||
// +build !no_templategen
|
||||
|
||||
// Code generated by Gosora. More below:
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "strconv"
|
||||
import "net/http"
|
||||
|
||||
// nolint
|
||||
func init() {
|
||||
template_topic_handle = template_topic
|
||||
//o_template_topic_handle = template_topic
|
||||
ctemplates = append(ctemplates,"topic")
|
||||
tmplPtrMap["topic"] = &template_topic_handle
|
||||
tmplPtrMap["o_topic"] = template_topic
|
||||
}
|
||||
|
||||
// nolint
|
||||
func template_topic(tmpl_topic_vars TopicPage, w http.ResponseWriter) error {
|
||||
w.Write(header_0)
|
||||
w.Write([]byte(tmpl_topic_vars.Title))
|
||||
w.Write(header_1)
|
||||
w.Write([]byte(tmpl_topic_vars.Header.Site.Name))
|
||||
w.Write(header_2)
|
||||
w.Write([]byte(tmpl_topic_vars.Header.ThemeName))
|
||||
w.Write(header_3)
|
||||
if len(tmpl_topic_vars.Header.Stylesheets) != 0 {
|
||||
for _, item := range tmpl_topic_vars.Header.Stylesheets {
|
||||
w.Write(header_4)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_5)
|
||||
}
|
||||
}
|
||||
w.Write(header_6)
|
||||
if len(tmpl_topic_vars.Header.Scripts) != 0 {
|
||||
for _, item := range tmpl_topic_vars.Header.Scripts {
|
||||
w.Write(header_7)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_8)
|
||||
}
|
||||
}
|
||||
w.Write(header_9)
|
||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||
w.Write(header_10)
|
||||
w.Write([]byte(tmpl_topic_vars.Header.Site.URL))
|
||||
w.Write(header_11)
|
||||
if !tmpl_topic_vars.CurrentUser.IsSuperMod {
|
||||
w.Write(header_12)
|
||||
}
|
||||
w.Write(header_13)
|
||||
w.Write(menu_0)
|
||||
w.Write(menu_1)
|
||||
w.Write([]byte(tmpl_topic_vars.Header.Site.ShortName))
|
||||
w.Write(menu_2)
|
||||
if tmpl_topic_vars.CurrentUser.Loggedin {
|
||||
w.Write(menu_3)
|
||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Link))
|
||||
w.Write(menu_4)
|
||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||
w.Write(menu_5)
|
||||
} else {
|
||||
w.Write(menu_6)
|
||||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_14)
|
||||
if tmpl_topic_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(header_15)
|
||||
}
|
||||
w.Write(header_16)
|
||||
if len(tmpl_topic_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topic_vars.Header.NoticeList {
|
||||
w.Write(header_17)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_18)
|
||||
}
|
||||
}
|
||||
w.Write(topic_0)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_1)
|
||||
if tmpl_topic_vars.Page > 1 {
|
||||
w.Write(topic_2)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_3)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Page - 1)))
|
||||
w.Write(topic_4)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_5)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Page - 1)))
|
||||
w.Write(topic_6)
|
||||
}
|
||||
if tmpl_topic_vars.LastPage != tmpl_topic_vars.Page {
|
||||
w.Write(topic_7)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_8)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Page + 1)))
|
||||
w.Write(topic_9)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_10)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Page + 1)))
|
||||
w.Write(topic_11)
|
||||
}
|
||||
w.Write(topic_12)
|
||||
if tmpl_topic_vars.Topic.Sticky {
|
||||
w.Write(topic_13)
|
||||
} else {
|
||||
if tmpl_topic_vars.Topic.IsClosed {
|
||||
w.Write(topic_14)
|
||||
}
|
||||
}
|
||||
w.Write(topic_15)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
||||
w.Write(topic_16)
|
||||
if tmpl_topic_vars.Topic.IsClosed {
|
||||
w.Write(topic_17)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
|
||||
w.Write(topic_18)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.Title))
|
||||
w.Write(topic_19)
|
||||
}
|
||||
w.Write(topic_20)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
|
||||
w.Write(topic_21)
|
||||
if tmpl_topic_vars.Topic.Avatar != "" {
|
||||
w.Write(topic_22)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
|
||||
w.Write(topic_23)
|
||||
w.Write([]byte(tmpl_topic_vars.Header.ThemeName))
|
||||
w.Write(topic_24)
|
||||
if tmpl_topic_vars.Topic.ContentLines <= 5 {
|
||||
w.Write(topic_25)
|
||||
}
|
||||
w.Write(topic_26)
|
||||
}
|
||||
w.Write(topic_27)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.ContentHTML))
|
||||
w.Write(topic_28)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.Content))
|
||||
w.Write(topic_29)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.UserLink))
|
||||
w.Write(topic_30)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName))
|
||||
w.Write(topic_31)
|
||||
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
|
||||
w.Write(topic_32)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_33)
|
||||
if tmpl_topic_vars.Topic.Liked {
|
||||
w.Write(topic_34)
|
||||
}
|
||||
w.Write(topic_35)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
|
||||
w.Write(topic_36)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_37)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.DeleteTopic {
|
||||
w.Write(topic_38)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_39)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.CloseTopic {
|
||||
if tmpl_topic_vars.Topic.IsClosed {
|
||||
w.Write(topic_40)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_41)
|
||||
} else {
|
||||
w.Write(topic_42)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_43)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.PinTopic {
|
||||
if tmpl_topic_vars.Topic.Sticky {
|
||||
w.Write(topic_44)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_45)
|
||||
} else {
|
||||
w.Write(topic_46)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_47)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_48)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.IPAddress))
|
||||
w.Write(topic_49)
|
||||
}
|
||||
w.Write(topic_50)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_51)
|
||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||
w.Write(topic_52)
|
||||
if tmpl_topic_vars.Topic.LikeCount > 0 {
|
||||
w.Write(topic_53)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount)))
|
||||
w.Write(topic_54)
|
||||
}
|
||||
if tmpl_topic_vars.Topic.Tag != "" {
|
||||
w.Write(topic_55)
|
||||
w.Write([]byte(tmpl_topic_vars.Topic.Tag))
|
||||
w.Write(topic_56)
|
||||
} else {
|
||||
w.Write(topic_57)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level)))
|
||||
w.Write(topic_58)
|
||||
}
|
||||
w.Write(topic_59)
|
||||
if len(tmpl_topic_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_topic_vars.ItemList {
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_60)
|
||||
w.Write([]byte(item.ActionIcon))
|
||||
w.Write(topic_61)
|
||||
w.Write([]byte(item.ActionType))
|
||||
w.Write(topic_62)
|
||||
} else {
|
||||
w.Write(topic_63)
|
||||
w.Write([]byte(item.ClassName))
|
||||
w.Write(topic_64)
|
||||
if item.Avatar != "" {
|
||||
w.Write(topic_65)
|
||||
w.Write([]byte(item.Avatar))
|
||||
w.Write(topic_66)
|
||||
w.Write([]byte(tmpl_topic_vars.Header.ThemeName))
|
||||
w.Write(topic_67)
|
||||
if item.ContentLines <= 5 {
|
||||
w.Write(topic_68)
|
||||
}
|
||||
w.Write(topic_69)
|
||||
}
|
||||
w.Write(topic_70)
|
||||
w.Write(topic_71)
|
||||
w.Write([]byte(item.ContentHtml))
|
||||
w.Write(topic_72)
|
||||
w.Write([]byte(item.UserLink))
|
||||
w.Write(topic_73)
|
||||
w.Write([]byte(item.CreatedByName))
|
||||
w.Write(topic_74)
|
||||
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
|
||||
w.Write(topic_75)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_76)
|
||||
if item.Liked {
|
||||
w.Write(topic_77)
|
||||
}
|
||||
w.Write(topic_78)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.EditReply {
|
||||
w.Write(topic_79)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_80)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply {
|
||||
w.Write(topic_81)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_82)
|
||||
}
|
||||
if tmpl_topic_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_83)
|
||||
w.Write([]byte(item.IPAddress))
|
||||
w.Write(topic_84)
|
||||
}
|
||||
w.Write(topic_85)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_86)
|
||||
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
|
||||
w.Write(topic_87)
|
||||
if item.LikeCount > 0 {
|
||||
w.Write(topic_88)
|
||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||
w.Write(topic_89)
|
||||
}
|
||||
if item.Tag != "" {
|
||||
w.Write(topic_90)
|
||||
w.Write([]byte(item.Tag))
|
||||
w.Write(topic_91)
|
||||
} else {
|
||||
w.Write(topic_92)
|
||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||
w.Write(topic_93)
|
||||
}
|
||||
w.Write(topic_94)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(topic_95)
|
||||
if tmpl_topic_vars.CurrentUser.Perms.CreateReply {
|
||||
w.Write(topic_96)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
|
||||
w.Write(topic_97)
|
||||
if tmpl_topic_vars.CurrentUser.Perms.UploadFiles {
|
||||
w.Write(topic_98)
|
||||
}
|
||||
w.Write(topic_99)
|
||||
}
|
||||
w.Write(topic_100)
|
||||
w.Write(footer_0)
|
||||
if len(tmpl_topic_vars.Header.Themes) != 0 {
|
||||
for _, item := range tmpl_topic_vars.Header.Themes {
|
||||
if !item.HideFromThemes {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(footer_2)
|
||||
if tmpl_topic_vars.Header.ThemeName == item.Name {
|
||||
w.Write(footer_3)
|
||||
}
|
||||
w.Write(footer_4)
|
||||
w.Write([]byte(item.FriendlyName))
|
||||
w.Write(footer_5)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(footer_6)
|
||||
if tmpl_topic_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(footer_7)
|
||||
w.Write([]byte(string(tmpl_topic_vars.Header.Widgets.RightSidebar)))
|
||||
w.Write(footer_8)
|
||||
}
|
||||
w.Write(footer_9)
|
||||
return nil
|
||||
}
|
@ -1,329 +0,0 @@
|
||||
// +build !no_templategen
|
||||
|
||||
// Code generated by Gosora. More below:
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "strconv"
|
||||
import "net/http"
|
||||
|
||||
// nolint
|
||||
func init() {
|
||||
template_topic_alt_handle = template_topic_alt
|
||||
//o_template_topic_alt_handle = template_topic_alt
|
||||
ctemplates = append(ctemplates,"topic_alt")
|
||||
tmplPtrMap["topic_alt"] = &template_topic_alt_handle
|
||||
tmplPtrMap["o_topic_alt"] = template_topic_alt
|
||||
}
|
||||
|
||||
// nolint
|
||||
func template_topic_alt(tmpl_topic_alt_vars TopicPage, w http.ResponseWriter) error {
|
||||
w.Write(header_0)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Title))
|
||||
w.Write(header_1)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Header.Site.Name))
|
||||
w.Write(header_2)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Header.ThemeName))
|
||||
w.Write(header_3)
|
||||
if len(tmpl_topic_alt_vars.Header.Stylesheets) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.Header.Stylesheets {
|
||||
w.Write(header_4)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_5)
|
||||
}
|
||||
}
|
||||
w.Write(header_6)
|
||||
if len(tmpl_topic_alt_vars.Header.Scripts) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.Header.Scripts {
|
||||
w.Write(header_7)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_8)
|
||||
}
|
||||
}
|
||||
w.Write(header_9)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(header_10)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Header.Site.URL))
|
||||
w.Write(header_11)
|
||||
if !tmpl_topic_alt_vars.CurrentUser.IsSuperMod {
|
||||
w.Write(header_12)
|
||||
}
|
||||
w.Write(header_13)
|
||||
w.Write(menu_0)
|
||||
w.Write(menu_1)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Header.Site.ShortName))
|
||||
w.Write(menu_2)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||
w.Write(menu_3)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
||||
w.Write(menu_4)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(menu_5)
|
||||
} else {
|
||||
w.Write(menu_6)
|
||||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_14)
|
||||
if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(header_15)
|
||||
}
|
||||
w.Write(header_16)
|
||||
if len(tmpl_topic_alt_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.Header.NoticeList {
|
||||
w.Write(header_17)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_18)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_alt_vars.Page > 1 {
|
||||
w.Write(topic_alt_0)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_1)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Page - 1)))
|
||||
w.Write(topic_alt_2)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_3)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Page - 1)))
|
||||
w.Write(topic_alt_4)
|
||||
}
|
||||
if tmpl_topic_alt_vars.LastPage != tmpl_topic_alt_vars.Page {
|
||||
w.Write(topic_alt_5)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_6)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Page + 1)))
|
||||
w.Write(topic_alt_7)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_8)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Page + 1)))
|
||||
w.Write(topic_alt_9)
|
||||
}
|
||||
w.Write(topic_alt_10)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_11)
|
||||
if tmpl_topic_alt_vars.Topic.Sticky {
|
||||
w.Write(topic_alt_12)
|
||||
} else {
|
||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||
w.Write(topic_alt_13)
|
||||
}
|
||||
}
|
||||
w.Write(topic_alt_14)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
||||
w.Write(topic_alt_15)
|
||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||
w.Write(topic_alt_16)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
||||
w.Write(topic_alt_17)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Title))
|
||||
w.Write(topic_alt_18)
|
||||
}
|
||||
w.Write(topic_alt_19)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Avatar))
|
||||
w.Write(topic_alt_20)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.UserLink))
|
||||
w.Write(topic_alt_21)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.CreatedByName))
|
||||
w.Write(topic_alt_22)
|
||||
if tmpl_topic_alt_vars.Topic.Tag != "" {
|
||||
w.Write(topic_alt_23)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Tag))
|
||||
w.Write(topic_alt_24)
|
||||
} else {
|
||||
w.Write(topic_alt_25)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.Level)))
|
||||
w.Write(topic_alt_26)
|
||||
}
|
||||
w.Write(topic_alt_27)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.ContentHTML))
|
||||
w.Write(topic_alt_28)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.Content))
|
||||
w.Write(topic_alt_29)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||
w.Write(topic_alt_30)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_31)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditTopic {
|
||||
w.Write(topic_alt_32)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_33)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteTopic {
|
||||
w.Write(topic_alt_34)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_35)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CloseTopic {
|
||||
if tmpl_topic_alt_vars.Topic.IsClosed {
|
||||
w.Write(topic_alt_36)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_37)
|
||||
} else {
|
||||
w.Write(topic_alt_38)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_39)
|
||||
}
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.PinTopic {
|
||||
if tmpl_topic_alt_vars.Topic.Sticky {
|
||||
w.Write(topic_alt_40)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_41)
|
||||
} else {
|
||||
w.Write(topic_alt_42)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_43)
|
||||
}
|
||||
}
|
||||
w.Write(topic_alt_44)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_45)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_46)
|
||||
}
|
||||
w.Write(topic_alt_47)
|
||||
if tmpl_topic_alt_vars.Topic.LikeCount > 0 {
|
||||
w.Write(topic_alt_48)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.LikeCount)))
|
||||
w.Write(topic_alt_49)
|
||||
}
|
||||
w.Write(topic_alt_50)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.RelativeCreatedAt))
|
||||
w.Write(topic_alt_51)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_52)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.Topic.IPAddress))
|
||||
w.Write(topic_alt_53)
|
||||
}
|
||||
w.Write(topic_alt_54)
|
||||
if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.ItemList {
|
||||
w.Write(topic_alt_55)
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_56)
|
||||
}
|
||||
w.Write(topic_alt_57)
|
||||
w.Write([]byte(item.Avatar))
|
||||
w.Write(topic_alt_58)
|
||||
w.Write([]byte(item.UserLink))
|
||||
w.Write(topic_alt_59)
|
||||
w.Write([]byte(item.CreatedByName))
|
||||
w.Write(topic_alt_60)
|
||||
if item.Tag != "" {
|
||||
w.Write(topic_alt_61)
|
||||
w.Write([]byte(item.Tag))
|
||||
w.Write(topic_alt_62)
|
||||
} else {
|
||||
w.Write(topic_alt_63)
|
||||
w.Write([]byte(strconv.Itoa(item.Level)))
|
||||
w.Write(topic_alt_64)
|
||||
}
|
||||
w.Write(topic_alt_65)
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_66)
|
||||
}
|
||||
w.Write(topic_alt_67)
|
||||
if item.ActionType != "" {
|
||||
w.Write(topic_alt_68)
|
||||
w.Write([]byte(item.ActionIcon))
|
||||
w.Write(topic_alt_69)
|
||||
w.Write([]byte(item.ActionType))
|
||||
w.Write(topic_alt_70)
|
||||
} else {
|
||||
w.Write(topic_alt_71)
|
||||
w.Write([]byte(item.ContentHtml))
|
||||
w.Write(topic_alt_72)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.LikeItem {
|
||||
w.Write(topic_alt_73)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_74)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.EditReply {
|
||||
w.Write(topic_alt_75)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_76)
|
||||
}
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.DeleteReply {
|
||||
w.Write(topic_alt_77)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_78)
|
||||
}
|
||||
w.Write(topic_alt_79)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topic_alt_80)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
|
||||
w.Write(topic_alt_81)
|
||||
}
|
||||
w.Write(topic_alt_82)
|
||||
if item.LikeCount > 0 {
|
||||
w.Write(topic_alt_83)
|
||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||
w.Write(topic_alt_84)
|
||||
}
|
||||
w.Write(topic_alt_85)
|
||||
w.Write([]byte(item.RelativeCreatedAt))
|
||||
w.Write(topic_alt_86)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.ViewIPs {
|
||||
w.Write(topic_alt_87)
|
||||
w.Write([]byte(item.IPAddress))
|
||||
w.Write(topic_alt_88)
|
||||
}
|
||||
w.Write(topic_alt_89)
|
||||
}
|
||||
w.Write(topic_alt_90)
|
||||
}
|
||||
}
|
||||
w.Write(topic_alt_91)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
||||
w.Write(topic_alt_92)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Avatar))
|
||||
w.Write(topic_alt_93)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Link))
|
||||
w.Write(topic_alt_94)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Name))
|
||||
w.Write(topic_alt_95)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Tag != "" {
|
||||
w.Write(topic_alt_96)
|
||||
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Tag))
|
||||
w.Write(topic_alt_97)
|
||||
} else {
|
||||
w.Write(topic_alt_98)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.Level)))
|
||||
w.Write(topic_alt_99)
|
||||
}
|
||||
w.Write(topic_alt_100)
|
||||
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.Topic.ID)))
|
||||
w.Write(topic_alt_101)
|
||||
if tmpl_topic_alt_vars.CurrentUser.Perms.UploadFiles {
|
||||
w.Write(topic_alt_102)
|
||||
}
|
||||
w.Write(topic_alt_103)
|
||||
}
|
||||
w.Write(topic_alt_104)
|
||||
w.Write(footer_0)
|
||||
if len(tmpl_topic_alt_vars.Header.Themes) != 0 {
|
||||
for _, item := range tmpl_topic_alt_vars.Header.Themes {
|
||||
if !item.HideFromThemes {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(footer_2)
|
||||
if tmpl_topic_alt_vars.Header.ThemeName == item.Name {
|
||||
w.Write(footer_3)
|
||||
}
|
||||
w.Write(footer_4)
|
||||
w.Write([]byte(item.FriendlyName))
|
||||
w.Write(footer_5)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(footer_6)
|
||||
if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(footer_7)
|
||||
w.Write([]byte(string(tmpl_topic_alt_vars.Header.Widgets.RightSidebar)))
|
||||
w.Write(footer_8)
|
||||
}
|
||||
w.Write(footer_9)
|
||||
return nil
|
||||
}
|
@ -1,226 +0,0 @@
|
||||
// +build !no_templategen
|
||||
|
||||
// Code generated by Gosora. More below:
|
||||
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||
package main
|
||||
import "net/http"
|
||||
import "strconv"
|
||||
|
||||
// nolint
|
||||
func init() {
|
||||
template_topics_handle = template_topics
|
||||
//o_template_topics_handle = template_topics
|
||||
ctemplates = append(ctemplates,"topics")
|
||||
tmplPtrMap["topics"] = &template_topics_handle
|
||||
tmplPtrMap["o_topics"] = template_topics
|
||||
}
|
||||
|
||||
// nolint
|
||||
func template_topics(tmpl_topics_vars TopicsPage, w http.ResponseWriter) error {
|
||||
w.Write(header_0)
|
||||
w.Write([]byte(tmpl_topics_vars.Title))
|
||||
w.Write(header_1)
|
||||
w.Write([]byte(tmpl_topics_vars.Header.Site.Name))
|
||||
w.Write(header_2)
|
||||
w.Write([]byte(tmpl_topics_vars.Header.ThemeName))
|
||||
w.Write(header_3)
|
||||
if len(tmpl_topics_vars.Header.Stylesheets) != 0 {
|
||||
for _, item := range tmpl_topics_vars.Header.Stylesheets {
|
||||
w.Write(header_4)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_5)
|
||||
}
|
||||
}
|
||||
w.Write(header_6)
|
||||
if len(tmpl_topics_vars.Header.Scripts) != 0 {
|
||||
for _, item := range tmpl_topics_vars.Header.Scripts {
|
||||
w.Write(header_7)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_8)
|
||||
}
|
||||
}
|
||||
w.Write(header_9)
|
||||
w.Write([]byte(tmpl_topics_vars.CurrentUser.Session))
|
||||
w.Write(header_10)
|
||||
w.Write([]byte(tmpl_topics_vars.Header.Site.URL))
|
||||
w.Write(header_11)
|
||||
if !tmpl_topics_vars.CurrentUser.IsSuperMod {
|
||||
w.Write(header_12)
|
||||
}
|
||||
w.Write(header_13)
|
||||
w.Write(menu_0)
|
||||
w.Write(menu_1)
|
||||
w.Write([]byte(tmpl_topics_vars.Header.Site.ShortName))
|
||||
w.Write(menu_2)
|
||||
if tmpl_topics_vars.CurrentUser.Loggedin {
|
||||
w.Write(menu_3)
|
||||
w.Write([]byte(tmpl_topics_vars.CurrentUser.Link))
|
||||
w.Write(menu_4)
|
||||
w.Write([]byte(tmpl_topics_vars.CurrentUser.Session))
|
||||
w.Write(menu_5)
|
||||
} else {
|
||||
w.Write(menu_6)
|
||||
}
|
||||
w.Write(menu_7)
|
||||
w.Write(header_14)
|
||||
if tmpl_topics_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(header_15)
|
||||
}
|
||||
w.Write(header_16)
|
||||
if len(tmpl_topics_vars.Header.NoticeList) != 0 {
|
||||
for _, item := range tmpl_topics_vars.Header.NoticeList {
|
||||
w.Write(header_17)
|
||||
w.Write([]byte(item))
|
||||
w.Write(header_18)
|
||||
}
|
||||
}
|
||||
w.Write(topics_0)
|
||||
if tmpl_topics_vars.CurrentUser.ID != 0 {
|
||||
w.Write(topics_1)
|
||||
}
|
||||
w.Write(topics_2)
|
||||
if tmpl_topics_vars.CurrentUser.ID != 0 {
|
||||
if len(tmpl_topics_vars.ForumList) != 0 {
|
||||
w.Write(topics_3)
|
||||
w.Write(topics_4)
|
||||
} else {
|
||||
w.Write(topics_5)
|
||||
}
|
||||
w.Write(topics_6)
|
||||
}
|
||||
w.Write(topics_7)
|
||||
if tmpl_topics_vars.CurrentUser.ID != 0 {
|
||||
w.Write(topics_8)
|
||||
if len(tmpl_topics_vars.ForumList) != 0 {
|
||||
w.Write(topics_9)
|
||||
if tmpl_topics_vars.CurrentUser.Avatar != "" {
|
||||
w.Write(topics_10)
|
||||
w.Write([]byte(tmpl_topics_vars.CurrentUser.Avatar))
|
||||
w.Write(topics_11)
|
||||
}
|
||||
w.Write(topics_12)
|
||||
if len(tmpl_topics_vars.ForumList) != 0 {
|
||||
for _, item := range tmpl_topics_vars.ForumList {
|
||||
w.Write(topics_13)
|
||||
if item.ID == tmpl_topics_vars.DefaultForum {
|
||||
w.Write(topics_14)
|
||||
}
|
||||
w.Write(topics_15)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topics_16)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(topics_17)
|
||||
}
|
||||
}
|
||||
w.Write(topics_18)
|
||||
if tmpl_topics_vars.CurrentUser.Perms.UploadFiles {
|
||||
w.Write(topics_19)
|
||||
}
|
||||
w.Write(topics_20)
|
||||
}
|
||||
}
|
||||
w.Write(topics_21)
|
||||
if len(tmpl_topics_vars.TopicList) != 0 {
|
||||
for _, item := range tmpl_topics_vars.TopicList {
|
||||
w.Write(topics_22)
|
||||
w.Write([]byte(strconv.Itoa(item.ID)))
|
||||
w.Write(topics_23)
|
||||
if item.Sticky {
|
||||
w.Write(topics_24)
|
||||
} else {
|
||||
if item.IsClosed {
|
||||
w.Write(topics_25)
|
||||
}
|
||||
}
|
||||
w.Write(topics_26)
|
||||
if item.Creator.Avatar != "" {
|
||||
w.Write(topics_27)
|
||||
w.Write([]byte(item.Creator.Link))
|
||||
w.Write(topics_28)
|
||||
w.Write([]byte(item.Creator.Avatar))
|
||||
w.Write(topics_29)
|
||||
}
|
||||
w.Write(topics_30)
|
||||
w.Write([]byte(item.Link))
|
||||
w.Write(topics_31)
|
||||
w.Write([]byte(item.Title))
|
||||
w.Write(topics_32)
|
||||
if item.ForumName != "" {
|
||||
w.Write(topics_33)
|
||||
w.Write([]byte(item.ForumLink))
|
||||
w.Write(topics_34)
|
||||
w.Write([]byte(item.ForumName))
|
||||
w.Write(topics_35)
|
||||
}
|
||||
w.Write(topics_36)
|
||||
w.Write([]byte(item.Creator.Link))
|
||||
w.Write(topics_37)
|
||||
w.Write([]byte(item.Creator.Name))
|
||||
w.Write(topics_38)
|
||||
if item.IsClosed {
|
||||
w.Write(topics_39)
|
||||
}
|
||||
if item.Sticky {
|
||||
w.Write(topics_40)
|
||||
}
|
||||
w.Write(topics_41)
|
||||
w.Write([]byte(strconv.Itoa(item.PostCount)))
|
||||
w.Write(topics_42)
|
||||
w.Write([]byte(strconv.Itoa(item.LikeCount)))
|
||||
w.Write(topics_43)
|
||||
if item.Sticky {
|
||||
w.Write(topics_44)
|
||||
} else {
|
||||
if item.IsClosed {
|
||||
w.Write(topics_45)
|
||||
}
|
||||
}
|
||||
w.Write(topics_46)
|
||||
if item.LastUser.Avatar != "" {
|
||||
w.Write(topics_47)
|
||||
w.Write([]byte(item.LastUser.Link))
|
||||
w.Write(topics_48)
|
||||
w.Write([]byte(item.LastUser.Avatar))
|
||||
w.Write(topics_49)
|
||||
}
|
||||
w.Write(topics_50)
|
||||
w.Write([]byte(item.LastUser.Link))
|
||||
w.Write(topics_51)
|
||||
w.Write([]byte(item.LastUser.Name))
|
||||
w.Write(topics_52)
|
||||
w.Write([]byte(item.RelativeLastReplyAt))
|
||||
w.Write(topics_53)
|
||||
}
|
||||
} else {
|
||||
w.Write(topics_54)
|
||||
if tmpl_topics_vars.CurrentUser.Perms.CreateTopic {
|
||||
w.Write(topics_55)
|
||||
}
|
||||
w.Write(topics_56)
|
||||
}
|
||||
w.Write(topics_57)
|
||||
w.Write(footer_0)
|
||||
if len(tmpl_topics_vars.Header.Themes) != 0 {
|
||||
for _, item := range tmpl_topics_vars.Header.Themes {
|
||||
if !item.HideFromThemes {
|
||||
w.Write(footer_1)
|
||||
w.Write([]byte(item.Name))
|
||||
w.Write(footer_2)
|
||||
if tmpl_topics_vars.Header.ThemeName == item.Name {
|
||||
w.Write(footer_3)
|
||||
}
|
||||
w.Write(footer_4)
|
||||
w.Write([]byte(item.FriendlyName))
|
||||
w.Write(footer_5)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Write(footer_6)
|
||||
if tmpl_topics_vars.Header.Widgets.RightSidebar != "" {
|
||||
w.Write(footer_7)
|
||||
w.Write([]byte(string(tmpl_topics_vars.Header.Widgets.RightSidebar)))
|
||||
w.Write(footer_8)
|
||||
}
|
||||
w.Write(footer_9)
|
||||
return nil
|
||||
}
|
@ -18,6 +18,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"./common"
|
||||
"github.com/Azareal/gopsutil/cpu"
|
||||
"github.com/Azareal/gopsutil/mem"
|
||||
"github.com/gorilla/websocket"
|
||||
@ -25,7 +26,7 @@ import (
|
||||
|
||||
type WSUser struct {
|
||||
conn *websocket.Conn
|
||||
User *User
|
||||
User *common.User
|
||||
}
|
||||
|
||||
type WSHub struct {
|
||||
@ -164,13 +165,13 @@ func (hub *WSHub) pushAlerts(users []int, asid int, event string, elementType st
|
||||
}
|
||||
|
||||
// TODO: How should we handle errors for this?
|
||||
func routeWebsockets(w http.ResponseWriter, r *http.Request, user User) RouteError {
|
||||
func routeWebsockets(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
conn, err := wsUpgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
userptr, err := users.Get(user.ID)
|
||||
if err != nil && err != ErrStoreCapacityOverflow {
|
||||
userptr, err := common.Users.Get(user.ID)
|
||||
if err != nil && err != common.ErrStoreCapacityOverflow {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -341,9 +342,9 @@ AdminStatLoop:
|
||||
onlineUsersColour = "stat_red"
|
||||
}
|
||||
|
||||
totonline, totunit = convertFriendlyUnit(totonline)
|
||||
uonline, uunit = convertFriendlyUnit(uonline)
|
||||
gonline, gunit = convertFriendlyUnit(gonline)
|
||||
totonline, totunit = common.ConvertFriendlyUnit(totonline)
|
||||
uonline, uunit = common.ConvertFriendlyUnit(uonline)
|
||||
gonline, gunit = common.ConvertFriendlyUnit(gonline)
|
||||
}
|
||||
|
||||
if cpuerr != nil {
|
||||
@ -364,8 +365,8 @@ AdminStatLoop:
|
||||
if ramerr != nil {
|
||||
ramstr = "Unknown"
|
||||
} else {
|
||||
totalCount, totalUnit := convertByteUnit(float64(memres.Total))
|
||||
usedCount := convertByteInUnit(float64(memres.Total-memres.Available), totalUnit)
|
||||
totalCount, totalUnit := common.ConvertByteUnit(float64(memres.Total))
|
||||
usedCount := common.ConvertByteInUnit(float64(memres.Total-memres.Available), totalUnit)
|
||||
|
||||
// Round totals with .9s up, it's how most people see it anyway. Floats are notoriously imprecise, so do it off 0.85
|
||||
var totstr string
|
||||
|
@ -1,45 +0,0 @@
|
||||
package main
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
type WordFilter struct {
|
||||
ID int
|
||||
Find string
|
||||
Replacement string
|
||||
}
|
||||
type WordFilterBox map[int]WordFilter
|
||||
|
||||
var wordFilterBox atomic.Value // An atomic value holding a WordFilterBox
|
||||
|
||||
func init() {
|
||||
wordFilterBox.Store(WordFilterBox(make(map[int]WordFilter)))
|
||||
}
|
||||
|
||||
func LoadWordFilters() error {
|
||||
rows, err := stmts.getWordFilters.Query()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var wordFilters = WordFilterBox(make(map[int]WordFilter))
|
||||
var wfid int
|
||||
var find string
|
||||
var replacement string
|
||||
|
||||
for rows.Next() {
|
||||
err := rows.Scan(&wfid, &find, &replacement)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wordFilters[wfid] = WordFilter{ID: wfid, Find: find, Replacement: replacement}
|
||||
}
|
||||
wordFilterBox.Store(wordFilters)
|
||||
return rows.Err()
|
||||
}
|
||||
|
||||
func addWordFilter(id int, find string, replacement string) {
|
||||
wordFilters := wordFilterBox.Load().(WordFilterBox)
|
||||
wordFilters[id] = WordFilter{ID: id, Find: find, Replacement: replacement}
|
||||
wordFilterBox.Store(wordFilters)
|
||||
}
|
Loading…
Reference in New Issue
Block a user