From 0356b681d75cbab2e8ff4b1b5d997da4d92adce0 Mon Sep 17 00:00:00 2001 From: Robert Chen Date: Wed, 26 Feb 2020 22:25:42 -0800 Subject: [PATCH 1/3] Added profile delete --- client/src/api/profile.js | 12 +++++++++++- client/src/pages/profile.js | 20 ++++++++++++++++++-- server/util/index.js | 8 +++++--- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/client/src/api/profile.js b/client/src/api/profile.js index 48246ac6..5a056ba3 100644 --- a/client/src/api/profile.js +++ b/client/src/api/profile.js @@ -1,4 +1,4 @@ -import { request } from './util' +import { request, relog } from './util' export const privateProfile = () => { return request('GET', '/users/me') @@ -9,3 +9,13 @@ export const publicProfile = uuid => { return request('GET', '/users/' + encodeURIComponent(uuid)) .then(resp => resp.data) } + +export const deleteAccount = () => { + return request('DELETE', '/users/me') + .then(resp => { + switch (resp.kind) { + case 'goodUserDelete': + return relog() + } + }) +} diff --git a/client/src/pages/profile.js b/client/src/pages/profile.js index 8707e481..d6b1720e 100644 --- a/client/src/pages/profile.js +++ b/client/src/pages/profile.js @@ -3,7 +3,7 @@ import config from '../../../config/client' import 'linkstate/polyfill' import withStyles from '../components/jss' -import { privateProfile, publicProfile } from '../api/profile' +import { privateProfile, publicProfile, deleteAccount } from '../api/profile' import util from '../util' import Trophy from '../../static/icons/trophy.svg' import AddressBook from '../../static/icons/address-book.svg' @@ -87,6 +87,14 @@ export default withStyles({ } } + handleDelete = e => { + const resp = prompt('Please type your team name to confirm: ' + this.state.name) + + if (resp === this.state.name) { + deleteAccount() + } + } + render ({ classes }, { name, division, placement, score, teamToken, solves, error, loaded }) { const priv = this.isPrivate() const hasError = error !== undefined @@ -99,7 +107,7 @@ export default withStyles({
-

Error

+

There was an error

{error}

@@ -122,6 +130,14 @@ export default withStyles({

Share this with your teammates to use at /login!

+
+
+

Danger Zone

+
+ +
+
+
}
diff --git a/server/util/index.js b/server/util/index.js index 0086ae1b..a4575248 100644 --- a/server/util/index.js +++ b/server/util/index.js @@ -24,9 +24,11 @@ module.exports = { return require(m) }, enableCORS: (req, res, next) => { - res.header('Access-Control-Allow-Origin', config.origin) - res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type') - res.header('Access-Control-Allow-Methods', 'GET, POST') + if (config.origin !== undefined) { + res.header('Access-Control-Allow-Origin', config.origin) + res.header('Access-Control-Allow-Headers', 'Authorization, Content-Type') + res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE') + } if (req.method === 'OPTIONS') { res.sendStatus(200) From 3427768666a6f5f7f584eb395951c87a19f0e99c Mon Sep 17 00:00:00 2001 From: jimmyl02 Date: Wed, 26 Feb 2020 23:41:47 -0800 Subject: [PATCH 2/3] Added updating user info --- client/src/api/profile.js | 8 +++++++ client/src/api/util.js | 2 +- client/src/pages/profile.js | 47 ++++++++++++++++++++++++++++++++++--- config/client.js.example | 9 ++++++- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/client/src/api/profile.js b/client/src/api/profile.js index 5a056ba3..f1cbcf25 100644 --- a/client/src/api/profile.js +++ b/client/src/api/profile.js @@ -19,3 +19,11 @@ export const deleteAccount = () => { } }) } + +export const updateAccount = (name, division) => { + return request('PATCH', '/users/me', { + name, + division: Number.parseInt(division) + }) + .then(resp => resp.data) +} diff --git a/client/src/api/util.js b/client/src/api/util.js index 7d87c2f0..8fc12ce3 100644 --- a/client/src/api/util.js +++ b/client/src/api/util.js @@ -1,7 +1,7 @@ import { route } from 'preact-router' import config from '../../../config/client' -const relog = () => { +export const relog = () => { localStorage.removeItem('token') route('/register') } diff --git a/client/src/pages/profile.js b/client/src/pages/profile.js index d6b1720e..5368d86f 100644 --- a/client/src/pages/profile.js +++ b/client/src/pages/profile.js @@ -3,10 +3,18 @@ import config from '../../../config/client' import 'linkstate/polyfill' import withStyles from '../components/jss' -import { privateProfile, publicProfile, deleteAccount } from '../api/profile' +import { privateProfile, publicProfile, deleteAccount, updateAccount } from '../api/profile' +import Form from '../components/form' import util from '../util' import Trophy from '../../static/icons/trophy.svg' import AddressBook from '../../static/icons/address-book.svg' +import UserCircle from '../../static/icons/user-circle.svg' + +const divisionMap = new Map() + +for (const division of Object.entries(config.divisions)) { + divisionMap.set(division[1], division[0]) +} export default withStyles({ quote: { @@ -31,13 +39,18 @@ export default withStyles({ teamToken: '', solves: [], uuid: '', - error: undefined + error: undefined, + updateName: '', + updateDivision: 0, + disabledButton: false } processGeneric ({ name, division, score, divisionPlace, solves }) { this.setState({ name: name, + updateName: name, division: division, + updateDivision: config.divisions[division], placement: util.strings.placementString(divisionPlace), score, solves: solves, @@ -87,6 +100,21 @@ export default withStyles({ } } + handleUpdate = e => { + e.preventDefault() + + this.setState({ + disabledButton: true + }) + + updateAccount(this.state.updateName, this.state.updateDivision) + .then(resp => this.setState({ + name: resp.user.name, + division: divisionMap.get(Number.parseInt(resp.user.division)), + disabledButton: false + })) + } + handleDelete = e => { const resp = prompt('Please type your team name to confirm: ' + this.state.name) @@ -95,7 +123,7 @@ export default withStyles({ } } - render ({ classes }, { name, division, placement, score, teamToken, solves, error, loaded }) { + render ({ classes }, { name, division, placement, score, teamToken, solves, error, loaded, updateName, updateDivision, disabledButton }) { const priv = this.isPrivate() const hasError = error !== undefined @@ -134,6 +162,19 @@ export default withStyles({

Danger Zone

+
+
+ } name='name' placeholder='Team Name' type='text' value={updateName} onChange={this.linkState('updateName')} /> + +
+
diff --git a/config/client.js.example b/config/client.js.example index 9c3ef8ce..d3e739b4 100644 --- a/config/client.js.example +++ b/config/client.js.example @@ -1,4 +1,4 @@ -export default { +const ret = { apiEndpoint: '/api/v1', staticEndpoint: '/static', ctfTitle: ' | yourCTF', @@ -17,3 +17,10 @@ export default { } ] } + +const shared = require('./shared') +Object.entries(shared).forEach(([key, val]) => { + if (ret[key] === undefined) ret[key] = val +}) + +module.exports = ret From 49386229b7f2af4ef51f35ba7b8422e7d2425933 Mon Sep 17 00:00:00 2001 From: Robert Chen Date: Thu, 27 Feb 2020 21:23:53 -0800 Subject: [PATCH 3/3] Refactored profile update panel --- client/src/pages/profile.js | 83 +++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/client/src/pages/profile.js b/client/src/pages/profile.js index 5368d86f..dc4a30fe 100644 --- a/client/src/pages/profile.js +++ b/client/src/pages/profile.js @@ -28,6 +28,15 @@ export default withStyles({ fill: '#333' }, marginRight: '25px' + }, + form: { + '& button': { + margin: 0, + lineHeight: '20px', + padding: '10px', + float: 'right' + }, + padding: '0 !important' } }, class Profile extends Component { state = { @@ -160,22 +169,22 @@ export default withStyles({
-

Danger Zone

-
-
-
- } name='name' placeholder='Team Name' type='text' value={updateName} onChange={this.linkState('updateName')} /> - -
-
- +

Update Information

+
+
+ } name='name' placeholder='Team Name' type='text' value={updateName} onChange={this.linkState('updateName')} /> + +
+
+
+
@@ -184,7 +193,7 @@ export default withStyles({
-
{name}
+
{name}

@@ -192,7 +201,7 @@ export default withStyles({ { score === 0 - ? ('No solves yet') + ? ('No points earned') : (placement + ' with ' + score + ' points') }

@@ -206,23 +215,27 @@ export default withStyles({
-
-
-
Solves
- - - - - - - - - - {solves.map(solve => )} - -
CategoryNamePoints
{solve.category}{solve.name}{solve.points}
-
-
+ { + solves.length !== 0 && +
+
+
Solves
+ + + + + + + + + + {solves.map(solve => )} + +
CategoryNamePoints
{solve.category}{solve.name}{solve.points}
+
+
+ } +
)