diff --git a/src/_helpers/router.js b/src/_helpers/router.js
index e507b3e..0739e79 100644
--- a/src/_helpers/router.js
+++ b/src/_helpers/router.js
@@ -2,6 +2,7 @@ import Vue from 'vue';
import Router from 'vue-router';
import HomePage from '../account/HomePage'
+import ActivationPage from '../auth/ActivationPage'
import RegisterPage from '../auth/RegisterPage'
import LoginPage from '../auth/LoginPage'
import MultifactorAuthPage from '../auth/MultifactorAuthPage'
@@ -64,10 +65,13 @@ export const router = new Router({
]
},
{ path: '/action', component: ActionPage },
+
+ { path: '/activate', component: ActivationPage },
{ path: '/register', component: RegisterPage },
{ path: '/auth', component: MultifactorAuthPage },
{ path: '/login', component: LoginPage },
{ path: '/logout', component: LoginPage },
+
{ path: '/admin/accounts', component: AccountsPage },
{ path: '/admin/accounts/:uuid', component: ProfilePage },
@@ -77,7 +81,7 @@ export const router = new Router({
});
router.beforeEach((to, from, next) => {
- const publicPages = ['/login', '/logout', '/register', '/auth'];
+ const publicPages = ['/login', '/logout', '/register', '/auth', '/activate'];
const authRequired = !publicPages.includes(to.path);
const user = util.currentUser();
diff --git a/src/_helpers/util.js b/src/_helpers/util.js
index 5754d09..10089d1 100644
--- a/src/_helpers/util.js
+++ b/src/_helpers/util.js
@@ -26,33 +26,51 @@ export const util = {
getWithAuth: function() {
return {
method: 'GET',
- headers: authHeader()
+ headers: util.authHeader()
};
},
+ entityNoAuth: function(method, obj) {
+ if (typeof obj === 'undefined' || obj === null || obj === 'undefined') {
+ return {
+ method: method,
+ headers: { 'Content-Type': 'application/json' }
+ };
+ } else {
+ return {
+ method: method,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(obj)
+ };
+ }
+ },
+
+ postNoAuth: function(obj) { return util.entityNoAuth('POST', obj); },
+ putNoAuth: function(obj) { return util.entityNoAuth('PUT', obj); },
+
entityWithAuth: function(method, obj) {
if (typeof obj === 'undefined' || obj === null || obj === 'undefined') {
return {
method: method,
- headers: { ...authHeader(), 'Content-Type': 'application/json' }
+ headers: { ...util.authHeader(), 'Content-Type': 'application/json' }
};
} else {
return {
method: method,
- headers: { ...authHeader(), 'Content-Type': 'application/json' },
+ headers: { ...util.authHeader(), 'Content-Type': 'application/json' },
body: JSON.stringify(obj)
};
}
},
- postWithAuth: function(obj) { return entityWithAuth('POST', obj); },
+ postWithAuth: function(obj) { return util.entityWithAuth('POST', obj); },
- putWithAuth: function(obj) { return entityWithAuth('PUT', obj); },
+ putWithAuth: function(obj) { return util.entityWithAuth('PUT', obj); },
deleteWithAuth: function() {
return {
method: 'DELETE',
- headers: authHeader()
+ headers: util.authHeader()
};
},
@@ -116,5 +134,5 @@ export const util = {
}
return false;
};
- },
+ }
};
diff --git a/src/_services/system.service.js b/src/_services/system.service.js
index 9aeec65..0dd17ec 100644
--- a/src/_services/system.service.js
+++ b/src/_services/system.service.js
@@ -2,6 +2,8 @@ import config from 'config';
import { util } from '../_helpers';
export const systemService = {
+ loadIsActivated,
+ activate,
loadSystemConfigs,
loadMessages,
loadTimezones,
@@ -9,6 +11,20 @@ export const systemService = {
detectLocale
};
+function loadIsActivated () {
+ const requestOptions = { method: 'GET' };
+ return fetch(`${config.apiUrl}/auth/activate`, requestOptions)
+ .then(util.handleBasicResponse)
+ .then(activated => { return activated; });
+}
+
+function activate (activation) {
+ const requestOptions = util.putNoAuth(activation);
+ return fetch(`${config.apiUrl}/auth/activate`, requestOptions)
+ .then(util.handleBasicResponse)
+ .then(admin => { return admin; });
+}
+
function loadSystemConfigs() {
const requestOptions = util.userLoggedIn() ? util.getWithAuth() : { method: 'GET' };
return fetch(`${config.apiUrl}/auth/configs`, requestOptions)
diff --git a/src/_store/account.module.js b/src/_store/account.module.js
index 10290e8..0d21176 100644
--- a/src/_store/account.module.js
+++ b/src/_store/account.module.js
@@ -1,12 +1,26 @@
-import { userService } from '../_services';
+import { userService, systemService } from '../_services';
import { router, util } from '../_helpers';
// todo: why can't we import currentUser from api-util and use that here?
// when I try to do that, webpack succeeds but then an error occurs loading any page, with the
// error message "_helpers.currentUser is not defined"
-const user = JSON.parse(localStorage.getItem('user'));
+// const user = JSON.parse(localStorage.getItem('user'));
+const user = util.currentUser();
+
+const defaultStatus = {
+ loggingIn: false,
+ loggedIn: false,
+ registering: false,
+ activating: false,
+ approving: false,
+ denying: false,
+ authenticating: false,
+ sendingVerification: false
+};
+
const state = {
- status: { loggedIn: (user !== null) },
+ activated: null,
+ status: Object.assign({}, defaultStatus, {loggedIn: (user != null)}),
user: user,
actionStatus: {}
};
@@ -122,16 +136,17 @@ const actions = {
const mutations = {
refreshUser(state, user) {
- state.status = { loggedIn: (user !== null) };
+ state.status.loggedIn = (user !== null);
state.user = user;
},
loginRequest(state, user) {
- state.status = { loggingIn: true };
+ state.status.loggingIn = true;
state.user = user;
},
loginSuccess(state, user) {
if (user.token) {
- state.status = { loggedIn: true };
+ state.status.loggingIn = false;
+ state.status.loggedIn = true;
} else if (user.multifactorAuth) {
state.status = { multifactorAuth: true };
} else {
@@ -141,51 +156,60 @@ const mutations = {
state.user = user;
},
loginFailure(state) {
- state.status = {};
+ state.status.loggingIn = false;
state.user = null;
},
logout(state) {
- state.status = {};
+ state.status = Object.assign({}, defaultStatus);
state.user = null;
},
registerRequest(state, user) {
- state.status = { registering: true };
+ state.status.registering = true;
state.user = user;
},
registerSuccess(state, user) {
- state.status = {};
+ state.status.registering = false;
state.user = user;
},
registerFailure(state) {
+ state.status.registering = false;
state.status = {};
},
approveActionRequest(state) {
+ state.status.approving = true;
state.actionStatus = { requesting: true, type: 'approve' };
},
approveActionSuccess(state, user) {
+ state.status.approving = false;
state.actionStatus = { success: true, type: 'approve', result: user };
if (user.token) state.user = user;
},
approveActionFailure(state, error) {
+ state.status.approving = false;
state.actionStatus = { error: error, type: 'approve' };
},
denyActionRequest(state) {
+ state.status.denying = true;
state.actionStatus = { requesting: true, type: 'deny' };
},
denyActionSuccess(state, denial) {
+ state.status.denying = false;
state.actionStatus = { success: true, type: 'deny', result: denial };
state.denial = denial;
},
denyActionFailure(state, error) {
+ state.status.denying = false;
state.actionStatus = { error: error, type: 'deny' };
},
sendAuthenticatorCodeRequest(state) {
+ state.status.authenticating = true;
state.actionStatus = { requesting: true, type: 'approve' };
},
sendAuthenticatorCodeSuccess(state, user) {
+ state.status.authenticating = false;
console.log("sendAuthenticatorCodeSuccess: user="+JSON.stringify(user));
state.actionStatus = { success: true, type: 'approve', result: user };
if (user.token) {
@@ -196,17 +220,21 @@ const mutations = {
}
},
sendAuthenticatorCodeFailure(state, error) {
+ state.status.authenticating = false;
state.actionStatus = { error: error, type: 'approve' };
},
resendVerificationCodeRequest(state) {
+ state.status.sendingVerification = true;
state.actionStatus = { requesting: true, type: 'verify' };
},
resendVerificationCodeSuccess(state, policy) {
+ state.status.sendingVerification = false;
console.log("resendVerificationCodeSuccess: policy="+JSON.stringify(policy));
state.actionStatus = { success: true, type: 'verify', result: policy };
},
resendVerificationCodeFailure(state, error) {
+ state.status.sendingVerification = false;
state.actionStatus = { error: error, type: 'verify' };
}
};
diff --git a/src/_store/system.module.js b/src/_store/system.module.js
index 4a87ecb..21f87d9 100644
--- a/src/_store/system.module.js
+++ b/src/_store/system.module.js
@@ -7,6 +7,7 @@ const state = {
paymentsEnabled: false,
sageLauncher: false
},
+ activated: null,
error: null,
messages: {
durationToMillis: function(count, units) {
@@ -35,6 +36,15 @@ const state = {
};
const actions = {
+ loadIsActivated({ commit }) {
+ commit('loadIsActivatedRequest');
+ systemService.loadIsActivated()
+ .then(
+ activated => commit('loadIsActivatedSuccess', activated),
+ error => commit('loadIsActivatedFailure', error)
+ );
+ },
+
loadSystemConfigs({ commit }) {
commit('loadSystemConfigsRequest');
systemService.loadSystemConfigs()
@@ -150,6 +160,32 @@ const messageNotFoundHandler = {
};
const mutations = {
+ loadIsActivatedRequest(state) {
+ console.log('loadIsActivatedRequest: starting');
+ },
+ loadIsActivatedSuccess(state, activated) {
+ console.log('loadIsActivatedSuccess: received '+activated);
+ state.activated = activated;
+ },
+ loadIsActivatedFailure(state, error) {
+ console.log('loadIsActivatedFailure: failed: '+error);
+ state.errors.activated = error;
+ },
+
+ activateRequest(state) {
+ state.status.activating = true;
+ },
+ activateSuccess(state, admin) {
+ state.status.activating = false;
+ state.activated = true;
+ state.user = admin;
+ state.status = { loggedIn: (admin !== null) };
+ },
+ activateFailure(state, error) {
+ state.status.activating = false;
+ state.errors.activated = error;
+ },
+
loadSystemConfigsRequest(state) {},
loadSystemConfigsSuccess(state, configs) {
state.configs = configs;
diff --git a/src/app/App.vue b/src/app/App.vue
index c066df3..afc34d8 100644
--- a/src/app/App.vue
+++ b/src/app/App.vue
@@ -19,7 +19,7 @@ export default {
name: 'app',
computed: {
...mapState('account', ['status']),
- ...mapState('system', ['configs', 'messages', 'menu']),
+ ...mapState('system', ['activated', 'configs', 'messages', 'menu']),
...mapGetters('system', ['menu']),
...mapState({
alert: state => state.alert
@@ -27,15 +27,20 @@ export default {
},
methods: {
...mapActions({ clearAlert: 'alert/clear' }),
- ...mapActions('system', ['loadSystemConfigs', 'loadMessages', 'loadTimezones'])
+ ...mapActions('system', ['loadIsActivated', 'loadSystemConfigs', 'loadMessages', 'loadTimezones'])
},
watch: {
$route (to, from){
// clear alert on location change
this.clearAlert();
+ },
+ activated (active) {
+ console.log('App.watch.activated: received: '+active);
+ if (!active) this.$router.replace('/activate');
}
},
created() {
+ this.loadIsActivated();
this.loadSystemConfigs(); // determine if we can show the registration link
// todo: allow user to choose locale
diff --git a/src/auth/ActivationPage.vue b/src/auth/ActivationPage.vue
new file mode 100644
index 0000000..00df7f0
--- /dev/null
+++ b/src/auth/ActivationPage.vue
@@ -0,0 +1,52 @@
+
+
+ Activation Page
+
+
+
+
\ No newline at end of file