From d1c0ccfcb84f1b8778e38b027a333d03e1f4ae9e Mon Sep 17 00:00:00 2001 From: jloup Date: Sun, 13 May 2018 15:02:48 +0100 Subject: [PATCH] Account information panel. --- api/routes.go | 15 ++++++ api/user.go | 59 +++++++++++++------- cmd/web/js/account.jsx | 120 ++++++++++++++++++++++++++++++----------- cmd/web/js/api.js | 8 +++ cmd/web/js/main.jsx | 4 +- 5 files changed, 152 insertions(+), 54 deletions(-) diff --git a/api/routes.go b/api/routes.go index d0e8cec..404f821 100644 --- a/api/routes.go +++ b/api/routes.go @@ -48,6 +48,13 @@ var Groups = []Group{ {"GET", []gin.HandlerFunc{GetPortfolio}, "/:name/portfolio"}, }, }, + { + "/user", + []Middleware{JwtAuth, UserConfirmed, OtpAuth}, + []Route{ + {"GET", []gin.HandlerFunc{UserAccount}, "/account"}, + }, + }, } func Signup(c *gin.Context) { @@ -169,3 +176,11 @@ func ConfirmEmail(c *gin.Context) { RunQuery(query, c) } + +func UserAccount(c *gin.Context) { + query := &UserAccountQuery{} + + query.In.User = GetUser(c) + + RunQuery(query, c) +} diff --git a/api/user.go b/api/user.go index 2848696..a2737fd 100644 --- a/api/user.go +++ b/api/user.go @@ -16,6 +16,26 @@ const ( VALID_EMAIL_REGEX = `(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$` ) +func UserConfirmed(c *gin.Context) *Error { + user, exists := c.Get("user") + + if !exists { + return &Error{NotAuthorized, "not authorized", fmt.Errorf("no user key in context")} + } + + if user.(db.User).Status != db.Confirmed { + return &Error{UserNotConfirmed, "user awaiting admin validation", fmt.Errorf("user '%v' not confirmed", user)} + } + + return nil +} + +func GetUser(c *gin.Context) db.User { + user, _ := c.Get("user") + + return user.(db.User) +} + func IsValidEmailAddress(email string) bool { r := regexp.MustCompile(VALID_EMAIL_REGEX) @@ -142,26 +162,6 @@ func (q SigninQuery) Run() (interface{}, *Error) { return SignResult{token}, nil } -func UserConfirmed(c *gin.Context) *Error { - user, exists := c.Get("user") - - if !exists { - return &Error{NotAuthorized, "not authorized", fmt.Errorf("no user key in context")} - } - - if user.(db.User).Status != db.Confirmed { - return &Error{UserNotConfirmed, "user awaiting admin validation", fmt.Errorf("user '%v' not confirmed", user)} - } - - return nil -} - -func GetUser(c *gin.Context) db.User { - user, _ := c.Get("user") - - return user.(db.User) -} - type ConfirmEmailQuery struct { In struct { Token string @@ -214,3 +214,22 @@ func (q ConfirmEmailQuery) Run() (interface{}, *Error) { return nil, nil } + +type UserAccountQuery struct { + In struct { + User db.User + } + Out struct { + Email string `json:"email"` + } +} + +func (q UserAccountQuery) ValidateParams() *Error { + return nil +} + +func (q UserAccountQuery) Run() (interface{}, *Error) { + q.Out.Email = q.In.User.Email + + return q.Out, nil +} diff --git a/cmd/web/js/account.jsx b/cmd/web/js/account.jsx index c80be33..3dc8afd 100644 --- a/cmd/web/js/account.jsx +++ b/cmd/web/js/account.jsx @@ -1,15 +1,68 @@ import Api from './api.js'; import React from 'react'; +import classnames from 'classnames'; + +class Panel extends React.Component { + render = () => { + if (this.props.component === null) { + return
; + } + + var className = classnames('row', this.props.topClassName); + + return ( +
+
+
+
{this.props.title}
+
+
+ {this.props.component} +
+
); + } +} + +class AccountInformation extends React.Component { + constructor(props) { + super(props); + this.state = {'email': null}; + } + + loadAccount = () => { + Api.Call('USER_ACCOUNT', {}, function(err, status, data) { + if (err) { + console.error(err, data); + return; + } + + this.setState({'email': data.email}); + }.bind(this)); + } + + componentDidMount = () => { + this.loadAccount(); + } + + render = () => { + var component =

Loading...

; + if (this.state.email !== null) { + component =

Email: {this.state.email}

; + } + + return component; + } + +} class PoloniexConfiguration extends React.Component { constructor(props) { super(props); - this.state = {'apiKey': '', 'apiSecret': '', 'apiRequested': false, 'status': 'loading', 'editMode': false}; + this.state = {'apiKey': '', 'apiSecret': '', 'status': 'loading', 'editMode': false}; } checkCredentials = () => { Api.Call('MARKET_TEST_CREDENTIALS', {'name': 'poloniex'}, function(err, status, data) { - this.setState({'apiRequested': true}); if (err) { console.error(err, data); if (err.code === 'invalid_market_credentials') { @@ -53,7 +106,7 @@ class PoloniexConfiguration extends React.Component { onEditClick = () => { Api.Call('MARKET', {'name': 'poloniex'}, function(err, status, data) { - this.setState({'apiRequested': true, 'editMode': true}); + this.setState({'editMode': true}); if (err) { console.error(err, data); return; @@ -90,11 +143,8 @@ class PoloniexConfiguration extends React.Component { console.error('unknown status', this.state.status); displayText = null; } - if (this.state.apiRequested === false) { - return
; - } + return ( -
-
); } } @@ -140,33 +189,40 @@ class PoloniexCredentialsForm extends React.Component { } return ( -
-
- Poloniex credentials -
-
-
- {this.props.statusMessage} -
-
-
-
-
- - - - -
-
-
+ +
+
+ {this.props.statusMessage}
+
+
+
+ + + + +
+
+
+
); } } -export default PoloniexConfiguration; +class UserAccount extends React.Component { + render = () => { + return ( + + } title="Account" /> + } title="Poloniex credentials" topClassName="api-credentials-form" /> + + ); + } +} + +export default UserAccount; diff --git a/cmd/web/js/api.js b/cmd/web/js/api.js index 62530ba..63355f0 100644 --- a/cmd/web/js/api.js +++ b/cmd/web/js/api.js @@ -116,6 +116,14 @@ var ApiEndpoints = { return '/market/' + params.name + '/update'; } }, + 'USER_ACCOUNT': { + 'type': 'GET', + 'auth': true, + 'parameters': [], + 'buildUrl': function(params) { + return '/user/account'; + } + }, 'OTP_ENROLL': { 'type': 'GET', 'auth': true, diff --git a/cmd/web/js/main.jsx b/cmd/web/js/main.jsx index dfc3337..7fa2d26 100644 --- a/cmd/web/js/main.jsx +++ b/cmd/web/js/main.jsx @@ -4,7 +4,7 @@ import PasswordResetForm from './password_reset.js'; import ChangePasswordForm from './change_password.js'; import OtpEnrollForm from './otp.js'; import PoloniexController from './poloniex.js'; -import PoloniexConfiguration from './account.js'; +import UserAccount from './account.js'; import App from './app.js'; import Api from './api.js'; import cookies from './cookies.js'; @@ -97,7 +97,7 @@ App.page('/me', true, function(context) { App.page('/account', true, function(context) { App.mount(
- +
); }); -- 2.41.0