1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-24 08:46:24 -07:00

(re)add board creation related to issue #51

This commit is contained in:
Eggbertx 2022-01-16 13:30:33 -08:00
parent a0966925cb
commit 9e82333c47
7 changed files with 194 additions and 415 deletions

19
go.sum
View file

@ -34,9 +34,11 @@ github.com/tdewolff/parse v2.3.4+incompatible h1:x05/cnGwIMf4ceLuDMBOdQ1qGniMoxp
github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE=
@ -64,11 +66,15 @@ golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk=
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201009032441-dbdefad45b89 h1:1GKfLldebiSdhTlt3nalwrb7L40Tixr/0IH+kSbRgmk=
golang.org/x/net v0.0.0-20201009032441-dbdefad45b89/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201022231255-08b38378de70 h1:Z6x4N9mAi4oF0TbHweCsH618MO6OI6UFgV0FP5n0wBY=
golang.org/x/net v0.0.0-20201022231255-08b38378de70/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201024042810-be3efd7ff127 h1:pZPp9+iYUqwYKLjht0SDBbRCRK/9gAXDy7pz5fRDpjo=
@ -97,15 +103,19 @@ golang.org/x/net v0.0.0-20210610132358-84b48f89b13b h1:k+E048sYJHyVnsr1GDrRZWQ32
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -116,3 +126,12 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk=
honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=

View file

