Skip to content

Commit

Permalink
Ability to create a session with the correct user credentials
Browse files Browse the repository at this point in the history
  • Loading branch information
dimroc committed Jul 20, 2018
1 parent 6fc569e commit 5cd4bda
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 9 deletions.
1 change: 1 addition & 0 deletions cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Client struct {
Auth Authenticator
UserInitializer UserInitializer
Runner Runner
RemoteClient RemoteClient
}

func (cli *Client) errorOut(err error) error {
Expand Down
85 changes: 78 additions & 7 deletions cmd/client_remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
Expand All @@ -13,6 +14,7 @@ import (

"github.com/manyminds/api2go/jsonapi"
homedir "github.com/mitchellh/go-homedir"
"github.com/smartcontractkit/chainlink/store"
"github.com/smartcontractkit/chainlink/store/models"
"github.com/smartcontractkit/chainlink/store/presenters"
"github.com/smartcontractkit/chainlink/utils"
Expand All @@ -25,12 +27,7 @@ import (
// DisplayAccountBalance renders a table containing the active account address
// with it's ETH & LINK balance
func (cli *Client) DisplayAccountBalance(c *clipkg.Context) error {
cfg := cli.Config
resp, err := utils.BasicAuthGet(
cfg.BasicAuthUsername,
cfg.BasicAuthPassword,
cfg.ClientNodeURL+"/v2/account_balance",
)
resp, err := cli.RemoteClient.Get("/v2/account_balance")
if err != nil {
return cli.errorOut(err)
}
Expand All @@ -46,10 +43,10 @@ func (cli *Client) DisplayAccountBalance(c *clipkg.Context) error {

// ShowJobSpec returns the status of the given JobID.
func (cli *Client) ShowJobSpec(c *clipkg.Context) error {
cfg := cli.Config
if !c.Args().Present() {
return cli.errorOut(errors.New("Must pass the job id to be shown"))
}
cfg := cli.Config
resp, err := utils.BasicAuthGet(
cfg.BasicAuthUsername,
cfg.BasicAuthPassword,
Expand Down Expand Up @@ -348,3 +345,77 @@ func (cli *Client) renderAPIResponse(resp *http.Response, dst interface{}) error
}
return cli.errorOut(cli.Render(dst))
}

type RemoteClient interface {
Get(string) (*http.Response, error)
Post(string) (*http.Response, error)
}

type httpPrompterClient struct {
config store.Config
client *http.Client
prompter Prompter
}

func NewHttpPrompterClient(cfg store.Config, prompter Prompter) RemoteClient {
return &httpPrompterClient{
config: cfg,
client: &http.Client{},
prompter: prompter,
}
}

func (h *httpPrompterClient) Get(path string) (*http.Response, error) {
cookie, err := h.login()
if err != nil {
return nil, err
}

request, err := http.NewRequest("GET", h.config.ClientNodeURL+path, nil)
if err != nil {
return nil, err
}

request.AddCookie(cookie)
return h.client.Do(request)
}

func (h *httpPrompterClient) Post(path string) (*http.Response, error) {
return nil, errors.New("bogus")
}

func (h *httpPrompterClient) login() (*http.Cookie, error) {
url := h.config.ClientNodeURL + "/sessions"
email := h.prompter.Prompt("Enter email: ")
pwd := h.prompter.PasswordPrompt("Enter password: ")
sessionRequest := models.SessionRequest{Email: email, Password: pwd}
b := new(bytes.Buffer)
err := json.NewEncoder(b).Encode(sessionRequest)
if err != nil {
return nil, err
}
req, err := http.NewRequest("POST", url, b)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")

resp, err := h.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

_, err = parseResponse(resp)
if err != nil {
return nil, err
}

cookies := resp.Cookies()
fmt.Println(cookies)
fmt.Println("response", resp)
if len(cookies) < 1 {
return nil, errors.New("Did not receive cookie with session id")
}
return cookies[0], nil
}
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,14 @@ func Run(client *cmd.Client, args ...string) {
// NewProductionClient configures an instance of the CLI to be used
// in production.
func NewProductionClient() *cmd.Client {
cfg := store.NewConfig()
return &cmd.Client{
Renderer: cmd.RendererTable{Writer: os.Stdout},
Config: store.NewConfig(),
Config: cfg,
AppFactory: cmd.ChainlinkAppFactory{},
Auth: cmd.TerminalAuthenticator{Prompter: cmd.NewTerminalPrompter()},
UserInitializer: cmd.NewTerminalUserInitializer(),
Runner: cmd.ChainlinkRunner{},
RemoteClient: cmd.NewHttpPrompterClient(cfg, cmd.NewTerminalPrompter()),
}
}
14 changes: 14 additions & 0 deletions store/models/orm.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package models

import (
"errors"
"fmt"
"math/big"
"reflect"
Expand Down Expand Up @@ -317,6 +318,19 @@ func (orm *ORM) FindUserBySession(sessionId string) (User, error) {
return user, nil
}

func (orm *ORM) CheckPasswordForSession(sr SessionRequest) (string, error) {
user, err := orm.FindUser()
if err != nil {
return "", err
}

if utils.CheckPasswordHash(sr.Password, user.HashedPassword) {
user.SessionID = utils.NewBytes32ID()
return user.SessionID, orm.Save(&user)
}
return "", errors.New("Invalid password")
}

func (orm *ORM) DeleteUser() (User, error) {
user, err := orm.FindUser()
if err != nil {
Expand Down
5 changes: 5 additions & 0 deletions store/models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ func NewUser(email, plainPwd string) (User, error) {
CreatedAt: Time{Time: time.Now()},
}, nil
}

type SessionRequest struct {
Email string `json:"email"`
Password string `json:"password"`
}
17 changes: 16 additions & 1 deletion web/sessions_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package web
import (
"errors"

"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/smartcontractkit/chainlink/services"
"github.com/smartcontractkit/chainlink/store/models"
)

// SnapshotsController manages Snapshot requests.
Expand All @@ -16,9 +18,22 @@ type SessionsController struct {
// Example:
// "/assignments/:AID/snapshots"
func (sc *SessionsController) Create(c *gin.Context) {
publicError(c, 404, errors.New("Job not found"))
session := sessions.Default(c)
var sr models.SessionRequest
if err := c.ShouldBindJSON(&sr); err != nil {
publicError(c, 400, err)
} else if sid, err := sc.App.GetStore().CheckPasswordForSession(sr); err != nil {
publicError(c, 400, err) // TODO: I never differentiate between the errors
} else if err := saveSessionId(session, sid); err != nil {
c.JSON(200, gin.H{})
}
}

func (sc *SessionsController) Destroy(c *gin.Context) {
publicError(c, 404, errors.New("Job not found"))
}

func saveSessionId(session sessions.Session, sessionId string) error {
session.Set(sessionIdKey, sessionId)
return session.Save()
}

0 comments on commit 5cd4bda

Please sign in to comment.