1 package objectapi
2
3 import (
4 "context"
5 "errors"
6 "time"
7 )
8
9
10 type Object struct {
11 Key string
12 Value string
13 Access time.Time
14 }
15
16
17
18
19 type Client struct {
20 token string
21 server *mockServer
22 }
23
24
25 func NewClient(token string) (*Client, error) {
26 return &Client{
27 token: token,
28 server: newMockServer(),
29 }, nil
30 }
31
32
33 func (c *Client) Create(ctx context.Context, key, value string, overwrite bool) error {
34 return c.server.create(c.token, key, value, overwrite)
35 }
36
37
38 func (c *Client) Delete(ctx context.Context, key string, force bool) (existed bool, err error) {
39 return c.server.delete(c.token, key, force)
40 }
41
42
43 func (c *Client) List(ctx context.Context) ([]Object, error) {
44 return c.server.list(c.token)
45 }
46
47
48
49
50
51 type mockServer struct {
52 token string
53 objects map[string]Object
54 }
55
56 func newMockServer() *mockServer {
57 return &mockServer{
58 token: "SECRET",
59 objects: defaultObjects,
60 }
61 }
62
63 func (s *mockServer) create(token, key, value string, overwrite bool) error {
64 if token != s.token {
65 return errors.New("not authorized")
66 }
67
68 if _, ok := s.objects[key]; ok && !overwrite {
69 return errors.New("object already exists")
70 }
71
72 s.objects[key] = Object{
73 Key: key,
74 Value: value,
75 Access: time.Now(),
76 }
77
78 return nil
79 }
80
81 func (s *mockServer) delete(token, key string, force bool) (existed bool, err error) {
82 if token != s.token {
83 return false, errors.New("not authorized")
84 }
85
86 _, ok := s.objects[key]
87 delete(s.objects, key)
88 return ok, nil
89 }
90
91 func (s *mockServer) list(token string) ([]Object, error) {
92 if token != s.token {
93 return nil, errors.New("not authorized")
94 }
95
96 result := make([]Object, 0, len(s.objects))
97 for _, obj := range s.objects {
98 result = append(result, obj)
99 }
100
101 return result, nil
102 }
103
104 var defaultObjects = map[string]Object{
105 "apple": Object{
106 Key: "apple",
107 Value: "The fruit of any of certain other species of tree of the same genus.",
108 Access: mustParseTime(time.RFC3339, "2019-03-15T15:01:00Z"),
109 },
110 "beach": Object{
111 Key: "beach",
112 Value: "The shore of a body of water, especially when sandy or pebbly.",
113 Access: mustParseTime(time.RFC3339, "2019-04-20T12:21:30Z"),
114 },
115 "carillon": Object{
116 Key: "carillon",
117 Value: "A stationary set of chromatically tuned bells in a tower.",
118 Access: mustParseTime(time.RFC3339, "2019-07-04T23:59:59Z"),
119 },
120 }
121
122 func mustParseTime(layout string, value string) time.Time {
123 t, err := time.Parse(layout, value)
124 if err != nil {
125 panic(err)
126 }
127 return t
128 }
129
View as plain text