Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/tasks.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRaimund Schlüßler <raimund.schluessler@mailbox.org>2020-04-30 11:42:20 +0300
committerRaimund Schlüßler <raimund.schluessler@mailbox.org>2020-04-30 19:37:43 +0300
commitfd1e90a244b963a33f7aa33a33c9d53f0966cc69 (patch)
treed50b05de4bdb0967c719b2b47d2508a82383a218 /src
parent740903e8838a044f5c548be7f4982da861b1f03d (diff)
Allow sharing with circles
Signed-off-by: Raimund Schlüßler <raimund.schluessler@mailbox.org>
Diffstat (limited to 'src')
-rw-r--r--src/components/AppNavigation/CalendarShare.vue161
-rw-r--r--src/store/calendars.js19
2 files changed, 148 insertions, 32 deletions
diff --git a/src/components/AppNavigation/CalendarShare.vue b/src/components/AppNavigation/CalendarShare.vue
index b3cf6fd8..c77dfb68 100644
--- a/src/components/AppNavigation/CalendarShare.vue
+++ b/src/components/AppNavigation/CalendarShare.vue
@@ -1,7 +1,12 @@
<!--
@copyright Copyright (c) 2018 Team Popcorn <teampopcornberlin@gmail.com>
+@copyright Copyright (c) 2019 Georg Ehrke <oc.list@georgehrke.com>
+@copyright Copyright (c) 2019 Jakob Röhrl <jakob.roehrl@web.de>
+@copyright Copyright (c) 2020 Raimund Schlüßler <raimund.schluessler@mailbox.org>
@author Team Popcorn <teampopcornberlin@gmail.com>
+@author Georg Ehrke <oc.list@georgehrke.com>
+@author Jakob Röhrl <jakob.roehrl@web.de>
@author Raimund Schlüßler <raimund.schluessler@mailbox.org>
@license GNU AGPL version 3 or any later version
@@ -39,7 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
track-by="user"
label="user"
@search-change="findSharee"
- @input="shareCalendar" />
+ @change="shareCalendar" />
</li>
<!-- list of user or groups calendar is shared with -->
<CalendarSharee v-for="sharee in calendar.shares"
@@ -51,11 +56,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</template>
<script>
+import CalendarSharee from './CalendarSharee'
import client from '../../services/cdav'
-import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
-import CalendarSharee from './CalendarSharee'
-// import debounce from 'debounce'
+import HttpClient from '@nextcloud/axios'
+import { generateOcsUrl } from '@nextcloud/router'
+import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
+import debounce from 'debounce'
export default {
name: 'CalendarShare',
@@ -95,48 +102,148 @@ export default {
* Share calendar
*
* @param {Object} data destructuring object
- * @param {string} data.user the userId
- * @param {string} data.displayName the displayName
- * @param {string} data.uri the sharing principalScheme uri
- * @param {boolean} data.isGroup is this a group ?
+ * @param {String} data.user the userId
+ * @param {String} data.displayName the displayName
+ * @param {String} data.uri the sharing principalScheme uri
+ * @param {Boolean} data.isGroup is this a group ?
+ * @param {Boolean} data.isCircle is this a circle?
*/
- shareCalendar({ user, displayName, uri, isGroup }) {
+ shareCalendar({ user, displayName, uri, isGroup, isCircle }) {
const calendar = this.calendar
uri = decodeURI(uri)
user = decodeURI(user)
- this.$store.dispatch('shareCalendar', { calendar, user, displayName, uri, isGroup })
+ this.$store.dispatch('shareCalendar', { calendar, user, displayName, uri, isGroup, isCircle })
},
/**
* Use the cdav client call to find matches to the query from the existing Users & Groups
*
- * @param {string} query The query string
+ * @param {String} query
*/
- async findSharee(query) {
+ findSharee: debounce(async function(query) {
+ const hiddenPrincipalSchemes = []
+ const hiddenUrls = []
+ this.calendar.shares.forEach((share) => {
+ hiddenPrincipalSchemes.push(share.uri)
+ })
+ if (this.$store.getters.getCurrentUserPrincipal) {
+ hiddenUrls.push(this.$store.getters.getCurrentUserPrincipal.url)
+ }
+ if (this.calendar.owner) {
+ hiddenUrls.push(this.calendar.owner)
+ }
+
this.isLoading = true
this.usersOrGroups = []
+
if (query.length > 0) {
- const results = await client.principalPropertySearchByDisplayname(query)
- this.usersOrGroups = results.reduce((list, result) => {
- if (['GROUP', 'INDIVIDUAL'].indexOf(result.calendarUserType) > -1
- && !this.calendar.shares.some((share) => share.uri === result.principalScheme)) {
- const isGroup = result.calendarUserType === 'GROUP'
- list.push({
- user: result[isGroup ? 'groupId' : 'userId'],
- displayName: result.displayname,
- icon: isGroup ? 'icon-group' : 'icon-user',
- uri: result.principalScheme,
- isGroup,
- })
- }
- return list
- }, [])
+ const davPromise = this.findShareesFromDav(query, hiddenPrincipalSchemes, hiddenUrls)
+ const ocsPromise = this.findShareesFromCircles(query, hiddenPrincipalSchemes, hiddenUrls)
+
+ const [davResults, ocsResults] = await Promise.all([davPromise, ocsPromise])
+ this.usersOrGroups = [
+ ...davResults,
+ ...ocsResults,
+ ]
+
this.isLoading = false
this.inputGiven = true
} else {
this.inputGiven = false
this.isLoading = false
}
+ }, 500),
+ /**
+ *
+ * @param {String} query The search query
+ * @param {String[]} hiddenPrincipals A list of principals to exclude from search results
+ * @param {String[]} hiddenUrls A list of urls to exclude from search results
+ * @returns {Promise<Object[]>}
+ */
+ async findShareesFromDav(query, hiddenPrincipals, hiddenUrls) {
+ let results
+ try {
+ results = await client.principalPropertySearchByDisplayname(query)
+ } catch (error) {
+ return []
+ }
+
+ return results.reduce((list, result) => {
+ if (hiddenPrincipals.includes(decodeURI(result.principalScheme))) {
+ return list
+ }
+ if (hiddenUrls.includes(result.url)) {
+ return list
+ }
+
+ // Don't show resources and rooms
+ if (!['GROUP', 'INDIVIDUAL'].includes(result.calendarUserType)) {
+ return list
+ }
+
+ const isGroup = result.calendarUserType === 'GROUP'
+ list.push({
+ user: result[isGroup ? 'groupId' : 'userId'],
+ displayName: result.displayname,
+ icon: isGroup ? 'icon-group' : 'icon-user',
+ uri: result.principalScheme,
+ isGroup,
+ isCircle: false,
+ isNoUser: isGroup,
+ search: query,
+ })
+ return list
+ }, [])
+ },
+ /**
+ *
+ * @param {String} query The search query
+ * @param {String[]} hiddenPrincipals A list of principals to exclude from search results
+ * @param {String[]} hiddenUrls A list of urls to exclude from search results
+ * @returns {Promise<Object[]>}
+ */
+ async findShareesFromCircles(query, hiddenPrincipals, hiddenUrls) {
+ let results
+ try {
+ results = await HttpClient.get(generateOcsUrl('apps/files_sharing/api/v1') + 'sharees', {
+ params: {
+ format: 'json',
+ search: query,
+ perPage: 200,
+ itemType: 'principals',
+ },
+ })
+ } catch (error) {
+ return []
+ }
+
+ if (results.data.ocs.meta.status === 'failure') {
+ return []
+ }
+ let circles = []
+ if (Array.isArray(results.data.ocs.data.circles)) {
+ circles = circles.concat(results.data.ocs.data.circles)
+ }
+ if (Array.isArray(results.data.ocs.data.exact.circles)) {
+ circles = circles.concat(results.data.ocs.data.exact.circles)
+ }
+
+ if (circles.length === 0) {
+ return []
+ }
+
+ return circles.filter((circle) => {
+ return !hiddenPrincipals.includes('principal:principals/circles/' + circle.value.shareWith)
+ }).map(circle => ({
+ user: circle.label,
+ displayName: circle.label,
+ icon: 'icon-circle',
+ uri: 'principal:principals/circles/' + circle.value.shareWith,
+ isGroup: false,
+ isCircle: true,
+ isNoUser: true,
+ search: query,
+ }))
},
},
}
diff --git a/src/store/calendars.js b/src/store/calendars.js
index 65f72d76..c3f3f7ed 100644
--- a/src/store/calendars.js
+++ b/src/store/calendars.js
@@ -127,14 +127,20 @@ export function mapDavCollectionToCalendar(calendar, currentUserPrincipal) {
*/
export function mapDavShareeToSharee(sharee) {
const id = sharee.href.split('/').slice(-1)[0]
- const name = sharee['common-name']
+ let name = sharee['common-name']
? sharee['common-name']
- : id
+ : sharee.href
+
+ if (sharee.href.startsWith('principal:principals/groups/') && name === sharee.href) {
+ name = sharee.href.substr(28)
+ }
+
return {
displayName: name,
id,
writeable: sharee.access[0].endsWith('read-write'),
isGroup: sharee.href.startsWith('principal:principals/groups/'),
+ isCircle: sharee.href.startsWith('principal:principals/circles/'),
uri: sharee.href,
}
}
@@ -391,14 +397,16 @@ const mutations = {
* @param {String} data.displayName The displayName
* @param {String} data.uri The sharing principalScheme uri
* @param {Boolean} data.isGroup Is this a group ?
+ * @param {Boolean} data.isCircle Is this a circle?
*/
- shareCalendar(state, { calendar, user, displayName, uri, isGroup }) {
+ shareCalendar(state, { calendar, user, displayName, uri, isGroup, isCircle }) {
calendar = state.calendars.find(search => search.id === calendar.id)
const newSharee = {
displayName,
id: user,
writeable: false,
isGroup,
+ isCircle,
uri,
}
if (!calendar.shares.some((share) => share.uri === uri)) {
@@ -686,11 +694,12 @@ const actions = {
* @param {String} data.displayName The displayName
* @param {String} data.uri The sharing principalScheme uri
* @param {Boolean} data.isGroup Is this a group ?
+ * @param {Boolean} data.isCircle Is this a circle?
*/
- async shareCalendar(context, { calendar, user, displayName, uri, isGroup }) {
+ async shareCalendar(context, { calendar, user, displayName, uri, isGroup, isCircle }) {
// Share calendar with entered group or user
await calendar.dav.share(uri)
- context.commit('shareCalendar', { calendar, user, displayName, uri, isGroup })
+ context.commit('shareCalendar', { calendar, user, displayName, uri, isGroup, isCircle })
},
}