<commit_before>// Except.go: Contains functions to make handling panics less PITA

package helpers

import (
	"fmt"
	"reflect"
	"runtime"
	"strconv"
	"time"

	"math/rand"

	"strings"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/bwmarrin/discordgo"
	"github.com/davecgh/go-spew/spew"
	"github.com/getsentry/raven-go"
	"github.com/olivere/elastic"
)

// RecoverDiscord recover()s and sends a message to discord
func RecoverDiscord(msg *discordgo.Message) {
	err := recover()
	if err != nil {
		if strings.Contains(fmt.Sprintf("%+#v", err), "handled discord error") {
			return
		}

		fmt.Printf("RecoverDiscord: %s\n", spew.Sdump(err))

		SendError(msg, err)
	}
}

// Recover recover()s and prints the error to console
func Recover() {
	err := recover()
	if err != nil {
		if strings.Contains(fmt.Sprintf("%+#v", err), "handled discord error") {
			return
		}

		fmt.Printf("Recover: %s\n", spew.Sdump(err))
		buf := make([]byte, 1<<16)
		stackSize := runtime.Stack(buf, false)

		fmt.Println(string(buf[0:stackSize]))

		if errD, ok := err.(*discordgo.RESTError); ok && errD != nil {
			if strings.Contains(errD.Message.Message, "500: Internal Server Error") {
				cache.GetLogger().WithField("module", "except").Error("discord internal error: " + fmt.Sprintf("%+#v", err))
				return
			}
		}

		raven.SetUserContext(&raven.User{})
		if errE, ok := err.(*elastic.Error); ok {
			raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{
				"Type":     errE.Details.Type,
				"Reason":   errE.Details.Reason,
				"Index":    errE.Details.Index,
				"CausedBy": spew.Sdump(errE.Details.CausedBy),
			})
		} else {
			raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{})
		}
	}
}

// SoftRelax is a softer form of Relax()
// Calls a callback instead of panicking
func SoftRelax(err error, cb Callback) {
	if err != nil {
		cb()
	}
}

// Relax is a helper to reduce if-checks if panicking is allowed
// If $err is nil this is a no-op. Panics otherwise.
func Relax(err error) {
	if err != nil {
		if DEBUG_MODE == true {
			spew.Dump(err)

			buf := make([]byte, 1<<16)
			stackSize := runtime.Stack(buf, false)

			fmt.Println(string(buf[0:stackSize]))

			if errD, ok := err.(*discordgo.RESTError); ok && errD != nil && errD.Message != nil && errD.Message.Message != "" {
				fmt.Println(strconv.Itoa(errD.Message.Code)+":", strings.Trim(errD.Message.Message, "\""))
			}

			panic(err)
		}
		panic(err)
	}
}

// RelaxEmbed does nothing if $err is nil, prints a notice if there are no permissions to embed, else sends it to Relax()
func RelaxEmbed(err error, channelID string, commandMessageID string) {
	if err != nil {
		if errD, ok := err.(*discordgo.RESTError); ok {
			if errD.Message.Code == 50013 {
				if channelID != "" {
					_, err = SendMessage(channelID, GetText("bot.errors.no-embed")) // TODO: check if embed or attach permission required
					RelaxMessage(err, channelID, commandMessageID)
				}
				panic("handled discord error")
				return
			}
		}
		Relax(err)
	}
}

// RelaxEmbed does nothing if $err is nil or if there are no permissions to send a message, else sends it to Relax()
func RelaxMessage(err error, channelID string, commandMessageID string) {
	if err != nil {
		if errD, ok := err.(*discordgo.RESTError); ok && errD != nil {
			if errD.Message.Code == discordgo.ErrCodeMissingPermissions {
				if channelID != "" && commandMessageID != "" {
					go AddNoPermissionsReaction(channelID, commandMessageID)
				}
				panic("handled discord error")
				return
			}
			if errD.Message.Code == discordgo.ErrCodeCannotSendMessagesToThisUser {
				if channelID != "" && commandMessageID != "" {
					go AddNoPermissionsReaction(channelID, commandMessageID)
				}
				panic("handled discord error")
				return
			} else {
				Relax(err)
			}
		} else {
			Relax(err)
		}
	}
}

func AddNoPermissionsReaction(channelID, messageID string) {
	reactions := []string{
		":blobstop:317034621953114112",
		"a:ablobweary:394026914479865856",
		":googlespeaknoevil:317036753074651139",
		":notlikeblob:349342777978519562",
		"a:ablobcry:393869333740126219",
		"a:ablobfrown:394026913292615701",
		"a:ablobunamused:393869335573037057",
	}
	// todo: global rand object in cache
	randSource := rand.NewSource(time.Now().UnixNano())
	randType := rand.New(randSource)
	cache.GetSession().MessageReactionAdd(channelID, messageID, reactions[randType.Intn(len(reactions))])
}

func RelaxLog(err error) {
	if err != nil {
		fmt.Printf("Error: %s\n", spew.Sdump(err))

		raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{})
	}
}

// RelaxAssertEqual panics if a is not b
func RelaxAssertEqual(a interface{}, b interface{}, err error) {
	if !reflect.DeepEqual(a, b) {
		Relax(err)
	}
}

// RelaxAssertUnequal panics if a is b
func RelaxAssertUnequal(a interface{}, b interface{}, err error) {
	if reflect.DeepEqual(a, b) {
		Relax(err)
	}
}

// SendError Takes an error and sends it to discord and sentry.io
func SendError(msg *discordgo.Message, err interface{}) {
	if errR, ok := err.(*discordgo.RESTError); ok && errR != nil && errR.Message != nil {
		if strings.Contains(errR.Message.Message, "500: Internal Server Error") {
			cache.GetLogger().WithField("module", "except").Error("discord internal error sending message to #" + msg.ChannelID + ": " + fmt.Sprintf("%+#v", err))
			return
		}
	}

	if DEBUG_MODE == true {
		buf := make([]byte, 1<<16)
		stackSize := runtime.Stack(buf, false)

		SendMessage(
			msg.ChannelID,
			"Error <a:ablobfrown:394026913292615701>\n```\n"+spew.Sdump(err)+fmt.Sprintf("%s\n", string(buf[0:stackSize]))+"\n```",
		)
	} else {
		if errR, ok := err.(*discordgo.RESTError); ok && errR != nil && errR.Message != nil {
			if msg != nil {
				SendMessage(
					msg.ChannelID,
					"Error <a:ablobfrown:394026913292615701>\n```\n"+fmt.Sprintf("%+#v", errR.Message.Message)+"\n```",
				)
			}
		} else {
			if msg != nil {
				SendMessage(
					msg.ChannelID,
					"Error <a:ablobfrown:394026913292615701>\n```\n"+fmt.Sprintf("%+#v", err)+"\n```",
				)
			}
		}
	}

	raven.SetUserContext(&raven.User{
		ID:       msg.ID,
		Username: msg.Author.Username + "#" + msg.Author.Discriminator,
	})

	raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{
		"ChannelID":       msg.ChannelID,
		"Content":         msg.Content,
		"Timestamp":       string(msg.Timestamp),
		"TTS":             strconv.FormatBool(msg.Tts),
		"MentionEveryone": strconv.FormatBool(msg.MentionEveryone),
		"IsBot":           strconv.FormatBool(msg.Author.Bot),
	})
}
<commit_msg>[except] improves exception handling safety 💣<commit_after>// Except.go: Contains functions to make handling panics less PITA

package helpers

import (
	"fmt"
	"reflect"
	"runtime"
	"strconv"
	"time"

	"math/rand"

	"strings"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/bwmarrin/discordgo"
	"github.com/davecgh/go-spew/spew"
	"github.com/getsentry/raven-go"
	"github.com/olivere/elastic"
)

// RecoverDiscord recover()s and sends a message to discord
func RecoverDiscord(msg *discordgo.Message) {
	err := recover()
	if err != nil {
		if strings.Contains(fmt.Sprintf("%+#v", err), "handled discord error") {
			return
		}

		fmt.Printf("RecoverDiscord: %s\n", spew.Sdump(err))

		SendError(msg, err)
	}
}

// Recover recover()s and prints the error to console
func Recover() {
	err := recover()
	if err != nil {
		if strings.Contains(fmt.Sprintf("%+#v", err), "handled discord error") {
			return
		}

		fmt.Printf("Recover: %s\n", spew.Sdump(err))
		buf := make([]byte, 1<<16)
		stackSize := runtime.Stack(buf, false)

		fmt.Println(string(buf[0:stackSize]))

		if errD, ok := err.(*discordgo.RESTError); ok && errD != nil && errD.Message != nil {
			if strings.Contains(errD.Message.Message, "500: Internal Server Error") {
				cache.GetLogger().WithField("module", "except").Error("discord internal error: " + fmt.Sprintf("%+#v", err))
				return
			}
		}

		raven.SetUserContext(&raven.User{})
		if errE, ok := err.(*elastic.Error); ok {
			raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{
				"Type":     errE.Details.Type,
				"Reason":   errE.Details.Reason,
				"Index":    errE.Details.Index,
				"CausedBy": spew.Sdump(errE.Details.CausedBy),
			})
		} else {
			raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{})
		}
	}
}

// SoftRelax is a softer form of Relax()
// Calls a callback instead of panicking
func SoftRelax(err error, cb Callback) {
	if err != nil {
		cb()
	}
}

// Relax is a helper to reduce if-checks if panicking is allowed
// If $err is nil this is a no-op. Panics otherwise.
func Relax(err error) {
	if err != nil {
		if DEBUG_MODE == true {
			spew.Dump(err)

			buf := make([]byte, 1<<16)
			stackSize := runtime.Stack(buf, false)

			fmt.Println(string(buf[0:stackSize]))

			if errD, ok := err.(*discordgo.RESTError); ok && errD != nil && errD.Message != nil && errD.Message.Message != "" {
				fmt.Println(strconv.Itoa(errD.Message.Code)+":", strings.Trim(errD.Message.Message, "\""))
			}

			panic(err)
		}
		panic(err)
	}
}

// RelaxEmbed does nothing if $err is nil, prints a notice if there are no permissions to embed, else sends it to Relax()
func RelaxEmbed(err error, channelID string, commandMessageID string) {
	if err != nil {
		if errD, ok := err.(*discordgo.RESTError); ok {
			if errD.Message.Code == 50013 {
				if channelID != "" {
					_, err = SendMessage(channelID, GetText("bot.errors.no-embed")) // TODO: check if embed or attach permission required
					RelaxMessage(err, channelID, commandMessageID)
				}
				panic("handled discord error")
				return
			}
		}
		Relax(err)
	}
}

// RelaxEmbed does nothing if $err is nil or if there are no permissions to send a message, else sends it to Relax()
func RelaxMessage(err error, channelID string, commandMessageID string) {
	if err != nil {
		if errD, ok := err.(*discordgo.RESTError); ok && errD != nil && errD.Message != nil {
			if errD.Message.Code == discordgo.ErrCodeMissingPermissions {
				if channelID != "" && commandMessageID != "" {
					go AddNoPermissionsReaction(channelID, commandMessageID)
				}
				panic("handled discord error")
				return
			}
			if errD.Message.Code == discordgo.ErrCodeCannotSendMessagesToThisUser {
				if channelID != "" && commandMessageID != "" {
					go AddNoPermissionsReaction(channelID, commandMessageID)
				}
				panic("handled discord error")
				return
			} else {
				Relax(err)
			}
		} else {
			Relax(err)
		}
	}
}

func AddNoPermissionsReaction(channelID, messageID string) {
	reactions := []string{
		":blobstop:317034621953114112",
		"a:ablobweary:394026914479865856",
		":googlespeaknoevil:317036753074651139",
		":notlikeblob:349342777978519562",
		"a:ablobcry:393869333740126219",
		"a:ablobfrown:394026913292615701",
		"a:ablobunamused:393869335573037057",
	}
	// todo: global rand object in cache
	randSource := rand.NewSource(time.Now().UnixNano())
	randType := rand.New(randSource)
	cache.GetSession().MessageReactionAdd(channelID, messageID, reactions[randType.Intn(len(reactions))])
}

func RelaxLog(err error) {
	if err != nil {
		fmt.Printf("Error: %s\n", spew.Sdump(err))

		raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{})
	}
}

// RelaxAssertEqual panics if a is not b
func RelaxAssertEqual(a interface{}, b interface{}, err error) {
	if !reflect.DeepEqual(a, b) {
		Relax(err)
	}
}

// RelaxAssertUnequal panics if a is b
func RelaxAssertUnequal(a interface{}, b interface{}, err error) {
	if reflect.DeepEqual(a, b) {
		Relax(err)
	}
}

// SendError Takes an error and sends it to discord and sentry.io
func SendError(msg *discordgo.Message, err interface{}) {
	if errR, ok := err.(*discordgo.RESTError); ok && errR != nil && errR.Message != nil {
		if strings.Contains(errR.Message.Message, "500: Internal Server Error") {
			cache.GetLogger().WithField("module", "except").Error("discord internal error sending message to #" + msg.ChannelID + ": " + fmt.Sprintf("%+#v", err))
			return
		}
	}

	if DEBUG_MODE == true {
		buf := make([]byte, 1<<16)
		stackSize := runtime.Stack(buf, false)

		SendMessage(
			msg.ChannelID,
			"Error <a:ablobfrown:394026913292615701>\n```\n"+spew.Sdump(err)+fmt.Sprintf("%s\n", string(buf[0:stackSize]))+"\n```",
		)
	} else {
		if errR, ok := err.(*discordgo.RESTError); ok && errR != nil && errR.Message != nil {
			if msg != nil {
				SendMessage(
					msg.ChannelID,
					"Error <a:ablobfrown:394026913292615701>\n```\n"+fmt.Sprintf("%+#v", errR.Message.Message)+"\n```",
				)
			}
		} else {
			if msg != nil {
				SendMessage(
					msg.ChannelID,
					"Error <a:ablobfrown:394026913292615701>\n```\n"+fmt.Sprintf("%+#v", err)+"\n```",
				)
			}
		}
	}

	raven.SetUserContext(&raven.User{
		ID:       msg.ID,
		Username: msg.Author.Username + "#" + msg.Author.Discriminator,
	})

	raven.CaptureError(fmt.Errorf(spew.Sdump(err)), map[string]string{
		"ChannelID":       msg.ChannelID,
		"Content":         msg.Content,
		"Timestamp":       string(msg.Timestamp),
		"TTS":             strconv.FormatBool(msg.Tts),
		"MentionEveryone": strconv.FormatBool(msg.MentionEveryone),
		"IsBot":           strconv.FormatBool(msg.Author.Bot),
	})
}
<|endoftext|>


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

package badger

import (
	"testing"

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

func TestBuildKeyValueSizeHistogram(t *testing.T) {
	t.Run("All same size key-values", func(t *testing.T) {
		runBadgerTest(t, nil, func(t *testing.T, db *DB) {
			entries := int64(40)
			err := db.Update(func(txn *Txn) error {
				for i := int64(0); i < entries; i++ {
					err := txn.SetEntry(NewEntry([]byte(string(i)), []byte("B")))
					if err != nil {
						return err
					}
				}
				return nil
			})
			require.NoError(t, err)

			histogram := db.buildHistogram(nil)
			keyHistogram := histogram.keySizeHistogram
			valueHistogram := histogram.valueSizeHistogram

			require.Equal(t, entries, keyHistogram.totalCount)
			require.Equal(t, entries, valueHistogram.totalCount)

			// Each entry is of size one. So the sum of sizes should be the same
			// as number of entries
			require.Equal(t, entries, valueHistogram.sum)
			require.Equal(t, entries, keyHistogram.sum)

			// All value sizes are same. The first bin should have all the values.
			require.Equal(t, entries, valueHistogram.countPerBin[0])
			require.Equal(t, entries, keyHistogram.countPerBin[0])

			require.Equal(t, int64(1), keyHistogram.max)
			require.Equal(t, int64(1), keyHistogram.min)
			require.Equal(t, int64(1), valueHistogram.max)
			require.Equal(t, int64(1), valueHistogram.min)
		})
	})

	t.Run("different size key-values", func(t *testing.T) {
		runBadgerTest(t, nil, func(t *testing.T, db *DB) {
			entries := int64(3)
			err := db.Update(func(txn *Txn) error {
				if err := txn.SetEntry(NewEntry([]byte("A"), []byte("B"))); err != nil {
					return err
				}

				if err := txn.SetEntry(NewEntry([]byte("AA"), []byte("BB"))); err != nil {
					return err
				}

				return txn.SetEntry(NewEntry([]byte("AAA"), []byte("BBB")))
			})
			require.NoError(t, err)

			histogram := db.buildHistogram(nil)
			keyHistogram := histogram.keySizeHistogram
			valueHistogram := histogram.valueSizeHistogram

			require.Equal(t, entries, keyHistogram.totalCount)
			require.Equal(t, entries, valueHistogram.totalCount)

			// Each entry is of size one. So the sum of sizes should be the same
			// as number of entries
			require.Equal(t, int64(6), valueHistogram.sum)
			require.Equal(t, int64(6), keyHistogram.sum)

			// Length 1 key is in first bucket, length 2 and 3 are in the second
			// bucket
			require.Equal(t, int64(1), valueHistogram.countPerBin[0])
			require.Equal(t, int64(2), valueHistogram.countPerBin[1])
			require.Equal(t, int64(1), keyHistogram.countPerBin[0])
			require.Equal(t, int64(2), keyHistogram.countPerBin[1])

			require.Equal(t, int64(3), keyHistogram.max)
			require.Equal(t, int64(1), keyHistogram.min)
			require.Equal(t, int64(3), valueHistogram.max)
			require.Equal(t, int64(1), valueHistogram.min)
		})
	})
}
<commit_msg>Fix build on golang tip (#1355)<commit_after>/*
 * Copyright 2019 Dgraph Labs, Inc. and Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package badger

import (
	"testing"

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

func TestBuildKeyValueSizeHistogram(t *testing.T) {
	t.Run("All same size key-values", func(t *testing.T) {
		runBadgerTest(t, nil, func(t *testing.T, db *DB) {
			entries := int64(40)
			err := db.Update(func(txn *Txn) error {
				for i := rune(0); i < rune(entries); i++ {
					err := txn.SetEntry(NewEntry([]byte(string(i)), []byte("B")))
					if err != nil {
						return err
					}
				}
				return nil
			})
			require.NoError(t, err)

			histogram := db.buildHistogram(nil)
			keyHistogram := histogram.keySizeHistogram
			valueHistogram := histogram.valueSizeHistogram

			require.Equal(t, entries, keyHistogram.totalCount)
			require.Equal(t, entries, valueHistogram.totalCount)

			// Each entry is of size one. So the sum of sizes should be the same
			// as number of entries
			require.Equal(t, entries, valueHistogram.sum)
			require.Equal(t, entries, keyHistogram.sum)

			// All value sizes are same. The first bin should have all the values.
			require.Equal(t, entries, valueHistogram.countPerBin[0])
			require.Equal(t, entries, keyHistogram.countPerBin[0])

			require.Equal(t, int64(1), keyHistogram.max)
			require.Equal(t, int64(1), keyHistogram.min)
			require.Equal(t, int64(1), valueHistogram.max)
			require.Equal(t, int64(1), valueHistogram.min)
		})
	})

	t.Run("different size key-values", func(t *testing.T) {
		runBadgerTest(t, nil, func(t *testing.T, db *DB) {
			entries := int64(3)
			err := db.Update(func(txn *Txn) error {
				if err := txn.SetEntry(NewEntry([]byte("A"), []byte("B"))); err != nil {
					return err
				}

				if err := txn.SetEntry(NewEntry([]byte("AA"), []byte("BB"))); err != nil {
					return err
				}

				return txn.SetEntry(NewEntry([]byte("AAA"), []byte("BBB")))
			})
			require.NoError(t, err)

			histogram := db.buildHistogram(nil)
			keyHistogram := histogram.keySizeHistogram
			valueHistogram := histogram.valueSizeHistogram

			require.Equal(t, entries, keyHistogram.totalCount)
			require.Equal(t, entries, valueHistogram.totalCount)

			// Each entry is of size one. So the sum of sizes should be the same
			// as number of entries
			require.Equal(t, int64(6), valueHistogram.sum)
			require.Equal(t, int64(6), keyHistogram.sum)

			// Length 1 key is in first bucket, length 2 and 3 are in the second
			// bucket
			require.Equal(t, int64(1), valueHistogram.countPerBin[0])
			require.Equal(t, int64(2), valueHistogram.countPerBin[1])
			require.Equal(t, int64(1), keyHistogram.countPerBin[0])
			require.Equal(t, int64(2), keyHistogram.countPerBin[1])

			require.Equal(t, int64(3), keyHistogram.max)
			require.Equal(t, int64(1), keyHistogram.min)
			require.Equal(t, int64(3), valueHistogram.max)
			require.Equal(t, int64(1), valueHistogram.min)
		})
	})
}
<|endoftext|>


<commit_before>// naprrqlhp.go
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/nsip/nias2/naprrql"
	"github.com/shomali11/parallelizer"
	"github.com/tidwall/gjson"
)

// simple test of worker pool to run all pipelines
func main() {

	// shutdown handler
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-c
		closeDB()
		os.Exit(1)
	}()

	startWebServer(true)
	runReports()

	// close down
	closeDB()
	os.Exit(1)

}

//
// run all report pipelines as parallel jobs
//
func runReports() {

	schools, err := getSchoolsList()
	if err != nil {
		log.Fatalln("Cannot connect to naprrql server: ", err)
	}

	schoolTemplates := getTemplates("./reporting_templates/school/")
	systemTemplates := getTemplates("./reporting_templates/system/")

	log.Println(schools)
	log.Println(len(schoolTemplates))
	log.Println(len(systemTemplates))

	group := parallelizer.NewGroup(parallelizer.WithPoolSize(1000), parallelizer.WithJobQueueSize(500))
	defer group.Close()

	// school reports
	for _, school := range schools {
		for filename, query := range schoolTemplates {
			f := filename
			q := query
			sch := school
			group.Add(func() {
				naprrql.RunSchoolReportPipeline(f, q, sch)
			})
		}
	}

	// system reports
	for filename, query := range systemTemplates {
		f := filename
		q := query
		group.Add(func() {
			naprrql.RunSystemReportPipeline(f, q, schools)
		})
	}

	// item print reports
	group.Add(func() {
		naprrql.RunItemPipeline(schools)
	})

	// writing extract reports
	group.Add(func() {
		naprrql.RunWritingExtractPipeline(schools, true)
	})

	// xml pipeline
	// system-level
	group.Add(func() {
		naprrql.RunXMLPipeline(schools)
	})
	// per school
	for _, school := range schools {
		sc := school
		group.Add(func() { naprrql.RunXMLPipelinePerSchool(sc) })
	}

	// qa reports
	group.Add(func() { naprrql.RunQAErdsReportPipeline(schools) })
	group.Add(func() { naprrql.RunQAItemRespReportPipeline(schools) })
	group.Add(func() { naprrql.RunQAMiscReportPipeline(schools) })
	group.Add(func() { naprrql.RunQAOrphanPipeline(schools) })
	group.Add(func() {
		naprrql.RunQASchoolSummaryPipeline(schools, "./out/qa", "./reporting_templates/qa/qaSchools_map.csv")
	})

	err = group.Wait()

	fmt.Println()
	fmt.Println("Done")
	fmt.Printf("Error: %v\n\n", err)
}

//
// connect to the server & retrieve list of known acara-ids for schools
//
func getSchoolsList() ([]string, error) {

	schoolsList := make([]string, 0)
	gqlc := naprrql.NewGqlClient()

	// create gql query parameters
	query := `query schoolDetails{school_details{ACARAId}}`
	variables := make(map[string]interface{})

	json, err := gqlc.DoQuery(naprrql.DEF_GQL_URL, query, variables)
	if err != nil {
		return schoolsList, err
	}
	acaraids := json.Get("#.ACARAId")
	acaraids.ForEach(func(key, value gjson.Result) bool {
		schoolsList = append(schoolsList, value.String())
		return true // keep iterating
	})

	return schoolsList, nil

}

//
// ensure clean shutdown of data store
//
func closeDB() {
	log.Println("Closing datastore...")
	naprrql.GetDB().Close()
	log.Println("Datastore closed.")
}

//
// launch the webserver
//
func startWebServer(silent bool) {
	go naprrql.RunQLServer()
	if !silent {
		fmt.Printf("\n\nBrowse to following locations:\n\n")
		fmt.Printf("\n\tFor qa reporting user interface:\n\n\t\thttp://localhost:1329/ui\n")
		fmt.Printf("\n\tFor data query explorer:\n\n\t\thttp://localhost:1329/sifql\n")
		fmt.Printf("\n\tFor data model viewer:\n\n\t\thttp://localhost:1329/datamodel\n\n ")
	}

}

//
//
// retrieves templates for reporting queries
// in effect these are just the graphQL queries saved to files
//
func getTemplates(templatesPath string) map[string]string {

	files := make([]string, 0)
	templates := make(map[string]string)

	// get the list of query templates
	gqlFiles, err := filepath.Glob(templatesPath + "*.gql")
	if err != nil {
		log.Fatalln("Unable to read system report template files: ", err)
	}
	files = append(files, gqlFiles...)
	if len(files) == 0 {
		log.Fatalln("No template (*.gql) files found in input folder " + templatesPath)
	}

	// store template against filename
	for _, file := range files {
		query, err := ioutil.ReadFile(file)
		if err != nil {
			log.Fatalln("Unable to load template query from file: ", err)
		}
		templates[file] = string(query)
	}

	return templates

}
<commit_msg>Remove extra param might cause conflict later<commit_after>// naprrqlhp.go
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/nsip/nias2/naprrql"
	"github.com/shomali11/parallelizer"
	"github.com/tidwall/gjson"
)

// simple test of worker pool to run all pipelines
func main() {

	// shutdown handler
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-c
		closeDB()
		os.Exit(1)
	}()

	startWebServer(true)
	runReports()

	// close down
	closeDB()
	os.Exit(1)

}

//
// run all report pipelines as parallel jobs
//
func runReports() {

	schools, err := getSchoolsList()
	if err != nil {
		log.Fatalln("Cannot connect to naprrql server: ", err)
	}

	schoolTemplates := getTemplates("./reporting_templates/school/")
	systemTemplates := getTemplates("./reporting_templates/system/")

	log.Println(schools)
	log.Println(len(schoolTemplates))
	log.Println(len(systemTemplates))

	group := parallelizer.NewGroup(parallelizer.WithPoolSize(1000), parallelizer.WithJobQueueSize(500))
	defer group.Close()

	// school reports
	for _, school := range schools {
		for filename, query := range schoolTemplates {
			f := filename
			q := query
			sch := school
			group.Add(func() {
				naprrql.RunSchoolReportPipeline(f, q, sch)
			})
		}
	}

	// system reports
	for filename, query := range systemTemplates {
		f := filename
		q := query
		group.Add(func() {
			naprrql.RunSystemReportPipeline(f, q, schools)
		})
	}

	// item print reports
	group.Add(func() {
		naprrql.RunItemPipeline(schools)
	})

	// writing extract reports
	group.Add(func() {
		naprrql.RunWritingExtractPipeline(schools)
	})

	// xml pipeline
	// system-level
	group.Add(func() {
		naprrql.RunXMLPipeline(schools)
	})
	// per school
	for _, school := range schools {
		sc := school
		group.Add(func() { naprrql.RunXMLPipelinePerSchool(sc) })
	}

	// qa reports
	group.Add(func() { naprrql.RunQAErdsReportPipeline(schools) })
	group.Add(func() { naprrql.RunQAItemRespReportPipeline(schools) })
	group.Add(func() { naprrql.RunQAMiscReportPipeline(schools) })
	group.Add(func() { naprrql.RunQAOrphanPipeline(schools) })
	group.Add(func() {
		naprrql.RunQASchoolSummaryPipeline(schools, "./out/qa", "./reporting_templates/qa/qaSchools_map.csv")
	})

	err = group.Wait()

	fmt.Println()
	fmt.Println("Done")
	fmt.Printf("Error: %v\n\n", err)
}

//
// connect to the server & retrieve list of known acara-ids for schools
//
func getSchoolsList() ([]string, error) {

	schoolsList := make([]string, 0)
	gqlc := naprrql.NewGqlClient()

	// create gql query parameters
	query := `query schoolDetails{school_details{ACARAId}}`
	variables := make(map[string]interface{})

	json, err := gqlc.DoQuery(naprrql.DEF_GQL_URL, query, variables)
	if err != nil {
		return schoolsList, err
	}
	acaraids := json.Get("#.ACARAId")
	acaraids.ForEach(func(key, value gjson.Result) bool {
		schoolsList = append(schoolsList, value.String())
		return true // keep iterating
	})

	return schoolsList, nil

}

//
// ensure clean shutdown of data store
//
func closeDB() {
	log.Println("Closing datastore...")
	naprrql.GetDB().Close()
	log.Println("Datastore closed.")
}

//
// launch the webserver
//
func startWebServer(silent bool) {
	go naprrql.RunQLServer()
	if !silent {
		fmt.Printf("\n\nBrowse to following locations:\n\n")
		fmt.Printf("\n\tFor qa reporting user interface:\n\n\t\thttp://localhost:1329/ui\n")
		fmt.Printf("\n\tFor data query explorer:\n\n\t\thttp://localhost:1329/sifql\n")
		fmt.Printf("\n\tFor data model viewer:\n\n\t\thttp://localhost:1329/datamodel\n\n ")
	}

}

//
//
// retrieves templates for reporting queries
// in effect these are just the graphQL queries saved to files
//
func getTemplates(templatesPath string) map[string]string {

	files := make([]string, 0)
	templates := make(map[string]string)

	// get the list of query templates
	gqlFiles, err := filepath.Glob(templatesPath + "*.gql")
	if err != nil {
		log.Fatalln("Unable to read system report template files: ", err)
	}
	files = append(files, gqlFiles...)
	if len(files) == 0 {
		log.Fatalln("No template (*.gql) files found in input folder " + templatesPath)
	}

	// store template against filename
	for _, file := range files {
		query, err := ioutil.ReadFile(file)
		if err != nil {
			log.Fatalln("Unable to load template query from file: ", err)
		}
		templates[file] = string(query)
	}

	return templates

}
<|endoftext|>


<commit_before>package auth

/*
 * Implements auth middleware for cention applications.
 * Expects to be running in Gin framework
 */

import (
	wf "c3/osm/webframework"
	"c3/web/controllers"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/cention-mujibur-rahman/gobcache"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/securecookie"
)

const (
	HTTP_UNAUTHORIZE_ACCESS = 401
	HTTP_FORBIDDEN_ACCESS   = 403
	HTTP_FOUND              = 302
)

var (
	hashKey                       = securecookie.GenerateRandomKey(64)
	blockKey                      = securecookie.GenerateRandomKey(32)
	sc                            = securecookie.New(hashKey, blockKey)
	ERROR_USER_PASS_MISMATCH      = errors.New("Username or Password doesnt match!")
	ERROR_USER_PASS_EMPTY         = errors.New("Username or Password is empty!")
	ERROR_CACHE_MISSED            = errors.New("Cache missed somehow!")
	ERROR_ON_SECURECOOKIE_HASHKEY = errors.New("HashKey doesn't match with secureCookie")
	ERROR_COOKIE_NOT_FOUND        = errors.New("Cookie: cention-suiteSSID=? not found")
	ERROR_WF_USER_NULL            = errors.New("webframework user is null")
	ERROR_MEMCACHE_FAILED         = errors.New("Sessiond not running")
	HostnPort                     = "localhost:11311"
)

type AuthCookieManager struct {
	UserId        int
	LastLoginTime int64
	LoggedIn      bool
}

func checkingMemcache() bool {
	conn, err := net.Dial("tcp", "localhost:11311")
	if err != nil {
		log.Println("Sessiond Server is not running! ", err)
		return false
	}
	defer conn.Close()
	return true
}

func getCookieHashKey(ctx *gin.Context) (string, error) {
	cookie, err := ctx.Request.Cookie("cention-suiteSSID")
	if err != nil {
		log.Println("getCookieHashKey(): Cookie is empty - ", err)
		return "", err
	}
	if cookie != nil && cookie.Value == "" && cookie.Value == "guest" {
		return "", ERROR_CACHE_MISSED
	}
	return cookie.Value, nil
}

func decodeCookie(ctx *gin.Context) (string, error) {
	cookie, err := getCookieHashKey(ctx)
	if err != nil {
		return "", err
	}
	if cookie != "" && cookie != "guest" {
		return cookie, nil
	}
	return "", ERROR_COOKIE_NOT_FOUND
}

func getCurrentSession(v []byte) (int, int, bool, error) {
	sv := string(v)
	sValue := strings.Split(sv, "/")
	if len(sValue) != 3 {
		return 0, 0, false, ERROR_CACHE_MISSED
	}
	uid, err := strconv.Atoi(sValue[0])
	if err != nil {
		log.Printf("Error on Uid conversion: %v", err)
		return 0, 0, false, err
	}
	ts, err := strconv.Atoi(sValue[1])
	if err != nil {
		log.Printf("Error on timestampLastLogin conversion: %v", err)
		return 0, 0, false, err
	}
	currentlyLoggedIn, err := strconv.ParseBool(sValue[2])
	if err != nil {
		log.Printf("Error on currentlyLoggedIn conversion: %v", err)
		return 0, 0, false, err
	}
	return uid, ts, currentlyLoggedIn, nil
}

func fetchFromCache(key string) error {
	skey := "Session_" + key
	sItems, err := gobcache.GetRawFromMemcache(skey, HostnPort)
	if err != nil {
		log.Println("[GetRawFromMemcache] key `Session` is empty!")
		return err
	}
	if sItems != nil {
		uid, timestamp, currentlyLogedin, err := getCurrentSession(sItems.Value)
		if err != nil {
			return err
		}
		//Mujibur: timestamp, thinking how to use it?
		_ = timestamp
		if uid != 0 && currentlyLogedin {
			return nil
		}
	}
	return ERROR_CACHE_MISSED
}

func CheckOrCreateAuthCookie(ctx *gin.Context) error {
	ssid, err := decodeCookie(ctx)
	if err != nil {
		err := createNewAuthCookie(ctx)
		if err != nil {
			return err
		}
		return nil
	}
	user := ctx.Request.FormValue("username")
	pass := ctx.Request.FormValue("password")
	if user == "" && pass == "" {
		if checkingMemcache() {
			if err = fetchFromCache(ssid); err != nil {
				return err
			}
			return nil
		}
		return ERROR_USER_PASS_EMPTY
	} else {
		log.Println("!!-- Setting cookie informations to memcache. First time login.")
		wfUser, err := validateUser(user, pass)
		if err != nil {
			log.Println("Error on CheckOrCreateAuthCookie() - validateUser: ", err)
			return err
		}
		if wfUser != nil {
			lastLoginTime := time.Now().Unix()
			if checkingMemcache() {
				sValue := fmt.Sprintf("%v/%v/%v", wfUser.Id, lastLoginTime, true)
				if err = saveToSessiondCache(ssid, sValue); err != nil {
					return err
				}
				log.Printf("CentionAuth: User `%s` just now Logged In", wfUser.Username)
				return nil
			} else {
				return ERROR_MEMCACHE_FAILED
			}
		}
	}
	return ERROR_WF_USER_NULL
}

func saveToSessiondCache(key, value string) error {
	sKey := "Session_" + key
	if err := gobcache.SetRawToMemcache(sKey, value, HostnPort); err != nil {
		log.Println("[`SetRawToMemcache`] Error on saving:", err)
		return err
	}
	return nil
}

func validateUser(user, pass string) (*wf.User, error) {
	wu, err := wf.QueryUser_byLogin(user)
	if err != nil {
		return nil, err
	}
	if wu != nil {
		if wu.Active && wu.Password == encodePassword(pass) {
			return wu, nil
		}
	}
	return nil, ERROR_USER_PASS_MISMATCH
}
func encodePassword(p string) string {
	ep := sha256.New()
	_, err := ep.Write([]byte(p))
	if err != nil {
		log.Println("encodePassword() - Error on Sha256: ", err)
		return ""
	}
	return base64.StdEncoding.EncodeToString(ep.Sum(nil))
}
func createNewAuthCookie(ctx *gin.Context) error {
	value := map[string]interface{}{
		"cookie-set-date": time.Now().Unix(),
	}
	encoded, err := sc.Encode("cention-suiteSSID", value)
	if err != nil {
		log.Printf("createNewAuthCookie(): Error %v, creating `guest` cookie", err)
		cookie := fmt.Sprintf("cention-suiteSSID=%s; Path=/", "guest")
		ctx.Writer.Header().Add("Set-Cookie", cookie)
		return err
	}
	cookie := fmt.Sprintf("cention-suiteSSID=%s; Path=/", encoded)
	ctx.Writer.Header().Add("Set-Cookie", cookie)
	return nil
}
func CheckAuthCookie(ctx *gin.Context) (bool, error) {
	cookie, err := decodeCookie(ctx)
	if err != nil {
		return false, err
	}
	ok, err := validateByBrowserCookie(cookie)
	if err != nil {
		return false, err
	}
	if !ok {
		return false, err
	}
	return true, nil
}

func fetchFromCacheWithValue(key string) (int, int, bool, error) {
	skey := "Session_" + key
	sItems, err := gobcache.GetRawFromMemcache(skey, HostnPort)
	if err != nil {
		log.Println("[GetRawFromMemcache] key `Session` is empty!")
		return 0, 0, false, err
	}
	if sItems != nil {
		uid, timestamp, currentlyLogedin, err := getCurrentSession(sItems.Value)
		if err != nil {
			return 0, 0, false, err
		}
		if uid != 0 && currentlyLogedin {
			return uid, timestamp, currentlyLogedin, nil
		}
	}
	return 0, 0, false, ERROR_CACHE_MISSED
}

func validateByBrowserCookie(ssid string) (bool, error) {
	if checkingMemcache() {
		uid, _, currentlyLogedin, err := fetchFromCacheWithValue(ssid)
		if err != nil {
			return false, err
		}
		if err := updateTimeStampToCache(ssid, uid, currentlyLogedin); err != nil {
			log.Printf("Error on validateByBrowserCookie(): %v", err)
			return false, err
		}
		log.Printf("CentionAuth: Cookie has verified with this info: %v", uid)
		return true, nil
	}
	return false, ERROR_MEMCACHE_FAILED
}

func destroyAuthCookie(ctx *gin.Context) error {
	ssid, err := decodeCookie(ctx)
	if err != nil {
		return err
	}
	if checkingMemcache() {
		uid, _, _, err := fetchFromCacheWithValue(ssid)
		if err != nil {
			return err
		}
		if err := updateTimeStampToCache(ssid, uid, false); err != nil {
			log.Printf("Error on validateByBrowserCookie(): %v", err)
			return err
		}
		return nil
	}
	return ERROR_MEMCACHE_FAILED
}
func Logout(ctx *gin.Context) error {
	return destroyAuthCookie(ctx)
}

func fetchCookieFromRequest(r *http.Request) (string, error) {
	cookie, err := r.Cookie("cention-suiteSSID")
	if err != nil {
		return "", err
	}
	return cookie.Value, nil
}
func GetWebframeworkUserFromRequest(r *http.Request) int {
	ssid, err := fetchCookieFromRequest(r)
	if err != nil {
		log.Printf("Error on getting SSID: %v", err)
		return 0
	}
	if ssid == "" {
		return 0
	}
	if checkingMemcache() {
		uid, _, currentlyLogedin, err := fetchFromCacheWithValue(ssid)
		if err != nil {
			log.Println("Error on fetchFromCacheWithValue(): ", err)
			return 0
		}
		if !currentlyLogedin {
			return 0
		}
		//Update timestamp for every request
		if err := updateTimeStampToCache(ssid, uid, currentlyLogedin); err != nil {
			log.Printf("Error on %v", err)
			return 0
		}
		return uid
	}
	return 0
}

func updateTimeStampToCache(ssid string, uid int, loginStatus bool) error {
	lastTimeGetRequest := time.Now().Unix()
	svalue := fmt.Sprintf("%v/%v/%v", uid, lastTimeGetRequest, loginStatus)
	if err := saveToSessiondCache(ssid, svalue); err != nil {
		return err
	}
	return nil
}
func Middleware() func(*gin.Context) {
	return func(ctx *gin.Context) {
		if strings.HasPrefix(ctx.Request.RequestURI, "/debug/pprof/") {
			ctx.Next()
			return
		}
		wfUserId := GetWebframeworkUserFromRequest(ctx.Request)
		if wfUserId == 0 {
			ctx.AbortWithStatus(HTTP_UNAUTHORIZE_ACCESS)
			return
		}
		currUser := controllers.FetchUserObject(wfUserId)
		ctx.Keys = make(map[string]interface{})
		ctx.Keys["loggedInUser"] = currUser
		ctx.Next()
	}
}
<commit_msg>Auth: modified according to gobcache changes<commit_after>package auth

/*
 * Implements auth middleware for cention applications.
 * Expects to be running in Gin framework
 */

import (
	wf "c3/osm/webframework"
	"c3/web/controllers"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/cention-mujibur-rahman/gobcache"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/securecookie"
)

const (
	HTTP_UNAUTHORIZE_ACCESS = 401
	HTTP_FORBIDDEN_ACCESS   = 403
	HTTP_FOUND              = 302
)

var (
	hashKey                       = securecookie.GenerateRandomKey(64)
	blockKey                      = securecookie.GenerateRandomKey(32)
	sc                            = securecookie.New(hashKey, blockKey)
	ERROR_USER_PASS_MISMATCH      = errors.New("Username or Password doesnt match!")
	ERROR_USER_PASS_EMPTY         = errors.New("Username or Password is empty!")
	ERROR_CACHE_MISSED            = errors.New("Cache missed somehow!")
	ERROR_ON_SECURECOOKIE_HASHKEY = errors.New("HashKey doesn't match with secureCookie")
	ERROR_COOKIE_NOT_FOUND        = errors.New("Cookie: cention-suiteSSID=? not found")
	ERROR_WF_USER_NULL            = errors.New("webframework user is null")
	ERROR_MEMCACHE_FAILED         = errors.New("Sessiond not running")
)

var (
	sessiond = gobcache.NewCache("localhost:11311")
)

type AuthCookieManager struct {
	UserId        int
	LastLoginTime int64
	LoggedIn      bool
}

func checkingMemcache() bool {
	conn, err := net.Dial("tcp", "localhost:11311")
	if err != nil {
		log.Println("Sessiond Server is not running! ", err)
		return false
	}
	defer conn.Close()
	return true
}

func getCookieHashKey(ctx *gin.Context) (string, error) {
	cookie, err := ctx.Request.Cookie("cention-suiteSSID")
	if err != nil {
		log.Println("getCookieHashKey(): Cookie is empty - ", err)
		return "", err
	}
	if cookie != nil && cookie.Value == "" && cookie.Value == "guest" {
		return "", ERROR_CACHE_MISSED
	}
	return cookie.Value, nil
}

func decodeCookie(ctx *gin.Context) (string, error) {
	cookie, err := getCookieHashKey(ctx)
	if err != nil {
		return "", err
	}
	if cookie != "" && cookie != "guest" {
		return cookie, nil
	}
	return "", ERROR_COOKIE_NOT_FOUND
}

func getCurrentSession(v []byte) (int, int, bool, error) {
	sv := string(v)
	sValue := strings.Split(sv, "/")
	if len(sValue) != 3 {
		return 0, 0, false, ERROR_CACHE_MISSED
	}
	uid, err := strconv.Atoi(sValue[0])
	if err != nil {
		log.Printf("Error on Uid conversion: %v", err)
		return 0, 0, false, err
	}
	ts, err := strconv.Atoi(sValue[1])
	if err != nil {
		log.Printf("Error on timestampLastLogin conversion: %v", err)
		return 0, 0, false, err
	}
	currentlyLoggedIn, err := strconv.ParseBool(sValue[2])
	if err != nil {
		log.Printf("Error on currentlyLoggedIn conversion: %v", err)
		return 0, 0, false, err
	}
	return uid, ts, currentlyLoggedIn, nil
}

func fetchFromCache(key string) error {
	skey := "Session_" + key
	sItems, err := sessiond.GetRawFromMemcache(skey)
	if err != nil {
		log.Println("[GetRawFromMemcache] key `Session` is empty!")
		return err
	}
	if sItems != nil {
		uid, timestamp, currentlyLogedin, err := getCurrentSession(sItems.Value)
		if err != nil {
			return err
		}
		//Mujibur: timestamp, thinking how to use it?
		_ = timestamp
		if uid != 0 && currentlyLogedin {
			return nil
		}
	}
	return ERROR_CACHE_MISSED
}

func CheckOrCreateAuthCookie(ctx *gin.Context) error {
	ssid, err := decodeCookie(ctx)
	if err != nil {
		err := createNewAuthCookie(ctx)
		if err != nil {
			return err
		}
		return nil
	}
	user := ctx.Request.FormValue("username")
	pass := ctx.Request.FormValue("password")
	if user == "" && pass == "" {
		if checkingMemcache() {
			if err = fetchFromCache(ssid); err != nil {
				return err
			}
			return nil
		}
		return ERROR_USER_PASS_EMPTY
	} else {
		log.Println("!!-- Setting cookie informations to memcache. First time login.")
		wfUser, err := validateUser(user, pass)
		if err != nil {
			log.Println("Error on CheckOrCreateAuthCookie() - validateUser: ", err)
			return err
		}
		if wfUser != nil {
			lastLoginTime := time.Now().Unix()
			if checkingMemcache() {
				sValue := fmt.Sprintf("%v/%v/%v", wfUser.Id, lastLoginTime, true)
				if err = saveToSessiondCache(ssid, sValue); err != nil {
					return err
				}
				log.Printf("CentionAuth: User `%s` just now Logged In", wfUser.Username)
				return nil
			} else {
				return ERROR_MEMCACHE_FAILED
			}
		}
	}
	return ERROR_WF_USER_NULL
}

func saveToSessiondCache(key, value string) error {
	sKey := "Session_" + key
	if err := sessiond.SetRawToMemcache(sKey, value); err != nil {
		log.Println("[`SetRawToMemcache`] Error on saving:", err)
		return err
	}
	return nil
}

func validateUser(user, pass string) (*wf.User, error) {
	wu, err := wf.QueryUser_byLogin(user)
	if err != nil {
		return nil, err
	}
	if wu != nil {
		if wu.Active && wu.Password == encodePassword(pass) {
			return wu, nil
		}
	}
	return nil, ERROR_USER_PASS_MISMATCH
}
func encodePassword(p string) string {
	ep := sha256.New()
	_, err := ep.Write([]byte(p))
	if err != nil {
		log.Println("encodePassword() - Error on Sha256: ", err)
		return ""
	}
	return base64.StdEncoding.EncodeToString(ep.Sum(nil))
}
func createNewAuthCookie(ctx *gin.Context) error {
	value := map[string]interface{}{
		"cookie-set-date": time.Now().Unix(),
	}
	encoded, err := sc.Encode("cention-suiteSSID", value)
	if err != nil {
		log.Printf("createNewAuthCookie(): Error %v, creating `guest` cookie", err)
		cookie := fmt.Sprintf("cention-suiteSSID=%s; Path=/", "guest")
		ctx.Writer.Header().Add("Set-Cookie", cookie)
		return err
	}
	cookie := fmt.Sprintf("cention-suiteSSID=%s; Path=/", encoded)
	ctx.Writer.Header().Add("Set-Cookie", cookie)
	return nil
}
func CheckAuthCookie(ctx *gin.Context) (bool, error) {
	cookie, err := decodeCookie(ctx)
	if err != nil {
		return false, err
	}
	ok, err := validateByBrowserCookie(cookie)
	if err != nil {
		return false, err
	}
	if !ok {
		return false, err
	}
	return true, nil
}

func fetchFromCacheWithValue(key string) (int, int, bool, error) {
	skey := "Session_" + key
	sItems, err := sessiond.GetRawFromMemcache(skey)
	if err != nil {
		log.Println("[GetRawFromMemcache] key `Session` is empty!")
		return 0, 0, false, err
	}
	if sItems != nil {
		uid, timestamp, currentlyLogedin, err := getCurrentSession(sItems.Value)
		if err != nil {
			return 0, 0, false, err
		}
		if uid != 0 && currentlyLogedin {
			return uid, timestamp, currentlyLogedin, nil
		}
	}
	return 0, 0, false, ERROR_CACHE_MISSED
}

func validateByBrowserCookie(ssid string) (bool, error) {
	if checkingMemcache() {
		uid, _, currentlyLogedin, err := fetchFromCacheWithValue(ssid)
		if err != nil {
			return false, err
		}
		if err := updateTimeStampToCache(ssid, uid, currentlyLogedin); err != nil {
			log.Printf("Error on validateByBrowserCookie(): %v", err)
			return false, err
		}
		log.Printf("CentionAuth: Cookie has verified with this info: %v", uid)
		return true, nil
	}
	return false, ERROR_MEMCACHE_FAILED
}

func destroyAuthCookie(ctx *gin.Context) error {
	ssid, err := decodeCookie(ctx)
	if err != nil {
		return err
	}
	if checkingMemcache() {
		uid, _, _, err := fetchFromCacheWithValue(ssid)
		if err != nil {
			return err
		}
		if err := updateTimeStampToCache(ssid, uid, false); err != nil {
			log.Printf("Error on validateByBrowserCookie(): %v", err)
			return err
		}
		return nil
	}
	return ERROR_MEMCACHE_FAILED
}
func Logout(ctx *gin.Context) error {
	return destroyAuthCookie(ctx)
}

func fetchCookieFromRequest(r *http.Request) (string, error) {
	cookie, err := r.Cookie("cention-suiteSSID")
	if err != nil {
		return "", err
	}
	return cookie.Value, nil
}
func GetWebframeworkUserFromRequest(r *http.Request) int {
	ssid, err := fetchCookieFromRequest(r)
	if err != nil {
		log.Printf("Error on getting SSID: %v", err)
		return 0
	}
	if ssid == "" {
		return 0
	}
	if checkingMemcache() {
		uid, _, currentlyLogedin, err := fetchFromCacheWithValue(ssid)
		if err != nil {
			log.Println("Error on fetchFromCacheWithValue(): ", err)
			return 0
		}
		if !currentlyLogedin {
			return 0
		}
		//Update timestamp for every request
		if err := updateTimeStampToCache(ssid, uid, currentlyLogedin); err != nil {
			log.Printf("Error on %v", err)
			return 0
		}
		return uid
	}
	return 0
}

func updateTimeStampToCache(ssid string, uid int, loginStatus bool) error {
	lastTimeGetRequest := time.Now().Unix()
	svalue := fmt.Sprintf("%v/%v/%v", uid, lastTimeGetRequest, loginStatus)
	if err := saveToSessiondCache(ssid, svalue); err != nil {
		return err
	}
	return nil
}
func Middleware() func(*gin.Context) {
	return func(ctx *gin.Context) {
		if strings.HasPrefix(ctx.Request.RequestURI, "/debug/pprof/") {
			ctx.Next()
			return
		}
		wfUserId := GetWebframeworkUserFromRequest(ctx.Request)
		if wfUserId == 0 {
			ctx.AbortWithStatus(HTTP_UNAUTHORIZE_ACCESS)
			return
		}
		currUser := controllers.FetchUserObject(wfUserId)
		ctx.Keys = make(map[string]interface{})
		ctx.Keys["loggedInUser"] = currUser
		ctx.Next()
	}
}
<|endoftext|>


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

package storage

import (
	"syscall/js"
	"testing"

	"github.com/google/chrome-ssh-agent/go/jsutil"
	jut "github.com/google/chrome-ssh-agent/go/jsutil/testing"
	st "github.com/google/chrome-ssh-agent/go/storage/testing"
	"github.com/google/go-cmp/cmp"
	"github.com/norunners/vert"
)

func dataToJSON(data map[string]js.Value) map[string]string {
	json := map[string]string{}
	for k, v := range data {
		json[k] = jsutil.ToJSON(v)
	}
	return json
}

type myStruct struct {
	IntField    int    `js:"intField"`
	StringField string `js:"stringField"`
}

func TestRawSetAndGet(t *testing.T) {
	testcases := []struct {
		description string
		data        map[string]js.Value
	}{
		{
			description: "empty data",
			data:        map[string]js.Value{},
		},
		{
			description: "simple entry",
			data: map[string]js.Value{
				"key": js.ValueOf(2),
			},
		},
		{
			description: "map entry",
			data: map[string]js.Value{
				"key": vert.ValueOf(map[string]int{
					"field": 2,
				}).JSValue(),
			},
		},
		{
			description: "object entry",
			data: map[string]js.Value{
				"key": vert.ValueOf(&myStruct{
					IntField: 2,
				}).JSValue(),
			},
		},
	}

	for _, tc := range testcases {
		t.Run(tc.description, func(t *testing.T) {
			jut.DoSync(func(ctx jsutil.AsyncContext) {
				s := NewRaw(st.NewMemArea())
				if err := s.Set(ctx, tc.data); err != nil {
					t.Fatalf("Set failed: %v", err)
				}
				got, err := s.Get(ctx)
				if err != nil {
					t.Fatalf("Get failed: %v", err)
				}
				if diff := cmp.Diff(dataToJSON(got), dataToJSON(tc.data)); diff != "" {
					t.Errorf("incorrect data; -got +want: %s", diff)
				}
			})
		})
	}
}
<commit_msg>Add back myStructLess, which was required for other tests.<commit_after>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"syscall/js"
	"testing"

	"github.com/google/chrome-ssh-agent/go/jsutil"
	jut "github.com/google/chrome-ssh-agent/go/jsutil/testing"
	st "github.com/google/chrome-ssh-agent/go/storage/testing"
	"github.com/google/go-cmp/cmp"
	"github.com/norunners/vert"
)

func dataToJSON(data map[string]js.Value) map[string]string {
	json := map[string]string{}
	for k, v := range data {
		json[k] = jsutil.ToJSON(v)
	}
	return json
}

type myStruct struct {
	IntField    int    `js:"intField"`
	StringField string `js:"stringField"`
}

func myStructLess(a *myStruct, b *myStruct) bool {
	if a.IntField != b.IntField {
		return a.IntField < b.IntField
	}
	return a.StringField < b.StringField
}

func TestRawSetAndGet(t *testing.T) {
	testcases := []struct {
		description string
		data        map[string]js.Value
	}{
		{
			description: "empty data",
			data:        map[string]js.Value{},
		},
		{
			description: "simple entry",
			data: map[string]js.Value{
				"key": js.ValueOf(2),
			},
		},
		{
			description: "map entry",
			data: map[string]js.Value{
				"key": vert.ValueOf(map[string]int{
					"field": 2,
				}).JSValue(),
			},
		},
		{
			description: "object entry",
			data: map[string]js.Value{
				"key": vert.ValueOf(&myStruct{
					IntField: 2,
				}).JSValue(),
			},
		},
	}

	for _, tc := range testcases {
		t.Run(tc.description, func(t *testing.T) {
			jut.DoSync(func(ctx jsutil.AsyncContext) {
				s := NewRaw(st.NewMemArea())
				if err := s.Set(ctx, tc.data); err != nil {
					t.Fatalf("Set failed: %v", err)
				}
				got, err := s.Get(ctx)
				if err != nil {
					t.Fatalf("Get failed: %v", err)
				}
				if diff := cmp.Diff(dataToJSON(got), dataToJSON(tc.data)); diff != "" {
					t.Errorf("incorrect data; -got +want: %s", diff)
				}
			})
		})
	}
}
<|endoftext|>


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

// +build !darwin,cgo

package x509

/*
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
#cgo LDFLAGS: -framework CoreFoundation -framework Security

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>

// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
//
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
// certificates of the system. On failure, the function returns -1.
//
// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
// we've consumed its content.
int FetchPEMRoots(CFDataRef *pemRoots) {
	if (pemRoots == NULL) {
		return -1;
	}

	CFArrayRef certs = NULL;
	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
	if (err != noErr) {
		return -1;
	}

	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
	int i, ncerts = CFArrayGetCount(certs);
	for (i = 0; i < ncerts; i++) {
		CFDataRef data = NULL;
		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
		if (cert == NULL) {
			continue;
		}

		// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
		// Once we support weak imports via cgo we should prefer that, and fall back to this
		// for older systems.
		err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
		if (err != noErr) {
			continue;
		}

		if (data != NULL) {
			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
			CFRelease(data);
		}
	}

	CFRelease(certs);

	*pemRoots = combinedData;
	return 0;
}
*/
import "C"
import "unsafe"

func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
	return nil, nil
}

func initSystemRoots() {
	roots := NewCertPool()

	var data C.CFDataRef = nil
	err := C.FetchPEMRoots(&data)
	if err == -1 {
		return
	}

	defer C.CFRelease(C.CFTypeRef(data))
	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
	roots.AppendCertsFromPEM(buf)
	systemRoots = roots
}
<commit_msg>Fix build flags in x509 package for darwin<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build darwin,cgo

package x509

/*
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
#cgo LDFLAGS: -framework CoreFoundation -framework Security

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>

// FetchPEMRootsCTX509 fetches the system's list of trusted X.509 root certificates.
//
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
// certificates of the system. On failure, the function returns -1.
//
// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
// we've consumed its content.
int FetchPEMRootsCTX509(CFDataRef *pemRoots) {
	if (pemRoots == NULL) {
		return -1;
	}

	CFArrayRef certs = NULL;
	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
	if (err != noErr) {
		return -1;
	}

	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
	int i, ncerts = CFArrayGetCount(certs);
	for (i = 0; i < ncerts; i++) {
		CFDataRef data = NULL;
		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
		if (cert == NULL) {
			continue;
		}

		// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
		// Once we support weak imports via cgo we should prefer that, and fall back to this
		// for older systems.
		err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
		if (err != noErr) {
			continue;
		}

		if (data != NULL) {
			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
			CFRelease(data);
		}
	}

	CFRelease(certs);

	*pemRoots = combinedData;
	return 0;
}
*/
import "C"
import "unsafe"

func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
	return nil, nil
}

func initSystemRoots() {
	roots := NewCertPool()

	var data C.CFDataRef = nil
	err := C.FetchPEMRootsCTX509(&data)
	if err == -1 {
		return
	}

	defer C.CFRelease(C.CFTypeRef(data))
	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
	roots.AppendCertsFromPEM(buf)
	systemRoots = roots
}
<|endoftext|>


<commit_before>package vcs

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

func TestRepository_ResolveRevision(t *testing.T) {
	defer removeTmpDirs()

	hgCommands := []string{
		"touch --date=2006-01-02T15:04:05Z f",
		"hg add f",
		"hg commit -m foo --date '2006-12-06 13:18:29 UTC' --user 'a <a@a.com>'",
	}
	tests := map[string]struct {
		repo         Repository
		spec         string
		wantCommitID CommitID
	}{
		"git": {
			repo: makeLocalGitRepository(t,
				"GIT_COMMITTER_DATE=2006-01-02T15:04:05Z git commit --allow-empty -m foo --author='a <a@a.com>' --date 2006-01-02T15:04:05Z",
			),
			spec:         "master",
			wantCommitID: "c556aa409427eed1322744a02ad23066f51040fb",
		},
		"hg": {
			repo:         makeLocalHgRepository(t, false, hgCommands...),
			spec:         "tip",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
		"python hg": {
			repo:         makeLocalHgRepository(t, true, hgCommands...),
			spec:         "tip",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
	}

	for label, test := range tests {
		commitID, err := test.repo.ResolveRevision(test.spec)
		if err != nil {
			t.Errorf("%s: ResolveRevision: %s", label, err)
			continue
		}

		if commitID != test.wantCommitID {
			t.Errorf("%s: got commitID == %v, want %v", label, commitID, test.wantCommitID)
		}
	}
}

func TestRepository_ResolveTag(t *testing.T) {
	defer removeTmpDirs()

	hgCommands := []string{
		"touch --date=2006-01-02T15:04:05Z f",
		"hg add f",
		"hg commit -m foo --date '2006-12-06 13:18:29 UTC' --user 'a <a@a.com>'",
		"hg tag t",
	}
	tests := map[string]struct {
		repo         Repository
		tag          string
		wantCommitID CommitID
	}{
		"git": {
			repo: makeLocalGitRepository(t,
				"GIT_COMMITTER_DATE=2006-01-02T15:04:05Z git commit --allow-empty -m foo --author='a <a@a.com>' --date 2006-01-02T15:04:05Z",
				"git tag t",
			),
			tag:          "t",
			wantCommitID: "c556aa409427eed1322744a02ad23066f51040fb",
		},
		"hg": {
			repo:         makeLocalHgRepository(t, false, hgCommands...),
			tag:          "t",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
		"python hg": {
			repo:         makeLocalHgRepository(t, true, hgCommands...),
			tag:          "t",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
	}

	for label, test := range tests {
		commitID, err := test.repo.ResolveTag(test.tag)
		if err != nil {
			t.Errorf("%s: ResolveTag: %s", label, err)
			continue
		}

		if commitID != test.wantCommitID {
			t.Errorf("%s: got commitID == %v, want %v", label, commitID, test.wantCommitID)
		}
	}
}

func TestRepository_FileSystem(t *testing.T) {
	defer removeTmpDirs()

	// In all tests, repo should contain two commits. The first commit (whose ID
	// is in the 'first' field) has a file at dir1/file1 with the contents
	// "myfile1" and the mtime 2006-01-02T15:04:05Z. The second commit (whose ID
	// is in the 'second' field) adds a file at file2 (in the top-level
	// directory of the repository) with the contents "infile2" and the mtime
	// 2014-05-06T19:20:21Z.
	//
	// TODO(sqs): add symlinks, etc.
	hgCommands := []string{
		"mkdir dir1",
		"echo -n infile1 > dir1/file1",
		"touch --date=2006-01-02T15:04:05Z dir1 dir1/file1",
		"hg add dir1/file1",
		"hg commit -m commit1 --user 'a <a@a.com>' --date '2006-01-02 15:04:05 UTC'",
		"echo -n infile2 > file2",
		"touch --date=2014-05-06T19:20:21Z file2",
		"hg add file2",
		"hg commit -m commit2 --user 'a <a@a.com>' --date '2014-05-06 19:20:21 UTC'",
	}
	tests := map[string]struct {
		repo          Repository
		first, second CommitID
	}{
		"git": {
			repo: makeLocalGitRepository(t,
				"mkdir dir1",
				"echo -n infile1 > dir1/file1",
				"touch --date=2006-01-02T15:04:05Z dir1 dir1/file1",
				"git add dir1/file1",
				"GIT_COMMITTER_DATE=2006-01-02T15:04:05Z git commit -m commit1 --author='a <a@a.com>' --date 2006-01-02T15:04:05Z",
				"echo -n infile2 > file2",
				"touch --date=2014-05-06T19:20:21Z file2",
				"git add file2",
				"GIT_COMMITTER_DATE=2014-05-06T19:20:21Z git commit -m commit2 --author='a <a@a.com>' --date 2014-05-06T19:20:21Z",
			),
			first:  "b57e3b5de36984ead5127a27f190fd69acb37fa4",
			second: "7c374610b4e4968b182ddfe2c220d033e62f0a3a",
		},
		"hg": {
			repo:   makeLocalHgRepository(t, false, hgCommands...),
			first:  "0b3260387c55ff0834b520fd7f5d4f4a15c22827",
			second: "810c55b76823441dabb1249837e7ebceab50ce1a",
		},
		"python hg": {
			repo:   makeLocalHgRepository(t, true, hgCommands...),
			first:  "0b3260387c55ff0834b520fd7f5d4f4a15c22827",
			second: "810c55b76823441dabb1249837e7ebceab50ce1a",
		},
	}

	for label, test := range tests {
		fs1, err := test.repo.FileSystem(test.first)
		if err != nil {
			t.Errorf("%s: FileSystem: %s", label, err)
			continue
		}

		// dir1 should exist and be a dir.
		dir1Info, err := fs1.Stat("dir1")
		if err != nil {
			t.Errorf("%s: fs1.Stat(dir1): %s", label, err)
			continue
		}
		if !dir1Info.Mode().IsDir() {
			t.Errorf("%s: dir1 stat !IsDir", label)
		}
		if name := dir1Info.Name(); name != "dir1" {
			t.Errorf("%s: got dir1 name %q, want 'dir1'", label, name)
		}

		// dir1 should contain one entry: file1.
		dir1Entries, err := fs1.ReadDir("dir1")
		if err != nil {
			t.Errorf("%s: fs1.ReadDir(dir1): %s", label, err)
			continue
		}
		if len(dir1Entries) != 1 {
			t.Errorf("%s: got %d dir1 entries, want 1", label, len(dir1Entries))
			continue
		}
		if file1Info := dir1Entries[0]; file1Info.Name() != "file1" {
			t.Errorf("%s: got dir1 entry name == %q, want 'file1'", label, file1Info.Name())
		}

		// dir1/file1 should exist, contain "infile1", and be a file.
		file1, err := fs1.Open("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs1.Open(dir1/file1): %s", label, err)
			continue
		}
		file1Data, err := ioutil.ReadAll(file1)
		if err != nil {
			t.Errorf("%s: ReadAll(file1): %s", label, err)
			continue
		}
		if !bytes.Equal(file1Data, []byte("infile1")) {
			t.Errorf("%s: got file1Data == %q, want %q", label, string(file1Data), "infile1")
		}
		file1Info, err := fs1.Stat("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs1.Stat(dir1/file1): %s", label, err)
			continue
		}
		if !file1Info.Mode().IsRegular() {
			t.Errorf("%s: file1 stat !IsRegular", label)
		}
		if name := file1Info.Name(); name != "file1" {
			t.Errorf("%s: got file1 name %q, want 'file1'", label, name)
		}
		if size, wantSize := file1Info.Size(), int64(len("infile1")); size != wantSize {
			t.Errorf("%s: got file1 size %d, want %d", label, size, wantSize)
		}

		// file2 shouldn't exist in the 1st commit.
		_, err = fs1.Open("file2")
		if !os.IsNotExist(err) {
			t.Errorf("%s: fs1.Open(file2): got err %v, want os.IsNotExist (file2 should not exist in this commit)", label, err)
		}

		// file2 should exist in the 2nd commit.
		fs2, err := test.repo.FileSystem(test.second)
		if err != nil {
			t.Errorf("%s: FileSystem: %s", label, err)
		}
		_, err = fs2.Open("file2")
		if err != nil {
			t.Errorf("%s: fs2.Open(file2): %s", label, err)
			continue
		}

		// file1 should also exist in the 2nd commit.
		file1Info, err = fs2.Stat("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs2.Stat(dir1/file1): %s", label, err)
			continue
		}
		file1, err = fs2.Open("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs2.Open(dir1/file1): %s", label, err)
			continue
		}
	}
}

