<commit_before>package gocouchlib

import (
	"net/http"
)

type Document struct {
	Id  string    `json:"_id"`
	Rev string    `json:"_rev"`
	Db  *Database `json:"-"`
}

func (doc *Document) endpoint(api string) string {
	return doc.Db.Server.FullUrl() + "/" + doc.Db.DbName + "/" + api
}

func (doc *Document) Exists() (bool, *CouchResponse) {

	headers := make(map[string][]string)

	if doc.Rev != "" {
		headers = map[string][]string{
			"If-None-Match": {"\"" + doc.Rev + "\""},
		}
	}

	couchResp, _ := httpClient.Head(doc.endpoint(doc.Id), headers)

	if (couchResp.StatusCode == http.StatusOK || couchResp.StatusCode == http.StatusNotModified) && couchResp.Headers.Get("ETag") != "" {
		doc.Rev = couchResp.Headers.Get("ETag")
	}

	return (couchResp.StatusCode == http.StatusOK || couchResp.StatusCode == http.StatusNotModified), couchResp
}
<commit_msg>Enhanced Exists() to use the ETag and introduced Get() function<commit_after>package gocouchlib

import (
	"net/http"
)

type Document struct {
	Id   string `json:"_id"`
	Rev  string `json:"_rev"`
	Json JsonObj

	Db *Database `json:"-"`
}

func (doc *Document) endpoint(api string) string {
	return doc.Db.Server.FullUrl() + "/" + doc.Db.DbName + "/" + api
}

func (doc *Document) Exists() (bool, *CouchResponse) {

	headers := make(http.Header)

	if doc.Rev != "" {
		headers.Add("If-None-Match", "\""+doc.Rev+"\"")
	}

	couchResp, _ := httpClient.Head(doc.endpoint(doc.Id), headers)

	// Set doc.Rev using the ETag on the response if it is currently empty
	if (couchResp.StatusCode == http.StatusOK || couchResp.StatusCode == http.StatusNotModified) && doc.Rev == "" && couchResp.Headers.Get("ETag") != "" {
		doc.Rev = couchResp.Headers.Get("ETag")
	}

	return (couchResp.StatusCode == http.StatusOK || couchResp.StatusCode == http.StatusNotModified), couchResp
}

func (doc *Document) Get() (JsonObj, *CouchResponse) {

	headers := make(http.Header)

	if doc.Rev != "" {
		headers.Add("If-None-Match", "\""+doc.Rev+"\"")
	}

	couchResp, _ := httpClient.Get(doc.endpoint(doc.Id), headers)
	var json JsonObj = nil
	if couchResp.StatusCode == http.StatusOK || couchResp.StatusCode == http.StatusNotModified {
		json = couchResp.Json
		doc.Json = couchResp.Json
	}

	return json, couchResp
}
<|endoftext|>


<commit_before>package rxgo

import (
	"context"
	"time"

	"github.com/stretchr/testify/mock"
)

// Infinite represents an infinite wait time
var Infinite int64 = -1

// Duration represents a duration
type Duration interface {
	duration() time.Duration
}

type duration struct {
	d time.Duration
}

func (d *duration) duration() time.Duration {
	return d.d
}

// WithDuration is a duration option
func WithDuration(d time.Duration) Duration {
	return &duration{
		d: d,
	}
}

var tick = struct{}{}

type causalityDuration struct {
	fs []func()
}

func timeCausality(elems ...interface{}) (context.Context, Observable, Duration) {
	ch := make(chan Item, 1)
	fs := make([]func(), len(elems)+1)
	ctx, cancel := context.WithCancel(context.Background())
	for i, elem := range elems {
		i := i
		elem := elem
		if elem == tick {
			fs[i] = func() {}
		} else {
			switch elem := elem.(type) {
			default:
				fs[i] = func() {
					ch <- Of(elem)
				}
			case error:
				fs[i] = func() {
					ch <- Error(elem)
				}
			}
		}
	}
	fs[len(elems)] = func() {
		cancel()
	}
	return ctx, FromChannel(ch), &causalityDuration{fs: fs}
}

func (d *causalityDuration) duration() time.Duration {
	d.fs[0]()
	d.fs = d.fs[1:]
	return 0
}

type mockDuration struct {
	mock.Mock
}

func (m *mockDuration) duration() time.Duration {
	args := m.Called()
	return args.Get(0).(time.Duration)
}
<commit_msg>Default causality duration<commit_after>package rxgo

import (
	"context"
	"time"

	"github.com/stretchr/testify/mock"
)

// Infinite represents an infinite wait time
var Infinite int64 = -1

// Duration represents a duration
type Duration interface {
	duration() time.Duration
}

type duration struct {
	d time.Duration
}

func (d *duration) duration() time.Duration {
	return d.d
}

// WithDuration is a duration option
func WithDuration(d time.Duration) Duration {
	return &duration{
		d: d,
	}
}

var tick = struct{}{}

type causalityDuration struct {
	fs []func()
}

func timeCausality(elems ...interface{}) (context.Context, Observable, Duration) {
	ch := make(chan Item, 1)
	fs := make([]func(), len(elems)+1)
	ctx, cancel := context.WithCancel(context.Background())
	for i, elem := range elems {
		i := i
		elem := elem
		if elem == tick {
			fs[i] = func() {}
		} else {
			switch elem := elem.(type) {
			default:
				fs[i] = func() {
					ch <- Of(elem)
				}
			case error:
				fs[i] = func() {
					ch <- Error(elem)
				}
			}
		}
	}
	fs[len(elems)] = func() {
		cancel()
	}
	return ctx, FromChannel(ch), &causalityDuration{fs: fs}
}

func (d *causalityDuration) duration() time.Duration {
	d.fs[0]()
	d.fs = d.fs[1:]
	return time.Nanosecond
}

type mockDuration struct {
	mock.Mock
}

func (m *mockDuration) duration() time.Duration {
	args := m.Called()
	return args.Get(0).(time.Duration)
}
<|endoftext|>


<commit_before>package GoSDK

