Browse Source

Merge branch 'master' into kris/add_restore_ui

# Conflicts:
#	src/_store/system.module.js
#	src/account/NetworkPage.vue
pull/8/head
Kristijan Mitrovic 4 years ago
parent
commit
996764eb56
12 changed files with 164 additions and 97 deletions
  1. +5
    -0
      src/_services/device.service.js
  2. +4
    -1
      src/_store/account.module.js
  3. +20
    -0
      src/_store/devices.module.js
  4. +2
    -1
      src/_store/system.module.js
  5. +92
    -29
      src/account/DevicesPage.vue
  6. +10
    -1
      src/account/NetworkPage.vue
  7. +12
    -12
      src/account/profile/ProfilePage.vue
  8. +1
    -1
      src/admin/AccountsPage.vue
  9. +5
    -1
      src/app/App.vue
  10. +0
    -40
      src/app/CheckCertPage.vue
  11. +8
    -0
      src/auth/AppLoginPage.vue
  12. +5
    -11
      src/auth/RegisterPage.vue

+ 5
- 0
src/_services/device.service.js View File

@@ -9,6 +9,7 @@ export const deviceService = {
getDevicesByUserId,
getAllDevicesByUserId,
getAllDeviceTypesByUserId,
setDeviceSecurityLevel,
getDeviceQRcodeById,
getDeviceVPNconfById,
addDeviceByUserId,
@@ -27,6 +28,10 @@ function getAllDeviceTypesByUserId(userId, messages, errors) {
return fetch(`${config.apiUrl}/users/${userId}/deviceTypes`, util.getWithAuth()).then(util.handleCrudResponse(messages, errors));
}

function setDeviceSecurityLevel(userId, deviceId, securityLevel, messages, errors) {
return fetch(`${config.apiUrl}/users/${userId}/devices/${deviceId}/securityLevel/${securityLevel}`, util.postWithAuth()).then(util.handleCrudResponse(messages, errors));
}

function getDeviceQRcodeById(userId, deviceId, messages, errors) {
return fetch(`${config.apiUrl}/users/${userId}/devices/${deviceId}/vpn/QR.png.base64`, util.getWithAuth()).then(util.handlePlaintextResponse(messages, errors));
}


+ 4
- 1
src/_store/account.module.js View File

@@ -270,7 +270,10 @@ const mutations = {
state.user = null;
},

appLoginRequest(state) {},
appLoginRequest(state) {
state.loginError = null;
state.status = Object.assign({}, state.status, {loggingIn: true});
},
appLoginSuccess(state, {user, uri}) {
if (user.token) {
if (util.currentUser() === null) {


+ 20
- 0
src/_store/devices.module.js View File

@@ -46,6 +46,15 @@ const actions = {
);
},

setDeviceSecurityLevel({ commit }, {userId, deviceId, securityLevel, messages, errors}) {
commit('setDeviceSecurityLevelRequest');
deviceService.setDeviceSecurityLevel(userId, deviceId, securityLevel, messages, errors)
.then(
device => commit('setDeviceSecurityLevelSuccess', device),
error => commit('setDeviceSecurityLevelFailure', error)
);
},

getDeviceQRcodeById({ commit }, {userId, deviceId, messages, errors}) {
commit('getDeviceQRcodeByIdRequest');
deviceService.getDeviceQRcodeById(userId, deviceId, messages, errors)
@@ -108,6 +117,17 @@ const mutations = {
state.error = error;
},

setDeviceSecurityLevelRequest(state) {
state.loading.setSecurityLevel = true;
},
setDeviceSecurityLevelSuccess(state, device) {
state.loading.setSecurityLevel = false;
},
setDeviceSecurityLevelFailure(state, error) {
state.loading.setSecurityLevel = false;
state.error = error;
},

getDeviceQRcodeByIdRequest(state) {
state.loading.qrCode = true;
state.qrCodeImageBase64 = null;


+ 2
- 1
src/_store/system.module.js View File

@@ -22,7 +22,8 @@ const state = {
promoCodePolicy: null,
requireSendMetrics: null,
isInRestoringStatus: false,
support: {}
support: {},
securityLevels: null
},
entityConfigs: {},
searchResults: [],


+ 92
- 29
src/account/DevicesPage.vue View File

@@ -8,11 +8,13 @@
<thead>
<tr>
<th nowrap="nowrap">{{messages.label_field_device_name}}</th>
<th nowrap="nowrap">{{messages.label_field_device_type}}</th>
<!-- <th nowrap="nowrap">{{messages.label_field_device_type}}</th>-->
<th nowrap="nowrap">{{messages.label_field_device_app}}</th>
<!-- <th nowrap="nowrap">{{messages.label_field_device_enabled}}</th>-->
<th>{{messages.label_field_device_vpn_config}}</th>
<th nowrap="nowrap">{{messages.label_field_device_certificate}}</th>
<th>{{messages.label_field_device_ctime}}</th>
<th nowrap="nowrap">{{messages.label_field_security_level}}</th>
<!-- <th>{{messages.label_field_device_ctime}}</th>-->
<th>{{messages.label_field_device_help}}</th>
<th><!-- delete --></th>
</tr>
@@ -20,32 +22,57 @@
<tbody>
<tr v-for="device in devices">
<td nowrap="nowrap">{{device.name}}</td>
<td nowrap="nowrap">{{messages['device_type_'+device.deviceType]}}</td>
<!-- <td nowrap="nowrap">-->
<!-- <i :class="messages['device_type_icon_'+device.deviceType]+' bubble-app-icon'"></i><br/>-->
<!-- {{messages['device_type_'+device.deviceType]}}-->
<!-- </td>-->
<td align="center">
<a v-if="appLinks" target="_blank" rel="noopener noreferrer" :href="appLinks[device.deviceType]">
<i :class="messages['device_type_icon_'+device.deviceType]+' bubble-app-icon'"></i><br/>
{{messages.message_download_app}}
</a>
</td>
<!-- <td>{{messages['message_'+device.enabled]}}</td>-->
<td>
<div v-if="displayVpnConfig[device.uuid] === true" class="device-vpn-config-div">
<h3>{{device.name}}</h3>
<hr/>

<div v-if="qrCodeImageBase64">
<div v-if="qrCodeImageBase64 && messages['device_type_vpn_'+device.deviceType] === 'show_qr_code'">
<img :src="'data:image/png;base64,'+qrCodeImageBase64"/>
<div v-if="errors.has('deviceQRcode')" class="invalid-feedback d-block">{{ errors.first('deviceQRcode') }}</div>
</div>
<div v-else-if="vpnConfBase64 && messages['device_type_vpn_'+device.deviceType] === 'download_conf'">
<button v-if="vpnConfBase64" @click="util.downloadURI('data:text/plain;base64,'+vpnConfBase64, 'vpn.conf')">{{messages.message_device_vpn_download_conf}}</button>
<div v-if="errors.has('deviceVpnConf')" class="invalid-feedback d-block">{{ errors.first('deviceVpnConf') }}</div>
</div>
<div v-else>
<h5>{{messages.message_device_vpn_unavailable}}</h5>
</div>
<div v-if="errors.has('deviceQRcode')" class="invalid-feedback d-block">{{ errors.first('deviceQRcode') }}</div>

<hr/>

<button v-if="vpnConfBase64" @click="util.downloadURI('data:text/plain;base64,'+vpnConfBase64, 'vpn.conf')">{{messages.message_device_vpn_download_conf}}</button>
<div v-if="errors.has('deviceVpnConf')" class="invalid-feedback d-block">{{ errors.first('deviceVpnConf') }}</div>

<hr/>
<button @click="hideVpnConfig()" class="btn btn-primary">{{messages.button_label_close_device_vpn_config}}</button>
</div>
<div v-else-if="messages['!button_label_vpn_config_'+messages['device_type_vpn_'+device.deviceType]]">
<button @click="showVpnConfig(device.uuid)">{{messages['button_label_vpn_config_'+messages['device_type_vpn_'+device.deviceType]]}}</button>
</div>
<div v-else>
<button @click="showVpnConfig(device.uuid)">{{messages.message_device_vpn_show_config}}</button>
{{messages.message_device_vpn_unavailable}}
</div>
</td>
<td nowrap="nowrap"><a v-if="device.deviceType" :href="'/api/auth/cacert?deviceType='+device.deviceType">{{messages['device_type_'+device.deviceType]}}</a></td>
<td nowrap="nowrap">{{messages.label_device_ctime_format.parseDateMessage(device.ctime, messages)}}</td>
<td nowrap="nowrap">
<a :href="'/api/auth/cacert?deviceType='+device.deviceType">
{{messages.message_download_ca_cert}}
</a>
</td>
<td>
<form v-if="configs.securityLevels" @submit.prevent="false">
<input type="hidden" name="deviceId" :value="device.uuid"/>
<select v-model="device.securityLevel" @change="setSecurityLevel($event)">
<option v-for="level in configs.securityLevels" :value="level">{{messages['device_security_level_'+level]}}</option>
</select>
</form>
</td>
<!-- <td nowrap="nowrap">{{messages.label_device_ctime_format.parseDateMessage(device.ctime, messages)}}</td>-->
<td>
<div v-if="displayDeviceHelp[device.uuid] === true" class="device-help-div">
<div v-html="messages['device_type_'+device.deviceType+'_help_html']"></div>
@@ -76,10 +103,10 @@
<div v-if="submitted && errors.has('deviceName')" class="invalid-feedback d-block">{{ errors.first('deviceName') }}</div>
</div>

<div class="form-group" v-if="deviceTypes">
<div class="form-group" v-if="addableDeviceTypes">
<label htmlFor="deviceType">{{messages.label_field_device_type}}</label>
<select v-model="deviceType" name="deviceType" class="form-control">
<option v-for="type in deviceTypes" :value="type">{{messages['device_type_'+type]}}</option>
<option v-for="type in addableDeviceTypes" :value="type">{{messages['device_type_'+type]}}</option>
</select>
</div>

@@ -92,15 +119,18 @@

<hr/>

<div>
<h4>{{messages.message_download_ca_cert}}</h4>
<!-- todo: use a v-for here, don't explicitly list deviceTypes, which may change -->
<a href="/api/auth/cacert?deviceType=macosx">{{messages.message_os_macosx}}</a> |
<a href="/api/auth/cacert?deviceType=ios">{{messages.message_os_ios}}</a> |
<a href="/api/auth/cacert?deviceType=windows">{{messages.message_os_windows}}</a> |
<a href="/api/auth/cacert?deviceType=android">{{messages.message_os_android}}</a> |
<a href="/api/auth/cacert?deviceType=linux">{{messages.message_os_linux}}</a> |
<a href="/api/auth/cacert?deviceType=firefox">{{messages.message_os_firefox}}</a>
<div v-if="certDeviceTypes">
<table border="0" width="100%">
<tr><td colspan="5"><h4>{{messages.message_download_ca_cert}}</h4></td></tr>
<tr>
<td v-for="certDevice in certDeviceTypes" align="center" :width="certDeviceWidth+'%'">
<a :href="'/api/auth/cacert?deviceType='+certDevice">
<i :class="messages['device_type_icon_'+certDevice]+' bubble-app-icon'"></i><br/>
{{messages['device_type_'+certDevice]}}
</a>
</td>
</tr>
</table>
<hr/>
</div>
</div>
@@ -128,10 +158,28 @@
},
computed: {
...mapState('devices', ['deviceTypes', 'devices', 'device', 'qrCodeImageBase64', 'vpnConfBase64']),
...mapState('system', ['messages']),
...mapState('system', ['messages', 'appLinks', 'configs']),
...mapGetters('devices', ['loading']),
addDeviceReady: function () {
return this.deviceName !== null && this.deviceName !== '' && this.deviceType !== null && this.deviceType !== '';
},
addableDeviceTypes: function () {
if (this.messages && this.messages['!addable_device_types']) {
return this.messages['addable_device_types'].split('|');
}
return [];
},
addableDeviceWidth: function () {
return 100.0/this.addableDeviceTypes.length
},
certDeviceTypes: function () {
if (this.messages && this.messages['!cert_device_types']) {
return this.messages['cert_device_types'].split('|');
}
return [];
},
certDeviceWidth: function () {
return 100.0/this.certDeviceTypes.length
}
},
created () {
@@ -144,7 +192,10 @@
userId: this.userId,
messages: this.messages,
errors: this.errors
})
});
const user = util.currentUser();
if (user) this.getAppLinks(user.locale);
this.loadSystemConfigs();
},
mounted() {
window.addEventListener('keyup', ev => {
@@ -157,8 +208,9 @@
methods: {
...mapActions('devices', [
'getAllDeviceTypesByUserId', 'getDevicesByUserId', 'addDeviceByUserId', 'removeDeviceByUserId',
'getDeviceQRcodeById', 'getDeviceVPNconfById'
'getDeviceQRcodeById', 'getDeviceVPNconfById', 'setDeviceSecurityLevel'
]),
...mapActions('system', ['getAppLinks', 'loadSystemConfigs']),
addDevice () {
this.errors.clear();
this.submitted = true;
@@ -182,7 +234,17 @@
errors: this.errors
});
},
setSecurityLevel (event) {
this.setDeviceSecurityLevel({
userId: this.userId,
deviceId: event.target.form.deviceId.value,
securityLevel: event.target.value,
messages: this.messages,
errors: this.errors
});
},
showVpnConfig (id) {
this.hideDeviceHelp();
const show = {};
show[id] = true;
this.errors.clear();
@@ -203,6 +265,7 @@
hideVpnConfig () { this.displayVpnConfig = {}; },

showDeviceHelp (id) {
this.hideVpnConfig();
this.displayDeviceHelp = {};
this.displayDeviceHelp[id] = true;
},
@@ -214,7 +277,7 @@
// after device added, clear device fields
this.deviceName = null;
this.deviceType = null;
if (dev.uuid) this.displayDeviceHelp[dev.uuid] = true;
if (dev.uuid) this.showVpnConfig(dev.uuid);
}
}
}


