github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/model/organizations.go (about)

     1  package model
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/go-openapi/strfmt"
     7  	"github.com/thoas/go-funk"
     8  
     9  	"github.com/ActiveState/cli/internal/errs"
    10  	"github.com/ActiveState/cli/internal/locale"
    11  	"github.com/ActiveState/cli/internal/logging"
    12  	"github.com/ActiveState/cli/pkg/platform/api"
    13  	"github.com/ActiveState/cli/pkg/platform/api/graphql"
    14  	"github.com/ActiveState/cli/pkg/platform/api/graphql/model"
    15  	"github.com/ActiveState/cli/pkg/platform/api/graphql/request"
    16  	clientOrgs "github.com/ActiveState/cli/pkg/platform/api/mono/mono_client/organizations"
    17  	"github.com/ActiveState/cli/pkg/platform/api/mono/mono_models"
    18  	"github.com/ActiveState/cli/pkg/platform/authentication"
    19  )
    20  
    21  var ErrMemberNotFound = errs.New("member not found")
    22  
    23  // FetchOrganizations fetches all organizations for the current user.
    24  func FetchOrganizations(auth *authentication.Auth) ([]*mono_models.Organization, error) {
    25  	authClient, err := auth.Client()
    26  	if err != nil {
    27  		return nil, errs.Wrap(err, "Could not get auth client")
    28  	}
    29  	params := clientOrgs.NewListOrganizationsParams()
    30  	memberOnly := true
    31  	params.SetMemberOnly(&memberOnly)
    32  	res, err := authClient.Organizations.ListOrganizations(params, auth.ClientAuth())
    33  
    34  	if err != nil {
    35  		return nil, processOrgErrorResponse(err)
    36  	}
    37  
    38  	return res.Payload, nil
    39  }
    40  
    41  // FetchOrgByURLName fetches an organization accessible to the current user by it's URL Name.
    42  func FetchOrgByURLName(urlName string, auth *authentication.Auth) (*mono_models.Organization, error) {
    43  	authClient, err := auth.Client()
    44  	if err != nil {
    45  		return nil, errs.Wrap(err, "Could not get auth client")
    46  	}
    47  	params := clientOrgs.NewGetOrganizationParams()
    48  	params.OrganizationIdentifier = urlName
    49  	resOk, err := authClient.Organizations.GetOrganization(params, auth.ClientAuth())
    50  	if err != nil {
    51  		return nil, processOrgErrorResponse(err)
    52  	}
    53  	return resOk.Payload, nil
    54  }
    55  
    56  // FetchOrgMembers fetches the members of an organization accessible to the current user by it's URL Name.
    57  func FetchOrgMembers(urlName string, auth *authentication.Auth) ([]*mono_models.Member, error) {
    58  	authClient, err := auth.Client()
    59  	if err != nil {
    60  		return nil, errs.Wrap(err, "Could not get auth client")
    61  	}
    62  	params := clientOrgs.NewGetOrganizationMembersParams()
    63  	params.OrganizationName = urlName
    64  	resOk, err := authClient.Organizations.GetOrganizationMembers(params, auth.ClientAuth())
    65  	if err != nil {
    66  		return nil, processOrgErrorResponse(err)
    67  	}
    68  	return resOk.Payload, nil
    69  }
    70  
    71  // FetchOrgMember fetches the member of an organization accessible to the current user by it's URL Name.
    72  func FetchOrgMember(orgName, name string, auth *authentication.Auth) (*mono_models.Member, error) {
    73  	members, err := FetchOrgMembers(orgName, auth)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	for _, member := range members {
    79  		if strings.EqualFold(name, member.User.Username) {
    80  			return member, nil
    81  		}
    82  	}
    83  
    84  	return nil, locale.WrapError(ErrMemberNotFound, "err_api_member_not_found")
    85  }
    86  
    87  // InviteUserToOrg invites a single user (via email address) to a given
    88  // organization.
    89  //
    90  // # The invited user can be added as an owner or a member
    91  //
    92  // Note: This method only returns the invitation for the new user, not existing
    93  // users.
    94  func InviteUserToOrg(orgName string, asOwner bool, email string, auth *authentication.Auth) (*mono_models.Invitation, error) {
    95  	authClient, err := auth.Client()
    96  	if err != nil {
    97  		return nil, errs.Wrap(err, "Could not get auth client")
    98  	}
    99  	params := clientOrgs.NewInviteOrganizationParams()
   100  	role := mono_models.RoleReader
   101  	if asOwner {
   102  		role = mono_models.RoleAdmin
   103  	}
   104  	body := clientOrgs.InviteOrganizationBody{
   105  		AddedOnly: true,
   106  		Role:      &role,
   107  	}
   108  	params.SetOrganizationName(orgName)
   109  	params.SetAttributes(body)
   110  	params.SetEmail(email)
   111  	resOk, err := authClient.Organizations.InviteOrganization(params, auth.ClientAuth())
   112  	if err != nil {
   113  		return nil, processInviteErrorResponse(err)
   114  	}
   115  	if len(resOk.Payload) != 1 {
   116  		return nil, locale.NewError("err_api_org_invite_expected_one_invite")
   117  	}
   118  	return resOk.Payload[0], nil
   119  
   120  }
   121  
   122  // FetchOrganizationsByIDs fetches organizations by their IDs
   123  func FetchOrganizationsByIDs(ids []strfmt.UUID, auth *authentication.Auth) ([]model.Organization, error) {
   124  	ids = funk.Uniq(ids).([]strfmt.UUID)
   125  	request := request.OrganizationsByIDs(ids)
   126  
   127  	gql := graphql.New(auth)
   128  	response := model.Organizations{}
   129  	err := gql.Run(request, &response)
   130  	if err != nil {
   131  		return nil, errs.Wrap(err, "gql.Run failed")
   132  	}
   133  
   134  	if len(response.Organizations) != len(ids) {
   135  		logging.Debug("Organization membership mismatch: %d members returned for %d members requested. Caller must account for this.", len(response.Organizations), len(ids))
   136  	}
   137  
   138  	return response.Organizations, nil
   139  }
   140  
   141  func processOrgErrorResponse(err error) error {
   142  	switch statusCode := api.ErrorCode(err); statusCode {
   143  	case 401:
   144  		return locale.NewExternalError("err_api_not_authenticated")
   145  	case 404:
   146  		return locale.NewExternalError("err_api_org_not_found")
   147  	default:
   148  		return err
   149  	}
   150  }
   151  
   152  func processInviteErrorResponse(err error) error {
   153  	switch statusCode := api.ErrorCode(err); statusCode {
   154  	case 400:
   155  		return locale.WrapExternalError(err, "err_api_invite_400", "Invalid request, did you enter a valid email address?")
   156  	case 401:
   157  		return locale.NewExternalError("err_api_not_authenticated")
   158  	case 404:
   159  		return locale.NewExternalError("err_api_org_not_found")
   160  	default:
   161  		return locale.WrapError(err, api.ErrorMessageFromPayload(err))
   162  	}
   163  }