import (
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

const (
	_EDGES_PREAMBLE          = "/admin/edges/"
	_EDGES_USER_PREAMBLE     = "/api/v/2/edges/"
	_EDGES_SYNC_MANAGEMENT   = "/admin/edges/sync/"
	_EDGES_DEPLOY_MANAGEMENT = "/admin/edges/resources/{systemKey}/deploy"
	_EDGES_USER_V3           = "/api/v/3/edges/"
)

type EdgeConfig struct {
	EdgeName     string
	EdgeToken    string
	PlatformIP   string
	PlatformPort string
	ParentSystem string
	HttpPort     string
	MqttPort     string
	MqttTlsPort  string
	WsPort       string
	WssPort      string
	AuthPort     string
	AuthWsPort   string
	Lean         bool
	Cache        bool
	LogLevel     string
	Stdout       *os.File
	Stderr       *os.File
}

func CreateNewEdge(e EdgeConfig) (*os.Process, error) {
	_, err := exec.LookPath("edge")
	if err != nil {
		println("edge not found in $PATH")
		return nil, err
	}
	cmd := parseEdgeConfig(e)
	return cmd.Process, cmd.Start()
}

func (u *UserClient) GetEdges(systemKey string) ([]interface{}, error) {
	return u.GetEdgesWithQuery(systemKey, nil)
}

func (u *UserClient) GetEdgesWithQuery(systemKey string, query *Query) ([]interface{}, error) {
	creds, err := u.credentials()
	if err != nil {
		return nil, err
	}

	qry, err := createQueryMap(query)
	if err != nil {
		return nil, err
	}

	resp, err := get(u, _EDGES_USER_PREAMBLE+systemKey, qry, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (d *DevClient) GetEdges(systemKey string) ([]interface{}, error) {
	return d.GetEdgesWithQuery(systemKey, nil)
}

func (d *DevClient) GetEdgesWithQuery(systemKey string, query *Query) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}

	qry, err := createQueryMap(query)
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_PREAMBLE+systemKey, qry, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (d *DevClient) GetEdge(systemKey, name string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_PREAMBLE+systemKey+"/"+name, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) CreateEdge(systemKey, name string,
	data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := post(d, _EDGES_PREAMBLE+systemKey+"/"+name, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) DeleteEdge(systemKey, name string) error {
	return deleteEdge(d, systemKey, _EDGES_PREAMBLE, name)
}

func (u *UserClient) DeleteEdge(systemKey, name string) error {
	return deleteEdge(u, systemKey, _EDGES_USER_V3, name)
}

func deleteEdge(client cbClient, systemKey, preamble string, name string) error {
	creds, err := client.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(client, preamble+systemKey+"/"+name, nil, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (d *DevClient) UpdateEdge(systemKey string, name string, changes map[string]interface{}) (map[string]interface{}, error) {
	return updateEdge(d, systemKey, _EDGES_PREAMBLE, name, changes)
}

func (u *UserClient) UpdateEdge(systemKey string, name string, changes map[string]interface{}) (map[string]interface{}, error) {
	return updateEdge(u, systemKey, _EDGES_USER_V3, name, changes)
}

func updateEdge(client cbClient, systemKey, preamble string, name string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := client.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(client, preamble+systemKey+"/"+name, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

const (
	ServiceSync = "service"
	LibrarySync = "library"
	TriggerSync = "trigger"
	TimerSync   = "timer"
)

func (d *DevClient) GetDeployResourcesForSystem(systemKey string) ([]map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1), nil, creds, nil)
	if err != nil {
		return nil, err
	}
	return makeSliceOfMaps(resp.Body)
}

func (d *DevClient) serializeQuery(qIF interface{}) (string, error) {
	switch qIF.(type) {
	case string:
		return qIF.(string), nil
	case *Query:
		q := qIF.(*Query)
		qs, err := json.Marshal(q.serialize())
		if err != nil {
			return "", err
		}
		return string(qs), nil
	default:
		return "", fmt.Errorf("Bad query type: %T", qIF)
	}
}

func (d *DevClient) CreateDeployResourcesForSystem(systemKey, resourceName, resourceType string, platform bool, edgeQueryInfo interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	queryString, err := d.serializeQuery(edgeQueryInfo)
	//queryString, err := json.Marshal(edgeQuery.serialize())
	if err != nil {
		return nil, err
	}
	deploySpec := map[string]interface{}{
		"edge":                string(queryString[:]),
		"platform":            platform,
		"resource_identifier": resourceName,
		"resource_type":       resourceType,
	}
	resp, err := post(d, strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1), deploySpec, creds, nil)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) UpdateDeployResourcesForSystem(systemKey, resourceName, resourceType string, platform bool, edgeQuery *Query) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	queryString, err := json.Marshal(edgeQuery.serialize())
	if err != nil {
		return nil, err
	}
	updatedDeploySpec := map[string]interface{}{
		"edge":                queryString,
		"platform":            platform,
		"resource_identifier": resourceName,
		"resource_type":       resourceType,
	}
	resp, err := put(d, strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1), updatedDeploySpec, creds, nil)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) DeleteDeployResourcesForSystem(systemKey, resourceName, resourceType string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	urlString := strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1)
	urlString += "?resource_type=" + resourceType + "&resource_identifier=" + resourceName
	_, err = put(d, urlString, nil, creds, nil)
	return err
}

func (d *DevClient) GetSyncResourcesForEdge(systemKey string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_SYNC_MANAGEMENT+systemKey, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) SyncResourceToEdge(systemKey, edgeName string, add map[string][]string, remove map[string][]string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	if add == nil {
		add = map[string][]string{}
	}
	if remove == nil {
		remove = map[string][]string{}
	}
	changes := map[string][]map[string]interface{}{
		"add":    mapSyncChanges(add),
		"remove": mapSyncChanges(remove),
	}
	resp, err := put(d, _EDGES_SYNC_MANAGEMENT+systemKey+"/"+edgeName, changes, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) CreateEdgeColumn(systemKey, colName, colType string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	data := map[string]interface{}{
		"column_name": colName,
		"type":        colType,
	}
	resp, err := post(d, _EDGES_PREAMBLE+systemKey+"/columns", data, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (d *DevClient) DeleteEdgeColumn(systemKey, colName string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(d, _EDGES_PREAMBLE+systemKey+"/columns", map[string]string{"column": colName}, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (d *DevClient) GetEdgeColumns(systemKey string) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_PREAMBLE+systemKey+"/columns", nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}
<commit_msg>allow users to create edges with permissions<commit_after>package GoSDK

import (
	"encoding/json"
	"fmt"
	"os"
	"os/exec"
	"strings"
)

const (
	_EDGES_PREAMBLE          = "/admin/edges/"
	_EDGES_USER_PREAMBLE     = "/api/v/2/edges/"
	_EDGES_SYNC_MANAGEMENT   = "/admin/edges/sync/"
	_EDGES_DEPLOY_MANAGEMENT = "/admin/edges/resources/{systemKey}/deploy"
	_EDGES_USER_V3           = "/api/v/3/edges/"
)

type EdgeConfig struct {
	EdgeName     string
	EdgeToken    string
	PlatformIP   string
	PlatformPort string
	ParentSystem string
	HttpPort     string
	MqttPort     string
	MqttTlsPort  string
	WsPort       string
	WssPort      string
	AuthPort     string
	AuthWsPort   string
	Lean         bool
	Cache        bool
	LogLevel     string
	Stdout       *os.File
	Stderr       *os.File
}

func CreateNewEdge(e EdgeConfig) (*os.Process, error) {
	_, err := exec.LookPath("edge")
	if err != nil {
		println("edge not found in $PATH")
		return nil, err
	}
	cmd := parseEdgeConfig(e)
	return cmd.Process, cmd.Start()
}

func (u *UserClient) GetEdges(systemKey string) ([]interface{}, error) {
	return u.GetEdgesWithQuery(systemKey, nil)
}

func (u *UserClient) GetEdgesWithQuery(systemKey string, query *Query) ([]interface{}, error) {
	creds, err := u.credentials()
	if err != nil {
		return nil, err
	}

	qry, err := createQueryMap(query)
	if err != nil {
		return nil, err
	}

	resp, err := get(u, _EDGES_USER_PREAMBLE+systemKey, qry, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (d *DevClient) GetEdges(systemKey string) ([]interface{}, error) {
	return d.GetEdgesWithQuery(systemKey, nil)
}

func (d *DevClient) GetEdgesWithQuery(systemKey string, query *Query) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}

	qry, err := createQueryMap(query)
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_PREAMBLE+systemKey, qry, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}

func (d *DevClient) GetEdge(systemKey, name string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_PREAMBLE+systemKey+"/"+name, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) CreateEdge(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return createEdge(d, systemKey, _EDGES_PREAMBLE, name, data)
}

func (u *UserClient) CreateEdge(systemKey, name string, data map[string]interface{}) (map[string]interface{}, error) {
	return createEdge(u, systemKey, _EDGES_USER_V3, name, data)
}

func createEdge(client cbClient, systemKey, preamble string, name string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := client.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := post(client, preamble+systemKey+"/"+name, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) DeleteEdge(systemKey, name string) error {
	return deleteEdge(d, systemKey, _EDGES_PREAMBLE, name)
}

func (u *UserClient) DeleteEdge(systemKey, name string) error {
	return deleteEdge(u, systemKey, _EDGES_USER_V3, name)
}

func deleteEdge(client cbClient, systemKey, preamble string, name string) error {
	creds, err := client.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(client, preamble+systemKey+"/"+name, nil, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (d *DevClient) UpdateEdge(systemKey string, name string, changes map[string]interface{}) (map[string]interface{}, error) {
	return updateEdge(d, systemKey, _EDGES_PREAMBLE, name, changes)
}

func (u *UserClient) UpdateEdge(systemKey string, name string, changes map[string]interface{}) (map[string]interface{}, error) {
	return updateEdge(u, systemKey, _EDGES_USER_V3, name, changes)
}

func updateEdge(client cbClient, systemKey, preamble string, name string, data map[string]interface{}) (map[string]interface{}, error) {
	creds, err := client.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := put(client, preamble+systemKey+"/"+name, data, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

const (
	ServiceSync = "service"
	LibrarySync = "library"
	TriggerSync = "trigger"
	TimerSync   = "timer"
)

func (d *DevClient) GetDeployResourcesForSystem(systemKey string) ([]map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1), nil, creds, nil)
	if err != nil {
		return nil, err
	}
	return makeSliceOfMaps(resp.Body)
}

func (d *DevClient) serializeQuery(qIF interface{}) (string, error) {
	switch qIF.(type) {
	case string:
		return qIF.(string), nil
	case *Query:
		q := qIF.(*Query)
		qs, err := json.Marshal(q.serialize())
		if err != nil {
			return "", err
		}
		return string(qs), nil
	default:
		return "", fmt.Errorf("Bad query type: %T", qIF)
	}
}

func (d *DevClient) CreateDeployResourcesForSystem(systemKey, resourceName, resourceType string, platform bool, edgeQueryInfo interface{}) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	queryString, err := d.serializeQuery(edgeQueryInfo)
	//queryString, err := json.Marshal(edgeQuery.serialize())
	if err != nil {
		return nil, err
	}
	deploySpec := map[string]interface{}{
		"edge":                string(queryString[:]),
		"platform":            platform,
		"resource_identifier": resourceName,
		"resource_type":       resourceType,
	}
	resp, err := post(d, strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1), deploySpec, creds, nil)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) UpdateDeployResourcesForSystem(systemKey, resourceName, resourceType string, platform bool, edgeQuery *Query) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	queryString, err := json.Marshal(edgeQuery.serialize())
	if err != nil {
		return nil, err
	}
	updatedDeploySpec := map[string]interface{}{
		"edge":                queryString,
		"platform":            platform,
		"resource_identifier": resourceName,
		"resource_type":       resourceType,
	}
	resp, err := put(d, strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1), updatedDeploySpec, creds, nil)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) DeleteDeployResourcesForSystem(systemKey, resourceName, resourceType string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	urlString := strings.Replace(_EDGES_DEPLOY_MANAGEMENT, "{systemKey}", systemKey, 1)
	urlString += "?resource_type=" + resourceType + "&resource_identifier=" + resourceName
	_, err = put(d, urlString, nil, creds, nil)
	return err
}

func (d *DevClient) GetSyncResourcesForEdge(systemKey string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_SYNC_MANAGEMENT+systemKey, nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) SyncResourceToEdge(systemKey, edgeName string, add map[string][]string, remove map[string][]string) (map[string]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	if add == nil {
		add = map[string][]string{}
	}
	if remove == nil {
		remove = map[string][]string{}
	}
	changes := map[string][]map[string]interface{}{
		"add":    mapSyncChanges(add),
		"remove": mapSyncChanges(remove),
	}
	resp, err := put(d, _EDGES_SYNC_MANAGEMENT+systemKey+"/"+edgeName, changes, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.(map[string]interface{}), nil
}

func (d *DevClient) CreateEdgeColumn(systemKey, colName, colType string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	data := map[string]interface{}{
		"column_name": colName,
		"type":        colType,
	}
	resp, err := post(d, _EDGES_PREAMBLE+systemKey+"/columns", data, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (d *DevClient) DeleteEdgeColumn(systemKey, colName string) error {
	creds, err := d.credentials()
	if err != nil {
		return err
	}
	resp, err := delete(d, _EDGES_PREAMBLE+systemKey+"/columns", map[string]string{"column": colName}, creds, nil)
	_, err = mapResponse(resp, err)
	return err
}

func (d *DevClient) GetEdgeColumns(systemKey string) ([]interface{}, error) {
	creds, err := d.credentials()
	if err != nil {
		return nil, err
	}
	resp, err := get(d, _EDGES_PREAMBLE+systemKey+"/columns", nil, creds, nil)
	resp, err = mapResponse(resp, err)
	if err != nil {
		return nil, err
	}
	return resp.Body.([]interface{}), nil
}
<|endoftext|>


<commit_before>package eff

type EffectivenessSlice []Effectiveness

func All() EffectivenessSlice {
	result := make([]Effectiveness, 4)
	for i, e := 0, EX; e <= EO; i, e = i+1, e+1 {
		result[i] = e
	}
	return result
}

func (es EffectivenessSlice) ForEach(consumer func(Effectiveness)) {
	for _, e := range es {
		consumer(e)
	}
}
<commit_msg>Updated 'EffectivenessSlice' to follow that of PokemonSlice<commit_after>package eff

import (
	"sort"
)

type EffectivenessIterable interface {
	ForEach(consumer func(Effectiveness))
	Filter(predicate func(Effectiveness) bool) EffectivenessIterable
	Sort(less func(Effectiveness, Effectiveness) bool) EffectivenessIterable
}

type EffectivenessSlice []Effectiveness

func (es EffectivenessSlice) ForEach(consumer func(Effectiveness)) {
	for _, e := range es {
		consumer(e)
	}
}

func (es EffectivenessSlice) Filter(predicate func(Effectiveness) bool) EffectivenessIterable {
	result := make(EffectivenessSlice, 0)
	for _, e := range es {
		if predicate(e) {
			result = append(result, e)
		}
	}
	return result
}

func (es EffectivenessSlice) Sort(less func(Effectiveness, Effectiveness) bool) EffectivenessIterable {
	result := make(EffectivenessSlice, len(es))
	copy(result, es)
	sort.Stable(sortableEffectivenessSlice{result, less})
	return result
}

func All() EffectivenessIterable {
	return virtualEffectivenessSlice(0)
}

type virtualEffectivenessSlice int

func (es virtualEffectivenessSlice) ForEach(consumer func(Effectiveness)) {
	for e := EX; e <= EO; e++ {
		consumer(e)
	}
}

func (es virtualEffectivenessSlice) Filter(predicate func(Effectiveness) bool) EffectivenessIterable {
	result := make(EffectivenessSlice, 0)
	for e := EX; e <= EO; e++ {
		if predicate(e) {
			result = append(result, e)
		}
	}
	return result
}

func (es virtualEffectivenessSlice) Sort(less func(Effectiveness, Effectiveness) bool) EffectivenessIterable {
	result := make(EffectivenessSlice, 4)
	for i, e := 0, EX; e <= EO; i, e = i+1, e+1 {
		result[i] = e
	}
	sort.Stable(sortableEffectivenessSlice{result, less})
	return result
}

type sortableEffectivenessSlice struct {
	slice EffectivenessSlice
	less  func(Effectiveness, Effectiveness) bool
}

func (es sortableEffectivenessSlice) Len() int {
	return len(es.slice)
}

func (es sortableEffectivenessSlice) Less(i, j int) bool {
	return es.less(es.slice[i], es.slice[j])
}

func (es sortableEffectivenessSlice) Swap(i, j int) {
	es.slice[i], es.slice[j] = es.slice[j], es.slice[i]
}
<|endoftext|>


<commit_before>package m_etcd

// NOTES
//
// These tests are in reality integration tests which require that
// etcd is running on the test system and its peers are found
// in the ENV variable ETCDCTL_PEERS. The tests do not clean
// out data and require a fresh set of etcd instances for
// each run. You can consider this a known bug which
// will be fixed in a future release.
//
// See: https://github.com/lytics/metafora/issues/31

import (
	"os"
	"strings"
	"testing"

	"github.com/coreos/go-etcd/etcd"
	"github.com/lytics/metafora"
)

const (
	Namespace   = `test`
	NodesDir    = `/test/nodes`
	Node1       = `node1`
	Node1Path   = NodesDir + `/` + Node1
	CommandJsor = `{"command":"testing"}`
)

// TestNodes tests that client.Nodes() returns the metafora nodes
// registered in etcd.
func TestNodes(t *testing.T) {
	eclient := newEtcdClient(t)
	const recursive = true
	eclient.Delete(Node1Path, recursive)

	mclient := NewClient(Namespace, eclient)

	if _, err := eclient.CreateDir(Node1Path, 0); err != nil {
		t.Fatalf("AddChild %v returned error: %v", NodesDir, err)
	}

	if nodes, err := mclient.Nodes(); err != nil {
		t.Fatalf("Nodes returned error: %v", err)
	} else {
		for i, n := range nodes {
			t.Logf("%v -> %v", i, n)
		}
	}
}

// TestSubmitTask tests that client.SubmitTask(...) adds a task to
// the proper path in etcd, and that the same task id cannot be
// submitted more than once.
func TestSubmitTask(t *testing.T) {
	eclient := newEtcdClient(t)

	mclient := NewClientWithLogger(Namespace, eclient, testLogger{"metafora-client", t})

	if err := mclient.DeleteTask("testid1"); err != nil {
		t.Logf("DeleteTask returned an error, which maybe ok.  Error:%v", err)
	}

	if err := mclient.SubmitTask("testid1"); err != nil {
		t.Fatalf("Submit task failed on initial submission, error: %v", err)
	}

	if err := mclient.SubmitTask("testid1"); err == nil {
		t.Fatalf("Submit task did not fail, but should of, when using existing tast id")
	}
}

// TestSubmitCommand tests that client.SubmitCommand(...) adds a command
// to the proper node path in etcd, and that it can be read back.
func TestSubmitCommand(t *testing.T) {
	eclient := newEtcdClient(t)

	mclient := NewClient(Namespace, eclient)

	if err := mclient.SubmitCommand(Node1, metafora.CommandFreeze()); err != nil {
		t.Fatalf("Unable to submit command.   error:%v", err)
	}

	if res, err := eclient.Get(NodesDir, false, false); err != nil {
		t.Fatalf("Get on path %v returned error: %v", NodesDir, err)
	} else if res.Node == nil || res.Node.Nodes == nil {
		t.Fatalf("Get on path %v returned nil for child nodes", NodesDir)
	} else {
		for i, n := range res.Node.Nodes {
			t.Logf("%v -> %v", i, n)
		}
	}
}

// newEtcdClient creates a new etcd client for use by the metafora client during testing.
func newEtcdClient(t *testing.T) *etcd.Client {
	if os.Getenv("ETCDTESTS") == "" {
		t.Skip("ETCDTESTS unset. Skipping etcd tests.")
	}

	// This is the same ENV variable that etcdctl uses for peers.
	peerAddrs := os.Getenv("ETCDCTL_PEERS")

	if peerAddrs == "" {
		peerAddrs = "127.0.0.1:5001,127.0.0.1:5002,127.0.0.1:5003"
	}

	peers := strings.Split(peerAddrs, ",")

	eclient := etcd.NewClient(peers)

	if ok := eclient.SyncCluster(); !ok {
		t.Fatalf("Cannot sync etcd cluster using peers: %v", strings.Join(peers, ", "))
	}

	eclient.SetConsistency(etcd.STRONG_CONSISTENCY)

	return eclient
}
<commit_msg>De-jsor<commit_after>package m_etcd

// NOTES
//
// These tests are in reality integration tests which require that
// etcd is running on the test system and its peers are found
// in the ENV variable ETCDCTL_PEERS. The tests do not clean
// out data and require a fresh set of etcd instances for
// each run. You can consider this a known bug which
// will be fixed in a future release.
//
// See: https://github.com/lytics/metafora/issues/31

import (
	"os"
	"strings"
	"testing"

	"github.com/coreos/go-etcd/etcd"
	"github.com/lytics/metafora"
)

const (
	Namespace = `test`
	NodesDir  = `/test/nodes`
	Node1     = `node1`
	Node1Path = NodesDir + `/` + Node1
)

// TestNodes tests that client.Nodes() returns the metafora nodes
// registered in etcd.
func TestNodes(t *testing.T) {
	eclient := newEtcdClient(t)
	const recursive = true
	eclient.Delete(Node1Path, recursive)

	mclient := NewClient(Namespace, eclient)

	if _, err := eclient.CreateDir(Node1Path, 0); err != nil {
		t.Fatalf("AddChild %v returned error: %v", NodesDir, err)
	}

	if nodes, err := mclient.Nodes(); err != nil {
		t.Fatalf("Nodes returned error: %v", err)
	} else {
		for i, n := range nodes {
			t.Logf("%v -> %v", i, n)
		}
	}
}

// TestSubmitTask tests that client.SubmitTask(...) adds a task to
// the proper path in etcd, and that the same task id cannot be
// submitted more than once.
func TestSubmitTask(t *testing.T) {
	eclient := newEtcdClient(t)

	mclient := NewClientWithLogger(Namespace, eclient, testLogger{"metafora-client", t})

	if err := mclient.DeleteTask("testid1"); err != nil {
		t.Logf("DeleteTask returned an error, which maybe ok.  Error:%v", err)
	}

	if err := mclient.SubmitTask("testid1"); err != nil {
		t.Fatalf("Submit task failed on initial submission, error: %v", err)
	}

	if err := mclient.SubmitTask("testid1"); err == nil {
		t.Fatalf("Submit task did not fail, but should of, when using existing tast id")
	}
}

// TestSubmitCommand tests that client.SubmitCommand(...) adds a command
// to the proper node path in etcd, and that it can be read back.
func TestSubmitCommand(t *testing.T) {
	eclient := newEtcdClient(t)

	mclient := NewClient(Namespace, eclient)

	if err := mclient.SubmitCommand(Node1, metafora.CommandFreeze()); err != nil {
		t.Fatalf("Unable to submit command.   error:%v", err)
	}

	if res, err := eclient.Get(NodesDir, false, false); err != nil {
		t.Fatalf("Get on path %v returned error: %v", NodesDir, err)
	} else if res.Node == nil || res.Node.Nodes == nil {
		t.Fatalf("Get on path %v returned nil for child nodes", NodesDir)
	} else {
		for i, n := range res.Node.Nodes {
			t.Logf("%v -> %v", i, n)
		}
	}
}

// newEtcdClient creates a new etcd client for use by the metafora client during testing.
func newEtcdClient(t *testing.T) *etcd.Client {
	if os.Getenv("ETCDTESTS") == "" {
		t.Skip("ETCDTESTS unset. Skipping etcd tests.")
	}

	// This is the same ENV variable that etcdctl uses for peers.
	peerAddrs := os.Getenv("ETCDCTL_PEERS")

	if peerAddrs == "" {
		peerAddrs = "127.0.0.1:5001,127.0.0.1:5002,127.0.0.1:5003"
	}

	peers := strings.Split(peerAddrs, ",")

	eclient := etcd.NewClient(peers)

	if ok := eclient.SyncCluster(); !ok {
		t.Fatalf("Cannot sync etcd cluster using peers: %v", strings.Join(peers, ", "))
	}

	eclient.SetConsistency(etcd.STRONG_CONSISTENCY)

	return eclient
}
<|endoftext|>


<commit_before>package m_etcd

import (
	"os"
	"strings"
	"testing"

	"github.com/coreos/go-etcd/etcd"
)

func TestEtcdClientIntegration(t *testing.T) {
	if os.Getenv("IntegrationTests") == "" {
		return
	}

	eclient := createEtcdClient(t)

	mclient := NewEtcdClient("test", eclient)

	if err := mclient.SubmitTask("testid1"); err != nil {
		t.Fatalf("Unable to submit task.   error:%v", err)
	}

	if err := mclient.SubmitTask("testid1"); err == nil {
		t.Fatalf("We shoudln't have been allowed to submit the same task twice.   error:%v", err)
	}
}

func createEtcdClient(t *testing.T) *etcd.Client {
	peers_from_environment := os.Getenv("ETCDCTL_PEERS") //This is the same ENV that etcdctl uses for Peers.

	if peers_from_environment == "" {
		peers_from_environment = "localhost:5001,localhost:5002,localhost:5003"
	}

	peers := strings.Split(peers_from_environment, ",")

	client := etcd.NewClient(peers)

	ok := client.SyncCluster()

	if !ok {
		t.Fatalf("Cannot sync with the cluster using peers " + strings.Join(peers, ", "))
	}

	if !isEtcdUp(client, t) {
		t.Fatalf("While testing etcd, the test couldn't connect to etcd. " + strings.Join(peers, ", "))
	}

	return client

}
<commit_msg>Adding skipEtcd(t) to the client tests.<commit_after>package m_etcd

import (
	"os"
	"strings"
	"testing"

	"github.com/coreos/go-etcd/etcd"
)

func TestEtcdClientIntegration(t *testing.T) {
	skipEtcd(t)

	eclient := createEtcdClient(t)

	mclient := NewEtcdClient("test", eclient)

	if err := mclient.SubmitTask("testid1"); err != nil {
		t.Fatalf("Unable to submit task.   error:%v", err)
	}

	if err := mclient.SubmitTask("testid1"); err == nil {
		t.Fatalf("We shoudln't have been allowed to submit the same task twice.   error:%v", err)
	}
}

func createEtcdClient(t *testing.T) *etcd.Client {
	peers_from_environment := os.Getenv("ETCDCTL_PEERS") //This is the same ENV that etcdctl uses for Peers.

	if peers_from_environment == "" {
		peers_from_environment = "localhost:5001,localhost:5002,localhost:5003"
	}

	peers := strings.Split(peers_from_environment, ",")

	client := etcd.NewClient(peers)

	ok := client.SyncCluster()

	if !ok {
		t.Fatalf("Cannot sync with the cluster using peers " + strings.Join(peers, ", "))
	}

	if !isEtcdUp(client, t) {
		t.Fatalf("While testing etcd, the test couldn't connect to etcd. " + strings.Join(peers, ", "))
	}

	return client

}
<|endoftext|>


<commit_before>package notification

import (
	"fmt"
	socialapimodels "socialapi/models"
	"socialapi/workers/notification/models"
	"time"

	"github.com/koding/bongo"
	"github.com/koding/logging"
	"github.com/koding/rabbitmq"
	"github.com/streadway/amqp"
)

const (
	NOTIFICATION_TYPE_SUBSCRIBE   = "subscribe"
	NOTIFICATION_TYPE_UNSUBSCRIBE = "unsubscribe"
)

type Controller struct {
	log             logging.Logger
	rmqConn         *amqp.Connection
	notifierRmqConn *amqp.Connection
}

func (n *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	n.log.Error("an error occured: %s", err)
	delivery.Ack(false)

	return false
}

func New(rmq *rabbitmq.RabbitMQ, log logging.Logger) (*Controller, error) {
	rmqConn, err := rmq.Connect("NewNotificationWorkerController")
	if err != nil {
		return nil, err
	}

	nwc := &Controller{
		log:     log,
		rmqConn: rmqConn.Conn(),
	}

	return nwc, nil
}

// this is temporary method used for hiding private message notifications
// previously created. Once it is run in all servers, it will be deleted
func HidePMNotifications() {
	// n.log.Debug("hiding pm notifications")
	fmt.Println("hiding pm notifications")
	var ids []int64
	nc := models.NewNotificationContent()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"type_constant": models.NotificationContent_TYPE_PM,
		},
		Pluck: "id",
	}

	if err := nc.Some(&ids, query); err != nil {
		fmt.Printf("Could not hide pm notifications: %s \n", err)
		return
	}

	if len(ids) == 0 {
		return
	}

	ntf := models.NewNotification()

	updateSql := "UPDATE " + ntf.TableName() + ` set "activated_at" = ? WHERE "notification_content_id" in (?)`

	err := bongo.B.DB.Exec(updateSql, time.Time{}, ids).Error
	if err != nil {
		fmt.Printf("Could not hide pm notifications: %s \n", err)
	}
}

// CreateReplyNotification notifies main thread owner.
func (n *Controller) CreateReplyNotification(mr *socialapimodels.MessageReply) error {
	// fetch replier
	reply := socialapimodels.NewChannelMessage()
	if err := reply.ById(mr.ReplyId); err != nil {
		return err
	}

	cm := socialapimodels.NewChannelMessage()
	// notify message owner
	if err := cm.ById(mr.MessageId); err != nil {
		return err
	}

	if cm.TypeConstant != socialapimodels.ChannelMessage_TYPE_POST {
		return nil
	}

	rn := models.NewReplyNotification()
	rn.TargetId = mr.MessageId
	rn.NotifierId = reply.AccountId
	rn.MessageId = reply.Id

	subscribedAt := time.Now()

	nc, err := models.CreateNotificationContent(rn)
	if err != nil {
		return err
	}

	// if it is not notifier's own message then add replier to subscribers
	// for further reply notifications
	if cm.AccountId != rn.NotifierId {
		n.subscribe(nc.Id, cm.AccountId, subscribedAt)
	}

	notifiedUsers, err := rn.GetNotifiedUsers(nc.Id)
	if err != nil {
		return err
	}

	mentionedUsers, err := n.CreateMentionNotification(reply, cm.Id)
	if err != nil {
		return err
	}

	// if a user is already subscribed to a post, and also mentioned in a reply
	// just send mention notification -no need for reply notification.
	notifiedUsers = filterRepliers(notifiedUsers, mentionedUsers)

	notifierSubscribed := false
	for _, recipient := range notifiedUsers {
		if recipient == rn.NotifierId {
			notifierSubscribed = true
		}
		n.notify(nc.Id, recipient)
	}

	if !notifierSubscribed {
		n.subscribe(nc.Id, rn.NotifierId, subscribedAt)
	}

	return nil
}

// func (n *Controller) UnsubscribeMessage(data *socialapimodels.ChannelMessageList) error {
// 	return subscription(data, NOTIFICATION_TYPE_UNSUBSCRIBE)
// }

func subscription(cml *socialapimodels.ChannelMessageList, typeConstant string) error {
	c := socialapimodels.NewChannel()
	if err := c.ById(cml.ChannelId); err != nil {
		return err
	}

	if c.TypeConstant != socialapimodels.Channel_TYPE_PINNED_ACTIVITY {
		return nil
	}

	// user pinned (followed) a message
	nc := models.NewNotificationContent()
	nc.TargetId = cml.MessageId

	n := models.NewNotification()
	n.AccountId = c.CreatorId

	switch typeConstant {
	case NOTIFICATION_TYPE_SUBSCRIBE:
		return n.Subscribe(nc)
	case NOTIFICATION_TYPE_UNSUBSCRIBE:
		return n.Unsubscribe(nc)
	}

	return nil
}

func (n *Controller) HandleMessage(cm *socialapimodels.ChannelMessage) error {
	switch cm.TypeConstant {
	case socialapimodels.ChannelMessage_TYPE_POST:
		_, err := n.CreateMentionNotification(cm, cm.Id)
		return err
	case socialapimodels.ChannelMessage_TYPE_PRIVATE_MESSAGE:
		return n.privateMessageNotification(cm)
	default:
		return nil
	}
}

func (n *Controller) privateMessageNotification(cm *socialapimodels.ChannelMessage) error {
	if cm.TypeConstant != socialapimodels.ChannelMessage_TYPE_PRIVATE_MESSAGE {
		return nil
	}

	// fetch participants
	cp := socialapimodels.NewChannelParticipant()
	cp.ChannelId = cm.InitialChannelId
	time.Sleep(3 * time.Second)
	participantIds, err := cp.ListAccountIds(0)
	if err != nil {
		return err
	}

	if len(participantIds) == 0 {
		n.log.Warning("Private channel participant count cannot be 0")
		return nil
	}

	pn := models.NewPMNotification()
	pn.TargetId = cm.InitialChannelId
	pn.NotifierId = cm.AccountId
	nc, err := models.CreateNotificationContent(pn)
	if err != nil {
		return err
	}

	for _, participant := range participantIds {
		if cm.AccountId != participant {
			n.notifyOnce(nc.Id, participant)
		}
	}

	return nil
}

// CreateMentionNotification creates mention notifications for the related channel messages
func (n *Controller) CreateMentionNotification(reply *socialapimodels.ChannelMessage, targetId int64) ([]int64, error) {
	mentionedUserIds := make([]int64, 0)
	usernames := reply.GetMentionedUsernames()

	// message does not contain any mentioned users
	if len(usernames) == 0 {
		return mentionedUserIds, nil
	}

	mentionedUsers, err := socialapimodels.FetchAccountsByNicks(usernames)
	if err != nil {
		return nil, err
	}

	for _, mentionedUser := range mentionedUsers {
		// if user mentions herself ignore it
		if mentionedUser.Id == reply.AccountId {
			continue
		}
		mn := models.NewMentionNotification()
		mn.TargetId = targetId
		mn.MessageId = reply.Id
		mn.NotifierId = reply.AccountId
		nc, err := models.CreateNotificationContent(mn)
		if err != nil {
			return nil, err
		}

		n.instantNotify(nc.Id, mentionedUser.Id)

		mentionedUserIds = append(mentionedUserIds, mentionedUser.Id)
	}

	return mentionedUserIds, nil
}

func (n *Controller) notify(contentId, notifierId int64) {
	notification := buildNotification(contentId, notifierId, time.Now())
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) instantNotify(contentId, notifierId int64) {
	notification := prepareActiveNotification(contentId, notifierId)
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) notifyOnce(contentId, notifierId int64) {
	notification := prepareActiveNotification(contentId, notifierId)
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func prepareActiveNotification(contentId, notifierId int64) *models.Notification {
	notification := buildNotification(contentId, notifierId, time.Now())
	notification.ActivatedAt = time.Now()

	return notification
}

func (n *Controller) subscribe(contentId, notifierId int64, subscribedAt time.Time) {
	notification := buildNotification(contentId, notifierId, subscribedAt)
	notification.SubscribeOnly = true
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while subscribing user %d: %s", notification.AccountId, err.Error())
	}
}

func buildNotification(contentId, notifierId int64, subscribedAt time.Time) *models.Notification {
	notification := models.NewNotification()
	notification.NotificationContentId = contentId
	notification.AccountId = notifierId
	notification.SubscribedAt = subscribedAt

	return notification
}

func (n *Controller) CreateInteractionNotification(i *socialapimodels.Interaction) error {
	cm := socialapimodels.NewChannelMessage()
	if err := cm.ById(i.MessageId); err != nil {
		return err
	}

	// user likes her own message, so we bypass notification
	if cm.AccountId == i.AccountId {
		return nil
	}

	in := models.NewInteractionNotification(i.TypeConstant)
	in.TargetId = i.MessageId
	in.NotifierId = i.AccountId
	nc, err := models.CreateNotificationContent(in)
	if err != nil {
		return err
	}

	notification := models.NewNotification()
	notification.NotificationContentId = nc.Id
	notification.AccountId = cm.AccountId // notify message owner
	notification.ActivatedAt = time.Now() // enables notification immediately
	if err = notification.Upsert(); err != nil {
		return fmt.Errorf("An error occurred while notifying user %d: %s", cm.AccountId, err.Error())
	}

	return nil
}

func filterRepliers(repliers, mentionedUsers []int64) []int64 {
	mentionMap := map[int64]struct{}{}
	flattened := make([]int64, 0)
	if len(mentionedUsers) == 0 {
		return repliers
	}

	for _, user := range mentionedUsers {
		mentionMap[user] = struct{}{}
	}

	for _, replier := range repliers {
		if _, ok := mentionMap[replier]; !ok {
			flattened = append(flattened, replier)
		}
	}

	return flattened
}
<commit_msg>Notification: Prevent private message notifications<commit_after>package notification

import (
	"fmt"
	socialapimodels "socialapi/models"
	"socialapi/workers/notification/models"
	"time"

	"github.com/koding/bongo"
	"github.com/koding/logging"
	"github.com/koding/rabbitmq"
	"github.com/streadway/amqp"
)

const (
	NOTIFICATION_TYPE_SUBSCRIBE   = "subscribe"
	NOTIFICATION_TYPE_UNSUBSCRIBE = "unsubscribe"
)

type Controller struct {
	log             logging.Logger
	rmqConn         *amqp.Connection
	notifierRmqConn *amqp.Connection
}

func (n *Controller) DefaultErrHandler(delivery amqp.Delivery, err error) bool {
	n.log.Error("an error occured: %s", err)
	delivery.Ack(false)

	return false
}

func New(rmq *rabbitmq.RabbitMQ, log logging.Logger) (*Controller, error) {
	rmqConn, err := rmq.Connect("NewNotificationWorkerController")
	if err != nil {
		return nil, err
	}

	nwc := &Controller{
		log:     log,
		rmqConn: rmqConn.Conn(),
	}

	return nwc, nil
}

// this is temporary method used for hiding private message notifications
// previously created. Once it is run in all servers, it will be deleted
func HidePMNotifications() {
	// n.log.Debug("hiding pm notifications")
	fmt.Println("hiding pm notifications")
	var ids []int64
	nc := models.NewNotificationContent()
	query := &bongo.Query{
		Selector: map[string]interface{}{
			"type_constant": models.NotificationContent_TYPE_PM,
		},
		Pluck: "id",
	}

	if err := nc.Some(&ids, query); err != nil {
		fmt.Printf("Could not hide pm notifications: %s \n", err)
		return
	}

	if len(ids) == 0 {
		return
	}

	ntf := models.NewNotification()

	updateSql := "UPDATE " + ntf.TableName() + ` set "activated_at" = ? WHERE "notification_content_id" in (?)`

	err := bongo.B.DB.Exec(updateSql, time.Time{}, ids).Error
	if err != nil {
		fmt.Printf("Could not hide pm notifications: %s \n", err)
	}
}

// CreateReplyNotification notifies main thread owner.
func (n *Controller) CreateReplyNotification(mr *socialapimodels.MessageReply) error {
	// fetch replier
	reply := socialapimodels.NewChannelMessage()
	if err := reply.ById(mr.ReplyId); err != nil {
		return err
	}

	cm := socialapimodels.NewChannelMessage()
	// notify message owner
	if err := cm.ById(mr.MessageId); err != nil {
		return err
	}

	if cm.TypeConstant != socialapimodels.ChannelMessage_TYPE_POST {
		return nil
	}

	rn := models.NewReplyNotification()
	rn.TargetId = mr.MessageId
	rn.NotifierId = reply.AccountId
	rn.MessageId = reply.Id

	subscribedAt := time.Now()

	nc, err := models.CreateNotificationContent(rn)
	if err != nil {
		return err
	}

	// if it is not notifier's own message then add replier to subscribers
	// for further reply notifications
	if cm.AccountId != rn.NotifierId {
		n.subscribe(nc.Id, cm.AccountId, subscribedAt)
	}

	notifiedUsers, err := rn.GetNotifiedUsers(nc.Id)
	if err != nil {
		return err
	}

	mentionedUsers, err := n.CreateMentionNotification(reply, cm.Id)
	if err != nil {
		return err
	}

	// if a user is already subscribed to a post, and also mentioned in a reply
	// just send mention notification -no need for reply notification.
	notifiedUsers = filterRepliers(notifiedUsers, mentionedUsers)

	notifierSubscribed := false
	for _, recipient := range notifiedUsers {
		if recipient == rn.NotifierId {
			notifierSubscribed = true
		}
		n.notify(nc.Id, recipient)
	}

	if !notifierSubscribed {
		n.subscribe(nc.Id, rn.NotifierId, subscribedAt)
	}

	return nil
}

// func (n *Controller) UnsubscribeMessage(data *socialapimodels.ChannelMessageList) error {
// 	return subscription(data, NOTIFICATION_TYPE_UNSUBSCRIBE)
// }

func subscription(cml *socialapimodels.ChannelMessageList, typeConstant string) error {
	c := socialapimodels.NewChannel()
	if err := c.ById(cml.ChannelId); err != nil {
		return err
	}

	if c.TypeConstant != socialapimodels.Channel_TYPE_PINNED_ACTIVITY {
		return nil
	}

	// user pinned (followed) a message
	nc := models.NewNotificationContent()
	nc.TargetId = cml.MessageId

	n := models.NewNotification()
	n.AccountId = c.CreatorId

	switch typeConstant {
	case NOTIFICATION_TYPE_SUBSCRIBE:
		return n.Subscribe(nc)
	case NOTIFICATION_TYPE_UNSUBSCRIBE:
		return n.Unsubscribe(nc)
	}

	return nil
}

func (n *Controller) HandleMessage(cm *socialapimodels.ChannelMessage) error {
	switch cm.TypeConstant {
	case socialapimodels.ChannelMessage_TYPE_POST:
		_, err := n.CreateMentionNotification(cm, cm.Id)
		return err
	default:
		return nil
	}
}

func (n *Controller) privateMessageNotification(cm *socialapimodels.ChannelMessage) error {
	if cm.TypeConstant != socialapimodels.ChannelMessage_TYPE_PRIVATE_MESSAGE {
		return nil
	}

	// fetch participants
	cp := socialapimodels.NewChannelParticipant()
	cp.ChannelId = cm.InitialChannelId
	time.Sleep(3 * time.Second)
	participantIds, err := cp.ListAccountIds(0)
	if err != nil {
		return err
	}

	if len(participantIds) == 0 {
		n.log.Warning("Private channel participant count cannot be 0")
		return nil
	}

	pn := models.NewPMNotification()
	pn.TargetId = cm.InitialChannelId
	pn.NotifierId = cm.AccountId
	nc, err := models.CreateNotificationContent(pn)
	if err != nil {
		return err
	}

	for _, participant := range participantIds {
		if cm.AccountId != participant {
			n.notifyOnce(nc.Id, participant)
		}
	}

	return nil
}

// CreateMentionNotification creates mention notifications for the related channel messages
func (n *Controller) CreateMentionNotification(reply *socialapimodels.ChannelMessage, targetId int64) ([]int64, error) {
	mentionedUserIds := make([]int64, 0)
	usernames := reply.GetMentionedUsernames()

	// message does not contain any mentioned users
	if len(usernames) == 0 {
		return mentionedUserIds, nil
	}

	mentionedUsers, err := socialapimodels.FetchAccountsByNicks(usernames)
	if err != nil {
		return nil, err
	}

	for _, mentionedUser := range mentionedUsers {
		// if user mentions herself ignore it
		if mentionedUser.Id == reply.AccountId {
			continue
		}
		mn := models.NewMentionNotification()
		mn.TargetId = targetId
		mn.MessageId = reply.Id
		mn.NotifierId = reply.AccountId
		nc, err := models.CreateNotificationContent(mn)
		if err != nil {
			return nil, err
		}

		n.instantNotify(nc.Id, mentionedUser.Id)

		mentionedUserIds = append(mentionedUserIds, mentionedUser.Id)
	}

	return mentionedUserIds, nil
}

func (n *Controller) notify(contentId, notifierId int64) {
	notification := buildNotification(contentId, notifierId, time.Now())
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) instantNotify(contentId, notifierId int64) {
	notification := prepareActiveNotification(contentId, notifierId)
	if err := notification.Upsert(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func (n *Controller) notifyOnce(contentId, notifierId int64) {
	notification := prepareActiveNotification(contentId, notifierId)
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while notifying user %d: %s", notification.AccountId, err.Error())
	}
}

func prepareActiveNotification(contentId, notifierId int64) *models.Notification {
	notification := buildNotification(contentId, notifierId, time.Now())
	notification.ActivatedAt = time.Now()

	return notification
}

func (n *Controller) subscribe(contentId, notifierId int64, subscribedAt time.Time) {
	notification := buildNotification(contentId, notifierId, subscribedAt)
	notification.SubscribeOnly = true
	if err := notification.Create(); err != nil {
		n.log.Error("An error occurred while subscribing user %d: %s", notification.AccountId, err.Error())
	}
}

func buildNotification(contentId, notifierId int64, subscribedAt time.Time) *models.Notification {
	notification := models.NewNotification()
	notification.NotificationContentId = contentId
	notification.AccountId = notifierId
	notification.SubscribedAt = subscribedAt

	return notification
}

func (n *Controller) CreateInteractionNotification(i *socialapimodels.Interaction) error {
	cm := socialapimodels.NewChannelMessage()
	if err := cm.ById(i.MessageId); err != nil {
		return err
	}

	// user likes her own message, so we bypass notification
	if cm.AccountId == i.AccountId {
		return nil
	}

	in := models.NewInteractionNotification(i.TypeConstant)
	in.TargetId = i.MessageId
	in.NotifierId = i.AccountId
	nc, err := models.CreateNotificationContent(in)
	if err != nil {
		return err
	}

	notification := models.NewNotification()
	notification.NotificationContentId = nc.Id
	notification.AccountId = cm.AccountId // notify message owner
	notification.ActivatedAt = time.Now() // enables notification immediately
	if err = notification.Upsert(); err != nil {
		return fmt.Errorf("An error occurred while notifying user %d: %s", cm.AccountId, err.Error())
	}

	return nil
}

func filterRepliers(repliers, mentionedUsers []int64) []int64 {
	mentionMap := map[int64]struct{}{}
	flattened := make([]int64, 0)
	if len(mentionedUsers) == 0 {
		return repliers
	}

	for _, user := range mentionedUsers {
		mentionMap[user] = struct{}{}
	}

	for _, replier := range repliers {
		if _, ok := mentionMap[replier]; !ok {
			flattened = append(flattened, replier)
		}
	}

	return flattened
}
<|endoftext|>


<commit_before>package render

import (
	"bytes"
	"encoding/json"
	"html/template"
	"log"
	"net/http"
	"path/filepath"
	"strings"
	"sync"
)

// An interface of suggested methods for rendering output in Go
type MiloRenderer interface {
	RenderTemplates(w http.ResponseWriter, r *http.Request, data map[string]interface{}, tpls ...string)
	RenderJson(w http.ResponseWriter, r *http.Request, data interface{})
	RenderError(w http.ResponseWriter, r *http.Request, code int, message string)
	RenderMessage(w http.ResponseWriter, r *http.Request, message string)
	RegisterTemplateFunc(key string, fn interface{})
	Redirect(w http.ResponseWriter, r *http.Request, url string, code int)
}

// Default milo renderer that can cache templates, sets a base template directory.
type DefaultMiloRenderer struct {
	templateCache map[string]*template.Template
	tplDir        string
	tplFuncs      map[string]interface{}
	cacheTpls     bool
	sync.RWMutex
}

// Create a new default milo renderer.
func NewDefaultMiloRenderer(tplDir string, cache bool) MiloRenderer {
	r := &DefaultMiloRenderer{templateCache: make(map[string]*template.Template), tplDir: tplDir, tplFuncs: make(map[string]interface{}), cacheTpls: cache}
	r.tplFuncs["host"] = Host
	r.tplFuncs["marshal"] = Marshal
	return r
}

// Takes care of rendering templates from file.
func (mr *DefaultMiloRenderer) RenderTemplates(w http.ResponseWriter, r *http.Request, data map[string]interface{}, tpls ...string) {
	if len(tpls) < 1 {
		w.WriteHeader(500)
		w.Write([]byte("Error: Template required!"))
		return
	}

	log.Println("Rendering the templates")

	list := make([]string, 0)
	for _, elem := range tpls {
		list = append(list, filepath.Join(mr.tplDir, elem))
	}

	if tpl, loadErr := mr.acquireTemplate(strings.Join(tpls, ""), list...); loadErr != nil {
		w.WriteHeader(500)
		w.Write([]byte(loadErr.Error()))
	} else {
		var doc bytes.Buffer
		err := tpl.Execute(&doc, data)
		if err == nil {
			w.WriteHeader(200)
			w.Write(doc.Bytes())
		} else {
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
		}
	}
}

// Unexported method to help handle template parsing.  If the cache template bool is set on the config
// struct this method with look in the cache & load the cache upon subsequent encounters.
// This should lower disk access penalties useful for production instances.
func (mr *DefaultMiloRenderer) acquireTemplate(key string, tpls ...string) (*template.Template, error) {
	var tpl *template.Template
	var loadErr error
	var ok bool

	if mr.cacheTpls {
		mr.RLock()
		tpl, ok = mr.templateCache[key]
		mr.RUnlock()
		if ok {
			return tpl, nil
		}
	}

	tpl, loadErr = template.New(filepath.Base(tpls[0])).Funcs(mr.tplFuncs).ParseFiles(tpls...)
	if loadErr != nil {
		return nil, loadErr
	}

	if mr.cacheTpls {
		mr.Lock()
		mr.templateCache[key] = tpl
		mr.Unlock()
	}
	return tpl, nil
}

// Render json output
func (mr *DefaultMiloRenderer) RenderJson(w http.ResponseWriter, r *http.Request, data interface{}) {
	if data, err := json.Marshal(data); err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
	} else {
		w.Header().Add("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(data)
	}
}

func (mr *DefaultMiloRenderer) RenderError(w http.ResponseWriter, r *http.Request, code int, message string) {
	w.WriteHeader(code)
	w.Write([]byte(message))
}

func (mr *DefaultMiloRenderer) RenderMessage(w http.ResponseWriter, r *http.Request, message string) {
	w.WriteHeader(200)
	w.Write([]byte(message))
}

// Register a template function with the MiloRenderer
func (mr *DefaultMiloRenderer) RegisterTemplateFunc(key string, fn interface{}) {
	mr.tplFuncs[key] = fn
}

// Setup an http redirect on the request.
func (mr *DefaultMiloRenderer) Redirect(w http.ResponseWriter, r *http.Request, url string, code int) {
	http.Redirect(w, r, url, code)
}
<commit_msg>Removed unneeded log statement.<commit_after>package render

import (
	"bytes"
	"encoding/json"
	"html/template"
	"net/http"
	"path/filepath"
	"strings"
	"sync"
)

// An interface of suggested methods for rendering output in Go
type MiloRenderer interface {
	RenderTemplates(w http.ResponseWriter, r *http.Request, data map[string]interface{}, tpls ...string)
	RenderJson(w http.ResponseWriter, r *http.Request, data interface{})
	RenderError(w http.ResponseWriter, r *http.Request, code int, message string)
	RenderMessage(w http.ResponseWriter, r *http.Request, message string)
	RegisterTemplateFunc(key string, fn interface{})
	Redirect(w http.ResponseWriter, r *http.Request, url string, code int)
}

// Default milo renderer that can cache templates, sets a base template directory.
type DefaultMiloRenderer struct {
	templateCache map[string]*template.Template
	tplDir        string
	tplFuncs      map[string]interface{}
	cacheTpls     bool
	sync.RWMutex
}

// Create a new default milo renderer.
func NewDefaultMiloRenderer(tplDir string, cache bool) MiloRenderer {
	r := &DefaultMiloRenderer{templateCache: make(map[string]*template.Template), tplDir: tplDir, tplFuncs: make(map[string]interface{}), cacheTpls: cache}
	r.tplFuncs["host"] = Host
	r.tplFuncs["marshal"] = Marshal
	return r
}

// Takes care of rendering templates from file.
func (mr *DefaultMiloRenderer) RenderTemplates(w http.ResponseWriter, r *http.Request, data map[string]interface{}, tpls ...string) {
	if len(tpls) < 1 {
		w.WriteHeader(500)
		w.Write([]byte("Error: Template required!"))
		return
	}

	list := make([]string, 0)
	for _, elem := range tpls {
		list = append(list, filepath.Join(mr.tplDir, elem))
	}

	if tpl, loadErr := mr.acquireTemplate(strings.Join(tpls, ""), list...); loadErr != nil {
		w.WriteHeader(500)
		w.Write([]byte(loadErr.Error()))
	} else {
		var doc bytes.Buffer
		err := tpl.Execute(&doc, data)
		if err == nil {
			w.WriteHeader(200)
			w.Write(doc.Bytes())
		} else {
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
		}
	}
}

// Unexported method to help handle template parsing.  If the cache template bool is set on the config
// struct this method with look in the cache & load the cache upon subsequent encounters.
// This should lower disk access penalties useful for production instances.
func (mr *DefaultMiloRenderer) acquireTemplate(key string, tpls ...string) (*template.Template, error) {
	var tpl *template.Template
	var loadErr error
	var ok bool

	if mr.cacheTpls {
		mr.RLock()
		tpl, ok = mr.templateCache[key]
		mr.RUnlock()
		if ok {
			return tpl, nil
		}
	}

	tpl, loadErr = template.New(filepath.Base(tpls[0])).Funcs(mr.tplFuncs).ParseFiles(tpls...)
	if loadErr != nil {
		return nil, loadErr
	}

	if mr.cacheTpls {
		mr.Lock()
		mr.templateCache[key] = tpl
		mr.Unlock()
	}
	return tpl, nil
}

// Render json output
func (mr *DefaultMiloRenderer) RenderJson(w http.ResponseWriter, r *http.Request, data interface{}) {
	if data, err := json.Marshal(data); err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
	} else {
		w.Header().Add("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		w.Write(data)
	}
}

func (mr *DefaultMiloRenderer) RenderError(w http.ResponseWriter, r *http.Request, code int, message string) {
	w.WriteHeader(code)
	w.Write([]byte(message))
}

func (mr *DefaultMiloRenderer) RenderMessage(w http.ResponseWriter, r *http.Request, message string) {
	w.WriteHeader(200)
	w.Write([]byte(message))
}

// Register a template function with the MiloRenderer
func (mr *DefaultMiloRenderer) RegisterTemplateFunc(key string, fn interface{}) {
	mr.tplFuncs[key] = fn
}

// Setup an http redirect on the request.
func (mr *DefaultMiloRenderer) Redirect(w http.ResponseWriter, r *http.Request, url string, code int) {
	http.Redirect(w, r, url, code)
}
<|endoftext|>


<commit_before>package render

import (
	"io"
	"os"
	"path/filepath"

	"github.com/vito/booklit"
)

type RenderingEngine interface {
	booklit.Visitor

	FileExtension() string
	RenderSection(io.Writer, *booklit.Section) error
}

type Writer struct {
	Engine RenderingEngine

	Destination string
}

func (writer Writer) WriteSection(section *booklit.Section) error {
	if section.Parent == nil || section.Parent.SplitSections {
		name := section.PrimaryTag.Name + "." + writer.Engine.FileExtension()
		path := filepath.Join(writer.Destination, name)

		file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
		if err != nil {
			return err
		}

		err = writer.Engine.RenderSection(file, section)
		if err != nil {
			return err
		}
	}

	errs := make(chan error, len(section.Children))
	for _, child := range section.Children {
		go func() {
			errs <- writer.WriteSection(child)
		}()
	}

	var anyErr error
	for i := 0; i < len(section.Children); i++ {
		err := <-errs
		if err != nil {
			anyErr = err
		}
	}

	return anyErr
}
<commit_msg>Revert "render sections in parallel"<commit_after>package render

import (
	"io"
	"os"
	"path/filepath"

	"github.com/vito/booklit"
)

type RenderingEngine interface {
	booklit.Visitor

	FileExtension() string
	RenderSection(io.Writer, *booklit.Section) error
}

type Writer struct {
	Engine RenderingEngine

	Destination string
}

func (writer Writer) WriteSection(section *booklit.Section) error {
	if section.Parent == nil || section.Parent.SplitSections {
		name := section.PrimaryTag.Name + "." + writer.Engine.FileExtension()
		path := filepath.Join(writer.Destination, name)

		file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
		if err != nil {
			return err
		}

		err = writer.Engine.RenderSection(file, section)
		if err != nil {
			return err
		}
	}

	for _, child := range section.Children {
		err := writer.WriteSection(child)
		if err != nil {
			return err
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package ephemeral

import (
	"log"
	"net"
	"net/http"

	"golang.org/x/net/netutil"

	"github.com/bfontaine/ephemeral/Godeps/_workspace/src/github.com/hydrogen18/stoppableListener"
)

type Server struct {
	http    http.Server
	sl      *stoppableListener.StoppableListener
	data    interface{}
	stopped bool
}

func New() *Server {
	return &Server{}
}

func (s *Server) Stop(data interface{}) {
	log.Println("stop")
	if s.stopped {
		return
	}
	log.Println("    ...")
	s.data = data
	s.sl.Stop()
	s.stopped = true
}

func (s *Server) HandleFunc(path string,
	fn func(*Server, http.ResponseWriter, *http.Request)) {

	http.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
		fn(s, w, r)
	})
}

func (s *Server) Listen(host string) (data interface{}, err error) {
	listener, err := net.Listen("tcp", host)
	if err != nil {
		return
	}

	s.sl, err = stoppableListener.New(listener)
	if err != nil {
		return
	}

	defer func() { data = s.data }()

	s.http.Serve(netutil.LimitListener(s.sl, 1))

	return
}
<commit_msg>non-working LimitListener removed<commit_after>package ephemeral

import (
	"net"
	"net/http"

	"github.com/bfontaine/ephemeral/Godeps/_workspace/src/github.com/hydrogen18/stoppableListener"
)

type Server struct {
	http    http.Server
	sl      *stoppableListener.StoppableListener
	data    interface{}
	stopped bool
}

func New() *Server {
	return &Server{}
}

func (s *Server) Stop(data interface{}) {
	if s.stopped {
		return
	}
	s.data = data
	s.sl.Stop()
	s.stopped = true
}

func (s *Server) HandleFunc(path string,
	fn func(*Server, http.ResponseWriter, *http.Request)) {

	http.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
		fn(s, w, r)
	})
}

func (s *Server) Listen(host string) (data interface{}, err error) {
	listener, err := net.Listen("tcp", host)
	if err != nil {
		return
	}

	s.sl, err = stoppableListener.New(listener)
	if err != nil {
		return
	}

	defer func() { data = s.data }()

	s.http.Serve(s.sl)

	return
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/configservice"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func testAccConfigRemediationConfiguration_basic(t *testing.T) {
	var rc configservice.RemediationConfiguration
	resourceName := "aws_config_remediation_configuration.foo"
	rInt := acctest.RandInt()
	expectedName := fmt.Sprintf("tf-acc-test-%d", rInt)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckConfigRemediationConfigurationDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccConfigRemediationConfigurationConfig_basic(rInt),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckConfigRemediationConfigurationExists("aws_config_remediation_configuration.foo", &rc),
					resource.TestCheckResourceAttr("aws_config_remediation_configuration.foo", "config_rule_name", expectedName),
					resource.TestCheckResourceAttr("aws_config_remediation_configuration.foo", "target_id", "SSM_DOCUMENT"),
					resource.TestCheckResourceAttr("aws_config_remediation_configuration.foo", "target_type", "AWS-PublishSNSNotification"),
					resource.TestCheckResourceAttr("aws_config_remediation_configuration.foo", "parameters.#", "2"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckConfigRemediationConfigurationExists(n string, obj *configservice.RemediationConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not Found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No config rule ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).configconn
		out, err := conn.DescribeRemediationConfigurations(&configservice.DescribeRemediationConfigurationsInput{
			ConfigRuleNames: []*string{aws.String(rs.Primary.Attributes["name"])},
		})
		if err != nil {
			return fmt.Errorf("Failed to describe config rule: %s", err)
		}
		if len(out.RemediationConfigurations) < 1 {
			return fmt.Errorf("No config rule found when describing %q", rs.Primary.Attributes["name"])
		}

		rc := out.RemediationConfigurations[0]
		*obj = *rc

		return nil
	}
}

func testAccCheckConfigRemediationConfigurationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).configconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_config_remediation_configuration" {
			continue
		}

		resp, err := conn.DescribeRemediationConfigurations(&configservice.DescribeRemediationConfigurationsInput{
			ConfigRuleNames: []*string{aws.String(rs.Primary.Attributes["name"])},
		})

		if err == nil {
			if len(resp.RemediationConfigurations) != 0 &&
				*resp.RemediationConfigurations[0].ConfigRuleName == rs.Primary.Attributes["name"] {
				return fmt.Errorf("remediation configuration(s) still exist for rule: %s", rs.Primary.Attributes["name"])
			}
		}
	}

	return nil
}

func testAccConfigRemediationConfigurationConfig_basic(randInt int) string {
	return fmt.Sprintf(`
resource "aws_config_remediation_configuration" "test" {
	config_rule_name = aws_config_config_rule.test.name

	resource_type = ""
	target_id = "SSM_DOCUMENT"
	target_type = "AWS-PublishSNSNotification"
	target_version = "1"

	parameter {
		resource_value = "Message"
	}

	parameter {
		static_value {
			key   = "TopicArn"
		f	value = aws_sns_topic.test.arn
		}
	}

	parameter {
		static_value {
			key   = "AutomationAssumeRole"
			value = aws_iam_role.test.arn
		}
	}
}

resource "aws_sns_topic" "test" {
  name = "sns_topic_name"
}

resource "aws_config_config_rule" "test" {
  name = "tf-acc-test-%d"

  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_VERSIONING_ENABLED"
  }

  depends_on = [aws_config_configuration_recorder.test]
}

resource "aws_config_configuration_recorder" "test" {
  name     = "tf-acc-test-%d"
  role_arn = aws_iam_role.r.arn
}

resource "aws_iam_role" "test" {
  name = "tf-acc-test-awsconfig-%d"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "config.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "test" {
  name = "tf-acc-test-awsconfig-%d"
  role = aws_iam_role.test.id

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Action": "config:Put*",
        "Effect": "Allow",
        "Resource": "*"

    }
  ]
}
EOF
}
`, randInt, randInt, randInt, randInt)
}
<commit_msg>Update aws/resource_aws_config_remediation_configuration_test.go<commit_after>package aws

import (
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/configservice"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func testAccConfigRemediationConfiguration_basic(t *testing.T) {
	var rc configservice.RemediationConfiguration
	resourceName := "aws_config_remediation_configuration.foo"
	rInt := acctest.RandInt()
	expectedName := fmt.Sprintf("tf-acc-test-%d", rInt)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckConfigRemediationConfigurationDestroy,
		Steps: []resource.TestStep{
			{
				Config: testAccConfigRemediationConfigurationConfig_basic(rInt),
				Check: resource.ComposeTestCheckFunc(
					testAccCheckConfigRemediationConfigurationExists(resourceName, &rc),
					resource.TestCheckResourceAttr(resourceName, "config_rule_name", expectedName),
					resource.TestCheckResourceAttr(resourceName, "target_id", "SSM_DOCUMENT"),
					resource.TestCheckResourceAttr(resourceName, "target_type", "AWS-PublishSNSNotification"),
					resource.TestCheckResourceAttr(resourceName, "parameters.#", "2"),
				),
			},
			{
				ResourceName:      resourceName,
				ImportState:       true,
				ImportStateVerify: true,
			},
		},
	})
}

func testAccCheckConfigRemediationConfigurationExists(n string, obj *configservice.RemediationConfiguration) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not Found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No config rule ID is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).configconn
		out, err := conn.DescribeRemediationConfigurations(&configservice.DescribeRemediationConfigurationsInput{
			ConfigRuleNames: []*string{aws.String(rs.Primary.Attributes["name"])},
		})
		if err != nil {
			return fmt.Errorf("Failed to describe config rule: %s", err)
		}
		if len(out.RemediationConfigurations) < 1 {
			return fmt.Errorf("No config rule found when describing %q", rs.Primary.Attributes["name"])
		}

		rc := out.RemediationConfigurations[0]
		*obj = *rc

		return nil
	}
}

func testAccCheckConfigRemediationConfigurationDestroy(s *terraform.State) error {
	conn := testAccProvider.Meta().(*AWSClient).configconn

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "aws_config_remediation_configuration" {
			continue
		}

		resp, err := conn.DescribeRemediationConfigurations(&configservice.DescribeRemediationConfigurationsInput{
			ConfigRuleNames: []*string{aws.String(rs.Primary.Attributes["name"])},
		})

		if err == nil {
			if len(resp.RemediationConfigurations) != 0 &&
				*resp.RemediationConfigurations[0].ConfigRuleName == rs.Primary.Attributes["name"] {
				return fmt.Errorf("remediation configuration(s) still exist for rule: %s", rs.Primary.Attributes["name"])
			}
		}
	}

	return nil
}

