ffdc9e7705
WordFilters.Create now returns the ID. Add the WordFilters.Get method. Reduce the boilerplate in the backup page and page store. Sanitise the names and titles in the Page Manager. Add page_unknown phrase. Add setting_unknown phrase. Add panel_logs_administration_action_page_create phrase. Add panel_logs_administration_action_page_delete phrase. Add panel_logs_administration_action_page_edit phrase. Add panel_logs_administration_action_setting_edit phrase. Add panel_logs_administration_action_word_filter_create phrase. Add panel_logs_administration_action_word_filter_delete phrase. Add panel_logs_administration_action_word_filter_edit phrase. Add panel_logs_administration_action_backup_download phrase.
176 lines
4.6 KiB
Go
176 lines
4.6 KiB
Go
package common
|
|
|
|
import (
|
|
"database/sql"
|
|
"strconv"
|
|
"strings"
|
|
|
|
qgen "github.com/Azareal/Gosora/query_gen"
|
|
)
|
|
|
|
type CustomPageStmts struct {
|
|
update *sql.Stmt
|
|
create *sql.Stmt
|
|
}
|
|
|
|
var customPageStmts CustomPageStmts
|
|
|
|
func init() {
|
|
DbInits.Add(func(acc *qgen.Accumulator) error {
|
|
customPageStmts = CustomPageStmts{
|
|
update: acc.Update("pages").Set("name = ?, title = ?, body = ?, allowedGroups = ?, menuID = ?").Where("pid = ?").Prepare(),
|
|
create: acc.Insert("pages").Columns("name, title, body, allowedGroups, menuID").Fields("?,?,?,?,?").Prepare(),
|
|
}
|
|
return acc.FirstError()
|
|
})
|
|
}
|
|
|
|
type CustomPage struct {
|
|
ID int
|
|
Name string // TODO: Let admins put pages in "virtual subdirectories"
|
|
Title string
|
|
Body string
|
|
AllowedGroups []int
|
|
MenuID int
|
|
}
|
|
|
|
func BlankCustomPage() *CustomPage {
|
|
return new(CustomPage)
|
|
}
|
|
|
|
func (p *CustomPage) AddAllowedGroup(gid int) {
|
|
p.AllowedGroups = append(p.AllowedGroups, gid)
|
|
}
|
|
|
|
func (p *CustomPage) getRawAllowedGroups() (rawAllowedGroups string) {
|
|
for _, group := range p.AllowedGroups {
|
|
rawAllowedGroups += strconv.Itoa(group) + ","
|
|
}
|
|
if len(rawAllowedGroups) > 0 {
|
|
rawAllowedGroups = rawAllowedGroups[:len(rawAllowedGroups)-1]
|
|
}
|
|
return rawAllowedGroups
|
|
}
|
|
|
|
func (p *CustomPage) Commit() error {
|
|
_, err := customPageStmts.update.Exec(p.Name, p.Title, p.Body, p.getRawAllowedGroups(), p.MenuID, p.ID)
|
|
Pages.Reload(p.ID)
|
|
return err
|
|
}
|
|
|
|
func (p *CustomPage) Create() (int, error) {
|
|
res, err := customPageStmts.create.Exec(p.Name, p.Title, p.Body, p.getRawAllowedGroups(), p.MenuID)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
pid64, err := res.LastInsertId()
|
|
return int(pid64), err
|
|
}
|
|
|
|
var Pages PageStore
|
|
|
|
// Holds the custom pages, but doesn't include the template pages in /pages/ which are a lot more flexible yet harder to use and which are too risky security-wise to make editable in the Control Panel
|
|
type PageStore interface {
|
|
Count() (count int)
|
|
Get(id int) (*CustomPage, error)
|
|
GetByName(name string) (*CustomPage, error)
|
|
GetOffset(offset int, perPage int) (pages []*CustomPage, err error)
|
|
Reload(id int) error
|
|
Delete(id int) error
|
|
}
|
|
|
|
// TODO: Add a cache to this to save on the queries
|
|
type DefaultPageStore struct {
|
|
get *sql.Stmt
|
|
getByName *sql.Stmt
|
|
getOffset *sql.Stmt
|
|
count *sql.Stmt
|
|
delete *sql.Stmt
|
|
}
|
|
|
|
func NewDefaultPageStore(acc *qgen.Accumulator) (*DefaultPageStore, error) {
|
|
pa := "pages"
|
|
return &DefaultPageStore{
|
|
get: acc.Select(pa).Columns("name, title, body, allowedGroups, menuID").Where("pid = ?").Prepare(),
|
|
getByName: acc.Select(pa).Columns("pid, name, title, body, allowedGroups, menuID").Where("name = ?").Prepare(),
|
|
getOffset: acc.Select(pa).Columns("pid, name, title, body, allowedGroups, menuID").Orderby("pid DESC").Limit("?,?").Prepare(),
|
|
count: acc.Count(pa).Prepare(),
|
|
delete: acc.Delete(pa).Where("pid = ?").Prepare(),
|
|
}, acc.FirstError()
|
|
}
|
|
|
|
func (s *DefaultPageStore) Count() (count int) {
|
|
err := s.count.QueryRow().Scan(&count)
|
|
if err != nil {
|
|
LogError(err)
|
|
}
|
|
return count
|
|
}
|
|
|
|
func (s *DefaultPageStore) parseAllowedGroups(raw string, page *CustomPage) error {
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
for _, sgroup := range strings.Split(raw, ",") {
|
|
group, err := strconv.Atoi(sgroup)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
page.AddAllowedGroup(group)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *DefaultPageStore) Get(id int) (*CustomPage, error) {
|
|
p := &CustomPage{ID: id}
|
|
rawAllowedGroups := ""
|
|
err := s.get.QueryRow(id).Scan(&p.Name, &p.Title, &p.Body, &rawAllowedGroups, &p.MenuID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return p, s.parseAllowedGroups(rawAllowedGroups, p)
|
|
}
|
|
|
|
func (s *DefaultPageStore) GetByName(name string) (*CustomPage, error) {
|
|
p := BlankCustomPage()
|
|
rawAllowedGroups := ""
|
|
err := s.getByName.QueryRow(name).Scan(&p.ID, &p.Name, &p.Title, &p.Body, &rawAllowedGroups, &p.MenuID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return p, s.parseAllowedGroups(rawAllowedGroups, p)
|
|
}
|
|
|
|
func (s *DefaultPageStore) GetOffset(offset int, perPage int) (pages []*CustomPage, err error) {
|
|
rows, err := s.getOffset.Query(offset, perPage)
|
|
if err != nil {
|
|
return pages, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
p := &CustomPage{ID: 0}
|
|
rawAllowedGroups := ""
|
|
err := rows.Scan(&p.ID, &p.Name, &p.Title, &p.Body, &rawAllowedGroups, &p.MenuID)
|
|
if err != nil {
|
|
return pages, err
|
|
}
|
|
err = s.parseAllowedGroups(rawAllowedGroups, p)
|
|
if err != nil {
|
|
return pages, err
|
|
}
|
|
pages = append(pages, p)
|
|
}
|
|
return pages, rows.Err()
|
|
}
|
|
|
|
// Always returns nil as there's currently no cache
|
|
func (s *DefaultPageStore) Reload(id int) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *DefaultPageStore) Delete(id int) error {
|
|
_, err := s.delete.Exec(id)
|
|
return err
|
|
}
|