Allow managers to view subordinate PF projects
All checks were successful
CI / hygiene (push) Successful in 3s
Build and Deploy / build-and-deploy (push) Successful in 36s
CI / go (push) Successful in 23s
CI / python (push) Successful in 1s

This commit is contained in:
Grendgi
2026-06-16 09:34:17 +03:00
parent ec62cc04cf
commit 703f544cdf

View File

@@ -1,6 +1,7 @@
package pf package pf
import ( import (
"database/sql"
"encoding/json" "encoding/json"
"errors" "errors"
"net/http" "net/http"
@@ -111,13 +112,23 @@ func (s Server) accessMe(w http.ResponseWriter, r *http.Request) {
} }
func (s Server) summary(w http.ResponseWriter, r *http.Request) { func (s Server) summary(w http.ResponseWriter, r *http.Request) {
emp, err := s.App.CurrentEmployee(r.Context(), portalUserID(r), false) var emp *Employee
if err != nil { var err error
writeError(w, http.StatusInternalServerError, err.Error()) if requested := ownerPortalIDFromQuery(r); requested != nil {
return var ok bool
} emp, ok = s.resolveProjectOwnerForRead(w, r, requested)
if emp != nil && emp.TGChatID == nil { if !ok {
emp = nil return
}
} else {
emp, err = s.App.CurrentEmployee(r.Context(), portalUserID(r), false)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
if emp != nil && emp.TGChatID == nil {
emp = nil
}
} }
out, err := s.App.Summary(r.Context(), emp) out, err := s.App.Summary(r.Context(), emp)
if err != nil { if err != nil {
@@ -226,7 +237,13 @@ func (s Server) employeeItem(w http.ResponseWriter, r *http.Request, path string
func (s Server) projects(w http.ResponseWriter, r *http.Request) { func (s Server) projects(w http.ResponseWriter, r *http.Request) {
switch r.Method { switch r.Method {
case http.MethodGet: case http.MethodGet:
emp, ok := s.requireEmployee(w, r) var emp *Employee
var ok bool
if requested := ownerPortalIDFromQuery(r); requested != nil {
emp, ok = s.resolveProjectOwnerForRead(w, r, requested)
} else {
emp, ok = s.requireEmployee(w, r)
}
if !ok { if !ok {
return return
} }
@@ -439,6 +456,27 @@ func (s Server) resolveProjectOwner(w http.ResponseWriter, r *http.Request, requ
return owner, true return owner, true
} }
func (s Server) resolveProjectOwnerForRead(w http.ResponseWriter, r *http.Request, requested *string) (*Employee, bool) {
if requested == nil || strings.TrimSpace(*requested) == "" {
return s.requireEmployee(w, r)
}
targetPortalID := strings.TrimSpace(*requested)
if !canManagePortalUser(r, targetPortalID) {
writeError(w, http.StatusForbidden, "Нет прав на просмотр объектов этого сотрудника")
return nil, false
}
owner, err := s.App.EmployeeByPortalUserID(r.Context(), targetPortalID)
if errors.Is(err, ErrNotFound) || errors.Is(err, sql.ErrNoRows) {
writeError(w, http.StatusNotFound, "employee not found")
return nil, false
}
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return nil, false
}
return owner, true
}
func (s Server) projectOwnerIDForAccess(w http.ResponseWriter, r *http.Request, projectID int64) (int64, bool) { func (s Server) projectOwnerIDForAccess(w http.ResponseWriter, r *http.Request, projectID int64) (int64, bool) {
owner, err := s.App.ProjectOwner(r.Context(), projectID) owner, err := s.App.ProjectOwner(r.Context(), projectID)
if errors.Is(err, ErrNotFound) { if errors.Is(err, ErrNotFound) {
@@ -511,6 +549,14 @@ func subordinatePortalIDs(r *http.Request) []string {
return out return out
} }
func ownerPortalIDFromQuery(r *http.Request) *string {
value := strings.TrimSpace(r.URL.Query().Get("owner_portal_user_id"))
if value == "" {
return nil
}
return &value
}
func nullablePlain(value string) *string { func nullablePlain(value string) *string {
if strings.TrimSpace(value) == "" { if strings.TrimSpace(value) == "" {
return nil return nil