feat(api): add display_name to member
This commit is contained in:
parent
c4ddde73ec
commit
73c5c9fc67
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- +migrate Up
|
||||||
|
|
||||||
|
-- 2022-11-20: add display name to members
|
||||||
|
alter table members add column display_name text;
|
Loading…
Reference in New Issue