var (
	tmpDirs     []string
	keepTmpDirs = flag.Bool("test.keeptmp", false, "don't remove temporary dirs after use")
)

func removeTmpDirs() {
	if *keepTmpDirs {
		return
	}
	for _, dir := range tmpDirs {
		err := os.RemoveAll(dir)
		if err != nil {
			log.Fatalf("tearDown: RemoveAll(%q) failed: %s", dir, err)
		}
	}
	tmpDirs = nil
}

// makeTmpDir creates a temporary directory and returns its path. The directory
// is added to the list of directories to be removed when the currently running
// test ends (assuming the test calls removeTmpDirs() after execution).
func makeTmpDir(t testing.TB, suffix string) string {
	dir, err := ioutil.TempDir("", "go-vcs-"+suffix)
	if err != nil {
		t.Fatal(err)
	}

	if *keepTmpDirs {
		t.Logf("Using temp dir %s.", dir)
	}

	tmpDirs = append(tmpDirs, dir)
	return dir
}

func makeLocalGitRepository(t testing.TB, cmds ...string) GitRepository {
	dir := makeTmpDir(t, "git")
	cmds = append([]string{"git init"}, cmds...)
	for _, cmd := range cmds {
		c := exec.Command("sh", "-c", cmd)
		c.Dir = dir
		out, err := c.CombinedOutput()
		if err != nil {
			t.Fatalf("Command %q failed. Output was:\n\n%s", cmd, out)
		}
	}

	r, err := OpenLocalGitRepository(filepath.Join(dir, ".git"))
	if err != nil {
		t.Fatal("OpenLocalGitRepository(%q) failed: %s", dir, err)
	}
	return r
}

func makeLocalHgRepository(t testing.TB, usePython bool, cmds ...string) Repository {
	dir := makeTmpDir(t, "hg")
	cmds = append([]string{"hg init"}, cmds...)
	for _, cmd := range cmds {
		c := exec.Command("sh", "-c", cmd)
		c.Dir = dir
		out, err := c.CombinedOutput()
		if err != nil {
			t.Fatalf("Command %q failed. Output was:\n\n%s", cmd, out)
		}
	}

	if usePython {
		return &LocalPythonHgRepository{dir}
	}

	r, err := OpenLocalHgRepository(dir)
	if err != nil {
		t.Fatal("OpenLocalHgRepository(%q) failed: %s", dir, err)
	}
	return r
}

func cp(src, dst string) error {
	cmd := exec.Command("cp", "-R", "--no-dereference", "--preserve=mode,ownership,timestamps", src, dst)
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("cp %s %s failed: %s: %q", src, dst, err, out)
	}
	return nil
}
<commit_msg>rm unused cp func<commit_after>package vcs

