fix
This commit is contained in:
@@ -20,20 +20,25 @@ func (s *Server) handleGetCompany(w http.ResponseWriter, r *http.Request) {
|
||||
name, language string
|
||||
merge bool
|
||||
contentLangs []string
|
||||
ownerUserID *uuid.UUID
|
||||
)
|
||||
err := s.Pool.QueryRow(r.Context(), `
|
||||
SELECT id, name, language, merge_products_by_gtin, COALESCE(content_languages, '{}')
|
||||
SELECT id, name, language, merge_products_by_gtin, COALESCE(content_languages, '{}'), owner_user_id
|
||||
FROM companies WHERE id = $1`, cid).
|
||||
Scan(&id, &name, &language, &merge, &contentLangs)
|
||||
Scan(&id, &name, &language, &merge, &contentLangs, &ownerUserID)
|
||||
if err != nil {
|
||||
Error(w, http.StatusNotFound, "company not found")
|
||||
return
|
||||
}
|
||||
parsed, _ := company.ParseContentLanguages(contentLangs, language)
|
||||
JSON(w, http.StatusOK, map[string]any{
|
||||
out := map[string]any{
|
||||
"id": id, "name": name, "language": language,
|
||||
"content_languages": parsed, "merge_products_by_gtin": merge,
|
||||
})
|
||||
}
|
||||
if ownerUserID != nil {
|
||||
out["owner_user_id"] = *ownerUserID
|
||||
}
|
||||
JSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
func (s *Server) handleUpdateCompany(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -150,6 +155,8 @@ func (s *Server) handlePutCompanySettings(w http.ResponseWriter, r *http.Request
|
||||
func (s *Server) handleListTeam(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
limit, offset := ParseLimitOffset(r)
|
||||
var ownerUserID *uuid.UUID
|
||||
_ = s.Pool.QueryRow(r.Context(), `SELECT owner_user_id FROM companies WHERE id = $1`, cid).Scan(&ownerUserID)
|
||||
var total int64
|
||||
if err := s.Pool.QueryRow(r.Context(), `
|
||||
SELECT count(*) FROM memberships m WHERE m.company_id = $1 AND m.status = 'active'`, cid).Scan(&total); err != nil {
|
||||
@@ -166,12 +173,13 @@ func (s *Server) handleListTeam(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer rows.Close()
|
||||
type member struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Role string `json:"role"`
|
||||
Status string `json:"status"`
|
||||
Email string `json:"email"`
|
||||
Name *string `json:"name"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
Role string `json:"role"`
|
||||
Status string `json:"status"`
|
||||
Email string `json:"email"`
|
||||
Name *string `json:"name"`
|
||||
IsOwner bool `json:"is_owner"`
|
||||
}
|
||||
out := make([]member, 0)
|
||||
for rows.Next() {
|
||||
@@ -180,9 +188,14 @@ func (s *Server) handleListTeam(w http.ResponseWriter, r *http.Request) {
|
||||
Error(w, http.StatusInternalServerError, "scan failed")
|
||||
return
|
||||
}
|
||||
m.IsOwner = ownerUserID != nil && *ownerUserID == m.UserID
|
||||
out = append(out, m)
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]any{"members": out, "total": total, "limit": limit, "offset": offset})
|
||||
resp := map[string]any{"members": out, "total": total, "limit": limit, "offset": offset}
|
||||
if ownerUserID != nil {
|
||||
resp["owner_user_id"] = *ownerUserID
|
||||
}
|
||||
JSON(w, http.StatusOK, resp)
|
||||
}
|
||||
|
||||
func (s *Server) handleCreateInvite(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -222,6 +235,7 @@ func (s *Server) handleCreateInvite(w http.ResponseWriter, r *http.Request) {
|
||||
// Token returned when email was not delivered so operators can share the accept link.
|
||||
if includeToken {
|
||||
resp["token"] = token
|
||||
resp["accept_url"] = mail.AcceptInviteURL(s.Config.WebOrigin, token)
|
||||
}
|
||||
JSON(w, http.StatusCreated, resp)
|
||||
}
|
||||
@@ -243,6 +257,13 @@ func (s *Server) handleRemoveMember(w http.ResponseWriter, r *http.Request) {
|
||||
Error(w, http.StatusBadRequest, "invalid user id")
|
||||
return
|
||||
}
|
||||
if ownerID, hasOwner, oerr := s.Auth.CompanyOwnerID(r.Context(), cid); oerr != nil {
|
||||
Error(w, http.StatusInternalServerError, "lookup failed")
|
||||
return
|
||||
} else if hasOwner && ownerID == userID {
|
||||
Error(w, http.StatusConflict, auth.ErrCannotRemoveOwner.Error())
|
||||
return
|
||||
}
|
||||
var currentRole, status string
|
||||
err = s.Pool.QueryRow(r.Context(), `
|
||||
SELECT role, status FROM memberships
|
||||
@@ -361,3 +382,49 @@ func (s *Server) handleUpdateMemberRole(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]any{"status": "ok", "role": newRole, "user_id": userID})
|
||||
}
|
||||
|
||||
func (s *Server) handleTransferOwnership(w http.ResponseWriter, r *http.Request) {
|
||||
cid, _ := CompanyIDFromContext(r.Context())
|
||||
uid, ok := UserIDFromContext(r.Context())
|
||||
if !ok {
|
||||
Error(w, http.StatusUnauthorized, "unauthorized")
|
||||
return
|
||||
}
|
||||
platformAdmin, err := s.checkPlatformAdmin(r.Context(), uid)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "authorization check failed")
|
||||
return
|
||||
}
|
||||
if !platformAdmin {
|
||||
isOwner, oerr := s.Auth.IsCompanyOwner(r.Context(), cid, uid)
|
||||
if oerr != nil {
|
||||
Error(w, http.StatusInternalServerError, "authorization check failed")
|
||||
return
|
||||
}
|
||||
if !isOwner {
|
||||
Error(w, http.StatusForbidden, auth.ErrNotCompanyOwner.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
var body struct {
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
if err := DecodeJSON(r, &body); err != nil || body.UserID == uuid.Nil {
|
||||
Error(w, http.StatusBadRequest, "invalid json")
|
||||
return
|
||||
}
|
||||
if err := s.Auth.TransferOwnership(r.Context(), cid, body.UserID); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, auth.ErrTransferSelf):
|
||||
JSON(w, http.StatusOK, map[string]any{"status": "ok", "owner_user_id": body.UserID})
|
||||
case errors.Is(err, auth.ErrOwnerRequired), errors.Is(err, auth.ErrNotCompanyMember):
|
||||
Error(w, http.StatusBadRequest, err.Error())
|
||||
case errors.Is(err, auth.ErrCompanyNotFound):
|
||||
Error(w, http.StatusNotFound, err.Error())
|
||||
default:
|
||||
ClientOrLog(w, http.StatusBadRequest, "could not transfer ownership", err, auth.ClientError)
|
||||
}
|
||||
return
|
||||
}
|
||||
JSON(w, http.StatusOK, map[string]any{"status": "ok", "owner_user_id": body.UserID})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user