<commit_before>package node

// xlattice_go/node/baseNode.go

import (
	"code.google.com/p/go.crypto/ssh"
	"crypto/rsa"
	"encoding/hex"
	"fmt"
	xc "github.com/jddixon/xlattice_go/crypto"
	xi "github.com/jddixon/xlattice_go/nodeID"
	xo "github.com/jddixon/xlattice_go/overlay"
	"strings"
)

/**
 * Basic abstraction underlying Peer and Node
 */

type BaseNode struct {
	name        string // convenience for testing
	nodeID      *xi.NodeID
	commsPubKey *rsa.PublicKey
	sigPubKey   *rsa.PublicKey
	overlays    []xo.OverlayI
}

func NewNewBaseNode(name string, id *xi.NodeID) (*BaseNode, error) {
	return NewBaseNode(name, id, nil, nil, nil)
}

func NewBaseNode(name string, id *xi.NodeID,
	ck *rsa.PublicKey, sk *rsa.PublicKey,
	o []xo.OverlayI) (p *BaseNode, err error) {

	// IDENTITY /////////////////////////////////////////////////////
	if id == nil {
		return nil, NilNodeID
	}
	nodeID, err := (*id).Clone()
	if err != nil {
		return
	}
	commsPubKey := ck
	sigPubKey := sk
	var overlays []xo.OverlayI // an empty slice
	if o != nil {
		count := len(o)
		for i := 0; i < count; i++ {
			overlays = append(overlays, o[i])
		}
	} // FOO
	p = new(BaseNode)
	p.name = name
	p.nodeID = nodeID // the clone
	p.commsPubKey = commsPubKey
	p.sigPubKey = sigPubKey
	p.overlays = overlays
	return p, nil
}
func (p *BaseNode) GetName() string {
	return p.name
}
func (p *BaseNode) GetNodeID() *xi.NodeID {
	return p.nodeID
}
func (p *BaseNode) GetCommsPublicKey() *rsa.PublicKey {
	return p.commsPubKey
}
func (p *BaseNode) GetSSHCommsPublicKey() string {
	out := ssh.MarshalAuthorizedKey(p.commsPubKey)
	return string(out)
}

func (p *BaseNode) GetSigPublicKey() *rsa.PublicKey {
	return p.sigPubKey
}

// OVERLAYS /////////////////////////////////////////////////////////
//func (p *BaseNode) addOverlayI(o xo.OverlayI) error {
//	if o == nil {
//		return NilOverlay
//	}
//	p.overlays = append(p.overlays, o)
//	return nil
//} // FOO
func (n *BaseNode) AddOverlay(o xo.OverlayI) (ndx int, err error) {
	ndx = -1
	if o == nil {
		err = NilOverlay
	} else {
		for i := 0; i < len(n.overlays); i++ {
			if n.overlays[i].Equal(o) {
				ndx = i
				break
			}
		}
		if ndx == -1 {
			n.overlays = append(n.overlays, o)
			ndx = len(n.overlays) - 1
		}
	}
	return
} // FOO

// Return a count of the number of overlays.
func (p *BaseNode) SizeOverlays() int {
	return len(p.overlays)
}

func (p *BaseNode) GetOverlay(n int) xo.OverlayI {
	return p.overlays[n]
}

// EQUAL ////////////////////////////////////////////////////////////
func (p *BaseNode) Equal(any interface{}) bool {
	if any == p {
		return true
	}
	if any == nil {
		return false
	}
	switch v := any.(type) {
	case *BaseNode:
		_ = v
	default:
		return false
	}
	other := any.(*BaseNode) // type assertion

	// THINK ABOUT publicKey.equals(any.publicKey)

	return xi.SameNodeID(p.nodeID, other.nodeID)
}

// SERIALIZATION ////////////////////////////////////////////////////

func addStringlet(slice *[]string, s string) {
	*slice = append(*slice, s)
}
func (p *BaseNode) Strings() []string {
	// DEBUG
	if p == nil {
		panic("BaseNode.Strings: nil p !")
	}
	if p.commsPubKey == nil {
		panic("BaseNode.Strings: nil p.commsPubKey !")
	}
	// END
	ckSSH, err := xc.RSAPubKeyToDisk(p.commsPubKey)
	if err != nil {
		panic(err)
	}
	skSSH, err := xc.RSAPubKeyToDisk(p.sigPubKey)
	if err != nil {
		panic(err)
	}

	var s []string
	addStringlet(&s, fmt.Sprintf("name: %s", p.name))
	addStringlet(&s, fmt.Sprintf("nodeID: %s", p.nodeID.String()))
	addStringlet(&s, fmt.Sprintf("commsPubKey: %s", ckSSH))
	addStringlet(&s, fmt.Sprintf("sigPubKey: %s", skSSH))
	addStringlet(&s, fmt.Sprintf("overlays {"))
	for i := 0; i < len(p.overlays); i++ {
		addStringlet(&s, fmt.Sprintf("    %s", p.overlays[i].String()))
	}
	addStringlet(&s, fmt.Sprintf("}"))
	return s
}
func (p *BaseNode) String() string {
	return strings.Join(p.Strings(), "\n")
}

// DESERIALIZATION //////////////////////////////////////////////////

// Return the next non-blank line in the slice of strings, trimmed.
// This line and any preceding blank lines are removed from the slice.
func NextNBLine(lines *[]string) string {
	if lines != nil {
		for len(*lines) > 0 {
			s := strings.TrimSpace((*lines)[0])
			*lines = (*lines)[1:]
			if s != "" {
				return s
			}
		}
	}
	return ""
}

// Parse a serialized BaseNode, ignoring blank lines and leading and
// trailing whitespace.  Expect the first line to be like "TYPE {"

func ParseBaseNode(data, whichType string) (bn *BaseNode, rest []string, err error) {
	ss := strings.Split(data, "\n") // yields a slice of strings
	return ParseBNFromStrings(ss, whichType)
}

// Version of the above which consumes a slice of strings.  XXX Copies the
// slice unnecessarily.
func ParseBNFromStrings(ss []string, whichType string) (bn *BaseNode, rest []string, err error) {
	var (
		name        string
		nodeID      *xi.NodeID
		commsPubKey *rsa.PublicKey
		sigPubKey   *rsa.PublicKey
		overlays    []xo.OverlayI
	)
	s := NextNBLine(&ss)
	opener := fmt.Sprintf("%s {", whichType) // "peer {" or "node {"
	if s != opener {
		err = NotExpectedOpener
	}
	if err == nil {
		s := NextNBLine(&ss)
		if strings.HasPrefix(s, "name: ") {
			name = s[6:]
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if strings.HasPrefix(s, "nodeID: ") {
			var val []byte
			val, err = hex.DecodeString(s[8:])
			if err == nil {
				nodeID, err = xi.NewNodeID(val)
			}
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if strings.HasPrefix(s, "commsPubKey: ") {
			// XXX we do not verify that the next line is empty
			ckSSH := []byte(s[13:] + "\n")
			commsPubKey, err = xc.RSAPubKeyFromDisk(ckSSH)
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if strings.HasPrefix(s, "sigPubKey: ") {
			skSSH := []byte(s[11:] + "\n")
			sigPubKey, err = xc.RSAPubKeyFromDisk(skSSH)
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if s == "overlays {" {
			for {
				s = NextNBLine(&ss)
				if s == "" { // end of strings
					err = NotABaseNode
					break
				} else if s == "}" {
					prepend := []string{s}
					ss = append(prepend, ss...)
					break
				}
				var o xo.OverlayI
				o, err = xo.Parse(s)
				if err == nil {
					overlays = append(overlays, o)
				}
			}
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if s != "}" {
			err = NotABaseNode
		}
	}
	if err == nil {
		var bn = BaseNode{name, nodeID, commsPubKey, sigPubKey, overlays}
		return &bn, ss, nil
	} else {
		return nil, nil, err
	}
}
<commit_msg>change required by change in g.crypto/ssh API<commit_after>package node

// xlattice_go/node/baseNode.go

import (
	// "code.google.com/p/go.crypto/ssh"
	"crypto/rsa"
	"encoding/hex"
	"fmt"
	xc "github.com/jddixon/xlattice_go/crypto"
	xi "github.com/jddixon/xlattice_go/nodeID"
	xo "github.com/jddixon/xlattice_go/overlay"
	"strings"
)

/**
 * Basic abstraction underlying Peer and Node
 */

type BaseNode struct {
	name        string // convenience for testing
	nodeID      *xi.NodeID
	commsPubKey *rsa.PublicKey
	sigPubKey   *rsa.PublicKey
	overlays    []xo.OverlayI
}

func NewNewBaseNode(name string, id *xi.NodeID) (*BaseNode, error) {
	return NewBaseNode(name, id, nil, nil, nil)
}

func NewBaseNode(name string, id *xi.NodeID,
	ck *rsa.PublicKey, sk *rsa.PublicKey,
	o []xo.OverlayI) (p *BaseNode, err error) {

	// IDENTITY /////////////////////////////////////////////////////
	if id == nil {
		return nil, NilNodeID
	}
	nodeID, err := (*id).Clone()
	if err != nil {
		return
	}
	commsPubKey := ck
	sigPubKey := sk
	var overlays []xo.OverlayI // an empty slice
	if o != nil {
		count := len(o)
		for i := 0; i < count; i++ {
			overlays = append(overlays, o[i])
		}
	} // FOO
	p = new(BaseNode)
	p.name = name
	p.nodeID = nodeID // the clone
	p.commsPubKey = commsPubKey
	p.sigPubKey = sigPubKey
	p.overlays = overlays
	return p, nil
}
func (p *BaseNode) GetName() string {
	return p.name
}
func (p *BaseNode) GetNodeID() *xi.NodeID {
	return p.nodeID
}
func (p *BaseNode) GetCommsPublicKey() *rsa.PublicKey {
	return p.commsPubKey
}
// XXX Commented out 2014-02-14 because ssh API has changed
//func (p *BaseNode) GetSSHCommsPublicKey() string {
//	out := ssh.MarshalAuthorizedKey(p.commsPubKey)
//	return string(out)
//}

func (p *BaseNode) GetSigPublicKey() *rsa.PublicKey {
	return p.sigPubKey
}

// OVERLAYS /////////////////////////////////////////////////////////
//func (p *BaseNode) addOverlayI(o xo.OverlayI) error {
//	if o == nil {
//		return NilOverlay
//	}
//	p.overlays = append(p.overlays, o)
//	return nil
//} // FOO
func (n *BaseNode) AddOverlay(o xo.OverlayI) (ndx int, err error) {
	ndx = -1
	if o == nil {
		err = NilOverlay
	} else {
		for i := 0; i < len(n.overlays); i++ {
			if n.overlays[i].Equal(o) {
				ndx = i
				break
			}
		}
		if ndx == -1 {
			n.overlays = append(n.overlays, o)
			ndx = len(n.overlays) - 1
		}
	}
	return
} // FOO

// Return a count of the number of overlays.
func (p *BaseNode) SizeOverlays() int {
	return len(p.overlays)
}

func (p *BaseNode) GetOverlay(n int) xo.OverlayI {
	return p.overlays[n]
}

// EQUAL ////////////////////////////////////////////////////////////
func (p *BaseNode) Equal(any interface{}) bool {
	if any == p {
		return true
	}
	if any == nil {
		return false
	}
	switch v := any.(type) {
	case *BaseNode:
		_ = v
	default:
		return false
	}
	other := any.(*BaseNode) // type assertion

	// THINK ABOUT publicKey.equals(any.publicKey)

	return xi.SameNodeID(p.nodeID, other.nodeID)
}

// SERIALIZATION ////////////////////////////////////////////////////

func addStringlet(slice *[]string, s string) {
	*slice = append(*slice, s)
}
func (p *BaseNode) Strings() []string {
	// DEBUG
	if p == nil {
		panic("BaseNode.Strings: nil p !")
	}
	if p.commsPubKey == nil {
		panic("BaseNode.Strings: nil p.commsPubKey !")
	}
	// END
	ckSSH, err := xc.RSAPubKeyToDisk(p.commsPubKey)
	if err != nil {
		panic(err)
	}
	skSSH, err := xc.RSAPubKeyToDisk(p.sigPubKey)
	if err != nil {
		panic(err)
	}

	var s []string
	addStringlet(&s, fmt.Sprintf("name: %s", p.name))
	addStringlet(&s, fmt.Sprintf("nodeID: %s", p.nodeID.String()))
	addStringlet(&s, fmt.Sprintf("commsPubKey: %s", ckSSH))
	addStringlet(&s, fmt.Sprintf("sigPubKey: %s", skSSH))
	addStringlet(&s, fmt.Sprintf("overlays {"))
	for i := 0; i < len(p.overlays); i++ {
		addStringlet(&s, fmt.Sprintf("    %s", p.overlays[i].String()))
	}
	addStringlet(&s, fmt.Sprintf("}"))
	return s
}
func (p *BaseNode) String() string {
	return strings.Join(p.Strings(), "\n")
}

// DESERIALIZATION //////////////////////////////////////////////////

// Return the next non-blank line in the slice of strings, trimmed.
// This line and any preceding blank lines are removed from the slice.
func NextNBLine(lines *[]string) string {
	if lines != nil {
		for len(*lines) > 0 {
			s := strings.TrimSpace((*lines)[0])
			*lines = (*lines)[1:]
			if s != "" {
				return s
			}
		}
	}
	return ""
}

// Parse a serialized BaseNode, ignoring blank lines and leading and
// trailing whitespace.  Expect the first line to be like "TYPE {"

func ParseBaseNode(data, whichType string) (bn *BaseNode, rest []string, err error) {
	ss := strings.Split(data, "\n") // yields a slice of strings
	return ParseBNFromStrings(ss, whichType)
}

// Version of the above which consumes a slice of strings.  XXX Copies the
// slice unnecessarily.
func ParseBNFromStrings(ss []string, whichType string) (bn *BaseNode, rest []string, err error) {
	var (
		name        string
		nodeID      *xi.NodeID
		commsPubKey *rsa.PublicKey
		sigPubKey   *rsa.PublicKey
		overlays    []xo.OverlayI
	)
	s := NextNBLine(&ss)
	opener := fmt.Sprintf("%s {", whichType) // "peer {" or "node {"
	if s != opener {
		err = NotExpectedOpener
	}
	if err == nil {
		s := NextNBLine(&ss)
		if strings.HasPrefix(s, "name: ") {
			name = s[6:]
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if strings.HasPrefix(s, "nodeID: ") {
			var val []byte
			val, err = hex.DecodeString(s[8:])
			if err == nil {
				nodeID, err = xi.NewNodeID(val)
			}
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if strings.HasPrefix(s, "commsPubKey: ") {
			// XXX we do not verify that the next line is empty
			ckSSH := []byte(s[13:] + "\n")
			commsPubKey, err = xc.RSAPubKeyFromDisk(ckSSH)
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if strings.HasPrefix(s, "sigPubKey: ") {
			skSSH := []byte(s[11:] + "\n")
			sigPubKey, err = xc.RSAPubKeyFromDisk(skSSH)
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if s == "overlays {" {
			for {
				s = NextNBLine(&ss)
				if s == "" { // end of strings
					err = NotABaseNode
					break
				} else if s == "}" {
					prepend := []string{s}
					ss = append(prepend, ss...)
					break
				}
				var o xo.OverlayI
				o, err = xo.Parse(s)
				if err == nil {
					overlays = append(overlays, o)
				}
			}
		} else {
			err = NotABaseNode
		}
	}
	if err == nil {
		s = NextNBLine(&ss)
		if s != "}" {
			err = NotABaseNode
		}
	}
	if err == nil {
		var bn = BaseNode{name, nodeID, commsPubKey, sigPubKey, overlays}
		return &bn, ss, nil
	} else {
		return nil, nil, err
	}
}
<|endoftext|>


<commit_before>package expr

import (
	"math"

	"github.com/grafana/metrictank/api/models"
	"github.com/grafana/metrictank/consolidation"
)

type FuncFilterSeries struct {
	in        GraphiteFunc
	fn        string
	operator  string
	threshold float64
}

func NewFilterSeries() GraphiteFunc {
	return &FuncFilterSeries{}
}

func (s *FuncFilterSeries) Signature() ([]Arg, []Arg) {
	return []Arg{
		ArgSeriesList{val: &s.in},
		ArgString{key: "func", val: &s.fn, validator: []Validator{IsConsolFunc}},
		ArgString{key: "operator", val: &s.operator, validator: []Validator{IsOperator}},
		ArgFloat{key: "threshold", val: &s.threshold},
	}, []Arg{ArgSeriesList{}}
}

func (s *FuncFilterSeries) Context(context Context) Context {
	return context
}

func (s *FuncFilterSeries) getOperatorFunc() func(float64) bool {
	switch s.operator {
	case "=":
		return func(val float64) bool {
			return val == s.threshold
		}

	case "!=":
		return func(val float64) bool {
			return val != s.threshold
		}

	case ">":
		return func(val float64) bool {
			return val > s.threshold
		}
	case ">=":
		return func(val float64) bool {
			return val >= s.threshold
		}

	case "<":
		return func(val float64) bool {
			return math.IsNaN(val) || val < s.threshold
		}
	case "<=":
		return func(val float64) bool {
			return math.IsNaN(val) || val <= s.threshold
		}
	}
	return func(val float64) bool { return false } // should never happen
}

func (s *FuncFilterSeries) Exec(cache map[Req][]models.Series) ([]models.Series, error) {
	series, err := s.in.Exec(cache)
	if err != nil {
		return nil, err
	}

	consolidationFunc := consolidation.GetAggFunc(consolidation.FromConsolidateBy(s.fn))
	operatorFunc := s.getOperatorFunc()

	out := make([]models.Series, 0, len(series))
	for _, serie := range series {
		if operatorFunc(consolidationFunc(serie.Datapoints)) {
			out = append(out, serie)
		}
	}

	return out, nil
}
<commit_msg>added error check and free function<commit_after>package expr

import (
	"errors"
	"math"

	"github.com/grafana/metrictank/api/models"
	"github.com/grafana/metrictank/consolidation"
)

type FuncFilterSeries struct {
	in        GraphiteFunc
	fn        string
	operator  string
	threshold float64
}

func NewFilterSeries() GraphiteFunc {
	return &FuncFilterSeries{}
}

func (s *FuncFilterSeries) Signature() ([]Arg, []Arg) {
	return []Arg{
		ArgSeriesList{val: &s.in},
		ArgString{key: "func", val: &s.fn, validator: []Validator{IsConsolFunc}},
		ArgString{key: "operator", val: &s.operator, validator: []Validator{IsOperator}},
		ArgFloat{key: "threshold", val: &s.threshold},
	}, []Arg{ArgSeriesList{}}
}

func (s *FuncFilterSeries) Context(context Context) Context {
	return context
}

func getOperatorFunc(operator string) (func(float64, float64) bool, error) {
	switch operator {
	case "=":
		return func(val, threshold float64) bool {
			return val == threshold
		}, nil

	case "!=":
		return func(val, threshold float64) bool {
			return val != threshold
		}, nil

	case ">":
		return func(val, threshold float64) bool {
			return val > threshold
		}, nil
	case ">=":
		return func(val, threshold float64) bool {
			return val >= threshold
		}, nil

	case "<":
		return func(val, threshold float64) bool {
			return math.IsNaN(val) || val < threshold
		}, nil
	case "<=":
		return func(val, threshold float64) bool {
			return math.IsNaN(val) || val <= threshold
		}, nil
	}
	return func(v1, v2 float64) bool { return false }, errors.New("Unsupported operator: " + operator)
}

func (s *FuncFilterSeries) Exec(cache map[Req][]models.Series) ([]models.Series, error) {
	series, err := s.in.Exec(cache)
	if err != nil {
		return nil, err
	}

	consolidationFunc := consolidation.GetAggFunc(consolidation.FromConsolidateBy(s.fn))
	operatorFunc, err := getOperatorFunc(s.operator)
	if err != nil {
		return nil, err
	}

	out := make([]models.Series, 0, len(series))
	for _, serie := range series {
		if operatorFunc(consolidationFunc(serie.Datapoints), s.threshold) {
			out = append(out, serie)
		}
	}

	return out, nil
}
<|endoftext|>


<commit_before>package build

import (
	"archive/zip"
	"encoding/json"
	"github.com/lonnc/golang-nw"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"text/template"
)

type Package struct {
	Name   string `json:"name"`
	Main   string `json:"main"`
	Window Window `json:"window"`
	Bin    string `json:"-"`
	EnvVar string `json:"-"`
}

type Window struct {
	Title    string `json:"title,omitempty"`
	Toolbar  bool   `json:"toolbar"`
	Show     bool   `json:"show,omitempty"`
	Position string `json:"position,omitempty"`
	Width    int    `json:"width,omitempty"`
	Height   int    `json:"height,omitempty"`
}

type Templates struct {
	IndexHtml string
	ClientJs  string
	ScriptJs  string
}

var DefaultTemplates = Templates{IndexHtml: index, ClientJs: client, ScriptJs: script}

// CreateNW creates a node-webkit .nw file
func (p Package) CreateNW(zw *zip.Writer, templates Templates, myapp io.Reader, includes string) error {
	// Add in a couple of package defaults
	p.Main = "index.html"
	p.EnvVar = nw.EnvVar

	if w, err := zw.Create("package.json"); err != nil {
		return err
	} else {
		if _, err := p.writeJsonTo(w); err != nil {
			return err
		}
	}

	filenameTemplates := map[string]string{
		"index.html": templates.IndexHtml,
		"client.js":  templates.ClientJs,
		"script.js":  templates.ScriptJs}
	for filename, str := range filenameTemplates {
		if w, err := zw.Create(filename); err != nil {
			return err
		} else {
			if t, err := template.New(filename).Parse(str); err != nil {
				return err
			} else {
				if err := t.Execute(w, p); err != nil {
					return err
				}
			}
		}
	}

	if includes != "" {
		if err := copyIncludes(zw, includes); err != nil {
			return err
		}
	}

	binHeader := zip.FileHeader{Name: p.Bin}
	binHeader.SetMode(0755) // Make it executable
	if w, err := zw.CreateHeader(&binHeader); err != nil {
		return err
	} else {
		if _, err := io.Copy(w, myapp); err != nil {
			return err
		}
	}

	return nil
}

func (p Package) writeJsonTo(w io.Writer) (int64, error) {
	b, err := json.Marshal(p)
	if err != nil {
		return 0, err
	}
	n, err := w.Write(b)
	return int64(n), err
}

// Copy any files from the includes directory
func copyIncludes(zw *zip.Writer, includes string) (includeErr error) {
	includes = path.Clean(includes)
	if !strings.HasSuffix(includes, "/") {
		includes += "/"
	}
	filepath.Walk(includes, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			includeErr = err
			return err
		}
		if info.IsDir() {
			return nil
		}
		if w, err := zw.Create(strings.TrimPrefix(path, includes)); err != nil {
			includeErr = err
			return err
		} else {
			b, err := ioutil.ReadFile(path)
			if err != nil {
				includeErr = err
				return err
			} else {
				_, err := w.Write(b)
				if err != nil {
					includeErr = err
					return err
				}
			}
		}
		return nil
	})
	return
}

<commit_msg>return correct error from filepath.Walk<commit_after>package build

import (
	"archive/zip"
	"encoding/json"
	"github.com/lonnc/golang-nw"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"text/template"
)

type Package struct {
	Name   string `json:"name"`
	Main   string `json:"main"`
	Window Window `json:"window"`
	Bin    string `json:"-"`
	EnvVar string `json:"-"`
}

type Window struct {
	Title    string `json:"title,omitempty"`
	Toolbar  bool   `json:"toolbar"`
	Show     bool   `json:"show,omitempty"`
	Position string `json:"position,omitempty"`
	Width    int    `json:"width,omitempty"`
	Height   int    `json:"height,omitempty"`
}

type Templates struct {
	IndexHtml string
	ClientJs  string
	ScriptJs  string
}

var DefaultTemplates = Templates{IndexHtml: index, ClientJs: client, ScriptJs: script}

// CreateNW creates a node-webkit .nw file
func (p Package) CreateNW(zw *zip.Writer, templates Templates, myapp io.Reader, includes string) error {
	// Add in a couple of package defaults
	p.Main = "index.html"
	p.EnvVar = nw.EnvVar

	if w, err := zw.Create("package.json"); err != nil {
		return err
	} else {
		if _, err := p.writeJsonTo(w); err != nil {
			return err
		}
	}

	filenameTemplates := map[string]string{
		"index.html": templates.IndexHtml,
		"client.js":  templates.ClientJs,
		"script.js":  templates.ScriptJs}
	for filename, str := range filenameTemplates {
		if w, err := zw.Create(filename); err != nil {
			return err
		} else {
			if t, err := template.New(filename).Parse(str); err != nil {
				return err
			} else {
				if err := t.Execute(w, p); err != nil {
					return err
				}
			}
		}
	}

	if includes != "" {
		if err := copyIncludes(zw, includes); err != nil {
			return err
		}
	}

	binHeader := zip.FileHeader{Name: p.Bin}
	binHeader.SetMode(0755) // Make it executable
	if w, err := zw.CreateHeader(&binHeader); err != nil {
		return err
	} else {
		if _, err := io.Copy(w, myapp); err != nil {
			return err
		}
	}

	return nil
}

func (p Package) writeJsonTo(w io.Writer) (int64, error) {
	b, err := json.Marshal(p)
	if err != nil {
		return 0, err
	}
	n, err := w.Write(b)
	return int64(n), err
}

// Copy any files from the includes directory
func copyIncludes(zw *zip.Writer, includes string) error {
	includes = path.Clean(includes)
	if !strings.HasSuffix(includes, "/") {
		includes += "/"
	}
	return filepath.Walk(includes, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		if w, err := zw.Create(strings.TrimPrefix(path, includes)); err != nil {
			return err
		} else {
			b, err := ioutil.ReadFile(path)
			if err != nil {
				return err
			} else {
				_, err := w.Write(b)
				if err != nil {
					return err
				}
			}
		}
		return nil
	})
}

<|endoftext|>


<commit_before>// Copyright 2012 James Cooper. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

//go:build !integration
// +build !integration

package gorp_test

import (
  "database/sql"
  "reflect"
  "testing"
  "time"

  "github.com/go-gorp/gorp"
  "github.com/poy/onpar"
  "github.com/poy/onpar/expect"
  "github.com/poy/onpar/matchers"
)

func TestSnowflakeDialect(t *testing.T) {
  o := onpar.New()
  defer o.Run(t)

  o.BeforeEach(func(t *testing.T) (expect.Expectation, gorp.SnowflakeDialect) {
    return expect.New(t), gorp.SnowflakeDialect{
      LowercaseFields: false,
    }
  })

  o.Group("ToSqlType", func() {
    tests := []struct {
      name     string
      value    interface{}
      maxSize  int
      autoIncr bool
      expected string
    }{
      {"bool", true, 0, false, "boolean"},
      {"int8", int8(1), 0, false, "integer"},
      {"uint8", uint8(1), 0, false, "integer"},
      {"int16", int16(1), 0, false, "integer"},
      {"uint16", uint16(1), 0, false, "integer"},
      {"int32", int32(1), 0, false, "integer"},
      {"int (treated as int32)", int(1), 0, false, "integer"},
      {"uint32", uint32(1), 0, false, "integer"},
      {"uint (treated as uint32)", uint(1), 0, false, "integer"},
      {"int64", int64(1), 0, false, "bigint"},
      {"uint64", uint64(1), 0, false, "bigint"},
      {"float32", float32(1), 0, false, "real"},
      {"float64", float64(1), 0, false, "double precision"},
      {"[]uint8", []uint8{1}, 0, false, "bytea"},
      {"NullInt64", sql.NullInt64{}, 0, false, "bigint"},
      {"NullFloat64", sql.NullFloat64{}, 0, false, "double precision"},
      {"NullBool", sql.NullBool{}, 0, false, "boolean"},
      {"Time", time.Time{}, 0, false, "timestamp with time zone"},
      {"default-size string", "", 0, false, "text"},
      {"sized string", "", 50, false, "varchar(50)"},
      {"large string", "", 1024, false, "varchar(1024)"},
    }
    for _, t := range tests {
      o.Spec(t.name, func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
        typ := reflect.TypeOf(t.value)
        sqlType := dialect.ToSqlType(typ, t.maxSize, t.autoIncr)
        expect(sqlType).To(matchers.Equal(t.expected))
      })
    }
  })

  o.Spec("AutoIncrStr", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.AutoIncrStr()).To(matchers.Equal(""))
  })

  o.Spec("AutoIncrBindValue", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.AutoIncrBindValue()).To(matchers.Equal("default"))
  })

  o.Spec("AutoIncrInsertSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.AutoIncrInsertSuffix(nil)).To(matchers.Equal(""))
  })

  o.Spec("CreateTableSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.CreateTableSuffix()).To(matchers.Equal(""))
  })

  o.Spec("CreateIndexSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.CreateIndexSuffix()).To(matchers.Equal(""))
  })

  o.Spec("DropIndexSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.DropIndexSuffix()).To(matchers.Equal(""))
  })

  o.Spec("TruncateClause", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.TruncateClause()).To(matchers.Equal("truncate"))
  })

  o.Spec("BindVar", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.BindVar(0)).To(matchers.Equal("?"))
    expect(dialect.BindVar(4)).To(matchers.Equal("?"))
  })

  o.Group("QuoteField", func() {
    o.Spec("By default, case is preserved", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
      expect(dialect.QuoteField("Foo")).To(matchers.Equal(`"Foo"`))
      expect(dialect.QuoteField("bar")).To(matchers.Equal(`"bar"`))
    })

    o.Group("With LowercaseFields set to true", func() {
      o.BeforeEach(func(expect expect.Expectation, dialect gorp.SnowflakeDialect) (expect.Expectation, gorp.SnowflakeDialect) {
        dialect.LowercaseFields = true
        return expect, dialect
      })

      o.Spec("fields are lowercased", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
        expect(dialect.QuoteField("Foo")).To(matchers.Equal(`"foo"`))
      })
    })
  })

  o.Group("QuotedTableForQuery", func() {
    o.Spec("using the default schema", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
      expect(dialect.QuotedTableForQuery("", "foo")).To(matchers.Equal(`"foo"`))
    })

    o.Spec("with a supplied schema", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
      expect(dialect.QuotedTableForQuery("foo", "bar")).To(matchers.Equal(`foo."bar"`))
    })
  })

  o.Spec("IfSchemaNotExists", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.IfSchemaNotExists("foo", "bar")).To(matchers.Equal("foo if not exists"))
  })

  o.Spec("IfTableExists", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.IfTableExists("foo", "bar", "baz")).To(matchers.Equal("foo if exists"))
  })

  o.Spec("IfTableNotExists", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.IfTableNotExists("foo", "bar", "baz")).To(matchers.Equal("foo if not exists"))
  })
}
<commit_msg>Fix import path<commit_after>// Copyright 2012 James Cooper. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

//go:build !integration
// +build !integration

package gorp_test

import (
  "database/sql"
  "reflect"
  "testing"
  "time"

  "github.com/go-gorp/gorp/v3"
  "github.com/poy/onpar"
  "github.com/poy/onpar/expect"
  "github.com/poy/onpar/matchers"
)

func TestSnowflakeDialect(t *testing.T) {
  o := onpar.New()
  defer o.Run(t)

  o.BeforeEach(func(t *testing.T) (expect.Expectation, gorp.SnowflakeDialect) {
    return expect.New(t), gorp.SnowflakeDialect{
      LowercaseFields: false,
    }
  })

  o.Group("ToSqlType", func() {
    tests := []struct {
      name     string
      value    interface{}
      maxSize  int
      autoIncr bool
      expected string
    }{
      {"bool", true, 0, false, "boolean"},
      {"int8", int8(1), 0, false, "integer"},
      {"uint8", uint8(1), 0, false, "integer"},
      {"int16", int16(1), 0, false, "integer"},
      {"uint16", uint16(1), 0, false, "integer"},
      {"int32", int32(1), 0, false, "integer"},
      {"int (treated as int32)", int(1), 0, false, "integer"},
      {"uint32", uint32(1), 0, false, "integer"},
      {"uint (treated as uint32)", uint(1), 0, false, "integer"},
      {"int64", int64(1), 0, false, "bigint"},
      {"uint64", uint64(1), 0, false, "bigint"},
      {"float32", float32(1), 0, false, "real"},
      {"float64", float64(1), 0, false, "double precision"},
      {"[]uint8", []uint8{1}, 0, false, "bytea"},
      {"NullInt64", sql.NullInt64{}, 0, false, "bigint"},
      {"NullFloat64", sql.NullFloat64{}, 0, false, "double precision"},
      {"NullBool", sql.NullBool{}, 0, false, "boolean"},
      {"Time", time.Time{}, 0, false, "timestamp with time zone"},
      {"default-size string", "", 0, false, "text"},
      {"sized string", "", 50, false, "varchar(50)"},
      {"large string", "", 1024, false, "varchar(1024)"},
    }
    for _, t := range tests {
      o.Spec(t.name, func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
        typ := reflect.TypeOf(t.value)
        sqlType := dialect.ToSqlType(typ, t.maxSize, t.autoIncr)
        expect(sqlType).To(matchers.Equal(t.expected))
      })
    }
  })

  o.Spec("AutoIncrStr", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.AutoIncrStr()).To(matchers.Equal(""))
  })

  o.Spec("AutoIncrBindValue", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.AutoIncrBindValue()).To(matchers.Equal("default"))
  })

  o.Spec("AutoIncrInsertSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.AutoIncrInsertSuffix(nil)).To(matchers.Equal(""))
  })

  o.Spec("CreateTableSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.CreateTableSuffix()).To(matchers.Equal(""))
  })

  o.Spec("CreateIndexSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.CreateIndexSuffix()).To(matchers.Equal(""))
  })

  o.Spec("DropIndexSuffix", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.DropIndexSuffix()).To(matchers.Equal(""))
  })

  o.Spec("TruncateClause", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.TruncateClause()).To(matchers.Equal("truncate"))
  })

  o.Spec("BindVar", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.BindVar(0)).To(matchers.Equal("?"))
    expect(dialect.BindVar(4)).To(matchers.Equal("?"))
  })

  o.Group("QuoteField", func() {
    o.Spec("By default, case is preserved", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
      expect(dialect.QuoteField("Foo")).To(matchers.Equal(`"Foo"`))
      expect(dialect.QuoteField("bar")).To(matchers.Equal(`"bar"`))
    })

    o.Group("With LowercaseFields set to true", func() {
      o.BeforeEach(func(expect expect.Expectation, dialect gorp.SnowflakeDialect) (expect.Expectation, gorp.SnowflakeDialect) {
        dialect.LowercaseFields = true
        return expect, dialect
      })

      o.Spec("fields are lowercased", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
        expect(dialect.QuoteField("Foo")).To(matchers.Equal(`"foo"`))
      })
    })
  })

  o.Group("QuotedTableForQuery", func() {
    o.Spec("using the default schema", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
      expect(dialect.QuotedTableForQuery("", "foo")).To(matchers.Equal(`"foo"`))
    })

    o.Spec("with a supplied schema", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
      expect(dialect.QuotedTableForQuery("foo", "bar")).To(matchers.Equal(`foo."bar"`))
    })
  })

  o.Spec("IfSchemaNotExists", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.IfSchemaNotExists("foo", "bar")).To(matchers.Equal("foo if not exists"))
  })

  o.Spec("IfTableExists", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.IfTableExists("foo", "bar", "baz")).To(matchers.Equal("foo if exists"))
  })

  o.Spec("IfTableNotExists", func(expect expect.Expectation, dialect gorp.SnowflakeDialect) {
    expect(dialect.IfTableNotExists("foo", "bar", "baz")).To(matchers.Equal("foo if not exists"))
  })
}
<|endoftext|>


<commit_before>package api

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/ponzu-cms/ponzu/system/admin/upload"
	"github.com/ponzu-cms/ponzu/system/admin/user"
	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/item"
)

// Updateable accepts or rejects update POST requests to endpoints such as:
// /api/content/update?type=Review&id=1
type Updateable interface {
	// AcceptUpdate allows external content update submissions of a specific type
	AcceptUpdate(http.ResponseWriter, *http.Request) error
}

func updateContentHandler(res http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		res.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
	if err != nil {
		log.Println("[Update] error:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	t := req.URL.Query().Get("type")
	if t == "" {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	p, found := item.Types[t]
	if !found {
		log.Println("[Update] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusNotFound)
		return
	}

	id := req.URL.Query().Get("id")
	if id == "" {
		log.Println("[Update] attempt to submit update with missing id from:", req.RemoteAddr)
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	if user.IsValid(req) == false {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	post := p()

	ext, ok := post.(Updateable)
	if !ok {
		log.Println("[Update] rejected non-replaceable type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	ts := fmt.Sprintf("%d", int64(time.Nanosecond)*time.Now().UnixNano()/int64(time.Millisecond))
	req.PostForm.Set("timestamp", ts)
	req.PostForm.Set("updated", ts)

	urlPaths, err := upload.StoreFiles(req)
	if err != nil {
		log.Println(err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	for name, urlPath := range urlPaths {
		req.PostForm.Set(name, urlPath)
	}

	// check for any multi-value fields (ex. checkbox fields)
	// and correctly format for db storage. Essentially, we need
	// fieldX.0: value1, fieldX.1: value2 => fieldX: []string{value1, value2}
	fieldOrderValue := make(map[string]map[string][]string)
	ordVal := make(map[string][]string)
	for k, v := range req.PostForm {
		if strings.Contains(k, ".") {
			fo := strings.Split(k, ".")

			// put the order and the field value into map
			field := string(fo[0])
			order := string(fo[1])
			fieldOrderValue[field] = ordVal

			// orderValue is 0:[?type=Thing&id=1]
			orderValue := fieldOrderValue[field]
			orderValue[order] = v
			fieldOrderValue[field] = orderValue

			// discard the post form value with name.N
			req.PostForm.Del(k)
		}

	}

	// add/set the key & value to the post form in order
	for f, ov := range fieldOrderValue {
		for i := 0; i < len(ov); i++ {
			position := fmt.Sprintf("%d", i)
			fieldValue := ov[position]

			if req.PostForm.Get(f) == "" {
				for i, fv := range fieldValue {
					if i == 0 {
						req.PostForm.Set(f, fv)
					} else {
						req.PostForm.Add(f, fv)
					}
				}
			} else {
				for _, fv := range fieldValue {
					req.PostForm.Add(f, fv)
				}
			}
		}
	}

	hook, ok := post.(item.Hookable)
	if !ok {
		log.Println("[Update] error: Type", t, "does not implement item.Hookable or embed item.Item.")
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	err = hook.BeforeAccept(res, req)
	if err != nil {
		log.Println("[Update] error calling BeforeAccept:", err)
		return
	}

	err = ext.AcceptUpdate(res, req)
	if err != nil {
		log.Println("[Update] error calling Accept:", err)
		return
	}

	err = hook.BeforeSave(res, req)
	if err != nil {
		log.Println("[Update] error calling BeforeSave:", err)
		return
	}

	// set specifier for db bucket in case content is/isn't Trustable
	var spec string

	_, err = db.SetContent(t+spec+":"+id, req.PostForm)
	if err != nil {
		log.Println("[Update] error calling SetContent:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	// set the target in the context so user can get saved value from db in hook
	ctx := context.WithValue(req.Context(), "target", fmt.Sprintf("%s:%d", t, id))
	req = req.WithContext(ctx)

	err = hook.AfterSave(res, req)
	if err != nil {
		log.Println("[Update] error calling AfterSave:", err)
		return
	}

	err = hook.AfterAccept(res, req)
	if err != nil {
		log.Println("[Update] error calling AfterAccept:", err)
		return
	}

	// create JSON response to send data back to client
	var data map[string]interface{}
	if spec != "" {
		spec = strings.TrimPrefix(spec, "__")
		data = map[string]interface{}{
			"status": spec,
			"type":   t,
		}
	} else {
		spec = "public"
		data = map[string]interface{}{
			"id":     id,
			"status": spec,
			"type":   t,
		}
	}

	resp := map[string]interface{}{
		"data": []map[string]interface{}{
			data,
		},
	}

	j, err := json.Marshal(resp)
	if err != nil {
		log.Println("[Update] error marshalling response to JSON:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.Header().Set("Content-Type", "application/json")
	_, err = res.Write(j)
	if err != nil {
		log.Println("[Update] error writing response:", err)
		return
	}

}
<commit_msg>added logging for failed user validation on api update<commit_after>package api

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/ponzu-cms/ponzu/system/admin/upload"
	"github.com/ponzu-cms/ponzu/system/admin/user"
	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/item"
)

// Updateable accepts or rejects update POST requests to endpoints such as:
// /api/content/update?type=Review&id=1
type Updateable interface {
	// AcceptUpdate allows external content update submissions of a specific type
	AcceptUpdate(http.ResponseWriter, *http.Request) error
}

func updateContentHandler(res http.ResponseWriter, req *http.Request) {
	if req.Method != http.MethodPost {
		res.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	err := req.ParseMultipartForm(1024 * 1024 * 4) // maxMemory 4MB
	if err != nil {
		log.Println("[Update] error:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	t := req.URL.Query().Get("type")
	if t == "" {
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	p, found := item.Types[t]
	if !found {
		log.Println("[Update] attempt to submit unknown type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusNotFound)
		return
	}

	id := req.URL.Query().Get("id")
	if id == "" {
		log.Println("[Update] attempt to submit update with missing id from:", req.RemoteAddr)
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	if user.IsValid(req) == false {
		log.Println("[Update] invalid user.")
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	post := p()

	ext, ok := post.(Updateable)
	if !ok {
		log.Println("[Update] rejected non-updateable type:", t, "from:", req.RemoteAddr)
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	ts := fmt.Sprintf("%d", int64(time.Nanosecond)*time.Now().UnixNano()/int64(time.Millisecond))
	req.PostForm.Set("timestamp", ts)
	req.PostForm.Set("updated", ts)

	urlPaths, err := upload.StoreFiles(req)
	if err != nil {
		log.Println(err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	for name, urlPath := range urlPaths {
		req.PostForm.Set(name, urlPath)
	}

	// check for any multi-value fields (ex. checkbox fields)
	// and correctly format for db storage. Essentially, we need
	// fieldX.0: value1, fieldX.1: value2 => fieldX: []string{value1, value2}
	fieldOrderValue := make(map[string]map[string][]string)
	ordVal := make(map[string][]string)
	for k, v := range req.PostForm {
		if strings.Contains(k, ".") {
			fo := strings.Split(k, ".")

			// put the order and the field value into map
			field := string(fo[0])
			order := string(fo[1])
			fieldOrderValue[field] = ordVal

			// orderValue is 0:[?type=Thing&id=1]
			orderValue := fieldOrderValue[field]
			orderValue[order] = v
			fieldOrderValue[field] = orderValue

			// discard the post form value with name.N
			req.PostForm.Del(k)
		}

	}

	// add/set the key & value to the post form in order
	for f, ov := range fieldOrderValue {
		for i := 0; i < len(ov); i++ {
			position := fmt.Sprintf("%d", i)
			fieldValue := ov[position]

			if req.PostForm.Get(f) == "" {
				for i, fv := range fieldValue {
					if i == 0 {
						req.PostForm.Set(f, fv)
					} else {
						req.PostForm.Add(f, fv)
					}
				}
			} else {
				for _, fv := range fieldValue {
					req.PostForm.Add(f, fv)
				}
			}
		}
	}

	hook, ok := post.(item.Hookable)
	if !ok {
		log.Println("[Update] error: Type", t, "does not implement item.Hookable or embed item.Item.")
		res.WriteHeader(http.StatusBadRequest)
		return
	}

	err = hook.BeforeAccept(res, req)
	if err != nil {
		log.Println("[Update] error calling BeforeAccept:", err)
		return
	}

	err = ext.AcceptUpdate(res, req)
	if err != nil {
		log.Println("[Update] error calling Accept:", err)
		return
	}

	err = hook.BeforeSave(res, req)
	if err != nil {
		log.Println("[Update] error calling BeforeSave:", err)
		return
	}

	// set specifier for db bucket in case content is/isn't Trustable
	var spec string

	_, err = db.SetContent(t+spec+":"+id, req.PostForm)
	if err != nil {
		log.Println("[Update] error calling SetContent:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	// set the target in the context so user can get saved value from db in hook
	ctx := context.WithValue(req.Context(), "target", fmt.Sprintf("%s:%d", t, id))
	req = req.WithContext(ctx)

	err = hook.AfterSave(res, req)
	if err != nil {
		log.Println("[Update] error calling AfterSave:", err)
		return
	}

	err = hook.AfterAccept(res, req)
	if err != nil {
		log.Println("[Update] error calling AfterAccept:", err)
		return
	}

	// create JSON response to send data back to client
	var data map[string]interface{}
	if spec != "" {
		spec = strings.TrimPrefix(spec, "__")
		data = map[string]interface{}{
			"status": spec,
			"type":   t,
		}
	} else {
		spec = "public"
		data = map[string]interface{}{
			"id":     id,
			"status": spec,
			"type":   t,
		}
	}

	resp := map[string]interface{}{
		"data": []map[string]interface{}{
			data,
		},
	}

	j, err := json.Marshal(resp)
	if err != nil {
		log.Println("[Update] error marshalling response to JSON:", err)
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.Header().Set("Content-Type", "application/json")
	_, err = res.Write(j)
	if err != nil {
		log.Println("[Update] error writing response:", err)
		return
	}

}
<|endoftext|>


<commit_before>package lang

import (
	. "jvmgo/any"
	"jvmgo/jvm/interpreter"
	"jvmgo/jvm/rtda"
	rtc "jvmgo/jvm/rtda/class"
)

func init() {
	_thread(isAlive, "isAlive", "()Z")
	_thread(setPriority0, "setPriority0", "(I)V")
	_thread(start0, "start0", "()V")
}

func _thread(method Any, name, desc string) {
	rtc.RegisterNativeMethod("java/lang/Thread", name, desc, method)
}

// @Deprecated public native int countStackFrames();
// private native boolean isInterrupted(boolean ClearInterrupted);
// private native void stop0(Object o);
// private native void suspend0();
// private native void resume0();
// private native void interrupt0();
// private native void setNativeName(String name);

// public final native boolean isAlive();
// ()Z
func isAlive(frame *rtda.Frame) {
	vars := frame.LocalVars()
	this := vars.GetThis()

	thread := _extraThread(this)
	alive := thread != nil && !thread.IsStackEmpty()

	stack := frame.OperandStack()
	stack.PushBoolean(alive)
}

func _extraThread(threadObj *rtc.Obj) *rtda.Thread {
	threadObj.RLockState()
	defer threadObj.RUnlockState()

	extra := threadObj.Extra()
	if extra == nil {
		return nil
	} else {
		return extra.(*rtda.Thread)
	}
}

// private native void setPriority0(int newPriority);
// (I)V
func setPriority0(frame *rtda.Frame) {
	// vars := frame.LocalVars()
	// this := vars.GetThis()
	// newPriority := vars.GetInt(1))
	// todo
}

// private native void start0();
// ()V
func start0(frame *rtda.Frame) {
	vars := frame.LocalVars()
	this := vars.GetThis()

	newThread := rtda.NewThread(this)
	runMethod := this.Class().GetInstanceMethod("run", "()V")
	newFrame := newThread.NewFrame(runMethod)
	newFrame.LocalVars().SetRef(0, this)
	newThread.PushFrame(newFrame)

	this.LockState()
	this.SetExtra(newThread)
	this.UnlockState()

	go interpreter.Loop(newThread)
}
<commit_msg>register native method: Thread. isInterrupted()<commit_after>package lang

import (
	. "jvmgo/any"
	"jvmgo/jvm/interpreter"
	"jvmgo/jvm/rtda"
	rtc "jvmgo/jvm/rtda/class"
)

func init() {
	_thread(isInterrupted, "isInterrupted", "(Z)Z")
	_thread(isAlive, "isAlive", "()Z")
	_thread(setPriority0, "setPriority0", "(I)V")
	_thread(start0, "start0", "()V")
}

func _thread(method Any, name, desc string) {
	rtc.RegisterNativeMethod("java/lang/Thread", name, desc, method)
}

// @Deprecated public native int countStackFrames();
// private native void stop0(Object o);
// private native void suspend0();
// private native void resume0();
// private native void interrupt0();
// private native void setNativeName(String name);

// public final native boolean isAlive();
// ()Z
func isAlive(frame *rtda.Frame) {
	vars := frame.LocalVars()
	this := vars.GetThis()

	thread := _extraThread(this)
	alive := thread != nil && !thread.IsStackEmpty()

	stack := frame.OperandStack()
	stack.PushBoolean(alive)
}

// private native boolean isInterrupted(boolean ClearInterrupted);
// (Z)Z
func isInterrupted(frame *rtda.Frame) {
	// todo
	panic("todo")
}

func _extraThread(threadObj *rtc.Obj) *rtda.Thread {
	threadObj.RLockState()
	defer threadObj.RUnlockState()

	extra := threadObj.Extra()
	if extra == nil {
		return nil
	} else {
		return extra.(*rtda.Thread)
	}
}

// private native void setPriority0(int newPriority);
// (I)V
func setPriority0(frame *rtda.Frame) {
	// vars := frame.LocalVars()
	// this := vars.GetThis()
	// newPriority := vars.GetInt(1))
	// todo
}

// private native void start0();
// ()V
func start0(frame *rtda.Frame) {
	vars := frame.LocalVars()
	this := vars.GetThis()

	newThread := rtda.NewThread(this)
	runMethod := this.Class().GetInstanceMethod("run", "()V")
	newFrame := newThread.NewFrame(runMethod)
	newFrame.LocalVars().SetRef(0, this)
	newThread.PushFrame(newFrame)

	this.LockState()
	this.SetExtra(newThread)
	this.UnlockState()

	go interpreter.Loop(newThread)
}
<|endoftext|>


<commit_before>package validation

import (
	"fmt"
	"os"

	"golang.org/x/net/context"

	"chain/errors"
	"chain/fedchain/bc"
	"chain/fedchain/state"
	"chain/fedchain/txscript"
)

var stubGenesisHash = bc.Hash{}

// ErrBadTx is returned for transactions failing validation
var ErrBadTx = errors.New("invalid transaction")

// ValidateTxInputs just validates that the tx inputs are present
// and unspent in the view.
func ValidateTxInputs(ctx context.Context, view state.ViewReader, tx *bc.Tx) error {
	// Verify inputs for double-spends and update ADPs on the view.
	for inIndex, txin := range tx.Inputs {
		if txin.IsIssuance() {
			continue
		}
		unspent := view.Output(ctx, txin.Previous)
		// It's possible to load a spent output here because BackedView
		// explicitly stores spent outputs in frontend to shadow unspent
		// outputs in backend.
		if unspent == nil || unspent.Spent {
			return errors.WithDetailf(ErrBadTx, "output %s for input %d is invalid or already spent", txin.Previous.String(), inIndex)
		}
	}
	return nil
}

// ValidateTx validates the given transaction
// against the given state and applies its
// changes to the view.
// If tx is invalid,
// it returns a non-nil error describing why.
func ValidateTx(ctx context.Context, view state.ViewReader, tx *bc.Tx, timestamp uint64) error {
	// Don't make a span here, because there are too many of them
	// to comfortably fit in a single trace for processing (creating
	// or applying) a block.
	// TODO(kr): ask Ben what's reasonable to do in this situation.

	err := txIsWellFormed(tx)
	if err != nil {
		return errors.Wrap(err, "well-formed test")
	}

	// Check time
	if tx.LockTime > timestamp {
		return errors.WithDetail(ErrBadTx, "transaction lock time is in the future")
	}

	// If this is an issuance tx, check its prevout hash against the
	// previous block hash if we have one.
	// NOTE: review this when we implement import inputs.
	// Maybe we'll need to have undo ADP.
	// TODO(erykwalder): some type of uniqueness check

	err = ValidateTxInputs(ctx, view, tx)
	if err != nil {
		return errors.Wrap(err, "validating inputs")
	}

	err = validateTxBalance(ctx, view, tx)
	if err != nil {
		return errors.Wrap(err, "validating balance")
	}

	engine, err := txscript.NewReusableEngine(ctx, view, &tx.TxData, txscript.StandardVerifyFlags)
	if err != nil {
		return fmt.Errorf("cannot create script engine: %s", err)
	}

	if false { // change to true for quick debug tracing
		txscript.SetLogWriter(os.Stdout, "trace")
		defer txscript.DisableLog()
	}

	for i, input := range tx.Inputs {
		if input.IsIssuance() {
			// TODO: implement issuance scheme
			continue
		}
		unspent := view.Output(ctx, input.Previous)
		err = engine.Prepare(unspent.Script, i)
		if err != nil {
			err = errors.Wrapf(ErrBadTx, "cannot prepare script engine to process input %d: %s", i, err)
			return errors.WithDetailf(err, "invalid script on input %d", i)
		}
		if err = engine.Execute(); err != nil {
			pkScriptStr, _ := txscript.DisasmString(unspent.Script)
			sigScriptStr, _ := txscript.DisasmString(input.SignatureScript)
			return errors.WithDetailf(ErrBadTx, "validation failed in script execution, input %d (sigscript[%s] pkscript[%s])", i, sigScriptStr, pkScriptStr)
		}
	}

	return nil
}

// txIsWellFormed checks whether tx passes context-free validation.
// If tx is well formed, it returns a nil error;
// otherwise, it returns an error describing why tx is invalid.
func txIsWellFormed(tx *bc.Tx) error {
	if len(tx.Inputs) == 0 {
		return errors.WithDetail(ErrBadTx, "inputs are missing")
	}

	// Check for duplicate inputs
	uniqueFilter := map[bc.Outpoint]bool{}
	for _, txin := range tx.Inputs {
		if txin.IsIssuance() {
			continue
		}
		if uniqueFilter[txin.Previous] {
			return errors.WithDetailf(ErrBadTx, "duplicated input for %s", txin.Previous.String())
		}
		uniqueFilter[txin.Previous] = true
	}

	// Check that every output has a valid value.
	for _, txout := range tx.Outputs {
		// Zero-value outputs are allowed for re-publishing
		// asset definition using issuance transactions.
		// Non-issuance transactions cannot have zero-value outputs.
		// If all inputs have zero value, tx therefore must have no outputs.
		// TODO: check that output asset id is an asset being issued
		if txout.Amount == 0 && !tx.HasIssuance() {
			return errors.WithDetailf(ErrBadTx, "non-issuance output value must be greater than 0")
		}
	}
	return nil
}

// validateTxBalance ensures that non-issuance transactions
// have the exact same input and output asset amounts.
func validateTxBalance(ctx context.Context, view state.ViewReader, tx *bc.Tx) error {
	parity := make(map[bc.AssetID]int64)
	issued := make(map[bc.AssetID]bool)
	for _, out := range tx.Outputs {
		parity[out.AssetID] -= int64(out.Amount)
	}
	for _, in := range tx.Inputs {
		if in.IsIssuance() {
			assetID, err := assetIDFromSigScript(in.SignatureScript)
			if err != nil {
				return err
			}
			issued[assetID] = true
			continue
		}
		unspent := view.Output(ctx, in.Previous)
		assetID := unspent.AssetID
		if assetID == (bc.AssetID{}) {
			assetID = bc.ComputeAssetID(unspent.Script, stubGenesisHash)
		}
		parity[assetID] += int64(unspent.Amount)
	}
	for asset, val := range parity {
		if val > 0 || (val < 0 && !issued[asset]) {
			return errors.WithDetailf(ErrBadTx, "amounts for asset %s are not balanced on inputs and outputs")
		}
	}
	return nil
}

// ApplyTx updates the view with all the changes to the ledger
func ApplyTx(ctx context.Context, view state.View, tx *bc.Tx) error {
	for _, in := range tx.Inputs {
		if in.IsIssuance() {
			continue
		}
		o := view.Output(ctx, in.Previous)
		o.Spent = true
		view.SaveOutput(o)
	}

	for _, in := range tx.Inputs {
		// If metadata field is empty, no update of ADP takes place.
		// See https://github.com/chain-engineering/fedchain/blob/master/documentation/fedchain-specification.md#extract-asset-definition.
		if in.IsIssuance() && len(in.AssetDefinition) > 0 {
			assetID, err := assetIDFromSigScript(in.SignatureScript)
			if err != nil {
				return err
			}
			defHash := bc.HashAssetDefinition(in.AssetDefinition)
			view.SaveAssetDefinitionPointer(assetID, defHash)
		}
	}

	for i, out := range tx.Outputs {
		o := &state.Output{
			TxOutput: *out,
			Outpoint: bc.Outpoint{Hash: tx.Hash, Index: uint32(i)},
			Spent:    false,
		}
		view.SaveOutput(o)
	}

	return nil
}

func assetIDFromSigScript(script []byte) (bc.AssetID, error) {
	redeemScript, err := txscript.RedeemScriptFromP2SHSigScript(script)
	if err != nil {
		return bc.AssetID{}, errors.Wrap(err, "extracting redeem script from sigscript")
	}
	pkScript := txscript.RedeemToPkScript(redeemScript)
	return bc.ComputeAssetID(pkScript, [32]byte{}), nil // TODO(tessr): get genesis hash
}
<commit_msg>fedchain/validation: fix WithDetailf call<commit_after>package validation

import (
	"fmt"
	"os"

	"golang.org/x/net/context"

	"chain/errors"
	"chain/fedchain/bc"
	"chain/fedchain/state"
	"chain/fedchain/txscript"
)

var stubGenesisHash = bc.Hash{}

// ErrBadTx is returned for transactions failing validation
var ErrBadTx = errors.New("invalid transaction")

// ValidateTxInputs just validates that the tx inputs are present
// and unspent in the view.
func ValidateTxInputs(ctx context.Context, view state.ViewReader, tx *bc.Tx) error {
	// Verify inputs for double-spends and update ADPs on the view.
	for inIndex, txin := range tx.Inputs {
		if txin.IsIssuance() {
			continue
		}
		unspent := view.Output(ctx, txin.Previous)
		// It's possible to load a spent output here because BackedView
		// explicitly stores spent outputs in frontend to shadow unspent
		// outputs in backend.
		if unspent == nil || unspent.Spent {
			return errors.WithDetailf(ErrBadTx, "output %s for input %d is invalid or already spent", txin.Previous.String(), inIndex)
		}
	}
	return nil
}

// ValidateTx validates the given transaction
// against the given state and applies its
// changes to the view.
// If tx is invalid,
// it returns a non-nil error describing why.
func ValidateTx(ctx context.Context, view state.ViewReader, tx *bc.Tx, timestamp uint64) error {
	// Don't make a span here, because there are too many of them
	// to comfortably fit in a single trace for processing (creating
	// or applying) a block.
	// TODO(kr): ask Ben what's reasonable to do in this situation.

	err := txIsWellFormed(tx)
	if err != nil {
		return errors.Wrap(err, "well-formed test")
	}

	// Check time
	if tx.LockTime > timestamp {
		return errors.WithDetail(ErrBadTx, "transaction lock time is in the future")
	}

	// If this is an issuance tx, check its prevout hash against the
	// previous block hash if we have one.
	// NOTE: review this when we implement import inputs.
	// Maybe we'll need to have undo ADP.
	// TODO(erykwalder): some type of uniqueness check

	err = ValidateTxInputs(ctx, view, tx)
	if err != nil {
		return errors.Wrap(err, "validating inputs")
	}

	err = validateTxBalance(ctx, view, tx)
	if err != nil {
		return errors.Wrap(err, "validating balance")
	}

	engine, err := txscript.NewReusableEngine(ctx, view, &tx.TxData, txscript.StandardVerifyFlags)
	if err != nil {
		return fmt.Errorf("cannot create script engine: %s", err)
	}

	if false { // change to true for quick debug tracing
		txscript.SetLogWriter(os.Stdout, "trace")
		defer txscript.DisableLog()
	}

	for i, input := range tx.Inputs {
		if input.IsIssuance() {
			// TODO: implement issuance scheme
			continue
		}
		unspent := view.Output(ctx, input.Previous)
		err = engine.Prepare(unspent.Script, i)
		if err != nil {
			err = errors.Wrapf(ErrBadTx, "cannot prepare script engine to process input %d: %s", i, err)
			return errors.WithDetailf(err, "invalid script on input %d", i)
		}
		if err = engine.Execute(); err != nil {
			pkScriptStr, _ := txscript.DisasmString(unspent.Script)
			sigScriptStr, _ := txscript.DisasmString(input.SignatureScript)
			return errors.WithDetailf(ErrBadTx, "validation failed in script execution, input %d (sigscript[%s] pkscript[%s])", i, sigScriptStr, pkScriptStr)
		}
	}

	return nil
}

// txIsWellFormed checks whether tx passes context-free validation.
// If tx is well formed, it returns a nil error;
// otherwise, it returns an error describing why tx is invalid.
func txIsWellFormed(tx *bc.Tx) error {
	if len(tx.Inputs) == 0 {
		return errors.WithDetail(ErrBadTx, "inputs are missing")
	}

	// Check for duplicate inputs
	uniqueFilter := map[bc.Outpoint]bool{}
	for _, txin := range tx.Inputs {
		if txin.IsIssuance() {
			continue
		}
		if uniqueFilter[txin.Previous] {
			return errors.WithDetailf(ErrBadTx, "duplicated input for %s", txin.Previous.String())
		}
		uniqueFilter[txin.Previous] = true
	}

	// Check that every output has a valid value.
	for _, txout := range tx.Outputs {
		// Zero-value outputs are allowed for re-publishing
		// asset definition using issuance transactions.
		// Non-issuance transactions cannot have zero-value outputs.
		// If all inputs have zero value, tx therefore must have no outputs.
		// TODO: check that output asset id is an asset being issued
		if txout.Amount == 0 && !tx.HasIssuance() {
			return errors.WithDetailf(ErrBadTx, "non-issuance output value must be greater than 0")
		}
	}
	return nil
}

// validateTxBalance ensures that non-issuance transactions
// have the exact same input and output asset amounts.
func validateTxBalance(ctx context.Context, view state.ViewReader, tx *bc.Tx) error {
	parity := make(map[bc.AssetID]int64)
	issued := make(map[bc.AssetID]bool)
	for _, out := range tx.Outputs {
		parity[out.AssetID] -= int64(out.Amount)
	}
	for _, in := range tx.Inputs {
		if in.IsIssuance() {
			assetID, err := assetIDFromSigScript(in.SignatureScript)
			if err != nil {
				return err
			}
			issued[assetID] = true
			continue
		}
		unspent := view.Output(ctx, in.Previous)
		assetID := unspent.AssetID
		if assetID == (bc.AssetID{}) {
			assetID = bc.ComputeAssetID(unspent.Script, stubGenesisHash)
		}
		parity[assetID] += int64(unspent.Amount)
	}
	for asset, val := range parity {
		if val > 0 || (val < 0 && !issued[asset]) {
			return errors.WithDetailf(ErrBadTx, "amounts for asset %s are not balanced on inputs and outputs", asset)
		}
	}
	return nil
}

// ApplyTx updates the view with all the changes to the ledger
func ApplyTx(ctx context.Context, view state.View, tx *bc.Tx) error {
	for _, in := range tx.Inputs {
		if in.IsIssuance() {
			continue
		}
		o := view.Output(ctx, in.Previous)
		o.Spent = true
		view.SaveOutput(o)
	}

	for _, in := range tx.Inputs {
		// If metadata field is empty, no update of ADP takes place.
		// See https://github.com/chain-engineering/fedchain/blob/master/documentation/fedchain-specification.md#extract-asset-definition.
		if in.IsIssuance() && len(in.AssetDefinition) > 0 {
			assetID, err := assetIDFromSigScript(in.SignatureScript)
			if err != nil {
				return err
			}
			defHash := bc.HashAssetDefinition(in.AssetDefinition)
			view.SaveAssetDefinitionPointer(assetID, defHash)
		}
	}

	for i, out := range tx.Outputs {
		o := &state.Output{
			TxOutput: *out,
			Outpoint: bc.Outpoint{Hash: tx.Hash, Index: uint32(i)},
			Spent:    false,
		}
		view.SaveOutput(o)
	}

	return nil
}

func assetIDFromSigScript(script []byte) (bc.AssetID, error) {
	redeemScript, err := txscript.RedeemScriptFromP2SHSigScript(script)
	if err != nil {
		return bc.AssetID{}, errors.Wrap(err, "extracting redeem script from sigscript")
	}
	pkScript := txscript.RedeemToPkScript(redeemScript)
	return bc.ComputeAssetID(pkScript, [32]byte{}), nil // TODO(tessr): get genesis hash
}
<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package lib

import (
	"encoding/json"
_	"fmt"
	"log"
	"net/http"
	"strconv"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/venicegeo/pz-gocommon"
	"github.com/venicegeo/pz-gocommon/elasticsearch"
)

type LockedAdminStats struct {
	sync.Mutex
	LoggerAdminStats
}

var stats LockedAdminStats

type LogData struct {
	sync.Mutex
	esIndex elasticsearch.IIndex
	id      int
}

var logData LogData

var schema = "LogData"

func initServer(sys *piazza.SystemConfig, esIndex elasticsearch.IIndex) {
	var err error

	stats.StartTime = time.Now()

	/***
	err = esIndex.Delete()
	if err != nil {
		log.Fatal(err)
	}
	if esIndex.IndexExists() {
		log.Fatal("index still exists")
	}
	err = esIndex.Create()
	if err != nil {
		log.Fatal(err)
	}
	***/

	if !esIndex.IndexExists() {
		err = esIndex.Create()
		if err != nil {
			log.Fatal(err)
		}

		mapping :=
			`{
		    "LogData":{
			    "properties":{
				    "service":{
					    "type": "string",
                        "store": true
    			    },
				    "address":{
					    "type": "string",
                        "store": true
    			    },
				    "stamp":{
					    "type": "long",
                        "store": true
    			    },
				    "severity":{
					    "type": "string",
                        "store": true
    			    },
				    "message":{
					    "type": "string",
                        "store": true
    			    }
	    	    }
	        }
        }`

		err = esIndex.SetMapping(schema, piazza.JsonString(mapping))
		if err != nil {
			log.Fatal(err)
		}
	}

	logData.esIndex = esIndex
}

func handleGetRoot(c *gin.Context) {
	//log.Print("got health-check request")
	c.String(http.StatusOK, "Hi. I'm pz-logger.")
}

func handlePostMessages(c *gin.Context) {
	var mssg Message
	err := c.BindJSON(&mssg)
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}

	err = mssg.Validate()
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}

	log.Printf("PZLOG: %s\n", mssg.String())

	logData.Lock()
	idStr := strconv.Itoa(logData.id)
	logData.id++
	logData.Unlock()
	indexResult, err := logData.esIndex.PostData(schema, idStr, mssg)
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}
	if !indexResult.Created {
		c.String(http.StatusBadRequest, "POST of log data failed")
		return
	}

	err = logData.esIndex.Flush()
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}

	stats.LoggerAdminStats.NumMessages++

	c.JSON(http.StatusOK, nil)
}

func handleGetAdminStats(c *gin.Context) {
	logData.Lock()
	t := stats.LoggerAdminStats
	logData.Unlock()
	c.JSON(http.StatusOK, t)
}

func handleGetMessages(c *gin.Context) {
	var err error

	format := elasticsearch.GetFormatParams(c, 10, 0, "stamp", elasticsearch.SortDescending)
	filterParams := parseFilterParams(c)

	//log.Printf("size %d, from %d, key %s, format %v",
	//	format.Size, format.From, format.Key, format.Order)

	log.Printf("filterParams: %v\n", filterParams)

	var searchResult *elasticsearch.SearchResult

	if len(filterParams) == 0 {
		searchResult, err = logData.esIndex.FilterByMatchAll(schema, format)
	} else  {
		var jsonString = createQueryDslAsString(format, filterParams)
		searchResult, err = logData.esIndex.SearchByJSON(schema, jsonString)
	}

	if err != nil {
		c.String(http.StatusBadRequest, "query failed: %s", err)
		return
	}

	// TODO: unsafe truncation
	count := int(searchResult.TotalHits())
	lines := make([]Message, count)

	i := 0
	for _, hit := range *searchResult.GetHits() {
		if hit == nil {
			log.Printf("null source hit")
			continue
		}
		src := *hit.Source
		//log.Printf("source hit: %s", string(src))

		tmp := &Message{}
		err = json.Unmarshal(src, tmp)
		if err != nil {
			log.Printf("UNABLE TO PARSE: %s", string(*hit.Source))
			c.String(http.StatusBadRequest, "query unmarshal failed: %s", err)
			return
		}
		err = tmp.Validate()
		if err != nil {
			log.Printf("UNABLE TO VALIDATE: %s", string(*hit.Source))
			//c.String(http.StatusBadRequest, "query unmarshal failed to validate: %s", err)
			//return
			continue
		}
		lines[i] = *tmp
		i++
	}

	c.JSON(http.StatusOK, lines)
}

func CreateHandlers(sys *piazza.SystemConfig, esi elasticsearch.IIndex) http.Handler {
	initServer(sys, esi)

	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	//router.Use(gin.Logger())
	//router.Use(gin.Recovery())

	router.GET("/", func(c *gin.Context) { handleGetRoot(c) })

	router.POST("/v1/messages", func(c *gin.Context) { handlePostMessages(c) })
	router.GET("/v1/messages", func(c *gin.Context) { handleGetMessages(c) })

	router.GET("/v1/admin/stats", func(c *gin.Context) { handleGetAdminStats(c) })

	return router
}

func parseFilterParams(c *gin.Context) map[string]interface{} {

	var filterParams = map[string]interface{}{}

	before, beforeExists := c.GetQuery("before")

	if beforeExists && before != "" {
		num, err := strconv.Atoi(before)
		if err == nil {
			filterParams["before"] =  num
		}
	}

	after, afterExists := c.GetQuery("after")

	if afterExists && after != "" {
		num, err := strconv.Atoi(after)
		if err == nil {
			filterParams["after"] =  num
		}
	}

	service, serviceExists := c.GetQuery("service")

	if serviceExists && service != "" {
		filterParams["service"] = service
	}

	contains, containsExists := c.GetQuery("contains")

	if containsExists && contains != "" {
		filterParams["contains"] = contains
	}

	return filterParams
}

func createQueryDslAsString(
    format elasticsearch.QueryFormat,
    params map[string]interface{},
) string {
    // fmt.Printf("%d\n", len(params))

    must := []map[string]interface{}{}

    if params["service"] != nil {
        must = append(must, map[string]interface{} {
            "match": map[string]interface{} {
                "service": params["service"],
            },
        })
    }

    if params["contains"] != nil {
        must = append(must, map[string]interface{} {
            "multi_match": map[string]interface{} {
                "query": params["contains"],
                "fields": []string {"address", "message", "service", "serverity"},
            },
        })
    }

    if params["after"] != nil || params["before"] != nil {
        rangeParams := map[string]int {}

        if params["after"] != nil {
            rangeParams["gte"] = params["after"].(int)
        }

        if params["before"] != nil {
            rangeParams["lte"] = params["before"].(int)
        }

        must = append(must, map[string]interface{} {
            "range": map[string]interface{} {
                "stamp": rangeParams,
            },
        })
    }

    dsl := map[string]interface{} {
        "query": map[string]interface{} {
            "filtered": map[string]interface{} {
                "query": map[string]interface{} {
                    "bool": map[string]interface{} {
                        "must": must,
                    },
                },
            },
        },
        "size": format.Size,
        "from": format.From,
    }

	var sortOrder string

	if format.Order {
		sortOrder = "desc"
	} else {
		sortOrder = "asc"
	}

	dsl["sort"] = map[string]string {
		format.Key: sortOrder,
	}

    output, _ := json.Marshal(dsl)
    return string(output)
}    <commit_msg>Added /v2 endpoints for 18F support.<commit_after>// Copyright 2016, RadiantBlue Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package lib

import (
	"encoding/json"
_	"fmt"
	"log"
	"net/http"
	"strconv"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/venicegeo/pz-gocommon"
	"github.com/venicegeo/pz-gocommon/elasticsearch"
)

type LockedAdminStats struct {
	sync.Mutex
	LoggerAdminStats
}

var stats LockedAdminStats

type LogData struct {
	sync.Mutex
	esIndex elasticsearch.IIndex
	id      int
}

var logData LogData

var schema = "LogData"

func initServer(sys *piazza.SystemConfig, esIndex elasticsearch.IIndex) {
	var err error

	stats.StartTime = time.Now()

	/***
	err = esIndex.Delete()
	if err != nil {
		log.Fatal(err)
	}
	if esIndex.IndexExists() {
		log.Fatal("index still exists")
	}
	err = esIndex.Create()
	if err != nil {
		log.Fatal(err)
	}
	***/

	if !esIndex.IndexExists() {
		err = esIndex.Create()
		if err != nil {
			log.Fatal(err)
		}

		mapping :=
			`{
		    "LogData":{
			    "properties":{
				    "service":{
					    "type": "string",
                        "store": true
    			    },
				    "address":{
					    "type": "string",
                        "store": true
    			    },
				    "stamp":{
					    "type": "long",
                        "store": true
    			    },
				    "severity":{
					    "type": "string",
                        "store": true
    			    },
				    "message":{
					    "type": "string",
                        "store": true
    			    }
	    	    }
	        }
        }`

		err = esIndex.SetMapping(schema, piazza.JsonString(mapping))
		if err != nil {
			log.Fatal(err)
		}
	}

	logData.esIndex = esIndex
}

func handleGetRoot(c *gin.Context) {
	//log.Print("got health-check request")
	c.String(http.StatusOK, "Hi. I'm pz-logger.")
}

func handlePostMessages(c *gin.Context) {
	var mssg Message
	err := c.BindJSON(&mssg)
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}

	err = mssg.Validate()
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}

	log.Printf("PZLOG: %s\n", mssg.String())

	logData.Lock()
	idStr := strconv.Itoa(logData.id)
	logData.id++
	logData.Unlock()
	indexResult, err := logData.esIndex.PostData(schema, idStr, mssg)
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}
	if !indexResult.Created {
		c.String(http.StatusBadRequest, "POST of log data failed")
		return
	}

	err = logData.esIndex.Flush()
	if err != nil {
		c.String(http.StatusBadRequest, "%v", err)
		return
	}

	stats.LoggerAdminStats.NumMessages++

	c.JSON(http.StatusOK, nil)
}

func handleGetAdminStats(c *gin.Context) {
	logData.Lock()
	t := stats.LoggerAdminStats
	logData.Unlock()
	c.JSON(http.StatusOK, t)
}

func handleGetMessages(c *gin.Context) {
	var err error

	format := elasticsearch.GetFormatParams(c, 10, 0, "stamp", elasticsearch.SortDescending)
	filterParams := parseFilterParams(c)

	//log.Printf("size %d, from %d, key %s, format %v",
	//	format.Size, format.From, format.Key, format.Order)

	log.Printf("filterParams: %v\n", filterParams)

	var searchResult *elasticsearch.SearchResult

	if len(filterParams) == 0 {
		searchResult, err = logData.esIndex.FilterByMatchAll(schema, format)
	} else  {
		var jsonString = createQueryDslAsString(format, filterParams)
		searchResult, err = logData.esIndex.SearchByJSON(schema, jsonString)
	}

	if err != nil {
		c.String(http.StatusBadRequest, "query failed: %s", err)
		return
	}

	// TODO: unsafe truncation
	count := int(searchResult.TotalHits())
	lines := make([]Message, count)

	i := 0
	for _, hit := range *searchResult.GetHits() {
		if hit == nil {
			log.Printf("null source hit")
			continue
		}
		src := *hit.Source
		//log.Printf("source hit: %s", string(src))

		tmp := &Message{}
		err = json.Unmarshal(src, tmp)
		if err != nil {
			log.Printf("UNABLE TO PARSE: %s", string(*hit.Source))
			c.String(http.StatusBadRequest, "query unmarshal failed: %s", err)
			return
		}
		err = tmp.Validate()
		if err != nil {
			log.Printf("UNABLE TO VALIDATE: %s", string(*hit.Source))
			//c.String(http.StatusBadRequest, "query unmarshal failed to validate: %s", err)
			//return
			continue
		}
		lines[i] = *tmp
		i++
	}

	c.JSON(http.StatusOK, lines)
}

func handleGetMessagesV2(c *gin.Context) {
	var err error

	format := elasticsearch.GetFormatParamsV2(c, 10, 0, "stamp", elasticsearch.SortDescending)
	filterParams := parseFilterParams(c)

	//log.Printf("size %d, from %d, key %s, format %v",
	//	format.Size, format.From, format.Key, format.Order)

	log.Printf("filterParams: %v\n", filterParams)

	var searchResult *elasticsearch.SearchResult

	if len(filterParams) == 0 {
		searchResult, err = logData.esIndex.FilterByMatchAll(schema, format)
	} else  {
		var jsonString = createQueryDslAsString(format, filterParams)
		searchResult, err = logData.esIndex.SearchByJSON(schema, jsonString)
	}

	if err != nil {
		c.String(http.StatusBadRequest, "query failed: %s", err)
		return
	}

	// TODO: unsafe truncation
	count := searchResult.TotalHits()
	matched := searchResult.NumberMatched()
	lines := make([]Message, count)

	i := 0
	for _, hit := range *searchResult.GetHits() {
		if hit == nil {
			log.Printf("null source hit")
			continue
		}
		src := *hit.Source
		//log.Printf("source hit: %s", string(src))

		tmp := &Message{}
		err = json.Unmarshal(src, tmp)
		if err != nil {
			log.Printf("UNABLE TO PARSE: %s", string(*hit.Source))
			c.String(http.StatusBadRequest, "query unmarshal failed: %s", err)
			return
		}
		err = tmp.Validate()
		if err != nil {
			log.Printf("UNABLE TO VALIDATE: %s", string(*hit.Source))
			//c.String(http.StatusBadRequest, "query unmarshal failed to validate: %s", err)
			//return
			continue
		}
		lines[i] = *tmp
		i++
	}

	bar := make([]interface{}, len(lines))

	for i, e := range lines {
		bar[i] = e
	}

	var order string

	if format.Order {
		order = "desc"
	} else {
		order = "asc"
	}

	foo := &piazza.Common18FListResponse{
		Data: bar,
		Pagination: piazza.Pagination {
			Page: format.From,
			PerPage: format.Size,
			Count: matched,
			SortBy: format.Key,
			Order: order,
		},
	}

	// c.JSON(http.StatusOK, lines)
	c.JSON(http.StatusOK, foo)
}

func CreateHandlers(sys *piazza.SystemConfig, esi elasticsearch.IIndex) http.Handler {
	initServer(sys, esi)

	gin.SetMode(gin.ReleaseMode)
	router := gin.New()
	//router.Use(gin.Logger())
	//router.Use(gin.Recovery())

	router.GET("/", func(c *gin.Context) { handleGetRoot(c) })

	router.POST("/v1/messages", func(c *gin.Context) { handlePostMessages(c) })
	router.GET("/v1/messages", func(c *gin.Context) { handleGetMessages(c) })

	router.POST("/v2/message", func(c *gin.Context) { handlePostMessages(c) })
	router.GET("/v2/message", func(c *gin.Context) { handleGetMessagesV2(c) })

	router.GET("/v1/admin/stats", func(c *gin.Context) { handleGetAdminStats(c) })

	return router
}

func parseFilterParams(c *gin.Context) map[string]interface{} {

	var filterParams = map[string]interface{}{}

	before, beforeExists := c.GetQuery("before")

	if beforeExists && before != "" {
		num, err := strconv.Atoi(before)
		if err == nil {
			filterParams["before"] =  num
		}
	}

	after, afterExists := c.GetQuery("after")

	if afterExists && after != "" {
		num, err := strconv.Atoi(after)
		if err == nil {
			filterParams["after"] =  num
		}
	}

	service, serviceExists := c.GetQuery("service")

	if serviceExists && service != "" {
		filterParams["service"] = service
	}

	contains, containsExists := c.GetQuery("contains")

	if containsExists && contains != "" {
		filterParams["contains"] = contains
	}

	return filterParams
}

func createQueryDslAsString(
    format elasticsearch.QueryFormat,
    params map[string]interface{},
) string {
    // fmt.Printf("%d\n", len(params))

    must := []map[string]interface{}{}

    if params["service"] != nil {
        must = append(must, map[string]interface{} {
            "match": map[string]interface{} {
                "service": params["service"],
            },
        })
    }

    if params["contains"] != nil {
        must = append(must, map[string]interface{} {
            "multi_match": map[string]interface{} {
                "query": params["contains"],
                "fields": []string {"address", "message", "service", "serverity"},
            },
        })
    }

    if params["after"] != nil || params["before"] != nil {
        rangeParams := map[string]int {}

        if params["after"] != nil {
            rangeParams["gte"] = params["after"].(int)
        }

        if params["before"] != nil {
            rangeParams["lte"] = params["before"].(int)
        }

        must = append(must, map[string]interface{} {
            "range": map[string]interface{} {
                "stamp": rangeParams,
            },
        })
    }

    dsl := map[string]interface{} {
        "query": map[string]interface{} {
            "filtered": map[string]interface{} {
                "query": map[string]interface{} {
                    "bool": map[string]interface{} {
                        "must": must,
                    },
                },
            },
        },
        "size": format.Size,
        "from": format.From,
    }

	var sortOrder string

	if format.Order {
		sortOrder = "desc"
	} else {
		sortOrder = "asc"
	}

	dsl["sort"] = map[string]string {
		format.Key: sortOrder,
	}

    output, _ := json.Marshal(dsl)
    return string(output)
}    <|endoftext|>


<commit_before>// Copyright (c) 2015 Serge Gebhardt. All rights reserved.
//
// Use of this source code is governed by the ISC
// license that can be found in the LICENSE file.

package command

import (
	"fmt"
)

type StorageCommand struct {
	Meta
}

func (c *StorageCommand) Help() string {
	return ""
}

func (c *StorageCommand) Run(_ []string) int {
	apiClient, err := c.NewAcdClient()
	if err != nil {
		c.Ui.Output(err.Error())
		return 1
	}

	accountUsage, _, err := apiClient.Account.GetUsage()
	if err != nil {
		fmt.Printf("\nerror: %v\n\n", err)
		return 3
	}

	fmt.Printf("Last Calculated: %v\n\n", *accountUsage.LastCalculated)
	fmt.Printf("Other:\n Total: %v bytes (%v files)\n Billable: %v bytes (%v files)\n\n",
		*accountUsage.Other.Total.Bytes, *accountUsage.Other.Total.Count,
		*accountUsage.Other.Billable.Bytes, *accountUsage.Other.Billable.Count)
	fmt.Printf("Doc:\n Total: %v bytes (%v files)\n Billable: %v bytes (%v files)\n\n",
		*accountUsage.Doc.Total.Bytes, *accountUsage.Doc.Total.Count,
		*accountUsage.Doc.Billable.Bytes, *accountUsage.Doc.Billable.Count)
	fmt.Printf("Photo:\n Total: %v bytes (%v files)\n Billable: %v bytes (%v files)\n\n",
		*accountUsage.Photo.Total.Bytes, *accountUsage.Photo.Total.Count,
		*accountUsage.Photo.Billable.Bytes, *accountUsage.Photo.Billable.Count)
	fmt.Printf("Video:\n Total: %v bytes (%v files)\n Billable: %v bytes (%v files)\n\n",
		*accountUsage.Video.Total.Bytes, *accountUsage.Video.Total.Count,
		*accountUsage.Video.Billable.Bytes, *accountUsage.Video.Billable.Count)

	return 0
}

func (c *StorageCommand) Synopsis() string {
	return "Prints information on storage usage and quota"
}
<commit_msg>Tabular human-readable storage info<commit_after>// Copyright (c) 2015 Serge Gebhardt. All rights reserved.
//
// Use of this source code is governed by the ISC
// license that can be found in the LICENSE file.

package command

import (
	"fmt"

	"github.com/dustin/go-humanize"
	"github.com/sgeb/go-acd/acd"
)

type StorageCommand struct {
	Meta
}

func (c *StorageCommand) Help() string {
	return ""
}

func (c *StorageCommand) Run(_ []string) int {
	apiClient, err := c.NewAcdClient()
	if err != nil {
		c.Ui.Output(err.Error())
		return 1
	}

	accountUsage, _, err := apiClient.Account.GetUsage()
	if err != nil {
		fmt.Printf("\nerror: %v\n\n", err)
		return 3
	}

	fmt.Printf("Last Calculated: %v (%v)\n",
		humanize.Time(*accountUsage.LastCalculated), *accountUsage.LastCalculated)
	fmt.Printf("%v\n", categoryUsageString("Photos", accountUsage.Photo))
	fmt.Printf("%v\n", categoryUsageString("Video", accountUsage.Video))
	fmt.Printf("%v\n", categoryUsageString("Doc", accountUsage.Doc))
	fmt.Printf("%v\n", categoryUsageString("Other", accountUsage.Other))

	return 0
}

func (c *StorageCommand) Synopsis() string {
	return "Prints information on storage usage and quota"
}

func categoryUsageString(category string, c *acd.CategoryUsage) string {
	return fmt.Sprintf(" %8v %8v %9v  %8v %9v",
		category,
		humanize.IBytes(*c.Total.Bytes), humanize.Comma(int64(*c.Total.Count)),
		humanize.IBytes(*c.Billable.Bytes), humanize.Comma(int64(*c.Billable.Count)))
}
<|endoftext|>