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

controllers.GetAllAvailableDecks   B

Complexity

Conditions 5

Size

Total Lines 34
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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