@ -18,7 +18,9 @@ import (
const GochanVersionKeyConstant = "gochan"
var (
ErrNilBoard = errors.New("Board is nil")
ErrNilBoard = errors.New("board is nil")
ErrBoardExists = errors.New("board already exists")
ErrBoardDoesNotExist = errors.New("board does not exist")
)
// GetAllNondeletedMessageRaw gets all the raw message texts from the database, saved per id
@ -315,8 +317,13 @@ func GetAllAccouncements() ([]Announcement, error) {
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func CreateBoard(values *Board) error {
exists := DoesBoardExistByDir(values.Dir)
if exists {
return ErrBoardExists
}
const maxThreads = 300
const sqlINSERT = `INSERT INTO DBPREFIXboards (navbar_position, dir, uri, title, subtitle, description, max_file_size, max_threads, default_style, locked, anonymous_name, force_anonymous, autosage_after, no_images_after, max_message_length, min_message_length, allow_embeds, redirect_to_thread, require_file, enable_catalog, section_id)
const sqlINSERT = `INSERT INTO DBPREFIXboards (
navbar_position, dir, uri, title, subtitle, description, max_file_size, max_threads, default_style, locked, anonymous_name, force_anonymous, autosage_after, no_images_after, max_message_length, min_message_length, allow_embeds, redirect_to_thread, require_file, enable_catalog, section_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
const sqlSELECT = "SELECT id FROM DBPREFIXboards WHERE dir = ?"
//Excecuted in two steps this way because last row id functions arent thread safe, dir and uri is unique
@ -324,7 +331,12 @@ func CreateBoard(values *Board) error {
if values == nil {
return ErrNilBoard
}
_, err := ExecSQL(sqlINSERT, values.ListOrder, values.Dir, values.Dir, values.Title, values.Subtitle, values.Description, values.MaxFilesize, maxThreads, values.DefaultStyle, values.Locked, values.Anonymous, values.ForcedAnon, values.AutosageAfter, values.NoImagesAfter, values.MaxMessageLength, 1, values.EmbedsAllowed, values.RedirectToThread, values.RequireFile, values.EnableCatalog, values.Section)
_, err := ExecSQL(sqlINSERT,
values.ListOrder, values.Dir, values.Dir, values.Title, values.Subtitle,
values.Description, values.MaxFilesize, maxThreads, values.DefaultStyle,
values.Locked, values.Anonymous, values.ForcedAnon, values.AutosageAfter,
values.NoImagesAfter, values.MaxMessageLength, 1, values.EmbedsAllowed,
values.RedirectToThread, values.RequireFile, values.EnableCatalog, values.Section)
if err != nil {
return err
}
@ -582,7 +594,8 @@ func SinceLastPost(postID int) (int, error) {
if err != nil {
return -1, err
}
return int(time.Now().Sub(when).Seconds()), nil
return int(time.Since(when).Seconds()), nil
}
// InsertPost insersts prepared post object into the SQL table so that it can be rendered
@ -942,12 +955,36 @@ func (board *Board) PopulateData(id int) error {
return QueryRowSQL(sql, interfaceSlice(id), interfaceSlice(&board.ID, &board.Section, &board.Dir, &board.ListOrder, &board.Title, &board.Subtitle, &board.Description, &board.MaxFilesize, &board.DefaultStyle, &board.Locked, &board.CreatedOn, &board.Anonymous, &board.ForcedAnon, &board.AutosageAfter, &board.NoImagesAfter, &board.MaxMessageLength, &board.EmbedsAllowed, &board.RedirectToThread, &board.RequireFile, &board.EnableCatalog))
}
func (board *Board) Delete() error {
exists := DoesBoardExistByID(board.ID)
if !exists {
return errors.New("board does not exist")
}
const delSql = `DELETE FROM DBPREFIXboards WHERE id = ?`
_, err := ExecSQL(delSql, board.ID)
if err != nil {
return err
}
absPath := board.AbsolutePath()
gclog.Printf(gclog.LStaffLog,
"Deleting board /%s/, absolute path: %s\n", board.Dir, absPath)
err = os.RemoveAll(absPath)
return err
}
//DoesBoardExistByID returns a bool indicating whether a board with a given id exists
func DoesBoardExistByID(ID int) (bool, error) {
const sql = `SELECT COUNT(id) FROM DBPREFIXboards WHERE id = ?`
func DoesBoardExistByID(ID int) bool {
const query = `SELECT COUNT(id) FROM DBPREFIXboards WHERE id = ?`
var count int
err := QueryRowSQL(sql, interfaceSlice(ID), interfaceSlice(&count))
return count > 0, err
QueryRowSQL(query, interfaceSlice(ID), interfaceSlice(&count))
return count > 0
}
func DoesBoardExistByDir(dir string) bool {
const query = `SELECT COUNT(dir) FROM DBPREFIXboards WHERE dir = ?`
var count int
QueryRowSQL(query, interfaceSlice(dir), interfaceSlice(&count))
return count > 0
}
//GetAllBoards gets a list of all existing boards

View file

@ -4,6 +4,7 @@ import (
"fmt"
"html"
"html/template"
"net/http"
"path"
"strconv"
"strings"
@ -209,7 +210,7 @@ func (board *Board) SetDefaults(title string, subtitle string, description strin
}
board.Section = 1
board.MaxFilesize = 10000
board.MaxPages = 16
board.MaxPages = 21
board.DefaultStyle = config.GetBoardConfig("").DefaultStyle
board.Locked = false
board.CreatedOn = time.Now()
@ -234,6 +235,43 @@ func (board *Board) SetDefaults(title string, subtitle string, description strin
board.ThreadsPerPage = 20
}
// ChangeFromRequest takes values from a HTTP request
func (board *Board) ChangeFromRequest(request *http.Request) {
board.Dir = request.FormValue("dir")
board.Title = request.FormValue("title")
board.Subtitle = request.FormValue("subtitle")
board.Description = request.FormValue("description")
board.Type, _ = strconv.Atoi(request.FormValue("boardtype"))
board.UploadType, _ = strconv.Atoi(request.FormValue("uploadtype"))
board.Section, _ = strconv.Atoi(request.FormValue("section"))
board.MaxFilesize, _ = strconv.Atoi(request.FormValue("maxfilesize"))
board.MaxPages, _ = strconv.Atoi(request.FormValue("maxpages"))
board.DefaultStyle = request.FormValue("defaultstyle")
board.Locked = len(request.Form["locked"]) > 0
board.Anonymous = request.FormValue("anonname")
board.ForcedAnon = len(request.Form["forcedanon"]) > 0
board.MaxAge, _ = strconv.Atoi(request.FormValue("maxage"))
board.AutosageAfter, _ = strconv.Atoi(request.FormValue("autosageafter"))
board.NoImagesAfter, _ = strconv.Atoi(request.FormValue("nouploadsafter"))
board.MaxMessageLength, _ = strconv.Atoi(request.FormValue("maxmessagelength"))
board.EmbedsAllowed = len(request.Form["embedsallowed"]) > 0
board.RedirectToThread = len(request.Form["redirecttothread"]) > 0
board.ShowID = len(request.Form["showid"]) > 0
board.RequireFile = len(request.Form["requirefile"]) > 0
board.EnableCatalog = len(request.Form["enablecatalog"]) > 0
board.EnableSpoileredImages = len(request.Form["enablefilespoilers"]) > 0
board.EnableSpoileredThreads = len(request.Form["enablethreadspoilers"]) > 0
board.Worksafe = len(request.Form["worksafe"]) > 0
board.Cooldowns.NewThread, _ = strconv.Atoi(request.FormValue("threadcooldown"))
board.Cooldowns.Reply, _ = strconv.Atoi(request.FormValue("replycooldown"))
board.Cooldowns.ImageReply, _ = strconv.Atoi(request.FormValue("imagecooldown"))
board.ThreadsPerPage, _ = strconv.Atoi(request.FormValue("threadsperpage"))
}
func (board *Board) Create() error {
return CreateBoard(board)
}
type BoardSection struct {
ID int
ListOrder int

View file

@ -58,8 +58,8 @@ type Action struct {
// and 3 is only accessible by admins
Permissions int `json:"perms"`
// JSONoutput sets what the action can output. If it is 0, it will throw an error
// if JSON is requested. If it is 1, it can output JSON if requested, and if 2, it always
// JSONoutput sets what the action can output. If it is 0, it will throw an error if
// JSON is requested. If it is 1, it can output JSON if requested, and if 2, it always
// outputs JSON whether it is requested or not
JSONoutput int `json:"jsonOutput"` // if it can sometimes return JSON, this should still be false
@ -249,219 +249,6 @@ var actions = []Action{
outputStr += manageBansBuffer.String()
return outputStr, nil
}},
{
ID: "config",
Title: "Configuration",
Permissions: AdminPerms,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
// do := request.FormValue("do")
// siteCfg := config.GetSiteConfig()
// boardCfg := config.GetBoardConfig("")
// var status string
// if do == "save" {
// configJSON, err := json.MarshalIndent(config.Config, "", "\t")
// if err != nil {
// status += gclog.Println(gclog.LErrorLog, err.Error()) + "<br />"
// } else if err = ioutil.WriteFile("gochan.json", configJSON, 0777); err != nil {
// status += gclog.Println(gclog.LErrorLog,
// "Error backing up old gochan.json, cancelling save:", err.Error())
// } else {
// siteCfg.CookieMaxAge = request.PostFormValue("CookieMaxAge")
// if _, err = gcutil.ParseDurationString(config.Config.CookieMaxAge); err != nil {
// status += err.Error()
// siteCfg.CookieMaxAge = "1y"
// }
// siteCfg.Lockdown = (request.PostFormValue("Lockdown") == "on")
// siteCfg.LockdownMessage = request.PostFormValue("LockdownMessage")
// SillytagsArr := strings.Split(request.PostFormValue("Sillytags"), "\n")
// var Sillytags []string
// for _, tag := range SillytagsArr {
// Sillytags = append(Sillytags, strings.Trim(tag, " \n\r"))
// }
// boardCfg.Sillytags = Sillytags
// boardCfg.UseSillytags = (request.PostFormValue("UseSillytags") == "on")
// siteCfg.Modboard = request.PostFormValue("Modboard")
// siteCfg.SiteName = request.PostFormValue("SiteName")
// siteCfg.SiteSlogan = request.PostFormValue("SiteSlogan")
// // boardCfg.WebRoot = request.PostFormValue("WebRoot")
// // TODO: Change this to match the new Style type in gochan.json
// /* Styles_arr := strings.Split(request.PostFormValue("Styles"), "\n")
// var Styles []string
// for _, style := range Styles_arr {
// Styles = append(Styles, strings.Trim(style, " \n\r"))
// }
// config.Styles = Styles */
// boardCfg.DefaultStyle = request.PostFormValue("DefaultStyle")
// boardCfg.RejectDuplicateImages = (request.PostFormValue("RejectDuplicateImages") == "on")
// NewThreadDelay, err := strconv.Atoi(request.PostFormValue("NewThreadDelay"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.NewThreadDelay = NewThreadDelay
// }
// ReplyDelay, err := strconv.Atoi(request.PostFormValue("ReplyDelay"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ReplyDelay = ReplyDelay
// }
// MaxLineLength, err := strconv.Atoi(request.PostFormValue("MaxLineLength"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.MaxLineLength = MaxLineLength
// }
// ReservedTripsArr := strings.Split(request.PostFormValue("ReservedTrips"), "\n")
// var ReservedTrips []string
// for _, trip := range ReservedTripsArr {
// ReservedTrips = append(ReservedTrips, strings.Trim(trip, " \n\r"))
// }
// boardCfg.ReservedTrips = ReservedTrips
// ThumbWidth, err := strconv.Atoi(request.PostFormValue("ThumbWidth"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ThumbWidth = ThumbWidth
// }
// ThumbHeight, err := strconv.Atoi(request.PostFormValue("ThumbHeight"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ThumbHeight = ThumbHeight
// }
// ThumbWidthReply, err := strconv.Atoi(request.PostFormValue("ThumbWidthReply"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ThumbWidthReply = ThumbWidthReply
// }
// ThumbHeightReply, err := strconv.Atoi(request.PostFormValue("ThumbHeightReply"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ThumbHeightReply = ThumbHeightReply
// }
// ThumbWidthCatalog, err := strconv.Atoi(request.PostFormValue("ThumbWidthCatalog"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ThumbWidthCatalog = ThumbWidthCatalog
// }
// ThumbHeightCatalog, err := strconv.Atoi(request.PostFormValue("ThumbHeightCatalog"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.ThumbHeightCatalog = ThumbHeightCatalog
// }
// RepliesOnBoardPage, err := strconv.Atoi(request.PostFormValue("RepliesOnBoardPage"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.RepliesOnBoardPage = RepliesOnBoardPage
// }
// StickyRepliesOnBoardPage, err := strconv.Atoi(request.PostFormValue("StickyRepliesOnBoardPage"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.StickyRepliesOnBoardPage = StickyRepliesOnBoardPage
// }
// boardCfg.BanMessage = request.PostFormValue("BanMessage")
// EmbedWidth, err := strconv.Atoi(request.PostFormValue("EmbedWidth"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.EmbedWidth = EmbedWidth
// }
// EmbedHeight, err := strconv.Atoi(request.PostFormValue("EmbedHeight"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.EmbedHeight = EmbedHeight
// }
// boardCfg.EnableEmbeds = (request.PostFormValue("EnableEmbeds") == "on")
// boardCfg.ImagesOpenNewTab = (request.PostFormValue("ImagesOpenNewTab") == "on")
// boardCfg.NewTabOnOutlinks = (request.PostFormValue("NewTabOnOutlinks") == "on")
// boardCfg.DateTimeFormat = request.PostFormValue("DateTimeFormat")
// siteCfg.MinifyHTML = (request.PostFormValue("MinifyHTML") == "on")
// siteCfg.MinifyJS = (request.PostFormValue("MinifyJS") == "on")
// AkismetAPIKey := request.PostFormValue("AkismetAPIKey")
// if err = serverutil.CheckAkismetAPIKey(AkismetAPIKey); err != nil {
// status += err.Error() + "<br />"
// } else {
// siteCfg.AkismetAPIKey = AkismetAPIKey
// }
// boardCfg.UseCaptcha = (request.PostFormValue("UseCaptcha") == "on")
// CaptchaWidth, err := strconv.Atoi(request.PostFormValue("CaptchaWidth"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.CaptchaWidth = CaptchaWidth
// }
// CaptchaHeight, err := strconv.Atoi(request.PostFormValue("CaptchaHeight"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// boardCfg.CaptchaHeight = CaptchaHeight
// }
// boardCfg.EnableGeoIP = (request.PostFormValue("EnableGeoIP") == "on")
// siteCfg.GeoIPDBlocation = request.PostFormValue("GeoIPDBlocation")
// MaxRecentPosts, err := strconv.Atoi(request.PostFormValue("MaxRecentPosts"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// siteCfg.MaxRecentPosts = MaxRecentPosts
// }
// MaxLogDays, err := strconv.Atoi(request.PostFormValue("MaxLogDays"))
// if err != nil {
// status += err.Error() + "<br />"
// } else {
// siteCfg.MaxLogDays = MaxLogDays
// }
// if err = config.WriteConfig(); err != nil {
// status = gclog.Print(gclog.LErrorLog, "Error writing gochan.json: ", err.Error()) + "<br />"
// } else {
// status = "Wrote gochan.json successfully<br />"
// }
// }
// }
// manageConfigBuffer := bytes.NewBufferString("")
// if err = serverutil.MinifyTemplate(gctemplates.ManageConfig,
// map[string]interface{}{
// "siteCfg": siteCfg,
// "boardCfg": boardCfg,
// "status": status,
// },
// manageConfigBuffer, "text/html"); err != nil {
// return "", errors.New(gclog.Print(gclog.LErrorLog,
// "Error executing config management page: ", err.Error()))
// }
// output += manageConfigBuffer.String()
// return output, nil
errStr := "web-based configuration tool has been temporarily disabled"
return errStr, errors.New(errStr)
}},
{
ID: "staff",
Title: "Staff",
@ -580,10 +367,53 @@ var actions = []Action{
ID: "boards",
Title: "Boards",
Permissions: AdminPerms,
JSONoutput: NoJSON,
Callback: func(writer http.ResponseWriter, request *http.Request, wantsJSON bool) (output interface{}, err error) {
pageBuffer := bytes.NewBufferString("")
tmpBoard := gcsql.Board{}
tmpBoard.SetDefaults("", "", "")
var board gcsql.Board
requestType, boardID, err := boardsRequestType(request)
if err != nil {
return "", err
}
if requestType == "cancel" || requestType == "" {
board.SetDefaults("", "", "")
}
switch requestType {
case "create":
// create button clicked, create the board with the request fields
board.ChangeFromRequest(request)
err = board.Create()
case "delete":
// delete button clicked, delete the board
if board, err = gcsql.GetBoardFromID(boardID); err != nil {
return "", err
}
err = board.Delete()
case "edit":
// edit button clicked, fill the input fields with board data to be edited
board, err = gcsql.GetBoardFromID(boardID)
if err != nil {
return "", err
}
case "modify":
// save changes button clicked, apply changes to the board based on the request fields
board, err = gcsql.GetBoardFromID(boardID)
if err != nil {
return "", err
}
board.ChangeFromRequest(request)
case "cancel":
// cancel button was clicked
fallthrough
case "":
fallthrough
default:
board.SetDefaults("", "", "")
}
if err != nil {
return "", err
}
if err = serverutil.MinifyTemplate(gctemplates.ManageBoards,
map[string]interface{}{
"webroot": config.GetSystemCriticalConfig().WebRoot,
@ -591,8 +421,8 @@ var actions = []Action{
"sections": gcsql.AllSections,
"boards": gcsql.AllBoards,
"board_config": config.GetBoardConfig(""),
"editing": true,
"board": tmpBoard,
"editing": requestType == "edit",
"board": board,
}, pageBuffer, "text/html"); err != nil {
gclog.Printf(gclog.LErrorLog|gclog.LStaffLog,
"Error executing manage boards template: %q", err.Error())
@ -600,170 +430,6 @@ var actions = []Action{
}
return pageBuffer.String(), nil
/* var outputStr string
do := request.FormValue("do")
var done bool
board := new(gcsql.Board)
var boardCreationStatus string
systemCritical := config.GetSystemCriticalConfig()
for !done {
switch {
case do == "add":
board.Dir = request.FormValue("dir")
if board.Dir == "" {
boardCreationStatus = `Error: "Directory" cannot be blank`
do = ""
continue
}
orderStr := request.FormValue("order")
if board.ListOrder, err = strconv.Atoi(orderStr); err != nil {
board.ListOrder = 0
}
board.Title = request.FormValue("title")
if board.Title == "" {
boardCreationStatus = `Error: "Title" cannot be blank`
do = ""
continue
}
board.Subtitle = request.FormValue("subtitle")
board.Description = request.FormValue("description")
sectionStr := request.FormValue("section")
if sectionStr == "none" {
sectionStr = "0"
}
board.CreatedOn = time.Now()
board.Section, err = strconv.Atoi(sectionStr)
if err != nil {
board.Section = 0
}
board.MaxFilesize, err = strconv.Atoi(request.FormValue("maximagesize"))
if err != nil {
board.MaxFilesize = 1024 * 4
}
board.MaxPages, err = strconv.Atoi(request.FormValue("maxpages"))
if err != nil {
board.MaxPages = 11
}
board.DefaultStyle = strings.Trim(request.FormValue("defaultstyle"), "\n")
board.Locked = (request.FormValue("locked") == "on")
board.ForcedAnon = (request.FormValue("forcedanon") == "on")
board.Anonymous = request.FormValue("anonymous")
if board.Anonymous == "" {
board.Anonymous = "Anonymous"
}
board.MaxAge, err = strconv.Atoi(request.FormValue("maxage"))
if err != nil {
board.MaxAge = 0
}
board.AutosageAfter, err = strconv.Atoi(request.FormValue("autosageafter"))
if err != nil {
board.AutosageAfter = 200
}
board.NoImagesAfter, err = strconv.Atoi(request.FormValue("noimagesafter"))
if err != nil {
board.NoImagesAfter = 0
}
board.MaxMessageLength, err = strconv.Atoi(request.FormValue("maxmessagelength"))
if err != nil {
board.MaxMessageLength = 1024 * 8
}
board.EmbedsAllowed = (request.FormValue("embedsallowed") == "on")
board.RedirectToThread = (request.FormValue("redirecttothread") == "on")
board.RequireFile = (request.FormValue("require_file") == "on")
board.EnableCatalog = (request.FormValue("enablecatalog") == "on")
//actually start generating stuff
if err = os.Mkdir(path.Join(systemCritical.DocumentRoot, board.Dir), 0666); err != nil {
do = ""
boardCreationStatus = gclog.Printf(gclog.LStaffLog|gclog.LErrorLog, "Directory %s/%s/ already exists.",
systemCritical.DocumentRoot, board.Dir)
break
}
if err = os.Mkdir(path.Join(systemCritical.DocumentRoot, board.Dir, "res"), 0666); err != nil {
do = ""
boardCreationStatus = gclog.Printf(gclog.LStaffLog|gclog.LErrorLog, "Directory %s/%s/res/ already exists.",
systemCritical.DocumentRoot, board.Dir)
break
}
if err = os.Mkdir(path.Join(systemCritical.DocumentRoot, board.Dir, "src"), 0666); err != nil {
do = ""
boardCreationStatus = gclog.Printf(gclog.LStaffLog|gclog.LErrorLog, "Directory %s/%s/src/ already exists.",
systemCritical.DocumentRoot, board.Dir)
break
}
if err = os.Mkdir(path.Join(systemCritical.DocumentRoot, board.Dir, "thumb"), 0666); err != nil {
do = ""
boardCreationStatus = gclog.Printf(gclog.LStaffLog|gclog.LErrorLog, "Directory %s/%s/thumb/ already exists.",
systemCritical.DocumentRoot, board.Dir)
break
}
if err = gcsql.CreateBoard(board); err != nil {
do = ""
boardCreationStatus = gclog.Print(gclog.LErrorLog, "Error creating board: ", err.Error())
break
}
boardCreationStatus = "Board created successfully"
building.BuildBoards(false)
gcsql.ResetBoardSectionArrays()
gclog.Print(gclog.LStaffLog, "Boards rebuilt successfully")
done = true
case do == "del":
// resetBoardSectionArrays()
case do == "edit":
// resetBoardSectionArrays()
default:
boardConfig := config.GetBoardConfig("")
// put the default column values in the text boxes
board.Section = 1
board.MaxFilesize = 4718592
board.MaxPages = 11
board.DefaultStyle = "pipes.css"
board.Anonymous = "Anonymous"
board.AutosageAfter = 200
board.MaxMessageLength = 8192
board.EmbedsAllowed = true
board.EnableCatalog = true
board.Worksafe = true
board.ThreadsPerPage = boardConfig.ThreadsPerPage
}
output = `<h1 class="manage-header">Manage boards</h1><form action="/manage?action=boards" method="POST"><input type="hidden" name="do" value="existing" /><select name="boardselect"><option>Select board...</option>`
var boards []string
boards, err = gcsql.GetBoardUris()
if err != nil {
err = errors.New(gclog.Print(gclog.LErrorLog,
"Error getting board list: ", err.Error()))
return "", err
}
for _, boardDir := range boards {
outputStr += "<option>" + boardDir + "</option>"
}
outputStr += `</select><input type="submit" value="Edit" /><input type="submit" value="Delete" /></form><hr />` +
`<h2 class="manage-header">Create new board</h2><span id="board-creation-message">` + boardCreationStatus + `</span><br />`
manageBoardsBuffer := bytes.NewBufferString("")
gcsql.AllSections, _ = gcsql.GetAllSectionsOrCreateDefault()
return outputStr + manageBoardsBuffer.String(), nil
}
gcsql.ResetBoardSectionArrays() */
return
}},
{
ID: "rebuildfront",

View file

@ -3,6 +3,7 @@ package manage
import (
"bytes"
"net/http"
"strconv"
"time"
"github.com/gochan-org/gochan/pkg/config"
@ -97,7 +98,7 @@ func GetStaffRank(request *http.Request) int {
// returns the action by its ID, or nil if it doesn't exist
func getAction(id string, rank int) *Action {
for a, _ := range actions {
for a := range actions {
if rank == NoPerms && actions[a].Permissions > NoPerms {
id = "login"
}
@ -165,3 +166,27 @@ func getStaffActions(writer http.ResponseWriter, request *http.Request, wantsJSO
availableActions := getAvailableActions(rank, false)
return availableActions, nil
}
// bordsRequestType takes the request and returns "cancel", "create", "delete",
// "edit", or "modify" and the board's ID according to the request
func boardsRequestType(request *http.Request) (string, int, error) {
var requestType string
var boardID int
var err error
if request.FormValue("docancel") != "" {
requestType = "cancel"
} else if request.FormValue("docreate") != "" {
requestType = "create"
} else if request.FormValue("dodelete") != "" {
requestType = "delete"
} else if request.FormValue("doedit") != "" {
requestType = "edit"
} else if request.FormValue("domodify") != "" {
requestType = "modify"
}
boardIDstr := request.FormValue("board")
if boardIDstr != "" {
boardID, err = strconv.Atoi(boardIDstr)
}
return requestType, boardID, err
}

View file

@ -224,12 +224,8 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
}
post.Filename = getNewFilename() + "." + ext
boardExists, err := gcsql.DoesBoardExistByID(
boardExists := gcsql.DoesBoardExistByID(
gcutil.HackyStringToInt(request.FormValue("boardid")))
if err != nil {
serverutil.ServeErrorPage(writer, "Server error: "+err.Error())
return
}
if !boardExists {
serverutil.ServeErrorPage(writer, "No boards have been created yet")
return

View file

@ -1,20 +1,19 @@
<h2>Manage Boards</h2>
<form action="{{$.webroot}}manage?action=boards" method="GET">
<input type="hidden" name="action" value="boards">
<input type="hidden" name="do" value="select">
{{with $.boards}}{{else}}
<input type="hidden" name="noboards" value="1">
{{end}}
{{/* <input type="hidden" name="confirm" value="1"> */}}
<select name="board" id="modifyboard">
{{range $_, $board := $.boards}}
<option value="{{$board.Dir}}">/{{$board.Dir}}/ - {{$board.Title}}</option>
<option value="{{$board.ID}}">/{{$board.Dir}}/ - {{$board.Title}}</option>
{{else}}
<option value="" selected="true" disabled="disabled">No boards</option>
{{end}}
</select><br>
<input type="submit" name="editsubmit" value="Edit" >
<input type="submit" name="delsubmit" value="Delete" onclick="return confirm('Are you sure you want to delete this board? This cannot be undone.');"><br>
<input type="submit" name="doedit" value="Edit" >
<input type="submit" name="dodelete" value="Delete" onclick="return confirm('Are you sure you want to delete this board? This cannot be undone.');"><br>
</form>
<hr />
{{if $.editing}}
@ -24,11 +23,6 @@
{{end}}
<form action="{{$.webroot}}manage?action=boards" method="GET">
<input type="hidden" name="action" value="boards">
{{if $.editing}}
<input type="hidden" name="do" value="edit">
{{else}}
<input type="hidden" name="do" value="create">
{{end}}
<table>
<tr>
@ -77,7 +71,7 @@
</tr>
<tr>
<td>Max number of pages</td>
<td><input type="number" min="0" name="numpages" value="{{$.board.MaxPages}}"></td>
<td><input type="number" min="0" name="maxpages" value="{{$.board.MaxPages}}"></td>
</tr>
<tr>
<td>Default style</td>
@ -99,7 +93,7 @@
</tr>
<tr>
<td>Forced anonymous</td>
<td><input type="checkbox" name="locked" {{- if $.board.ForcedAnon}}checked="checked"{{end}}/></td>
<td><input type="checkbox" name="forcedanon" {{- if $.board.ForcedAnon}}checked="checked"{{end}}/></td>
</tr>
<tr>
<td>Max age</td>
@ -111,7 +105,7 @@
</tr>
<tr>
<td>Don't allow uploads after # replies</td>
<td><input type="number" min="0" name="noimagesafter" value="{{$.board.NoImagesAfter}}"></td>
<td><input type="number" min="0" name="nouploadsafter" value="{{$.board.NoImagesAfter}}"></td>
</tr>
<tr>
<td>Max message length (in characters)</td>
@ -144,12 +138,12 @@
</tr>
<tr>
<td>Allow file spoilers</td>
<td><input type="checkbox" name="enablespoileredimages" {{if $.board.EnableSpoileredImages}}checked="checked"{{end}}/>
<td><input type="checkbox" name="enablefilespoilers" {{if $.board.EnableSpoileredImages}}checked="checked"{{end}}/>
</td>
</tr>
<tr>
<td>Enable spoilered threads</td>
<td><input type="checkbox" name="enablespoileredthreads" {{if $.board.ForcedAnon}}checked="checked"{{end}}/>
<td><input type="checkbox" name="enablethreadspoilers" {{if $.board.ForcedAnon}}checked="checked"{{end}}/>
</td>
</tr>
<tr>
@ -174,7 +168,11 @@
<td><input type="number" min="0" name="threadsperpage" value="{{$.board.ThreadsPerPage}}"></td>
</tr>
</table>
<input type="submit" name="submitchanges" value="
{{- if $.editing}}Save changes{{else}}Create new board
{{- end}}" onclick="return confirm('Click ok to confirm')"/></form>
{{- if $.editing -}}
<input type="submit" name="domodify" value="Save changes" onclick="return confirm('Click ok to confirm')"/>
<input type="submit" name="docancel" value="Cancel" onclick="window.location = './manage?action=boards'; return false"/>
{{- else -}}
<input type="submit" name="docreate" value="Create new board" onclick="return confirm('Click ok to confirm')"/>
{{- end -}}
</form>