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

controllers.GetAllPublicDecks   A

Complexity

Conditions 3

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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