/
githubmirror
/
grafana
Обзор
Документация
Войти
/
githubmirror
/
grafana
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
pkg/api/preferences.go
283 строки
10 KB
Ashley Harrison
Preferences: promote api to v1 (#127173)
29 июн 2026, 12:57
Не верифицирован
29 июн 2026, 12:57
4ad4f8c
Код
Авторство
О чём код?
package api import ( "context" "net/http" preferences "github.com/grafana/grafana/apps/preferences/pkg/apis/preferences/v1" "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/api/response" "github.com/grafana/grafana/pkg/apimachinery/identity" prefutils "github.com/grafana/grafana/pkg/registry/apis/preferences/utils" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/featuremgmt" pref "github.com/grafana/grafana/pkg/services/preference" "github.com/grafana/grafana/pkg/services/preference/prefapi" "github.com/grafana/grafana/pkg/web" "github.com/open-feature/go-sdk/openfeature" ) var ofClient = openfeature.NewDefaultClient() // swagger:route GET /user/preferences signed_in_user preferences getUserPreferences // // Get user preferences. // // Use /apis/preferences.grafana.app/v1/namespaces/{namespace}/preferences/user-{uid} // // Deprecated: true // // Responses: // 200: getPreferencesResponse // 401: unauthorisedError // 500: internalServerError func (hs *HTTPServer) GetUserPreferences(c *contextmodel.ReqContext) response.Response { ctx := c.Req.Context() if ofClient.Boolean(ctx, featuremgmt.FlagPreferencesRerouteLegacyAPIs, false, openfeature.TransactionContext(ctx)) { return hs.preferenceK8sHandler.GetPreferences(c, prefutils.UserOwner(c.GetIdentifier())) } userID, err := identity.UserIdentifier(c.GetID()) if err != nil { return response.Error(http.StatusUnauthorized, "Not a valid identity", err) } return prefapi.GetPreferencesFor(c.Req.Context(), hs.DashboardService, hs.preferenceService, hs.Features, c.GetOrgID(), userID, 0) } // swagger:route PUT /user/preferences signed_in_user preferences updateUserPreferences // // Update user preferences. // // Use /apis/preferences.grafana.app/v1/namespaces/{namespace}/preferences/user-{uid} // // Deprecated: true // // Omitting a key (`theme`, `homeDashboardUID`, `timezone`) will cause the current value to be replaced with the system default value. // // Responses: // 200: okResponse // 400: badRequestError // 401: unauthorisedError // 500: internalServerError func (hs *HTTPServer) UpdateUserPreferences(c *contextmodel.ReqContext) response.Response { dtoCmd := dtos.UpdatePrefsCmd{} if err := web.Bind(c.Req, &dtoCmd); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } ctx := c.Req.Context() if ofClient.Boolean(ctx, featuremgmt.FlagPreferencesRerouteLegacyAPIs, false, openfeature.TransactionContext(ctx)) { return hs.preferenceK8sHandler.UpdatePreferences(c, prefutils.UserOwner(c.GetIdentifier()), &dtoCmd) } userID, err := identity.UserIdentifier(c.GetID()) if err != nil { return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err) } return prefapi.UpdatePreferencesFor(c.Req.Context(), hs.DashboardService, hs.preferenceService, hs.Features, c.GetOrgID(), userID, 0, &dtoCmd) } // swagger:route PATCH /user/preferences signed_in_user preferences patchUserPreferences // // Patch user preferences. // // Use /apis/preferences.grafana.app/v1/namespaces/{namespace}/preferences/user-{uid} // // Deprecated: true // // Responses: // 200: okResponse // 400: badRequestError // 401: unauthorisedError // 500: internalServerError func (hs *HTTPServer) PatchUserPreferences(c *contextmodel.ReqContext) response.Response { dtoCmd := dtos.PatchPrefsCmd{} if err := web.Bind(c.Req, &dtoCmd); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } ctx := c.Req.Context() if ofClient.Boolean(ctx, featuremgmt.FlagPreferencesRerouteLegacyAPIs, false, openfeature.TransactionContext(ctx)) { return hs.preferenceK8sHandler.PatchPreferences(c, prefutils.UserOwner(c.GetIdentifier()), &dtoCmd) } userID, err := identity.UserIdentifier(c.GetID()) if err != nil { return response.Error(http.StatusInternalServerError, "Failed to update user preferences", err) } return hs.patchPreferencesFor(c.Req.Context(), c.GetOrgID(), userID, 0, &dtoCmd) } func (hs *HTTPServer) patchPreferencesFor(ctx context.Context, orgID, userID, teamId int64, dtoCmd *dtos.PatchPrefsCmd) response.Response { if dtoCmd.Theme != nil && !pref.IsValidThemeID(*dtoCmd.Theme) { return response.Error(http.StatusBadRequest, "Invalid theme", nil) } if dtoCmd.Timezone != nil && !pref.IsValidTimezone(*dtoCmd.Timezone) { return response.Error(http.StatusBadRequest, "Invalid timezone. Must be a valid IANA timezone (e.g., America/New_York), 'utc', 'browser', or empty string", nil) } // convert dashboard UID to ID in order to store internally if it exists in the query, otherwise take the id from query // nolint:staticcheck dashboardID := dtoCmd.HomeDashboardID if dtoCmd.HomeDashboardUID != nil { query := dashboards.GetDashboardQuery{UID: *dtoCmd.HomeDashboardUID, OrgID: orgID} if query.UID == "" { // clear the value defaultDash := int64(0) dashboardID = &defaultDash } else { queryResult, err := hs.DashboardService.GetDashboard(ctx, &query) if err != nil { return response.Error(http.StatusNotFound, "Dashboard not found", err) } dashboardID = &queryResult.ID } } else if dtoCmd.HomeDashboardID != nil { // make sure uid is always set if id is set queryResult, err := hs.DashboardService.GetDashboard(ctx, &dashboards.GetDashboardQuery{ID: *dtoCmd.HomeDashboardID, OrgID: orgID}) // nolint:staticcheck if err != nil { return response.Error(http.StatusNotFound, "Dashboard not found", err) } dtoCmd.HomeDashboardUID = &queryResult.UID } // nolint:staticcheck dtoCmd.HomeDashboardID = dashboardID patchCmd := pref.PatchPreferenceCommand{ UserID: userID, OrgID: orgID, TeamID: teamId, Theme: dtoCmd.Theme, Timezone: dtoCmd.Timezone, WeekStart: dtoCmd.WeekStart, HomeDashboardID: dtoCmd.HomeDashboardID, // nolint:staticcheck HomeDashboardUID: dtoCmd.HomeDashboardUID, Language: dtoCmd.Language, QueryHistory: dtoCmd.QueryHistory, Navbar: dtoCmd.Navbar, } if err := hs.preferenceService.Patch(ctx, &patchCmd); err != nil { return response.ErrOrFallback(http.StatusInternalServerError, "Failed to save preferences", err) } return response.Success("Preferences updated") } // swagger:route GET /org/preferences org preferences getOrgPreferences // // Get Current Org Prefs. // // Use /apis/preferences.grafana.app/v1/namespaces/{namespace}/preferences/namespace // // Deprecated: true // // Responses: // 200: getPreferencesResponse // 401: unauthorisedError // 403: forbiddenError // 500: internalServerError func (hs *HTTPServer) GetOrgPreferences(c *contextmodel.ReqContext) response.Response { ctx := c.Req.Context() if ofClient.Boolean(ctx, featuremgmt.FlagPreferencesRerouteLegacyAPIs, false, openfeature.TransactionContext(ctx)) { return hs.preferenceK8sHandler.GetPreferences(c, prefutils.NamespaceOwner()) } return prefapi.GetPreferencesFor(ctx, hs.DashboardService, hs.preferenceService, hs.Features, c.GetOrgID(), 0, 0) } // swagger:route PUT /org/preferences org preferences updateOrgPreferences // // Update Current Org Prefs. // // Use /apis/preferences.grafana.app/v1/namespaces/{namespace}/preferences/namespace // // Deprecated: true // // Responses: // 200: okResponse // 400: badRequestError // 401: unauthorisedError // 403: forbiddenError // 500: internalServerError func (hs *HTTPServer) UpdateOrgPreferences(c *contextmodel.ReqContext) response.Response { dtoCmd := dtos.UpdatePrefsCmd{} if err := web.Bind(c.Req, &dtoCmd); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } ctx := c.Req.Context() if ofClient.Boolean(ctx, featuremgmt.FlagPreferencesRerouteLegacyAPIs, false, openfeature.TransactionContext(ctx)) { return hs.preferenceK8sHandler.UpdatePreferences(c, prefutils.NamespaceOwner(), &dtoCmd) } return prefapi.UpdatePreferencesFor(ctx, hs.DashboardService, hs.preferenceService, hs.Features, c.GetOrgID(), 0, 0, &dtoCmd) } // swagger:route PATCH /org/preferences org preferences patchOrgPreferences // // Patch Current Org Prefs. // // Use /apis/preferences.grafana.app/v1/namespaces/{namespace}/preferences/namespace // // Deprecated: true // // Responses: // 200: okResponse // 400: badRequestError // 401: unauthorisedError // 403: forbiddenError // 500: internalServerError func (hs *HTTPServer) PatchOrgPreferences(c *contextmodel.ReqContext) response.Response { dtoCmd := dtos.PatchPrefsCmd{} if err := web.Bind(c.Req, &dtoCmd); err != nil { return response.Error(http.StatusBadRequest, "bad request data", err) } ctx := c.Req.Context() if ofClient.Boolean(ctx, featuremgmt.FlagPreferencesRerouteLegacyAPIs, false, openfeature.TransactionContext(ctx)) { return hs.preferenceK8sHandler.PatchPreferences(c, prefutils.NamespaceOwner(), &dtoCmd) } return hs.patchPreferencesFor(ctx, c.GetOrgID(), 0, 0, &dtoCmd) } // swagger:parameters updateUserPreferences type UpdateUserPreferencesParams struct { // in:body // required:true Body dtos.UpdatePrefsCmd `json:"body"` } // swagger:parameters updateOrgPreferences type UpdateOrgPreferencesParams struct { // in:body // required:true Body dtos.UpdatePrefsCmd `json:"body"` } // swagger:response getPreferencesResponse type GetPreferencesResponse struct { // in:body Body preferences.PreferencesSpec `json:"body"` } // swagger:parameters patchUserPreferences type PatchUserPreferencesParams struct { // in:body // required:true Body dtos.PatchPrefsCmd `json:"body"` } // swagger:parameters patchOrgPreferences type PatchOrgPreferencesParams struct { // in:body // required:true Body dtos.PatchPrefsCmd `json:"body"` }