<commit_before>package main

import (
	"fmt"
	"github.com/spf13/cobra"
)

type Options struct {
	verbose  bool
	force    bool
	kill     bool
	config   string
	manifest string
	group    string
}

var options = Options{
	false,
	false,
	false,
	"",
	"",
	"",
}
var defaultManifests = []string{"crane.json", "crane.yaml", "crane.yml", "Cranefile"}

func manifestFiles() []string {
	var result = []string(nil)
	if len(options.manifest) > 0 {
		result = []string{options.manifest}
	} else {
		result = defaultManifests
	}
	return result
}

func isVerbose() bool {
	return options.verbose
}

// returns a function to be set as a cobra command run, wrapping a command meant to be run on a set of containers
func containersCommand(wrapped func(containers Containers)) func(cmd *cobra.Command, args []string) {
	return func(cmd *cobra.Command, args []string) {
		if len(args) > 0 {
			cmd.Printf("Error: too many arguments given: %#q", args)
			cmd.Usage()
			return
		}
		containers := getContainers(options)
		wrapped(containers)
	}
}

func handleCmd() {

	var cmdLift = &cobra.Command{
		Use:   "lift",
		Short: "Build or pull images, then run or start the containers",
		Long: `
lift will use specified Dockerfiles to build all the containers, or the specified one(s).
If no Dockerfile is given, it will pull the image(s) from the given registry.`,
		Run: containersCommand(func(containers Containers) {
			containers.lift(options.force, options.kill)
		}),
	}

	var cmdProvision = &cobra.Command{
		Use:   "provision",
		Short: "Build or pull images",
		Long: `
provision will use specified Dockerfiles to build all the containers, or the specified one(s).
If no Dockerfile is given, it will pull the image(s) from the given registry.`,
		Run: containersCommand(func(containers Containers) {
			containers.provision(options.force)
		}),
	}

	var cmdRun = &cobra.Command{
		Use:   "run",
		Short: "Run the containers",
		Long:  `run will call docker run on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.run(options.force, options.kill)
		}),
	}

	var cmdRm = &cobra.Command{
		Use:   "rm",
		Short: "Remove the containers",
		Long:  `rm will call docker rm on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.rm(options.force, options.kill)
		}),
	}

	var cmdKill = &cobra.Command{
		Use:   "kill",
		Short: "Kill the containers",
		Long:  `kill will call docker kill on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.kill()
		}),
	}

	var cmdStart = &cobra.Command{
		Use:   "start",
		Short: "Start the containers",
		Long:  `start will call docker start on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.start()
		}),
	}

	var cmdStop = &cobra.Command{
		Use:   "stop",
		Short: "Stop the containers",
		Long:  `stop will call docker stop on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.stop()
		}),
	}

	var cmdStatus = &cobra.Command{
		Use:   "status",
		Short: "Displays status of containers",
		Long:  `Displays the current status of all the containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.status()
		}),
	}

	var cmdVersion = &cobra.Command{
		Use:   "version",
		Short: "Display version",
		Long:  `Displays the version of Crane.`,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("v0.7.0")
		},
	}

	var craneCmd = &cobra.Command{
		Use:   "crane",
		Short: "crane - Lift containers with ease",
		Long: `
Crane is a little tool to orchestrate Docker containers.
It works by reading in JSON or YAML (either from crane.json, crane.yaml, the string specified in --config, or a json or yml file specified by --manifest) which describes how to obtain container images and how to run them.
See the corresponding docker commands for more information.`,
	}

	craneCmd.PersistentFlags().BoolVarP(&options.verbose, "verbose", "v", false, "verbose output")
	craneCmd.PersistentFlags().StringVarP(&options.config, "config", "c", "", "config to read from")
	craneCmd.PersistentFlags().StringVarP(&options.manifest, "manifest", "m", "", "config file to read from")
	craneCmd.PersistentFlags().StringVarP(&options.group, "group", "g", "", "group or container to restrict the command to")
	cmdLift.Flags().BoolVarP(&options.force, "force", "f", false, "rebuild all images")
	cmdLift.Flags().BoolVarP(&options.kill, "kill", "k", false, "kill containers")
	cmdProvision.Flags().BoolVarP(&options.force, "force", "f", false, "rebuild all images")
	cmdRun.Flags().BoolVarP(&options.force, "force", "f", false, "stop and remove running containers first")
	cmdRun.Flags().BoolVarP(&options.kill, "kill", "k", false, "when using --force, kill containers instead of stopping them")
	cmdRm.Flags().BoolVarP(&options.force, "force", "f", false, "stop running containers first")
	cmdRm.Flags().BoolVarP(&options.kill, "kill", "k", false, "when using --force, kill containers instead of stopping them")
	craneCmd.AddCommand(cmdLift, cmdProvision, cmdRun, cmdRm, cmdKill, cmdStart, cmdStop, cmdStatus, cmdVersion)
	err := craneCmd.Execute()
	if err != nil {
		panic(StatusError{status: 64})
	}
}
<commit_msg>USAGE for unused arguments<commit_after>package main

import (
	"fmt"
	"github.com/spf13/cobra"
)

type Options struct {
	verbose  bool
	force    bool
	kill     bool
	config   string
	manifest string
	group    string
}

var options = Options{
	false,
	false,
	false,
	"",
	"",
	"",
}
var defaultManifests = []string{"crane.json", "crane.yaml", "crane.yml", "Cranefile"}

func manifestFiles() []string {
	var result = []string(nil)
	if len(options.manifest) > 0 {
		result = []string{options.manifest}
	} else {
		result = defaultManifests
	}
	return result
}

func isVerbose() bool {
	return options.verbose
}

// returns a function to be set as a cobra command run, wrapping a command meant to be run on a set of containers
func containersCommand(wrapped func(containers Containers)) func(cmd *cobra.Command, args []string) {
	return func(cmd *cobra.Command, args []string) {
		if len(args) > 0 {
			cmd.Printf("Error: too many arguments given: %#q", args)
			cmd.Usage()
			panic(StatusError{status: 64})
		}
		containers := getContainers(options)
		wrapped(containers)
	}
}

