From d725e813f8b55981f5f2f68d11d33e49f8511d1e Mon Sep 17 00:00:00 2001 From: Lucas TESSON Date: Wed, 7 Feb 2024 16:58:14 +0100 Subject: [PATCH] feat: improve support of users and teams --- api/setup_test.go | 122 ++++++++++++++++++++++++++++++++++++++++++++++ api/teams.go | 30 +++++++----- api/users.go | 30 ++++++++---- 3 files changed, 162 insertions(+), 20 deletions(-) diff --git a/api/setup_test.go b/api/setup_test.go index 013f624..7c011ad 100644 --- a/api/setup_test.go +++ b/api/setup_test.go @@ -317,3 +317,125 @@ func Test_F_AdvancedSetup(t *testing.T) { return } } + +func Test_F_UsersAndTeams(t *testing.T) { + // Scenario: + // + // As an Ops, your job is to import all the registered users and teams + // before the event such that at the very beginning you are sure no one + // is lost. + + assert := assert.New(t) + + // 1a. Get nonce and session to mock a browser first + nonce, session, err := api.GetNonceAndSession(CTFD_URL) + if !assert.Nil(err, "got error: %s", err) { + return + } + client := api.NewClient(CTFD_URL, nonce, session, "") + + t.Cleanup(func() { + _ = client.Reset(&api.ResetParams{ + Accounts: ptr("y"), + Submissions: ptr("y"), + Challenges: ptr("y"), + Pages: ptr("y"), + Notifications: ptr("y"), + }) + }) + + // 1b. Configure the CTF + err = client.Setup(&api.SetupParams{ + CTFName: "CTFer", + CTFDescription: "Ephemeral CTFd running for API tests purposes.", + UserMode: "teams", + Name: "ctfer", + Email: "ctfer-io@protonmail.com", + Password: "password", // This is not real, don't bother trying x) + ChallengeVisibility: "admins", + AccountVisibility: "private", + ScoreVisibility: "hidden", + RegistrationVisibility: "mlc", + VerifyEmails: false, + TeamSize: ptr(4), + CTFLogo: nil, + CTFBanner: nil, + CTFSmallIcon: nil, + CTFTheme: "core", + ThemeColor: "", + Start: "", + End: "", + Nonce: nonce, + }) + if !assert.Nil(err, "got error: %s", err) { + return + } + + // 1c. Create an API Key to avoid session/nonce+cookies dance + token, err := client.PostTokens(&api.PostTokensParams{ + Expiration: "2222-01-01", + Description: "Example API token.", + }) + if !assert.Nil(err, "got error: %s", err) { + return + } + client.SetAPIKey(*token.Value) + + // Define all users and teams + type User struct { + name, email, password string + } + type Team struct { + name, email, password string + users []User + } + var teams = []Team{ + { + name: "MILF CTF Team", + email: "milfctf@example.com", + password: "password", + users: []User{ + { + name: "hashp4", + email: "hashp4@example.com", + password: "password", + }, + // ... + }, + }, + } + + // 2. Create all the users and their teams + for _, team := range teams { + // 2a. Create team + tm, err := client.PostTeams(&api.PostTeamsParams{ + Name: team.name, + Email: team.email, + Password: team.password, + }) + if !assert.Nil(err, "got error: %s", err) { + return + } + + for _, user := range team.users { + // 2b. Create user + usr, err := client.PostUsers(&api.PostUsersParams{ + Name: user.name, + Email: user.email, + Password: user.password, + Type: "user", + }) + if !assert.Nil(err, "got error: %s", err) { + return + } + + // 2c. Join user to team + _, err = client.PostTeamMembers(tm.ID, &api.PostTeamsMembers{ + UserID: usr.ID, + }) + if !assert.Nil(err, "got error: %s", err) { + return + } + } + } +} diff --git a/api/teams.go b/api/teams.go index c2c9ffb..67aeba8 100644 --- a/api/teams.go +++ b/api/teams.go @@ -19,12 +19,15 @@ func (client *Client) GetTeams(params *GetTeamsParams, opts ...Option) ([]*Team, } type PostTeamsParams struct { - Name string `json:"name"` - Password string `json:"password"` - Email string `json:"email"` - Banned bool `json:"banned"` - Hidden bool `json:"hidden"` - Fields []string `json:"fields"` + Name string `json:"name"` + Email string `json:"email"` + Password string `json:"password"` + Website *string `json:"website,omitempty"` + Affiliation *string `json:"affiliation,omitempty"` + Country *string `json:"country,omitempty"` + Banned bool `json:"banned"` + Hidden bool `json:"hidden"` + Fields []Field `json:"fields"` } func (client *Client) PostTeams(params *PostTeamsParams, opts ...Option) (*Team, error) { @@ -48,11 +51,16 @@ func (client *Client) DeleteTeamsMe(opts ...Option) error { } type PatchTeamsParams struct { - CaptainID *int `json:"captain_id,omitempty"` - Banned *bool `json:"banned,omitempty"` - Fields []Field `json:"fields,omitempty"` - Hidden *bool `json:"hidden,omitempty"` - Name *string `json:"name,omitempty"` + CaptainID *int `json:"captain_id,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + Password *string `json:"password,omitempty"` + Website *string `json:"website,omitempty"` + Affiliation *string `json:"affiliation,omitempty"` + Country *string `json:"country,omitempty"` + Banned *bool `json:"banned,omitempty"` + Hidden *bool `json:"hidden,omitempty"` + Fields []Field `json:"fields"` } func (client *Client) PatchTeamsMe(params *PatchTeamsParams, opts ...Option) (*Team, error) { diff --git a/api/users.go b/api/users.go index 6f98e39..cd294fc 100644 --- a/api/users.go +++ b/api/users.go @@ -20,14 +20,18 @@ func (client *Client) GetUsers(params *GetUsersParams, opts ...Option) ([]*User, } type PostUsersParams struct { - Name string `json:"name"` - Password string `json:"password"` - Email string `json:"email"` - Type string `json:"type"` - Banned bool `json:"banned"` - Hidden bool `json:"hidden"` - Verified bool `json:"verified"` - Fields []string `json:"fields"` + Name string `json:"name"` + Email string `json:"email"` + Language *string `json:"language,omitempty"` + Password string `json:"password"` + Website *string `json:"website,omitempty"` + Affiliation *string `json:"affiliation,omitempty"` + Country *string `json:"country,omitempty"` + Type string `json:"type"` // "user" or "admin" + Verified bool `json:"verified"` + Hidden bool `json:"hidden"` + Banned bool `json:"banned"` + Fields []Field `json:"fields"` } func (client *Client) PostUsers(params *PostUsersParams, opts ...Option) (*User, error) { @@ -49,7 +53,15 @@ func (client *Client) GetUsersMe(opts ...Option) (*User, error) { type PatchUsersParams struct { Name string `json:"name"` Email string `json:"email"` - Affiliation string `json:"affiliation"` + Language *string `json:"language,omitempty"` + Password *string `json:"password,omitempty"` + Website *string `json:"website,omitempty"` + Affiliation *string `json:"affiliation,omitempty"` + Country *string `json:"country,omitempty"` + Type string `json:"type"` + Verified bool `json:"verified"` + Hidden bool `json:"hidden"` + Banned bool `json:"banned"` Fields []Field `json:"fields"` }