diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cdf8e76 --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +.DEFAULT_GOAL := help +SHELL := bash +.ONESHELL: +.SHELLFLAGS := -eu -o pipefail -c +.DELETE_ON_ERROR: +MAKEFLAGS += --warn-undefined-variables +MAKEFLAGS += --no-builtin-rules + +ifeq ($(origin .RECIPEPREFIX), undefined) + $(error This Make does not support .RECIPEPREFIX. Please use GNU Make 4.0 or later) +endif +.RECIPEPREFIX = > + +# Default - top level rule is what gets ran when you run just `make` +build: out/image-id +.PHONY: build + +# Clean up the output directories; since all the sentinel files go under tmp, this will cause everything to get rebuilt +clean: +> rm -rf tmp +> rm -rf out +.PHONY: clean + +# Tests - re-ran if any file under src has been changed since tmp/.tests-passed.sentinel was last touched +tmp/.tests-passed.sentinel: $(shell find src -type f) +> mkdir -p $(@D) +> node run test +> touch $@ + +# Webpack - re-built if the tests have been rebuilt (and so, by proxy, whenever the source files have changed) +tmp/.packed.sentinel: tmp/.tests-passed.sentinel +> mkdir -p $(@D) +> webpack .. +> touch $@ + +# Docker image - re-built if the webpack output has been rebuilt +out/image-id: tmp/.packed.sentinel +> mkdir -p $(@D) +> image_id="example.com/my-app:$$(pwgen -1)" +> docker build --tag="$${image_id} +> echo "$${image_id}" > out/image-id + +help: + + # @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) \ + # | sed -n 's/^\(.*\): \(.*\)##\(.*\)/\1\3/p' \ + # | column -t -s ' ' +.PHONY: help diff --git a/cmd/auth-demo/home.html b/cmd/auth-demo/home.html deleted file mode 100755 index 220ec05..0000000 --- a/cmd/auth-demo/home.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - -
-
- -
-
- - \ No newline at end of file diff --git a/cmd/auth-demo/main.go b/cmd/auth-demo/main.go deleted file mode 100755 index de835bb..0000000 --- a/cmd/auth-demo/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "net/http" - "os" - - "github.com/codegangsta/negroni" - "github.com/jchenry/jchenry/internal/auth" - _http "github.com/jchenry/jchenry/internal/http" -) - -func main() { - auth.Init() - StartServer() -} - -func StartServer() { - auth.PrintConfig() - s := _http.NewServer(negroni.New(), _http.NewJulienschmidtHTTPRouter()). - Static("/public/*filepath", http.Dir("public/")). - Service("", auth.Service(auth.FromEnv())). - Get("/", "", http.HandlerFunc(HomeHandler)) - - port := os.Getenv("PORT") - if port == "" { - port = "3000" - } - - s.Run(":" + port) -} - -func HomeHandler(w http.ResponseWriter, r *http.Request) { - _http.RenderTemplate(w, "home", nil) -} diff --git a/cmd/auth-demo/public/app.css b/cmd/auth-demo/public/app.css deleted file mode 100755 index 5d6a003..0000000 --- a/cmd/auth-demo/public/app.css +++ /dev/null @@ -1,95 +0,0 @@ -body { - font-family: "proxima-nova", sans-serif; - text-align: center; - font-size: 300%; - font-weight: 100; - } - input[type=checkbox], - input[type=radio] { - position: absolute; - opacity: 0; - } - input[type=checkbox] + label, - input[type=radio] + label { - display: inline-block; - } - input[type=checkbox] + label:before, - input[type=radio] + label:before { - content: ""; - display: inline-block; - vertical-align: -0.2em; - width: 1em; - height: 1em; - border: 0.15em solid #0074d9; - border-radius: 0.2em; - margin-right: 0.3em; - background-color: white; - } - input[type=radio] + label:before { - border-radius: 50%; - } - input[type=radio]:checked + label:before, - input[type=checkbox]:checked + label:before { - background-color: #0074d9; - box-shadow: inset 0 0 0 0.15em white; - } - input[type=radio]:focus + label:before, - input[type=checkbox]:focus + label:before { - outline: 0; - } - .btn { - font-size: 140%; - text-transform: uppercase; - letter-spacing: 1px; - border: 0; - background-color: #16214D; - color: white; - } - .btn:hover { - background-color: #44C7F4; - } - .btn:focus { - outline: none !important; - } - .btn.btn-lg { - padding: 20px 30px; - } - .btn:disabled { - background-color: #333; - color: #666; - } - h1, - h2, - h3 { - font-weight: 100; - } - #logo img { - width: 300px; - margin-bottom: 60px; - } - .home-description { - font-weight: 100; - margin: 100px 0; - } - h2 { - margin-top: 30px; - margin-bottom: 40px; - font-size: 200%; - } - label { - font-size: 100%; - font-weight: 300; - } - .btn-next { - margin-top: 30px; - } - .answer { - width: 70%; - margin: auto; - text-align: left; - padding-left: 10%; - margin-bottom: 20px; - } - .login-page .login-box { - padding: 100px 0; - } \ No newline at end of file diff --git a/cmd/auth-demo/run.sh b/cmd/auth-demo/run.sh deleted file mode 100755 index f129eda..0000000 --- a/cmd/auth-demo/run.sh +++ /dev/null @@ -1 +0,0 @@ -AUTH_DOMAIN="https://dev-pb4s8m55.auth0.com/" AUTH_CLIENT_ID="ae1e02bTwXA35O3r3Xxk4kbRf31j5ge9" AUTH_CLIENT_SECRET="NFC5KYeM9GA2z0ptvzKPo9jmkQDRjx_WcsWyK0hzOJmr1CykS9cEmTcNh0-hKiMd" AUTH_CALLBACK_URL="http://localhost:3000/callback" ./auth-demo \ No newline at end of file diff --git a/cmd/auth-demo/user.html b/cmd/auth-demo/user.html deleted file mode 100755 index e327ed3..0000000 --- a/cmd/auth-demo/user.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - -
-
-
- -

Welcome {{.Nickname}}

- Logout -
-
-
- - \ No newline at end of file diff --git a/cmd/email-stats/main.go b/cmd/email-stats/main.go deleted file mode 100755 index a4ea546..0000000 --- a/cmd/email-stats/main.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "fmt" - "log" - "sort" - - "github.com/rsc/rsc/google" - "github.com/rsc/rsc/imap" -) - -type Pair struct { - Key string - Value uint64 -} - -type PairList []*Pair - -func (p PairList) Len() int { return len(p) } -func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value } -func (p PairList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -func main() { - - acct := google.Acct("") - - c, err := imap.NewClient(imap.TLS, "imap.gmail.com", acct.Email, acct.Password, "/") - if err != nil { - log.Fatal(err) - } - - all := c.Inbox() - // all := c.Box("[Gmail]/All Mail") - - if err := all.Check(); err != nil { - log.Fatal(err) - } - - msgs := all.Msgs() - - counts := make(map[string]*Pair) - labels := make(map[string]struct{}) - var pairs PairList = make([]*Pair, 0) - - for _, m := range msgs { - ls := m.GmailLabels - for _, l := range ls { - labels[l] = struct{}{} - } - - email := m.Hdr.From[0].Email - if _, ok := counts[email]; ok { - counts[email].Value = counts[email].Value + 1 - } else { - p := Pair{email, 1} - pairs = append(pairs, &p) - counts[email] = &p - } - } - - keys := []string{} - - for k := range counts { - keys = append(keys, k) - } - - sort.Sort(pairs) - - for _, e := range pairs { - fmt.Printf("%d %s\t\t\thttps://mail.google.com/mail/u/0/#search/in%%3Ainbox+from%%3A(%s)\n", e.Value, e.Key, e.Key) - } - - // for k, _ := range labels { - // fmt.Printf("%s, ", k) - // } - fmt.Println() - -} diff --git a/cmd/gcal2calendar/main.go b/cmd/gcal2calendar/main.go deleted file mode 100644 index d5ebdb7..0000000 --- a/cmd/gcal2calendar/main.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "time" - - "github.com/PuloV/ics-golang" -) - -func main() { - - // calendarFile = flag.String("f", os.Env, "the calendar to convert") - help := flag.Bool("help", false, "this help.") - flag.Parse() - if *help { - flag.Usage() - return - } - - parser := ics.New() - parserChan := parser.GetInputChan() - outputChan := parser.GetOutputChan() - go func() { - nowYear := time.Now().Year() - for event := range outputChan { - if event.GetStart().Year() == nowYear { - printEvent(event) - } - } - }() - - parserChan <- "https://calendar.google.com/calendar/ical/colin%40jchenry.me/private-ff5ffa18eb856032d166c7f410fe33c0/basic.ics" - - parser.Wait() -} - -func printEvent(evt *ics.Event) { - fmt.Printf("%s - %s : %s (%s)\n", fmtTime(evt.GetStart()), fmtTime(evt.GetEnd()), evt.GetSummary(), evt.GetLocation()) -} - -func fmtTime(t time.Time) string { - loc, err := time.LoadLocation("America/Los_Angeles") - if err != nil { - panic("bad timezone") - } - - return t.In(loc).Format("Jan 02\t2006 15:04 MST") -} diff --git a/cmd/jchsh/main.go b/cmd/jchsh/main.go deleted file mode 100644 index e08dae3..0000000 --- a/cmd/jchsh/main.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "bufio" - "errors" - "fmt" - "os" - "os/exec" - "strings" - "time" - - "github.com/jchenry/jchenry/pkg/arvelie" - "github.com/jchenry/jchenry/pkg/neralie" -) - -func main() { - if err := run(); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } -} - -func run() (err error) { - PS1 := "[%]: " - reader := bufio.NewReader(os.Stdin) - - for { - fmt.Print(PS1) - if input, err := reader.ReadString('\n'); err == nil { - if err = execute(input); err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - } - } else { - fmt.Fprintln(os.Stderr, err.Error()) - } - - } - -} - -func execute(input string) error { - input = strings.TrimSuffix(input, "\n") - args := strings.Split(input, " ") - - switch args[0] { - case "cd": - if len(args) < 2 { - return errors.New("path required") - } - return os.Chdir(args[1]) - case "now": - t := time.Now() - fmt.Printf("%s %s\n", arvelie.FromDate(t), neralie.FromTime(t)) - return nil - case "exit": - os.Exit(0) - } - - cmd := exec.Command(args[0], args[1:]...) - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stdout - return cmd.Run() -} diff --git a/cmd/now/main.go b/cmd/now/main.go deleted file mode 100755 index 9f3b79d..0000000 --- a/cmd/now/main.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/jchenry/jchenry/pkg/neralie" -) - -func main() { - a := neralie.FromTime(time.Now()) - fmt.Println(a) -} diff --git a/cmd/now/now b/cmd/now/now deleted file mode 100755 index 2362686..0000000 Binary files a/cmd/now/now and /dev/null differ diff --git a/cmd/sub-demo/home.html b/cmd/sub-demo/home.html deleted file mode 100755 index 220ec05..0000000 --- a/cmd/sub-demo/home.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - -
-
- -
-
- - \ No newline at end of file diff --git a/cmd/sub-demo/main.go b/cmd/sub-demo/main.go deleted file mode 100755 index 7d94524..0000000 --- a/cmd/sub-demo/main.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "net/http" - "os" - - "github.com/codegangsta/negroni" - "github.com/jchenry/jchenry/internal/auth" - _http "github.com/jchenry/jchenry/internal/http" - "github.com/jchenry/jchenry/internal/payments" -) - -func main() { - auth.Init() - StartServer() -} - -func StartServer() { - auth.PrintConfig() - payments.PrintConfig() - - auth_service := auth.Service(auth.FromEnv()) - s := _http.NewServer(negroni.New(), _http.NewJulienschmidtHTTPRouter()). - Static("/public/*filepath", http.Dir("public/")). - Service("", auth_service). - Service("", payments.Service(payments.FromEnv(), &auth_service)). - Get("/", "", http.HandlerFunc(HomeHandler)) - - port := os.Getenv("PORT") - if port == "" { - port = "3000" - } - - s.Run(":" + port) -} - -func HomeHandler(w http.ResponseWriter, r *http.Request) { - _http.RenderTemplate(w, "home", nil) -} diff --git a/cmd/sub-demo/public/app.css b/cmd/sub-demo/public/app.css deleted file mode 100755 index 5d6a003..0000000 --- a/cmd/sub-demo/public/app.css +++ /dev/null @@ -1,95 +0,0 @@ -body { - font-family: "proxima-nova", sans-serif; - text-align: center; - font-size: 300%; - font-weight: 100; - } - input[type=checkbox], - input[type=radio] { - position: absolute; - opacity: 0; - } - input[type=checkbox] + label, - input[type=radio] + label { - display: inline-block; - } - input[type=checkbox] + label:before, - input[type=radio] + label:before { - content: ""; - display: inline-block; - vertical-align: -0.2em; - width: 1em; - height: 1em; - border: 0.15em solid #0074d9; - border-radius: 0.2em; - margin-right: 0.3em; - background-color: white; - } - input[type=radio] + label:before { - border-radius: 50%; - } - input[type=radio]:checked + label:before, - input[type=checkbox]:checked + label:before { - background-color: #0074d9; - box-shadow: inset 0 0 0 0.15em white; - } - input[type=radio]:focus + label:before, - input[type=checkbox]:focus + label:before { - outline: 0; - } - .btn { - font-size: 140%; - text-transform: uppercase; - letter-spacing: 1px; - border: 0; - background-color: #16214D; - color: white; - } - .btn:hover { - background-color: #44C7F4; - } - .btn:focus { - outline: none !important; - } - .btn.btn-lg { - padding: 20px 30px; - } - .btn:disabled { - background-color: #333; - color: #666; - } - h1, - h2, - h3 { - font-weight: 100; - } - #logo img { - width: 300px; - margin-bottom: 60px; - } - .home-description { - font-weight: 100; - margin: 100px 0; - } - h2 { - margin-top: 30px; - margin-bottom: 40px; - font-size: 200%; - } - label { - font-size: 100%; - font-weight: 300; - } - .btn-next { - margin-top: 30px; - } - .answer { - width: 70%; - margin: auto; - text-align: left; - padding-left: 10%; - margin-bottom: 20px; - } - .login-page .login-box { - padding: 100px 0; - } \ No newline at end of file diff --git a/cmd/sub-demo/run.sh b/cmd/sub-demo/run.sh deleted file mode 100755 index c95d2ac..0000000 --- a/cmd/sub-demo/run.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -AUTH_DOMAIN="https://dev-pb4s8m55.auth0.com/" \ -AUTH_CLIENT_ID="ae1e02bTwXA35O3r3Xxk4kbRf31j5ge9" \ -AUTH_CLIENT_SECRET="NFC5KYeM9GA2z0ptvzKPo9jmkQDRjx_WcsWyK0hzOJmr1CykS9cEmTcNh0-hKiMd" \ -AUTH_CALLBACK_URL="http://localhost:3000/callback" \ -AUTH_MGMT_CLIENT_ID="0SpgXDo7HleFZ6NH9ds2t2vkntEzgYqy" \ -AUTH_MGMT_CLIENT_SECRET="DhOE1JqO7A2uosadjuyCluK5P3NlxOf4V9mPkEDy4gDO_lYnMffzYfVpgcINvzfr" \ -STRIPE_KEY="sk_test_3yIcJl5ev3WfFZ4HNbTMqWv800B26e0c4V" \ -STRIPE_PRODUCT_ID="prod_FtzugcD89mNVhp" \ -./sub-demo \ No newline at end of file diff --git a/cmd/sub-demo/subscription.html b/cmd/sub-demo/subscription.html deleted file mode 100755 index f30daa1..0000000 --- a/cmd/sub-demo/subscription.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - -
- {{.Product.Name}} -
-
- {{range .Plans}} -
- - -
- {{end}} - -
- -
- -
- - - -
- - - -
-
- -
- - - - \ No newline at end of file diff --git a/cmd/sub-demo/user.html b/cmd/sub-demo/user.html deleted file mode 100755 index 78cfe44..0000000 --- a/cmd/sub-demo/user.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - -
-
-
- -

Welcome {{.Nickname}}

- Logout -
-
-
- - - - \ No newline at end of file diff --git a/cmd/today/main.go b/cmd/today/main.go deleted file mode 100755 index a3e48c1..0000000 --- a/cmd/today/main.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/jchenry/jchenry/pkg/arvelie" -) - -func main() { - a := arvelie.FromDate(time.Now()) - fmt.Println(a) -} diff --git a/cmd/today/today b/cmd/today/today deleted file mode 100755 index 796e254..0000000 Binary files a/cmd/today/today and /dev/null differ diff --git a/cmd/web-tinkertoy/db.go b/cmd/web-tinkertoy/db.go deleted file mode 100644 index 01a3bd9..0000000 --- a/cmd/web-tinkertoy/db.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "context" - "database/sql" - "fmt" - - "github.com/jchenry/jchenry/db" - "rsc.io/dbstore" -) - -type DBFunc func(db *sql.DB) - -type DBActor struct { - DB *sql.DB - ActionChan chan DBFunc -} - -func (a *DBActor) Run(ctx context.Context) error { - for { - select { - case f := <-a.ActionChan: - f(a.DB) - case <-ctx.Done(): - return ctx.Err() - } - } -} - -func DBStoreInsert(store *dbstore.Storage, e interface{}) db.Func { - return func(db *sql.DB) { - err := store.Insert(db, e) - fmt.Println(err) - } -} - -func DBStoreDelete(store *dbstore.Storage, e interface{}) db.Func { - return func(db *sql.DB) { - store.Delete(db, e) - } -} - -func DBStoreSelect(store *dbstore.Storage, - err chan error, - results chan interface{}, - ent interface{}, - query string, - args ...interface{}) db.Func { - return func(db *sql.DB) { - if e := store.Select(db, ent, query, args...); e != nil { - err <- e - } else { - results <- ent - } - } -} - -func DBStoreRead(store *dbstore.Storage, - err chan error, - results chan interface{}, - ent interface{}, - columns ...string) db.Func { - return func(db *sql.DB) { - if e := store.Read(db, ent, columns...); e != nil { - err <- e - } else { - results <- ent - } - } -} diff --git a/cmd/web-tinkertoy/echo.go b/cmd/web-tinkertoy/echo.go deleted file mode 100644 index ee94fe2..0000000 --- a/cmd/web-tinkertoy/echo.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "net/http" - "sync" - "text/template" -) - -func (s *server) handleEcho() http.HandlerFunc { - var ( - init sync.Once - tmpl *template.Template - tplerr error - ) - return func(w http.ResponseWriter, r *http.Request) { - init.Do(func() { - tmpl, tplerr = template.ParseFiles("echoform.tmpl") - }) - if tplerr != nil { - http.Error(w, tplerr.Error(), http.StatusInternalServerError) - return - } - - switch r.Method { - case http.MethodPost: - r.ParseForm() - s.echoMessage = r.Form.Get("msg") - http.Redirect(w, r, "/echo", 301) - return - case http.MethodGet: - if err := tmpl.Execute(w, map[string]string{"Message": s.echoMessage}); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - } - } -} diff --git a/cmd/web-tinkertoy/echoform.tmpl b/cmd/web-tinkertoy/echoform.tmpl deleted file mode 100644 index bac403f..0000000 --- a/cmd/web-tinkertoy/echoform.tmpl +++ /dev/null @@ -1,15 +0,0 @@ - - - -{{if (eq .Message "")}} -
- - -
-{{else}} - - {{.Message}} - -{{end}} - - diff --git a/cmd/web-tinkertoy/foo.db b/cmd/web-tinkertoy/foo.db deleted file mode 100644 index 9e6daf3..0000000 Binary files a/cmd/web-tinkertoy/foo.db and /dev/null differ diff --git a/cmd/web-tinkertoy/fortune.go b/cmd/web-tinkertoy/fortune.go deleted file mode 100644 index 2035ebb..0000000 --- a/cmd/web-tinkertoy/fortune.go +++ /dev/null @@ -1,96 +0,0 @@ -package main - -import ( - "bufio" - "context" - "fmt" - "log" - "net/http" - "sync" - "text/template" - - "github.com/jchenry/jchenry/db" - "rsc.io/dbstore" -) - -func (s *server) handleFortune() http.HandlerFunc { - var ( - init sync.Once - dba *db.Actor - storage *dbstore.Storage - tmpl *template.Template - tplerr error - ) - - type fortuneWrapper struct { - Fortune string - } - - return func(w http.ResponseWriter, r *http.Request) { - init.Do(func() { - ctx, _ := context.WithCancel(context.Background()) - dba = &db.Actor{ - DB: s.db, - ActionChan: make(chan db.Func), - } - go dba.Run(ctx) - storage = new(dbstore.Storage) - storage.Register(&fortuneWrapper{}) - err := storage.CreateTables(dba.DB) - if err != nil { - fmt.Println(err) - } - tmpl, tplerr = template.ParseFiles("fortunesupload.tmpl") - }) - - if tplerr != nil { - http.Error(w, tplerr.Error(), http.StatusInternalServerError) - return - } - - switch r.Method { - case http.MethodPost: - r.ParseMultipartForm(10 << 20) - file, _, err := r.FormFile("fortunes") - if err != nil { - fmt.Println("Error Retrieving the File") - fmt.Println(err) - return - } - defer file.Close() - - scanner := bufio.NewScanner(file) - var fortune string - for scanner.Scan() { - switch scanner.Text() { - case "%": - dba.ActionChan <- DBStoreInsert(storage, &fortuneWrapper{Fortune: fortune}) - default: - fortune = scanner.Text() - } - - } - - if err := scanner.Err(); err != nil { - log.Fatal(err) - } - case http.MethodGet: - f := fortuneWrapper{} - results := make(chan interface{}) - err := make(chan error) - - dba.ActionChan <- DBStoreSelect(storage, err, results, &f, "ORDER BY RANDOM() LIMIT 1", "*") - select { - case r := <-results: - if err := tmpl.Execute(w, map[string]string{"Message": r.(*fortuneWrapper).Fortune}); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - case e := <-err: - http.Error(w, e.Error(), http.StatusInternalServerError) - } - - } - - } -} diff --git a/cmd/web-tinkertoy/fortunesupload.tmpl b/cmd/web-tinkertoy/fortunesupload.tmpl deleted file mode 100644 index c374a6e..0000000 --- a/cmd/web-tinkertoy/fortunesupload.tmpl +++ /dev/null @@ -1,15 +0,0 @@ - - - -{{if (eq .Message "")}} -
- - -
-{{else}} - {{.Message}} -{{end}} - - diff --git a/cmd/web-tinkertoy/go.mod b/cmd/web-tinkertoy/go.mod deleted file mode 100644 index 50d51d5..0000000 --- a/cmd/web-tinkertoy/go.mod +++ /dev/null @@ -1,22 +0,0 @@ -module github.com/jchenry/jchenry/cmd/web-tinkertoy - -go 1.14 - -require ( - github.com/codegangsta/negroni v1.0.0 // indirect - github.com/coreos/go-oidc v2.1.0+incompatible // indirect - github.com/gorilla/sessions v1.2.0 // indirect - github.com/jchenry/jchenry v0.0.0-00010101000000-000000000000 - github.com/julienschmidt/httprouter v1.2.0 // indirect - github.com/mattn/go-sqlite3 v2.0.3+incompatible - github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect - github.com/stretchr/testify v1.4.0 // indirect - github.com/stripe/stripe-go v63.4.0+incompatible // indirect - golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad // indirect - golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect - gopkg.in/auth0.v1 v1.2.7 // indirect - gopkg.in/square/go-jose.v2 v2.3.1 // indirect - rsc.io/dbstore v0.1.1 -) - -replace github.com/jchenry/jchenry => ../../ diff --git a/cmd/web-tinkertoy/go.sum b/cmd/web-tinkertoy/go.sum deleted file mode 100644 index b8731fd..0000000 --- a/cmd/web-tinkertoy/go.sum +++ /dev/null @@ -1,42 +0,0 @@ -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/PuerkitoBio/rehttp v0.0.0-20180310210549-11cf6ea5d3e9/go.mod h1:ItsOiHl4XeMOV3rzbZqQRjLc3QQxbE6391/9iNG7rE8= -github.com/PuloV/ics-golang v0.0.0-20190808201353-a3394d3bcade/go.mod h1:f1P3hjG+t54/IrnXMnnw+gRmFCDR/ryj9xSQ7MPMkQw= -github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61/go.mod h1:Rp8e0DCtEKwXFOC6JPJQVTz8tuGoGvw6Xfexggh/ed0= -github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/jchenry/jchenry v0.0.0-20191107034549-4697006d1099 h1:qUy+BhiLM5LzN0cOGtqvuC2v7FNfmQFg1cjZbNcMnBY= -github.com/jchenry/jchenry v0.0.0-20191107034549-4697006d1099/go.mod h1:5ywsKLPV6YOTZ7oNNmQo7EQRDKhlGCD311r/ZRZgHDM= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c= -github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= -github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stripe/stripe-go v63.4.0+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -gopkg.in/auth0.v1 v1.2.7/go.mod h1:1FRtMXwYDgygZcO7Of7kj/I4mf9UjHGhMHUOqNT0d0M= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -rsc.io/dbstore v0.1.1 h1:LI4gBJUwbejn0wHJWe0KTwgCM33zUVP3BsNz5y2fkEE= -rsc.io/dbstore v0.1.1/go.mod h1:zI7k1PCSLg9r/T2rBM4E/SctbGmqdtt3kjQSemVh1Rs= -rsc.io/sqlite v0.5.0/go.mod h1:fqHuveM9iIqMzjD0WiZIvKYMty/WqTo2bxE9+zC54WE= diff --git a/cmd/web-tinkertoy/main.go b/cmd/web-tinkertoy/main.go deleted file mode 100644 index 31c85ce..0000000 --- a/cmd/web-tinkertoy/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "database/sql" - "fmt" - "io" - "net/http" - "os" - - _ "github.com/mattn/go-sqlite3" -) - -func main() { - if err := run(os.Args, os.Stdout); err != nil { - fmt.Fprintf(os.Stderr, "%s\n", err) - os.Exit(1) - } -} - -func run(args []string, stdout io.Writer) error { - s := server{ - router: http.NewServeMux(), - } - - s.routes() - - if db, err := sql.Open("sqlite3", "foo.db"); err == nil { - s.db = db - } else { - return err - } - return http.ListenAndServe(":8080", s.router) - -} diff --git a/cmd/web-tinkertoy/server.go b/cmd/web-tinkertoy/server.go deleted file mode 100644 index 7b4204e..0000000 --- a/cmd/web-tinkertoy/server.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "database/sql" - "net/http" -) - -type server struct { - db *sql.DB - router *http.ServeMux - echoMessage string -} - -func (s *server) routes() { - s.router.HandleFunc("/time", s.handleTime()) - s.router.HandleFunc("/echo", s.handleEcho()) - s.router.HandleFunc("/fortune", s.handleFortune()) -} diff --git a/cmd/web-tinkertoy/time.go b/cmd/web-tinkertoy/time.go deleted file mode 100644 index 9239450..0000000 --- a/cmd/web-tinkertoy/time.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "fmt" - "io" - "net/http" - "time" - - "github.com/jchenry/jchenry/arvelie" - "github.com/jchenry/jchenry/neralie" -) - -func (s *server) handleTime() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - t := time.Now() - w.WriteHeader(200) - io.WriteString(w, t.String()) - io.WriteString(w, fmt.Sprintf("\n%s %s", - arvelie.FromDate(t), - neralie.FromTime(t))) - } -} diff --git a/cmd/wiki/edit.go b/cmd/wiki/edit.go deleted file mode 100644 index fb16702..0000000 --- a/cmd/wiki/edit.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "net/http" - "os" -) - -func edit(pageName string, w http.ResponseWriter, r *http.Request) (err error) { - if body, err := getFile(pageName, os.O_RDWR|os.O_CREATE); err == nil { - return render(pageName, "edit", body, w) - } - return -} diff --git a/cmd/wiki/http.go b/cmd/wiki/http.go deleted file mode 100644 index 340408f..0000000 --- a/cmd/wiki/http.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "net/http" - "os" -) - -func auth(fn http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - user, pass, _ := r.BasicAuth() - if !(user == os.Getenv("WIKI_USERNAME") && pass == os.Getenv("WIKI_PASSWORD")) { - w.Header().Set("WWW-Authenticate", `Basic realm="wiki"`) - http.Error(w, "Unauthorized.", 401) - return - } - fn(w, r) - } -} diff --git a/cmd/wiki/main.go b/cmd/wiki/main.go deleted file mode 100644 index e057c8f..0000000 --- a/cmd/wiki/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "flag" - "log" - "net/http" - "os" - "path" - "path/filepath" -) - -type actionFunc func(s string, w http.ResponseWriter, r *http.Request) error - -var pageDir *string - -func main() { - p, err := filepath.Abs(filepath.Dir(os.Args[0])) - if err != nil { - panic(err) - } - pageDir = flag.String("pageDir", path.Join(p, "pages"), "the directory in which pages exist") - httpAddr := flag.String("http", "127.0.0.1:8080", " HTTP service address") - help := flag.Bool("help", false, "this help.") - flag.Parse() - if *help { - flag.Usage() - return - } - for path, action := range map[string]actionFunc{"/wiki/": view, "/edit/": edit, "/save/": save, "/search/": search} { - register(path, action) - } - http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) - http.Handle("/", auth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { view("WelcomeVisitors", w, r) }))) - log.Printf("using log/pass: %s/%s", os.Getenv("WIKI_USERNAME"), os.Getenv("WIKI_PASSWORD")) - log.Printf("wiki has started listening at %s", *httpAddr) - log.Fatal(http.ListenAndServe(*httpAddr, nil)) -} - -func register(path string, action actionFunc) { - http.Handle(path, http.StripPrefix(path, auth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "" { - if err := action(r.URL.Path, w, r); err != nil { - log.Fatal(err) - } - } - })))) -} diff --git a/cmd/wiki/os.go b/cmd/wiki/os.go deleted file mode 100644 index 5272ee8..0000000 --- a/cmd/wiki/os.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "io/ioutil" - "os" - "path" -) - -func getFile(pageName string, flags int) (file []byte, err error) { - if f, err := os.OpenFile(path.Join(*pageDir, pageName), flags, 0755); err == nil { - return ioutil.ReadAll(f) - } - return file, err -} - -func saveFile(pageName string, contents []byte) error { - return ioutil.WriteFile(path.Join(*pageDir, pageName), contents, 0700) -} diff --git a/cmd/wiki/render.go b/cmd/wiki/render.go deleted file mode 100644 index 6394d12..0000000 --- a/cmd/wiki/render.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "net/http" - "text/template" -) - -func render(p string, m string, body []byte, w http.ResponseWriter) (err error) { - if tmpl, err := template.ParseFiles("page.tmpl.html"); err == nil { - return tmpl.Execute(w, struct { - Mode string - Body string - Page string - }{m, string(body), p}) - } - return err -} diff --git a/cmd/wiki/save.go b/cmd/wiki/save.go deleted file mode 100644 index 2d33fd7..0000000 --- a/cmd/wiki/save.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "fmt" - "net/http" -) - -func save(pageName string, w http.ResponseWriter, r *http.Request) (err error) { - r.ParseForm() - if err = saveFile(pageName, []byte(r.Form.Get("Text"))); err == nil { - http.Redirect(w, r, fmt.Sprintf("/wiki/%s", pageName), http.StatusTemporaryRedirect) - } - return -} diff --git a/cmd/wiki/search.go b/cmd/wiki/search.go deleted file mode 100644 index 9f1eb91..0000000 --- a/cmd/wiki/search.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "net/http" - "os" - "regexp" -) - -const resultFmt = "%s . . . . . . %s
\n" - -func search(keyword string, w http.ResponseWriter, r *http.Request) (err error) { - var results string - if files, err := ioutil.ReadDir(*pageDir); err == nil { - re := regexp.MustCompile(keyword) - for _, f := range files { - if f.Name() == keyword { - results += fmt.Sprintf(resultFmt, f.Name(), f.Name(), f.Name()) - } - if body, err := getFile(f.Name(), os.O_RDWR); err == nil { - for _, occur := range re.FindSubmatch(body) { - results += fmt.Sprintf(resultFmt, f.Name(), f.Name(), occur) - } - } else { - return err - } - } - render("search", "view", []byte(results), w) - } - return err -} diff --git a/cmd/wiki/view.go b/cmd/wiki/view.go deleted file mode 100644 index 24bc2fa..0000000 --- a/cmd/wiki/view.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "bytes" - "fmt" - "net/http" - "os" - "regexp" - "strings" - - "github.com/russross/blackfriday/v2" -) - -var patterns [5]*regexp.Regexp -var renderers [5]func([]byte) []byte - -func init() { - // /*autoLinkRegexp*/ patterns[0], renderers[0] = regexp.MustCompile("[A-Z][a-z0-9]+([A-Z][a-z0-9]+)+"), func(s []byte) []byte { return []byte(fmt.Sprintf(`%s`, string(s), string(s))) } - /*BracketedAutoLinkRegexp*/ - patterns[0], renderers[0] = regexp.MustCompile("\\[\\[[A-Za-z0-9 ]+([A-Za-z0-9 ]+)+\\]\\]"), func(s []byte) []byte { return []byte(fmt.Sprintf(`%s`, string(s), string(s))) } - - /*searchRegexp*/ - patterns[1], renderers[1] = regexp.MustCompile("\\[Search\\]"), func(s []byte) []byte { - return []byte(`
`) - } - /*youTubeLinkRegexp*/ patterns[2], renderers[2] = regexp.MustCompile("https://(www.)?youtube.com/watch\\?v=([-\\w]+)"), func(s []byte) []byte { - return []byte(fmt.Sprintf(``, strings.Split(string(s), "=")[1])) - } - /*isbnLinkRegexp*/ patterns[3], renderers[3] = regexp.MustCompile("ISBN:*([0-9]{10,})"), func(s []byte) []byte { - return []byte(fmt.Sprintf(`ISBN %s`, bytes.Replace(bytes.Split(s, []byte(":"))[1], []byte("-"), []byte(""), -1), bytes.Split(s, []byte(":"))[1])) - } - /*alltextRegexp*/ patterns[4], renderers[4] = regexp.MustCompile(".*"), func(s []byte) []byte { - return blackfriday.Run(s, blackfriday.WithExtensions(blackfriday.CommonExtensions)) - } -} - -func view(pageName string, w http.ResponseWriter, r *http.Request) (err error) { - var body []byte - if body, err = getFile(pageName, os.O_RDWR); os.IsNotExist(err) { - http.Redirect(w, r, fmt.Sprintf("/edit/%s", pageName), http.StatusTemporaryRedirect) // no page? redirect to edit/create it. - return nil - } - for i := range renderers { - body = patterns[i].ReplaceAllFunc(body, renderers[i]) - } - return render(pageName, "view", body, w) -} diff --git a/pkg/db/actor.go b/database/actor.go similarity index 94% rename from pkg/db/actor.go rename to database/actor.go index 0604597..ab7f6dc 100644 --- a/pkg/db/actor.go +++ b/database/actor.go @@ -1,4 +1,4 @@ -package db +package database import ( "context" diff --git a/pkg/db/doc.go b/database/doc.go similarity index 79% rename from pkg/db/doc.go rename to database/doc.go index d1d9b18..8241f01 100644 --- a/pkg/db/doc.go +++ b/database/doc.go @@ -1,14 +1,15 @@ -package db +package database + /* -Example usage: - +Example usage: + ctx, _ := context.WithCancel(context.Background()) dba = &db.Actor{ DB: s.db, ActionChan: make(chan db.Func), } - + go dba.Run(ctx) -*/ \ No newline at end of file +*/ diff --git a/encoding/coder.go b/encoding/coder.go new file mode 100644 index 0000000..c98a057 --- /dev/null +++ b/encoding/coder.go @@ -0,0 +1,6 @@ +package encoding + +import "io" + +type Encoder func(io.Writer, interface{}) error +type Decoder func(io.Reader, interface{}) error diff --git a/encoding/json/json.go b/encoding/json/json.go new file mode 100644 index 0000000..3d5eb8d --- /dev/null +++ b/encoding/json/json.go @@ -0,0 +1,23 @@ +package json + +import ( + "encoding/json" + "io" +) + +func Encoder(w io.Writer, e interface{}) error { + return json.NewEncoder(w).Encode(e) +} + +func Decoder(r io.Reader, e interface{}) error { + return json.NewDecoder(r).Decode(e) +} + +// func Decoder(get func() interface{}) func(io.Reader) (interface{}, error) { +// //TODO I dont like the get() function, find a better way of dealing with this +// return func(r io.Reader) (interface{}, error) { +// e := get() +// err := json.NewDecoder(r).Decode(e) +// return e, err +// } +// } diff --git a/encoding/xml/xml.go b/encoding/xml/xml.go new file mode 100644 index 0000000..5dd563e --- /dev/null +++ b/encoding/xml/xml.go @@ -0,0 +1,24 @@ +package xml + +import ( + "encoding/xml" + "io" +) + +func Encoder(w io.Writer, e interface{}) error { + return xml.NewEncoder(w).Encode(e) +} + +func Decoder(r io.Reader, e interface{}) error { + return xml.NewDecoder(r).Decode(e) +} + +// func Decoder(get func() interface{}) func(io.Reader) (interface{}, error) { +// //TODO I dont like the get() function, find a better way of dealing with this +// return func(r io.Reader) (interface{}, error) { +// e := get() +// err := xml.NewDecoder(r).Decode(e) +// return e, err +// } +// } +// diff --git a/go.mod b/go.mod index bf150d6..a9d17b2 100755 --- a/go.mod +++ b/go.mod @@ -1,21 +1,22 @@ -module github.com/jchenry/jchenry +module github.com/jchenry/x go 1.13 require ( + fyne.io/fyne v1.3.0 github.com/PuloV/ics-golang v0.0.0-20190808201353-a3394d3bcade github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 // indirect github.com/codegangsta/negroni v1.0.0 github.com/coreos/go-oidc v2.1.0+incompatible github.com/gorilla/sessions v1.2.0 + github.com/jchenry/jchenry v0.0.0-20200615172632-cb0bc37e6b16 github.com/julienschmidt/httprouter v1.2.0 github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect github.com/rsc/rsc v0.0.0-20180427141835-fc6202590229 github.com/russross/blackfriday/v2 v2.0.1 github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect - github.com/stretchr/testify v1.4.0 // indirect github.com/stripe/stripe-go v63.4.0+incompatible - golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad // indirect + golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 gopkg.in/auth0.v1 v1.2.7 gopkg.in/square/go-jose.v2 v2.3.1 // indirect diff --git a/go.sum b/go.sum index 7e46086..60e204b 100755 --- a/go.sum +++ b/go.sum @@ -1,8 +1,12 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +fyne.io/fyne v1.3.0 h1:FLlgX/JkD3Chal7tEhRL7fOONVAjQJM/yrVNA+cK/dc= +fyne.io/fyne v1.3.0/go.mod h1:AcBUeR8hetITnnfaLvuVqioWM/lT18WPeMVAobhMbg8= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= github.com/PuerkitoBio/rehttp v0.0.0-20180310210549-11cf6ea5d3e9 h1:VE0eMvNSQI72dADsq4gm5KpNPmt97WgqneTfaS5MWrs= github.com/PuerkitoBio/rehttp v0.0.0-20180310210549-11cf6ea5d3e9/go.mod h1:ItsOiHl4XeMOV3rzbZqQRjLc3QQxbE6391/9iNG7rE8= github.com/PuloV/ics-golang v0.0.0-20190808201353-a3394d3bcade h1:odEkSCl2gLWPtvraEdCyBZbeYyMMTysWPLMurnB8sUY= github.com/PuloV/ics-golang v0.0.0-20190808201353-a3394d3bcade/go.mod h1:f1P3hjG+t54/IrnXMnnw+gRmFCDR/ryj9xSQ7MPMkQw= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61 h1:o64h9XF42kVEUuhuer2ehqrlX8rZmvQSU0+Vpj1rF6Q= github.com/channelmeter/iso8601duration v0.0.0-20150204201828-8da3af7a2a61/go.mod h1:Rp8e0DCtEKwXFOC6JPJQVTz8tuGoGvw6Xfexggh/ed0= github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY= @@ -11,14 +15,39 @@ github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fyne-io/mobile v0.0.2 h1:eGmCR5lkFxk0PnPafGppLFRD5QODJfSVdrjhLjanOVg= +github.com/fyne-io/mobile v0.0.2/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY= +github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= +github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= +github.com/jchenry/jchenry v0.0.0-20200615172632-cb0bc37e6b16 h1:vVomaWqIbI/Vyb6uGE8ANmF8V3ktoLiOXdcKQLvwUc4= +github.com/jchenry/jchenry v0.0.0-20200615172632-cb0bc37e6b16/go.mod h1:WLNY6BKAzrUIfnkPA8WCUxkKchKZss4fRSVmbKZuhMg= +github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU= @@ -30,38 +59,75 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stripe/stripe-go v63.4.0+incompatible h1:zzZR004GZ/si7nyckn4NBhoQOViUu5VJ/sA7NT7oTSs= github.com/stripe/stripe-go v63.4.0+incompatible/go.mod h1:A1dQZmO/QypXmsL0T8axYZkSN/uA/T/A64pfKdBAMiY= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775 h1:TC0v2RSO1u2kn1ZugjrFXkRZAEaqMN/RW+OTZkBzmLE= +golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/auth0.v1 v1.2.7 h1:9UCE5rKFL60rqQENmmJaGdNu7/aby8r8wVcJ83Vj5oU= gopkg.in/auth0.v1 v1.2.7/go.mod h1:1FRtMXwYDgygZcO7Of7kj/I4mf9UjHGhMHUOqNT0d0M= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= rsc.io/dbstore v0.1.1 h1:LI4gBJUwbejn0wHJWe0KTwgCM33zUVP3BsNz5y2fkEE= rsc.io/dbstore v0.1.1/go.mod h1:zI7k1PCSLg9r/T2rBM4E/SctbGmqdtt3kjQSemVh1Rs= rsc.io/rsc v0.0.0-20180427141835-fc6202590229 h1:6s5zUknxnRp4D3GlNb7uDzlcfFVq9G2ficO+k4Bcb6w= diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 8463a2b..5f9c34b 100755 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -1,40 +1,40 @@ package auth -import ( - "context" - "log" +// import ( +// "context" +// "log" - "golang.org/x/oauth2" +// "golang.org/x/oauth2" - oidc "github.com/coreos/go-oidc" -) +// oidc "github.com/coreos/go-oidc" +// ) -type Authenticator struct { - Provider *oidc.Provider - Config oauth2.Config - Ctx context.Context -} +// type Authenticator struct { +// Provider *oidc.Provider +// Config oauth2.Config +// Ctx context.Context +// } -func NewAuthenticator(domain, clientID, clientSecret, callback string) (*Authenticator, error) { - ctx := context.Background() +// func NewAuthenticator(domain, clientID, clientSecret, callback string) (*Authenticator, error) { +// ctx := context.Background() - provider, err := oidc.NewProvider(ctx, domain) - if err != nil { - log.Printf("failed to get provider: %v", err) - return nil, err - } +// provider, err := oidc.NewProvider(ctx, domain) +// if err != nil { +// log.Printf("failed to get provider: %v", err) +// return nil, err +// } - conf := oauth2.Config{ - ClientID: clientID, - ClientSecret: clientSecret, - RedirectURL: callback, - Endpoint: provider.Endpoint(), - Scopes: []string{oidc.ScopeOpenID, "profile"}, - } +// conf := oauth2.Config{ +// ClientID: clientID, +// ClientSecret: clientSecret, +// RedirectURL: callback, +// Endpoint: provider.Endpoint(), +// Scopes: []string{oidc.ScopeOpenID, "profile"}, +// } - return &Authenticator{ - Provider: provider, - Config: conf, - Ctx: ctx, - }, nil -} +// return &Authenticator{ +// Provider: provider, +// Config: conf, +// Ctx: ctx, +// }, nil +// } diff --git a/internal/auth/callback.go b/internal/auth/callback.go index 06266b6..9fcf46f 100755 --- a/internal/auth/callback.go +++ b/internal/auth/callback.go @@ -1,89 +1,89 @@ package auth -import ( - "context" - "log" - "net/http" +// import ( +// "context" +// "log" +// "net/http" - oidc "github.com/coreos/go-oidc" -) +// oidc "github.com/coreos/go-oidc" +// ) -func NewCallbackHandler(c Config) http.HandlerFunc { +// func NewCallbackHandler(c Config) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - session, err := Store.Get(r, SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// return func(w http.ResponseWriter, r *http.Request) { +// session, err := Store.Get(r, SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - if r.URL.Query().Get("state") != session.Values["state"] { - http.Error(w, "Invalid state parameter", http.StatusBadRequest) - return - } +// if r.URL.Query().Get("state") != session.Values["state"] { +// http.Error(w, "Invalid state parameter", http.StatusBadRequest) +// return +// } - authenticator, err := NewAuthenticator(c.Domain, c.ClientID, c.ClientSecret, c.CallbackURL) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// authenticator, err := NewAuthenticator(c.Domain, c.ClientID, c.ClientSecret, c.CallbackURL) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - token, err := authenticator.Config.Exchange(context.TODO(), r.URL.Query().Get("code")) - if err != nil { - log.Printf("no token found: %v", err) - w.WriteHeader(http.StatusUnauthorized) - return - } +// token, err := authenticator.Config.Exchange(context.TODO(), r.URL.Query().Get("code")) +// if err != nil { +// log.Printf("no token found: %v", err) +// w.WriteHeader(http.StatusUnauthorized) +// return +// } - rawIDToken, ok := token.Extra("id_token").(string) - if !ok { - http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError) - return - } +// rawIDToken, ok := token.Extra("id_token").(string) +// if !ok { +// http.Error(w, "No id_token field in oauth2 token.", http.StatusInternalServerError) +// return +// } - oidcConfig := &oidc.Config{ - ClientID: c.ClientID, - } +// oidcConfig := &oidc.Config{ +// ClientID: c.ClientID, +// } - idToken, err := authenticator.Provider.Verifier(oidcConfig).Verify(context.TODO(), rawIDToken) +// idToken, err := authenticator.Provider.Verifier(oidcConfig).Verify(context.TODO(), rawIDToken) - if err != nil { - http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError) - return - } +// if err != nil { +// http.Error(w, "Failed to verify ID Token: "+err.Error(), http.StatusInternalServerError) +// return +// } - // Getting now the userInfo - user := User{} - if err := idToken.Claims(&user); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// // Getting now the userInfo +// user := User{} +// if err := idToken.Claims(&user); err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - session.Values["id_token"] = rawIDToken - session.Values["access_token"] = token.AccessToken - session.Values["profile"] = user - err = session.Save(r, w) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// session.Values["id_token"] = rawIDToken +// session.Values["access_token"] = token.AccessToken +// session.Values["profile"] = user +// err = session.Save(r, w) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - // if application ID is non existent, and therefore does not have a tenant - // Create or associate? - // Create: - // - Create Tenant - // - Specify plan - // - Specify payment info - // - Associate Tenant - // - by email address domain? - //set tenant ID on application ID in App Metadata on user +// // if application ID is non existent, and therefore does not have a tenant +// // Create or associate? +// // Create: +// // - Create Tenant +// // - Specify plan +// // - Specify payment info +// // - Associate Tenant +// // - by email address domain? +// //set tenant ID on application ID in App Metadata on user - // if c.CallbackFunc != nil { - // c.CallbackFunc(c, user) - // } else { - // Redirect to logged in page - http.Redirect(w, r, c.RedirectURL, http.StatusSeeOther) - // } +// // if c.CallbackFunc != nil { +// // c.CallbackFunc(c, user) +// // } else { +// // Redirect to logged in page +// http.Redirect(w, r, c.RedirectURL, http.StatusSeeOther) +// // } - } -} +// } +// } diff --git a/internal/auth/config.go b/internal/auth/config.go index e53329c..4c8eb4f 100755 --- a/internal/auth/config.go +++ b/internal/auth/config.go @@ -1,36 +1,36 @@ package auth -import ( - "fmt" - "os" -) +// import ( +// "fmt" +// "os" +// ) -type Config struct { - Domain string - ClientID string - ClientSecret string - ManagementClientID string - ManagementClientSecret string +// type Config struct { +// Domain string +// ClientID string +// ClientSecret string +// ManagementClientID string +// ManagementClientSecret string - CallbackURL string - RedirectURL string -} +// CallbackURL string +// RedirectURL string +// } -func FromEnv() Config { - return Config{ - Domain: os.Getenv("AUTH_DOMAIN"), - ClientID: os.Getenv("AUTH_CLIENT_ID"), - ClientSecret: os.Getenv("AUTH_CLIENT_SECRET"), - ManagementClientID: os.Getenv("AUTH_MGMT_CLIENT_ID"), - ManagementClientSecret: os.Getenv("AUTH_MGMT_CLIENT_SECRET"), +// func FromEnv() Config { +// return Config{ +// Domain: os.Getenv("AUTH_DOMAIN"), +// ClientID: os.Getenv("AUTH_CLIENT_ID"), +// ClientSecret: os.Getenv("AUTH_CLIENT_SECRET"), +// ManagementClientID: os.Getenv("AUTH_MGMT_CLIENT_ID"), +// ManagementClientSecret: os.Getenv("AUTH_MGMT_CLIENT_SECRET"), - CallbackURL: os.Getenv("AUTH_CALLBACK_URL"), - RedirectURL: "/user", - } -} +// CallbackURL: os.Getenv("AUTH_CALLBACK_URL"), +// RedirectURL: "/user", +// } +// } -func PrintConfig() { - fmt.Printf("%#v\n", FromEnv()) -} +// func PrintConfig() { +// fmt.Printf("%#v\n", FromEnv()) +// } -type CallbackFunc func(c Config, u User) error +// type CallbackFunc func(c Config, u User) error diff --git a/internal/auth/login.go b/internal/auth/login.go index 5312158..7f4c0f2 100755 --- a/internal/auth/login.go +++ b/internal/auth/login.go @@ -2,42 +2,42 @@ package auth -import ( - "crypto/rand" - "encoding/base64" - "net/http" -) +// import ( +// "crypto/rand" +// "encoding/base64" +// "net/http" +// ) -func NewLoginHandler(c Config) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - // Generate random state - b := make([]byte, 32) - _, err := rand.Read(b) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - state := base64.StdEncoding.EncodeToString(b) +// func NewLoginHandler(c Config) http.HandlerFunc { +// return func(w http.ResponseWriter, r *http.Request) { +// // Generate random state +// b := make([]byte, 32) +// _, err := rand.Read(b) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } +// state := base64.StdEncoding.EncodeToString(b) - session, err := Store.Get(r, SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - session.Values["state"] = state - err = session.Save(r, w) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// session, err := Store.Get(r, SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } +// session.Values["state"] = state +// err = session.Save(r, w) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - authenticator, err := NewAuthenticator(c.Domain, c.ClientID, c.ClientSecret, c.CallbackURL) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// authenticator, err := NewAuthenticator(c.Domain, c.ClientID, c.ClientSecret, c.CallbackURL) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - http.Redirect(w, r, authenticator.Config.AuthCodeURL(state), http.StatusTemporaryRedirect) - } +// http.Redirect(w, r, authenticator.Config.AuthCodeURL(state), http.StatusTemporaryRedirect) +// } -} +// } diff --git a/internal/auth/logout.go b/internal/auth/logout.go index 497851a..9e4860f 100755 --- a/internal/auth/logout.go +++ b/internal/auth/logout.go @@ -1,43 +1,43 @@ package auth -import ( - "net/http" - "net/url" -) +// import ( +// "net/http" +// "net/url" +// ) -func LogoutHandler(w http.ResponseWriter, r *http.Request) { +// func LogoutHandler(w http.ResponseWriter, r *http.Request) { - if cook, err := r.Cookie(SessionName); err == nil { - cook.MaxAge = -1 - http.SetCookie(w, cook) - } +// if cook, err := r.Cookie(SessionName); err == nil { +// cook.MaxAge = -1 +// http.SetCookie(w, cook) +// } - domain := "dev-pb4s8m55.auth0.com" +// domain := "dev-pb4s8m55.auth0.com" - // var Url *url.URL - URL, err := url.Parse("https://" + domain) +// // var Url *url.URL +// URL, err := url.Parse("https://" + domain) - if err != nil { - panic(err.Error()) - } +// if err != nil { +// panic(err.Error()) +// } - session, err := Store.Get(r, SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - session.Options.MaxAge = -1 +// session, err := Store.Get(r, SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } +// session.Options.MaxAge = -1 - err = session.Save(r, w) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } +// err = session.Save(r, w) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// } - URL.Path += "/v2/logout" - parameters := url.Values{} - parameters.Add("returnTo", "http://localhost:3000") - parameters.Add("client_id", "ae1e02bTwXA35O3r3Xxk4kbRf31j5ge9") - URL.RawQuery = parameters.Encode() +// URL.Path += "/v2/logout" +// parameters := url.Values{} +// parameters.Add("returnTo", "http://localhost:3000") +// parameters.Add("client_id", "ae1e02bTwXA35O3r3Xxk4kbRf31j5ge9") +// URL.RawQuery = parameters.Encode() - http.Redirect(w, r, URL.String(), http.StatusTemporaryRedirect) -} +// http.Redirect(w, r, URL.String(), http.StatusTemporaryRedirect) +// } diff --git a/internal/auth/middleware.go b/internal/auth/middleware.go index 4e918b8..2df42ab 100755 --- a/internal/auth/middleware.go +++ b/internal/auth/middleware.go @@ -1,19 +1,19 @@ package auth -import "net/http" +// import "net/http" -func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { +// func IsAuthenticated(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - session, err := Store.Get(r, SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// session, err := Store.Get(r, SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - if _, ok := session.Values["profile"]; !ok { - //TODO allow customization of redirect - http.Redirect(w, r, "/", http.StatusSeeOther) - } else { - next(w, r) - } -} +// if _, ok := session.Values["profile"]; !ok { +// //TODO allow customization of redirect +// http.Redirect(w, r, "/", http.StatusSeeOther) +// } else { +// next(w, r) +// } +// } diff --git a/internal/auth/service.go b/internal/auth/service.go index 21afd76..2a993f9 100755 --- a/internal/auth/service.go +++ b/internal/auth/service.go @@ -1,39 +1,38 @@ package auth -import ( - "net/http" +// import ( +// "github.com/jchenry/x/internal/http" +// ) - "github.com/codegangsta/negroni" - _http "github.com/jchenry/jchenry/internal/http" - "gopkg.in/auth0.v1/management" -) +// func Service(c Config) ServiceInstance { +// return ServiceInstance{c: c} +// } -func Service(c Config) ServiceInstance { - return ServiceInstance{c: c} -} +// type ServiceInstance struct { +// c Config +// } -type ServiceInstance struct { - c Config -} +// func (si ServiceInstance) Register(m *http.Mux) { +// } -func (si ServiceInstance) Register(uriBase string, s *_http.Server) { +// func (si ServiceInstance) Register(uriBase string, s *_http.Server) { - s.Get(uriBase+"/login", "login endpoint", http.HandlerFunc(NewLoginHandler(si.c))) - s.Get(uriBase+"/logout", "logout endpoint", http.HandlerFunc(LogoutHandler)) - s.Get(uriBase+"/callback", "oidc callback", http.HandlerFunc(NewCallbackHandler(si.c))) - s.Get(uriBase+"/user", "user info endpoint", negroni.New( - negroni.HandlerFunc(IsAuthenticated), - negroni.Wrap(http.HandlerFunc(UserHandler)), - )) -} +// s.Get(uriBase+"/login", "login endpoint", http.HandlerFunc(NewLoginHandler(si.c))) +// s.Get(uriBase+"/logout", "logout endpoint", http.HandlerFunc(LogoutHandler)) +// s.Get(uriBase+"/callback", "oidc callback", http.HandlerFunc(NewCallbackHandler(si.c))) +// s.Get(uriBase+"/user", "user info endpoint", negroni.New( +// negroni.HandlerFunc(IsAuthenticated), +// negroni.Wrap(http.HandlerFunc(UserHandler)), +// )) +// } -func (si ServiceInstance) UpdateUser(u User) error { - m, err := management.New(si.c.Domain, si.c.ManagementClientID, si.c.ManagementClientSecret) - if err != nil { - return err - } +// func (si ServiceInstance) UpdateUser(u User) error { +// m, err := management.New(si.c.Domain, si.c.ManagementClientID, si.c.ManagementClientSecret) +// if err != nil { +// return err +// } - um := management.NewUserManager(m) +// um := management.NewUserManager(m) - return um.Update(u.ID, &management.User{AppMetadata: u.Apps}) -} +// return um.Update(u.ID, &management.User{AppMetadata: u.Apps}) +// } diff --git a/internal/auth/session.go b/internal/auth/session.go index 287d1b7..d237604 100755 --- a/internal/auth/session.go +++ b/internal/auth/session.go @@ -1,19 +1,19 @@ package auth -import ( - "encoding/gob" +// import ( +// "encoding/gob" - "github.com/gorilla/sessions" -) +// "github.com/gorilla/sessions" +// ) -const SessionName = "auth-session" +// const SessionName = "auth-session" -var ( - Store *sessions.FilesystemStore -) +// var ( +// Store *sessions.FilesystemStore +// ) -func Init() error { - Store = sessions.NewFilesystemStore("", []byte("something-very-secret")) - gob.Register(User{}) - return nil -} +// func Init() error { +// Store = sessions.NewFilesystemStore("", []byte("something-very-secret")) +// gob.Register(User{}) +// return nil +// } diff --git a/internal/auth/user.go b/internal/auth/user.go index 98b5741..bb5dc3e 100755 --- a/internal/auth/user.go +++ b/internal/auth/user.go @@ -1,28 +1,28 @@ package auth -import ( - "net/http" +// import ( +// "net/http" - jchenry_http "github.com/jchenry/jchenry/internal/http" -) +// jchenry_http "github.com/jchenry/x/internal/http" +// ) -func UserHandler(w http.ResponseWriter, r *http.Request) { +// func UserHandler(w http.ResponseWriter, r *http.Request) { - session, err := Store.Get(r, SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// session, err := Store.Get(r, SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - jchenry_http.RenderTemplate(w, "user", session.Values["profile"]) -} +// jchenry_http.RenderTemplate(w, "user", session.Values["profile"]) +// } -type User struct { - ID string `json:"sub"` - Email string `json:"email"` - FirstName string `json:"given_name"` - LastName string `json:"family_name"` - Picture string `json:"picture"` - Nickname string `json:"nickname"` - Apps map[string]interface{} `json:"app_metadata,omitempty"` -} +// type User struct { +// ID string `json:"sub"` +// Email string `json:"email"` +// FirstName string `json:"given_name"` +// LastName string `json:"family_name"` +// Picture string `json:"picture"` +// Nickname string `json:"nickname"` +// Apps map[string]interface{} `json:"app_metadata,omitempty"` +// } diff --git a/internal/crud/service.go b/internal/crud/service.go index 5618f2d..22ad748 100644 --- a/internal/crud/service.go +++ b/internal/crud/service.go @@ -1,8 +1,6 @@ package crud -import ( - "github.com/jchenry/jchenry/pkg/db" -) +import "github.com/jchenry/jchenry/pkg/db" type Service interface { // Find returns a pointer to an array of the results found based on params diff --git a/internal/gopher/client.go b/internal/gopher/client.go new file mode 100644 index 0000000..4762e24 --- /dev/null +++ b/internal/gopher/client.go @@ -0,0 +1,79 @@ +package gopher + +import ( + "bufio" + "bytes" + "net" + "sync" +) + +const ( + // RFC 1436 types + Text byte = '0' + Submenu byte = '1' + Nameserver byte = '2' + Error byte = '3' + Binhex byte = '4' + DOS byte = '5' + UUencode byte = '6' + Search byte = '7' + Telnet byte = '8' + Binary byte = '9' + Mirror byte = '+' + Gif byte = 'g' + Image byte = 'I' + Telnet3270 byte = 'T' + + // UnRFC'd Extensions + Doc byte = 'd' + Html byte = 'h' + Info byte = 'i' + Sound byte = 's' +) + +type Client struct { + Socket net.Conn + in *bufio.Reader + out *bufio.Writer + init sync.Once +} + +func (c *Client) Select(selector string) (m Menu, err error) { + c.init.Do(func() { + c.in = bufio.NewReader(c.Socket) + c.out = bufio.NewWriter(c.Socket) + }) + c.out.WriteString(selector) + + for { + if l, _, err := c.in.ReadLine(); err == nil { + s := Selector{} + s.Type = l[0] + bs := bytes.Split(l[1:], []byte{'\t'}) + s.Display = string(bs[0]) + s.Path = string(bs[1]) + s.Hostname = string(bytes.Join(bs[2:3], []byte{':'})) + m = append(m, s) + } else { + break + } + } + + // s := Selector{ + // Type: Text, + // Display: "", + // Hostname: "", + // Path: "", + // } + return Menu{}, nil +} + +type Menu []Selector + +type Selector struct { + Type byte + Display string + Path string + Hostname string + Port string +} diff --git a/internal/http/error.go b/internal/http/error.go new file mode 100644 index 0000000..a36f17f --- /dev/null +++ b/internal/http/error.go @@ -0,0 +1,14 @@ +package http + +import "net/http" + +// Error is an error wrapper for the standard HTTP error codes +type Error int + +func (e Error) Error() string { + return http.StatusText(int(e)) +} + +func (e Error) Code() int { + return int(e) +} diff --git a/internal/http/mux.go b/internal/http/mux.go new file mode 100644 index 0000000..ff066a2 --- /dev/null +++ b/internal/http/mux.go @@ -0,0 +1,8 @@ +package http + +import "net/http" + +type Mux interface { + Handle(pattern string, handler http.Handler) + HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) +} diff --git a/internal/http/server.go b/internal/http/server.go index 5c6063f..363b0a9 100755 --- a/internal/http/server.go +++ b/internal/http/server.go @@ -1,7 +1,8 @@ package http import ( - "log" + + // "log" "net/http" go_http "net/http" ) @@ -17,86 +18,87 @@ type Router interface { AddHandler(method, path string, handler go_http.Handler) } -type Service interface { - Register(uriBase string, restServer *Server) -} +// type Service interface { +// Register(uriBase string, restServer *Server) +// } -type ServiceFunc func(uriBase string, restServer *Server) +// type ServiceFunc func(uriBase string, restServer *Server) -func (f ServiceFunc) Register(uriBase string, restServer *Server) { - f(uriBase, restServer) -} +// func (f ServiceFunc) Register(uriBase string, restServer *Server) { +// f(uriBase, restServer) +// } -var docString = "%s \t%s\t- %s" +// var docString = "%s \t%s\t- %s" type Server struct { router Router middleware Middleware } -func NewServer(m Middleware, r Router) *Server { - s := &Server{ - router: r, - middleware: m, - } +// func NewServer(m Middleware, r Router) *Server { +// s := &Server{ +// router: r, +// middleware: m, +// } - s.middleware.UseHandler(s.router) +// s.middleware.UseHandler(s.router) - return s -} +// return s +// } func (r *Server) Get(path string, documentation string, handle go_http.Handler) *Server { r.handle("GET", path, documentation, handle) return r } -func (r *Server) Patch(path string, documentation string, handle go_http.Handler) *Server { - r.handle("PATCH", path, documentation, handle) - return r -} +// func (r *Server) Patch(path string, documentation string, handle go_http.Handler) *Server { +// r.handle("PATCH", path, documentation, handle) + +// return r +// } func (r *Server) Post(path string, documentation string, handle go_http.Handler) *Server { r.handle("POST", path, documentation, handle) - return r } -func (r *Server) Put(path string, documentation string, handle go_http.Handler) *Server { - r.handle("PUT", path, documentation, handle) - return r -} -func (r *Server) Delete(path string, documentation string, handle go_http.Handler) *Server { - r.handle("DELETE", path, documentation, handle) +// func (r *Server) Put(path string, documentation string, handle go_http.Handler) *Server { +// r.handle("PUT", path, documentation, handle) - return r -} +// return r +// } +// func (r *Server) Delete(path string, documentation string, handle go_http.Handler) *Server { +// r.handle("DELETE", path, documentation, handle) + +// return r +// } func (r *Server) handle(method, path string, documentation string, handler go_http.Handler) { - log.Printf(docString, method, path, documentation) + // log.Printf(docString, method, path, documentation) r.router.AddHandler(method, path, handler) } -func (r *Server) Banner(banner string) *Server { - log.Printf(banner) - return r -} +// func (r *Server) Banner(banner string) *Server { +// log.Printf(banner) +// return r +// } -func (r *Server) Service(basePath string, service Service) *Server { - service.Register(basePath, r) - return r -} -func (r *Server) Static(path string, root go_http.FileSystem) *Server { - r.router.ServeFiles(path, root) - return r -} -func (r *Server) Middleware(handler go_http.Handler) *Server { - r.middleware.UseHandler(handler) - return r -} +// func (r *Server) Service(basePath string, service Service) *Server { +// service.Register(basePath, r) +// return r +// } +// func (r *Server) Static(path string, root go_http.FileSystem) *Server { +// r.router.ServeFiles(path, root) +// return r +// } +// func (r *Server) Middleware(handler go_http.Handler) *Server { +// r.middleware.UseHandler(handler) +// return r +// } -func (r *Server) Run(addr string) { - log.Printf("listening on %s", addr) - log.Fatal(http.ListenAndServe(addr, r.middleware)) -} +// func (r *Server) Run(addr string) { +// log.Printf("listening on %s", addr) +// log.Fatal(http.ListenAndServe(addr, r.middleware)) +// } -func (r *Server) ServeHTTP(w go_http.ResponseWriter, req *go_http.Request) { - r.middleware.ServeHTTP(w, req) -} +// func (r *Server) ServeHTTP(w go_http.ResponseWriter, req *go_http.Request) { +// r.middleware.ServeHTTP(w, req) +// } diff --git a/internal/http/server_test.go b/internal/http/server_test.go index f24c007..bbdb381 100755 --- a/internal/http/server_test.go +++ b/internal/http/server_test.go @@ -1,34 +1,34 @@ package http_test -import ( - "os" +// import ( +// "os" - "github.com/codegangsta/negroni" - "github.com/jchenry/jchenry/http" - "github.com/jchenry/jchenry/rest" -) +// "github.com/codegangsta/negroni" +// "github.com/jchenry/jchenry/http" +// "github.com/jchenry/jchenry/rest" +// ) -func ExampleServer() { - type contact struct { - ID int64 `json:"id"` - First string `json:"firstName"` - Last string `json:"lastName"` - Email string `json:"emailAddress"` - } +// func ExampleServer() { +// type contact struct { +// ID int64 `json:"id"` +// First string `json:"firstName"` +// Last string `json:"lastName"` +// Email string `json:"emailAddress"` +// } - s := http.NewServer( - negroni.Classic(), - http.NewJulienschmidtHTTPRouter()). - Service("", - rest.Collection(new(contact), - nil, - ), - ) +// s := http.NewServer( +// negroni.Classic(), +// http.NewJulienschmidtHTTPRouter()). +// Service("", +// rest.Collection(new(contact), +// nil, +// ), +// ) - port := os.Getenv("PORT") - if port == "" { - port = "8080" - } +// port := os.Getenv("PORT") +// if port == "" { +// port = "8080" +// } - s.Run(":" + port) -} +// s.Run(":" + port) +// } diff --git a/internal/http/service.go b/internal/http/service.go index bf0f23c..9adb4d8 100644 --- a/internal/http/service.go +++ b/internal/http/service.go @@ -26,3 +26,13 @@ package http // MethodConnect = "CONNECT" // MethodOptions = "OPTIONS" // MethodTrace = "TRACE" + +type Service interface { + Register(m *Mux) error +} + +type ServiceFunc func(m *Mux) error + +func (s ServiceFunc) Register(m *Mux) error { + return s(m) +} diff --git a/internal/payments/config.go b/internal/payments/config.go index 23df01c..15875d1 100755 --- a/internal/payments/config.go +++ b/internal/payments/config.go @@ -1,25 +1,25 @@ package payments -import ( - "fmt" - "os" -) +// import ( +// "fmt" +// "os" +// ) -type Config struct { - StripeKey string - StripeProductID string - RedirectURL string - TenantSetup func(subscriptionID, customerID string) (tenantID string) -} +// type Config struct { +// StripeKey string +// StripeProductID string +// RedirectURL string +// TenantSetup func(subscriptionID, customerID string) (tenantID string) +// } -func FromEnv() Config { - return Config{ - StripeKey: os.Getenv("STRIPE_KEY"), - StripeProductID: os.Getenv("STRIPE_PRODUCT_ID"), - RedirectURL: "/", - } -} +// func FromEnv() Config { +// return Config{ +// StripeKey: os.Getenv("STRIPE_KEY"), +// StripeProductID: os.Getenv("STRIPE_PRODUCT_ID"), +// RedirectURL: "/", +// } +// } -func PrintConfig() { - fmt.Printf("%#v\n", FromEnv()) -} +// func PrintConfig() { +// fmt.Printf("%#v\n", FromEnv()) +// } diff --git a/internal/payments/middleware.go b/internal/payments/middleware.go index 64a26d5..6c4d407 100755 --- a/internal/payments/middleware.go +++ b/internal/payments/middleware.go @@ -1,27 +1,26 @@ package payments -import ( - "net/http" +// import ( +// "net/http" - "github.com/jchenry/jchenry/internal/auth" -) +// "github.com/jchenry/x/internal/auth" +// ) -func HasTenantAndSubscription(productID string) func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { - return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { +// func HasTenantAndSubscription(productID string) func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { +// return func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { +// session, err := auth.Store.Get(r, auth.SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - session, err := auth.Store.Get(r, auth.SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if u, ok := session.Values["profile"]; ok { - user := u.(auth.User) - if _, exist := user.Apps[productID]; exist { - next(w, r) - } else { - http.Redirect(w, r, "/subscription", http.StatusSeeOther) - } - } - } -} +// if u, ok := session.Values["profile"]; ok { +// user := u.(auth.User) +// if _, exist := user.Apps[productID]; exist { +// next(w, r) +// } else { +// http.Redirect(w, r, "/subscription", http.StatusSeeOther) +// } +// } +// } +// } diff --git a/internal/payments/service.go b/internal/payments/service.go index abd1895..f89ea35 100755 --- a/internal/payments/service.go +++ b/internal/payments/service.go @@ -1,121 +1,121 @@ package payments -import ( - "fmt" - "net/http" +// import ( +// "fmt" +// "net/http" - "github.com/codegangsta/negroni" - "github.com/jchenry/jchenry/internal/auth" - _http "github.com/jchenry/jchenry/internal/http" - "github.com/stripe/stripe-go" - "github.com/stripe/stripe-go/client" - "github.com/stripe/stripe-go/customer" - "github.com/stripe/stripe-go/plan" - "github.com/stripe/stripe-go/product" - "github.com/stripe/stripe-go/sub" -) +// "github.com/codegangsta/negroni" +// "github.com/jchenry/x/internal/auth" +// _http "github.com/jchenry/x/internal/http" +// "github.com/stripe/stripe-go" +// "github.com/stripe/stripe-go/client" +// "github.com/stripe/stripe-go/customer" +// "github.com/stripe/stripe-go/plan" +// "github.com/stripe/stripe-go/product" +// "github.com/stripe/stripe-go/sub" +// ) -func Service(c Config, auth *auth.ServiceInstance) ServiceInstance { - stripe.Key = c.StripeKey - sc := &client.API{} - sc.Init(c.StripeKey, nil) - return ServiceInstance{ - c: c, - stripe: sc, - auth: auth, - } -} +// func Service(c Config, auth *auth.ServiceInstance) ServiceInstance { +// stripe.Key = c.StripeKey +// sc := &client.API{} +// sc.Init(c.StripeKey, nil) +// return ServiceInstance{ +// c: c, +// stripe: sc, +// auth: auth, +// } +// } -type ServiceInstance struct { - c Config - stripe *client.API - auth *auth.ServiceInstance -} +// type ServiceInstance struct { +// c Config +// stripe *client.API +// auth *auth.ServiceInstance +// } -func (si ServiceInstance) Register(uriBase string, s *_http.Server) { - s.Get(uriBase+"/subscription", "subscription info endpoint", negroni.New( - negroni.HandlerFunc(auth.IsAuthenticated), - negroni.Wrap(http.HandlerFunc(si.subscriptionHandler)), - )).Post(uriBase+"/subscription", "subscription payment endpoint", negroni.New( - negroni.HandlerFunc(auth.IsAuthenticated), - negroni.Wrap(http.HandlerFunc(si.paymentHandler)), - )) +// func (si ServiceInstance) Register(uriBase string, s *_http.Server) { +// s.Get(uriBase+"/subscription", "subscription info endpoint", negroni.New( +// negroni.HandlerFunc(auth.IsAuthenticated), +// negroni.Wrap(http.HandlerFunc(si.subscriptionHandler)), +// )).Post(uriBase+"/subscription", "subscription payment endpoint", negroni.New( +// negroni.HandlerFunc(auth.IsAuthenticated), +// negroni.Wrap(http.HandlerFunc(si.paymentHandler)), +// )) -} +// } -func (si ServiceInstance) subscriptionHandler(w http.ResponseWriter, r *http.Request) { +// func (si ServiceInstance) subscriptionHandler(w http.ResponseWriter, r *http.Request) { - prod, _ := product.Get(si.c.StripeProductID, nil) +// prod, _ := product.Get(si.c.StripeProductID, nil) - params := &stripe.PlanListParams{ - Product: &si.c.StripeProductID, - } +// params := &stripe.PlanListParams{ +// Product: &si.c.StripeProductID, +// } - it := plan.List(params) - var plans []stripe.Plan - for it.Next() { - plans = append(plans, *it.Plan()) - } - _http.RenderTemplate(w, "subscription", offering{Product: *prod, Plans: plans}) -} +// it := plan.List(params) +// var plans []stripe.Plan +// for it.Next() { +// plans = append(plans, *it.Plan()) +// } +// _http.RenderTemplate(w, "subscription", offering{Product: *prod, Plans: plans}) +// } -type offering struct { - Product stripe.Product - Plans []stripe.Plan -} +// type offering struct { +// Product stripe.Product +// Plans []stripe.Plan +// } -func (si ServiceInstance) paymentHandler(w http.ResponseWriter, r *http.Request) { +// func (si ServiceInstance) paymentHandler(w http.ResponseWriter, r *http.Request) { - session, err := auth.Store.Get(r, auth.SessionName) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// session, err := auth.Store.Get(r, auth.SessionName) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - if u, ok := session.Values["profile"]; ok { - user := u.(auth.User) - r.ParseForm() +// if u, ok := session.Values["profile"]; ok { +// user := u.(auth.User) +// r.ParseForm() - params := &stripe.CustomerParams{ - Email: stripe.String(user.Email), - Name: stripe.String(fmt.Sprintf("%s, %s", user.LastName, user.FirstName)), - } - params.SetSource(r.PostFormValue("stripeToken")) - cus, err := customer.New(params) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// params := &stripe.CustomerParams{ +// Email: stripe.String(user.Email), +// Name: stripe.String(fmt.Sprintf("%s, %s", user.LastName, user.FirstName)), +// } +// params.SetSource(r.PostFormValue("stripeToken")) +// cus, err := customer.New(params) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - p := &stripe.SubscriptionParams{ - Customer: stripe.String(cus.ID), - Items: []*stripe.SubscriptionItemsParams{ - { - Plan: stripe.String(r.PostFormValue("plan")), - }, - }, - } - s, err := sub.New(p) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// p := &stripe.SubscriptionParams{ +// Customer: stripe.String(cus.ID), +// Items: []*stripe.SubscriptionItemsParams{ +// { +// Plan: stripe.String(r.PostFormValue("plan")), +// }, +// }, +// } +// s, err := sub.New(p) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - if si.c.TenantSetup == nil { - panic("need code to setup the tenant") - } +// if si.c.TenantSetup == nil { +// panic("need code to setup the tenant") +// } - if user.Apps == nil { - user.Apps = map[string]interface{}{} - } - user.Apps[si.c.StripeProductID] = si.c.TenantSetup(s.ID, user.ID) - err = si.auth.UpdateUser(user) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } +// if user.Apps == nil { +// user.Apps = map[string]interface{}{} +// } +// user.Apps[si.c.StripeProductID] = si.c.TenantSetup(s.ID, user.ID) +// err = si.auth.UpdateUser(user) +// if err != nil { +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } - http.Redirect(w, r, si.c.RedirectURL, http.StatusSeeOther) +// http.Redirect(w, r, si.c.RedirectURL, http.StatusSeeOther) - } -} +// } +// } diff --git a/internal/rest/collection.go b/internal/rest/collection.go deleted file mode 100755 index 1ef83dd..0000000 --- a/internal/rest/collection.go +++ /dev/null @@ -1,204 +0,0 @@ -package rest - -import ( - "fmt" - "net/http" - "reflect" - "strconv" - "strings" - - _http "github.com/jchenry/jchenry/internal/http" -) - -const ( - //IDPathParameter represents the entity's id in the parameter map IDPathParameter = "id" - IDPathParameter = "id" -) - -// Collection - A Restful Collection interface backed by crud.CrudService -type CollectionInstance struct { - basePath string - name string - instanceType reflect.Type - service CollectionStore -} - -type CollectionStore interface { - // Find returns a pointer to an array of the results found based on params - // or an error - Find(entityArrPtr interface{}, params map[string]interface{}) error - // Create returns the identifier for the newly accepted entity, or error - Create(entityPtr interface{}) error - // Update returns the id of the newly updated entity, or error - Update(entityPtr interface{}) error - // Delete returns whether the entity, specified by id, was successfully deleted - // or error - Delete(entityPtr interface{}) error -} - -// type GetIDPathParameter func(*http.Request) - -// Collection - Create a new instance of RESTCollection -func Collection(entityPtr interface{}, service CollectionStore) *CollectionInstance { - t := reflect.TypeOf(entityPtr).Elem() - return &CollectionInstance{ - name: strings.ToLower(t.Name()), - instanceType: t, - service: service, - } -} - -func (collection *CollectionInstance) Register(uriBase string, restServer *_http.Server) { - plural := properPlural(collection.name) - - urlBase := uriBase + "/" + plural //collection.name + "s" - restServer. - Post(urlBase, "create a "+collection.name, http.HandlerFunc(collection.create)). - Put(urlBase+"/:"+IDPathParameter, "update a "+collection.name, http.HandlerFunc(collection.update)). - Delete(urlBase+"/:"+IDPathParameter, "delete a "+collection.name, http.HandlerFunc(collection.remove)). - Get(urlBase+"/:"+IDPathParameter, "get a "+collection.name+" by id", http.HandlerFunc(collection.find)). - Get(urlBase, "get "+collection.name+"s", http.HandlerFunc(collection.find)) -} - -func properPlural(word string) string { - if strings.HasSuffix(word, "s") { - return word - } else if strings.HasSuffix(word, "y") { - return word[:len(word)-1] + "ies" - } else { - return word + "s" - } -} - -func (collection *CollectionInstance) create(response http.ResponseWriter, request *http.Request) { - entityPtr := reflect.New(collection.instanceType).Interface() //collection.instanceProviderPtr.NewInstance() - - err := _http.ReadEntity(request, entityPtr) - if err != nil { - _http.WriteErrorResponse(response, http.StatusBadRequest, err.Error()) - return - } - - err = collection.service.Create(entityPtr) - if err != nil { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusCreated) - _http.WriteEntity(response, entityPtr) -} - -func (collection *CollectionInstance) update(response http.ResponseWriter, request *http.Request) { - entityPtr := reflect.New(collection.instanceType).Interface() //collection.instanceProviderPtr.NewInstance() - err := _http.ReadEntity(request, entityPtr) - - if err != nil { - _http.WriteErrorResponse(response, http.StatusBadRequest, err.Error()) - return - } - id := request.Form.Get(IDPathParameter) - err = collection.service.Find(&[]interface{}{}, map[string]interface{}{IDPathParameter: id}) - - if err != nil { - if err == _http.ErrNotFound { - _http.WriteErrorResponse(response, http.StatusNotFound, fmt.Sprintf("%v with id %v not found", collection.name, id)) - } else { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - } - return - } - err = collection.service.Update(entityPtr) - if err != nil { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusOK) - _http.WriteEntity(response, entityPtr) -} - -func (collection *CollectionInstance) remove(response http.ResponseWriter, request *http.Request) { - id := request.Form.Get(IDPathParameter) - err := collection.service.Find(&[]interface{}{}, map[string]interface{}{IDPathParameter: id}) - if err != nil { - if err == _http.ErrNotFound { - _http.WriteErrorResponse(response, http.StatusNotFound, fmt.Sprintf("%v with id %v not found", collection.name, id)) - } else { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - } - return - } - entityPtr := reflect.New(collection.instanceType).Interface() //collection.instanceProviderPtr.NewInstance() - field := reflect.Indirect(reflect.ValueOf(entityPtr)).FieldByName(strings.ToUpper(IDPathParameter)) - if !field.CanSet() { - _http.WriteErrorResponse(response, http.StatusInternalServerError, "entity does not have "+IDPathParameter+" field or field is not setable") - } - parsedID, err := strconv.ParseInt(id, 0, 64) - if err != nil { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - - } - field.SetInt(parsedID) - - err = collection.service.Delete(entityPtr) - if err != nil { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - return - } - - response.WriteHeader(http.StatusNoContent) -} - -func (collection *CollectionInstance) find(response http.ResponseWriter, request *http.Request) { - id := request.Form.Get(IDPathParameter) - arrv := reflect.New(reflect.SliceOf(reflect.PtrTo(collection.instanceType))) - arri := arrv.Interface() - err := collection.service.Find(arri, valuesToMap(request.URL.Query(), id)) - - if err != nil { - if err == _http.ErrNotFound { - _http.WriteErrorResponse(response, http.StatusNotFound, fmt.Sprintf("%v with id %v not found", collection.name, id)) - } else { - _http.WriteErrorResponse(response, http.StatusInternalServerError, err.Error()) - } - return - } - - var results interface{} - - if reflect.Indirect(arrv).Len() == 1 { - results = reflect.Indirect(arrv).Index(0).Interface() - fmt.Println(results) - } else { - results = &ResultSetResponse{ - Metadata: Metadata{ - ResultSet: ResultSetMetadata{ - Count: reflect.Indirect(arrv).Len(), - //TODO: need to accomidate limit and offset here. - }, - }, - Results: arri, - } - } - - response.WriteHeader(http.StatusOK) - _http.WriteEntity(response, results) -} - -func valuesToMap(params map[string][]string, id string) map[string]interface{} { - m := make(map[string]interface{}) - for key, val := range params { - if len(val) == 1 { - m[key] = val[0] - } else { - m[key] = val - } - } - - if id != "" { - m[IDPathParameter] = id - } - - return m -} diff --git a/internal/rest/collection_test.go b/internal/rest/collection_test.go deleted file mode 100755 index ec712de..0000000 --- a/internal/rest/collection_test.go +++ /dev/null @@ -1,294 +0,0 @@ -package rest_test - -// import ( -// "encoding/json" -// "fmt" -// "io/ioutil" -// "log" -// "net/http" -// "net/http/httptest" -// "path/filepath" -// "reflect" -// "runtime" -// "strings" -// "testing" - -// // "github.com/jchenry/crud" -// keel_http "github.com/jchenry/http" -// keel_httptest "github.com/jchenry/http/httptest" -// // "github.com/jchenry/rest" -// ) - -// type TestObject struct { -// ID int64 `json:"id"` -// Name string `json:"name"` -// } - -// var service *crud.InMemoryCrudService -// var instanceType reflect.Type = reflect.TypeOf(TestObject{}) - -// func Setup() { -// if service == nil { -// service = crud.NewInMemoryCrudService() -// } -// log.SetOutput(ioutil.Discard) - -// } - -// // func TestRESTCollectionTestSuite(t *testing.T) { -// // rsuite := new(RESTCollectionTestSuite) -// // rservice = db.NewInMemoryCrudService() -// // rinstanceType = reflect.TypeOf(TestObject{}) -// // log.SetOutput(ioutil.Discard) -// // Run(t, rsuite) -// // } - -// func TestCollectionCreate(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" - -// container := createCollectionContainer(instanceType, service) - -// requestJSON, err := json.Marshal(TestObject{Name: "Foo"}) -// if err != nil { -// Fail(t, "unable to json body") -// } - -// request, err := http.NewRequest("POST", "/testobjects", strings.NewReader(string(requestJSON))) -// request.Header.Add("Content-Type", keel_http.MimeJSON) -// if err != nil { -// Fail(t, "unable to create request") -// } -// response := httptest.NewRecorder() - -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 201, "{\n \"id\": 1,\n \"name\": \"Foo\"\n }") -// } - -// func TestCollectionCreateBadRequest(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" - -// container := createCollectionContainer(instanceType, service) - -// request, err := http.NewRequest("POST", "/testobjects", strings.NewReader(string("{malformedjson}"))) -// request.Header.Add("Content-Type", keel_http.MimeJSON) -// if err != nil { -// Fail(t, "unable to create request") -// } -// response := httptest.NewRecorder() - -// container.ServeHTTP(response, request) - -// keel_httptest.ValidateResponse(t, response, 400, "{\n \"Status\": 400,\n \"DeveloperMessage\": \"invalid character 'm' looking for beginning of object key string\"\n }") -// } - -// func TestCollectionCreateInternalError(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" - -// container := createCollectionContainer(instanceType, NewAllFailingCrudService()) - -// requestJSON, err := json.Marshal(TestObject{Name: "Foo"}) -// if err != nil { -// Fail(t, "unable to json body") -// } -// request, err := http.NewRequest("POST", "/testobjects", strings.NewReader(string(requestJSON))) -// request.Header.Add("Content-Type", keel_http.MimeJSON) -// if err != nil { -// Fail(t, "unable to create request") -// } -// response := httptest.NewRecorder() - -// container.ServeHTTP(response, request) - -// keel_httptest.ValidateResponse(t, response, 500, "{\n \"Status\": 500,\n \"DeveloperMessage\": \"unable to create\"\n }") -// } - -// func TestCollectionUpdate(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 1 - -// container := createCollectionContainer(instanceType, service) - -// requestJSON := keel_httptest.GetJSONReader(t, to) - -// request, response := keel_httptest.GetRequestAndResponse(t, "PUT", "/testobjects/1", requestJSON) - -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 200, "{\n \"id\": 1,\n \"name\": \"foo\"\n }") - -// } - -// func TestCollectionUpdateBadRequest(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 1 - -// container := createCollectionContainer(instanceType, service) - -// request, response := keel_httptest.GetRequestAndResponse(t, "PUT", "/testobjects/1", strings.NewReader(string("{malformedjson}"))) - -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 400, "{\n \"Status\": 400,\n \"DeveloperMessage\": \"invalid character 'm' looking for beginning of object key string\"\n }") -// } - -// func TestCollectionUpdateBadEntityID(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 42 - -// container := createCollectionContainer(instanceType, service) -// requestJSON := keel_httptest.GetJSONReader(t, to) - -// request, response := keel_httptest.GetRequestAndResponse(t, "PUT", "/testobjects/42", requestJSON) - -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 404, "{\n \"Status\": 404,\n \"DeveloperMessage\": \"testobject with id 42 not found\"\n }") -// } - -// func TestCollectionUpdateInternalErrorOnFind(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 1 - -// container := createCollectionContainer(instanceType, NewAllFailingCrudService()) -// requestJSON := keel_httptest.GetJSONReader(t, to) -// request, response := keel_httptest.GetRequestAndResponse(t, "PUT", "/testobjects/1", requestJSON) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 500, "{\n \"Status\": 500,\n \"DeveloperMessage\": \"unable to find\"\n }") -// } - -// func TestCollectionUpdateInternalErrorOnServiceUpdate(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 1 - -// container := createCollectionContainer(instanceType, NewFailingCrudService(service, false, false, true, false)) -// requestJSON := keel_httptest.GetJSONReader(t, to) -// request, response := keel_httptest.GetRequestAndResponse(t, "PUT", "/testobjects/1", requestJSON) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 500, "{\n \"Status\": 500,\n \"DeveloperMessage\": \"unable to update\"\n }") -// } - -// func TestDelete(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "deleteObject" - -// _, err := service.Create(to) -// if err != nil { -// Fail(t, "unable to create deleteObject") -// } - -// container := createCollectionContainer(instanceType, service) -// uri := fmt.Sprintf("/testobjects/%d", int(to.ID)) -// request, response := keel_httptest.GetRequestAndResponse(t, "DELETE", uri, nil) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 204, "") - -// request, response = keel_httptest.GetRequestAndResponse(t, "DELETE", uri, nil) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 404, "{\n \"Status\": 404,\n \"DeveloperMessage\": \"testobject with id 2 not found\"\n }") - -// } - -// func TestCollectionDeleteInternalErrorOnFind(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 1 - -// container := createCollectionContainer(instanceType, NewAllFailingCrudService()) -// requestJSON := keel_httptest.GetJSONReader(t, to) -// request, response := keel_httptest.GetRequestAndResponse(t, "DELETE", "/testobjects/1", requestJSON) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 500, "{\n \"Status\": 500,\n \"DeveloperMessage\": \"unable to find\"\n }") -// } - -// func TestCollectionDeleteInternalErrorOnServiceDelete(t *testing.T) { -// Setup() -// to := new(TestObject) -// to.Name = "foo" -// to.ID = 1 - -// container := createCollectionContainer(instanceType, NewFailingCrudService(service, false, false, false, true)) -// requestJSON := keel_httptest.GetJSONReader(t, to) -// request, response := keel_httptest.GetRequestAndResponse(t, "DELETE", "/testobjects/1", requestJSON) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 500, "{\n \"Status\": 500,\n \"DeveloperMessage\": \"unable to delete\"\n }") -// } - -// func TestCollectionFindSingleItem(t *testing.T) { -// Setup() -// container := createCollectionContainer(instanceType, service) -// uri := fmt.Sprintf("/testobjects/%d", 1) -// request, response := keel_httptest.GetRequestAndResponse(t, "GET", uri, nil) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 200, "{\n \"id\": 1,\n \"name\": \"foo\"\n }") - -// } - -// //TODO we really should support thie in InMemoryCrudService for code coverage purposes -// // func TestFindOnQuery(t *testing.T) { -// // container := createCollectionContainer(TestObject{}, service) -// // uri := "/testobjects?name=foo" -// // request, response := keel_httptest.GetRequestAndResponse(t, "GET", uri, nil) -// // container.ServeHTTP(response, request) -// // keel_httptest.ValidateResponse(t, response, 200, "{\n \"id\": 1,\n \"name\": \"Foo\"\n }") -// // -// // } - -// func TestCollectionFindInternalFailure(t *testing.T) { -// Setup() -// container := createCollectionContainer(instanceType, NewFailingCrudService(service, false, true, false, false)) -// uri := fmt.Sprintf("/testobjects/%d", 1) -// request, response := keel_httptest.GetRequestAndResponse(t, "GET", uri, nil) -// container.ServeHTTP(response, request) -// keel_httptest.ValidateResponse(t, response, 500, "{\n \"Status\": 500,\n \"DeveloperMessage\": \"unable to find\"\n }") -// } - -// func createCollectionContainer(entity reflect.Type, service crud.CrudService) *rest.Server { -// s := rest.NewServer(). -// Service("", rest.NewCollection(entity, service)) -// return s -// } - -// func Fail(tb testing.TB, msg string) { -// Assert(tb, false, msg) -// } - -// // Assert fails the test if the condition is false. -// func Assert(tb testing.TB, condition bool, msg string, v ...interface{}) { -// if !condition { -// _, file, line, _ := runtime.Caller(1) -// fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...) -// tb.FailNow() -// } -// } - -// func NewAllFailingCrudService() crud.CrudService { -// return failingCrudService{} -// } - -// type failingCrudService struct{} - -// func (a *failingCrudService) Find(entityArrPtr interface{}, params map[string]interface{}) (err error) { -// return crud.ErrNotFound -// } -// func (a *failingCrudService) Create(entityPtr interface{}) (id interface{}, err error) { -// return nil, crud.ErrBadIDType -// } -// func (a *failingCrudService) Update(entityPtr interface{}) (id interface{}, err error) { -// return nil, crud.ErrNotFound -// } -// func (a *failingCrudService) Delete(entityPtr interface{}) error { return crud.ErrNotFound } diff --git a/internal/rest/resultset_response.go b/internal/rest/resultset_response.go deleted file mode 100755 index ab60ef2..0000000 --- a/internal/rest/resultset_response.go +++ /dev/null @@ -1,19 +0,0 @@ -package rest - -//ResultSetMetadata - -type ResultSetMetadata struct { - Count int `json:"count"` - Offset int `json:"offset"` - Limit int `json:"limit"` -} - -//Metadata - -type Metadata struct { - ResultSet ResultSetMetadata `json:"resultset"` -} - -//ResultSetResponse - -type ResultSetResponse struct { - Metadata Metadata `json:"metadata"` - Results interface{} `json:"results"` -} diff --git a/internal/rss/model.go b/internal/rss/model.go new file mode 100644 index 0000000..72c8e25 --- /dev/null +++ b/internal/rss/model.go @@ -0,0 +1,118 @@ +package rss + +import ( + "encoding/json" + "time" +) + +// Feed is an RSS Feed +type Feed struct { + Title string `json:"title,omitempty"` + Link string `json:"link,omitempty"` + Description string `json:"description,omitempty"` + Language string `json:"language,omitempty"` + Copyright string `json:"copyright,omitempty"` + ManagingEditor string `json:"managingEditor,omitempty"` + WebMaster string `json:"webMaster,omitempty"` + PubDate string `json:"pubDate,omitempty"` + PubDateParsed *time.Time `json:"pubDateParsed,omitempty"` + LastBuildDate string `json:"lastBuildDate,omitempty"` + LastBuildDateParsed *time.Time `json:"lastBuildDateParsed,omitempty"` + Categories []*Category `json:"categories,omitempty"` + Generator string `json:"generator,omitempty"` + Docs string `json:"docs,omitempty"` + TTL string `json:"ttl,omitempty"` + Image *Image `json:"image,omitempty"` + Rating string `json:"rating,omitempty"` + SkipHours []string `json:"skipHours,omitempty"` + SkipDays []string `json:"skipDays,omitempty"` + Cloud *Cloud `json:"cloud,omitempty"` + TextInput *TextInput `json:"textInput,omitempty"` + // DublinCoreExt *ext.DublinCoreExtension `json:"dcExt,omitempty"` + // ITunesExt *ext.ITunesFeedExtension `json:"itunesExt,omitempty"` + // Extensions ext.Extensions `json:"extensions,omitempty"` + Items []*Item `json:"items"` + Version string `json:"version"` +} + +func (f Feed) String() string { + json, _ := json.MarshalIndent(f, "", " ") + return string(json) +} + +// Item is an RSS Item +type Item struct { + Title string `json:"title,omitempty"` + Link string `json:"link,omitempty"` + Description string `json:"description,omitempty"` + Content string `json:"content,omitempty"` + Author string `json:"author,omitempty"` + Categories []*Category `json:"categories,omitempty"` + Comments string `json:"comments,omitempty"` + Enclosure *Enclosure `json:"enclosure,omitempty"` + GUID *GUID `json:"guid,omitempty"` + PubDate string `json:"pubDate,omitempty"` + PubDateParsed *time.Time `json:"pubDateParsed,omitempty"` + Source *Source `json:"source,omitempty"` + // DublinCoreExt *ext.DublinCoreExtension `json:"dcExt,omitempty"` + // ITunesExt *ext.ITunesItemExtension `json:"itunesExt,omitempty"` + // Extensions ext.Extensions `json:"extensions,omitempty"` +} + +// Image is an image that represents the feed +type Image struct { + URL string `json:"url,omitempty"` + Link string `json:"link,omitempty"` + Title string `json:"title,omitempty"` + Width string `json:"width,omitempty"` + Height string `json:"height,omitempty"` + Description string `json:"description,omitempty"` +} + +// Enclosure is a media object that is attached to +// the item +type Enclosure struct { + URL string `json:"url,omitempty"` + Length string `json:"length,omitempty"` + Type string `json:"type,omitempty"` +} + +// GUID is a unique identifier for an item +type GUID struct { + Value string `json:"value,omitempty"` + IsPermalink string `json:"isPermalink,omitempty"` +} + +// Source contains feed information for another +// feed if a given item came from that feed +type Source struct { + Title string `json:"title,omitempty"` + URL string `json:"url,omitempty"` +} + +// Category is category metadata for Feeds and Entries +type Category struct { + Domain string `json:"domain,omitempty"` + Value string `json:"value,omitempty"` +} + +// TextInput specifies a text input box that +// can be displayed with the channel +type TextInput struct { + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Name string `json:"name,omitempty"` + Link string `json:"link,omitempty"` +} + +// Cloud allows processes to register with a +// cloud to be notified of updates to the channel, +// implementing a lightweight publish-subscribe protocol +// for RSS feeds +type Cloud struct { + Domain string `json:"domain,omitempty"` + Port string `json:"port,omitempty"` + Path string `json:"path,omitempty"` + RegisterProcedure string `json:"registerProcedure,omitempty"` + Protocol string `json:"protocol,omitempty"` +} diff --git a/internal/rss/parser.go b/internal/rss/parser.go new file mode 100644 index 0000000..a5a98b9 --- /dev/null +++ b/internal/rss/parser.go @@ -0,0 +1,21 @@ +package rss + +import ( + "io" + + "golang.org/x/net/html" +) + +func Parse(r io.Reader) *Feed { + + // z := html.NewTokenizer(r) + + return nil +} + +func parseFeed(z html.Tokenizer) *Feed { + z.Next() + return nil +} + +func parseVersion(z html.Tokenizer) {} diff --git a/pkg/http/auth.go b/net/http/auth.go similarity index 100% rename from pkg/http/auth.go rename to net/http/auth.go diff --git a/pkg/http/multihandler.go b/net/http/multihandler.go similarity index 99% rename from pkg/http/multihandler.go rename to net/http/multihandler.go index b859ab9..bb5d8f8 100644 --- a/pkg/http/multihandler.go +++ b/net/http/multihandler.go @@ -32,6 +32,5 @@ func MutliHandler(h map[string]http.Handler) (http.HandlerFunc, error) { } else { NotFoundHandler.ServeHTTP(w, r) } - }, nil } diff --git a/pkg/http/status_handler.go b/net/http/status_handler.go similarity index 100% rename from pkg/http/status_handler.go rename to net/http/status_handler.go diff --git a/rest/collection.go b/rest/collection.go new file mode 100755 index 0000000..94426bb --- /dev/null +++ b/rest/collection.go @@ -0,0 +1,107 @@ +package rest + +import ( + "net/http" + "net/url" + "path/filepath" + "sync" + + "github.com/jchenry/x/encoding" +) + +type CollectionStore interface { + All(params url.Values) (interface{}, error) + Get(id string) (interface{}, error) + Delete(id string) error + Update(e interface{}) error + New(e interface{}) error +} + +// Example: Collection(p, c, JSONEncoder, json.Decode(func()interface{}{return &foo{}})) + +// type Decoder func(io.Reader) (interface{}, error) + +func Collection(pool *sync.Pool, store CollectionStore, encode EntityEncoder, decode encoding.Decoder) http.HandlerFunc { + return EntityHandler( + collectionGet(store, encode), + collectionPost(store, encode, decode, pool), + collectionPut(store, encode, decode, pool), + collectionDelete(store, encode), + ) +} + +func collectionGet(store CollectionStore, encode EntityEncoder) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { // GET + if id := filepath.Base(r.URL.Path); id != "" { + if e, err := store.Get(id); err == nil { // handle individual entity + encode(w, e) + } else { + w.WriteHeader(http.StatusInternalServerError) + encode(w, err) + } + } else { + if params, err := url.ParseQuery(r.URL.RawQuery); err == nil { + if e, err := store.All(params); err == nil { // handle all entities + encode(w, e) + } else { + // TODO: we really should write a header here, but need to figure out what it should be + w.WriteHeader(http.StatusInternalServerError) + } + } else { + // encode(w, err) + w.WriteHeader(http.StatusBadRequest) + + } + } + } +} + +func collectionPost(store CollectionStore, encode EntityEncoder, decode encoding.Decoder, pool *sync.Pool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { // POST TODO + e := pool.New() + defer pool.Put(e) + if err := decode(r.Body, e); err == nil { + if err = store.New(e); err == nil { + w.WriteHeader(http.StatusCreated) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + } else { + w.WriteHeader(http.StatusBadRequest) + } + } +} + +func collectionPut(store CollectionStore, encode EntityEncoder, decode encoding.Decoder, pool *sync.Pool) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { // PUT TODO + e := pool.New() + defer pool.Put(e) + if err := decode(r.Body, e); err == nil { + if err = store.Update(e); err == nil { + w.WriteHeader(http.StatusAccepted) + encode(w, e) + } else { + w.WriteHeader(http.StatusInternalServerError) + encode(w, err) + } + } else { + w.WriteHeader(http.StatusBadRequest) + encode(w, err) + + } + } +} + +func collectionDelete(store CollectionStore, encode EntityEncoder) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { // DELETE TODO + if id := filepath.Base(r.URL.Path); id != "" { + if err := store.Delete(id); err == nil { + w.WriteHeader(http.StatusNoContent) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + } else { + w.WriteHeader(http.StatusBadRequest) + } + } +} diff --git a/rest/entity_handler.go b/rest/entity_handler.go new file mode 100644 index 0000000..a96f1a4 --- /dev/null +++ b/rest/entity_handler.go @@ -0,0 +1,23 @@ +package rest + +import ( + gohttp "net/http" + + "github.com/jchenry/x/net/http" +) + +// EntityHandler returns a handler that provides restful verbs, following a CRUD model +func EntityHandler( + get gohttp.Handler, + post gohttp.Handler, + put gohttp.Handler, + delete gohttp.Handler, +) gohttp.HandlerFunc { + h, _ := http.MutliHandler(map[string]gohttp.Handler{ + gohttp.MethodGet: get, + gohttp.MethodPost: post, + gohttp.MethodPut: put, + gohttp.MethodDelete: delete, + }) + return h +} diff --git a/rest/response_encoder.go b/rest/response_encoder.go new file mode 100644 index 0000000..7a69b5d --- /dev/null +++ b/rest/response_encoder.go @@ -0,0 +1,32 @@ +package rest + +import ( + "net/http" + + "github.com/jchenry/x/encoding" + "github.com/jchenry/x/encoding/json" + "github.com/jchenry/x/encoding/xml" +) + +type EntityEncoder func(w http.ResponseWriter, e interface{}) + +func JSONEncoder(w http.ResponseWriter, e interface{}) error { + return EntityResponseEncoder(w, "application/json", json.Encoder, e) +} + +func XMLEncoder(w http.ResponseWriter, e interface{}) error { + return EntityResponseEncoder(w, "application/xml", xml.Encoder, e) +} + +func EntityResponseEncoder(w http.ResponseWriter, contentType string, encoder encoding.Encoder, e interface{}) error { + w.Header().Set("content-type", contentType) + return encoder(w, e) +} + +func ErrorResponseEncoder(w http.ResponseWriter, contentType string, encoder encoding.Encoder, status int, err error) error { + w.WriteHeader(status) + return EntityResponseEncoder(w, contentType, encoder, map[string]interface{}{ + "status": status, + "message": err.Error, + }) +} diff --git a/scripts/bin/openapigen.bash b/scripts/bin/openapigen.bash deleted file mode 100755 index a4ea025..0000000 --- a/scripts/bin/openapigen.bash +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \ - -i $1 \ #https://raw.githubusercontent.com/openapitools/openapi-generator/master/modules/openapi-generator/src/test/resources/2_0/petstore.yaml \ - -g go \ - -o /local/out/go \ No newline at end of file diff --git a/scripts/bin/tel.bash b/scripts/bin/tel.bash deleted file mode 100755 index 40d1246..0000000 --- a/scripts/bin/tel.bash +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -# A port of plan9 'tel' program - -for var in "$@" -do - if test -f "$HOME/.tel"; then - grep -i $1 $HOME/.tel - fi - - grep -hi $1 /usr/lib/tel /usr/lib/areacodes -done - -exit - - diff --git a/pkg/snowflake/README.md b/snowflake/README.md similarity index 100% rename from pkg/snowflake/README.md rename to snowflake/README.md diff --git a/pkg/snowflake/snowflake.go b/snowflake/snowflake.go similarity index 100% rename from pkg/snowflake/snowflake.go rename to snowflake/snowflake.go diff --git a/pkg/snowflake/snowflake_test.go b/snowflake/snowflake_test.go similarity index 100% rename from pkg/snowflake/snowflake_test.go rename to snowflake/snowflake_test.go diff --git a/pkg/arvelie/arvelie.go b/time/arvelie/arvelie.go similarity index 100% rename from pkg/arvelie/arvelie.go rename to time/arvelie/arvelie.go diff --git a/pkg/arvelie/arvelie_test.go b/time/arvelie/arvelie_test.go similarity index 96% rename from pkg/arvelie/arvelie_test.go rename to time/arvelie/arvelie_test.go index 166702c..7744519 100755 --- a/pkg/arvelie/arvelie_test.go +++ b/time/arvelie/arvelie_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/jchenry/libs/arvelie" + "github.com/jchenry/x/time/arvelie" ) func TestFromDate(t *testing.T) { @@ -49,5 +49,4 @@ func TestToDate(t *testing.T) { t.Fail() } } - } diff --git a/pkg/arvelie/doc.go b/time/arvelie/doc.go similarity index 100% rename from pkg/arvelie/doc.go rename to time/arvelie/doc.go diff --git a/pkg/neralie/doc.go b/time/neralie/doc.go similarity index 100% rename from pkg/neralie/doc.go rename to time/neralie/doc.go diff --git a/pkg/neralie/neralie.go b/time/neralie/neralie.go similarity index 100% rename from pkg/neralie/neralie.go rename to time/neralie/neralie.go diff --git a/pkg/neralie/neralie_test.go b/time/neralie/neralie_test.go similarity index 96% rename from pkg/neralie/neralie_test.go rename to time/neralie/neralie_test.go index 200fa28..1c5d7eb 100755 --- a/pkg/neralie/neralie_test.go +++ b/time/neralie/neralie_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/jchenry/libs/neralie" + "github.com/jchenry/x/time/neralie" ) func TestFromTime(t *testing.T) {