<commit_before>package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/version"

	"crypto/tls"
	"encoding/json"
	"io/ioutil"
	"sync"
)

const (
	namespace = "fluentd" //for Prometheus metrics.
)

// declare variables for fluentd metrics
var (
	listeningAddress = flag.String("telementry.address", ":9309", "Address on which to expose metrics.")
	metricsEndpoint  = flag.String("Telementry.endpoint", "/metrics", "Path under which to expose metric.")
	scrapeURI        = flag.String("scrape_uri", "http://localhost:24220/api/plugins.json", "URI to fluentd metrics")
	insecure         = flag.Bool("insecure", false, "Ignore server certificate if using https, Default: false.")
	showVersion      = flag.Bool("version", false, "Print version information.")
)

type Exporter struct {
	URI    string
	mutex  sync.Mutex
	client *http.Client

	up *prometheus.Desc
	bufferQueueLength *prometheus.Desc
	bufferTotalQueuedSize *prometheus.Desc
	retryCount            *prometheus.Desc

	pluginId map[string]*prometheus.Desc
}

// NewExporter returns an initialized Exporter.

func NewExporter(uri string) *Exporter {
	return &Exporter{
		URI: uri,
		up: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "up"),
			"Could fluentd be reached",
			nil,
			nil),
		bufferQueueLength: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "buffer_queue_length"),
			"Buffered queue length",
			[]string{"pluginId", "pluginCategory"},
			nil),
		bufferTotalQueuedSize: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "buffer_queued_size"),
			"size of the total queued",
			[]string{"pluginId", "pluginCategory"},
			nil),
		retryCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "retry_total"),
			"fluentd retry count",
			[]string{"pluginId", "pluginCategory"},
			nil),
		client: &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{InsecureSkipVerify: *insecure},
			},
		},
	}
}

// Describe describes all the metrics ever exported by the fluentd exporter. It
// implements prometheus.Collector.
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- e.bufferQueueLength
	ch <- e.bufferTotalQueuedSize
	ch <- e.retryCount
}

// json data structure for fluentd
type jsonData struct {
	Plugins []struct {
		PluginID              string `json:"plugin_id"`
		PluginCategory        string `json:"plugin_category"`
		Type                  string `json:"type"`
		RetryCount            int    `json:"retry_count"`
		BufferQueueLength     int    `json:"buffer_queue_length,omitempty"`
		BufferTotalQueuedSize int    `json:"buffer_total_queued_size,omitempty"`
	} `json:"plugins"`
}

// Collect fetches the stats from configured location and delivers them
// as Prometheus metrics.
// It implements prometheus.Collector.
func (e *Exporter) collect(ch chan<- prometheus.Metric) error {
	resp, err := e.client.Get(e.URI)
	if err != nil {
		ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0)
		return fmt.Errorf("Error scraping fluentd: %v", err)
	}
	ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1)

	// get data from body of response and check if there was a read error
	body, readErr := ioutil.ReadAll(resp.Body)
	if readErr != nil {
		log.Fatal(readErr)
	}

	// close connection
	resp.Body.Close()
	if resp.StatusCode != 200 {
		fmt.Println("There was an error")
		return fmt.Errorf("Status %s (%d)", resp.Status, resp.StatusCode)
	}

	//init struct for unmarshal and check that there was no unmarshalling error
	jdata := jsonData{}
	jError := json.Unmarshal(body, &jdata)
	if jError != nil {
		log.Fatal(jError)
	}

	// organise json response and map to created metrics
	//parse through json response from fluentd
	for _, plugin := range jdata.Plugins {
		if plugin.PluginCategory == "input" {
			continue
		}
		ch <- prometheus.MustNewConstMetric(e.bufferQueueLength, prometheus.GaugeValue, float64(plugin.BufferQueueLength), plugin.PluginID, plugin.PluginCategory)
		ch <- prometheus.MustNewConstMetric(e.bufferTotalQueuedSize, prometheus.CounterValue, float64(plugin.BufferTotalQueuedSize), plugin.PluginID, plugin.PluginCategory)
		ch <- prometheus.MustNewConstMetric(e.retryCount, prometheus.CounterValue, float64(plugin.RetryCount), plugin.PluginID, plugin.PluginCategory)
	}

	return nil
}

// Collect fetches the stats from configured fluentd location and delivers them
// as Prometheus metrics.
// It implements prometheus.Collector.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	e.mutex.Lock() // To protect metrics from concurrent collects.
	defer e.mutex.Unlock()
	if err := e.collect(ch); err != nil {
		log.Errorf("Error scraping fluentd: %s", err)
	}
	return
}

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Fprintln(os.Stdout, version.Print("fluentd_exporter"))
		os.Exit(0)
	}

	exporter := NewExporter(*scrapeURI)

	prometheus.MustRegister(exporter)
	prometheus.MustRegister(version.NewCollector("fluentd_exporter"))

	log.Infoln("Starting fluentd_exporter", version.Info())
	log.Infoln("Build context", version.BuildContext())

	log.Infof("Starting Server: %s", *listeningAddress)
	http.Handle(*metricsEndpoint, promhttp.Handler())
	log.Fatal(http.ListenAndServe(*listeningAddress, nil))
}
<commit_msg>removed unused attribute<commit_after>package main

import (
	"flag"
	"fmt"
	"net/http"
	"os"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/version"

	"crypto/tls"
	"encoding/json"
	"io/ioutil"
	"sync"
)

const (
	namespace = "fluentd" //for Prometheus metrics.
)

// declare variables for fluentd metrics
var (
	listeningAddress = flag.String("telementry.address", ":9309", "Address on which to expose metrics.")
	metricsEndpoint  = flag.String("Telementry.endpoint", "/metrics", "Path under which to expose metric.")
	scrapeURI        = flag.String("scrape_uri", "http://localhost:24220/api/plugins.json", "URI to fluentd metrics")
	insecure         = flag.Bool("insecure", false, "Ignore server certificate if using https, Default: false.")
	showVersion      = flag.Bool("version", false, "Print version information.")
)

type Exporter struct {
	URI    string
	mutex  sync.Mutex
	client *http.Client

	up *prometheus.Desc
	bufferQueueLength *prometheus.Desc
	bufferTotalQueuedSize *prometheus.Desc
	retryCount            *prometheus.Desc
}

// NewExporter returns an initialized Exporter.

func NewExporter(uri string) *Exporter {
	return &Exporter{
		URI: uri,
		up: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "up"),
			"Could fluentd be reached",
			nil,
			nil),
		bufferQueueLength: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "buffer_queue_length"),
			"Buffered queue length",
			[]string{"pluginId", "pluginCategory"},
			nil),
		bufferTotalQueuedSize: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "buffer_queued_size"),
			"size of the total queued",
			[]string{"pluginId", "pluginCategory"},
			nil),
		retryCount: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "", "retry_total"),
			"fluentd retry count",
			[]string{"pluginId", "pluginCategory"},
			nil),
		client: &http.Client{
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{InsecureSkipVerify: *insecure},
			},
		},
	}
}

// Describe describes all the metrics ever exported by the fluentd exporter. It
// implements prometheus.Collector.
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
	ch <- e.bufferQueueLength
	ch <- e.bufferTotalQueuedSize
	ch <- e.retryCount
}

// json data structure for fluentd
type jsonData struct {
	Plugins []struct {
		PluginID              string `json:"plugin_id"`
		PluginCategory        string `json:"plugin_category"`
		Type                  string `json:"type"`
		RetryCount            int    `json:"retry_count"`
		BufferQueueLength     int    `json:"buffer_queue_length,omitempty"`
		BufferTotalQueuedSize int    `json:"buffer_total_queued_size,omitempty"`
	} `json:"plugins"`
}

// Collect fetches the stats from configured location and delivers them
// as Prometheus metrics.
// It implements prometheus.Collector.
func (e *Exporter) collect(ch chan<- prometheus.Metric) error {
	resp, err := e.client.Get(e.URI)
	if err != nil {
		ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 0)
		return fmt.Errorf("Error scraping fluentd: %v", err)
	}
	ch <- prometheus.MustNewConstMetric(e.up, prometheus.GaugeValue, 1)

	// get data from body of response and check if there was a read error
	body, readErr := ioutil.ReadAll(resp.Body)
	if readErr != nil {
		log.Fatal(readErr)
	}

	// close connection
	resp.Body.Close()
	if resp.StatusCode != 200 {
		fmt.Println("There was an error")
		return fmt.Errorf("Status %s (%d)", resp.Status, resp.StatusCode)
	}

	//init struct for unmarshal and check that there was no unmarshalling error
	jdata := jsonData{}
	jError := json.Unmarshal(body, &jdata)
	if jError != nil {
		log.Fatal(jError)
	}

	// organise json response and map to created metrics
	//parse through json response from fluentd
	for _, plugin := range jdata.Plugins {
		if plugin.PluginCategory == "input" {
			continue
		}
		ch <- prometheus.MustNewConstMetric(e.bufferQueueLength, prometheus.GaugeValue, float64(plugin.BufferQueueLength), plugin.PluginID, plugin.PluginCategory)
		ch <- prometheus.MustNewConstMetric(e.bufferTotalQueuedSize, prometheus.CounterValue, float64(plugin.BufferTotalQueuedSize), plugin.PluginID, plugin.PluginCategory)
		ch <- prometheus.MustNewConstMetric(e.retryCount, prometheus.CounterValue, float64(plugin.RetryCount), plugin.PluginID, plugin.PluginCategory)
	}

	return nil
}

// Collect fetches the stats from configured fluentd location and delivers them
// as Prometheus metrics.
// It implements prometheus.Collector.
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
	e.mutex.Lock() // To protect metrics from concurrent collects.
	defer e.mutex.Unlock()
	if err := e.collect(ch); err != nil {
		log.Errorf("Error scraping fluentd: %s", err)
	}
	return
}

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Fprintln(os.Stdout, version.Print("fluentd_exporter"))
		os.Exit(0)
	}

	exporter := NewExporter(*scrapeURI)

	prometheus.MustRegister(exporter)
	prometheus.MustRegister(version.NewCollector("fluentd_exporter"))

	log.Infoln("Starting fluentd_exporter", version.Info())
	log.Infoln("Build context", version.BuildContext())

	log.Infof("Starting Server: %s", *listeningAddress)
	http.Handle(*metricsEndpoint, promhttp.Handler())
	log.Fatal(http.ListenAndServe(*listeningAddress, nil))
}
<|endoftext|>


<commit_before>package core

import (
	"database/sql"

	"github.com/jmoiron/sqlx"

	// Include sqlite3 driver
	_ "github.com/mattn/go-sqlite3"
)

// sqliteBackend represents a sqlite3-based database backend
type sqliteBackend struct {
	Path string
}

// DSN sets the Path for use with sqlite3
func (s *sqliteBackend) DSN(path string) {
	s.Path = path
}

// Open opens a new sqlx database connection
func (s *sqliteBackend) Open() (*sqlx.DB, error) {
	// Open connection using path
	db, err := sqlx.Open("sqlite3", s.Path)
	if err != nil {
		return nil, err
	}

	// Performance tuning
	if _, err := db.Exec("PRAGMA synchronous = OFF;"); err != nil {
		return nil, err
	}

	return db, nil
}

// AllArtists loads a slice of all Artist structs from the database
func (s *sqliteBackend) AllArtists() ([]Artist, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return nil, err
	}
	defer db.Close()

	// Query for a list of all artists
	rows, err := db.Queryx("SELECT * FROM artists;")
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	// Iterate all rows
	artists := make([]Artist, 0)
	a := Artist{}
	for rows.Next() {
		// Scan artist into struct
		if err := rows.StructScan(&a); err != nil {
			return nil, err
		}

		// Append to list
		artists = append(artists, a)
	}

	return artists, nil
}

// PurgeOrphanArtists deletes all artists who are "orphaned", meaning that they no
// longer have any songs which reference their ID
func (s *sqliteBackend) PurgeOrphanArtists() (int, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return -1, err
	}
	defer db.Close()

	// Select all artists without a song referencing their artist ID
	rows, err := db.Queryx("SELECT artists.id FROM artists LEFT JOIN songs ON " +
		"artists.id = songs.artist_id WHERE songs.artist_id IS NULL;")
	if err != nil && err != sql.ErrNoRows {
		return -1, err
	}

	// Open a transaction to remove all orphaned artists
	tx := db.MustBegin()

	// Iterate all rows
	artist := new(Artist)
	total := 0
	for rows.Next() {
		// Scan ID into struct
		if err := rows.StructScan(artist); err != nil {
			return -1, err
		}

		// Remove artist
		tx.Exec("DELETE FROM artists WHERE id = ?;", artist.ID)
		total++
	}

	return total, tx.Commit()
}

// LoadArtist loads an Artist from the database, populating the parameter struct
func (s *sqliteBackend) LoadArtist(a *Artist) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Load the artist via ID if available
	if a.ID != 0 {
		if err := db.Get(a, "SELECT * FROM artists WHERE id = ?;", a.ID); err != nil {
			return err
		}

		return nil
	}

	// Load via title
	if err := db.Get(a, "SELECT * FROM artists WHERE title = ?;", a.Title); err != nil {
		return err
	}

	return nil
}

// SaveArtist attempts to save an Artist to the database
func (s *sqliteBackend) SaveArtist(a *Artist) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Insert new artist
	query := "INSERT INTO artists (`title`) VALUES (?);"
	tx := db.MustBegin()
	tx.Exec(query, a.Title)

	// Commit transaction
	if err := tx.Commit(); err != nil {
		return err
	}

	// If no ID, reload to grab it
	if a.ID == 0 {
		if err := s.LoadArtist(a); err != nil {
			return err
		}
	}

	return nil
}

// AllAlbums loads a slice of all Album structs from the database
func (s *sqliteBackend) AllAlbums() ([]Album, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return nil, err
	}
	defer db.Close()

	// Query for a list of all albums, adding artist information via join
	rows, err := db.Queryx("SELECT albums.*,artists.title AS artist FROM albums " +
		"JOIN artists ON albums.artist_id = artists.id;")
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	// Iterate all rows
	albums := make([]Album, 0)
	a := Album{}
	for rows.Next() {
		// Scan album into struct
		if err := rows.StructScan(&a); err != nil {
			return nil, err
		}

		// Append to list
		albums = append(albums, a)
	}

	return albums, nil
}

// PurgeOrphanAlbums deletes all albums who are "orphaned", meaning that they no
// longer have any songs which reference their ID
func (s *sqliteBackend) PurgeOrphanAlbums() (int, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return -1, err
	}
	defer db.Close()

	// Select all albums without a song referencing their album ID
	rows, err := db.Queryx("SELECT albums.id FROM albums LEFT JOIN songs ON " +
		"albums.id = songs.album_id WHERE songs.album_id IS NULL;")
	if err != nil && err != sql.ErrNoRows {
		return -1, err
	}

	// Open a transaction to remove all orphaned albums
	tx := db.MustBegin()

	// Iterate all rows
	album := new(Album)
	total := 0
	for rows.Next() {
		// Scan ID into struct
		if err := rows.StructScan(album); err != nil {
			return -1, err
		}

		// Remove album
		tx.Exec("DELETE FROM albums WHERE id = ?;", album.ID)
		total++
	}

	return total, tx.Commit()
}

// LoadAlbum loads an Album from the database, populating the parameter struct
func (s *sqliteBackend) LoadAlbum(a *Album) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Load the album via ID if available
	if a.ID != 0 {
		if err := db.Get(a, "SELECT albums.*,artists.title AS artist FROM albums " +
			"JOIN artists ON albums.artist_id = artists.id WHERE albums.id = ?;", a.ID); err != nil {
			return err
		}

		return nil
	}

	// Load via artist ID and title
	if err := db.Get(a, "SELECT albums.*,artists.title AS artist FROM albums " +
		"JOIN artists ON albums.artist_id = artists.id WHERE albums.artist_id = ? AND albums.title = ?;", a.ArtistID, a.Title); err != nil {
		return err
	}

	return nil
}

// SaveAlbum attempts to save an Album to the database
func (s *sqliteBackend) SaveAlbum(a *Album) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Insert new album
	query := "INSERT INTO albums (`artist_id`, `title`, `year`) VALUES (?, ?, ?);"
	tx := db.MustBegin()
	tx.Exec(query, a.ArtistID, a.Title, a.Year)

	// Commit transaction
	if err := tx.Commit(); err != nil {
		return err
	}

	// If no ID, reload to grab it
	if a.ID == 0 {
		if err := s.LoadAlbum(a); err != nil {
			return err
		}
	}

	return nil
}

// AllSongs loads a slice of all Song structs from the database
func (s *sqliteBackend) AllSongs() ([]Song, error) {
	return s.songQuery("SELECT * FROM songs;")
}

// SongsForAlbum loads a slice of all Song structs which have the matching album ID
func (s *sqliteBackend) SongsForAlbum(ID int) ([]Song, error) {
	return s.songQuery("SELECT * FROM songs WHERE album_id = ?;", ID)
}

// SongsInPath loads a slice of all Song structs residing under the specified
// filesystem path from the database
func (s *sqliteBackend) SongsInPath(path string) ([]Song, error) {
	return s.songQuery("SELECT * FROM songs WHERE file_name LIKE ?;", path+"%")
}

// SongsNotInPath loads a slice of all Song structs that do not reside under the specified
// filesystem path from the database
func (s *sqliteBackend) SongsNotInPath(path string) ([]Song, error) {
	return s.songQuery("SELECT * FROM songs WHERE file_name NOT LIKE ?;", path+"%")
}

// DeleteSong removes a Song from the database
func (s *sqliteBackend) DeleteSong(a *Song) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Attempt to delete this song by its ID, if available
	tx := db.MustBegin()
	if a.ID != 0 {
		tx.Exec("DELETE FROM songs WHERE id = ?;", a.ID)
		return tx.Commit()
	}

	// Else, attempt to remove the song by its file name
	tx.Exec("DELETE FROM songs WHERE file_name = ?;", a.FileName)
	return tx.Commit()
}

// LoadSong loads a Song from the database, populating the parameter struct
func (s *sqliteBackend) LoadSong(a *Song) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Load the song via ID if available
	if a.ID != 0 {
		if err := db.Get(a, "SELECT * FROM songs WHERE id = ?;", a.ID); err != nil {
			return err
		}

		return nil
	}

	// Load via file name
	if err := db.Get(a, "SELECT * FROM songs WHERE file_name = ?;", a.FileName); err != nil {
		return err
	}

	return nil
}

// SaveSong attempts to save a Song to the database
func (s *sqliteBackend) SaveSong(a *Song) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Insert new song
	query := "INSERT INTO songs (`album_id`, `artist_id`, `bitrate`, `channels`, `comment`, `file_name`, " +
		"`file_size`, `file_type`, `genre`, `last_modified`, `length`, `sample_rate`, `title`, `track`, `year`) " +
		" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
	tx := db.MustBegin()
	tx.Exec(query, a.AlbumID, a.ArtistID, a.Bitrate, a.Channels, a.Comment, a.FileName, a.FileSize, a.FileType,
		a.Genre, a.LastModified, a.Length, a.SampleRate, a.Title, a.Track, a.Year)

	// Commit transaction
	if err := tx.Commit(); err != nil {
		return err
	}

	// If no ID, reload to grab it
	if a.ID == 0 {
		if err := s.LoadSong(a); err != nil {
			return err
		}
	}

	return nil
}

// songQuery loads a slice of Song structs matching the input query
func (s *sqliteBackend) songQuery(query string, args ...interface{}) ([]Song, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return nil, err
	}
	defer db.Close()

	// Perform input query with arguments
	rows, err := db.Queryx(query, args...)
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	// Iterate all rows
	songs := make([]Song, 0)
	a := Song{}
	for rows.Next() {
		// Scan song into struct
		if err := rows.StructScan(&a); err != nil {
			return nil, err
		}

		// Append to list
		songs = append(songs, a)
	}

	return songs, nil
}
<commit_msg>Fix song queries, so they load artist and album titles<commit_after>package core

import (
	"database/sql"

	"github.com/jmoiron/sqlx"

	// Include sqlite3 driver
	_ "github.com/mattn/go-sqlite3"
)

// sqliteBackend represents a sqlite3-based database backend
type sqliteBackend struct {
	Path string
}

// DSN sets the Path for use with sqlite3
func (s *sqliteBackend) DSN(path string) {
	s.Path = path
}

// Open opens a new sqlx database connection
func (s *sqliteBackend) Open() (*sqlx.DB, error) {
	// Open connection using path
	db, err := sqlx.Open("sqlite3", s.Path)
	if err != nil {
		return nil, err
	}

	// Performance tuning
	if _, err := db.Exec("PRAGMA synchronous = OFF;"); err != nil {
		return nil, err
	}

	return db, nil
}

// AllArtists loads a slice of all Artist structs from the database
func (s *sqliteBackend) AllArtists() ([]Artist, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return nil, err
	}
	defer db.Close()

	// Query for a list of all artists
	rows, err := db.Queryx("SELECT * FROM artists;")
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	// Iterate all rows
	artists := make([]Artist, 0)
	a := Artist{}
	for rows.Next() {
		// Scan artist into struct
		if err := rows.StructScan(&a); err != nil {
			return nil, err
		}

		// Append to list
		artists = append(artists, a)
	}

	return artists, nil
}

// PurgeOrphanArtists deletes all artists who are "orphaned", meaning that they no
// longer have any songs which reference their ID
func (s *sqliteBackend) PurgeOrphanArtists() (int, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return -1, err
	}
	defer db.Close()

	// Select all artists without a song referencing their artist ID
	rows, err := db.Queryx("SELECT artists.id FROM artists LEFT JOIN songs ON " +
		"artists.id = songs.artist_id WHERE songs.artist_id IS NULL;")
	if err != nil && err != sql.ErrNoRows {
		return -1, err
	}

	// Open a transaction to remove all orphaned artists
	tx := db.MustBegin()

	// Iterate all rows
	artist := new(Artist)
	total := 0
	for rows.Next() {
		// Scan ID into struct
		if err := rows.StructScan(artist); err != nil {
			return -1, err
		}

		// Remove artist
		tx.Exec("DELETE FROM artists WHERE id = ?;", artist.ID)
		total++
	}

	return total, tx.Commit()
}

// LoadArtist loads an Artist from the database, populating the parameter struct
func (s *sqliteBackend) LoadArtist(a *Artist) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Load the artist via ID if available
	if a.ID != 0 {
		if err := db.Get(a, "SELECT * FROM artists WHERE id = ?;", a.ID); err != nil {
			return err
		}

		return nil
	}

	// Load via title
	if err := db.Get(a, "SELECT * FROM artists WHERE title = ?;", a.Title); err != nil {
		return err
	}

	return nil
}

// SaveArtist attempts to save an Artist to the database
func (s *sqliteBackend) SaveArtist(a *Artist) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Insert new artist
	query := "INSERT INTO artists (`title`) VALUES (?);"
	tx := db.MustBegin()
	tx.Exec(query, a.Title)

	// Commit transaction
	if err := tx.Commit(); err != nil {
		return err
	}

	// If no ID, reload to grab it
	if a.ID == 0 {
		if err := s.LoadArtist(a); err != nil {
			return err
		}
	}

	return nil
}

// AllAlbums loads a slice of all Album structs from the database
func (s *sqliteBackend) AllAlbums() ([]Album, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return nil, err
	}
	defer db.Close()

	// Query for a list of all albums, adding artist information via join
	rows, err := db.Queryx("SELECT albums.*,artists.title AS artist FROM albums " +
		"JOIN artists ON albums.artist_id = artists.id;")
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	// Iterate all rows
	albums := make([]Album, 0)
	a := Album{}
	for rows.Next() {
		// Scan album into struct
		if err := rows.StructScan(&a); err != nil {
			return nil, err
		}

		// Append to list
		albums = append(albums, a)
	}

	return albums, nil
}

// PurgeOrphanAlbums deletes all albums who are "orphaned", meaning that they no
// longer have any songs which reference their ID
func (s *sqliteBackend) PurgeOrphanAlbums() (int, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return -1, err
	}
	defer db.Close()

	// Select all albums without a song referencing their album ID
	rows, err := db.Queryx("SELECT albums.id FROM albums LEFT JOIN songs ON " +
		"albums.id = songs.album_id WHERE songs.album_id IS NULL;")
	if err != nil && err != sql.ErrNoRows {
		return -1, err
	}

	// Open a transaction to remove all orphaned albums
	tx := db.MustBegin()

	// Iterate all rows
	album := new(Album)
	total := 0
	for rows.Next() {
		// Scan ID into struct
		if err := rows.StructScan(album); err != nil {
			return -1, err
		}

		// Remove album
		tx.Exec("DELETE FROM albums WHERE id = ?;", album.ID)
		total++
	}

	return total, tx.Commit()
}

// LoadAlbum loads an Album from the database, populating the parameter struct
func (s *sqliteBackend) LoadAlbum(a *Album) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Load the album via ID if available
	if a.ID != 0 {
		if err := db.Get(a, "SELECT albums.*,artists.title AS artist FROM albums " +
			"JOIN artists ON albums.artist_id = artists.id WHERE albums.id = ?;", a.ID); err != nil {
			return err
		}

		return nil
	}

	// Load via artist ID and title
	if err := db.Get(a, "SELECT albums.*,artists.title AS artist FROM albums " +
		"JOIN artists ON albums.artist_id = artists.id WHERE albums.artist_id = ? AND albums.title = ?;", a.ArtistID, a.Title); err != nil {
		return err
	}

	return nil
}

// SaveAlbum attempts to save an Album to the database
func (s *sqliteBackend) SaveAlbum(a *Album) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Insert new album
	query := "INSERT INTO albums (`artist_id`, `title`, `year`) VALUES (?, ?, ?);"
	tx := db.MustBegin()
	tx.Exec(query, a.ArtistID, a.Title, a.Year)

	// Commit transaction
	if err := tx.Commit(); err != nil {
		return err
	}

	// If no ID, reload to grab it
	if a.ID == 0 {
		if err := s.LoadAlbum(a); err != nil {
			return err
		}
	}

	return nil
}

// AllSongs loads a slice of all Song structs from the database
func (s *sqliteBackend) AllSongs() ([]Song, error) {
	return s.songQuery("SELECT songs.*,artists.title AS artist,albums.title AS album FROM songs " +
		"JOIN artists ON songs.artist_id = artists.id JOIN albums ON songs.album_id = albums.id;")
}

// SongsForAlbum loads a slice of all Song structs which have the matching album ID
func (s *sqliteBackend) SongsForAlbum(ID int) ([]Song, error) {
	return s.songQuery("SELECT songs.*,artists.title AS artist,albums.title AS album FROM songs " +
		"JOIN artists ON songs.artist_id = artists.id JOIN albums ON songs.album_id = albums.id " +
		"WHERE songs.album_id = ?;", ID)
}

// SongsInPath loads a slice of all Song structs residing under the specified
// filesystem path from the database
func (s *sqliteBackend) SongsInPath(path string) ([]Song, error) {
	return s.songQuery("SELECT songs.*,artists.title AS artist,albums.title AS album FROM songs " +
		"JOIN artists ON songs.artist_id = artists.id JOIN albums ON songs.album_id = albums.id " +
		"WHERE songs.file_name LIKE ?;", path+"%")
}

// SongsNotInPath loads a slice of all Song structs that do not reside under the specified
// filesystem path from the database
func (s *sqliteBackend) SongsNotInPath(path string) ([]Song, error) {
	return s.songQuery("SELECT songs.*,artists.title AS artist,albums.title AS album FROM songs " +
		"JOIN artists ON songs.artist_id = artists.id JOIN albums ON songs.album_id = albums.id " +
		"WHERE songs.file_name NOT LIKE ?;", path+"%")
}

// DeleteSong removes a Song from the database
func (s *sqliteBackend) DeleteSong(a *Song) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Attempt to delete this song by its ID, if available
	tx := db.MustBegin()
	if a.ID != 0 {
		tx.Exec("DELETE FROM songs WHERE id = ?;", a.ID)
		return tx.Commit()
	}

	// Else, attempt to remove the song by its file name
	tx.Exec("DELETE FROM songs WHERE file_name = ?;", a.FileName)
	return tx.Commit()
}

// LoadSong loads a Song from the database, populating the parameter struct
func (s *sqliteBackend) LoadSong(a *Song) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Load the song via ID if available
	if a.ID != 0 {
		if err := db.Get(a, "SELECT * FROM songs WHERE id = ?;", a.ID); err != nil {
			return err
		}

		return nil
	}

	// Load via file name
	if err := db.Get(a, "SELECT * FROM songs WHERE file_name = ?;", a.FileName); err != nil {
		return err
	}

	return nil
}

// SaveSong attempts to save a Song to the database
func (s *sqliteBackend) SaveSong(a *Song) error {
	// Open database
	db, err := s.Open()
	if err != nil {
		return err
	}
	defer db.Close()

	// Insert new song
	query := "INSERT INTO songs (`album_id`, `artist_id`, `bitrate`, `channels`, `comment`, `file_name`, " +
		"`file_size`, `file_type`, `genre`, `last_modified`, `length`, `sample_rate`, `title`, `track`, `year`) " +
		" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"
	tx := db.MustBegin()
	tx.Exec(query, a.AlbumID, a.ArtistID, a.Bitrate, a.Channels, a.Comment, a.FileName, a.FileSize, a.FileType,
		a.Genre, a.LastModified, a.Length, a.SampleRate, a.Title, a.Track, a.Year)

	// Commit transaction
	if err := tx.Commit(); err != nil {
		return err
	}

	// If no ID, reload to grab it
	if a.ID == 0 {
		if err := s.LoadSong(a); err != nil {
			return err
		}
	}

	return nil
}

// songQuery loads a slice of Song structs matching the input query
func (s *sqliteBackend) songQuery(query string, args ...interface{}) ([]Song, error) {
	// Open database
	db, err := s.Open()
	if err != nil {
		return nil, err
	}
	defer db.Close()

	// Perform input query with arguments
	rows, err := db.Queryx(query, args...)
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	// Iterate all rows
	songs := make([]Song, 0)
	a := Song{}
	for rows.Next() {
		// Scan song into struct
		if err := rows.StructScan(&a); err != nil {
			return nil, err
		}

		// Append to list
		songs = append(songs, a)
	}

	return songs, nil
}
<|endoftext|>


<commit_before>package httpserver

import (
	"net/http"

	"github.com/mtojek/greenwall/middleware/configuration"
)

type HTTPServer struct {
	applicationConfiguration *configuration.ApplicationConfiguration
}

func NewHTTPServer(applicationConfiguration *configuration.ApplicationConfiguration) *HTTPServer {
	return &HTTPServer{
		applicationConfiguration: applicationConfiguration,
	}
}

func (httpServer *HTTPServer) ListenAndServe() {
	staticHandler := http.FileServer(http.Dir(httpServer.applicationConfiguration.StaticDir))
	http.ListenAndServe(httpServer.applicationConfiguration.HostPort, staticHandler)
}
<commit_msg>Log error when HTTP server can't be started<commit_after>package httpserver

import (
	"net/http"

	"log"

	"github.com/mtojek/greenwall/middleware/configuration"
)

type HTTPServer struct {
	applicationConfiguration *configuration.ApplicationConfiguration
}

func NewHTTPServer(applicationConfiguration *configuration.ApplicationConfiguration) *HTTPServer {
	return &HTTPServer{
		applicationConfiguration: applicationConfiguration,
	}
}

func (httpServer *HTTPServer) ListenAndServe() {
	staticHandler := http.FileServer(http.Dir(httpServer.applicationConfiguration.StaticDir))
	err := http.ListenAndServe(httpServer.applicationConfiguration.HostPort, staticHandler)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2018 The Fractal Team Authors
// This file is part of the fractal project.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package blockchain

import (
	"fmt"
	"math/big"
	"reflect"
	"testing"

	"github.com/davecgh/go-spew/spew"
	"github.com/fractalplatform/fractal/common"
	"github.com/fractalplatform/fractal/consensus/dpos"
	"github.com/fractalplatform/fractal/params"
	"github.com/fractalplatform/fractal/rawdb"
	"github.com/fractalplatform/fractal/utils/fdb"
)

var defaultgenesisBlockHash = common.HexToHash("0xcb3ac1968ff990f05e624445e53ed4019aa919a9ec0ff24b1d6f02865223d7f4")

func TestDefaultGenesisBlock(t *testing.T) {
	block := DefaultGenesis().ToBlock(nil)
	if block.Hash() != defaultgenesisBlockHash {
		t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash().Hex(), defaultgenesisBlockHash.Hex())
	}
}

func TestSetupGenesis(t *testing.T) {
	var (
		customghash = common.HexToHash("0x8f821669d30590f23078b78b0d30e9255c80d8ce62a2f7c5f9acc61012cfc5e7")
		customg     = Genesis{
			Config:        &params.ChainConfig{ChainID: big.NewInt(3), SysName: "systemio", SysToken: "fractalfoundation"},
			Dpos:          dpos.DefaultConfig,
			Coinbase:      "coinbase",
			AllocAccounts: DefaultGenesisAccounts(),
			AllocAssets:   DefaultGenesisAssets(),
		}
		oldcustomg = customg
	)
	oldcustomg.Config = &params.ChainConfig{ChainID: big.NewInt(2), SysName: "ftsystem", SysToken: "ftoken"}

	tests := []struct {
		name       string
		fn         func(fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error)
		wantConfig *params.ChainConfig
		wantDpos   *dpos.Config
		wantHash   common.Hash
		wantErr    error
	}{
		{
			name: "genesis without ChainConfig",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				return SetupGenesisBlock(db, new(Genesis))
			},
			wantErr:    errGenesisNoConfig,
			wantConfig: params.DefaultChainconfig,
			wantDpos:   dpos.DefaultConfig,
		},
		{
			name: "no block in DB, genesis == nil",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				return SetupGenesisBlock(db, nil)
			},
			wantHash:   defaultgenesisBlockHash,
			wantConfig: params.DefaultChainconfig,
			wantDpos:   dpos.DefaultConfig,
		},
		{
			name: "mainnet block in DB, genesis == nil",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				if _, err := DefaultGenesis().Commit(db); err != nil {
					return nil, nil, common.Hash{}, err
				}
				return SetupGenesisBlock(db, nil)
			},
			wantHash:   defaultgenesisBlockHash,
			wantConfig: params.DefaultChainconfig,
			wantDpos:   dpos.DefaultConfig,
		},
		{
			name: "compatible config in DB",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				if _, err := oldcustomg.Commit(db); err != nil {
					return nil, nil, common.Hash{}, err
				}
				fmt.Println("=====>SetupGenesisBlock")
				return SetupGenesisBlock(db, &customg)
			},
			wantHash:   customghash,
			wantConfig: customg.Config,
			wantDpos:   customg.Dpos,
		},
	}

	for i, test := range tests {
		db := fdb.NewMemDatabase()
		fmt.Println("=====>", i, test.name)

		config, dpos, hash, err := test.fn(db)
		fmt.Println("=====>", i, test.name, err)

		// Check the return values.
		if !reflect.DeepEqual(err, test.wantErr) {
			spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
			t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
		}
		if !reflect.DeepEqual(config, test.wantConfig) {
			t.Errorf("%s:\n returned %v\nwant     %v", test.name, config, test.wantConfig)
		}

		if !reflect.DeepEqual(dpos, test.wantDpos) {
			t.Errorf("%s:\nreturned %v\nwant     %v", test.name, config, test.wantConfig)
		}

		if hash != test.wantHash {
			t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
		} else if err == nil {
			// Check database content.
			stored := rawdb.ReadBlock(db, test.wantHash, 0)
			if stored.Hash() != test.wantHash {
				t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
			}
		}
	}
}
<commit_msg>fix genesis_test bug<commit_after>// Copyright 2018 The Fractal Team Authors
// This file is part of the fractal project.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package blockchain

import (
	"fmt"
	"math/big"
	"reflect"
	"testing"

	"github.com/davecgh/go-spew/spew"
	"github.com/fractalplatform/fractal/common"
	"github.com/fractalplatform/fractal/consensus/dpos"
	"github.com/fractalplatform/fractal/params"
	"github.com/fractalplatform/fractal/rawdb"
	"github.com/fractalplatform/fractal/utils/fdb"
)

var defaultgenesisBlockHash = common.HexToHash("0x13a095789777033eb093bd28b76607d2001b01e42a04b344ec7e0ef33b2862d5")

func TestDefaultGenesisBlock(t *testing.T) {
	block := DefaultGenesis().ToBlock(nil)
	if block.Hash() != defaultgenesisBlockHash {
		t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash().Hex(), defaultgenesisBlockHash.Hex())
	}
}

func TestSetupGenesis(t *testing.T) {
	var (
		customghash = common.HexToHash("0xb218822f1ea61e3e622bfeea145d875c7f79123ad61264032944fdf3b461c7ce")
		customg     = Genesis{
			Config:        &params.ChainConfig{ChainID: big.NewInt(3), SysName: "systemio", SysToken: "fractalfoundation"},
			Dpos:          dpos.DefaultConfig,
			Coinbase:      "coinbase",
			AllocAccounts: DefaultGenesisAccounts(),
			AllocAssets:   DefaultGenesisAssets(),
		}
		oldcustomg     = customg
		oldcustomghash = common.HexToHash("0xc927067fedbc34fd5b9667bb973cee16e7730200383bf07f417580c10df77f30")
	)
	oldcustomg.Config = &params.ChainConfig{ChainID: big.NewInt(2), SysName: "ftsystem", SysToken: "ftoken"}

	tests := []struct {
		name       string
		fn         func(fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error)
		wantConfig *params.ChainConfig
		wantDpos   *dpos.Config
		wantHash   common.Hash
		wantErr    error
	}{
		{
			name: "genesis without ChainConfig",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				return SetupGenesisBlock(db, new(Genesis))
			},
			wantErr:    errGenesisNoConfig,
			wantConfig: params.DefaultChainconfig,
			wantDpos:   dpos.DefaultConfig,
		},
		{
			name: "no block in DB, genesis == nil",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				return SetupGenesisBlock(db, nil)
			},
			wantHash:   defaultgenesisBlockHash,
			wantConfig: params.DefaultChainconfig,
			wantDpos:   dpos.DefaultConfig,
		},
		{
			name: "mainnet block in DB, genesis == nil",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				if _, err := DefaultGenesis().Commit(db); err != nil {
					return nil, nil, common.Hash{}, err
				}
				return SetupGenesisBlock(db, nil)
			},
			wantHash:   defaultgenesisBlockHash,
			wantConfig: params.DefaultChainconfig,
			wantDpos:   dpos.DefaultConfig,
		},
		{
			name: "compatible config in DB",
			fn: func(db fdb.Database) (*params.ChainConfig, *dpos.Config, common.Hash, error) {
				if _, err := oldcustomg.Commit(db); err != nil {
					return nil, nil, common.Hash{}, err
				}
				fmt.Println("=====>SetupGenesisBlock")
				return SetupGenesisBlock(db, &customg)
			},
			wantErr: &GenesisMismatchError{
				oldcustomghash,
				customghash,
			},
			wantHash:   customghash,
			wantConfig: customg.Config,
			wantDpos:   customg.Dpos,
		},
	}

	for i, test := range tests {
		db := fdb.NewMemDatabase()
		fmt.Println("=====>", i, test.name)

		config, dpos, hash, err := test.fn(db)
		fmt.Println("=====>", i, test.name, err)

		// Check the return values.
		if !reflect.DeepEqual(err, test.wantErr) {
			spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
			t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
		}
		if !reflect.DeepEqual(config, test.wantConfig) {
			t.Errorf("%s:\n returned %v\nwant     %v", test.name, config, test.wantConfig)
		}

		if !reflect.DeepEqual(dpos, test.wantDpos) {
			t.Errorf("%s:\nreturned %v\nwant     %v", test.name, config, test.wantConfig)
		}

		if hash != test.wantHash {
			t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
		} else if err == nil {
			// Check database content.
			stored := rawdb.ReadBlock(db, test.wantHash, 0)
			if stored.Hash() != test.wantHash {
				t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
			}
		}
	}
}
<|endoftext|>


<commit_before>account_bongo.go<commit_msg>account_bongo: some functions have transferred here from account<commit_after>package models

import (
	"errors"
	"fmt"
	"socialapi/request"

	"github.com/koding/bongo"
)

func NewAccount() *Account {
	return &Account{}
}

func (a Account) GetId() int64 {
	return a.Id
}

func (a Account) TableName() string {
	return "api.account"
}

func (a *Account) AfterUpdate() {
	SetAccountToCache(a)
}

func (a *Account) AfterCreate() {
	SetAccountToCache(a)
}

func (a *Account) One(q *bongo.Query) error {
	return bongo.B.One(a, a, q)
}

func (a *Account) ById(id int64) error {
	return bongo.B.ById(a, id)
}

func (a *Account) Update() error {
	return bongo.B.Update(a)
}

func (a *Account) Create() error {
	if a.OldId == "" {
		return errors.New("old id is not set")
	}

	return bongo.B.Create(a)
}

func (a *Account) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(a, data, q)
}<|endoftext|>


<commit_before>package gerrit

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func (g GerritInstance) getChangeInformation(changeID string) (*ChangeInfo, error) {
	urlToCall := fmt.Sprintf("%s/changes/%s/?o=CURRENT_REVISION", g.getAPIUrl(), changeID)

	client := &http.Client{}
	req, _ := http.NewRequest("GET", urlToCall, nil)
	req.SetBasicAuth(g.Username, g.Password)
	req.Header.Add("Content-Type", "application/json;charset=UTF-8")

	resp, err := client.Do(req)
	defer resp.Body.Close()

	if err != nil {
		return nil, err
	}

	if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
		log.Printf("> Change-details for change id \"%s\" received", changeID)

	} else {
		log.Printf("> Call success, but the status code doesn`t match ~200: %s", resp.Status)
		return nil, errors.New("Call success, but the status code doesn`t match ~200")
	}

	var change ChangeInfo

	respBody, err := ioutil.ReadAll(resp.Body)
	// Every Gerrit response starts with ")]}'"
	jsonBody := string(respBody)[4:]

	err = json.Unmarshal([]byte(jsonBody), &change)
	if err != nil {
		return nil, err
	}

	return &change, nil
}

// https://review.typo3.org/Documentation/rest-api-changes.html#set-review
func (g GerritInstance) PostCommentOnChangeset(m *Message, vote int, msg string) {
	log.Printf("> Start posting review for %s (%s)", m.Change.URL, m.Patchset.Ref)

	changeID := m.Change.ID
	revisionID := m.Patchset.Revision
	urlToCall := fmt.Sprintf("%s/changes/%s/revisions/%s/review", g.getAPIUrl(true), changeID, revisionID)

	log.Printf("> Calling %s", urlToCall)

	bodyStruct := &ReviewInput{
		Message: msg,
		Labels: map[string]int{
			// Code-Review
			"Verified": vote,
		},
	}

	body, _ := json.Marshal(bodyStruct)

	client := &http.Client{}
	req, _ := http.NewRequest("POST", urlToCall, strings.NewReader(string(body)))
	req.SetBasicAuth(g.Username, g.Password)
	req.Header.Add("Content-Type", "application/json;charset=UTF-8")

	resp, err := client.Do(req)
	defer resp.Body.Close()

	if err != nil {
		log.Println("> Call failed", err)
	}

	if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
		log.Printf("> Call success: %s", resp.Status)
	} else {
		log.Printf("> Call success, but the status code doesn`t match ~200: %s", resp.Status)
	}
}
<commit_msg>Added some more logging<commit_after>package gerrit

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func (g GerritInstance) GetChangeInformation(changeID string) (*ChangeInfo, error) {
	urlToCall := fmt.Sprintf("%s/changes/%s/?o=CURRENT_REVISION", g.getAPIUrl(false), changeID)
	log.Printf("Calling %s\n", urlToCall)

	client := &http.Client{}
	req, _ := http.NewRequest("GET", urlToCall, nil)
	req.SetBasicAuth(g.Username, g.Password)
	req.Header.Add("Content-Type", "application/json;charset=UTF-8")

	resp, err := client.Do(req)
	defer resp.Body.Close()

	if err != nil {
		return nil, err
	}

	if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
		log.Printf("> Change-details for change id \"%s\" received", changeID)

	} else {
		log.Printf("> Call success, but the status code doesn`t match ~200: %s - %s", resp.Status, err)
		return nil, errors.New("Call success, but the status code doesn`t match ~200")
	}

	var change ChangeInfo

	respBody, err := ioutil.ReadAll(resp.Body)
	// Every Gerrit response starts with ")]}'"
	jsonBody := string(respBody)[4:]

	err = json.Unmarshal([]byte(jsonBody), &change)
	if err != nil {
		return nil, err
	}

	return &change, nil
}