func testAccConfigRemediationConfigurationConfig_basic(randInt int) string {
	return fmt.Sprintf(`
resource "aws_config_remediation_configuration" "test" {
	config_rule_name = aws_config_config_rule.test.name

	resource_type = ""
	target_id = "SSM_DOCUMENT"
	target_type = "AWS-PublishSNSNotification"
	target_version = "1"

	parameter {
		resource_value = "Message"
	}

	parameter {
		static_value {
			key   = "TopicArn"
		f	value = aws_sns_topic.test.arn
		}
	}

	parameter {
		static_value {
			key   = "AutomationAssumeRole"
			value = aws_iam_role.test.arn
		}
	}
}

resource "aws_sns_topic" "test" {
  name = "sns_topic_name"
}

resource "aws_config_config_rule" "test" {
  name = "tf-acc-test-%d"

  source {
    owner             = "AWS"
    source_identifier = "S3_BUCKET_VERSIONING_ENABLED"
  }

  depends_on = [aws_config_configuration_recorder.test]
}

resource "aws_config_configuration_recorder" "test" {
  name     = "tf-acc-test-%d"
  role_arn = aws_iam_role.r.arn
}

resource "aws_iam_role" "test" {
  name = "tf-acc-test-awsconfig-%d"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "config.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "test" {
  name = "tf-acc-test-awsconfig-%d"
  role = aws_iam_role.test.id

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
        "Action": "config:Put*",
        "Effect": "Allow",
        "Resource": "*"

    }
  ]
}
EOF
}
`, randInt, randInt, randInt, randInt)
}
<|endoftext|>