+ 10
- 1
src/account/NetworkPage.vue View File

@@ -20,7 +20,7 @@
<h5 v-html="messages.title_launch_help_html"></h5>
<div v-if="network && network.state === 'running'" v-html="messages.message_launch_success_help_html"></div>
<div v-else v-html="messages.message_launch_help_html"></div>
<div v-if="appLinks">
<div v-if="appLinks && addableDeviceTypes">
<div v-if="network && network.state === 'running'" v-html="messages.message_launch_success_apps"></div>
<div v-else v-html="messages.message_launch_help_apps"></div>
<br/>
@@ -204,6 +204,15 @@
showSetupHelp () {
return (this.network !== null && this.network.uuid !== this.configs.networkUuid
&& (this.network.state === 'running' || this.network.state === 'starting'));
},
addableDeviceTypes: function () {
if (this.messages && this.messages['!addable_device_types']) {
return this.messages['addable_device_types'].split('|');
}
return [];
},
addableDeviceWidth: function () {
return 100.0/this.addableDeviceTypes.length
}
},
methods: {


+ 12
- 12
src/account/profile/ProfilePage.vue View File

@@ -41,17 +41,17 @@
<div v-if="submitted && errors.has('password')" class="invalid-feedback d-block">{{ errors.first('password') }}</div>
</div>

<div class="form-group">
<label htmlFor="url">{{messages.field_label_url}}</label>
<input type="text" v-model="subject.url" name="url" class="form-control"/>
<div v-if="submitted && errors.has('url')" class="invalid-feedback d-block">{{ errors.first('url') }}</div>
</div>
<!-- <div class="form-group">-->
<!-- <label htmlFor="url">{{messages.field_label_url}}</label>-->
<!-- <input type="text" v-model="subject.url" name="url" class="form-control"/>-->
<!-- <div v-if="submitted && errors.has('url')" class="invalid-feedback d-block">{{ errors.first('url') }}</div>-->
<!-- </div>-->

<div class="form-group">
<label htmlFor="description">{{messages.field_label_description}}</label>
<input type="text" v-model="subject.description" name="description" class="form-control"/>
<div v-if="submitted && errors.has('description')" class="invalid-feedback d-block">{{ errors.first('description') }}</div>
</div>
<!-- <div class="form-group">-->
<!-- <label htmlFor="description">{{messages.field_label_description}}</label>-->
<!-- <input type="text" v-model="subject.description" name="description" class="form-control"/>-->
<!-- <div v-if="submitted && errors.has('description')" class="invalid-feedback d-block">{{ errors.first('description') }}</div>-->
<!-- </div>-->

<div v-if="admin === true && currentUser.uuid !== subject.uuid" class="form-group">
<label for="admin">{{messages.field_label_administrator}}</label>
@@ -219,9 +219,9 @@
watch: {
user (u) {
if (u) {
console.log('watch.user: received: '+JSON.stringify(u));
// console.log('watch.user: received: '+JSON.stringify(u));
if (this.submitted) {
console.log('watch.user: action was successful, refreshing page');
// console.log('watch.user: action was successful, refreshing page');
if (this.me) {
this.$router.push('/');
} else if (this.admin) {


+ 1
- 1
src/admin/AccountsPage.vue View File

@@ -105,7 +105,7 @@
watch: {
users (uList) {
if (uList !== null && this.lastAction !== null) {
console.log('watch.users: updated, refreshing...');
// console.log('watch.users: updated, refreshing...');
this.lastAction = null;
this.refreshData()
}


+ 5
- 1
src/app/App.vue View File

@@ -92,7 +92,11 @@ export default {
} else {
const user = util.currentUser();
if (user !== null && (typeof user.token !== 'undefined' && user.token !== null)) {
this.checkSession({messages: this.messages, errors: this.errors});
if (this.status.loggingIn || this.status.loggedIn) {
// console.log('activated: this.status.loggingIn='+this.status.loggingIn+', this.status.loggedIn='+this.status.loggedIn+', not checking session');
} else {
this.checkSession({messages: this.messages, errors: this.errors});
}
}
}
},


+ 0
- 40
src/app/CheckCertPage.vue View File

@@ -1,40 +0,0 @@
<!-- Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ -->
<template>
<div>
<h2>{{messages.title_check_certificate}}</h2>
<hr/>
<div v-if="cert_verified !== null">
<h4>{{messages['check_cert_'+cert_verified]}}</h4> ({{cert_verified}})
</div>
<!-- <iframe style="visibility: hidden" id="cert_check_frame" v-if="configs && configs.certValidationHost" :src="'https://'+configs.certValidationHost" @load="frameLoaded()"></iframe>-->
<iframe id="cert_check_frame" v-if="configs && configs.certValidationHost" :src="'https://'+configs.certValidationHost" @load="frameLoaded()"></iframe>
</div>
</template>

<script>
import { mapState, mapActions } from 'vuex'
export default {
data() {
return {
cert_verified: null
}
},
computed: {
...mapState('system', ['messages', 'configs'])
},
created() {
this.loadSystemConfigs();
const vue = this;
window.setTimeout(() => {
if (vue.cert_verified === null) vue.cert_verified = false;
}, 10000);
},
methods: {
...mapActions('system', ['loadSystemConfigs']),
frameLoaded() {
console.log('frame loaded!');
this.cert_verified = true;
}
}
};
</script>

+ 8
- 0
src/auth/AppLoginPage.vue View File

@@ -53,6 +53,14 @@
methods: {
...mapActions('account', ['login', 'logout', 'appLogin']),
...mapActions('system', ['loadSystemConfigs', 'loadMessages']),
},
watch: {
user (u) {
if (u.token) {
this.loadMessages('post_auth', u.locale);
this.loadMessages('apps', u.locale);
}
}
}
};
</script>

+ 5
- 11
src/auth/RegisterPage.vue View File

@@ -132,17 +132,6 @@ export default {
if (this.user.password !== this.confirmPassword) {
this.errors.add({field: 'confirmPassword', msg: this.messages['err_confirmPassword_mismatch']})
} else {
if (this.plan !== null) {
// if (this.paymentMethodObject === null) {
// this.errors.add({field: 'paymentMethod', msg: this.messages['err_paymentMethod_required']});
// return;
// } else {
console.log('handleSubmit: setting this.user.preferredPlan = '+this.plan.uuid);
this.user.preferredPlan = this.plan.uuid;
// this.user.paymentMethodObject = this.paymentMethodObject;
// this.user.paymentMethodObject.cloud = this.selectedPaymentMethod.name;
// }
}
this.register({
user: this.user,
messages: this.messages,
@@ -174,6 +163,11 @@ export default {
if (apm) {
this.paymentMethodObject = apm;
}
},
plan (p) {
if (p.uuid) {
this.user.preferredPlan = p.uuid;
}
}
}
};


Loading…
Cancel
Save