mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-02 15:06:23 -07:00
Add is_secure_tripcode column to posts and update gochan-migration to add it
This commit is contained in:
parent
ffac903eb5
commit
4c0ce122ad
16 changed files with 182 additions and 90 deletions
2
build.py
2
build.py
|
@ -40,7 +40,7 @@ release_files = (
|
||||||
)
|
)
|
||||||
|
|
||||||
GOCHAN_VERSION = "4.1.0"
|
GOCHAN_VERSION = "4.1.0"
|
||||||
DATABASE_VERSION = "4" # stored in DBNAME.DBPREFIXdatabase_version
|
DATABASE_VERSION = "5" # stored in DBNAME.DBPREFIXdatabase_version
|
||||||
|
|
||||||
PATH_NOTHING = -1
|
PATH_NOTHING = -1
|
||||||
PATH_UNKNOWN = 0
|
PATH_UNKNOWN = 0
|
||||||
|
|
|
@ -32,7 +32,7 @@ func updateMysqlDB(ctx context.Context, dbu *GCDatabaseUpdater, sqlConfig *confi
|
||||||
}
|
}
|
||||||
|
|
||||||
var rows *sql.Rows
|
var rows *sql.Rows
|
||||||
query = `SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?`
|
query = `SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = ? AND TABLE_TYPE = 'BASE TABLE'`
|
||||||
rows, err = db.QueryContextSQL(ctx, nil, query, dbName)
|
rows, err = db.QueryContextSQL(ctx, nil, query, dbName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -181,5 +181,17 @@ func updateMysqlDB(ctx context.Context, dbu *GCDatabaseUpdater, sqlConfig *confi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add is_secure_tripcode column to DBPREFIXposts
|
||||||
|
dataType, err = common.ColumnType(ctx, db, nil, "is_secure_tripcode", "DBPREFIXposts", sqlConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dataType == "" {
|
||||||
|
query = `ALTER TABLE DBPREFIXposts ADD COLUMN is_secure_tripcode BOOL NOT NULL DEFAULT FALSE`
|
||||||
|
if _, err = db.ExecContextSQL(ctx, nil, query); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,5 +93,17 @@ func updatePostgresDB(ctx context.Context, dbu *GCDatabaseUpdater, sqlConfig *co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add is_secure_tripcode column to DBPREFIXposts
|
||||||
|
dataType, err = common.ColumnType(ctx, db, nil, "is_secure_tripcode", "DBPREFIXposts", sqlConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dataType == "" {
|
||||||
|
query = `ALTER TABLE DBPREFIXposts ADD COLUMN is_secure_tripcode BOOL NOT NULL DEFAULT FALSE`
|
||||||
|
if _, err = db.ExecContextSQL(ctx, nil, query); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,5 +111,17 @@ func updateSqliteDB(ctx context.Context, dbu *GCDatabaseUpdater, sqlConfig *conf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add is_secure_tripcode column to DBPREFIXposts
|
||||||
|
dataType, err = common.ColumnType(ctx, db, nil, "is_secure_tripcode", "DBPREFIXposts", sqlConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dataType == "" {
|
||||||
|
query = `ALTER TABLE DBPREFIXposts ADD COLUMN is_secure_tripcode BOOL NOT NULL DEFAULT FALSE`
|
||||||
|
if _, err = db.ExecContextSQL(ctx, nil, query); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,8 +97,8 @@ func (m *Pre2021Migrator) MigratePosts() error {
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var thread migrationPost
|
var thread migrationPost
|
||||||
if err = rows.Scan(
|
if err = rows.Scan(
|
||||||
&thread.oldID, &thread.oldBoardID, &thread.oldParentID, &thread.Name, &thread.Tripcode, &thread.Email,
|
&thread.oldID, &thread.oldBoardID, &thread.oldParentID, &thread.Name, &thread.Tripcode, &thread.IsSecureTripcode,
|
||||||
&thread.Subject, &thread.Message, &thread.MessageRaw, &thread.Password, &thread.filename,
|
&thread.Email, &thread.Subject, &thread.Message, &thread.MessageRaw, &thread.Password, &thread.filename,
|
||||||
&thread.filenameOriginal, &thread.fileChecksum, &thread.filesize, &thread.imageW, &thread.imageH,
|
&thread.filenameOriginal, &thread.fileChecksum, &thread.filesize, &thread.imageW, &thread.imageH,
|
||||||
&thread.thumbW, &thread.thumbH, &thread.IP, &thread.CreatedOn, &thread.autosage,
|
&thread.thumbW, &thread.thumbH, &thread.IP, &thread.CreatedOn, &thread.autosage,
|
||||||
&thread.bumped, &thread.stickied, &thread.locked,
|
&thread.bumped, &thread.stickied, &thread.locked,
|
||||||
|
@ -137,8 +137,8 @@ func (m *Pre2021Migrator) MigratePosts() error {
|
||||||
for replyRows.Next() {
|
for replyRows.Next() {
|
||||||
var reply migrationPost
|
var reply migrationPost
|
||||||
if err = replyRows.Scan(
|
if err = replyRows.Scan(
|
||||||
&reply.oldID, &reply.oldBoardID, &reply.oldParentID, &reply.Name, &reply.Tripcode, &reply.Email,
|
&reply.oldID, &reply.oldBoardID, &reply.oldParentID, &reply.Name, &reply.Tripcode, &reply.IsSecureTripcode,
|
||||||
&reply.Subject, &reply.Message, &reply.MessageRaw, &reply.Password, &reply.filename,
|
&reply.Email, &reply.Subject, &reply.Message, &reply.MessageRaw, &reply.Password, &reply.filename,
|
||||||
&reply.filenameOriginal, &reply.fileChecksum, &reply.filesize, &reply.imageW, &reply.imageH,
|
&reply.filenameOriginal, &reply.fileChecksum, &reply.filesize, &reply.imageW, &reply.imageH,
|
||||||
&reply.thumbW, &reply.thumbH, &reply.IP, &reply.CreatedOn, &reply.autosage,
|
&reply.thumbW, &reply.thumbH, &reply.IP, &reply.CreatedOn, &reply.autosage,
|
||||||
&reply.bumped, &reply.stickied, &reply.locked,
|
&reply.bumped, &reply.stickied, &reply.locked,
|
||||||
|
|
|
@ -8,7 +8,7 @@ default_style, locked, created_on, anonymous, forced_anon, autosage_after, no_im
|
||||||
redirect_to_thread, require_file, enable_catalog
|
redirect_to_thread, require_file, enable_catalog
|
||||||
FROM DBPREFIXboards`
|
FROM DBPREFIXboards`
|
||||||
|
|
||||||
postsQuery = `SELECT id, boardid, parentid, name, tripcode, email, subject, message, message_raw, password, filename,
|
postsQuery = `SELECT id, boardid, parentid, name, tripcode, is_secure_tripcode, email, subject, message, message_raw, password, filename,
|
||||||
filename_original, file_checksum, filesize, image_w, image_h, thumb_w, thumb_h, ip, timestamp, autosage,
|
filename_original, file_checksum, filesize, image_w, image_h, thumb_w, thumb_h, ip, timestamp, autosage,
|
||||||
bumped, stickied, locked FROM DBPREFIXposts WHERE deleted_timestamp IS NULL`
|
bumped, stickied, locked FROM DBPREFIXposts WHERE deleted_timestamp IS NULL`
|
||||||
|
|
||||||
|
|
|
@ -201,24 +201,25 @@ type IPBanAppealAudit struct {
|
||||||
|
|
||||||
// table: DBPREFIXposts
|
// table: DBPREFIXposts
|
||||||
type Post struct {
|
type Post struct {
|
||||||
ID int `json:"no"` // sql: id
|
ID int `json:"no"` // sql: id
|
||||||
ThreadID int `json:"-"` // sql: thread_id
|
ThreadID int `json:"-"` // sql: thread_id
|
||||||
IsTopPost bool `json:"-"` // sql: is_top_post
|
IsTopPost bool `json:"-"` // sql: is_top_post
|
||||||
IP string `json:"-"` // sql: ip
|
IP string `json:"-"` // sql: ip
|
||||||
CreatedOn time.Time `json:"time"` // sql: created_on
|
CreatedOn time.Time `json:"time"` // sql: created_on
|
||||||
Name string `json:"name"` // sql: name
|
Name string `json:"name"` // sql: name
|
||||||
Tripcode string `json:"trip"` // sql: tripcode
|
Tripcode string `json:"trip"` // sql: tripcode
|
||||||
IsRoleSignature bool `json:"-"` // sql: is_role_signature
|
IsSecureTripcode bool `json:"-"` // sql: is_secure_tripcode
|
||||||
Email string `json:"email"` // sql: email
|
IsRoleSignature bool `json:"-"` // sql: is_role_signature
|
||||||
Subject string `json:"sub"` // sql: subject
|
Email string `json:"email"` // sql: email
|
||||||
Message template.HTML `json:"-"` // sql: message
|
Subject string `json:"sub"` // sql: subject
|
||||||
MessageRaw string `json:"com"` // sql: message_raw
|
Message template.HTML `json:"-"` // sql: message
|
||||||
Password string `json:"-"` // sql: `password`
|
MessageRaw string `json:"com"` // sql: message_raw
|
||||||
DeletedAt time.Time `json:"-"` // sql: deleted_at
|
Password string `json:"-"` // sql: `password`
|
||||||
IsDeleted bool `json:"-"` // sql: is_deleted
|
DeletedAt time.Time `json:"-"` // sql: deleted_at
|
||||||
BannedMessage string `json:"-"` // sql: banned_message
|
IsDeleted bool `json:"-"` // sql: is_deleted
|
||||||
Flag string `json:"-"` // sql: flag
|
BannedMessage string `json:"-"` // sql: banned_message
|
||||||
Country string `json:"-"` // sql: country
|
Flag string `json:"-"` // sql: flag
|
||||||
|
Country string `json:"-"` // sql: country
|
||||||
|
|
||||||
// used for convenience to avoid needing to do multiple queries
|
// used for convenience to avoid needing to do multiple queries
|
||||||
opID int
|
opID int
|
||||||
|
|
|
@ -77,44 +77,6 @@ func TestMarshalJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNameParsing(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
nameAndTrip string
|
|
||||||
expectedName string
|
|
||||||
expectedTripcode string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
nameAndTrip: "Name#Trip",
|
|
||||||
expectedName: "Name",
|
|
||||||
expectedTripcode: "piec1MorXg",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nameAndTrip: "#Trip",
|
|
||||||
expectedName: "",
|
|
||||||
expectedTripcode: "piec1MorXg",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nameAndTrip: "Name",
|
|
||||||
expectedName: "Name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nameAndTrip: "Name#",
|
|
||||||
expectedName: "Name",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nameAndTrip: "#",
|
|
||||||
expectedName: "",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tC := range testCases {
|
|
||||||
t.Run(tC.nameAndTrip, func(t *testing.T) {
|
|
||||||
name, trip := ParseName(tC.nameAndTrip)
|
|
||||||
assert.Equal(t, tC.expectedName, name)
|
|
||||||
assert.Equal(t, tC.expectedTripcode, trip)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetRealIP(t *testing.T) {
|
func TestGetRealIP(t *testing.T) {
|
||||||
const remoteAddr = "192.168.56.1"
|
const remoteAddr = "192.168.56.1"
|
||||||
const testIP = "192.168.56.2"
|
const testIP = "192.168.56.2"
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/aquilax/tripcode"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
x_html "golang.org/x/net/html"
|
x_html "golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
@ -147,22 +146,6 @@ func MarshalJSON(data any, indent bool) (string, error) {
|
||||||
return string(jsonBytes), err
|
return string(jsonBytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseName takes a name string from a request object and returns the name and tripcode parts
|
|
||||||
func ParseName(name string) (string, string) {
|
|
||||||
var namePart string
|
|
||||||
var tripcodePart string
|
|
||||||
if !strings.Contains(name, "#") {
|
|
||||||
namePart = name
|
|
||||||
} else if strings.Index(name, "#") == 0 {
|
|
||||||
tripcodePart = tripcode.Tripcode(name[1:])
|
|
||||||
} else if strings.Index(name, "#") > 0 {
|
|
||||||
postNameArr := strings.SplitN(name, "#", 2)
|
|
||||||
namePart = postNameArr[0]
|
|
||||||
tripcodePart = tripcode.Tripcode(postNameArr[1])
|
|
||||||
}
|
|
||||||
return namePart, tripcodePart
|
|
||||||
}
|
|
||||||
|
|
||||||
// RandomString returns a randomly generated string of the given length
|
// RandomString returns a randomly generated string of the given length
|
||||||
func RandomString(length int) string {
|
func RandomString(length int) string {
|
||||||
var str string
|
var str string
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package posting
|
package posting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/aquilax/tripcode"
|
||||||
"github.com/gochan-org/gochan/pkg/building"
|
"github.com/gochan-org/gochan/pkg/building"
|
||||||
"github.com/gochan-org/gochan/pkg/config"
|
"github.com/gochan-org/gochan/pkg/config"
|
||||||
"github.com/gochan-org/gochan/pkg/events"
|
"github.com/gochan-org/gochan/pkg/events"
|
||||||
|
@ -170,7 +172,43 @@ func getEmailAndCommand(request *http.Request) (string, string) {
|
||||||
return formEmail[:sepIndex], formEmail[sepIndex+1:]
|
return formEmail[:sepIndex], formEmail[sepIndex+1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPostFromRequest(request *http.Request, infoEv, errEv *zerolog.Event) (post *gcsql.Post, err error) {
|
// ParseName takes a name and board string and returns the name and tripcode parts,
|
||||||
|
// using the board's reserved tripcodes if applicable.
|
||||||
|
func ParseName(name string, boardConfig *config.BoardConfig) (string, string) {
|
||||||
|
var namePart string
|
||||||
|
var tripcodePart string
|
||||||
|
var secure bool
|
||||||
|
if strings.Contains(name, "##") {
|
||||||
|
parts := strings.SplitN(name, "##", 2)
|
||||||
|
namePart = parts[0]
|
||||||
|
tripcodePart = parts[1]
|
||||||
|
secure = true
|
||||||
|
} else if strings.Contains(name, "#") {
|
||||||
|
parts := strings.SplitN(name, "#", 2)
|
||||||
|
namePart = parts[0]
|
||||||
|
tripcodePart = parts[1]
|
||||||
|
} else {
|
||||||
|
namePart = name
|
||||||
|
}
|
||||||
|
|
||||||
|
if tripcodePart != "" {
|
||||||
|
reservedTrip, reserved := boardConfig.ReservedTrips[tripcodePart]
|
||||||
|
if secure && reserved {
|
||||||
|
tripcodePart = reservedTrip
|
||||||
|
} else if secure {
|
||||||
|
hash := gcutil.Md5Sum(tripcodePart + config.GetSystemCriticalConfig().RandomSeed)
|
||||||
|
for range 64 {
|
||||||
|
hash = gcutil.Md5Sum(hash + name)
|
||||||
|
}
|
||||||
|
tripcodePart = base64.StdEncoding.EncodeToString([]byte(hash))[:10]
|
||||||
|
} else {
|
||||||
|
tripcodePart = tripcode.Tripcode(tripcodePart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return namePart, tripcodePart
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPostFromRequest(request *http.Request, boardConfig *config.BoardConfig, infoEv, errEv *zerolog.Event) (post *gcsql.Post, err error) {
|
||||||
post = &gcsql.Post{
|
post = &gcsql.Post{
|
||||||
IP: gcutil.GetRealIP(request),
|
IP: gcutil.GetRealIP(request),
|
||||||
Subject: request.PostFormValue("postsubject"),
|
Subject: request.PostFormValue("postsubject"),
|
||||||
|
@ -197,7 +235,8 @@ func getPostFromRequest(request *http.Request, infoEv, errEv *zerolog.Event) (po
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
post.Name, post.Tripcode = gcutil.ParseName(request.PostFormValue("postname"))
|
post.Name, post.Tripcode = ParseName(request.PostFormValue("postname"), boardConfig)
|
||||||
|
post.IsSecureTripcode = strings.Contains(post.Tripcode, "##")
|
||||||
post.Email, _ = getEmailAndCommand(request)
|
post.Email, _ = getEmailAndCommand(request)
|
||||||
|
|
||||||
password := request.PostFormValue("postpassword")
|
password := request.PostFormValue("postpassword")
|
||||||
|
@ -300,12 +339,6 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
post, err := getPostFromRequest(request, infoEv, errEv)
|
|
||||||
if err != nil {
|
|
||||||
server.ServeError(writer, err.Error(), wantsJSON, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
boardidStr := request.PostFormValue("boardid")
|
boardidStr := request.PostFormValue("boardid")
|
||||||
boardID, err := strconv.Atoi(boardidStr)
|
boardID, err := strconv.Atoi(boardidStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -335,6 +368,12 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
post, err := getPostFromRequest(request, boardConfig, infoEv, errEv)
|
||||||
|
if err != nil {
|
||||||
|
server.ServeError(writer, err.Error(), wantsJSON, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if boardConfig.MaxMessageLength > 0 && len(post.MessageRaw) > boardConfig.MaxMessageLength {
|
if boardConfig.MaxMessageLength > 0 && len(post.MessageRaw) > boardConfig.MaxMessageLength {
|
||||||
warnEv.
|
warnEv.
|
||||||
Int("messageLength", len(post.MessageRaw)).
|
Int("messageLength", len(post.MessageRaw)).
|
||||||
|
|
67
pkg/posting/post_test.go
Normal file
67
pkg/posting/post_test.go
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package posting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gochan-org/gochan/pkg/config"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type parseNameTestCase struct {
|
||||||
|
nameAndTrip string
|
||||||
|
expectedName string
|
||||||
|
expectedTripcode string
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseName(t *testing.T) {
|
||||||
|
config.SetVersion("4.1")
|
||||||
|
boardConfig := config.GetBoardConfig("test")
|
||||||
|
boardConfig.ReservedTrips = map[string]string{
|
||||||
|
"reserved": "TripOut",
|
||||||
|
}
|
||||||
|
config.SetBoardConfig("test", boardConfig)
|
||||||
|
|
||||||
|
config.SetRandomSeed("lol")
|
||||||
|
|
||||||
|
testCases := []parseNameTestCase{
|
||||||
|
{
|
||||||
|
nameAndTrip: "Name#Trip",
|
||||||
|
expectedName: "Name",
|
||||||
|
expectedTripcode: "piec1MorXg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameAndTrip: "#Trip",
|
||||||
|
expectedName: "",
|
||||||
|
expectedTripcode: "piec1MorXg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameAndTrip: "Name",
|
||||||
|
expectedName: "Name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameAndTrip: "Name#",
|
||||||
|
expectedName: "Name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameAndTrip: "#",
|
||||||
|
expectedName: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameAndTrip: "Name##reserved",
|
||||||
|
expectedName: "Name",
|
||||||
|
expectedTripcode: "TripOut",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameAndTrip: "Name##notReserved",
|
||||||
|
expectedName: "Name",
|
||||||
|
expectedTripcode: "MDlhNmNmYj",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tC := range testCases {
|
||||||
|
t.Run(tC.nameAndTrip, func(t *testing.T) {
|
||||||
|
name, trip := ParseName(tC.nameAndTrip, boardConfig)
|
||||||
|
assert.Equal(t, tC.expectedName, name)
|
||||||
|
assert.Equal(t, tC.expectedTripcode, trip)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,6 +73,7 @@ CREATE TABLE DBPREFIXposts(
|
||||||
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
name VARCHAR(50) NOT NULL DEFAULT '',
|
name VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
||||||
|
is_secure_tripcode BOOL NOT NULL DEFAULT FALSE,
|
||||||
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
||||||
email VARCHAR(50) NOT NULL DEFAULT '',
|
email VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
subject VARCHAR(100) NOT NULL DEFAULT '',
|
subject VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
|
|
@ -73,6 +73,7 @@ CREATE TABLE DBPREFIXposts(
|
||||||
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
name VARCHAR(50) NOT NULL DEFAULT '',
|
name VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
||||||
|
is_secure_tripcode BOOL NOT NULL DEFAULT FALSE,
|
||||||
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
||||||
email VARCHAR(50) NOT NULL DEFAULT '',
|
email VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
subject VARCHAR(100) NOT NULL DEFAULT '',
|
subject VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
|
|
@ -73,6 +73,7 @@ CREATE TABLE DBPREFIXposts(
|
||||||
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
name VARCHAR(50) NOT NULL DEFAULT '',
|
name VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
||||||
|
is_secure_tripcode BOOL NOT NULL DEFAULT FALSE,
|
||||||
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
||||||
email VARCHAR(50) NOT NULL DEFAULT '',
|
email VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
subject VARCHAR(100) NOT NULL DEFAULT '',
|
subject VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
|
|
@ -73,6 +73,7 @@ CREATE TABLE DBPREFIXposts(
|
||||||
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
name VARCHAR(50) NOT NULL DEFAULT '',
|
name VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
tripcode VARCHAR(10) NOT NULL DEFAULT '',
|
||||||
|
is_secure_tripcode BOOL NOT NULL DEFAULT FALSE,
|
||||||
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
is_role_signature BOOL NOT NULL DEFAULT FALSE,
|
||||||
email VARCHAR(50) NOT NULL DEFAULT '',
|
email VARCHAR(50) NOT NULL DEFAULT '',
|
||||||
subject VARCHAR(100) NOT NULL DEFAULT '',
|
subject VARCHAR(100) NOT NULL DEFAULT '',
|
||||||
|
|
|
@ -24,7 +24,7 @@ CREATE VIEW DBPREFIXv_top_post_thread_ids AS
|
||||||
SELECT id, thread_id FROM DBPREFIXposts WHERE is_top_post;
|
SELECT id, thread_id FROM DBPREFIXposts WHERE is_top_post;
|
||||||
|
|
||||||
CREATE VIEW DBPREFIXv_building_posts AS
|
CREATE VIEW DBPREFIXv_building_posts AS
|
||||||
SELECT p.id AS id, p.thread_id AS thread_id, ip, name, tripcode,
|
SELECT p.id AS id, p.thread_id AS thread_id, ip, name, tripcode, is_secure_tripcode,
|
||||||
email, subject, created_on, created_on as last_modified, op.id AS parent_id, t.last_bump as last_bump,
|
email, subject, created_on, created_on as last_modified, op.id AS parent_id, t.last_bump as last_bump,
|
||||||
message, message_raw, t.board_id,
|
message, message_raw, t.board_id,
|
||||||
(SELECT dir FROM DBPREFIXboards WHERE id = t.board_id LIMIT 1) AS dir,
|
(SELECT dir FROM DBPREFIXboards WHERE id = t.board_id LIMIT 1) AS dir,
|
||||||
|
@ -95,7 +95,7 @@ LEFT JOIN DBPREFIXv_thread_board_ids t ON t.id = DBPREFIXposts.thread_id
|
||||||
INNER JOIN DBPREFIXv_top_post_thread_ids op on op.thread_id = DBPREFIXposts.thread_id;
|
INNER JOIN DBPREFIXv_top_post_thread_ids op on op.thread_id = DBPREFIXposts.thread_id;
|
||||||
|
|
||||||
CREATE VIEW DBPREFIXv_post_with_board AS
|
CREATE VIEW DBPREFIXv_post_with_board AS
|
||||||
SELECT p.id, thread_id, is_top_post, created_on, name, tripcode, is_role_signature, email,
|
SELECT p.id, thread_id, is_top_post, created_on, name, tripcode, is_secure_tripcode, is_role_signature, email,
|
||||||
subject, message, message_raw, password, p.deleted_at AS deleted_at, p.is_deleted AS is_deleted,
|
subject, message, message_raw, password, p.deleted_at AS deleted_at, p.is_deleted AS is_deleted,
|
||||||
banned_message, ip, flag, country, dir, board_id
|
banned_message, ip, flag, country, dir, board_id
|
||||||
FROM DBPREFIXposts p
|
FROM DBPREFIXposts p
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue