Passed
Push — main ( 6c7dd4...414036 )
by Yume
01:05
created

controllers.GetCardByID   A

Complexity

Conditions 3

Size

Total Lines 32
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 22
nop 1
dl 0
loc 32
rs 9.352
c 0
b 0
f 0
1
package controllers
2
3
import (
4
	"memnixrest/app/database"
5
	"memnixrest/app/models"
6
	"memnixrest/pkg/queries"
7
	"net/http"
8
	"strconv"
9
	"strings"
10
11
	"github.com/gofiber/fiber/v2"
12
)
13
14
// GetTodayCard method
15
// @Description Get next today card
16
// @Summary get a card
17
// @Tags Card
18
// @Produce json
19
// @Success 200 {object} models.Card
20
// @Router /v1/cards/today [get]
21
func GetTodayCard(c *fiber.Ctx) error {
22
	res := *new(models.ResponseHTTP)
23
24
	auth := CheckAuth(c, models.PermUser) // Check auth
25
	if !auth.Success {
26
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
27
			Success: false,
28
			Message: auth.Message,
29
			Data:    nil,
30
			Count:   0,
31
		})
32
	}
33
34
	if res = queries.FetchNextTodayCard(c, &auth.User); !res.Success {
35
		return c.Status(http.StatusInternalServerError).JSON(models.ResponseHTTP{
36
			Success: false,
37
			Message: res.Message,
38
			Data:    nil,
39
			Count:   0,
40
		})
41
	}
42
43
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
44
		Success: true,
45
		Message: "Get todays card",
46
		Data:    res.Data,
47
		Count:   1,
48
	})
49
}
50
51
// GetNextCard method
52
// @Description Get next card
53
// @Summary get a card
54
// @Tags Card
55
// @Produce json
56
// @Success 200 {object} models.Card
57
// @Router /v1/cards/next [get]
58
func GetNextCard(c *fiber.Ctx) error {
59
	//db := database.DBConn // DB Conn
60
61
	res := *new(models.ResponseHTTP)
62
	auth := CheckAuth(c, models.PermUser) // Check auth
63
	if !auth.Success {
64
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
65
			Success: false,
66
			Message: auth.Message,
67
			Data:    nil,
68
			Count:   0,
69
		})
70
	}
71
72
	if res = queries.FetchNextCard(c, &auth.User); !res.Success {
73
		return c.Status(http.StatusInternalServerError).JSON(models.ResponseHTTP{
74
			Success: false,
75
			Message: res.Message,
76
			Data:    nil,
77
			Count:   0,
78
		})
79
	}
80
81
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
82
		Success: true,
83
		Message: "Get next card",
84
		Data:    res.Data,
85
		Count:   1,
86
	})
87
}
88
89
// GetNextCard method
90
// @Description Get next card by deckID
91
// @Summary get a card
92
// @Tags Card
93
// @Produce json
94
// @Success 200 {object} models.Card
95
// @Router /v1/cards/{deckID}/next [get]
96
func GetNextCardByDeck(c *fiber.Ctx) error {
97
	//db := database.DBConn // DB Conn
98
99
	deckID := c.Params("deckID")
100
101
	res := *new(models.ResponseHTTP)
102
	auth := CheckAuth(c, models.PermUser) // Check auth
103
	if !auth.Success {
104
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
105
			Success: false,
106
			Message: auth.Message,
107
			Data:    nil,
108
			Count:   0,
109
		})
110
	}
111
112
	if res = queries.FetchNextCardByDeck(c, &auth.User, deckID); !res.Success {
113
		return c.Status(http.StatusInternalServerError).JSON(models.ResponseHTTP{
114
			Success: false,
115
			Message: res.Message,
116
			Data:    nil,
117
			Count:   0,
118
		})
119
	}
120
121
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
122
		Success: true,
123
		Message: "Get next card by deck",
124
		Data:    res.Data,
125
		Count:   1,
126
	})
