Passed
Push — main ( 3865bb...da977d )
by Yume
01:29 queued 12s
created

controllers.UpdateCard   A

Complexity

Conditions 5

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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