feat: seller/buyer view toggle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6ab568ba4f
commit
135d23468a
|
|
@ -77,6 +77,44 @@ func (h *Handler) createSession(w http.ResponseWriter, userID string) {
|
|||
})
|
||||
}
|
||||
|
||||
func (h *Handler) handleViewToggle(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
profile := getProfile(r.Context())
|
||||
if profile.Role != "owner" && profile.Role != "admin" {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// Toggle the cookie
|
||||
current := false
|
||||
if c, err := r.Cookie("view_as_buyer"); err == nil && c.Value == "1" {
|
||||
current = true
|
||||
}
|
||||
|
||||
value := "1"
|
||||
if current {
|
||||
value = ""
|
||||
}
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "view_as_buyer",
|
||||
Value: value,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
|
||||
// Redirect back to referrer or dashboard
|
||||
ref := r.Header.Get("Referer")
|
||||
if ref == "" {
|
||||
ref = "/"
|
||||
}
|
||||
http.Redirect(w, r, ref, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func generateToken() string {
|
||||
b := make([]byte, 32)
|
||||
rand.Read(b)
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ func (h *Handler) getRequests(dealID string, profile *model.Profile) []*model.Di
|
|||
query := "SELECT id, deal_id, item_number, section, description, priority, atlas_status, atlas_note, confidence, buyer_comment, seller_comment, buyer_group FROM diligence_requests WHERE deal_id = ?"
|
||||
args := []interface{}{dealID}
|
||||
|
||||
if rbac.IsBuyer(profile.Role) {
|
||||
if rbac.EffectiveIsBuyer(profile) {
|
||||
groups := rbac.BuyerGroups(profile)
|
||||
if len(groups) > 0 {
|
||||
placeholders := make([]string, len(groups))
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
|
|||
mux.HandleFunc("/login", h.handleLoginPage)
|
||||
mux.HandleFunc("/auth/login", h.handleLogin)
|
||||
mux.HandleFunc("/auth/logout", h.handleLogout)
|
||||
mux.HandleFunc("/auth/view-toggle", h.requireAuth(h.handleViewToggle))
|
||||
|
||||
// Pages (auth required)
|
||||
mux.HandleFunc("/", h.requireAuth(h.handleDashboard))
|
||||
|
|
@ -94,6 +95,13 @@ func (h *Handler) requireAuth(next http.HandlerFunc) http.HandlerFunc {
|
|||
return
|
||||
}
|
||||
|
||||
// Check view-as-buyer toggle (only applies to sellers)
|
||||
if profile.Role == "owner" || profile.Role == "admin" {
|
||||
if c, err := r.Cookie("view_as_buyer"); err == nil && c.Value == "1" {
|
||||
profile.ViewAsBuyer = true
|
||||
}
|
||||
}
|
||||
|
||||
ctx := setProfile(r.Context(), &profile)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func (h *Handler) handleUpdateComment(w http.ResponseWriter, r *http.Request) {
|
|||
value := r.FormValue("value")
|
||||
|
||||
field := "seller_comment"
|
||||
if rbac.IsBuyer(profile.Role) {
|
||||
if rbac.EffectiveIsBuyer(profile) {
|
||||
field = "buyer_comment"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ type Profile struct {
|
|||
PasswordHash string
|
||||
CreatedAt time.Time
|
||||
LastLogin *time.Time
|
||||
ViewAsBuyer bool // Not persisted, set per-request from cookie
|
||||
}
|
||||
|
||||
type Deal struct {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ func IsBuyer(role string) bool {
|
|||
return role == "viewer" || role == "member"
|
||||
}
|
||||
|
||||
// EffectiveIsBuyer returns true if ViewAsBuyer is set OR real role is buyer
|
||||
func EffectiveIsBuyer(profile *model.Profile) bool {
|
||||
return profile.ViewAsBuyer || IsBuyer(profile.Role)
|
||||
}
|
||||
|
||||
// BuyerGroups returns the buyer groups for the demo buyer
|
||||
func BuyerGroups(profile *model.Profile) []string {
|
||||
if IsBuyer(profile.Role) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue