1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-02 10:56:25 -07:00

Add filter enabling/disabling

This commit is contained in:
Eggbertx 2024-08-11 00:40:45 -07:00
parent e3a4efd9c0
commit fa56d500b8
5 changed files with 147 additions and 30 deletions

View file

@ -25,8 +25,12 @@ h1, h2 {
table.mgmt-table {
margin-top: 4px;
width: 100%;
td.table-actions {
td.table-actions,col.row-actions,col.row-staff {
text-align: center;
width: 7%;
}
col.row-date {
width: 20%;
}
th {
padding: 4px;

View file

@ -324,8 +324,12 @@ table.mgmt-table {
margin-top: 4px;
width: 100%;
}
table.mgmt-table td.table-actions {
table.mgmt-table td.table-actions, table.mgmt-table col.row-actions, table.mgmt-table col.row-staff {
text-align: center;
width: 7%;
}
table.mgmt-table col.row-date {
width: 20%;
}
table.mgmt-table th {
padding: 4px;

View file

@ -5,26 +5,43 @@ import (
"errors"
)
const (
AllFilters ShowFilters = iota
OnlyActiveFilters
OnlyInactiveFilters
)
var (
ErrInvalidConditionField = errors.New("unrecognized conditional field")
ErrInvalidMatchAction = errors.New("unrecognized filter action")
ErrInvalidFilter = errors.New("unrecognized filter id")
)
type ShowFilters int
func GetFilterByID(id int) (*Filter, error) {
var filter Filter
err := QueryRowTimeoutSQL(nil,
`SELECT id, staff_id, staff_note, issued_at, match_action, match_detail, is_active FROM DBPREFIXfilters WHERE id = ?`,
[]any{id}, []any{&filter.ID, &filter.StaffID, &filter.StaffNote, &filter.IssuedAt, &filter.MatchAction, &filter.MatchDetail, &filter.IsActive},
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrInvalidFilter
} else if err != nil {
return nil, err
}
return &filter, nil
}
// GetAllFilters returns an array of all post filters, and an error if one occured
func GetAllFilters() ([]Filter, error) {
// GetAllFilters returns an array of all post filters, and an error if one occured. It can optionally return only the active or
// only the inactive filters (or return all)
func GetAllFilters(show ShowFilters) ([]Filter, error) {
query := `SELECT id, staff_id, staff_note, issued_at, match_action, match_detail, is_active FROM DBPREFIXfilters`
if show == OnlyActiveFilters {
query += " WHERE is_active = TRUE"
} else if show == OnlyInactiveFilters {
query += " WHERE is_active = FALSE"
}
rows, cancel, err := QueryTimeoutSQL(nil, query)
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
@ -133,7 +150,9 @@ func (f *Filter) BoardDirs() ([]string, error) {
func (f *Filter) BoardIDs() ([]int, error) {
rows, cancel, err := QueryTimeoutSQL(nil, `SELECT board_id FROM DBPREFIXfilter_boards WHERE filter_id = ?`, f.ID)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
} else if err != nil {
return nil, err
}
defer func() {
@ -150,3 +169,14 @@ func (f *Filter) BoardIDs() ([]int, error) {
}
return ids, nil
}
// SetFilterActive updates the filter with the given id, setting its active status and returning an error if one occured
func SetFilterActive(id int, active bool) error {
_, err := ExecTimeoutSQL(nil, `UPDATE DBPREFIXfilters SET is_active = ? WHERE id = ?`, active, id)
return err
}
func DeleteFilter(id int) error {
_, err := ExecTimeoutSQL(nil, `DELETE FROM DBPREFIXfilters WHERE id = ?`, id)
return err
}

View file

@ -9,6 +9,7 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
"github.com/gochan-org/gochan/pkg/building"
"github.com/gochan-org/gochan/pkg/config"
@ -36,10 +37,15 @@ var (
{Value: "hasfile", Text: "Has file"},
{Value: "nofile", Text: "No file"},
{Value: "filename", Text: "Filename"},
{Value: "filechecksum", Text: "File checksum"},
{Value: "imgfingerprint", Text: "Image fingerprint"},
{Value: "checksum", Text: "File checksum"},
{Value: "ahash", Text: "Image fingerprint"},
{Value: "useragent", Text: "User agent"},
}
filterActionsMap = map[string]string{
"reject": "Reject post",
"ban": "Ban IP",
"log": "Log match",
}
)
func bansCallback(_ http.ResponseWriter, request *http.Request, staff *gcsql.Staff, _ bool, infoEv *zerolog.Event, errEv *zerolog.Event) (output interface{}, err error) {
@ -354,12 +360,82 @@ func filtersCallback(_ http.ResponseWriter, request *http.Request, staff *gcsql.
// doFilterAdd = request.PostFormValue("dofilteradd")
// filterID := request.FormValue("filterid")
// editFilter := request.FormValue("editfilter")
// delFilter := request.FormValue("delfilter")
disableFilterIDStr := request.FormValue("disable")
enableFilterIDStr := request.FormValue("enable")
if disableFilterIDStr != "" {
disableFilterID, err := strconv.Atoi(disableFilterIDStr)
if err != nil {
return nil, err
}
gcsql.SetFilterActive(disableFilterID, false)
} else if enableFilterIDStr != "" {
enableFilterID, err := strconv.Atoi(enableFilterIDStr)
if err != nil {
return nil, err
}
gcsql.SetFilterActive(enableFilterID, true)
}
showStr := request.FormValue("show")
var show gcsql.ShowFilters
switch showStr {
case "active":
show = gcsql.OnlyActiveFilters
case "inactive":
show = gcsql.OnlyInactiveFilters
default:
show = gcsql.AllFilters
}
filters, err := gcsql.GetAllFilters(show)
if err != nil {
errEv.Err(err).Caller().Msg("Unable to get filter list")
return nil, err
}
fieldsMap := make(map[string]string)
for _, ff := range filterFields {
fieldsMap[ff.Value] = ff.Text
}
var staffUsernames []string
var conditionsText []string
for _, filter := range filters {
if _, ok := filterActionsMap[filter.MatchAction]; !ok {
return nil, gcsql.ErrInvalidMatchAction
}
conditions, err := filter.Conditions()
if err != nil {
errEv.Err(err).Caller().Int("filterID", filter.ID).Msg("Unable to get filter conditions")
return nil, err
}
var filterConditionsText string
for _, condition := range conditions {
text, ok := fieldsMap[condition.Field]
if !ok {
return nil, gcsql.ErrInvalidConditionField
}
filterConditionsText += text + ","
}
filterConditionsText = strings.TrimRight(filterConditionsText, ",")
conditionsText = append(conditionsText, filterConditionsText)
username, err := gcsql.GetStaffUsernameFromID(*filter.StaffID)
if err != nil {
return nil, err
}
staffUsernames = append(staffUsernames, username)
}
var buf bytes.Buffer
if err = serverutil.MinifyTemplate(gctemplates.ManageFilters, map[string]any{
"allBoards": gcsql.AllBoards,
"fields": filterFields,
"allBoards": gcsql.AllBoards,
"fields": filterFields,
"filters": filters,
"conditions": conditionsText,
"actions": filterActionsMap,
"staff": staffUsernames,
"show": showStr,
}, &buf, "text/html"); err != nil {
errEv.Err(err).Caller().Str("template", gctemplates.ManageFilters).Send()
return "", errors.New("Unable to execute filter management template: " + err.Error())

View file

@ -66,34 +66,37 @@
</form>
<hr/>
<h2>Filter list</h2>
<form action="{{webPath `/manage/filters`}}" method="GET">
<select name="show" id="">
<option value="all" {{if or (eq $.show `all`) (eq $.show ``)}}selected{{end}}>All filters</option>
<option value="active" {{if eq $.show `active`}}selected{{end}}>Only active</option>
<option value="inactive" {{if eq $.show `inactive`}}selected{{end}}>Only inactive</option>
</select>
<input type="submit" value="Show">
</form>
</form>
<table class="mgmt-table filterlist">
<colgroup>
<col class="row-actions">
<col class="filter-action">
<col class="filter-conditions">
<col class="staff-note">
<col class="row-staff">
<col class="is-active">
<col class="row-date">
</colgroup>
<tr>
<th>Actions</th><th>Filter action</th><th>Conditions</th><th>Staff</th><th>Last modified</th>
<th>Actions</th><th>Filter action</th><th>Conditions</th><th>Staff note</th><th>Staff</th><th>Is active</th><th>Last modified</th>
</tr>
<!-- TODO: replace dummy data with actual data -->
{{- range $f, $filter := $.filters -}}
<tr>
<td>
<a href="{{webPath `/manage/filters?edit=1`}}">Edit</a> | <a href="{{webPath `/manage/filters?delete=1`}}">Delete</a>
</td>
<td>Ban IP</td>
<td>User agent, Name, Tripcode, First time poster</td>
<td>admin</td>
<td>2024-07-01 12:00:00</td>
</tr>
<tr>
<td>
<a href="{{webPath `/manage/filters?edit=2`}}">Edit</a> |
<a href="{{webPath `/manage/filters?delete=2`}}">Delete</a>
</td>
<td>Reject post</td>
<td>Name, Tripcode, Email, Subject, Message body, First time poster, Not a first time poster, Is OP, Is reply, Has file, No file, Filename, File checksum, Image fingerprint, User agent</td>
<td>admin</td>
<td>2024-07-01 12:00:00</td>
<td><a href="{{webPath `/manage/filters`}}?edit={{$filter.ID}}">Edit</a> | <a href="{{webPath `/manage/filters`}}?{{if $filter.IsActive}}disable{{else}}enable{{end}}={{$filter.ID}}">{{if $filter.IsActive}}Disable{{else}}Enable{{end}}</a></td>
<td>{{index $.actions $filter.MatchAction}}</td>
<td>{{index $.conditions $f}}</td>
<td>{{$filter.StaffNote}}</td>
<td>{{index $.staff $f}}</td>
<td>{{$filter.IsActive}}</td>
<td>{{formatTimestamp $filter.IssuedAt}}</td>
</tr>
{{- end -}}
</table>