Passed
Pull Request — main (#45)
by Yume
01:43
created

controllers.PublishDeckRequest   A

Complexity

Conditions 4

Size

Total Lines 38
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 25
nop 1
dl 0
loc 38
rs 9.28
c 0
b 0
f 0
1
package controllers
2
3
import (
4
	"fmt"
5
	"github.com/memnix/memnixrest/app/models"
6
	"github.com/memnix/memnixrest/app/queries"
7
	"github.com/memnix/memnixrest/pkg/database"
8
	"github.com/memnix/memnixrest/pkg/utils"
9
	"net/http"
10
	"sort"
11
	"strconv"
12
	"strings"
13
14
	"github.com/gofiber/fiber/v2"
15
)
16
17
// GET
18
19
// GetAllDecks method to get all decks
20
// @Description Get every deck. Shouldn't really be used, consider using /v1/decks/public instead !
21
// @Summary gets all decks
22
// @Tags Deck
23
// @Produce json
24
// @Success 200 {object} models.Deck
25
// @Router /v1/decks [get]
26
func GetAllDecks(c *fiber.Ctx) error {
27
	db := database.DBConn // DB Conn
28
29
	auth := CheckAuth(c, models.PermAdmin) // Check auth
30
	if !auth.Success {
31
		return queries.AuthError(c, &auth)
32
	}
33
34
	var decks []models.Deck
35
36
	if res := db.Find(&decks); res.Error != nil {
37
		return queries.RequestError(c, http.StatusInternalServerError, utils.ErrorRequestFailed)
38
	}
39
40
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
41
		Success: true,
42
		Message: "Get all decks",
43
		Data:    decks,
44
		Count:   len(decks),
45
	})
46
}
47
48
// GetDeckByID method to get a deck
49
// @Description Get a deck by tech ID
50
// @Summary get a deck
51
// @Tags Deck
52
// @Produce json
53
// @Param id path int true "Deck ID"
54
// @Success 200 {model} models.Deck
55
// @Router /v1/decks/{deckID} [get]
56
func GetDeckByID(c *fiber.Ctx) error {
57
	db := database.DBConn // DB Conn
58
59
	// Params
60
	id := c.Params("deckID")
61
62
	auth := CheckAuth(c, models.PermAdmin) // Check auth
63
	if !auth.Success {
64
		return queries.AuthError(c, &auth)
65
	}
66
67
	deck := new(models.Deck)
68
69
	if err := db.First(&deck, id).Error; err != nil {
70
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
71
	}
72
73
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
74
		Success: true,
75
		Message: "Success get deck by ID.",
76
		Data:    *deck,
77
		Count:   1,
78
	})
79
}
80
81
// GetAllSubDecks method to get a deck
82
// @Description Get decks a user is sub to
83
// @Summary gets a list of deck
84
// @Tags Deck
85
// @Produce json
86
// @Success 200 {array} models.ResponseDeck
87
// @Router /v1/decks/sub [get]
88
func GetAllSubDecks(c *fiber.Ctx) error {
89
	db := database.DBConn // DB Conn
90
91
	auth := CheckAuth(c, models.PermUser) // Check auth
92
	if !auth.Success {
93
		return queries.AuthError(c, &auth)
94
	}
95
96
	var responseDeck []models.ResponseDeck
97
	var accesses []models.Access // Accesses array
98
99
	if err := db.Joins("Deck").Joins("User").Where("accesses.user_id = ? AND accesses.permission >= ?", auth.User.ID, models.AccessStudent).Find(&accesses).Error; err != nil {
100
		log := models.CreateLog(fmt.Sprintf("Error from %s on GetAllSubDecks: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
101
		_ = log.SendLog()
102
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
103
	}
104
105
	for i := range accesses {
106
		responseDeck = append(responseDeck, queries.FillResponseDeck(&accesses[i].Deck, accesses[i].Permission, accesses[i].ToggleToday))
107
	}
108
109
	sort.Slice(responseDeck, func(i, j int) bool {
110
		return responseDeck[i].Deck.DeckName < responseDeck[j].Deck.DeckName
111
	})
112
113
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
114
		Success: true,
115
		Message: "Get all sub decks",
116
		Data:    responseDeck,
117
		Count:   len(responseDeck),
118
	})
119
}
120
121
// GetAllEditorDecks method to get a deck
122
// @Description Get decks the user is an editor
123
// @Summary gets a list of deck
124
// @Tags Deck
125
// @Produce json
126
// @Success 200 {array} models.ResponseDeck
127
// @Router /v1/decks/editor [get]
128
func GetAllEditorDecks(c *fiber.Ctx) error {
129
	db := database.DBConn // DB Conn
130
131
	auth := CheckAuth(c, models.PermUser) // Check auth
132
	if !auth.Success {
133
		return queries.AuthError(c, &auth)
134
	}
135
136
	var responseDeck []models.ResponseDeck
137
138
	var accesses []models.Access // Accesses array
139
140
	if err := db.Joins("Deck").Joins("User").Where("accesses.user_id = ? AND accesses.permission >= ?", auth.User.ID, models.AccessEditor).Find(&accesses).Error; err != nil {
141
		log := models.CreateLog(fmt.Sprintf("Error from %s on GetAllEditorDecks: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
142
		_ = log.SendLog()
143
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
144
	}
145
146
	for i := range accesses {
147
		responseDeck = append(responseDeck, queries.FillResponseDeck(&accesses[i].Deck, accesses[i].Permission, accesses[i].ToggleToday))
148
	}
149
150
	sort.Slice(responseDeck, func(i, j int) bool {
151
		return responseDeck[i].Deck.DeckName < responseDeck[j].Deck.DeckName
152
	})
153
154
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
155
		Success: true,
156
		Message: "Get all sub decks",
157
		Data:    responseDeck,
158
		Count:   len(responseDeck),
159
	})
160
}
161
162
// GetAllSubUsers method to get a list of users
163
// @Description Get all the sub users to a deck
164
// @Summary gets a list of users
165
// @Tags Deck
166
// @Produce json
167
// @Success 200 {array} models.User
168
// @Router /v1/decks/{deckID}/users [get]
169
func GetAllSubUsers(c *fiber.Ctx) error {
170
171
	// Params
172
	deckID := c.Params("deckID")
173
	result := new(models.ResponseHTTP)
174
	auth := CheckAuth(c, models.PermUser) // Check auth
175
	if !auth.Success {
176
		return queries.AuthError(c, &auth)
177
	}
178
179
	var users []models.User
180
	id, _ := strconv.ParseUint(deckID, 10, 32)
181
182
	if result = queries.GetSubUsers(uint(id)); !result.Success {
183
		log := models.CreateLog(fmt.Sprintf("Error from %s on GetAllSubUsers: %s", auth.User.Email, result.Message), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
184
		_ = log.SendLog()
185
		return queries.RequestError(c, http.StatusInternalServerError, utils.ErrorRequestFailed)
186
	}
187
188
	switch result.Data.(type) {
189
	default:
190
		return queries.RequestError(c, http.StatusInternalServerError, utils.ErrorRequestFailed)
191
	case []models.User:
192
		users = result.Data.([]models.User)
193
	}
194
195
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
196
		Success: true,
197
		Message: "Get all sub users",
198
		Data:    users,
199
		Count:   len(users),
200
	})
201
}
202
203
// GetAllAvailableDecks method to get a list of deck
204
// @Description Get all public deck that you are not sub to
205
// @Summary get a list of deck
206
// @Tags Deck
207
// @Produce json
208
// @Success 200 {array} models.ResponseDeck
209
// @Router /v1/decks/available [get]
210
func GetAllAvailableDecks(c *fiber.Ctx) error {
211
	db := database.DBConn // DB Conn
212
213
	auth := CheckAuth(c, models.PermUser) // Check auth
214
	if !auth.Success {
215
		return queries.AuthError(c, &auth)
216
	}
217
218
	var responseDeck []models.ResponseDeck
219
	var decks []models.Deck
220
221
	if err := db.Raw(
222
		"SELECT DISTINCT public.decks.* FROM public.decks LEFT JOIN public.accesses ON public.decks.id = public.accesses.deck_id AND public.accesses.user_id = ? WHERE "+
223
			"(public.accesses.deck_id IS NULL  OR public.accesses.permission = 0 OR public.accesses.deleted_at IS NOT NULL) AND public.decks.status = 3",
224
		auth.User.ID).Scan(&decks).Error; err != nil {
225
		log := models.CreateLog(fmt.Sprintf("Error from %s on GetAllAvailableDecks: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
226
		_ = log.SendLog()
227
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
228
	}
229
230
	for i := range decks {
231
		responseDeck = append(responseDeck, queries.FillResponseDeck(&decks[i], models.AccessNone, false))
232
	}
233
234
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
235
		Success: true,
236
		Message: "Get all available decks",
237
		Data:    responseDeck,
238
		Count:   len(responseDeck),
239
	})
240
}
241
242
// GetAllPublicDecks method to get a list of deck
243
// @Description Get all public deck
244
// @Summary gets a list of deck
245
// @Tags Deck
246
// @Produce json
247
// @Success 200 {array} models.Deck
248
// @Router /v1/decks/public [get]
249
func GetAllPublicDecks(c *fiber.Ctx) error {
250
	db := database.DBConn // DB Conn
251
252
	auth := CheckAuth(c, models.PermAdmin) // Check auth
253
	if !auth.Success {
254
		return queries.AuthError(c, &auth)
255
	}
256
257
	var decks []models.Deck
258
259
	if err := db.Where("decks.status = ?", models.DeckPublic).Find(&decks).Error; err != nil {
260
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
261
	}
262
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
263
		Success: true,
264
		Message: "Get all public decks",
265
		Data:    decks,
266
		Count:   len(decks),
267
	})
268
}
269
270
// POST
271
272
// CreateNewDeck method
273
// @Description Create a new deck
274
// @Summary creates a deck
275
// @Tags Deck
276
// @Produce json
277
// @Success 200
278
// @Accept json
279
// @Param deck body models.Deck true "Deck to create"
280
// @Router /v1/decks/new [post]
281
func CreateNewDeck(c *fiber.Ctx) error {
282
	db := database.DBConn // DB Conn
283
284
	auth := CheckAuth(c, models.PermUser) // Check auth
285
	if !auth.Success {
286
		return queries.AuthError(c, &auth)
287
	}
288
289
	deck := new(models.Deck)
290
291
	if err := c.BodyParser(&deck); err != nil {
292
		log := models.CreateLog(fmt.Sprintf("Error from %s on CreateNewDeck: %s", auth.User.Email, err.Error()), models.LogBodyParserError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
293
		_ = log.SendLog()
294
		return queries.RequestError(c, http.StatusBadRequest, err.Error())
295
	}
296
297
	if len(strings.TrimSpace(deck.Key)) != utils.DeckKeyLen {
298
		deck.Key = strings.ToUpper(strings.ReplaceAll(deck.DeckName, " ", "")[0:utils.DeckKeyLen])
299
	}
300
301
	if deck.NotValidate() {
302
		log := models.CreateLog(fmt.Sprintf("Error from %s on CreateNewDeck: BadRequest", auth.User.Email), models.LogBadRequest).SetType(models.LogTypeWarning).AttachIDs(auth.User.ID, 0, 0)
303
		_ = log.SendLog()
304
		return queries.RequestError(c, http.StatusBadRequest, utils.ErrorDeckName)
305
	}
306
307
	if res := queries.CheckDeckLimit(&auth.User); !res {
308
		log := models.CreateLog(fmt.Sprintf("Forbidden from %s on CreateNewDeck: This user has reached his limit", auth.User.Email), models.LogUserDeckLimit).SetType(models.LogTypeWarning).AttachIDs(auth.User.ID, 0, 0)
309
		_ = log.SendLog()
310
		return queries.RequestError(c, http.StatusBadRequest, "You can't create more deck !")
311
	}
312
313
	deck.Key = strings.ToUpper(deck.Key)
314
	deck.GenerateCode()
315
316
	i := 0
317
	for !queries.CheckCode(deck.Key, deck.Code) {
318
		if i > 10 {
319
			log := models.CreateLog(fmt.Sprintf("Error from %s on CreateNewDeck Generate Code: Couldn't generate code after 10 attempts", auth.User.Email), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
320
			_ = log.SendLog()
321
			return queries.RequestError(c, http.StatusBadRequest, utils.ErrorRequestFailed)
322
		}
323
		deck.GenerateCode()
324
		i++
325
	}
326
327
	deck.Status = models.DeckPrivate
328
	db.Create(deck)
329
330
	log := models.CreateLog(fmt.Sprintf("Created: %d - %s", deck.ID, deck.DeckName), models.LogDeckCreated).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, deck.ID, 0)
331
	_ = log.SendLog()
332
333
	if err := queries.GenerateCreatorAccess(&auth.User, deck); !err.Success {
334
		log = models.CreateLog(fmt.Sprintf("Error from %s on CreateNewDeck Generate Creator Access: %s", auth.User.Email, err.Message), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
335
		_ = log.SendLog()
336
		return queries.RequestError(c, http.StatusBadRequest, err.Message)
337
	}
338
339
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
340
		Success: true,
341
		Message: "Success register a deck",
342
		Data:    *deck,
343
		Count:   1,
344
	})
345
}
346
347
// UnSubToDeck method
348
// @Description Unsubscribe to a deck
349
// @Summary unsub deck
350
// @Tags Deck
351
// @Produce json
352
// @Success 200
353
// @Accept json
354
// @Router /v1/decks/{deckID}/unsubscribe [post]
355
func UnSubToDeck(c *fiber.Ctx) error {
356
	db := database.DBConn // DB Conn
357
358
	auth := CheckAuth(c, models.PermUser) // Check auth
359
	if !auth.Success {
360
		return queries.AuthError(c, &auth)
361
	}
362
363
	// Params
364
	deckID := c.Params("deckID")
365
	deckidInt, _ := strconv.ParseUint(deckID, 10, 32)
366
367
	access := new(models.Access)
368
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id = ?", auth.User.ID, deckID).Find(&access).Error; err != nil {
369
		log := models.CreateLog(fmt.Sprintf("Error from %s on UnSubToDeck to %d: %s", auth.User.Email, deckidInt, err.Error()), models.LogBadRequest).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
370
		_ = log.SendLog()
371
		return queries.RequestError(c, http.StatusBadRequest, utils.ErrorNotSub)
372
	}
373
374
	if access.Permission == 0 {
375
		return queries.RequestError(c, http.StatusForbidden, utils.ErrorNotSub)
376
	}
377
378
	access.Permission = 0
379
	db.Preload("User").Preload("Deck").Save(access)
380
381
	log := models.CreateLog(fmt.Sprintf("Unsubscribed: User - %d (%s) | Deck - %d (%s)", access.UserID, access.User.Username, access.DeckID, access.Deck.DeckName), models.LogUnsubscribe).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, access.DeckID, 0)
382
	_ = log.SendLog()
383
384
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
385
		Success: true,
386
		Message: "Success unsub to the deck",
387
		Data:    nil,
388
		Count:   0,
389
	})
390
}
391
392
// SubToPrivateDeck method
393
// @Description Subscribe to a private deck
394
// @Summary sub deck
395
// @Tags Deck
396
// @Produce json
397
// @Success 200
398
// @Accept json
399
// @Router /v1/decks/private/{key}/{code}/subscribe [post]
400
func SubToPrivateDeck(c *fiber.Ctx) error {
401
	db := database.DBConn
402
	key := c.Params("key")
403
	code := c.Params("code")
404
405
	deck := new(models.Deck)
406
407
	// Check auth
408
	auth := CheckAuth(c, models.PermUser)
409
	if !auth.Success {
410
		return queries.AuthError(c, &auth)
411
	}
412
413
	if err := db.Where("decks.key = ? AND decks.code = ? AND decks.share IS TRUE", key, code).First(&deck).Error; err != nil {
414
		log := models.CreateLog(fmt.Sprintf("Error from %s on SubToPrivateDeck: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, 0, 0)
415
		_ = log.SendLog()
416
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
417
	}
418
419
	if err := queries.GenerateAccess(&auth.User, deck); !err.Success {
420
		log := models.CreateLog(fmt.Sprintf("Error from %s on SubToPrivateDeck: %s", auth.User.Email, err.Message), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, deck.ID, 0)
421
		_ = log.SendLog()
422
		return queries.RequestError(c, http.StatusInternalServerError, err.Message)
423
	}
424
425
	if err := queries.PopulateMemDate(&auth.User, deck); !err.Success {
426
		log := models.CreateLog(fmt.Sprintf("Error from %s on SubToPrivateDeck: %s", auth.User.Email, err.Message), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, deck.ID, 0)
427
		_ = log.SendLog()
428
		return queries.RequestError(c, http.StatusInternalServerError, err.Message)
429
	}
430
431
	log := models.CreateLog(fmt.Sprintf("SubToPrivateDeck: User - %d (%s)| Deck - %d (%s)", auth.User.ID, auth.User.Username, deck.ID, deck.DeckName), models.LogSubscribe).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, deck.ID, 0)
432
	_ = log.SendLog()
433
434
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
435
		Success: true,
436
		Message: "Success subscribing to deck",
437
		Data:    nil,
438
		Count:   0,
439
	})
