Skip to content

Commit

Permalink
Add token generation support to the user-managment-page (Closes #91) (#…
Browse files Browse the repository at this point in the history
…92)

* "#91- Update webgme to the latest version for token support"

* WIP-#91: Initial Implementation of tokens management from user-management-page

* #91: Display tokens table if atleast one token available

* #91 Change glyphicon color to default, display only newly generated token ids, change generate tokens button text to generate token

* Move Token Generation Logic to a different page

* WIP- Change Tokens Logic to latest webgme code

1. Tokens now have unique display name.
2. Add Copy to clipboard logic to the tokens using navigator.clipboard

* WIP- Rename variable tokenID to tokenName in tokensClient.js

* WIP- Remove token index from display name

* WIP- Gracefully handle errors on tokens generation and deletion, modify existing guest tokens creation logic

* WIP - updated webgme version

Co-authored-by: kecso <tamas.kecskes@vandebrilt.edu>
  • Loading branch information
umesh-timalsina and kecso committed Mar 19, 2020
1 parent 70d2662 commit a9a92f0
Show file tree
Hide file tree
Showing 17 changed files with 3,925 additions and 2,664 deletions.
6,070 changes: 3,440 additions & 2,630 deletions package-lock.json

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,51 +40,51 @@
},
"homepage": "https://github.com/webgme/user-management-page#readme",
"dependencies": {
"body-parser": "^1.18.3",
"ejs": "^2.4.2",
"body-parser": "^1.19.0",
"ejs": "^2.7.4",
"express": "4.16.3"
},
"devDependencies": {
"admin-lte": "2.4.3",
"babel-core": "^6.8.0",
"babel-eslint": "^8.2.3",
"babel-eslint": "^8.2.6",
"babel-istanbul": "^0.12.2",
"babel-loader": "^7.1.4",
"babel-loader": "^7.1.5",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"blockies": "0.0.2",
"bootstrap": "^3.3.6",
"bootstrap": "^3.4.1",
"bootstrap-webpack": "0.0.6",
"chai": "^4.1.2",
"chai": "^4.2.0",
"chart.js": "^1.1.1",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"eslint-config-google": "^0.9.1",
"eslint-plugin-react": "^7.9.1",
"eslint-plugin-react": "^7.19.0",
"exports-loader": "^0.7.0",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^1.1.11",
"font-awesome": "^4.5.0",
"font-awesome-webpack": "0.0.5-beta.2",
"imports-loader": "^0.8.0",
"less": "^3.0.4",
"less": "^3.11.1",
"less-loader": "^4.1.0",
"mocha": "^5.2.0",
"prop-types": "^15.6.2",
"react": "^16.4.1",
"react-bootstrap": "^0.32.1",
"prop-types": "^15.7.2",
"react": "^16.13.0",
"react-bootstrap": "^0.32.4",
"react-chartjs": "^1.2.0",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-dom": "^16.13.0",
"react-redux": "^5.1.2",
"react-router-dom": "^4.3.1",
"react-select": "^1.2.1",
"redux": "^4.0.0",
"react-select": "^1.3.0",
"redux": "^4.0.5",
"redux-thunk": "^2.2.0",
"style-loader": "^0.21.0",
"superagent": "^3.8.3",
"url-loader": "^1.0.1",
"webgme": "^2.30.0",
"url-loader": "^1.1.2",
"webgme": "github:webgme/webgme#master",
"webpack": "^3.12.0"
}
}
2 changes: 2 additions & 0 deletions src/client/rest_client/restClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import OrganizationsClient from './organizationsClient';
import ProjectsClient from './projectsClient';
import UserClient from './userClient';
import UsersClient from './usersClient';
import TokensClient from './tokensClient';

/**
* Single rest clients that contains user, users, projects, and orgs clients
Expand All @@ -26,6 +27,7 @@ function RestClient(baseUrl) {
this.projects = new ProjectsClient(baseUrl);
this.user = new UserClient(baseUrl);
this.users = new UsersClient(baseUrl);
this.tokens = new TokensClient();

/**
* Gets the current user
Expand Down
31 changes: 31 additions & 0 deletions src/client/rest_client/tokensClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Tokens client - all rest calls for personal access tokens
* @author Umesh Timalsina / https://github.com/umesh-timalsina
*/

/* eslint-env node, browser */
import BaseClient from './baseClient';