// https://review.typo3.org/Documentation/rest-api-changes.html#set-review
func (g GerritInstance) PostCommentOnChangeset(m *Message, vote int, msg string) {
	log.Printf("> Start posting review for %s (%s)", m.Change.URL, m.Patchset.Ref)

	changeID := m.Change.ID
	revisionID := m.Patchset.Revision
	urlToCall := fmt.Sprintf("%s/changes/%s/revisions/%s/review", g.getAPIUrl(true), changeID, revisionID)

	log.Printf("> Calling %s", urlToCall)

	bodyStruct := &ReviewInput{
		Message: msg,
		Labels: map[string]int{
			// Code-Review
			"Verified": vote,
		},
	}

	body, _ := json.Marshal(bodyStruct)

	client := &http.Client{}
	req, _ := http.NewRequest("POST", urlToCall, strings.NewReader(string(body)))
	req.SetBasicAuth(g.Username, g.Password)
	req.Header.Add("Content-Type", "application/json;charset=UTF-8")

	resp, err := client.Do(req)
	defer resp.Body.Close()

	if err != nil {
		log.Println("> Call failed", err)
	}

	if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
		log.Printf("> Call success: %s", resp.Status)
	} else {
		log.Printf("> Call success, but the status code doesn`t match ~200: %s", resp.Status)
	}
}
<|endoftext|>


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

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/codegangsta/cli"
	"github.com/jcjones/github-pr-status/api"
)

var authenticationConfig api.AuthConfig

func showError(c *cli.Context, err error) error {
	fmt.Println("ERROR: ")
	fmt.Println(err.Error())
	fmt.Println("")
	cli.ShowCommandHelp(c, c.Command.Name)
	return err
}

func actionSetStatus(c *cli.Context) {
	var err error

	if !c.IsSet("state") {
		err = fmt.Errorf("A state must be specified")
		showError(c, err)
		return
	}
	state := c.String("state")

	switch state {
	case "pending":
		fallthrough
	case "success":
		fallthrough
	case "error":
		fallthrough
	case "failure":
		// OK
		break
	default:
		showError(c, fmt.Errorf("Not a valid state: %s", c.String("state")))
		return
	}

	if !c.IsSet("context") {
		err = fmt.Errorf("A context must be specified")
		showError(c, err)
		return
	}
	context := c.String("context")

	if !c.IsSet("sha") {
		err = fmt.Errorf("A commit ID must be specified")
		showError(c, err)
		return
	}
	sha := c.String("sha")

	// Optionals
	url := c.String("url")
	description := c.String("description")

	// Accept description from stdin
	if description == "-" {
		data, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			showError(c, err)
			return
		}

		description = string(data)
	}

	// Checked at the global scope
	owner := c.GlobalString("owner")
	repo := c.GlobalString("repo")
	debug := c.GlobalBool("debug")

	fmt.Printf("Status ID=%s State=%s Context=%s URL=%s Description=%s\n", sha, state, context, url, description)
	err = api.StatusSet(authenticationConfig, owner, repo, sha, state, context, url, description, debug)
	if err != nil {
		fmt.Printf("Could not post: %s\n", err.Error())
	}
}

func actionAddComment(c *cli.Context) {
	var err error

	if !c.IsSet("body") {
		err = fmt.Errorf("A comment body must be specified")
		showError(c, err)
		return
	}
	body := c.String("body")

	// Accept body from stdin
	if body == "-" {
		data, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			showError(c, err)
			return
		}

		body = string(data)
	}

	if !c.IsSet("pr") {
		err = fmt.Errorf("A PR must be specified")
		showError(c, err)
		return
	}

	pr := c.Int("pr")
	if pr < 1 {
		err = fmt.Errorf("PRs must be >0")
		showError(c, err)
		return
	}

	fmt.Printf("Comment PR=#%d\n", pr)

	// Checked at the global scope
	owner := c.GlobalString("owner")
	repo := c.GlobalString("repo")
	debug := c.GlobalBool("debug")

	err = api.IssueAddComment(authenticationConfig, owner, repo, body, pr, debug)
	if err != nil {
		fmt.Printf("Could not post: %s\n", err.Error())
	}

}

func loadAuthDetailsAndConfigureLogging(c *cli.Context) (err error) {
	if !c.GlobalIsSet("authfile") {
		err = fmt.Errorf("You must specifiy a path to the authfile.")
		return showError(c, err)
	}

	path := c.GlobalString("authfile")
	configJSON, err := ioutil.ReadFile(path)
	if err != nil {
		err = fmt.Errorf("Could not read authentication details. Path=%s Err=%s", path, err)
		return showError(c, err)
	}

	err = json.Unmarshal(configJSON, &authenticationConfig)
	if err != nil {
		err = fmt.Errorf("Could not parse authentication details. Err=%s", err)
		return showError(c, err)
	}

	if authenticationConfig.Type == nil || *authenticationConfig.Type != "basic" {
		err = fmt.Errorf("Only authentication type supported is 'basic'.")
		return showError(c, err)
	}

	if authenticationConfig.Username == nil {
		err = fmt.Errorf("You must provide a username in the authfile.")
		return showError(c, err)
	}

	if authenticationConfig.Password == nil {
		err = fmt.Errorf("You must provide a password or token in the authfile.")
		return showError(c, err)
	}

	if !c.GlobalIsSet("owner") {
		err = fmt.Errorf("You must provide a repo owner.")
		return showError(c, err)
	}

	if !c.GlobalIsSet("repo") {
		err = fmt.Errorf("You must provide a repo to operate on.")
		return showError(c, err)
	}

	return
}

func main() {
	app := cli.NewApp()
	app.Usage = "GitHub CI PR Tools"
	app.Version = "0.4.0"
	app.Copyright = "Copyright 2015 ISRG.  All rights reserved."
	app.Authors = []cli.Author{
		cli.Author{Name: "James 'J.C.' Jones", Email: "jcjones@letsencrypt.org"},
	}
	app.Before = loadAuthDetailsAndConfigureLogging

	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "debug, D", Usage: "Enable debugging output"},
		cli.StringFlag{Name: "owner, o", Usage: "Owner segment of GitHub Path"},
		cli.StringFlag{Name: "repo, r", Usage: "Repo segment of GitHub Path"},
		cli.StringFlag{Name: "authfile, f", Usage: "Authentication details"},
	}

	statusCommand := cli.Command{
		Name:   "status",
		Usage:  "Set or update a status on a commit",
		Action: actionSetStatus,
		Flags: []cli.Flag{
			cli.StringFlag{Name: "sha, i", Usage: "Commit ID"},
			cli.StringFlag{Name: "state, s", Usage: "One of {pending, success, error, failure}"},
			cli.StringFlag{Name: "url, l", Usage: "URL to link from the status"},
			cli.StringFlag{Name: "context, c", Usage: "Status context, such as 'integration/gofmt'"},
			cli.StringFlag{Name: "description, d", Usage: "Extra descriptive text, or '-' to read from stdin"},
		},
	}

	commentCommand := cli.Command{
		Name:   "comment",
		Usage:  "Add a comment to a PR",
		Action: actionAddComment,
		Flags: []cli.Flag{
			cli.IntFlag{Name: "pr, n", Usage: "Pull Request #"},
			cli.StringFlag{Name: "body, b", Usage: "Body of the comment, or '-' to read from stdin"},
		},
	}

	app.Commands = []cli.Command{
		statusCommand, commentCommand,
	}

	app.Run(os.Args)
}
<commit_msg>Don't print to stdout in non-error circumstances<commit_after>// Copyright 2015 ISRG.  All rights reserved
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/codegangsta/cli"
	"github.com/jcjones/github-pr-status/api"
)

var authenticationConfig api.AuthConfig

func showError(c *cli.Context, err error) error {
	fmt.Println("ERROR: ")
	fmt.Println(err.Error())
	fmt.Println("")
	cli.ShowCommandHelp(c, c.Command.Name)
	return err
}

func actionSetStatus(c *cli.Context) {
	var err error

	if !c.IsSet("state") {
		err = fmt.Errorf("A state must be specified")
		showError(c, err)
		return
	}
	state := c.String("state")

	switch state {
	case "pending":
		fallthrough
	case "success":
		fallthrough
	case "error":
		fallthrough
	case "failure":
		// OK
		break
	default:
		showError(c, fmt.Errorf("Not a valid state: %s", c.String("state")))
		return
	}

	if !c.IsSet("context") {
		err = fmt.Errorf("A context must be specified")
		showError(c, err)
		return
	}
	context := c.String("context")

	if !c.IsSet("sha") {
		err = fmt.Errorf("A commit ID must be specified")
		showError(c, err)
		return
	}
	sha := c.String("sha")

	// Optionals
	url := c.String("url")
	description := c.String("description")

	// Accept description from stdin
	if description == "-" {
		data, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			showError(c, err)
			return
		}

		description = string(data)
	}

	// Checked at the global scope
	owner := c.GlobalString("owner")
	repo := c.GlobalString("repo")
	debug := c.GlobalBool("debug")

	err = api.StatusSet(authenticationConfig, owner, repo, sha, state, context, url, description, debug)
	if err != nil {
		fmt.Printf("Could not post: %s\n", err.Error())
	}
}

func actionAddComment(c *cli.Context) {
	var err error

	if !c.IsSet("body") {
		err = fmt.Errorf("A comment body must be specified")
		showError(c, err)
		return
	}
	body := c.String("body")

	// Accept body from stdin
	if body == "-" {
		data, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			showError(c, err)
			return
		}

		body = string(data)
	}

	if !c.IsSet("pr") {
		err = fmt.Errorf("A PR must be specified")
		showError(c, err)
		return
	}

	pr := c.Int("pr")
	if pr < 1 {
		err = fmt.Errorf("PRs must be >0")
		showError(c, err)
		return
	}

	fmt.Printf("Comment PR=#%d\n", pr)

	// Checked at the global scope
	owner := c.GlobalString("owner")
	repo := c.GlobalString("repo")
	debug := c.GlobalBool("debug")

	err = api.IssueAddComment(authenticationConfig, owner, repo, body, pr, debug)
	if err != nil {
		fmt.Printf("Could not post: %s\n", err.Error())
	}

}

func loadAuthDetailsAndConfigureLogging(c *cli.Context) (err error) {
	if !c.GlobalIsSet("authfile") {
		err = fmt.Errorf("You must specifiy a path to the authfile.")
		return showError(c, err)
	}

	path := c.GlobalString("authfile")
	configJSON, err := ioutil.ReadFile(path)
	if err != nil {
		err = fmt.Errorf("Could not read authentication details. Path=%s Err=%s", path, err)
		return showError(c, err)
	}

	err = json.Unmarshal(configJSON, &authenticationConfig)
	if err != nil {
		err = fmt.Errorf("Could not parse authentication details. Err=%s", err)
		return showError(c, err)
	}

	if authenticationConfig.Type == nil || *authenticationConfig.Type != "basic" {
		err = fmt.Errorf("Only authentication type supported is 'basic'.")
		return showError(c, err)
	}

	if authenticationConfig.Username == nil {
		err = fmt.Errorf("You must provide a username in the authfile.")
		return showError(c, err)
	}

	if authenticationConfig.Password == nil {
		err = fmt.Errorf("You must provide a password or token in the authfile.")
		return showError(c, err)
	}

	if !c.GlobalIsSet("owner") {
		err = fmt.Errorf("You must provide a repo owner.")
		return showError(c, err)
	}

	if !c.GlobalIsSet("repo") {
		err = fmt.Errorf("You must provide a repo to operate on.")
		return showError(c, err)
	}

	return
}

func main() {
	app := cli.NewApp()
	app.Usage = "GitHub CI PR Tools"
	app.Version = "0.4.0"
	app.Copyright = "Copyright 2015 ISRG.  All rights reserved."
	app.Authors = []cli.Author{
		cli.Author{Name: "James 'J.C.' Jones", Email: "jcjones@letsencrypt.org"},
	}
	app.Before = loadAuthDetailsAndConfigureLogging

	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "debug, D", Usage: "Enable debugging output"},
		cli.StringFlag{Name: "owner, o", Usage: "Owner segment of GitHub Path"},
		cli.StringFlag{Name: "repo, r", Usage: "Repo segment of GitHub Path"},
		cli.StringFlag{Name: "authfile, f", Usage: "Authentication details"},
	}

	statusCommand := cli.Command{
		Name:   "status",
		Usage:  "Set or update a status on a commit",
		Action: actionSetStatus,
		Flags: []cli.Flag{
			cli.StringFlag{Name: "sha, i", Usage: "Commit ID"},
			cli.StringFlag{Name: "state, s", Usage: "One of {pending, success, error, failure}"},
			cli.StringFlag{Name: "url, l", Usage: "URL to link from the status"},
			cli.StringFlag{Name: "context, c", Usage: "Status context, such as 'integration/gofmt'"},
			cli.StringFlag{Name: "description, d", Usage: "Extra descriptive text, or '-' to read from stdin"},
		},
	}

	commentCommand := cli.Command{
		Name:   "comment",
		Usage:  "Add a comment to a PR",
		Action: actionAddComment,
		Flags: []cli.Flag{
			cli.IntFlag{Name: "pr, n", Usage: "Pull Request #"},
			cli.StringFlag{Name: "body, b", Usage: "Body of the comment, or '-' to read from stdin"},
		},
	}

	app.Commands = []cli.Command{
		statusCommand, commentCommand,
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package handler

import (
	"fmt"
	"net/http"

	"golang.org/x/oauth2"

	"gopkg.in/mgo.v2"

	"github.com/Lunchr/luncher-api/db/model"
	"github.com/Lunchr/luncher-api/router"
	fbmodel "github.com/deiwin/facebook/model"
	"github.com/julienschmidt/httprouter"
)

// RedirectToFBForRegistration returns a handler that redirects the user to Facebook to log in
// so they could be registered in our system
func (f Facebook) RedirectToFBForRegistration() router.Handler {
	return func(w http.ResponseWriter, r *http.Request) *router.HandlerError {
		session := f.sessionManager.GetOrInit(w, r)
		redirectURL := f.registrationAuth.AuthURL(session)
		http.Redirect(w, r, redirectURL, http.StatusSeeOther)
		return nil
	}
}

// RedirectedFromFBForRegistration provides a handler that stores the data about the current user
// required to continue the registration in the DB.
func (f Facebook) RedirectedFromFBForRegistration() router.Handler {
	return func(w http.ResponseWriter, r *http.Request) *router.HandlerError {
		session := f.sessionManager.GetOrInit(w, r)
		tok, handlerErr := f.getLongTermToken(session, r)
		if handlerErr != nil {
			return handlerErr
		}
		fbUserID, err := f.getUserID(tok)
		if err != nil {
			return router.NewHandlerError(err, "Failed to get the user information from Facebook", http.StatusInternalServerError)
		}
		// We can't guarantee that the user doesn't just close the browser or something during the registration process.
		// Because of this, there already might be a user object with this FB User ID in the DB.
		_, err = f.usersCollection.GetFbID(fbUserID)
		if err == mgo.ErrNotFound {
			err = f.usersCollection.Insert(&model.User{FacebookUserID: fbUserID})
			if err != nil {
				return router.NewHandlerError(err, "Failed to create a User object in the DB", http.StatusInternalServerError)
			}
		} else if err != nil {
			return router.NewHandlerError(err, "Failed to check the DB for users", http.StatusInternalServerError)
		}
		err = f.storeAccessTokensInDB(fbUserID, tok, session)
		if err != nil {
			return router.NewHandlerError(err, "Failed to persist Facebook login information", http.StatusInternalServerError)
		}
		http.Redirect(w, r, "/#/register/pages", http.StatusSeeOther)
		return nil
	}
}

// ListPagesManagedByUser returns a handler that lists all pages managed by the currently logged in user
func (f Facebook) ListPagesManagedByUser() router.Handler {
	handler := func(w http.ResponseWriter, r *http.Request, user *model.User) *router.HandlerError {
		fbPages, err := f.getPages(&user.Session.FacebookUserToken)
		if err != nil {
			return router.NewHandlerError(err, "Couldn't get the list of pages managed by this user", http.StatusBadGateway)
		}
		pages := mapFBPagesToModelPages(fbPages)
		return writeJSON(w, pages)
	}
	return checkLogin(f.sessionManager, f.usersCollection, handler)
}

// Page returns a handler that returns information about the specified page
func (f Facebook) Page() router.HandlerWithParams {
	handler := func(w http.ResponseWriter, r *http.Request, ps httprouter.Params, user *model.User) *router.HandlerError {
		id := ps.ByName("id")
		if id == "" {
			return router.NewSimpleHandlerError("Expecting a Page ID", http.StatusBadRequest)
		}
		fbPage, err := f.getPage(id, &user.Session.FacebookUserToken)
		if err != nil {
			return err
		}
		page := mapFBPageToModelPage(fbPage)
		return writeJSON(w, page)
	}
	return checkLoginWithParams(f.sessionManager, f.usersCollection, handler)
}

func (f Facebook) getPages(tok *oauth2.Token) ([]fbmodel.Page, error) {
	api := f.registrationAuth.APIConnection(tok)
	accs, err := api.Accounts()
	if err != nil {
		return nil, err
	}
	return accs.Data, nil
}

func (f Facebook) getPage(id string, tok *oauth2.Token) (*fbmodel.Page, *router.HandlerError) {
	api := f.registrationAuth.APIConnection(tok)
	page, err := api.Page(id)
	if err != nil {
		return nil, router.NewHandlerError(err, "Couldn't get the page", http.StatusBadGateway)
	}
	if page == nil {
		return nil, router.NewSimpleHandlerError("Page not found", http.StatusNotFound)
	}
	return page, nil
}

// Page represents a Facebook page
type Page struct {
	ID      string `json:"id"`
	Name    string `json:"name"`
	Address string `json:"address,omitempty"`
	Phone   string `json:"phone,omitempty"`
	Website string `json:"website,omitempty"`
}

// mapFBPagesToModelPages only maps the ID and the Name field, because that's really
// all that's required for the page listing
func mapFBPagesToModelPages(fbPages []fbmodel.Page) []Page {
	pages := make([]Page, len(fbPages))
	for i, v := range fbPages {
		pages[i] = Page{
			ID:   v.ID,
			Name: v.Name,
		}
	}
	return pages
}

func mapFBPageToModelPage(fbPage *fbmodel.Page) *Page {
	return &Page{
		ID:      fbPage.ID,
		Name:    fbPage.Name,
		Address: formAddressFromFBLocation(fbPage.Location),
		Phone:   fbPage.Phone,
		Website: fbPage.Website,
	}
}

func formAddressFromFBLocation(loc fbmodel.Location) string {
	return fmt.Sprintf("%s, %s, %s", loc.Street, loc.City, loc.Country)
}
<commit_msg>update registration process to fail if user already in DB<commit_after>package handler

import (
	"fmt"
	"net/http"

	"golang.org/x/oauth2"

	"gopkg.in/mgo.v2"

	"github.com/Lunchr/luncher-api/db/model"
	"github.com/Lunchr/luncher-api/router"
	fbmodel "github.com/deiwin/facebook/model"
	"github.com/julienschmidt/httprouter"
)

// RedirectToFBForRegistration returns a handler that redirects the user to Facebook to log in
// so they could be registered in our system
func (f Facebook) RedirectToFBForRegistration() router.Handler {
	return func(w http.ResponseWriter, r *http.Request) *router.HandlerError {
		session := f.sessionManager.GetOrInit(w, r)
		redirectURL := f.registrationAuth.AuthURL(session)
		http.Redirect(w, r, redirectURL, http.StatusSeeOther)
		return nil
	}
}

// RedirectedFromFBForRegistration provides a handler that stores the data about the current user
// required to continue the registration in the DB.
func (f Facebook) RedirectedFromFBForRegistration() router.Handler {
	return func(w http.ResponseWriter, r *http.Request) *router.HandlerError {
		session := f.sessionManager.GetOrInit(w, r)
		tok, handlerErr := f.getLongTermToken(session, r)
		if handlerErr != nil {
			return handlerErr
		}
		fbUserID, err := f.getUserID(tok)
		if err != nil {
			return router.NewHandlerError(err, "Failed to get the user information from Facebook", http.StatusInternalServerError)
		}
		// We can't guarantee that the user doesn't just close the browser or something during the registration process.
		// Because of this, there already might be a user object with this FB User ID in the DB. If the user exists in the DB,
		// but doesn't have a restaurant connected to it, continue as the user would've been just created. But, to be safe, when
		// the user already exists and has a restaurant connected to it, fail immediately.
		user, err := f.usersCollection.GetFbID(fbUserID)
		if err == mgo.ErrNotFound {
			err = f.usersCollection.Insert(&model.User{FacebookUserID: fbUserID})
			if err != nil {
				return router.NewHandlerError(err, "Failed to create a User object in the DB", http.StatusInternalServerError)
			}
		} else if err != nil {
			return router.NewHandlerError(err, "Failed to check the DB for users", http.StatusInternalServerError)
		} else if err == nil && user.RestaurantID != "" {
			return router.NewSimpleHandlerError("This Facebook user is already registered", http.StatusForbidden)
		}
		err = f.storeAccessTokensInDB(fbUserID, tok, session)
		if err != nil {
			return router.NewHandlerError(err, "Failed to persist Facebook login information", http.StatusInternalServerError)
		}
		http.Redirect(w, r, "/#/register/pages", http.StatusSeeOther)
		return nil
	}
}

// ListPagesManagedByUser returns a handler that lists all pages managed by the currently logged in user
func (f Facebook) ListPagesManagedByUser() router.Handler {
	handler := func(w http.ResponseWriter, r *http.Request, user *model.User) *router.HandlerError {
		fbPages, err := f.getPages(&user.Session.FacebookUserToken)
		if err != nil {
			return router.NewHandlerError(err, "Couldn't get the list of pages managed by this user", http.StatusBadGateway)
		}
		pages := mapFBPagesToModelPages(fbPages)
		return writeJSON(w, pages)
	}
	return checkLogin(f.sessionManager, f.usersCollection, handler)
}

// Page returns a handler that returns information about the specified page
func (f Facebook) Page() router.HandlerWithParams {
	handler := func(w http.ResponseWriter, r *http.Request, ps httprouter.Params, user *model.User) *router.HandlerError {
		id := ps.ByName("id")
		if id == "" {
			return router.NewSimpleHandlerError("Expecting a Page ID", http.StatusBadRequest)
		}
		fbPage, err := f.getPage(id, &user.Session.FacebookUserToken)
		if err != nil {
			return err
		}
		page := mapFBPageToModelPage(fbPage)
		return writeJSON(w, page)
	}
	return checkLoginWithParams(f.sessionManager, f.usersCollection, handler)
}

func (f Facebook) getPages(tok *oauth2.Token) ([]fbmodel.Page, error) {
	api := f.registrationAuth.APIConnection(tok)
	accs, err := api.Accounts()
	if err != nil {
		return nil, err
	}
	return accs.Data, nil
}

func (f Facebook) getPage(id string, tok *oauth2.Token) (*fbmodel.Page, *router.HandlerError) {
	api := f.registrationAuth.APIConnection(tok)
	page, err := api.Page(id)
	if err != nil {
		return nil, router.NewHandlerError(err, "Couldn't get the page", http.StatusBadGateway)
	}
	if page == nil {
		return nil, router.NewSimpleHandlerError("Page not found", http.StatusNotFound)
	}
	return page, nil
}

// Page represents a Facebook page
type Page struct {
	ID      string `json:"id"`
	Name    string `json:"name"`
	Address string `json:"address,omitempty"`
	Phone   string `json:"phone,omitempty"`
	Website string `json:"website,omitempty"`
}

// mapFBPagesToModelPages only maps the ID and the Name field, because that's really
// all that's required for the page listing
func mapFBPagesToModelPages(fbPages []fbmodel.Page) []Page {
	pages := make([]Page, len(fbPages))
	for i, v := range fbPages {
		pages[i] = Page{
			ID:   v.ID,
			Name: v.Name,
		}
	}
	return pages
}

func mapFBPageToModelPage(fbPage *fbmodel.Page) *Page {
	return &Page{
		ID:      fbPage.ID,
		Name:    fbPage.Name,
		Address: formAddressFromFBLocation(fbPage.Location),
		Phone:   fbPage.Phone,
		Website: fbPage.Website,
	}
}

func formAddressFromFBLocation(loc fbmodel.Location) string {
	return fmt.Sprintf("%s, %s, %s", loc.Street, loc.City, loc.Country)
}
<|endoftext|>


<commit_before>package builtin

import (
	"fmt"
	"math"
	"pfi/sensorbee/sensorbee/bql/udf"
	"pfi/sensorbee/sensorbee/core"
	"pfi/sensorbee/sensorbee/data"
)

// singleParamFunc is a template for functions that
// have exactly one parameter
type singleParamFunc struct {
}

func (f *singleParamFunc) Accept(arity int) bool {
	return arity == 1
}

func (f *singleParamFunc) IsAggregationParameter(k int) bool {
	return false
}

// typePreservingSingleParamNumericFunc is a template for
// numeric functions that have the same return type as
// input type. If intFun is nil, then the result is computed
// by converting input and output of floatFun.
type typePreservingSingleParamNumericFunc struct {
	singleParamFunc
	intFun   func(int64) int64
	floatFun func(float64) float64
}

func (f *typePreservingSingleParamNumericFunc) Call(ctx *core.Context, args ...data.Value) (data.Value, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("function takes exactly one argument")
	}
	arg := args[0]
	if arg.Type() == data.TypeNull {
		return data.Null{}, nil
	} else if arg.Type() == data.TypeInt && f.intFun == nil {
		i, _ := data.AsInt(arg)
		return data.Int(f.floatFun(float64(i))), nil
	} else if arg.Type() == data.TypeInt {
		i, _ := data.AsInt(arg)
		return data.Int(f.intFun(i)), nil
	} else if arg.Type() == data.TypeFloat {
		d, _ := data.AsFloat(arg)
		return data.Float(f.floatFun(d)), nil
	}
	return nil, fmt.Errorf("cannot interpret %s as number", arg)
}

// floatValuedSingleParamNumericFunc is a template for
// numeric functions that return a floating point value
// even if the input is integral
type floatValuedSingleParamNumericFunc struct {
	singleParamFunc
	floatFun func(float64) float64
}

func (f *floatValuedSingleParamNumericFunc) Call(ctx *core.Context, args ...data.Value) (data.Value, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("function takes exactly one argument")
	}
	arg := args[0]
	if arg.Type() == data.TypeNull {
		return data.Null{}, nil
	} else if arg.Type() == data.TypeInt {
		i, _ := data.AsInt(arg)
		return data.Float(f.floatFun(float64(i))), nil
	} else if arg.Type() == data.TypeFloat {
		d, _ := data.AsFloat(arg)
		return data.Float(f.floatFun(d)), nil
	}
	return nil, fmt.Errorf("cannot interpret %s as number", arg)
}

// absFunc computes the absolute value of a number.
// See also: math.Abs.
//
// That UDF can be used in BQL as `abs`.
//
//  Input: Int or Float
//  Return Type: same as input
var absFunc udf.UDF = &typePreservingSingleParamNumericFunc{
	floatFun: math.Abs,
}

// cbrtFunc computes the cube root of a number.
// See also: math.Cbrt.
//
// That UDF can be used in BQL as `cbrt`.
//
//  Input: Int or Float
//  Return Type: Float
var cbrtFunc udf.UDF = &floatValuedSingleParamNumericFunc{
	floatFun: math.Cbrt,
}

// ceilFunc computes the smallest integer not less than its argument.
// See also: math.Ceil.
//
// That UDF can be used in BQL as `ceil`.
//
//  Input: Int or Float
//  Return Type: same as input
var ceilFunc = &typePreservingSingleParamNumericFunc{
	floatFun: math.Ceil,
}

// degreesFunc converts radians to degrees.
//
// That UDF can be used in BQL as `degrees`.
//
//  Input: Int or Float
//  Return Type: Float
var degreesFunc = &floatValuedSingleParamNumericFunc{
	floatFun: func(f float64) float64 {
		return f / math.Pi * 180
	},
}

// TODO DivFunc

// expFunc computes the exponential of a number.
// See also: math.Exp.
//
// That UDF can be used in BQL as `exp`.
//
//  Input: Int or Float
//  Return Type: Float
var expFunc = &floatValuedSingleParamNumericFunc{
	floatFun: math.Exp,
}

// floorFunc computes the largest integer not greater than its argument.
// See also: math.Floor.
//
// That UDF can be used in BQL as `floor`.
//
//  Input: Int or Float
//  Return Type: same as input
var floorFunc = &typePreservingSingleParamNumericFunc{
	floatFun: math.Floor,
}
<commit_msg>fix comments<commit_after>package builtin

import (
	"fmt"
	"math"
	"pfi/sensorbee/sensorbee/bql/udf"
	"pfi/sensorbee/sensorbee/core"
	"pfi/sensorbee/sensorbee/data"
)

// singleParamFunc is a template for functions that
// have exactly one parameter
type singleParamFunc struct {
}

func (f *singleParamFunc) Accept(arity int) bool {
	return arity == 1
}

func (f *singleParamFunc) IsAggregationParameter(k int) bool {
	return false
}

// typePreservingSingleParamNumericFunc is a template for
// numeric functions that have the same return type as
// input type. If intFun is nil, then the result is computed
// by converting input and output of floatFun.
type typePreservingSingleParamNumericFunc struct {
	singleParamFunc
	intFun   func(int64) int64
	floatFun func(float64) float64
}

func (f *typePreservingSingleParamNumericFunc) Call(ctx *core.Context, args ...data.Value) (data.Value, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("function takes exactly one argument")
	}
	arg := args[0]
	if arg.Type() == data.TypeNull {
		return data.Null{}, nil
	} else if arg.Type() == data.TypeInt && f.intFun == nil {
		i, _ := data.AsInt(arg)
		return data.Int(f.floatFun(float64(i))), nil
	} else if arg.Type() == data.TypeInt {
		i, _ := data.AsInt(arg)
		return data.Int(f.intFun(i)), nil
	} else if arg.Type() == data.TypeFloat {
		d, _ := data.AsFloat(arg)
		return data.Float(f.floatFun(d)), nil
	}
	return nil, fmt.Errorf("cannot interpret %s as number", arg)
}

// floatValuedSingleParamNumericFunc is a template for
// numeric functions that return a floating point value
// even if the input is integral
type floatValuedSingleParamNumericFunc struct {
	singleParamFunc
	floatFun func(float64) float64
}

func (f *floatValuedSingleParamNumericFunc) Call(ctx *core.Context, args ...data.Value) (data.Value, error) {
	if len(args) != 1 {
		return nil, fmt.Errorf("function takes exactly one argument")
	}
	arg := args[0]
	if arg.Type() == data.TypeNull {
		return data.Null{}, nil
	} else if arg.Type() == data.TypeInt {
		i, _ := data.AsInt(arg)
		return data.Float(f.floatFun(float64(i))), nil
	} else if arg.Type() == data.TypeFloat {
		d, _ := data.AsFloat(arg)
		return data.Float(f.floatFun(d)), nil
	}
	return nil, fmt.Errorf("cannot interpret %s as number", arg)
}

// absFunc computes the absolute value of a number.
// See also: math.Abs.
//
// It can be used in BQL as `abs`.
//
//  Input: Int or Float
//  Return Type: same as input
var absFunc udf.UDF = &typePreservingSingleParamNumericFunc{
	floatFun: math.Abs,
}

// cbrtFunc computes the cube root of a number.
// See also: math.Cbrt.
//
// It can be used in BQL as `cbrt`.
//
//  Input: Int or Float
//  Return Type: Float
var cbrtFunc udf.UDF = &floatValuedSingleParamNumericFunc{
	floatFun: math.Cbrt,
}

// ceilFunc computes the smallest integer not less than its argument.
// See also: math.Ceil.
//
// It can be used in BQL as `ceil`.
//
//  Input: Int or Float
//  Return Type: same as input
var ceilFunc udf.UDF = &typePreservingSingleParamNumericFunc{
	floatFun: math.Ceil,
}

// degreesFunc converts radians to degrees.
//
// It can be used in BQL as `degrees`.
//
//  Input: Int or Float
//  Return Type: Float
var degreesFunc udf.UDF = &floatValuedSingleParamNumericFunc{
	floatFun: func(f float64) float64 {
		return f / math.Pi * 180
	},
}

// TODO DivFunc

// expFunc computes the exponential of a number.
// See also: math.Exp.
//
// It can be used in BQL as `exp`.
//
//  Input: Int or Float
//  Return Type: Float
var expFunc udf.UDF = &floatValuedSingleParamNumericFunc{
	floatFun: math.Exp,
}

// floorFunc computes the largest integer not greater than its argument.
// See also: math.Floor.
//
// It can be used in BQL as `floor`.
//
//  Input: Int or Float
//  Return Type: same as input
var floorFunc udf.UDF = &typePreservingSingleParamNumericFunc{
	floatFun: math.Floor,
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/binary"
	"fmt"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
	"io/ioutil"
	"os"
	"unsafe"

	"github.com/lunixbochs/usercorn/go/cmd"
)

/*
#include <stdlib.h>
#include <sys/shm.h>

void *afl_setup() {
	char *id = getenv("__AFL_SHM_ID");
	if (id == NULL) {
		return NULL;
	}
	void *afl_area = shmat(atoi(id), NULL, 0);
	if (afl_area == (void *)-1) {
		return NULL;
	}
	return afl_area;
}

*/
import "C"

var MAP_SIZE uint64 = 1 << 16
var FORKSRV_FD = 198
var aflHello = []byte{1, 2, 3, 4}

func main() {
	message := []byte("In fuzz main")
	ioutil.WriteFile("/tmp/outfile", message, 0444)

	forksrvCtrl := os.NewFile(uintptr(FORKSRV_FD), "afl_ctrl")
	forksrvStatus := os.NewFile(uintptr(FORKSRV_FD+1), "afl_status")

	c := cmd.NewUsercornCmd()
	var forkAddr *uint64
	var fuzzInterp *bool

	aflArea := C.afl_setup()
	if aflArea == nil {
		panic("could not set up AFL shared memory")
	}
	fuzzMap := []byte((*[1 << 30]byte)(unsafe.Pointer(aflArea))[:])

	// Set one bit to true to go through successful count_bytes
	fuzzMap[1] = 1

	var lastPos uint64
	blockTrace := func(_ uc.Unicorn, addr uint64, size uint32) {
		if lastPos == 0 {
			lastPos = addr >> 1
			return
		}
		loc := (addr >> 4) ^ (addr << 8)
		loc &= MAP_SIZE - 1
		fuzzMap[loc]++
		lastPos = addr >> 1
	}
	c.SetupFlags = func() error {
		forkAddr = c.Flags.Uint64("forkaddr", 0, "wait until this address to fork and begin fuzzing")
		fuzzInterp = c.Flags.Bool("fuzzinterp", false, "controls whether fuzzing is delayed until program's main entry point")
		return nil
	}
	c.SetupUsercorn = func() error {
		if _, err := c.Usercorn.HookAdd(uc.HOOK_BLOCK, blockTrace, 1, 0); err != nil {
			return err
		}
		return nil
	}
	c.RunUsercorn = func(args, env []string) error {
		fmt.Println("In RunUsercorn\n")
		if _, err := forksrvStatus.Write(aflHello); err != nil {
			fmt.Println("Write hello handshake failed")
			return err
		}
		var aflMsg [4]byte
		// afl forkserver loop
		for {
			if _, err := forksrvCtrl.Read(aflMsg[:]); err != nil {
				return err
			}
			// TODO: spawn a fake child so AFL has something other than us to kill
			// monitor it and if afl kills it, stop the current emulation

			args := []string{"/bin/cat"}
			var procAttr os.ProcAttr
			proc, err := os.StartProcess(args[0], args, &procAttr)
			if err != nil {
				return err
			}

			binary.LittleEndian.PutUint32(aflMsg[:], uint32(proc.Pid))
			if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
				return err
			}

			// Goroutine to stop usercorn if afl-fuzz kills our fake process
			go func() {
				defer c.Usercorn.Stop()

				_, err := proc.Wait()
				if err != nil {
					return
				}

				// TODO: Replace this with correct waitpid status
				binary.LittleEndian.PutUint32(aflMsg[:], uint32(0))
				if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
					return
				}
			}()

			// TODO: mixed endian?
			//binary.LittleEndian.PutUint32(aflMsg[:], uint32(os.Getpid()))
			//if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
			//return err
			//}

			//err := c.Usercorn.Run(args, env)

			c.Usercorn.Run(args, env)
			//if err != nil {
			//status = 257
			//}
			// binary.LittleEndian.PutUint32(aflMsg[:], uint32(status))

		}
	}

	c.Run(os.Args, os.Environ())
}
<commit_msg>tweak afl integration<commit_after>package main

import (
	"encoding/binary"
	"fmt"
	uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
	"io/ioutil"
	"os"
	"unsafe"

	"github.com/lunixbochs/usercorn/go/cmd"
)

/*
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>

void *afl_setup() {
	char *id = getenv("__AFL_SHM_ID");
	if (id == NULL) {
		return NULL;
	}
	void *afl_area = shmat(atoi(id), NULL, 0);
	if (afl_area == (void *)-1) {
		return NULL;
	}
	memset(afl_area, 1, 1 << 16);
	return afl_area;
}

*/
import "C"

var MAP_SIZE uint64 = 1 << 16
var FORKSRV_FD = 198
var aflHello = []byte{1, 2, 3, 4}

func main() {
	message := []byte("In fuzz main")
	ioutil.WriteFile("/tmp/outfile", message, 0444)

	forksrvCtrl := os.NewFile(uintptr(FORKSRV_FD), "afl_ctrl")
	forksrvStatus := os.NewFile(uintptr(FORKSRV_FD+1), "afl_status")

	c := cmd.NewUsercornCmd()
	var forkAddr *uint64
	var fuzzInterp *bool

	aflArea := C.afl_setup()
	if aflArea == nil {
		panic("could not set up AFL shared memory")
	}
	fuzzMap := []byte((*[1 << 30]byte)(unsafe.Pointer(aflArea))[:])

	// Set one bit to true to go through successful count_bytes
	fuzzMap[1] = 1

	var lastPos uint64
	blockTrace := func(_ uc.Unicorn, addr uint64, size uint32) {
		if lastPos == 0 {
			lastPos = addr >> 1
			return
		}
		loc := (addr >> 4) ^ (addr << 8)
		loc &= MAP_SIZE - 1
		fuzzMap[loc]++
		lastPos = addr >> 1
	}
	c.SetupFlags = func() error {
		forkAddr = c.Flags.Uint64("forkaddr", 0, "wait until this address to fork and begin fuzzing")
		fuzzInterp = c.Flags.Bool("fuzzinterp", false, "controls whether fuzzing is delayed until program's main entry point")
		return nil
	}
	c.SetupUsercorn = func() error {
		if _, err := c.Usercorn.HookAdd(uc.HOOK_BLOCK, blockTrace, 1, 0); err != nil {
			return err
		}
		return nil
	}
	c.RunUsercorn = func(args, env []string) error {
		fmt.Println("In RunUsercorn\n")
		if _, err := forksrvStatus.Write(aflHello); err != nil {
			fmt.Println("Write hello handshake failed")
			return err
		}
		var aflMsg [4]byte
		// afl forkserver loop
		for {
			if _, err := forksrvCtrl.Read(aflMsg[:]); err != nil {
				return err
			}
			// spawn a fake child so AFL has something other than us to kill
			// monitor it and if afl kills it, stop the current emulation
			args := []string{"/bin/cat"}
			var procAttr os.ProcAttr
			proc, err := os.StartProcess(args[0], args, &procAttr)
			if err != nil {
				return err
			}

			binary.LittleEndian.PutUint32(aflMsg[:], uint32(proc.Pid))
			if _, err := forksrvStatus.Write(aflMsg[:]); err != nil {
				return err
			}

			// Goroutine to stop usercorn if afl-fuzz kills our fake process
			go func() {
				proc.Wait()
				c.Usercorn.Stop()
			}()

			status := 0
			err = c.Usercorn.Run(args, env)
			if err != nil {
				status = 257
			}
			binary.LittleEndian.PutUint32(aflMsg[:], uint32(status))

			proc.Kill()
			proc.Wait()
		}
	}

	c.Run(os.Args, os.Environ())
}
<|endoftext|>


<commit_before>package engine

import (
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
	"golang.org/x/crypto/nacl/box"
)

func getMySecretKey(
	g *libkb.GlobalContext, secretUI libkb.SecretUI,
	secretKeyType libkb.SecretKeyType, reason string) (
	libkb.GenericKey, error) {
	me, err := libkb.LoadMe(libkb.NewLoadUserArg(g))
	if err != nil {
		return nil, err
	}

	return g.Keyrings.GetSecretKeyWithPrompt(nil,
		libkb.SecretKeyArg{
			Me:      me,
			KeyType: secretKeyType,
		}, secretUI, reason)
}

// SignED25519 signs the given message with the current user's private
// signing key.
func SignED25519(g *libkb.GlobalContext, secretUI libkb.SecretUI,
	arg keybase1.SignED25519Arg) (
	ret keybase1.ED25519SignatureInfo, err error) {
	signingKey, err := getMySecretKey(
		g, secretUI, libkb.DeviceSigningKeyType, arg.Reason)
	if err != nil {
		return
	}

	kp, ok := signingKey.(libkb.NaclSigningKeyPair)
	if !ok || kp.Private == nil {
		err = libkb.KeyCannotSignError{}
		return
	}

	sig := *kp.Private.Sign(arg.Msg)
	publicKey := kp.Public
	ret = keybase1.ED25519SignatureInfo{
		Sig:       keybase1.ED25519Signature(sig),
		PublicKey: keybase1.ED25519PublicKey(publicKey),
	}
	return
}

// UnboxBytes32 decrypts the given message with the current user's
// private encryption key and the given nonce and peer public key.
func UnboxBytes32(g *libkb.GlobalContext, secretUI libkb.SecretUI,
	arg keybase1.UnboxBytes32Arg) (bytes32 keybase1.Bytes32, err error) {
	encryptionKey, err := getMySecretKey(
		g, secretUI, libkb.DeviceEncryptionKeyType, arg.Reason)
	if err != nil {
		return
	}

	kp, ok := encryptionKey.(libkb.NaclDHKeyPair)
	if !ok || kp.Private == nil {
		err = libkb.KeyCannotDecryptError{}
		return
	}

	decryptedData, ok := box.Open(nil, arg.EncryptedBytes32[:],
		(*[24]byte)(&arg.Nonce), (*[32]byte)(&arg.PeersPublicKey),
		(*[32]byte)(kp.Private))
	if !ok {
		err = libkb.DecryptionError{}
		return
	}

	if len(decryptedData) != len(bytes32) {
		err = libkb.DecryptionError{}
		return
	}

	copy(bytes32[:], decryptedData)
	return
}
<commit_msg>Get cached secret keys earlier<commit_after>package engine

import (
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
	"golang.org/x/crypto/nacl/box"
)

func getMySecretKey(
	g *libkb.GlobalContext, secretUI libkb.SecretUI,
	secretKeyType libkb.SecretKeyType, reason string) (
	libkb.GenericKey, error) {

	var key libkb.GenericKey
	var err error
	aerr := g.LoginState().Account(func(a *libkb.Account) {
		key, err = a.CachedSecretKey(libkb.SecretKeyArg{KeyType: secretKeyType})
	}, "Keyrings - cachedSecretKey")
	if key != nil && err == nil {
		return key, nil
	}
	if aerr != nil {
		g.Log.Debug("error getting account: %s", aerr)
	}

	me, err := libkb.LoadMe(libkb.NewLoadUserArg(g))
	if err != nil {
		return nil, err
	}

	return g.Keyrings.GetSecretKeyWithPrompt(nil,
		libkb.SecretKeyArg{
			Me:      me,
			KeyType: secretKeyType,
		}, secretUI, reason)
}

// SignED25519 signs the given message with the current user's private
// signing key.
func SignED25519(g *libkb.GlobalContext, secretUI libkb.SecretUI,
	arg keybase1.SignED25519Arg) (
	ret keybase1.ED25519SignatureInfo, err error) {
	signingKey, err := getMySecretKey(
		g, secretUI, libkb.DeviceSigningKeyType, arg.Reason)
	if err != nil {
		return
	}

	kp, ok := signingKey.(libkb.NaclSigningKeyPair)
	if !ok || kp.Private == nil {
		err = libkb.KeyCannotSignError{}
		return
	}

	sig := *kp.Private.Sign(arg.Msg)
	publicKey := kp.Public
	ret = keybase1.ED25519SignatureInfo{
		Sig:       keybase1.ED25519Signature(sig),
		PublicKey: keybase1.ED25519PublicKey(publicKey),
	}
	return
}

// UnboxBytes32 decrypts the given message with the current user's
// private encryption key and the given nonce and peer public key.
func UnboxBytes32(g *libkb.GlobalContext, secretUI libkb.SecretUI,
	arg keybase1.UnboxBytes32Arg) (bytes32 keybase1.Bytes32, err error) {
	encryptionKey, err := getMySecretKey(
		g, secretUI, libkb.DeviceEncryptionKeyType, arg.Reason)
	if err != nil {
		return
	}

	kp, ok := encryptionKey.(libkb.NaclDHKeyPair)
	if !ok || kp.Private == nil {
		err = libkb.KeyCannotDecryptError{}
		return
	}

	decryptedData, ok := box.Open(nil, arg.EncryptedBytes32[:],
		(*[24]byte)(&arg.Nonce), (*[32]byte)(&arg.PeersPublicKey),
		(*[32]byte)(kp.Private))
	if !ok {
		err = libkb.DecryptionError{}
		return
	}

	if len(decryptedData) != len(bytes32) {
		err = libkb.DecryptionError{}
		return
	}

	copy(bytes32[:], decryptedData)
	return
}
<|endoftext|>