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  }