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

mendersoftware / iot-manager / 1457622833

13 Sep 2024 11:01AM UTC coverage: 87.172%. Remained the same
1457622833

push

gitlab-ci

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

Chore/deprecate

3255 of 3734 relevant lines covered (87.17%)

11.38 hits per line

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

95.24
/api/http/management.go
1
// Copyright 2022 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
        "strings"
21

22
        "github.com/gin-gonic/gin"
23
        "github.com/google/uuid"
24
        "github.com/pkg/errors"
25

26
        "github.com/mendersoftware/go-lib-micro/identity"
27
        "github.com/mendersoftware/go-lib-micro/rest.utils"
28

29
        "github.com/mendersoftware/iot-manager/app"
30
        "github.com/mendersoftware/iot-manager/model"
31
)
32

33
var (
34
        ErrMissingUserAuthentication = errors.New(
35
                "user identity missing from authorization token",
36
        )
37
        ErrIntegrationNotFound = errors.New("integration not found")
38
)
39

40
const hdrLocation = "Location"
41

42
func getContextAndIdentity(c *gin.Context) (context.Context, *identity.Identity, error) {
60✔
43
        var (
60✔
44
                ctx = c.Request.Context()
60✔
45
                id  = identity.FromContext(ctx)
60✔
46
        )
60✔
47
        if id == nil || !id.IsUser {
68✔
48
                rest.RenderError(c, http.StatusForbidden, ErrMissingUserAuthentication)
8✔
49
                return nil, nil, ErrMissingUserAuthentication
8✔
50
        }
8✔
51
        return ctx, id, nil
52✔
52
}
53

54
// ManagementHandler is the namespace for management API handlers.
55
type ManagementHandler APIHandler
56

57
// GET /integrations
58
func (h *ManagementHandler) GetIntegrations(c *gin.Context) {
4✔
59
        ctx, _, err := getContextAndIdentity(c)
4✔
60
        if err != nil {
5✔
61
                return
1✔
62
        }
1✔
63

64
        integrations, err := h.app.GetIntegrations(ctx)
3✔
65
        if err != nil {
4✔
66
                rest.RenderError(c,
1✔
67
                        http.StatusInternalServerError,
1✔
68
                        err,
1✔
69
                )
1✔
70
                return
1✔
71
        }
1✔
72

73
        c.JSON(http.StatusOK, integrations)
2✔
74
}
75

76
// POST /integrations
77
func (h *ManagementHandler) CreateIntegration(c *gin.Context) {
12✔
78
        ctx, _, err := getContextAndIdentity(c)
12✔
79
        if err != nil {
13✔
80
                return
1✔
81
        }
1✔
82

83
        integration := model.Integration{}
11✔
84
        if err := c.ShouldBindJSON(&integration); err != nil {
12✔
85
                rest.RenderError(c,
1✔
86
                        http.StatusBadRequest,
1✔
87
                        errors.Wrap(err, "malformed request body"),
1✔
88
                )
1✔
89
                return
1✔
90
        }
1✔
91

92
        // TODO verify that Azure connectionstring / AWS equivalent has correct permissions
93
        //      - service
94
        //      - registry read/write
95

96
        inserted, err := h.app.CreateIntegration(ctx, integration)
10✔
97
        if err != nil {
12✔
98
                switch cause := errors.Cause(err); cause {
2✔
99
                case app.ErrIntegrationExists:
1✔
100
                        // NOTE: temporary limitation
1✔
101
                        rest.RenderError(c, http.StatusConflict, cause)
1✔
102
                default:
1✔
103
                        _ = c.Error(err)
1✔
104
                        rest.RenderError(c,
1✔
105
                                http.StatusInternalServerError,
1✔
106
                                err,
1✔
107
                        )
1✔
108
                }
109
                return
2✔
110
        }
111

112
        path := strings.Replace(APIURLIntegration, ":id", inserted.ID.String(), 1)
8✔
113
        c.Header(hdrLocation, APIURLManagement+path)
8✔
114
        c.Status(http.StatusCreated)
8✔
115

116
}
117

118
// GET /integrations/{id}
119
func (h *ManagementHandler) GetIntegrationById(c *gin.Context) {
5✔
120
        ctx, _, err := getContextAndIdentity(c)
5✔
121
        if err != nil {
6✔
122
                return
1✔
123
        }
1✔
124
        integrationID, err := uuid.Parse(c.Param("id"))
4✔
125
        if err != nil {
5✔
126
                rest.RenderError(c,
1✔
127
                        http.StatusBadRequest,
1✔
128
                        errors.Wrap(err, "integration ID must be a valid UUID"),
1✔
129
                )
1✔
130
                return
1✔
131
        }
1✔
132

133
        integration, err := h.app.GetIntegrationById(ctx, integrationID)
3✔
134
        if err != nil {
5✔
135
                switch cause := errors.Cause(err); cause {
2✔
136
                case app.ErrIntegrationNotFound:
1✔
137
                        rest.RenderError(c, http.StatusNotFound, ErrIntegrationNotFound)
1✔
138
                default:
1✔
139
                        rest.RenderError(c,
1✔
140
                                http.StatusInternalServerError,
1✔
141
                                err,
1✔
142
                        )
1✔
143
                }
144
                return
2✔
145
        }
146

147
        c.JSON(http.StatusOK, integration)
1✔
148
}
149

150
// PUT /integrations/{id}/credentials
151
func (h *ManagementHandler) SetIntegrationCredentials(c *gin.Context) {
6✔
152
        ctx, _, err := getContextAndIdentity(c)
6✔
153
        if err != nil {
7✔
154
                return
1✔
155
        }
1✔
156
        integrationID, err := uuid.Parse(c.Param("id"))
5✔
157
        if err != nil {
6✔
158
                rest.RenderError(c,
1✔
159
                        http.StatusBadRequest,
1✔
160
                        errors.Wrap(err, "integration ID must be a valid UUID"),
1✔
161
                )
1✔
162
                return
1✔
163
        }
1✔
164

165
        credentials := model.Credentials{}
4✔
166
        if err := c.ShouldBindJSON(&credentials); err != nil {
5✔
167
                rest.RenderError(c,
1✔
168
                        http.StatusBadRequest,
1✔
169
                        errors.Wrap(err, "malformed request body"),
1✔
170
                )
1✔
171
                return
1✔
172
        }
1✔
173

174
        err = h.app.SetIntegrationCredentials(ctx, integrationID, credentials)
3✔
175
        if err != nil {
5✔
176
                switch cause := errors.Cause(err); cause {
2✔
177
                case app.ErrIntegrationNotFound:
1✔
178
                        rest.RenderError(c, http.StatusNotFound, ErrIntegrationNotFound)
1✔
179
                default:
1✔
180
                        rest.RenderError(c,
1✔
181
                                http.StatusInternalServerError,
1✔
182
                                err,
1✔
183
                        )
1✔
184
                }
185
                return
2✔
186
        }
187

188
        c.Status(http.StatusNoContent)
1✔
189
}
190

191
// DELETE /integrations/{id}
192
func (h *ManagementHandler) RemoveIntegration(c *gin.Context) {
6✔
193
        ctx, _, err := getContextAndIdentity(c)
6✔
194
        if err != nil {
7✔
195
                return
1✔
196
        }
1✔
197
        integrationID, err := uuid.Parse(c.Param("id"))
5✔
198
        if err != nil {
6✔
199
                rest.RenderError(c,
1✔
200
                        http.StatusBadRequest,
1✔
201
                        errors.Wrap(err, "integration ID must be a valid UUID"),
1✔
202
                )
1✔
203
                return
1✔
204
        }
1✔
205
        if err = h.app.RemoveIntegration(ctx, integrationID); err != nil {
7✔
206
                switch cause := errors.Cause(err); cause {
3✔
207
                case app.ErrIntegrationNotFound:
1✔
208
                        rest.RenderError(c, http.StatusNotFound, ErrIntegrationNotFound)
1✔
209
                case app.ErrCannotRemoveIntegration:
1✔
210
                        rest.RenderError(c, http.StatusConflict, app.ErrCannotRemoveIntegration)
1✔
211
                default:
1✔
212
                        rest.RenderError(c,
1✔
213
                                http.StatusInternalServerError,
1✔
214
                                err,
1✔
215
                        )
1✔
216
                }
217
                return
3✔
218
        }
219
        c.Status(http.StatusNoContent)
1✔
220
}
221

222
// GET /events
223
func (h *ManagementHandler) GetEvents(c *gin.Context) {
6✔
224
        ctx, _, err := getContextAndIdentity(c)
6✔
225
        if err != nil {
6✔
226
                return
×
227
        }
×
228

229
        filter, err := getEventsFilterFromQuery(c)
6✔
230
        if err != nil {
7✔
231
                rest.RenderError(c,
1✔
232
                        http.StatusBadRequest,
1✔
233
                        err,
1✔
234
                )
1✔
235
                return
1✔
236
        }
1✔
237

238
        events, err := h.app.GetEvents(ctx, *filter)
5✔
239
        if err != nil {
5✔
240
                rest.RenderError(c,
×
241
                        http.StatusInternalServerError,
×
242
                        err,
×
243
                )
×
244
                return
×
245
        }
×
246

247
        c.JSON(http.StatusOK, events)
5✔
248
}
249

250
// get events filter from query params
251
func getEventsFilterFromQuery(c *gin.Context) (*model.EventsFilter, error) {
6✔
252
        filter := model.EventsFilter{}
6✔
253
        page, perPage, err := rest.ParsePagingParameters(c.Request)
6✔
254
        if err != nil {
7✔
255
                return nil, err
1✔
256
        }
1✔
257
        filter.Skip = (page - 1) * perPage
5✔
258
        filter.Limit = perPage
5✔
259
        return &filter, err
5✔
260
}
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