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, ¶ms.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, ¶ms.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, ¶ms) 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 }