Passed
Pull Request — main (#42)
by Yume
01:18
created

controllers.CreateNewDeck   C

Complexity

Conditions 9

Size

Total Lines 63
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 43
nop 1
dl 0
loc 63
rs 6.5146
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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