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