Skip to content

Commit e3604d6

Browse files
committed
feat: toggle scoreboard support
1 parent 24cce55 commit e3604d6

10 files changed

Lines changed: 77 additions & 11 deletions

File tree

domain/error/code.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const (
5353
ErrUpdateWorkspace = 30014
5454
ErrDeleteWorkspace = 30015
5555
ErrWorkspaceAlreadyJoin = 30016
56+
ErrToggleScoreboard = 30017
5657

5758
ErrCreateInvitation = 31000
5859
ErrGetInvitation = 31001

domain/workspace.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ import (
66
)
77

88
type RawWorkspace struct {
9-
Id int `json:"id" db:"id"`
10-
Name string `json:"name" db:"name"`
11-
ProfileUrl string `json:"profileUrl" db:"profile_url"`
12-
CreatedAt time.Time `json:"createdAt" db:"created_at"`
13-
OwnerName string `json:"ownerName" db:"owner_name"`
14-
OwnerProfileUrl string `json:"ownerProfileUrl" db:"owner_profile_url"`
15-
ParticipantCount int `json:"participantCount" db:"participant_count"`
16-
TotalAssignment int `json:"totalAssignment" db:"total_assignment"`
17-
IsArchived bool `json:"isArchived" db:"is_archived"`
18-
IsOpenScoreboard bool `json:"-" db:"is_open_scoreboard"`
19-
IsDeleted bool `json:"-" db:"is_deleted"`
9+
Id int `json:"id" db:"id"`
10+
Name string `json:"name" db:"name"`
11+
ProfileUrl string `json:"profileUrl" db:"profile_url"`
12+
CreatedAt time.Time `json:"createdAt" db:"created_at"`
13+
OwnerName string `json:"ownerName" db:"owner_name"`
14+
OwnerProfileUrl string `json:"ownerProfileUrl" db:"owner_profile_url"`
15+
ParticipantCount int `json:"participantCount" db:"participant_count"`
16+
TotalAssignment int `json:"totalAssignment" db:"total_assignment"`
17+
IsArchived bool `json:"isArchived" db:"is_archived"`
18+
IsScoreboardEnabled bool `json:"is_scoreboard_enabled" db:"is_scoreboard_enabled"`
19+
IsOpenScoreboard bool `json:"-" db:"is_open_scoreboard"`
20+
IsDeleted bool `json:"-" db:"is_deleted"`
2021
}
2122

2223
type Workspace struct {
@@ -100,6 +101,7 @@ type WorkspaceRepository interface {
100101
GetRaw(id int) (*RawWorkspace, error)
101102
GetRole(userId string, workspaceId int) (*WorkspaceRole, error)
102103
GetScoreboard(workspaceId int) ([]WorkspaceRank, error)
104+
ToggleScoreboard(workspaceId int, enabled bool) error
103105
List(userId string) ([]Workspace, error)
104106
ListParticipant(workspaceId int) ([]WorkspaceParticipant, error)
105107
Update(userId string, workspace *Workspace) error
@@ -123,6 +125,7 @@ type WorkspaceUsecase interface {
123125
GetRaw(id int) (*RawWorkspace, error)
124126
GetRole(userId string, workspaceId int) (*WorkspaceRole, error)
125127
GetScoreboard(workspaceId int) ([]WorkspaceRank, error)
128+
ToggleScoreboard(workspaceId int, enabled bool) error
126129
CheckPerm(userId string, workspaceId int) (bool, error)
127130
CheckPermRole(userId string, workspaceId int, roles []WorkspaceRole) (bool, error)
128131
List(userId string) ([]Workspace, error)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE `workspace`
2+
DROP `is_scoreboard_enabled`;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE `workspace`
2+
ADD `is_scoreboard_enabled` TINYINT(1) NOT NULL DEFAULT '0' AFTER `profile_url`;

platform/server/controller/workspace.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,19 @@ func (c *WorkspaceController) GetScoreboard(ctx *fiber.Ctx) error {
175175
return response.NewSuccessResponse(ctx, fiber.StatusOK, scoreboard)
176176
}
177177

178+
func (c *WorkspaceController) ToggleScoreboard(ctx *fiber.Ctx) error {
179+
var pl payload.ToggleScoreboardPayload
180+
if ok, err := c.validator.Validate(&pl, ctx); !ok {
181+
return err
182+
}
183+
184+
if err := c.workspaceUsecase.ToggleScoreboard(pl.WorkspaceId, pl.Enabled); err != nil {
185+
return err
186+
}
187+
188+
return response.NewSuccessResponse(ctx, fiber.StatusOK, nil)
189+
}
190+
178191
func (c *WorkspaceController) CreateInvitation(ctx *fiber.Ctx) error {
179192
var pl payload.CreateInvitationPayload
180193
if ok, err := c.validator.Validate(&pl, ctx); !ok {

platform/server/fiber.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ func (s *FiberServer) applyRoutes() {
140140
workspace.Patch("/:workspaceId/participants/:userId", authMiddleware, workspaceMiddleware, workspaceController.UpdateParticipant)
141141
workspace.Delete("/:workspaceId/participants/:userId", authMiddleware, workspaceMiddleware, workspaceController.DeleteParticipant)
142142
workspace.Get("/:workspaceId/scoreboard", scoreboardMiddleware, cache.New(), workspaceController.GetScoreboard)
143+
workspace.Patch("/:workspaceId/scoreboard", authMiddleware, workspaceMiddleware, workspaceController.ToggleScoreboard)
143144

144145
assignment := workspace.Group("/:workspaceId/assignments")
145146
assignment.Get("/", authMiddleware, workspaceMiddleware, assignmentController.List)

platform/server/middleware/scoreboard.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,27 @@ func NewScoreboardMiddleware(
3434
return errs.New(errs.SameCode, "workspace id %d not found", pl.WorkspaceId)
3535
}
3636

37+
if !workspace.IsScoreboardEnabled {
38+
// Bypass for workspace owner and admin
39+
sid, _ := validator.ValidateAuth(ctx)
40+
if sid != "" {
41+
user, err := authUsecase.Authenticate(sid)
42+
if err != nil {
43+
return errs.New(errs.SameCode, "cannot get user to get scoreboard", err)
44+
}
45+
role, err := workspaceUsecase.GetRole(user.Id, workspace.Id)
46+
if err != nil {
47+
return errs.New(errs.SameCode, "cannot get user role to get scoreboard", err)
48+
}
49+
50+
if *role == domain.OwnerRole || *role == domain.AdminRole {
51+
return ctx.Next()
52+
}
53+
}
54+
55+
return errs.New(errs.ErrGetScoreboard, "scoreboard is disabled")
56+
}
57+
3758
if !workspace.IsOpenScoreboard {
3859
sid, err := validator.ValidateAuth(ctx)
3960
if sid == "" {

platform/server/payload/workspace.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,8 @@ type UpdateParticipantPayload struct {
4848
WorkspaceParticipantPath
4949
Role string `json:"role" validate:"required"`
5050
}
51+
52+
type ToggleScoreboardPayload struct {
53+
WorkspacePath
54+
Enabled bool `json:"enabled"`
55+
}

repository/workspace.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ func (r *workspaceRepository) GetScoreboard(workspaceId int) ([]domain.Workspace
225225
return scoreboard, nil
226226
}
227227

228+
func (r *workspaceRepository) ToggleScoreboard(workspaceId int, enabled bool) error {
229+
_, err := r.db.Exec(
230+
"UPDATE workspace SET is_scoreboard_enabled = ? WHERE id = ?",
231+
enabled, workspaceId,
232+
)
233+
if err != nil {
234+
return fmt.Errorf("cannot query to toggle scoreboard: %w", err)
235+
}
236+
return nil
237+
}
238+
228239
func (r *workspaceRepository) List(userId string) ([]domain.Workspace, error) {
229240
var workspaceIds []int
230241

usecase/workspace.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,13 @@ func (u *workspaceUsecase) GetScoreboard(workspaceId int) ([]domain.WorkspaceRan
235235
return scoreboard, nil
236236
}
237237

238+
func (u *workspaceUsecase) ToggleScoreboard(workspaceId int, enabled bool) error {
239+
if err := u.workspaceRepository.ToggleScoreboard(workspaceId, enabled); err != nil {
240+
return errs.New(errs.ErrToggleScoreboard, "cannot toggle scoreboard", err)
241+
}
242+
return nil
243+
}
244+
238245
func (u *workspaceUsecase) GetInvitation(id string) (*domain.WorkspaceInvitation, error) {
239246
invitation, err := u.workspaceRepository.GetInvitation(id)
240247
if err != nil {

0 commit comments

Comments
 (0)