Removed old project logo url fields

This commit is contained in:
Asaf Gartner 2022-02-13 22:07:09 +02:00
parent d32cd0a849
commit 8e7c20fffa
7 changed files with 62 additions and 158 deletions

View File

@ -1,23 +1,16 @@
package admintools package admintools
import ( import (
"bytes"
"context" "context"
"errors" "errors"
"fmt" "fmt"
"image"
"net/http"
"os" "os"
"path"
"strconv" "strconv"
"strings"
"time" "time"
"git.handmade.network/hmn/hmn/src/assets"
"git.handmade.network/hmn/hmn/src/auth" "git.handmade.network/hmn/hmn/src/auth"
"git.handmade.network/hmn/hmn/src/db" "git.handmade.network/hmn/hmn/src/db"
"git.handmade.network/hmn/hmn/src/email" "git.handmade.network/hmn/hmn/src/email"
"git.handmade.network/hmn/hmn/src/hmndata"
"git.handmade.network/hmn/hmn/src/logging" "git.handmade.network/hmn/hmn/src/logging"
"git.handmade.network/hmn/hmn/src/models" "git.handmade.network/hmn/hmn/src/models"
"git.handmade.network/hmn/hmn/src/oops" "git.handmade.network/hmn/hmn/src/oops"
@ -360,140 +353,5 @@ func init() {
moveThreadsToSubforumCommand.MarkFlagRequired("subforum_slug") moveThreadsToSubforumCommand.MarkFlagRequired("subforum_slug")
adminCommand.AddCommand(moveThreadsToSubforumCommand) adminCommand.AddCommand(moveThreadsToSubforumCommand)
uploadProjectLogos := &cobra.Command{
Use: "uploadprojectlogos",
Short: "Uploads project imagefiles to S3 and replaces them with assets",
Run: func(cmd *cobra.Command, args []string) {
ctx := context.Background()
conn := db.NewConnPool(1, 1)
defer conn.Close()
allProjects, err := db.Query(ctx, conn, models.Project{}, `SELECT $columns FROM handmade_project`)
if err != nil {
panic(oops.New(err, "Failed to fetch projects from db"))
}
var fixupProjects []*models.Project
numImages := 0
for _, project := range allProjects {
p := project.(*models.Project)
if p.LogoLight != "" || p.LogoDark != "" {
fixupProjects = append(fixupProjects, p)
}
if p.LogoLight != "" {
numImages += 1
}
if p.LogoDark != "" {
numImages += 1
}
}
fmt.Printf("%d images to upload\n", numImages)
uploadImage := func(ctx context.Context, conn db.ConnOrTx, filepath string, owner *models.User) *models.Asset {
filepath = "./public/media/" + filepath
contents, err := os.ReadFile(filepath)
if err != nil {
panic(oops.New(err, fmt.Sprintf("Failed to read file: %s", filepath)))
}
width := 0
height := 0
mime := ""
fileExtensionOverrides := []string{".svg"}
fileExt := strings.ToLower(path.Ext(filepath))
tryDecode := true
for _, ext := range fileExtensionOverrides {
if fileExt == ext {
tryDecode = false
}
}
if tryDecode {
config, _, err := image.DecodeConfig(bytes.NewReader(contents))
if err != nil {
panic(oops.New(err, fmt.Sprintf("Failed to decode file: %s", filepath)))
}
width = config.Width
height = config.Height
mime = http.DetectContentType(contents)
} else {
if fileExt == ".svg" {
mime = "image/svg+xml"
}
}
filename := path.Base(filepath)
asset, err := assets.Create(ctx, conn, assets.CreateInput{
Content: contents,
Filename: filename,
ContentType: mime,
UploaderID: &owner.ID,
Width: width,
Height: height,
})
if err != nil {
panic(oops.New(err, "Failed to create asset"))
}
return asset
}
for _, p := range fixupProjects {
owners, err := hmndata.FetchProjectOwners(ctx, conn, p.ID)
if err != nil {
panic(oops.New(err, "Failed to fetch project owners"))
}
if len(owners) == 0 {
fmt.Printf("PROBLEM!! Project %d (%s) doesn't have owners!!\n", p.ID, p.Name)
continue
}
if p.LogoLight != "" {
lightAsset := uploadImage(ctx, conn, p.LogoLight, owners[0])
_, err := conn.Exec(ctx,
`
UPDATE handmade_project
SET
logolight_asset_id = $2,
logolight = NULL
WHERE
id = $1
`,
p.ID,
lightAsset.ID,
)
if err != nil {
panic(oops.New(err, "Failed to update project"))
}
numImages -= 1
fmt.Printf(".")
}
if p.LogoDark != "" {
darkAsset := uploadImage(ctx, conn, p.LogoDark, owners[0])
_, err := conn.Exec(ctx,
`
UPDATE handmade_project
SET
logodark_asset_id = $2,
logodark = NULL
WHERE
id = $1
`,
p.ID,
darkAsset.ID,
)
if err != nil {
panic(oops.New(err, "Failed to update project"))
}
numImages -= 1
fmt.Printf(".")
}
}
fmt.Printf("\nDone! %d images not patched for some reason.\n\n", numImages)
},
}
adminCommand.AddCommand(uploadProjectLogos)
addProjectCommands(adminCommand) addProjectCommands(adminCommand)
} }

View File

@ -0,0 +1,49 @@
package migrations
import (
"context"
"time"
"git.handmade.network/hmn/hmn/src/migration/types"
"github.com/jackc/pgx/v4"
)
func init() {
registerMigration(RemoveProjectLogoUrls{})
}
type RemoveProjectLogoUrls struct{}
func (m RemoveProjectLogoUrls) Version() types.MigrationVersion {
return types.MigrationVersion(time.Date(2022, 2, 13, 20, 1, 55, 0, time.UTC))
}
func (m RemoveProjectLogoUrls) Name() string {
return "RemoveProjectLogoUrls"
}
func (m RemoveProjectLogoUrls) Description() string {
return "Remove project logo url fields as we're now using assets"
}
func (m RemoveProjectLogoUrls) Up(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
ALTER TABLE handmade_project
DROP COLUMN logolight,
DROP COLUMN logodark;
`,
)
return err
}
func (m RemoveProjectLogoUrls) Down(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
ALTER TABLE handmade_project
ADD COLUMN logolight character varying(100),
ADD COLUMN logodark character varying(100);
`,
)
return err
}

View File

@ -72,9 +72,6 @@ type Project struct {
Color1 string `db:"color_1"` Color1 string `db:"color_1"`
Color2 string `db:"color_2"` Color2 string `db:"color_2"`
LogoLight string `db:"logolight"`
LogoDark string `db:"logodark"`
Personal bool `db:"personal"` Personal bool `db:"personal"`
Hidden bool `db:"hidden"` Hidden bool `db:"hidden"`
Featured bool `db:"featured"` Featured bool `db:"featured"`

View File

@ -64,16 +64,13 @@ func ProjectLogoUrl(p *models.Project, lightAsset *models.Asset, darkAsset *mode
if theme == "dark" { if theme == "dark" {
if darkAsset != nil { if darkAsset != nil {
return hmnurl.BuildS3Asset(darkAsset.S3Key) return hmnurl.BuildS3Asset(darkAsset.S3Key)
} else {
return hmnurl.BuildUserFile(p.LogoDark)
} }
} else { } else {
if lightAsset != nil { if lightAsset != nil {
return hmnurl.BuildS3Asset(lightAsset.S3Key) return hmnurl.BuildS3Asset(lightAsset.S3Key)
} else {
return hmnurl.BuildUserFile(p.LogoLight)
} }
} }
return ""
} }
func ProjectToTemplate( func ProjectToTemplate(

View File

@ -58,7 +58,7 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc
ReportIssueMailto: "team@handmade.network", ReportIssueMailto: "team@handmade.network",
OpenGraphItems: buildDefaultOpenGraphItems(&project, title), OpenGraphItems: buildDefaultOpenGraphItems(&project, c.CurrentProjectLogoUrl, title),
IsProjectPage: !project.IsHMN(), IsProjectPage: !project.IsHMN(),
Header: templates.Header{ Header: templates.Header{
@ -114,14 +114,14 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc
return baseData return baseData
} }
func buildDefaultOpenGraphItems(project *models.Project, title string) []templates.OpenGraphItem { func buildDefaultOpenGraphItems(project *models.Project, projectLogoUrl string, title string) []templates.OpenGraphItem {
if title == "" { if title == "" {
title = "Handmade Network" title = "Handmade Network"
} }
image := hmnurl.BuildPublic("logo.png", false) image := hmnurl.BuildPublic("logo.png", false)
if !project.IsHMN() { if !project.IsHMN() {
image = hmnurl.BuildUserFile(project.LogoLight) image = projectLogoUrl
} }
return []templates.OpenGraphItem{ return []templates.OpenGraphItem{

View File

@ -159,12 +159,13 @@ type RequestContext struct {
// We sometimes need the original response object so that some functions of the http package can set connection-management flags on it. // We sometimes need the original response object so that some functions of the http package can set connection-management flags on it.
Res http.ResponseWriter Res http.ResponseWriter
Conn *pgxpool.Pool Conn *pgxpool.Pool
CurrentProject *models.Project CurrentProject *models.Project
CurrentUser *models.User CurrentProjectLogoUrl string
CurrentSession *models.Session CurrentUser *models.User
Theme string CurrentSession *models.Session
UrlContext *hmnurl.UrlContext Theme string
UrlContext *hmnurl.UrlContext
CurrentUserCanEditCurrentProject bool CurrentUserCanEditCurrentProject bool

View File

@ -476,6 +476,7 @@ func LoadCommonWebsiteData(c *RequestContext) (bool, ResponseData) {
}) })
if err == nil { if err == nil {
c.CurrentProject = &dbProject.Project c.CurrentProject = &dbProject.Project
c.CurrentProjectLogoUrl = templates.ProjectLogoUrl(&dbProject.Project, dbProject.LogoLightAsset, dbProject.LogoDarkAsset, c.Theme)
owners = dbProject.Owners owners = dbProject.Owners
} else { } else {
if errors.Is(err, db.NotFound) { if errors.Is(err, db.NotFound) {
@ -495,6 +496,7 @@ func LoadCommonWebsiteData(c *RequestContext) (bool, ResponseData) {
panic(oops.New(err, "failed to fetch HMN project")) panic(oops.New(err, "failed to fetch HMN project"))
} }
c.CurrentProject = &dbProject.Project c.CurrentProject = &dbProject.Project
c.CurrentProjectLogoUrl = templates.ProjectLogoUrl(&dbProject.Project, dbProject.LogoLightAsset, dbProject.LogoDarkAsset, c.Theme)
} }
if c.CurrentProject == nil { if c.CurrentProject == nil {