diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/ansible/conf.toml.j2 | 3 | ||||
-rw-r--r-- | cmd/ansible/vars.yml | 50 | ||||
-rw-r--r-- | cmd/app/conf.toml | 3 | ||||
-rw-r--r-- | cmd/app/main.go | 11 | ||||
-rw-r--r-- | cmd/web/Makefile | 2 | ||||
-rw-r--r-- | cmd/web/js/api.js | 21 | ||||
-rw-r--r-- | cmd/web/js/change_password.jsx | 62 | ||||
-rw-r--r-- | cmd/web/js/main.jsx | 34 | ||||
-rw-r--r-- | cmd/web/js/password_reset.jsx | 57 | ||||
-rw-r--r-- | cmd/web/package.json | 1 | ||||
-rw-r--r-- | cmd/web/yarn.lock | 4 |
11 files changed, 220 insertions, 28 deletions
diff --git a/cmd/ansible/conf.toml.j2 b/cmd/ansible/conf.toml.j2 index b2c3137..7b048af 100644 --- a/cmd/ansible/conf.toml.j2 +++ b/cmd/ansible/conf.toml.j2 | |||
@@ -17,6 +17,9 @@ database=0 | |||
17 | [api] | 17 | [api] |
18 | domain="{{ app_domain }}" | 18 | domain="{{ app_domain }}" |
19 | jwt_secret="{{ jwt_secret }}" | 19 | jwt_secret="{{ jwt_secret }}" |
20 | password_reset_secret="{{ reset_password_reset }}" | ||
21 | free_sms_user="20996747" | ||
22 | free_sms_pass="bM2ZPETB4zzWg3" | ||
20 | 23 | ||
21 | [app] | 24 | [app] |
22 | public_dir="/var/cryptoportfolio-app/static" | 25 | public_dir="/var/cryptoportfolio-app/static" |
diff --git a/cmd/ansible/vars.yml b/cmd/ansible/vars.yml index 1de7413..59a5eb8 100644 --- a/cmd/ansible/vars.yml +++ b/cmd/ansible/vars.yml | |||
@@ -1,22 +1,30 @@ | |||
1 | $ANSIBLE_VAULT;1.1;AES256 | 1 | $ANSIBLE_VAULT;1.1;AES256 |
2 | 63613535333830393037646665363566636635366534636261623839326130663431653839346266 | 2 | 66653734343938333339346336333430336239376539663338333431626461656430393931353165 |
3 | 3832643338623561313362663837323234663537663439350a313034326663383235663964626132 | 3 | 3564303163396337646466376265633537636362346434330a376630333634366165353832613063 |
4 | 38343964396265323539396439383731336464393337383833653666643736303539626136383431 | 4 | 36353931626633306565613862396566353138353439666336376231643432343637613636633634 |
5 | 6536316338376538360a343862626636363031353037626462333364623433613861393137353336 | 5 | 6531666131343361340a633839363864643037373638356433613830666137626665343362303363 |
6 | 37396664663030363530333364633266653862393538313835326138663465626638326363656561 | 6 | 64323766333830646463313130316234316161383031646132346633316162366335643137663835 |
7 | 30393836386664633834663838666432383836623432363936343635313835303166393531643966 | 7 | 63663866613335643330653839393762373163366530376538643666653630636462363535613137 |
8 | 33313361383565363232373066306534613465386534386266306564383365373762613361366365 | 8 | 63663966343335346564316462323463666130313733396164663761613966366165653162663432 |
9 | 61366530623863623336643531346463323233323539333139336335383439373132373233663031 | 9 | 66616232633733613766336465336632373765326362383035613465303463306330623632356232 |
10 | 39666535633362383135376534376532333663636136366130653762643164333436313261646137 | 10 | 38636136633661323137336431646666323464383033346239633032336561613433646632363564 |
11 | 37353139633361636163326366616234613466393731373631616138386263383131663537633533 | 11 | 33323737313235313463643866373465366436376138303430633535623335393163343862366264 |
12 | 31393763316561623134623063623735356334363833623939313437386330323837626131356332 | 12 | 35626263336462353264656637643437326635633237333932613666646666313235396561663762 |
13 | 30383863373535366137366138633832623566613061313138396539306536633763633934313562 | 13 | 36373762363662613635633065383037336634323665333865363533616136373565633436653566 |
14 | 35383763653532336539346632623935303634353866636264373262363839326439313837313765 | 14 | 34393033356566663433343864623664386330376339653463623834393036643733666237393964 |
15 | 36303539613734646238636432393166616438666665363363323331373437633362613838653564 | 15 | 32316134653666306134623135636664643461303831376336373839356531663764636433323539 |
16 | 64393639346661646333383466363162633638643838386666383564366665656266333836363435 | 16 | 62663938363437623235383666363163353562646165633564323635343534316130663062373332 |
17 | 35643231323362323566303535303561626139333830393538383635326631656666323166343863 | 17 | 39303239363166366538623763396563616664663038346465336263666365306435376364366337 |
18 | 31393566346531653535393738326166303261376238316532373833616432306638326139353234 | 18 | 66363137303731613638323839393731326539356262626634373136316265323937303863363637 |
19 | 32653132323764316231393634663262313765393230656232343833373438636430643663353965 | 19 | 37313565663534353035313834626139353333386337643263663264376238393030386363613435 |
20 | 36333931303731646333316430646534383531313264353936396565336338663530303434643036 | 20 | 33616432383131303761306265653566306266366263616162323363383365333363363334653132 |
21 | 34356663373533663137636235386164646334356262336464363862643332636661313339303531 | 21 | 32343235666434636361656133636332303131313766326665393233316135323566633433303362 |
22 | 35663833656564393331636139663738323834373862623436633666306661373166 | 22 | 62383431313861323036616331633134386238313034633936353931313838383038373435653235 |
23 | 32333230646439613134613337333762313062613839613232663037363761353664373935356264 | ||
24 | 61386239366330653939613637333264313532666363626633386632376138643265373432373233 | ||
25 | 39313234326430663561343961313732666465613939343839663263353964663963356639633231 | ||
26 | 64663330323761393932613039326339643737303939363033333666346439393631623038316561 | ||
27 | 34313233626666663234613339306539343030616266333565326565346563353739613363363464 | ||
28 | 65323763653436303030643765663739383965313335373265636336633762636134653536326364 | ||
29 | 65353366643639663765663566663065316334383463343464366662373939343763356333343731 | ||
30 | 6361 | ||
diff --git a/cmd/app/conf.toml b/cmd/app/conf.toml index 13e3e0b..16087e5 100644 --- a/cmd/app/conf.toml +++ b/cmd/app/conf.toml | |||
@@ -16,6 +16,9 @@ database=0 | |||
16 | [api] | 16 | [api] |
17 | domain="localhost" | 17 | domain="localhost" |
18 | jwt_secret="secret" | 18 | jwt_secret="secret" |
19 | password_reset_secret="resetsecret" | ||
20 | free_sms_user="20996747" | ||
21 | free_sms_pass="bM2ZPETB4zzWg3" | ||
19 | 22 | ||
20 | [app] | 23 | [app] |
21 | public_dir="../web/build/static" | 24 | public_dir="../web/build/static" |
diff --git a/cmd/app/main.go b/cmd/app/main.go index 65e8b5a..a0463d2 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go | |||
@@ -21,8 +21,8 @@ type AppConfig struct { | |||
21 | } | 21 | } |
22 | 22 | ||
23 | type ApiConfig struct { | 23 | type ApiConfig struct { |
24 | Domain string `toml:"domain"` | 24 | api.Config |
25 | JwtSecret string `toml:"jwt_secret"` | 25 | Domain string `toml:"domain"` |
26 | } | 26 | } |
27 | 27 | ||
28 | type Config struct { | 28 | type Config struct { |
@@ -45,9 +45,6 @@ func (c *Config) SetToDefaults() { | |||
45 | App: AppConfig{ | 45 | App: AppConfig{ |
46 | PublicDir: "./public", | 46 | PublicDir: "./public", |
47 | }, | 47 | }, |
48 | Api: ApiConfig{ | ||
49 | JwtSecret: "secret", | ||
50 | }, | ||
51 | } | 48 | } |
52 | 49 | ||
53 | c.LogConfiguration.SetToDefaults() | 50 | c.LogConfiguration.SetToDefaults() |
@@ -63,7 +60,7 @@ func init() { | |||
63 | panic(err) | 60 | panic(err) |
64 | } | 61 | } |
65 | 62 | ||
66 | api.SetJwtSecretKey(C.Api.JwtSecret) | 63 | api.SetConfig(C.Api.Config) |
67 | 64 | ||
68 | db.Init(C.Db, C.Redis) | 65 | db.Init(C.Db, C.Redis) |
69 | 66 | ||
@@ -142,6 +139,8 @@ func main() { | |||
142 | "/", | 139 | "/", |
143 | "/signup", | 140 | "/signup", |
144 | "/signin", | 141 | "/signin", |
142 | "/reset-password", | ||
143 | "/change-password", | ||
145 | "/signout", | 144 | "/signout", |
146 | "/me", | 145 | "/me", |
147 | "/otp/enroll", | 146 | "/otp/enroll", |
diff --git a/cmd/web/Makefile b/cmd/web/Makefile index c6bc2bd..c5d5d62 100644 --- a/cmd/web/Makefile +++ b/cmd/web/Makefile | |||
@@ -4,7 +4,7 @@ export PATH := $(PATH):./node_modules/.bin | |||
4 | 4 | ||
5 | SRC_DIR=js | 5 | SRC_DIR=js |
6 | BUILD_DIR=build/js | 6 | BUILD_DIR=build/js |
7 | JSX_SRC= main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx | 7 | JSX_SRC= main.jsx signup.jsx signin.jsx otp.jsx poloniex.jsx password_reset.jsx change_password.jsx |
8 | JS_SRC= cookies.js app.js api.js | 8 | JS_SRC= cookies.js app.js api.js |
9 | STATIC_FILES= index.html style.css | 9 | STATIC_FILES= index.html style.css |
10 | JSX_OBJS=$(addprefix $(BUILD_DIR)/,$(JSX_SRC:.jsx=.js)) | 10 | JSX_OBJS=$(addprefix $(BUILD_DIR)/,$(JSX_SRC:.jsx=.js)) |
diff --git a/cmd/web/js/api.js b/cmd/web/js/api.js index 5cbf5eb..c9b4ef5 100644 --- a/cmd/web/js/api.js +++ b/cmd/web/js/api.js | |||
@@ -43,6 +43,27 @@ var ApiEndpoints = { | |||
43 | return '/signin'; | 43 | return '/signin'; |
44 | } | 44 | } |
45 | }, | 45 | }, |
46 | 'RESET_PASSWORD': { | ||
47 | 'type': 'POST', | ||
48 | 'auth': false, | ||
49 | 'parameters': [ | ||
50 | {'name': 'email', 'mandatory': true, 'inquery': true}, | ||
51 | ], | ||
52 | 'buildUrl': function() { | ||
53 | return '/passwordreset'; | ||
54 | } | ||
55 | }, | ||
56 | 'CHANGE_PASSWORD': { | ||
57 | 'type': 'POST', | ||
58 | 'auth': false, | ||
59 | 'parameters': [ | ||
60 | {'name': 'token', 'mandatory': true, 'inquery': true}, | ||
61 | {'name': 'password', 'mandatory': true, 'inquery': true}, | ||
62 | ], | ||
63 | 'buildUrl': function() { | ||
64 | return '/changepassword'; | ||
65 | } | ||
66 | }, | ||
46 | 'MARKET': { | 67 | 'MARKET': { |
47 | 'type': 'GET', | 68 | 'type': 'GET', |
48 | 'auth': true, | 69 | 'auth': true, |
diff --git a/cmd/web/js/change_password.jsx b/cmd/web/js/change_password.jsx new file mode 100644 index 0000000..aedf4af --- /dev/null +++ b/cmd/web/js/change_password.jsx | |||
@@ -0,0 +1,62 @@ | |||
1 | import Api from './api.js'; | ||
2 | import App from './app.js'; | ||
3 | import classNames from 'classnames'; | ||
4 | import React from 'react'; | ||
5 | |||
6 | class ChangePasswordForm extends React.Component { | ||
7 | constructor(props) { | ||
8 | super(props); | ||
9 | this.state = {'hideMsg': true, 'msg': '', 'msgOk': false, 'password': ''}; | ||
10 | } | ||
11 | |||
12 | handleSubmit = (e) => { | ||
13 | Api.Call( | ||
14 | 'CHANGE_PASSWORD', | ||
15 | { | ||
16 | 'password': this.state.password, | ||
17 | 'token': this.props.token | ||
18 | }, | ||
19 | function(err, status, data) { | ||
20 | if (err) { | ||
21 | console.error(err, data); | ||
22 | this.displayMessage(App.errorCodeToMessage(err.code), false); | ||
23 | return; | ||
24 | } | ||
25 | |||
26 | this.displayMessage('You password has been reset.', true); | ||
27 | this.props.onSuccess(); | ||
28 | |||
29 | }.bind(this) | ||
30 | ); | ||
31 | e.preventDefault(); | ||
32 | } | ||
33 | |||
34 | handlePasswordChange = (event) => { | ||
35 | this.setState({'password': event.target.value}); | ||
36 | } | ||
37 | |||
38 | hideMessage = () => { | ||
39 | this.setState({'hideMsg': true}); | ||
40 | } | ||
41 | |||
42 | displayMessage = (msg, ok) => { | ||
43 | this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); | ||
44 | } | ||
45 | |||
46 | render = () => { | ||
47 | var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); | ||
48 | return ( | ||
49 | <div className="row sign-in"> | ||
50 | <div className="offset-4 col-4 col-xs-offset-1 col-xs-10 text-center"> | ||
51 | <form role="form" onSubmit={this.handleSubmit}> | ||
52 | <input className="form-control" type="password" placeholder="password" onChange={this.handlePasswordChange} /> | ||
53 | <input className="form-control submit" type="submit" value="Change password" /> | ||
54 | <div className={cName}>{this.state.msg}</div> | ||
55 | </form> | ||
56 | </div> | ||
57 | </div> | ||
58 | ); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | export default ChangePasswordForm; | ||
diff --git a/cmd/web/js/main.jsx b/cmd/web/js/main.jsx index e64adc7..909f1bd 100644 --- a/cmd/web/js/main.jsx +++ b/cmd/web/js/main.jsx | |||
@@ -1,11 +1,14 @@ | |||
1 | import SignupForm from './signup.js'; | 1 | import SignupForm from './signup.js'; |
2 | import SigninForm from './signin.js'; | 2 | import SigninForm from './signin.js'; |
3 | import PasswordResetForm from './password_reset.js'; | ||
4 | import ChangePasswordForm from './change_password.js'; | ||
3 | import OtpEnrollForm from './otp.js'; | 5 | import OtpEnrollForm from './otp.js'; |
4 | import PoloniexController from './poloniex.js'; | 6 | import PoloniexController from './poloniex.js'; |
5 | import App from './app.js'; | 7 | import App from './app.js'; |
6 | import Api from './api.js'; | 8 | import Api from './api.js'; |
7 | import cookies from './cookies.js'; | 9 | import cookies from './cookies.js'; |
8 | import React from 'react'; | 10 | import React from 'react'; |
11 | import qs from 'qs'; | ||
9 | 12 | ||
10 | class Header extends React.Component { | 13 | class Header extends React.Component { |
11 | render = () => { | 14 | render = () => { |
@@ -60,6 +63,37 @@ App.page('/signin', false, function(context) { | |||
60 | </div>); | 63 | </div>); |
61 | }); | 64 | }); |
62 | 65 | ||
66 | App.page('/reset-password', false, function(context) { | ||
67 | if (App.isUserSignedIn()) { | ||
68 | App.go('/me'); | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | App.mount(<div> | ||
73 | <Header /> | ||
74 | <PasswordResetForm /> | ||
75 | </div>); | ||
76 | }); | ||
77 | |||
78 | App.page('/change-password', false, function(context) { | ||
79 | if (App.isUserSignedIn()) { | ||
80 | App.go('/me'); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | var token = qs.parse(context.querystring).token; | ||
85 | |||
86 | if (token === undefined) { | ||
87 | App.go('/'); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | App.mount(<div> | ||
92 | <Header /> | ||
93 | <ChangePasswordForm token={token} onSuccess={App.go.bind(App, '/signin')}/> | ||
94 | </div>); | ||
95 | }); | ||
96 | |||
63 | App.page('/signout', true, function(context) { | 97 | App.page('/signout', true, function(context) { |
64 | cookies.removeItem('jwt'); | 98 | cookies.removeItem('jwt'); |
65 | 99 | ||
diff --git a/cmd/web/js/password_reset.jsx b/cmd/web/js/password_reset.jsx new file mode 100644 index 0000000..8cbdc60 --- /dev/null +++ b/cmd/web/js/password_reset.jsx | |||
@@ -0,0 +1,57 @@ | |||
1 | import Api from './api.js'; | ||
2 | import App from './app.js'; | ||
3 | import classNames from 'classnames'; | ||
4 | import React from 'react'; | ||
5 | |||
6 | class PasswordResetForm extends React.Component { | ||
7 | constructor(props) { | ||
8 | super(props); | ||
9 | this.state = {'hideMsg': true, 'msg': '', 'msgOk': false, 'email': ''}; | ||
10 | } | ||
11 | |||
12 | handleSubmit = (e) => { | ||
13 | Api.Call('RESET_PASSWORD', {'email': this.state.email}, function(err, status, data) { | ||
14 | if (err) { | ||
15 | console.error(err, data); | ||
16 | this.displayMessage(App.errorCodeToMessage(err.code), false); | ||
17 | return; | ||
18 | } | ||
19 | |||
20 | this.displayMessage('You will receive a reset link to reset your password.', true); | ||
21 | if (this.props.onSuccess) { | ||
22 | this.props.onSuccess(); | ||
23 | } | ||
24 | |||
25 | }.bind(this)); | ||
26 | e.preventDefault(); | ||
27 | } | ||
28 | |||
29 | handleEmailChange = (event) => { | ||
30 | this.setState({'email': event.target.value}); | ||
31 | } | ||
32 | |||
33 | hideMessage = () => { | ||
34 | this.setState({'hideMsg': true}); | ||
35 | } | ||
36 | |||
37 | displayMessage = (msg, ok) => { | ||
38 | this.setState({'msg': msg, 'msgOk': ok, 'hideMsg': false}); | ||
39 | } | ||
40 | |||
41 | render = () => { | ||
42 | var cName = classNames('form-message', {'hidden': this.state.hideMsg, 'message-ok': this.state.msgOk}); | ||
43 | return ( | ||
44 | <div className="row sign-in"> | ||
45 | <div className="offset-4 col-4 col-xs-offset-1 col-xs-10 text-center"> | ||
46 | <form role="form" onSubmit={this.handleSubmit}> | ||
47 | <input className="form-control" type="email" placeholder="email" onChange={this.handleEmailChange} /> | ||
48 | <input className="form-control submit" type="submit" value="Reset" /> | ||
49 | <div className={cName}>{this.state.msg}</div> | ||
50 | </form> | ||
51 | </div> | ||
52 | </div> | ||
53 | ); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | export default PasswordResetForm; \ No newline at end of file | ||
diff --git a/cmd/web/package.json b/cmd/web/package.json index c9241f1..a867313 100644 --- a/cmd/web/package.json +++ b/cmd/web/package.json | |||
@@ -14,6 +14,7 @@ | |||
14 | "localenvify": "^1.0.1", | 14 | "localenvify": "^1.0.1", |
15 | "page": "^1.8.3", | 15 | "page": "^1.8.3", |
16 | "path-to-regexp": "^1.2.1", | 16 | "path-to-regexp": "^1.2.1", |
17 | "qs": "^6.5.1", | ||
17 | "react": "^16.2.0" | 18 | "react": "^16.2.0" |
18 | }, | 19 | }, |
19 | "devDependencies": { | 20 | "devDependencies": { |
diff --git a/cmd/web/yarn.lock b/cmd/web/yarn.lock index 0d162a9..b2218ee 100644 --- a/cmd/web/yarn.lock +++ b/cmd/web/yarn.lock | |||
@@ -3536,6 +3536,10 @@ q@~1.0.0, q@~1.0.1: | |||
3536 | version "1.0.1" | 3536 | version "1.0.1" |
3537 | resolved "https://registry.yarnpkg.com/q/-/q-1.0.1.tgz#11872aeedee89268110b10a718448ffb10112a14" | 3537 | resolved "https://registry.yarnpkg.com/q/-/q-1.0.1.tgz#11872aeedee89268110b10a718448ffb10112a14" |
3538 | 3538 | ||
3539 | qs@^6.5.1: | ||
3540 | version "6.5.1" | ||
3541 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" | ||
3542 | |||
3539 | qs@~1.2.0: | 3543 | qs@~1.2.0: |
3540 | version "1.2.2" | 3544 | version "1.2.2" |
3541 | resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.2.tgz#19b57ff24dc2a99ce1f8bdf6afcda59f8ef61f88" | 3545 | resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.2.tgz#19b57ff24dc2a99ce1f8bdf6afcda59f8ef61f88" |