• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / reporting / 1571619767

13 Sep 2024 10:52AM UTC coverage: 85.292% (+0.06%) from 85.235%
1571619767

push

gitlab-ci

web-flow
Merge pull request #202 from mzedel/chore/deprecate

Chore/deprecate

2998 of 3515 relevant lines covered (85.29%)

14.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.55
/api/http/management_devices.go
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
package http
16

17
import (
18
        "context"
19
        "net/http"
20
        "os"
21
        "strconv"
22
        "strings"
23

24
        "github.com/gin-gonic/gin"
25
        "github.com/pkg/errors"
26

27
        "github.com/mendersoftware/go-lib-micro/identity"
28
        "github.com/mendersoftware/go-lib-micro/rbac"
29
        "github.com/mendersoftware/go-lib-micro/rest.utils"
30

31
        "github.com/mendersoftware/reporting/model"
32
)
33

34
type attributes struct {
35
        Limit      int         `json:"limit"`
36
        Count      int         `json:"count"`
37
        Attributes []attribute `json:"attributes"`
38
}
39

40
type attribute struct {
41
        Name  string `json:"name"`
42
        Scope string `json:"scope"`
43
}
44

45
func (mc *ManagementController) AggregateDevices(c *gin.Context) {
6✔
46
        ctx := c.Request.Context()
6✔
47

6✔
48
        params, err := parseAggregateDevicesParams(ctx, c)
6✔
49
        if err != nil {
8✔
50
                rest.RenderError(c,
2✔
51
                        http.StatusBadRequest,
2✔
52
                        errors.Wrap(err, "malformed request body"),
2✔
53
                )
2✔
54
                return
2✔
55
        }
2✔
56

57
        res, err := mc.reporting.AggregateDevices(ctx, params)
4✔
58
        if err != nil {
5✔
59
                rest.RenderError(c,
1✔
60
                        http.StatusInternalServerError,
1✔
61
                        err,
1✔
62
                )
1✔
63
                return
1✔
64
        }
1✔
65

66
        c.JSON(http.StatusOK, res)
3✔
67
}
68

69
func parseAggregateDevicesParams(ctx context.Context, c *gin.Context) (
70
        *model.AggregateParams, error) {
6✔
71
        var aggregateParams model.AggregateParams
6✔
72

6✔
73
        err := c.ShouldBindJSON(&aggregateParams)
6✔
74
        if err != nil {
7✔
75
                return nil, err
1✔
76
        }
1✔
77

78
        if id := identity.FromContext(ctx); id != nil {
10✔
79
                aggregateParams.TenantID = id.Tenant
5✔
80
        } else {
5✔
81
                return nil, errors.New("missing tenant ID from the context")
×
82
        }
×
83

84
        if scope := rbac.ExtractScopeFromHeader(c.Request); scope != nil {
5✔
85
                aggregateParams.Groups = scope.DeviceGroups
×
86
        }
×
87

88
        if err := aggregateParams.Validate(); err != nil {
6✔
89
                return nil, err
1✔
90
        }
1✔
91

92
        return &aggregateParams, nil
4✔
93
}
94

