/
tables.go
315 lines (287 loc) · 9.46 KB
/
tables.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
package gcsql
import (
"errors"
"html/template"
"net"
"time"
"github.com/gochan-org/gochan/pkg/gcutil"
)
// table: DBPREFIXannouncements
type Announcement struct {
ID uint // sql: `id`
StaffID uint // sql: `staff_id`
Subject string // sql: `subject`
Message string // sql: `message`
Timestamp time.Time // sql: `timestamp`
}
// table: DBPREFIXboard_staff
type BoardStaff struct {
BoardID uint // sql: `board_id`
StaffID uint // sql: `staff_id`
}
// table: DBPREFIXboards
type Board struct {
ID int // sql: `id`
SectionID int // sql: `section_id`
URI string // sql: `uri`
Dir string // sql: `dir`
NavbarPosition int // sql: `navbar_position`
Title string // sql: `title`
Subtitle string // sql: `suttitle`
Description string // sql: `description`
MaxFilesize int // sql: `max_file_size`
MaxThreads int // sql: `max_threads`
DefaultStyle string // sql: `default_style`
Locked bool // sql: `locked`
CreatedAt time.Time // sql: `created_at`
AnonymousName string // sql: `anonymous_name`
ForceAnonymous bool // sql: `force_anonymous`
AutosageAfter int // sql: `autosage_after`
NoImagesAfter int // sql: `no_images_after`
MaxMessageLength int // sql: `max_message_length`
MinMessageLength int // sql: `min_message_length`
AllowEmbeds bool // sql: `allow_embeds`
RedirectToThread bool // sql: `redirect_to_thread`
RequireFile bool // sql: `require_file`
EnableCatalog bool // sql: `enable_catalog`
}
// FileBan contains the information associated with a specific file ban.
// table: DBPREFIXfile_ban
type FileBan 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`
Checksum string // sql: `checksum`
Fingerprinter *string // sql: `fingerprinter`
BanIP bool // sql: `ban_ip`
BanIPMessage *string // sql: `ban_ip_message`
}
// ApplyIPBan bans the given IP if it posted a banned image
// If BanIP is false, it returns with no error
func (fb *FileBan) ApplyIPBan(postIP string) error {
if !fb.BanIP {
return nil
}
now := time.Now()
ipBan := &IPBan{
RangeStart: postIP,
RangeEnd: postIP,
IssuedAt: now,
}
ipBan.IsActive = true
ipBan.CanAppeal = true
ipBan.AppealAt = now
ipBan.StaffID = fb.StaffID
ipBan.Permanent = true
if fb.BoardID != nil {
ipBan.BoardID = new(int)
*ipBan.BoardID = *fb.BoardID
}
if fb.BanIPMessage == nil {
ipBan.Message = "posting disallowed image, resulting in ban"
} else {
ipBan.Message = *fb.BanIPMessage
}
if fb.StaffNote == "" {
ipBan.StaffNote = "fingerprint"
}
return NewIPBan(ipBan)
}
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 {
filenameOrUsernameBanBase
Filename string // sql: `filename`
IsRegex bool // sql: `is_regex`
}
// Upload represents a file attached to a post.
// table: DBPREFIXfiles
type Upload struct {
ID int // sql: `id`
PostID int // sql: `post_id`
FileOrder int // sql: `file_order`
OriginalFilename string // sql: `original_filename`
Filename string // sql: `filename`
Checksum string // sql: `checksum`
FileSize int // sql: `file_size`
IsSpoilered bool // sql: `is_spoilered`
ThumbnailWidth int // sql: `thumbnail_width`
ThumbnailHeight int // sql: `thumbnail_height`
Width int // sql: `width`
Height int // sql: `height`
}
// IPBanBase used to composition IPBan and IPBanAudit. It does not represent a SQL table by itself
type IPBanBase struct {
IsActive bool
IsThreadBan bool
ExpiresAt time.Time
StaffID int
AppealAt time.Time
Permanent bool
StaffNote string
Message string
CanAppeal bool
}
// IPBan contains the information association with a specific ip ban.
// table: DBPREFIXip_ban
type IPBan struct {
ID int
BoardID *int
BannedForPostID *int
CopyPostText template.HTML
RangeStart string
RangeEnd string
IssuedAt time.Time
IPBanBase
}
// IP was previously a field in the IPBan struct before range bans were
// implemented. This is here as a fallback for templates
//
// Deprecated: Use the RangeStart and RangeEnd fields or gcutil.GetIPRangeSubnet
func (ipb *IPBan) IP() string {
if ipb.RangeStart == ipb.RangeEnd {
return ipb.RangeStart
}
inet, err := gcutil.GetIPRangeSubnet(ipb.RangeStart, ipb.RangeEnd)
if err != nil {
return "?"
}
return inet.String()
}
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`
Timestamp time.Time // sql: `timestamp`
IPBanBase
}
// used to composition IPBanAppeal and IPBanAppealAudit
type ipBanAppealBase struct {
StaffID int // sql: `staff_id`
AppealText string // sql: `appeal_text`
StaffResponse string // sql: `staff_response`
IsDenied bool // sql: `is_denied`
}
// table: DBPREFIXip_ban_appeals
type IPBanAppeal struct {
ID int // sql: `id`
IPBanID int // sql: `ip_ban_id`
ipBanAppealBase
}
// table: DBPREFIXip_ban_appeals_audit
type IPBanAppealAudit struct {
AppealID int // sql: `appeal_id`
Timestamp time.Time // sql: `timestamp`
ipBanAppealBase
}
// table: DBPREFIXposts
type Post struct {
ID int // sql: `id`
ThreadID int // sql: `thread_id`
IsTopPost bool // sql: `is_top_post`
IP string // sql: `ip`
CreatedOn time.Time // sql: `created_on`
Name string // sql: `name`
Tripcode string // sql: `tripcode`
IsRoleSignature bool // sql: `is_role_signature`
Email string // sql: `email`
Subject string // sql: `subject`
Message template.HTML // sql: `message`
MessageRaw string // sql: `message_raw`
Password string `json:"-"` // sql: `password`
DeletedAt time.Time // sql: `deleted_at`
IsDeleted bool // sql: `is_deleted`
BannedMessage string // sql: `banned_message`
Flag string // sql: `flag`
Country string // sql: `country`
}
// table: DBPREFIXreports
type Report struct {
ID int // sql: `id`
HandledByStaffID int // sql: `handled_by_staff_id`
PostID int // sql: `post_id`
IP string // sql: `ip`
Reason string // sql: `reason`
IsCleared bool // sql: `is_cleared`
}
// table: DBPREFIXreports_audit
type ReportAudit struct {
Report int // sql: `report_id`
Timestamp time.Time // sql: `timestamp`
HandledByStaffID int // sql: `handled_by_staff_id`
IsCleared bool // sql: `is_cleared`
}
// table: DBPREFIXsections
type Section struct {
ID int // sql: `id`
Name string // sql: `name`
Abbreviation string // sql: `abbreviation`
Position int // sql: `position`
Hidden bool // sql: `hidden`
}
// table: DBPREFIXsessions
type LoginSession struct {
ID int // sql: `id`
StaffID int // sql: `staff_id`
Expires time.Time // sql: `expires`
Data string // sql: `data`
}
// DBPREFIXstaff
type Staff struct {
ID int // sql: `id`
Username string // sql: `username`
PasswordChecksum string `json:"-"` // sql: `password_checksum`
Rank int // sql: `global_rank`
AddedOn time.Time `json:"-"` // sql: `added_on`
LastLogin time.Time `json:"-"` // sql: `last_login`
IsActive bool `json:"-"` // sql: `is_active`
}
// table: DBPREFIXthreads
type Thread struct {
ID int // sql: `id`
BoardID int // sql: `board_id`
Locked bool // sql: `locked`
Stickied bool // sql: `stickied`
Anchored bool // sql: `anchored`
Cyclical bool // sql: `cyclical`
LastBump time.Time // sql: `last_bump`
DeletedAt time.Time // sql: `deleted_at`
IsDeleted bool // sql: `is_deleted`
}
// table: DBPREFIXusername_ban
type UsernameBan struct {
filenameOrUsernameBanBase
Username string // sql: `username`
}
// table DBPREFIXwordfilters
type Wordfilter struct {
ID int `json:"id"` // sql: `id`
BoardDirs *string `json:"boards"` // sql: `board_dirs`
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`
Search string `json:"search"` // sql: `search`
IsRegex bool `json:"is_regex"` // sql: `is_regex`
ChangeTo string `json:"change_to"` // sql: `change_to`
}