From a67b74cae0a9abe280bcbbb14fe4a9a6c0cb2549 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Thu, 24 Sep 2020 17:24:27 +0200 Subject: [PATCH 01/24] backend for export user data --- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/resolvers/userData.js | 33 +++++++++++++++++++ backend/src/schema/types/type/UserData.gql | 10 ++++++ 3 files changed, 44 insertions(+) create mode 100644 backend/src/schema/resolvers/userData.js create mode 100644 backend/src/schema/types/type/UserData.gql diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 2c8d7ff63..f4f8c654b 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -105,6 +105,7 @@ export default shield( blockedUsers: isAuthenticated, notifications: isAuthenticated, Donations: isAuthenticated, + userData: isAuthenticated, }, Mutation: { '*': deny, diff --git a/backend/src/schema/resolvers/userData.js b/backend/src/schema/resolvers/userData.js new file mode 100644 index 000000000..98e0e700e --- /dev/null +++ b/backend/src/schema/resolvers/userData.js @@ -0,0 +1,33 @@ +import log from './helpers/databaseLogger' + +export default { + Query: { + userData: async (object, args, context, resolveInfo) => { + const id = context.user.id + const cypher = ` + MATCH (u:User { id: $id }) + WITH u AS user + MATCH (p:Post) + WHERE (p)<-[:COMMENTS]-(:Comment)<-[:WROTE]-(user) + OR (user)-[:WROTE]->(p) + RETURN { user: properties(user), posts: collect(properties(p)) } + AS result + ` + const session = context.driver.session() + const resultPromise = session.readTransaction(async (transaction) => { + const transactionResponse = transaction.run(cypher, { + id, + }) + return transactionResponse + }) + + try { + const result = await resultPromise + log(result.records[0].get('result')) + return result.records[0].get('result') + } finally { + session.close() + } + }, + }, +} diff --git a/backend/src/schema/types/type/UserData.gql b/backend/src/schema/types/type/UserData.gql new file mode 100644 index 000000000..60ad5c12f --- /dev/null +++ b/backend/src/schema/types/type/UserData.gql @@ -0,0 +1,10 @@ +type UserData { + user: User! + posts: [Post] +} + +type Query { + userData( + id: ID + ): UserData +} From 0e678a55595030e9ba652fc90f89fe97c678499d Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 29 Sep 2020 13:35:47 +0200 Subject: [PATCH 02/24] basic json download of user data --- backend/src/schema/resolvers/userData.js | 3 -- webapp/graphql/User.js | 21 ++++++++++++ webapp/pages/settings.vue | 30 ++++++++--------- webapp/pages/settings/data-download.vue | 42 +++++++++++++++++++++--- 4 files changed, 73 insertions(+), 23 deletions(-) diff --git a/backend/src/schema/resolvers/userData.js b/backend/src/schema/resolvers/userData.js index 98e0e700e..e8dc75588 100644 --- a/backend/src/schema/resolvers/userData.js +++ b/backend/src/schema/resolvers/userData.js @@ -1,5 +1,3 @@ -import log from './helpers/databaseLogger' - export default { Query: { userData: async (object, args, context, resolveInfo) => { @@ -23,7 +21,6 @@ export default { try { const result = await resultPromise - log(result.records[0].get('result')) return result.records[0].get('result') } finally { session.close() diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index 3b015dacc..60026f0b7 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -292,3 +292,24 @@ export const currentUserCountQuery = () => gql` } } ` + +export const userDataQuery = (i18n) => { + return gql` + ${userFragment} + ${postFragment} + ${commentFragment} + query($id: ID!) { + userData(id: $id) { + user { + ...user + } + posts { + ...post + comments { + ...comment + } + } + } + } + ` +} diff --git a/webapp/pages/settings.vue b/webapp/pages/settings.vue index 950652028..6bd78b701 100644 --- a/webapp/pages/settings.vue +++ b/webapp/pages/settings.vue @@ -51,32 +51,30 @@ export default { name: this.$t('settings.embeds.name'), path: `/settings/embeds`, }, + { + name: this.$t('settings.download.name'), + path: `/settings/data-download`, + }, { name: this.$t('settings.deleteUserAccount.name'), path: `/settings/delete-account`, }, // TODO implement /* { - name: this.$t('settings.invites.name'), - path: `/settings/invites` - }, */ + name: this.$t('settings.invites.name'), + path: `/settings/invites` + }, */ // TODO implement /* { - name: this.$t('settings.download.name'), - path: `/settings/data-download` - }, */ - // TODO implement + name: this.$t('settings.organizations.name'), + path: `/settings/my-organizations` + }, */ // TODO implement /* { - name: this.$t('settings.organizations.name'), - path: `/settings/my-organizations` - }, */ - // TODO implement - /* { - name: this.$t('settings.languages.name'), - path: `/settings/languages` - }, - } */ + name: this.$t('settings.languages.name'), + path: `/settings/languages` + }, + } */ ] }, }, diff --git a/webapp/pages/settings/data-download.vue b/webapp/pages/settings/data-download.vue index b7951182d..ff812e155 100644 --- a/webapp/pages/settings/data-download.vue +++ b/webapp/pages/settings/data-download.vue @@ -1,16 +1,50 @@ From f0354c337fb06e9df69468efda41c21c848f6054 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 29 Sep 2020 15:54:21 +0200 Subject: [PATCH 03/24] Export of user data as XML --- webapp/assets/_new/icons/svgs/download.svg | 5 ++++ webapp/graphql/User.js | 3 +++ webapp/locales/de.json | 4 ++- webapp/locales/en.json | 4 ++- webapp/package.json | 1 + webapp/pages/settings/data-download.vue | 29 ++++++++++++++++++---- webapp/yarn.lock | 7 ++++++ 7 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 webapp/assets/_new/icons/svgs/download.svg diff --git a/webapp/assets/_new/icons/svgs/download.svg b/webapp/assets/_new/icons/svgs/download.svg new file mode 100644 index 000000000..b988fa171 --- /dev/null +++ b/webapp/assets/_new/icons/svgs/download.svg @@ -0,0 +1,5 @@ + + +download + + diff --git a/webapp/graphql/User.js b/webapp/graphql/User.js index 60026f0b7..5dab239e4 100644 --- a/webapp/graphql/User.js +++ b/webapp/graphql/User.js @@ -306,6 +306,9 @@ export const userDataQuery = (i18n) => { posts { ...post comments { + author { + slug + } ...comment } } diff --git a/webapp/locales/de.json b/webapp/locales/de.json index adee8921c..ecba2d516 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -648,7 +648,9 @@ "success": "Konto erfolgreich gelöscht!" }, "download": { - "name": "Daten herunterladen" + "json": "als JSON", + "name": "Daten herunterladen", + "xml": "als XML" }, "email": { "change-successful": "Deine E-Mail-Adresse wurde erfolgreich geändert.", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 8959e3830..aae5d3bec 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -648,7 +648,9 @@ "success": "Account successfully deleted!" }, "download": { - "name": "Download Data" + "json": "as JSON", + "name": "Download Data", + "xml": "as XML" }, "email": { "change-successful": "Your e-mail address has been changed successfully.", diff --git a/webapp/package.json b/webapp/package.json index d2c7c9678..6ebfe8338 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -93,6 +93,7 @@ "vue-scrollto": "^2.17.1", "vue-sweetalert-icons": "~4.2.0", "vuex-i18n": "~1.13.1", + "xml-js": "^1.6.11", "xregexp": "^4.3.0", "zxcvbn": "^4.4.2" }, diff --git a/webapp/pages/settings/data-download.vue b/webapp/pages/settings/data-download.vue index ff812e155..ae130c822 100644 --- a/webapp/pages/settings/data-download.vue +++ b/webapp/pages/settings/data-download.vue @@ -1,15 +1,25 @@