func handleCmd() {

	var cmdLift = &cobra.Command{
		Use:   "lift",
		Short: "Build or pull images, then run or start the containers",
		Long: `
lift will use specified Dockerfiles to build all the containers, or the specified one(s).
If no Dockerfile is given, it will pull the image(s) from the given registry.`,
		Run: containersCommand(func(containers Containers) {
			containers.lift(options.force, options.kill)
		}),
	}

	var cmdProvision = &cobra.Command{
		Use:   "provision",
		Short: "Build or pull images",
		Long: `
provision will use specified Dockerfiles to build all the containers, or the specified one(s).
If no Dockerfile is given, it will pull the image(s) from the given registry.`,
		Run: containersCommand(func(containers Containers) {
			containers.provision(options.force)
		}),
	}

	var cmdRun = &cobra.Command{
		Use:   "run",
		Short: "Run the containers",
		Long:  `run will call docker run on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.run(options.force, options.kill)
		}),
	}

	var cmdRm = &cobra.Command{
		Use:   "rm",
		Short: "Remove the containers",
		Long:  `rm will call docker rm on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.rm(options.force, options.kill)
		}),
	}

	var cmdKill = &cobra.Command{
		Use:   "kill",
		Short: "Kill the containers",
		Long:  `kill will call docker kill on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.kill()
		}),
	}

	var cmdStart = &cobra.Command{
		Use:   "start",
		Short: "Start the containers",
		Long:  `start will call docker start on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.start()
		}),
	}

	var cmdStop = &cobra.Command{
		Use:   "stop",
		Short: "Stop the containers",
		Long:  `stop will call docker stop on all containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.stop()
		}),
	}

	var cmdStatus = &cobra.Command{
		Use:   "status",
		Short: "Displays status of containers",
		Long:  `Displays the current status of all the containers, or the specified one(s).`,
		Run: containersCommand(func(containers Containers) {
			containers.status()
		}),
	}

	var cmdVersion = &cobra.Command{
		Use:   "version",
		Short: "Display version",
		Long:  `Displays the version of Crane.`,
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("v0.7.0")
		},
	}

	var craneCmd = &cobra.Command{
		Use:   "crane",
		Short: "crane - Lift containers with ease",
		Long: `
Crane is a little tool to orchestrate Docker containers.
It works by reading in JSON or YAML (either from crane.json, crane.yaml, the string specified in --config, or a json or yml file specified by --manifest) which describes how to obtain container images and how to run them.
See the corresponding docker commands for more information.`,
	}

	craneCmd.PersistentFlags().BoolVarP(&options.verbose, "verbose", "v", false, "verbose output")
	craneCmd.PersistentFlags().StringVarP(&options.config, "config", "c", "", "config to read from")
	craneCmd.PersistentFlags().StringVarP(&options.manifest, "manifest", "m", "", "config file to read from")
	craneCmd.PersistentFlags().StringVarP(&options.group, "group", "g", "", "group or container to restrict the command to")
	cmdLift.Flags().BoolVarP(&options.force, "force", "f", false, "rebuild all images")
	cmdLift.Flags().BoolVarP(&options.kill, "kill", "k", false, "kill containers")
	cmdProvision.Flags().BoolVarP(&options.force, "force", "f", false, "rebuild all images")
	cmdRun.Flags().BoolVarP(&options.force, "force", "f", false, "stop and remove running containers first")
	cmdRun.Flags().BoolVarP(&options.kill, "kill", "k", false, "when using --force, kill containers instead of stopping them")
	cmdRm.Flags().BoolVarP(&options.force, "force", "f", false, "stop running containers first")
	cmdRm.Flags().BoolVarP(&options.kill, "kill", "k", false, "when using --force, kill containers instead of stopping them")
	craneCmd.AddCommand(cmdLift, cmdProvision, cmdRun, cmdRm, cmdKill, cmdStart, cmdStop, cmdStatus, cmdVersion)
	err := craneCmd.Execute()
	if err != nil {
		panic(StatusError{status: 64})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/brnstz/bus/common"
	"github.com/brnstz/bus/models"
)

func floatOrDie(w http.ResponseWriter, r *http.Request, name string) (f float64, err error) {

	val := r.FormValue(name)
	f, err = strconv.ParseFloat(val, 64)
	if err != nil {
		log.Println("bad float value", val, err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	return
}

func getStops(w http.ResponseWriter, r *http.Request) {
	lat, err := floatOrDie(w, r, "lat")
	if err != nil {
		return
	}

	lon, err := floatOrDie(w, r, "lon")
	if err != nil {
		return
	}

	miles, err := floatOrDie(w, r, "miles")
	if err != nil {
		return
	}

	filter := r.FormValue("filter")

	meters := common.MileToMeter(miles)

	stops, err := models.GetStopsByLoc(common.DB, lat, lon, meters, filter)
	if err != nil {
		log.Println("can't get stops", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, err := json.Marshal(stops)
	if err != nil {
		log.Println("can't marshal to json", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Write(b)
}

func getUI(w http.ResponseWriter, r *http.Request) {
	ui := []byte(`
		<!DOCTYPE html>

		Latitude: <input type="text" id="lat" name="lat">

		Longitude: <input type="text" id="lon" name="lon">

		Filter:
			<select id="filter">
				<option value="">Subway and bus</option>
				<option value="subway">Subway only</option>
				<option value="bus">Bus only</option>
			</select>

		Radius: <input type="text" id="miles" value="0.2"> miles

		<button onclick="getLocation()">Detect location</button>

		<button onclick="setLocation(40.758895,-73.985131, 0.2)">Times Square</button>

		<button onclick="setLocation(40.7236448,-74.0006793, 0.2)">SoHo</button>

		<button onclick="setLocation(40.7293373,-73.9458161, 0.2)">Greenpoint</button>

		<button onclick="setLocation(40.6825236,-73.9750134, 0.2)">Barclays Center</button>

		<button onclick="setLocation(40.84932,-73.877154,15, 0.2)">Bronx Zoo</button>

		<button onclick="setLocation(40.7501217,-73.8463344, 0.3)">US Open</button>

		<button onclick="setLocation(40.5031274,-74.253251, 0.3)">Conference House Park</button>

		<button onclick="getTrips()">Get upcoming trips</button>

	`)
	w.Write(ui)
}

func main() {
	log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)

	//go loader.LoadForever()

	http.HandleFunc("/api/v1/stops", getStops)
	http.HandleFunc("/", getUI)

	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", os.Getenv("BUS_API_PORT")), nil))

}
<commit_msg>fix miles setting<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"strconv"

	"github.com/brnstz/bus/common"
	"github.com/brnstz/bus/models"
)

func floatOrDie(w http.ResponseWriter, r *http.Request, name string) (f float64, err error) {

	val := r.FormValue(name)
	f, err = strconv.ParseFloat(val, 64)
	if err != nil {
		log.Println("bad float value", val, err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	return
}

func getStops(w http.ResponseWriter, r *http.Request) {
	lat, err := floatOrDie(w, r, "lat")
	if err != nil {
		return
	}

	lon, err := floatOrDie(w, r, "lon")
	if err != nil {
		return
	}

	miles, err := floatOrDie(w, r, "miles")
	if err != nil {
		return
	}

	filter := r.FormValue("filter")

	meters := common.MileToMeter(miles)

	stops, err := models.GetStopsByLoc(common.DB, lat, lon, meters, filter)
	if err != nil {
		log.Println("can't get stops", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	b, err := json.Marshal(stops)
	if err != nil {
		log.Println("can't marshal to json", err)
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Write(b)
}

func getUI(w http.ResponseWriter, r *http.Request) {
	ui := []byte(`
		<!DOCTYPE html>

		Latitude: <input type="text" id="lat" name="lat">

		Longitude: <input type="text" id="lon" name="lon">

		Filter:
			<select id="filter">
				<option value="">Subway and bus</option>
				<option value="subway">Subway only</option>
				<option value="bus">Bus only</option>
			</select>

		Radius: <input type="text" id="miles" value="0.2"> miles

		<button onclick="getLocation()">Detect location</button>

		<button onclick="setLocation(40.758895,-73.985131, 0.2)">Times Square</button>

		<button onclick="setLocation(40.7236448,-74.0006793, 0.2)">SoHo</button>

		<button onclick="setLocation(40.7293373,-73.9458161, 0.2)">Greenpoint</button>

		<button onclick="setLocation(40.6825236,-73.9750134, 0.2)">Barclays Center</button>

		<button onclick="setLocation(40.84932,-73.877154, 0.2)">Bronx Zoo</button>

		<button onclick="setLocation(40.7501217,-73.8463344, 0.3)">US Open</button>

		<button onclick="setLocation(40.5031274,-74.253251, 0.3)">Conference House Park</button>

		<button onclick="getTrips()">Get upcoming trips</button>

	`)
	w.Write(ui)
}

func main() {
	log.SetFlags(log.Lshortfile | log.Ldate | log.Ltime)

	//go loader.LoadForever()

	http.HandleFunc("/api/v1/stops", getStops)
	http.HandleFunc("/", getUI)

	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", os.Getenv("BUS_API_PORT")), nil))

}
<|endoftext|>


<commit_before>package activity

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"

	"github.com/koding/bongo"
)

func GetPinnedActivityChannel(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(fmt.Errorf("Account id is not set for fetching pinned activity channel"))
	}

	return helpers.HandleResultAndError(
		ensurePinnedActivityChannel(
			query.AccountId,
			query.GroupName,
		),
	)
}

func checkPinMessagePrerequisites(channel *models.Channel, pinRequest *models.PinRequest) error {
	if channel.TypeConstant != models.Channel_TYPE_PINNED_ACTIVITY {
		return errors.New("You can not add pinned message into this channel")
	}

	if channel.GroupName != pinRequest.GroupName {
		return errors.New("Grop name and channel group name doesnt match")
	}

	if channel.CreatorId != pinRequest.AccountId {
		return errors.New("Only owner can add new pinned message into this channel")
	}

	return nil
}

func PinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(c.AddMessage(req.MessageId))
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(errors.New("Account id is not set for fetching pinned activities"))
	}

	c, err := ensurePinnedActivityChannel(query.AccountId, query.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if c.CreatorId != query.AccountId {
		return helpers.NewBadRequestResponse(errors.New("Only owner can list pinned messages"))
	}

	cml := models.NewChannelMessageList()
	cml.ChannelId = c.Id
	return helpers.HandleResultAndError(cml.List(query))
}

func UnpinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		c.RemoveMessage(req.MessageId),
	)
}

func validatePinRequest(req *models.PinRequest) error {
	if req.MessageId == 0 {
		return errors.New("Message id is not set")
	}

	if req.AccountId == 0 {
		return errors.New("Account id is not set")
	}

	if req.GroupName == "" {
		return errors.New("Group name is not set")
	}

	return nil
}

func ensurePinnedActivityChannel(accountId int64, groupName string) (*models.Channel, error) {
	c := models.NewChannel()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"creator_id":    accountId,
			"group_name":    groupName,
			"type_constant": models.Channel_TYPE_PINNED_ACTIVITY,
		},
		Pagination: *bongo.NewPagination(1, 0),
	}

	if err := c.Some(c, query); err != nil {
		return nil, err
	}

	// if we found the channel
	// return early
	if c.Id != 0 {
		return c, nil
	}

	c.Name = "PinnedActivity"
	c.CreatorId = accountId
	c.GroupName = groupName
	c.Purpose = "Pinned Activity"
	c.TypeConstant = models.Channel_TYPE_PINNED_ACTIVITY
	c.PrivacyConstant = models.Channel_PRIVACY_PRIVATE
	if err := c.Create(); err != nil {
		return nil, err
	}

	// after creating pinned channel
	// add user a participant
	// todo add test for this case
	_, err := c.AddParticipant(accountId)
	if err != nil {
		return nil, err
	}

	return c, nil
}
<commit_msg>Social: update documentation<commit_after>package activity

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/models"
	"socialapi/workers/api/modules/helpers"

	"github.com/koding/bongo"
)

func GetPinnedActivityChannel(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(fmt.Errorf("Account id is not set for fetching pinned activity channel"))
	}

	return helpers.HandleResultAndError(
		ensurePinnedActivityChannel(
			query.AccountId,
			query.GroupName,
		),
	)
}

func checkPinMessagePrerequisites(channel *models.Channel, pinRequest *models.PinRequest) error {
	if channel.TypeConstant != models.Channel_TYPE_PINNED_ACTIVITY {
		return errors.New("You can not add pinned message into this channel")
	}

	if channel.GroupName != pinRequest.GroupName {
		return errors.New("Grop name and channel group name doesnt match")
	}

	if channel.CreatorId != pinRequest.AccountId {
		return errors.New("Only owner can add new pinned message into this channel")
	}

	return nil
}

func PinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(c.AddMessage(req.MessageId))
}

func List(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	query := helpers.GetQuery(u)

	if query.AccountId == 0 {
		return helpers.NewBadRequestResponse(errors.New("Account id is not set for fetching pinned activities"))
	}

	c, err := ensurePinnedActivityChannel(query.AccountId, query.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if c.CreatorId != query.AccountId {
		return helpers.NewBadRequestResponse(errors.New("Only owner can list pinned messages"))
	}

	cml := models.NewChannelMessageList()
	cml.ChannelId = c.Id
	return helpers.HandleResultAndError(cml.List(query))
}

func UnpinMessage(u *url.URL, h http.Header, req *models.PinRequest) (int, http.Header, interface{}, error) {
	if err := validatePinRequest(req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	c, err := ensurePinnedActivityChannel(req.AccountId, req.GroupName)
	if err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	if err := checkPinMessagePrerequisites(c, req); err != nil {
		return helpers.NewBadRequestResponse(err)
	}

	return helpers.HandleResultAndError(
		c.RemoveMessage(req.MessageId),
	)
}

func validatePinRequest(req *models.PinRequest) error {
	if req.MessageId == 0 {
		return errors.New("Message id is not set")
	}

	if req.AccountId == 0 {
		return errors.New("Account id is not set")
	}

	if req.GroupName == "" {
		return errors.New("Group name is not set")
	}

	return nil
}

func ensurePinnedActivityChannel(accountId int64, groupName string) (*models.Channel, error) {
	c := models.NewChannel()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"creator_id":    accountId,
			"group_name":    groupName,
			"type_constant": models.Channel_TYPE_PINNED_ACTIVITY,
		},
		Pagination: *bongo.NewPagination(1, 0),
	}

	if err := c.Some(c, query); err != nil {
		return nil, err
	}

	// if we find the channel
	// return early
	if c.Id != 0 {
		return c, nil
	}

	c.Name = "PinnedActivity"
	c.CreatorId = accountId
	c.GroupName = groupName
	c.Purpose = "Pinned Activity"
	c.TypeConstant = models.Channel_TYPE_PINNED_ACTIVITY
	c.PrivacyConstant = models.Channel_PRIVACY_PRIVATE
	if err := c.Create(); err != nil {
		return nil, err
	}

	// after creating pinned channel
	// add user a participant
	// todo add test for this case
	_, err := c.AddParticipant(accountId)
	if err != nil {
		return nil, err
	}

	return c, nil
}
<|endoftext|>


<commit_before>package sqlx

import (
	"bytes"
	"database/sql/driver"
	"errors"
	"reflect"
	"strconv"
	"strings"
	"sync"

	"github.com/jmoiron/sqlx/reflectx"
)

// Bindvar types supported by Rebind, BindMap and BindStruct.
const (
	UNKNOWN = iota
	QUESTION
	DOLLAR
	NAMED
	AT
)

var defaultBinds = map[int][]string{
	DOLLAR:   []string{"postgres", "pgx", "pq-timeouts", "cloudsqlpostgres", "ql", "nrpostgres"},
	QUESTION: []string{"mysql", "sqlite3", "nrmysql", "nrsqlite3"},
	NAMED:    []string{"oci8", "ora", "goracle"},
	AT:       []string{"sqlserver"},
}

var binds sync.Map

func init() {
	for bind, drivers := range defaultBinds {
		for _, driver := range drivers {
			BindDriver(driver, bind)
		}
	}

}

// BindType returns the bindtype for a given database given a drivername.
func BindType(driverName string) int {
	itype, ok := binds.Load(driverName)
	if !ok {
		return UNKNOWN
	}
	return itype.(int)
}

// BindDriver sets the BindType for driverName to bindType.
func BindDriver(driverName string, bindType int) {
	binds.Store(driverName, bindType)
}

// FIXME: this should be able to be tolerant of escaped ?'s in queries without
// losing much speed, and should be to avoid confusion.

// Rebind a query from the default bindtype (QUESTION) to the target bindtype.
func Rebind(bindType int, query string) string {
	switch bindType {
	case QUESTION, UNKNOWN:
		return query
	}

	// Add space enough for 10 params before we have to allocate
	rqb := make([]byte, 0, len(query)+10)

	var i, j int

	for i = strings.Index(query, "?"); i != -1; i = strings.Index(query, "?") {
		rqb = append(rqb, query[:i]...)

		switch bindType {
		case DOLLAR:
			rqb = append(rqb, '$')
		case NAMED:
			rqb = append(rqb, ':', 'a', 'r', 'g')
		case AT:
			rqb = append(rqb, '@', 'p')
		}

		j++
		rqb = strconv.AppendInt(rqb, int64(j), 10)

		query = query[i+1:]
	}

	return string(append(rqb, query...))
}

// Experimental implementation of Rebind which uses a bytes.Buffer.  The code is
// much simpler and should be more resistant to odd unicode, but it is twice as
// slow.  Kept here for benchmarking purposes and to possibly replace Rebind if
// problems arise with its somewhat naive handling of unicode.
func rebindBuff(bindType int, query string) string {
	if bindType != DOLLAR {
		return query
	}

	b := make([]byte, 0, len(query))
	rqb := bytes.NewBuffer(b)
	j := 1
	for _, r := range query {
		if r == '?' {
			rqb.WriteRune('$')
			rqb.WriteString(strconv.Itoa(j))
			j++
		} else {
			rqb.WriteRune(r)
		}
	}

	return rqb.String()
}

func asSliceForIn(i interface{}) (v reflect.Value, ok bool) {
	if i == nil {
		return reflect.Value{}, false
	}

	v = reflect.ValueOf(i)
	t := reflectx.Deref(v.Type())

	// Only expand slices
	if t.Kind() != reflect.Slice {
		return reflect.Value{}, false
	}

	// []byte is a driver.Value type so it should not be expanded
	if t == reflect.TypeOf([]byte{}) {
		return reflect.Value{}, false

	}

	return v, true
}

// In expands slice values in args, returning the modified query string
// and a new arg list that can be executed by a database. The `query` should
// use the `?` bindVar.  The return value uses the `?` bindVar.
func In(query string, args ...interface{}) (string, []interface{}, error) {
	// argMeta stores reflect.Value and length for slices and
	// the value itself for non-slice arguments
	type argMeta struct {
		v      reflect.Value
		i      interface{}
		length int
	}

	var flatArgsCount int
	var anySlices bool

	var stackMeta [32]argMeta

	var meta []argMeta
	if len(args) <= len(stackMeta) {
		meta = stackMeta[:len(args)]
	} else {
		meta = make([]argMeta, len(args))
	}

	for i, arg := range args {
		if a, ok := arg.(driver.Valuer); ok {
			var err error
			arg, err = a.Value()
			if err != nil {
				return "", nil, err
			}
		}

		if v, ok := asSliceForIn(arg); ok {
			meta[i].length = v.Len()
			meta[i].v = v

			anySlices = true
			flatArgsCount += meta[i].length

			if meta[i].length == 0 {
				return "", nil, errors.New("empty slice passed to 'in' query")
			}
		} else {
			meta[i].i = arg
			flatArgsCount++
		}
	}

	// don't do any parsing if there aren't any slices;  note that this means
	// some errors that we might have caught below will not be returned.
	if !anySlices {
		return query, args, nil
	}

	newArgs := make([]interface{}, 0, flatArgsCount)

	var buf strings.Builder
	buf.Grow(len(query) + len(", ?")*flatArgsCount)

	var arg, offset int

	for i := strings.IndexByte(query[offset:], '?'); i != -1; i = strings.IndexByte(query[offset:], '?') {
		if arg >= len(meta) {
			// if an argument wasn't passed, lets return an error;  this is
			// not actually how database/sql Exec/Query works, but since we are
			// creating an argument list programmatically, we want to be able
			// to catch these programmer errors earlier.
			return "", nil, errors.New("number of bindVars exceeds arguments")
		}

		argMeta := meta[arg]
		arg++

		// not a slice, continue.
		// our questionmark will either be written before the next expansion
		// of a slice or after the loop when writing the rest of the query
		if argMeta.length == 0 {
			offset = offset + i + 1
			newArgs = append(newArgs, argMeta.i)
			continue
		}

		// write everything up to and including our ? character
		buf.WriteString(query[:offset+i+1])

		for si := 1; si < argMeta.length; si++ {
			buf.WriteString(", ?")
		}

		newArgs = appendReflectSlice(newArgs, argMeta.v, argMeta.length)

		// slice the query and reset the offset. this avoids some bookkeeping for
		// the write after the loop
		query = query[offset+i+1:]
		offset = 0
	}

	buf.WriteString(query)

	if arg < len(meta) {
		return "", nil, errors.New("number of bindVars less than number arguments")
	}

	return buf.String(), newArgs, nil
}

func appendReflectSlice(args []interface{}, v reflect.Value, vlen int) []interface{} {
	switch val := v.Interface().(type) {
	case []interface{}:
		args = append(args, val...)
	case []int:
		for i := range val {
			args = append(args, &val[i])
		}
	case []string:
		for i := range val {
			args = append(args, &val[i])
		}
	default:
		for si := 0; si < vlen; si++ {
			args = append(args, v.Index(si).Interface())
		}
	}

	return args
}
<commit_msg>add cockroach driver to default driver list as DOLLAR<commit_after>package sqlx

import (
	"bytes"
	"database/sql/driver"
	"errors"
	"reflect"
	"strconv"
	"strings"
	"sync"

	"github.com/jmoiron/sqlx/reflectx"
)

// Bindvar types supported by Rebind, BindMap and BindStruct.
const (
	UNKNOWN = iota
	QUESTION
	DOLLAR
	NAMED
	AT
)

var defaultBinds = map[int][]string{
	DOLLAR:   []string{"postgres", "pgx", "pq-timeouts", "cloudsqlpostgres", "ql", "nrpostgres", "cockroach"},
	QUESTION: []string{"mysql", "sqlite3", "nrmysql", "nrsqlite3"},
	NAMED:    []string{"oci8", "ora", "goracle"},
	AT:       []string{"sqlserver"},
}

var binds sync.Map

func init() {
	for bind, drivers := range defaultBinds {
		for _, driver := range drivers {
			BindDriver(driver, bind)
		}
	}

}

// BindType returns the bindtype for a given database given a drivername.
func BindType(driverName string) int {
	itype, ok := binds.Load(driverName)
	if !ok {
		return UNKNOWN
	}
	return itype.(int)
}

// BindDriver sets the BindType for driverName to bindType.
func BindDriver(driverName string, bindType int) {
	binds.Store(driverName, bindType)
}

// FIXME: this should be able to be tolerant of escaped ?'s in queries without
// losing much speed, and should be to avoid confusion.

// Rebind a query from the default bindtype (QUESTION) to the target bindtype.
func Rebind(bindType int, query string) string {
	switch bindType {
	case QUESTION, UNKNOWN:
		return query
	}

	// Add space enough for 10 params before we have to allocate
	rqb := make([]byte, 0, len(query)+10)

	var i, j int

	for i = strings.Index(query, "?"); i != -1; i = strings.Index(query, "?") {
		rqb = append(rqb, query[:i]...)

		switch bindType {
		case DOLLAR:
			rqb = append(rqb, '$')
		case NAMED:
			rqb = append(rqb, ':', 'a', 'r', 'g')
		case AT:
			rqb = append(rqb, '@', 'p')
		}

		j++
		rqb = strconv.AppendInt(rqb, int64(j), 10)

		query = query[i+1:]
	}

	return string(append(rqb, query...))
}

// Experimental implementation of Rebind which uses a bytes.Buffer.  The code is
// much simpler and should be more resistant to odd unicode, but it is twice as
// slow.  Kept here for benchmarking purposes and to possibly replace Rebind if
// problems arise with its somewhat naive handling of unicode.
func rebindBuff(bindType int, query string) string {
	if bindType != DOLLAR {
		return query
	}

	b := make([]byte, 0, len(query))
	rqb := bytes.NewBuffer(b)
	j := 1
	for _, r := range query {
		if r == '?' {
			rqb.WriteRune('$')
			rqb.WriteString(strconv.Itoa(j))
			j++
		} else {
			rqb.WriteRune(r)
		}
	}

	return rqb.String()
}

func asSliceForIn(i interface{}) (v reflect.Value, ok bool) {
	if i == nil {
		return reflect.Value{}, false
	}

	v = reflect.ValueOf(i)
	t := reflectx.Deref(v.Type())

	// Only expand slices
	if t.Kind() != reflect.Slice {
		return reflect.Value{}, false
	}

	// []byte is a driver.Value type so it should not be expanded
	if t == reflect.TypeOf([]byte{}) {
		return reflect.Value{}, false

	}

	return v, true
}

// In expands slice values in args, returning the modified query string
// and a new arg list that can be executed by a database. The `query` should
// use the `?` bindVar.  The return value uses the `?` bindVar.
func In(query string, args ...interface{}) (string, []interface{}, error) {
	// argMeta stores reflect.Value and length for slices and
	// the value itself for non-slice arguments
	type argMeta struct {
		v      reflect.Value
		i      interface{}
		length int
	}

	var flatArgsCount int
	var anySlices bool

	var stackMeta [32]argMeta

	var meta []argMeta
	if len(args) <= len(stackMeta) {
		meta = stackMeta[:len(args)]
	} else {
		meta = make([]argMeta, len(args))
	}

	for i, arg := range args {
		if a, ok := arg.(driver.Valuer); ok {
			var err error
			arg, err = a.Value()
			if err != nil {
				return "", nil, err
			}
		}

		if v, ok := asSliceForIn(arg); ok {
			meta[i].length = v.Len()
			meta[i].v = v

			anySlices = true
			flatArgsCount += meta[i].length

			if meta[i].length == 0 {
				return "", nil, errors.New("empty slice passed to 'in' query")
			}
		} else {
			meta[i].i = arg
			flatArgsCount++
		}
	}

	// don't do any parsing if there aren't any slices;  note that this means
	// some errors that we might have caught below will not be returned.
	if !anySlices {
		return query, args, nil
	}

	newArgs := make([]interface{}, 0, flatArgsCount)

	var buf strings.Builder
	buf.Grow(len(query) + len(", ?")*flatArgsCount)

	var arg, offset int

	for i := strings.IndexByte(query[offset:], '?'); i != -1; i = strings.IndexByte(query[offset:], '?') {
		if arg >= len(meta) {
			// if an argument wasn't passed, lets return an error;  this is
			// not actually how database/sql Exec/Query works, but since we are
			// creating an argument list programmatically, we want to be able
			// to catch these programmer errors earlier.
			return "", nil, errors.New("number of bindVars exceeds arguments")
		}

		argMeta := meta[arg]
		arg++

		// not a slice, continue.
		// our questionmark will either be written before the next expansion
		// of a slice or after the loop when writing the rest of the query
		if argMeta.length == 0 {
			offset = offset + i + 1
			newArgs = append(newArgs, argMeta.i)
			continue
		}

		// write everything up to and including our ? character
		buf.WriteString(query[:offset+i+1])

		for si := 1; si < argMeta.length; si++ {
			buf.WriteString(", ?")
		}

		newArgs = appendReflectSlice(newArgs, argMeta.v, argMeta.length)

		// slice the query and reset the offset. this avoids some bookkeeping for
		// the write after the loop
		query = query[offset+i+1:]
		offset = 0
	}

	buf.WriteString(query)

	if arg < len(meta) {
		return "", nil, errors.New("number of bindVars less than number arguments")
	}

	return buf.String(), newArgs, nil
}

func appendReflectSlice(args []interface{}, v reflect.Value, vlen int) []interface{} {
	switch val := v.Interface().(type) {
	case []interface{}:
		args = append(args, val...)
	case []int:
		for i := range val {
			args = append(args, &val[i])
		}
	case []string:
		for i := range val {
			args = append(args, &val[i])
		}
	default:
		for si := 0; si < vlen; si++ {
			args = append(args, v.Index(si).Interface())
		}
	}

	return args
}
<|endoftext|>


<commit_before>package configschema

import (
	"github.com/hashicorp/go-cty/cty"
)

// ImpliedType returns the cty.Type that would result from decoding a
// configuration block using the receiving block schema.
//
// ImpliedType always returns a result, even if the given schema is
// inconsistent. Code that creates configschema.Block objects should be
// tested using the InternalValidate method to detect any inconsistencies
// that would cause this method to fall back on defaults and assumptions.
func (b *Block) ImpliedType() cty.Type {
	if b == nil {
		return cty.EmptyObject
	}

	atys := make(map[string]cty.Type)

	for name, attrS := range b.Attributes {
		atys[name] = attrS.Type
	}

	for name, blockS := range b.BlockTypes {
		if _, exists := atys[name]; exists {
			// This indicates an invalid schema, since it's not valid to
			// define both an attribute and a block type of the same name.
			// However, we don't raise this here since it's checked by
			// InternalValidate.
			continue
		}

		childType := blockS.Block.ImpliedType()

		switch blockS.Nesting {
		case NestingSingle, NestingGroup:
			atys[name] = childType
		case NestingList:
			// We prefer to use a list where possible, since it makes our
			// implied type more complete, but if there are any
			// dynamically-typed attributes inside we must use a tuple
			// instead, which means our type _constraint_ must be
			// cty.DynamicPseudoType to allow the tuple type to be decided
			// separately for each value.
			if childType.HasDynamicTypes() {
				atys[name] = cty.DynamicPseudoType
			} else {
				atys[name] = cty.List(childType)
			}
		case NestingSet:
			// We forbid dynamically-typed attributes inside NestingSet in
			// InternalValidate, so we will consider that a bug in the caller
			// if we see it here. (There is no set equivalent to tuple and
			// object types, because cty's set implementation depends on
			// knowing the static type in order to properly compute its
			// internal hashes.)
			if childType.HasDynamicTypes() {
				panic("can't use cty.DynamicPseudoType inside a block type with NestingSet")
			}
			atys[name] = cty.Set(childType)
		case NestingMap:
			// We prefer to use a map where possible, since it makes our
			// implied type more complete, but if there are any
			// dynamically-typed attributes inside we must use an object
			// instead, which means our type _constraint_ must be
			// cty.DynamicPseudoType to allow the tuple type to be decided
			// separately for each value.
			if childType.HasDynamicTypes() {
				atys[name] = cty.DynamicPseudoType
			} else {
				atys[name] = cty.Map(childType)
			}
		default:
			// Invalid nesting type is just ignored. It's checked by
			// InternalValidate.
			continue
		}
	}

	return cty.Object(atys)
}
<commit_msg>Panic since no more InternalValidate<commit_after>package configschema

import (
	"github.com/hashicorp/go-cty/cty"
)

// ImpliedType returns the cty.Type that would result from decoding a
// configuration block using the receiving block schema.
//
// ImpliedType always returns a result, even if the given schema is
// inconsistent.
func (b *Block) ImpliedType() cty.Type {
	if b == nil {
		return cty.EmptyObject
	}

	atys := make(map[string]cty.Type)

	for name, attrS := range b.Attributes {
		atys[name] = attrS.Type
	}

	for name, blockS := range b.BlockTypes {
		if _, exists := atys[name]; exists {
			panic("invalid schema, blocks and attributes cannot have the same name")
		}

		childType := blockS.Block.ImpliedType()

		switch blockS.Nesting {
		case NestingSingle, NestingGroup:
			atys[name] = childType
		case NestingList:
			// We prefer to use a list where possible, since it makes our
			// implied type more complete, but if there are any
			// dynamically-typed attributes inside we must use a tuple
			// instead, which means our type _constraint_ must be
			// cty.DynamicPseudoType to allow the tuple type to be decided
			// separately for each value.
			if childType.HasDynamicTypes() {
				atys[name] = cty.DynamicPseudoType
			} else {
				atys[name] = cty.List(childType)
			}
		case NestingSet:
			if childType.HasDynamicTypes() {
				panic("can't use cty.DynamicPseudoType inside a block type with NestingSet")
			}
			atys[name] = cty.Set(childType)
		case NestingMap:
			// We prefer to use a map where possible, since it makes our
			// implied type more complete, but if there are any
			// dynamically-typed attributes inside we must use an object
			// instead, which means our type _constraint_ must be
			// cty.DynamicPseudoType to allow the tuple type to be decided
			// separately for each value.
			if childType.HasDynamicTypes() {
				atys[name] = cty.DynamicPseudoType
			} else {
				atys[name] = cty.Map(childType)
			}
		default:
			panic("invalid nesting type")
		}
	}

	return cty.Object(atys)
}
<|endoftext|>


<commit_before>package yalzo

import (
	"bufio"
	"os"
	"strconv"
	"strings"
)

func ReadCSV(fp *os.File) ([]Todo, error) {
	scanner := bufio.NewScanner(fp)
    if err := scanner.Err(); err != nil {
        return nil, err
    }

	todos := make([]Todo, 0, 100)

	for scanner.Scan() {
		line := scanner.Text()
		items := strings.Split(line, ",")

		no, err := strconv.Atoi(strings.TrimSpace(items[0]))
		if err != nil {
			return nil, err
		}

		todo := &Todo{
			no:    no,
			label: strings.TrimSpace(items[1]),
			title: strings.TrimSpace(items[2]),
		}
		todos = append(todos, (*todo))
	}
	return todos, nil
}
<commit_msg>fmtわすれ<commit_after>package yalzo

import (
	"bufio"
	"os"
	"strconv"
	"strings"
)

func ReadCSV(fp *os.File) ([]Todo, error) {
	scanner := bufio.NewScanner(fp)
	if err := scanner.Err(); err != nil {
		return nil, err
	}

	todos := make([]Todo, 0, 100)

	for scanner.Scan() {
		line := scanner.Text()
		items := strings.Split(line, ",")

		no, err := strconv.Atoi(strings.TrimSpace(items[0]))
		if err != nil {
			return nil, err
		}

		todo := &Todo{
			no:    no,
			label: strings.TrimSpace(items[1]),
			title: strings.TrimSpace(items[2]),
		}
		todos = append(todos, (*todo))
	}
	return todos, nil
}
<|endoftext|>


<commit_before>package cronv

import (
	"fmt"
	"github.com/tkmgo/cronexpr"
	"os"
	"strings"
	"time"
)

type Cronv struct {
	Crontab         *Crontab
	expr            *cronexpr.Expression
	startTime       time.Time
	durationMinutes float64
}

func NewCronv(line string, startTime time.Time, durationMinutes float64) (*Cronv, error) {
	crontab, err := parseCrontab(line)
	if err != nil {
		return nil, err
	}

	expr, err := cronexpr.Parse(crontab.Schedule.toCrontab())
	if err != nil {
		return nil, err
	}

	cronv := &Cronv{
		Crontab:         crontab,
		expr:            expr,
		startTime:       startTime,
		durationMinutes: durationMinutes,
	}
	return cronv, nil
}

type Exec struct {
	Start time.Time
	End   time.Time
}

func (self *Cronv) iter() <-chan *Exec {
	ch := make(chan *Exec)
	eneTime := self.startTime.Add(time.Duration(self.durationMinutes) * time.Minute)
	next := self.expr.Next(self.startTime)
	go func() {
		for next.Equal(eneTime) || eneTime.After(next) {
			ch <- &Exec{
				Start: next,
				End:   next.Add(time.Duration(1) * time.Minute),
			}
			next = self.expr.Next(next)
		}
		close(ch)
	}()
	return ch
}

type CronvCtx struct {
	Opts            *Command
	TimeFrom        time.Time
	TimeTo          time.Time
	CronEntries     []*Cronv
	durationMinutes float64
}

func NewCtx(opts *Command) (*CronvCtx, error) {
	timeFrom, err := opts.toFromTime()
	if err != nil {
		return nil, err
	}

	durationMinutes, err := opts.toDurationMinutes()
	if err != nil {
		return nil, err
	}

	return &CronvCtx{
		Opts:            opts,
		TimeFrom:        timeFrom,
		TimeTo:          timeFrom.Add(time.Duration(durationMinutes) * time.Minute),
		CronEntries:     []*Cronv{},
		durationMinutes: durationMinutes,
	}, nil
}

func (self *CronvCtx) AppendNewLine(line string) (bool, error) {
	trimed := strings.TrimSpace(line)
	if len(trimed) == 0 || string(trimed[0]) == "#" {
		return false, nil
	}
	cronv, err := NewCronv(trimed, self.TimeFrom, self.durationMinutes)
	if err != nil {
		switch err.(type) {
		case *InvalidTaskError:
			return false, nil // pass
		default:
			return false, fmt.Errorf("Failed to analyze cron '%s': %s", line, err)
		}
	}
	self.CronEntries = append(self.CronEntries, cronv)
	return true, nil
}

func (self *CronvCtx) Dump() (string, error) {
	output, err := os.Create(self.Opts.OutputFilePath)
	if err != nil {
		return "", err
	}
	makeTemplate().Execute(output, self)
	return self.Opts.OutputFilePath, nil
}
<commit_msg>Remove unnecessary initialization<commit_after>package cronv

import (
	"fmt"
	"github.com/tkmgo/cronexpr"
	"os"
	"strings"
	"time"
)

type Cronv struct {
	Crontab         *Crontab
	expr            *cronexpr.Expression
	startTime       time.Time
	durationMinutes float64
}

func NewCronv(line string, startTime time.Time, durationMinutes float64) (*Cronv, error) {
	crontab, err := parseCrontab(line)
	if err != nil {
		return nil, err
	}

	expr, err := cronexpr.Parse(crontab.Schedule.toCrontab())
	if err != nil {
		return nil, err
	}

	cronv := &Cronv{
		Crontab:         crontab,
		expr:            expr,
		startTime:       startTime,
		durationMinutes: durationMinutes,
	}
	return cronv, nil
}

type Exec struct {
	Start time.Time
	End   time.Time
}

func (self *Cronv) iter() <-chan *Exec {
	ch := make(chan *Exec)
	eneTime := self.startTime.Add(time.Duration(self.durationMinutes) * time.Minute)
	next := self.expr.Next(self.startTime)
	go func() {
		for next.Equal(eneTime) || eneTime.After(next) {
			ch <- &Exec{
				Start: next,
				End:   next.Add(time.Duration(1) * time.Minute),
			}
			next = self.expr.Next(next)
		}
		close(ch)
	}()
	return ch
}

type CronvCtx struct {
	Opts            *Command
	TimeFrom        time.Time
	TimeTo          time.Time
	CronEntries     []*Cronv
	durationMinutes float64
}

func NewCtx(opts *Command) (*CronvCtx, error) {
	timeFrom, err := opts.toFromTime()
	if err != nil {
		return nil, err
	}

	durationMinutes, err := opts.toDurationMinutes()
	if err != nil {
		return nil, err
	}

	return &CronvCtx{
		Opts:            opts,
		TimeFrom:        timeFrom,
		TimeTo:          timeFrom.Add(time.Duration(durationMinutes) * time.Minute),
		durationMinutes: durationMinutes,
	}, nil
}

func (self *CronvCtx) AppendNewLine(line string) (bool, error) {
	trimed := strings.TrimSpace(line)
	if len(trimed) == 0 || string(trimed[0]) == "#" {
		return false, nil
	}
	cronv, err := NewCronv(trimed, self.TimeFrom, self.durationMinutes)
	if err != nil {
		switch err.(type) {
		case *InvalidTaskError:
			return false, nil // pass
		default:
			return false, fmt.Errorf("Failed to analyze cron '%s': %s", line, err)
		}
	}
	self.CronEntries = append(self.CronEntries, cronv)
	return true, nil
}

func (self *CronvCtx) Dump() (string, error) {
	output, err := os.Create(self.Opts.OutputFilePath)
	if err != nil {
		return "", err
	}
	makeTemplate().Execute(output, self)
	return self.Opts.OutputFilePath, nil
}
<|endoftext|>


<commit_before>package boids

import (
	"bytes"
	//"fmt"
	//"math/rand"
	//"math"
)

//Game state
type Game struct {
	Flock Flock
	Map   BoidMap
}

//Game map
type BoidMap struct {
	Height int
	Width  int
}

//Holds state of a boid
type Boid struct {
	Location     PVector
	Velocity     PVector
	Acceleration PVector
	R            float64
	MaxForce     float64 // Maximum steering force
	MaxSpeed     float64 // Maximum speed
}

//Flock of boids
type Flock struct {
	Boids []Boid
}

func NewGame() Game {
	bMap := BoidMap{Height: 25, Width: 75}
	flock := NewFlock()
	game := Game{}
	game.Flock = flock
	game.Map = bMap

	return game
}

// func NewCustomGame() {
// 	game := NewGame()
// 	return game
// }

//Creates a new Flock
func NewFlock() Flock {
	flock := Flock{}
	flock.Boids = make([]Boid, 25)

	for n := 0; n < 25; n++ {
		flock.Boids[n] = NewBoid(float64(25), float64(10))
	}
	return flock
}

//Run 1 step on game
//Returns string representation of the game board
func (game *Game) Run() string {
	for n, _ := range game.Flock.Boids {
		game.Flock.Boids[n].Run(game.Flock.Boids, game.Map)
	}

	var buf bytes.Buffer
	for h := 0; h < game.Map.Height; h++ {
		for w := 0; w < game.Map.Width; w++ {
			hit := false
			for _, boid := range game.Flock.Boids {
				if int(boid.Location.X) == w && int(boid.Location.Y) == h {
					hit = true
					break
				}
			}
			if hit {
				buf.WriteByte('*')
			} else {
				buf.WriteByte(' ')
			}
		}
		buf.WriteByte('|')
		buf.WriteByte('\n')
	}
	return buf.String()
}

//Creates a new Boid
func NewBoid(x float64, y float64) Boid {
	result := Boid{}
	result.Acceleration = NewPVector2D(0, 0)
	result.Velocity = NewRandom2dPVector()
	result.Location = NewPVector2D(x, y)
	result.R = 2.0
	result.MaxSpeed = 2
	result.MaxForce = 0.03
	return result
}

//Run 1 step in simulation
func (boid *Boid) Run(neighbours []Boid, bMap BoidMap) {
	boid.Flock(neighbours)
	boid.Update()
	boid.Wrap(bMap)
}

//Wrap location when hitting edge of map
func (boid *Boid) Wrap(bMap BoidMap) {
	if boid.Location.X < -boid.R {
		boid.Location.X = float64(bMap.Width) + boid.R
	}
	if boid.Location.Y < -boid.R {
		boid.Location.Y = float64(bMap.Height) + boid.R
	}
	if boid.Location.X > float64(bMap.Width)+boid.R {
		boid.Location.X = -boid.R
	}
	if boid.Location.Y > float64(bMap.Height)+boid.R {
		boid.Location.Y = -boid.R
	}
}

//
func (boid *Boid) ApplyForce(force PVector) {
	boid.Acceleration.Add(force)
}

//Compute new acceleration value based on the 3
// rules (Separation, Alignment, Cohesion)
func (boid *Boid) Flock(neighbours []Boid) {
	sep := boid.Separate(neighbours)
	aln := boid.Align(neighbours)
	coh := boid.Cohesion(neighbours)
	// Weight forces
	sep.Mult(1.0)
	aln.Mult(1.0)
	coh.Mult(1.0)

	//Add forces to boids acceleration
	boid.ApplyForce(sep)
	boid.ApplyForce(aln)
	boid.ApplyForce(coh)
}

//Steers boid towards specified target
func (boid *Boid) Seek(target PVector) PVector {
	desired := target.Diff(boid.Location)
	desired.Normalize()
	desired.Mult(boid.MaxSpeed)

	steer := desired.Diff(boid.Velocity)
	steer.Limit(boid.MaxForce)
	return steer
}

//Calculates steering vector towards center of all neighbour boids
func (boid *Boid) Cohesion(neighbours []Boid) PVector {
	neighbourDist := 5.0
	sum := NewPVector2D(0, 0)
	count := 0

	for _, neighbour := range neighbours {
		d := boid.Location.Dist(neighbour.Location)
		if d > 0.0 && d < neighbourDist {
			sum.Add(neighbour.Location)
			count++
		}
	}

	if count > 0 {
		sum.Div(float64(count))
		return boid.Seek(sum)
	} else {
		return NewPVector2D(0, 0)
	}
}

//Aligns boid with neighbouring boids
func (boid *Boid) Align(neighbours []Boid) PVector {
	neighbourDist := 50.0
	sum := NewPVector2D(0, 0)
	count := 0

	for _, neighbour := range neighbours {
		d := boid.Location.Dist(neighbour.Location)
		if (d > 0.0) && d < neighbourDist {
			sum.Add(neighbour.Velocity)
			count++
		}
	}

	if count > 0 {
		sum.Div(float64(count))
		// Steering = Desired - Velocity
		sum.Normalize()
		sum.Mult(boid.MaxSpeed)
		steer := sum.Diff(boid.Velocity)
		steer.Limit(boid.MaxForce)
		return steer
	} else {
		return NewPVector2D(0, 0)
	}

}

//Steers boid away from neighbours to prevent collisions
// trys to maintain minSpace distance from neighbours
func (boid *Boid) Separate(boids []Boid) PVector {
	minSpace := 25.0
	steer := NewPVector2D(0, 0)
	count := 0

	for _, neighbour := range boids {
		d := boid.Location.Dist(neighbour.Location)
		// If the distance is greater than 0 (yourself)
		// and less than min desired distance
		if (d > 0) && (d < minSpace) {
			// Calculate vector pointing away from neighbour
			diff := boid.Location.Diff(neighbour.Location)
			diff.Normalize()
			diff.Div(d) // Weight by distance
			steer.Add(diff)
			count++
		}
	}

	// calc average of added vectors
	if count > 0 {
		steer.Div(float64(count))
	}

	// As long as the vector is greater than 0
	if steer.Mag() > 0 {
		//steering = desired - velocity
		steer.Normalize()
		steer.Mult(boid.MaxSpeed)
		steer = steer.Diff(boid.Velocity)
		steer.Limit(boid.MaxForce)
	}

	return steer
}

//Updates a boids location on map
func (boid *Boid) Update() {
	// Update velocity
	boid.Velocity.Add(boid.Acceleration)
	// Limit speed
	boid.Velocity.Limit(boid.MaxSpeed)
	boid.Location.Add(boid.Velocity)
	// Reset accelertion to 0 each cycle
	boid.Acceleration.Mult(0)
}
<commit_msg>random start positions and colored output<commit_after>package boids

import (
	"bytes"
	//"fmt"
	"math/rand"
	//"math"
)

//Game state
type Game struct {
	Flock Flock
	Map   BoidMap
}

//Game map
type BoidMap struct {
	Height int
	Width  int
}

//Holds state of a boid
type Boid struct {
	Location     PVector
	Velocity     PVector
	Acceleration PVector
	R            float64
	MaxForce     float64 // Maximum steering force
	MaxSpeed     float64 // Maximum speed
}

//Flock of boids
type Flock struct {
	Boids []Boid
}

func NewGame() Game {
	bMap := BoidMap{Height: 25, Width: 75}
	flock := NewFlock()
	game := Game{}
	game.Flock = flock
	game.Map = bMap

	return game
}

// func NewCustomGame() {
// 	game := NewGame()
// 	return game
// }

//Creates a new Flock
func NewFlock() Flock {
	flock := Flock{}
	flock.Boids = make([]Boid, 25)

	for n := 0; n < 25; n++ {
		//flock.Boids[n] = NewBoid(float64(25), float64(10))
		flock.Boids[n] = NewBoid(float64(rand.Intn(75)), float64(rand.Intn(25)))
	}
	return flock
}

//Run 1 step on game
//Returns string representation of the game board
func (game *Game) Run() string {
	for n, _ := range game.Flock.Boids {
		game.Flock.Boids[n].Run(game.Flock.Boids, game.Map)
	}

	var buf bytes.Buffer
	for h := 0; h < game.Map.Height; h++ {
		for w := 0; w < game.Map.Width; w++ {
			hit := false
			for _, boid := range game.Flock.Boids {
				if int(boid.Location.X) == w && int(boid.Location.Y) == h {
					hit = true
					break
				}
			}
			if hit {
				buf.WriteString("\x1b[31;1m")
				buf.WriteByte('*')
			} else {
				buf.WriteByte(' ')
			}
		}
		buf.WriteString("\x1b[0m")
		buf.WriteByte('|')
		buf.WriteByte('\n')
	}
	return buf.String()
}

//Creates a new Boid
func NewBoid(x float64, y float64) Boid {
	result := Boid{}
	result.Acceleration = NewPVector2D(0, 0)
	result.Velocity = NewRandom2dPVector()
	result.Location = NewPVector2D(x, y)
	result.R = 2.0
	result.MaxSpeed = 2
	result.MaxForce = 0.03
	return result
}

//Run 1 step in simulation
func (boid *Boid) Run(neighbours []Boid, bMap BoidMap) {
	boid.Flock(neighbours)
	boid.Update()
	boid.Wrap(bMap)
}

//Wrap location when hitting edge of map
func (boid *Boid) Wrap(bMap BoidMap) {
	if boid.Location.X < -boid.R {
		boid.Location.X = float64(bMap.Width) + boid.R
	}
	if boid.Location.Y < -boid.R {
		boid.Location.Y = float64(bMap.Height) + boid.R
	}
	if boid.Location.X > float64(bMap.Width)+boid.R {
		boid.Location.X = -boid.R
	}
	if boid.Location.Y > float64(bMap.Height)+boid.R {
		boid.Location.Y = -boid.R
	}
}

//
func (boid *Boid) ApplyForce(force PVector) {
	boid.Acceleration.Add(force)
}

//Compute new acceleration value based on the 3
// rules (Separation, Alignment, Cohesion)
func (boid *Boid) Flock(neighbours []Boid) {
	sep := boid.Separate(neighbours)
	aln := boid.Align(neighbours)
	coh := boid.Cohesion(neighbours)
	// Weight forces
	sep.Mult(1.0)
	aln.Mult(1.0)
	coh.Mult(1.0)

	//Add forces to boids acceleration
	boid.ApplyForce(sep)
	boid.ApplyForce(aln)
	boid.ApplyForce(coh)
}

//Steers boid towards specified target
func (boid *Boid) Seek(target PVector) PVector {
	desired := target.Diff(boid.Location)
	desired.Normalize()
	desired.Mult(boid.MaxSpeed)

	steer := desired.Diff(boid.Velocity)
	steer.Limit(boid.MaxForce)
	return steer
}

//Calculates steering vector towards center of all neighbour boids
func (boid *Boid) Cohesion(neighbours []Boid) PVector {
	neighbourDist := 5.0
	sum := NewPVector2D(0, 0)
	count := 0

	for _, neighbour := range neighbours {
		d := boid.Location.Dist(neighbour.Location)
		if d > 0.0 && d < neighbourDist {
			sum.Add(neighbour.Location)
			count++
		}
	}

	if count > 0 {
		sum.Div(float64(count))
		return boid.Seek(sum)
	} else {
		return NewPVector2D(0, 0)
	}
}

//Aligns boid with neighbouring boids
func (boid *Boid) Align(neighbours []Boid) PVector {
	neighbourDist := 50.0
	sum := NewPVector2D(0, 0)
	count := 0

	for _, neighbour := range neighbours {
		d := boid.Location.Dist(neighbour.Location)
		if (d > 0.0) && d < neighbourDist {
			sum.Add(neighbour.Velocity)
			count++
		}
	}

	if count > 0 {
		sum.Div(float64(count))
		// Steering = Desired - Velocity
		sum.Normalize()
		sum.Mult(boid.MaxSpeed)
		steer := sum.Diff(boid.Velocity)
		steer.Limit(boid.MaxForce)
		return steer
	} else {
		return NewPVector2D(0, 0)
	}

}

//Steers boid away from neighbours to prevent collisions
// trys to maintain minSpace distance from neighbours
func (boid *Boid) Separate(boids []Boid) PVector {
	minSpace := 25.0
	steer := NewPVector2D(0, 0)
	count := 0

	for _, neighbour := range boids {
		d := boid.Location.Dist(neighbour.Location)
		// If the distance is greater than 0 (yourself)
		// and less than min desired distance
		if (d > 0) && (d < minSpace) {
			// Calculate vector pointing away from neighbour
			diff := boid.Location.Diff(neighbour.Location)
			diff.Normalize()
			diff.Div(d) // Weight by distance
			steer.Add(diff)
			count++
		}
	}

	// calc average of added vectors
	if count > 0 {
		steer.Div(float64(count))
	}

	// As long as the vector is greater than 0
	if steer.Mag() > 0 {
		//steering = desired - velocity
		steer.Normalize()
		steer.Mult(boid.MaxSpeed)
		steer = steer.Diff(boid.Velocity)
		steer.Limit(boid.MaxForce)
	}

	return steer
}

//Updates a boids location on map
func (boid *Boid) Update() {
	// Update velocity
	boid.Velocity.Add(boid.Acceleration)
	// Limit speed
	boid.Velocity.Limit(boid.MaxSpeed)
	boid.Location.Add(boid.Velocity)
	// Reset accelertion to 0 each cycle
	boid.Acceleration.Mult(0)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"sync"
)

func main() {
	threads := flag.Int("threads", runtime.NumCPU(), "set GOMAXPROCS")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s: filenames..\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	runtime.GOMAXPROCS(*threads)

	files := flag.Args()
	if len(files) == 0 {
		log.Fatal("no config files specified")
		flag.Usage()
		os.Exit(1)
	}

	shovels := make([]ShovelConfig, len(files))
	for i, f := range files {
		reader, err := os.Open(f)
		if err != nil {
			log.Fatal(err)
		}
		shovels[i] = ParseShovel(reader)
	}

	var wg sync.WaitGroup
	wg.Add(len(shovels))

	for _, shovel := range shovels {
		log.Println("initializing", shovel.Name)

		wg.Add(shovel.Concurrency)

		for i := 0; i < shovel.Concurrency; i++ {
			worker := Worker{ShovelConfig: shovel}
			worker.Name = fmt.Sprintf("%s [%d]", worker.Name, i+1)
			worker.Init()
			go func() {
				defer wg.Done()
				worker.Work()
			}()
		}
	}

	log.Println("workers are up and running")

	wg.Wait()
}
<commit_msg>fixed waitgroup counting<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"sync"
)

func main() {
	threads := flag.Int("threads", runtime.NumCPU(), "set GOMAXPROCS")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s: filenames..\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	runtime.GOMAXPROCS(*threads)

	files := flag.Args()
	if len(files) == 0 {
		log.Fatal("no config files specified")
		flag.Usage()
		os.Exit(1)
	}

	shovels := make([]ShovelConfig, len(files))
	for i, f := range files {
		reader, err := os.Open(f)
		if err != nil {
			log.Fatal(err)
		}
		shovels[i] = ParseShovel(reader)
	}

	var wg sync.WaitGroup

	for _, shovel := range shovels {
		log.Println("initializing", shovel.Name)

		for i := 0; i < shovel.Concurrency; i++ {
			worker := Worker{ShovelConfig: shovel}
			worker.Name = fmt.Sprintf("%s [%d]", worker.Name, i+1)
			worker.Init()
			go func() {
				wg.Add(1)
				defer wg.Done()
				worker.Work()
			}()
		}
	}

	log.Println("workers are up and running")

	wg.Wait()
}
<|endoftext|>


<commit_before>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/audit"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
	"github.com/eirka/eirka-libs/redis"
	"github.com/eirka/eirka-libs/user"
)

// gin router for tests
var router *gin.Engine

func init() {
	user.Secret = "secret"

	// Set up fake Redis connection
	redis.NewRedisMock()

	gin.SetMode(gin.ReleaseMode)

	router = gin.New()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJsonRequest(r http.Handler, method, path string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func errorMessage(err error) string {
	return fmt.Sprintf(`{"error_message":"%s"}`, err)
}

func successMessage(message string) string {
	return fmt.Sprintf(`{"success_message":"%s"}`, message)
}

func TestAddTagController(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	mock.ExpectExec("INSERT into tagmap").
		WithArgs(1, 1).
		WillReturnResult(sqlmock.NewResult(1, 1))

	mock.ExpectExec(`INSERT INTO audit \(user_id,ib_id,audit_type,audit_ip,audit_time,audit_action,audit_info\)`).
		WithArgs(1, 1, audit.BoardLog, "127.0.0.1", audit.AuditAddTag).
		WillReturnResult(sqlmock.NewResult(1, 1))

	redis.RedisCache.Mock.Command("DEL", "tags:1", "tag:1:1", "image:1")

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 200, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), successMessage(audit.AuditAddTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerBadInput(t *testing.T) {

	var reuesttests = []struct {
		name string
		in   []byte
	}{
		{"nofield", []byte(`{}`)},
		{"badfield", []byte(`{"derp": 1}`)},
		{"badmissing", []byte(`{"ib": 0}`)},
		{"badmissing", []byte(`{"ib": 0, "tag": 1}`)},
		{"badmissing", []byte(`{"image": 1}`)},
		{"badib", []byte(`{"ib": 0, "tag": 1, "image": 1}`)},
		{"badib", []byte(`{"ib": dur, "tag": 1, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": 0, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": dur, "image": 1}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": 0}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": dur}`)},
		{"badall", []byte(`{"ib": 0, "tag": 0, "image": 0}`)},
	}

	for _, test := range reuesttests {
		first := performJsonRequest(router, "POST", "/tag/add", test.in)
		assert.Equal(t, first.Code, 400, fmt.Sprintf("HTTP request code should match for request %s", test.name))
	}

}

func TestAddTagControllerImageNotFound(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrNotFound), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerDuplicate(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrDuplicateTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}
<commit_msg>add controller tests<commit_after>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/audit"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
	"github.com/eirka/eirka-libs/redis"
	"github.com/eirka/eirka-libs/user"
)

// gin router for tests
var router *gin.Engine

func init() {
	user.Secret = "secret"

	// Set up fake Redis connection
	redis.NewRedisMock()

	gin.SetMode(gin.ReleaseMode)

	router = gin.New()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJsonRequest(r http.Handler, method, path string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func errorMessage(err error) string {
	return fmt.Sprintf(`{"error_message":"%s"}`, err)
}

func successMessage(message string) string {
	return fmt.Sprintf(`{"success_message":"%s"}`, message)
}

func TestAddTagController(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	mock.ExpectExec("INSERT into tagmap").
		WithArgs(1, 1).
		WillReturnResult(sqlmock.NewResult(1, 1))

	mock.ExpectExec(`INSERT INTO audit \(user_id,ib_id,audit_type,audit_ip,audit_time,audit_action,audit_info\)`).
		WithArgs(1, 1, audit.BoardLog, "127.0.0.1", audit.AuditAddTag, "1").
		WillReturnResult(sqlmock.NewResult(1, 1))

	redis.RedisCache.Mock.Command("DEL", "tags:1", "tag:1:1", "image:1")

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 200, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), successMessage(audit.AuditAddTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerBadInput(t *testing.T) {

	var reuesttests = []struct {
		name string
		in   []byte
	}{
		{"nofield", []byte(`{}`)},
		{"badfield", []byte(`{"derp": 1}`)},
		{"badmissing", []byte(`{"ib": 0}`)},
		{"badmissing", []byte(`{"ib": 0, "tag": 1}`)},
		{"badmissing", []byte(`{"image": 1}`)},
		{"badib", []byte(`{"ib": 0, "tag": 1, "image": 1}`)},
		{"badib", []byte(`{"ib": dur, "tag": 1, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": 0, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": dur, "image": 1}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": 0}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": dur}`)},
		{"badall", []byte(`{"ib": 0, "tag": 0, "image": 0}`)},
	}

	for _, test := range reuesttests {
		first := performJsonRequest(router, "POST", "/tag/add", test.in)
		assert.Equal(t, first.Code, 400, fmt.Sprintf("HTTP request code should match for request %s", test.name))
	}

}

func TestAddTagControllerImageNotFound(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrNotFound), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerDuplicate(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrDuplicateTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}
<|endoftext|>


<commit_before>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/audit"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
	"github.com/eirka/eirka-libs/redis"
	"github.com/eirka/eirka-libs/user"
)

// gin router for tests
var router *gin.Engine

func init() {
	user.Secret = "secret"

	// Set up fake Redis connection
	redis.NewRedisMock()

	gin.SetMode(gin.ReleaseMode)

	router = gin.Default()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	req.Header.Set("X-Forwarded-For", "127.0.0.1")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJsonRequest(r http.Handler, method, path string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Forwarded-For", "127.0.0.1")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func errorMessage(err error) string {
	return fmt.Sprintf(`{"error_message":"%s"}`, err)
}

func successMessage(message string) string {
	return fmt.Sprintf(`{"success_message":"%s"}`, message)
}

func TestAddTagController(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	mock.ExpectExec("INSERT into tagmap").
		WithArgs(1, 1).
		WillReturnResult(sqlmock.NewResult(1, 1))

	mock.ExpectExec(`INSERT INTO audit \(user_id,ib_id,audit_type,audit_ip,audit_time,audit_action,audit_info\)`).
		WithArgs(1, 1, audit.BoardLog, "127.0.0.1", audit.AuditAddTag, "1").
		WillReturnResult(sqlmock.NewResult(1, 1))

	redis.RedisCache.Mock.Command("DEL", "tags:1", "tag:1:1", "image:1")

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 200, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), successMessage(audit.AuditAddTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerBadInput(t *testing.T) {

	var reuesttests = []struct {
		name string
		in   []byte
	}{
		{"nofield", []byte(`{}`)},
		{"badfield", []byte(`{"derp": 1}`)},
		{"badmissing", []byte(`{"ib": 0}`)},
		{"badmissing", []byte(`{"ib": 0, "tag": 1}`)},
		{"badmissing", []byte(`{"image": 1}`)},
		{"badib", []byte(`{"ib": 0, "tag": 1, "image": 1}`)},
		{"badib", []byte(`{"ib": dur, "tag": 1, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": 0, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": dur, "image": 1}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": 0}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": dur}`)},
		{"badall", []byte(`{"ib": 0, "tag": 0, "image": 0}`)},
	}

	for _, test := range reuesttests {
		first := performJsonRequest(router, "POST", "/tag/add", test.in)
		assert.Equal(t, first.Code, 400, fmt.Sprintf("HTTP request code should match for request %s", test.name))
	}

}

func TestAddTagControllerImageNotFound(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrNotFound), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerDuplicate(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrDuplicateTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}
<commit_msg>add controller tests<commit_after>package controllers

import (
	"bytes"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"gopkg.in/DATA-DOG/go-sqlmock.v1"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/eirka/eirka-libs/audit"
	"github.com/eirka/eirka-libs/db"
	e "github.com/eirka/eirka-libs/errors"
	"github.com/eirka/eirka-libs/redis"
	"github.com/eirka/eirka-libs/user"
)

// gin router for tests
var router *gin.Engine

func init() {
	user.Secret = "secret"

	// Set up fake Redis connection
	redis.NewRedisMock()

	gin.SetMode(gin.ReleaseMode)

	router = gin.Default()

	router.Use(user.Auth(false))

	router.POST("/tag/add", AddTagController)
}

func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, nil)
	req.Header.Set("X-Real-Ip", "127.0.0.1")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func performJsonRequest(r http.Handler, method, path string, body []byte) *httptest.ResponseRecorder {
	req, _ := http.NewRequest(method, path, bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-Real-Ip", "127.0.0.1")
	w := httptest.NewRecorder()
	r.ServeHTTP(w, req)
	return w
}

func errorMessage(err error) string {
	return fmt.Sprintf(`{"error_message":"%s"}`, err)
}

func successMessage(message string) string {
	return fmt.Sprintf(`{"success_message":"%s"}`, message)
}

func TestAddTagController(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	mock.ExpectExec("INSERT into tagmap").
		WithArgs(1, 1).
		WillReturnResult(sqlmock.NewResult(1, 1))

	mock.ExpectExec(`INSERT INTO audit \(user_id,ib_id,audit_type,audit_ip,audit_time,audit_action,audit_info\)`).
		WithArgs(1, 1, audit.BoardLog, "127.0.0.1", audit.AuditAddTag, "1").
		WillReturnResult(sqlmock.NewResult(1, 1))

	redis.RedisCache.Mock.Command("DEL", "tags:1", "tag:1:1", "image:1")

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 200, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), successMessage(audit.AuditAddTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerBadInput(t *testing.T) {

	var reuesttests = []struct {
		name string
		in   []byte
	}{
		{"nofield", []byte(`{}`)},
		{"badfield", []byte(`{"derp": 1}`)},
		{"badmissing", []byte(`{"ib": 0}`)},
		{"badmissing", []byte(`{"ib": 0, "tag": 1}`)},
		{"badmissing", []byte(`{"image": 1}`)},
		{"badib", []byte(`{"ib": 0, "tag": 1, "image": 1}`)},
		{"badib", []byte(`{"ib": dur, "tag": 1, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": 0, "image": 1}`)},
		{"badtag", []byte(`{"ib": 1, "tag": dur, "image": 1}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": 0}`)},
		{"badimage", []byte(`{"ib": 1, "tag": 1, "image": dur}`)},
		{"badall", []byte(`{"ib": 0, "tag": 0, "image": 0}`)},
	}

	for _, test := range reuesttests {
		first := performJsonRequest(router, "POST", "/tag/add", test.in)
		assert.Equal(t, first.Code, 400, fmt.Sprintf("HTTP request code should match for request %s", test.name))
	}

}

func TestAddTagControllerImageNotFound(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(0)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrNotFound), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}

func TestAddTagControllerDuplicate(t *testing.T) {

	var err error

	mock, err := db.NewTestDb()
	assert.NoError(t, err, "An error was not expected")

	statusrows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`SELECT count\(1\) FROM images`).WillReturnRows(statusrows)

	duperows := sqlmock.NewRows([]string{"count"}).AddRow(1)
	mock.ExpectQuery(`select count\(1\) from tagmap`).WillReturnRows(duperows)

	request := []byte(`{"ib": 1, "tag": 1, "image": 1}`)

	first := performJsonRequest(router, "POST", "/tag/add", request)

	assert.Equal(t, first.Code, 400, "HTTP request code should match")
	assert.JSONEq(t, first.Body.String(), errorMessage(e.ErrDuplicateTag), "HTTP response should match")

	assert.NoError(t, mock.ExpectationsWereMet(), "An error was not expected")

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package envs

import (
	"encoding/json"
	"net/http"
	"strings"

	h "github.com/ernestio/api-gateway/helpers"
	"github.com/ernestio/api-gateway/models"
)

// Update : responds to PUT /projects/:project:/envs/:env/ by updating an
// existing environment
func Update(au models.User, name string, body []byte) (int, []byte) {
	var err error
	var resp []byte
	var e models.Env
	var input models.Env
	var p models.Project
	var r models.Role
	var roles []models.Role
	var pRoles []models.Role

	computedRoles := make(map[string]models.Role, 0)

	if input.Map(body) != nil {
		return 400, models.NewJSONError("Input is not valid")
	}

	err = input.Validate()
	if err != nil {
		h.L.Error(err.Error())
		return http.StatusBadRequest, models.NewJSONError(err.Error())
	}

	if input.Name != name {
		return 400, models.NewJSONError("Environment name does not match payload name")
	}

	// Get existing environment
	if err = e.FindByName(name); err != nil {
		return 404, models.NewJSONError(err.Error())
	}

	if err = p.FindByID(e.ProjectID); err != nil {
		if strings.Contains(err.Error(), "not found") {
			return 404, models.NewJSONError("Specified environment name does not exist")
		}
		h.L.Error(err.Error())
		return 500, models.NewJSONError("Internal error")
	}

	if err = r.FindAllByResource(e.Project, p.GetType(), &pRoles); err == nil {
		for _, v := range pRoles {
			computedRoles[v.UserID] = v
		}
	}
	if err = r.FindAllByResource(e.GetID(), e.GetType(), &roles); err == nil {
		for _, v := range roles {
			computedRoles[v.UserID] = v
		}
	}

	for _, v := range computedRoles {
		e.Members = append(e.Members, v)
	}

	if st, res := h.IsAuthorizedToResource(&au, h.UpdateEnv, input.GetType(), name); st != 200 {
		return st, res
	}

	e.Options = input.Options
	e.Schedules = input.Schedules
	e.Credentials = input.Credentials

	if err = e.Save(); err != nil {
		return 500, models.NewJSONError(err.Error())
	}

	if input.Members == nil {
		resp, err = json.Marshal(e)
		if err != nil {
			h.L.Error(err.Error())
			return http.StatusBadRequest, models.NewJSONError(err.Error())
		}

		return http.StatusOK, resp
	}

	for _, ir := range input.Members {
		// create role
		if ir.ID == 0 {
			if !strings.Contains(ir.ResourceID, "/") || ir.ResourceType != "environment" {
				return http.StatusBadRequest, models.NewJSONError("project memberships must be modified on the project")
			}

			if !au.IsAdmin() {
				if ok := au.IsOwner(ir.ResourceType, ir.ResourceID); !ok {
					return 403, models.NewJSONError("You're not authorized to perform this action")
				}
			}

			err = ir.Save()
			if err != nil {
				h.L.Error(err.Error())
				return http.StatusBadRequest, models.NewJSONError(err.Error())
			}

			continue
		}

		for _, er := range e.Members {
			// update role
			if ir.ID == er.ID && ir.Role != er.Role {
				if !strings.Contains(er.ResourceID, "/") || ir.ResourceType != "environment" {
					return http.StatusBadRequest, models.NewJSONError("project memberships must be modified on the project")
				}

				if !au.IsAdmin() {
					if ok := au.IsOwner(ir.ResourceType, ir.ResourceID); !ok {
						return 403, models.NewJSONError("You're not authorized to perform this action")
					}
				}

				err = ir.Save()
				if err != nil {
					h.L.Error(err.Error())
					return http.StatusBadRequest, models.NewJSONError(err.Error())
				}
			}
		}
	}

	for _, er := range e.Members {
		var exists bool

		for _, ir := range input.Members {
			if ir.ID == er.ID {
				exists = true
			}
		}

		// delete roles
		if !exists {
			if !strings.Contains(er.ResourceID, "/") || er.ResourceType != "environment" {
				return http.StatusBadRequest, models.NewJSONError("project memberships must be removed on the project")
			}

			if !au.IsAdmin() {
				if ok := au.IsOwner(er.ResourceType, er.ResourceID); !ok {
					return 403, models.NewJSONError("You're not authorized to perform this action")
				}
			}

			err = er.Delete()
			if err != nil {
				h.L.Error(err.Error())
				return http.StatusBadRequest, models.NewJSONError(err.Error())
			}
		}
	}

	e.Members = input.Members

	resp, err = json.Marshal(e)
	if err != nil {
		h.L.Error(err.Error())
		return http.StatusBadRequest, models.NewJSONError(err.Error())
	}

	return http.StatusOK, resp
}
<commit_msg>fixed rendering of members<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package envs

import (
	"encoding/json"
	"net/http"
	"strings"

	h "github.com/ernestio/api-gateway/helpers"
	"github.com/ernestio/api-gateway/models"
)

// Update : responds to PUT /projects/:project:/envs/:env/ by updating an
// existing environment
func Update(au models.User, name string, body []byte) (int, []byte) {
	var err error
	var resp []byte
	var e models.Env
	var input models.Env
	var p models.Project
	var r models.Role
	var roles []models.Role
	var pRoles []models.Role

	computedRoles := make(map[string]models.Role, 0)

	if input.Map(body) != nil {
		return 400, models.NewJSONError("Input is not valid")
	}

	err = input.Validate()
	if err != nil {
		h.L.Error(err.Error())
		return http.StatusBadRequest, models.NewJSONError(err.Error())
	}

	if input.Name != name {
		return 400, models.NewJSONError("Environment name does not match payload name")
	}

	// Get existing environment
	if err = e.FindByName(name); err != nil {
		return 404, models.NewJSONError(err.Error())
	}

	if err = p.FindByID(e.ProjectID); err != nil {
		if strings.Contains(err.Error(), "not found") {
			return 404, models.NewJSONError("Specified environment name does not exist")
		}
		h.L.Error(err.Error())
		return 500, models.NewJSONError("Internal error")
	}

	if err = r.FindAllByResource(e.GetProject(), p.GetType(), &pRoles); err == nil {
		for _, v := range pRoles {
			computedRoles[v.UserID] = v
		}
	}
	if err = r.FindAllByResource(e.GetID(), e.GetType(), &roles); err == nil {
		for _, v := range roles {
			computedRoles[v.UserID] = v
		}
	}

	for _, v := range computedRoles {
		e.Members = append(e.Members, v)
	}

	if st, res := h.IsAuthorizedToResource(&au, h.UpdateEnv, input.GetType(), name); st != 200 {
		return st, res
	}

	e.Options = input.Options
	e.Schedules = input.Schedules
	e.Credentials = input.Credentials

	if err = e.Save(); err != nil {
		return 500, models.NewJSONError(err.Error())
	}

	if input.Members == nil {
		resp, err = json.Marshal(e)
		if err != nil {
			h.L.Error(err.Error())
			return http.StatusBadRequest, models.NewJSONError(err.Error())
		}

		return http.StatusOK, resp
	}

	for _, ir := range input.Members {
		// create role
		if ir.ID == 0 {
			if !strings.Contains(ir.ResourceID, "/") || ir.ResourceType != "environment" {
				return http.StatusBadRequest, models.NewJSONError("project memberships must be modified on the project")
			}

			if !au.IsAdmin() {
				if ok := au.IsOwner(ir.ResourceType, ir.ResourceID); !ok {
					return 403, models.NewJSONError("You're not authorized to perform this action")
				}
			}

			err = ir.Save()
			if err != nil {
				h.L.Error(err.Error())
				return http.StatusBadRequest, models.NewJSONError(err.Error())
			}

			continue
		}

		for _, er := range e.Members {
			// update role
			if ir.ID == er.ID && ir.Role != er.Role {
				if !strings.Contains(er.ResourceID, "/") || ir.ResourceType != "environment" {
					return http.StatusBadRequest, models.NewJSONError("project memberships must be modified on the project")
				}

				if !au.IsAdmin() {
					if ok := au.IsOwner(ir.ResourceType, ir.ResourceID); !ok {
						return 403, models.NewJSONError("You're not authorized to perform this action")
					}
				}

				err = ir.Save()
				if err != nil {
					h.L.Error(err.Error())
					return http.StatusBadRequest, models.NewJSONError(err.Error())
				}
			}
		}
	}

	for _, er := range e.Members {
		var exists bool

		for _, ir := range input.Members {
			if ir.ID == er.ID {
				exists = true
			}
		}

		// delete roles
		if !exists {
			if !strings.Contains(er.ResourceID, "/") || er.ResourceType != "environment" {
				return http.StatusBadRequest, models.NewJSONError("project memberships must be removed on the project")
			}

			if !au.IsAdmin() {
				if ok := au.IsOwner(er.ResourceType, er.ResourceID); !ok {
					return 403, models.NewJSONError("You're not authorized to perform this action")
				}
			}

			err = er.Delete()
			if err != nil {
				h.L.Error(err.Error())
				return http.StatusBadRequest, models.NewJSONError(err.Error())
			}
		}
	}

	e.Members = input.Members

	resp, err = json.Marshal(e)
	if err != nil {
		h.L.Error(err.Error())
		return http.StatusBadRequest, models.NewJSONError(err.Error())
	}

	return http.StatusOK, resp
}
<|endoftext|>


<commit_before>package MySQLProtocol

func BuildFixedInt1(value uint8) (data [1]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt1() (value uint8) {
    value |= uint8(packet.data[packet.offset] & 0xFF)
    packet.offset += 1
    return value
}

func BuildFixedInt2(value uint16) (data [2]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt2() (value uint16) {
    value |= uint16(packet.data[packet.offset+1] & 0xFF)
    value <<= 8
    value |= uint16(packet.data[packet.offset] & 0xFF)
    packet.offset += 2
    return value
}

func BuildFixedInt3(value uint32) (data [3]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	data[2] = byte(value >> 16 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt3() (value uint32) {
    value |= uint32(packet.data[packet.offset+2] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+1] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset] & 0xFF)
    packet.offset += 3
    return value
}

func BuildFixedInt4(value uint32) (data [4]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	data[2] = byte(value >> 16 & 0xFF)
	data[3] = byte(value >> 24 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt4() (value uint32) {
    value |= uint32(packet.data[packet.offset+3] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+2] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+1] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset] & 0xFF)
    packet.offset += 4
    return value
}

func BuildFixedInt8(value uint64) (data [8]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	data[2] = byte(value >> 16 & 0xFF)
	data[3] = byte(value >> 24 & 0xFF)
	data[4] = byte(value >> 32 & 0xFF)
	data[5] = byte(value >> 40 & 0xFF)
	data[6] = byte(value >> 48 & 0xFF)
	data[7] = byte(value >> 56 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt8() (value uint32) {
    value |= uint32(packet.data[packet.offset+7] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+6] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+5] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+4] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+3] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+2] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset+1] & 0xFF)
    value <<= 8
    value |= uint32(packet.data[packet.offset] & 0xFF)
    packet.offset += 8
    return value
}
<commit_msg>Clean up the code<commit_after>package MySQLProtocol

func BuildFixedInt1(value uint8) (data [1]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt1() (value uint8) {
    value |= uint8(packet.data[packet.offset] & 0xFF)
    packet.offset += 1
    return value
}

func BuildFixedInt2(value uint16) (data [2]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt2() (value uint16) {
    value |= uint16(packet.data[packet.offset+1] & 0xFF) << 8
    value |= uint16(packet.data[packet.offset] & 0xFF)
    packet.offset += 2
    return value
}

func BuildFixedInt3(value uint32) (data [3]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	data[2] = byte(value >> 16 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt3() (value uint32) {
    value |= uint32(packet.data[packet.offset+2] & 0xFF) << 16
    value |= uint32(packet.data[packet.offset+1] & 0xFF) << 8
    value |= uint32(packet.data[packet.offset] & 0xFF)
    packet.offset += 3
    return value
}

func BuildFixedInt4(value uint32) (data [4]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	data[2] = byte(value >> 16 & 0xFF)
	data[3] = byte(value >> 24 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt4() (value uint32) {
    value |= uint32(packet.data[packet.offset+3] & 0xFF) << 24
    value |= uint32(packet.data[packet.offset+2] & 0xFF) << 16
    value |= uint32(packet.data[packet.offset+1] & 0xFF) << 8
    value |= uint32(packet.data[packet.offset] & 0xFF)
    packet.offset += 4
    return value
}

func BuildFixedInt8(value uint64) (data [8]byte) {
	data[0] = byte(value >> 0 & 0xFF)
	data[1] = byte(value >> 8 & 0xFF)
	data[2] = byte(value >> 16 & 0xFF)
	data[3] = byte(value >> 24 & 0xFF)
	data[4] = byte(value >> 32 & 0xFF)
	data[5] = byte(value >> 40 & 0xFF)
	data[6] = byte(value >> 48 & 0xFF)
	data[7] = byte(value >> 56 & 0xFF)
	return data
}

func (packet Packet) GetFixedInt8() (value uint64) {
    value |= uint64(packet.data[packet.offset+7] & 0xFF) << 56
    value |= uint64(packet.data[packet.offset+6] & 0xFF) << 48
    value |= uint64(packet.data[packet.offset+5] & 0xFF) << 40
    value |= uint64(packet.data[packet.offset+4] & 0xFF) << 32
    value |= uint64(packet.data[packet.offset+3] & 0xFF) << 24
    value |= uint64(packet.data[packet.offset+2] & 0xFF) << 16
    value |= uint64(packet.data[packet.offset+1] & 0xFF) << 8
    value |= uint64(packet.data[packet.offset] & 0xFF)
    packet.offset += 8
    return value
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package users

import (
	"errors"
	"net/http"
	"strconv"

	"appengine"

	"github.com/taironas/route"

	"github.com/santiaago/gonawin/helpers"
	"github.com/santiaago/gonawin/helpers/log"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"
	mdl "github.com/santiaago/gonawin/models"
)

// User score user handler.
func Score(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	desc := "User Score Handler:"
	c := appengine.NewContext(r)

	if r.Method == "GET" {
		// get user id
		strUserId, err := route.Context.Get(r, "userId")
		if err != nil {
			log.Errorf(c, "%s error getting user id, err:%v", desc, err)
			return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
		}

		var userId int64
		userId, err = strconv.ParseInt(strUserId, 0, 64)
		if err != nil {
			log.Errorf(c, "%s error converting user id from string to int64, err:%v", desc, err)
			return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
		}

		var user *mdl.User
		user, err = mdl.UserById(c, userId)
		if err != nil {
			log.Errorf(c, "%s user not found", desc)
			return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeUserNotFound)}
		}

		//scores := user.Scores(c)
		scores := user.TournamentsScores(c)
		// data
		data := struct {
			Scores []*mdl.ScoreOverall
		}{
			scores,
		}

		return templateshlp.RenderJson(w, c, data)
	}
	return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
}
<commit_msg>user score - exit first<commit_after>/*
 * Copyright (c) 2014 Santiago Arias | Remy Jourde
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package users

import (
	"errors"
	"net/http"
	"strconv"

	"appengine"

	"github.com/taironas/route"

	"github.com/santiaago/gonawin/helpers"
	"github.com/santiaago/gonawin/helpers/log"
	templateshlp "github.com/santiaago/gonawin/helpers/templates"
	mdl "github.com/santiaago/gonawin/models"
)

// User score user handler.
func Score(w http.ResponseWriter, r *http.Request, u *mdl.User) error {
	if r.Method != "GET" {
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeNotSupported)}
	}

	desc := "User Score Handler:"
	c := appengine.NewContext(r)

	// get user id
	strUserId, err := route.Context.Get(r, "userId")
	if err != nil {
		log.Errorf(c, "%s error getting user id, err:%v", desc, err)
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}

	var userId int64
	userId, err = strconv.ParseInt(strUserId, 0, 64)
	if err != nil {
		log.Errorf(c, "%s error converting user id from string to int64, err:%v", desc, err)
		return &helpers.BadRequest{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}

	var user *mdl.User
	user, err = mdl.UserById(c, userId)
	if err != nil {
		log.Errorf(c, "%s user not found", desc)
		return &helpers.NotFound{Err: errors.New(helpers.ErrorCodeUserNotFound)}
	}

	//scores := user.Scores(c)
	scores := user.TournamentsScores(c)
	// data
	data := struct {
		Scores []*mdl.ScoreOverall
	}{
		scores,
	}

	return templateshlp.RenderJson(w, c, data)
}
<|endoftext|>