Auth: Add anonymous users view and stats (#78685)
* Add anonymous stats and user table - anonymous users users page - add feature toggle `anonymousAccess` - remove check for enterprise for `Device-Id` header in request - add anonusers/device count to stats * promise all, review comments * make use of promise all settled * refactoring: devices instead of users * review comments, moved countdevices to httpserver * fakeAnonService for tests and generate openapi spec * do not commit openapi3 and api-merged * add openapi * Apply suggestions from code review Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> * formatin * precise anon devices to avoid confusion --------- Co-authored-by: Alex Khomenko <Clarity-89@users.noreply.github.com> Co-authored-by: jguer <me@jguer.space>
This commit is contained in:
co-authored by
Alex Khomenko
jguer
parent
fd863cfc93
commit
59bdff0280
@@ -0,0 +1,98 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/anonymous/anonimpl/anonstore"
|
||||
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
thirtyDays = 30 * 24 * time.Hour
|
||||
)
|
||||
|
||||
type deviceDTO struct {
|
||||
anonstore.Device
|
||||
LastSeenAt string `json:"lastSeenAt"`
|
||||
AvatarUrl string `json:"avatarUrl"`
|
||||
}
|
||||
|
||||
type AnonDeviceServiceAPI struct {
|
||||
cfg *setting.Cfg
|
||||
store anonstore.AnonStore
|
||||
accesscontrol accesscontrol.AccessControl
|
||||
RouterRegister routing.RouteRegister
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func NewAnonDeviceServiceAPI(
|
||||
cfg *setting.Cfg,
|
||||
anonstore anonstore.AnonStore,
|
||||
accesscontrol accesscontrol.AccessControl,
|
||||
routerRegister routing.RouteRegister,
|
||||
) *AnonDeviceServiceAPI {
|
||||
return &AnonDeviceServiceAPI{
|
||||
cfg: cfg,
|
||||
store: anonstore,
|
||||
accesscontrol: accesscontrol,
|
||||
RouterRegister: routerRegister,
|
||||
log: log.New("anon.api"),
|
||||
}
|
||||
}
|
||||
|
||||
func (api *AnonDeviceServiceAPI) RegisterAPIEndpoints() {
|
||||
auth := accesscontrol.Middleware(api.accesscontrol)
|
||||
api.RouterRegister.Group("/api/anonymous", func(anonRoutes routing.RouteRegister) {
|
||||
anonRoutes.Get("/devices", auth(accesscontrol.EvalPermission(accesscontrol.ActionUsersRead)), routing.Wrap(api.ListDevices))
|
||||
})
|
||||
}
|
||||
|
||||
// swagger:route GET /stats devices listDevices
|
||||
//
|
||||
// # Lists all devices within the last 30 days
|
||||
//
|
||||
// Produces:
|
||||
// - application/json
|
||||
//
|
||||
// Responses:
|
||||
//
|
||||
// 200: devicesResponse
|
||||
// 401: unauthorisedError
|
||||
// 403: forbiddenError
|
||||
// 404: notFoundError
|
||||
// 500: internalServerError
|
||||
func (api *AnonDeviceServiceAPI) ListDevices(c *contextmodel.ReqContext) response.Response {
|
||||
fromTime := time.Now().Add(-thirtyDays)
|
||||
toTime := time.Now()
|
||||
|
||||
devices, err := api.store.ListDevices(c.Req.Context(), &fromTime, &toTime)
|
||||
if err != nil {
|
||||
return response.ErrOrFallback(http.StatusInternalServerError, "Failed to list devices", err)
|
||||
}
|
||||
|
||||
// convert to response format
|
||||
resDevices := make([]*deviceDTO, 0, len(devices))
|
||||
for _, device := range devices {
|
||||
resDevices = append(resDevices, &deviceDTO{
|
||||
Device: *device,
|
||||
LastSeenAt: util.GetAgeString(device.UpdatedAt),
|
||||
AvatarUrl: dtos.GetGravatarUrl(device.DeviceID),
|
||||
})
|
||||
}
|
||||
|
||||
return response.JSON(http.StatusOK, resDevices)
|
||||
}
|
||||
|
||||
// swagger:response devicesResponse
|
||||
type DevicesResponse struct {
|
||||
// in:body
|
||||
Body []deviceDTO `json:"body"`
|
||||
}
|
||||
Reference in New Issue
Block a user