More conversations work.
Add support for AS in columns for SimpleInnerJoin. Add a referrer policy to improve privacy a little. Shorten /static/ to /s/ since it comes up so much. Remove some obsolete code. Shorten some variable names. Reduce the amount of boilerplate in the patcher. Added the RefNoTrack and RefNoRef privacy config settings. You may need to run the updater / patcher for this commit.
This commit is contained in:
parent
6ba4b665e3
commit
4d8c97812d
|
@ -362,7 +362,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
)
|
)
|
||||||
|
|
||||||
//columns("participants, createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?")
|
//columns("participants, createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?")
|
||||||
/*qgen.Install.CreateTable("conversations", "", "",
|
qgen.Install.CreateTable("conversations", "", "",
|
||||||
[]tC{
|
[]tC{
|
||||||
tC{"cid", "int", 0, false, true, ""},
|
tC{"cid", "int", 0, false, true, ""},
|
||||||
tC{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
tC{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
|
@ -393,7 +393,7 @@ func createTables(adapter qgen.Adapter) error {
|
||||||
tC{"uid", "int", 0, false, false, ""},
|
tC{"uid", "int", 0, false, false, ""},
|
||||||
tC{"cid", "int", 0, false, false, ""},
|
tC{"cid", "int", 0, false, false, ""},
|
||||||
}, nil,
|
}, nil,
|
||||||
)*/
|
)
|
||||||
|
|
||||||
qgen.Install.CreateTable("activity_stream_matches", "", "",
|
qgen.Install.CreateTable("activity_stream_matches", "", "",
|
||||||
[]tC{
|
[]tC{
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
//"strconv"
|
//"strconv"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
@ -17,62 +18,63 @@ var Convos ConversationStore
|
||||||
var convoStmts ConvoStmts
|
var convoStmts ConvoStmts
|
||||||
|
|
||||||
type ConvoStmts struct {
|
type ConvoStmts struct {
|
||||||
getPosts *sql.Stmt
|
fetchPost *sql.Stmt
|
||||||
|
getPosts *sql.Stmt
|
||||||
countPosts *sql.Stmt
|
countPosts *sql.Stmt
|
||||||
edit *sql.Stmt
|
edit *sql.Stmt
|
||||||
create *sql.Stmt
|
create *sql.Stmt
|
||||||
delete *sql.Stmt
|
delete *sql.Stmt
|
||||||
|
|
||||||
editPost *sql.Stmt
|
editPost *sql.Stmt
|
||||||
createPost *sql.Stmt
|
createPost *sql.Stmt
|
||||||
|
deletePost *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func init() {
|
func init() {
|
||||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||||
convoStmts = ConvoStmts{
|
convoStmts = ConvoStmts{
|
||||||
getPosts: acc.Select("conversations_posts").Columns("pid, body, post, createdBy").Where("cid = ?").Limit("?,?").Prepare(),
|
fetchPost: acc.Select("conversations_posts").Columns("cid, body, post, createdBy").Where("pid = ?").Prepare(),
|
||||||
|
getPosts: acc.Select("conversations_posts").Columns("pid, body, post, createdBy").Where("cid = ?").Limit("?,?").Prepare(),
|
||||||
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
|
countPosts: acc.Count("conversations_posts").Where("cid = ?").Prepare(),
|
||||||
//edit: acc.Update("conversations").Set("participants = ?, lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
||||||
edit: acc.Update("conversations").Set("lastReplyBy = ?, lastReplyAt = ?").Where("cid = ?").Prepare(),
|
create: acc.Insert("conversations").Columns("createdAt, lastReplyAt").Fields("UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||||
//create: acc.Insert("conversations").Columns("participants, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
|
||||||
create: acc.Insert("conversations").Columns("createdAt, lastReplyAt").Fields("UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
|
||||||
|
|
||||||
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("cid = ?").Prepare(),
|
editPost: acc.Update("conversations_posts").Set("body = ?, post = ?").Where("cid = ?").Prepare(),
|
||||||
createPost: acc.Insert("conversations_posts").Columns("cid, body, post, createdBy").Fields("?,?,?,?").Prepare(),
|
createPost: acc.Insert("conversations_posts").Columns("cid, body, post, createdBy").Fields("?,?,?,?").Prepare(),
|
||||||
|
deletePost: acc.Delete("conversations_posts").Where("pid = ?").Prepare(),
|
||||||
}
|
}
|
||||||
return acc.FirstError()
|
return acc.FirstError()
|
||||||
})
|
})
|
||||||
}*/
|
}
|
||||||
|
|
||||||
type Conversation struct {
|
type Conversation struct {
|
||||||
ID int
|
ID int
|
||||||
//Participants string
|
CreatedBy int
|
||||||
CreatedBy int
|
CreatedAt time.Time
|
||||||
CreatedAt time.Time
|
|
||||||
LastReplyBy int
|
LastReplyBy int
|
||||||
LastReplyAt time.Time
|
LastReplyAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Conversation) Posts(offset int) (posts []*ConversationPost, err error) {
|
func (co *Conversation) Posts(offset, itemsPerPage int) (posts []*ConversationPost, err error) {
|
||||||
rows, err := convoStmts.getPosts.Query(co.ID, offset, Config.ItemsPerPage)
|
rows, err := convoStmts.getPosts.Query(co.ID, offset, itemsPerPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
convo := &ConversationPost{CID: co.ID}
|
p := &ConversationPost{CID: co.ID}
|
||||||
err := rows.Scan(&convo.ID, &convo.Body, &convo.Post, &convo.CreatedBy)
|
err := rows.Scan(&p.ID, &p.Body, &p.Post, &p.CreatedBy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
convo, err = ConvoPostProcess.OnLoad(convo)
|
p, err = ConvoPostProcess.OnLoad(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
posts = append(posts, convo)
|
posts = append(posts, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
return posts, rows.Err()
|
return posts, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,12 +87,12 @@ func (co *Conversation) PostsCount() (count int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Conversation) Update() error {
|
func (co *Conversation) Update() error {
|
||||||
_, err := convoStmts.edit.Exec(/*co.Participants, */co.CreatedAt, co.LastReplyBy, co.LastReplyAt, co.ID)
|
_, err := convoStmts.edit.Exec(co.CreatedAt, co.LastReplyBy, co.LastReplyAt, co.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Conversation) Create() (int, error) {
|
func (co *Conversation) Create() (int, error) {
|
||||||
res, err := convoStmts.create.Exec(/*co.Participants*/)
|
res, err := convoStmts.create.Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -109,39 +111,34 @@ type ConversationStore interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultConversationStore struct {
|
type DefaultConversationStore struct {
|
||||||
get *sql.Stmt
|
get *sql.Stmt
|
||||||
getUser *sql.Stmt
|
getUser *sql.Stmt
|
||||||
getUserCount *sql.Stmt
|
getUserCount *sql.Stmt
|
||||||
delete *sql.Stmt
|
delete *sql.Stmt
|
||||||
deletePosts *sql.Stmt
|
deletePosts *sql.Stmt
|
||||||
create *sql.Stmt
|
deleteParticipants *sql.Stmt
|
||||||
|
create *sql.Stmt
|
||||||
addParticipant *sql.Stmt
|
addParticipant *sql.Stmt
|
||||||
count *sql.Stmt
|
count *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultConversationStore(acc *qgen.Accumulator) (*DefaultConversationStore, error) {
|
func NewDefaultConversationStore(acc *qgen.Accumulator) (*DefaultConversationStore, error) {
|
||||||
return &DefaultConversationStore{
|
return &DefaultConversationStore{
|
||||||
//get: acc.Select("conversations").Columns("participants, createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
||||||
get: acc.Select("conversations").Columns("createdBy, createdAt, lastReplyBy, lastReplyAt").Where("cid = ?").Prepare(),
|
getUser: acc.SimpleInnerJoin("conversations_participants AS cp", "conversations AS c", "cp.cid, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt", "cp.cid = c.cid", "cp.uid = ?", "c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC", "?,?"),
|
||||||
|
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
||||||
//("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.likeCount, replies.attachCount, replies.actionType", "replies.createdBy = users.uid", "replies.tid = ?", "replies.rid ASC", "?,?")
|
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
||||||
//(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string)
|
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
||||||
|
deleteParticipants: acc.Delete("conversations_participants").Where("cid = ?").Prepare(),
|
||||||
//getUser: acc.SimpleLeftJoin("conversations_participants AS cp","conversations AS c","c.cid, c.participants, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt","cp.cid = c.cid","cp.uid = ?","c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC","?,?"),
|
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
||||||
getUser: acc.SimpleLeftJoin("conversations_participants AS cp","conversations AS c","c.cid, c.createdBy, c.createdAt, c.lastReplyBy, c.lastReplyAt","cp.cid = c.cid","cp.uid = ?","c.lastReplyAt DESC, c.createdAt DESC, c.cid DESC","?,?"),
|
|
||||||
getUserCount: acc.Count("conversations_participants").Where("uid = ?").Prepare(),
|
|
||||||
delete: acc.Delete("conversations").Where("cid = ?").Prepare(),
|
|
||||||
deletePosts: acc.Delete("conversations_posts").Where("cid = ?").Prepare(),
|
|
||||||
//create: acc.Insert("conversations").Columns("participants, createdBy, createdAt, lastReplyAt").Fields("?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
|
||||||
create: acc.Insert("conversations").Columns("createdBy, createdAt, lastReplyAt").Fields("?,UTC_TIMESTAMP(),UTC_TIMESTAMP()").Prepare(),
|
|
||||||
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
addParticipant: acc.Insert("conversations_participants").Columns("uid, cid").Fields("?,?").Prepare(),
|
||||||
count: acc.Count("conversations").Prepare(),
|
count: acc.Count("conversations").Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DefaultConversationStore) Get(id int) (*Conversation, error) {
|
func (s *DefaultConversationStore) Get(id int) (*Conversation, error) {
|
||||||
convo := &Conversation{ID: id}
|
convo := &Conversation{ID: id}
|
||||||
err := s.get.QueryRow(id).Scan(/*&convo.Participants, */&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
|
err := s.get.QueryRow(id).Scan(&convo.CreatedBy, &convo.CreatedAt, &convo.LastReplyBy, &convo.LastReplyAt)
|
||||||
return convo, err
|
return convo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +151,7 @@ func (s *DefaultConversationStore) GetUser(uid int, offset int) (cos []*Conversa
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
co := &Conversation{}
|
co := &Conversation{}
|
||||||
err := rows.Scan(&co.ID, /*&co.Participants,*/ &co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
|
err := rows.Scan(&co.ID, &co.CreatedBy, &co.CreatedAt, &co.LastReplyBy, &co.LastReplyAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -179,6 +176,10 @@ func (s *DefaultConversationStore) Delete(id int) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = s.deletePosts.Exec(id)
|
_, err = s.deletePosts.Exec(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = s.deleteParticipants.Exec(id)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,13 +187,7 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici
|
||||||
if len(participants) == 0 {
|
if len(participants) == 0 {
|
||||||
return 0, errors.New("no participants set")
|
return 0, errors.New("no participants set")
|
||||||
}
|
}
|
||||||
/*var pstr string
|
res, err := s.create.Exec(createdBy)
|
||||||
for _, parti := range participants {
|
|
||||||
pstr += strconv.Itoa(parti) + ","
|
|
||||||
}
|
|
||||||
pstr = pstr[:len(pstr)-1]*/
|
|
||||||
|
|
||||||
res, err := s.create.Exec(createdBy/*, pstr*/)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -211,12 +206,12 @@ func (s *DefaultConversationStore) Create(content string, createdBy int, partici
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range participants {
|
for _, p := range participants {
|
||||||
_, err := s.addParticipant.Exec(p,lastID)
|
_, err := s.addParticipant.Exec(p, lastID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err = s.addParticipant.Exec(createdBy,lastID)
|
_, err = s.addParticipant.Exec(createdBy, lastID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -231,4 +226,4 @@ func (s *DefaultConversationStore) Count() (count int) {
|
||||||
LogError(err)
|
LogError(err)
|
||||||
}
|
}
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"encoding/hex"
|
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ConvoPostProcess ConvoPostProcessor = NewDefaultConvoPostProcessor()
|
var ConvoPostProcess ConvoPostProcessor = NewDefaultConvoPostProcessor()
|
||||||
|
@ -99,13 +99,17 @@ func (pr *AesConvoPostProcessor) OnSave(co *ConversationPost) (*ConversationPost
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConversationPost struct {
|
type ConversationPost struct {
|
||||||
ID int
|
ID int
|
||||||
CID int
|
CID int
|
||||||
Body string
|
Body string
|
||||||
Post string // aes, ''
|
Post string // aes, ''
|
||||||
CreatedBy int
|
CreatedBy int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (co *ConversationPost) Fetch() error {
|
||||||
|
return convoStmts.fetchPost.QueryRow(co.ID).Scan(&co.CID, &co.Body, &co.Post, &co.CreatedBy)
|
||||||
|
}
|
||||||
|
|
||||||
func (co *ConversationPost) Update() error {
|
func (co *ConversationPost) Update() error {
|
||||||
lco, err := ConvoPostProcess.OnSave(co)
|
lco, err := ConvoPostProcess.OnSave(co)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -122,11 +126,16 @@ func (co *ConversationPost) Create() (int, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
//GetHookTable().VhookNoRet("convo_post_create", lco)
|
//GetHookTable().VhookNoRet("convo_post_create", lco)
|
||||||
res, err := convoStmts.createPost.Exec(lco.CID, lco.Body, lco.Post)
|
res, err := convoStmts.createPost.Exec(lco.CID, lco.Body, lco.Post, lco.CreatedBy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lastID, err := res.LastInsertId()
|
lastID, err := res.LastInsertId()
|
||||||
return int(lastID), err
|
return int(lastID), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (co *ConversationPost) Delete() error {
|
||||||
|
_, err := convoStmts.deletePost.Exec(co.ID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ func (list SFileList) JSTmplInit() error {
|
||||||
hasher.Write(data)
|
hasher.Write(data)
|
||||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
list.Set("/static/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
list.Set("/s/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||||
|
|
||||||
DebugLogf("Added the '%s' static file.", path)
|
DebugLogf("Added the '%s' static file.", path)
|
||||||
return nil
|
return nil
|
||||||
|
@ -285,7 +285,7 @@ func (list SFileList) Init() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.Set("/static/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mimetype, f, f.ModTime().UTC().Format(http.TimeFormat)})
|
list.Set("/s/"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mimetype, f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||||
|
|
||||||
DebugLogf("Added the '%s' static file.", path)
|
DebugLogf("Added the '%s' static file.", path)
|
||||||
return nil
|
return nil
|
||||||
|
@ -318,7 +318,7 @@ func (list SFileList) Add(path string, prefix string) error {
|
||||||
hasher.Write(data)
|
hasher.Write(data)
|
||||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
list.Set("/static"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
list.Set("/s"+path, SFile{data, gzipData, checksum,path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||||
|
|
||||||
DebugLogf("Added the '%s' static file", path)
|
DebugLogf("Added the '%s' static file", path)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Azareal/Gosora/common/phrases"
|
p "github.com/Azareal/Gosora/common/phrases"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*type HResource struct {
|
/*type HResource struct {
|
||||||
|
@ -15,7 +15,7 @@ import (
|
||||||
Hash string
|
Hash string
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
// TODO: Allow resources in spots other than /static/ and possibly even external domains (e.g. CDNs)
|
// TODO: Allow resources in spots other than /s/ and possibly even external domains (e.g. CDNs)
|
||||||
// TODO: Preload Trumboyg on Cosora on the forum list
|
// TODO: Preload Trumboyg on Cosora on the forum list
|
||||||
type Header struct {
|
type Header struct {
|
||||||
Title string
|
Title string
|
||||||
|
@ -50,9 +50,9 @@ type Header struct {
|
||||||
ExtData ExtData
|
ExtData ExtData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (header *Header) AddScript(name string) {
|
func (h *Header) AddScript(name string) {
|
||||||
// TODO: Use a secondary static file map to avoid this concatenation?
|
// TODO: Use a secondary static file map to avoid this concatenation?
|
||||||
fname := "/static/" + name
|
fname := "/s/" + name
|
||||||
var oname string
|
var oname string
|
||||||
if fname[0] == '/' && fname[1] != '/' {
|
if fname[0] == '/' && fname[1] != '/' {
|
||||||
file, ok := StaticFiles.Get(fname)
|
file, ok := StaticFiles.Get(fname)
|
||||||
|
@ -64,11 +64,11 @@ func (header *Header) AddScript(name string) {
|
||||||
oname = name
|
oname = name
|
||||||
}
|
}
|
||||||
//log.Print("oname:", oname)
|
//log.Print("oname:", oname)
|
||||||
header.Scripts = append(header.Scripts, oname)
|
h.Scripts = append(h.Scripts, oname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (header *Header) AddPreScriptAsync(name string) {
|
func (h *Header) AddPreScriptAsync(name string) {
|
||||||
fname := "/static/" + name
|
fname := "/s/" + name
|
||||||
var oname string
|
var oname string
|
||||||
if fname[0] == '/' && fname[1] != '/' {
|
if fname[0] == '/' && fname[1] != '/' {
|
||||||
file, ok := StaticFiles.Get(fname)
|
file, ok := StaticFiles.Get(fname)
|
||||||
|
@ -79,11 +79,11 @@ func (header *Header) AddPreScriptAsync(name string) {
|
||||||
if oname == "" {
|
if oname == "" {
|
||||||
oname = name
|
oname = name
|
||||||
}
|
}
|
||||||
header.PreScriptsAsync = append(header.PreScriptsAsync, oname)
|
h.PreScriptsAsync = append(h.PreScriptsAsync, oname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (header *Header) AddScriptAsync(name string) {
|
func (h *Header) AddScriptAsync(name string) {
|
||||||
fname := "/static/" + name
|
fname := "/s/" + name
|
||||||
var oname string
|
var oname string
|
||||||
if fname[0] == '/' && fname[1] != '/' {
|
if fname[0] == '/' && fname[1] != '/' {
|
||||||
file, ok := StaticFiles.Get(fname)
|
file, ok := StaticFiles.Get(fname)
|
||||||
|
@ -94,15 +94,15 @@ func (header *Header) AddScriptAsync(name string) {
|
||||||
if oname == "" {
|
if oname == "" {
|
||||||
oname = name
|
oname = name
|
||||||
}
|
}
|
||||||
header.ScriptsAsync = append(header.ScriptsAsync, oname)
|
h.ScriptsAsync = append(h.ScriptsAsync, oname)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func (header *Header) Preload(name string) {
|
/*func (h *Header) Preload(name string) {
|
||||||
header.Preload = append(header.Preload, name)
|
h.Preload = append(h.Preload, name)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
func (header *Header) AddSheet(name string) {
|
func (h *Header) AddSheet(name string) {
|
||||||
fname := "/static/" + name
|
fname := "/s/" + name
|
||||||
var oname string
|
var oname string
|
||||||
if fname[0] == '/' && fname[1] != '/' {
|
if fname[0] == '/' && fname[1] != '/' {
|
||||||
file, ok := StaticFiles.Get(fname)
|
file, ok := StaticFiles.Get(fname)
|
||||||
|
@ -113,11 +113,11 @@ func (header *Header) AddSheet(name string) {
|
||||||
if oname == "" {
|
if oname == "" {
|
||||||
oname = name
|
oname = name
|
||||||
}
|
}
|
||||||
header.Stylesheets = append(header.Stylesheets, oname)
|
h.Stylesheets = append(h.Stylesheets, oname)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (header *Header) AddNotice(name string) {
|
func (h *Header) AddNotice(name string) {
|
||||||
header.NoticeList = append(header.NoticeList, phrases.GetNoticePhrase(name))
|
h.NoticeList = append(h.NoticeList, p.GetNoticePhrase(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add this to routes which don't use templates. E.g. Json APIs.
|
// TODO: Add this to routes which don't use templates. E.g. Json APIs.
|
||||||
|
@ -289,9 +289,18 @@ type ConvoListPage struct {
|
||||||
Paginator
|
Paginator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConvoViewRow struct {
|
||||||
|
*ConversationPost
|
||||||
|
User *User
|
||||||
|
ClassName string
|
||||||
|
ContentLines string
|
||||||
|
}
|
||||||
|
|
||||||
type ConvoViewPage struct {
|
type ConvoViewPage struct {
|
||||||
*Header
|
*Header
|
||||||
Posts []*ConversationPost
|
Convo *Conversation
|
||||||
|
Posts []ConvoViewRow
|
||||||
|
CanModify bool
|
||||||
Paginator
|
Paginator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,9 @@ type config struct {
|
||||||
DisableNoavatarRange bool
|
DisableNoavatarRange bool
|
||||||
DisableDefaultNoavatar bool
|
DisableDefaultNoavatar bool
|
||||||
|
|
||||||
|
RefNoTrack bool
|
||||||
|
RefNoRef bool
|
||||||
|
|
||||||
Noavatar string // ? - Move this into the settings table?
|
Noavatar string // ? - Move this into the settings table?
|
||||||
ItemsPerPage int // ? - Move this into the settings table?
|
ItemsPerPage int // ? - Move this into the settings table?
|
||||||
MaxTopicTitleLength int
|
MaxTopicTitleLength int
|
||||||
|
|
|
@ -167,7 +167,7 @@ func (theme *Theme) AddThemeStaticFiles() error {
|
||||||
hasher.Write(data)
|
hasher.Write(data)
|
||||||
checksum := hex.EncodeToString(hasher.Sum(nil))
|
checksum := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
StaticFiles.Set("/static/"+theme.Name+path, SFile{data, gzipData, checksum,theme.Name+path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
StaticFiles.Set("/s/"+theme.Name+path, SFile{data, gzipData, checksum,theme.Name+path + "?h=" + checksum, 0, int64(len(data)), int64(len(gzipData)),strconv.Itoa(len(gzipData)), mime.TypeByExtension(ext), f, f.ModTime().UTC().Format(http.TimeFormat)})
|
||||||
|
|
||||||
DebugLog("Added the '/" + theme.Name + path + "' static file for theme " + theme.Name + ".")
|
DebugLog("Added the '/" + theme.Name + path + "' static file for theme " + theme.Name + ".")
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -472,7 +472,7 @@ func buildNoavatar(uid int, width int) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !Config.DisableDefaultNoavatar && uid < 5 {
|
if !Config.DisableDefaultNoavatar && uid < 5 {
|
||||||
return "/static/n"+strconv.Itoa(uid)+"-"+strconv.Itoa(width)+".png?i=0"
|
return "/s/n"+strconv.Itoa(uid)+"-"+strconv.Itoa(width)+".png?i=0"
|
||||||
}
|
}
|
||||||
return strings.Replace(strings.Replace(Config.Noavatar, "{id}", strconv.Itoa(uid), 1), "{width}", strconv.Itoa(width), 1)
|
return strings.Replace(strings.Replace(Config.Noavatar, "{id}", strconv.Itoa(uid), 1), "{width}", strconv.Itoa(width), 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,10 @@ DisableNoavatarRange - This switch lets you disable the noavatar algorithm which
|
||||||
|
|
||||||
DisableDefaultNoavatar - This switch lets you disable the default noavatar algorithm which may intercept noavatars for increased efficiency. Default: false
|
DisableDefaultNoavatar - This switch lets you disable the default noavatar algorithm which may intercept noavatars for increased efficiency. Default: false
|
||||||
|
|
||||||
|
RefNoTrack - This switch disables tracking the referrers of users who click from another site to your site and the referrers of any requests to resources from other sites as-well.
|
||||||
|
|
||||||
|
RefNoRef - This switch makes it so that if a user clicks on a link, then the incoming site won't know which site they're coming from.
|
||||||
|
|
||||||
NoAvatar - The default avatar to use for users when they don't have their own. The default for this may change in the near future to better utilise HTTP/2. Example: https://api.adorable.io/avatars/{width}/{id}.png
|
NoAvatar - The default avatar to use for users when they don't have their own. The default for this may change in the near future to better utilise HTTP/2. Example: https://api.adorable.io/avatars/{width}/{id}.png
|
||||||
|
|
||||||
ItemsPerPage - The number of posts, topics, etc. you want on each page.
|
ItemsPerPage - The number of posts, topics, etc. you want on each page.
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 3px;padding-left: 4px;clear: both;border-bottom: solid 1px #ccc;padding-right: 3px;padding-bottom: 6px;">
|
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 3px;padding-left: 4px;clear: both;border-bottom: solid 1px #ccc;padding-right: 3px;padding-bottom: 6px;">
|
||||||
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;">
|
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;">
|
||||||
<div class="avatar_item" style="background-image: url(/uploads/avatar_1.jpg), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
<div class="avatar_item" style="background-image: url(/uploads/avatar_1.jpg), url(/s/white-dot.jpg);background-position:0px -10px;background-repeat:no-repeat, repeat-y;background-size:128px;width:128px;height:100%;min-height: 128px;border-style:solid;border-color:#eaeaea;border-width:1px;"> </div>
|
||||||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">Azareal</div>
|
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">Azareal</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content_container" style="background: white;margin-left: 137px;min-height: 128px;margin-bottom: 0;margin-right: 3px;">
|
<div class="content_container" style="background:white;margin-left:137px;min-height:128px;margin-bottom:0;margin-right:3px;">
|
||||||
<div class="editable_block user_content" style="padding: 5px;margin-top: 3px;margin-bottom: 0;background: white;min-height: 133px;padding-bottom: 0;width: 100%;">boo</div>
|
<div class="editable_block user_content" style="padding: 5px;margin-top: 3px;margin-bottom: 0;background: white;min-height: 133px;padding-bottom: 0;width: 100%;">boo</div>
|
||||||
<div class="button_container" style="border-top: solid 1px #eaeaea;border-spacing: 0px;border-collapse: collapse;padding: 0;margin: 0;display: block;">
|
<div class="button_container" style="border-top: solid 1px #eaeaea;border-spacing: 0px;border-collapse: collapse;padding: 0;margin: 0;display: block;">
|
||||||
<a style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 5px;padding-right: 5px;">Edit</a>
|
<a style="border-right: solid 1px #eaeaea;color: #505050;font-size: 13px;padding-left: 5px;padding-right: 5px;">Edit</a>
|
||||||
|
|
434
gen_router.go
434
gen_router.go
|
@ -125,6 +125,14 @@ var RouteMap = map[string]interface{}{
|
||||||
"routes.AccountEditEmailTokenSubmit": routes.AccountEditEmailTokenSubmit,
|
"routes.AccountEditEmailTokenSubmit": routes.AccountEditEmailTokenSubmit,
|
||||||
"routes.AccountLogins": routes.AccountLogins,
|
"routes.AccountLogins": routes.AccountLogins,
|
||||||
"routes.LevelList": routes.LevelList,
|
"routes.LevelList": routes.LevelList,
|
||||||
|
"routes.Convos": routes.Convos,
|
||||||
|
"routes.ConvosCreate": routes.ConvosCreate,
|
||||||
|
"routes.Convo": routes.Convo,
|
||||||
|
"routes.ConvosCreateSubmit": routes.ConvosCreateSubmit,
|
||||||
|
"routes.ConvosDeleteSubmit": routes.ConvosDeleteSubmit,
|
||||||
|
"routes.ConvosCreateReplySubmit": routes.ConvosCreateReplySubmit,
|
||||||
|
"routes.ConvosDeleteReplySubmit": routes.ConvosDeleteReplySubmit,
|
||||||
|
"routes.ConvosEditReplySubmit": routes.ConvosEditReplySubmit,
|
||||||
"routes.ViewProfile": routes.ViewProfile,
|
"routes.ViewProfile": routes.ViewProfile,
|
||||||
"routes.BanUserSubmit": routes.BanUserSubmit,
|
"routes.BanUserSubmit": routes.BanUserSubmit,
|
||||||
"routes.UnbanUser": routes.UnbanUser,
|
"routes.UnbanUser": routes.UnbanUser,
|
||||||
|
@ -278,53 +286,61 @@ var routeMapEnum = map[string]int{
|
||||||
"routes.AccountEditEmailTokenSubmit": 99,
|
"routes.AccountEditEmailTokenSubmit": 99,
|
||||||
"routes.AccountLogins": 100,
|
"routes.AccountLogins": 100,
|
||||||
"routes.LevelList": 101,
|
"routes.LevelList": 101,
|
||||||
"routes.ViewProfile": 102,
|
"routes.Convos": 102,
|
||||||
"routes.BanUserSubmit": 103,
|
"routes.ConvosCreate": 103,
|
||||||
"routes.UnbanUser": 104,
|
"routes.Convo": 104,
|
||||||
"routes.ActivateUser": 105,
|
"routes.ConvosCreateSubmit": 105,
|
||||||
"routes.IPSearch": 106,
|
"routes.ConvosDeleteSubmit": 106,
|
||||||
"routes.CreateTopicSubmit": 107,
|
"routes.ConvosCreateReplySubmit": 107,
|
||||||
"routes.EditTopicSubmit": 108,
|
"routes.ConvosDeleteReplySubmit": 108,
|
||||||
"routes.DeleteTopicSubmit": 109,
|
"routes.ConvosEditReplySubmit": 109,
|
||||||
"routes.StickTopicSubmit": 110,
|
"routes.ViewProfile": 110,
|
||||||
"routes.UnstickTopicSubmit": 111,
|
"routes.BanUserSubmit": 111,
|
||||||
"routes.LockTopicSubmit": 112,
|
"routes.UnbanUser": 112,
|
||||||
"routes.UnlockTopicSubmit": 113,
|
"routes.ActivateUser": 113,
|
||||||
"routes.MoveTopicSubmit": 114,
|
"routes.IPSearch": 114,
|
||||||
"routes.LikeTopicSubmit": 115,
|
"routes.CreateTopicSubmit": 115,
|
||||||
"routes.AddAttachToTopicSubmit": 116,
|
"routes.EditTopicSubmit": 116,
|
||||||
"routes.RemoveAttachFromTopicSubmit": 117,
|
"routes.DeleteTopicSubmit": 117,
|
||||||
"routes.ViewTopic": 118,
|
"routes.StickTopicSubmit": 118,
|
||||||
"routes.CreateReplySubmit": 119,
|
"routes.UnstickTopicSubmit": 119,
|
||||||
"routes.ReplyEditSubmit": 120,
|
"routes.LockTopicSubmit": 120,
|
||||||
"routes.ReplyDeleteSubmit": 121,
|
"routes.UnlockTopicSubmit": 121,
|
||||||
"routes.ReplyLikeSubmit": 122,
|
"routes.MoveTopicSubmit": 122,
|
||||||
"routes.AddAttachToReplySubmit": 123,
|
"routes.LikeTopicSubmit": 123,
|
||||||
"routes.RemoveAttachFromReplySubmit": 124,
|
"routes.AddAttachToTopicSubmit": 124,
|
||||||
"routes.ProfileReplyCreateSubmit": 125,
|
"routes.RemoveAttachFromTopicSubmit": 125,
|
||||||
"routes.ProfileReplyEditSubmit": 126,
|
"routes.ViewTopic": 126,
|
||||||
"routes.ProfileReplyDeleteSubmit": 127,
|
"routes.CreateReplySubmit": 127,
|
||||||
"routes.PollVote": 128,
|
"routes.ReplyEditSubmit": 128,
|
||||||
"routes.PollResults": 129,
|
"routes.ReplyDeleteSubmit": 129,
|
||||||
"routes.AccountLogin": 130,
|
"routes.ReplyLikeSubmit": 130,
|
||||||
"routes.AccountRegister": 131,
|
"routes.AddAttachToReplySubmit": 131,
|
||||||
"routes.AccountLogout": 132,
|
"routes.RemoveAttachFromReplySubmit": 132,
|
||||||
"routes.AccountLoginSubmit": 133,
|
"routes.ProfileReplyCreateSubmit": 133,
|
||||||
"routes.AccountLoginMFAVerify": 134,
|
"routes.ProfileReplyEditSubmit": 134,
|
||||||
"routes.AccountLoginMFAVerifySubmit": 135,
|
"routes.ProfileReplyDeleteSubmit": 135,
|
||||||
"routes.AccountRegisterSubmit": 136,
|
"routes.PollVote": 136,
|
||||||
"routes.AccountPasswordReset": 137,
|
"routes.PollResults": 137,
|
||||||
"routes.AccountPasswordResetSubmit": 138,
|
"routes.AccountLogin": 138,
|
||||||
"routes.AccountPasswordResetToken": 139,
|
"routes.AccountRegister": 139,
|
||||||
"routes.AccountPasswordResetTokenSubmit": 140,
|
"routes.AccountLogout": 140,
|
||||||
"routes.DynamicRoute": 141,
|
"routes.AccountLoginSubmit": 141,
|
||||||
"routes.UploadedFile": 142,
|
"routes.AccountLoginMFAVerify": 142,
|
||||||
"routes.StaticFile": 143,
|
"routes.AccountLoginMFAVerifySubmit": 143,
|
||||||
"routes.RobotsTxt": 144,
|
"routes.AccountRegisterSubmit": 144,
|
||||||
"routes.SitemapXml": 145,
|
"routes.AccountPasswordReset": 145,
|
||||||
"routes.OpenSearchXml": 146,
|
"routes.AccountPasswordResetSubmit": 146,
|
||||||
"routes.BadRoute": 147,
|
"routes.AccountPasswordResetToken": 147,
|
||||||
"routes.HTTPSRedirect": 148,
|
"routes.AccountPasswordResetTokenSubmit": 148,
|
||||||
|
"routes.DynamicRoute": 149,
|
||||||
|
"routes.UploadedFile": 150,
|
||||||
|
"routes.StaticFile": 151,
|
||||||
|
"routes.RobotsTxt": 152,
|
||||||
|
"routes.SitemapXml": 153,
|
||||||
|
"routes.OpenSearchXml": 154,
|
||||||
|
"routes.BadRoute": 155,
|
||||||
|
"routes.HTTPSRedirect": 156,
|
||||||
}
|
}
|
||||||
var reverseRouteMapEnum = map[int]string{
|
var reverseRouteMapEnum = map[int]string{
|
||||||
0: "routes.Overview",
|
0: "routes.Overview",
|
||||||
|
@ -429,53 +445,61 @@ var reverseRouteMapEnum = map[int]string{
|
||||||
99: "routes.AccountEditEmailTokenSubmit",
|
99: "routes.AccountEditEmailTokenSubmit",
|
||||||
100: "routes.AccountLogins",
|
100: "routes.AccountLogins",
|
||||||
101: "routes.LevelList",
|
101: "routes.LevelList",
|
||||||
102: "routes.ViewProfile",
|
102: "routes.Convos",
|
||||||
103: "routes.BanUserSubmit",
|
103: "routes.ConvosCreate",
|
||||||
104: "routes.UnbanUser",
|
104: "routes.Convo",
|
||||||
105: "routes.ActivateUser",
|
105: "routes.ConvosCreateSubmit",
|
||||||
106: "routes.IPSearch",
|
106: "routes.ConvosDeleteSubmit",
|
||||||
107: "routes.CreateTopicSubmit",
|
107: "routes.ConvosCreateReplySubmit",
|
||||||
108: "routes.EditTopicSubmit",
|
108: "routes.ConvosDeleteReplySubmit",
|
||||||
109: "routes.DeleteTopicSubmit",
|
109: "routes.ConvosEditReplySubmit",
|
||||||
110: "routes.StickTopicSubmit",
|
110: "routes.ViewProfile",
|
||||||
111: "routes.UnstickTopicSubmit",
|
111: "routes.BanUserSubmit",
|
||||||
112: "routes.LockTopicSubmit",
|
112: "routes.UnbanUser",
|
||||||
113: "routes.UnlockTopicSubmit",
|
113: "routes.ActivateUser",
|
||||||
114: "routes.MoveTopicSubmit",
|
114: "routes.IPSearch",
|
||||||
115: "routes.LikeTopicSubmit",
|
115: "routes.CreateTopicSubmit",
|
||||||
116: "routes.AddAttachToTopicSubmit",
|
116: "routes.EditTopicSubmit",
|
||||||
117: "routes.RemoveAttachFromTopicSubmit",
|
117: "routes.DeleteTopicSubmit",
|
||||||
118: "routes.ViewTopic",
|
118: "routes.StickTopicSubmit",
|
||||||
119: "routes.CreateReplySubmit",
|
119: "routes.UnstickTopicSubmit",
|
||||||
120: "routes.ReplyEditSubmit",
|
120: "routes.LockTopicSubmit",
|
||||||
121: "routes.ReplyDeleteSubmit",
|
121: "routes.UnlockTopicSubmit",
|
||||||
122: "routes.ReplyLikeSubmit",
|
122: "routes.MoveTopicSubmit",
|
||||||
123: "routes.AddAttachToReplySubmit",
|
123: "routes.LikeTopicSubmit",
|
||||||
124: "routes.RemoveAttachFromReplySubmit",
|
124: "routes.AddAttachToTopicSubmit",
|
||||||
125: "routes.ProfileReplyCreateSubmit",
|
125: "routes.RemoveAttachFromTopicSubmit",
|
||||||
126: "routes.ProfileReplyEditSubmit",
|
126: "routes.ViewTopic",
|
||||||
127: "routes.ProfileReplyDeleteSubmit",
|
127: "routes.CreateReplySubmit",
|
||||||
128: "routes.PollVote",
|
128: "routes.ReplyEditSubmit",
|
||||||
129: "routes.PollResults",
|
129: "routes.ReplyDeleteSubmit",
|
||||||
130: "routes.AccountLogin",
|
130: "routes.ReplyLikeSubmit",
|
||||||
131: "routes.AccountRegister",
|
131: "routes.AddAttachToReplySubmit",
|
||||||
132: "routes.AccountLogout",
|
132: "routes.RemoveAttachFromReplySubmit",
|
||||||
133: "routes.AccountLoginSubmit",
|
133: "routes.ProfileReplyCreateSubmit",
|
||||||
134: "routes.AccountLoginMFAVerify",
|
134: "routes.ProfileReplyEditSubmit",
|
||||||
135: "routes.AccountLoginMFAVerifySubmit",
|
135: "routes.ProfileReplyDeleteSubmit",
|
||||||
136: "routes.AccountRegisterSubmit",
|
136: "routes.PollVote",
|
||||||
137: "routes.AccountPasswordReset",
|
137: "routes.PollResults",
|
||||||
138: "routes.AccountPasswordResetSubmit",
|
138: "routes.AccountLogin",
|
||||||
139: "routes.AccountPasswordResetToken",
|
139: "routes.AccountRegister",
|
||||||
140: "routes.AccountPasswordResetTokenSubmit",
|
140: "routes.AccountLogout",
|
||||||
141: "routes.DynamicRoute",
|
141: "routes.AccountLoginSubmit",
|
||||||
142: "routes.UploadedFile",
|
142: "routes.AccountLoginMFAVerify",
|
||||||
143: "routes.StaticFile",
|
143: "routes.AccountLoginMFAVerifySubmit",
|
||||||
144: "routes.RobotsTxt",
|
144: "routes.AccountRegisterSubmit",
|
||||||
145: "routes.SitemapXml",
|
145: "routes.AccountPasswordReset",
|
||||||
146: "routes.OpenSearchXml",
|
146: "routes.AccountPasswordResetSubmit",
|
||||||
147: "routes.BadRoute",
|
147: "routes.AccountPasswordResetToken",
|
||||||
148: "routes.HTTPSRedirect",
|
148: "routes.AccountPasswordResetTokenSubmit",
|
||||||
|
149: "routes.DynamicRoute",
|
||||||
|
150: "routes.UploadedFile",
|
||||||
|
151: "routes.StaticFile",
|
||||||
|
152: "routes.RobotsTxt",
|
||||||
|
153: "routes.SitemapXml",
|
||||||
|
154: "routes.OpenSearchXml",
|
||||||
|
155: "routes.BadRoute",
|
||||||
|
156: "routes.HTTPSRedirect",
|
||||||
}
|
}
|
||||||
var osMapEnum = map[string]int{
|
var osMapEnum = map[string]int{
|
||||||
"unknown": 0,
|
"unknown": 0,
|
||||||
|
@ -633,7 +657,7 @@ type HTTPSRedirect struct {}
|
||||||
|
|
||||||
func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
w.Header().Set("Connection", "close")
|
w.Header().Set("Connection", "close")
|
||||||
counters.RouteViewCounter.Bump(148)
|
counters.RouteViewCounter.Bump(156)
|
||||||
dest := "https://" + req.Host + req.URL.String()
|
dest := "https://" + req.Host + req.URL.String()
|
||||||
http.Redirect(w, req, dest, http.StatusTemporaryRedirect)
|
http.Redirect(w, req, dest, http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
@ -828,6 +852,11 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
h.Set("X-Frame-Options", "deny")
|
h.Set("X-Frame-Options", "deny")
|
||||||
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
|
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
|
||||||
h.Set("X-Content-Type-Options", "nosniff")
|
h.Set("X-Content-Type-Options", "nosniff")
|
||||||
|
if c.Config.RefNoRef || !c.Site.EnableSsl {
|
||||||
|
h.Set("Referrer-Policy","no-referrer")
|
||||||
|
} else {
|
||||||
|
h.Set("Referrer-Policy","strict-origin")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Dev.SuperDebug {
|
if c.Dev.SuperDebug {
|
||||||
|
@ -836,8 +865,8 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
// Increment the request counter
|
// Increment the request counter
|
||||||
counters.GlobalViewCounter.Bump()
|
counters.GlobalViewCounter.Bump()
|
||||||
|
|
||||||
if prefix == "/static" {
|
if prefix == "/s" { //old prefix: /static
|
||||||
counters.RouteViewCounter.Bump(143)
|
counters.RouteViewCounter.Bump(151)
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
routes.StaticFile(w, req)
|
routes.StaticFile(w, req)
|
||||||
return
|
return
|
||||||
|
@ -988,14 +1017,16 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
counters.LangViewCounter.Bump("none")
|
counters.LangViewCounter.Bump("none")
|
||||||
}
|
}
|
||||||
|
|
||||||
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
if !c.Config.RefNoTrack {
|
||||||
if referrer != "" {
|
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||||
// ? Optimise this a little?
|
if referrer != "" {
|
||||||
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
// ? Optimise this a little?
|
||||||
referrer = strings.Split(referrer,"/")[0]
|
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||||
portless := strings.Split(referrer,":")[0]
|
referrer = strings.Split(referrer,"/")[0]
|
||||||
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
portless := strings.Split(referrer,":")[0]
|
||||||
counters.ReferrerTracker.Bump(referrer)
|
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
||||||
|
counters.ReferrerTracker.Bump(referrer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1813,9 +1844,110 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = routes.LevelList(w,req,user,head)
|
err = routes.LevelList(w,req,user,head)
|
||||||
|
case "/user/convos/":
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(102)
|
||||||
|
head, err := c.UserCheck(w,req,&user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = routes.Convos(w,req,user,head)
|
||||||
|
case "/user/convos/create/":
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(103)
|
||||||
|
head, err := c.UserCheck(w,req,&user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = routes.ConvosCreate(w,req,user,head)
|
||||||
|
case "/user/convo/":
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(104)
|
||||||
|
head, err := c.UserCheck(w,req,&user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = routes.Convo(w,req,user,head,extraData)
|
||||||
|
case "/user/convos/create/submit/":
|
||||||
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(105)
|
||||||
|
err = routes.ConvosCreateSubmit(w,req,user)
|
||||||
|
case "/user/convos/delete/submit/":
|
||||||
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(106)
|
||||||
|
err = routes.ConvosDeleteSubmit(w,req,user,extraData)
|
||||||
|
case "/user/convo/create/submit/":
|
||||||
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(107)
|
||||||
|
err = routes.ConvosCreateReplySubmit(w,req,user)
|
||||||
|
case "/user/convo/delete/submit/":
|
||||||
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(108)
|
||||||
|
err = routes.ConvosDeleteReplySubmit(w,req,user,extraData)
|
||||||
|
case "/user/convo/edit/submit/":
|
||||||
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.MemberOnly(w,req,user)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
counters.RouteViewCounter.Bump(109)
|
||||||
|
err = routes.ConvosEditReplySubmit(w,req,user,extraData)
|
||||||
default:
|
default:
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
counters.RouteViewCounter.Bump(102)
|
counters.RouteViewCounter.Bump(110)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1835,7 +1967,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(103)
|
counters.RouteViewCounter.Bump(111)
|
||||||
err = routes.BanUserSubmit(w,req,user,extraData)
|
err = routes.BanUserSubmit(w,req,user,extraData)
|
||||||
case "/users/unban/":
|
case "/users/unban/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1848,7 +1980,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(104)
|
counters.RouteViewCounter.Bump(112)
|
||||||
err = routes.UnbanUser(w,req,user,extraData)
|
err = routes.UnbanUser(w,req,user,extraData)
|
||||||
case "/users/activate/":
|
case "/users/activate/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1861,7 +1993,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(105)
|
counters.RouteViewCounter.Bump(113)
|
||||||
err = routes.ActivateUser(w,req,user,extraData)
|
err = routes.ActivateUser(w,req,user,extraData)
|
||||||
case "/users/ips/":
|
case "/users/ips/":
|
||||||
err = c.MemberOnly(w,req,user)
|
err = c.MemberOnly(w,req,user)
|
||||||
|
@ -1869,7 +2001,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(106)
|
counters.RouteViewCounter.Bump(114)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1893,7 +2025,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(107)
|
counters.RouteViewCounter.Bump(115)
|
||||||
err = routes.CreateTopicSubmit(w,req,user)
|
err = routes.CreateTopicSubmit(w,req,user)
|
||||||
case "/topic/edit/submit/":
|
case "/topic/edit/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1906,7 +2038,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(108)
|
counters.RouteViewCounter.Bump(116)
|
||||||
err = routes.EditTopicSubmit(w,req,user,extraData)
|
err = routes.EditTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/delete/submit/":
|
case "/topic/delete/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1920,7 +2052,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
}
|
}
|
||||||
|
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
counters.RouteViewCounter.Bump(109)
|
counters.RouteViewCounter.Bump(117)
|
||||||
err = routes.DeleteTopicSubmit(w,req,user)
|
err = routes.DeleteTopicSubmit(w,req,user)
|
||||||
case "/topic/stick/submit/":
|
case "/topic/stick/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1933,7 +2065,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(110)
|
counters.RouteViewCounter.Bump(118)
|
||||||
err = routes.StickTopicSubmit(w,req,user,extraData)
|
err = routes.StickTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/unstick/submit/":
|
case "/topic/unstick/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1946,7 +2078,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(111)
|
counters.RouteViewCounter.Bump(119)
|
||||||
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
err = routes.UnstickTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/lock/submit/":
|
case "/topic/lock/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1960,7 +2092,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
}
|
}
|
||||||
|
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
counters.RouteViewCounter.Bump(112)
|
counters.RouteViewCounter.Bump(120)
|
||||||
err = routes.LockTopicSubmit(w,req,user)
|
err = routes.LockTopicSubmit(w,req,user)
|
||||||
case "/topic/unlock/submit/":
|
case "/topic/unlock/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1973,7 +2105,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(113)
|
counters.RouteViewCounter.Bump(121)
|
||||||
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
err = routes.UnlockTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/move/submit/":
|
case "/topic/move/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1986,7 +2118,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(114)
|
counters.RouteViewCounter.Bump(122)
|
||||||
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
err = routes.MoveTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/like/submit/":
|
case "/topic/like/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -1999,7 +2131,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(115)
|
counters.RouteViewCounter.Bump(123)
|
||||||
err = routes.LikeTopicSubmit(w,req,user,extraData)
|
err = routes.LikeTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/attach/add/submit/":
|
case "/topic/attach/add/submit/":
|
||||||
err = c.MemberOnly(w,req,user)
|
err = c.MemberOnly(w,req,user)
|
||||||
|
@ -2016,7 +2148,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(116)
|
counters.RouteViewCounter.Bump(124)
|
||||||
err = routes.AddAttachToTopicSubmit(w,req,user,extraData)
|
err = routes.AddAttachToTopicSubmit(w,req,user,extraData)
|
||||||
case "/topic/attach/remove/submit/":
|
case "/topic/attach/remove/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2029,10 +2161,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(117)
|
counters.RouteViewCounter.Bump(125)
|
||||||
err = routes.RemoveAttachFromTopicSubmit(w,req,user,extraData)
|
err = routes.RemoveAttachFromTopicSubmit(w,req,user,extraData)
|
||||||
default:
|
default:
|
||||||
counters.RouteViewCounter.Bump(118)
|
counters.RouteViewCounter.Bump(126)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2056,7 +2188,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(119)
|
counters.RouteViewCounter.Bump(127)
|
||||||
err = routes.CreateReplySubmit(w,req,user)
|
err = routes.CreateReplySubmit(w,req,user)
|
||||||
case "/reply/edit/submit/":
|
case "/reply/edit/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2069,7 +2201,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(120)
|
counters.RouteViewCounter.Bump(128)
|
||||||
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
err = routes.ReplyEditSubmit(w,req,user,extraData)
|
||||||
case "/reply/delete/submit/":
|
case "/reply/delete/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2082,7 +2214,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(121)
|
counters.RouteViewCounter.Bump(129)
|
||||||
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
|
||||||
case "/reply/like/submit/":
|
case "/reply/like/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2095,7 +2227,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(122)
|
counters.RouteViewCounter.Bump(130)
|
||||||
err = routes.ReplyLikeSubmit(w,req,user,extraData)
|
err = routes.ReplyLikeSubmit(w,req,user,extraData)
|
||||||
case "/reply/attach/add/submit/":
|
case "/reply/attach/add/submit/":
|
||||||
err = c.MemberOnly(w,req,user)
|
err = c.MemberOnly(w,req,user)
|
||||||
|
@ -2112,7 +2244,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(123)
|
counters.RouteViewCounter.Bump(131)
|
||||||
err = routes.AddAttachToReplySubmit(w,req,user,extraData)
|
err = routes.AddAttachToReplySubmit(w,req,user,extraData)
|
||||||
case "/reply/attach/remove/submit/":
|
case "/reply/attach/remove/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2125,7 +2257,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(124)
|
counters.RouteViewCounter.Bump(132)
|
||||||
err = routes.RemoveAttachFromReplySubmit(w,req,user,extraData)
|
err = routes.RemoveAttachFromReplySubmit(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
case "/profile":
|
case "/profile":
|
||||||
|
@ -2141,7 +2273,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(125)
|
counters.RouteViewCounter.Bump(133)
|
||||||
err = routes.ProfileReplyCreateSubmit(w,req,user)
|
err = routes.ProfileReplyCreateSubmit(w,req,user)
|
||||||
case "/profile/reply/edit/submit/":
|
case "/profile/reply/edit/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2154,7 +2286,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(126)
|
counters.RouteViewCounter.Bump(134)
|
||||||
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
|
||||||
case "/profile/reply/delete/submit/":
|
case "/profile/reply/delete/submit/":
|
||||||
err = c.NoSessionMismatch(w,req,user)
|
err = c.NoSessionMismatch(w,req,user)
|
||||||
|
@ -2167,7 +2299,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(127)
|
counters.RouteViewCounter.Bump(135)
|
||||||
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
case "/poll":
|
case "/poll":
|
||||||
|
@ -2183,23 +2315,23 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(128)
|
counters.RouteViewCounter.Bump(136)
|
||||||
err = routes.PollVote(w,req,user,extraData)
|
err = routes.PollVote(w,req,user,extraData)
|
||||||
case "/poll/results/":
|
case "/poll/results/":
|
||||||
counters.RouteViewCounter.Bump(129)
|
counters.RouteViewCounter.Bump(137)
|
||||||
err = routes.PollResults(w,req,user,extraData)
|
err = routes.PollResults(w,req,user,extraData)
|
||||||
}
|
}
|
||||||
case "/accounts":
|
case "/accounts":
|
||||||
switch(req.URL.Path) {
|
switch(req.URL.Path) {
|
||||||
case "/accounts/login/":
|
case "/accounts/login/":
|
||||||
counters.RouteViewCounter.Bump(130)
|
counters.RouteViewCounter.Bump(138)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = routes.AccountLogin(w,req,user,head)
|
err = routes.AccountLogin(w,req,user,head)
|
||||||
case "/accounts/create/":
|
case "/accounts/create/":
|
||||||
counters.RouteViewCounter.Bump(131)
|
counters.RouteViewCounter.Bump(139)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2216,7 +2348,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(132)
|
counters.RouteViewCounter.Bump(140)
|
||||||
err = routes.AccountLogout(w,req,user)
|
err = routes.AccountLogout(w,req,user)
|
||||||
case "/accounts/login/submit/":
|
case "/accounts/login/submit/":
|
||||||
err = c.ParseForm(w,req,user)
|
err = c.ParseForm(w,req,user)
|
||||||
|
@ -2224,10 +2356,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(133)
|
counters.RouteViewCounter.Bump(141)
|
||||||
err = routes.AccountLoginSubmit(w,req,user)
|
err = routes.AccountLoginSubmit(w,req,user)
|
||||||
case "/accounts/mfa_verify/":
|
case "/accounts/mfa_verify/":
|
||||||
counters.RouteViewCounter.Bump(134)
|
counters.RouteViewCounter.Bump(142)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2239,7 +2371,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(135)
|
counters.RouteViewCounter.Bump(143)
|
||||||
err = routes.AccountLoginMFAVerifySubmit(w,req,user)
|
err = routes.AccountLoginMFAVerifySubmit(w,req,user)
|
||||||
case "/accounts/create/submit/":
|
case "/accounts/create/submit/":
|
||||||
err = c.ParseForm(w,req,user)
|
err = c.ParseForm(w,req,user)
|
||||||
|
@ -2247,10 +2379,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(136)
|
counters.RouteViewCounter.Bump(144)
|
||||||
err = routes.AccountRegisterSubmit(w,req,user)
|
err = routes.AccountRegisterSubmit(w,req,user)
|
||||||
case "/accounts/password-reset/":
|
case "/accounts/password-reset/":
|
||||||
counters.RouteViewCounter.Bump(137)
|
counters.RouteViewCounter.Bump(145)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2262,10 +2394,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(138)
|
counters.RouteViewCounter.Bump(146)
|
||||||
err = routes.AccountPasswordResetSubmit(w,req,user)
|
err = routes.AccountPasswordResetSubmit(w,req,user)
|
||||||
case "/accounts/password-reset/token/":
|
case "/accounts/password-reset/token/":
|
||||||
counters.RouteViewCounter.Bump(139)
|
counters.RouteViewCounter.Bump(147)
|
||||||
head, err := c.UserCheck(w,req,&user)
|
head, err := c.UserCheck(w,req,&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2277,7 +2409,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.RouteViewCounter.Bump(140)
|
counters.RouteViewCounter.Bump(148)
|
||||||
err = routes.AccountPasswordResetTokenSubmit(w,req,user)
|
err = routes.AccountPasswordResetTokenSubmit(w,req,user)
|
||||||
}
|
}
|
||||||
/*case "/sitemaps": // TODO: Count these views
|
/*case "/sitemaps": // TODO: Count these views
|
||||||
|
@ -2294,7 +2426,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
h.Del("Content-Type")
|
h.Del("Content-Type")
|
||||||
h.Del("Content-Encoding")
|
h.Del("Content-Encoding")
|
||||||
}
|
}
|
||||||
counters.RouteViewCounter.Bump(142)
|
counters.RouteViewCounter.Bump(150)
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
// TODO: Find a way to propagate errors up from this?
|
// TODO: Find a way to propagate errors up from this?
|
||||||
r.UploadHandler(w,req) // TODO: Count these views
|
r.UploadHandler(w,req) // TODO: Count these views
|
||||||
|
@ -2304,7 +2436,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
// TODO: Add support for favicons and robots.txt files
|
// TODO: Add support for favicons and robots.txt files
|
||||||
switch(extraData) {
|
switch(extraData) {
|
||||||
case "robots.txt":
|
case "robots.txt":
|
||||||
counters.RouteViewCounter.Bump(144)
|
counters.RouteViewCounter.Bump(152)
|
||||||
return routes.RobotsTxt(w,req)
|
return routes.RobotsTxt(w,req)
|
||||||
case "favicon.ico":
|
case "favicon.ico":
|
||||||
gzw, ok := w.(c.GzipResponseWriter)
|
gzw, ok := w.(c.GzipResponseWriter)
|
||||||
|
@ -2314,14 +2446,14 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
h.Del("Content-Type")
|
h.Del("Content-Type")
|
||||||
h.Del("Content-Encoding")
|
h.Del("Content-Encoding")
|
||||||
}
|
}
|
||||||
req.URL.Path = "/static/favicon.ico"
|
req.URL.Path = "/s/favicon.ico"
|
||||||
routes.StaticFile(w,req)
|
routes.StaticFile(w,req)
|
||||||
return nil
|
return nil
|
||||||
case "opensearch.xml":
|
case "opensearch.xml":
|
||||||
counters.RouteViewCounter.Bump(146)
|
counters.RouteViewCounter.Bump(154)
|
||||||
return routes.OpenSearchXml(w,req)
|
return routes.OpenSearchXml(w,req)
|
||||||
/*case "sitemap.xml":
|
/*case "sitemap.xml":
|
||||||
counters.RouteViewCounter.Bump(145)
|
counters.RouteViewCounter.Bump(153)
|
||||||
return routes.SitemapXml(w,req)*/
|
return routes.SitemapXml(w,req)*/
|
||||||
}
|
}
|
||||||
return c.NotFound(w,req,nil)
|
return c.NotFound(w,req,nil)
|
||||||
|
@ -2332,7 +2464,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
r.RUnlock()
|
r.RUnlock()
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
counters.RouteViewCounter.Bump(141) // TODO: Be more specific about *which* dynamic route it is
|
counters.RouteViewCounter.Bump(149) // TODO: Be more specific about *which* dynamic route it is
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
return handle(w,req,user)
|
return handle(w,req,user)
|
||||||
}
|
}
|
||||||
|
@ -2343,7 +2475,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
} else {
|
} else {
|
||||||
r.DumpRequest(req,"Bad Route")
|
r.DumpRequest(req,"Bad Route")
|
||||||
}
|
}
|
||||||
counters.RouteViewCounter.Bump(147)
|
counters.RouteViewCounter.Bump(155)
|
||||||
return c.NotFound(w,req,nil)
|
return c.NotFound(w,req,nil)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -567,7 +567,7 @@ func BenchmarkRoutesSerial(b *testing.B) {
|
||||||
b.Log("Plugins have already been initialised, they can't be deinitialised so these tests will run with plugins on")
|
b.Log("Plugins have already been initialised, they can't be deinitialised so these tests will run with plugins on")
|
||||||
}
|
}
|
||||||
static_w := httptest.NewRecorder()
|
static_w := httptest.NewRecorder()
|
||||||
static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil))
|
static_req := httptest.NewRequest("get","/s/global.js",bytes.NewReader(nil))
|
||||||
static_handler := http.HandlerFunc(route_static)
|
static_handler := http.HandlerFunc(route_static)
|
||||||
|
|
||||||
topic_w := httptest.NewRecorder()
|
topic_w := httptest.NewRecorder()
|
||||||
|
@ -1134,7 +1134,7 @@ func TestStaticRoute(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static_w := httptest.NewRecorder()
|
static_w := httptest.NewRecorder()
|
||||||
static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil))
|
static_req := httptest.NewRequest("get","/s/global.js",bytes.NewReader(nil))
|
||||||
static_handler := http.HandlerFunc(route_static)
|
static_handler := http.HandlerFunc(route_static)
|
||||||
|
|
||||||
static_handler.ServeHTTP(static_w,static_req)
|
static_handler.ServeHTTP(static_w,static_req)
|
||||||
|
|
|
@ -318,6 +318,8 @@
|
||||||
"password_reset_email_sent":"An email was sent to you. Please follow the steps within.",
|
"password_reset_email_sent":"An email was sent to you. Please follow the steps within.",
|
||||||
"password_reset_token_token_verified":"Your password was successfully updated.",
|
"password_reset_token_token_verified":"Your password was successfully updated.",
|
||||||
|
|
||||||
|
"convo_dev":"Messages are currently under development. Some features may not work yet and your messages may be purged every now and then.",
|
||||||
|
|
||||||
"panel_forum_created":"The forum was successfully created.",
|
"panel_forum_created":"The forum was successfully created.",
|
||||||
"panel_forum_deleted":"The forum was successfully deleted.",
|
"panel_forum_deleted":"The forum was successfully deleted.",
|
||||||
"panel_forum_updated":"The forum was successfully updated.",
|
"panel_forum_updated":"The forum was successfully updated.",
|
||||||
|
|
4
main.go
4
main.go
|
@ -134,10 +134,10 @@ func storeInit() (err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
/*c.Convos, err = c.NewDefaultConversationStore(acc)
|
c.Convos, err = c.NewDefaultConversationStore(acc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}*/
|
}
|
||||||
|
|
||||||
err = phrases.InitPhrases(c.Site.Language)
|
err = phrases.InitPhrases(c.Site.Language)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type tblColumn = qgen.DBTableColumn
|
type tblColumn = qgen.DBTableColumn
|
||||||
|
type tC = tblColumn
|
||||||
type tblKey = qgen.DBTableKey
|
type tblKey = qgen.DBTableKey
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -35,6 +36,7 @@ func init() {
|
||||||
addPatch(20, patch20)
|
addPatch(20, patch20)
|
||||||
addPatch(21, patch21)
|
addPatch(21, patch21)
|
||||||
addPatch(22, patch22)
|
addPatch(22, patch22)
|
||||||
|
addPatch(23, patch23)
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch0(scanner *bufio.Scanner) (err error) {
|
func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
|
@ -48,8 +50,8 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.CreateTable("menus", "", "",
|
err = execStmt(qgen.Builder.CreateTable("menus", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"mid", "int", 0, false, true, ""},
|
tC{"mid", "int", 0, false, true, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"mid", "primary","",false},
|
tblKey{"mid", "primary","",false},
|
||||||
|
@ -60,23 +62,23 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.CreateTable("menu_items", "", "",
|
err = execStmt(qgen.Builder.CreateTable("menu_items", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"miid", "int", 0, false, true, ""},
|
tC{"miid", "int", 0, false, true, ""},
|
||||||
tblColumn{"mid", "int", 0, false, false, ""},
|
tC{"mid", "int", 0, false, false, ""},
|
||||||
tblColumn{"name", "varchar", 200, false, false, ""},
|
tC{"name", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"htmlID", "varchar", 200, false, false, "''"},
|
tC{"htmlID", "varchar", 200, false, false, "''"},
|
||||||
tblColumn{"cssClass", "varchar", 200, false, false, "''"},
|
tC{"cssClass", "varchar", 200, false, false, "''"},
|
||||||
tblColumn{"position", "varchar", 100, false, false, ""},
|
tC{"position", "varchar", 100, false, false, ""},
|
||||||
tblColumn{"path", "varchar", 200, false, false, "''"},
|
tC{"path", "varchar", 200, false, false, "''"},
|
||||||
tblColumn{"aria", "varchar", 200, false, false, "''"},
|
tC{"aria", "varchar", 200, false, false, "''"},
|
||||||
tblColumn{"tooltip", "varchar", 200, false, false, "''"},
|
tC{"tooltip", "varchar", 200, false, false, "''"},
|
||||||
tblColumn{"tmplName", "varchar", 200, false, false, "''"},
|
tC{"tmplName", "varchar", 200, false, false, "''"},
|
||||||
tblColumn{"order", "int", 0, false, false, "0"},
|
tC{"order", "int", 0, false, false, "0"},
|
||||||
|
|
||||||
tblColumn{"guestOnly", "boolean", 0, false, false, "0"},
|
tC{"guestOnly", "boolean", 0, false, false, "0"},
|
||||||
tblColumn{"memberOnly", "boolean", 0, false, false, "0"},
|
tC{"memberOnly", "boolean", 0, false, false, "0"},
|
||||||
tblColumn{"staffOnly", "boolean", 0, false, false, "0"},
|
tC{"staffOnly", "boolean", 0, false, false, "0"},
|
||||||
tblColumn{"adminOnly", "boolean", 0, false, false, "0"},
|
tC{"adminOnly", "boolean", 0, false, false, "0"},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"miid", "primary","",false},
|
tblKey{"miid", "primary","",false},
|
||||||
|
@ -176,14 +178,14 @@ func patch2(scanner *bufio.Scanner) error {
|
||||||
|
|
||||||
func patch3(scanner *bufio.Scanner) error {
|
func patch3(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.CreateTable("registration_logs", "", "",
|
return execStmt(qgen.Builder.CreateTable("registration_logs", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"rlid", "int", 0, false, true, ""},
|
tC{"rlid", "int", 0, false, true, ""},
|
||||||
tblColumn{"username", "varchar", 100, false, false, ""},
|
tC{"username", "varchar", 100, false, false, ""},
|
||||||
tblColumn{"email", "varchar", 100, false, false, ""},
|
tC{"email", "varchar", 100, false, false, ""},
|
||||||
tblColumn{"failureReason", "varchar", 100, false, false, ""},
|
tC{"failureReason", "varchar", 100, false, false, ""},
|
||||||
tblColumn{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
tC{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
||||||
tblColumn{"ipaddress", "varchar", 200, false, false, ""},
|
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"doneAt", "createdAt", 0, false, false, ""},
|
tC{"doneAt", "createdAt", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"rlid", "primary","",false},
|
tblKey{"rlid", "primary","",false},
|
||||||
|
@ -240,13 +242,13 @@ func patch4(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.CreateTable("pages", "utf8mb4", "utf8mb4_general_ci",
|
err = execStmt(qgen.Builder.CreateTable("pages", "utf8mb4", "utf8mb4_general_ci",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"pid", "int", 0, false, true, ""},
|
tC{"pid", "int", 0, false, true, ""},
|
||||||
tblColumn{"name", "varchar", 200, false, false, ""},
|
tC{"name", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"title", "varchar", 200, false, false, ""},
|
tC{"title", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"body", "text", 0, false, false, ""},
|
tC{"body", "text", 0, false, false, ""},
|
||||||
tblColumn{"allowedGroups", "text", 0, false, false, ""},
|
tC{"allowedGroups", "text", 0, false, false, ""},
|
||||||
tblColumn{"menuID", "int", 0, false, false, "-1"},
|
tC{"menuID", "int", 0, false, false, "-1"},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"pid", "primary","",false},
|
tblKey{"pid", "primary","",false},
|
||||||
|
@ -278,18 +280,18 @@ func patch5(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.CreateTable("users_2fa_keys", "utf8mb4", "utf8mb4_general_ci",
|
err = execStmt(qgen.Builder.CreateTable("users_2fa_keys", "utf8mb4", "utf8mb4_general_ci",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"uid", "int", 0, false, false, ""},
|
tC{"uid", "int", 0, false, false, ""},
|
||||||
tblColumn{"secret", "varchar", 100, false, false, ""},
|
tC{"secret", "varchar", 100, false, false, ""},
|
||||||
tblColumn{"scratch1", "varchar", 50, false, false, ""},
|
tC{"scratch1", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch2", "varchar", 50, false, false, ""},
|
tC{"scratch2", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch3", "varchar", 50, false, false, ""},
|
tC{"scratch3", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch4", "varchar", 50, false, false, ""},
|
tC{"scratch4", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch5", "varchar", 50, false, false, ""},
|
tC{"scratch5", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch6", "varchar", 50, false, false, ""},
|
tC{"scratch6", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch7", "varchar", 50, false, false, ""},
|
tC{"scratch7", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"scratch8", "varchar", 50, false, false, ""},
|
tC{"scratch8", "varchar", 50, false, false, ""},
|
||||||
tblColumn{"createdAt", "createdAt", 0, false, false, ""},
|
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"uid", "primary","",false},
|
tblKey{"uid", "primary","",false},
|
||||||
|
@ -308,8 +310,8 @@ func patch6(scanner *bufio.Scanner) error {
|
||||||
|
|
||||||
func patch7(scanner *bufio.Scanner) error {
|
func patch7(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.CreateTable("users_avatar_queue", "", "",
|
return execStmt(qgen.Builder.CreateTable("users_avatar_queue", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
tC{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"uid", "primary","",false},
|
tblKey{"uid", "primary","",false},
|
||||||
|
@ -371,8 +373,8 @@ func patch8(scanner *bufio.Scanner) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return execStmt(qgen.Builder.CreateTable("updates", "", "",
|
return execStmt(qgen.Builder.CreateTable("updates", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"dbVersion", "int", 0, false, false, "0"},
|
tC{"dbVersion", "int", 0, false, false, "0"},
|
||||||
},
|
},
|
||||||
[]tblKey{},
|
[]tblKey{},
|
||||||
))
|
))
|
||||||
|
@ -386,12 +388,12 @@ func patch9(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return execStmt(qgen.Builder.CreateTable("login_logs", "", "",
|
return execStmt(qgen.Builder.CreateTable("login_logs", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"lid", "int", 0, false, true, ""},
|
tC{"lid", "int", 0, false, true, ""},
|
||||||
tblColumn{"uid", "int", 0, false, false, ""},
|
tC{"uid", "int", 0, false, false, ""},
|
||||||
tblColumn{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
tC{"success", "bool", 0, false, false, "0"}, // Did this attempt succeed?
|
||||||
tblColumn{"ipaddress", "varchar", 200, false, false, ""},
|
tC{"ipaddress", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"doneAt", "createdAt", 0, false, false, ""},
|
tC{"doneAt", "createdAt", 0, false, false, ""},
|
||||||
},
|
},
|
||||||
[]tblKey{
|
[]tblKey{
|
||||||
tblKey{"lid", "primary","",false},
|
tblKey{"lid", "primary","",false},
|
||||||
|
@ -403,11 +405,11 @@ var acc = qgen.NewAcc
|
||||||
var itoa = strconv.Itoa
|
var itoa = strconv.Itoa
|
||||||
|
|
||||||
func patch10(scanner *bufio.Scanner) error {
|
func patch10(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddColumn("topics", tblColumn{"attachCount", "int", 0, false, false, "0"}, nil))
|
err := execStmt(qgen.Builder.AddColumn("topics", tC{"attachCount", "int", 0, false, false, "0"}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = execStmt(qgen.Builder.AddColumn("topics", tblColumn{"lastReplyID", "int", 0, false, false, "0"}, nil))
|
err = execStmt(qgen.Builder.AddColumn("topics", tC{"lastReplyID", "int", 0, false, false, "0"}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -443,7 +445,7 @@ func patch10(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch11(scanner *bufio.Scanner) error {
|
func patch11(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddColumn("replies", tblColumn{"attachCount", "int", 0, false, false, "0"}, nil))
|
err := execStmt(qgen.Builder.AddColumn("replies", tC{"attachCount", "int", 0, false, false, "0"}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -517,7 +519,7 @@ func patch12(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch13(scanner *bufio.Scanner) error {
|
func patch13(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddColumn("widgets", tblColumn{"wid", "int", 0, false, true, ""}, &tblKey{"wid", "primary","",false}))
|
err := execStmt(qgen.Builder.AddColumn("widgets", tC{"wid", "int", 0, false, true, ""}, &tblKey{"wid", "primary","",false}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -548,18 +550,18 @@ func patch15(scanner *bufio.Scanner) error {
|
||||||
|
|
||||||
func patch16(scanner *bufio.Scanner) error {
|
func patch16(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.CreateTable("password_resets", "", "",
|
return execStmt(qgen.Builder.CreateTable("password_resets", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"email", "varchar", 200, false, false, ""},
|
tC{"email", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
tC{"uid", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
tblColumn{"validated", "varchar", 200, false, false, ""}, // Token given once the one-use token is consumed, used to prevent multiple people consuming the same one-use token
|
tC{"validated", "varchar", 200, false, false, ""}, // Token given once the one-use token is consumed, used to prevent multiple people consuming the same one-use token
|
||||||
tblColumn{"token", "varchar", 200, false, false, ""},
|
tC{"token", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"createdAt", "createdAt", 0, false, false, ""},
|
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
}, nil,
|
}, nil,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch17(scanner *bufio.Scanner) error {
|
func patch17(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddColumn("attachments", tblColumn{"extra", "varchar", 200, false, false, ""}, nil))
|
err := execStmt(qgen.Builder.AddColumn("attachments", tC{"extra", "varchar", 200, false, false, ""}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -595,14 +597,14 @@ func patch17(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch18(scanner *bufio.Scanner) error {
|
func patch18(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.AddColumn("forums", tblColumn{"order", "int", 0, false, false, "0"}, nil))
|
return execStmt(qgen.Builder.AddColumn("forums", tC{"order", "int", 0, false, false, "0"}, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch19(scanner *bufio.Scanner) error {
|
func patch19(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.CreateTable("memchunks", "", "",
|
return execStmt(qgen.Builder.CreateTable("memchunks", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"count", "int", 0, false, false, "0"},
|
tC{"count", "int", 0, false, false, "0"},
|
||||||
tblColumn{"createdAt", "datetime", 0, false, false, ""},
|
tC{"createdAt", "datetime", 0, false, false, ""},
|
||||||
}, nil,
|
}, nil,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -631,29 +633,82 @@ func patch20(scanner *bufio.Scanner) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch21(scanner *bufio.Scanner) error {
|
func patch21(scanner *bufio.Scanner) error {
|
||||||
err := execStmt(qgen.Builder.AddColumn("memchunks", tblColumn{"stack", "int", 0, false, false, "0"}, nil))
|
err := execStmt(qgen.Builder.AddColumn("memchunks", tC{"stack", "int", 0, false, false, "0"}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.AddColumn("memchunks", tblColumn{"heap", "int", 0, false, false, "0"}, nil))
|
err = execStmt(qgen.Builder.AddColumn("memchunks", tC{"heap", "int", 0, false, false, "0"}, nil))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.CreateTable("meta", "", "",
|
err = execStmt(qgen.Builder.CreateTable("meta", "", "",
|
||||||
[]tblColumn{
|
[]tC{
|
||||||
tblColumn{"name", "varchar", 200, false, false, ""},
|
tC{"name", "varchar", 200, false, false, ""},
|
||||||
tblColumn{"value", "varchar", 200, false, false, ""},
|
tC{"value", "varchar", 200, false, false, ""},
|
||||||
}, nil,
|
}, nil,
|
||||||
))
|
))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return execStmt(qgen.Builder.AddColumn("activity_stream", tblColumn{"createdAt", "createdAt", 0, false, false, ""}, nil))
|
return execStmt(qgen.Builder.AddColumn("activity_stream", tC{"createdAt", "createdAt", 0, false, false, ""}, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch22(scanner *bufio.Scanner) error {
|
func patch22(scanner *bufio.Scanner) error {
|
||||||
return execStmt(qgen.Builder.AddColumn("forums", tblColumn{"tmpl", "varchar", 200, false, false, "''"}, nil))
|
return execStmt(qgen.Builder.AddColumn("forums", tC{"tmpl", "varchar", 200, false, false, "''"}, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func patch23(scanner *bufio.Scanner) error {
|
||||||
|
err := execStmt(qgen.Builder.DropTable("conversations"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = execStmt(qgen.Builder.CreateTable("conversations", "", "",
|
||||||
|
[]tC{
|
||||||
|
tC{"cid", "int", 0, false, true, ""},
|
||||||
|
tC{"createdBy", "int", 0, false, false, ""}, // TODO: Make this a foreign key
|
||||||
|
tC{"createdAt", "createdAt", 0, false, false, ""},
|
||||||
|
tC{"lastReplyAt", "datetime", 0, false, false, ""},
|
||||||
|
tC{"lastReplyBy", "int", 0, false, false, ""},
|
||||||
|
},
|
||||||
|
[]tblKey{
|
||||||
|
tblKey{"cid", "primary","",false},
|
||||||
|
},
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = execStmt(qgen.Builder.DropTable("conversations_posts"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = execStmt(qgen.Builder.CreateTable("conversations_posts", "", "",
|
||||||
|
[]tC{
|
||||||
|
tC{"pid", "int", 0, false, true, ""},
|
||||||
|
tC{"cid", "int", 0, false, false, ""},
|
||||||
|
tC{"createdBy", "int", 0, false, false, ""},
|
||||||
|
tC{"body", "varchar", 50, false, false, ""},
|
||||||
|
tC{"post", "varchar", 50, false, false, "''"},
|
||||||
|
},
|
||||||
|
[]tblKey{
|
||||||
|
tblKey{"pid", "primary","",false},
|
||||||
|
},
|
||||||
|
))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = execStmt(qgen.Builder.DropTable("conversations_participants"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return execStmt(qgen.Builder.CreateTable("conversations_participants", "", "",
|
||||||
|
[]tC{
|
||||||
|
tC{"uid", "int", 0, false, false, ""},
|
||||||
|
tC{"cid", "int", 0, false, false, ""},
|
||||||
|
}, nil,
|
||||||
|
))
|
||||||
}
|
}
|
|
@ -83,9 +83,9 @@ function asyncGetScript(source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function notifyOnScript(source) {
|
function notifyOnScript(source) {
|
||||||
source = "/static/"+source;
|
source = "/s/"+source;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let ss = source.replace("/static/","");
|
let ss = source.replace("/s/","");
|
||||||
try {
|
try {
|
||||||
let ssp = ss.charAt(0).toUpperCase() + ss.slice(1)
|
let ssp = ss.charAt(0).toUpperCase() + ss.slice(1)
|
||||||
console.log("ssp:",ssp)
|
console.log("ssp:",ssp)
|
||||||
|
@ -138,8 +138,8 @@ function loadScript(name, callback,fail) {
|
||||||
let parts = value.split("; current_theme=");
|
let parts = value.split("; current_theme=");
|
||||||
if (parts.length == 2) fname += "_"+ parts.pop().split(";").shift();
|
if (parts.length == 2) fname += "_"+ parts.pop().split(";").shift();
|
||||||
|
|
||||||
let url = "/static/"+fname+".js"
|
let url = "/s/"+fname+".js"
|
||||||
let iurl = "/static/"+name+".js"
|
let iurl = "/s/"+name+".js"
|
||||||
asyncGetScript(url)
|
asyncGetScript(url)
|
||||||
.then(callback)
|
.then(callback)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
@ -161,7 +161,7 @@ function loadScript(name, callback,fail) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
function loadTmpl(name,callback) {
|
function loadTmpl(name,callback) {
|
||||||
let url = "/static/"+name
|
let url = "/s/"+name
|
||||||
let worker = new Worker(url);
|
let worker = new Worker(url);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
$.emojiarea.path = '/static/smilies/emojiarea';
|
$.emojiarea.path = '/s/smilies/emojiarea';
|
||||||
$.emojiarea.icons = [{"name" : "<i class='icon-smile'></i>", "icons" : {':bowtie:' : 'bowtie.png',
|
$.emojiarea.icons = [{"name" : "<i class='icon-smile'></i>", "icons" : {':bowtie:' : 'bowtie.png',
|
||||||
':smile:' : 'smile.png',
|
':smile:' : 'smile.png',
|
||||||
':laughing:' : 'laughing.png',
|
':laughing:' : 'laughing.png',
|
||||||
|
|
|
@ -654,7 +654,7 @@ func (a *MysqlAdapter) complexSelect(preBuilder *selectPrebuilder, sb *strings.B
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
func (a *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
||||||
if table1 == "" {
|
if table1 == "" {
|
||||||
return "", errors.New("You need a name for the left table")
|
return "", errors.New("You need a name for the left table")
|
||||||
}
|
}
|
||||||
|
@ -668,7 +668,7 @@ func (adapter *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 s
|
||||||
return "", errors.New("No joiners found for SimpleLeftJoin")
|
return "", errors.New("No joiners found for SimpleLeftJoin")
|
||||||
}
|
}
|
||||||
|
|
||||||
whereStr, err := adapter.buildJoinWhere(where)
|
whereStr, err := a.buildJoinWhere(where)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -684,14 +684,14 @@ func (adapter *MysqlAdapter) SimpleLeftJoin(name string, table1 string, table2 s
|
||||||
as2 = " AS `"+ thalf2[1]+"`"
|
as2 = " AS `"+ thalf2[1]+"`"
|
||||||
}
|
}
|
||||||
|
|
||||||
var querystr = "SELECT" + adapter.buildJoinColumns(columns) + " FROM `" + thalf1[0] + "`"+as1+" LEFT JOIN `" + thalf2[0] + "`"+as2+" ON " + adapter.buildJoiners(joiners) + whereStr + adapter.buildOrderby(orderby) + adapter.buildLimit(limit)
|
q := "SELECT" + a.buildJoinColumns(columns) + " FROM `" + thalf1[0] + "`"+as1+" LEFT JOIN `" + thalf2[0] + "`"+as2+" ON " + a.buildJoiners(joiners) + whereStr + a.buildOrderby(orderby) + a.buildLimit(limit)
|
||||||
|
|
||||||
querystr = strings.TrimSpace(querystr)
|
q = strings.TrimSpace(q)
|
||||||
adapter.pushStatement(name, "select", querystr)
|
a.pushStatement(name, "select", q)
|
||||||
return querystr, nil
|
return q, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *MysqlAdapter) SimpleInnerJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
func (a *MysqlAdapter) SimpleInnerJoin(name string, table1 string, table2 string, columns string, joiners string, where string, orderby string, limit string) (string, error) {
|
||||||
if table1 == "" {
|
if table1 == "" {
|
||||||
return "", errors.New("You need a name for the left table")
|
return "", errors.New("You need a name for the left table")
|
||||||
}
|
}
|
||||||
|
@ -705,16 +705,27 @@ func (adapter *MysqlAdapter) SimpleInnerJoin(name string, table1 string, table2
|
||||||
return "", errors.New("No joiners found for SimpleInnerJoin")
|
return "", errors.New("No joiners found for SimpleInnerJoin")
|
||||||
}
|
}
|
||||||
|
|
||||||
whereStr, err := adapter.buildJoinWhere(where)
|
whereStr, err := a.buildJoinWhere(where)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var querystr = "SELECT " + adapter.buildJoinColumns(columns) + " FROM `" + table1 + "` INNER JOIN `" + table2 + "` ON " + adapter.buildJoiners(joiners) + whereStr + adapter.buildOrderby(orderby) + adapter.buildLimit(limit)
|
thalf1 := strings.Split(strings.Replace(table1," as ", " AS ",-1)," AS ")
|
||||||
|
var as1 string
|
||||||
|
if len(thalf1) == 2 {
|
||||||
|
as1 = " AS `"+ thalf1[1]+"`"
|
||||||
|
}
|
||||||
|
thalf2 := strings.Split(strings.Replace(table2," as ", " AS ",-1)," AS ")
|
||||||
|
var as2 string
|
||||||
|
if len(thalf2) == 2 {
|
||||||
|
as2 = " AS `"+ thalf2[1]+"`"
|
||||||
|
}
|
||||||
|
|
||||||
querystr = strings.TrimSpace(querystr)
|
q := "SELECT " + a.buildJoinColumns(columns) + " FROM `" + thalf1[0] + "`"+as1+" INNER JOIN `" + thalf2[0] + "`"+as2+" ON " + a.buildJoiners(joiners) + whereStr + a.buildOrderby(orderby) + a.buildLimit(limit)
|
||||||
adapter.pushStatement(name, "select", querystr)
|
|
||||||
return querystr, nil
|
q = strings.TrimSpace(q)
|
||||||
|
a.pushStatement(name, "select", q)
|
||||||
|
return q, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *MysqlAdapter) SimpleUpdateSelect(up *updatePrebuilder) (string, error) {
|
func (adapter *MysqlAdapter) SimpleUpdateSelect(up *updatePrebuilder) (string, error) {
|
||||||
|
@ -767,7 +778,7 @@ func (adapter *MysqlAdapter) SimpleInsertLeftJoin(name string, ins DBInsert, sel
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var q = "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` LEFT JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
q := "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` LEFT JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
||||||
|
|
||||||
q = strings.TrimSpace(q)
|
q = strings.TrimSpace(q)
|
||||||
adapter.pushStatement(name, "insert", q)
|
adapter.pushStatement(name, "insert", q)
|
||||||
|
@ -856,7 +867,7 @@ func (adapter *MysqlAdapter) SimpleInsertInnerJoin(name string, ins DBInsert, se
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var q = "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` INNER JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
q := "INSERT INTO `" + ins.Table + "`(" + adapter.buildColumns(ins.Columns) + ") SELECT" + adapter.buildJoinColumns(sel.Columns) + " FROM `" + sel.Table1 + "` INNER JOIN `" + sel.Table2 + "` ON " + adapter.buildJoiners(sel.Joiners) + whereStr + adapter.buildOrderby(sel.Orderby) + adapter.buildLimit(sel.Limit)
|
||||||
|
|
||||||
q = strings.TrimSpace(q)
|
q = strings.TrimSpace(q)
|
||||||
adapter.pushStatement(name, "insert", q)
|
adapter.pushStatement(name, "insert", q)
|
||||||
|
@ -882,13 +893,13 @@ func (adapter *MysqlAdapter) Builder() *prebuilder {
|
||||||
return &prebuilder{adapter}
|
return &prebuilder{adapter}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *MysqlAdapter) Write() error {
|
func (a *MysqlAdapter) Write() error {
|
||||||
var stmts, body string
|
var stmts, body string
|
||||||
for _, name := range adapter.BufferOrder {
|
for _, name := range a.BufferOrder {
|
||||||
if name[0] == '_' {
|
if name[0] == '_' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stmt := adapter.Buffer[name]
|
stmt := a.Buffer[name]
|
||||||
// ? - Table creation might be a little complex for Go to do outside a SQL file :(
|
// ? - Table creation might be a little complex for Go to do outside a SQL file :(
|
||||||
if stmt.Type == "upsert" {
|
if stmt.Type == "upsert" {
|
||||||
stmts += "\t" + name + " *qgen.MySQLUpsertCallback\n"
|
stmts += "\t" + name + " *qgen.MySQLUpsertCallback\n"
|
||||||
|
@ -945,12 +956,12 @@ func _gen_mysql() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal methods, not exposed in the interface
|
// Internal methods, not exposed in the interface
|
||||||
func (adapter *MysqlAdapter) pushStatement(name string, stype string, querystr string) {
|
func (a *MysqlAdapter) pushStatement(name string, stype string, querystr string) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
adapter.Buffer[name] = DBStmt{querystr, stype}
|
a.Buffer[name] = DBStmt{querystr, stype}
|
||||||
adapter.BufferOrder = append(adapter.BufferOrder, name)
|
a.BufferOrder = append(a.BufferOrder, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (adapter *MysqlAdapter) stringyType(ctype string) bool {
|
func (adapter *MysqlAdapter) stringyType(ctype string) bool {
|
||||||
|
|
|
@ -593,6 +593,11 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
h.Set("X-Frame-Options", "deny")
|
h.Set("X-Frame-Options", "deny")
|
||||||
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
|
h.Set("X-XSS-Protection", "1; mode=block") // TODO: Remove when we add a CSP? CSP's are horrendously glitchy things, tread with caution before removing
|
||||||
h.Set("X-Content-Type-Options", "nosniff")
|
h.Set("X-Content-Type-Options", "nosniff")
|
||||||
|
if c.Config.RefNoRef || !c.Site.EnableSsl {
|
||||||
|
h.Set("Referrer-Policy","no-referrer")
|
||||||
|
} else {
|
||||||
|
h.Set("Referrer-Policy","strict-origin")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Dev.SuperDebug {
|
if c.Dev.SuperDebug {
|
||||||
|
@ -601,7 +606,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
// Increment the request counter
|
// Increment the request counter
|
||||||
counters.GlobalViewCounter.Bump()
|
counters.GlobalViewCounter.Bump()
|
||||||
|
|
||||||
if prefix == "/static" {
|
if prefix == "/s" { //old prefix: /static
|
||||||
counters.RouteViewCounter.Bump({{ index .AllRouteMap "routes.StaticFile" }})
|
counters.RouteViewCounter.Bump({{ index .AllRouteMap "routes.StaticFile" }})
|
||||||
req.URL.Path += extraData
|
req.URL.Path += extraData
|
||||||
routes.StaticFile(w, req)
|
routes.StaticFile(w, req)
|
||||||
|
@ -753,14 +758,16 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
counters.LangViewCounter.Bump("none")
|
counters.LangViewCounter.Bump("none")
|
||||||
}
|
}
|
||||||
|
|
||||||
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
if !c.Config.RefNoTrack {
|
||||||
if referrer != "" {
|
referrer := req.Header.Get("Referer") // Check the 'referrer' header too? :P
|
||||||
// ? Optimise this a little?
|
if referrer != "" {
|
||||||
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
// ? Optimise this a little?
|
||||||
referrer = strings.Split(referrer,"/")[0]
|
referrer = strings.TrimPrefix(strings.TrimPrefix(referrer,"http://"),"https://")
|
||||||
portless := strings.Split(referrer,":")[0]
|
referrer = strings.Split(referrer,"/")[0]
|
||||||
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
portless := strings.Split(referrer,":")[0]
|
||||||
counters.ReferrerTracker.Bump(referrer)
|
if portless != "localhost" && portless != "127.0.0.1" && portless != c.Site.Host {
|
||||||
|
counters.ReferrerTracker.Bump(referrer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -840,7 +847,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
|
||||||
h.Del("Content-Type")
|
h.Del("Content-Type")
|
||||||
h.Del("Content-Encoding")
|
h.Del("Content-Encoding")
|
||||||
}
|
}
|
||||||
req.URL.Path = "/static/favicon.ico"
|
req.URL.Path = "/s/favicon.ico"
|
||||||
routes.StaticFile(w,req)
|
routes.StaticFile(w,req)
|
||||||
return nil
|
return nil
|
||||||
case "opensearch.xml":
|
case "opensearch.xml":
|
||||||
|
|
|
@ -49,7 +49,7 @@ func userRoutes() *RouteGroup {
|
||||||
return newRouteGroup("/user/").Routes(
|
return newRouteGroup("/user/").Routes(
|
||||||
View("routes.ViewProfile", "/user/").LitBefore("req.URL.Path += extraData"),
|
View("routes.ViewProfile", "/user/").LitBefore("req.URL.Path += extraData"),
|
||||||
|
|
||||||
Set("routes.AccountEdit","/user/edit",
|
Set("routes.AccountEdit", "/user/edit/",
|
||||||
MView("", "/"),
|
MView("", "/"),
|
||||||
MView("Password", "/password/"),
|
MView("Password", "/password/"),
|
||||||
Action("PasswordSubmit", "/password/submit/"), // TODO: Full test this
|
Action("PasswordSubmit", "/password/submit/"), // TODO: Full test this
|
||||||
|
@ -82,14 +82,15 @@ func userRoutes() *RouteGroup {
|
||||||
MView("routes.LevelList", "/user/levels/"),
|
MView("routes.LevelList", "/user/levels/"),
|
||||||
//MView("routes.LevelRankings", "/user/rankings/"),
|
//MView("routes.LevelRankings", "/user/rankings/"),
|
||||||
//MView("routes.Alerts", "/user/alerts/"),
|
//MView("routes.Alerts", "/user/alerts/"),
|
||||||
|
|
||||||
/*MView("routes.Convos", "/user/convos/"),
|
MView("routes.Convos", "/user/convos/"),
|
||||||
MView("routes.ConvosCreate", "/user/convos/create/"),
|
MView("routes.ConvosCreate", "/user/convos/create/"),
|
||||||
MView("routes.Convo", "/user/convo/","extraData"),
|
MView("routes.Convo", "/user/convo/", "extraData"),
|
||||||
Action("routes.ConvosCreateSubmit", "/user/convos/create/submit/"),
|
Action("routes.ConvosCreateSubmit", "/user/convos/create/submit/"),
|
||||||
Action("routes.ConvosDeleteSubmit", "/user/convos/delete/submit/","extraData"),
|
Action("routes.ConvosDeleteSubmit", "/user/convos/delete/submit/", "extraData"),
|
||||||
Action("routes.ConvosCreateReplySubmit", "/user/convo/create/submit/"),
|
Action("routes.ConvosCreateReplySubmit", "/user/convo/create/submit/"),
|
||||||
Action("routes.ConvosDeleteReplySubmit", "/user/convo/delete/submit/"),*/
|
Action("routes.ConvosDeleteReplySubmit", "/user/convo/delete/submit/","extraData"),
|
||||||
|
Action("routes.ConvosEditReplySubmit", "/user/convo/edit/submit/", "extraData"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +172,8 @@ func accountRoutes() *RouteGroup {
|
||||||
func panelRoutes() *RouteGroup {
|
func panelRoutes() *RouteGroup {
|
||||||
return newRouteGroup("/panel/").Before("SuperModOnly").NoHeader().Routes(
|
return newRouteGroup("/panel/").Before("SuperModOnly").NoHeader().Routes(
|
||||||
View("panel.Dashboard", "/panel/"),
|
View("panel.Dashboard", "/panel/"),
|
||||||
|
//View("panel.StatsDisk", "/panel/stats/disk/"),
|
||||||
|
|
||||||
View("panel.Forums", "/panel/forums/"),
|
View("panel.Forums", "/panel/forums/"),
|
||||||
Action("panel.ForumsCreateSubmit", "/panel/forums/create/"),
|
Action("panel.ForumsCreateSubmit", "/panel/forums/create/"),
|
||||||
Action("panel.ForumsDelete", "/panel/forums/delete/", "extraData"),
|
Action("panel.ForumsDelete", "/panel/forums/delete/", "extraData"),
|
||||||
|
|
|
@ -21,8 +21,8 @@ func ParseSEOURL(urlBit string) (slug string, id int, err error) {
|
||||||
return halves[0], tid, err
|
return halves[0], tid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var slen1 = len("</static/>; rel=preload; as=script,")
|
var slen1 = len("</s/>; rel=preload; as=script,")
|
||||||
var slen2 = len("</static/>; rel=preload; as=style,")
|
var slen2 = len("</s/>; rel=preload; as=style,")
|
||||||
|
|
||||||
func doPush(w http.ResponseWriter, header *c.Header) {
|
func doPush(w http.ResponseWriter, header *c.Header) {
|
||||||
//fmt.Println("in doPush")
|
//fmt.Println("in doPush")
|
||||||
|
@ -32,7 +32,7 @@ func doPush(w http.ResponseWriter, header *c.Header) {
|
||||||
var push = func(in []string) {
|
var push = func(in []string) {
|
||||||
sb.Grow((slen1 + 5) * len(in))
|
sb.Grow((slen1 + 5) * len(in))
|
||||||
for _, path := range in {
|
for _, path := range in {
|
||||||
sb.WriteString("</static/")
|
sb.WriteString("</s/")
|
||||||
sb.WriteString(path)
|
sb.WriteString(path)
|
||||||
sb.WriteString(">; rel=preload; as=script,")
|
sb.WriteString(">; rel=preload; as=script,")
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func doPush(w http.ResponseWriter, header *c.Header) {
|
||||||
if len(header.Stylesheets) > 0 {
|
if len(header.Stylesheets) > 0 {
|
||||||
sb.Grow((slen2 + 6) * len(header.Stylesheets))
|
sb.Grow((slen2 + 6) * len(header.Stylesheets))
|
||||||
for _, path := range header.Stylesheets {
|
for _, path := range header.Stylesheets {
|
||||||
sb.WriteString("</static/")
|
sb.WriteString("</s/")
|
||||||
sb.WriteString(path)
|
sb.WriteString(path)
|
||||||
sb.WriteString(">; rel=preload; as=style,")
|
sb.WriteString(">; rel=preload; as=style,")
|
||||||
}
|
}
|
||||||
|
@ -69,9 +69,9 @@ func doPush(w http.ResponseWriter, header *c.Header) {
|
||||||
|
|
||||||
var push = func(in []string) {
|
var push = func(in []string) {
|
||||||
for _, path := range in {
|
for _, path := range in {
|
||||||
//fmt.Println("pushing /static/" + path)
|
//fmt.Println("pushing /s/" + path)
|
||||||
// TODO: Avoid concatenating here
|
// TODO: Avoid concatenating here
|
||||||
err := pusher.Push("/static/"+path, nil)
|
err := pusher.Push("/s/"+path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ func renderTemplate3(tmplName string, hookName string, w http.ResponseWriter, r
|
||||||
h.Stylesheets = nil
|
h.Stylesheets = nil
|
||||||
c.PrepResources(&h.CurrentUser, h, h.Theme)
|
c.PrepResources(&h.CurrentUser, h, h.Theme)
|
||||||
for _, ss := range s {
|
for _, ss := range s {
|
||||||
h.Stylesheets = append(h.Stylesheets,ss)
|
h.Stylesheets = append(h.Stylesheets, ss)
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.CurrentUser.Loggedin {
|
if h.CurrentUser.Loggedin {
|
||||||
|
@ -141,4 +141,4 @@ func renderTemplate3(tmplName string, hookName string, w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rename renderTemplate to RenderTemplate instead of using this hack to avoid breaking things
|
// TODO: Rename renderTemplate to RenderTemplate instead of using this hack to avoid breaking things
|
||||||
var RenderTemplate = renderTemplate3
|
var RenderTemplate = renderTemplate3
|
||||||
|
|
|
@ -7,11 +7,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
c "github.com/Azareal/Gosora/common"
|
c "github.com/Azareal/Gosora/common"
|
||||||
"github.com/Azareal/Gosora/common/phrases"
|
p "github.com/Azareal/Gosora/common/phrases"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||||
accountEditHead("convos", w, r, &user, header)
|
accountEditHead("convos", w, r, &user, header)
|
||||||
|
header.AddNotice("convo_dev")
|
||||||
ccount := c.Convos.GetUserCount(user.ID)
|
ccount := c.Convos.GetUserCount(user.ID)
|
||||||
page, _ := strconv.Atoi(r.FormValue("page"))
|
page, _ := strconv.Atoi(r.FormValue("page"))
|
||||||
offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage)
|
offset, page, lastPage := c.PageOffset(ccount, page, c.Config.ItemsPerPage)
|
||||||
|
@ -30,9 +31,11 @@ func Convos(w http.ResponseWriter, r *http.Request, user c.User, header *c.Heade
|
||||||
|
|
||||||
func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header, scid string) c.RouteError {
|
func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header, scid string) c.RouteError {
|
||||||
accountEditHead("convo", w, r, &user, header)
|
accountEditHead("convo", w, r, &user, header)
|
||||||
|
header.AddSheet(header.Theme.Name + "/convo.css")
|
||||||
|
header.AddNotice("convo_dev")
|
||||||
cid, err := strconv.Atoi(scid)
|
cid, err := strconv.Atoi(scid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalError(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
convo, err := c.Convos.Get(cid)
|
convo, err := c.Convos.Get(cid)
|
||||||
|
@ -50,7 +53,7 @@ func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header
|
||||||
offset, page, lastPage := c.PageOffset(pcount, page, c.Config.ItemsPerPage)
|
offset, page, lastPage := c.PageOffset(pcount, page, c.Config.ItemsPerPage)
|
||||||
pageList := c.Paginate(page, lastPage, 5)
|
pageList := c.Paginate(page, lastPage, 5)
|
||||||
|
|
||||||
posts, err := convo.Posts(offset)
|
posts, err := convo.Posts(offset, c.Config.ItemsPerPage)
|
||||||
// TODO: Report a better error for no posts
|
// TODO: Report a better error for no posts
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.NotFound(w, r, header)
|
return c.NotFound(w, r, header)
|
||||||
|
@ -58,12 +61,23 @@ func Convo(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
pi := c.Account{header, "dashboard", "convo", c.ConvoViewPage{header, posts, c.Paginator{pageList, page, lastPage}}}
|
pitems := make([]c.ConvoViewRow, len(posts))
|
||||||
|
for i, post := range posts {
|
||||||
|
user, err := c.Users.Get(post.CreatedBy)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
pitems[i] = c.ConvoViewRow{post, user, "", "4"}
|
||||||
|
}
|
||||||
|
canModify := user.ID == convo.CreatedBy || user.IsSuperMod
|
||||||
|
|
||||||
|
pi := c.Account{header, "dashboard", "convo", c.ConvoViewPage{header, convo, pitems, canModify, c.Paginator{pageList, page, lastPage}}}
|
||||||
return renderTemplate("account", w, r, header, pi)
|
return renderTemplate("account", w, r, header, pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvosCreate(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
func ConvosCreate(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||||
accountEditHead("create_convo", w, r, &user, header)
|
accountEditHead("create_convo", w, r, &user, header)
|
||||||
|
header.AddNotice("convo_dev")
|
||||||
recpName := ""
|
recpName := ""
|
||||||
pi := c.Account{header, "dashboard", "create_convo", c.ConvoCreatePage{header, recpName}}
|
pi := c.Account{header, "dashboard", "create_convo", c.ConvoCreatePage{header, recpName}}
|
||||||
return renderTemplate("account", w, r, header, pi)
|
return renderTemplate("account", w, r, header, pi)
|
||||||
|
@ -103,13 +117,6 @@ func ConvosCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.R
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*type ConversationPost struct {
|
|
||||||
ID int
|
|
||||||
CID int
|
|
||||||
Body string
|
|
||||||
Post string // aes, ''
|
|
||||||
}*/
|
|
||||||
|
|
||||||
func ConvosDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.User, scid string) c.RouteError {
|
func ConvosDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.User, scid string) c.RouteError {
|
||||||
_, ferr := c.SimpleUserCheck(w, r, &user)
|
_, ferr := c.SimpleUserCheck(w, r, &user)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
|
@ -117,7 +124,7 @@ func ConvosDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.User, sci
|
||||||
}
|
}
|
||||||
cid, err := strconv.Atoi(scid)
|
cid, err := strconv.Atoi(scid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalError(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.Convos.Delete(cid)
|
err = c.Convos.Delete(cid)
|
||||||
|
@ -138,11 +145,61 @@ func ConvosCreateReplySubmit(w http.ResponseWriter, r *http.Request, user c.User
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvosDeleteReplySubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
|
func ConvosDeleteReplySubmit(w http.ResponseWriter, r *http.Request, user c.User, scpid string) c.RouteError {
|
||||||
|
_, ferr := c.SimpleUserCheck(w, r, &user)
|
||||||
|
if ferr != nil {
|
||||||
|
return ferr
|
||||||
|
}
|
||||||
|
cpid, err := strconv.Atoi(scpid)
|
||||||
|
if err != nil {
|
||||||
|
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
post := &c.ConversationPost{ID: cpid}
|
||||||
|
err = post.Fetch()
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return c.NotFound(w, r, nil)
|
||||||
|
} else if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
convo, err := c.Convos.Get(post.CID)
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return c.NotFound(w, r, nil)
|
||||||
|
} else if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
pcount := convo.PostsCount()
|
||||||
|
if pcount == 0 {
|
||||||
|
return c.NotFound(w, r, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
posts, err := convo.Posts(0, c.Config.ItemsPerPage)
|
||||||
|
// TODO: Report a better error for no posts
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return c.NotFound(w, r, nil)
|
||||||
|
} else if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
if post.ID == posts[0].ID {
|
||||||
|
err = c.Convos.Delete(convo.ID)
|
||||||
|
} else {
|
||||||
|
err = post.Delete()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/user/convo/"+strconv.Itoa(post.CID), http.StatusSeeOther)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConvosEditReplySubmit(w http.ResponseWriter, r *http.Request, user c.User, scpid string) c.RouteError {
|
||||||
_, ferr := c.SimpleUserCheck(w, r, &user)
|
_, ferr := c.SimpleUserCheck(w, r, &user)
|
||||||
if ferr != nil {
|
if ferr != nil {
|
||||||
return ferr
|
return ferr
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/user/convo/id", http.StatusSeeOther)
|
http.Redirect(w, r, "/user/convo/id", http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,8 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||||
|
|
||||||
// TODO: Localise these titles and bodies
|
// TODO: Localise these titles and bodies
|
||||||
var title, content string
|
var title, content string
|
||||||
if itemType == "reply" {
|
switch itemType {
|
||||||
|
case "reply":
|
||||||
reply, err := c.Rstore.Get(itemID)
|
reply, err := c.Rstore.Get(itemID)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.LocalError("We were unable to find the reported post", w, r, user)
|
return c.LocalError("We were unable to find the reported post", w, r, user)
|
||||||
|
@ -41,7 +42,7 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||||
|
|
||||||
title = "Reply: " + topic.Title
|
title = "Reply: " + topic.Title
|
||||||
content = reply.Content + "\n\nOriginal Post: #rid-" + strconv.Itoa(itemID)
|
content = reply.Content + "\n\nOriginal Post: #rid-" + strconv.Itoa(itemID)
|
||||||
} else if itemType == "user-reply" {
|
case "user-reply":
|
||||||
userReply, err := c.Prstore.Get(itemID)
|
userReply, err := c.Prstore.Get(itemID)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.LocalError("We weren't able to find the reported post", w, r, user)
|
return c.LocalError("We weren't able to find the reported post", w, r, user)
|
||||||
|
@ -57,7 +58,7 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||||
}
|
}
|
||||||
title = "Profile: " + profileOwner.Name
|
title = "Profile: " + profileOwner.Name
|
||||||
content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID)
|
content = userReply.Content + "\n\nOriginal Post: @" + strconv.Itoa(userReply.ParentID)
|
||||||
} else if itemType == "topic" {
|
case "topic":
|
||||||
topic, err := c.Topics.Get(itemID)
|
topic, err := c.Topics.Get(itemID)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.NotFound(w, r, nil)
|
return c.NotFound(w, r, nil)
|
||||||
|
@ -66,7 +67,27 @@ func ReportSubmit(w http.ResponseWriter, r *http.Request, user c.User, sitemID s
|
||||||
}
|
}
|
||||||
title = "Topic: " + topic.Title
|
title = "Topic: " + topic.Title
|
||||||
content = topic.Content + "\n\nOriginal Post: #tid-" + strconv.Itoa(itemID)
|
content = topic.Content + "\n\nOriginal Post: #tid-" + strconv.Itoa(itemID)
|
||||||
} else {
|
case "convo-reply":
|
||||||
|
post := &c.ConversationPost{ID: itemID}
|
||||||
|
err := post.Fetch()
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return c.NotFound(w, r, nil)
|
||||||
|
} else if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
post, err = c.ConvoPostProcess.OnLoad(post)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
user, err := c.Users.Get(post.CreatedBy)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalError(err, w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
title = "Convo Post: " + user.Name
|
||||||
|
content = post.Body + "\n\nOriginal Post: #cpid-" + strconv.Itoa(itemID)
|
||||||
|
default:
|
||||||
_, hasHook := headerLite.Hooks.VhookNeedHook("report_preassign", &itemID, &itemType)
|
_, hasHook := headerLite.Hooks.VhookNeedHook("report_preassign", &itemID, &itemType)
|
||||||
if hasHook {
|
if hasHook {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE [conversations] (
|
||||||
|
[cid] int not null IDENTITY,
|
||||||
|
[createdBy] int not null,
|
||||||
|
[createdAt] datetime not null,
|
||||||
|
[lastReplyAt] datetime not null,
|
||||||
|
[lastReplyBy] int not null,
|
||||||
|
primary key([cid])
|
||||||
|
);
|
|
@ -0,0 +1,4 @@
|
||||||
|
CREATE TABLE [conversations_participants] (
|
||||||
|
[uid] int not null,
|
||||||
|
[cid] int not null
|
||||||
|
);
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE [conversations_posts] (
|
||||||
|
[pid] int not null IDENTITY,
|
||||||
|
[cid] int not null,
|
||||||
|
[createdBy] int not null,
|
||||||
|
[body] nvarchar (50) not null,
|
||||||
|
[post] nvarchar (50) DEFAULT '' not null,
|
||||||
|
primary key([pid])
|
||||||
|
);
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE `conversations` (
|
||||||
|
`cid` int not null AUTO_INCREMENT,
|
||||||
|
`createdBy` int not null,
|
||||||
|
`createdAt` datetime not null,
|
||||||
|
`lastReplyAt` datetime not null,
|
||||||
|
`lastReplyBy` int not null,
|
||||||
|
primary key(`cid`)
|
||||||
|
);
|
|
@ -0,0 +1,4 @@
|
||||||
|
CREATE TABLE `conversations_participants` (
|
||||||
|
`uid` int not null,
|
||||||
|
`cid` int not null
|
||||||
|
);
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE `conversations_posts` (
|
||||||
|
`pid` int not null AUTO_INCREMENT,
|
||||||
|
`cid` int not null,
|
||||||
|
`createdBy` int not null,
|
||||||
|
`body` varchar(50) not null,
|
||||||
|
`post` varchar(50) DEFAULT '' not null,
|
||||||
|
primary key(`pid`)
|
||||||
|
);
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE "conversations" (
|
||||||
|
`cid` serial not null,
|
||||||
|
`createdBy` int not null,
|
||||||
|
`createdAt` timestamp not null,
|
||||||
|
`lastReplyAt` timestamp not null,
|
||||||
|
`lastReplyBy` int not null,
|
||||||
|
primary key(`cid`)
|
||||||
|
);
|
|
@ -0,0 +1,4 @@
|
||||||
|
CREATE TABLE "conversations_participants" (
|
||||||
|
`uid` int not null,
|
||||||
|
`cid` int not null
|
||||||
|
);
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE "conversations_posts" (
|
||||||
|
`pid` serial not null,
|
||||||
|
`cid` int not null,
|
||||||
|
`createdBy` int not null,
|
||||||
|
`body` varchar (50) not null,
|
||||||
|
`post` varchar (50) DEFAULT '' not null,
|
||||||
|
primary key(`pid`)
|
||||||
|
);
|
|
@ -9,6 +9,8 @@
|
||||||
<div class="rowitem passive"><a href="/user/edit/email/">{{lang "account_menu_email"}}</a></div>
|
<div class="rowitem passive"><a href="/user/edit/email/">{{lang "account_menu_email"}}</a></div>
|
||||||
<!--<div class="rowitem passive"><a href="/user/edit/notifications/">{{lang "account_menu_notifications"}}</a> <span class="account_soon">Coming Soon</span></div>-->
|
<!--<div class="rowitem passive"><a href="/user/edit/notifications/">{{lang "account_menu_notifications"}}</a> <span class="account_soon">Coming Soon</span></div>-->
|
||||||
<div class="rowitem passive"><a href="/user/edit/logins/">{{lang "account_menu_logins"}}</a></div>
|
<div class="rowitem passive"><a href="/user/edit/logins/">{{lang "account_menu_logins"}}</a></div>
|
||||||
|
<!--<div class="rowitem passive"><a href="/user/edit/penalties/">{{lang "account_menu_penalties"}}</a></div>-->
|
||||||
|
<div class="rowitem passive"><a href="/user/convos/">{{lang "account_menu_messages"}}</a></div>
|
||||||
{{/** TODO: Add an alerts page with pagination to go through alerts which either don't fit in the alerts drop-down or which have already been dismissed. Bear in mind though that dismissed alerts older than two weeks might be purged to save space and to speed up the database **/}}
|
{{/** TODO: Add an alerts page with pagination to go through alerts which either don't fit in the alerts drop-down or which have already been dismissed. Bear in mind though that dismissed alerts older than two weeks might be purged to save space and to speed up the database **/}}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -3,8 +3,4 @@
|
||||||
<h1>{{lang "convo_head"}}</h1>
|
<h1>{{lang "convo_head"}}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{range .Posts}}
|
<div class="colstack_item hash_hide">{{template "convo_row.html" . }}</div>
|
||||||
<div class="colstack_item">
|
|
||||||
<div class="rowitem">{{.Body}}</div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{{/** TODO: Temporary hack until we find a more granular way of doing this. Perhaps, a custom include function? **/}}
|
||||||
|
{{if .Header.Theme.BgAvatars}}
|
||||||
|
{{range .Posts}}
|
||||||
|
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="background-image:url({{.User.Avatar}}),url(/s/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;">
|
||||||
|
<span class="editable_block user_content simple">{{.Body}}</span>
|
||||||
|
<span class="controls">
|
||||||
|
<a href="{{.User.Link}}" class="real_username username">{{.User.Name}}</a>
|
||||||
|
|
||||||
|
{{if $.CanModify}}<a href="/user/convo/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||||
|
|
||||||
|
<a href="/user/convo/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
|
||||||
|
|
||||||
|
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=convo-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||||
|
|
||||||
|
{{if .User.Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.User.Tag}}</a>{{end}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{else}}
|
||||||
|
{{template "convo_row_alt.html" . }}
|
||||||
|
{{end}}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{{range .Posts}}
|
||||||
|
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent comment {{.ClassName}}">
|
||||||
|
<div class="topRow">
|
||||||
|
<div class="userbit">
|
||||||
|
<img src="{{.User.MicroAvatar}}" alt="Avatar" title="{{.User.Name}}'s Avatar" aria-hidden="true" />
|
||||||
|
<span class="nameAndTitle">
|
||||||
|
<a href="{{.User.Link}}" class="real_username username">{{.User.Name}}</a>
|
||||||
|
{{if .User.Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.User.Tag}}</a>{{end}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span class="controls">
|
||||||
|
{{if $.CanModify}}
|
||||||
|
<a href="/user/convo/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||||
|
|
||||||
|
<a href="/user/convo/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=convo-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="content_column">
|
||||||
|
<span class="editable_block user_content">{{.Body}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="after_comment"></div>
|
||||||
|
{{end}}
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="colstack_item colstack_head rowhead">
|
<div class="colstack_item colstack_head rowhead">
|
||||||
<div class="rowitem">
|
<div class="rowitem">
|
||||||
<h1>{{lang "convos_head"}}</h1>
|
<h1>{{lang "convos_head"}}</h1>
|
||||||
<h2>Create Convo</h2>
|
<h2><a href="/user/convos/create/">Create Convo</a></h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="colstack_item">
|
<div class="colstack_item">
|
||||||
|
|
|
@ -3,16 +3,16 @@
|
||||||
<head>
|
<head>
|
||||||
<title>{{.Title}} | {{.Header.Site.Name}}</title>
|
<title>{{.Title}} | {{.Header.Site.Name}}</title>
|
||||||
{{range .Header.Stylesheets}}
|
{{range .Header.Stylesheets}}
|
||||||
<link href="/static/{{.}}" rel="stylesheet" type="text/css">{{end}}
|
<link href="/s/{{.}}" rel="stylesheet" type="text/css">{{end}}
|
||||||
{{range .Header.PreScriptsAsync}}
|
{{range .Header.PreScriptsAsync}}
|
||||||
<script async type="text/javascript" src="/static/{{.}}"></script>{{end}}
|
<script async type="text/javascript" src="/s/{{.}}"></script>{{end}}
|
||||||
<meta property="x-loggedin" content="{{.CurrentUser.Loggedin}}" />
|
<meta property="x-loggedin" content="{{.CurrentUser.Loggedin}}" />
|
||||||
<script type="text/javascript" src="/static/init.js?i=8"></script>
|
<script type="text/javascript" src="/s/init.js?i=9"></script>
|
||||||
{{range .Header.ScriptsAsync}}
|
{{range .Header.ScriptsAsync}}
|
||||||
<script async type="text/javascript" src="/static/{{.}}"></script>{{end}}
|
<script async type="text/javascript" src="/s/{{.}}"></script>{{end}}
|
||||||
<script type="text/javascript" src="/static/jquery-3.1.1.min.js"></script>
|
<script type="text/javascript" src="/s/jquery-3.1.1.min.js"></script>
|
||||||
{{range .Header.Scripts}}
|
{{range .Header.Scripts}}
|
||||||
<script type="text/javascript" src="/static/{{.}}"></script>{{end}}
|
<script type="text/javascript" src="/s/{{.}}"></script>{{end}}
|
||||||
<meta name="viewport" content="width=device-width,initial-scale = 1.0, maximum-scale=1.0,user-scalable=no" />
|
<meta name="viewport" content="width=device-width,initial-scale = 1.0, maximum-scale=1.0,user-scalable=no" />
|
||||||
{{if .Header.MetaDesc}}<meta name="description" content="{{.Header.MetaDesc}}" />{{end}}
|
{{if .Header.MetaDesc}}<meta name="description" content="{{.Header.MetaDesc}}" />{{end}}
|
||||||
{{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}
|
{{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_primary_themes" class="colstack_item panel_themes complex_rowlist">
|
<div id="panel_primary_themes" class="colstack_item panel_themes complex_rowlist">
|
||||||
{{range .PrimaryThemes}}
|
{{range .PrimaryThemes}}
|
||||||
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image: url('/static/{{.FullImage}}');background-position: center;background-size: 50%;background-repeat: no-repeat;"{{end}}>
|
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image:url('/s/{{.FullImage}}');background-position:center;background-size:50%;background-repeat:no-repeat;"{{end}}>
|
||||||
<span style="float: left;">
|
<span style="float:left;">
|
||||||
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size: 17px;">{{.FriendlyName}}</a><br />
|
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size:17px;">{{.FriendlyName}}</a><br />
|
||||||
<small class="panel_theme_author" style="margin-left: 2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
<small class="panel_theme_author" style="margin-left:2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
||||||
</span>
|
</span>
|
||||||
<span class="panel_floater">
|
<span class="panel_floater">
|
||||||
{{if .MobileFriendly}}<span class="panel_tag panel_theme_mobile" title="{{lang "panel_themes_mobile_friendly_tooltip"}}" aria-label="{{lang "panel_themes_mobile_friendly_aria"}}">📱</span>{{end}}
|
{{if .MobileFriendly}}<span class="panel_tag panel_theme_mobile" title="{{lang "panel_themes_mobile_friendly_tooltip"}}" aria-label="{{lang "panel_themes_mobile_friendly_aria"}}">📱</span>{{end}}
|
||||||
|
@ -22,10 +22,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_variant_themes" class="colstack_item panel_themes">
|
<div id="panel_variant_themes" class="colstack_item panel_themes">
|
||||||
{{range .VariantThemes}}
|
{{range .VariantThemes}}
|
||||||
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image: url('/static/{{.FullImage}}');background-position: center;background-size: 50%;background-repeat: no-repeat;"{{end}}>
|
<div class="theme_row rowitem editable_parent"{{if .FullImage}} style="background-image:url('/s/{{.FullImage}}');background-position:center;background-size:50%;background-repeat:no-repeat;"{{end}}>
|
||||||
<span style="float: left;">
|
<span style="float: left;">
|
||||||
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size: 17px;">{{.FriendlyName}}</a><br />
|
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size:17px;">{{.FriendlyName}}</a><br />
|
||||||
<small class="panel_theme_author" style="margin-left: 2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
<small class="panel_theme_author" style="margin-left:2px;">{{lang "panel_themes_author_prefix"}}<a href="//{{.URL}}">{{.Creator}}</a></small>
|
||||||
</span>
|
</span>
|
||||||
<span class="panel_floater">
|
<span class="panel_floater">
|
||||||
{{if .MobileFriendly}}<span class="panel_tag panel_theme_mobile" title="{{lang "panel_themes_mobile_friendly_tooltip"}}" aria-label="{{lang "panel_themes_mobile_friendly_aria"}}">📱</span>{{end}}
|
{{if .MobileFriendly}}<span class="panel_tag panel_theme_mobile" title="{{lang "panel_themes_mobile_friendly_tooltip"}}" aria-label="{{lang "panel_themes_mobile_friendly_aria"}}">📱</span>{{end}}
|
||||||
|
|
|
@ -27,9 +27,9 @@
|
||||||
{{if not .CurrentUser.Loggedin}}<div class="rowitem passive">
|
{{if not .CurrentUser.Loggedin}}<div class="rowitem passive">
|
||||||
<a class="profile_menu_item">{{lang "profile_login_for_options"}}</a>
|
<a class="profile_menu_item">{{lang "profile_login_for_options"}}</a>
|
||||||
</div>{{else}}
|
</div>{{else}}
|
||||||
<!--<div class="rowitem passive">
|
<div class="rowitem passive">
|
||||||
<a href="/user/convos/create/" class="profile_menu_item">{{lang "profile_send_message"}}</a>
|
<a href="/user/convos/create/" class="profile_menu_item">{{lang "profile_send_message"}}</a>
|
||||||
</div>-->
|
</div>
|
||||||
<!--<div class="rowitem passive">
|
<!--<div class="rowitem passive">
|
||||||
<a class="profile_menu_item">{{lang "profile_add_friend"}}</a>
|
<a class="profile_menu_item">{{lang "profile_add_friend"}}</a>
|
||||||
</div>-->
|
</div>-->
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
{{/** TODO: Temporary hack until we find a more granular way of doing this. Perhaps, a custom include function? **/}}
|
{{/** TODO: Temporary hack until we find a more granular way of doing this. Perhaps, a custom include function? **/}}
|
||||||
{{if .Header.Theme.BgAvatars}}
|
{{if .Header.Theme.BgAvatars}}
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="background-image:url({{.Avatar}}),url(/static/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;">
|
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="background-image:url({{.Avatar}}),url(/s/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;">
|
||||||
<span class="editable_block user_content simple">{{.ContentHtml}}</span>
|
<span class="editable_block user_content simple">{{.ContentHtml}}</span>
|
||||||
<span class="controls">
|
<span class="controls">
|
||||||
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
||||||
|
|
||||||
{{if $.CurrentUser.IsMod}}<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
{{if $.CurrentUser.IsMod}}<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||||
|
|
||||||
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
|
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>{{end}}
|
||||||
|
|
||||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||||
|
|
||||||
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{template "profile_comments_row_alt.html" . }}
|
{{template "profile_comments_row_alt.html" . }}
|
||||||
{{end}}
|
{{end}}
|
|
@ -1,24 +1,24 @@
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent comment {{.ClassName}}">
|
<div id="post-{{.ID}}" class="rowitem passive deletable_block editable_parent comment {{.ClassName}}">
|
||||||
<div class="topRow">
|
<div class="topRow">
|
||||||
<div class="userbit">
|
<div class="userbit">
|
||||||
<img src="{{.MicroAvatar}}" alt="Avatar" title="{{.CreatedByName}}'s Avatar" aria-hidden="true" />
|
<img src="{{.MicroAvatar}}" alt="Avatar" title="{{.CreatedByName}}'s Avatar" aria-hidden="true" />
|
||||||
<span class="nameAndTitle">
|
<span class="nameAndTitle">
|
||||||
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
<a href="{{.UserLink}}" class="real_username username">{{.CreatedByName}}</a>
|
||||||
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
{{if .Tag}}<a class="username hide_on_mobile user_tag" style="float:right;">{{.Tag}}</a>{{end}}
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span class="controls">
|
|
||||||
{{if $.CurrentUser.IsMod}}
|
|
||||||
<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
|
||||||
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>
|
|
||||||
{{end}}
|
|
||||||
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="content_column">
|
<span class="controls">
|
||||||
<span class="editable_block user_content">{{.ContentHtml}}</span>
|
{{if $.CurrentUser.IsMod}}
|
||||||
</div>
|
<a href="/profile/reply/edit/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_edit_tooltip"}}" aria-label="{{lang "profile_comments_edit_aria"}}"><button class="username edit_item edit_label"></button></a>
|
||||||
|
<a href="/profile/reply/delete/submit/{{.ID}}?s={{$.CurrentUser.Session}}" class="mod_button" title="{{lang "profile_comments_delete_tooltip"}}" aria-label="{{lang "profile_comments_delete_aria"}}"><button class="username delete_item delete_label"></button></a>
|
||||||
|
{{end}}
|
||||||
|
<a class="mod_button" href="/report/submit/{{.ID}}?s={{$.CurrentUser.Session}}&type=user-reply"><button class="username report_item flag_label" title="{{lang "profile_comments_report_tooltip"}}" aria-label="{{lang "profile_comments_report_aria"}}"></button></a>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="after_comment"></div>
|
<div class="content_column">
|
||||||
|
<span class="editable_block user_content">{{.ContentHtml}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="after_comment"></div>
|
||||||
{{end}}
|
{{end}}
|
|
@ -31,7 +31,7 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
<article {{scope "opening_post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowblock post_container top_post" aria-label="{{lang "topic.opening_post_aria"}}">
|
<article {{scope "opening_post"}} itemscope itemtype="http://schema.org/CreativeWork" class="rowblock post_container top_post" aria-label="{{lang "topic.opening_post_aria"}}">
|
||||||
<div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="background-image: url({{.Topic.Avatar}}), url(/static/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
<div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="background-image:url({{.Topic.Avatar}}), url(/s/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position:0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||||
<div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div>
|
<div class="hide_on_edit topic_content user_content" itemprop="text">{{.Topic.ContentHTML}}</div>
|
||||||
{{if .CurrentUser.Loggedin}}<textarea name="topic_content" class="show_on_edit topic_content_input edit_source">{{.Topic.Content}}</textarea>{{end}}
|
{{if .CurrentUser.Loggedin}}<textarea name="topic_content" class="show_on_edit topic_content_input edit_source">{{.Topic.Content}}</textarea>{{end}}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="rowblock topic_reply_container">
|
<div class="rowblock topic_reply_container">
|
||||||
<div class="userinfo" aria-label="{{lang "topic.your_information"}}">
|
<div class="userinfo" aria-label="{{lang "topic.your_information"}}">
|
||||||
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/static/white-dot.jpg);background-position:0px -10px;"> </div>
|
<div class="avatar_item" style="background-image:url({{.CurrentUser.Avatar}}),url(/s/white-dot.jpg);background-position:0px -10px;"> </div>
|
||||||
<div class="user_meta">
|
<div class="user_meta">
|
||||||
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
|
<a href="{{.CurrentUser.Link}}" class="the_name" rel="author">{{.CurrentUser.Name}}</a>
|
||||||
{{if .CurrentUser.Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.CurrentUser.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .CurrentUser.Level}}</div><div class="tag_post"></div></div>{{end}}
|
{{if .CurrentUser.Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.CurrentUser.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .CurrentUser.Level}}</div><div class="tag_post"></div></div>{{end}}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="userinfo" aria-label="{{lang "topic.userinfo_aria"}}">
|
<div class="userinfo" aria-label="{{lang "topic.userinfo_aria"}}">
|
||||||
<div class="avatar_item" style="background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;"> </div>
|
<div class="avatar_item" style="background-image:url({{.Avatar}}), url(/s/white-dot.jpg);background-position:0px -10px;"> </div>
|
||||||
<div class="user_meta">
|
<div class="user_meta">
|
||||||
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
<a href="{{.UserLink}}" class="the_name" rel="author">{{.CreatedByName}}</a>
|
||||||
{{if .Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .Level}}</div><div class="tag_post"></div></div>{{end}}
|
{{if .Tag}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag">{{.Tag}}</div><div class="tag_post"></div></div>{{else}}<div class="tag_block"><div class="tag_pre"></div><div class="post_tag post_level">{{level .Level}}</div><div class="tag_post"></div></div>{{end}}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<article class="rowblock post_container poll" aria-level="{{lang "topic.poll_aria"}}">
|
<article class="rowblock post_container poll" aria-level="{{lang "topic.poll_aria"}}">
|
||||||
<div class="rowitem passive editable_parent post_item poll_item {{.Topic.ClassName}}" style="background-image: url({{.Topic.Avatar}}), url(/static/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
<div class="rowitem passive editable_parent post_item poll_item {{.Topic.ClassName}}" style="background-image:url({{.Topic.Avatar}}), url(/s/{{.Header.Theme.Name}}/post-avatar-bg.jpg);background-position:0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||||
<div class="topic_content user_content">
|
<div class="topic_content user_content">
|
||||||
{{range .Poll.QuickOptions}}
|
{{range .Poll.QuickOptions}}
|
||||||
<div class="poll_option">
|
<div class="poll_option">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<span itemprop="text">{{.ActionType}}</span>
|
<span itemprop="text">{{.ActionType}}</span>
|
||||||
</article>
|
</article>
|
||||||
{{else}}
|
{{else}}
|
||||||
<article {{scope "post"}} id="post-{{.ID}}" itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="background-image: url({{.Avatar}}), url(/static/{{$.Header.Theme.Name}}/post-avatar-bg.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
<article {{scope "post"}} id="post-{{.ID}}" itemscope itemtype="http://schema.org/CreativeWork" class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="background-image:url({{.Avatar}}), url(/s/{{$.Header.Theme.Name}}/post-avatar-bg.jpg);background-position:0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;">
|
||||||
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
||||||
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
||||||
{{if $.CurrentUser.Loggedin}}<div class="auto_hide edit_source">{{.Content}}</div>{{end}}
|
{{if $.CurrentUser.Loggedin}}<div class="auto_hide edit_source">{{.Content}}</div>{{end}}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
//console.log("af")
|
//console.log("af")
|
||||||
let loggedIn = document.head.querySelector("[property='x-loggedin']").content;
|
let loggedIn = document.head.querySelector("[property='x-loggedin']").content;
|
||||||
if(loggedIn) {
|
if(loggedIn) {
|
||||||
if(navigator.userAgent.indexOf("Firefox") != -1) $.trumbowyg.svgPath = "/static/trumbowyg/ui/icons.svg";
|
if(navigator.userAgent.indexOf("Firefox") != -1) $.trumbowyg.svgPath = "/s/trumbowyg/ui/icons.svg";
|
||||||
|
|
||||||
// Is there we way we can append instead? Maybe, an editor plugin?
|
// Is there we way we can append instead? Maybe, an editor plugin?
|
||||||
attachItemCallback = function(attachItem) {
|
attachItemCallback = function(attachItem) {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
.rowitem .topRow {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.rowitem .userbit {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.rowitem .topRow .nameAndTitle {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.nameAndTitle .real_username {
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
.userbit img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 24px;
|
||||||
|
}
|
||||||
|
.controls {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.controls a {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.content_column {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
|
@ -351,6 +351,10 @@ h1, h2, h3, h4, h5 {
|
||||||
.rowhead h1, .opthead h1, .colstack_head h1 {
|
.rowhead h1, .opthead h1, .colstack_head h1 {
|
||||||
font-size: 21px;
|
font-size: 21px;
|
||||||
}
|
}
|
||||||
|
.rowhead h1 + h2, .opthead h1 + h2, .colstack_right .colstack_head .rowitem h1 + h2 {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar .rowhead {
|
.sidebar .rowhead {
|
||||||
margin-left: 18px;
|
margin-left: 18px;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
}
|
||||||
.nameRow {
|
.nameRow {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
Loading…
Reference in New Issue