github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/clientlists/client_list.go (about)

     1  package clientlists
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"net/url"
     8  	"strconv"
     9  
    10  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/edgegriderr"
    11  	validation "github.com/go-ozzo/ozzo-validation/v4"
    12  )
    13  
    14  type (
    15  	// Lists interface to support creating, retrieving, updating and removing client lists.
    16  	Lists interface {
    17  		// GetClientLists lists all client lists accessible for an authenticated user
    18  		//
    19  		// See: https://techdocs.akamai.com/client-lists/reference/get-lists
    20  		GetClientLists(ctx context.Context, params GetClientListsRequest) (*GetClientListsResponse, error)
    21  
    22  		// GetClientList retrieves client list with specific list id
    23  		//
    24  		// See: https://techdocs.akamai.com/client-lists/reference/get-list
    25  		GetClientList(ctx context.Context, params GetClientListRequest) (*GetClientListResponse, error)
    26  
    27  		// CreateClientList creates a new client list
    28  		//
    29  		// See: https://techdocs.akamai.com/client-lists/reference/post-create-list
    30  		CreateClientList(ctx context.Context, params CreateClientListRequest) (*CreateClientListResponse, error)
    31  
    32  		// UpdateClientList updates existing client list
    33  		//
    34  		// See: https://techdocs.akamai.com/client-lists/reference/put-update-list
    35  		UpdateClientList(ctx context.Context, params UpdateClientListRequest) (*UpdateClientListResponse, error)
    36  
    37  		// UpdateClientListItems updates items/entries of an existing client lists
    38  		//
    39  		// See: https://techdocs.akamai.com/client-lists/reference/post-update-items
    40  		UpdateClientListItems(ctx context.Context, params UpdateClientListItemsRequest) (*UpdateClientListItemsResponse, error)
    41  
    42  		// DeleteClientList removes a client list
    43  		//
    44  		// See: https://techdocs.akamai.com/client-lists/reference/delete-list
    45  		DeleteClientList(ctx context.Context, params DeleteClientListRequest) error
    46  	}
    47  
    48  	// ClientListType represents client list type
    49  	ClientListType string
    50  
    51  	// GetClientListsRequest contains request parameters for GetClientLists method
    52  	GetClientListsRequest struct {
    53  		Type               []ClientListType
    54  		Name               string
    55  		Search             string
    56  		IncludeItems       bool
    57  		IncludeDeprecated  bool
    58  		IncludeNetworkList bool
    59  		Page               *int
    60  		PageSize           *int
    61  		Sort               []string
    62  	}
    63  
    64  	// GetClientListsResponse contains response parameters from GetClientLists method
    65  	GetClientListsResponse struct {
    66  		Content []ClientList
    67  	}
    68  
    69  	// ClientList contains list content and items
    70  	ClientList struct {
    71  		ListContent
    72  		Items []ListItemContent
    73  	}
    74  
    75  	// ListContent contains list content
    76  	ListContent struct {
    77  		Name                       string         `json:"name"`
    78  		Type                       ClientListType `json:"type"`
    79  		Notes                      string         `json:"notes"`
    80  		Tags                       []string       `json:"tags"`
    81  		ListID                     string         `json:"listId"`
    82  		Version                    int64          `json:"version"`
    83  		ItemsCount                 int64          `json:"itemsCount"`
    84  		CreateDate                 string         `json:"createDate"`
    85  		CreatedBy                  string         `json:"createdBy"`
    86  		UpdateDate                 string         `json:"updateDate"`
    87  		UpdatedBy                  string         `json:"updatedBy"`
    88  		ProductionActivationStatus string         `json:"productionActivationStatus"`
    89  		StagingActivationStatus    string         `json:"stagingActivationStatus"`
    90  		ProductionActiveVersion    int64          `json:"productionActiveVersion"`
    91  		StagingActiveVersion       int64          `json:"stagingActiveVersion"`
    92  		ListType                   string         `json:"listType"`
    93  		Shared                     bool           `json:"shared"`
    94  		ReadOnly                   bool           `json:"readOnly"`
    95  		Deprecated                 bool           `json:"deprecated"`
    96  	}
    97  
    98  	// ListItemContent contains client list item information
    99  	ListItemContent struct {
   100  		Value            string         `json:"value"`
   101  		Tags             []string       `json:"tags"`
   102  		Description      string         `json:"description"`
   103  		ExpirationDate   string         `json:"expirationDate"`
   104  		CreateDate       string         `json:"createDate"`
   105  		CreatedBy        string         `json:"createdBy"`
   106  		CreatedVersion   int64          `json:"createdVersion"`
   107  		ProductionStatus string         `json:"productionStatus"`
   108  		StagingStatus    string         `json:"stagingStatus"`
   109  		Type             ClientListType `json:"type"`
   110  		UpdateDate       string         `json:"updateDate"`
   111  		UpdatedBy        string         `json:"updatedBy"`
   112  	}
   113  
   114  	// ListItemPayload contains item's editable fields to use as update/create/delete payload
   115  	ListItemPayload struct {
   116  		Value          string   `json:"value"`
   117  		Tags           []string `json:"tags"`
   118  		Description    string   `json:"description"`
   119  		ExpirationDate string   `json:"expirationDate"`
   120  	}
   121  
   122  	// GetClientListRequest contains request params for GetClientList method
   123  	GetClientListRequest struct {
   124  		ListID       string
   125  		IncludeItems bool
   126  	}
   127  
   128  	// GetClientListResponse contains response from GetClientList method
   129  	GetClientListResponse struct {
   130  		ListContent
   131  		ContractID string            `json:"contractId"`
   132  		GroupID    int64             `json:"groupId"`
   133  		GroupName  string            `json:"groupName"`
   134  		Items      []ListItemContent `json:"items"`
   135  	}
   136  
   137  	// CreateClientListRequest contains request params for CreateClientList method
   138  	CreateClientListRequest struct {
   139  		ContractID string            `json:"contractId"`
   140  		GroupID    int64             `json:"groupId"`
   141  		Name       string            `json:"name"`
   142  		Type       ClientListType    `json:"type"`
   143  		Notes      string            `json:"notes"`
   144  		Tags       []string          `json:"tags"`
   145  		Items      []ListItemPayload `json:"items"`
   146  	}
   147  
   148  	// CreateClientListResponse contains response from CreateClientList method
   149  	CreateClientListResponse GetClientListResponse
   150  
   151  	// UpdateClientListRequest contains request params for UpdateClientList method
   152  	UpdateClientListRequest struct {
   153  		UpdateClientList
   154  		ListID string
   155  	}
   156  
   157  	// UpdateClientList contains the body of client list update request
   158  	UpdateClientList struct {
   159  		Name  string   `json:"name"`
   160  		Notes string   `json:"notes"`
   161  		Tags  []string `json:"tags"`
   162  	}
   163  
   164  	// UpdateClientListResponse contains response from UpdateClientList method
   165  	UpdateClientListResponse struct {
   166  		ListContent
   167  		ContractID string `json:"contractId"`
   168  		GroupName  string `json:"groupName"`
   169  		GroupID    int64  `json:"groupId"`
   170  	}
   171  
   172  	// UpdateClientListItemsRequest contains request params for UpdateClientListItems method
   173  	UpdateClientListItemsRequest struct {
   174  		UpdateClientListItems
   175  		ListID string
   176  	}
   177  
   178  	// UpdateClientListItems contains the body of client list items update request
   179  	UpdateClientListItems struct {
   180  		Append []ListItemPayload `json:"append"`
   181  		Update []ListItemPayload `json:"update"`
   182  		Delete []ListItemPayload `json:"delete"`
   183  	}
   184  
   185  	// UpdateClientListItemsResponse contains response from UpdateClientListItems method
   186  	UpdateClientListItemsResponse struct {
   187  		Appended []ListItemContent `json:"appended"`
   188  		Updated  []ListItemContent `json:"updated"`
   189  		Deleted  []ListItemContent `json:"deleted"`
   190  	}
   191  
   192  	// DeleteClientListRequest contains request params for DeleteClientList method
   193  	DeleteClientListRequest struct {
   194  		ListID string
   195  	}
   196  )
   197  
   198  func (p *clientlists) GetClientLists(ctx context.Context, params GetClientListsRequest) (*GetClientListsResponse, error) {
   199  	logger := p.Log(ctx)
   200  	logger.Debug("GetClientLists")
   201  
   202  	if err := params.validate(); err != nil {
   203  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   204  	}
   205  
   206  	uri, err := url.Parse("/client-list/v1/lists")
   207  	if err != nil {
   208  		return nil, fmt.Errorf("Error parsing URL: %s", err.Error())
   209  	}
   210  
   211  	q := uri.Query()
   212  	if params.Name != "" {
   213  		q.Add("name", params.Name)
   214  	}
   215  	if params.Type != nil {
   216  		for _, v := range params.Type {
   217  			q.Add("type", string(v))
   218  		}
   219  	}
   220  	if params.Search != "" {
   221  		q.Add("search", params.Search)
   222  	}
   223  	if params.IncludeItems {
   224  		q.Add("includeItems", strconv.FormatBool(params.IncludeItems))
   225  	}
   226  	if params.IncludeDeprecated {
   227  		q.Add("includeDeprecated", strconv.FormatBool(params.IncludeDeprecated))
   228  	}
   229  	if params.IncludeNetworkList {
   230  		q.Add("includeNetworkList", strconv.FormatBool(params.IncludeNetworkList))
   231  	}
   232  	if params.Page != nil {
   233  		q.Add("page", fmt.Sprintf("%d", *params.Page))
   234  	}
   235  	if params.PageSize != nil {
   236  		q.Add("pageSize", fmt.Sprintf("%d", *params.PageSize))
   237  	}
   238  	if params.Sort != nil {
   239  		for _, v := range params.Sort {
   240  			q.Add("sort", string(v))
   241  		}
   242  	}
   243  	uri.RawQuery = q.Encode()
   244  
   245  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   246  	if err != nil {
   247  		return nil, fmt.Errorf("failed to create getClientLists request: %s", err.Error())
   248  	}
   249  
   250  	var rval GetClientListsResponse
   251  
   252  	resp, err := p.Exec(req, &rval)
   253  	if err != nil {
   254  		return nil, fmt.Errorf("getClientLists request failed: %s", err.Error())
   255  	}
   256  
   257  	if resp.StatusCode != http.StatusOK {
   258  		return nil, p.Error(resp)
   259  	}
   260  
   261  	return &rval, nil
   262  }
   263  
   264  func (p *clientlists) GetClientList(ctx context.Context, params GetClientListRequest) (*GetClientListResponse, error) {
   265  	logger := p.Log(ctx)
   266  	logger.Debug("GetClientList")
   267  
   268  	if err := params.validate(); err != nil {
   269  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   270  	}
   271  
   272  	uri, err := url.Parse(fmt.Sprintf("/client-list/v1/lists/%s", params.ListID))
   273  	if err != nil {
   274  		return nil, fmt.Errorf("failed to parse url: %w", err)
   275  	}
   276  
   277  	q := uri.Query()
   278  	if params.IncludeItems {
   279  		q.Add("includeItems", strconv.FormatBool(params.IncludeItems))
   280  	}
   281  	uri.RawQuery = q.Encode()
   282  
   283  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri.String(), nil)
   284  	if err != nil {
   285  		return nil, fmt.Errorf("failed to create getClientList request: %s", err.Error())
   286  	}
   287  
   288  	var rval GetClientListResponse
   289  	resp, err := p.Exec(req, &rval)
   290  	if err != nil {
   291  		return nil, fmt.Errorf("getClientList request failed: %s", err.Error())
   292  	}
   293  
   294  	if resp.StatusCode != http.StatusOK {
   295  		return nil, p.Error(resp)
   296  	}
   297  
   298  	return &rval, nil
   299  }
   300  
   301  func (p *clientlists) UpdateClientList(ctx context.Context, params UpdateClientListRequest) (*UpdateClientListResponse, error) {
   302  	logger := p.Log(ctx)
   303  	logger.Debug("UpdateClientList")
   304  
   305  	if err := params.validate(); err != nil {
   306  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   307  	}
   308  
   309  	uri := fmt.Sprintf("/client-list/v1/lists/%s", params.ListID)
   310  
   311  	req, err := http.NewRequestWithContext(ctx, http.MethodPut, uri, nil)
   312  	if err != nil {
   313  		return nil, fmt.Errorf("failed to create updateClientList request: %s", err.Error())
   314  	}
   315  
   316  	var rval UpdateClientListResponse
   317  	resp, err := p.Exec(req, &rval, &params.UpdateClientList)
   318  	if err != nil {
   319  		return nil, fmt.Errorf("updateClientList request failed: %s", err.Error())
   320  	}
   321  
   322  	if resp.StatusCode != http.StatusOK {
   323  		return nil, p.Error(resp)
   324  	}
   325  
   326  	return &rval, nil
   327  }
   328  
   329  func (p *clientlists) UpdateClientListItems(ctx context.Context, params UpdateClientListItemsRequest) (*UpdateClientListItemsResponse, error) {
   330  	logger := p.Log(ctx)
   331  	logger.Debug("UpdateClientListItems")
   332  
   333  	if err := params.validate(); err != nil {
   334  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   335  	}
   336  
   337  	uri := fmt.Sprintf("/client-list/v1/lists/%s/items", params.ListID)
   338  
   339  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uri, nil)
   340  	if err != nil {
   341  		return nil, fmt.Errorf("failed to create UpdateClientListItems request: %s", err.Error())
   342  	}
   343  
   344  	var rval UpdateClientListItemsResponse
   345  	resp, err := p.Exec(req, &rval, &params.UpdateClientListItems)
   346  	if err != nil {
   347  		return nil, fmt.Errorf("UpdateClientListItems request failed: %s", err.Error())
   348  	}
   349  
   350  	if resp.StatusCode != http.StatusOK {
   351  		return nil, p.Error(resp)
   352  	}
   353  
   354  	return &rval, nil
   355  }
   356  
   357  func (p *clientlists) CreateClientList(ctx context.Context, params CreateClientListRequest) (*CreateClientListResponse, error) {
   358  	logger := p.Log(ctx)
   359  	logger.Debug("CreateClientList")
   360  
   361  	if err := params.validate(); err != nil {
   362  		return nil, fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   363  	}
   364  
   365  	req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/client-list/v1/lists", nil)
   366  	if err != nil {
   367  		return nil, fmt.Errorf("failed to create createClientList request: %s", err.Error())
   368  	}
   369  
   370  	var rval CreateClientListResponse
   371  	resp, err := p.Exec(req, &rval, &params)
   372  	if err != nil {
   373  		return nil, fmt.Errorf("createClientList request failed: %s", err.Error())
   374  	}
   375  
   376  	if resp.StatusCode != http.StatusCreated {
   377  		return nil, p.Error(resp)
   378  	}
   379  
   380  	return &rval, nil
   381  }
   382  
   383  func (p *clientlists) DeleteClientList(ctx context.Context, params DeleteClientListRequest) error {
   384  	logger := p.Log(ctx)
   385  	logger.Debug("DeleteClientList")
   386  
   387  	if err := params.validate(); err != nil {
   388  		return fmt.Errorf("%w: %s", ErrStructValidation, err.Error())
   389  	}
   390  
   391  	uri := fmt.Sprintf("%s/%s", "/client-list/v1/lists", params.ListID)
   392  	req, err := http.NewRequestWithContext(ctx, http.MethodDelete, uri, nil)
   393  	if err != nil {
   394  		return fmt.Errorf("failed to create deleteClientList request: %s", err.Error())
   395  	}
   396  
   397  	resp, err := p.Exec(req, nil)
   398  	if err != nil {
   399  		return fmt.Errorf("deleteClientList request failed: %s", err.Error())
   400  	}
   401  
   402  	if resp.StatusCode != http.StatusNoContent {
   403  		return p.Error(resp)
   404  	}
   405  
   406  	return nil
   407  }
   408  
   409  func (v GetClientListRequest) validate() error {
   410  	return edgegriderr.ParseValidationErrors(validation.Errors{
   411  		"ListID": validation.Validate(v.ListID, validation.Required),
   412  	})
   413  }
   414  
   415  func (v UpdateClientListRequest) validate() error {
   416  	return edgegriderr.ParseValidationErrors(validation.Errors{
   417  		"ListID": validation.Validate(v.ListID, validation.Required),
   418  		"Name":   validation.Validate(v.ListID, validation.Required),
   419  	})
   420  }
   421  
   422  func (v UpdateClientListItemsRequest) validate() error {
   423  	return edgegriderr.ParseValidationErrors(validation.Errors{
   424  		"ListID": validation.Validate(v.ListID, validation.Required),
   425  	})
   426  }
   427  
   428  func (v CreateClientListRequest) validate() error {
   429  	return edgegriderr.ParseValidationErrors(validation.Errors{
   430  		"Name": validation.Validate(v.Name, validation.Required),
   431  		"Type": validation.Validate(v.Type, validation.Required),
   432  	})
   433  }
   434  
   435  func (v DeleteClientListRequest) validate() error {
   436  	return edgegriderr.ParseValidationErrors(validation.Errors{
   437  		"ListID": validation.Validate(v.ListID, validation.Required),
   438  	})
   439  }
   440  
   441  func (v GetClientListsRequest) validate() error {
   442  	listTypes := getValidListTypesAsInterface()
   443  	return edgegriderr.ParseValidationErrors(validation.Errors{
   444  		"Type": validation.Validate(v.Type, validation.Each(validation.In(listTypes...).Error(
   445  			fmt.Sprintf("Invalid 'type' value(s) provided. Valid values are: %s", listTypes)))),
   446  	})
   447  }
   448  
   449  const (
   450  	// IP for ip type list type
   451  	IP ClientListType = "IP"
   452  	// GEO for geo/countries list type
   453  	GEO ClientListType = "GEO"
   454  	// ASN for AS Number list type
   455  	ASN ClientListType = "ASN"
   456  	// TLSFingerprint for TLS Fingerprint list type
   457  	TLSFingerprint ClientListType = "TLS_FINGERPRINT"
   458  	// FileHash for file hash type list
   459  	FileHash ClientListType = "FILE_HASH"
   460  )
   461  
   462  func getValidListTypesAsInterface() []interface{} {
   463  	return []interface{}{
   464  		IP,
   465  		GEO,
   466  		ASN,
   467  		TLSFingerprint,
   468  		FileHash,
   469  	}
   470  }