1package desec
2
3import (
4	"context"
5	"fmt"
6	"net/http"
7	"time"
8)
9
10// Token a token representation.
11type Token struct {
12	ID      string     `json:"id,omitempty"`
13	Name    string     `json:"name,omitempty"`
14	Value   string     `json:"token,omitempty"`
15	Created *time.Time `json:"created,omitempty"`
16}
17
18// TokensService handles communication with the tokens related methods of the deSEC API.
19//
20// https://desec.readthedocs.io/en/latest/auth/tokens.html
21type TokensService struct {
22	client *Client
23}
24
25// GetAll retrieving all current tokens.
26// https://desec.readthedocs.io/en/latest/auth/tokens.html#retrieving-all-current-tokens
27func (s *TokensService) GetAll(ctx context.Context) ([]Token, error) {
28	endpoint, err := s.client.createEndpoint("auth", "tokens")
29	if err != nil {
30		return nil, fmt.Errorf("failed to create endpoint: %w", err)
31	}
32
33	req, err := s.client.newRequest(ctx, http.MethodGet, endpoint, nil)
34	if err != nil {
35		return nil, err
36	}
37
38	resp, err := s.client.httpClient.Do(req)
39	if err != nil {
40		return nil, fmt.Errorf("failed to call API: %w", err)
41	}
42
43	defer func() { _ = resp.Body.Close() }()
44
45	if resp.StatusCode != http.StatusOK {
46		return nil, handleError(resp)
47	}
48
49	var tokens []Token
50	err = handleResponse(resp, &tokens)
51	if err != nil {
52		return nil, err
53	}
54
55	return tokens, nil
56}
57
58// Create creates additional tokens.
59// https://desec.readthedocs.io/en/latest/auth/tokens.html#create-additional-tokens
60func (s *TokensService) Create(ctx context.Context, name string) (*Token, error) {
61	endpoint, err := s.client.createEndpoint("auth", "tokens")
62	if err != nil {
63		return nil, fmt.Errorf("failed to create endpoint: %w", err)
64	}
65
66	req, err := s.client.newRequest(ctx, http.MethodPost, endpoint, Token{Name: name})
67	if err != nil {
68		return nil, err
69	}
70
71	resp, err := s.client.httpClient.Do(req)
72	if err != nil {
73		return nil, fmt.Errorf("failed to call API: %w", err)
74	}
75
76	defer func() { _ = resp.Body.Close() }()
77
78	if resp.StatusCode != http.StatusCreated {
79		return nil, handleError(resp)
80	}
81
82	var token Token
83	err = handleResponse(resp, &token)
84	if err != nil {
85		return nil, err
86	}
87
88	return &token, nil
89}
90
91// Delete deletes tokens.
92// https://desec.readthedocs.io/en/latest/auth/tokens.html#delete-tokens
93func (s *TokensService) Delete(ctx context.Context, tokenID string) error {
94	endpoint, err := s.client.createEndpoint("auth", "tokens", tokenID)
95	if err != nil {
96		return fmt.Errorf("failed to create endpoint: %w", err)
97	}
98
99	req, err := s.client.newRequest(ctx, http.MethodDelete, endpoint, nil)
100	if err != nil {
101		return err
102	}
103
104	resp, err := s.client.httpClient.Do(req)
105	if err != nil {
106		return fmt.Errorf("failed to call API: %w", err)
107	}
108
109	defer func() { _ = resp.Body.Close() }()
110
111	if resp.StatusCode != http.StatusNoContent {
112		return handleError(resp)
113	}
114
115	return nil
116}
117