avatar

package
v2.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 36 Imported by: 3

Documentation

Overview

Package avatar implements avatart proxy for oauth and defines store interface and implements local (fs), gridfs (mongo) and boltdb stores.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("avatar not found")

ErrNotFound is returned by Store.Remove when the requested avatar does not exist, so callers can tell a missing avatar from a real failure with errors.Is.

Functions

func GenerateAvatar

func GenerateAvatar(user string) ([]byte, error)

GenerateAvatar for give user with identicon

func GetGravatarURL

func GetGravatarURL(email string) (res string, err error)

GetGravatarURL returns url to gravatar picture for given email

func Migrate

func Migrate(dst, src Store) (int, error)

Migrate copies avatars from src to dst, returning the number of ids enumerated from src and the first List error if any. Per-avatar Get/Put/Close failures are logged with [WARN] and skipped — they do not abort the migration or surface in the returned error, so the returned count is "ids attempted", not "ids stored".

Types

type BoltDB

type BoltDB struct {
	// contains filtered or unexported fields
}

BoltDB implements avatar store with bolt using separate db (file) with "avatars" bucket to keep image bin and "metas" bucket to keep a sha1 fingerprint of the stored bytes. avatarID (base file name) used as a key for both.

func NewBoltDB

func NewBoltDB(fileName string, options bolt.Options) (*BoltDB, error)

NewBoltDB makes bolt avatar store

func (*BoltDB) Close

func (b *BoltDB) Close() error

Close bolt store

func (*BoltDB) Get

func (b *BoltDB) Get(avatarID string) (reader io.ReadCloser, size int, err error)

Get avatar reader for avatar id.image, avatarID used as the direct key

func (*BoltDB) ID

func (b *BoltDB) ID(avatarID string) (id string)

ID returns a fingerprint of the avatar content.

func (*BoltDB) List

func (b *BoltDB) List() (ids []string, err error)

List all avatars (ids) from metas bucket note: id includes .image suffix

func (*BoltDB) Put

func (b *BoltDB) Put(userID string, reader io.Reader) (avatar string, err error)

Put stores avatar bytes read from reader in the "avatars" bucket and a sha1 of the same bytes in the "metas" bucket, both keyed by the encoded userID with .image suffix. Resizing happens upstream in Proxy.resize; this layer only writes what it is given.

func (*BoltDB) Remove

func (b *BoltDB) Remove(avatarID string) (err error)

Remove avatar from bolt

func (*BoltDB) String

func (b *BoltDB) String() string

type GridFS

type GridFS struct {
	// contains filtered or unexported fields
}

GridFS implements Store for GridFS

func NewGridFS

func NewGridFS(client *mongo.Client, dbName, bucketName string, timeout time.Duration) *GridFS

NewGridFS makes gridfs (mongo) avatar store

func (*GridFS) Close

func (gf *GridFS) Close() error

Close gridfs store

func (*GridFS) Get

func (gf *GridFS) Get(avatar string) (reader io.ReadCloser, size int, err error)

Get avatar reader for avatar id.image

func (*GridFS) ID

func (gf *GridFS) ID(avatar string) (id string)

ID returns the sha1 fingerprint of the avatar content stored in the GridFS file's metadata at Put time, or an encoded fallback id when the file lookup/decode fails.

func (*GridFS) List

func (gf *GridFS) List() (ids []string, err error)

List all avatars (ids) on gfs note: id includes .image suffix

func (*GridFS) Put

func (gf *GridFS) Put(userID string, reader io.Reader) (avatar string, err error)

Put stores avatar bytes read from reader in GridFS, keyed by the encoded userID with .image suffix, and records the sha1 of those bytes in the file's metadata. Resizing happens upstream in Proxy.resize; this layer only writes what it is given.

func (*GridFS) Remove

func (gf *GridFS) Remove(avatar string) error

Remove avatar from gridfs

func (*GridFS) String

func (gf *GridFS) String() string

type LocalFS

type LocalFS struct {
	// contains filtered or unexported fields
}

LocalFS implements Store for local file system

func NewLocalFS

func NewLocalFS(storePath string) *LocalFS

NewLocalFS makes file-system avatar store

func (*LocalFS) Close

func (fs *LocalFS) Close() error

Close LocalFS does nothing but satisfies interface

func (*LocalFS) Get

func (fs *LocalFS) Get(avatar string) (reader io.ReadCloser, size int, err error)

Get avatar reader for avatar id.image

func (*LocalFS) ID

func (fs *LocalFS) ID(avatar string) (id string)

ID returns a fingerprint of the avatar content.

func (*LocalFS) List

func (fs *LocalFS) List() (ids []string, err error)

List all avatars (ids) on local file system note: id includes .image suffix

func (*LocalFS) Put

func (fs *LocalFS) Put(userID string, reader io.Reader) (avatar string, err error)

Put avatar for userID to file and return avatar's file name (base), like 12345678.image userID can be avatarID as well, in this case encoding just strip .image prefix

func (*LocalFS) Remove

func (fs *LocalFS) Remove(avatar string) error

Remove avatar file

func (*LocalFS) String

func (fs *LocalFS) String() string

type NoOp

type NoOp struct{}

NoOp is an empty (no-op) implementation of Store interface

func NewNoOp

func NewNoOp() *NoOp

NewNoOp provides an empty (no-op) implementation of Store interface

func (*NoOp) Close

func (s *NoOp) Close() error

Close is a NoOp implementation

func (*NoOp) Get

func (s *NoOp) Get(string) (reader io.ReadCloser, size int, err error)

Get is a NoOp implementation

func (*NoOp) ID

func (s *NoOp) ID(string) (id string)

ID is a NoOp implementation

func (*NoOp) List

func (s *NoOp) List() (ids []string, err error)

List is a NoOp implementation

func (*NoOp) Put

func (s *NoOp) Put(string, io.Reader) (avatarID string, err error)

Put is a NoOp implementation

func (*NoOp) Remove

func (s *NoOp) Remove(string) error

Remove is a NoOp implementation

func (*NoOp) String

func (s *NoOp) String() string

String is a NoOp implementation

type Proxy

type Proxy struct {
	logger.L
	Store       Store
	RoutePath   string
	URL         string
	ResizeLimit int
}

Proxy provides http handler for avatars from avatar.Store On user login token will call Put and it will retrieve and save picture locally.

func (*Proxy) Handler

func (p *Proxy) Handler(w http.ResponseWriter, r *http.Request)

Handler serves stored avatar content by avatar id. GET only; rejects invalid ids (403) and stored bytes that fail the safeImgContentType sniff (415). Layered defense headers are set on every response via setAvatarDefenseHeaders.

func (*Proxy) Put

func (p *Proxy) Put(u token.User, client *http.Client) (avatarURL string, err error)

Put fetches u.Picture, validates and optionally resizes the body, stores it via Store, and returns the proxied avatar URL. If u.Picture is empty, the fetch fails, or the upstream bytes are not a recognized image format within the configured dimension and size limits, Put silently falls back to a generated identicon and returns its proxied URL — the caller is not told upstream was rejected.

func (*Proxy) PutContent added in v2.1.3

func (p *Proxy) PutContent(userID string, content io.Reader) (avatarURL string, err error)

PutContent stores already-fetched avatar bytes via the underlying Store and returns the proxied URL. It exists so providers that authenticate with credentials embedded in the upstream URL (e.g. Telegram bot file API: /file/bot{TOKEN}/...) can fetch the content themselves and avoid exposing the credential to Put's URL-fetching path — where it would land in u.Picture, debug logs, and the user JSON returned to clients.

Bytes are read into memory bounded by maxAvatarFetchSize so an unbounded caller (e.g. a streaming HTTP body) cannot exhaust process memory.

type Store

type Store interface {
	fmt.Stringer
	Put(userID string, reader io.Reader) (avatarID string, err error) // save avatar data from the reader and return base name
	Get(avatarID string) (reader io.ReadCloser, size int, err error)  // load avatar via reader
	ID(avatarID string) (id string)                                   // unique id of stored avatar's data
	Remove(avatarID string) error                                     // remove avatar data
	List() (ids []string, err error)                                  // list all avatar ids
	Close() error                                                     // close store
}

Store defines interface to store and load avatars

func NewStore

func NewStore(uri string) (Store, error)

NewStore provides factory for all supported stores making the one based on uri protocol. Default (no protocol) is file-system

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL