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

Add filename and username banning, add more de-deprecation stuff to posting/post.go

This commit is contained in:
Eggbertx 2022-11-07 12:56:51 -08:00
parent b69536b772
commit 379e846daf
10 changed files with 531 additions and 405 deletions

View file

@ -1,18 +1,26 @@
package gcsql
import "database/sql"
import (
"database/sql"
"regexp"
)
type Ban interface {
IsGlobalBan() bool
}
// 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
func CheckIPBan(ip string) (*IPBan, error) {
func CheckIPBan(ip string, boardID int) (*IPBan, error) {
const query = `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
FROM DBPREFIXip_ban WHERE ip = ? AND is_active AND (expires_at > CURRENT_TIMESTAMP OR permanent)
FROM DBPREFIXip_ban WHERE ip = ? 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), interfaceSlice(
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))
@ -23,6 +31,70 @@ func CheckIPBan(ip string) (*IPBan, error) {
}
// IsGlobalBan returns true if BoardID is a nil int, meaning they are banned on all boards, as opposed to a specific one
func (ipb *IPBan) IsGlobalBan() bool {
func (ipb IPBan) IsGlobalBan() bool {
return ipb.BoardID == nil
}
func checkUsernameOrFilename(usernameFilename string, check string, boardID int) (*filenameOrUsernameBanBase, error) {
query := `SELECT
id, board_id, staff_id, staff_note, issued_at, ` + usernameFilename + `, is_regex
FROM DBPREFIX` + usernameFilename + `_ban WHERE (` + usernameFilename + ` = ? OR is_regex) AND (board_id IS NULL OR board_id = ?)`
rows, err := QuerySQL(query, check, boardID)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var ban filenameOrUsernameBanBase
err = rows.Scan(&ban.ID, &ban.BoardID, &ban.StaffID, &ban.StaffNote, &ban.IssuedAt, &ban.check, &ban.IsRegex)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
return nil, err
}
if ban.IsRegex {
match, err := regexp.MatchString(ban.check, check)
if err != nil {
return nil, err
}
if match {
return &ban, nil
}
} else if ban.check == check {
return &ban, nil
}
}
return nil, nil
}
func CheckNameBan(name string, boardID int) (*UsernameBan, error) {
banBase, err := checkUsernameOrFilename("username", name, boardID)
if err != nil {
return nil, err
}
if banBase == nil {
return nil, nil
}
return &UsernameBan{
Username: banBase.check,
filenameOrUsernameBanBase: *banBase,
}, nil
}
func (ub filenameOrUsernameBanBase) IsGlobalBan() bool {
return ub.BoardID == nil
}
func CheckFilenameBan(filename string, boardID int) (*FilenameBan, error) {
banBase, err := checkUsernameOrFilename("filename", filename, boardID)
if err != nil {
return nil, err
}
if banBase == nil {
return nil, nil
}
return &FilenameBan{
Filename: banBase.check,
filenameOrUsernameBanBase: *banBase,
}, nil
}

View file

@ -4,6 +4,7 @@ import (
"database/sql"
"errors"
"fmt"
"html"
"html/template"
"time"
@ -231,6 +232,18 @@ func (p *Post) GetUpload() (*Upload, error) {
return upload, err
}
// Sanitize escapes HTML strings in a post. This should be run immediately before
// the post is inserted into the database
func (p *Post) Sanitize() {
if !p.sanitized {
p.Name = html.EscapeString(p.Name)
p.Email = html.EscapeString(p.Email)
p.Subject = html.EscapeString(p.Subject)
p.Password = html.EscapeString(p.Password)
p.sanitized = true
}
}
// UnlinkUploads disassociates the post with any uploads in DBPREFIXfiles
// that may have been uploaded with it, optionally leaving behind a "File Deleted"
// frame where the thumbnail appeared

View file

@ -60,16 +60,22 @@ type FileBan struct {
Checksum string `json:"checksum"` // sql: `checksum`
}
type filenameOrUsernameBanBase struct {
ID int // sql: id
BoardID *int // sql: board_id
StaffID int // sql: staff_id
StaffNote string // sql: staff_note
IssuedAt time.Time // sql: issued_at
check string // replaced with username or filename
IsRegex bool // sql: is_regex
}
// FilenameBan represents a ban on a specific filename or filename regular expression.
// table: DBPREFIXfilename_ban
type FilenameBan struct {
ID int `json:"id"` // sql: `id`
BoardID int `json:"board_id"` // sql: `board_id`
StaffID int `json:"staff_id"` // sql: `staff_id`
StaffNote string `json:"staff_note"` // sql: `staff_note`
IssuedAt time.Time `json:"issued_at"` // sql: `issued_at`
Filename string `json:"filename"` // sql: `filename`
IsRegex bool `json:"is_regex"` // sql: `is_regex`
filenameOrUsernameBanBase
Filename string // sql: `filename`
IsRegex bool // sql: `is_regex`
}
// Upload represents a file attached to a post.
@ -161,6 +167,8 @@ type Post struct {
DeletedAt time.Time // sql: `deleted_at`
IsDeleted bool // sql: `is_deleted`
BannedMessage string // sql: `banned_message`
sanitized bool
}
// table: DBPREFIXreports
@ -224,13 +232,8 @@ type Thread struct {
// table: DBPREFIXusername_ban
type UsernameBan struct {
ID int `json:"id"` // sql: `id`
BoardID *int `json:"board"` // sql: `board_id`
StaffID int `json:"staff_id"` // sql: `staff_id`
StaffNote string `json:"staff_note"` // sql: `staff_note`
IssuedAt time.Time `json:"issued_at"` // sql: `issued_at`
Username string `json:"username"` // sql: `username`
IsRegex bool `json:"is_regex"` // sql: `is_regex`
filenameOrUsernameBanBase
Username string // sql: `username`
}
// table DBPREFIXwordfilters

View file

@ -1,6 +1,8 @@
package gcsql
import (
"errors"
"github.com/gochan-org/gochan/pkg/gcsql.bak"
"github.com/gochan-org/gochan/pkg/gcutil"
)
@ -12,10 +14,9 @@ const (
FROM DBPREFIXfiles `
)
// ThumbnailPath returns the thumbnail path of the upload, given an thumbnail type ("thumbnail" or "catalog")
func (u *Upload) ThumbnailPath(thumbType string) string {
return gcutil.GetThumbnailPath(thumbType, u.Filename)
}
var (
ErrAlreadyAttached = errors.New("upload already processed")
)
// GetThreadFiles gets a list of the files owned by posts in the thread, including thumbnails for convenience.
func GetThreadFiles(post *Post) ([]Upload, error) {
@ -40,3 +41,30 @@ func GetThreadFiles(post *Post) ([]Upload, error) {
}
return uploads, nil
}
func (p *Post) AttachFile(upload *Upload) error {
const query = `INSERT INTO DBPREFIXfiles (
post_id, file_order, original_filename, filename, checksum, file_size,
is_spoilered, thumbnail_width, thumbnail_height, width, height)
VALUES(?,?,?,?,?,?,?,?,?,?,?)`
if upload.ID > 0 {
return ErrAlreadyAttached
}
uploadID, err := getNextFreeID("DBPREFIXfiles")
if err != nil {
return err
}
if _, err = ExecSQL(query,
&upload.PostID, &upload.FileOrder, &upload.OriginalFilename, &upload.Filename, &upload.Checksum, &upload.FileSize,
&upload.IsSpoilered, &upload.ThumbnailWidth, &upload.ThumbnailHeight, &upload.Width, &upload.Height,
); err != nil {
return err
}
upload.ID = uploadID
return nil
}
// ThumbnailPath returns the thumbnail path of the upload, given an thumbnail type ("thumbnail" or "catalog")
func (u *Upload) ThumbnailPath(thumbType string) string {
return gcutil.GetThumbnailPath(thumbType, u.Filename)
}