440
441
}
442
443
// PublishDeckRequest method
444
// @Description Request to publish deck
445
// @Summary publishes a deck
446
// @Tags Deck
447
// @Produce json
448
// @Success 200
449
// @Accept json
450
// @Router /v1/decks/{deckID}/publish [post]
451
func PublishDeckRequest(c *fiber.Ctx) error {
452
	db := database.DBConn
453
	id := c.Params("deckID")
454
	deckidInt, _ := strconv.ParseUint(id, 10, 32)
455
456
	deck := new(models.Deck)
457
458
	// Check auth
459
	auth := CheckAuth(c, models.PermUser)
460
	if !auth.Success {
461
		return queries.AuthError(c, &auth)
462
	}
463
464
	if err := db.First(&deck, id).Error; err != nil {
465
		log := models.CreateLog(fmt.Sprintf("Error from %s on PublishDeckRequest: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
466
		_ = log.SendLog()
467
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
468
	}
469
470
	if res := queries.CheckAccess(auth.User.ID, deck.ID, models.AccessOwner); !res.Success {
471
		log := models.CreateLog(fmt.Sprintf("Forbidden from %s on deck %d - PublishDeckRequest: %s", auth.User.Email, deckidInt, res.Message), models.LogPermissionForbidden).SetType(models.LogTypeWarning).AttachIDs(auth.User.ID, uint(deckidInt), 0)
472
		_ = log.SendLog()
473
		return queries.RequestError(c, http.StatusForbidden, utils.ErrorForbidden)
474
	}
475
476
	deck.Status = models.DeckWaitingReview
477
478
	db.Save(deck)
479
	// TODO: Error handling
480
481
	log := models.CreateLog(fmt.Sprintf("PublishDeckRequest: User - %d (%s)| Deck - %d (%s)", auth.User.ID, auth.User.Username, deck.ID, deck.DeckName), models.LogPublishRequest).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, deck.ID, 0)
482
	_ = log.SendLog()
483
484
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
485
		Success: true,
486
		Message: "Success sending a publish request to deck",
487
		Data:    nil,
488
		Count:   0,
489
	})
490
}
491
492
// SubToDeck method
493
// @Description Subscribe to a deck
494
// @Summary sub deck
495
// @Tags Deck
496
// @Produce json
497
// @Success 200
498
// @Accept json
499
// @Router /v1/decks/{deckID}/subscribe [post]
500
func SubToDeck(c *fiber.Ctx) error {
501
	db := database.DBConn // DB Conn
502
	deckID := c.Params("deckID")
503
	deckidInt, _ := strconv.ParseUint(deckID, 10, 32)
504
505
	deck := new(models.Deck)
506
507
	// Check auth
508
	auth := CheckAuth(c, models.PermUser)
509
	if !auth.Success {
510
		return queries.AuthError(c, &auth)
511
	}
512
513
	if err := db.First(&deck, deckID).Error; err != nil {
514
		log := models.CreateLog(fmt.Sprintf("Error from %s on SubToDeck: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
515
		_ = log.SendLog()
516
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
517
	}
518
519
	if err := queries.GenerateAccess(&auth.User, deck); !err.Success {
520
		log := models.CreateLog(fmt.Sprintf("Error from %s on SubToDeck: %s", auth.User.Email, err.Message), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
521
		_ = log.SendLog()
522
		return queries.RequestError(c, http.StatusInternalServerError, err.Message)
523
	}
524
525
	if err := queries.PopulateMemDate(&auth.User, deck); !err.Success {
526
		log := models.CreateLog(fmt.Sprintf("Error from %s on SubToDeck: %s", auth.User.Email, err.Message), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
527
		_ = log.SendLog()
528
		return queries.RequestError(c, http.StatusInternalServerError, err.Message)
529
	}
530
531
	log := models.CreateLog(fmt.Sprintf("Subscribed: User - %d (%s)| Deck - %d (%s)", auth.User.ID, auth.User.Username, deck.ID, deck.DeckName), models.LogSubscribe).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, deck.ID, 0)
532
	_ = log.SendLog()
533
534
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
535
		Success: true,
536
		Message: "Success subscribing to deck",
537
		Data:    nil,
538
		Count:   0,
539
	})
540
}
541
542
// PUT
543
544
// UpdateDeckByID method
545
// @Description Edit a deck
546
// @Summary edits a deck
547
// @Tags Deck
548
// @Produce json
549
// @Success 200
550
// @Accept json
551
// @Param deck body models.Deck true "Deck to edit"
552
// @Router /v1/decks/{deckID}/edit [put]
553
func UpdateDeckByID(c *fiber.Ctx) error {
554
	db := database.DBConn // DB Conn
555
556
	// Params
557
	id := c.Params("deckID")
558
	deckidInt, _ := strconv.ParseUint(id, 10, 32)
559
560
	auth := CheckAuth(c, models.PermUser) // Check auth
561
	if !auth.Success {
562
		return queries.AuthError(c, &auth)
563
	}
564
565
	deck := new(models.Deck)
566
567
	if err := db.First(&deck, id).Error; err != nil {
568
		log := models.CreateLog(fmt.Sprintf("Error from %s on UpdateDeckByID: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
569
		_ = log.SendLog()
570
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
571
	}
572
573
	if res := queries.CheckAccess(auth.User.ID, deck.ID, models.AccessOwner); !res.Success {
574
		log := models.CreateLog(fmt.Sprintf("Forbidden from %s on deck %d - UpdateDeckByID: %s", auth.User.Email, deckidInt, res.Message), models.LogPermissionForbidden).SetType(models.LogTypeWarning).AttachIDs(auth.User.ID, uint(deckidInt), 0)
575
		_ = log.SendLog()
576
		return queries.RequestError(c, http.StatusForbidden, utils.ErrorForbidden)
577
	}
578
579
	if err := UpdateDeck(c, deck); !err.Success {
580
		log := models.CreateLog(fmt.Sprintf("Error on UpdateDeckByID: %s from %s", err.Message, auth.User.Email), models.LogBadRequest).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
581
		_ = log.SendLog()
582
		return queries.RequestError(c, http.StatusBadRequest, err.Message)
583
	}
584
585
	log := models.CreateLog(fmt.Sprintf("Updated: %d - %s", deck.ID, deck.DeckName), models.LogDeckEdited).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, deck.ID, 0)
586
	_ = log.SendLog()
587
588
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
589
		Success: true,
590
		Message: "Success update deck by ID",
591
		Data:    *deck,
592
		Count:   1,
593
	})
594
}
595
596
// UpdateDeck function
597
func UpdateDeck(c *fiber.Ctx, deck *models.Deck) *models.ResponseHTTP {
598
	db := database.DBConn
599
600
	deckStatus := deck.Status
601
602
	res := new(models.ResponseHTTP)
603
604
	if err := c.BodyParser(&deck); err != nil {
605
		res.GenerateError(err.Error())
606
		return res
607
	}
608
609
	if deck.Status != deckStatus {
610
		res.GenerateError(utils.ErrorBreak)
611
		return res
612
	}
613
614
	if deck.NotValidate() {
615
		res.GenerateError(utils.ErrorDeckName)
616
		return res
617
	}
618
619
	if len(strings.TrimSpace(deck.Key)) != utils.DeckKeyLen {
620
		deck.Key = strings.ToUpper(strings.ReplaceAll(deck.DeckName, " ", "")[0:utils.DeckKeyLen])
621
	}
622
623
	deck.Key = strings.ToUpper(deck.Key)
624
	deck.GenerateCode()
625
626
	i := 0
627
	for !queries.CheckCode(deck.Key, deck.Code) {
628
		if i > 10 {
629
			res.GenerateError(utils.ErrorRequestFailed)
630
			return res
631
		}
632
		deck.GenerateCode()
633
		i++
634
	}
635
636
	db.Save(deck)
637
638
	res.GenerateSuccess("Success update deck", nil, 0)
639
	return res
640
}
641
642
// DeleteDeckById method
643
// @Description Delete a deck
644
// @Summary delete a deck
645
// @Tags Deck
646
// @Produce json
647
// @Success 200
648
// @Router /v1/decks/{deckID} [delete]
649
func DeleteDeckById(c *fiber.Ctx) error {
650
	db := database.DBConn // DB Conn
651
	id := c.Params("deckID")
652
	deckidInt, _ := strconv.ParseUint(id, 10, 32)
653
654
	auth := CheckAuth(c, models.PermUser) // Check auth
655
	if !auth.Success {
656
		return queries.AuthError(c, &auth)
657
	}
658
659
	deck := new(models.Deck)
660
661
	if err := db.First(&deck, id).Error; err != nil {
662
		log := models.CreateLog(fmt.Sprintf("Error from %s on DeleteDeckById: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
663
		_ = log.SendLog()
664
		return queries.RequestError(c, http.StatusInternalServerError, err.Error())
665
666
	}
667
668
	if res := queries.CheckAccess(auth.User.ID, deck.ID, models.AccessOwner); !res.Success {
669
		log := models.CreateLog(fmt.Sprintf("Forbidden from %s on deck %d - DeleteDeckById: %s", auth.User.Email, deckidInt, res.Message), models.LogPermissionForbidden).SetType(models.LogTypeWarning).AttachIDs(auth.User.ID, uint(deckidInt), 0)
670
		_ = log.SendLog()
671
		return queries.RequestError(c, http.StatusForbidden, utils.ErrorForbidden)
672
	}
673
674
	var memDates []models.MemDate
675
	var accesses []models.Access
676
	var cards []models.Card
677
678
	if err := db.Joins("Card").Where("mem_dates.deck_id = ?", deck.ID).Find(&memDates).Error; err != nil {
679
		log := models.CreateLog(fmt.Sprintf("Error from %s on DeleteDeckById: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
680
		_ = log.SendLog()
681
		return queries.RequestError(c, http.StatusInternalServerError, utils.ErrorRequestFailed)
682
		// TODO: Error
683
	}
684
685
	if err := db.Where("accesses.deck_id = ?", deck.ID).Find(&accesses).Error; err != nil {
686
		log := models.CreateLog(fmt.Sprintf("Error from %s on DeleteDeckById: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
687
		_ = log.SendLog()
688
		return queries.RequestError(c, http.StatusInternalServerError, utils.ErrorRequestFailed)
689
		// TODO: Error
690
	}
691
692
	if err := db.Where("cards.deck_id = ?", deck.ID).Find(&cards).Error; err != nil {
693
		log := models.CreateLog(fmt.Sprintf("Error from %s on DeleteDeckById: %s", auth.User.Email, err.Error()), models.LogQueryGetError).SetType(models.LogTypeError).AttachIDs(auth.User.ID, uint(deckidInt), 0)
694
		_ = log.SendLog()
695
		return queries.RequestError(c, http.StatusInternalServerError, utils.ErrorRequestFailed)
696
	}
697
698
	db.Unscoped().Delete(memDates)
699
	db.Unscoped().Delete(accesses)
700
701
	db.Delete(cards)
702
	db.Delete(deck)
703
704
	log := models.CreateLog(fmt.Sprintf("Deleted: %d - %s", deck.ID, deck.DeckName), models.LogDeckDeleted).SetType(models.LogTypeInfo).AttachIDs(auth.User.ID, deck.ID, 0)
705
	_ = log.SendLog()
706
707
	return c.Status(http.StatusOK).JSON(models.ResponseHTTP{
708
		Success: true,
709
		Message: "Success delete deck by ID",
710
		Data:    *deck,
711
		Count:   1,
712
	})
713
714
}
715