diff --git a/core/authentication/api_v2.py b/core/authentication/api_v2.py index 7935ae8..514a697 100644 --- a/core/authentication/api_v2.py +++ b/core/authentication/api_v2.py @@ -16,11 +16,12 @@ from authentication.models import ExtendedUser class UserSerializer(serializers.ModelSerializer): permissions = serializers.SerializerMethodField() + groups = serializers.SlugRelatedField(many=True, read_only=True, slug_field='name') class Meta: model = ExtendedUser - fields = ('id', 'username', 'email', 'first_name', 'last_name', 'permissions') - read_only_fields = ('id', 'username', 'email', 'first_name', 'last_name', 'permissions') + fields = ('id', 'username', 'email', 'first_name', 'last_name', 'permissions', 'groups') + read_only_fields = ('id', 'username', 'email', 'first_name', 'last_name', 'permissions', 'groups') def get_permissions(self, obj): return list(set(obj.get_permissions())) diff --git a/core/authentication/tests/v2/test_users.py b/core/authentication/tests/v2/test_users.py index c60cbcc..125be9b 100644 --- a/core/authentication/tests/v2/test_users.py +++ b/core/authentication/tests/v2/test_users.py @@ -38,10 +38,13 @@ class UserApiTest(TestCase): self.assertEqual(response.json()[0]['first_name'], '') self.assertEqual(response.json()[0]['last_name'], '') self.assertEqual(response.json()[0]['id'], 1) + self.assertEqual(response.json()[0]['groups'], []) self.assertEqual(response.json()[1]['username'], 'testuser') self.assertEqual(response.json()[1]['email'], 'test') self.assertEqual(response.json()[1]['first_name'], '') self.assertEqual(response.json()[1]['last_name'], '') + self.assertEqual(response.json()[1]['id'], 2) + self.assertEqual(response.json()[1]['groups'], ['testgroup1', 'testgroup2']) def test_self_user(self): response = self.client.get('/api/2/self/') diff --git a/web/src/components/Matrix2D.vue b/web/src/components/Matrix2D.vue new file mode 100644 index 0000000..dd9fdbc --- /dev/null +++ b/web/src/components/Matrix2D.vue @@ -0,0 +1,45 @@ + + + + + \ No newline at end of file diff --git a/web/src/components/Matrix3D.vue b/web/src/components/Matrix3D.vue new file mode 100644 index 0000000..bf731d3 --- /dev/null +++ b/web/src/components/Matrix3D.vue @@ -0,0 +1,61 @@ + + + + + \ No newline at end of file diff --git a/web/src/components/Table3D.vue b/web/src/components/Table3D.vue deleted file mode 100644 index dc0acc4..0000000 --- a/web/src/components/Table3D.vue +++ /dev/null @@ -1,72 +0,0 @@ - - - - - \ No newline at end of file diff --git a/web/src/main.js b/web/src/main.js index 6111cd4..597802a 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -36,6 +36,7 @@ import { faUser, faComments, faArchive, + faMinus, } from '@fortawesome/free-solid-svg-icons'; import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'; @@ -43,7 +44,7 @@ import vueDebounce from 'vue-debounce'; library.add(faPlus, faCheckCircle, faEdit, faTrash, faCat, faSyncAlt, faSort, faSortUp, faSortDown, faTh, faList, faWindowClose, faCamera, faStop, faPen, faCheck, faTimes, faSave, faEye, faComment, faUser, faComments, faEnvelope, - faArchive); + faArchive, faMinus); Vue.component('font-awesome-icon', FontAwesomeIcon); //import VueQRCodeComponent from 'vue-qrcode-component' diff --git a/web/src/store/index.js b/web/src/store/index.js index 9092495..5109142 100644 --- a/web/src/store/index.js +++ b/web/src/store/index.js @@ -167,6 +167,9 @@ const store = new Vuex.Store({ if (user) localStorage.setItem('user', user); }, + setPassword(state, password) { + state.password = password; + }, setPermissions(state, permissions) { state.userPermissions = permissions; if (permissions) @@ -186,7 +189,8 @@ const store = new Vuex.Store({ localStorage.removeItem('permissions'); localStorage.removeItem('token'); localStorage.removeItem('token_expiry'); - router.push('/login'); + if (router.currentRoute.name !== 'login') + router.push('/login'); }, }, actions: { @@ -216,23 +220,24 @@ const store = new Vuex.Store({ }, async reloadToken({commit, state}) { try { - const data = await fetch('/api/2/login/', { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({username: state.user, password: state.password}), - credentials: 'omit' - }).then(r => r.json()) - if (data.token) { - commit('setToken', data); - axios.defaults.headers.common['Authorization'] = `Token ${data.token}`; - return true; + if (data.password) { + const data = await fetch('/api/2/login/', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({username: state.user, password: state.password}), + credentials: 'omit' + }).then(r => r.json()) + if (data.token) { + commit('setToken', data); + axios.defaults.headers.common['Authorization'] = `Token ${data.token}`; + return true; + } } } catch (e) { console.error(e); } //credentials failed, logout store.commit('logout'); - router.push('/login'); }, async afterLogin({dispatch}) { const boxes = dispatch('loadBoxes'); diff --git a/web/src/views/admin/AccessControl.vue b/web/src/views/admin/AccessControl.vue index fd02246..339e35a 100644 --- a/web/src/views/admin/AccessControl.vue +++ b/web/src/views/admin/AccessControl.vue @@ -1,40 +1,59 @@