export default class TokensClient extends BaseClient {
constructor(baseUrl) {
if (typeof baseUrl !== 'string') {
baseUrl = '/rest/tokens/';
}
super(baseUrl);
}

getTokensForCurrentUser() {
return super.get(['']);
}

createTokenForCurrentUser(name) {
if (!name) {
return super.post(['create']);
}
return super.post(['create', name]);
}

deleteTokenForCurrentUser(tokenName) {
return super.delete([tokenName]);
}
}
9 changes: 8 additions & 1 deletion src/client/style/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export const ProfileBox = {
fontFamily: "monospace",
fontSize: "12px",
resize: "vertical"
}
},
};

export const ProfilePage = {
Expand Down Expand Up @@ -313,6 +313,13 @@ export const SideBarUserPanel = {
}
};

export const TokensTable = {
tableWrap: {
maxHeight: "700px",
overflow: "auto"
},
};

export const UserMenu = {
logoutButtonPadding: {
padding: "9px 100px"
Expand Down
54 changes: 54 additions & 0 deletions src/common/actions/tokens.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Tokens actions
* @author Umesh Timalsina / https://github.com/umesh-timalsina
*/

// Self-defined
import TokensClient from '../../client/rest_client/tokensClient';
const tokensClient = new TokensClient();

export const REQUEST_TOKENS = 'REQUEST_TOKENS';
export const RECEIVE_TOKENS = 'RECEIVE_TOKENS';

export const requestTokens = () => {
return {
type: REQUEST_TOKENS,
};
};

export const receiveTokens = (tokens) => {
return {
type: RECEIVE_TOKENS,
tokens,
};
};

export const shouldFetchTokens = (state) => {
const {hasFetched, isFetching} = state.tokens;

let shouldFetch = true;
if (hasFetched || isFetching) {
shouldFetch = false;
}

return shouldFetch;
};

export const fetchTokens = () => {
return (dispatch) => {
dispatch(requestTokens());
return tokensClient.getTokensForCurrentUser()
.then((tokens) => {
dispatch(receiveTokens(tokens));
});
};
};

export const fetchTokensIfNeeded = () => {
return (dispatch, getState) => {
if (shouldFetchTokens(getState())) {
return dispatch(fetchTokens());
}
};
};

7 changes: 7 additions & 0 deletions src/common/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import UserPage from '../../common/containers/content/pages/UserPage';
import UsersPage from '../../common/containers/content/pages/UsersPage';
import NewUserPage from '../../common/containers/content/pages/NewUserPage';
import StatusPage from '../../common/containers/content/pages/StatusPage';
import TokensPage from '../../common/containers/content/pages/TokensPage';

export default class App extends Component {

Expand Down Expand Up @@ -84,6 +85,12 @@ export default class App extends Component {
}
/>

<Route
exact
path={`${basePath}tokens`}
render={() => (<TokensPage pathname={pathname} restClient={restClient}/>)}
/>

<Route
exact
path={`${basePath}projects`}
Expand Down
25 changes: 25 additions & 0 deletions src/common/components/content/pages/TokensPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

// Libraries
import React, { Component } from 'react';
// Self defined
import TokensTable from '../../../containers/content/widgets/data_tables/TokensTable';


export default class TokensPage extends Component {
render() {
return (
<section className="content">
<div className="row">
<div className="col-md-8 col-md-offset-2">
<div className="box box-primary">
<TokensTable
basePath={this.props.basePath}
restClient={this.props.restClient}/>
</div>
</div>
</div>
</section>
);
}

}
25 changes: 15 additions & 10 deletions src/common/components/content/widgets/CustomModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@ export default class CustomModal extends Component {
{this.props.children}

<Modal.Footer>
<Button bsStyle={this.props.confirmButtonStyle}
id={this.props.confirmId}
onClick={this.props.confirmHandler} >
{this.props.confirmButtonMessage}
</Button>
<Button bsStyle={this.props.cancelButtonStyle}
onClick={this.props.closeHandler}>
{this.props.cancelButtonMessage}
</Button>
{this.props.hideConfirmBtn ? null :
<Button bsStyle={this.props.confirmButtonStyle}
id={this.props.confirmId}
onClick={this.props.confirmHandler} >
{this.props.confirmButtonMessage}
</Button>}
{this.props.hideCancelBtn? null :
<Button
bsStyle={this.props.cancelButtonStyle}
onClick={this.props.closeHandler}>
{this.props.cancelButtonMessage}
</Button>}
</Modal.Footer>

</Modal>
Expand All @@ -57,5 +60,7 @@ CustomModal.propTypes = {
modalMessage: PropTypes.string,
showModal: PropTypes.bool.isRequired,
style: PropTypes.object,
title: PropTypes.string
title: PropTypes.string,
hideCancelBtn: PropTypes.bool,
hideConfirmBtn: PropTypes.bool,
};
Loading

0 comments on commit a9a92f0

Please sign in to comment.