mirror of
https://github.com/Lissy93/dashy.git
synced 2025-07-26 23:24:38 +02:00
🚧 Move user processing from widget to mixin
plus * some template and style tweaking * improve tooltips * enforce Nextcloud app-password instead of login password
This commit is contained in:
parent
caf131df23
commit
a43988f3cd
@ -11,11 +11,11 @@
|
|||||||
<div class="info">
|
<div class="info">
|
||||||
<p class="brand">{{ branding.name }}</p>
|
<p class="brand">{{ branding.name }}</p>
|
||||||
<p class="version" v-if="version.string">
|
<p class="version" v-if="version.string">
|
||||||
{{ $t('widgets.nextcloud-info.label-version') }} {{ version.string }}
|
<small>{{ $t('widgets.nextcloud-info.label-version') }} {{ version.string }}</small>
|
||||||
</p>
|
</p>
|
||||||
<p class="username">{{ user.displayName }} <em v-if="user.id">({{ user.id }})</em></p>
|
<p class="username">{{ user.displayName }} <em v-if="user.id">({{ user.id }})</em></p>
|
||||||
<p class="login" v-tooltip="lastLoginTooltip()">
|
<p class="login" v-tooltip="lastLoginTooltip()">
|
||||||
{{ $t('widgets.nextcloud-info.label-last-login') }}
|
<span>{{ $t('widgets.nextcloud-info.label-last-login') }}</span>
|
||||||
<small>{{ getTimeAgo(user.lastLogin) }}</small>
|
<small>{{ getTimeAgo(user.lastLogin) }}</small>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@ -76,10 +76,10 @@
|
|||||||
<p v-tooltip="sharesTooltip()">
|
<p v-tooltip="sharesTooltip()">
|
||||||
<i class="fal fa-share"></i>
|
<i class="fal fa-share"></i>
|
||||||
<em>{{ formatNumber(server.nextcloud.shares.num_shares) }}</em>
|
<em>{{ formatNumber(server.nextcloud.shares.num_shares) }}</em>
|
||||||
<strong>{{ $t('shares') }}</strong> <small> {{ $t('and') }}</small>
|
<strong>{{ $t('autonomous') }}</strong> <small> {{ $t('and') }}</small>
|
||||||
<em>
|
<em>
|
||||||
{{ formatNumber(server.nextcloud.shares.num_fed_shares_sent) }}
|
{{ formatNumber(server.nextcloud.shares.num_fed_shares_sent +
|
||||||
/ {{ formatNumber(server.nextcloud.shares.num_fed_shares_received) }}
|
server.nextcloud.shares.num_fed_shares_received) }}
|
||||||
</em>
|
</em>
|
||||||
<strong>{{ $t('federated shares') }}</strong>
|
<strong>{{ $t('federated shares') }}</strong>
|
||||||
</p>
|
</p>
|
||||||
@ -109,7 +109,7 @@
|
|||||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||||
import NextcloudMixin from '@/mixins/NextcloudMixin';
|
import NextcloudMixin from '@/mixins/NextcloudMixin';
|
||||||
import { convertBytes } from '@/utils/MiscHelpers';
|
import { convertBytes } from '@/utils/MiscHelpers';
|
||||||
// //import { NcdUsr, NcdServer } from '@/utils/ncd';
|
// //import { NcdServer } from '@/utils/ncd';
|
||||||
|
|
||||||
const NextcloudSchema = {
|
const NextcloudSchema = {
|
||||||
branding: {
|
branding: {
|
||||||
@ -122,19 +122,6 @@ const NextcloudSchema = {
|
|||||||
string: null,
|
string: null,
|
||||||
edition: null,
|
edition: null,
|
||||||
},
|
},
|
||||||
user: {
|
|
||||||
id: null,
|
|
||||||
isAdmin: false,
|
|
||||||
displayName: null,
|
|
||||||
email: null,
|
|
||||||
quota: {
|
|
||||||
relative: null,
|
|
||||||
total: null,
|
|
||||||
used: null,
|
|
||||||
free: null,
|
|
||||||
quota: null,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
server: {
|
server: {
|
||||||
server: {
|
server: {
|
||||||
webserver: null,
|
webserver: null,
|
||||||
@ -213,33 +200,15 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchData() {
|
async fetchData() {
|
||||||
const promise = this.fetchCapabilities()
|
await this.loadCapabilities();
|
||||||
.then(() => this.makeRequest(this.endpoint('user'), this.headers))
|
await this.loadUser();
|
||||||
// //.then(() => NcdUsr)
|
|
||||||
.then(this.processUser);
|
|
||||||
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
if (this.user.isAdmin) {
|
if (this.user.isAdmin) {
|
||||||
promise.then(() => this.makeRequest(this.endpoint('serverinfo'), this.headers))
|
this.processServerInfo(
|
||||||
// //promise.then(() => NcdServer)
|
await this.makeRequest(this.endpoint('serverinfo'), this.headers),
|
||||||
.then(this.processServerInfo);
|
// //NcdServer,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
this.finishLoading();
|
||||||
promise.finally(() => this.finishLoading());
|
|
||||||
},
|
|
||||||
processUser(userData) {
|
|
||||||
const user = userData?.ocs?.data;
|
|
||||||
if (!user) {
|
|
||||||
this.error('Invalid response');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.user.id = user.id;
|
|
||||||
this.user.email = user.email;
|
|
||||||
this.user.quota = user.quota;
|
|
||||||
this.user.displayName = user.displayname;
|
|
||||||
this.user.lastLogin = user.lastLogin;
|
|
||||||
this.user.isAdmin = user.groups && user.groups.includes('admin');
|
|
||||||
},
|
},
|
||||||
processServerInfo(serverData) {
|
processServerInfo(serverData) {
|
||||||
const data = serverData?.ocs?.data;
|
const data = serverData?.ocs?.data;
|
||||||
@ -278,10 +247,10 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
appUpdatesTooltip() {
|
appUpdatesTooltip() {
|
||||||
const content = 'Updates are available for: '
|
const content = 'Updates are available for:<br><br>'
|
||||||
+ ` ${Object.keys(this.server.nextcloud.system.apps.app_updates).join(', ')}`;
|
+ ` ${Object.entries(this.server.nextcloud.system.apps.app_updates).join('<br>')}`;
|
||||||
return {
|
return {
|
||||||
content, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
|
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
storagesTooltip() {
|
storagesTooltip() {
|
||||||
@ -302,7 +271,9 @@ export default {
|
|||||||
+ `${this.server.nextcloud.shares.num_shares_room} chat room<br>`
|
+ `${this.server.nextcloud.shares.num_shares_room} chat room<br>`
|
||||||
+ `${this.server.nextcloud.shares.num_shares_link} private link<br>`
|
+ `${this.server.nextcloud.shares.num_shares_link} private link<br>`
|
||||||
+ `${this.server.nextcloud.shares.num_shares_link_no_password} public link<br>`
|
+ `${this.server.nextcloud.shares.num_shares_link_no_password} public link<br>`
|
||||||
+ '<br><sup>*</sup>Federated shares: sent/received';
|
+ '<br>Federated shares:<br><br>'
|
||||||
|
+ `${this.server.nextcloud.shares.num_fed_shares_sent} sent<br>`
|
||||||
|
+ `${this.server.nextcloud.shares.num_fed_shares_received} received<br>`;
|
||||||
return {
|
return {
|
||||||
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
|
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
|
||||||
};
|
};
|
||||||
@ -351,6 +322,9 @@ export default {
|
|||||||
font-size: 105%;
|
font-size: 105%;
|
||||||
margin-left: .25rem;
|
margin-left: .25rem;
|
||||||
}
|
}
|
||||||
|
small {
|
||||||
|
opacity: .66;
|
||||||
|
}
|
||||||
hr {
|
hr {
|
||||||
color: var(--widget-text-color);
|
color: var(--widget-text-color);
|
||||||
border: none;
|
border: none;
|
||||||
@ -376,14 +350,13 @@ export default {
|
|||||||
margin: 0 0 1rem 0;
|
margin: 0 0 1rem 0;
|
||||||
}
|
}
|
||||||
p.brand {
|
p.brand {
|
||||||
margin: 0 0 .23rem 0;
|
margin: 0;
|
||||||
font-size: 135%;
|
font-size: 135%;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 3px;
|
letter-spacing: 3px;
|
||||||
}
|
}
|
||||||
p.version {
|
p.version small {
|
||||||
font-size: 80%;
|
font-size: 75%;
|
||||||
opacity: .66;
|
|
||||||
}
|
}
|
||||||
p.username {
|
p.username {
|
||||||
font-size: 110%;
|
font-size: 110%;
|
||||||
@ -392,17 +365,16 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.login {
|
p.login {
|
||||||
|
span {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
small {
|
margin-right: .25rem;
|
||||||
opacity: .75;
|
|
||||||
margin-left: .25rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div.server-info {
|
div.server-info {
|
||||||
span[data-has-updates] {
|
span[data-has-updates] {
|
||||||
color: var(--success);
|
color: var(--success);
|
||||||
padding-left: .75rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { serviceEndpoints } from '@/utils/defaults';
|
import { serviceEndpoints } from '@/utils/defaults';
|
||||||
import { convertBytes, formatNumber, getTimeAgo } from '@/utils/MiscHelpers';
|
import { convertBytes, formatNumber, getTimeAgo } from '@/utils/MiscHelpers';
|
||||||
// //import { NcdCap } from '@/utils/ncd';
|
// //import { NcdCap, NcdUsr } from '@/utils/ncd';
|
||||||
|
|
||||||
/** Reusable mixin for Nextcloud widgets */
|
/** Reusable mixin for Nextcloud widgets */
|
||||||
export default {
|
export default {
|
||||||
@ -11,6 +11,19 @@ export default {
|
|||||||
activity: null,
|
activity: null,
|
||||||
},
|
},
|
||||||
capabilitiesLastUpdated: 0,
|
capabilitiesLastUpdated: 0,
|
||||||
|
user: {
|
||||||
|
id: null,
|
||||||
|
isAdmin: false,
|
||||||
|
displayName: null,
|
||||||
|
email: null,
|
||||||
|
quota: {
|
||||||
|
relative: null,
|
||||||
|
total: null,
|
||||||
|
used: null,
|
||||||
|
free: null,
|
||||||
|
quota: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -24,6 +37,9 @@ export default {
|
|||||||
},
|
},
|
||||||
password() {
|
password() {
|
||||||
if (!this.options.password) this.error('An app-password is required');
|
if (!this.options.password) this.error('An app-password is required');
|
||||||
|
if (!/^([a-z0-9]{5}-){4}[a-z0-9]{5}$/i.test(this.options.password)) {
|
||||||
|
this.error('Please use an app-password for this widget, not your login password.');
|
||||||
|
}
|
||||||
return this.options.password;
|
return this.options.password;
|
||||||
},
|
},
|
||||||
headers() {
|
headers() {
|
||||||
@ -33,6 +49,9 @@ export default {
|
|||||||
Authorization: `Basic ${window.btoa(`${this.username}:${this.password}`)}`,
|
Authorization: `Basic ${window.btoa(`${this.username}:${this.password}`)}`,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
capabilitiesTtl() {
|
||||||
|
return (parseInt(this.options.capabilitiesTtl, 10) || 3600) * 1000;
|
||||||
|
},
|
||||||
proxyReqEndpoint() {
|
proxyReqEndpoint() {
|
||||||
const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin;
|
const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin;
|
||||||
return `${baseUrl}${serviceEndpoints.corsProxy}`;
|
return `${baseUrl}${serviceEndpoints.corsProxy}`;
|
||||||
@ -40,21 +59,23 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
endpoint(id) {
|
endpoint(id) {
|
||||||
const endpoints = {
|
switch (id) {
|
||||||
capabilities: `${this.hostname}/ocs/v1.php/cloud/capabilities`,
|
case 'capabilities':
|
||||||
user: `${this.hostname}/ocs/v1.php/cloud/users/${this.username}`,
|
default:
|
||||||
serverinfo: `${this.hostname}/ocs/v2.php/apps/serverinfo/api/v1/info`,
|
return `${this.hostname}/ocs/v1.php/cloud/capabilities`;
|
||||||
};
|
case 'user':
|
||||||
return endpoints[id];
|
return `${this.hostname}/ocs/v1.php/cloud/users/${this.username}`;
|
||||||
|
case 'serverinfo':
|
||||||
|
return `${this.hostname}/ocs/v2.php/apps/serverinfo/api/v1/info`;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fetchCapabilities() {
|
loadCapabilities() {
|
||||||
const promise = Promise.resolve();
|
if ((new Date().getTime()) - this.capabilitiesLastUpdated > this.capabilitiesTtl) {
|
||||||
if ((new Date().getTime()) - this.capabilitiesLastUpdated > 3600000) {
|
return this.makeRequest(this.endpoint('capabilities'), this.headers)
|
||||||
promise.then(() => this.makeRequest(this.endpoint('capabilities'), this.headers))
|
// //return Promise.resolve(NcdCap)
|
||||||
// //promise.then(() => NcdCap)
|
|
||||||
.then(this.processCapabilities);
|
.then(this.processCapabilities);
|
||||||
}
|
}
|
||||||
return promise;
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
processCapabilities(data) {
|
processCapabilities(data) {
|
||||||
const ocdata = data?.ocs?.data;
|
const ocdata = data?.ocs?.data;
|
||||||
@ -69,6 +90,23 @@ export default {
|
|||||||
this.version.edition = ocdata?.version?.edition;
|
this.version.edition = ocdata?.version?.edition;
|
||||||
this.capabilitiesLastUpdated = new Date().getTime();
|
this.capabilitiesLastUpdated = new Date().getTime();
|
||||||
},
|
},
|
||||||
|
loadUser() {
|
||||||
|
return this.makeRequest(this.endpoint('user'), this.headers).then(this.processUser);
|
||||||
|
// //return Promise.resolve(NcdUsr).then(this.processUser);
|
||||||
|
},
|
||||||
|
processUser(userData) {
|
||||||
|
const user = userData?.ocs?.data;
|
||||||
|
if (!user) {
|
||||||
|
this.error('Invalid response');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.user.id = user.id;
|
||||||
|
this.user.email = user.email;
|
||||||
|
this.user.quota = user.quota;
|
||||||
|
this.user.displayName = user.displayname;
|
||||||
|
this.user.lastLogin = user.lastLogin;
|
||||||
|
this.user.isAdmin = user.groups && user.groups.includes('admin');
|
||||||
|
},
|
||||||
formatNumber(number) {
|
formatNumber(number) {
|
||||||
return formatNumber(number);
|
return formatNumber(number);
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user