Skip to content

Commit 7012f01

Browse files
author
Sascha Pfeiffer
committed
Fix #12 Added possibility to add users
Signed-off-by: Sascha Pfeiffer <sascha.pfeiffer@psono.com>
1 parent 787bb13 commit 7012f01

File tree

9 files changed

+445
-69
lines changed

9 files changed

+445
-69
lines changed

public/locales/de/translation.json

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"USER_LIMIT_REACHED": "Benutzer Limit erreicht",
3+
"LICENSE_EXPIRED": "Lizenz abgelaufen",
4+
"USER_WITH_EMAIL_ALREADY_EXISTS": "Email bereits vergeben",
5+
"USER_WITH_USERNAME_ALREADY_EXISTS": "Benutzername bereits vergeben",
26
"DELETE_USER_CONFIRM_DIALOG": "Sie sind dabei Benutzer zu löschen. Sind sie sich sicher?",
37
"DELETE_GROUP_CONFIRM_DIALOG": "Sie sind dabei Gruppen zu löschen. Sind sie sich sicher?",
48
"ABORT": "Abbrechen",
@@ -87,6 +91,7 @@
8791
"FILESERVER_INFO": "Fileserver Info:",
8892
"TITLE": "Title",
8993
"GROUP_NAME": "Gruppen Name",
94+
"CREATE_USER": "Benutzer Erstellen",
9095
"CREATE_GROUP": "Gruppe Erstellen",
9196
"ADD_NECESSARY_DETAILS_BELOW": "Geben sie die notwendigen Details unten an",
9297
"VERSION": "Version",
@@ -238,6 +243,7 @@
238243
"LOGIN": "Login",
239244
"USERNAME": "Benutzername",
240245
"PASSWORD": "Passwort",
246+
"PASSWORD_REPEAT": "Passwort (wiederholen)",
241247
"REQUEST_PASSWORD_RESET": "Passwort Zurücksetzen",
242248
"LOST_PASSWORD": "Passwort verloren",
243249
"PRIVACY_POLICY": "Datenschutz",

public/locales/en/translation.json

+6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
{
2+
"USER_LIMIT_REACHED": "User limit reached",
3+
"LICENSE_EXPIRED": "License expired",
4+
"USER_WITH_EMAIL_ALREADY_EXISTS": "Email address already taken",
5+
"USER_WITH_USERNAME_ALREADY_EXISTS": "Username already taken",
26
"DELETE_USER_CONFIRM_DIALOG": "You are about to delete users. Are you sure?",
37
"DELETE_GROUP_CONFIRM_DIALOG": "You are about to delete groups. Are you sure?",
48
"ABORT": "Abort",
@@ -87,6 +91,7 @@
8791
"FILESERVER_INFO": "Fileserver Info:",
8892
"TITLE": "Title",
8993
"GROUP_NAME": "Group Name",
94+
"CREATE_USER": "Create User",
9095
"CREATE_GROUP": "Create Group",
9196
"ADD_NECESSARY_DETAILS_BELOW": "Add the necessary details below",
9297
"VERSION": "Version",
@@ -238,6 +243,7 @@
238243
"LOGIN": "Login",
239244
"USERNAME": "Username",
240245
"PASSWORD": "Password",
246+
"PASSWORD_REPEAT": "Password (repeat)",
241247
"REQUEST_PASSWORD_RESET": "Request Password Reset",
242248
"LOST_PASSWORD": "Lost password",
243249
"PRIVACY_POLICY": "Privacy Policy",

src/components/Card/UsersCard.jsx

+7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class UsersCard extends React.Component {
3838
onDeleteSessions,
3939
onDeleteGroups,
4040
onCreateGroup,
41+
onCreateUser,
4142
show_create_group_button
4243
} = this.props;
4344
return (
@@ -146,6 +147,12 @@ class UsersCard extends React.Component {
146147
deleteUsers: [data]
147148
});
148149
}
150+
},
151+
{
152+
tooltip: t('CREATE_USER'),
153+
isFreeAction: true,
154+
icon: Add,
155+
onClick: evt => onCreateUser()
149156
}
150157
]}
151158
/>

