1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-09-05 11:06:23 -07:00

Replace IP field of IPBan with RangeStart and RangeEnd

This commit is contained in:
Eggbertx 2023-12-28 23:06:44 -08:00
parent 04c892bba8
commit 57693ba549
16 changed files with 178 additions and 100 deletions

View file

@ -13,7 +13,7 @@ import (
const (
// if the database version is less than this, it is assumed to be out of date, and the schema needs to be adjusted
latestDatabaseVersion = 2
latestDatabaseVersion = 3
)
type GCDatabaseUpdater struct {
@ -94,7 +94,7 @@ func (dbu *GCDatabaseUpdater) MigrateDB() (bool, error) {
}
if numColumns == 0 {
query = `ALTER TABLE DBPREFIXwordfilters ADD COLUMN board_dirs varchar(255) DEFAULT '*'`
if _, err = gcsql.ExecTxSQL(tx, query); err != nil {
if _, err = dbu.db.ExecTxSQL(tx, query); err != nil {
return false, err
}
}
@ -137,9 +137,9 @@ func (dbu *GCDatabaseUpdater) MigrateDB() (bool, error) {
if numColumns > 0 {
// add range_start and range_end columns
query = `ALTER TABLE DBPREFIXip_ban
ADD COLUMN IF NOT EXISTS range_start VARBINARY(16) NOT NULL
ADD COLUMN IF NOT EXISTS range_start VARBINARY(16) NOT NULL,
ADD COLUMN IF NOT EXISTS range_end VARBINARY(16) NOT NULL`
if _, err = gcsql.ExecTxSQL(tx, query); err != nil {
if _, err = dbu.db.ExecTxSQL(tx, query); err != nil {
return false, err
}
// convert string to IP range
@ -157,12 +157,13 @@ func (dbu *GCDatabaseUpdater) MigrateDB() (bool, error) {
if rangeStart, rangeEnd, err = gcutil.ParseIPRange(ipOrCIDR); err != nil {
return false, err
}
query = `UPDATE DBPREFIXip_ban SET range_start = INET6_ATON(?), range_end = ? WHERE id = ?`
if _, err = gcsql.ExecTxSQL(tx, query, rangeStart, rangeEnd, id); err != nil {
query = `UPDATE DBPREFIXip_ban
SET range_start = INET6_ATON(?), range_end = INET6_ATON(?) WHERE id = ?`
if _, err = dbu.db.ExecTxSQL(tx, query, rangeStart, rangeEnd, id); err != nil {
return false, err
}
query = `ALTER TABLE DBPREFIXip_ban DROP COLUMN ip`
if _, err = gcsql.ExecTxSQL(tx, query); err != nil {
if _, err = dbu.db.ExecTxSQL(tx, query); err != nil {
return false, err
}
}
@ -178,7 +179,7 @@ func (dbu *GCDatabaseUpdater) MigrateDB() (bool, error) {
return false, err
}
case "sqlite3":
_, err = gcsql.ExecSQL(`PRAGMA foreign_keys = ON`)
_, err = dbu.db.ExecSQL(`PRAGMA foreign_keys = ON`)
if err != nil {
return false, err
}

View file

@ -19,7 +19,8 @@ macros = [
"BIGINT NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY",
"INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL"),
macro("fk to serial", "BIGINT", "BIGINT", "BIGINT"),
macro("drop fk", "DROP CONSTRAINT", "DROP FOREIGN KEY", "DROP CONSTRAINT")
macro("drop fk", "DROP CONSTRAINT", "DROP FOREIGN KEY", "DROP CONSTRAINT"),
macro("inet", "INET", "VARBINARY(16)", "VARCHAR(45)")
]

View file

@ -5,13 +5,15 @@ import (
"errors"
"regexp"
"strconv"
"github.com/gochan-org/gochan/pkg/config"
)
const (
ipBanQueryBase = `SELECT
id, staff_id, board_id, banned_for_post_id, copy_post_text, is_thread_ban,
is_active, ip, issued_at, appeal_at, expires_at, permanent, staff_note,
message, can_appeal
is_active, INET_START, INET_END, issued_at, appeal_at, expires_at,
permanent, staff_note, message, can_appeal
FROM DBPREFIXip_ban`
)
@ -26,9 +28,10 @@ type Ban interface {
func NewIPBan(ban *IPBan) error {
const query = `INSERT INTO DBPREFIXip_ban
(staff_id, board_id, banned_for_post_id, copy_post_text, is_thread_ban, is_active, ip,
appeal_at, expires_at, permanent, staff_note, message, can_appeal)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
(staff_id, board_id, banned_for_post_id, copy_post_text, is_thread_ban,
is_active, INET_RANGE_START, INET_RANGE_END, appeal_at, expires_at,
permanent, staff_note, message, can_appeal)
VALUES(?, ?, ?, ?, ?, ?, INET_PARAM, INET_PARAM, ?, ?, ?, ?, ?, ?)`
if ban.ID > 0 {
return ErrBanAlreadyInserted
}
@ -43,8 +46,9 @@ func NewIPBan(ban *IPBan) error {
}
defer stmt.Close()
if _, err = stmt.Exec(
ban.StaffID, ban.BoardID, ban.BannedForPostID, ban.CopyPostText, ban.IsThreadBan, ban.IsActive, ban.IP,
ban.AppealAt, ban.ExpiresAt, ban.Permanent, ban.StaffNote, ban.Message, ban.CanAppeal,
ban.StaffID, ban.BoardID, ban.BannedForPostID, ban.CopyPostText,
ban.IsThreadBan, ban.IsActive, ban.RangeStart, ban.RangeEnd, ban.AppealAt,
ban.ExpiresAt, ban.Permanent, ban.StaffNote, ban.Message, ban.CanAppeal,
); err != nil {
return err
}
@ -55,17 +59,26 @@ func NewIPBan(ban *IPBan) error {
return tx.Commit()
}
// CheckIPBan returns the latest active IP ban for the given IP, as well as any errors. If the
// IPBan pointer is nil, the IP has no active bans
// CheckIPBan returns the latest active IP ban for the given IP, as well as any
// errors. If the IPBan pointer is nil, the IP has no active bans. Because
// SQLite 3 does not support a native IP type, range bans are not supported if
// DBtype == "sqlite3"
func CheckIPBan(ip string, boardID int) (*IPBan, error) {
const query = ipBanQueryBase + ` WHERE ip = ? AND (board_id IS NULL OR board_id = ?) AND
is_active AND (expires_at > CURRENT_TIMESTAMP OR permanent)
query := ipBanQueryBase + " WHERE "
if config.GetSystemCriticalConfig().DBtype == "sqlite3" {
query += "INET_RANGE_START = ? OR INET_RANGE_END = ?"
} else {
query += "INET_RANGE_START <= INET_PARAM AND INET_PARAM <= INET_RANGE_END"
}
query += ` AND (board_id IS NULL OR board_id = ?) AND is_active AND
(expires_at > CURRENT_TIMESTAMP OR permanent)
ORDER BY id DESC LIMIT 1`
var ban IPBan
err := QueryRowSQL(query, interfaceSlice(ip, boardID), interfaceSlice(
&ban.ID, &ban.StaffID, &ban.BoardID, &ban.BannedForPostID, &ban.CopyPostText, &ban.IsThreadBan,
&ban.IsActive, &ban.IP, &ban.IssuedAt, &ban.AppealAt, &ban.ExpiresAt, &ban.Permanent, &ban.StaffNote,
&ban.Message, &ban.CanAppeal))
&ban.ID, &ban.StaffID, &ban.BoardID, &ban.BannedForPostID, &ban.CopyPostText,
&ban.IsThreadBan, &ban.IsActive, &ban.RangeStart, &ban.RangeEnd, &ban.IssuedAt,
&ban.AppealAt, &ban.ExpiresAt, &ban.Permanent, &ban.StaffNote, &ban.Message,
&ban.CanAppeal))
if err == sql.ErrNoRows {
return nil, nil
}
@ -76,9 +89,10 @@ func GetIPBanByID(id int) (*IPBan, error) {
const query = ipBanQueryBase + " WHERE id = ?"
var ban IPBan
err := QueryRowSQL(query, interfaceSlice(id), interfaceSlice(
&ban.ID, &ban.StaffID, &ban.BoardID, &ban.BannedForPostID, &ban.CopyPostText, &ban.IsThreadBan,
&ban.IsActive, &ban.IP, &ban.IssuedAt, &ban.AppealAt, &ban.ExpiresAt, &ban.Permanent, &ban.StaffNote,
&ban.Message, &ban.CanAppeal))
&ban.ID, &ban.StaffID, &ban.BoardID, &ban.BannedForPostID, &ban.CopyPostText,
&ban.IsThreadBan, &ban.IsActive, &ban.RangeStart, &ban.RangeEnd, &ban.IssuedAt,
&ban.AppealAt, &ban.ExpiresAt, &ban.Permanent, &ban.StaffNote, &ban.Message,
&ban.CanAppeal))
if err != nil {
return nil, err
}
@ -106,8 +120,8 @@ func GetIPBans(boardID int, limit int, onlyActive bool) ([]IPBan, error) {
var ban IPBan
if err = rows.Scan(
&ban.ID, &ban.StaffID, &ban.BoardID, &ban.BannedForPostID, &ban.CopyPostText, &ban.IsThreadBan,
&ban.IsActive, &ban.IP, &ban.IssuedAt, &ban.AppealAt, &ban.ExpiresAt, &ban.Permanent, &ban.StaffNote,
&ban.Message, &ban.CanAppeal,
&ban.IsActive, &ban.RangeStart, &ban.RangeEnd, &ban.IssuedAt, &ban.AppealAt, &ban.ExpiresAt,
&ban.Permanent, &ban.StaffNote, &ban.Message, &ban.CanAppeal,
); err != nil {
rows.Close()
return nil, err
@ -199,7 +213,9 @@ func CheckNameBan(name string, boardID int) (*UsernameBan, error) {
}
func NewNameBan(name string, isRegex bool, boardID int, staffID int, staffNote string) (*UsernameBan, error) {
const query = `INSERT INTO DBPREFIXusername_ban (board_id, staff_id, staff_note, username, is_regex) VALUES(?,?,?,?,?)`
const query = `INSERT INTO DBPREFIXusername_ban
(board_id, staff_id, staff_note, username, is_regex)
VALUES(?,?,?,?,?)`
var ban UsernameBan
if boardID > 0 {
ban.BoardID = new(int)
@ -234,7 +250,9 @@ func NewNameBan(name string, isRegex bool, boardID int, staffID int, staffNote s
}
func GetNameBans(boardID int, limit int) ([]UsernameBan, error) {
query := `SELECT id, board_id, staff_id, staff_note, issued_at, username, is_regex FROM DBPREFIXusername_ban`
query := `SELECT
id, board_id, staff_id, staff_note, issued_at, username, is_regex
FROM DBPREFIXusername_ban`
limitStr := ""
if limit > 0 {
limitStr = " LIMIT " + strconv.Itoa(limit)
@ -446,7 +464,8 @@ func GetChecksumBans(boardID int, limit int) ([]FileBan, error) {
}
func NewFileChecksumBan(checksum string, boardID int, staffID int, staffNote string) (*FileBan, error) {
const query = `INSERT INTO DBPREFIXfile_ban (board_id, staff_id, staff_note, checksum) VALUES(?,?,?,?)`
const query = `INSERT INTO DBPREFIXfile_ban
(board_id, staff_id, staff_note, checksum) VALUES(?,?,?,?)`
var ban FileBan
var err error

View file

@ -195,10 +195,23 @@ func (db *GCDB) QuerySQL(query string, a ...interface{}) (*sql.Rows, error) {
func Open(host, dbDriver, dbName, username, password, prefix string) (db *GCDB, err error) {
db = &GCDB{
driver: dbDriver,
replacer: strings.NewReplacer(
}
if dbDriver == "mysql" {
db.replacer = strings.NewReplacer(
"DBNAME", dbName,
"DBPREFIX", prefix,
"\n", " "),
"INET_RANGE_START", "INET6_ATON(range_start)",
"INET_RANGE_END", "INET6_ATON(range_end)",
"INET_PARAM", "INET6_ATON(?)",
"\n", " ")
} else {
db.replacer = strings.NewReplacer(
"DBNAME", dbName,
"DBPREFIX", prefix,
"INET_RANGE_START", "range_start",
"INET_RANGE_END", "range_end",
"INET_PARAM", "?",
"\n", " ")
}
if dbDriver != "sqlite3" {

View file

@ -1,8 +1,12 @@
package gcsql
import (
"errors"
"html/template"
"net"
"time"
"github.com/gochan-org/gochan/pkg/gcutil"
)
// table: DBPREFIXannouncements
@ -113,13 +117,24 @@ type IPBan struct {
BoardID *int
BannedForPostID *int
CopyPostText template.HTML
IP string
IPRangeStart string
IPRangeEnd string
RangeStart string
RangeEnd string
IssuedAt time.Time
ipBanBase
}
func (ipb *IPBan) IsBanned(ipStr string) (bool, error) {
ipn, err := gcutil.GetIPRangeSubnet(ipb.RangeStart, ipb.RangeEnd)
if err != nil {
return false, err
}
ip := net.ParseIP(ipStr)
if ip == nil {
return false, errors.New("invalid IP address")
}
return ipn.Contains(ip), nil
}
// table: DBPREFIXip_ban_audit
type IPBanAudit struct {
IPBanID int // sql: `ip_ban_id`

View file

@ -179,7 +179,14 @@ var funcMap = template.FuncMap{
if err != nil || ban == nil {
return "?"
}
return ban.IP
if ban.RangeStart == ban.RangeEnd {
return ban.RangeStart
}
ipn, err := gcutil.GetIPRangeSubnet(ban.RangeStart, ban.RangeEnd)
if err != nil {
return "?"
}
return ipn.String()
},
"getCatalogThumbnail": func(img string) string {
_, catalogThumb := uploads.GetThumbnailFilenames(img)

View file

@ -192,22 +192,19 @@ func ParseIPRange(ipOrCIDR string) (string, string, error) {
return ipStart.String(), ipStart.String(), nil
}
// GetIPRangeString returns an IP address if start == end, or the subnet of all IP
// addresses between start and end
func GetIPRangeString(start string, end string) (string, error) {
if start == end {
return start, nil
}
// GetIPRangeSubnet returns the smallest subnet that contains the start and end
// IP addresses, and any errors that occured
func GetIPRangeSubnet(start string, end string) (*net.IPNet, error) {
startIP := net.ParseIP(start)
endIP := net.ParseIP(end)
if startIP == nil {
return "", fmt.Errorf("invalid IP address %s", start)
return nil, fmt.Errorf("invalid IP address %s", start)
}
if endIP == nil {
return "", fmt.Errorf("invalid IP address %s", end)
return nil, fmt.Errorf("invalid IP address %s", end)
}
if len(startIP) != len(endIP) {
return "", errors.New("ip addresses must both be IPv4 or IPv6")
return nil, errors.New("ip addresses must both be IPv4 or IPv6")
}
if startIP.To4() != nil {
@ -216,7 +213,7 @@ func GetIPRangeString(start string, end string) (string, error) {
}
bits := 0
var ipn net.IPNet
var ipn *net.IPNet
for b := range startIP {
if startIP[b] == endIP[b] {
bits += 8
@ -227,12 +224,11 @@ func GetIPRangeString(start string, end string) (string, error) {
bits++
continue
}
ipn = net.IPNet{IP: startIP, Mask: net.CIDRMask(bits, len(startIP)*8)}
return ipn.String(), nil
ipn = &net.IPNet{IP: startIP, Mask: net.CIDRMask(bits, len(startIP)*8)}
return ipn, nil
}
}
ipn = net.IPNet{IP: startIP, Mask: net.CIDRMask(bits, len(startIP)*8)}
return ipn.String(), nil
return &net.IPNet{IP: startIP, Mask: net.CIDRMask(bits, len(startIP)*8)}, nil
}
// ParseName takes a name string from a request object and returns the name and tripcode parts

View file

@ -50,21 +50,19 @@ func registerModeratorPages() {
}
} else if request.FormValue("do") == "add" {
gcutil.LogStr("banIP", ban.IP, infoEv, errEv)
gcutil.LogStr("reason", ban.Message, infoEv, errEv)
if ban.Permanent {
gcutil.LogBool("permanent", true, infoEv, errEv)
} else {
gcutil.LogTime("expiresAt", ban.ExpiresAt)
}
gcutil.LogBool("appealable", ban.CanAppeal, infoEv, errEv)
if ban.CanAppeal {
gcutil.LogTime("appealAt", ban.AppealAt)
}
err := ipBanFromRequest(&ban, request, errEv)
ip := request.PostFormValue("ip")
ban.RangeStart, ban.RangeEnd, err = gcutil.ParseIPRange(ip)
if err != nil {
errEv.Err(err).Caller().
Msg("Unable to create new ban")
Str("ip", ip)
return "", err
}
gcutil.LogStr("rangeStart", ban.RangeStart, infoEv, errEv)
gcutil.LogStr("rangeEnd", ban.RangeEnd, infoEv, errEv)
gcutil.LogStr("reason", ban.Message, infoEv, errEv)
gcutil.LogBool("appealable", ban.CanAppeal, infoEv, errEv)
err := ipBanFromRequest(&ban, request, infoEv, errEv)
if err != nil {
return "", err
}
infoEv.Msg("Added IP ban")
@ -74,11 +72,12 @@ func registerModeratorPages() {
errEv.Err(err).Caller().Send()
return "", err
}
if ban.IP, err = gcsql.GetPostIP(postID); err != nil {
if ban.RangeStart, err = gcsql.GetPostIP(postID); err != nil {
errEv.Err(err).Caller().
Int("postID", postID).Send()
return "", err
}
ban.RangeEnd = ban.RangeStart
}
filterBoardIDstr := request.FormValue("filterboardid")

View file

@ -9,31 +9,39 @@ import (
"github.com/Eggbertx/durationutil"
"github.com/gochan-org/gochan/pkg/gcsql"
"github.com/gochan-org/gochan/pkg/gcutil"
"github.com/rs/zerolog"
)
func ipBanFromRequest(ban *gcsql.IPBan, request *http.Request, errEv *zerolog.Event) error {
func ipBanFromRequest(ban *gcsql.IPBan, request *http.Request, infoEv *zerolog.Event, errEv *zerolog.Event) error {
now := time.Now()
banIDStr := request.FormValue("edit")
if banIDStr != "" && request.FormValue("do") == "edit" {
banID, err := strconv.Atoi(banIDStr)
if err != nil {
errEv.Err(err).
Str("editBanID", banIDStr).
Caller().Send()
errEv.Err(err).Caller().
Str("editBanID", banIDStr).Send()
return errors.New("invalid 'edit' field value (must be int)")
}
editing, err := gcsql.GetIPBanByID(banID)
if err != nil {
errEv.Err(err).
Int("editBanID", banID).
Caller().Send()
errEv.Err(err).Caller().
Int("editBanID", banID).Send()
return errors.New("Unable to get ban with id " + banIDStr + " (SQL error)")
}
*ban = *editing
return nil
}
ban.IP = request.FormValue("ip")
var err error
ip := request.PostFormValue("ip")
ban.RangeStart, ban.RangeEnd, err = gcutil.ParseIPRange(ip)
if err != nil {
errEv.Err(err).Caller().
Str("ip", ip)
}
gcutil.LogStr("rangeStart", ban.RangeStart, infoEv, errEv)
gcutil.LogStr("rangeEnd", ban.RangeEnd, infoEv, errEv)
ban.Permanent = request.FormValue("permanent") == "on"
if ban.Permanent {
ban.ExpiresAt = now
@ -55,9 +63,9 @@ func ipBanFromRequest(ban *gcsql.IPBan, request *http.Request, errEv *zerolog.Ev
if appealWaitStr != "" {
appealDuration, err := durationutil.ParseLongerDuration(appealWaitStr)
if err != nil {
errEv.Err(err).
errEv.Err(err).Caller().
Str("appealwait", appealWaitStr).
Caller().Msg("Invalid appeal delay duration string")
Msg("Invalid appeal delay duration string")
return err
}
ban.AppealAt = now.Add(appealDuration)
@ -73,16 +81,18 @@ func ipBanFromRequest(ban *gcsql.IPBan, request *http.Request, errEv *zerolog.Ev
if boardIDstr != "" && boardIDstr != "0" {
boardID, err := strconv.Atoi(boardIDstr)
if err != nil {
errEv.Err(err).
Str("boardid", boardIDstr).
Caller().Send()
errEv.Err(err).Caller().
Str("boardid", boardIDstr).Send()
return err
}
gcutil.LogInt("boardID", boardID, infoEv, errEv)
ban.BoardID = new(int)
*ban.BoardID = boardID
}
ban.Message = html.EscapeString(request.FormValue("reason"))
ban.StaffNote = html.EscapeString(request.FormValue("staffnote"))
ban.IsActive = true
gcutil.LogStr("banMessage", request.FormValue("reason"), infoEv, errEv)
gcutil.LogStr("staffNote", request.FormValue("staffnote"), infoEv, errEv)
return gcsql.NewIPBan(ban)
}

View file

@ -8,6 +8,7 @@ import (
"github.com/Eggbertx/durationutil"
"github.com/gochan-org/gochan/pkg/gcplugin/luautil"
"github.com/gochan-org/gochan/pkg/gcsql"
"github.com/gochan-org/gochan/pkg/gcutil"
"github.com/rs/zerolog"
lua "github.com/yuin/gopher-lua"
luar "layeh.com/gopher-luar"
@ -18,15 +19,20 @@ const (
)
func luaBanIP(l *lua.LState) int {
ban := &gcsql.IPBan{
IP: l.CheckString(1),
ban := &gcsql.IPBan{}
ip := l.CheckString(1)
var err error
ban.RangeStart, ban.RangeEnd, err = gcutil.ParseIPRange(ip)
if err != nil {
l.Push(luar.New(l, err))
return 1
}
ban.IsActive = true
ban.AppealAt = time.Now()
ban.CanAppeal = true
durOrNil := l.CheckAny(2)
var err error
switch durOrNil.Type() {
case lua.LTNil:
ban.Permanent = true

View file

@ -94,7 +94,7 @@ func checkUsernameBan(post *gcsql.Post, postBoard *gcsql.Board, writer http.Resp
return true
}
func handleAppeal(writer http.ResponseWriter, request *http.Request, errEv *zerolog.Event) {
func handleAppeal(writer http.ResponseWriter, request *http.Request, infoEv *zerolog.Event, errEv *zerolog.Event) {
banIDstr := request.FormValue("banid")
if banIDstr == "" {
errEv.Caller().Msg("Appeal sent without banid field")
@ -114,7 +114,8 @@ func handleAppeal(writer http.ResponseWriter, request *http.Request, errEv *zero
server.ServeErrorPage(writer, fmt.Sprintf("Invalid banid value %q", banIDstr))
return
}
errEv.Int("banID", banID)
gcutil.LogInt("banID", banID, infoEv, errEv)
ban, err := gcsql.GetIPBanByID(banID)
if err != nil {
errEv.Err(err).
@ -124,14 +125,21 @@ func handleAppeal(writer http.ResponseWriter, request *http.Request, errEv *zero
}
if ban == nil {
errEv.Caller().Msg("GetIPBanByID returned a nil ban (presumably not banned)")
server.ServeErrorPage(writer, fmt.Sprintf("Invalid banid %d", banID))
server.ServeErrorPage(writer, fmt.Sprintf("Invalid ban ID %d", banID))
return
}
if ban.IP != gcutil.GetRealIP(request) {
gcutil.LogStr("rangeStart", ban.RangeStart, infoEv, errEv)
gcutil.LogStr("rangeEnd", ban.RangeEnd, infoEv, errEv)
isCorrectIP, err := ban.IsBanned(gcutil.GetRealIP(request))
if err != nil {
errEv.Err(err).Caller().Send()
server.ServeErrorPage(writer, err.Error())
}
if !isCorrectIP {
errEv.Caller().
Str("banIP", ban.IP).
Msg("User tried to appeal a ban from a different IP")
server.ServeErrorPage(writer, fmt.Sprintf("Invalid banid %d", banID))
server.ServeErrorPage(writer, fmt.Sprintf("Invalid ban id", banID))
return
}
if !ban.IsActive {
@ -157,10 +165,6 @@ func handleAppeal(writer http.ResponseWriter, request *http.Request, errEv *zero
return
}
board := request.FormValue("board")
gcutil.LogInfo().
Str("IP", gcutil.GetRealIP(request)).
Int("banID", banID).
Str("board", board).
Msg("Appeal submitted")
infoEv.Str("board", board).Msg("Appeal submitted")
http.Redirect(writer, request, config.WebPath(request.FormValue("board")), http.StatusFound)
}

View file

@ -68,7 +68,7 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
}
if request.FormValue("doappeal") != "" {
handleAppeal(writer, request, errEv)
handleAppeal(writer, request, infoEv, errEv)
return
}

View file

@ -146,8 +146,8 @@ CREATE TABLE DBPREFIXip_ban(
copy_post_text TEXT NOT NULL,
is_thread_ban BOOL NOT NULL,
is_active BOOL NOT NULL,
range_start VARBINARY(16) NOT NULL,
range_end VARBINARY(16) NOT NULL,
range_start {inet} NOT NULL,
range_end {inet} NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
appeal_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -146,8 +146,8 @@ CREATE TABLE DBPREFIXip_ban(
copy_post_text TEXT NOT NULL,
is_thread_ban BOOL NOT NULL,
is_active BOOL NOT NULL,
range_start VARBINARY(16) NOT NULL,
range_end VARBINARY(16) NOT NULL,
range_start INET NOT NULL,
range_end INET NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
appeal_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -146,8 +146,8 @@ CREATE TABLE DBPREFIXip_ban(
copy_post_text TEXT NOT NULL,
is_thread_ban BOOL NOT NULL,
is_active BOOL NOT NULL,
range_start VARBINARY(16) NOT NULL,
range_end VARBINARY(16) NOT NULL,
range_start VARCHAR(45) NOT NULL,
range_end VARCHAR(45) NOT NULL,
issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
appeal_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View file

@ -1,7 +1,14 @@
<table border="1">
<tr><th>Action</th><th>Appeal Text</th><th>Banned IP</th></tr>
{{range $_,$appeal := $.appeals}}
<tr><td><a href="{{webPath "manage/appeals"}}?approve={{$appeal.ID}}">Approve</a> | <a href="{{webPath "manage/appeals"}}?deny={{$appeal.ID}}">Deny</a></td><td>{{$appeal.AppealText}}</td><td>{{getAppealBanIP $appeal.IPBanID}}</td></tr>
<tr>
<td>
<a href="{{webPath "manage/appeals"}}?approve={{$appeal.ID}}">Approve</a> |
<a href="{{webPath "manage/appeals"}}?deny={{$appeal.ID}}">Deny</a>
</td>
<td>{{$appeal.AppealText}}</td>
<td>{{getAppealBanIP $appeal.IPBanID}}</td>
</tr>
<tr></tr>
{{end}}
</table>