Put timestamp in avatar filenames to avoid cache problems
This commit is contained in:
parent
f1e2e99663
commit
36bb2ce2d5
|
@ -42,6 +42,18 @@ var Config = HMNConfig{
|
|||
AssetsPathPrefix: "", // Empty is fine for production, but may be necessary for dev
|
||||
AssetsPublicUrlRoot: "", // e.g. "https://bucket-name.region.cdn.digitaloceanspaces.com/". Note the trailing slash...
|
||||
},
|
||||
Discord: DiscordConfig{
|
||||
BotToken: "",
|
||||
BotUserID: "",
|
||||
|
||||
OAuthClientID: "",
|
||||
OAuthClientSecret: "",
|
||||
|
||||
GuildID: "",
|
||||
MemberRoleID: "",
|
||||
ShowcaseChannelID: "",
|
||||
LibraryChannelID: "",
|
||||
},
|
||||
EpisodeGuide: EpisodeGuide{
|
||||
CineraOutputPath: "./annotations/",
|
||||
Projects: map[string]string{"hero": "code", "riscy": "riscy", "bitwise": "bitwise"},
|
||||
|
|
|
@ -167,7 +167,7 @@ func Scrape(ctx context.Context, dbConn *pgxpool.Pool, channelID string, earlies
|
|||
return
|
||||
}
|
||||
|
||||
err := handleHistoryMessage(ctx, dbConn, &msg, true)
|
||||
err := handleHistoryMessage(ctx, dbConn, &msg, createSnippets)
|
||||
if err != nil {
|
||||
errLog := logging.ExtractLogger(ctx).Error()
|
||||
if errors.Is(err, errNotEnoughInfo) {
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"git.handmade.network/hmn/hmn/src/migration/types"
|
||||
"git.handmade.network/hmn/hmn/src/oops"
|
||||
"github.com/jackc/pgx/v4"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerMigration(ImageFileNotNull{})
|
||||
}
|
||||
|
||||
type ImageFileNotNull struct{}
|
||||
|
||||
func (m ImageFileNotNull) Version() types.MigrationVersion {
|
||||
return types.MigrationVersion(time.Date(2021, 9, 8, 0, 43, 57, 0, time.UTC))
|
||||
}
|
||||
|
||||
func (m ImageFileNotNull) Name() string {
|
||||
return "ImageFileNotNull"
|
||||
}
|
||||
|
||||
func (m ImageFileNotNull) Description() string {
|
||||
return "Don't allow the filename of an image file to be null"
|
||||
}
|
||||
|
||||
func (m ImageFileNotNull) Up(ctx context.Context, tx pgx.Tx) error {
|
||||
_, err := tx.Exec(ctx, `
|
||||
ALTER TABLE handmade_imagefile
|
||||
ALTER file SET NOT NULL;
|
||||
`)
|
||||
if err != nil {
|
||||
return oops.New(err, "failed to make imagefile filename not nullable")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m ImageFileNotNull) Down(ctx context.Context, tx pgx.Tx) error {
|
||||
_, err := tx.Exec(ctx, `
|
||||
ALTER TABLE handmade_imagefile
|
||||
ALTER file SET NULL;
|
||||
`)
|
||||
if err != nil {
|
||||
return oops.New(err, "failed to make imagefile filename nullable again")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package models
|
||||
|
||||
type ImageFile struct {
|
||||
ID int `db:"id"`
|
||||
File string `db:"file"` // relative to public/media
|
||||
Size int `db:"size"`
|
||||
Sha1Sum string `db:"sha1sum"`
|
||||
Protected bool `db:"protected"`
|
||||
Height int `db:"height"`
|
||||
Width int `db:"width"`
|
||||
}
|
|
@ -11,11 +11,12 @@ import (
|
|||
"os"
|
||||
|
||||
"git.handmade.network/hmn/hmn/src/db"
|
||||
"git.handmade.network/hmn/hmn/src/models"
|
||||
"git.handmade.network/hmn/hmn/src/oops"
|
||||
)
|
||||
|
||||
type SaveImageFileResult struct {
|
||||
ImageFileID int
|
||||
ImageFile *models.ImageFile
|
||||
ValidationError string
|
||||
FatalError error
|
||||
}
|
||||
|
@ -88,15 +89,15 @@ func SaveImageFile(c *RequestContext, dbConn db.ConnOrTx, fileFieldName string,
|
|||
img.Seek(0, io.SeekStart)
|
||||
io.Copy(hasher, img) // NOTE(asaf): Writing to hash.Hash never returns an error according to the docs
|
||||
sha1sum := hasher.Sum(nil)
|
||||
var imageId int
|
||||
err = dbConn.QueryRow(c.Context(),
|
||||
// TODO(db): Should use insert helper
|
||||
imageFile, err := db.QueryOne(c.Context(), dbConn, models.ImageFile{},
|
||||
`
|
||||
INSERT INTO handmade_imagefile (file, size, sha1sum, protected, width, height)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING id
|
||||
RETURNING $columns
|
||||
`,
|
||||
filename, header.Size, hex.EncodeToString(sha1sum), false, width, height,
|
||||
).Scan(&imageId)
|
||||
)
|
||||
if err != nil {
|
||||
return SaveImageFileResult{
|
||||
FatalError: oops.New(err, "Failed to insert image file row"),
|
||||
|
@ -104,7 +105,7 @@ func SaveImageFile(c *RequestContext, dbConn db.ConnOrTx, fileFieldName string,
|
|||
}
|
||||
|
||||
return SaveImageFileResult{
|
||||
ImageFileID: imageId,
|
||||
ImageFile: imageFile.(*models.ImageFile),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ func PodcastEditSubmit(c *RequestContext) ResponseData {
|
|||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(imageSaveResult.FatalError, "Failed to save podcast image"))
|
||||
}
|
||||
|
||||
if imageSaveResult.ImageFileID != 0 {
|
||||
if imageSaveResult.ImageFile != nil {
|
||||
_, err = tx.Exec(c.Context(),
|
||||
`
|
||||
UPDATE handmade_podcast
|
||||
|
@ -168,7 +168,7 @@ func PodcastEditSubmit(c *RequestContext) ResponseData {
|
|||
`,
|
||||
title,
|
||||
description,
|
||||
imageSaveResult.ImageFileID,
|
||||
imageSaveResult.ImageFile.ID,
|
||||
podcastResult.Podcast.ID,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.handmade.network/hmn/hmn/src/auth"
|
||||
"git.handmade.network/hmn/hmn/src/config"
|
||||
|
@ -452,11 +453,26 @@ func UserSettingsSave(c *RequestContext) ResponseData {
|
|||
}
|
||||
|
||||
// Update avatar
|
||||
imageSaveResult := SaveImageFile(c, tx, "avatar", 1*1024*1024, fmt.Sprintf("members/avatars/%s", c.CurrentUser.Username))
|
||||
imageSaveResult := SaveImageFile(c, tx, "avatar", 1*1024*1024, fmt.Sprintf("members/avatars/%s-%d", c.CurrentUser.Username, time.Now().UTC().Unix()))
|
||||
if imageSaveResult.ValidationError != "" {
|
||||
return RejectRequest(c, imageSaveResult.ValidationError)
|
||||
} else if imageSaveResult.FatalError != nil {
|
||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(imageSaveResult.FatalError, "failed to save new avatar"))
|
||||
} else if imageSaveResult.ImageFile != nil {
|
||||
_, err = tx.Exec(c.Context(),
|
||||
`
|
||||
UPDATE auth_user
|
||||
SET
|
||||
avatar = $2
|
||||
WHERE
|
||||
id = $1
|
||||
`,
|
||||
c.CurrentUser.ID,
|
||||
imageSaveResult.ImageFile.File,
|
||||
)
|
||||
if err != nil {
|
||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to update user"))
|
||||
}
|
||||
}
|
||||
|
||||
err = tx.Commit(c.Context())
|
||||
|
|
Loading…
Reference in New Issue