feat(api): add display_name to member

This commit is contained in:
Sam 2022-11-20 21:09:29 +01:00
parent c4ddde73ec
commit 73c5c9fc67
7 changed files with 61 additions and 39 deletions

View file

@ -13,12 +13,13 @@ import (
const MaxMemberCount = 500 const MaxMemberCount = 500
type Member struct { type Member struct {
ID xid.ID ID xid.ID
UserID xid.ID UserID xid.ID
Name string Name string
Bio *string DisplayName *string
AvatarURLs []string `db:"avatar_urls"` Bio *string
Links []string AvatarURLs []string `db:"avatar_urls"`
Links []string
} }
const ( const (
@ -79,10 +80,10 @@ func (db *DB) UserMembers(ctx context.Context, userID xid.ID) (ms []Member, err
} }
// CreateMember creates a member. // CreateMember creates a member.
func (db *DB) CreateMember(ctx context.Context, tx pgx.Tx, userID xid.ID, name, bio string, links []string) (m Member, err error) { func (db *DB) CreateMember(ctx context.Context, tx pgx.Tx, userID xid.ID, name string, displayName *string, bio string, links []string) (m Member, err error) {
sql, args, err := sq.Insert("members"). sql, args, err := sq.Insert("members").
Columns("user_id", "id", "name", "bio", "links"). Columns("user_id", "id", "name", "display_name", "bio", "links").
Values(userID, xid.New(), name, bio, links). Values(userID, xid.New(), name, displayName, bio, links).
Suffix("RETURNING *").ToSql() Suffix("RETURNING *").ToSql()
if err != nil { if err != nil {
return m, errors.Wrap(err, "building sql") return m, errors.Wrap(err, "building sql")

View file

@ -12,13 +12,14 @@ import (
) )
type CreateMemberRequest struct { type CreateMemberRequest struct {
Name string `json:"name"` Name string `json:"name"`
Bio string `json:"bio"` DisplayName *string `json:"display_name"`
Avatar string `json:"avatar"` Bio string `json:"bio"`
Links []string `json:"links"` Avatar string `json:"avatar"`
Names []db.Name `json:"names"` Links []string `json:"links"`
Pronouns []db.Pronoun `json:"pronouns"` Names []db.Name `json:"names"`
Fields []db.Field `json:"fields"` Pronouns []db.Pronoun `json:"pronouns"`
Fields []db.Field `json:"fields"`
} }
func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error) { func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error) {
@ -54,7 +55,12 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error
if cmr.Name == "" { if cmr.Name == "" {
return server.APIError{ return server.APIError{
Code: server.ErrBadRequest, Code: server.ErrBadRequest,
Details: "name may not be empty", Details: "Name may not be empty",
}
} else if len(cmr.Name) > 100 {
return server.APIError{
Code: server.ErrBadRequest,
Details: "Name may not be longer than 100 characters",
} }
} }
@ -76,25 +82,29 @@ func (s *Server) createMember(w http.ResponseWriter, r *http.Request) (err error
} }
defer tx.Rollback(ctx) defer tx.Rollback(ctx)
m, err := s.DB.CreateMember(ctx, tx, claims.UserID, cmr.Name, cmr.Bio, cmr.Links) m, err := s.DB.CreateMember(ctx, tx, claims.UserID, cmr.Name, cmr.DisplayName, cmr.Bio, cmr.Links)
if err != nil { if err != nil {
if errors.Cause(err) == db.ErrMemberNameInUse {
return server.APIError{Code: server.ErrMemberNameInUse}
}
return err return err
} }
// set names, pronouns, fields // set names, pronouns, fields
err = s.DB.SetMemberNames(ctx, tx, claims.UserID, cmr.Names) err = s.DB.SetMemberNames(ctx, tx, m.ID, cmr.Names)
if err != nil { if err != nil {
log.Errorf("setting names for user %v: %v", claims.UserID, err) log.Errorf("setting names for member %v: %v", m.ID, err)
return err return err
} }
err = s.DB.SetMemberPronouns(ctx, tx, claims.UserID, cmr.Pronouns) err = s.DB.SetMemberPronouns(ctx, tx, m.ID, cmr.Pronouns)
if err != nil { if err != nil {
log.Errorf("setting pronouns for user %v: %v", claims.UserID, err) log.Errorf("setting pronouns for member %v: %v", m.ID, err)
return err return err
} }
err = s.DB.SetMemberFields(ctx, tx, claims.UserID, cmr.Fields) err = s.DB.SetMemberFields(ctx, tx, m.ID, cmr.Fields)
if err != nil { if err != nil {
log.Errorf("setting fields for user %v: %v", claims.UserID, err) log.Errorf("setting fields for member %v: %v", m.ID, err)
return err return err
} }

View file

@ -12,11 +12,12 @@ import (
) )
type GetMemberResponse struct { type GetMemberResponse struct {
ID xid.ID `json:"id"` ID xid.ID `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Bio *string `json:"bio"` DisplayName *string `json:"display_name"`
AvatarURLs []string `json:"avatar_urls"` Bio *string `json:"bio"`
Links []string `json:"links"` AvatarURLs []string `json:"avatar_urls"`
Links []string `json:"links"`
Names []db.Name `json:"names"` Names []db.Name `json:"names"`
Pronouns []db.Pronoun `json:"pronouns"` Pronouns []db.Pronoun `json:"pronouns"`
@ -27,11 +28,12 @@ type GetMemberResponse struct {
func dbMemberToMember(u db.User, m db.Member, names []db.Name, pronouns []db.Pronoun, fields []db.Field) GetMemberResponse { func dbMemberToMember(u db.User, m db.Member, names []db.Name, pronouns []db.Pronoun, fields []db.Field) GetMemberResponse {
return GetMemberResponse{ return GetMemberResponse{
ID: m.ID, ID: m.ID,
Name: m.Name, Name: m.Name,
Bio: m.Bio, DisplayName: m.DisplayName,
AvatarURLs: m.AvatarURLs, Bio: m.Bio,
Links: m.Links, AvatarURLs: m.AvatarURLs,
Links: m.Links,
Names: names, Names: names,
Pronouns: pronouns, Pronouns: pronouns,

View file

@ -11,11 +11,12 @@ import (
) )
type memberListResponse struct { type memberListResponse struct {
ID xid.ID `json:"id"` ID xid.ID `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Bio *string `json:"bio"` DisplayName *string `json:"display_name"`
AvatarURLs []string `json:"avatar_urls"` Bio *string `json:"bio"`
Links []string `json:"links"` AvatarURLs []string `json:"avatar_urls"`
Links []string `json:"links"`
} }
func membersToMemberList(ms []db.Member) []memberListResponse { func membersToMemberList(ms []db.Member) []memberListResponse {

View file

@ -90,6 +90,7 @@ const (
// Member-related error codes // Member-related error codes
ErrMemberNotFound = 3001 ErrMemberNotFound = 3001
ErrMemberLimitReached = 3002 ErrMemberLimitReached = 3002
ErrMemberNameInUse = 3003
// General request error codes // General request error codes
ErrRequestTooBig = 4001 ErrRequestTooBig = 4001
@ -118,6 +119,7 @@ var errCodeMessages = map[int]string{
ErrMemberNotFound: "Member not found", ErrMemberNotFound: "Member not found",
ErrMemberLimitReached: "Member limit reached", ErrMemberLimitReached: "Member limit reached",
ErrMemberNameInUse: "Member name already in use",
ErrRequestTooBig: "Request too big (max 2 MB)", ErrRequestTooBig: "Request too big (max 2 MB)",
} }
@ -145,6 +147,7 @@ var errCodeStatuses = map[int]int{
ErrMemberNotFound: http.StatusNotFound, ErrMemberNotFound: http.StatusNotFound,
ErrMemberLimitReached: http.StatusBadRequest, ErrMemberLimitReached: http.StatusBadRequest,
ErrMemberNameInUse: http.StatusBadRequest,
ErrRequestTooBig: http.StatusBadRequest, ErrRequestTooBig: http.StatusBadRequest,
} }

View file

@ -19,6 +19,7 @@ export interface User {
export interface PartialMember { export interface PartialMember {
id: string; id: string;
name: string; name: string;
display_name: string | null;
avatar_urls: string[] | null; avatar_urls: string[] | null;
} }

View file

@ -0,0 +1,4 @@
-- +migrate Up
-- 2022-11-20: add display name to members
alter table members add column display_name text;