95
func (mc *ManagementController) DeviceAttrs(c *gin.Context) {
4✔
96
        ctx := c.Request.Context()
4✔
97

4✔
98
        var tenantID string
4✔
99
        if id := identity.FromContext(ctx); id != nil {
8✔
100
                tenantID = id.Tenant
4✔
101
        } else {
4✔
102
                rest.RenderError(c,
×
103
                        http.StatusBadRequest,
×
104
                        errors.New("missing tenant ID from the context"),
×
105
                )
×
106
                return
×
107
        }
×
108

109
        mapping, err := mc.reporting.GetMapping(ctx, tenantID)
4✔
110
        if err != nil {
5✔
111
                rest.RenderError(c,
1✔
112
                        http.StatusInternalServerError,
1✔
113
                        errors.Wrap(err, "failed to retrieve the mapping"),
1✔
114
                )
1✔
115
                return
1✔
116
        } else if mapping == nil {
5✔
117
                mapping = &model.Mapping{}
1✔
118
        }
1✔
119

120
        n := model.MaxMappingInventoryAttributes
3✔
121
        if n > len(mapping.Inventory) {
6✔
122
                n = len(mapping.Inventory)
3✔
123
        }
3✔
124
        attributesList := make([]attribute, 0, n)
3✔
125
        if mapping.Inventory != nil {
4✔
126
                for _, attr := range mapping.Inventory[:n] {
3✔
127
                        parts := strings.SplitN(attr, string(os.PathSeparator), 2)
2✔
128
                        attributesList = append(attributesList, attribute{
2✔
129
                                Name:  parts[1],
2✔
130
                                Scope: parts[0],
2✔
131
                        })
2✔
132
                }
2✔
133
        }
134
        res := &attributes{
3✔
135
                Limit:      model.MaxMappingInventoryAttributes,
3✔
136
                Count:      len(attributesList),
3✔
137
                Attributes: attributesList,
3✔
138
        }
3✔
139

3✔
140
        c.JSON(http.StatusOK, res)
3✔
141
}
142

143
func (mc *ManagementController) SearchDevices(c *gin.Context) {
19✔
144
        ctx := c.Request.Context()
19✔
145
        params, err := parseSearchDevicesParams(ctx, c)
19✔
146
        if err != nil {
21✔
147
                rest.RenderError(c,
2✔
148
                        http.StatusBadRequest,
2✔
149
                        errors.Wrap(err, "malformed request body"),
2✔
150
                )
2✔
151
                return
2✔
152
        }
2✔
153

154
        res, total, err := mc.reporting.SearchDevices(ctx, params)
17✔
155
        if err != nil {
18✔
156
                rest.RenderError(c,
1✔
157
                        http.StatusInternalServerError,
1✔
158
                        err,
1✔
159
                )
1✔
160
                return
1✔
161
        }
1✔
162

163
        pageLinkHdrs(c, params.Page, params.PerPage, total)
16✔
164

16✔
165
        c.Header(hdrTotalCount, strconv.Itoa(total))
16✔
166
        c.JSON(http.StatusOK, res)
16✔
167
}
168

169
func parseSearchDevicesParams(ctx context.Context, c *gin.Context) (*model.SearchParams, error) {
31✔
170
        var searchParams model.SearchParams
31✔
171

31✔
172
        err := c.ShouldBindJSON(&searchParams)
31✔
173
        if err != nil {
32✔
174
                return nil, err
1✔
175
        }
1✔
176

177
        if id := identity.FromContext(ctx); id != nil {
60✔
178
                searchParams.TenantID = id.Tenant
30✔
179
        } else {
30✔
180
                return nil, errors.New("missing tenant ID from the context")
×
181
        }
×
182

183
        if scope := rbac.ExtractScopeFromHeader(c.Request); scope != nil {
31✔
184
                searchParams.Groups = scope.DeviceGroups
1✔
185
        }
1✔
186

187
        if searchParams.PerPage <= 0 {
56✔
188
                searchParams.PerPage = ParamPerPageDefault
26✔
189
        }
26✔
190
        if searchParams.Page <= 0 {
56✔
191
                searchParams.Page = ParamPageDefault
26✔
192
        }
26✔
193

194
        if err := searchParams.Validate(); err != nil {
32✔
195
                return nil, err
2✔
196
        }
2✔
197

198
        return &searchParams, nil
28✔
199
}
200

201
func (mc *ManagementController) SearchDeviceAttrs(c *gin.Context) {
3✔
202
        ctx := c.Request.Context()
3✔
203

3✔
204
        id := identity.FromContext(ctx)
3✔
205
        res, err := mc.reporting.GetSearchableInvAttrs(ctx, id.Tenant)
3✔
206
        if err != nil {
4✔
207
                rest.RenderError(c,
1✔
208
                        http.StatusInternalServerError,
1✔
209
                        err,
1✔
210
                )
1✔
211
                return
1✔
212
        }
1✔
213

214
        c.JSON(http.StatusOK, res)
2✔
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc