token_policies.go raw

   1  package desec
   2  
   3  import (
   4  	"context"
   5  	"fmt"
   6  	"net/http"
   7  )
   8  
   9  // TokenPolicy represents a policy applied to a token.
  10  type TokenPolicy struct {
  11  	ID              string  `json:"id,omitempty"`
  12  	Domain          *string `json:"domain"`
  13  	SubName         *string `json:"subname"`
  14  	Type            *string `json:"type"`
  15  	WritePermission bool    `json:"perm_write,omitempty"`
  16  }
  17  
  18  // TokenPoliciesService handles communication with the token policy related methods of the deSEC API.
  19  //
  20  // https://desec.readthedocs.io/en/latest/auth/tokens.html
  21  type TokenPoliciesService struct {
  22  	client *Client
  23  }
  24  
  25  // Deprecated: use [TokenPoliciesService.GetAll] instead.
  26  func (s *TokenPoliciesService) Get(ctx context.Context, tokenID string) ([]TokenPolicy, error) {
  27  	return s.GetAll(ctx, tokenID)
  28  }
  29  
  30  // GetOne retrieves a specific token rrset policy.
  31  // https://desec.readthedocs.io/en/latest/auth/tokens.html#token-policy-management
  32  func (s *TokenPoliciesService) GetOne(ctx context.Context, tokenID, policyID string) (*TokenPolicy, error) {
  33  	endpoint, err := s.client.createEndpoint("auth", "tokens", tokenID, "policies", "rrsets", policyID)
  34  	if err != nil {
  35  		return nil, fmt.Errorf("failed to create endpoint: %w", err)
  36  	}
  37  
  38  	req, err := s.client.newRequest(ctx, http.MethodGet, endpoint, nil)
  39  	if err != nil {
  40  		return nil, err
  41  	}
  42  
  43  	resp, err := s.client.httpClient.Do(req)
  44  	if err != nil {
  45  		return nil, fmt.Errorf("failed to call API: %w", err)
  46  	}
  47  
  48  	defer func() { _ = resp.Body.Close() }()
  49  
  50  	if resp.StatusCode != http.StatusOK {
  51  		return nil, handleError(resp)
  52  	}
  53  
  54  	policy := &TokenPolicy{}
  55  
  56  	err = handleResponse(resp, policy)
  57  	if err != nil {
  58  		return nil, err
  59  	}
  60  
  61  	return policy, nil
  62  }
  63  
  64  // GetAll retrieves all rrset policies for a token.
  65  // https://desec.readthedocs.io/en/latest/auth/tokens.html#token-policy-management
  66  func (s *TokenPoliciesService) GetAll(ctx context.Context, tokenID string) ([]TokenPolicy, error) {
  67  	endpoint, err := s.client.createEndpoint("auth", "tokens", tokenID, "policies", "rrsets")
  68  	if err != nil {
  69  		return nil, fmt.Errorf("failed to create endpoint: %w", err)
  70  	}
  71  
  72  	req, err := s.client.newRequest(ctx, http.MethodGet, endpoint, nil)
  73  	if err != nil {
  74  		return nil, err
  75  	}
  76  
  77  	resp, err := s.client.httpClient.Do(req)
  78  	if err != nil {
  79  		return nil, fmt.Errorf("failed to call API: %w", err)
  80  	}
  81  
  82  	defer func() { _ = resp.Body.Close() }()
  83  
  84  	if resp.StatusCode != http.StatusOK {
  85  		return nil, handleError(resp)
  86  	}
  87  
  88  	var policies []TokenPolicy
  89  
  90  	err = handleResponse(resp, &policies)
  91  	if err != nil {
  92  		return nil, err
  93  	}
  94  
  95  	return policies, nil
  96  }
  97  
  98  // Create creates token policy.
  99  // https://desec.readthedocs.io/en/latest/auth/tokens.html#create-additional-tokens
 100  func (s *TokenPoliciesService) Create(ctx context.Context, tokenID string, policy TokenPolicy) (*TokenPolicy, error) {
 101  	endpoint, err := s.client.createEndpoint("auth", "tokens", tokenID, "policies", "rrsets")
 102  	if err != nil {
 103  		return nil, fmt.Errorf("failed to create endpoint: %w", err)
 104  	}
 105  
 106  	req, err := s.client.newRequest(ctx, http.MethodPost, endpoint, policy)
 107  	if err != nil {
 108  		return nil, err
 109  	}
 110  
 111  	resp, err := s.client.httpClient.Do(req)
 112  	if err != nil {
 113  		return nil, fmt.Errorf("failed to call API: %w", err)
 114  	}
 115  
 116  	defer func() { _ = resp.Body.Close() }()
 117  
 118  	if resp.StatusCode != http.StatusCreated {
 119  		return nil, handleError(resp)
 120  	}
 121  
 122  	var tokenPolicy TokenPolicy
 123  
 124  	err = handleResponse(resp, &tokenPolicy)
 125  	if err != nil {
 126  		return nil, err
 127  	}
 128  
 129  	return &tokenPolicy, nil
 130  }
 131  
 132  // Update a token policy
 133  // https://desec.readthedocs.io/en/latest/auth/tokens.html#token-policy-management
 134  func (s *TokenPoliciesService) Update(ctx context.Context, tokenID, policyID string, policy TokenPolicy) (*TokenPolicy, error) {
 135  	endpoint, err := s.client.createEndpoint("auth", "tokens", tokenID, "policies", "rrsets", policyID)
 136  	if err != nil {
 137  		return nil, fmt.Errorf("failed to create endpoint: %w", err)
 138  	}
 139  
 140  	// Copy values, including only fields that can be modified
 141  	req, err := s.client.newRequest(ctx, http.MethodPatch, endpoint, TokenPolicy{
 142  		Domain:          policy.Domain,
 143  		SubName:         policy.SubName,
 144  		Type:            policy.Type,
 145  		WritePermission: policy.WritePermission,
 146  	})
 147  	if err != nil {
 148  		return nil, err
 149  	}
 150  
 151  	resp, err := s.client.httpClient.Do(req)
 152  	if err != nil {
 153  		return nil, fmt.Errorf("failed to call API: %w", err)
 154  	}
 155  
 156  	defer func() { _ = resp.Body.Close() }()
 157  
 158  	if resp.StatusCode != http.StatusOK {
 159  		return nil, handleError(resp)
 160  	}
 161  
 162  	result := &TokenPolicy{}
 163  
 164  	err = handleResponse(resp, result)
 165  	if err != nil {
 166  		return nil, err
 167  	}
 168  
 169  	return result, nil
 170  }
 171  
 172  // Delete deletes a token rrset's policy.
 173  // https://desec.readthedocs.io/en/latest/auth/tokens.html#token-policy-management
 174  func (s *TokenPoliciesService) Delete(ctx context.Context, tokenID, policyID string) error {
 175  	endpoint, err := s.client.createEndpoint("auth", "tokens", tokenID, "policies", "rrsets", policyID)
 176  	if err != nil {
 177  		return fmt.Errorf("failed to create endpoint: %w", err)
 178  	}
 179  
 180  	req, err := s.client.newRequest(ctx, http.MethodDelete, endpoint, nil)
 181  	if err != nil {
 182  		return err
 183  	}
 184  
 185  	resp, err := s.client.httpClient.Do(req)
 186  	if err != nil {
 187  		return fmt.Errorf("failed to call API: %w", err)
 188  	}
 189  
 190  	defer func() { _ = resp.Body.Close() }()
 191  
 192  	if resp.StatusCode != http.StatusNoContent {
 193  		return handleError(resp)
 194  	}
 195  
 196  	return nil
 197  }
 198