127
}
128
129
// GetAllCards method
130
// @Description Get every cards. Shouldn't really be used
131
// @Summary get all cards
132
// @Tags Card
133
// @Produce json
134
// @Success 200 {array} models.Card
135
// @Router /v1/cards/ [get]
136
func GetAllCards(c *fiber.Ctx) error {
137
	db := database.DBConn // DB Conn
138
139
	auth := CheckAuth(c, models.PermAdmin) // Check auth
140
	if !auth.Success {
141
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
142
			Success: false,
143
			Message: auth.Message,
144
			Data:    nil,
145
			Count:   0,
146
		})
147
	}
148
149
	var cards []models.Card
150
151
	if res := db.Joins("Deck").Find(&cards); res.Error != nil {
152
153
		return c.Status(http.StatusInternalServerError).JSON(models.ResponseHTTP{
154
			Success: false,
155
			Message: "Failed to get all cards",
156
			Data:    nil,
157
			Count:   0,
158
		})
159
	}
160
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
161
		Success: true,
162
		Message: "Get All cards",
163
		Data:    cards,
164
		Count:   len(cards),
165
	})
166
167
}
168
169
// GetCardByID method to get a card by id
170
// @Description Get a card by tech id
171
// @Summary get a card
172
// @Tags Card
173
// @Produce json
174
// @Param id path int true "Card ID"
175
// @Success 200 {object} models.Card
176
// @Router /v1/cards/id/{id} [get]
177
func GetCardByID(c *fiber.Ctx) error {
178
	db := database.DBConn // DB Conn
179
180
	auth := CheckAuth(c, models.PermAdmin) // Check auth
181
	if !auth.Success {
182
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
183
			Success: false,
184
			Message: auth.Message,
185
			Data:    nil,
186
			Count:   0,
187
		})
188
	}
189
190
	// Params
191
	id := c.Params("id")
192
193
	card := new(models.Card)
194
195
	if err := db.Joins("Deck").First(&card, id).Error; err != nil {
196
		return c.Status(http.StatusServiceUnavailable).JSON(models.ResponseHTTP{
197
			Success: false,
198
			Message: err.Error(),
199
			Data:    nil,
200
			Count:   0,
201
		})
202
	}
203
204
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
205
		Success: true,
206
		Message: "Success get card by ID.",
207
		Data:    *card,
208
		Count:   1,
209
	})
210
}
211
212
// GetCardsFromDeck method to get cards from deck
213
// @Description Get every cards from a deck
214
// @Summary get a list of card
215
// @Tags Card
216
// @Produce json
217
// @Param deckID path int true "Deck ID"
218
// @Success 200 {array} models.Card
219
// @Router /v1/cards/deck/{deckID} [get]
220
func GetCardsFromDeck(c *fiber.Ctx) error {
221
	db := database.DBConn // DB Conn
222
223
	// Params
224
	id := c.Params("deckID")
225
226
	auth := CheckAuth(c, models.PermAdmin) // Check auth
227
	if !auth.Success {
228
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
229
			Success: false,
230
			Message: auth.Message,
231
			Data:    nil,
232
			Count:   0,
233
		})
234
	}
235
236
	var cards []models.Card
237
238
	if err := db.Joins("Deck").Where("cards.deck_id = ?", id).Find(&cards).Error; err != nil {
239
		return c.Status(http.StatusServiceUnavailable).JSON(models.ResponseHTTP{
240
			Success: false,
241
			Message: err.Error(),
242
			Data:    nil,
243
			Count:   0,
244
		})
245
	}
246
247
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
248
		Success: true,
249
		Message: "Success get cards from deck.",
250
		Data:    cards,
251
		Count:   len(cards),
252
	})
253
}
254
255
// POST
256
257
// CreateNewCard method
258
// @Description Create a new card
259
// @Summary create a card
260
// @Tags Card
261
// @Produce json
262
// @Accept json
263
// @Param card body models.Card true "Card to create"
264
// @Success 200
265
// @Router /v1/cards/new [post]
266
func CreateNewCard(c *fiber.Ctx) error {
267
	db := database.DBConn // DB Conn
268
269
	card := new(models.Card)
270
271
	auth := CheckAuth(c, models.PermUser) // Check auth
272
	if !auth.Success {
273
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
274
			Success: false,
275
			Message: auth.Message,
276
			Data:    nil,
277
			Count:   0,
278
		})
279
	}
280
281
	if err := c.BodyParser(&card); err != nil {
282
		return c.Status(http.StatusBadRequest).JSON(models.ResponseHTTP{
283
			Success: false,
284
			Message: err.Error(),
285
			Data:    nil,
286
			Count:   0,
287
		})
288
	}
289
290
	if res := queries.CheckAccess(c, auth.User.ID, card.DeckID, models.AccessEditor); !res.Success {
291
		return c.Status(http.StatusServiceUnavailable).JSON(models.ResponseHTTP{
292
			Success: false,
293
			Message: "You don't have the permission to add a card to this deck !",
294
			Data:    nil,
295
			Count:   0,
296
		})
297
	}
298
299
	if len(card.Question) < 1 || len(card.Answer) < 1 {
300
		return c.Status(http.StatusBadRequest).JSON(models.ResponseHTTP{
301
			Success: false,
302
			Message: "You must provide a question and an answer.",
303
			Data:    nil,
304
			Count:   0,
305
		})
306
	}
307
308
	db.Create(card)
309
310
	log := queries.CreateLog(models.LogCardCreated, auth.User.Username+" created "+card.Question)
311
	_ = queries.CreateUserLog(auth.User.ID, *log)
312
	_ = queries.CreateDeckLog(card.DeckID, *log)
313
	_ = queries.CreateCardLog(card.ID, *log)
314
315
	var users []models.User
316
317
	if users = queries.GetSubUsers(c, card.DeckID); len(users) > 0 {
318
		ch := make(chan models.ResponseHTTP)
319
320
		for _, s := range users {
321
			go func(c *fiber.Ctx, user models.User, card *models.Card) {
322
				res := queries.GenerateMemDate(c, &user, card)
323
				ch <- res
324
			}(c, s, card)
325
		}
326
	}
327
328
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
329
		Success: true,
330
		Message: "Success register a card",
331
		Data:    *card,
332
		Count:   1,
333
	})
334
}
335
336
// CreateNewCardBulk method
337
// @Description Create cards
338
// @Summary create cards
339
// @Tags Card
340
// @Produce json
341
// @Accept json
342
// @Param card body models.Card true "Cards to create"
343
// @Success 200
344
// @Router /v1/cards/deck/{deckID}/bulk [post]
345
func CreateNewCardBulk(c *fiber.Ctx) error {
346
	db := database.DBConn // DB Conn
347
348
	deckID, _ := strconv.ParseUint(c.Params("deckID"), 10, 32)
349
350
	auth := CheckAuth(c, models.PermUser) // Check auth
351
	if !auth.Success {
352
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
353
			Success: false,
354
			Message: auth.Message,
355
			Data:    nil,
356
			Count:   0,
357
		})
358
	}
359
360
	type Data struct {
361
		Cards []models.Card `json:"cards"`
362
	}
363
364
	data := new(Data)
365
366
	if err := c.BodyParser(&data); err != nil {
367
		return c.Status(http.StatusBadRequest).JSON(models.ResponseHTTP{
368
			Success: false,
369
			Message: err.Error(),
370
			Data:    nil,
371
			Count:   0,
372
		})
373
	}
374
375
	if res := queries.CheckAccess(c, auth.User.ID, uint(deckID), models.AccessEditor); !res.Success {
376
		return c.Status(http.StatusServiceUnavailable).JSON(models.ResponseHTTP{
377
			Success: false,
378
			Message: "You don't have the permission to add a card to this deck !",
379
			Data:    nil,
380
			Count:   0,
381
		})
382
	}
383
384
	ch := make(chan models.ResponseHTTP)
385
386
	for _, card := range data.Cards {
387
		go func(c *fiber.Ctx, card models.Card, deckID uint) {
388
389
			print("Card: " + card.Question)
390
391
			var res models.ResponseHTTP
392
393
			if len(card.Question) < 1 || len(card.Answer) < 1 {
394
				res = models.ResponseHTTP{
395
					Success: false,
396
					Message: "You must provide a question and an answer.",
397
					Data:    nil,
398
					Count:   0,
399
				}
400
			} else {
401
				ca := &card
402
				ca.DeckID = deckID
403
				db.Create(ca)
404
405
				log := queries.CreateLog(models.LogCardCreated, auth.User.Username+" created "+ca.Question)
406
				_ = queries.CreateUserLog(auth.User.ID, *log)
407
				_ = queries.CreateDeckLog(deckID, *log)
408
				_ = queries.CreateCardLog(ca.ID, *log)
409
410
				res = models.ResponseHTTP{
411
					Success: true,
412
					Message: "Success creating card",
413
					Data:    nil,
414
					Count:   0,
415
				}
416
417
				var users []models.User
418
419
				if users = queries.GetSubUsers(c, deckID); len(users) > 0 {
420
					ch2 := make(chan models.ResponseHTTP)
421
422
					for _, s := range users {
423
						go func(c *fiber.Ctx, user models.User, card models.Card) {
424
							res2 := queries.GenerateMemDate(c, &user, &card)
425
							ch2 <- res2
426
						}(c, s, card)
427
					}
428
				}
429
			}
430
			ch <- res
431
		}(c, card, uint(deckID))
432
	}
433
	//TODO: handle errors in chan
434
435
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
436
		Success: true,
437
		Message: "Success bulk creation",
438
		Data:    data.Cards,
439
		Count:   len(data.Cards),
440
	})
441
}
442
443
// PostResponse method
444
// @Description Post a response and check it
445
// @Summary post a response
446
// @Tags Card
447
// @Produce json
448
// @Success 200
449
// @Accept json
450
// @Router /v1/cards/response [post]
451
func PostResponse(c *fiber.Ctx) error {
452
	db := database.DBConn // DB Conn
453
454
	auth := CheckAuth(c, models.PermUser) // Check auth
455
	if !auth.Success {
456
		return c.Status(http.StatusUnauthorized).JSON(models.ResponseHTTP{
457
			Success: false,
458
			Message: auth.Message,
459
			Data:    nil,
460
			Count:   0,
461
		})
462
	}
463
464
	response := new(models.CardResponse)
465
	card := new(models.Card)
466
467
	if err := c.BodyParser(&response); err != nil {
468
		return c.Status(http.StatusBadRequest).JSON(models.ResponseHTTP{
469
			Success: false,
470
			Message: err.Error(),
471
			Data:    nil,
472
			Count:   0,
473
		})
474
	}
475
476
	if err := db.Joins("Deck").First(&card, response.CardID).Error; err != nil {
477
		return c.Status(http.StatusServiceUnavailable).JSON(models.ResponseHTTP{
478
			Success: false,
479
			Message: err.Error(),
480
			Data:    nil,
481
			Count:   0,
482
		})
483
	}
484
485
	res := queries.CheckAccess(c, auth.User.ID, card.Deck.ID, models.AccessStudent)
486
487
	if !res.Success {
488
		return c.Status(http.StatusServiceUnavailable).JSON(models.ResponseHTTP{
489
			Success: false,
490
			Message: "You don't have the permission to answer this deck!",
491
			Data:    nil,
492
			Count:   0,
493
		})
494
	}
495
496
	validation := new(models.CardResponseValidation)
497
498
	if strings.EqualFold(strings.TrimSpace(response.Response), strings.TrimSpace(card.Answer)) {
499
		validation.Validate = true
500
		validation.Message = "Correct answer"
501
	} else {
502
		validation.Validate = false
503
		validation.Message = "Incorrect answer"
504
	}
505
506
	_ = queries.PostMem(c, auth.User, *card, *validation)
507
508
	validation.Answer = card.Answer
509
510
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
511
		Success: true,
512
		Message: "Success post response",
513
		Data:    *validation,
514
		Count:   1,
515
	})
516
}
517