Add CreateProfileReply and AutoEmbed group permissions.
Log profile reply deletions in the moderator log. Split the global permissions in the UI to make them easier to manage. Experiment with showing group ID in group edit header. Avoid loading groups multiple times for the same profile reply. Initialise disabled IP log points to empty string rather than 0. Add CreateProfileReply perm phrase. Add AutoEmbed perm phrase. Add panel_group_mod_permissions phrase. Add panel_logs_mod_action_profile_reply_delete phrase.
This commit is contained in:
parent
2178efb8f0
commit
0c1d6f0516
|
@ -118,6 +118,8 @@ func seedTables(a qgen.Adapter) error {
|
||||||
UploadFiles
|
UploadFiles
|
||||||
UploadAvatars
|
UploadAvatars
|
||||||
UseConvos
|
UseConvos
|
||||||
|
CreateProfileReply
|
||||||
|
AutoEmbed
|
||||||
// CreateConvo ?
|
// CreateConvo ?
|
||||||
// CreateConvoReply ?
|
// CreateConvoReply ?
|
||||||
|
|
||||||
|
@ -142,7 +144,7 @@ func seedTables(a qgen.Adapter) error {
|
||||||
}
|
}
|
||||||
return string(jBytes)
|
return string(jBytes)
|
||||||
}
|
}
|
||||||
addGroup := func(name string, perms c.Perms, mod bool, admin bool, banned bool, tag string) {
|
addGroup := func(name string, perms c.Perms, mod, admin, banned bool, tag string) {
|
||||||
mi, ai, bi := "0", "0", "0"
|
mi, ai, bi := "0", "0", "0"
|
||||||
if mod {
|
if mod {
|
||||||
mi = "1"
|
mi = "1"
|
||||||
|
@ -161,10 +163,10 @@ func seedTables(a qgen.Adapter) error {
|
||||||
perms.EditGroupAdmin = false
|
perms.EditGroupAdmin = false
|
||||||
addGroup("Administrator", perms, true, true, false, "Admin")
|
addGroup("Administrator", perms, true, true, false, "Admin")
|
||||||
|
|
||||||
perms = c.Perms{BanUsers: true, ActivateUsers: true, EditUser: true, EditUserEmail: false, EditUserGroup: true, ViewIPs: true, UploadFiles: true, UploadAvatars: true, UseConvos: true, ViewTopic: true, LikeItem: true, CreateTopic: true, EditTopic: true, DeleteTopic: true, CreateReply: true, EditReply: true, DeleteReply: true, PinTopic: true, CloseTopic: true, MoveTopic: true}
|
perms = c.Perms{BanUsers: true, ActivateUsers: true, EditUser: true, EditUserEmail: false, EditUserGroup: true, ViewIPs: true, UploadFiles: true, UploadAvatars: true, UseConvos: true, CreateProfileReply: true, AutoEmbed: true, ViewTopic: true, LikeItem: true, CreateTopic: true, EditTopic: true, DeleteTopic: true, CreateReply: true, EditReply: true, DeleteReply: true, PinTopic: true, CloseTopic: true, MoveTopic: true}
|
||||||
addGroup("Moderator", perms, true, false, false, "Mod")
|
addGroup("Moderator", perms, true, false, false, "Mod")
|
||||||
|
|
||||||
perms = c.Perms{UploadFiles: true, UploadAvatars: true, UseConvos: true, ViewTopic: true, LikeItem: true, CreateTopic: true, CreateReply: true}
|
perms = c.Perms{UploadFiles: true, UploadAvatars: true, UseConvos: true, CreateProfileReply: true, AutoEmbed: true, ViewTopic: true, LikeItem: true, CreateTopic: true, CreateReply: true}
|
||||||
addGroup("Member", perms, false, false, false, "")
|
addGroup("Member", perms, false, false, false, "")
|
||||||
|
|
||||||
perms = c.Perms{ViewTopic: true}
|
perms = c.Perms{ViewTopic: true}
|
||||||
|
|
|
@ -594,6 +594,7 @@ type PanelEditGroupPermsPage struct {
|
||||||
Name string
|
Name string
|
||||||
LocalPerms []NameLangToggle
|
LocalPerms []NameLangToggle
|
||||||
GlobalPerms []NameLangToggle
|
GlobalPerms []NameLangToggle
|
||||||
|
ModPerms []NameLangToggle
|
||||||
}
|
}
|
||||||
|
|
||||||
type GroupPromotionExtend struct {
|
type GroupPromotionExtend struct {
|
||||||
|
|
|
@ -465,19 +465,25 @@ func (ps *ParseSettings) CopyPtr() *ParseSettings {
|
||||||
// TODO: Write a test for this
|
// TODO: Write a test for this
|
||||||
// TODO: We need a lot more hooks here. E.g. To add custom media types and handlers.
|
// TODO: We need a lot more hooks here. E.g. To add custom media types and handlers.
|
||||||
// TODO: Use templates to reduce the amount of boilerplate?
|
// TODO: Use templates to reduce the amount of boilerplate?
|
||||||
func ParseMessage(msg string, sectionID int, sectionType string, settings *ParseSettings /*, user User*/) string {
|
func ParseMessage(msg string, sectionID int, sectionType string, settings *ParseSettings, user *User) string {
|
||||||
if settings == nil {
|
if settings == nil {
|
||||||
settings = DefaultParseSettings
|
settings = DefaultParseSettings
|
||||||
}
|
}
|
||||||
|
if user == nil {
|
||||||
|
user = &GuestUser
|
||||||
|
}
|
||||||
// TODO: Word boundary detection for these to avoid mangling code
|
// TODO: Word boundary detection for these to avoid mangling code
|
||||||
msg = strings.Replace(msg, ":)", "😀", -1)
|
rep := func(find, replace string) {
|
||||||
msg = strings.Replace(msg, ":(", "😞", -1)
|
msg = strings.Replace(msg, find, replace, -1)
|
||||||
msg = strings.Replace(msg, ":D", "😃", -1)
|
}
|
||||||
msg = strings.Replace(msg, ":P", "😛", -1)
|
rep(":)", "😀")
|
||||||
msg = strings.Replace(msg, ":O", "😲", -1)
|
rep(":(", "😞")
|
||||||
msg = strings.Replace(msg, ":p", "😛", -1)
|
rep(":D", "😃")
|
||||||
msg = strings.Replace(msg, ":o", "😲", -1)
|
rep(":P", "😛")
|
||||||
msg = strings.Replace(msg, ";)", "😉", -1)
|
rep(":O", "😲")
|
||||||
|
rep(":p", "😛")
|
||||||
|
rep(":o", "😲")
|
||||||
|
rep(";)", "😉")
|
||||||
|
|
||||||
// Word filter list. E.g. Swear words and other things the admins don't like
|
// Word filter list. E.g. Swear words and other things the admins don't like
|
||||||
wordFilters, err := WordFilters.GetAll()
|
wordFilters, err := WordFilters.GetAll()
|
||||||
|
|
|
@ -40,6 +40,8 @@ var GlobalPermList = []string{
|
||||||
"UploadFiles",
|
"UploadFiles",
|
||||||
"UploadAvatars",
|
"UploadAvatars",
|
||||||
"UseConvos",
|
"UseConvos",
|
||||||
|
"CreateProfileReply",
|
||||||
|
"AutoEmbed",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Permission Structure: ActionComponent[Subcomponent]Flag
|
// Permission Structure: ActionComponent[Subcomponent]Flag
|
||||||
|
@ -69,6 +71,8 @@ type Perms struct {
|
||||||
UploadFiles bool `json:",omitempty"`
|
UploadFiles bool `json:",omitempty"`
|
||||||
UploadAvatars bool `json:",omitempty"`
|
UploadAvatars bool `json:",omitempty"`
|
||||||
UseConvos bool `json:",omitempty"`
|
UseConvos bool `json:",omitempty"`
|
||||||
|
CreateProfileReply bool `json:",omitempty"`
|
||||||
|
AutoEmbed bool `json:",omitempty"`
|
||||||
|
|
||||||
// Forum permissions
|
// Forum permissions
|
||||||
ViewTopic bool `json:",omitempty"`
|
ViewTopic bool `json:",omitempty"`
|
||||||
|
@ -125,6 +129,8 @@ func init() {
|
||||||
UploadFiles: true,
|
UploadFiles: true,
|
||||||
UploadAvatars: true,
|
UploadAvatars: true,
|
||||||
UseConvos: true,
|
UseConvos: true,
|
||||||
|
CreateProfileReply: true,
|
||||||
|
AutoEmbed: true,
|
||||||
|
|
||||||
ViewTopic: true,
|
ViewTopic: true,
|
||||||
LikeItem: true,
|
LikeItem: true,
|
||||||
|
|
|
@ -65,7 +65,7 @@ func (r *ProfileReply) Delete() error {
|
||||||
|
|
||||||
func (r *ProfileReply) SetBody(content string) error {
|
func (r *ProfileReply) SetBody(content string) error {
|
||||||
content = PreparseMessage(html.UnescapeString(content))
|
content = PreparseMessage(html.UnescapeString(content))
|
||||||
_, err := profileReplyStmts.edit.Exec(content, ParseMessage(content, 0, "", nil), r.ID)
|
_, err := profileReplyStmts.edit.Exec(content, ParseMessage(content, 0, "", nil, nil), r.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,9 @@ func (s *SQLProfileReplyStore) Exists(id int) bool {
|
||||||
|
|
||||||
func (s *SQLProfileReplyStore) Create(profileID int, content string, createdBy int, ip string) (id int, err error) {
|
func (s *SQLProfileReplyStore) Create(profileID int, content string, createdBy int, ip string) (id int, err error) {
|
||||||
if Config.DisablePostIP {
|
if Config.DisablePostIP {
|
||||||
ip = "0"
|
ip = ""
|
||||||
}
|
}
|
||||||
res, err := s.create.Exec(profileID, content, ParseMessage(content, 0, "", nil), createdBy, ip)
|
res, err := s.create.Exec(profileID, content, ParseMessage(content, 0, "", nil, nil), createdBy, ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ func (r *Reply) SetPost(content string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
content = PreparseMessage(html.UnescapeString(content))
|
content = PreparseMessage(html.UnescapeString(content))
|
||||||
parsedContent := ParseMessage(content, topic.ParentID, "forums", nil)
|
parsedContent := ParseMessage(content, topic.ParentID, "forums", nil, nil)
|
||||||
_, err = replyStmts.edit.Exec(content, parsedContent, r.ID) // TODO: Sniff if this changed anything to see if we hit an existing poll
|
_, err = replyStmts.edit.Exec(content, parsedContent, r.ID) // TODO: Sniff if this changed anything to see if we hit an existing poll
|
||||||
_ = Rstore.GetCache().Remove(r.ID)
|
_ = Rstore.GetCache().Remove(r.ID)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -99,9 +99,9 @@ func (s *SQLReplyStore) Exists(id int) bool {
|
||||||
// TODO: Write a test for this
|
// TODO: Write a test for this
|
||||||
func (s *SQLReplyStore) Create(t *Topic, content, ip string, uid int) (rid int, err error) {
|
func (s *SQLReplyStore) Create(t *Topic, content, ip string, uid int) (rid int, err error) {
|
||||||
if Config.DisablePostIP {
|
if Config.DisablePostIP {
|
||||||
ip = "0"
|
ip = ""
|
||||||
}
|
}
|
||||||
res, err := s.create.Exec(t.ID, content, ParseMessage(content, t.ParentID, "forums", nil), ip, WordCount(content), uid)
|
res, err := s.create.Exec(t.ID, content, ParseMessage(content, t.ParentID, "forums", nil, nil), ip, WordCount(content), uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,9 @@ func (s *DefaultReportStore) Create(title, content string, u *User, itemType str
|
||||||
|
|
||||||
ip := u.GetIP()
|
ip := u.GetIP()
|
||||||
if Config.DisablePostIP {
|
if Config.DisablePostIP {
|
||||||
ip = "0"
|
ip = ""
|
||||||
}
|
}
|
||||||
res, err := s.create.Exec(title, content, ParseMessage(content, 0, "", nil), ip, u.ID, u.ID, itemType+"_"+strconv.Itoa(itemID), ReportForumID)
|
res, err := s.create.Exec(title, content, ParseMessage(content, 0, "", nil, nil), ip, u.ID, u.ID, itemType+"_"+strconv.Itoa(itemID), ReportForumID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -400,7 +400,7 @@ func handleAttachments(stmt *sql.Stmt, id int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Only load a row per createdBy, maybe with group by?
|
// TODO: Only load a row per createdBy, maybe with group by?
|
||||||
func handleTopicReplies(umap map[int]struct{}, uid int, tid int) error {
|
func handleTopicReplies(umap map[int]struct{}, uid, tid int) error {
|
||||||
rows, err := userStmts.getRepliesOfTopic.Query(uid, tid)
|
rows, err := userStmts.getRepliesOfTopic.Query(uid, tid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -505,7 +505,7 @@ func (t *Topic) Update(name, content string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
content = PreparseMessage(html.UnescapeString(content))
|
content = PreparseMessage(html.UnescapeString(content))
|
||||||
parsedContent := ParseMessage(content, t.ParentID, "forums", nil)
|
parsedContent := ParseMessage(content, t.ParentID, "forums", nil, nil)
|
||||||
_, err := topicStmts.edit.Exec(name, content, parsedContent, t.ID)
|
_, err := topicStmts.edit.Exec(name, content, parsedContent, t.ID)
|
||||||
t.cacheRemove()
|
t.cacheRemove()
|
||||||
return err
|
return err
|
||||||
|
@ -518,9 +518,9 @@ func (t *Topic) SetPoll(pollID int) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Have this go through the ReplyStore?
|
// TODO: Have this go through the ReplyStore?
|
||||||
func (t *Topic) CreateActionReply(action string, ip string, uid int) (err error) {
|
func (t *Topic) CreateActionReply(action, ip string, uid int) (err error) {
|
||||||
if Config.DisablePostIP {
|
if Config.DisablePostIP {
|
||||||
ip = "0"
|
ip = ""
|
||||||
}
|
}
|
||||||
res, err := topicStmts.createAction.Exec(t.ID, action, ip, uid)
|
res, err := topicStmts.createAction.Exec(t.ID, action, ip, uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -566,13 +566,13 @@ var unlockai = "🔓"
|
||||||
var stickai = "📌"
|
var stickai = "📌"
|
||||||
var unstickai = "📌" + aipost
|
var unstickai = "📌" + aipost
|
||||||
|
|
||||||
func (ru *ReplyUser) Init() error {
|
func (ru *ReplyUser) Init() (group *Group, err error) {
|
||||||
ru.UserLink = BuildProfileURL(NameToSlug(ru.CreatedByName), ru.CreatedBy)
|
ru.UserLink = BuildProfileURL(NameToSlug(ru.CreatedByName), ru.CreatedBy)
|
||||||
ru.ContentLines = strings.Count(ru.Content, "\n")
|
ru.ContentLines = strings.Count(ru.Content, "\n")
|
||||||
|
|
||||||
postGroup, err := Groups.Get(ru.Group)
|
postGroup, err := Groups.Get(ru.Group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if postGroup.IsMod {
|
if postGroup.IsMod {
|
||||||
ru.ClassName = Config.StaffCSS
|
ru.ClassName = Config.StaffCSS
|
||||||
|
@ -581,9 +581,6 @@ func (ru *ReplyUser) Init() error {
|
||||||
|
|
||||||
// TODO: Make a function for this? Build a more sophisticated noavatar handling system? Do bulk user loads and let the c.UserStore initialise this?
|
// TODO: Make a function for this? Build a more sophisticated noavatar handling system? Do bulk user loads and let the c.UserStore initialise this?
|
||||||
ru.Avatar, ru.MicroAvatar = BuildAvatar(ru.CreatedBy, ru.Avatar)
|
ru.Avatar, ru.MicroAvatar = BuildAvatar(ru.CreatedBy, ru.Avatar)
|
||||||
if ru.Tag == "" {
|
|
||||||
ru.Tag = postGroup.Tag
|
|
||||||
}
|
|
||||||
|
|
||||||
// We really shouldn't have inline HTML, we should do something about this...
|
// We really shouldn't have inline HTML, we should do something about this...
|
||||||
if ru.ActionType != "" {
|
if ru.ActionType != "" {
|
||||||
|
@ -604,18 +601,18 @@ func (ru *ReplyUser) Init() error {
|
||||||
forum, err := Forums.Get(fid)
|
forum, err := Forums.Get(fid)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ru.ActionType = p.GetTmplPhrasef("topic.action_topic_move_dest", forum.Link, forum.Name, ru.UserLink, ru.CreatedByName)
|
ru.ActionType = p.GetTmplPhrasef("topic.action_topic_move_dest", forum.Link, forum.Name, ru.UserLink, ru.CreatedByName)
|
||||||
return nil
|
return postGroup, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// TODO: Only fire this off if a corresponding phrase for the ActionType doesn't exist? Or maybe have some sort of action registry?
|
// TODO: Only fire this off if a corresponding phrase for the ActionType doesn't exist? Or maybe have some sort of action registry?
|
||||||
ru.ActionType = p.GetTmplPhrasef("topic.action_topic_default", ru.ActionType)
|
ru.ActionType = p.GetTmplPhrasef("topic.action_topic_default", ru.ActionType)
|
||||||
return nil
|
return postGroup, nil
|
||||||
}
|
}
|
||||||
ru.ActionType = p.GetTmplPhrasef("topic.action_topic_"+action, ru.UserLink, ru.CreatedByName)
|
ru.ActionType = p.GetTmplPhrasef("topic.action_topic_"+action, ru.UserLink, ru.CreatedByName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return postGroup, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Factor TopicUser into a *Topic and *User, as this starting to become overly complicated x.x
|
// TODO: Factor TopicUser into a *Topic and *User, as this starting to become overly complicated x.x
|
||||||
|
@ -648,12 +645,21 @@ func (t *TopicUser) Replies(offset, pFrag int, user *User) (rlist []*ReplyUser,
|
||||||
hTbl := GetHookTable()
|
hTbl := GetHookTable()
|
||||||
rf := func(r *ReplyUser) error {
|
rf := func(r *ReplyUser) error {
|
||||||
//log.Printf("before r: %+v\n", r)
|
//log.Printf("before r: %+v\n", r)
|
||||||
err := r.Init()
|
group, err := r.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//log.Printf("after r: %+v\n", r)
|
//log.Printf("after r: %+v\n", r)
|
||||||
r.ContentHtml = ParseMessage(r.Content, t.ParentID, "forums", user.ParseSettings)
|
|
||||||
|
var parseSettings *ParseSettings
|
||||||
|
if !group.Perms.AutoEmbed && (user.ParseSettings == nil || !user.ParseSettings.NoEmbed) {
|
||||||
|
parseSettings = DefaultParseSettings.CopyPtr()
|
||||||
|
parseSettings.NoEmbed = true
|
||||||
|
} else {
|
||||||
|
parseSettings = user.ParseSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
r.ContentHtml = ParseMessage(r.Content, t.ParentID, "forums", parseSettings, user)
|
||||||
// TODO: Do this more efficiently by avoiding the allocations entirely in ParseMessage, if there's nothing to do.
|
// TODO: Do this more efficiently by avoiding the allocations entirely in ParseMessage, if there's nothing to do.
|
||||||
if r.ContentHtml == r.Content {
|
if r.ContentHtml == r.Content {
|
||||||
r.ContentHtml = r.Content
|
r.ContentHtml = r.Content
|
||||||
|
|
|
@ -222,14 +222,14 @@ func (s *DefaultTopicStore) Create(fid int, name, content string, uid int, ip st
|
||||||
return 0, ErrLongTitle
|
return 0, ErrLongTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedContent := strings.TrimSpace(ParseMessage(content, fid, "forums", nil))
|
parsedContent := strings.TrimSpace(ParseMessage(content, fid, "forums", nil, nil))
|
||||||
if parsedContent == "" {
|
if parsedContent == "" {
|
||||||
return 0, ErrNoBody
|
return 0, ErrNoBody
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move this statement into the topic store
|
// TODO: Move this statement into the topic store
|
||||||
if Config.DisablePostIP {
|
if Config.DisablePostIP {
|
||||||
ip = "0"
|
ip = ""
|
||||||
}
|
}
|
||||||
res, err := s.create.Exec(fid, name, content, parsedContent, uid, ip, WordCount(content), uid)
|
res, err := s.create.Exec(fid, name, content, parsedContent, uid, ip, WordCount(content), uid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -936,7 +936,7 @@ func BenchmarkParserSerial(b *testing.B) {
|
||||||
f := func(name, msg string) func(b *testing.B) {
|
f := func(name, msg string) func(b *testing.B) {
|
||||||
return func(b *testing.B) {
|
return func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_ = c.ParseMessage(msg, 0, "", nil)
|
_ = c.ParseMessage(msg, 0, "", nil, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
"UploadFiles": "Can upload files",
|
"UploadFiles": "Can upload files",
|
||||||
"UploadAvatars": "Can upload avatars",
|
"UploadAvatars": "Can upload avatars",
|
||||||
"UseConvos":"Can use conversations",
|
"UseConvos":"Can use conversations",
|
||||||
|
"CreateProfileReply": "Can create profile replies",
|
||||||
|
"AutoEmbed":"Automatically embed media they post",
|
||||||
|
|
||||||
"ViewTopic": "Can view topics",
|
"ViewTopic": "Can view topics",
|
||||||
"LikeItem": "Can like items",
|
"LikeItem": "Can like items",
|
||||||
|
@ -919,6 +921,7 @@
|
||||||
"panel_group_tag_placeholder":"VIP",
|
"panel_group_tag_placeholder":"VIP",
|
||||||
"panel_group_update_button":"Update Group",
|
"panel_group_update_button":"Update Group",
|
||||||
"panel_group_extended_permissions":"Extended Permissions",
|
"panel_group_extended_permissions":"Extended Permissions",
|
||||||
|
"panel_group_mod_permissions":"Moderator Permissions",
|
||||||
|
|
||||||
"panel_group_promotions_level_prefix":"level ",
|
"panel_group_promotions_level_prefix":"level ",
|
||||||
"panel_group_promotions_posts_prefix":"posts ",
|
"panel_group_promotions_posts_prefix":"posts ",
|
||||||
|
@ -1029,6 +1032,7 @@
|
||||||
"panel_logs_mod_action_topic_move_dest":"<a href='%s'>%s</a> was moved to <a href='%s'>%s</a> by <a href='%s'>%s</a>",
|
"panel_logs_mod_action_topic_move_dest":"<a href='%s'>%s</a> was moved to <a href='%s'>%s</a> by <a href='%s'>%s</a>",
|
||||||
"panel_logs_mod_action_topic_unknown":"Unknown action '%s' on elementType '%s' by <a href='%s'>%s</a>",
|
"panel_logs_mod_action_topic_unknown":"Unknown action '%s' on elementType '%s' by <a href='%s'>%s</a>",
|
||||||
"panel_logs_mod_action_reply_delete":"A reply in <a href='%s'>%s</a> was deleted by <a href='%s'>%s</a>",
|
"panel_logs_mod_action_reply_delete":"A reply in <a href='%s'>%s</a> was deleted by <a href='%s'>%s</a>",
|
||||||
|
"panel_logs_mod_action_profile_reply_delete":"A reply on <a href='%s'>%s</a>'s profile was deleted by <a href='%s'>%s</a>",
|
||||||
"panel_logs_mod_action_user_ban":"<a href='%s'>%s</a> was banned by <a href='%s'>%s</a>",
|
"panel_logs_mod_action_user_ban":"<a href='%s'>%s</a> was banned by <a href='%s'>%s</a>",
|
||||||
"panel_logs_mod_action_user_unban":"<a href='%s'>%s</a> was unbanned by <a href='%s'>%s</a>",
|
"panel_logs_mod_action_user_unban":"<a href='%s'>%s</a> was unbanned by <a href='%s'>%s</a>",
|
||||||
"panel_logs_mod_action_user_delete-posts":"<a href='%s'>%s</a> had their posts purged by <a href='%s'>%s</a>",
|
"panel_logs_mod_action_user_delete-posts":"<a href='%s'>%s</a> had their posts purged by <a href='%s'>%s</a>",
|
||||||
|
|
68
misc_test.go
68
misc_test.go
|
@ -59,17 +59,17 @@ func TestUserStore(t *testing.T) {
|
||||||
func userStoreTest(t *testing.T, newUserID int) {
|
func userStoreTest(t *testing.T, newUserID int) {
|
||||||
ucache := c.Users.GetCache()
|
ucache := c.Users.GetCache()
|
||||||
// Go doesn't have short-circuiting, so this'll allow us to do one liner tests
|
// Go doesn't have short-circuiting, so this'll allow us to do one liner tests
|
||||||
isCacheLengthZero := func(ucache c.UserCache) bool {
|
isCacheLengthZero := func(uc c.UserCache) bool {
|
||||||
if ucache == nil {
|
if uc == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return ucache.Length() == 0
|
return uc.Length() == 0
|
||||||
}
|
}
|
||||||
cacheLength := func(ucache c.UserCache) int {
|
cacheLength := func(uc c.UserCache) int {
|
||||||
if ucache == nil {
|
if uc == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return ucache.Length()
|
return uc.Length()
|
||||||
}
|
}
|
||||||
expect(t, isCacheLengthZero(ucache), fmt.Sprintf("The initial ucache length should be zero, not %d", cacheLength(ucache)))
|
expect(t, isCacheLengthZero(ucache), fmt.Sprintf("The initial ucache length should be zero, not %d", cacheLength(ucache)))
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||||
user, err := c.Users.Get(1)
|
user, err := c.Users.Get(1)
|
||||||
recordMustExist(t, err, "Couldn't find UID #1")
|
recordMustExist(t, err, "Couldn't find UID #1")
|
||||||
|
|
||||||
expectW := func(cond bool, expec bool, prefix string, suffix string) {
|
expectW := func(cond, expec bool, prefix, suffix string) {
|
||||||
midfix := "should not be"
|
midfix := "should not be"
|
||||||
if expec {
|
if expec {
|
||||||
midfix = "should be"
|
midfix = "should be"
|
||||||
|
@ -93,7 +93,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add email checks too? Do them separately?
|
// TODO: Add email checks too? Do them separately?
|
||||||
expectUser := func(u *c.User, uid int, name string, group int, super bool, admin bool, mod bool, banned bool) {
|
expectUser := func(u *c.User, uid int, name string, group int, super, admin, mod, banned bool) {
|
||||||
expect(t, u.ID == uid, fmt.Sprintf("u.ID should be %d. Got '%d' instead.", uid, u.ID))
|
expect(t, u.ID == uid, fmt.Sprintf("u.ID should be %d. Got '%d' instead.", uid, u.ID))
|
||||||
expect(t, u.Name == name, fmt.Sprintf("u.Name should be '%s', not '%s'", name, u.Name))
|
expect(t, u.Name == name, fmt.Sprintf("u.Name should be '%s', not '%s'", name, u.Name))
|
||||||
expectW(u.Group == group, true, u.Name, "in group"+strconv.Itoa(group))
|
expectW(u.Group == group, true, u.Name, "in group"+strconv.Itoa(group))
|
||||||
|
@ -258,7 +258,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||||
dummyRequest2 := httptest.NewRequest("", "/forum/"+strconv.Itoa(generalForumID), bytesBuffer)
|
dummyRequest2 := httptest.NewRequest("", "/forum/"+strconv.Itoa(generalForumID), bytesBuffer)
|
||||||
var user2 *c.User
|
var user2 *c.User
|
||||||
|
|
||||||
changeGroupTest := func(oldGroup int, newGroup int) {
|
changeGroupTest := func(oldGroup, newGroup int) {
|
||||||
err = user.ChangeGroup(newGroup)
|
err = user.ChangeGroup(newGroup)
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
// ! I don't think ChangeGroup should be changing the value of user... Investigate this.
|
// ! I don't think ChangeGroup should be changing the value of user... Investigate this.
|
||||||
|
@ -270,7 +270,7 @@ func userStoreTest(t *testing.T, newUserID int) {
|
||||||
*user2 = *user
|
*user2 = *user
|
||||||
}
|
}
|
||||||
|
|
||||||
changeGroupTest2 := func(rank string, firstShouldBe bool, secondShouldBe bool) {
|
changeGroupTest2 := func(rank string, firstShouldBe, secondShouldBe bool) {
|
||||||
head, err := c.UserCheck(dummyResponseRecorder, dummyRequest1, user)
|
head, err := c.UserCheck(dummyResponseRecorder, dummyRequest1, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -364,7 +364,7 @@ func expectNilErr(t *testing.T, item error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func expectIntToBeX(t *testing.T, item int, expect int, errmsg string) {
|
func expectIntToBeX(t *testing.T, item, expect int, errmsg string) {
|
||||||
if item != expect {
|
if item != expect {
|
||||||
debug.PrintStack()
|
debug.PrintStack()
|
||||||
t.Fatalf(errmsg, item)
|
t.Fatalf(errmsg, item)
|
||||||
|
@ -452,14 +452,14 @@ func TestTopicStore(t *testing.T) {
|
||||||
c.Config.DisablePostIP = false
|
c.Config.DisablePostIP = false
|
||||||
topicStoreTest(t, 2, "::1")
|
topicStoreTest(t, 2, "::1")
|
||||||
c.Config.DisablePostIP = true
|
c.Config.DisablePostIP = true
|
||||||
topicStoreTest(t, 3, "0")
|
topicStoreTest(t, 3, "")
|
||||||
|
|
||||||
c.Topics, err = c.NewDefaultTopicStore(nil)
|
c.Topics, err = c.NewDefaultTopicStore(nil)
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
c.Config.DisablePostIP = false
|
c.Config.DisablePostIP = false
|
||||||
topicStoreTest(t, 4, "::1")
|
topicStoreTest(t, 4, "::1")
|
||||||
c.Config.DisablePostIP = true
|
c.Config.DisablePostIP = true
|
||||||
topicStoreTest(t, 5, "0")
|
topicStoreTest(t, 5, "")
|
||||||
}
|
}
|
||||||
func topicStoreTest(t *testing.T, newID int, ip string) {
|
func topicStoreTest(t *testing.T, newID int, ip string) {
|
||||||
var topic *c.Topic
|
var topic *c.Topic
|
||||||
|
@ -914,20 +914,20 @@ func TestReplyStore(t *testing.T) {
|
||||||
c.Config.DisablePostIP = false
|
c.Config.DisablePostIP = false
|
||||||
testReplyStore(t, 2, 1, "::1")
|
testReplyStore(t, 2, 1, "::1")
|
||||||
c.Config.DisablePostIP = true
|
c.Config.DisablePostIP = true
|
||||||
testReplyStore(t, 5, 3, "0")
|
testReplyStore(t, 5, 3, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testReplyStore(t *testing.T, newID, newPostCount int, ip string) {
|
func testReplyStore(t *testing.T, newID, newPostCount int, ip string) {
|
||||||
replyTest2 := func(reply *c.Reply, err error, rid int, parentID int, createdBy int, content string, ip string) {
|
replyTest2 := func(r *c.Reply, err error, rid, parentID, createdBy int, content, ip string) {
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
expect(t, reply.ID == rid, fmt.Sprintf("RID #%d has the wrong ID. It should be %d not %d", rid, rid, reply.ID))
|
expect(t, r.ID == rid, fmt.Sprintf("RID #%d has the wrong ID. It should be %d not %d", rid, rid, r.ID))
|
||||||
expect(t, reply.ParentID == parentID, fmt.Sprintf("The parent topic of RID #%d should be %d not %d", rid, parentID, reply.ParentID))
|
expect(t, r.ParentID == parentID, fmt.Sprintf("The parent topic of RID #%d should be %d not %d", rid, parentID, r.ParentID))
|
||||||
expect(t, reply.CreatedBy == createdBy, fmt.Sprintf("The creator of RID #%d should be %d not %d", rid, createdBy, reply.CreatedBy))
|
expect(t, r.CreatedBy == createdBy, fmt.Sprintf("The creator of RID #%d should be %d not %d", rid, createdBy, r.CreatedBy))
|
||||||
expect(t, reply.Content == content, fmt.Sprintf("The contents of RID #%d should be '%s' not %s", rid, content, reply.Content))
|
expect(t, r.Content == content, fmt.Sprintf("The contents of RID #%d should be '%s' not %s", rid, content, r.Content))
|
||||||
expect(t, reply.IP == ip, fmt.Sprintf("The IP of RID#%d should be '%s' not %s", rid, ip, reply.IP))
|
expect(t, r.IP == ip, fmt.Sprintf("The IP of RID#%d should be '%s' not %s", rid, ip, r.IP))
|
||||||
}
|
}
|
||||||
|
|
||||||
replyTest := func(rid int, parentID int, createdBy int, content string, ip string) {
|
replyTest := func(rid, parentID, createdBy int, content, ip string) {
|
||||||
reply, err := c.Rstore.Get(rid)
|
reply, err := c.Rstore.Get(rid)
|
||||||
replyTest2(reply, err, rid, parentID, createdBy, content, ip)
|
replyTest2(reply, err, rid, parentID, createdBy, content, ip)
|
||||||
reply, err = c.Rstore.GetCache().Get(rid)
|
reply, err = c.Rstore.GetCache().Get(rid)
|
||||||
|
@ -1015,7 +1015,7 @@ func TestProfileReplyStore(t *testing.T) {
|
||||||
c.Config.DisablePostIP = false
|
c.Config.DisablePostIP = false
|
||||||
testProfileReplyStore(t, 1, "::1")
|
testProfileReplyStore(t, 1, "::1")
|
||||||
c.Config.DisablePostIP = true
|
c.Config.DisablePostIP = true
|
||||||
testProfileReplyStore(t, 2, "0")
|
testProfileReplyStore(t, 2, "")
|
||||||
}
|
}
|
||||||
func testProfileReplyStore(t *testing.T, newID int, ip string) {
|
func testProfileReplyStore(t *testing.T, newID int, ip string) {
|
||||||
// ? - Commented this one out as strong constraints like this put an unreasonable load on the database, we only want errors if a delete which should succeed fails
|
// ? - Commented this one out as strong constraints like this put an unreasonable load on the database, we only want errors if a delete which should succeed fails
|
||||||
|
@ -1466,22 +1466,22 @@ func TestWidgets(t *testing.T) {
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
expect(t, wid == 1, "wid should be 1")
|
expect(t, wid == 1, "wid should be 1")
|
||||||
|
|
||||||
|
wtest := func(w, w2 *c.Widget) {
|
||||||
|
expect(t, w.Position == w2.Position, "wrong position")
|
||||||
|
expect(t, w.Side == w2.Side, "wrong side")
|
||||||
|
expect(t, w.Type == w2.Type, "wrong type")
|
||||||
|
expect(t, w2.Enabled, "not enabled")
|
||||||
|
expect(t, w.Location == w2.Location, "wrong location")
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Do a test for the widget body
|
// TODO: Do a test for the widget body
|
||||||
widget2, err := c.Widgets.Get(1)
|
widget2, err := c.Widgets.Get(1)
|
||||||
expectNilErr(t, err)
|
expectNilErr(t, err)
|
||||||
expect(t, widget2.Position == widget.Position, "wrong position")
|
wtest(widget, widget2)
|
||||||
expect(t, widget2.Side == widget.Side, "wrong side")
|
|
||||||
expect(t, widget2.Type == widget.Type, "wrong type")
|
|
||||||
expect(t, widget2.Enabled, "not enabled")
|
|
||||||
expect(t, widget2.Location == widget.Location, "wrong location")
|
|
||||||
|
|
||||||
widgets = c.Docks.RightSidebar.Items
|
widgets = c.Docks.RightSidebar.Items
|
||||||
expect(t, len(widgets) == 1, fmt.Sprintf("RightSidebar should have 1 item, not %d", len(widgets)))
|
expect(t, len(widgets) == 1, fmt.Sprintf("RightSidebar should have 1 item, not %d", len(widgets)))
|
||||||
expect(t, widgets[0].Position == widget.Position, "wrong position")
|
wtest(widget, widgets[0])
|
||||||
expect(t, widgets[0].Side == widget.Side, "wrong side")
|
|
||||||
expect(t, widgets[0].Type == widget.Type, "wrong type")
|
|
||||||
expect(t, widgets[0].Enabled, "not enabled")
|
|
||||||
expect(t, widgets[0].Location == widget.Location, "wrong location")
|
|
||||||
|
|
||||||
widget2.Enabled = false
|
widget2.Enabled = false
|
||||||
ewidget = &c.WidgetEdit{widget2, map[string]string{"Name": "Test", "Text": "Testing"}}
|
ewidget = &c.WidgetEdit{widget2, map[string]string{"Name": "Test", "Text": "Testing"}}
|
||||||
|
@ -1493,7 +1493,7 @@ func TestWidgets(t *testing.T) {
|
||||||
expect(t, widget2.Position == widget.Position, "wrong position")
|
expect(t, widget2.Position == widget.Position, "wrong position")
|
||||||
expect(t, widget2.Side == widget.Side, "wrong side")
|
expect(t, widget2.Side == widget.Side, "wrong side")
|
||||||
expect(t, widget2.Type == widget.Type, "wrong type")
|
expect(t, widget2.Type == widget.Type, "wrong type")
|
||||||
expect(t, !widget2.Enabled, "not enabled")
|
expect(t, !widget2.Enabled, "should not be enabled")
|
||||||
expect(t, widget2.Location == widget.Location, "wrong location")
|
expect(t, widget2.Location == widget.Location, "wrong location")
|
||||||
|
|
||||||
widgets = c.Docks.RightSidebar.Items
|
widgets = c.Docks.RightSidebar.Items
|
||||||
|
@ -1501,7 +1501,7 @@ func TestWidgets(t *testing.T) {
|
||||||
expect(t, widgets[0].Position == widget.Position, "wrong position")
|
expect(t, widgets[0].Position == widget.Position, "wrong position")
|
||||||
expect(t, widgets[0].Side == widget.Side, "wrong side")
|
expect(t, widgets[0].Side == widget.Side, "wrong side")
|
||||||
expect(t, widgets[0].Type == widget.Type, "wrong type")
|
expect(t, widgets[0].Type == widget.Type, "wrong type")
|
||||||
expect(t, !widgets[0].Enabled, "not enabled")
|
expect(t, !widgets[0].Enabled, "should not be enabled")
|
||||||
expect(t, widgets[0].Location == widget.Location, "wrong location")
|
expect(t, widgets[0].Location == widget.Location, "wrong location")
|
||||||
|
|
||||||
err = widget2.Delete()
|
err = widget2.Delete()
|
||||||
|
|
|
@ -300,7 +300,7 @@ func TestParser(t *testing.T) {
|
||||||
|
|
||||||
// TODO: Fix this hack and make the results a bit more reproducible, push the tests further in the process.
|
// TODO: Fix this hack and make the results a bit more reproducible, push the tests further in the process.
|
||||||
for _, item := range l.Items {
|
for _, item := range l.Items {
|
||||||
if res := c.ParseMessage(item.Msg, 1, "forums", nil); res != item.Expects {
|
if res := c.ParseMessage(item.Msg, 1, "forums", nil, nil); res != item.Expects {
|
||||||
if item.Name != "" {
|
if item.Name != "" {
|
||||||
t.Error("Name: ", item.Name)
|
t.Error("Name: ", item.Name)
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ func TestParser(t *testing.T) {
|
||||||
l.Add("//"+c.Site.URL+"\n", "<a href='https://"+c.Site.URL+"'>"+c.Site.URL+"</a><br>")
|
l.Add("//"+c.Site.URL+"\n", "<a href='https://"+c.Site.URL+"'>"+c.Site.URL+"</a><br>")
|
||||||
l.Add("//"+c.Site.URL+"\n//"+c.Site.URL, "<a href='https://"+c.Site.URL+"'>"+c.Site.URL+"</a><br><a href='https://"+c.Site.URL+"'>"+c.Site.URL+"</a>")
|
l.Add("//"+c.Site.URL+"\n//"+c.Site.URL, "<a href='https://"+c.Site.URL+"'>"+c.Site.URL+"</a><br><a href='https://"+c.Site.URL+"'>"+c.Site.URL+"</a>")
|
||||||
for _, item := range l.Items {
|
for _, item := range l.Items {
|
||||||
if res := c.ParseMessage(item.Msg, 1, "forums", nil); res != item.Expects {
|
if res := c.ParseMessage(item.Msg, 1, "forums", nil, nil); res != item.Expects {
|
||||||
if item.Name != "" {
|
if item.Name != "" {
|
||||||
t.Error("Name: ", item.Name)
|
t.Error("Name: ", item.Name)
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,7 @@ func TestParser(t *testing.T) {
|
||||||
}
|
}
|
||||||
c.WriteURL(sb, c.BuildTopicURL("", tid), "#nnid-"+strconv.Itoa(tid))
|
c.WriteURL(sb, c.BuildTopicURL("", tid), "#nnid-"+strconv.Itoa(tid))
|
||||||
})
|
})
|
||||||
res := c.ParseMessage("#nnid-1", 1, "forums", nil)
|
res := c.ParseMessage("#nnid-1", 1, "forums", nil, nil)
|
||||||
expect := "<a href='/topic/1'>#nnid-1</a>"
|
expect := "<a href='/topic/1'>#nnid-1</a>"
|
||||||
if res != expect {
|
if res != expect {
|
||||||
t.Error("Bad output:", "'"+res+"'")
|
t.Error("Bad output:", "'"+res+"'")
|
||||||
|
@ -363,7 +363,7 @@ func TestParser(t *testing.T) {
|
||||||
}
|
}
|
||||||
c.WriteURL(sb, c.BuildTopicURL("", tid), "#longidnameneedtooverflowhack-"+strconv.Itoa(tid))
|
c.WriteURL(sb, c.BuildTopicURL("", tid), "#longidnameneedtooverflowhack-"+strconv.Itoa(tid))
|
||||||
})
|
})
|
||||||
res = c.ParseMessage("#longidnameneedtooverflowhack-1", 1, "forums", nil)
|
res = c.ParseMessage("#longidnameneedtooverflowhack-1", 1, "forums", nil,nil)
|
||||||
expect = "<a href='/topic/1'>#longidnameneedtooverflowhack-1</a>"
|
expect = "<a href='/topic/1'>#longidnameneedtooverflowhack-1</a>"
|
||||||
if res != expect {
|
if res != expect {
|
||||||
t.Error("Bad output:", "'"+res+"'")
|
t.Error("Bad output:", "'"+res+"'")
|
||||||
|
|
|
@ -336,6 +336,17 @@ func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user c.User, sgid s
|
||||||
globalPerms = append(globalPerms, c.NameLangToggle{permStr, p.GetPermPhrase(permStr), perm})
|
globalPerms = append(globalPerms, c.NameLangToggle{permStr, p.GetPermPhrase(permStr), perm})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addPerm("UploadFiles", g.Perms.UploadFiles)
|
||||||
|
addPerm("UploadAvatars", g.Perms.UploadAvatars)
|
||||||
|
addPerm("UseConvos", g.Perms.UseConvos)
|
||||||
|
addPerm("CreateProfileReply", g.Perms.CreateProfileReply)
|
||||||
|
addPerm("AutoEmbed", g.Perms.AutoEmbed)
|
||||||
|
|
||||||
|
var modPerms []c.NameLangToggle
|
||||||
|
addPerm = func(permStr string, perm bool) {
|
||||||
|
modPerms = append(modPerms, c.NameLangToggle{permStr, p.GetPermPhrase(permStr), perm})
|
||||||
|
}
|
||||||
|
|
||||||
addPerm("BanUsers", g.Perms.BanUsers)
|
addPerm("BanUsers", g.Perms.BanUsers)
|
||||||
addPerm("ActivateUsers", g.Perms.ActivateUsers)
|
addPerm("ActivateUsers", g.Perms.ActivateUsers)
|
||||||
addPerm("EditUser", g.Perms.EditUser)
|
addPerm("EditUser", g.Perms.EditUser)
|
||||||
|
@ -355,11 +366,8 @@ func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user c.User, sgid s
|
||||||
addPerm("ManagePlugins", g.Perms.ManagePlugins)
|
addPerm("ManagePlugins", g.Perms.ManagePlugins)
|
||||||
addPerm("ViewAdminLogs", g.Perms.ViewAdminLogs)
|
addPerm("ViewAdminLogs", g.Perms.ViewAdminLogs)
|
||||||
addPerm("ViewIPs", g.Perms.ViewIPs)
|
addPerm("ViewIPs", g.Perms.ViewIPs)
|
||||||
addPerm("UploadFiles", g.Perms.UploadFiles)
|
|
||||||
addPerm("UploadAvatars", g.Perms.UploadAvatars)
|
|
||||||
addPerm("UseConvos", g.Perms.UseConvos)
|
|
||||||
|
|
||||||
pi := c.PanelEditGroupPermsPage{basePage, g.ID, g.Name, localPerms, globalPerms}
|
pi := c.PanelEditGroupPermsPage{basePage, g.ID, g.Name, localPerms, globalPerms, modPerms}
|
||||||
return renderTemplate("panel_group_edit_perms", w, r, basePage.Header, pi)
|
return renderTemplate("panel_group_edit_perms", w, r, basePage.Header, pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,21 +39,21 @@ func LogsRegs(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
|
||||||
|
|
||||||
// TODO: Log errors when something really screwy is going on?
|
// TODO: Log errors when something really screwy is going on?
|
||||||
// TODO: Base the slugs on the localised usernames?
|
// TODO: Base the slugs on the localised usernames?
|
||||||
func handleUnknownUser(user *c.User, err error) *c.User {
|
func handleUnknownUser(u *c.User, err error) *c.User {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &c.User{Name: p.GetTmplPhrase("user_unknown"), Link: c.BuildProfileURL("unknown", 0)}
|
return &c.User{Name: p.GetTmplPhrase("user_unknown"), Link: c.BuildProfileURL("unknown", 0)}
|
||||||
}
|
}
|
||||||
return user
|
return u
|
||||||
}
|
}
|
||||||
func handleUnknownTopic(topic *c.Topic, err error) *c.Topic {
|
func handleUnknownTopic(t *c.Topic, err error) *c.Topic {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &c.Topic{Title: p.GetTmplPhrase("topic_unknown"), Link: c.BuildTopicURL("unknown", 0)}
|
return &c.Topic{Title: p.GetTmplPhrase("topic_unknown"), Link: c.BuildTopicURL("unknown", 0)}
|
||||||
}
|
}
|
||||||
return topic
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move the log building logic into /common/ and it's own abstraction
|
// TODO: Move the log building logic into /common/ and it's own abstraction
|
||||||
func topicElementTypeAction(action string, elementType string, elementID int, actor *c.User, topic *c.Topic) (out string) {
|
func topicElementTypeAction(action, elementType string, elementID int, actor *c.User, topic *c.Topic) (out string) {
|
||||||
if action == "delete" {
|
if action == "delete" {
|
||||||
return p.GetTmplPhrasef("panel_logs_mod_action_topic_delete", elementID, actor.Link, actor.Name)
|
return p.GetTmplPhrasef("panel_logs_mod_action_topic_delete", elementID, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ func topicElementTypeAction(action string, elementType string, elementID int, ac
|
||||||
return fmt.Sprintf(out, topic.Link, topic.Title, actor.Link, actor.Name)
|
return fmt.Sprintf(out, topic.Link, topic.Title, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func modlogsElementType(action string, elementType string, elementID int, actor *c.User) (out string) {
|
func modlogsElementType(action, elementType string, elementID int, actor *c.User) (out string) {
|
||||||
switch elementType {
|
switch elementType {
|
||||||
case "topic":
|
case "topic":
|
||||||
topic := handleUnknownTopic(c.Topics.Get(elementID))
|
topic := handleUnknownTopic(c.Topics.Get(elementID))
|
||||||
|
@ -93,6 +93,18 @@ func modlogsElementType(action string, elementType string, elementID int, actor
|
||||||
topic := handleUnknownTopic(c.TopicByReplyID(elementID))
|
topic := handleUnknownTopic(c.TopicByReplyID(elementID))
|
||||||
out = p.GetTmplPhrasef("panel_logs_mod_action_reply_delete", topic.Link, topic.Title, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_mod_action_reply_delete", topic.Link, topic.Title, actor.Link, actor.Name)
|
||||||
}
|
}
|
||||||
|
case "profile-reply":
|
||||||
|
if action == "delete" {
|
||||||
|
// TODO: Optimise this
|
||||||
|
var profile *c.User
|
||||||
|
profileReply, err := c.Prstore.Get(elementID)
|
||||||
|
if err != nil {
|
||||||
|
profile = &c.User{Name: p.GetTmplPhrase("user_unknown"), Link: c.BuildProfileURL("unknown", 0)}
|
||||||
|
} else {
|
||||||
|
profile = handleUnknownUser(c.Users.Get(profileReply.ParentID))
|
||||||
|
}
|
||||||
|
out = p.GetTmplPhrasef("panel_logs_mod_action_profile_reply_delete", profile.Link, profile.Name, actor.Link, actor.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if out == "" {
|
if out == "" {
|
||||||
out = p.GetTmplPhrasef("panel_logs_mod_action_unknown", action, elementType, actor.Link, actor.Name)
|
out = p.GetTmplPhrasef("panel_logs_mod_action_unknown", action, elementType, actor.Link, actor.Name)
|
||||||
|
@ -100,7 +112,7 @@ func modlogsElementType(action string, elementType string, elementID int, actor
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func adminlogsElementType(action string, elementType string, elementID int, actor *c.User, extra string) (out string) {
|
func adminlogsElementType(action, elementType string, elementID int, actor *c.User, extra string) (out string) {
|
||||||
switch elementType {
|
switch elementType {
|
||||||
// TODO: Record more detail for this, e.g. which field/s was changed
|
// TODO: Record more detail for this, e.g. which field/s was changed
|
||||||
case "user":
|
case "user":
|
||||||
|
|
|
@ -28,11 +28,10 @@ func init() {
|
||||||
|
|
||||||
// TODO: Remove the View part of the name?
|
// TODO: Remove the View part of the name?
|
||||||
func ViewProfile(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
func ViewProfile(w http.ResponseWriter, r *http.Request, user c.User, header *c.Header) c.RouteError {
|
||||||
var err error
|
var reCreatedAt time.Time
|
||||||
var replyCreatedAt time.Time
|
var reContent, reCreatedByName, reAvatar string
|
||||||
var replyContent, replyCreatedByName, replyAvatar string
|
var rid, reCreatedBy, reLastEdit, reLastEditBy, reGroup int
|
||||||
var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyGroup int
|
var reList []*c.ReplyUser
|
||||||
var replyList []*c.ReplyUser
|
|
||||||
|
|
||||||
// TODO: Do a 301 if it's the wrong username? Do a canonical too?
|
// TODO: Do a 301 if it's the wrong username? Do a canonical too?
|
||||||
_, pid, err := ParseSEOURL(r.URL.Path[len("/user/"):])
|
_, pid, err := ParseSEOURL(r.URL.Path[len("/user/"):])
|
||||||
|
@ -71,28 +70,24 @@ func ViewProfile(w http.ResponseWriter, r *http.Request, user c.User, header *c.
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &replyGroup)
|
err := rows.Scan(&rid, &reContent, &reCreatedBy, &reCreatedAt, &reLastEdit, &reLastEditBy, &reAvatar, &reCreatedByName, &reGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
replyLiked := false
|
reLiked := false
|
||||||
replyLikeCount := 0
|
reLikeCount := 0
|
||||||
ru := &c.ReplyUser{Reply: c.Reply{rid, puser.ID, replyContent, replyCreatedBy, replyGroup, replyCreatedAt, replyLastEdit, replyLastEditBy, 0, "", replyLiked, replyLikeCount, 0, ""}, ContentHtml: c.ParseMessage(replyContent, 0, "", user.ParseSettings), CreatedByName: replyCreatedByName, Avatar: replyAvatar, Level: 0}
|
ru := &c.ReplyUser{Reply: c.Reply{rid, puser.ID, reContent, reCreatedBy, reGroup, reCreatedAt, reLastEdit, reLastEditBy, 0, "", reLiked, reLikeCount, 0, ""}, ContentHtml: c.ParseMessage(reContent, 0, "", user.ParseSettings, &user), CreatedByName: reCreatedByName, Avatar: reAvatar, Level: 0}
|
||||||
ru.Init()
|
_, err = ru.Init()
|
||||||
|
|
||||||
group, err := c.Groups.Get(ru.Group)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
if group.Tag != "" {
|
if puser.ID == ru.CreatedBy {
|
||||||
ru.Tag = group.Tag
|
|
||||||
} else if puser.ID == ru.CreatedBy {
|
|
||||||
ru.Tag = phrases.GetTmplPhrase("profile.owner_tag")
|
ru.Tag = phrases.GetTmplPhrase("profile.owner_tag")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add a hook here
|
// TODO: Add a hook here
|
||||||
replyList = append(replyList, ru)
|
reList = append(reList, ru)
|
||||||
}
|
}
|
||||||
if err := rows.Err(); err != nil {
|
if err := rows.Err(); err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
|
@ -114,8 +109,8 @@ func ViewProfile(w http.ResponseWriter, r *http.Request, user c.User, header *c.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
canMessage := (!blockedInv && user.Perms.UseConvos) || user.IsSuperMod
|
canMessage := (!blockedInv && user.Perms.UseConvos) || user.IsSuperMod
|
||||||
canComment := !blockedInv && user.Perms.ViewTopic && user.Perms.CreateReply
|
canComment := !blockedInv && user.Perms.CreateProfileReply
|
||||||
|
|
||||||
ppage := c.ProfilePage{header, replyList, *puser, currentScore, nextScore, blocked, canMessage, canComment}
|
ppage := c.ProfilePage{header, reList, *puser, currentScore, nextScore, blocked, canMessage, canComment}
|
||||||
return renderTemplate("profile", w, r, header, ppage)
|
return renderTemplate("profile", w, r, header, ppage)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProfileReplyCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
|
func ProfileReplyCreateSubmit(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError {
|
||||||
if !user.Perms.ViewTopic || !user.Perms.CreateReply {
|
if !user.Perms.CreateProfileReply {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
uid, err := strconv.Atoi(r.PostFormValue("uid"))
|
uid, err := strconv.Atoi(r.PostFormValue("uid"))
|
||||||
|
@ -74,6 +74,9 @@ func ProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, user c.User,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
if !user.Perms.CreateProfileReply {
|
||||||
|
return c.NoPermissionsJSQ(w, r, user, js)
|
||||||
|
}
|
||||||
// ? Does the admin understand that this group perm affects this?
|
// ? Does the admin understand that this group perm affects this?
|
||||||
if user.ID != creator.ID && !user.Perms.EditReply {
|
if user.ID != creator.ID && !user.Perms.EditReply {
|
||||||
return c.NoPermissionsJSQ(w, r, user, js)
|
return c.NoPermissionsJSQ(w, r, user, js)
|
||||||
|
@ -127,5 +130,10 @@ func ProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, user c.Use
|
||||||
} else {
|
} else {
|
||||||
w.Write(successJSONBytes)
|
w.Write(successJSONBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = c.ModLogs.Create("delete", reply.ParentID, "profile-reply", user.GetIP(), user.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user c.User) c.Ro
|
||||||
|
|
||||||
prid, _ := strconv.Atoi(r.FormValue("prid"))
|
prid, _ := strconv.Atoi(r.FormValue("prid"))
|
||||||
if js && (prid == 0 || rids[0] == prid) {
|
if js && (prid == 0 || rids[0] == prid) {
|
||||||
outBytes, err := json.Marshal(JsonReply{c.ParseMessage(reply.Content, topic.ParentID, "forums", user.ParseSettings)})
|
outBytes, err := json.Marshal(JsonReply{c.ParseMessage(reply.Content, topic.ParentID, "forums", user.ParseSettings, &user)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ func ReplyEditSubmit(w http.ResponseWriter, r *http.Request, user c.User, srid s
|
||||||
if !js {
|
if !js {
|
||||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(topic.ID)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther)
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(topic.ID)+"#reply-"+strconv.Itoa(rid), http.StatusSeeOther)
|
||||||
} else {
|
} else {
|
||||||
outBytes, err := json.Marshal(JsonReply{c.ParseMessage(reply.Content, topic.ParentID, "forums", user.ParseSettings)})
|
outBytes, err := json.Marshal(JsonReply{c.ParseMessage(reply.Content, topic.ParentID, "forums", user.ParseSettings, &user)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,14 +72,7 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user c.User, header *c.He
|
||||||
header.Title = topic.Title
|
header.Title = topic.Title
|
||||||
header.Path = c.BuildTopicURL(c.NameToSlug(topic.Title), topic.ID)
|
header.Path = c.BuildTopicURL(c.NameToSlug(topic.Title), topic.ID)
|
||||||
|
|
||||||
// TODO: Cache ContentHTML when possible?
|
|
||||||
topic.ContentHTML = c.ParseMessage(topic.Content, topic.ParentID, "forums", user.ParseSettings)
|
|
||||||
// TODO: Do this more efficiently by avoiding the allocations entirely in ParseMessage, if there's nothing to do.
|
|
||||||
if topic.ContentHTML == topic.Content {
|
|
||||||
topic.ContentHTML = topic.Content
|
|
||||||
}
|
|
||||||
topic.ContentLines = strings.Count(topic.Content, "\n")
|
topic.ContentLines = strings.Count(topic.Content, "\n")
|
||||||
|
|
||||||
if len(topic.Content) > 200 {
|
if len(topic.Content) > 200 {
|
||||||
header.OGDesc = topic.Content[:197] + "..."
|
header.OGDesc = topic.Content[:197] + "..."
|
||||||
} else {
|
} else {
|
||||||
|
@ -90,6 +83,22 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user c.User, header *c.He
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parseSettings *c.ParseSettings
|
||||||
|
if !postGroup.Perms.AutoEmbed && (user.ParseSettings == nil || !user.ParseSettings.NoEmbed) {
|
||||||
|
parseSettings = c.DefaultParseSettings.CopyPtr()
|
||||||
|
parseSettings.NoEmbed = true
|
||||||
|
} else {
|
||||||
|
parseSettings = user.ParseSettings
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Cache ContentHTML when possible?
|
||||||
|
topic.ContentHTML = c.ParseMessage(topic.Content, topic.ParentID, "forums", parseSettings, &user)
|
||||||
|
// TODO: Do this more efficiently by avoiding the allocations entirely in ParseMessage, if there's nothing to do.
|
||||||
|
if topic.ContentHTML == topic.Content {
|
||||||
|
topic.ContentHTML = topic.Content
|
||||||
|
}
|
||||||
|
|
||||||
topic.Tag = postGroup.Tag
|
topic.Tag = postGroup.Tag
|
||||||
if postGroup.IsMod {
|
if postGroup.IsMod {
|
||||||
topic.ClassName = c.Config.StaffCSS
|
topic.ClassName = c.Config.StaffCSS
|
||||||
|
@ -604,7 +613,7 @@ func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user c.User, stid s
|
||||||
if !js {
|
if !js {
|
||||||
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
|
||||||
} else {
|
} else {
|
||||||
outBytes, err := json.Marshal(JsonReply{c.ParseMessage(topic.Content, topic.ParentID, "forums", user.ParseSettings)})
|
outBytes, err := json.Marshal(JsonReply{c.ParseMessage(topic.Content, topic.ParentID, "forums", user.ParseSettings, &user)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalErrorJSQ(err, w, r, js)
|
return c.InternalErrorJSQ(err, w, r, js)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ INSERT INTO [settings] ([name],[content],[type]) VALUES ('rapid_loading','1','bo
|
||||||
INSERT INTO [settings] ([name],[content],[type]) VALUES ('google_site_verify','','html-attribute');
|
INSERT INTO [settings] ([name],[content],[type]) VALUES ('google_site_verify','','html-attribute');
|
||||||
INSERT INTO [themes] ([uname],[default]) VALUES ('cosora',1);
|
INSERT INTO [themes] ([uname],[default]) VALUES ('cosora',1);
|
||||||
INSERT INTO [emails] ([email],[uid],[validated]) VALUES ('admin@localhost',1,1);
|
INSERT INTO [emails] ([email],[uid],[validated]) VALUES ('admin@localhost',1,1);
|
||||||
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,0,'Admin');
|
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,0,'Admin');
|
||||||
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,0,0,'Mod');
|
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,0,0,'Mod');
|
||||||
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}',0,0,0,"");
|
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}',0,0,0,"");
|
||||||
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Banned','{"ViewTopic":true}','{}',0,0,1,"");
|
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Banned','{"ViewTopic":true}','{}',0,0,1,"");
|
||||||
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}',0,0,0,"");
|
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}',0,0,0,"");
|
||||||
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Not Loggedin','{"ViewTopic":true}','{}',0,0,0,'Guest');
|
INSERT INTO [users_groups] ([name],[permissions],[plugin_perms],[is_mod],[is_admin],[is_banned],[tag]) VALUES ('Not Loggedin','{"ViewTopic":true}','{}',0,0,0,'Guest');
|
||||||
|
|
|
@ -15,9 +15,9 @@ INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('rapid_loading','1','boo
|
||||||
INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('google_site_verify','','html-attribute');
|
INSERT INTO `settings`(`name`,`content`,`type`) VALUES ('google_site_verify','','html-attribute');
|
||||||
INSERT INTO `themes`(`uname`,`default`) VALUES ('cosora',1);
|
INSERT INTO `themes`(`uname`,`default`) VALUES ('cosora',1);
|
||||||
INSERT INTO `emails`(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1);
|
INSERT INTO `emails`(`email`,`uid`,`validated`) VALUES ('admin@localhost',1,1);
|
||||||
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,0,'Admin');
|
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,0,'Admin');
|
||||||
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,0,0,'Mod');
|
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,0,0,'Mod');
|
||||||
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}',0,0,0,"");
|
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}',0,0,0,"");
|
||||||
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Banned','{"ViewTopic":true}','{}',0,0,1,"");
|
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Banned','{"ViewTopic":true}','{}',0,0,1,"");
|
||||||
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}',0,0,0,"");
|
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Awaiting Activation','{"ViewTopic":true}','{}',0,0,0,"");
|
||||||
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}',0,0,0,'Guest');
|
INSERT INTO `users_groups`(`name`,`permissions`,`plugin_perms`,`is_mod`,`is_admin`,`is_banned`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}',0,0,0,'Guest');
|
||||||
|
|
|
@ -7,9 +7,9 @@ INSERT INTO "settings"("name","content","type") VALUES ('rapid_loading','1','boo
|
||||||
INSERT INTO "settings"("name","content","type") VALUES ('google_site_verify','','html-attribute');
|
INSERT INTO "settings"("name","content","type") VALUES ('google_site_verify','','html-attribute');
|
||||||
INSERT INTO "themes"("uname","default") VALUES ('cosora',1);
|
INSERT INTO "themes"("uname","default") VALUES ('cosora',1);
|
||||||
INSERT INTO "emails"("email","uid","validated") VALUES ('admin@localhost',1,1);
|
INSERT INTO "emails"("email","uid","validated") VALUES ('admin@localhost',1,1);
|
||||||
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,0,'Admin');
|
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditGroup":true,"EditGroupLocalPerms":true,"EditGroupGlobalPerms":true,"EditGroupSuperMod":true,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewAdminLogs":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,1,0,'Admin');
|
||||||
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,0,0,'Mod');
|
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserGroup":true,"ViewIPs":true,"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true,"MoveTopic":true}','{}',1,0,0,'Mod');
|
||||||
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}',0,0,0,"");
|
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Member','{"UploadFiles":true,"UploadAvatars":true,"UseConvos":true,"CreateProfileReply":true,"AutoEmbed":true,"ViewTopic":true,"LikeItem":true,"CreateTopic":true,"CreateReply":true}','{}',0,0,0,"");
|
||||||
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Banned','{"ViewTopic":true}','{}',0,0,1,"");
|
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Banned','{"ViewTopic":true}','{}',0,0,1,"");
|
||||||
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Awaiting Activation','{"ViewTopic":true}','{}',0,0,0,"");
|
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Awaiting Activation','{"ViewTopic":true}','{}',0,0,0,"");
|
||||||
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Not Loggedin','{"ViewTopic":true}','{}',0,0,0,'Guest');
|
INSERT INTO "users_groups"("name","permissions","plugin_perms","is_mod","is_admin","is_banned","tag") VALUES ('Not Loggedin','{"ViewTopic":true}','{}',0,0,0,'Guest');
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
{{template "panel_before_head.html" . }}
|
{{template "panel_before_head.html" . }}
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><h1>{{.Name}}{{lang "panel_group_head_suffix"}}</h1></div>
|
<div class="rowitem"><h1>{{.Name}}{{lang "panel_group_head_suffix"}} - #{{.ID}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="panel_group" class="colstack_item the_form">
|
<div id="panel_group" class="colstack_item the_form">
|
||||||
<form action="/panel/groups/edit/submit/{{.ID}}?s={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/groups/edit/submit/{{.ID}}?s={{.CurrentUser.Session}}" method="post">
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<main class="colstack_right">
|
<main class="colstack_right">
|
||||||
{{template "panel_before_head.html" . }}
|
{{template "panel_before_head.html" . }}
|
||||||
<div class="colstack_item colstack_head">
|
<div class="colstack_item colstack_head">
|
||||||
<div class="rowitem"><h1>{{.Name}}{{lang "panel_group_head_suffix"}}</h1></div>
|
<div class="rowitem"><h1>{{.Name}}{{lang "panel_group_head_suffix"}} - #{{.ID}}</h1></div>
|
||||||
</div>
|
</div>
|
||||||
<form action="/panel/groups/edit/perms/submit/{{.ID}}?s={{.CurrentUser.Session}}" method="post">
|
<form action="/panel/groups/edit/perms/submit/{{.ID}}?s={{.CurrentUser.Session}}" method="post">
|
||||||
{{if .CurrentUser.Perms.EditGroupLocalPerms}}
|
{{if .CurrentUser.Perms.EditGroupLocalPerms}}
|
||||||
|
@ -50,6 +50,29 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if .CurrentUser.Perms.EditGroupGlobalPerms}}
|
||||||
|
<div class="colstack_item colstack_head">
|
||||||
|
<div class="rowitem"><h1>{{lang "panel_group_mod_permissions"}}</h1></div>
|
||||||
|
</div>
|
||||||
|
<div class="colstack_item rowlist formlist the_form panel_group_perms">
|
||||||
|
{{range .ModPerms}}
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem">
|
||||||
|
<a>{{.LangStr}}</a>
|
||||||
|
<div class="to_right">
|
||||||
|
<select name="perm-{{.Name}}">
|
||||||
|
<option{{if .Toggle}} selected{{end}} value=1>{{lang "option_yes"}}</option>
|
||||||
|
<option{{if not .Toggle}} selected{{end}} value=0>{{lang "option_no"}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><button name="panel-button" class="formbutton form_middle_button">{{lang "panel_group_update_button"}}</button></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue