Files
olons_server/internal/httpapi/portal.go
T

214 lines
5.4 KiB
Go

package httpapi
import (
"errors"
"net/http"
"strings"
"git.118im.com/im_team/im_workbench/internal/portal"
"git.118im.com/im_team/im_workbench/internal/store"
)
var publicContentKeys = map[string]struct{}{
"privacy_policy": {},
"user_agreement": {},
}
func (a *API) home(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
profile, err := a.accounts.Profile(r.Context(), principal.TenantID, principal.MemberID)
if err != nil {
writeProfileError(w, r, err)
return
}
result, err := a.portal.Home(r.Context(), principal.TenantID, principal.MemberID, profile)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, result)
}
func (a *API) banners(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
position := strings.TrimSpace(r.URL.Query().Get("position"))
if position == "" {
position = "home_top"
}
items, err := a.portal.Banners(r.Context(), principal.TenantID, position)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, items)
}
func (a *API) content(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
if a.auth == nil {
writeError(w, r, http.StatusServiceUnavailable, 90001, "SERVICE_UNAVAILABLE", "service unavailable", nil)
return
}
key := strings.TrimPrefix(r.URL.Path, "/v1/contents/")
key = strings.ToLower(strings.TrimSpace(key))
if strings.Contains(key, "/") {
writePortalError(w, r, portal.ErrContentKeyInvalid)
return
}
tenantID := a.auth.DefaultTenantID()
if _, public := publicContentKeys[key]; !public {
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
tenantID = principal.TenantID
}
result, err := a.portal.Content(r.Context(), tenantID, key)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, result)
}
func (a *API) memberLevels(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
items, err := a.portal.MemberLevels(r.Context(), principal.TenantID)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, items)
}
func (a *API) leaderboard(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
items, err := a.portal.Leaderboard(r.Context(), principal.TenantID)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, items)
}
func (a *API) customerServices(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
items, err := a.portal.CustomerServices(r.Context(), principal.TenantID)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, items)
}
func (a *API) notices(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
methodNotAllowed(w, r, http.MethodGet)
return
}
if !a.ensurePortal(w, r) {
return
}
principal, ok := a.authenticateMember(w, r)
if !ok {
return
}
page, ok := optionalPositiveInt(w, r, "page")
if !ok {
writePortalError(w, r, portal.ErrPageInvalid)
return
}
pageSize, ok := optionalPositiveInt(w, r, "page_size")
if !ok {
writePortalError(w, r, portal.ErrPageSizeInvalid)
return
}
result, err := a.portal.Notices(r.Context(), principal.TenantID, principal.MemberID, page, pageSize)
if err != nil {
writePortalError(w, r, err)
return
}
writeSuccess(w, r, result)
}
func (a *API) ensurePortal(w http.ResponseWriter, r *http.Request) bool {
if a.portal != nil {
return true
}
writeError(w, r, http.StatusServiceUnavailable, 90001, "SERVICE_UNAVAILABLE", "service unavailable", nil)
return false
}
func writePortalError(w http.ResponseWriter, r *http.Request, err error) {
switch {
case errors.Is(err, portal.ErrPositionInvalid):
writeError(w, r, http.StatusBadRequest, 30000, "BANNER_POSITION_INVALID", "validation failed", map[string]any{"field": "position"})
case errors.Is(err, portal.ErrContentKeyInvalid):
writeError(w, r, http.StatusBadRequest, 30000, "CONTENT_KEY_INVALID", "validation failed", map[string]any{"field": "content_key"})
case errors.Is(err, portal.ErrPageInvalid):
writeError(w, r, http.StatusBadRequest, 30000, "PAGE_INVALID", "validation failed", map[string]any{"field": "page"})
case errors.Is(err, portal.ErrPageSizeInvalid):
writeError(w, r, http.StatusBadRequest, 30000, "PAGE_SIZE_INVALID", "validation failed", map[string]any{"field": "page_size"})
case errors.Is(err, store.ErrResourceNotFound):
writeError(w, r, http.StatusNotFound, 30044, "RESOURCE_NOT_FOUND", "resource not found", nil)
default:
writeError(w, r, http.StatusInternalServerError, 90000, reasonInternal, "internal error", nil)
}
}