214 lines
5.4 KiB
Go
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)
|
|
}
|
|
}
|