1 package webserver
2
3 import (
4 "errors"
5 "io"
6 "net/http"
7
8 jsoniter "github.com/json-iterator/go"
9
10 "github.com/cybertec-postgresql/pgwatch/v3/internal/sources"
11 )
12
13 func (server *WebUIServer) handleSources(w http.ResponseWriter, r *http.Request) {
14 var (
15 err error
16 status = http.StatusInternalServerError
17 params []byte
18 res string
19 )
20
21 defer func() {
22 if err != nil {
23 http.Error(w, err.Error(), status)
24 }
25 }()
26
27 switch r.Method {
28 case http.MethodGet:
29
30 if res, err = server.GetSources(); err != nil {
31 return
32 }
33 _, err = w.Write([]byte(res))
34
35 case http.MethodPost:
36
37 if params, err = io.ReadAll(r.Body); err != nil {
38 return
39 }
40 err = server.CreateSource(params)
41 if err != nil {
42 if errors.Is(err, sources.ErrSourceExists) {
43 status = http.StatusConflict
44 }
45 return
46 }
47 w.WriteHeader(http.StatusCreated)
48
49 case http.MethodOptions:
50 w.Header().Set("Allow", "GET, POST, OPTIONS")
51 w.WriteHeader(http.StatusOK)
52
53 default:
54 w.Header().Set("Allow", "GET, POST, OPTIONS")
55 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
56 }
57 }
58
59
60 func (server *WebUIServer) GetSources() (res string, err error) {
61 var dbs sources.Sources
62 if dbs, err = server.sourcesReaderWriter.GetSources(); err != nil {
63 return
64 }
65 b, _ := jsoniter.ConfigFastest.Marshal(dbs)
66 res = string(b)
67 return
68 }
69
70
71 func (server *WebUIServer) DeleteSource(database string) error {
72 return server.sourcesReaderWriter.DeleteSource(database)
73 }
74
75
76 func (server *WebUIServer) UpdateSource(params []byte) error {
77 var md sources.Source
78 err := jsoniter.ConfigFastest.Unmarshal(params, &md)
79 if err != nil {
80 return err
81 }
82 return server.sourcesReaderWriter.UpdateSource(md)
83 }
84
85
86 func (server *WebUIServer) CreateSource(params []byte) error {
87 var md sources.Source
88 err := jsoniter.ConfigFastest.Unmarshal(params, &md)
89 if err != nil {
90 return err
91 }
92 return server.sourcesReaderWriter.CreateSource(md)
93 }
94
95
96
97 func (server *WebUIServer) handleSourceItem(w http.ResponseWriter, r *http.Request) {
98 name := r.PathValue("name")
99 if name == "" {
100 http.Error(w, "source name is required", http.StatusBadRequest)
101 return
102 }
103
104 switch r.Method {
105 case http.MethodGet:
106 server.getSourceByName(w, name)
107 case http.MethodPut:
108 server.updateSourceByName(w, r, name)
109 case http.MethodDelete:
110 server.deleteSourceByName(w, name)
111 case http.MethodOptions:
112 w.Header().Set("Allow", "GET, PUT, DELETE, OPTIONS")
113 w.WriteHeader(http.StatusOK)
114 default:
115 w.Header().Set("Allow", "GET, PUT, DELETE, OPTIONS")
116 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
117 }
118 }
119
120
121 func (server *WebUIServer) getSourceByName(w http.ResponseWriter, name string) {
122 var (
123 err error
124 status = http.StatusInternalServerError
125 srcs sources.Sources
126 )
127
128 defer func() {
129 if err != nil {
130 http.Error(w, err.Error(), status)
131 }
132 }()
133
134 if srcs, err = server.sourcesReaderWriter.GetSources(); err != nil {
135 return
136 }
137
138 for _, src := range srcs {
139 if src.Name == name {
140 b, _ := jsoniter.ConfigFastest.Marshal(src)
141 w.Header().Set("Content-Type", "application/json")
142 _, err = w.Write(b)
143 return
144 }
145 }
146
147 err = sources.ErrSourceNotFound
148 status = http.StatusNotFound
149 }
150
151
152 func (server *WebUIServer) updateSourceByName(w http.ResponseWriter, r *http.Request, name string) {
153 params, err := io.ReadAll(r.Body)
154 if err != nil {
155 http.Error(w, "invalid request body", http.StatusBadRequest)
156 return
157 }
158
159 var md sources.Source
160 if err := jsoniter.ConfigFastest.Unmarshal(params, &md); err != nil {
161 http.Error(w, "invalid JSON format", http.StatusBadRequest)
162 return
163 }
164
165
166 if md.Name != name {
167 http.Error(w, "name in URL and body must match", http.StatusBadRequest)
168 return
169 }
170
171 if err := server.sourcesReaderWriter.UpdateSource(md); err != nil {
172 http.Error(w, err.Error(), http.StatusInternalServerError)
173 return
174 }
175
176 w.WriteHeader(http.StatusOK)
177 }
178
179
180 func (server *WebUIServer) deleteSourceByName(w http.ResponseWriter, name string) {
181 if err := server.sourcesReaderWriter.DeleteSource(name); err != nil {
182 http.Error(w, err.Error(), http.StatusInternalServerError)
183 return
184 }
185
186 w.WriteHeader(http.StatusOK)
187 }
188