github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/service/templatefuncs.go (about)

     1  package service
     2  
     3  import (
     4  	"crypto/md5"
     5  	"fmt"
     6  	"io"
     7  	"net/url"
     8  	"regexp"
     9  	"time"
    10  
    11  	"github.com/evergreen-ci/evergreen/model/user"
    12  	"github.com/evergreen-ci/evergreen/util"
    13  	"github.com/gorilla/mux"
    14  	"github.com/mongodb/grip"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  const defaultHelpURL = "https://github.com/evergreen-ci/evergreen/wiki/How-To-Read-Evergreen"
    19  
    20  // FuncOptions are global variables injected into our templating functions.
    21  type FuncOptions struct {
    22  	WebHome  string
    23  	HelpHome string
    24  	IsProd   bool
    25  	Router   *mux.Router
    26  }
    27  
    28  // MutableVar is a setable variable for UI templates.
    29  // This utility allows us to set and retrieve values, which
    30  // is not a built in feature of Go HTML templates.
    31  type MutableVar struct {
    32  	Value interface{}
    33  }
    34  
    35  // Get returns the value of the variable.
    36  func (self *MutableVar) Get() interface{} {
    37  	return self.Value
    38  }
    39  
    40  // Set sets the value of the variable.
    41  // Set returns the empty string so as to not pollute the resulting template.
    42  func (self *MutableVar) Set(v interface{}) interface{} {
    43  	self.Value = v
    44  	return ""
    45  }
    46  
    47  // MakeTemplateFuncs creates and registers all of our built-in template functions.
    48  func MakeTemplateFuncs(fo FuncOptions, superUsers []string) (map[string]interface{}, error) {
    49  	r := map[string]interface{}{
    50  		// IsSuperUser returns true if the given user Id has super user privileges.
    51  		"IsSuperUser": func(userName string) bool {
    52  			return len(superUsers) == 0 || util.SliceContains(superUsers, userName)
    53  		},
    54  		// Gravatar returns a Gravatar URL for the given email string.
    55  		"Gravatar": func(email string) string {
    56  			h := md5.New()
    57  			_, err := io.WriteString(h, email)
    58  			grip.Warning(err)
    59  			return fmt.Sprintf("http://www.gravatar.com/avatar/%x?s=50", h.Sum(nil))
    60  		},
    61  
    62  		// DateFormat returns a time Formatted to the given layout and timezone.
    63  		// If the timezone is unset, it defaults to "New_York."
    64  		"DateFormat": func(when time.Time, layout string, timezone string) string {
    65  			if len(timezone) == 0 {
    66  				timezone = "America/New_York" // I ♥ NY
    67  			}
    68  			loc, err := time.LoadLocation(timezone)
    69  			if err != nil {
    70  				return when.Format(layout)
    71  			}
    72  
    73  			whenTZ := when.In(loc)
    74  			return whenTZ.Format(layout)
    75  		},
    76  
    77  		// Static returns a link to a static file.
    78  		"Static": func(filetype, filename string) string {
    79  			return fmt.Sprintf("/static/%s/%s", filetype, filename)
    80  		},
    81  
    82  		// RemoveANSI strips out ANSI color sequences in cases where it doesn't make sense to include
    83  		// them, e.g. raw task logs
    84  		"RemoveANSI": func(line string) string {
    85  			re, err := regexp.Compile("\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]")
    86  			if err != nil {
    87  				return ""
    88  			}
    89  			return re.ReplaceAllString(line, "")
    90  		},
    91  
    92  		// Is Prod returns whether or not Evergreen is running in "production."
    93  		// Currently this is only used to toggle the use of minified css files.
    94  		"IsProd": func() bool {
    95  			return fo.IsProd
    96  		},
    97  
    98  		// GetTimezone returns the timezone for a user.
    99  		// Defaults to "New_York".
   100  		"GetTimezone": func(u *user.DBUser) string {
   101  			if u != nil && u.Settings.Timezone != "" {
   102  				return u.Settings.Timezone
   103  			}
   104  			return "America/New_York"
   105  		},
   106  
   107  		// MutableVar creates an unset MutableVar.
   108  		"MutableVar": func() interface{} {
   109  			return &MutableVar{""}
   110  		},
   111  
   112  		// Trunc cuts off a string to be n characters long.
   113  		"Trunc": func(s string, n int) string {
   114  			if n > len(s) {
   115  				return s
   116  			}
   117  			return s[0:n]
   118  		},
   119  
   120  		// UrlFor generates a URL for the given route.
   121  		"UrlFor": func(name string, pairs ...interface{}) (*url.URL, error) {
   122  			size := len(pairs)
   123  			strPairs := make([]string, size)
   124  			for i := 0; i < size; i++ {
   125  				if v, ok := pairs[i].(string); ok {
   126  					strPairs[i] = v
   127  				} else {
   128  					strPairs[i] = fmt.Sprint(pairs[i])
   129  				}
   130  			}
   131  
   132  			route := fo.Router.Get(name)
   133  			if route == nil {
   134  				return nil, errors.Errorf("UrlFor: can't find a route named %v", name)
   135  			}
   136  
   137  			return route.URL(strPairs...)
   138  		},
   139  
   140  		// HelpUrl returns the address of the Evergreen help page,
   141  		// if one is set.
   142  		"HelpUrl": func() string {
   143  			if fo.HelpHome != "" {
   144  				return fo.HelpHome
   145  			}
   146  			return defaultHelpURL
   147  		},
   148  	}
   149  
   150  	staticsMD5, err := DirectoryChecksum(fo.WebHome)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	r["StaticsMD5"] = func() string {
   156  		return staticsMD5
   157  	}
   158  	return r, nil
   159  
   160  }