<commit_before>package marshal

import (
	//"errors"
	"reflect"
	"strings"

	"github.com/xitongsys/parquet-go/common"
	"github.com/xitongsys/parquet-go/layout"
	"github.com/xitongsys/parquet-go/schema"
	"github.com/xitongsys/parquet-go/types"
)

//Record Map KeyValue pair
type KeyValue struct {
	Key   reflect.Value
	Value reflect.Value
}

type MapRecord struct {
	KeyValues []KeyValue
	Index     int
}

type SliceRecord struct {
	Values	[]reflect.Value
	Index	int
}

//Convert the table map to objects slice. desInterface is a slice of pointers of objects
func Unmarshal(tableMap *map[string]*layout.Table, bgn int, end int, dstInterface interface{}, schemaHandler *schema.SchemaHandler, prefixPath string) (err error) {
	/*
	defer func() {
		if r := recover(); r != nil {
			switch x := r.(type) {
			case string:
				err = errors.New(x)
			case error:
				err = x
			default:
				err = errors.New("unknown error")
			}
		}
	}()
	*/

	tableNeeds := make(map[string]*layout.Table)
	tableBgn, tableEnd := make(map[string]int), make(map[string]int)
	for name, table := range *tableMap {
		if !strings.HasPrefix(name, prefixPath) {
			continue
		}

		tableNeeds[name] = table

		ln := len(table.Values)
		num := -1
		tableBgn[name], tableEnd[name] = -1, -1
		for i := 0; i < ln; i++ {
			if table.RepetitionLevels[i] == 0 {
				num++
				if num == bgn {
					tableBgn[name] = i
				}
				if num == end {
					tableEnd[name] = i
					break
				}
			}
		}

		if tableEnd[name] < 0 {
			tableEnd[name] = ln
		}
		if tableBgn[name] < 0 {
			return
		}
	}

	mapRecords := make(map[reflect.Value]*MapRecord)
	mapRecordsStack := make([]reflect.Value, 0)
	sliceRecords := make(map[reflect.Value]*SliceRecord)
	sliceRecordsStack := make([]reflect.Value, 0)
	root := reflect.ValueOf(dstInterface).Elem()

	for name, table := range tableNeeds {
		path := table.Path
		bgn := tableBgn[name]
		end := tableEnd[name]
		schemaIndex := schemaHandler.MapIndex[common.PathToStr(path)]
		pT, cT := schemaHandler.SchemaElements[schemaIndex].Type, schemaHandler.SchemaElements[schemaIndex].ConvertedType

		repetitionLevels, definitionLevels := make([]int32, len(path)), make([]int32, len(path))
		for i := 0; i<len(path); i++ {
			repetitionLevels[i], _ = schemaHandler.MaxRepetitionLevel(path[:i+1])
			definitionLevels[i], _ = schemaHandler.MaxDefinitionLevel(path[:i+1])
		}

		for _, rc := range sliceRecords {
			rc.Index = -1
		}
		for _, rc := range mapRecords {
			rc.Index = -1
		}

		for i := bgn; i < end; i++ {
			rl, dl, val := table.RepetitionLevels[i], table.DefinitionLevels[i], table.Values[i]
			po, index := root, 0
			for index < len(path) {
				if po.Type().Kind() == reflect.Slice {
					if po.IsNil() {
						po.Set(reflect.MakeSlice(po.Type(), 0, 0))
					}

					if _, ok := sliceRecords[po]; !ok {
						sliceRecords[po] = &SliceRecord{
							Values:	[]reflect.Value{},
							Index:	-1,
						}
						sliceRecordsStack = append(sliceRecordsStack, po)
					}

					if rl == repetitionLevels[index] || sliceRecords[po].Index < 0 {
						sliceRecords[po].Index++
					}

					if sliceRecords[po].Index >= len(sliceRecords[po].Values) {
						sliceRecords[po].Values = append(sliceRecords[po].Values, reflect.New(po.Type().Elem()).Elem())
					}

					po = sliceRecords[po].Values[sliceRecords[po].Index]

				} else if po.Type().Kind() == reflect.Map {
					if po.IsNil() {
						po.Set(reflect.MakeMap(po.Type()))
					}

					if _, ok := mapRecords[po]; !ok {
						mapRecords[po] = &MapRecord{
							KeyValues:	[]KeyValue{},
							Index:		-1,
						}
						mapRecordsStack = append(mapRecordsStack, po)
					}

					index++
					if definitionLevels[index] > dl {
						break
					}

					if rl == repetitionLevels[index] || mapRecords[po].Index < 0 {
						mapRecords[po].Index++
					}

					if mapRecords[po].Index >= len(mapRecords[po].KeyValues) {
						mapRecords[po].KeyValues = append(mapRecords[po].KeyValues,
							KeyValue{
								Key: reflect.New(po.Type().Key()).Elem(),
								Value: reflect.New(po.Type().Elem()).Elem(),
						})
					}

					if path[index + 1] == "key" {
						po = mapRecords[po].KeyValues[mapRecords[po].Index].Key

					}else {
						po = mapRecords[po].KeyValues[mapRecords[po].Index].Value
					}

					index++
					if definitionLevels[index] > dl {
						break
					}

				} else if po.Type().Kind() == reflect.Ptr {
					if po.IsNil() {
						po.Set(reflect.New(po.Type().Elem()))
					}

					po = po.Elem()

				} else if po.Type().Kind() == reflect.Struct {
					index++
					if definitionLevels[index] > dl {
						break;
					}
					po = po.FieldByName(path[index])

				} else {
					po.Set(reflect.ValueOf(types.ParquetTypeToGoType(val, pT, cT)))
					break
				}
			}
		}
	}

	for i := len(sliceRecordsStack) - 1; i >= 0; i-- {
		po := sliceRecordsStack[i]
		vs := sliceRecords[po]
		potmp := reflect.Append(po, vs.Values...)
		po.Set(potmp)
	}

	for i := len(mapRecordsStack) - 1; i >= 0; i-- {
		po := mapRecordsStack[i]
		for _, kv := range mapRecords[po].KeyValues {
			po.SetMapIndex(kv.Key, kv.Value)
		}
	}

	return nil
}
<commit_msg>updating<commit_after>package marshal

import (
	//"errors"
	"reflect"
	"strings"

	"github.com/xitongsys/parquet-go/common"
	"github.com/xitongsys/parquet-go/layout"
	"github.com/xitongsys/parquet-go/schema"
	"github.com/xitongsys/parquet-go/types"
	"github.com/xitongsys/parquet-go/parquet"
)

//Record Map KeyValue pair
type KeyValue struct {
	Key   reflect.Value
	Value reflect.Value
}

type MapRecord struct {
	KeyValues []KeyValue
	Index     int
}

type SliceRecord struct {
	Values	[]reflect.Value
	Index	int
}

//Convert the table map to objects slice. desInterface is a slice of pointers of objects
func Unmarshal(tableMap *map[string]*layout.Table, bgn int, end int, dstInterface interface{}, schemaHandler *schema.SchemaHandler, prefixPath string) (err error) {
	/*
	defer func() {
		if r := recover(); r != nil {
			switch x := r.(type) {
			case string:
				err = errors.New(x)
			case error:
				err = x
			default:
				err = errors.New("unknown error")
			}
		}
	}()
	*/

	tableNeeds := make(map[string]*layout.Table)
	tableBgn, tableEnd := make(map[string]int), make(map[string]int)
	for name, table := range *tableMap {
		if !strings.HasPrefix(name, prefixPath) {
			continue
		}

		tableNeeds[name] = table

		ln := len(table.Values)
		num := -1
		tableBgn[name], tableEnd[name] = -1, -1
		for i := 0; i < ln; i++ {
			if table.RepetitionLevels[i] == 0 {
				num++
				if num == bgn {
					tableBgn[name] = i
				}
				if num == end {
					tableEnd[name] = i
					break
				}
			}
		}

		if tableEnd[name] < 0 {
			tableEnd[name] = ln
		}
		if tableBgn[name] < 0 {
			return
		}
	}

	mapRecords := make(map[reflect.Value]*MapRecord)
	mapRecordsStack := make([]reflect.Value, 0)
	sliceRecords := make(map[reflect.Value]*SliceRecord)
	sliceRecordsStack := make([]reflect.Value, 0)
	root := reflect.ValueOf(dstInterface).Elem()

	for name, table := range tableNeeds {
		path := table.Path
		bgn := tableBgn[name]
		end := tableEnd[name]
		schemaIndexs := make([]int, len(path))
		for i := 0; i< len(path); i++ {
			curPathStr := common.PathToStr(path[:i + 1])
			schemaIndexs[i] = int(schemaHandler.MapIndex[curPathStr])
		}

		repetitionLevels, definitionLevels := make([]int32, len(path)), make([]int32, len(path))
		for i := 0; i<len(path); i++ {
			repetitionLevels[i], _ = schemaHandler.MaxRepetitionLevel(path[:i+1])
			definitionLevels[i], _ = schemaHandler.MaxDefinitionLevel(path[:i+1])
		}

		for _, rc := range sliceRecords {
			rc.Index = -1
		}
		for _, rc := range mapRecords {
			rc.Index = -1
		}

		for i := bgn; i < end; i++ {
			rl, dl, val := table.RepetitionLevels[i], table.DefinitionLevels[i], table.Values[i]
			po, index := root, 0
			for index < len(path) {
				schemaIndex := schemaIndexs[index]
				pT, cT := schemaHandler.SchemaElements[schemaIndex].Type, schemaHandler.SchemaElements[schemaIndex].ConvertedType

				if po.Type().Kind() == reflect.Slice && (cT == nil || *cT != parquet.ConvertedType_LIST){
					if po.IsNil() {
						po.Set(reflect.MakeSlice(po.Type(), 0, 0))
					}

					if _, ok := sliceRecords[po]; !ok {
						sliceRecords[po] = &SliceRecord{
							Values:	[]reflect.Value{},
							Index:	-1,
						}
						sliceRecordsStack = append(sliceRecordsStack, po)
					}

					if rl == repetitionLevels[index] || sliceRecords[po].Index < 0 {
						sliceRecords[po].Index++
					}

					if sliceRecords[po].Index >= len(sliceRecords[po].Values) {
						sliceRecords[po].Values = append(sliceRecords[po].Values, reflect.New(po.Type().Elem()).Elem())
					}

					po = sliceRecords[po].Values[sliceRecords[po].Index]

				} else if po.Type().Kind() == reflect.Slice && cT != nil && *cT == parquet.ConvertedType_LIST {
					if po.IsNil() {
						po.Set(reflect.MakeSlice(po.Type(), 0, 0))
					}

					if _, ok := sliceRecords[po]; !ok {
						sliceRecords[po] = &SliceRecord{
							Values:	[]reflect.Value{},
							Index:	-1,
						}
						sliceRecordsStack = append(sliceRecordsStack, po)
					}

					index++
					if definitionLevels[index] > dl {
						break
					}

					if rl == repetitionLevels[index] || sliceRecords[po].Index < 0 {
						sliceRecords[po].Index++
					}

					if sliceRecords[po].Index >= len(sliceRecords[po].Values) {
						sliceRecords[po].Values = append(sliceRecords[po].Values, reflect.New(po.Type().Elem()).Elem())
					}

					po = sliceRecords[po].Values[sliceRecords[po].Index]
					index++
					if definitionLevels[index] > dl {
						break
					}

				} else if po.Type().Kind() == reflect.Map {
					if po.IsNil() {
						po.Set(reflect.MakeMap(po.Type()))
					}

					if _, ok := mapRecords[po]; !ok {
						mapRecords[po] = &MapRecord{
							KeyValues:	[]KeyValue{},
							Index:		-1,
						}
						mapRecordsStack = append(mapRecordsStack, po)
					}

					index++
					if definitionLevels[index] > dl {
						break
					}

					if rl == repetitionLevels[index] || mapRecords[po].Index < 0 {
						mapRecords[po].Index++
					}

					if mapRecords[po].Index >= len(mapRecords[po].KeyValues) {
						mapRecords[po].KeyValues = append(mapRecords[po].KeyValues,
							KeyValue{
								Key: reflect.New(po.Type().Key()).Elem(),
								Value: reflect.New(po.Type().Elem()).Elem(),
						})
					}

					if path[index + 1] == "key" {
						po = mapRecords[po].KeyValues[mapRecords[po].Index].Key

					}else {
						po = mapRecords[po].KeyValues[mapRecords[po].Index].Value
					}

					index++
					if definitionLevels[index] > dl {
						break
					}

				} else if po.Type().Kind() == reflect.Ptr {
					if po.IsNil() {
						po.Set(reflect.New(po.Type().Elem()))
					}

					po = po.Elem()

				} else if po.Type().Kind() == reflect.Struct {
					index++
					if definitionLevels[index] > dl {
						break;
					}
					po = po.FieldByName(path[index])

				} else {
					po.Set(reflect.ValueOf(types.ParquetTypeToGoType(val, pT, cT)))
					break
				}
			}
		}
	}

	for i := len(sliceRecordsStack) - 1; i >= 0; i-- {
		po := sliceRecordsStack[i]
		vs := sliceRecords[po]
		potmp := reflect.Append(po, vs.Values...)
		po.Set(potmp)
	}

	for i := len(mapRecordsStack) - 1; i >= 0; i-- {
		po := mapRecordsStack[i]
		for _, kv := range mapRecords[po].KeyValues {
			po.SetMapIndex(kv.Key, kv.Value)
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package report

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"talisman/detector/helpers"
	"talisman/utility"

	"github.com/fatih/color"
)

const jsonFileName string = "report.json"
const htmlReportDir string = "talisman_html_report"

// GenerateReport generates a talisman scan report in html format
func GenerateReport(r *helpers.DetectionResults, directory string) (path string, err error) {

	var jsonFilePath string
	var homeDir string
	var baseReportDirPath string

	usr, err := user.Current()
	if err != nil {
		return "", fmt.Errorf("error getting current user: %v", err.Error())
	}
	homeDir = usr.HomeDir

	if directory == htmlReportDir {
		path = directory
		baseReportDirPath = filepath.Join(homeDir, ".talisman", htmlReportDir)
		jsonFilePath = filepath.Join(path, "/data", jsonFileName)
		err = utility.Dir(baseReportDirPath, htmlReportDir)
		if err != nil {
			generateErrorMsg()
			return "", fmt.Errorf("error copying reports: %v", err)
		}
	} else {
		path = filepath.Join(directory, "talisman_reports", "/data")
		jsonFilePath = filepath.Join(path, jsonFileName)
	}

	err = os.MkdirAll(path, 0755)
	if err != nil {
		return "", fmt.Errorf("error creating path %s: %v", path, err)
	}

	jsonFile, err := os.Create(jsonFilePath)
	defer func() {
		if err = jsonFile.Close(); err != nil {
			err = fmt.Errorf("error closing file %s: %v", jsonFilePath, err)
		}
	}()

	if err != nil {
		return "", fmt.Errorf("error creating file %s: %v", jsonFilePath, err)
	}

	jsonString, err := json.Marshal(r)
	if err != nil {
		return "", fmt.Errorf("error while marshal the report: %v", err)
	}
	_, err = jsonFile.Write(jsonString)
	if err != nil {
		return "", fmt.Errorf("error while writing report to file: %v", err)
	}
	return path, nil
}

func generateErrorMsg() {
	color.HiMagenta("\nLooks like you are using 'talisman --scanWithHtml' for scanning.")
	color.HiMagenta("But it appears that you have not installed Talisman Html Report")
	color.HiMagenta("Please go through Talisman Readme and make sure you install the same from:")
	color.Yellow("\nhttps://github.com/jaydeepc/talisman-html-report")
	color.Cyan("\nOR use 'talisman --scan' if you want the JSON report alone\n")
	fmt.Printf("\n")
	color.Red("Failed: Unable to perform Scan")
	fmt.Printf("\n")
	log.Fatalln("Run Status: Failed")
}
<commit_msg>Fix Case of Arbitrary File Overwrite while scanning malicious repo (#225)<commit_after>package report

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"talisman/detector/helpers"
	"talisman/utility"

	"github.com/fatih/color"
)

const jsonFileName string = "report.json"
const htmlReportDir string = "talisman_html_report"

// GenerateReport generates a talisman scan report in html format
func GenerateReport(r *helpers.DetectionResults, directory string) (path string, err error) {

	var jsonFilePath string
	var homeDir string
	var baseReportDirPath string

	usr, err := user.Current()
	if err != nil {
		return "", fmt.Errorf("error getting current user: %v", err.Error())
	}
	homeDir = usr.HomeDir

	if directory == htmlReportDir {
		path = directory
		baseReportDirPath = filepath.Join(homeDir, ".talisman", htmlReportDir)
		jsonFilePath = filepath.Join(path, "/data", jsonFileName)
		err = utility.Dir(baseReportDirPath, htmlReportDir)
		if err != nil {
			generateErrorMsg()
			return "", fmt.Errorf("error copying reports: %v", err)
		}
	} else {
		path = filepath.Join(directory, "talisman_reports")
		_ = os.RemoveAll(path)
		path = filepath.Join(path, "data")
		jsonFilePath = filepath.Join(path, jsonFileName)
	}

	err = os.MkdirAll(path, 0755)
	if err != nil {
		return "", fmt.Errorf("error creating path %s: %v", path, err)
	}

	jsonFile, err := os.Create(jsonFilePath)
	defer func() {
		if err = jsonFile.Close(); err != nil {
			err = fmt.Errorf("error closing file %s: %v", jsonFilePath, err)
		}
	}()

	if err != nil {
		return "", fmt.Errorf("error creating file %s: %v", jsonFilePath, err)
	}

	jsonString, err := json.Marshal(r)
	if err != nil {
		return "", fmt.Errorf("error while marshal the report: %v", err)
	}
	_, err = jsonFile.Write(jsonString)
	if err != nil {
		return "", fmt.Errorf("error while writing report to file: %v", err)
	}
	return path, nil
}

func generateErrorMsg() {
	color.HiMagenta("\nLooks like you are using 'talisman --scanWithHtml' for scanning.")
	color.HiMagenta("But it appears that you have not installed Talisman Html Report")
	color.HiMagenta("Please go through Talisman Readme and make sure you install the same from:")
	color.Yellow("\nhttps://github.com/jaydeepc/talisman-html-report")
	color.Cyan("\nOR use 'talisman --scan' if you want the JSON report alone\n")
	fmt.Printf("\n")
	color.Red("Failed: Unable to perform Scan")
	fmt.Printf("\n")
	log.Fatalln("Run Status: Failed")
}
<|endoftext|>


<commit_before>package webapi

// webapiだお

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/RobotClubKut/SlackBot/lib/conf"
	"github.com/RobotClubKut/SlackBot/lib/mysql"
)

func home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}

func deny(w http.ResponseWriter, r *http.Request) {
	configure := conf.ReadConfigure()
	text := r.PostFormValue("text")
	token := r.PostFormValue("token")
	userName := r.PostFormValue("user_name")
	if strings.Contains(text, "deny:") && configure.OutgoingSlackConf.Token == token && configure.OutgoingSlackConf.UserName == userName {
		text = strings.Replace(text, "deny:", "", 0)
		text = strings.Replace(text, " ", "", 0)
		words := strings.Split(text, ":")
		mysql.InsertDenyWord(words)
		//postText := "{\"text\":\"" +  + ""\"}"
		postText := "{\"text\":\""
		for _, w := range words {
			if w != "" {
				postText += w
				postText += ","
			}
		}
		postText += "\"}"
		fmt.Fprintf(w, postText)
	} else {
		postText := "{\"text\":\"nilぱすー\"}"
		fmt.Fprintf(w, postText)
	}
}

//ViewWebPage is view web api
func ViewWebPage() {
	configure := conf.ReadConfigure()
	http.HandleFunc("/", home)
	http.ListenAndServe(":"+configure.OutgoingSlackConf.Port, nil)
}
<commit_msg>api test<commit_after>package webapi

// webapiだお

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/RobotClubKut/SlackBot/lib/conf"
	"github.com/RobotClubKut/SlackBot/lib/mysql"
)

func home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}

func deny(w http.ResponseWriter, r *http.Request) {
	configure := conf.ReadConfigure()
	text := r.PostFormValue("text")
	token := r.PostFormValue("token")
	userName := r.PostFormValue("user_name")
	fmt.Println("test")
	if strings.Contains(text, "deny:") && configure.OutgoingSlackConf.Token == token && configure.OutgoingSlackConf.UserName == userName {
		fmt.Println("catch")
		text = strings.Replace(text, "deny:", "", 0)
		text = strings.Replace(text, " ", "", 0)
		words := strings.Split(text, ":")
		mysql.InsertDenyWord(words)
		//postText := "{\"text\":\"" +  + ""\"}"
		postText := "{\"text\":\""
		for _, w := range words {
			if w != "" {
				postText += w
				postText += ","
			}
		}
		postText += "\"}"
		fmt.Fprintf(w, postText)
	} else {
		postText := "{\"text\":\"nilぱすー\"}"
		fmt.Fprintf(w, postText)
	}
}

//ViewWebPage is view web api
func ViewWebPage() {
	configure := conf.ReadConfigure()
	http.HandleFunc("/", home)
	http.ListenAndServe(":"+configure.OutgoingSlackConf.Port, nil)
}
<|endoftext|>


<commit_before>package router

import (
	"net/http"
	//"reflect"
)

type Handler func(http.ResponseWriter, *http.Request)

//Route struct to store path with each methods and functions
type route struct {
	path    string
	methods []string
	funcs   []Handler
}

//Router struct (class abstraction)
type Router struct {
	routes []route
}

//Contructor
func New() *Router {
	var routes []route
	return &Router{routes}
}

//Functions to add method and function to a path

//GET
func (r *Router) GET(path string, handler Handler) {
	r.addMethod("GET", path, handler)
	return
}

//POST
func (r *Router) POST(path string, handler Handler) {
	r.addMethod("POST", path, handler)
	return
}

//PUT
func (r *Router) PUT(path string, handler Handler) {
	r.addMethod("PUT", path, handler)
	return
}

//DELETE
func (r *Router) DELETE(path string, handler Handler) {
	r.addMethod("DELETE", path, handler)
	return
}

//Add Method check if path exists to append new method-function relation or create path with it
func (r *Router) addMethod(method, path string, handler Handler) {
	position := -1

	for i, route := range r.routes {
		if route.path == path {
			position = i
			break
		}
	}

	if position > -1 {
		r.routes[position].methods = append(r.routes[position].methods, method)
		r.routes[position].funcs = append(r.routes[position].funcs, handler)
	} else {
		methods := []string{method}
		funcs := []Handler{handler}
		r.routes = append(r.routes, route{path, methods, funcs})
	}

	return
}

//Serve routes over all its methods
func handleRoute(path string, methods []string, funcs []Handler) {
	http.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
		for position, method := range methods {
			if method == r.Method {
				handleFunc(w, r, &funcs[position])
			}
		}
	})
}

func handleFunc(w http.ResponseWriter, r *http.Request, handler *Handler) {
	f := *handler
	f(w, r)
	return
}

//Iterate over routes and launch goroutine
func (r *Router) RunServer(port string) {
	for _, route := range r.routes {
		go handleRoute(route.path, route.methods, route.funcs)
	}
	http.ListenAndServe(":"+port, nil)
}
<commit_msg>Fix issues<commit_after>package router

import (
	"net/http"
)

type Handler func(http.ResponseWriter, *http.Request)

//Route struct to store path with each methods and functions
type route struct {
	path    string
	methods []string
	funcs   []*Handler
}

//Router struct (class abstraction)
type Router struct {
	routes []route
}

//Contructor
func New() *Router {
	var routes []route
	return &Router{routes}
}

//Functions to add method and function to a path

//GET
func (r *Router) GET(path string, handler Handler) {
	r.addMethod("GET", path, &handler)
	return
}

//POST
func (r *Router) POST(path string, handler Handler) {
	r.addMethod("POST", path, &handler)
	return
}

//PUT
func (r *Router) PUT(path string, handler Handler) {
	r.addMethod("PUT", path, &handler)
	return
}

//DELETE
func (r *Router) DELETE(path string, handler Handler) {
	r.addMethod("DELETE", path, &handler)
	return
}

//Add Method check if path exists to append new method-function relation or create path with it
func (r *Router) addMethod(method, path string, handler *Handler) {
	position := -1

	for i, route := range r.routes {
		if route.path == path {
			position = i
			break
		}
	}

	if position > -1 {
		r.routes[position].methods = append(r.routes[position].methods, method)
		r.routes[position].funcs = append(r.routes[position].funcs, handler)
	} else {
		methods := []string{method}
		funcs := []*Handler{handler}
		r.routes = append(r.routes, route{path, methods, funcs})
	}

	return
}

//Serve routes over all its methods
func handleRoute(path string, methods []string, funcs []*Handler) {
	http.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
		for position, method := range methods {
			if method == r.Method {
				f := *funcs[position]
				f(w, r)
			}
		}
	})
	return
}

//Iterate over routes and launch goroutine
func (r *Router) RunServer(port string) {
	for _, route := range r.routes {
		go handleRoute(route.path, route.methods, route.funcs)
	}

	http.ListenAndServe(":"+port, nil)
}
<|endoftext|>