(w http.ResponseWriter, r *http.Request, userID string)
| 464 | } |
| 465 | |
| 466 | func (a *userAPI) handleUserCredentials(w http.ResponseWriter, r *http.Request, userID string) { |
| 467 | user, err := a.users.GetUser(userID) |
| 468 | if err != nil { |
| 469 | writeUserError(w, err) |
| 470 | return |
| 471 | } |
| 472 | switch r.Method { |
| 473 | case http.MethodGet: |
| 474 | writeJSON(w, http.StatusOK, map[string]any{ |
| 475 | "uuid": user.UUID, |
| 476 | "secret": user.Secret, |
| 477 | }) |
| 478 | case http.MethodPut: |
| 479 | var req struct { |
| 480 | UUID string `json:"uuid"` |
| 481 | Secret string `json:"secret"` |
| 482 | } |
| 483 | if err := json.NewDecoder(r.Body).Decode(&req); err != nil { |
| 484 | writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid json"}) |
| 485 | return |
| 486 | } |
| 487 | if req.UUID == "" { |
| 488 | req.UUID = randomUUID() |
| 489 | } else if !isValidUUID(req.UUID) { |
| 490 | writeJSON(w, http.StatusBadRequest, map[string]any{"error": "invalid uuid format"}) |
| 491 | return |
| 492 | } |
| 493 | if req.Secret == "" { |
| 494 | req.Secret = randomToken(16) |
| 495 | } |
| 496 | if err := a.users.SetCredentials(userID, req.UUID, req.Secret); err != nil { |
| 497 | internalError(w, r, err) |
| 498 | return |
| 499 | } |
| 500 | // 重新下发所有相关节点配置 |
| 501 | if err := a.triggerUserApply(userID); err != nil { |
| 502 | log.Printf("warn: re-apply after credentials change user %s: %v", userID, err) |
| 503 | } |
| 504 | writeJSON(w, http.StatusOK, map[string]any{"uuid": req.UUID, "secret": req.Secret}) |
| 505 | default: |
| 506 | writeMethodNotAllowed(w, http.MethodGet+", "+http.MethodPut) |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | // handleAccessApply 将该节点的完整配置重新下发。 |
| 511 | func (a *userAPI) handleAccessApply(w http.ResponseWriter, r *http.Request, userID, ibID string) { |
no test coverage detected