Commit 2b949927 authored by rdoerge's avatar rdoerge
Browse files

Merge branch 'master' into feature/addpasswordfield

parents 60e0867e b08dd0cb
......@@ -12,6 +12,20 @@ And now, start developing:
npm run start
```
*Warning*: For installation on Ubuntu 16.04 (and possibly similar), you need to install nodejs from the repos source.
1. Remove nodejs if you already have it (ONLY IF YOU REALLY WANT!):
```
sudo apt remove nodejs
```
2. Add nodejs10 from repo (download): `curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -`
3. Install: `sudo apt install -y nodejs`
4. Clean-up and install the packages for amiv-admintools
```
rm -rf node_modules/
npm install
npm run start
```
This will open up a local server outputting the current version of the admintools. It refreshes automatically as soon as you save changes in any `.js` file.
### File Structure:
......
......@@ -9,9 +9,7 @@ import config from './resourceConfig.json';
const APISession = {
authenticated: false,
token: '',
// user admins are a very special case as the permissions on the resource can only
// be seen by requesting users and check whether you see their membership
isUserAdmin: false,
userID: null,
};
const amivapi = axios.create({
......@@ -36,7 +34,7 @@ function resetSession() {
function checkToken(token) {
// check if a token is still valid
return new Promise((resolve, reject) => {
amivapi.get('users', {
amivapi.get(`sessions/${token}`, {
headers: { 'Content-Type': 'application/json', Authorization: token },
}).then((response) => {
if (response.status === 200) resolve(response.data);
......@@ -56,14 +54,10 @@ export function checkAuthenticated() {
console.log(`found this token: ${token}`);
if (token !== '') {
// check of token is valid
checkToken(token).then((users) => {
checkToken(token).then((session) => {
APISession.token = token;
APISession.authenticated = true;
// if we see the membership of more than 1 person in the response, we
// have admin rights on users
if (users._items[0].membership && users._items[1].membership) {
APISession.isUserAdmin = true;
}
APISession.userID = session.user;
console.log(APISession);
resolve();
}).catch(resetSession);
......@@ -108,6 +102,10 @@ export function deleteSession() {
});
}
export function getCurrentUser() {
return APISession.userID;
}
export class ResourceHandler {
/* Handler to get and manipulate resource items
*
......@@ -309,7 +307,15 @@ export class OauthRedirect {
APISession.authenticated = true;
APISession.token = response.accessToken;
localStorage.set('token', response.accessToken);
m.route.set('/users');
amivapi.get(`sessions/${response.accessToken}`, {
headers: { 'Content-Type': 'application/json', Authorization: APISession.token },
}).then((response) => {
console.log(response);
APISession.userID = response.data.user;
m.route.set('/');
}).catch(() => {
resetSession();
});
});
return 'redirecting...';
}
......
......@@ -2,17 +2,21 @@ import m from 'mithril';
import { Card } from 'polythene-mithril';
import { DatalistController } from 'amiv-web-ui-components';
import { loadingScreen } from '../layout';
import { ResourceHandler } from '../auth';
import { ResourceHandler, getCurrentUser } from '../auth';
import { colors } from '../style';
class GroupListItem {
view({ attrs: { name, _id } }) {
view({ attrs: { name, _id, color = '#ffffff' } }) {
return m('div', {
style: { 'max-width': '500px', margin: '5px' },
onclick: () => {
m.route.set(`/groups/${_id}`);
},
}, m(Card, { content: [{ primary: { title: name } }] }));
}, m(Card, {
content: [{ primary: { title: name } }],
style: { backgroundColor: color },
}));
}
}
......@@ -24,20 +28,59 @@ export default class GroupList {
(query, search) => this.handler.get({ search, ...query }),
{ sort: [['name', 1]] },
);
this.data = [];
this.ctrl.getFullList().then((list) => { this.data = list; m.redraw(); });
this.groups = [];
this.moderatedGroups = [];
this.ctrl.getFullList().then((list) => {
this.groups = list;
this.ctrl.setQuery({ where: { moderator: getCurrentUser() } });
this.ctrl.getFullList().then((moderatedList) => {
this.moderatedGroups = moderatedList;
m.redraw();
})
});
}
view() {
if (!this.data) return m(loadingScreen);
if (!this.groups) return m(loadingScreen);
return m(
'div.maincontainer', { style: { display: 'flex', 'flex-wrap': 'wrap', 'margin-top': '5px' } },
this.data.map(item => m(GroupListItem, item)),
m('div', {
style: { 'max-width': '500px', margin: '5px' },
onclick: () => { m.route.set('/newgroup'); },
}, m(Card, { content: [{ primary: { title: '+ add' } }] })),
);
return m('div', [
this.moderatedGroups.length > 0 && m('div.maincontainer', {
style: {
'margin-top': '5px',
'border-bottom': '1px solid #aaaaaa',
'padding-bottom': '20px',
},
}, [
m('div', {
style: {
'font-size': '20px',
'margin': '10px 5px'
},
}, 'moderated by you'),
m('div', {
style: { display: 'flex', 'flex-wrap': 'wrap' }
}, this.moderatedGroups.map(item =>
m(GroupListItem, { ...item } ))),
]),
m('div.maincontainer', {
style: { display: 'flex', 'flex-wrap': 'wrap', 'margin-top': '5px' },
}, [
this.moderatedGroups.length > 0 && m('div', {
style: {
'font-size': '20px',
'margin': '10px 5px'
},
}, 'all groups'),
m('div', {
style: { display: 'flex', 'flex-wrap': 'wrap' }
},
this.groups.map(item => m(GroupListItem, item)),
m('div', {
style: { 'max-width': '500px', margin: '5px' },
onclick: () => { m.route.set('/newgroup'); },
}, m(Card, { content: [{ primary: { title: '+ add' } }] })),
),
]),
]);
}
}
......@@ -34,6 +34,7 @@ export default class UserView extends ItemView {
where: { _id: { $nin: groupIds } },
});
});
this.sessionsHandler = new ResourceHandler('sessions');
}
oninit() {
......@@ -154,6 +155,24 @@ export default class UserView extends ItemView {
]),
})),
]),
], [
m(Button, {
label: 'log out all Sessions',
className: 'itemView-delete-button',
border: true,
events: {
onclick: () => {
this.sessionsHandler.get({
where: { user: this.data._id },
}).then((response) => {
response._items.forEach((session) => {
this.sessionsHandler.delete(session);
});
console.log(response);
});
},
},
}),
]);
}
}
......@@ -50,7 +50,7 @@ export default class ItemView {
});
}
layout(children) {
layout(children, buttons = []) {
if (!this.controller || !this.controller.data) return m(loadingScreen);
return m('div', [
m(Toolbar, m('div.pe-button-row', [
......@@ -66,6 +66,7 @@ export default class ItemView {
border: true,
events: { onclick: () => this.delete() },
}),
...buttons,
])),
m('div', {
style: { height: 'calc(100vh - 130px)', 'overflow-y': 'scroll' },
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment