package classes import ( "context" "errors" "strconv" "git.golem15.com/golem15/sm-user-plugin/models" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/lagoon/attach" "gocloud.dev/blob" "gorm.io/gorm" ) // OrganisationLogoSize is the edge in pixels of the logo thumbnail // OrganisationLogoFields answers. const OrganisationLogoSize = 256 // organisationLogo loads the organisation's logo attachment, or nil. func organisationLogo(ctx context.Context, app *backpack.App, org *models.Organisation) (*attach.File, error) { if app == nil || org == nil || org.ID == 0 { return nil, nil } gdb, ok := app.Lookup[*gorm.DB]() if !ok || gdb == nil { return nil, nil } var f attach.File err := gdb.WithContext(ctx). Where("attachment_type = ? AND attachment_id = ? AND field = ?", org.MorphName(), strconv.FormatUint(uint64(org.ID), 10), models.OrganisationLogoField). Take(&f).Error if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } if err != nil { return nil, err } return &f, nil } // OrganisationLogoURL returns the URL of the organisation's logo at size // pixels, the way AvatarURL serves a user's picture: the thumbnail (size by // size, mode auto) of the logo attachment, or the attachment's file path // when the thumbnail fails (logged). It answers false when the organisation // has no logo or no file bucket is published. The URL may be relative; a // caller that needs an absolute URL resolves it. Only a failing database // lookup is an error. func OrganisationLogoURL(ctx context.Context, app *backpack.App, org *models.Organisation, size int) (string, bool, error) { f, err := organisationLogo(ctx, app, org) if err != nil || f == nil { return "", false, err } bucket, ok := app.Lookup[*blob.Bucket]() if !ok || bucket == nil { return "", false, nil } url, err := f.Thumb(ctx, bucket, size, size, "auto") if err != nil { pluginLog.Error("golem15.user: organisation logo thumb", "err", err) return "/" + attach.BlobKey(f.DiskName), true, nil } return url, true, nil } // OrganisationLogoFields answers the logo keys an application adds to its // own organisation payloads, named like the user payload's avatar keys: // has_logo (bool), logo (the attachment's disk name, or nil) and logo_url // (the OrganisationLogoSize thumbnail URL, or nil). An organisation without // a logo answers false, nil and nil. Only a failing database lookup is an // error. func OrganisationLogoFields(ctx context.Context, app *backpack.App, org *models.Organisation) (map[string]any, error) { out := map[string]any{"has_logo": false, "logo": nil, "logo_url": nil} f, err := organisationLogo(ctx, app, org) if err != nil { return nil, err } if f == nil { return out, nil } out["has_logo"] = true out["logo"] = f.DiskName url, ok, err := OrganisationLogoURL(ctx, app, org, OrganisationLogoSize) if err != nil { return nil, err } if ok && url != "" { out["logo_url"] = url } return out, nil }