diff --git a/database/migrations/exported.go b/database/migrations/exported.go index 775c01b..0b5d36e 100644 --- a/database/migrations/exported.go +++ b/database/migrations/exported.go @@ -50,6 +50,7 @@ func Migrate() { goose.AddNamedMigration("1_initial.go", InitialUp, nil) goose.AddNamedMigration("2_paste_lang.go", PasteLangUp, PasteLangDown) goose.AddNamedMigration("3_private_pastes.go", PrivatePastesUp, PrivatePastesDown) + goose.AddNamedMigration("4_passworded_pastes.go", PasswordedPastesUp, PasswordedPastesDown) // Add new migrations BEFORE this message. dbConn := c.Database.GetDatabaseConnection() diff --git a/pastes/api_http.go b/pastes/api_http.go index 99ad23d..5c45424 100644 --- a/pastes/api_http.go +++ b/pastes/api_http.go @@ -69,7 +69,13 @@ func pasteGET(ec echo.Context) error { // Get paste. paste, err1 := GetByID(pasteID) if err1 != nil { - c.Logger.Error().Msgf("Failed to get paste #%d from database: %s", pasteID, err1.Error()) + c.Logger.Error().Msgf("Failed to get paste #%d: %s", pasteID, err1.Error()) + errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Paste #"+strconv.Itoa(pasteID)+" not found", 1) + return ec.HTML(http.StatusBadRequest, errhtmlAsString) + } + + if paste.IsExpired() { + c.Logger.Error().Msgf("Paste #%d is expired", pasteID) errhtmlAsString := strings.Replace(string(errhtml), "{error}", "Paste #"+strconv.Itoa(pasteID)+" not found", 1) return ec.HTML(http.StatusBadRequest, errhtmlAsString) } @@ -258,6 +264,11 @@ func pasteRawGET(ec echo.Context) error { return ec.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.") } + if paste.IsExpired() { + c.Logger.Error().Msgf("Paste #%d is expired", pasteID) + return ec.HTML(http.StatusBadRequest, "Paste #"+pasteIDRaw+" does not exist.") + } + // Check if we have a private paste and it's parameters are correct. if paste.Private { tsProvidedStr := ec.Param("timestamp") diff --git a/pastes/model.go b/pastes/model.go index 18a4b91..d90c026 100644 --- a/pastes/model.go +++ b/pastes/model.go @@ -57,4 +57,34 @@ type Paste struct { KeepForUnitType int `db:"keep_for_unit_type"` Language string `db:"language"` Private bool `db:"private"` + Password string `db:"password"` + PasswordSalt string `db:"password_salt"` +} + +func (p *Paste) GetExpirationTime() time.Time { + var expirationTime time.Time + switch p.KeepForUnitType { + case PASTE_KEEP_FOR_MINUTES: + expirationTime = p.CreatedAt.Add(time.Minute * time.Duration(p.KeepFor)) + case PASTE_KEEP_FOR_HOURS: + expirationTime = p.CreatedAt.Add(time.Hour * time.Duration(p.KeepFor)) + case PASTE_KEEP_FOR_DAYS: + expirationTime = p.CreatedAt.Add(time.Hour * 24 * time.Duration(p.KeepFor)) + case PASTE_KEEP_FOR_MONTHS: + expirationTime = p.CreatedAt.Add(time.Hour * 24 * 30 * time.Duration(p.KeepFor)) + } + + return expirationTime +} + +// IsExpired checks if paste is already expired (or not). +func (p *Paste) IsExpired() bool { + curTime := time.Now().UTC() + expirationTime := p.GetExpirationTime() + + if curTime.Sub(expirationTime).Seconds() > 0 { + return true + } + + return false } diff --git a/pastes/queries.go b/pastes/queries.go index ab91a04..6560a39 100644 --- a/pastes/queries.go +++ b/pastes/queries.go @@ -25,7 +25,7 @@ package pastes const ( - // Pagination. Hardcoded for 30 for now. + // Pagination. Hardcoded for 10 for now. PAGINATION = 10 ) @@ -38,25 +38,34 @@ func GetByID(id int) (*Paste, error) { return nil, err } + // Lets go with checking. + return p, nil } // GetPagedPastes returns a paged slice of pastes. func GetPagedPastes(page int) ([]Paste, error) { + var pastesRaw []Paste var pastes []Paste dbConn := c.Database.GetDatabaseConnection() - // Pagination - 30 pastes on page. + // Pagination - 10 pastes on page. var startPagination = 0 if page > 1 { startPagination = (page - 1) * PAGINATION } - err := dbConn.Select(&pastes, dbConn.Rebind("SELECT * FROM `pastes` WHERE private != true ORDER BY id DESC LIMIT ? OFFSET ?"), PAGINATION, startPagination) + err := dbConn.Select(&pastesRaw, dbConn.Rebind("SELECT * FROM `pastes` WHERE private != true ORDER BY id DESC LIMIT ? OFFSET ?"), PAGINATION, startPagination) if err != nil { return nil, err } + for i := range pastesRaw { + if !pastesRaw[i].IsExpired() { + pastes = append(pastes, pastesRaw[i]) + } + } + return pastes, nil } @@ -64,17 +73,25 @@ func GetPagedPastes(page int) ([]Paste, error) { // GetPastesPages returns an integer that represents quantity of pages // that can be requested (or drawn in paginator). func GetPastesPages() int { - var pastesCount int + var pastesRaw []Paste + var pastes []Paste dbConn := c.Database.GetDatabaseConnection() - err := dbConn.Get(&pastesCount, "SELECT COUNT(id) FROM `pastes` WHERE private != true") + err := dbConn.Get(&pastesRaw, "SELECT * FROM `pastes` WHERE private != true") if err != nil { return 1 } + // Check if pastes isn't expired. + for i := range pastesRaw { + if !pastesRaw[i].IsExpired() { + pastes = append(pastes, pastesRaw[i]) + } + } + // Calculate pages. - pages := pastesCount / PAGINATION + pages := len(pastes) / PAGINATION // Check if we have any remainder. Add 1 to pages count if so. - if pastesCount%PAGINATION > 0 { + if len(pastes)%PAGINATION > 0 { pages++ }