diff --git a/CONCEPT.md b/CONCEPT.md
index 0af71eb..9a44e20 100644
--- a/CONCEPT.md
+++ b/CONCEPT.md
@@ -106,7 +106,7 @@
Отдельной таблицей по отношению к пользователям (многие ко многим? - да владеть двумя командами это возможно):
- команда uuid - *уникальный идентификатор*
-- Роль в команде - (четыре захаркоженные роли: owner, captain, vice-captain, player)
+- Роль в [команде](https://github.com/sea-kg/ctf01d-training-platform/issues/44) - (owner, captain, vice-captain, player, guest)
- Название роли в команде - *роли придуманные капитанами и замами команд*
- публичный комментарий - *виден всем*
- приватный комментарий - *виден только владельцу капитану и зам капитана*
diff --git a/api/openapi.yaml b/api/openapi.yaml
index 58d4839..035b331 100644
--- a/api/openapi.yaml
+++ b/api/openapi.yaml
@@ -892,6 +892,11 @@ components:
ProfileResponse:
type: object
description: The response schema for a user's profile, including id, timestamps, team name, and team history.
+ required:
+ - id
+ - created_at
+ - team_name
+ - team_role
properties:
id:
type: string
@@ -908,6 +913,15 @@ components:
team_name:
type: string
description: The current name of the user's team.
+ team_role:
+ type: string
+ description: The current role of the user's team.
+ enum:
+ - owner
+ - captain
+ - vice-captain
+ - player
+ - guest
team_history:
type: array
description: The list of teams the user has been part of, including the periods of membership.
@@ -917,12 +931,21 @@ components:
required:
- name
- join
+ - role
type: object
description: The schema for recording the history of teams a user has joined and left.
properties:
name:
type: string
description: The name of the team.
+ role:
+ type: string
+ description: The current role of the user's team.
+ enum:
+ - owner
+ - captain
+ - vice-captain
+ - player
join:
type: string
format: date-time
diff --git a/html/assets/js/index.js b/html/assets/js/index.js
index aadb2b0..9eeec05 100644
--- a/html/assets/js/index.js
+++ b/html/assets/js/index.js
@@ -716,13 +716,13 @@ function showMyTeams(userId) {
for (var i in data.team_history) {
var team = data.team_history[i];
teamHistoryHtml += '
';
- teamHistoryHtml += '
' + team.name + '
';
+ teamHistoryHtml += '
[' + team.name + '] ' + team.role + '
';
teamHistoryHtml += '
Joined at: ' + new Date(team.join).toLocaleString() +
(team.left ? ', Left at: ' + new Date(team.left).toLocaleString() : ', ... ') + '
';
teamHistoryHtml += '
';
}
teamHistoryHtml += '';
- var currentTeamHtml = 'Current Team: ' + data.team_name + '
';
+ var currentTeamHtml = 'Current Team: [' + data.team_name + '] ' + data.team_role + '
';
$('#my_teams_content').html(currentTeamHtml + teamHistoryHtml);
$('#modal_my_teams').modal('show');
});
diff --git a/internal/app/database/struct_updater.go b/internal/app/database/struct_updater.go
index decda7e..a6b773c 100644
--- a/internal/app/database/struct_updater.go
+++ b/internal/app/database/struct_updater.go
@@ -44,6 +44,7 @@ func RegisterAllUpdates() map[string][]DatabaseUpdateFunc {
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0015_update0016)
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0016_update0016testdata)
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0016_update0017_no_university)
+ allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0017_update0018)
return allUpdates
}
diff --git a/internal/app/database/update0016_update0017.go b/internal/app/database/update0016_update0017.go
new file mode 100644
index 0000000..110f048
--- /dev/null
+++ b/internal/app/database/update0016_update0017.go
@@ -0,0 +1,32 @@
+package database
+
+import (
+ "database/sql"
+ "log/slog"
+ "runtime"
+)
+
+func DatabaseUpdate_update0016_update0017(db *sql.DB, getInfo bool) (string, string, string, error) {
+
+ // WARNING!!!
+ // Do not change the update if it has already been installed by other developers or in production.
+ // To correct the database, create a new update and register it in the list of updates.
+
+ fromUpdateId, toUpdateId := ParseNameFuncUpdate(runtime.Caller(0))
+ description := "Add role to profile and team history"
+ if getInfo {
+ return fromUpdateId, toUpdateId, description, nil
+ }
+ query := `
+ BEGIN;
+ ALTER TABLE profiles ADD COLUMN role varchar(50) default 'player' NOT NULL;
+ ALTER TABLE team_history ADD COLUMN role varchar(50) default 'player' NOT NULL;
+ COMMIT;
+ `
+ _, err := db.Query(query)
+ if err != nil {
+ slog.Error("Problem with select, query: " + query + "\n error:" + err.Error())
+ return fromUpdateId, toUpdateId, description, err
+ }
+ return fromUpdateId, toUpdateId, description, nil
+}
diff --git a/internal/app/database/update0017_update0017testdata.go b/internal/app/database/update0017_update0017testdata.go
new file mode 100644
index 0000000..249388e
--- /dev/null
+++ b/internal/app/database/update0017_update0017testdata.go
@@ -0,0 +1,29 @@
+package database
+
+import (
+ "database/sql"
+ "log/slog"
+ "runtime"
+)
+
+func DatabaseUpdate_update0017_update0017testdata(db *sql.DB, getInfo bool) (string, string, string, error) {
+
+ // WARNING!!!
+ // Do not change the update if it has already been installed by other developers or in production.
+ // To correct the database, create a new update and register it in the list of updates.
+
+ fromUpdateId, toUpdateId := ParseNameFuncUpdate(runtime.Caller(0))
+ description := "Flush team_history table"
+ if getInfo {
+ return fromUpdateId, toUpdateId, description, nil
+ }
+
+ query := `
+ `
+ _, err := db.Query(query)
+ if err != nil {
+ slog.Error("Problem with select, query: " + query + "\n error:" + err.Error())
+ return fromUpdateId, toUpdateId, description, err
+ }
+ return fromUpdateId, toUpdateId, description, nil
+}
diff --git a/internal/app/database/update0017_update0018.go b/internal/app/database/update0017_update0018.go
new file mode 100644
index 0000000..8159b24
--- /dev/null
+++ b/internal/app/database/update0017_update0018.go
@@ -0,0 +1,32 @@
+package database
+
+import (
+ "database/sql"
+ "log/slog"
+ "runtime"
+)
+
+func DatabaseUpdate_update0017_update0018(db *sql.DB, getInfo bool) (string, string, string, error) {
+
+ // WARNING!!!
+ // Do not change the update if it has already been installed by other developers or in production.
+ // To correct the database, create a new update and register it in the list of updates.
+
+ fromUpdateId, toUpdateId := ParseNameFuncUpdate(runtime.Caller(0))
+ description := "Add role to profile and team history"
+ if getInfo {
+ return fromUpdateId, toUpdateId, description, nil
+ }
+ query := `
+ BEGIN;
+ ALTER TABLE profiles ADD COLUMN role varchar(50) default 'player' NOT NULL;
+ ALTER TABLE team_history ADD COLUMN role varchar(50) default 'player' NOT NULL;
+ COMMIT;
+ `
+ _, err := db.Query(query)
+ if err != nil {
+ slog.Error("Problem with select, query: " + query + "\n error:" + err.Error())
+ return fromUpdateId, toUpdateId, description, err
+ }
+ return fromUpdateId, toUpdateId, description, nil
+}
diff --git a/internal/app/db/profile.go b/internal/app/db/profile.go
index ce72465..f7bac51 100644
--- a/internal/app/db/profile.go
+++ b/internal/app/db/profile.go
@@ -2,17 +2,22 @@ package db
import (
"time"
+
+ openapi_types "github.com/oapi-codegen/runtime/types"
)
type Profile struct {
- CurrentTeam string `db:"name"`
- CreatedAt time.Time `db:"created_at"`
- UpdatedAt time.Time `db:"created_at"`
+ Id openapi_types.UUID `db:"id"`
+ CurrentTeam string `db:"name"`
+ CreatedAt time.Time `db:"created_at"`
+ UpdatedAt time.Time `db:"created_at"`
+ Role string `db:"role"`
}
type ProfileTeams struct {
JoinedAt time.Time `db:"joined_at"`
LeftAt *time.Time `db:"left_at"`
+ Role string `db:"role"`
Name string `db:"name"`
}
diff --git a/internal/app/repository/user.go b/internal/app/repository/user.go
index c8dfe8e..f36534f 100644
--- a/internal/app/repository/user.go
+++ b/internal/app/repository/user.go
@@ -51,17 +51,17 @@ func (r *userRepo) AddUserToTeams(ctx context.Context, userId openapi_types.UUID
func (r *userRepo) GetProfileWithHistory(ctx context.Context, id openapi_types.UUID) (*models.ProfileWithHistory, error) {
query := `
- SELECT teams.name, created_at, updated_at
+ SELECT profiles.id, teams.name, role, created_at, updated_at
FROM profiles JOIN teams on profiles.current_team_id=teams.id
WHERE profiles.user_id = $1
`
profile := models.Profile{}
- err := r.db.QueryRowContext(ctx, query, id).Scan(&profile.CurrentTeam, &profile.CreatedAt, &profile.UpdatedAt)
+ err := r.db.QueryRowContext(ctx, query, id).Scan(&profile.Id, &profile.CurrentTeam, &profile.Role, &profile.CreatedAt, &profile.UpdatedAt)
if err != nil {
return nil, err
}
query = `
- SELECT joined_at, left_at, name
+ SELECT joined_at, left_at, name, role
FROM team_history
JOIN teams ON teams.id = team_history.team_id
WHERE user_id = $1
@@ -70,7 +70,7 @@ func (r *userRepo) GetProfileWithHistory(ctx context.Context, id openapi_types.U
var history []models.ProfileTeams
for rows.Next() {
var team models.ProfileTeams
- err := rows.Scan(&team.JoinedAt, &team.LeftAt, &team.Name)
+ err := rows.Scan(&team.JoinedAt, &team.LeftAt, &team.Name, &team.Role)
if err != nil {
return nil, err
}
diff --git a/internal/app/server/server.gen.go b/internal/app/server/server.gen.go
index 69b7ee8..de77224 100644
--- a/internal/app/server/server.gen.go
+++ b/internal/app/server/server.gen.go
@@ -13,6 +13,23 @@ import (
openapi_types "github.com/oapi-codegen/runtime/types"
)
+// Defines values for ProfileResponseTeamRole.
+const (
+ ProfileResponseTeamRoleCaptain ProfileResponseTeamRole = "captain"
+ ProfileResponseTeamRoleGuest ProfileResponseTeamRole = "guest"
+ ProfileResponseTeamRoleOwner ProfileResponseTeamRole = "owner"
+ ProfileResponseTeamRolePlayer ProfileResponseTeamRole = "player"
+ ProfileResponseTeamRoleViceCaptain ProfileResponseTeamRole = "vice-captain"
+)
+
+// Defines values for TeamHistoryRole.
+const (
+ TeamHistoryRoleCaptain TeamHistoryRole = "captain"
+ TeamHistoryRoleOwner TeamHistoryRole = "owner"
+ TeamHistoryRolePlayer TeamHistoryRole = "player"
+ TeamHistoryRoleViceCaptain TeamHistoryRole = "vice-captain"
+)
+
// Defines values for UserRequestRole.
const (
UserRequestRoleAdmin UserRequestRole = "admin"
@@ -57,21 +74,27 @@ type GameResponse struct {
// ProfileResponse The response schema for a user's profile, including id, timestamps, team name, and team history.
type ProfileResponse struct {
// CreatedAt The timestamp when the user profile was created.
- CreatedAt *time.Time `json:"created_at,omitempty"`
+ CreatedAt time.Time `json:"created_at"`
// Id The unique identifier for the user.
- Id *openapi_types.UUID `json:"id,omitempty"`
+ Id openapi_types.UUID `json:"id"`
// TeamHistory The list of teams the user has been part of, including the periods of membership.
TeamHistory *[]TeamHistory `json:"team_history,omitempty"`
// TeamName The current name of the user's team.
- TeamName *string `json:"team_name,omitempty"`
+ TeamName string `json:"team_name"`
+
+ // TeamRole The current role of the user's team.
+ TeamRole ProfileResponseTeamRole `json:"team_role"`
// UpdatedAt The timestamp when the user profile was last updated.
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
+// ProfileResponseTeamRole The current role of the user's team.
+type ProfileResponseTeamRole string
+
// ResultRequest defines model for ResultRequest.
type ResultRequest struct {
// GameId Identifier of the game this result is for
@@ -165,8 +188,14 @@ type TeamHistory struct {
// Name The name of the team.
Name string `json:"name"`
+
+ // Role The current role of the user's team.
+ Role TeamHistoryRole `json:"role"`
}
+// TeamHistoryRole The current role of the user's team.
+type TeamHistoryRole string
+
// TeamRequest defines model for TeamRequest.
type TeamRequest struct {
// AvatarUrl URL to the team's avatar
diff --git a/internal/app/view/profile.go b/internal/app/view/profile.go
index afeee2a..537df81 100644
--- a/internal/app/view/profile.go
+++ b/internal/app/view/profile.go
@@ -8,9 +8,11 @@ import (
func NewProfileFromModel(p *db.ProfileWithHistory) *server.ProfileResponse {
return &server.ProfileResponse{
- CreatedAt: &p.Profile.CreatedAt,
+ Id: p.Profile.Id,
+ CreatedAt: p.Profile.CreatedAt,
UpdatedAt: &p.Profile.UpdatedAt,
- TeamName: &p.Profile.CurrentTeam,
+ TeamName: p.Profile.CurrentTeam,
+ TeamRole: server.ProfileResponseTeamRole(p.Profile.Role),
TeamHistory: makeTeamHistory(p.History),
}
}
@@ -22,6 +24,7 @@ func makeTeamHistory(tms []db.ProfileTeams) *[]server.TeamHistory {
Join: tm.JoinedAt,
Left: tm.LeftAt,
Name: tm.Name,
+ Role: server.TeamHistoryRole(tm.Role),
})
}
return &out