github.com/elliott5/community@v0.14.1-0.20160709191136-823126fb026a/documize/section/papertrail/papertrail.go (about) 1 // Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved. 2 // 3 // This software (Documize Community Edition) is licensed under 4 // GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html 5 // 6 // You can operate outside the AGPL restrictions by purchasing 7 // Documize Enterprise Edition and obtaining a commercial license 8 // by contacting <sales@documize.com>. 9 // 10 // https://documize.com 11 12 package papertrail 13 14 import ( 15 "bytes" 16 "encoding/json" 17 "errors" 18 "fmt" 19 "html/template" 20 "io/ioutil" 21 "net/http" 22 "net/url" 23 24 "github.com/documize/community/documize/section/provider" 25 "github.com/documize/community/wordsmith/log" 26 ) 27 28 const me = "papertrail" 29 30 // Provider represents Gemini 31 type Provider struct { 32 } 33 34 // Meta describes us. 35 func (*Provider) Meta() provider.TypeMeta { 36 section := provider.TypeMeta{} 37 section.ID = "db0a3a0a-b5d4-4d00-bfac-ee28abba451d" 38 section.Title = "Papertrail" 39 section.Description = "Display log entries" 40 section.ContentType = "papertrail" 41 42 return section 43 } 44 45 // Render converts Papertrail data into HTML suitable for browser rendering. 46 func (*Provider) Render(ctx *provider.Context, config, data string) string { 47 var search papertrailSearch 48 var events []papertrailEvent 49 var payload = papertrailRender{} 50 var c = papertrailConfig{} 51 52 json.Unmarshal([]byte(data), &search) 53 json.Unmarshal([]byte(config), &c) 54 55 c.APIToken = ctx.GetSecrets("APIToken") 56 57 max := len(search.Events) 58 if c.Max < max { 59 max = c.Max 60 } 61 62 events = search.Events[:max] 63 payload.Count = len(events) 64 payload.HasData = payload.Count > 0 65 66 payload.Events = events 67 payload.Config = c 68 payload.Authenticated = c.APIToken != "" 69 70 t := template.New("items") 71 t, _ = t.Parse(renderTemplate) 72 73 buffer := new(bytes.Buffer) 74 t.Execute(buffer, payload) 75 76 return buffer.String() 77 } 78 79 // Command handles authentication, workspace listing and items retrieval. 80 func (p *Provider) Command(ctx *provider.Context, w http.ResponseWriter, r *http.Request) { 81 query := r.URL.Query() 82 method := query.Get("method") 83 84 if len(method) == 0 { 85 provider.WriteMessage(w, me, "missing method name") 86 return 87 } 88 89 defer r.Body.Close() 90 body, err := ioutil.ReadAll(r.Body) 91 92 if err != nil { 93 provider.WriteMessage(w, me, "Bad payload") 94 return 95 } 96 97 var config = papertrailConfig{} 98 err = json.Unmarshal(body, &config) 99 100 if err != nil { 101 provider.WriteMessage(w, me, "Bad config") 102 return 103 } 104 105 config.Clean() 106 107 if config.APIToken == provider.SecretReplacement || config.APIToken == "" { 108 config.APIToken = ctx.GetSecrets("APIToken") 109 } 110 111 if len(config.APIToken) == 0 { 112 provider.WriteMessage(w, me, "Missing API token") 113 return 114 } 115 116 switch method { 117 case "auth": 118 auth(ctx, config, w, r) 119 case "options": 120 options(config, w, r) 121 } 122 } 123 124 // Refresh just sends back data as-is. 125 func (*Provider) Refresh(ctx *provider.Context, config, data string) (newData string) { 126 var c = papertrailConfig{} 127 err := json.Unmarshal([]byte(config), &c) 128 129 if err != nil { 130 log.Error("unable to read Papertrail config", err) 131 return 132 } 133 134 c.Clean() 135 136 c.APIToken = ctx.GetSecrets("APIToken") 137 138 if len(c.APIToken) == 0 { 139 log.Error("missing API token", err) 140 return 141 } 142 143 result, err := fetchEvents(c) 144 145 if err != nil { 146 log.Error("Papertrail fetchEvents failed", err) 147 return 148 } 149 150 j, err := json.Marshal(result) 151 152 if err != nil { 153 log.Error("unable to marshal Papaertrail events", err) 154 return 155 } 156 157 newData = string(j) 158 return 159 } 160 161 func auth(ctx *provider.Context, config papertrailConfig, w http.ResponseWriter, r *http.Request) { 162 result, err := fetchEvents(config) 163 164 if result == nil { 165 err = errors.New("nil result of papertrail query") 166 } 167 168 if err != nil { 169 170 log.IfErr(ctx.SaveSecrets(`{"APIToken":""}`)) // invalid token, so reset it 171 172 if err.Error() == "forbidden" { 173 provider.WriteForbidden(w) 174 } else { 175 provider.WriteError(w, me, err) 176 } 177 178 return 179 } 180 181 log.IfErr(ctx.SaveSecrets(`{"APIToken":"` + config.APIToken + `"}`)) 182 183 provider.WriteJSON(w, result) 184 } 185 186 func options(config papertrailConfig, w http.ResponseWriter, r *http.Request) { 187 // get systems 188 req, err := http.NewRequest("GET", "https://papertrailapp.com/api/v1/systems.json", nil) 189 req.Header.Set("X-Papertrail-Token", config.APIToken) 190 191 client := &http.Client{} 192 res, err := client.Do(req) 193 194 if err != nil { 195 fmt.Println(err) 196 provider.WriteError(w, me, err) 197 return 198 } 199 200 if res.StatusCode != http.StatusOK { 201 provider.WriteForbidden(w) 202 return 203 } 204 205 defer res.Body.Close() 206 var systems []papertrailOption 207 208 dec := json.NewDecoder(res.Body) 209 err = dec.Decode(&systems) 210 211 if err != nil { 212 fmt.Println(err) 213 provider.WriteError(w, me, err) 214 return 215 } 216 217 // get groups 218 req, err = http.NewRequest("GET", "https://papertrailapp.com/api/v1/groups.json", nil) 219 req.Header.Set("X-Papertrail-Token", config.APIToken) 220 221 client = &http.Client{} 222 res, err = client.Do(req) 223 224 if err != nil { 225 fmt.Println(err) 226 provider.WriteError(w, me, err) 227 return 228 } 229 230 if res.StatusCode != http.StatusOK { 231 provider.WriteForbidden(w) 232 return 233 } 234 235 defer res.Body.Close() 236 var groups []papertrailOption 237 238 dec = json.NewDecoder(res.Body) 239 err = dec.Decode(&groups) 240 241 if err != nil { 242 fmt.Println(err) 243 provider.WriteError(w, me, err) 244 return 245 } 246 247 var options = papertrailOptions{} 248 options.Groups = groups 249 options.Systems = systems 250 251 provider.WriteJSON(w, options) 252 } 253 254 func fetchEvents(config papertrailConfig) (result interface{}, err error) { 255 var filter string 256 if len(config.Query) > 0 { 257 filter = fmt.Sprintf("q=%s", url.QueryEscape(config.Query)) 258 } 259 if config.Group.ID > 0 { 260 prefix := "" 261 if len(filter) > 0 { 262 prefix = "&" 263 } 264 filter = fmt.Sprintf("%s%sgroup_id=%d", filter, prefix, config.Group.ID) 265 } 266 267 var req *http.Request 268 req, err = http.NewRequest("GET", "https://papertrailapp.com/api/v1/events/search.json?"+filter, nil) 269 if err != nil { 270 log.Error("new request", err) 271 return 272 } 273 req.Header.Set("X-Papertrail-Token", config.APIToken) 274 275 client := &http.Client{} 276 var res *http.Response 277 res, err = client.Do(req) 278 279 if err != nil { 280 log.Error("message", err) 281 return 282 } 283 284 if res.StatusCode != http.StatusOK { 285 log.Error("forbidden", err) 286 return 287 } 288 289 defer res.Body.Close() 290 291 dec := json.NewDecoder(res.Body) 292 err = dec.Decode(&result) 293 294 if err != nil { 295 log.Error("unable to read result", err) 296 } 297 298 return 299 }