import (
	"bytes"
	"flag"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

func TestRepository_ResolveRevision(t *testing.T) {
	defer removeTmpDirs()

	hgCommands := []string{
		"touch --date=2006-01-02T15:04:05Z f",
		"hg add f",
		"hg commit -m foo --date '2006-12-06 13:18:29 UTC' --user 'a <a@a.com>'",
	}
	tests := map[string]struct {
		repo         Repository
		spec         string
		wantCommitID CommitID
	}{
		"git": {
			repo: makeLocalGitRepository(t,
				"GIT_COMMITTER_DATE=2006-01-02T15:04:05Z git commit --allow-empty -m foo --author='a <a@a.com>' --date 2006-01-02T15:04:05Z",
			),
			spec:         "master",
			wantCommitID: "c556aa409427eed1322744a02ad23066f51040fb",
		},
		"hg": {
			repo:         makeLocalHgRepository(t, false, hgCommands...),
			spec:         "tip",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
		"python hg": {
			repo:         makeLocalHgRepository(t, true, hgCommands...),
			spec:         "tip",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
	}

	for label, test := range tests {
		commitID, err := test.repo.ResolveRevision(test.spec)
		if err != nil {
			t.Errorf("%s: ResolveRevision: %s", label, err)
			continue
		}

		if commitID != test.wantCommitID {
			t.Errorf("%s: got commitID == %v, want %v", label, commitID, test.wantCommitID)
		}
	}
}

func TestRepository_ResolveTag(t *testing.T) {
	defer removeTmpDirs()

	hgCommands := []string{
		"touch --date=2006-01-02T15:04:05Z f",
		"hg add f",
		"hg commit -m foo --date '2006-12-06 13:18:29 UTC' --user 'a <a@a.com>'",
		"hg tag t",
	}
	tests := map[string]struct {
		repo         Repository
		tag          string
		wantCommitID CommitID
	}{
		"git": {
			repo: makeLocalGitRepository(t,
				"GIT_COMMITTER_DATE=2006-01-02T15:04:05Z git commit --allow-empty -m foo --author='a <a@a.com>' --date 2006-01-02T15:04:05Z",
				"git tag t",
			),
			tag:          "t",
			wantCommitID: "c556aa409427eed1322744a02ad23066f51040fb",
		},
		"hg": {
			repo:         makeLocalHgRepository(t, false, hgCommands...),
			tag:          "t",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
		"python hg": {
			repo:         makeLocalHgRepository(t, true, hgCommands...),
			tag:          "t",
			wantCommitID: "e8e11ff1be92a7be71b9b5cdb4cc674b7dc9facf",
		},
	}

	for label, test := range tests {
		commitID, err := test.repo.ResolveTag(test.tag)
		if err != nil {
			t.Errorf("%s: ResolveTag: %s", label, err)
			continue
		}

		if commitID != test.wantCommitID {
			t.Errorf("%s: got commitID == %v, want %v", label, commitID, test.wantCommitID)
		}
	}
}

func TestRepository_FileSystem(t *testing.T) {
	defer removeTmpDirs()

	// In all tests, repo should contain two commits. The first commit (whose ID
	// is in the 'first' field) has a file at dir1/file1 with the contents
	// "myfile1" and the mtime 2006-01-02T15:04:05Z. The second commit (whose ID
	// is in the 'second' field) adds a file at file2 (in the top-level
	// directory of the repository) with the contents "infile2" and the mtime
	// 2014-05-06T19:20:21Z.
	//
	// TODO(sqs): add symlinks, etc.
	hgCommands := []string{
		"mkdir dir1",
		"echo -n infile1 > dir1/file1",
		"touch --date=2006-01-02T15:04:05Z dir1 dir1/file1",
		"hg add dir1/file1",
		"hg commit -m commit1 --user 'a <a@a.com>' --date '2006-01-02 15:04:05 UTC'",
		"echo -n infile2 > file2",
		"touch --date=2014-05-06T19:20:21Z file2",
		"hg add file2",
		"hg commit -m commit2 --user 'a <a@a.com>' --date '2014-05-06 19:20:21 UTC'",
	}
	tests := map[string]struct {
		repo          Repository
		first, second CommitID
	}{
		"git": {
			repo: makeLocalGitRepository(t,
				"mkdir dir1",
				"echo -n infile1 > dir1/file1",
				"touch --date=2006-01-02T15:04:05Z dir1 dir1/file1",
				"git add dir1/file1",
				"GIT_COMMITTER_DATE=2006-01-02T15:04:05Z git commit -m commit1 --author='a <a@a.com>' --date 2006-01-02T15:04:05Z",
				"echo -n infile2 > file2",
				"touch --date=2014-05-06T19:20:21Z file2",
				"git add file2",
				"GIT_COMMITTER_DATE=2014-05-06T19:20:21Z git commit -m commit2 --author='a <a@a.com>' --date 2014-05-06T19:20:21Z",
			),
			first:  "b57e3b5de36984ead5127a27f190fd69acb37fa4",
			second: "7c374610b4e4968b182ddfe2c220d033e62f0a3a",
		},
		"hg": {
			repo:   makeLocalHgRepository(t, false, hgCommands...),
			first:  "0b3260387c55ff0834b520fd7f5d4f4a15c22827",
			second: "810c55b76823441dabb1249837e7ebceab50ce1a",
		},
		"python hg": {
			repo:   makeLocalHgRepository(t, true, hgCommands...),
			first:  "0b3260387c55ff0834b520fd7f5d4f4a15c22827",
			second: "810c55b76823441dabb1249837e7ebceab50ce1a",
		},
	}

	for label, test := range tests {
		fs1, err := test.repo.FileSystem(test.first)
		if err != nil {
			t.Errorf("%s: FileSystem: %s", label, err)
			continue
		}

		// dir1 should exist and be a dir.
		dir1Info, err := fs1.Stat("dir1")
		if err != nil {
			t.Errorf("%s: fs1.Stat(dir1): %s", label, err)
			continue
		}
		if !dir1Info.Mode().IsDir() {
			t.Errorf("%s: dir1 stat !IsDir", label)
		}
		if name := dir1Info.Name(); name != "dir1" {
			t.Errorf("%s: got dir1 name %q, want 'dir1'", label, name)
		}

		// dir1 should contain one entry: file1.
		dir1Entries, err := fs1.ReadDir("dir1")
		if err != nil {
			t.Errorf("%s: fs1.ReadDir(dir1): %s", label, err)
			continue
		}
		if len(dir1Entries) != 1 {
			t.Errorf("%s: got %d dir1 entries, want 1", label, len(dir1Entries))
			continue
		}
		if file1Info := dir1Entries[0]; file1Info.Name() != "file1" {
			t.Errorf("%s: got dir1 entry name == %q, want 'file1'", label, file1Info.Name())
		}

		// dir1/file1 should exist, contain "infile1", and be a file.
		file1, err := fs1.Open("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs1.Open(dir1/file1): %s", label, err)
			continue
		}
		file1Data, err := ioutil.ReadAll(file1)
		if err != nil {
			t.Errorf("%s: ReadAll(file1): %s", label, err)
			continue
		}
		if !bytes.Equal(file1Data, []byte("infile1")) {
			t.Errorf("%s: got file1Data == %q, want %q", label, string(file1Data), "infile1")
		}
		file1Info, err := fs1.Stat("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs1.Stat(dir1/file1): %s", label, err)
			continue
		}
		if !file1Info.Mode().IsRegular() {
			t.Errorf("%s: file1 stat !IsRegular", label)
		}
		if name := file1Info.Name(); name != "file1" {
			t.Errorf("%s: got file1 name %q, want 'file1'", label, name)
		}
		if size, wantSize := file1Info.Size(), int64(len("infile1")); size != wantSize {
			t.Errorf("%s: got file1 size %d, want %d", label, size, wantSize)
		}

		// file2 shouldn't exist in the 1st commit.
		_, err = fs1.Open("file2")
		if !os.IsNotExist(err) {
			t.Errorf("%s: fs1.Open(file2): got err %v, want os.IsNotExist (file2 should not exist in this commit)", label, err)
		}

		// file2 should exist in the 2nd commit.
		fs2, err := test.repo.FileSystem(test.second)
		if err != nil {
			t.Errorf("%s: FileSystem: %s", label, err)
		}
		_, err = fs2.Open("file2")
		if err != nil {
			t.Errorf("%s: fs2.Open(file2): %s", label, err)
			continue
		}

		// file1 should also exist in the 2nd commit.
		file1Info, err = fs2.Stat("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs2.Stat(dir1/file1): %s", label, err)
			continue
		}
		file1, err = fs2.Open("dir1/file1")
		if err != nil {
			t.Errorf("%s: fs2.Open(dir1/file1): %s", label, err)
			continue
		}
	}
}

var (
	tmpDirs     []string
	keepTmpDirs = flag.Bool("test.keeptmp", false, "don't remove temporary dirs after use")
)

func removeTmpDirs() {
	if *keepTmpDirs {
		return
	}
	for _, dir := range tmpDirs {
		err := os.RemoveAll(dir)
		if err != nil {
			log.Fatalf("tearDown: RemoveAll(%q) failed: %s", dir, err)
		}
	}
	tmpDirs = nil
}

// makeTmpDir creates a temporary directory and returns its path. The directory
// is added to the list of directories to be removed when the currently running
// test ends (assuming the test calls removeTmpDirs() after execution).
func makeTmpDir(t testing.TB, suffix string) string {
	dir, err := ioutil.TempDir("", "go-vcs-"+suffix)
	if err != nil {
		t.Fatal(err)
	}

	if *keepTmpDirs {
		t.Logf("Using temp dir %s.", dir)
	}

	tmpDirs = append(tmpDirs, dir)
	return dir
}

func makeLocalGitRepository(t testing.TB, cmds ...string) GitRepository {
	dir := makeTmpDir(t, "git")
	cmds = append([]string{"git init"}, cmds...)
	for _, cmd := range cmds {
		c := exec.Command("sh", "-c", cmd)
		c.Dir = dir
		out, err := c.CombinedOutput()
		if err != nil {
			t.Fatalf("Command %q failed. Output was:\n\n%s", cmd, out)
		}
	}

	r, err := OpenLocalGitRepository(filepath.Join(dir, ".git"))
	if err != nil {
		t.Fatal("OpenLocalGitRepository(%q) failed: %s", dir, err)
	}
	return r
}

func makeLocalHgRepository(t testing.TB, usePython bool, cmds ...string) Repository {
	dir := makeTmpDir(t, "hg")
	cmds = append([]string{"hg init"}, cmds...)
	for _, cmd := range cmds {
		c := exec.Command("sh", "-c", cmd)
		c.Dir = dir
		out, err := c.CombinedOutput()
		if err != nil {
			t.Fatalf("Command %q failed. Output was:\n\n%s", cmd, out)
		}
	}

	if usePython {
		return &LocalPythonHgRepository{dir}
	}

	r, err := OpenLocalHgRepository(dir)
	if err != nil {
		t.Fatal("OpenLocalHgRepository(%q) failed: %s", dir, err)
	}
	return r
}
<|endoftext|>


<commit_before>package handle

import (
	"fmt"

	"github.com/kataras/iris"

	"jiacrontab/libs/rpc"
	"jiacrontab/server/conf"

	"jiacrontab/libs/proto"
	"jiacrontab/model"
	"net/http"
	"strconv"
)

func ListDaemonTask(ctx iris.Context) {

	page := ctx.FormValueDefault("page", "1")
	pagesize := ctx.FormValueDefault("pagesize", "200")
	addr := ctx.FormValue("addr")

	if ctx.Request().Method == http.MethodPost {
		if addr == "" {
			ctx.JSON(map[string]interface{}{
				"code": -1,
				"msg":  "addr地址不能为空",
			})
			return
		}

		pageInt, err1 := strconv.Atoi(page)
		pagesizeInt, err2 := strconv.Atoi(pagesize)

		if err1 != nil || err2 != nil {
			ctx.JSON(map[string]interface{}{
				"code": -1,
				"msg":  "分页参数错误",
			})
			return
		}

		var daemonTaskList []model.DaemonTask

		err := rpc.Call(addr, "DaemonTask.ListDaemonTask", struct{ Page, Pagesize int }{
			Page:     pageInt,
			Pagesize: pagesizeInt,
		}, &daemonTaskList)

		if err != nil {

			ctx.JSON(map[string]interface{}{
				"code": -1,
				"msg":  err.Error(),
			})
			return

		}
		ctx.JSON(map[string]interface{}{
			"code": 0,
			"data": daemonTaskList,
		})
		return
	}

	ctx.View("daemon/list.html")
}

func EditDaemonTask(ctx iris.Context) {

	addr := ctx.FormValue("addr")
	taskId := ctx.FormValue("taskId")

	ctx.ViewData("allowCommands", conf.ConfigArgs.AllowCommands)

	if ctx.Request().Method == http.MethodPost {

		name := ctx.PostValueTrim("name")
		mailNotify, err := ctx.PostValueBool("mailNotify")
		mailTo := ctx.PostValueTrim("mailTo")
		command := ctx.PostValue("command")
		args := ctx.PostValue("args")

		if addr == "" || name == "" || command == "" {
			ctx.ViewData("errorMsg", "参数不正确")
			ctx.ViewData("formValues", ctx.FormValues())
			ctx.View("daemon/edit.html")
			return
		}

		remoteArgs := model.DaemonTask{
			Name:       name,
			MailNofity: mailNotify,
			MailTo:     mailTo,
			Command:    command,
			Args:       args,
		}
		var reply int
		err = rpc.Call(addr, "DaemonTask.CreateDaemonTask", remoteArgs, &reply)
		fmt.Println(reply)
		if err != nil {
			ctx.ViewData("formValues", ctx.FormValues())
			ctx.ViewData("errorMsg", err)
			ctx.View("daemon/edit.html")
			return
		}

		ctx.Redirect("/daemon/task/list?addr=" + addr)
	}

	if taskId != "" {

		taskIdInt, err := strconv.Atoi(taskId)
		if err != nil {
			ctx.ViewData("errorMsg", "参数不正确")
			ctx.View("daemon/edit.html")
			return
		}
		var daemonTask model.DaemonTask
		err = rpc.Call(addr, "DaemonTask.GetDaemonTask", taskIdInt, &daemonTask)
		if err != nil {
			ctx.ViewData("errorMsg", "查询不到任务")
			ctx.View("daemon/edit.html")
			return
		}

		ctx.ViewData("daemonTask", daemonTask)
		ctx.ViewData("errorMsg", "参数不正确")
		ctx.View("daemon/edit.html")
		return

	}

	ctx.View("daemon/edit.html")
}

func ActionDaemonTask(ctx iris.Context) {
	var replay bool
	action := ctx.FormValue("action")
	addr := ctx.FormValue("addr")
	taskId, err := strconv.Atoi(ctx.FormValue("taskId"))
	if err != nil {
		ctx.View("public/error.html", map[string]interface{}{
			"error": "invalid taskId",
		})
		return
	}
	var op int
	switch action {
	case "start":
		op = proto.StartDaemonTask
	case "stop":
		op = proto.StopDaemonTask
	case "delete":
		op = proto.StopDaemonTask
	default:
		ctx.View("public/error.html", map[string]interface{}{
			"error": "invalid action",
		})
		return
	}

	err = rpc.Call(addr, "DaemonTask.ActionDaemonTask", proto.ActionDaemonTaskArgs{
		Action: op,
		TaskId: taskId,
	}, &replay)
	if err != nil {
		ctx.View("public/error.html", map[string]interface{}{
			"error": err,
		})
		return
	}

	ctx.Redirect("/daemon/task/list?addr=" + addr)
}
<commit_msg>update<commit_after>package handle

import (
	"fmt"
	"sort"

	"github.com/kataras/iris"

	"jiacrontab/libs/rpc"
	"jiacrontab/server/conf"

	"jiacrontab/libs/proto"
	"jiacrontab/model"
	storeModel "jiacrontab/server/model"
	"net/http"
	"strconv"
)

func ListDaemonTask(ctx iris.Context) {

	page := ctx.FormValueDefault("page", "1")
	pagesize := ctx.FormValueDefault("pagesize", "200")
	addr := ctx.FormValue("addr")

	sortedClientList := make([]proto.ClientConf, 0)

	var m = storeModel.NewModel()
	clientList, _ := m.GetRPCClientList()

	if clientList != nil && len(clientList) > 0 {
		for _, v := range clientList {
			sortedClientList = append(sortedClientList, v)
		}
		sort.SliceStable(sortedClientList, func(i, j int) bool {
			return sortedClientList[i].Addr > sortedClientList[j].Addr
		})
	}

	if ctx.Request().Method == http.MethodPost {
		if addr == "" {
			ctx.JSON(map[string]interface{}{
				"code": -1,
				"msg":  "addr地址不能为空",
			})
			return
		}

		pageInt, err1 := strconv.Atoi(page)
		pagesizeInt, err2 := strconv.Atoi(pagesize)

		if err1 != nil || err2 != nil {
			ctx.JSON(map[string]interface{}{
				"code": -1,
				"msg":  "分页参数错误",
			})
			return
		}

		var daemonTaskList []model.DaemonTask

		err := rpc.Call(addr, "DaemonTask.ListDaemonTask", struct{ Page, Pagesize int }{
			Page:     pageInt,
			Pagesize: pagesizeInt,
		}, &daemonTaskList)

		if err != nil {

			ctx.JSON(map[string]interface{}{
				"code": -1,
				"msg":  err.Error(),
			})
			return

		}
		ctx.JSON(map[string]interface{}{
			"code": 0,
			"data": daemonTaskList,
		})
		return
	}

	ctx.ViewData("addrs", sortedClientList)
	ctx.View("daemon/list.html")
}

func EditDaemonTask(ctx iris.Context) {

	addr := ctx.FormValue("addr")
	taskId := ctx.FormValue("taskId")

	ctx.ViewData("allowCommands", conf.ConfigArgs.AllowCommands)

	if ctx.Request().Method == http.MethodPost {

		name := ctx.PostValueTrim("name")
		mailNotify, err := ctx.PostValueBool("mailNotify")
		mailTo := ctx.PostValueTrim("mailTo")
		command := ctx.PostValue("command")
		args := ctx.PostValue("args")

		if addr == "" || name == "" || command == "" {
			ctx.ViewData("errorMsg", "参数不正确")
			ctx.ViewData("formValues", ctx.FormValues())
			ctx.View("daemon/edit.html")
			return
		}

		remoteArgs := model.DaemonTask{
			Name:       name,
			MailNofity: mailNotify,
			MailTo:     mailTo,
			Command:    command,
			Args:       args,
		}
		var reply int
		err = rpc.Call(addr, "DaemonTask.CreateDaemonTask", remoteArgs, &reply)
		fmt.Println(reply)
		if err != nil {
			ctx.ViewData("formValues", ctx.FormValues())
			ctx.ViewData("errorMsg", err)
			ctx.View("daemon/edit.html")
			return
		}

		ctx.Redirect("/daemon/task/list?addr=" + addr)
	}

	if taskId != "" {

		taskIdInt, err := strconv.Atoi(taskId)
		if err != nil {
			ctx.ViewData("errorMsg", "参数不正确")
			ctx.View("daemon/edit.html")
			return
		}
		var daemonTask model.DaemonTask
		err = rpc.Call(addr, "DaemonTask.GetDaemonTask", taskIdInt, &daemonTask)
		if err != nil {
			ctx.ViewData("errorMsg", "查询不到任务")
			ctx.View("daemon/edit.html")
			return
		}

		ctx.ViewData("daemonTask", daemonTask)
		ctx.ViewData("errorMsg", "参数不正确")
		ctx.View("daemon/edit.html")
		return

	}

	ctx.View("daemon/edit.html")
}

func ActionDaemonTask(ctx iris.Context) {
	var replay bool
	action := ctx.FormValue("action")
	addr := ctx.FormValue("addr")
	taskId, err := strconv.Atoi(ctx.FormValue("taskId"))
	if err != nil {
		ctx.View("public/error.html", map[string]interface{}{
			"error": "invalid taskId",
		})
		return
	}
	var op int
	switch action {
	case "start":
		op = proto.StartDaemonTask
	case "stop":
		op = proto.StopDaemonTask
	case "delete":
		op = proto.StopDaemonTask
	default:
		ctx.View("public/error.html", map[string]interface{}{
			"error": "invalid action",
		})
		return
	}

	err = rpc.Call(addr, "DaemonTask.ActionDaemonTask", proto.ActionDaemonTaskArgs{
		Action: op,
		TaskId: taskId,
	}, &replay)
	if err != nil {
		ctx.View("public/error.html", map[string]interface{}{
			"error": err,
		})
		return
	}

	ctx.Redirect("/daemon/task/list?addr=" + addr)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/Ronny95/goseq"
	"log"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var _region = flag.String("region", "USW", "Region code to get results for. \n"+
	"One of USE, USW, SA, EU, AS, AU, ME, AF, OTHER.")

var _asyncOkay = flag.Bool("async", true, "Allow async sub-querying of Source Servers to get info. \n"+
	"Extreme increase of performance with this enabled.")

var _printFields = flag.String("fields", "ip=21,name", "The fields to be included. Optionally includes the min-length space."+
	"See -showfields")

var _fieldDivider = flag.String("divider", " ¦ ", "Characters used to seperate fields.")

var _startIp = flag.String("start", goseq.NoAddress, "Where to start reading IPs from. Defaults to start.")

var _showHeader = flag.Bool("header", true, "Show header w/ column names.")

var _fieldregexp = regexp.MustCompile(`\s*(([a-z]+)(=(\d+))?)\s*,?\s*`)

type FieldSpec struct {
	name   string
	length int
}

type SvResponse struct {
	err    error
	server goseq.Server
	info   goseq.ServerInfo
}

func masterctx() {

	userRegionStr := strings.ToUpper(*_region)

	region, found := regionData[userRegionStr]

	if !found {
		fmt.Errorf("Region '%s' does not exist.", *_region)
		return
	}

	fields, err := parseFields(*_printFields, serverFieldProperties)

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

	master := goseq.NewMasterServer()
	master.SetRegion(region)
	master.SetAddr(goseq.MasterSourceServers[0])

	servers, err := master.Query(*_startIp)
	numServers := len(servers)

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

	rec := make(chan SvResponse)
	printer := make(chan SvResponse)

	//tups := make([]SvResponse, 0, numServers)

	if *_asyncOkay {
		go AsyncQueryServers(rec, servers, 1*time.Second)
	} else {
		go serialQueryServers(rec, servers, 1*time.Second)
	}

	go printServerLine(fields, printer)

	if *_showHeader {
		printHeaderLine(fields, serverFieldProperties)
	}

	for i := 0; i < numServers; i++ {
		//tups = append(tups, <-rec)
		printer <- <-rec
	}

	close(rec)
	close(printer)
}

func serialQueryServers(send chan SvResponse, servers []goseq.Server, timeout time.Duration) {
	for _, server := range servers {
		info, err := server.Info(timeout)
		if err != nil {
			send <- SvResponse{err: err, server: server}
		}
		send <- SvResponse{err: err, server: server, info: info}
	}
}

func AsyncQueryServers(send chan SvResponse, servers []goseq.Server, timeout time.Duration) {
	for _, server := range servers {
		go serialQueryServers(send, []goseq.Server{server}, timeout)
	}
}

func parseFields(spec string, properties map[string]FieldProperty) ([]FieldSpec, error) {
	specs := make([]FieldSpec, 0, 1)
	found := _fieldregexp.FindAllStringSubmatch(spec, -1)

	if len(found) == 0 && len(strings.TrimSpace(spec)) != 0 {
		return nil, errors.New("Couldn't parse field list.")
	}

	for _, match := range found {

		if _, ok := serverMethodAccessors[match[2]]; !ok {
			if _, ok = serverProperties[match[2]]; !ok {
				return nil, errors.New("Attempted to use an unregistered field!")
			}
		}

		sp := FieldSpec{
			name:   match[2],
			length: -1,
		}

		if def, ok := properties[match[2]]; ok {
			sp.length = def.size
		}

		if match[4] != "" {
			val, err := strconv.Atoi(match[4])
			if err == nil {
				sp.length = val
			}
		}

		specs = append(specs, sp)
	}

	return specs, nil
}

func printServerLine(fields []FieldSpec, in <-chan SvResponse) {

	for sv := range in {
		for i, field := range fields {
			if i > 0 {
				fmt.Print(*_fieldDivider)
			}

			var val interface{}

			if handler, ok := serverMethodAccessors[field.name]; ok {
				val = handler(sv.info)
			}

			if handler, ok := serverProperties[field.name]; ok {
				val = handler(sv.server)
			}

			if transformer, ok := serverFieldTransformers[field.name]; ok {
				val = transformer(val)
			}

			written, _ := fmt.Print(val)

			for ; written < field.length; written++ {
				fmt.Print(" ")
			}
		}
		fmt.Print("\n")
	}
}

func printHeaderLine(fields []FieldSpec, props map[string]FieldProperty) {
	for i, field := range fields {

		if i > 0 {
			fmt.Print(*_fieldDivider)
		}

		title := field.name

		if prop, ok := props[field.name]; ok {
			title = prop.name
		}

		sz := len(title)

		var padL int = 0
		var padR int = 0

		if sz < field.length {
			var rem int = field.length - sz
			padL = rem / 2
			padR = rem - padL
		}

		for j := 0; j < padL; j++ {
			fmt.Print(" ")
		}

		fmt.Print(title)

		for j := 0; j < padR; j++ {
			fmt.Print(" ")
		}
	}
	fmt.Print("\n")
}
<commit_msg>Use better error handling<commit_after>package main

import (
	"errors"
	"flag"
	"fmt"
	"github.com/Ronny95/goseq"
	"log"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var _region = flag.String("region", "USW", "Region code to get results for. \n"+
	"One of USE, USW, SA, EU, AS, AU, ME, AF, OTHER.")

var _asyncOkay = flag.Bool("async", true, "Allow async sub-querying of Source Servers to get info. \n"+
	"Extreme increase of performance with this enabled.")

var _printFields = flag.String("fields", "ip=21,name", "The fields to be included. Optionally includes the min-length space."+
	"See -showfields")

var _fieldDivider = flag.String("divider", " ¦ ", "Characters used to seperate fields.")

var _startIp = flag.String("start", goseq.NoAddress, "Where to start reading IPs from. Defaults to start.")

var _showHeader = flag.Bool("header", true, "Show header w/ column names.")

var _showUnreachable = flag.Bool("unreachable", false, "Show unreachable servers (couldn't be connected to).")

var _showErrorSummary = flag.Bool("errors", true, "Show error summary.")

var _fieldregexp = regexp.MustCompile(`\s*(([a-z]+)(=(\d+))?)\s*,?\s*`)

type FieldSpec struct {
	name   string
	length int
}

type SvResponse struct {
	err    error
	server goseq.Server
	info   goseq.ServerInfo
}

func masterctx() {

	log.SetFlags(0)

	unreachable := 0
	errorsEncountererd := make([]error, 0)

	userRegionStr := strings.ToUpper(*_region)

	region, found := regionData[userRegionStr]

	if !found {
		fmt.Errorf("Region '%s' does not exist.", *_region)
		return
	}

	fields, err := parseFields(*_printFields, serverFieldProperties)

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

	master := goseq.NewMasterServer()
	master.SetRegion(region)
	master.SetAddr(goseq.MasterSourceServers[0])

	servers, err := master.Query(*_startIp)
	numServers := len(servers)

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

	rec := make(chan SvResponse)
	printer := make(chan SvResponse)

	//tups := make([]SvResponse, 0, numServers)

	if *_asyncOkay {
		go AsyncQueryServers(rec, servers, 1*time.Second)
	} else {
		go serialQueryServers(rec, servers, 1*time.Second)
	}

	go printServerLine(fields, printer)

	if *_showHeader {
		printHeaderLine(fields, serverFieldProperties)
	}

	for i := 0; i < numServers; i++ {
		//tups = append(tups, <-rec)
		recd := <-rec

		if recd.err != nil {
			errorsEncountererd = append(errorsEncountererd, recd.err)
		}

		if recd.err != nil && !*_showUnreachable {
			unreachable++
			continue
		}

		printer <- recd
	}

	close(rec)
	close(printer)

	if !*_showUnreachable {
		log.Println(unreachable, "unreachable servers were hidden.")
	}

	if *_showErrorSummary {
		log.Printf("Errors Encountered (%dx):\n", len(errorsEncountererd))

		for _, detail := range errorsEncountererd {
			log.Println("\t", detail)
		}
	}
}

func serialQueryServers(send chan SvResponse, servers []goseq.Server, timeout time.Duration) {
	for _, server := range servers {
		info, err := server.Info(timeout)
		if err != nil {
			send <- SvResponse{err: err, server: server}
		}
		send <- SvResponse{err: err, server: server, info: info}
	}
}

func AsyncQueryServers(send chan SvResponse, servers []goseq.Server, timeout time.Duration) {
	for _, server := range servers {
		go serialQueryServers(send, []goseq.Server{server}, timeout)
	}
}

func parseFields(spec string, properties map[string]FieldProperty) ([]FieldSpec, error) {
	specs := make([]FieldSpec, 0, 1)
	found := _fieldregexp.FindAllStringSubmatch(spec, -1)

	if len(found) == 0 && len(strings.TrimSpace(spec)) != 0 {
		return nil, errors.New("Couldn't parse field list.")
	}

	for _, match := range found {

		if _, ok := serverMethodAccessors[match[2]]; !ok {
			if _, ok = serverProperties[match[2]]; !ok {
				return nil, errors.New("Attempted to use an unregistered field!")
			}
		}

		sp := FieldSpec{
			name:   match[2],
			length: -1,
		}

		if def, ok := properties[match[2]]; ok {
			sp.length = def.size
		}

		if match[4] != "" {
			val, err := strconv.Atoi(match[4])
			if err == nil {
				sp.length = val
			}
		}

		specs = append(specs, sp)
	}

	return specs, nil
}

func printServerLine(fields []FieldSpec, in <-chan SvResponse) {

	for sv := range in {
		for i, field := range fields {
			if i > 0 {
				fmt.Print(*_fieldDivider)
			}

			var val interface{}

			if handler, ok := serverMethodAccessors[field.name]; ok {
				val = handler(sv.info)
			}

			if handler, ok := serverProperties[field.name]; ok {
				val = handler(sv.server)
			}

			if transformer, ok := serverFieldTransformers[field.name]; ok {
				val = transformer(val)
			}

			written, _ := fmt.Print(val)

			for ; written < field.length; written++ {
				fmt.Print(" ")
			}
		}
		fmt.Print("\n")
	}
}

func printHeaderLine(fields []FieldSpec, props map[string]FieldProperty) {
	for i, field := range fields {

		if i > 0 {
			fmt.Print(*_fieldDivider)
		}

		title := field.name

		if prop, ok := props[field.name]; ok {
			title = prop.name
		}

		sz := len(title)

		var padL int = 0
		var padR int = 0

		if sz < field.length {
			var rem int = field.length - sz
			padL = rem / 2
			padR = rem - padL
		}

		for j := 0; j < padL; j++ {
			fmt.Print(" ")
		}

		fmt.Print(title)

		for j := 0; j < padR; j++ {
			fmt.Print(" ")
		}
	}
	fmt.Print("\n")
}

type ErrorCount struct {
	err   error
	count int
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
)

type client struct {
	Chan chan<- string
	Name string
}

var (
	entering = make(chan client)
	leaving  = make(chan client)
	messages = make(chan string)
)

func broadcaster() {
	var online int
	clients := make(map[client]bool)
	for {
		select {
		case msg := <-messages:
			for cln := range clients {
				cln.Chan <- "\t" + msg
			}
		case cln := <-entering:
			clients[cln] = true
			online++
			cln.Chan <- fmt.Sprintf("Online: %d", online)
			for c := range clients {
				cln.Chan <- "[ " + c.Name + " ]"
			}

		case cln := <-leaving:
			online--
			delete(clients, cln)
			close(cln.Chan)
		}
	}
}

func handleConn(conn net.Conn) {
	var who string

	ch := make(chan string)
	go clientWriter(conn, ch)

	ch <- "Input your name: "

	input := bufio.NewScanner(conn)
	if input.Scan() {
		who = input.Text() // no protection
	}

	messages <- who + " has arrived"
	cln := client{Chan: ch, Name: who}
	entering <- cln

	for input.Scan() {
		text := input.Text()
		if text == "!exit" {
			break
		}
		messages <- who + ": " + text
	}
	leaving <- cln
	messages <- who + " has left"
	conn.Close()
}

func clientWriter(conn net.Conn, ch <-chan string) {
	for msg := range ch {
		fmt.Fprintln(conn, msg)
	}
}

func main() {
	listener, err := net.Listen("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}

	go broadcaster()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Print(err)
			continue
		}
		go handleConn(conn)
	}
}
<commit_msg>[8.13] add name if no out from scan<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"net"
)

type client struct {
	Chan chan<- string
	Name string
}

var (
	entering = make(chan client)
	leaving  = make(chan client)
	messages = make(chan string)
)

func broadcaster() {
	var online int
	clients := make(map[client]bool)
	for {
		select {
		case msg := <-messages:
			for cln := range clients {
				cln.Chan <- "\t" + msg
			}
		case cln := <-entering:
			clients[cln] = true
			online++
			cln.Chan <- fmt.Sprintf("Online: %d", online)
			for c := range clients {
				cln.Chan <- "[ " + c.Name + " ]"
			}

		case cln := <-leaving:
			online--
			delete(clients, cln)
			close(cln.Chan)
		}
	}
}

func handleConn(conn net.Conn) {
	var who string

	ch := make(chan string)
	go clientWriter(conn, ch)

	ch <- "Input your name: "

	input := bufio.NewScanner(conn)
	if input.Scan() {
		who = input.Text() // no protection
	} else {
		who = conn.RemoteAddr().String()
	}

	messages <- who + " has arrived"
	cln := client{Chan: ch, Name: who}
	entering <- cln

	for input.Scan() {
		text := input.Text()
		if text == "!exit" {
			break
		}
		messages <- who + ": " + text
	}
	leaving <- cln
	messages <- who + " has left"
	conn.Close()
}

func clientWriter(conn net.Conn, ch <-chan string) {
	for msg := range ch {
		fmt.Fprintln(conn, msg)
	}
}

func main() {
	listener, err := net.Listen("tcp", "localhost:8000")
	if err != nil {
		log.Fatal(err)
	}

	go broadcaster()

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Print(err)
			continue
		}
		go handleConn(conn)
	}
}
<|endoftext|>


<commit_before>package main
import (
	"fmt"
	"net"
)

func sendResponse(conn *net.UDPConn, addr *net.UDPAddr) {
	_,err := conn.WriteToUDP([]byte("From server: Hello I got your mesage "), addr)
	if err != nil {
		fmt.Printf("Couldn't send response %v", err)
	}
}

func main() {
	p := make([]byte, 2048)
	addr := net.UDPAddr{
		Port: 8009,
		IP: net.ParseIP("0.0.0.0"),
	}
	ser, err := net.ListenUDP("udp", &addr)
	if err != nil {
		fmt.Printf("Some error %v\n", err)
		return
	}
	for {
		_,remoteaddr,err := ser.ReadFromUDP(p)
		fmt.Printf("Read a message from %v %s \n", remoteaddr, p)
		if err !=  nil {
			fmt.Printf("Some error  %v", err)
			continue
		}
		go sendResponse(ser, remoteaddr)
	}
}<commit_msg>Update server.go<commit_after>// Copyright 2017 Gruppe 12 IS-105. All rights reserved.
package main
import (
	"fmt"
	"net"
)

func sendResponse(conn *net.UDPConn, addr *net.UDPAddr) {
	_,err := conn.WriteToUDP([]byte("From server: Hello I got your mesage "), addr)
	if err != nil {
		fmt.Printf("Couldn't send response %v", err)
	}
}

func main() {
	p := make([]byte, 2048)
	addr := net.UDPAddr{
		Port: 8009,
		IP: net.ParseIP("0.0.0.0"),
	}
	ser, err := net.ListenUDP("udp", &addr)
	if err != nil {
		fmt.Printf("Some error %v\n", err)
		return
	}
	for {
		_,remoteaddr,err := ser.ReadFromUDP(p)
		fmt.Printf("Read a message from %v %s \n", remoteaddr, p)
		if err !=  nil {
			fmt.Printf("Some error  %v", err)
			continue
		}
		go sendResponse(ser, remoteaddr)
	}
}
<|endoftext|>