mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: tokens (#4380)
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package codersdk
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type APIKey struct {
|
||||
ID string `json:"id" validate:"required"`
|
||||
// NOTE: do not ever return the HashedSecret
|
||||
UserID uuid.UUID `json:"user_id" validate:"required"`
|
||||
LastUsed time.Time `json:"last_used" validate:"required"`
|
||||
ExpiresAt time.Time `json:"expires_at" validate:"required"`
|
||||
CreatedAt time.Time `json:"created_at" validate:"required"`
|
||||
UpdatedAt time.Time `json:"updated_at" validate:"required"`
|
||||
LoginType LoginType `json:"login_type" validate:"required"`
|
||||
LifetimeSeconds int64 `json:"lifetime_seconds" validate:"required"`
|
||||
}
|
||||
|
||||
type LoginType string
|
||||
|
||||
const (
|
||||
LoginTypePassword LoginType = "password"
|
||||
LoginTypeGithub LoginType = "github"
|
||||
LoginTypeOIDC LoginType = "oidc"
|
||||
LoginTypeToken LoginType = "token"
|
||||
)
|
||||
|
||||
// CreateToken generates an API key that doesn't expire.
|
||||
func (c *Client) CreateToken(ctx context.Context, userID string) (*GenerateAPIKeyResponse, error) {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys/tokens", userID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode > http.StatusCreated {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
apiKey := &GenerateAPIKeyResponse{}
|
||||
return apiKey, json.NewDecoder(res.Body).Decode(apiKey)
|
||||
}
|
||||
|
||||
// GetTokens list machine API keys.
|
||||
func (c *Client) GetTokens(ctx context.Context, userID string) ([]APIKey, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/keys/tokens", userID), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode > http.StatusOK {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
var apiKey = []APIKey{}
|
||||
return apiKey, json.NewDecoder(res.Body).Decode(&apiKey)
|
||||
}
|
||||
|
||||
// GetAPIKey returns the api key by id.
|
||||
func (c *Client) GetAPIKey(ctx context.Context, userID string, id string) (*APIKey, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/keys/%s", userID, id), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode > http.StatusCreated {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
apiKey := &APIKey{}
|
||||
return apiKey, json.NewDecoder(res.Body).Decode(apiKey)
|
||||
}
|
||||
|
||||
// DeleteAPIKey deletes API key by id.
|
||||
func (c *Client) DeleteAPIKey(ctx context.Context, userID string, id string) error {
|
||||
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/users/%s/keys/%s", userID, id), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode > http.StatusNoContent {
|
||||
return readBodyAsError(res)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -22,14 +22,6 @@ const (
|
||||
UserStatusSuspended UserStatus = "suspended"
|
||||
)
|
||||
|
||||
type LoginType string
|
||||
|
||||
const (
|
||||
LoginTypePassword LoginType = "password"
|
||||
LoginTypeGithub LoginType = "github"
|
||||
LoginTypeOIDC LoginType = "oidc"
|
||||
)
|
||||
|
||||
type UsersRequest struct {
|
||||
Search string `json:"search,omitempty" typescript:"-"`
|
||||
// Filter users by status.
|
||||
@@ -55,18 +47,6 @@ type User struct {
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
type APIKey struct {
|
||||
ID string `json:"id" validate:"required"`
|
||||
// NOTE: do not ever return the HashedSecret
|
||||
UserID uuid.UUID `json:"user_id" validate:"required"`
|
||||
LastUsed time.Time `json:"last_used" validate:"required"`
|
||||
ExpiresAt time.Time `json:"expires_at" validate:"required"`
|
||||
CreatedAt time.Time `json:"created_at" validate:"required"`
|
||||
UpdatedAt time.Time `json:"updated_at" validate:"required"`
|
||||
LoginType LoginType `json:"login_type" validate:"required"`
|
||||
LifetimeSeconds int64 `json:"lifetime_seconds" validate:"required"`
|
||||
}
|
||||
|
||||
type CreateFirstUserRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Username string `json:"username" validate:"required,username"`
|
||||
@@ -287,33 +267,6 @@ func (c *Client) GetUserRoles(ctx context.Context, user string) (UserRoles, erro
|
||||
return roles, json.NewDecoder(res.Body).Decode(&roles)
|
||||
}
|
||||
|
||||
// CreateAPIKey generates an API key for the user ID provided.
|
||||
func (c *Client) CreateAPIKey(ctx context.Context, user string) (*GenerateAPIKeyResponse, error) {
|
||||
res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/users/%s/keys", user), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode > http.StatusCreated {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
apiKey := &GenerateAPIKeyResponse{}
|
||||
return apiKey, json.NewDecoder(res.Body).Decode(apiKey)
|
||||
}
|
||||
|
||||
func (c *Client) GetAPIKey(ctx context.Context, user string, id string) (*APIKey, error) {
|
||||
res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/users/%s/keys/%s", user, id), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode > http.StatusCreated {
|
||||
return nil, readBodyAsError(res)
|
||||
}
|
||||
apiKey := &APIKey{}
|
||||
return apiKey, json.NewDecoder(res.Body).Decode(apiKey)
|
||||
}
|
||||
|
||||
// LoginWithPassword creates a session token authenticating with an email and password.
|
||||
// Call `SetSessionToken()` to apply the newly acquired token to the client.
|
||||
func (c *Client) LoginWithPassword(ctx context.Context, req LoginWithPasswordRequest) (LoginWithPasswordResponse, error) {
|
||||
|
||||
Reference in New Issue
Block a user