src/components/Table/CustomMaterialTable.jsx

+65-57
Original file line numberDiff line numberDiff line change
@@ -72,66 +72,74 @@ class CustomMaterialTable extends React.Component {
7272
const mergedOptions = { ...defaultOptions, ...options };
7373

7474
return (
75-
<MaterialTable
76-
icons={tableIcons}
77-
title={title}
78-
columns={columns}
79-
data={data}
80-
options={mergedOptions}
81-
actions={actions}
82-
localization={{
83-
body: {
84-
emptyDataSourceMessage: t(
85-
'MATERIAL_TABLE_NO_RECORD_TO_DISPLAY'
86-
),
87-
addTooltip: t('MATERIAL_TABLE_ADD'),
88-
deleteTooltip: t('MATERIAL_TABLE_DELETE'),
89-
editTooltip: t('MATERIAL_TABLE_EDIT'),
90-
filterRow: {
91-
filterTooltip: t('MATERIAL_TABLE_FILTER')
75+
<div>
76+
<MaterialTable
77+
icons={tableIcons}
78+
title={title}
79+
columns={columns}
80+
data={data}
81+
options={mergedOptions}
82+
actions={actions}
83+
localization={{
84+
body: {
85+
emptyDataSourceMessage: t(
86+
'MATERIAL_TABLE_NO_RECORD_TO_DISPLAY'
87+
),
88+
addTooltip: t('MATERIAL_TABLE_ADD'),
89+
deleteTooltip: t('MATERIAL_TABLE_DELETE'),
90+
editTooltip: t('MATERIAL_TABLE_EDIT'),
91+
filterRow: {
92+
filterTooltip: t('MATERIAL_TABLE_FILTER')
93+
},
94+
editRow: {
95+
deleteText: t(
96+
'MATERIAL_TABLE_ARE_YOU_SURE_DELETE_THIS_ROW'
97+
),
98+
cancelTooltip: t('MATERIAL_TABLE_CANCEL'),
99+
saveTooltip: t('MATERIAL_TABLE_SAVE')
100+
}
101+
},
102+
grouping: {
103+
placeholder: t('MATERIAL_TABLE_DRAG_HEADERS')
92104
},
93-
editRow: {
94-
deleteText: t(
95-
'MATERIAL_TABLE_ARE_YOU_SURE_DELETE_THIS_ROW'
105+
header: {
106+
actions: t('MATERIAL_TABLE_ACTIONS')
107+
},
108+
pagination: {
109+
labelDisplayedRows: t(
110+
'MATERIAL_TABLE_FROM_TO_COUNT'
111+
),
112+
labelRowsSelect: t('MATERIAL_TABLE_ROWS'),
113+
labelRowsPerPage: t('MATERIAL_TABLE_ROWS_PER_PAGE'),
114+
firstAriaLabel: t('MATERIAL_TABLE_FIRST_PAGE'),
115+
firstTooltip: t('MATERIAL_TABLE_FIRST_PAGE'),
116+
previousAriaLabel: t(
117+
'MATERIAL_TABLE_PREVIOUS_PAGE'
118+
),
119+
previousTooltip: t('MATERIAL_TABLE_PREVIOUS_PAGE'),
120+
nextAriaLabel: t('MATERIAL_TABLE_NEXT_PAGE'),
121+
nextTooltip: t('MATERIAL_TABLE_NEXT_PAGE'),
122+
lastAriaLabel: t('MATERIAL_TABLE_LAST_PAGE'),
123+
lastTooltip: t('MATERIAL_TABLE_LAST_PAGE')
124+
},
125+
toolbar: {
126+
addRemoveColumns: t(
127+
'MATERIAL_TABLE_ADD_OR_REMOVE_COLUMNS'
128+
),
129+
nRowsSelected: t('MATERIAL_TABLE_N_ROWS_SELECTED'),
130+
showColumnsTitle: t('MATERIAL_TABLE_SHOW_COLUMNS'),
131+
showColumnsAriaLabel: t(
132+
'MATERIAL_TABLE_SHOW_COLUMNS'
96133
),
97-
cancelTooltip: t('MATERIAL_TABLE_CANCEL'),
98-
saveTooltip: t('MATERIAL_TABLE_SAVE')
134+
exportTitle: t('MATERIAL_TABLE_EXPORT'),
135+
exportAriaLabel: t('MATERIAL_TABLE_EXPORT'),
136+
exportName: t('MATERIAL_TABLE_EXPORT_AS_CSV'),
137+
searchTooltip: t('MATERIAL_TABLE_SEARCH'),
138+
searchPlaceholder: t('MATERIAL_TABLE_SEARCH')
99139
}
100-
},
101-
grouping: {
102-
placeholder: t('MATERIAL_TABLE_DRAG_HEADERS')
103-
},
104-
header: {
105-
actions: t('MATERIAL_TABLE_ACTIONS')
106-
},
107-
pagination: {
108-
labelDisplayedRows: t('MATERIAL_TABLE_FROM_TO_COUNT'),
109-
labelRowsSelect: t('MATERIAL_TABLE_ROWS'),
110-
labelRowsPerPage: t('MATERIAL_TABLE_ROWS_PER_PAGE'),
111-
firstAriaLabel: t('MATERIAL_TABLE_FIRST_PAGE'),
112-
firstTooltip: t('MATERIAL_TABLE_FIRST_PAGE'),
113-
previousAriaLabel: t('MATERIAL_TABLE_PREVIOUS_PAGE'),
114-
previousTooltip: t('MATERIAL_TABLE_PREVIOUS_PAGE'),
115-
nextAriaLabel: t('MATERIAL_TABLE_NEXT_PAGE'),
116-
nextTooltip: t('MATERIAL_TABLE_NEXT_PAGE'),
117-
lastAriaLabel: t('MATERIAL_TABLE_LAST_PAGE'),
118-
lastTooltip: t('MATERIAL_TABLE_LAST_PAGE')
119-
},
120-
toolbar: {
121-
addRemoveColumns: t(
122-
'MATERIAL_TABLE_ADD_OR_REMOVE_COLUMNS'
123-
),
124-
nRowsSelected: t('MATERIAL_TABLE_N_ROWS_SELECTED'),
125-
showColumnsTitle: t('MATERIAL_TABLE_SHOW_COLUMNS'),
126-
showColumnsAriaLabel: t('MATERIAL_TABLE_SHOW_COLUMNS'),
127-
exportTitle: t('MATERIAL_TABLE_EXPORT'),
128-
exportAriaLabel: t('MATERIAL_TABLE_EXPORT'),
129-
exportName: t('MATERIAL_TABLE_EXPORT_AS_CSV'),
130-
searchTooltip: t('MATERIAL_TABLE_SEARCH'),
131-
searchPlaceholder: t('MATERIAL_TABLE_SEARCH')
132-
}
133-
}}
134-
/>
140+
}}
141+
/>
142+
</div>
135143
);
136144
}
137145
}

src/routes/other.jsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import SecurityReportEdit from '../views/SecurityReport/Edit';
22
import UserEdit from '../views/User/Edit';
33
import GroupEdit from '../views/Group/Edit';
44
import GroupCreate from '../views/Group/Create';
5+
import UserCreate from '../views/User/Create';
56

67
import { Person, Group, Timeline } from '@material-ui/icons';
78

@@ -31,8 +32,15 @@ let routes = [
3132
path: '/groups/create',
3233
sidebarName: 'CREATE_GROUP',
3334
navbarName: 'CREATE_GROUP',
34-
icon: Person,
35+
icon: Group,
3536
component: GroupCreate
37+
},
38+
{
39+
path: '/users/create',
40+
sidebarName: 'CREATE_USER',
41+
navbarName: 'CREATE_USER',
42+
icon: Person,
43+
component: UserCreate
3644
}
3745
];
3846

src/services/api-server.js

+34-1
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,38 @@ function admin_saml_delete_group_map(
509509
return call(connection_type, endpoint, data, headers, session_secret_key);
510510
}
511511

512+
/**
513+
* POST: Creates a user (for administrators)
514+
*
515+
* @param {string} token authentication token of the user, returned by authentication_login(email, authkey)
516+
* @param {string} session_secret_key The session secret key
517+
* @param {string} username The name of the user to create
518+
* @param {string} email The email of the user to create
519+
* @param {string} password The password of the user to create
520+
*
521+
* @returns {Promise<AxiosResponse<any>>}
522+
*/
523+
function admin_create_user(
524+
token,
525+
session_secret_key,
526+
username,
527+
password,
528+
email
529+
) {
530+
const endpoint = '/admin/user/';
531+
const connection_type = 'POST';
532+
const data = {
533+
username: username,
534+
email: email,
535+
password: password
536+
};
537+
const headers = {
538+
Authorization: 'Token ' + token
539+
};
540+
541+
return call(connection_type, endpoint, data, headers, session_secret_key);
542+
}
543+
512544
/**
513545
* DELETE: Deletes a user (for administrators)
514546
*
@@ -561,7 +593,7 @@ function admin_delete_session(token, session_secret_key, session_id) {
561593
*
562594
* @param {string} token authentication token of the user, returned by authentication_login(email, authkey)
563595
* @param {string} session_secret_key The session secret key
564-
* @param {uuid} name The name of the group to create
596+
* @param {string} name The name of the group to create
565597
*
566598
* @returns {Promise<AxiosResponse<any>>}
567599
*/
@@ -2572,6 +2604,7 @@ const service = {
25722604
admin_session,
25732605
admin_group,
25742606
admin_security_report,
2607+
admin_create_user,
25752608
admin_delete_user,
25762609
admin_delete_session,
25772610
admin_create_group,

src/views/Group/Create.js

+27-10
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@ import {
88
RegularCard,
99
CustomInput,
1010
GridItem,
11-
Button
11+
Button,
12+
SnackbarContent
1213
} from '../../components/index';
1314
import psono_server from '../../services/api-server';
1415
import customInputStyle from '../../assets/jss/material-dashboard-react/customInputStyle';
1516

16-
class User extends React.Component {
17+
class Group extends React.Component {
1718
state = {
1819
errors_list: [],
1920
errors_dict: {},
@@ -106,13 +107,29 @@ class User extends React.Component {
106107
</div>
107108
}
108109
footer={
109-
<Button
110-
color="primary"
111-
onClick={this.createGroup}
112-
disabled={!this.state.createGroupPossible}
113-
>
114-
{t('CREATE_GROUP')}
115-
</Button>
110+
<div>
111+
<Button
112+
color="primary"
113+
onClick={this.createGroup}
114+
disabled={
115+
!this.state.createGroupPossible
116+
}
117+
>
118+
{t('CREATE_GROUP')}
119+
</Button>
120+
{errors_dict.hasOwnProperty(
121+
'non_field_errors'
122+
) ? (
123+
<SnackbarContent
124+
message={t(
125+
errors_dict['non_field_errors']
126+
)}
127+
color="danger"
128+
/>
129+
) : (
130+
''
131+
)}
132+
</div>
116133
}
117134
/>
118135
</GridItem>
@@ -122,4 +139,4 @@ class User extends React.Component {
122139
}
123140
}
124141

125-
export default compose(withTranslation(), withStyles(customInputStyle))(User);
142+
export default compose(withTranslation(), withStyles(customInputStyle))(Group);

0 commit comments

Comments
 (0)