-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
167 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"crypto/tls" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
// Client holds the connection to the OpenSlides server. | ||
type Client struct { | ||
addr string | ||
hc *http.Client | ||
|
||
authCookie *http.Cookie | ||
authToken string | ||
} | ||
|
||
// New initializes a new client. | ||
func New(addr string) (*Client, error) { | ||
c := Client{ | ||
addr: addr, | ||
hc: &http.Client{ | ||
Transport: &http.Transport{ | ||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, | ||
}, | ||
}, | ||
} | ||
|
||
return &c, nil | ||
} | ||
|
||
// Do is like http.Do but uses the credentials. | ||
func (c *Client) Do(req *http.Request) (*http.Response, error) { | ||
req.Header.Set("authentication", c.authToken) | ||
req.Header.Add("cookie", c.authCookie.String()) | ||
return checkStatus(c.hc.Do(req)) | ||
} | ||
|
||
// Login uses the username and password to login the client. Sets the returned | ||
// cookie for later requests. | ||
func (c *Client) Login(ctx context.Context, username, password string) error { | ||
url := c.addr + "/system/auth/login" | ||
payload := fmt.Sprintf(`{"username": "%s", "password": "%s"}`, username, password) | ||
|
||
req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(payload)) | ||
if err != nil { | ||
return fmt.Errorf("creating request: %w", err) | ||
} | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
resp, err := checkStatus(c.hc.Do(req)) | ||
if err != nil { | ||
return fmt.Errorf("sending login request: %w", err) | ||
} | ||
defer resp.Body.Close() | ||
|
||
c.authToken = resp.Header.Get("authentication") | ||
for _, cookie := range resp.Cookies() { | ||
if cookie.Name == "refreshId" { | ||
c.authCookie = cookie | ||
break | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// checkStatus is a helper that can be used around http.Do(). | ||
// | ||
// It checks, that the returned status code in the 200er range. | ||
func checkStatus(resp *http.Response, err error) (*http.Response, error) { | ||
if err != nil { | ||
return nil, fmt.Errorf("sending login request: %w", err) | ||
} | ||
|
||
if resp.StatusCode < 200 || resp.StatusCode > 299 { | ||
body, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
body = []byte("[can not read body]") | ||
} | ||
resp.Body.Close() | ||
return nil, fmt.Errorf("got status %s: %s", resp.Status, body) | ||
} | ||
return resp, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"strings" | ||
"time" | ||
|
||
"github.com/OpenSlides/openslides-performance/client" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const createUsersHelp = `Creates many users | ||
This command does not run any test. It is a helper for other tests that | ||
require, that there a many users created at the server. | ||
Do not run this command against a productive instance. It will change | ||
the database. | ||
Each user is called dummy1, dummy2 etc and has the password "pass".` | ||
|
||
func cmdCreateUsers(cfg *config) *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "create_users", | ||
Short: "Create a lot of users.", | ||
Long: createUsersHelp, | ||
} | ||
createUserAmount := cmd.Flags().IntP("amount", "a", 10, "Amount of users to create.") | ||
|
||
cmd.RunE = func(cmd *cobra.Command, args []string) error { | ||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) | ||
defer cancel() | ||
|
||
c, err := client.New(cfg.addr()) | ||
if err != nil { | ||
return fmt.Errorf("creating client: %w", err) | ||
} | ||
|
||
if err := c.Login(ctx, cfg.username, cfg.password); err != nil { | ||
return fmt.Errorf("login client: %w", err) | ||
} | ||
|
||
var users []string | ||
for i := 0; i < *createUserAmount; i++ { | ||
users = append(users, fmt.Sprintf(`{"username":"dummy%d","default_password":"pass","is_active":true}`, i+1)) | ||
} | ||
|
||
createBody := fmt.Sprintf( | ||
`[{ | ||
"action": "user.create", | ||
"data": [%s] | ||
}]`, | ||
strings.Join(users, ","), | ||
) | ||
|
||
req, err := http.NewRequestWithContext( | ||
ctx, | ||
"POST", | ||
cfg.addr()+"/system/action/handle_request", | ||
strings.NewReader(createBody), | ||
) | ||
if err != nil { | ||
return fmt.Errorf("creating request: %w", err) | ||
} | ||
req.Header.Set("Content-Type", "application/json") | ||
|
||
if _, err := c.Do(req); err != nil { | ||
return fmt.Errorf("sending request: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters