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

package main

import (
	"fmt"
	"strings"

	"github.com/danryan/hal"
)

var whoisHandler = hear(`who\s?is ([A-Za-z0-9\-_\{\}\[\]\\]+)`, func(res *hal.Response) error {
	name := res.Match[1]
	key := strings.ToUpper(name)
	val, err := res.Robot.Store.Get(key)
	if err != nil {
		res.Send(fmt.Sprintf("%s is no one to me\n", name))
		return err
	}
	return res.Send(fmt.Sprintf("%s is %s", name, string(val)))
})

var isHandler = hear(`([^who].+) is (.+)`, func(res *hal.Response) error {
	name := res.Match[1]
	key := strings.ToUpper(name)
	role := res.Match[2]

	storedRoles, err := res.Robot.Store.Get(key)
	roleToStore := role
	if len(storedRoles) > 0 {
		roleToStore = roleToStore + ", " + string(storedRoles)
	}

	err = res.Robot.Store.Set(key, []byte(roleToStore))
	if err != nil {
		res.Send(fmt.Sprint("There's something wrong"))
		return err
	}
	return res.Send(fmt.Sprintf("Got it. %s is %s\n", name, role))
})

var whoamHandler = hear(`who am (?i)I`, func(res *hal.Response) error {
	name := res.UserName()
	key := strings.ToUpper(name)
	val, err := res.Robot.Store.Get(key)
	if err != nil {
		return res.Send(fmt.Sprintf("%s?  I have no memory of who you are.", name))
	}

	return res.Send(fmt.Sprintf("%s, you are %s", name, string(val)))
})
<commit_msg>Remove unneeded fmt.Sprint call<commit_after>// Copyright 2014 Chadev. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"strings"

	"github.com/danryan/hal"
)

var whoisHandler = hear(`who\s?is ([A-Za-z0-9\-_\{\}\[\]\\]+)`, func(res *hal.Response) error {
	name := res.Match[1]
	key := strings.ToUpper(name)
	val, err := res.Robot.Store.Get(key)
	if err != nil {
		res.Send(fmt.Sprintf("%s is no one to me\n", name))
		return err
	}
	return res.Send(fmt.Sprintf("%s is %s", name, string(val)))
})

var isHandler = hear(`([^who].+) is (.+)`, func(res *hal.Response) error {
	name := res.Match[1]
	key := strings.ToUpper(name)
	role := res.Match[2]

	storedRoles, err := res.Robot.Store.Get(key)
	roleToStore := role
	if len(storedRoles) > 0 {
		roleToStore = roleToStore + ", " + string(storedRoles)
	}

	err = res.Robot.Store.Set(key, []byte(roleToStore))
	if err != nil {
		res.Send("There's something wrong")
		return err
	}
	return res.Send(fmt.Sprintf("Got it. %s is %s\n", name, role))
})

var whoamHandler = hear(`who am (?i)I`, func(res *hal.Response) error {
	name := res.UserName()
	key := strings.ToUpper(name)
	val, err := res.Robot.Store.Get(key)
	if err != nil {
		return res.Send(fmt.Sprintf("%s?  I have no memory of who you are.", name))
	}

	return res.Send(fmt.Sprintf("%s, you are %s", name, string(val)))
})
<|endoftext|>


<commit_before>package errors

import (
	"crypto/x509"
	"encoding/json"
	"errors"
	"testing"
)

func TestNew(t *testing.T) {
	err := New(CertificateError, Unknown)
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(CertificateError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != "Unknown certificate error" {
		t.Fatal("Error message construction failed.")
	}

	code := New(OCSPError, ReadFailed).ErrorCode
	if code != 8001 {
		t.Fatal("Improper error code")
	}

	code = New(OCSPError, IssuerMismatch).ErrorCode
	if code != 8100 {
		t.Fatal("Improper error code")
	}

	code = New(OCSPError, InvalidStatus).ErrorCode
	if code != 8200 {
		t.Fatal("Improper error code")
	}

	code = New(CertificateError, Unknown).ErrorCode
	if code != 1000 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, ReadFailed).ErrorCode
	if code != 1001 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, DecodeFailed).ErrorCode
	if code != 1002 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, ParseFailed).ErrorCode
	if code != 1003 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, SelfSigned).ErrorCode
	if code != 1100 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, VerifyFailed).ErrorCode
	if code != 1200 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, BadRequest).ErrorCode
	if code != 1300 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, MissingSerial).ErrorCode
	if code != 1400 {
		t.Fatal("Improper error code")
	}

	code = New(PrivateKeyError, Unknown).ErrorCode
	if code != 2000 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, ReadFailed).ErrorCode
	if code != 2001 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, DecodeFailed).ErrorCode
	if code != 2002 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, ParseFailed).ErrorCode
	if code != 2003 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, Encrypted).ErrorCode
	if code != 2100 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, NotRSAOrECC).ErrorCode
	if code != 2200 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, KeyMismatch).ErrorCode
	if code != 2300 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, GenerationFailed).ErrorCode
	if code != 2400 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, Unavailable).ErrorCode
	if code != 2500 {
		t.Fatal("Improper error code")
	}

	code = New(IntermediatesError, Unknown).ErrorCode
	if code != 3000 {
		t.Fatal("Improper error code")
	}
	code = New(IntermediatesError, ReadFailed).ErrorCode
	if code != 3001 {
		t.Fatal("Improper error code")
	}
	code = New(IntermediatesError, DecodeFailed).ErrorCode
	if code != 3002 {
		t.Fatal("Improper error code")
	}
	code = New(IntermediatesError, ParseFailed).ErrorCode
	if code != 3003 {
		t.Fatal("Improper error code")
	}

	code = New(RootError, Unknown).ErrorCode
	if code != 4000 {
		t.Fatal("Improper error code")
	}
	code = New(RootError, ReadFailed).ErrorCode
	if code != 4001 {
		t.Fatal("Improper error code")
	}
	code = New(RootError, DecodeFailed).ErrorCode
	if code != 4002 {
		t.Fatal("Improper error code")
	}
	code = New(RootError, ParseFailed).ErrorCode
	if code != 4003 {
		t.Fatal("Improper error code")
	}

	code = New(PolicyError, Unknown).ErrorCode
	if code != 5000 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, NoKeyUsages).ErrorCode
	if code != 5100 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, InvalidPolicy).ErrorCode
	if code != 5200 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, InvalidRequest).ErrorCode
	if code != 5300 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, UnknownProfile).ErrorCode
	if code != 5400 {
		t.Fatal("Improper error code")
	}

	code = New(DialError, Unknown).ErrorCode
	if code != 6000 {
		t.Fatal("Improper error code")
	}

	code = New(APIClientError, AuthenticationFailure).ErrorCode
	if code != 7100 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, JSONError).ErrorCode
	if code != 7200 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, ClientHTTPError).ErrorCode
	if code != 7400 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, IOError).ErrorCode
	if code != 7300 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, ServerRequestFailed).ErrorCode
	if code != 7500 {
		t.Fatal("Improper error code")
	}

	code = New(CSRError, Unknown).ErrorCode
	if code != 9000 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, ReadFailed).ErrorCode
	if code != 9001 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, DecodeFailed).ErrorCode
	if code != 9002 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, ParseFailed).ErrorCode
	if code != 9003 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, KeyMismatch).ErrorCode
	if code != 9300 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, BadRequest).ErrorCode
	if code != 9300 {
		t.Fatal("Improper error code")
	}

	code = New(CTError, Unknown).ErrorCode
	if code != 10000 {
		t.Fatal("Improper error code")
	}
	code = New(CTError, PrecertSubmissionFailed).ErrorCode
	if code != 10100 {
		t.Fatal("Improper error code")
	}
}

func TestWrap(t *testing.T) {
	msg := "Arbitrary error message"
	err := Wrap(CertificateError, Unknown, errors.New(msg))
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(CertificateError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != msg {
		t.Fatal("Error message construction failed.")
	}

	err = Wrap(CertificateError, VerifyFailed, x509.CertificateInvalidError{Reason: x509.Expired})
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(CertificateError)+int(VerifyFailed)+certificateInvalid+int(x509.Expired) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != "x509: certificate has expired or is not yet valid" {
		t.Fatal("Error message construction failed.")
	}

	err = Wrap(CertificateError, VerifyFailed, x509.UnknownAuthorityError{})
	if err == nil {
		t.Fatal("Error creation failed.")
	}

	err = Wrap(RootError, Unknown, errors.New(msg))
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(RootError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != msg {
		t.Fatal("Error message construction failed.")
	}
}

func TestMarshal(t *testing.T) {
	msg := "Arbitrary error message"
	err := Wrap(CertificateError, Unknown, errors.New(msg))
	bytes, _ := json.Marshal(err)
	var received Error
	json.Unmarshal(bytes, &received)
	if received.ErrorCode != int(CertificateError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if received.Message != msg {
		t.Fatal("Error message construction failed.")
	}
}

func TestErrorString(t *testing.T) {
	msg := "Arbitrary error message"
	err := Wrap(CertificateError, Unknown, errors.New(msg))
	str := err.Error()
	if str != `{"code":1000,"message":"`+msg+`"}` {
		t.Fatal("Incorrect Error():", str)
	}
}

func TestHTTP(t *testing.T) {
	err := NewMethodNotAllowed("GET")
	if err == nil {
		t.Fatal("New Mathod Check failed")
	}

	err = NewBadRequest(errors.New("Bad Request"))
	if err == nil {
		t.Fatal("New Bad Request Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request error code construction failed")
	}

	err = NewBadRequestString("Bad Request String")
	if err == nil {
		t.Fatal("New Bad Request String Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request String error code construction failed")
	}

	err = NewBadRequestMissingParameter("Request Missing Parameter")
	if err == nil {
		t.Fatal("New Bad Request Missing Parameter Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request Missing Parameter error code construction failed")
	}

	err = NewBadRequestUnwantedParameter("Unwanted Parameter Present In Request")
	if err == nil {
		t.Fatal("New Bad Request Unwanted Parameter Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request Unwanted Parameter error code construction failed")
	}

}

func TestHTTPErrorString(t *testing.T) {
	method := "GET"
	err := NewMethodNotAllowed(method)
	str := err.Error()
	if str != `Method is not allowed:"`+method+`"` {
		t.Fatal("Incorrect Error():", str)
	}
}
<commit_msg>Correctly check for different golang versions #1076 (#1083)<commit_after>package errors

import (
	"crypto/x509"
	"encoding/json"
	"errors"
	"testing"
)

func TestNew(t *testing.T) {
	err := New(CertificateError, Unknown)
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(CertificateError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != "Unknown certificate error" {
		t.Fatal("Error message construction failed.")
	}

	code := New(OCSPError, ReadFailed).ErrorCode
	if code != 8001 {
		t.Fatal("Improper error code")
	}

	code = New(OCSPError, IssuerMismatch).ErrorCode
	if code != 8100 {
		t.Fatal("Improper error code")
	}

	code = New(OCSPError, InvalidStatus).ErrorCode
	if code != 8200 {
		t.Fatal("Improper error code")
	}

	code = New(CertificateError, Unknown).ErrorCode
	if code != 1000 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, ReadFailed).ErrorCode
	if code != 1001 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, DecodeFailed).ErrorCode
	if code != 1002 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, ParseFailed).ErrorCode
	if code != 1003 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, SelfSigned).ErrorCode
	if code != 1100 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, VerifyFailed).ErrorCode
	if code != 1200 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, BadRequest).ErrorCode
	if code != 1300 {
		t.Fatal("Improper error code")
	}
	code = New(CertificateError, MissingSerial).ErrorCode
	if code != 1400 {
		t.Fatal("Improper error code")
	}

	code = New(PrivateKeyError, Unknown).ErrorCode
	if code != 2000 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, ReadFailed).ErrorCode
	if code != 2001 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, DecodeFailed).ErrorCode
	if code != 2002 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, ParseFailed).ErrorCode
	if code != 2003 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, Encrypted).ErrorCode
	if code != 2100 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, NotRSAOrECC).ErrorCode
	if code != 2200 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, KeyMismatch).ErrorCode
	if code != 2300 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, GenerationFailed).ErrorCode
	if code != 2400 {
		t.Fatal("Improper error code")
	}
	code = New(PrivateKeyError, Unavailable).ErrorCode
	if code != 2500 {
		t.Fatal("Improper error code")
	}

	code = New(IntermediatesError, Unknown).ErrorCode
	if code != 3000 {
		t.Fatal("Improper error code")
	}
	code = New(IntermediatesError, ReadFailed).ErrorCode
	if code != 3001 {
		t.Fatal("Improper error code")
	}
	code = New(IntermediatesError, DecodeFailed).ErrorCode
	if code != 3002 {
		t.Fatal("Improper error code")
	}
	code = New(IntermediatesError, ParseFailed).ErrorCode
	if code != 3003 {
		t.Fatal("Improper error code")
	}

	code = New(RootError, Unknown).ErrorCode
	if code != 4000 {
		t.Fatal("Improper error code")
	}
	code = New(RootError, ReadFailed).ErrorCode
	if code != 4001 {
		t.Fatal("Improper error code")
	}
	code = New(RootError, DecodeFailed).ErrorCode
	if code != 4002 {
		t.Fatal("Improper error code")
	}
	code = New(RootError, ParseFailed).ErrorCode
	if code != 4003 {
		t.Fatal("Improper error code")
	}

	code = New(PolicyError, Unknown).ErrorCode
	if code != 5000 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, NoKeyUsages).ErrorCode
	if code != 5100 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, InvalidPolicy).ErrorCode
	if code != 5200 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, InvalidRequest).ErrorCode
	if code != 5300 {
		t.Fatal("Improper error code")
	}
	code = New(PolicyError, UnknownProfile).ErrorCode
	if code != 5400 {
		t.Fatal("Improper error code")
	}

	code = New(DialError, Unknown).ErrorCode
	if code != 6000 {
		t.Fatal("Improper error code")
	}

	code = New(APIClientError, AuthenticationFailure).ErrorCode
	if code != 7100 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, JSONError).ErrorCode
	if code != 7200 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, ClientHTTPError).ErrorCode
	if code != 7400 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, IOError).ErrorCode
	if code != 7300 {
		t.Fatal("Improper error code")
	}
	code = New(APIClientError, ServerRequestFailed).ErrorCode
	if code != 7500 {
		t.Fatal("Improper error code")
	}

	code = New(CSRError, Unknown).ErrorCode
	if code != 9000 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, ReadFailed).ErrorCode
	if code != 9001 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, DecodeFailed).ErrorCode
	if code != 9002 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, ParseFailed).ErrorCode
	if code != 9003 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, KeyMismatch).ErrorCode
	if code != 9300 {
		t.Fatal("Improper error code")
	}
	code = New(CSRError, BadRequest).ErrorCode
	if code != 9300 {
		t.Fatal("Improper error code")
	}

	code = New(CTError, Unknown).ErrorCode
	if code != 10000 {
		t.Fatal("Improper error code")
	}
	code = New(CTError, PrecertSubmissionFailed).ErrorCode
	if code != 10100 {
		t.Fatal("Improper error code")
	}
}

func TestWrap(t *testing.T) {
	msg := "Arbitrary error message"
	err := Wrap(CertificateError, Unknown, errors.New(msg))
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(CertificateError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != msg {
		t.Fatal("Error message construction failed.")
	}

	err = Wrap(CertificateError, VerifyFailed, x509.CertificateInvalidError{Reason: x509.Expired})
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(CertificateError)+int(VerifyFailed)+certificateInvalid+int(x509.Expired) {
		t.Fatal("Error code construction failed.")
	}
	errorString := "x509: certificate has expired or is not yet valid:"
	if err.Message[:49] != errorString[:49] {
		t.Fatal("Error message construction failed.")
	}

	err = Wrap(CertificateError, VerifyFailed, x509.UnknownAuthorityError{})
	if err == nil {
		t.Fatal("Error creation failed.")
	}

	err = Wrap(RootError, Unknown, errors.New(msg))
	if err == nil {
		t.Fatal("Error creation failed.")
	}
	if err.ErrorCode != int(RootError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if err.Message != msg {
		t.Fatal("Error message construction failed.")
	}
}

func TestMarshal(t *testing.T) {
	msg := "Arbitrary error message"
	err := Wrap(CertificateError, Unknown, errors.New(msg))
	bytes, _ := json.Marshal(err)
	var received Error
	json.Unmarshal(bytes, &received)
	if received.ErrorCode != int(CertificateError)+int(Unknown) {
		t.Fatal("Error code construction failed.")
	}
	if received.Message != msg {
		t.Fatal("Error message construction failed.")
	}
}

func TestErrorString(t *testing.T) {
	msg := "Arbitrary error message"
	err := Wrap(CertificateError, Unknown, errors.New(msg))
	str := err.Error()
	if str != `{"code":1000,"message":"`+msg+`"}` {
		t.Fatal("Incorrect Error():", str)
	}
}

func TestHTTP(t *testing.T) {
	err := NewMethodNotAllowed("GET")
	if err == nil {
		t.Fatal("New Mathod Check failed")
	}

	err = NewBadRequest(errors.New("Bad Request"))
	if err == nil {
		t.Fatal("New Bad Request Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request error code construction failed")
	}

	err = NewBadRequestString("Bad Request String")
	if err == nil {
		t.Fatal("New Bad Request String Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request String error code construction failed")
	}

	err = NewBadRequestMissingParameter("Request Missing Parameter")
	if err == nil {
		t.Fatal("New Bad Request Missing Parameter Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request Missing Parameter error code construction failed")
	}

	err = NewBadRequestUnwantedParameter("Unwanted Parameter Present In Request")
	if err == nil {
		t.Fatal("New Bad Request Unwanted Parameter Check failed")
	}

	if err.StatusCode != 400 {
		t.Fatal("New Bad Request Unwanted Parameter error code construction failed")
	}

}

func TestHTTPErrorString(t *testing.T) {
	method := "GET"
	err := NewMethodNotAllowed(method)
	str := err.Error()
	if str != `Method is not allowed:"`+method+`"` {
		t.Fatal("Incorrect Error():", str)
	}
}
<|endoftext|>


<commit_before>package influx

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"github.com/influxdata/chronograf"
)

// AllDB returns all databases from within Influx
func (c *Client) AllDB(ctx context.Context) ([]chronograf.Database, error) {
	databases, err := c.showDatabases(ctx)
	if err != nil {
		return nil, err
	}

	return databases, nil
}

// CreateDB creates a database within Influx
func (c *Client) CreateDB(ctx context.Context, db *chronograf.Database) (*chronograf.Database, error) {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`CREATE DATABASE "%s"`, db.Name),
	})
	if err != nil {
		return nil, err
	}

	res := &chronograf.Database{Name: db.Name}

	return res, nil
}

// DropDB drops a database within Influx
func (c *Client) DropDB(ctx context.Context, database string) error {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`DROP DATABASE "%s"`, database),
		DB:      database,
	})
	if err != nil {
		return err
	}
	return nil
}

// AllRP returns all the retention policies for a specific database
func (c *Client) AllRP(ctx context.Context, database string) ([]chronograf.RetentionPolicy, error) {
	retentionPolicies, err := c.showRetentionPolicies(ctx, database)
	if err != nil {
		return nil, err
	}

	return retentionPolicies, nil
}

func (c *Client) getRP(ctx context.Context, db, name string) (chronograf.RetentionPolicy, error) {
	rps, err := c.AllRP(ctx, db)
	if err != nil {
		return chronograf.RetentionPolicy{}, err
	}

	for _, rp := range rps {
		if rp.Name == name {
			return rp, nil
		}
	}
	return chronograf.RetentionPolicy{}, fmt.Errorf("unknown retention policy")
}

// CreateRP creates a retention policy for a specific database
func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`CREATE RETENTION POLICY "%s" ON "%s" DURATION %s REPLICATION %d`, rp.Name, database, rp.Duration, rp.Replication),
		DB:      database,
	})
	if err != nil {
		return nil, err
	}

	res, err := c.getRP(ctx, database, rp.Name)
	if err != nil {
		return nil, err
	}

	return &res, nil
}

// UpdateRP updates a specific retention policy for a specific database
func (c *Client) UpdateRP(ctx context.Context, database string, name string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) {
	var buffer bytes.Buffer
	buffer.WriteString(fmt.Sprintf(`ALTER RETENTION POLICY "%s" ON "%s"`, name, database))
	if len(rp.Duration) > 0 {
		buffer.WriteString(" DURATION " + rp.Duration)
	}
	if rp.Replication > 0 {
		buffer.WriteString(" REPLICATION " + fmt.Sprint(rp.Replication))
	}
	if len(rp.ShardDuration) > 0 {
		buffer.WriteString(" SHARD DURATION " + rp.ShardDuration)
	}
	if rp.Default == true {
		buffer.WriteString(" DEFAULT")
	}

	_, err := c.Query(ctx, chronograf.Query{
		Command: buffer.String(),
		DB:      database,
		RP:      name,
	})
	if err != nil {
		return nil, err
	}

	res, err := c.getRP(ctx, database, rp.Name)
	if err != nil {
		return nil, err
	}

	return &res, nil
}

// DropRP removes a specific retention policy for a specific database
func (c *Client) DropRP(ctx context.Context, database string, rp string) error {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`DROP RETENTION POLICY "%s" ON "%s"`, rp, database),
		DB:      database,
		RP:      rp,
	})
	if err != nil {
		return err
	}
	return nil
}

func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) {
	res, err := c.Query(ctx, chronograf.Query{
		Command: `SHOW DATABASES`,
	})
	if err != nil {
		return nil, err
	}
	octets, err := res.MarshalJSON()
	if err != nil {
		return nil, err
	}

	results := showResults{}
	if err := json.Unmarshal(octets, &results); err != nil {
		return nil, err
	}

	return results.Databases(), nil
}

func (c *Client) showRetentionPolicies(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) {
	retentionPolicies, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`SHOW RETENTION POLICIES ON "%s"`, name),
		DB:      name,
	})

	if err != nil {
		return nil, err
	}
	octets, err := retentionPolicies.MarshalJSON()
	if err != nil {
		return nil, err
	}

	results := showResults{}
	if err := json.Unmarshal(octets, &results); err != nil {
		return nil, err
	}

	return results.RetentionPolicies(), nil
}
<commit_msg>Fix create retention policies InfluxQL<commit_after>package influx

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"

	"github.com/influxdata/chronograf"
)

// AllDB returns all databases from within Influx
func (c *Client) AllDB(ctx context.Context) ([]chronograf.Database, error) {
	databases, err := c.showDatabases(ctx)
	if err != nil {
		return nil, err
	}

	return databases, nil
}

// CreateDB creates a database within Influx
func (c *Client) CreateDB(ctx context.Context, db *chronograf.Database) (*chronograf.Database, error) {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`CREATE DATABASE "%s"`, db.Name),
	})
	if err != nil {
		return nil, err
	}

	res := &chronograf.Database{Name: db.Name}

	return res, nil
}

// DropDB drops a database within Influx
func (c *Client) DropDB(ctx context.Context, database string) error {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`DROP DATABASE "%s"`, database),
		DB:      database,
	})
	if err != nil {
		return err
	}
	return nil
}

// AllRP returns all the retention policies for a specific database
func (c *Client) AllRP(ctx context.Context, database string) ([]chronograf.RetentionPolicy, error) {
	retentionPolicies, err := c.showRetentionPolicies(ctx, database)
	if err != nil {
		return nil, err
	}

	return retentionPolicies, nil
}

func (c *Client) getRP(ctx context.Context, db, name string) (chronograf.RetentionPolicy, error) {
	rps, err := c.AllRP(ctx, db)
	if err != nil {
		return chronograf.RetentionPolicy{}, err
	}

	for _, rp := range rps {
		if rp.Name == name {
			return rp, nil
		}
	}
	return chronograf.RetentionPolicy{}, fmt.Errorf("unknown retention policy")
}

// CreateRP creates a retention policy for a specific database
func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) {
	query := fmt.Sprintf(`CREATE RETENTION POLICY "%s" ON "%s" DURATION %s REPLICATION %d`, rp.Name, database, rp.Duration, rp.Replication)
	if len(rp.ShardDuration) != 0 {
		query = fmt.Sprintf(`%s SHARD DURATION %s`, query, rp.ShardDuration)
	}

	if rp.Default {
		query = fmt.Sprintf(`%s DEFAULT`, query)
	}

	_, err := c.Query(ctx, chronograf.Query{
		Command: query,
		DB:      database,
	})
	if err != nil {
		return nil, err
	}

	res, err := c.getRP(ctx, database, rp.Name)
	if err != nil {
		return nil, err
	}

	return &res, nil
}

// UpdateRP updates a specific retention policy for a specific database
func (c *Client) UpdateRP(ctx context.Context, database string, name string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) {
	var buffer bytes.Buffer
	buffer.WriteString(fmt.Sprintf(`ALTER RETENTION POLICY "%s" ON "%s"`, name, database))
	if len(rp.Duration) > 0 {
		buffer.WriteString(" DURATION " + rp.Duration)
	}
	if rp.Replication > 0 {
		buffer.WriteString(" REPLICATION " + fmt.Sprint(rp.Replication))
	}
	if len(rp.ShardDuration) > 0 {
		buffer.WriteString(" SHARD DURATION " + rp.ShardDuration)
	}
	if rp.Default == true {
		buffer.WriteString(" DEFAULT")
	}
	queryRes, err := c.Query(ctx, chronograf.Query{
		Command: buffer.String(),
		DB:      database,
		RP:      name,
	})
	if err != nil {
		return nil, err
	}

	// The ALTER RETENTION POLICIES statements puts the error within the results itself
	// So, we have to crack open the results to see what happens
	octets, err := queryRes.MarshalJSON()
	if err != nil {
		return nil, err
	}

	results := make([]struct{ Error string }, 0)
	if err := json.Unmarshal(octets, &results); err != nil {
		return nil, err
	}

	// At last, we can check if there are any error strings
	for _, r := range results {
		if r.Error != "" {
			return nil, fmt.Errorf(r.Error)
		}
	}

	res, err := c.getRP(ctx, database, rp.Name)
	if err != nil {
		return nil, err
	}

	return &res, nil
}

// DropRP removes a specific retention policy for a specific database
func (c *Client) DropRP(ctx context.Context, database string, rp string) error {
	_, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`DROP RETENTION POLICY "%s" ON "%s"`, rp, database),
		DB:      database,
		RP:      rp,
	})
	if err != nil {
		return err
	}
	return nil
}

func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) {
	res, err := c.Query(ctx, chronograf.Query{
		Command: `SHOW DATABASES`,
	})
	if err != nil {
		return nil, err
	}
	octets, err := res.MarshalJSON()
	if err != nil {
		return nil, err
	}

	results := showResults{}
	if err := json.Unmarshal(octets, &results); err != nil {
		return nil, err
	}

	return results.Databases(), nil
}

func (c *Client) showRetentionPolicies(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) {
	retentionPolicies, err := c.Query(ctx, chronograf.Query{
		Command: fmt.Sprintf(`SHOW RETENTION POLICIES ON "%s"`, name),
		DB:      name,
	})

	if err != nil {
		return nil, err
	}
	octets, err := retentionPolicies.MarshalJSON()
	if err != nil {
		return nil, err
	}

	results := showResults{}
	if err := json.Unmarshal(octets, &results); err != nil {
		return nil, err
	}

	return results.RetentionPolicies(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/gorilla/websocket"
	"github.com/pterodactyl/wings/config"
	"github.com/pterodactyl/wings/server"
	"go.uber.org/zap"
	"net/http"
)

// Entrypoint for the Wings application. Configures the logger and checks any
// flags that were passed through in the boot arguments.
func main() {
	var configPath = *flag.String("config", "config.yml", "set the location for the configuration file")
	var debug = *flag.Bool("debug", false, "pass in order to run wings in debug mode")

	flag.Parse()

	zap.S().Infof("using configuration file: %s", configPath)

	c, err := config.ReadConfiguration(configPath)
	if err != nil {
		panic(err)
		return
	}

	if debug {
		c.Debug = true
	}

	printLogo()
	if err := configureLogging(c.Debug); err != nil {
		panic(err)
	}

	if c.Debug {
		zap.S().Debugw("running in debug mode")
	}

	zap.S().Infof("checking for pterodactyl system user \"%s\"", c.System.User)
	if su, err := c.EnsurePterodactylUser(); err != nil {
		zap.S().Panicw("failed to create pterodactyl system user", zap.Error(err))
		return
	} else {
		zap.S().Infow("configured system user", zap.String("username", su.Username), zap.String("uid", su.Uid), zap.String("gid", su.Gid))
	}

	zap.S().Infow("beginnning file permission setting on server data directories")
	if err := c.EnsureFilePermissions(); err != nil {
		zap.S().Errorw("failed to properly chown data directories", zap.Error(err))
	} else {
		zap.S().Infow("finished ensuring file permissions")
	}

	servers, err := server.LoadDirectory("data/servers", c.System)
	if err != nil {
		zap.S().Fatalw("failed to load server configurations", zap.Error(err))
		return
	}

	for _, s := range servers {
		zap.S().Infow("loaded configuration for server", zap.String("server", s.Uuid))
		zap.S().Infow("ensuring envrionment exists", zap.String("server", s.Uuid))

		if err := s.Environment.Create(); err != nil {
			zap.S().Errorw("failed to create an environment for server", zap.String("server", s.Uuid), zap.Error(err))
		}

		if r, err := s.Environment.IsRunning(); err != nil {
			zap.S().Errorw("error checking server environment status", zap.String("server", s.Uuid), zap.Error(err))
		} else if r {
			zap.S().Infow("detected server is running, re-attaching to process", zap.String("server", s.Uuid))
			if err := s.Environment.Attach(); err != nil {
				zap.S().Errorw("error attaching to server environment", zap.String("server", s.Uuid), zap.Error(err))
			}
		}
	}

	r := &Router{
		Servers: servers,
		token: c.AuthenticationToken,
		upgrader: websocket.Upgrader{
			// Ensure that the websocket request is originating from the Panel itself,
			// and not some other location.
			CheckOrigin: func(r *http.Request) bool {
				return r.Header.Get("Origin") == c.PanelLocation
			},
		},
	}

	router := r.ConfigureRouter()
	zap.S().Infow("configuring webserver", zap.String("host", c.Api.Host), zap.Int("port", c.Api.Port))
	if err := http.ListenAndServe(fmt.Sprintf("%s:%d", c.Api.Host, c.Api.Port), router); err != nil {
		zap.S().Fatalw("failed to configure HTTP server", zap.Error(err))
	}
}

// Configures the global logger for Zap so that we can call it from any location
// in the code without having to pass around a logger instance.
func configureLogging(debug bool) error {
	cfg := zap.NewProductionConfig()
	if debug {
		cfg = zap.NewDevelopmentConfig()
	}

	cfg.Encoding = "console"
	cfg.OutputPaths = []string{
		"stdout",
	}

	logger, err := cfg.Build()
	if err != nil {
		return err
	}

	zap.ReplaceGlobals(logger)

	return nil
}

// Prints the wings logo, nothing special here!
func printLogo() {
	fmt.Println()
	fmt.Println(`                     ____`)
	fmt.Println(`__ Pterodactyl _____/___/_______ _______ ______`)
	fmt.Println(`\_____\    \/\/    /   /       /  __   /   ___/`)
	fmt.Println(`   \___\          /   /   /   /  /_/  /___   /`)
	fmt.Println(`        \___/\___/___/___/___/___    /______/`)
	fmt.Println(`                            /_______/ v` + Version)
	fmt.Println()
}
<commit_msg>Support listening for SSL connections<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/gorilla/websocket"
	"github.com/pterodactyl/wings/config"
	"github.com/pterodactyl/wings/server"
	"go.uber.org/zap"
	"net/http"
)

// Entrypoint for the Wings application. Configures the logger and checks any
// flags that were passed through in the boot arguments.
func main() {
	var configPath = *flag.String("config", "config.yml", "set the location for the configuration file")
	var debug = *flag.Bool("debug", false, "pass in order to run wings in debug mode")

	flag.Parse()

	zap.S().Infof("using configuration file: %s", configPath)

	c, err := config.ReadConfiguration(configPath)
	if err != nil {
		panic(err)
		return
	}

	if debug {
		c.Debug = true
	}

	printLogo()
	if err := configureLogging(c.Debug); err != nil {
		panic(err)
	}

	if c.Debug {
		zap.S().Debugw("running in debug mode")
	}

	zap.S().Infof("checking for pterodactyl system user \"%s\"", c.System.User)
	if su, err := c.EnsurePterodactylUser(); err != nil {
		zap.S().Panicw("failed to create pterodactyl system user", zap.Error(err))
		return
	} else {
		zap.S().Infow("configured system user", zap.String("username", su.Username), zap.String("uid", su.Uid), zap.String("gid", su.Gid))
	}

	zap.S().Infow("beginnning file permission setting on server data directories")
	if err := c.EnsureFilePermissions(); err != nil {
		zap.S().Errorw("failed to properly chown data directories", zap.Error(err))
	} else {
		zap.S().Infow("finished ensuring file permissions")
	}

	servers, err := server.LoadDirectory("data/servers", c.System)
	if err != nil {
		zap.S().Fatalw("failed to load server configurations", zap.Error(err))
		return
	}

	for _, s := range servers {
		zap.S().Infow("loaded configuration for server", zap.String("server", s.Uuid))
		zap.S().Infow("ensuring envrionment exists", zap.String("server", s.Uuid))

		if err := s.Environment.Create(); err != nil {
			zap.S().Errorw("failed to create an environment for server", zap.String("server", s.Uuid), zap.Error(err))
		}

		if r, err := s.Environment.IsRunning(); err != nil {
			zap.S().Errorw("error checking server environment status", zap.String("server", s.Uuid), zap.Error(err))
		} else if r {
			zap.S().Infow("detected server is running, re-attaching to process", zap.String("server", s.Uuid))
			if err := s.Environment.Attach(); err != nil {
				zap.S().Errorw("error attaching to server environment", zap.String("server", s.Uuid), zap.Error(err))
			}
		}
	}

	r := &Router{
		Servers: servers,
		token:   c.AuthenticationToken,
		upgrader: websocket.Upgrader{
			// Ensure that the websocket request is originating from the Panel itself,
			// and not some other location.
			CheckOrigin: func(r *http.Request) bool {
				return r.Header.Get("Origin") == c.PanelLocation
			},
		},
	}

	router := r.ConfigureRouter()
	zap.S().Infow("configuring webserver", zap.Bool("ssl", c.Api.Ssl.Enabled), zap.String("host", c.Api.Host), zap.Int("port", c.Api.Port))

	addr := fmt.Sprintf("%s:%d", c.Api.Host, c.Api.Port)
	if c.Api.Ssl.Enabled {
		if err := http.ListenAndServeTLS(addr, c.Api.Ssl.CertificateFile, c.Api.Ssl.KeyFile, router); err != nil {
			zap.S().Fatalw("failed to configure HTTPS server", zap.Error(err))
		}
	} else {
		if err := http.ListenAndServe(addr, router); err != nil {
			zap.S().Fatalw("failed to configure HTTP server", zap.Error(err))
		}
	}
}

// Configures the global logger for Zap so that we can call it from any location
// in the code without having to pass around a logger instance.
func configureLogging(debug bool) error {
	cfg := zap.NewProductionConfig()
	if debug {
		cfg = zap.NewDevelopmentConfig()
	}

	cfg.Encoding = "console"
	cfg.OutputPaths = []string{
		"stdout",
	}

	logger, err := cfg.Build()
	if err != nil {
		return err
	}

	zap.ReplaceGlobals(logger)

	return nil
}

// Prints the wings logo, nothing special here!
func printLogo() {
	fmt.Println()
	fmt.Println(`                     ____`)
	fmt.Println(`__ Pterodactyl _____/___/_______ _______ ______`)
	fmt.Println(`\_____\    \/\/    /   /       /  __   /   ___/`)
	fmt.Println(`   \___\          /   /   /   /  /_/  /___   /`)
	fmt.Println(`        \___/\___/___/___/___/___    /______/`)
	fmt.Println(`                            /_______/ v` + Version)
	fmt.Println()
}
<|endoftext|>


<commit_before>package gosql

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"log"
	"strings"
	"time"
)

const createMigrationsSql = `
  CREATE TABLE migrations (idx INTEGER PRIMARY KEY NOT NULL, md5 UUID NOT NULL, statement VARCHAR NOT NULL, created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL)
`

func NewMigrator(migrations ...interface{}) *Migrator {
	return &Migrator{steps: migrations}
}

type Migrator struct {
	Logger *log.Logger
	steps  []interface{}
}

type migrations []*Migration

func (list migrations) Execute(tx Dbi) (int, error) {
	if len(list) == 0 {
		return 0, fmt.Errorf("nothing to execute")
	}
	return list.ExecuteUntil(tx, list[len(list)-1].Idx)
}

func (list migrations) ExecuteUntil(tx Dbi, step int) (int, error) {
	_, e := setupMigrations(tx)
	if e != nil {
		return 0, e
	}
	cnt := 0
	for _, m := range list {
		if m.Idx <= step {
			if m.Executed {
				m.log("SKIP")
			} else {
				m.log("EXECUTE")
				if _, e := m.Execute(tx); e != nil {
					return cnt, e
				}
				m.Executed = true
				cnt++
			}
		}
	}
	return cnt, nil
}

func (m *Migrator) migrations(tx Dbi) (migrations, error) {
	out := []*Migration{}

	_, e := setupMigrations(tx)
	if e != nil {
		return nil, e
	}
	for idx, i := range m.steps {
		m, e := newMigration(idx+1, i)
		if e != nil {
			return nil, e
		}
		var cs string
		if e = tx.QueryRow("SELECT md5 FROM migrations where idx = $1", m.Idx).Scan(&cs); e != nil {
			if e != sql.ErrNoRows {
				return nil, e
			}
		} else {
			cs = strings.Replace(cs, "-", "", -1)
			if cs == m.checksum() {
				m.Executed = true
			} else {
				return nil, fmt.Errorf("migration %d (new checksum %s) already exists with checksum %q", m.Idx, cs, m.checksum())
			}
		}
		out = append(out, m)
	}
	return out, nil
}

func (list *Migrator) Execute(tx Dbi) error {
	_, e := setupMigrations(tx)
	if e != nil {
		return e
	}

	return func() error {
		for idx, i := range list.steps {
			m, e := newMigration(idx+1, i)
			if e != nil {
				return e
			}
			m.Logger = list.Logger
			_, e = m.Execute(tx)
			if e != nil {
				return e
			}
		}
		return nil
	}()
}

func newMigration(idx int, statement interface{}) (*Migration, error) {
	m := &Migration{Idx: idx}

	switch casted := statement.(type) {
	case string:
		m.Statement = casted
	case fmt.Stringer:
		m.Statement = casted.String()
	default:
		return nil, fmt.Errorf("type %T not supported", casted)
	}
	return m, nil
}

type Migration struct {
	Idx       int
	Statement string
	Logger    *log.Logger
	Executed  bool
}

const errorMigrationsDoesNotExist = `pq: relation "migrations" does not exist`

func setupMigrations(tx Dbi) (sql.Result, error) {
	row := tx.QueryRow("SELECT COUNT(1) FROM pg_tables WHERE schemaname = $1 AND tablename = $2", "public", "migrations")
	var cnt int
	e := row.Scan(&cnt)
	if e != nil {
		return nil, e
	}

	if cnt == 0 {
		return tx.Exec(createMigrationsSql)
	}
	return nil, nil
}

func (m *Migration) log(t string) {
	if m.Logger != nil {
		out := []string{}
		lines := strings.Split(strings.TrimSpace(m.Statement), "\n")
		for _, l := range lines {
			out = append(out, strings.TrimSpace(l))
		}
		m.Logger.Printf(t+": migration %d %q %q", m.Idx, m.checksum(), strings.Join(strings.Fields(strings.Join(out, " ")), " "))
	}
}

func (m *Migration) checksum() string {
	return fmt.Sprintf("%x", md5.Sum([]byte(m.Statement)))
}

func (m *Migration) Execute(tx Dbi) (sql.Result, error) {
	res, e := tx.Exec(m.Statement)
	if e != nil {
		return nil, e
	}
	_, e = tx.Exec("INSERT INTO migrations (idx, md5, statement, created_at) VALUES ($1, $2, $3, $4)", m.Idx, m.checksum(), m.Statement, time.Now().UTC().Format(time.RFC3339Nano))
	return res, e
}
<commit_msg>fix Migrator.Execute<commit_after>package gosql

import (
	"crypto/md5"
	"database/sql"
	"fmt"
	"log"
	"strings"
	"time"
)

const createMigrationsSql = `
  CREATE TABLE migrations (idx INTEGER PRIMARY KEY NOT NULL, md5 UUID NOT NULL, statement VARCHAR NOT NULL, created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL)
`

func NewMigrator(migrations ...interface{}) *Migrator {
	return &Migrator{steps: migrations}
}

type Migrator struct {
	Logger *log.Logger
	steps  []interface{}
}

type migrations []*Migration

func (list migrations) Execute(tx Dbi) (int, error) {
	if len(list) == 0 {
		return 0, fmt.Errorf("nothing to execute")
	}
	return list.ExecuteUntil(tx, list[len(list)-1].Idx)
}

func (list migrations) ExecuteUntil(tx Dbi, step int) (int, error) {
	_, e := setupMigrations(tx)
	if e != nil {
		return 0, e
	}
	cnt := 0
	for _, m := range list {
		if m.Idx <= step {
			if m.Executed {
				m.log("SKIP")
			} else {
				m.log("EXECUTE")
				if _, e := m.Execute(tx); e != nil {
					return cnt, e
				}
				m.Executed = true
				cnt++
			}
		}
	}
	return cnt, nil
}

func (migrator *Migrator) migrations(tx Dbi) (migrations, error) {
	out := []*Migration{}

	_, e := setupMigrations(tx)
	if e != nil {
		return nil, e
	}
	for idx, i := range migrator.steps {
		m, e := newMigration(idx+1, i)
		if e != nil {
			return nil, e
		}
		m.Logger = migrator.Logger
		var cs string
		if e = tx.QueryRow("SELECT md5 FROM migrations where idx = $1", m.Idx).Scan(&cs); e != nil {
			if e != sql.ErrNoRows {
				return nil, e
			}
		} else {
			cs = strings.Replace(cs, "-", "", -1)
			if cs == m.checksum() {
				m.Executed = true
			} else {
				return nil, fmt.Errorf("migration %d (new checksum %s) already exists with checksum %q", m.Idx, cs, m.checksum())
			}
		}
		out = append(out, m)
	}
	return out, nil
}

func (list *Migrator) Execute(tx Dbi) error {
	migs, e := list.migrations(tx)
	if e != nil {
		return e
	}
	_, e = migs.Execute(tx)
	return e
}

func newMigration(idx int, statement interface{}) (*Migration, error) {
	m := &Migration{Idx: idx}

	switch casted := statement.(type) {
	case string:
		m.Statement = casted
	case fmt.Stringer:
		m.Statement = casted.String()
	default:
		return nil, fmt.Errorf("type %T not supported", casted)
	}
	return m, nil
}

type Migration struct {
	Idx       int
	Statement string
	Logger    *log.Logger
	Executed  bool
}

const errorMigrationsDoesNotExist = `pq: relation "migrations" does not exist`

func setupMigrations(tx Dbi) (sql.Result, error) {
	row := tx.QueryRow("SELECT COUNT(1) FROM pg_tables WHERE schemaname = $1 AND tablename = $2", "public", "migrations")
	var cnt int
	e := row.Scan(&cnt)
	if e != nil {
		return nil, e
	}

	if cnt == 0 {
		return tx.Exec(createMigrationsSql)
	}
	return nil, nil
}

func (m *Migration) log(t string) {
	if m.Logger != nil {
		out := []string{}
		lines := strings.Split(strings.TrimSpace(m.Statement), "\n")
		for _, l := range lines {
			out = append(out, strings.TrimSpace(l))
		}
		m.Logger.Printf(t+": migration %d %q %q", m.Idx, m.checksum(), strings.Join(strings.Fields(strings.Join(out, " ")), " "))
	}
}

func (m *Migration) checksum() string {
	return fmt.Sprintf("%x", md5.Sum([]byte(m.Statement)))
}

func (m *Migration) Execute(tx Dbi) (sql.Result, error) {
	res, e := tx.Exec(m.Statement)
	if e != nil {
		return nil, e
	}
	_, e = tx.Exec("INSERT INTO migrations (idx, md5, statement, created_at) VALUES ($1, $2, $3, $4)", m.Idx, m.checksum(), m.Statement, time.Now().UTC().Format(time.RFC3339Nano))
	return res, e
}
<|endoftext|>


<commit_before>package oas

import (
	"net/http"
	"sort"
	"strings"

	"github.com/TykTechnologies/tyk/apidef"
)

type Middleware struct {
	// Global contains the configurations related to the global middleware.
	Global *Global `bson:"global,omitempty" json:"global,omitempty"`
	Paths  Paths   `bson:"paths,omitempty" json:"paths,omitempty"`
}

func (m *Middleware) Fill(api apidef.APIDefinition) {
	if m.Global == nil {
		m.Global = &Global{}
	}

	m.Global.Fill(api)
	if ShouldOmit(m.Global) {
		m.Global = nil
	}

	if m.Paths == nil {
		m.Paths = make(Paths)
	}

	m.Paths.Fill(api.VersionData.Versions[""].ExtendedPaths)
	if ShouldOmit(m.Paths) {
		m.Paths = nil
	}
}

func (m *Middleware) ExtractTo(api *apidef.APIDefinition) {
	if m.Global != nil {
		m.Global.ExtractTo(api)
	}

	if m.Paths != nil {
		var ep apidef.ExtendedPathsSet
		m.Paths.ExtractTo(&ep)
		base := apidef.VersionInfo{UseExtendedPaths: true, ExtendedPaths: ep}
		if api.VersionData.Versions == nil {
			api.VersionData.Versions = make(map[string]apidef.VersionInfo)
		}

		api.VersionData.Versions[""] = base
	}
}

type Global struct {
	CORS *CORS `bson:"cors,omitempty" json:"cors,omitempty"`
	// Cache contains the configurations related to caching.
	// Old API Definition: `cache_options`
	Cache *Cache `bson:"cache,omitempty" json:"cache,omitempty"`
}

func (g *Global) Fill(api apidef.APIDefinition) {
	// CORS
	if g.CORS == nil {
		g.CORS = &CORS{}
	}

	g.CORS.Fill(api.CORS)
	if ShouldOmit(g.CORS) {
		g.CORS = nil
	}

	// Cache
	if g.Cache == nil {
		g.Cache = &Cache{}
	}

	g.Cache.Fill(api.CacheOptions)
	if ShouldOmit(g.Cache) {
		g.Cache = nil
	}
}

func (g *Global) ExtractTo(api *apidef.APIDefinition) {
	if g.CORS != nil {
		g.CORS.ExtractTo(&api.CORS)
	}

	if g.Cache != nil {
		g.Cache.ExtractTo(&api.CacheOptions)
	}
}

type CORS struct {
	Enabled            bool     `bson:"enabled" json:"enabled"` // required
	MaxAge             int      `bson:"maxAge,omitempty" json:"maxAge,omitempty"`
	AllowCredentials   bool     `bson:"allowCredentials,omitempty" json:"allowCredentials,omitempty"`
	ExposedHeaders     []string `bson:"exposedHeaders,omitempty" json:"exposedHeaders,omitempty"`
	AllowedHeaders     []string `bson:"allowedHeaders,omitempty" json:"allowedHeaders,omitempty"`
	OptionsPassthrough bool     `bson:"optionsPassthrough,omitempty" json:"optionsPassthrough,omitempty"`
	Debug              bool     `bson:"debug,omitempty" json:"debug,omitempty"`
	AllowedOrigins     []string `bson:"allowedOrigins,omitempty" json:"allowedOrigins,omitempty"`
	AllowedMethods     []string `bson:"allowedMethods,omitempty" json:"allowedMethods,omitempty"`
}

func (c *CORS) Fill(cors apidef.CORSConfig) {
	c.Enabled = cors.Enable
	c.MaxAge = cors.MaxAge
	c.AllowCredentials = cors.AllowCredentials
	c.ExposedHeaders = cors.ExposedHeaders
	c.AllowedHeaders = cors.AllowedHeaders
	c.OptionsPassthrough = cors.OptionsPassthrough
	c.Debug = cors.Debug
	c.AllowedOrigins = cors.AllowedOrigins
	c.AllowedMethods = cors.AllowedMethods
}

func (c *CORS) ExtractTo(cors *apidef.CORSConfig) {
	cors.Enable = c.Enabled
	cors.MaxAge = c.MaxAge
	cors.AllowCredentials = c.AllowCredentials
	cors.ExposedHeaders = c.ExposedHeaders
	cors.AllowedHeaders = c.AllowedHeaders
	cors.OptionsPassthrough = c.OptionsPassthrough
	cors.Debug = c.Debug
	cors.AllowedOrigins = c.AllowedOrigins
	cors.AllowedMethods = c.AllowedMethods
}

type Cache struct {
	// Enabled turns global cache middleware on or off. It is still possible to enable caching on a per-path basis
	// by explicitly setting the endpoint cache middleware.
	// Old API Definition: `cache_options.enable_cache`
	Enabled bool `bson:"enabled" json:"enabled"` // required
	// Timeout is the TTL for a cached object in seconds.
	// Old API Definition: `cache_options.cache_timeout`
	Timeout int64 `bson:"timeout,omitempty" json:"timeout,omitempty"`
	// CacheAllSafeRequests caches responses to (`GET`, `HEAD`, `OPTIONS`) requests overrides per-path cache settings in versions,
	// applies across versions.
	// Old API Definition: `cache_options.cache_all_safe_requests`
	CacheAllSafeRequests bool `bson:"cacheAllSafeRequests,omitempty" json:"cacheAllSafeRequests,omitempty"`
	// CacheResponseCodes is an array of response codes which are safe to cache e.g. `404`.
	// Old API Definition: `cache_options.cache_response_codes`
	CacheResponseCodes []int `bson:"cacheResponseCodes,omitempty" json:"cacheResponseCodes,omitempty"`
	// CacheByHeaders allows header values to be used as part of the cache key.
	// Old API Definition: `cache_options.cache_by_headers`
	CacheByHeaders []string `bson:"cacheByHeaders,omitempty" json:"cacheByHeaders,omitempty"`
	// EnableUpstreamCacheControl instructs Tyk Cache to respect upstream cache control headers.
	// Old API Definition: `cache_options.enable_upstream_cache_control`
	EnableUpstreamCacheControl bool `bson:"enableUpstreamCacheControl,omitempty" json:"enableUpstreamCacheControl,omitempty"`
	// ControlTTLHeaderName is the response header which tells Tyk how long it is safe to cache the response for.
	// Old API Definition: `cache_options.cache_control_ttl_header`
	ControlTTLHeaderName string `bson:"controlTTLHeaderName,omitempty" json:"controlTTLHeaderName,omitempty"`
}

func (c *Cache) Fill(cache apidef.CacheOptions) {
	c.Enabled = cache.EnableCache
	c.Timeout = cache.CacheTimeout
	c.CacheAllSafeRequests = cache.CacheAllSafeRequests
	c.CacheResponseCodes = cache.CacheOnlyResponseCodes
	c.CacheByHeaders = cache.CacheByHeaders
	c.EnableUpstreamCacheControl = cache.EnableUpstreamCacheControl
	c.ControlTTLHeaderName = cache.CacheControlTTLHeader
}

func (c *Cache) ExtractTo(cache *apidef.CacheOptions) {
	cache.EnableCache = c.Enabled
	cache.CacheTimeout = c.Timeout
	cache.CacheAllSafeRequests = c.CacheAllSafeRequests
	cache.CacheOnlyResponseCodes = c.CacheResponseCodes
	cache.CacheByHeaders = c.CacheByHeaders
	cache.EnableUpstreamCacheControl = c.EnableUpstreamCacheControl
	cache.CacheControlTTLHeader = c.ControlTTLHeaderName
}

type Paths map[string]*Path

func (ps Paths) Fill(ep apidef.ExtendedPathsSet) {
	ps.fillAllowance(ep, allow)
	ps.fillAllowance(ep, block)
	ps.fillAllowance(ep, ignoreAuthentication)
}

func (ps Paths) fillAllowance(ep apidef.ExtendedPathsSet, typ AllowanceType) {
	endpointMetas := ep.WhiteList

	switch typ {
	case block:
		endpointMetas = ep.BlackList
	case ignoreAuthentication:
		endpointMetas = ep.Ignored
	}

	for _, em := range endpointMetas {
		for method := range em.MethodActions {
			if _, ok := ps[em.Path]; !ok {
				ps[em.Path] = &Path{}
			}

			plugins := ps[em.Path].getMethod(method)
			plugins.fillAllowance(em, typ)
		}
	}
}

func (ps Paths) ExtractTo(ep *apidef.ExtendedPathsSet) {
	var paths []string
	for path := range ps {
		paths = append(paths, path)
	}

	sort.Strings(paths)

	for _, path := range paths {
		ps[path].ExtractTo(ep, path)
	}
}

type Path struct {
	Delete  *Plugins `bson:"DELETE,omitempty" json:"DELETE,omitempty"`
	Get     *Plugins `bson:"GET,omitempty" json:"GET,omitempty"`
	Head    *Plugins `bson:"HEAD,omitempty" json:"HEAD,omitempty"`
	Options *Plugins `bson:"OPTIONS,omitempty" json:"OPTIONS,omitempty"`
	Patch   *Plugins `bson:"PATCH,omitempty" json:"PATCH,omitempty"`
	Post    *Plugins `bson:"POST,omitempty" json:"POST,omitempty"`
	Put     *Plugins `bson:"PUT,omitempty" json:"PUT,omitempty"`
	Trace   *Plugins `bson:"TRACE,omitempty" json:"TRACE,omitempty"`
	Connect *Plugins `bson:"CONNECT,omitempty" json:"CONNECT,omitempty"`
}

func (p *Path) ExtractTo(ep *apidef.ExtendedPathsSet, path string) {
	if p.Get != nil {
		p.Get.ExtractTo(ep, path, http.MethodGet)
	}

	if p.Post != nil {
		p.Post.ExtractTo(ep, path, http.MethodPost)
	}

	if p.Put != nil {
		p.Put.ExtractTo(ep, path, http.MethodPut)
	}

	if p.Delete != nil {
		p.Delete.ExtractTo(ep, path, http.MethodDelete)
	}

	if p.Head != nil {
		p.Head.ExtractTo(ep, path, http.MethodHead)
	}

	if p.Options != nil {
		p.Options.ExtractTo(ep, path, http.MethodOptions)
	}

	if p.Trace != nil {
		p.Trace.ExtractTo(ep, path, http.MethodTrace)
	}

	if p.Patch != nil {
		p.Patch.ExtractTo(ep, path, http.MethodPatch)
	}

	if p.Connect != nil {
		p.Connect.ExtractTo(ep, path, http.MethodConnect)
	}
}

func (p *Path) getMethod(name string) *Plugins {
	switch {
	case strings.EqualFold(http.MethodGet, name):
		if p.Get == nil {
			p.Get = &Plugins{}
		}

		return p.Get
	case strings.EqualFold(http.MethodPost, name):
		if p.Post == nil {
			p.Post = &Plugins{}
		}

		return p.Post
	case strings.EqualFold(http.MethodPut, name):
		if p.Put == nil {
			p.Put = &Plugins{}
		}

		return p.Put
	case strings.EqualFold(http.MethodDelete, name):
		if p.Delete == nil {
			p.Delete = &Plugins{}
		}

		return p.Delete
	case strings.EqualFold(http.MethodHead, name):
		if p.Head == nil {
			p.Head = &Plugins{}
		}

		return p.Head
	case strings.EqualFold(http.MethodOptions, name):
		if p.Options == nil {
			p.Options = &Plugins{}
		}

		return p.Options
	case strings.EqualFold(http.MethodTrace, name):
		if p.Trace == nil {
			p.Trace = &Plugins{}
		}

		return p.Trace
	case strings.EqualFold(http.MethodPatch, name):
		if p.Patch == nil {
			p.Patch = &Plugins{}
		}

		return p.Patch
	case strings.EqualFold(http.MethodConnect, name):
		if p.Connect == nil {
			p.Connect = &Plugins{}
		}

		return p.Connect
	default:
		if p.Get == nil {
			p.Get = &Plugins{}
		}

		return p.Get
	}
}

type AllowanceType int

const (
	allow                AllowanceType = 0
	block                AllowanceType = 1
	ignoreAuthentication AllowanceType = 2
)

type Plugins struct {
	Allow                *Allowance `bson:"allow,omitempty" json:"allow,omitempty"`
	Block                *Allowance `bson:"block,omitempty" json:"block,omitempty"`
	IgnoreAuthentication *Allowance `bson:"ignoreAuthentication,omitempty" json:"ignoreAuthentication,omitempty"`
}

func (p *Plugins) fillAllowance(endpointMeta apidef.EndPointMeta, typ AllowanceType) {
	var allowance *Allowance

	switch typ {
	case block:
		if p.Block == nil {
			p.Block = &Allowance{}
		}

		allowance = p.Block
	case ignoreAuthentication:
		if p.IgnoreAuthentication == nil {
			p.IgnoreAuthentication = &Allowance{}
		}

		allowance = p.IgnoreAuthentication
	default:
		if p.Allow == nil {
			p.Allow = &Allowance{}
		}

		allowance = p.Allow
	}

	allowance.Fill(endpointMeta)
	if ShouldOmit(allowance) {
		allowance = nil
	}
}

func (p *Plugins) ExtractTo(ep *apidef.ExtendedPathsSet, path string, method string) {
	p.extractAllowance(ep, path, method, allow)
	p.extractAllowance(ep, path, method, block)
	p.extractAllowance(ep, path, method, ignoreAuthentication)
}

func (p *Plugins) extractAllowance(ep *apidef.ExtendedPathsSet, path string, method string, typ AllowanceType) {
	allowance := p.Allow
	endpointMetas := &ep.WhiteList

	switch typ {
	case block:
		allowance = p.Block
		endpointMetas = &ep.BlackList
	case ignoreAuthentication:
		allowance = p.IgnoreAuthentication
		endpointMetas = &ep.Ignored
	}

	if allowance != nil {
		newPath := true
		for i, em := range *endpointMetas {
			if path == em.Path {
				(*endpointMetas)[i].MethodActions[method] = apidef.EndpointMethodMeta{Action: apidef.NoAction}
				newPath = false
				break
			}
		}

		if newPath {
			methodActions := map[string]apidef.EndpointMethodMeta{
				method: {Action: apidef.NoAction},
			}

			endpointMeta := apidef.EndPointMeta{Path: path, MethodActions: methodActions}
			allowance.ExtractTo(&endpointMeta)
			*endpointMetas = append(*endpointMetas, endpointMeta)
		}
	}
}

type Allowance struct {
	Enabled    bool `bson:"enabled" json:"enabled"`
	IgnoreCase bool `bson:"ignoreCase,omitempty" json:"ignoreCase,omitempty"`
}

func (a *Allowance) Fill(endpointMeta apidef.EndPointMeta) {
	a.Enabled = !endpointMeta.Disabled
	a.IgnoreCase = endpointMeta.IgnoreCase
}

func (a *Allowance) ExtractTo(endpointMeta *apidef.EndPointMeta) {
	endpointMeta.Disabled = !a.Enabled
	endpointMeta.IgnoreCase = a.IgnoreCase
}
<commit_msg>Refactor allowance oas conversion (#3808)<commit_after>package oas

import (
	"net/http"
	"sort"
	"strings"

	"github.com/TykTechnologies/tyk/apidef"
)

type Middleware struct {
	// Global contains the configurations related to the global middleware.
	Global *Global `bson:"global,omitempty" json:"global,omitempty"`
	Paths  Paths   `bson:"paths,omitempty" json:"paths,omitempty"`
}

func (m *Middleware) Fill(api apidef.APIDefinition) {
	if m.Global == nil {
		m.Global = &Global{}
	}

	m.Global.Fill(api)
	if ShouldOmit(m.Global) {
		m.Global = nil
	}

	if m.Paths == nil {
		m.Paths = make(Paths)
	}

	m.Paths.Fill(api.VersionData.Versions[""].ExtendedPaths)
	if ShouldOmit(m.Paths) {
		m.Paths = nil
	}
}

func (m *Middleware) ExtractTo(api *apidef.APIDefinition) {
	if m.Global != nil {
		m.Global.ExtractTo(api)
	}

	if m.Paths != nil {
		var ep apidef.ExtendedPathsSet
		m.Paths.ExtractTo(&ep)
		base := apidef.VersionInfo{UseExtendedPaths: true, ExtendedPaths: ep}
		if api.VersionData.Versions == nil {
			api.VersionData.Versions = make(map[string]apidef.VersionInfo)
		}

		api.VersionData.Versions[""] = base
	}
}

type Global struct {
	CORS *CORS `bson:"cors,omitempty" json:"cors,omitempty"`
	// Cache contains the configurations related to caching.
	// Old API Definition: `cache_options`
	Cache *Cache `bson:"cache,omitempty" json:"cache,omitempty"`
}

func (g *Global) Fill(api apidef.APIDefinition) {
	// CORS
	if g.CORS == nil {
		g.CORS = &CORS{}
	}

	g.CORS.Fill(api.CORS)
	if ShouldOmit(g.CORS) {
		g.CORS = nil
	}

	// Cache
	if g.Cache == nil {
		g.Cache = &Cache{}
	}

	g.Cache.Fill(api.CacheOptions)
	if ShouldOmit(g.Cache) {
		g.Cache = nil
	}
}

func (g *Global) ExtractTo(api *apidef.APIDefinition) {
	if g.CORS != nil {
		g.CORS.ExtractTo(&api.CORS)
	}

	if g.Cache != nil {
		g.Cache.ExtractTo(&api.CacheOptions)
	}
}

type CORS struct {
	Enabled            bool     `bson:"enabled" json:"enabled"` // required
	MaxAge             int      `bson:"maxAge,omitempty" json:"maxAge,omitempty"`
	AllowCredentials   bool     `bson:"allowCredentials,omitempty" json:"allowCredentials,omitempty"`
	ExposedHeaders     []string `bson:"exposedHeaders,omitempty" json:"exposedHeaders,omitempty"`
	AllowedHeaders     []string `bson:"allowedHeaders,omitempty" json:"allowedHeaders,omitempty"`
	OptionsPassthrough bool     `bson:"optionsPassthrough,omitempty" json:"optionsPassthrough,omitempty"`
	Debug              bool     `bson:"debug,omitempty" json:"debug,omitempty"`
	AllowedOrigins     []string `bson:"allowedOrigins,omitempty" json:"allowedOrigins,omitempty"`
	AllowedMethods     []string `bson:"allowedMethods,omitempty" json:"allowedMethods,omitempty"`
}

func (c *CORS) Fill(cors apidef.CORSConfig) {
	c.Enabled = cors.Enable
	c.MaxAge = cors.MaxAge
	c.AllowCredentials = cors.AllowCredentials
	c.ExposedHeaders = cors.ExposedHeaders
	c.AllowedHeaders = cors.AllowedHeaders
	c.OptionsPassthrough = cors.OptionsPassthrough
	c.Debug = cors.Debug
	c.AllowedOrigins = cors.AllowedOrigins
	c.AllowedMethods = cors.AllowedMethods
}

func (c *CORS) ExtractTo(cors *apidef.CORSConfig) {
	cors.Enable = c.Enabled
	cors.MaxAge = c.MaxAge
	cors.AllowCredentials = c.AllowCredentials
	cors.ExposedHeaders = c.ExposedHeaders
	cors.AllowedHeaders = c.AllowedHeaders
	cors.OptionsPassthrough = c.OptionsPassthrough
	cors.Debug = c.Debug
	cors.AllowedOrigins = c.AllowedOrigins
	cors.AllowedMethods = c.AllowedMethods
}

type Cache struct {
	// Enabled turns global cache middleware on or off. It is still possible to enable caching on a per-path basis
	// by explicitly setting the endpoint cache middleware.
	// Old API Definition: `cache_options.enable_cache`
	Enabled bool `bson:"enabled" json:"enabled"` // required
	// Timeout is the TTL for a cached object in seconds.
	// Old API Definition: `cache_options.cache_timeout`
	Timeout int64 `bson:"timeout,omitempty" json:"timeout,omitempty"`
	// CacheAllSafeRequests caches responses to (`GET`, `HEAD`, `OPTIONS`) requests overrides per-path cache settings in versions,
	// applies across versions.
	// Old API Definition: `cache_options.cache_all_safe_requests`
	CacheAllSafeRequests bool `bson:"cacheAllSafeRequests,omitempty" json:"cacheAllSafeRequests,omitempty"`
	// CacheResponseCodes is an array of response codes which are safe to cache e.g. `404`.
	// Old API Definition: `cache_options.cache_response_codes`
	CacheResponseCodes []int `bson:"cacheResponseCodes,omitempty" json:"cacheResponseCodes,omitempty"`
	// CacheByHeaders allows header values to be used as part of the cache key.
	// Old API Definition: `cache_options.cache_by_headers`
	CacheByHeaders []string `bson:"cacheByHeaders,omitempty" json:"cacheByHeaders,omitempty"`
	// EnableUpstreamCacheControl instructs Tyk Cache to respect upstream cache control headers.
	// Old API Definition: `cache_options.enable_upstream_cache_control`
	EnableUpstreamCacheControl bool `bson:"enableUpstreamCacheControl,omitempty" json:"enableUpstreamCacheControl,omitempty"`
	// ControlTTLHeaderName is the response header which tells Tyk how long it is safe to cache the response for.
	// Old API Definition: `cache_options.cache_control_ttl_header`
	ControlTTLHeaderName string `bson:"controlTTLHeaderName,omitempty" json:"controlTTLHeaderName,omitempty"`
}

func (c *Cache) Fill(cache apidef.CacheOptions) {
	c.Enabled = cache.EnableCache
	c.Timeout = cache.CacheTimeout
	c.CacheAllSafeRequests = cache.CacheAllSafeRequests
	c.CacheResponseCodes = cache.CacheOnlyResponseCodes
	c.CacheByHeaders = cache.CacheByHeaders
	c.EnableUpstreamCacheControl = cache.EnableUpstreamCacheControl
	c.ControlTTLHeaderName = cache.CacheControlTTLHeader
}

func (c *Cache) ExtractTo(cache *apidef.CacheOptions) {
	cache.EnableCache = c.Enabled
	cache.CacheTimeout = c.Timeout
	cache.CacheAllSafeRequests = c.CacheAllSafeRequests
	cache.CacheOnlyResponseCodes = c.CacheResponseCodes
	cache.CacheByHeaders = c.CacheByHeaders
	cache.EnableUpstreamCacheControl = c.EnableUpstreamCacheControl
	cache.CacheControlTTLHeader = c.ControlTTLHeaderName
}

type Paths map[string]*Path

func (ps Paths) Fill(ep apidef.ExtendedPathsSet) {
	ps.fillAllowance(ep.WhiteList, allow)
	ps.fillAllowance(ep.BlackList, block)
	ps.fillAllowance(ep.Ignored, ignoreAuthentication)
}

func (ps Paths) fillAllowance(endpointMetas []apidef.EndPointMeta, typ AllowanceType) {
	for _, em := range endpointMetas {
		if _, ok := ps[em.Path]; !ok {
			ps[em.Path] = &Path{}
		}

		plugins := ps[em.Path].getMethod(em.Method)
		var allowance *Allowance

		switch typ {
		case block:
			if plugins.Block == nil {
				plugins.Block = &Allowance{}
			}

			allowance = plugins.Block
		case ignoreAuthentication:
			if plugins.IgnoreAuthentication == nil {
				plugins.IgnoreAuthentication = &Allowance{}
			}

			allowance = plugins.IgnoreAuthentication
		default:
			if plugins.Allow == nil {
				plugins.Allow = &Allowance{}
			}

			allowance = plugins.Allow
		}

		allowance.Fill(em)
		if ShouldOmit(allowance) {
			allowance = nil
		}
	}
}

func (ps Paths) ExtractTo(ep *apidef.ExtendedPathsSet) {
	var paths []string
	for path := range ps {
		paths = append(paths, path)
	}

	sort.Strings(paths)

	for _, path := range paths {
		ps[path].ExtractTo(ep, path)
	}
}

type Path struct {
	Delete  *Plugins `bson:"DELETE,omitempty" json:"DELETE,omitempty"`
	Get     *Plugins `bson:"GET,omitempty" json:"GET,omitempty"`
	Head    *Plugins `bson:"HEAD,omitempty" json:"HEAD,omitempty"`
	Options *Plugins `bson:"OPTIONS,omitempty" json:"OPTIONS,omitempty"`
	Patch   *Plugins `bson:"PATCH,omitempty" json:"PATCH,omitempty"`
	Post    *Plugins `bson:"POST,omitempty" json:"POST,omitempty"`
	Put     *Plugins `bson:"PUT,omitempty" json:"PUT,omitempty"`
	Trace   *Plugins `bson:"TRACE,omitempty" json:"TRACE,omitempty"`
	Connect *Plugins `bson:"CONNECT,omitempty" json:"CONNECT,omitempty"`
}

func (p *Path) ExtractTo(ep *apidef.ExtendedPathsSet, path string) {
	if p.Get != nil {
		p.Get.ExtractTo(ep, path, http.MethodGet)
	}

	if p.Post != nil {
		p.Post.ExtractTo(ep, path, http.MethodPost)
	}

	if p.Put != nil {
		p.Put.ExtractTo(ep, path, http.MethodPut)
	}

	if p.Delete != nil {
		p.Delete.ExtractTo(ep, path, http.MethodDelete)
	}

	if p.Head != nil {
		p.Head.ExtractTo(ep, path, http.MethodHead)
	}

	if p.Options != nil {
		p.Options.ExtractTo(ep, path, http.MethodOptions)
	}

	if p.Trace != nil {
		p.Trace.ExtractTo(ep, path, http.MethodTrace)
	}

	if p.Patch != nil {
		p.Patch.ExtractTo(ep, path, http.MethodPatch)
	}

	if p.Connect != nil {
		p.Connect.ExtractTo(ep, path, http.MethodConnect)
	}
}

func (p *Path) getMethod(name string) *Plugins {
	switch {
	case strings.EqualFold(http.MethodGet, name):
		if p.Get == nil {
			p.Get = &Plugins{}
		}

		return p.Get
	case strings.EqualFold(http.MethodPost, name):
		if p.Post == nil {
			p.Post = &Plugins{}
		}

		return p.Post
	case strings.EqualFold(http.MethodPut, name):
		if p.Put == nil {
			p.Put = &Plugins{}
		}

		return p.Put
	case strings.EqualFold(http.MethodDelete, name):
		if p.Delete == nil {
			p.Delete = &Plugins{}
		}

		return p.Delete
	case strings.EqualFold(http.MethodHead, name):
		if p.Head == nil {
			p.Head = &Plugins{}
		}

		return p.Head
	case strings.EqualFold(http.MethodOptions, name):
		if p.Options == nil {
			p.Options = &Plugins{}
		}

		return p.Options
	case strings.EqualFold(http.MethodTrace, name):
		if p.Trace == nil {
			p.Trace = &Plugins{}
		}

		return p.Trace
	case strings.EqualFold(http.MethodPatch, name):
		if p.Patch == nil {
			p.Patch = &Plugins{}
		}

		return p.Patch
	case strings.EqualFold(http.MethodConnect, name):
		if p.Connect == nil {
			p.Connect = &Plugins{}
		}

		return p.Connect
	default:
		if p.Get == nil {
			p.Get = &Plugins{}
		}

		return p.Get
	}
}

type AllowanceType int

const (
	allow                AllowanceType = 0
	block                AllowanceType = 1
	ignoreAuthentication AllowanceType = 2
)

type Plugins struct {
	Allow                *Allowance    `bson:"allow,omitempty" json:"allow,omitempty"`
	Block                *Allowance    `bson:"block,omitempty" json:"block,omitempty"`
	IgnoreAuthentication *Allowance    `bson:"ignoreAuthentication,omitempty" json:"ignoreAuthentication,omitempty"`
}

func (p *Plugins) ExtractTo(ep *apidef.ExtendedPathsSet, path string, method string) {
	p.extractAllowance(ep, path, method, allow)
	p.extractAllowance(ep, path, method, block)
	p.extractAllowance(ep, path, method, ignoreAuthentication)
}

func (p *Plugins) extractAllowance(ep *apidef.ExtendedPathsSet, path string, method string, typ AllowanceType) {
	allowance := p.Allow
	endpointMetas := &ep.WhiteList

	switch typ {
	case block:
		allowance = p.Block
		endpointMetas = &ep.BlackList
	case ignoreAuthentication:
		allowance = p.IgnoreAuthentication
		endpointMetas = &ep.Ignored
	}

	if allowance != nil {
		endpointMeta := apidef.EndPointMeta{Path: path, Method: method}
		allowance.ExtractTo(&endpointMeta)
		*endpointMetas = append(*endpointMetas, endpointMeta)
	}
}

type Allowance struct {
	Enabled    bool `bson:"enabled" json:"enabled"`
	IgnoreCase bool `bson:"ignoreCase,omitempty" json:"ignoreCase,omitempty"`
}

func (a *Allowance) Fill(endpointMeta apidef.EndPointMeta) {
	a.Enabled = !endpointMeta.Disabled
	a.IgnoreCase = endpointMeta.IgnoreCase
}

func (a *Allowance) ExtractTo(endpointMeta *apidef.EndPointMeta) {
	endpointMeta.Disabled = !a.Enabled
	endpointMeta.IgnoreCase = a.IgnoreCase
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Paolo Galeone. All right reserved.
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 tfgo

import (
	"fmt"
	tf "github.com/galeone/tensorflow/tensorflow/go"
	"io/ioutil"
)

// Model represents a trained model
type Model struct {
	saved *tf.SavedModel
}

// LoadModel creates a new *Model, loading it from the exportDir.
// The graph loaded is identified by the set of tags specified when exporting it.
// This operation creates a session with specified `options`
// Panics if the model can't be loaded
func LoadModel(exportDir string, tags []string, options *tf.SessionOptions) (model *Model) {
	var err error
	model = new(Model)
	model.saved, err = tf.LoadSavedModel(exportDir, tags, options)
	if err != nil {
		panic(err.Error())
	}
	return
}

// ImportModel creates a new *Model, loading the graph from the serialized representation.
// This operation creates a session with specified `options`
// Panics if the model can't be loaded
func ImportModel(serializedModel, prefix string, options *tf.SessionOptions) (model *Model) {
	model = new(Model)
	contents, err := ioutil.ReadFile(serializedModel)
	if err != nil {
		panic(err.Error())
	}

	graph := tf.NewGraph()
	if err := graph.Import(contents, prefix); err != nil {
		panic(err.Error())
	}

	session, err := tf.NewSession(graph, options)
	if err != nil {
		panic(err.Error())
	}

	model.saved = &tf.SavedModel{Session: session, Graph: graph}
	return
}

// Exec executes the nodes/tensors that must be present in the loaded model
// feedDict values to feed to placeholders (that must have been saved in the model definition)
// panics on error
func (model *Model) Exec(tensors []tf.Output, feedDict map[tf.Output]*tf.Tensor) (results []*tf.Tensor) {
	var err error
	if results, err = model.saved.Session.Run(feedDict, tensors, nil); err == nil {
		return results
	}
	panic(err)
}

// Op extracts the output in position idx of the tensor with the specified name from the model graph
func (model *Model) Op(name string, idx int) tf.Output {
	op := model.saved.Graph.Operation(name)
	if op == nil {
		panic(fmt.Errorf("op %s not found", name))
	}
	nout := op.NumOutputs()
	if nout <= idx {
		panic(fmt.Errorf("op %s has %d outputs. Requested output number %d", name, nout, idx))
	}
	return op.Output(idx)
}
<commit_msg>use finalizer to avoid leak on *tf.Session<commit_after>/*
Copyright 2017 Paolo Galeone. All right reserved.
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 tfgo

import (
	"fmt"
	"io/ioutil"
	"runtime"

	tf "github.com/galeone/tensorflow/tensorflow/go"
)

// Model represents a trained model
type Model struct {
	saved *tf.SavedModel
}

// LoadModel creates a new *Model, loading it from the exportDir.
// The graph loaded is identified by the set of tags specified when exporting it.
// This operation creates a session with specified `options`
// Panics if the model can't be loaded
func LoadModel(exportDir string, tags []string, options *tf.SessionOptions) (model *Model) {
	var err error
	model = new(Model)
	model.saved, err = tf.LoadSavedModel(exportDir, tags, options)
	runtime.SetFinalizer(model, func(model *Model) {
		if model.saved != nil && model.saved.Session != nil {
			_ = model.saved.Session.Close()
		}
	})
	if err != nil {
		panic(err.Error())
	}
	return
}

// ImportModel creates a new *Model, loading the graph from the serialized representation.
// This operation creates a session with specified `options`
// Panics if the model can't be loaded
func ImportModel(serializedModel, prefix string, options *tf.SessionOptions) (model *Model) {
	model = new(Model)
	contents, err := ioutil.ReadFile(serializedModel)
	if err != nil {
		panic(err.Error())
	}

	graph := tf.NewGraph()
	if err := graph.Import(contents, prefix); err != nil {
		panic(err.Error())
	}

	session, err := tf.NewSession(graph, options)
	if err != nil {
		panic(err.Error())
	}

	model.saved = &tf.SavedModel{Session: session, Graph: graph}
	return
}

// Exec executes the nodes/tensors that must be present in the loaded model
// feedDict values to feed to placeholders (that must have been saved in the model definition)
// panics on error
func (model *Model) Exec(tensors []tf.Output, feedDict map[tf.Output]*tf.Tensor) (results []*tf.Tensor) {
	var err error
	if results, err = model.saved.Session.Run(feedDict, tensors, nil); err == nil {
		return results
	}
	panic(err)
}

// Op extracts the output in position idx of the tensor with the specified name from the model graph
func (model *Model) Op(name string, idx int) tf.Output {
	op := model.saved.Graph.Operation(name)
	if op == nil {
		panic(fmt.Errorf("op %s not found", name))
	}
	nout := op.NumOutputs()
	if nout <= idx {
		panic(fmt.Errorf("op %s has %d outputs. Requested output number %d", name, nout, idx))
	}
	return op.Output(idx)
}
<|endoftext|>


<commit_before>package main

import (
	"math/rand"
	"time"
)

// Speeds
const slowestSpeed = 700 * time.Millisecond
const fastestSpeed = 60 * time.Millisecond

// Game play
const numSquares = 4
const numTypes = 7
const defaultLevel = 1
const maxLevel = 10
const rowsPerLevel = 5

// Pieces
var dxBank = [][]int{
	{},
	{0, 1, -1, 0},
	{0, 1, -1, -1},
	{0, 1, -1, 1},
	{0, -1, 1, 0},
	{0, 1, -1, 0},
	{0, 1, -1, -2},
	{0, 1, 1, 0},
}

var dyBank = [][]int{
	{},
	{0, 0, 0, 1},
	{0, 0, 0, 1},
	{0, 0, 0, 1},
	{0, 0, 1, 1},
	{0, 0, 1, 1},
	{0, 0, 0, 0},
	{0, 0, 1, 1},
}

type gameState int

const (
	gameIntro gameState = iota
	gameStarted
	gamePaused
	gameOver
)

// Struct Game contains all the game state.
type Game struct {
	board        [][]int // [y][x]
	state        gameState
	level        int
	numLines     int
	piece        int
	x            int
	y            int
	dx           []int
	dy           []int
	dxPrime      []int
	dyPrime      []int
	skyline      int
	fallingTimer *time.Timer
}

// NewGame returns a fully-initialized game.
func NewGame() *Game {
	g := new(Game)
	g.resetGame()
	return g
}

// Reset the game in order to play again.
func (g *Game) resetGame() {
	g.board = make([][]int, boardHeight)
	for y := 0; y < boardHeight; y++ {
		g.board[y] = make([]int, boardWidth)
		for x := 0; x < boardWidth; x++ {
			g.board[y][x] = 0
		}
	}

	g.state = gameIntro
	g.level = 1
	g.numLines = 0
	g.x = 1
	g.y = 1
	g.dx = []int{0, 0, 0, 0}
	g.dy = []int{0, 0, 0, 0}
	g.dxPrime = []int{0, 0, 0, 0}
	g.dyPrime = []int{0, 0, 0, 0}
	g.skyline = boardHeight - 1

	g.fallingTimer = time.NewTimer(time.Duration(1000000 * time.Second))
	g.fallingTimer.Stop()
}

// Set the timer to make the pieces fall again.
func (g *Game) resetFallingTimer() {
	g.fallingTimer.Reset(g.speed())
}

// Function speed calculates the speed based on the level.
func (g *Game) speed() time.Duration {
	return slowestSpeed - fastestSpeed*time.Duration(g.level)
}

// This gets called everytime g.fallingTimer goes off.
func (g *Game) play() {
	if g.moveDown() {
		g.resetFallingTimer()
	} else {
		g.lockPiece()
	}
}

func (g *Game) lockPiece() {
	g.fillMatrix()
	g.removeLines()
	if g.skyline > 0 && g.getPiece() {
		g.resetFallingTimer()
	} else {
		g.state = gameOver
	}
}

// This gets called as part of the piece falling.
func (g *Game) fillMatrix() {
	for k := 0; k < numSquares; k++ {
		x := g.x + g.dx[k]
		y := g.y + g.dy[k]
		if 0 <= y && y < boardHeight && 0 <= x && x < boardWidth {
			g.board[y][x] = g.piece
			if y < g.skyline {
				g.skyline = y
			}
		}
	}
}

// Look for completed lines and remove them.
func (g *Game) removeLines() {
	for y := 0; y < boardHeight; y++ {
		gapFound := false
		for x := 0; x < boardWidth; x++ {
			if g.board[y][x] == 0 {
				gapFound = true
				break
			}
		}
		if !gapFound {
			for k := y; k >= g.skyline; k-- {
				for x := 0; x < boardWidth; x++ {
					g.board[k][x] = g.board[k-1][x]
				}
			}
			for x := 0; x < boardWidth; x++ {
				g.board[0][x] = 0
			}
			g.numLines++
			g.skyline++
			if g.numLines%rowsPerLevel == 0 && g.level < maxLevel {
				g.level++
			}
		}
	}
}

// Return whether or not a piece fits.
func (g *Game) pieceFits(x, y int) bool {
	for k := 0; k < numSquares; k++ {
		theX := x + g.dxPrime[k]
		theY := y + g.dyPrime[k]
		if theX < 0 || theX >= boardWidth || theY >= boardHeight {
			return false
		}
		if theY > -1 && g.board[theY][theX] > 0 {
			return false
		}
	}
	return true
}

// This gets called when a piece moves to a new location.
func (g *Game) erasePiece() {
	for k := 0; k < numSquares; k++ {
		x := g.x + g.dx[k]
		y := g.y + g.dy[k]
		if 0 <= y && y < boardHeight && 0 <= x && x < boardWidth {
			g.board[y][x] = 0
		}
	}
}

// Place the piece in the board.
func (g *Game) placePiece() {
	for k := 0; k < numSquares; k++ {
		x := g.x + g.dx[k]
		y := g.y + g.dy[k]
		if 0 <= y && y < boardHeight && 0 <= x && x < boardWidth && g.board[y][x] != -g.piece {
			g.board[y][x] = -g.piece
		}
	}
}

// The user pressed the 's' key to start the game.
func (g *Game) start() {
	switch g.state {
	case gameStarted:
		return
	case gamePaused:
		g.resume()
		return
	case gameOver:
		g.resetGame()
		fallthrough
	default:
		g.state = gameStarted
		g.getPiece()
		g.placePiece()
		g.resetFallingTimer()
	}
}

// The user pressed the 'p' key to pause the game.
func (g *Game) pause() {
	switch g.state {
	case gameStarted:
		g.state = gamePaused
		g.fallingTimer.Stop()
	case gamePaused:
		g.resume()
	}
}

// The user pressed the left arrow.
func (g *Game) moveLeft() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if g.pieceFits(g.x-1, g.y) {
		g.erasePiece()
		g.x--
		g.placePiece()
	}
}

// The user pressed the right arrow.
func (g *Game) moveRight() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if g.pieceFits(g.x+1, g.y) {
		g.erasePiece()
		g.x++
		g.placePiece()
	}
}

// The user pressed the up arrow in order to rotate the piece.
func (g *Game) rotate() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dy[k]
		g.dyPrime[k] = -g.dx[k]
	}
	if g.pieceFits(g.x, g.y) {
		g.erasePiece()
		for k := 0; k < numSquares; k++ {
			g.dx[k] = g.dxPrime[k]
			g.dy[k] = g.dyPrime[k]
		}
		g.placePiece()
	}
}

// Move the piece downward if possible.
func (g *Game) moveDown() bool {
	if g.state != gameStarted {
		return false
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if !g.pieceFits(g.x, g.y+1) {
		return false
	}
	g.erasePiece()
	g.y++
	g.placePiece()
	return true
}

// The user pressed the space bar to make the piece fall.
func (g *Game) fall() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if !g.pieceFits(g.x, g.y+1) {
		return
	}
	g.fallingTimer.Stop()
	g.erasePiece()
	for g.pieceFits(g.x, g.y+1) {
		g.y++
	}
	g.placePiece()
	g.resetFallingTimer()
	g.lockPiece()
}

// Get a random piece and try to place it.
func (g *Game) getPiece() bool {
	g.piece = 1 + rand.Int()%numTypes
	g.x = boardWidth / 2
	g.y = 0
	for k := 0; k < numSquares; k++ {
		g.dx[k] = dxBank[g.piece][k]
		g.dy[k] = dyBank[g.piece][k]
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if !g.pieceFits(g.x, g.y) {
		return false
	}
	g.placePiece()
	return true
}

// Resume after pausing.
func (g *Game) resume() {
	g.state = gameStarted
	g.play()
}
<commit_msg>Added a comment<commit_after>package main

import (
	"math/rand"
	"time"
)

// Speeds
const slowestSpeed = 700 * time.Millisecond
const fastestSpeed = 60 * time.Millisecond

// Game play
const numSquares = 4
const numTypes = 7
const defaultLevel = 1
const maxLevel = 10
const rowsPerLevel = 5

// Pieces
var dxBank = [][]int{
	{},
	{0, 1, -1, 0},
	{0, 1, -1, -1},
	{0, 1, -1, 1},
	{0, -1, 1, 0},
	{0, 1, -1, 0},
	{0, 1, -1, -2},
	{0, 1, 1, 0},
}

var dyBank = [][]int{
	{},
	{0, 0, 0, 1},
	{0, 0, 0, 1},
	{0, 0, 0, 1},
	{0, 0, 1, 1},
	{0, 0, 1, 1},
	{0, 0, 0, 0},
	{0, 0, 1, 1},
}

type gameState int

const (
	gameIntro gameState = iota
	gameStarted
	gamePaused
	gameOver
)

// Struct Game contains all the game state.
type Game struct {
	board        [][]int // [y][x]
	state        gameState
	level        int
	numLines     int
	piece        int
	x            int
	y            int
	dx           []int
	dy           []int
	dxPrime      []int
	dyPrime      []int
	skyline      int
	fallingTimer *time.Timer
}

// NewGame returns a fully-initialized game.
func NewGame() *Game {
	g := new(Game)
	g.resetGame()
	return g
}

// Reset the game in order to play again.
func (g *Game) resetGame() {
	g.board = make([][]int, boardHeight)
	for y := 0; y < boardHeight; y++ {
		g.board[y] = make([]int, boardWidth)
		for x := 0; x < boardWidth; x++ {
			g.board[y][x] = 0
		}
	}

	g.state = gameIntro
	g.level = 1
	g.numLines = 0
	g.x = 1
	g.y = 1
	g.dx = []int{0, 0, 0, 0}
	g.dy = []int{0, 0, 0, 0}
	g.dxPrime = []int{0, 0, 0, 0}
	g.dyPrime = []int{0, 0, 0, 0}
	g.skyline = boardHeight - 1

	g.fallingTimer = time.NewTimer(time.Duration(1000000 * time.Second))
	g.fallingTimer.Stop()
}

// Set the timer to make the pieces fall again.
func (g *Game) resetFallingTimer() {
	g.fallingTimer.Reset(g.speed())
}

// Function speed calculates the speed based on the level.
func (g *Game) speed() time.Duration {
	return slowestSpeed - fastestSpeed*time.Duration(g.level)
}

// This gets called everytime g.fallingTimer goes off.
func (g *Game) play() {
	if g.moveDown() {
		g.resetFallingTimer()
	} else {
		g.lockPiece()
	}
}

// Pressing spacebar should immediately lock the piece at the bottom.
func (g *Game) lockPiece() {
	g.fillMatrix()
	g.removeLines()
	if g.skyline > 0 && g.getPiece() {
		g.resetFallingTimer()
	} else {
		g.state = gameOver
	}
}

// This gets called as part of the piece falling.
func (g *Game) fillMatrix() {
	for k := 0; k < numSquares; k++ {
		x := g.x + g.dx[k]
		y := g.y + g.dy[k]
		if 0 <= y && y < boardHeight && 0 <= x && x < boardWidth {
			g.board[y][x] = g.piece
			if y < g.skyline {
				g.skyline = y
			}
		}
	}
}

// Look for completed lines and remove them.
func (g *Game) removeLines() {
	for y := 0; y < boardHeight; y++ {
		gapFound := false
		for x := 0; x < boardWidth; x++ {
			if g.board[y][x] == 0 {
				gapFound = true
				break
			}
		}
		if !gapFound {
			for k := y; k >= g.skyline; k-- {
				for x := 0; x < boardWidth; x++ {
					g.board[k][x] = g.board[k-1][x]
				}
			}
			for x := 0; x < boardWidth; x++ {
				g.board[0][x] = 0
			}
			g.numLines++
			g.skyline++
			if g.numLines%rowsPerLevel == 0 && g.level < maxLevel {
				g.level++
			}
		}
	}
}

// Return whether or not a piece fits.
func (g *Game) pieceFits(x, y int) bool {
	for k := 0; k < numSquares; k++ {
		theX := x + g.dxPrime[k]
		theY := y + g.dyPrime[k]
		if theX < 0 || theX >= boardWidth || theY >= boardHeight {
			return false
		}
		if theY > -1 && g.board[theY][theX] > 0 {
			return false
		}
	}
	return true
}

// This gets called when a piece moves to a new location.
func (g *Game) erasePiece() {
	for k := 0; k < numSquares; k++ {
		x := g.x + g.dx[k]
		y := g.y + g.dy[k]
		if 0 <= y && y < boardHeight && 0 <= x && x < boardWidth {
			g.board[y][x] = 0
		}
	}
}

// Place the piece in the board.
func (g *Game) placePiece() {
	for k := 0; k < numSquares; k++ {
		x := g.x + g.dx[k]
		y := g.y + g.dy[k]
		if 0 <= y && y < boardHeight && 0 <= x && x < boardWidth && g.board[y][x] != -g.piece {
			g.board[y][x] = -g.piece
		}
	}
}

// The user pressed the 's' key to start the game.
func (g *Game) start() {
	switch g.state {
	case gameStarted:
		return
	case gamePaused:
		g.resume()
		return
	case gameOver:
		g.resetGame()
		fallthrough
	default:
		g.state = gameStarted
		g.getPiece()
		g.placePiece()
		g.resetFallingTimer()
	}
}

// The user pressed the 'p' key to pause the game.
func (g *Game) pause() {
	switch g.state {
	case gameStarted:
		g.state = gamePaused
		g.fallingTimer.Stop()
	case gamePaused:
		g.resume()
	}
}

// The user pressed the left arrow.
func (g *Game) moveLeft() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if g.pieceFits(g.x-1, g.y) {
		g.erasePiece()
		g.x--
		g.placePiece()
	}
}

// The user pressed the right arrow.
func (g *Game) moveRight() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if g.pieceFits(g.x+1, g.y) {
		g.erasePiece()
		g.x++
		g.placePiece()
	}
}

// The user pressed the up arrow in order to rotate the piece.
func (g *Game) rotate() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dy[k]
		g.dyPrime[k] = -g.dx[k]
	}
	if g.pieceFits(g.x, g.y) {
		g.erasePiece()
		for k := 0; k < numSquares; k++ {
			g.dx[k] = g.dxPrime[k]
			g.dy[k] = g.dyPrime[k]
		}
		g.placePiece()
	}
}

// Move the piece downward if possible.
func (g *Game) moveDown() bool {
	if g.state != gameStarted {
		return false
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if !g.pieceFits(g.x, g.y+1) {
		return false
	}
	g.erasePiece()
	g.y++
	g.placePiece()
	return true
}

// The user pressed the space bar to make the piece fall.
func (g *Game) fall() {
	if g.state != gameStarted {
		return
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if !g.pieceFits(g.x, g.y+1) {
		return
	}
	g.fallingTimer.Stop()
	g.erasePiece()
	for g.pieceFits(g.x, g.y+1) {
		g.y++
	}
	g.placePiece()
	g.resetFallingTimer()
	g.lockPiece()
}

// Get a random piece and try to place it.
func (g *Game) getPiece() bool {
	g.piece = 1 + rand.Int()%numTypes
	g.x = boardWidth / 2
	g.y = 0
	for k := 0; k < numSquares; k++ {
		g.dx[k] = dxBank[g.piece][k]
		g.dy[k] = dyBank[g.piece][k]
	}
	for k := 0; k < numSquares; k++ {
		g.dxPrime[k] = g.dx[k]
		g.dyPrime[k] = g.dy[k]
	}
	if !g.pieceFits(g.x, g.y) {
		return false
	}
	g.placePiece()
	return true
}

// Resume after pausing.
func (g *Game) resume() {
	g.state = gameStarted
	g.play()
}
<|endoftext|>


<commit_before>package ethcrypto

import (
	"github.com/ethereum/eth-go/ethutil"
	"github.com/obscuren/secp256k1-go"
)

type KeyPair struct {
	PrivateKey []byte
	PublicKey  []byte

	// The associated account
	// account *StateObject
}

func GenerateNewKeyPair() *KeyPair {
	_, prv := secp256k1.GenerateKeyPair()
	keyPair, _ := NewKeyPairFromSec(prv) // swallow error, this one cannot err
	return keyPair
}

func NewKeyPairFromSec(seckey []byte) (*KeyPair, error) {
	pubkey, err := secp256k1.GeneratePubKey(seckey)
	if err != nil {
		return nil, err
	}

	return &KeyPair{PrivateKey: seckey, PublicKey: pubkey}, nil
}

func (k *KeyPair) Address() []byte {
	return Sha3Bin(k.PublicKey[1:])[12:]
}

func (k *KeyPair) RlpEncode() []byte {
	return k.RlpValue().Encode()
}

func (k *KeyPair) RlpValue() *ethutil.Value {
	return ethutil.NewValue(k.PrivateKey)
}
<commit_msg>added Mnemonic() and AsStrings() methods, added memoization for address<commit_after>package ethcrypto

import (
	"github.com/ethereum/eth-go/ethutil"
	"github.com/obscuren/secp256k1-go"
	"strings"
)

type KeyPair struct {
	PrivateKey []byte
	PublicKey  []byte
	address    []byte
	mnemonic   string
	// The associated account
	// account *StateObject
}

func GenerateNewKeyPair() *KeyPair {
	_, prv := secp256k1.GenerateKeyPair()
	keyPair, _ := NewKeyPairFromSec(prv) // swallow error, this one cannot err
	return keyPair
}

func NewKeyPairFromSec(seckey []byte) (*KeyPair, error) {
	pubkey, err := secp256k1.GeneratePubKey(seckey)
	if err != nil {
		return nil, err
	}

	return &KeyPair{PrivateKey: seckey, PublicKey: pubkey}, nil
}

func (k *KeyPair) Address() []byte {
	if k.address == nil {
		k.address = Sha3Bin(k.PublicKey[1:])[12:]
	}
	return k.address
}

func (k *KeyPair) Mnemonic() string {
	if k.mnemonic == "" {
		k.mnemonic = strings.Join(MnemonicEncode(ethutil.Bytes2Hex(k.PrivateKey)), " ")
	}
	return k.mnemonic
}

func (k *KeyPair) AsStrings() (string, string, string, string) {
	return k.Mnemonic(), ethutil.Bytes2Hex(k.Address()), ethutil.Bytes2Hex(k.PrivateKey), ethutil.Bytes2Hex(k.PublicKey)
}

func (k *KeyPair) RlpEncode() []byte {
	return k.RlpValue().Encode()
}

func (k *KeyPair) RlpValue() *ethutil.Value {
	return ethutil.NewValue(k.PrivateKey)
}
<|endoftext|>


<commit_before>// Package ethwire provides low level access to the Ethereum network and allows
// you to broadcast data over the network.
package ethwire

import (
	"bytes"
	"fmt"
	"net"
	"time"

	"github.com/ethereum/eth-go/ethutil"
)

// Connection interface describing the methods required to implement the wire protocol.
type Conn interface {
	Write(typ MsgType, v ...interface{}) error
	Read() *Msg
}

// The magic token which should be the first 4 bytes of every message and can be used as separator between messages.
var MagicToken = []byte{34, 64, 8, 145}

type MsgType byte

const (
	// Values are given explicitly instead of by iota because these values are
	// defined by the wire protocol spec; it is easier for humans to ensure
	// correctness when values are explicit.
	MsgHandshakeTy = 0x00
	MsgDiscTy      = 0x01
	MsgPingTy      = 0x02
	MsgPongTy      = 0x03
	MsgGetPeersTy  = 0x04
	MsgPeersTy     = 0x05

	MsgStatusTy         = 0x10
	MsgGetTxsTy         = 0x11
	MsgTxTy             = 0x12
	MsgGetBlockHashesTy = 0x13
	MsgBlockHashesTy    = 0x14
	MsgGetBlocksTy      = 0x15
	MsgBlockTy          = 0x16
)

var msgTypeToString = map[MsgType]string{
	MsgHandshakeTy:      "Handshake",
	MsgDiscTy:           "Disconnect",
	MsgPingTy:           "Ping",
	MsgPongTy:           "Pong",
	MsgGetPeersTy:       "Get peers",
	MsgStatusTy:         "Status",
	MsgPeersTy:          "Peers",
	MsgTxTy:             "Transactions",
	MsgBlockTy:          "Blocks",
	MsgGetTxsTy:         "Get Txs",
	MsgGetBlockHashesTy: "Get block hashes",
	MsgBlockHashesTy:    "Block hashes",
	MsgGetBlocksTy:      "Get blocks",
}

func (mt MsgType) String() string {
	return msgTypeToString[mt]
}

type Msg struct {
	Type MsgType // Specifies how the encoded data should be interpreted
	//Data []byte
	Data *ethutil.Value
}

func NewMessage(msgType MsgType, data interface{}) *Msg {
	return &Msg{
		Type: msgType,
		Data: ethutil.NewValue(data),
	}
}

type Messages []*Msg

// The basic message reader waits for data on the given connection, decoding
// and doing a few sanity checks such as if there's a data type and
// unmarhals the given data
func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
	// The recovering function in case anything goes horribly wrong
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("ethwire.ReadMessage error: %v", r)
		}
	}()

	var (
		buff      []byte
		messages  [][]byte
		msgLength int
	)

	for {
		// Give buffering some time
		conn.SetReadDeadline(time.Now().Add(5 * time.Millisecond))
		// Create a new temporarily buffer
		b := make([]byte, 1440)
		n, _ := conn.Read(b)
		if err != nil && n == 0 {
			if err.Error() != "EOF" {
				fmt.Println("err now", err)
				return nil, err
			} else {
				break
			}
		}

		if n == 0 && len(buff) == 0 {
			continue
		}

		buff = append(buff, b[:n]...)
		if msgLength == 0 {
			// Check if the received 4 first bytes are the magic token
			if bytes.Compare(MagicToken, buff[:4]) != 0 {
				return nil, fmt.Errorf("MagicToken mismatch. Received %v", buff[:4])
			}

			// Read the length of the message
			msgLength = int(ethutil.BytesToNumber(buff[4:8]))

			// Remove the token and length
			buff = buff[8:]
		}

		if len(buff) >= msgLength {
			messages = append(messages, buff[:msgLength])
			buff = buff[msgLength:]
			msgLength = 0

			if len(buff) == 0 {
				break
			}
		}
	}

	for _, m := range messages {
		decoder := ethutil.NewValueFromBytes(m)
		// Type of message
		t := decoder.Get(0).Uint()
		// Actual data
		d := decoder.SliceFrom(1)

		msgs = append(msgs, &Msg{Type: MsgType(t), Data: d})
	}

	return
}

// The basic message writer takes care of writing data over the given
// connection and does some basic error checking
func WriteMessage(conn net.Conn, msg *Msg) error {
	var pack []byte

	// Encode the type and the (RLP encoded) data for sending over the wire
	encoded := ethutil.NewValue(append([]interface{}{byte(msg.Type)}, msg.Data.Slice()...)).Encode()
	payloadLength := ethutil.NumberToBytes(uint32(len(encoded)), 32)

	// Write magic token and payload length (first 8 bytes)
	pack = append(MagicToken, payloadLength...)
	pack = append(pack, encoded...)
	//fmt.Printf("payload %v (%v) %q\n", msg.Type, conn.RemoteAddr(), encoded)

	// Write to the connection
	_, err := conn.Write(pack)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Up deadline to reduce cpu load<commit_after>// Package ethwire provides low level access to the Ethereum network and allows
// you to broadcast data over the network.
package ethwire

import (
	"bytes"
	"fmt"
	"net"
	"time"

	"github.com/ethereum/eth-go/ethutil"
)

// Connection interface describing the methods required to implement the wire protocol.
type Conn interface {
	Write(typ MsgType, v ...interface{}) error
	Read() *Msg
}

// The magic token which should be the first 4 bytes of every message and can be used as separator between messages.
var MagicToken = []byte{34, 64, 8, 145}

type MsgType byte

const (
	// Values are given explicitly instead of by iota because these values are
	// defined by the wire protocol spec; it is easier for humans to ensure
	// correctness when values are explicit.
	MsgHandshakeTy = 0x00
	MsgDiscTy      = 0x01
	MsgPingTy      = 0x02
	MsgPongTy      = 0x03
	MsgGetPeersTy  = 0x04
	MsgPeersTy     = 0x05

	MsgStatusTy         = 0x10
	MsgGetTxsTy         = 0x11
	MsgTxTy             = 0x12
	MsgGetBlockHashesTy = 0x13
	MsgBlockHashesTy    = 0x14
	MsgGetBlocksTy      = 0x15
	MsgBlockTy          = 0x16
)

var msgTypeToString = map[MsgType]string{
	MsgHandshakeTy:      "Handshake",
	MsgDiscTy:           "Disconnect",
	MsgPingTy:           "Ping",
	MsgPongTy:           "Pong",
	MsgGetPeersTy:       "Get peers",
	MsgStatusTy:         "Status",
	MsgPeersTy:          "Peers",
	MsgTxTy:             "Transactions",
	MsgBlockTy:          "Blocks",
	MsgGetTxsTy:         "Get Txs",
	MsgGetBlockHashesTy: "Get block hashes",
	MsgBlockHashesTy:    "Block hashes",
	MsgGetBlocksTy:      "Get blocks",
}

func (mt MsgType) String() string {
	return msgTypeToString[mt]
}

type Msg struct {
	Type MsgType // Specifies how the encoded data should be interpreted
	//Data []byte
	Data *ethutil.Value
}

func NewMessage(msgType MsgType, data interface{}) *Msg {
	return &Msg{
		Type: msgType,
		Data: ethutil.NewValue(data),
	}
}

type Messages []*Msg

// The basic message reader waits for data on the given connection, decoding
// and doing a few sanity checks such as if there's a data type and
// unmarhals the given data
func ReadMessages(conn net.Conn) (msgs []*Msg, err error) {
	// The recovering function in case anything goes horribly wrong
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("ethwire.ReadMessage error: %v", r)
		}
	}()

	var (
		buff      []byte
		messages  [][]byte
		msgLength int
	)

	for {
		// Give buffering some time
		conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
		// Create a new temporarily buffer
		b := make([]byte, 1440)
		n, _ := conn.Read(b)
		if err != nil && n == 0 {
			if err.Error() != "EOF" {
				fmt.Println("err now", err)
				return nil, err
			} else {
				break
			}
		}

		if n == 0 && len(buff) == 0 {
			continue
		}

		buff = append(buff, b[:n]...)
		if msgLength == 0 {
			// Check if the received 4 first bytes are the magic token
			if bytes.Compare(MagicToken, buff[:4]) != 0 {
				return nil, fmt.Errorf("MagicToken mismatch. Received %v", buff[:4])
			}

			// Read the length of the message
			msgLength = int(ethutil.BytesToNumber(buff[4:8]))

			// Remove the token and length
			buff = buff[8:]
		}

		if len(buff) >= msgLength {
			messages = append(messages, buff[:msgLength])
			buff = buff[msgLength:]
			msgLength = 0

			if len(buff) == 0 {
				break
			}
		}
	}

	for _, m := range messages {
		decoder := ethutil.NewValueFromBytes(m)
		// Type of message
		t := decoder.Get(0).Uint()
		// Actual data
		d := decoder.SliceFrom(1)

		msgs = append(msgs, &Msg{Type: MsgType(t), Data: d})
	}

	return
}

// The basic message writer takes care of writing data over the given
// connection and does some basic error checking
func WriteMessage(conn net.Conn, msg *Msg) error {
	var pack []byte

	// Encode the type and the (RLP encoded) data for sending over the wire
	encoded := ethutil.NewValue(append([]interface{}{byte(msg.Type)}, msg.Data.Slice()...)).Encode()
	payloadLength := ethutil.NumberToBytes(uint32(len(encoded)), 32)

	// Write magic token and payload length (first 8 bytes)
	pack = append(MagicToken, payloadLength...)
	pack = append(pack, encoded...)
	//fmt.Printf("payload %v (%v) %q\n", msg.Type, conn.RemoteAddr(), encoded)

	// Write to the connection
	_, err := conn.Write(pack)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>