Skip to content
This repository has been archived by the owner on Jun 21, 2024. It is now read-only.

Commit

Permalink
add Invitations service and User creation methods (#346)
Browse files Browse the repository at this point in the history
* add Invitations service and User creation methods

Signed-off-by: Marques Johansson <[email protected]>
  • Loading branch information
displague committed Sep 28, 2022
1 parent 3db2829 commit 3db8aff
Show file tree
Hide file tree
Showing 3 changed files with 191 additions and 5 deletions.
155 changes: 155 additions & 0 deletions invitations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package packngo

import (
"path"
)

const (
invitationsBasePath = "/invitations"
)

// InvitationService interface defines available invitation methods
type InvitationService interface {
Create(string, *InvitationCreateRequest, *GetOptions) (*Invitation, *Response, error)
List(string, *ListOptions) ([]Invitation, *Response, error)
Get(string, *GetOptions) (*Invitation, *Response, error)
Accept(string, *InvitationUpdateRequest) (*Invitation, *Response, error)
Resend(string) (*Invitation, *Response, error)
Delete(string) (*Response, error)
}

type invitationsRoot struct {
Invitations []Invitation `json:"invitations"`
Meta meta `json:"meta"`
}

// Invitation represents an Equinix Metal invitation
type Invitation struct {
*Href `json:",inline"`
ID string `json:"id,omitempty"`
Invitation Href `json:"invitation,omitempty"`
InvitedBy Href `json:"invited_by,omitempty"`
Invitee string `json:"invitee,omitempty"`
Nonce string `json:"nonce,omitempty"`
Organization Href `json:"organization,omitempty"`
Projects []Href `json:"projects,omitempty"`
Roles []string `json:"roles,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}

// InvitationCreateRequest struct for InvitationService.Create
type InvitationCreateRequest struct {
// Invitee is the email address of the recipient
Invitee string `json:"invitee"`
Message string `json:"message,omitempty"`
ProjectsIDs []string `json:"projects_ids,omitempty"`
Roles []string `json:"roles,omitempty"`
}

// InvitationUpdateRequest struct for InvitationService.Update
type InvitationUpdateRequest struct{}

func (u Invitation) String() string {
return Stringify(u)
}

// InvitationServiceOp implements InvitationService
type InvitationServiceOp struct {
client *Client
}

var _ InvitationService = (*InvitationServiceOp)(nil)

// Lists open invitations to the project
func (s *InvitationServiceOp) List(organizationID string, opts *ListOptions) (invitations []Invitation, resp *Response, err error) {
endpointPath := path.Join(organizationBasePath, organizationID, invitationsBasePath)
apiPathQuery := opts.WithQuery(endpointPath)

for {
subset := new(invitationsRoot)

resp, err = s.client.DoRequest("GET", apiPathQuery, nil, subset)
if err != nil {
return nil, resp, err
}

invitations = append(invitations, subset.Invitations...)

if apiPathQuery = nextPage(subset.Meta, opts); apiPathQuery != "" {
continue
}
return
}
}

// Create a Invitation with the given InvitationCreateRequest. New invitation VerificationStage
// will be AccountCreated, unless InvitationCreateRequest contains an valid
// InvitationID and Nonce in which case the VerificationStage will be Verified.
func (s *InvitationServiceOp) Create(organizationID string, createRequest *InvitationCreateRequest, opts *GetOptions) (*Invitation, *Response, error) {
endpointPath := path.Join(organizationBasePath, organizationID, invitationsBasePath)
apiPathQuery := opts.WithQuery(endpointPath)
invitation := new(Invitation)

resp, err := s.client.DoRequest("POST", apiPathQuery, createRequest, invitation)
if err != nil {
return nil, resp, err
}

return invitation, resp, err
}

func (s *InvitationServiceOp) Get(invitationID string, opts *GetOptions) (*Invitation, *Response, error) {
if validateErr := ValidateUUID(invitationID); validateErr != nil {
return nil, nil, validateErr
}
endpointPath := path.Join(invitationsBasePath, invitationID)
apiPathQuery := opts.WithQuery(endpointPath)
invitation := new(Invitation)

resp, err := s.client.DoRequest("GET", apiPathQuery, nil, invitation)
if err != nil {
return nil, resp, err
}

return invitation, resp, err
}

// Update updates the current invitation
func (s *InvitationServiceOp) Delete(id string) (*Response, error) {
opts := &GetOptions{}
endpointPath := path.Join(invitationsBasePath, id)
apiPathQuery := opts.WithQuery(endpointPath)

return s.client.DoRequest("DELETE", apiPathQuery, nil, nil)
}

// Update updates the current invitation
func (s *InvitationServiceOp) Accept(id string, updateRequest *InvitationUpdateRequest) (*Invitation, *Response, error) {
opts := &GetOptions{}
endpointPath := path.Join(invitationsBasePath, id)
apiPathQuery := opts.WithQuery(endpointPath)
invitation := new(Invitation)

resp, err := s.client.DoRequest("PUT", apiPathQuery, updateRequest, invitation)
if err != nil {
return nil, resp, err
}

return invitation, resp, err
}

// Update updates the current invitation
func (s *InvitationServiceOp) Resend(id string) (*Invitation, *Response, error) {
opts := &GetOptions{}
endpointPath := path.Join(invitationsBasePath, id)
apiPathQuery := opts.WithQuery(endpointPath)
invitation := new(Invitation)

resp, err := s.client.DoRequest("POST", apiPathQuery, nil, invitation)
if err != nil {
return nil, resp, err
}

return invitation, resp, err
}
4 changes: 2 additions & 2 deletions packngo.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ type Client struct {
Events EventService
Facilities FacilityService
HardwareReservations HardwareReservationService
Invitations InvitationService
Metros MetroService
Notifications NotificationService
OperatingSystems OSService
Expand Down Expand Up @@ -339,7 +340,6 @@ func NewClient() (*Client, error) {
}
c := NewClientWithAuth("packngo lib", apiToken, nil)
return c, nil

}

// NewClientWithAuth initializes and returns a Client, use this to get an API Client to operate on
Expand Down Expand Up @@ -377,6 +377,7 @@ func NewClientWithBaseURL(consumerToken string, apiKey string, httpClient *http.
c.Events = &EventServiceOp{client: c}
c.Facilities = &FacilityServiceOp{client: c}
c.HardwareReservations = &HardwareReservationServiceOp{client: c}
c.Invitations = &InvitationServiceOp{client: c}
c.Metros = &MetroServiceOp{client: c}
c.Notifications = &NotificationServiceOp{client: c}
c.OperatingSystems = &OSServiceOp{client: c}
Expand All @@ -403,7 +404,6 @@ func NewClientWithBaseURL(consumerToken string, apiKey string, httpClient *http.
}

func checkResponse(r *http.Response) error {

if s := r.StatusCode; s >= 200 && s <= 299 {
// response is good, return
return nil
Expand Down
37 changes: 34 additions & 3 deletions user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import (
"path"
)

const usersBasePath = "/users"
const userBasePath = "/user"
const (
usersBasePath = "/users"
userBasePath = "/user"
)

// UserService interface defines available user methods
type UserService interface {
Create(*UserCreateRequest) (*User, *Response, error)
Current() (*User, *Response, error)
List(*ListOptions) ([]User, *Response, error)
Get(string, *GetOptions) (*User, *Response, error)
Current() (*User, *Response, error)
Update(*UserUpdateRequest) (*User, *Response, error)
}

Expand Down Expand Up @@ -83,6 +86,17 @@ type UserLite struct {
AvatarThumbURL string `json:"avatar_thumb_url,omitempty"`
}

// UserCreateRequest struct for UserService.Create
type UserCreateRequest struct {
InvitationID string `json:"invitation_id,omitempty"`
Nonce string `json:"nonce,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
Password string `json:"password,omitempty"`
Customdata *interface{} `json:"customdata,omitempty"`
Emails []EmailRequest `json:"emails,omitempty"`
}

// UserUpdateRequest struct for UserService.Update
type UserUpdateRequest struct {
FirstName *string `json:"first_name,omitempty"`
Expand Down Expand Up @@ -124,6 +138,23 @@ func (s *UserServiceOp) List(opts *ListOptions) (users []User, resp *Response, e
}
}

// Create a User with the given UserCreateRequest. New user VerificationStage
// will be AccountCreated, unless UserCreateRequest contains an valid
// InvitationID and Nonce in which case the VerificationStage will be Verified.
func (s *UserServiceOp) Create(createRequest *UserCreateRequest) (*User, *Response, error) {
opts := &GetOptions{}
endpointPath := path.Join(usersBasePath)
apiPathQuery := opts.WithQuery(endpointPath)
user := new(User)

resp, err := s.client.DoRequest("POST", apiPathQuery, createRequest, user)
if err != nil {
return nil, resp, err
}

return user, resp, err
}

// Returns the user object for the currently logged-in user.
func (s *UserServiceOp) Current() (*User, *Response, error) {
user := new(User)
Expand Down

0 comments on commit 3db8aff

Please sign in to comment.