Fixed timezone things with postgresql and made "Forever" work.

This commit is contained in:
Stanislav Nikitin 2018-12-01 03:49:04 +05:00
parent aa5e11329f
commit c565ec8f21
4 changed files with 56 additions and 24 deletions

View File

@ -46,7 +46,7 @@ func InitialUp(tx *sql.Tx) error {
COMMENT ON COLUMN pastes.data IS 'Paste data'; COMMENT ON COLUMN pastes.data IS 'Paste data';
COMMENT ON COLUMN pastes.created_at IS 'Paste creation timestamp'; COMMENT ON COLUMN pastes.created_at IS 'Paste creation timestamp';
COMMENT ON COLUMN pastes.keep_for IS 'Keep for integer. 0 - forever.'; COMMENT ON COLUMN pastes.keep_for IS 'Keep for integer. 0 - forever.';
COMMENT ON COLUMN pastes.keep_for_unit_type IS 'Keep for unit type. 1 - minutes, 2 - hours, 3 - days, 4 - months.'; COMMENT ON COLUMN pastes.keep_for_unit_type IS 'Keep for unit type. 0 - forever, 1 - minutes, 2 - hours, 3 - days, 4 - months.';
`) `)
if err != nil { if err != nil {
return err return err

View File

@ -28,6 +28,7 @@ import (
// stdlib // stdlib
"database/sql" "database/sql"
"fmt" "fmt"
"time"
// local // local
"gitlab.com/pztrn/fastpastebin/database/dialects/postgresql/migrations" "gitlab.com/pztrn/fastpastebin/database/dialects/postgresql/migrations"
@ -66,6 +67,13 @@ func (db *Database) GetPaste(pasteID int) (*pastesmodel.Paste, error) {
return nil, err return nil, err
} }
// We're aware of timezone in PostgreSQL, so SELECT will return
// timestamps in server's local timezone. We should convert them.
loc, _ := time.LoadLocation("UTC")
utcCreatedAt := p.CreatedAt.In(loc)
p.CreatedAt = &utcCreatedAt
return p, nil return p, nil
} }
@ -85,9 +93,15 @@ func (db *Database) GetPagedPastes(page int) ([]pastesmodel.Paste, error) {
return nil, err return nil, err
} }
for i := range pastesRaw { // We're aware of timezone in PostgreSQL, so SELECT will return
if !pastesRaw[i].IsExpired() { // timestamps in server's local timezone. We should convert them.
pastes = append(pastes, pastesRaw[i]) loc, _ := time.LoadLocation("UTC")
for _, paste := range pastesRaw {
if !paste.IsExpired() {
utcCreatedAt := paste.CreatedAt.In(loc)
paste.CreatedAt = &utcCreatedAt
pastes = append(pastes, paste)
} }
} }
@ -104,9 +118,9 @@ func (db *Database) GetPastesPages() int {
} }
// Check if pastes isn't expired. // Check if pastes isn't expired.
for i := range pastesRaw { for _, paste := range pastesRaw {
if !pastesRaw[i].IsExpired() { if !paste.IsExpired() {
pastes = append(pastes, pastesRaw[i]) pastes = append(pastes, paste)
} }
} }

View File

@ -118,9 +118,14 @@ func pasteGET(ec echo.Context) error {
pasteData["pasteTitle"] = paste.Title pasteData["pasteTitle"] = paste.Title
pasteData["pasteID"] = strconv.Itoa(paste.ID) pasteData["pasteID"] = strconv.Itoa(paste.ID)
pasteData["pasteDate"] = paste.CreatedAt.Format("2006-01-02 @ 15:04:05") + " UTC" pasteData["pasteDate"] = paste.CreatedAt.Format("2006-01-02 @ 15:04:05") + " UTC"
pasteData["pasteExpiration"] = paste.GetExpirationTime().Format("2006-01-02 @ 15:04:05") + " UTC"
pasteData["pasteLanguage"] = paste.Language pasteData["pasteLanguage"] = paste.Language
pasteExpirationString := "Never"
if paste.KeepFor != 0 && paste.KeepForUnitType != 0 {
pasteExpirationString = paste.GetExpirationTime().Format("2006-01-02 @ 15:04:05") + " UTC"
}
pasteData["pasteExpiration"] = pasteExpirationString
if paste.Private { if paste.Private {
pasteData["pasteType"] = "<span class='has-text-danger'>Private</span>" pasteData["pasteType"] = "<span class='has-text-danger'>Private</span>"
pasteData["pasteTs"] = strconv.FormatInt(paste.CreatedAt.Unix(), 10) + "/" pasteData["pasteTs"] = strconv.FormatInt(paste.CreatedAt.Unix(), 10) + "/"
@ -264,7 +269,7 @@ func pastePOST(ec echo.Context) error {
return ec.HTML(http.StatusBadRequest, errtpl) return ec.HTML(http.StatusBadRequest, errtpl)
} }
if !strings.ContainsAny(params["paste-keep-for"][0], "Mmhd") { if !strings.ContainsAny(params["paste-keep-for"][0], "Mmhd") && params["paste-keep-for"][0] != "forever" {
c.Logger.Debug().Msgf("'Keep paste for' field have invalid value: %s", params["paste-keep-for"][0]) c.Logger.Debug().Msgf("'Keep paste for' field have invalid value: %s", params["paste-keep-for"][0])
errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).") errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).")
return ec.HTML(http.StatusBadRequest, errtpl) return ec.HTML(http.StatusBadRequest, errtpl)
@ -288,21 +293,30 @@ func pastePOST(ec echo.Context) error {
paste.CreatedAt = &createdAt paste.CreatedAt = &createdAt
// Parse "keep for" field. // Parse "keep for" field.
// Defaulting to "forever".
keepFor := 0
keepForUnit := 0
if params["paste-keep-for"][0] != "forever" {
keepForUnitRegex := regexp.MustCompile("[Mmhd]")
// Get integers and strings separately. keepForRaw := regexInts.FindAllString(params["paste-keep-for"][0], 1)[0]
keepForUnitRegex := regexp.MustCompile("[Mmhd]") var err error
keepFor, err = strconv.Atoi(keepForRaw)
if err != nil {
if params["paste-keep-for"][0] == "forever" {
c.Logger.Debug().Msg("Keeping paste forever!")
keepFor = 0
} else {
c.Logger.Debug().Err(err).Msg("Failed to parse 'Keep for' integer")
errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).")
return ec.HTML(http.StatusBadRequest, errtpl)
}
}
keepForRaw := regexInts.FindAllString(params["paste-keep-for"][0], 1)[0] keepForUnitRaw := keepForUnitRegex.FindAllString(params["paste-keep-for"][0], 1)[0]
keepFor, err1 := strconv.Atoi(keepForRaw) keepForUnit = pastesmodel.PASTE_KEEPS_CORELLATION[keepForUnitRaw]
if err1 != nil {
c.Logger.Debug().Msgf("Failed to parse 'Keep for' integer: %s", err1.Error())
errtpl := templater.GetErrorTemplate(ec, "Invalid 'Paste should be available for' parameter passed. Please do not try to hack us ;).")
return ec.HTML(http.StatusBadRequest, errtpl)
} }
paste.KeepFor = keepFor paste.KeepFor = keepFor
keepForUnitRaw := keepForUnitRegex.FindAllString(params["paste-keep-for"][0], 1)[0]
keepForUnit := pastesmodel.PASTE_KEEPS_CORELLATION[keepForUnitRaw]
paste.KeepForUnitType = keepForUnit paste.KeepForUnitType = keepForUnit
// Try to autodetect if it was selected. // Try to autodetect if it was selected.

View File

@ -36,6 +36,7 @@ import (
) )
const ( const (
PASTE_KEEP_FOREVER = 0
PASTE_KEEP_FOR_MINUTES = 1 PASTE_KEEP_FOR_MINUTES = 1
PASTE_KEEP_FOR_HOURS = 2 PASTE_KEEP_FOR_HOURS = 2
PASTE_KEEP_FOR_DAYS = 3 PASTE_KEEP_FOR_DAYS = 3
@ -46,10 +47,11 @@ const (
var ( var (
PASTE_KEEPS_CORELLATION = map[string]int{ PASTE_KEEPS_CORELLATION = map[string]int{
"M": PASTE_KEEP_FOR_MINUTES, "M": PASTE_KEEP_FOR_MINUTES,
"h": PASTE_KEEP_FOR_HOURS, "h": PASTE_KEEP_FOR_HOURS,
"d": PASTE_KEEP_FOR_DAYS, "d": PASTE_KEEP_FOR_DAYS,
"m": PASTE_KEEP_FOR_MONTHS, "m": PASTE_KEEP_FOR_MONTHS,
"forever": PASTE_KEEP_FOREVER,
} }
) )
@ -99,6 +101,8 @@ func (p *Paste) GenerateCryptedCookieValue() string {
func (p *Paste) GetExpirationTime() time.Time { func (p *Paste) GetExpirationTime() time.Time {
var expirationTime time.Time var expirationTime time.Time
switch p.KeepForUnitType { switch p.KeepForUnitType {
case PASTE_KEEP_FOREVER:
expirationTime = time.Now().UTC().Add(time.Hour * 1)
case PASTE_KEEP_FOR_MINUTES: case PASTE_KEEP_FOR_MINUTES:
expirationTime = p.CreatedAt.Add(time.Minute * time.Duration(p.KeepFor)) expirationTime = p.CreatedAt.Add(time.Minute * time.Duration(p.KeepFor))
case PASTE_KEEP_FOR_HOURS: case PASTE_KEEP_FOR_HOURS: