diff --git a/.travis.yml b/.travis.yml
index 04fc54e60..f48b0bb36 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,7 +29,7 @@ script:
- docker-compose exec backend yarn run test:jest --ci --verbose=false --coverage
- docker-compose exec backend yarn run db:reset
- docker-compose exec backend yarn run db:seed
- - docker-compose exec backend yarn run test:cucumber
+ - docker-compose exec backend yarn run test:cucumber --tags "not @wip"
- docker-compose exec backend yarn run db:reset
- docker-compose exec backend yarn run db:seed
# Frontend
diff --git a/backend/package.json b/backend/package.json
index f6cb0de6b..c8537ae0b 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -47,12 +47,12 @@
"apollo-client": "~2.6.2",
"apollo-link-context": "~1.0.14",
"apollo-link-http": "~1.5.14",
- "apollo-server": "~2.6.2",
+ "apollo-server": "~2.6.3",
"bcryptjs": "~2.4.3",
"cheerio": "~1.0.0-rc.3",
"cors": "~2.8.5",
"cross-env": "~5.2.0",
- "date-fns": "2.0.0-alpha.31",
+ "date-fns": "2.0.0-alpha.33",
"debug": "~4.1.1",
"dotenv": "~8.0.0",
"express": "~4.17.1",
@@ -87,7 +87,7 @@
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
"@babel/preset-env": "~7.4.5",
"@babel/register": "~7.4.4",
- "apollo-server-testing": "~2.6.2",
+ "apollo-server-testing": "~2.6.3",
"babel-core": "~7.0.0-0",
"babel-eslint": "~10.0.1",
"babel-jest": "~24.8.0",
diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js
index bc9b4c525..1f0ffd79a 100644
--- a/backend/src/middleware/permissionsMiddleware.js
+++ b/backend/src/middleware/permissionsMiddleware.js
@@ -1,4 +1,4 @@
-import { rule, shield, allow, or } from 'graphql-shield'
+import { rule, shield, deny, allow, or } from 'graphql-shield'
/*
* TODO: implement
@@ -16,6 +16,12 @@ const isAdmin = rule()(async (parent, args, { user }, info) => {
return user && user.role === 'admin'
})
+const onlyYourself = rule({
+ cache: 'no_cache',
+})(async (parent, args, context, info) => {
+ return context.user.id === args.id
+})
+
const isMyOwn = rule({
cache: 'no_cache',
})(async (parent, args, context, info) => {
@@ -48,6 +54,13 @@ const belongsToMe = rule({
return Boolean(notification)
})
+/* TODO: decide if we want to remove this check: the check
+ * `onlyEnabledContent` throws authorization errors only if you have
+ * arguments for `disabled` or `deleted` assuming these are filter
+ * parameters. Soft-delete middleware obfuscates data on its way out
+ * anyways. Furthermore, `neo4j-graphql-js` offers many ways to filter for
+ * data so I believe, this is not a good check anyways.
+ */
const onlyEnabledContent = rule({
cache: 'strict',
})(async (parent, args, ctx, info) => {
@@ -81,46 +94,62 @@ const isAuthor = rule({
})
// Permissions
-const permissions = shield({
- Query: {
- Notification: isAdmin,
- statistics: allow,
- currentUser: allow,
- Post: or(onlyEnabledContent, isModerator),
+const permissions = shield(
+ {
+ Query: {
+ '*': deny,
+ findPosts: allow,
+ Category: isAdmin,
+ Tag: isAdmin,
+ Report: isModerator,
+ Notification: isAdmin,
+ statistics: allow,
+ currentUser: allow,
+ Post: or(onlyEnabledContent, isModerator),
+ Comment: allow,
+ User: allow,
+ isLoggedIn: allow,
+ },
+ Mutation: {
+ '*': deny,
+ login: allow,
+ UpdateNotification: belongsToMe,
+ CreateUser: isAdmin,
+ UpdateUser: onlyYourself,
+ CreatePost: isAuthenticated,
+ UpdatePost: isAuthor,
+ DeletePost: isAuthor,
+ report: isAuthenticated,
+ CreateBadge: isAdmin,
+ UpdateBadge: isAdmin,
+ DeleteBadge: isAdmin,
+ AddUserBadges: isAdmin,
+ CreateSocialMedia: isAuthenticated,
+ DeleteSocialMedia: isAuthenticated,
+ // AddBadgeRewarded: isAdmin,
+ // RemoveBadgeRewarded: isAdmin,
+ reward: isAdmin,
+ unreward: isAdmin,
+ // addFruitToBasket: isAuthenticated
+ follow: isAuthenticated,
+ unfollow: isAuthenticated,
+ shout: isAuthenticated,
+ unshout: isAuthenticated,
+ changePassword: isAuthenticated,
+ enable: isModerator,
+ disable: isModerator,
+ CreateComment: isAuthenticated,
+ DeleteComment: isAuthor,
+ },
+ User: {
+ email: isMyOwn,
+ password: isMyOwn,
+ privateKey: isMyOwn,
+ },
},
- Mutation: {
- UpdateNotification: belongsToMe,
- CreatePost: isAuthenticated,
- UpdatePost: isAuthor,
- DeletePost: isAuthor,
- report: isAuthenticated,
- CreateBadge: isAdmin,
- UpdateBadge: isAdmin,
- DeleteBadge: isAdmin,
- AddUserBadges: isAdmin,
- CreateSocialMedia: isAuthenticated,
- DeleteSocialMedia: isAuthenticated,
- // AddBadgeRewarded: isAdmin,
- // RemoveBadgeRewarded: isAdmin,
- reward: isAdmin,
- unreward: isAdmin,
- // addFruitToBasket: isAuthenticated
- follow: isAuthenticated,
- unfollow: isAuthenticated,
- shout: isAuthenticated,
- unshout: isAuthenticated,
- changePassword: isAuthenticated,
- enable: isModerator,
- disable: isModerator,
- CreateComment: isAuthenticated,
- DeleteComment: isAuthor,
- // CreateUser: allow,
+ {
+ fallbackRule: allow,
},
- User: {
- email: isMyOwn,
- password: isMyOwn,
- privateKey: isMyOwn,
- },
-})
+)
export default permissions
diff --git a/backend/src/middleware/slugifyMiddleware.spec.js b/backend/src/middleware/slugifyMiddleware.spec.js
index 79bba0a5d..4e060dc90 100644
--- a/backend/src/middleware/slugifyMiddleware.spec.js
+++ b/backend/src/middleware/slugifyMiddleware.spec.js
@@ -7,12 +7,14 @@ let headers
const factory = Factory()
beforeEach(async () => {
- await factory.create('User', { email: 'user@example.org', password: '1234' })
+ const adminParams = { role: 'admin', email: 'admin@example.org', password: '1234' }
+ await factory.create('User', adminParams)
await factory.create('User', {
email: 'someone@example.org',
password: '1234',
})
- headers = await login({ email: 'user@example.org', password: '1234' })
+ // we need to be an admin, otherwise we're not authorized to create a user
+ headers = await login(adminParams)
authenticatedClient = new GraphQLClient(host, { headers })
})
diff --git a/backend/src/schema/resolvers/user_management.spec.js b/backend/src/schema/resolvers/user_management.spec.js
index cf648a6bd..463c5ea6d 100644
--- a/backend/src/schema/resolvers/user_management.spec.js
+++ b/backend/src/schema/resolvers/user_management.spec.js
@@ -315,6 +315,8 @@ describe('change password', () => {
describe('do not expose private RSA key', () => {
let headers
let client
+ let authenticatedClient
+
const queryUserPuplicKey = gql`
query($queriedUserSlug: String) {
User(slug: $queriedUserSlug) {
@@ -332,7 +334,7 @@ describe('do not expose private RSA key', () => {
}
`
- const actionGenUserWithKeys = async () => {
+ const generateUserWithKeys = async authenticatedClient => {
// Generate user with "privateKey" via 'CreateUser' mutation instead of using the factories "factory.create('User', {...})", see above.
const variables = {
id: 'bcb2d923-f3af-479e-9f00-61b12e864667',
@@ -341,7 +343,7 @@ describe('do not expose private RSA key', () => {
name: 'Apfel Strudel',
email: 'apfel-strudel@test.org',
}
- await client.request(
+ await authenticatedClient.request(
gql`
mutation($id: ID, $password: String!, $slug: String, $name: String, $email: String!) {
CreateUser(id: $id, password: $password, slug: $slug, name: $name, email: $email) {
@@ -353,14 +355,23 @@ describe('do not expose private RSA key', () => {
)
}
- // not authenticate
beforeEach(async () => {
+ const adminParams = {
+ role: 'admin',
+ email: 'admin@example.org',
+ password: '1234',
+ }
+ // create an admin user who has enough permissions to create other users
+ await factory.create('User', adminParams)
+ const headers = await login(adminParams)
+ authenticatedClient = new GraphQLClient(host, { headers })
+ // but also create an unauthenticated client to issue the `User` query
client = new GraphQLClient(host)
})
describe('unauthenticated query of "publicKey" (does the RSA key pair get generated at all?)', () => {
it('returns publicKey', async () => {
- await actionGenUserWithKeys()
+ await generateUserWithKeys(authenticatedClient)
await expect(
await client.request(queryUserPuplicKey, { queriedUserSlug: 'apfel-strudel' }),
).toEqual(
@@ -378,7 +389,7 @@ describe('do not expose private RSA key', () => {
describe('unauthenticated query of "privateKey"', () => {
it('throws "Not Authorised!"', async () => {
- await actionGenUserWithKeys()
+ await generateUserWithKeys(authenticatedClient)
await expect(
client.request(queryUserPrivateKey, { queriedUserSlug: 'apfel-strudel' }),
).rejects.toThrow('Not Authorised')
@@ -393,7 +404,7 @@ describe('do not expose private RSA key', () => {
describe('authenticated query of "publicKey"', () => {
it('returns publicKey', async () => {
- await actionGenUserWithKeys()
+ await generateUserWithKeys(authenticatedClient)
await expect(
await client.request(queryUserPuplicKey, { queriedUserSlug: 'apfel-strudel' }),
).toEqual(
@@ -411,7 +422,7 @@ describe('do not expose private RSA key', () => {
describe('authenticated query of "privateKey"', () => {
it('throws "Not Authorised!"', async () => {
- await actionGenUserWithKeys()
+ await generateUserWithKeys(authenticatedClient)
await expect(
client.request(queryUserPrivateKey, { queriedUserSlug: 'apfel-strudel' }),
).rejects.toThrow('Not Authorised')
diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js
index a5c50f4f9..6334272dd 100644
--- a/backend/src/schema/resolvers/users.spec.js
+++ b/backend/src/schema/resolvers/users.spec.js
@@ -1,5 +1,5 @@
import { GraphQLClient } from 'graphql-request'
-import { host } from '../../jest/helpers'
+import { login, host } from '../../jest/helpers'
import Factory from '../../seed/factories'
const factory = Factory()
@@ -18,27 +18,58 @@ describe('users', () => {
}
}
`
- client = new GraphQLClient(host)
-
- it('with password and email', async () => {
+ describe('given valid password and email', () => {
const variables = {
name: 'John Doe',
password: '123',
email: '123@123.de',
}
- const expected = {
- CreateUser: {
- id: expect.any(String),
- },
- }
- await expect(client.request(mutation, variables)).resolves.toEqual(expected)
+
+ describe('unauthenticated', () => {
+ beforeEach(async () => {
+ client = new GraphQLClient(host)
+ })
+
+ it('is not allowed to create users', async () => {
+ await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
+ })
+ })
+
+ describe('authenticated admin', () => {
+ beforeEach(async () => {
+ const adminParams = {
+ role: 'admin',
+ email: 'admin@example.org',
+ password: '1234',
+ }
+ await factory.create('User', adminParams)
+ const headers = await login(adminParams)
+ client = new GraphQLClient(host, { headers })
+ })
+
+ it('is allowed to create new users', async () => {
+ const expected = {
+ CreateUser: {
+ id: expect.any(String),
+ },
+ }
+ await expect(client.request(mutation, variables)).resolves.toEqual(expected)
+ })
+ })
})
})
describe('UpdateUser', () => {
- beforeEach(async () => {
- await factory.create('User', { id: 'u47', name: 'John Doe' })
- })
+ const userParams = {
+ email: 'user@example.org',
+ password: '1234',
+ id: 'u47',
+ name: 'John Doe',
+ }
+ const variables = {
+ id: 'u47',
+ name: 'John Doughnut',
+ }
const mutation = `
mutation($id: ID!, $name: String) {
@@ -48,38 +79,62 @@ describe('users', () => {
}
}
`
- client = new GraphQLClient(host)
- it('name within specifications', async () => {
- const variables = {
- id: 'u47',
- name: 'James Doe',
- }
- const expected = {
- UpdateUser: {
- id: 'u47',
+ beforeEach(async () => {
+ await factory.create('User', userParams)
+ })
+
+ describe('as another user', () => {
+ beforeEach(async () => {
+ const someoneElseParams = {
+ email: 'someoneElse@example.org',
+ password: '1234',
name: 'James Doe',
- },
- }
- await expect(client.request(mutation, variables)).resolves.toEqual(expected)
+ }
+
+ await factory.create('User', someoneElseParams)
+ const headers = await login(someoneElseParams)
+ client = new GraphQLClient(host, { headers })
+ })
+
+ it('is not allowed to change other user accounts', async () => {
+ await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised')
+ })
})
- it('with no name', async () => {
- const variables = {
- id: 'u47',
- name: null,
- }
- const expected = 'Username must be at least 3 characters long!'
- await expect(client.request(mutation, variables)).rejects.toThrow(expected)
- })
+ describe('as the same user', () => {
+ beforeEach(async () => {
+ const headers = await login(userParams)
+ client = new GraphQLClient(host, { headers })
+ })
- it('with too short name', async () => {
- const variables = {
- id: 'u47',
- name: ' ',
- }
- const expected = 'Username must be at least 3 characters long!'
- await expect(client.request(mutation, variables)).rejects.toThrow(expected)
+ it('name within specifications', async () => {
+ const expected = {
+ UpdateUser: {
+ id: 'u47',
+ name: 'John Doughnut',
+ },
+ }
+ await expect(client.request(mutation, variables)).resolves.toEqual(expected)
+ })
+
+ it('with no name', async () => {
+ const variables = {
+ id: 'u47',
+ name: null,
+ }
+ const expected = 'Username must be at least 3 characters long!'
+ await expect(client.request(mutation, variables)).rejects.toThrow(expected)
+ })
+
+ it('with too short name', async () => {
+ const variables = {
+ id: 'u47',
+ name: ' ',
+ }
+ const expected = 'Username must be at least 3 characters long!'
+ await expect(client.request(mutation, variables)).rejects.toThrow(expected)
+ })
})
})
})
diff --git a/backend/test/features/activity-follow.feature b/backend/test/features/activity-follow.feature
index 3cfe73340..7aa0c447d 100644
--- a/backend/test/features/activity-follow.feature
+++ b/backend/test/features/activity-follow.feature
@@ -10,6 +10,7 @@ Feature: Follow a user
| stuart-little |
| tero-vota |
+ @wip
Scenario: Send a follow to a user inbox and make sure it's added to the right followers collection
When I send a POST request with the following activity to "/activitypub/users/tero-vota/inbox":
"""
diff --git a/backend/test/features/activity-like.feature b/backend/test/features/activity-like.feature
index ec8c99110..26ef9c857 100644
--- a/backend/test/features/activity-like.feature
+++ b/backend/test/features/activity-like.feature
@@ -27,6 +27,7 @@ Feature: Like an object like an article or note
}
"""
+ @wip
Scenario: Send a like of a person to an users inbox and make sure it's added to the likes collection
When I send a POST request with the following activity to "/activitypub/users/karl-heinz/inbox":
"""
diff --git a/backend/yarn.lock b/backend/yarn.lock
index e92070fe9..d2c5da176 100644
--- a/backend/yarn.lock
+++ b/backend/yarn.lock
@@ -1029,10 +1029,10 @@
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
-"@types/express@4.16.1":
- version "4.16.1"
- resolved "https://registry.yarnpkg.com/@types/express/-/express-4.16.1.tgz#d756bd1a85c34d87eaf44c888bad27ba8a4b7cf0"
- integrity sha512-V0clmJow23WeyblmACoxbHBu2JKlE5TiIme6Lem14FnPW9gsttyHtk6wq7njcdIWH1njAaFgR8gW09lgY98gQg==
+"@types/express@4.17.0":
+ version "4.17.0"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.0.tgz#49eaedb209582a86f12ed9b725160f12d04ef287"
+ integrity sha512-CjaMu57cjgjuZbh9DpkloeGxV45CnMGlVd+XpG7Gm9QgVrd7KFq+X4HY0vM+2v0bczS48Wg7bvnMY5TN+Xmcfw==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "*"
@@ -1351,14 +1351,14 @@ apollo-engine-reporting-protobuf@0.3.1:
dependencies:
protobufjs "^6.8.6"
-apollo-engine-reporting@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.3.0.tgz#50151811a0f5e70f4a73e7092a61fec422d8e722"
- integrity sha512-xP+Z+wdQH4ee7xfuP3WsJcIe30AH68gpp2lQm2+rnW5JfjIqD5YehSoO2Svi2jK3CSv8Y561i3QMW9i34P7hEQ==
+apollo-engine-reporting@1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.3.1.tgz#f2c2c63f865871a57c15cdbb2a3bcd4b4af28115"
+ integrity sha512-e0Xp+0yite8DH/xm9fnJt42CxfWAcY6waiq3icCMAgO9T7saXzVOPpl84SkuA+hIJUBtfaKrTnC+7Jxi/I7OrQ==
dependencies:
apollo-engine-reporting-protobuf "0.3.1"
apollo-graphql "^0.3.0"
- apollo-server-core "2.6.2"
+ apollo-server-core "2.6.3"
apollo-server-env "2.4.0"
async-retry "^1.2.1"
graphql-extensions "0.7.2"
@@ -1431,17 +1431,17 @@ apollo-server-caching@0.4.0:
dependencies:
lru-cache "^5.0.0"
-apollo-server-core@2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.6.2.tgz#a792b50d4df9e26ec03759a31fbcbce38361b218"
- integrity sha512-AbAnfoQ26NPsNIyBa/BVKBtA/wRsNL/E6eEem1VIhzitfgO25bVXFbEZDLxbgz6wvJ+veyRFpse7Qi1bvRpxOw==
+apollo-server-core@2.6.3:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.6.3.tgz#786c8251c82cf29acb5cae9635a321f0644332ae"
+ integrity sha512-tfC0QO1NbJW3ShkB5pRCnUaYEkW2AwnswaTeedkfv//EO3yiC/9LeouCK5F22T8stQG+vGjvCqf0C8ldI/XsIA==
dependencies:
"@apollographql/apollo-tools" "^0.3.6"
"@apollographql/graphql-playground-html" "1.6.20"
"@types/ws" "^6.0.0"
apollo-cache-control "0.7.2"
apollo-datasource "0.5.0"
- apollo-engine-reporting "1.3.0"
+ apollo-engine-reporting "1.3.1"
apollo-server-caching "0.4.0"
apollo-server-env "2.4.0"
apollo-server-errors "2.3.0"
@@ -1479,18 +1479,18 @@ apollo-server-errors@2.3.0:
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.0.tgz#700622b66a16dffcad3b017e4796749814edc061"
integrity sha512-rUvzwMo2ZQgzzPh2kcJyfbRSfVKRMhfIlhY7BzUfM4x6ZT0aijlgsf714Ll3Mbf5Fxii32kD0A/DmKsTecpccw==
-apollo-server-express@2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.6.2.tgz#526297c01a7a32fe9215566f9fd7ff92e82f1fa0"
- integrity sha512-nbL3noJ5KxKGg+hT8UsAA7++oHWq/KNSevfdCluWTfUNqH1vYRTvAnARx/6JM06S9zcPTfOLcqwHnDnY9zYFxA==
+apollo-server-express@2.6.3:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.6.3.tgz#62034c978f84207615c0430fb37ab006f71146fe"
+ integrity sha512-8ca+VpKArgNzFar0D3DesWnn0g9YDtFLhO56TQprHh2Spxu9WxTnYNjsYs2MCCNf+iV/uy7vTvEknErvnIcZaQ==
dependencies:
"@apollographql/graphql-playground-html" "1.6.20"
"@types/accepts" "^1.3.5"
"@types/body-parser" "1.17.0"
"@types/cors" "^2.8.4"
- "@types/express" "4.16.1"
+ "@types/express" "4.17.0"
accepts "^1.3.5"
- apollo-server-core "2.6.2"
+ apollo-server-core "2.6.3"
body-parser "^1.18.3"
cors "^2.8.4"
graphql-subscriptions "^1.0.0"
@@ -1523,20 +1523,20 @@ apollo-server-plugin-base@0.5.2:
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.5.2.tgz#f97ba983f1e825fec49cba8ff6a23d00e1901819"
integrity sha512-j81CpadRLhxikBYHMh91X4aTxfzFnmmebEiIR9rruS6dywWCxV2aLW87l9ocD1MiueNam0ysdwZkX4F3D4csNw==
-apollo-server-testing@~2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.6.2.tgz#e0ecddd565fce1c38a346f9fbe6118f543ccf6a6"
- integrity sha512-I9QLFk4I/z9oOIXfnLc8RPBYAKih6Olrg3RDeRvWhDjLQ8gfALXVhCO+7WuvM35wNZcZVn7aXBeZ8Y3mlgkj8w==
+apollo-server-testing@~2.6.3:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.6.3.tgz#a0199a5d42000e60ecf0dea44b851f5f581e280e"
+ integrity sha512-LTkegcGVSkM+pA0FINDSYVl3TiFYKZyfjlKrEr/LN6wLiL6gbRgy6LMtk2j+qli/bnTDqqQREX8OEqmV8FKUoQ==
dependencies:
- apollo-server-core "2.6.2"
+ apollo-server-core "2.6.3"
-apollo-server@~2.6.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.6.2.tgz#33fe894b740588f059a7679346516ffce50377d5"
- integrity sha512-fMXaAKIb0dX0lzcZ4zlu7ay1L596d9HTNkdn8cKuM7zmTpugZSAL966COguJUDSjUS9CaB1Kh5hl1yRuRqHXSA==
+apollo-server@~2.6.3:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.6.3.tgz#71235325449c6d3881a5143975ca44c07a07d2d7"
+ integrity sha512-pTIXE5xEMAikKLTIBIqLNvimMETiZbzmiqDb6BGzIUicAz4Rxa1/+bDi1ZeJWrZQjE/TfBLd2Si3qam7dZGrjw==
dependencies:
- apollo-server-core "2.6.2"
- apollo-server-express "2.6.2"
+ apollo-server-core "2.6.3"
+ apollo-server-express "2.6.3"
express "^4.0.0"
graphql-subscriptions "^1.0.0"
graphql-tools "^4.0.0"
@@ -2586,10 +2586,10 @@ data-urls@^1.0.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
-date-fns@2.0.0-alpha.31:
- version "2.0.0-alpha.31"
- resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0-alpha.31.tgz#51bcfdca25dfc9bea334a556ab33dfc0bb00421c"
- integrity sha512-S19PwMqnbYsqcbCg02Yj9gv4veVNZ0OX7v2+zcd+Mq0RI7LoDKJipJjnMrTZ3Cc6blDuTce5G/pHXcVIGRwJWQ==
+date-fns@2.0.0-alpha.33:
+ version "2.0.0-alpha.33"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0-alpha.33.tgz#c2f73c3cc50ac301c9217eb93603c9bc40e891bf"
+ integrity sha512-tqUVEk3oxnJuNIvwAMKHAMo4uFRG0zXvjxZQll+BonoPt+m4NMcUgO14NDxbHuy7uYcrVErd2GdSsw02EDZQ7w==
debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
diff --git a/package.json b/package.json
index dd7454c54..fed6c742b 100644
--- a/package.json
+++ b/package.json
@@ -22,8 +22,8 @@
"codecov": "^3.5.0",
"cross-env": "^5.2.0",
"cypress": "^3.3.1",
- "cypress-cucumber-preprocessor": "^1.11.2",
- "cypress-file-upload": "^3.1.2",
+ "cypress-cucumber-preprocessor": "^1.12.0",
+ "cypress-file-upload": "^3.1.4",
"cypress-plugin-retries": "^1.2.2",
"dotenv": "^8.0.0",
"faker": "^4.1.0",
diff --git a/webapp/components/Avatar/Avatar.spec.js b/webapp/components/Avatar/Avatar.spec.js
index ae91fecfe..d3ebcb030 100644
--- a/webapp/components/Avatar/Avatar.spec.js
+++ b/webapp/components/Avatar/Avatar.spec.js
@@ -1,9 +1,11 @@
import { mount, createLocalVue } from '@vue/test-utils'
import Styleguide from '@human-connection/styleguide'
import Avatar from './Avatar.vue'
+import Filters from '~/plugins/vue-filters'
const localVue = createLocalVue()
localVue.use(Styleguide)
+localVue.use(Filters)
describe('Avatar.vue', () => {
let propsData = {}
diff --git a/webapp/components/Avatar/Avatar.vue b/webapp/components/Avatar/Avatar.vue
index 0d997c745..ec2f9b28b 100644
--- a/webapp/components/Avatar/Avatar.vue
+++ b/webapp/components/Avatar/Avatar.vue
@@ -1,5 +1,10 @@
-
+
diff --git a/webapp/components/Image/spec.js b/webapp/components/Image/spec.js
deleted file mode 100644
index be568964a..000000000
--- a/webapp/components/Image/spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { shallowMount } from '@vue/test-utils'
-import Image from '.'
-
-describe('Image', () => {
- let propsData = { imageProps: { class: 'hc-badge', src: '' } }
-
- const Wrapper = () => {
- return shallowMount(Image, { propsData })
- }
-
- it('renders', () => {
- expect(Wrapper().is('img')).toBe(true)
- })
-
- it('passes properties down to `img`', () => {
- expect(Wrapper().classes()).toEqual(['hc-badge'])
- })
-
- describe('given a relative `src`', () => {
- beforeEach(() => {
- propsData.imageProps.src = '/img/badges/fundraisingbox_de_airship.svg'
- })
-
- it('adds a prefix to load the image from the backend', () => {
- expect(Wrapper().attributes('src')).toBe('/api/img/badges/fundraisingbox_de_airship.svg')
- })
- })
-
- describe('given an absolute `src`', () => {
- beforeEach(() => {
- propsData.imageProps.src = 'http://lorempixel.com/640/480/animals'
- })
-
- it('keeps the URL as is', () => {
- // e.g. our seeds have absolute image URLs
- expect(Wrapper().attributes('src')).toBe('http://lorempixel.com/640/480/animals')
- })
- })
-})
diff --git a/webapp/components/Password/Change.spec.js b/webapp/components/Password/Change.spec.js
index cffe86466..a15695a55 100644
--- a/webapp/components/Password/Change.spec.js
+++ b/webapp/components/Password/Change.spec.js
@@ -1,10 +1,12 @@
import { mount, createLocalVue } from '@vue/test-utils'
import ChangePassword from './Change.vue'
import Styleguide from '@human-connection/styleguide'
+import Filters from '~/plugins/vue-filters'
const localVue = createLocalVue()
localVue.use(Styleguide)
+localVue.use(Filters)
describe('ChangePassword.vue', () => {
let mocks
diff --git a/webapp/components/PostCard/index.vue b/webapp/components/PostCard/index.vue
index d8172cb77..64c96f634 100644
--- a/webapp/components/PostCard/index.vue
+++ b/webapp/components/PostCard/index.vue
@@ -1,6 +1,9 @@
-
+
str)
localVue.use(Vuex)
localVue.use(VTooltip)
localVue.use(Styleguide)
+localVue.use(Filters)
localVue.filter('truncate', filter)
diff --git a/webapp/components/comments/CommentList/CommentList.spec.js b/webapp/components/comments/CommentList/CommentList.spec.js
index 9bfa13ea5..c4ee0624c 100644
--- a/webapp/components/comments/CommentList/CommentList.spec.js
+++ b/webapp/components/comments/CommentList/CommentList.spec.js
@@ -3,11 +3,13 @@ import CommentList from '.'
import Empty from '~/components/Empty'
import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide'
+import Filters from '~/plugins/vue-filters'
const localVue = createLocalVue()
localVue.use(Styleguide)
localVue.use(Vuex)
+localVue.use(Filters)
localVue.filter('truncate', string => string)
config.stubs['v-popover'] = ''
diff --git a/webapp/package.json b/webapp/package.json
index aa26eedb6..b5c74de99 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -59,7 +59,7 @@
"apollo-client": "~2.6.2",
"cookie-universal-nuxt": "~2.0.16",
"cross-env": "~5.2.0",
- "date-fns": "2.0.0-alpha.31",
+ "date-fns": "2.0.0-alpha.33",
"express": "~4.17.1",
"graphql": "~14.3.1",
"jsonwebtoken": "~8.5.1",
diff --git a/webapp/pages/profile/_id/_slug.spec.js b/webapp/pages/profile/_id/_slug.spec.js
index 4b5bbf69b..a56cb0046 100644
--- a/webapp/pages/profile/_id/_slug.spec.js
+++ b/webapp/pages/profile/_id/_slug.spec.js
@@ -2,11 +2,13 @@ import { config, mount, shallowMount, createLocalVue } from '@vue/test-utils'
import ProfileSlug from './_slug.vue'
import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide'
+import Filters from '~/plugins/vue-filters'
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Styleguide)
+localVue.use(Filters)
localVue.filter('date', d => d)
config.stubs['no-ssr'] = ''
diff --git a/webapp/pages/settings/my-social-media.spec.js b/webapp/pages/settings/my-social-media.spec.js
index 34793e066..55ba27bb8 100644
--- a/webapp/pages/settings/my-social-media.spec.js
+++ b/webapp/pages/settings/my-social-media.spec.js
@@ -2,11 +2,13 @@ import { mount, createLocalVue } from '@vue/test-utils'
import MySocialMedia from './my-social-media.vue'
import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide'
+import Filters from '~/plugins/vue-filters'
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Styleguide)
+localVue.use(Filters)
describe('my-social-media.vue', () => {
let wrapper
diff --git a/webapp/pages/settings/my-social-media.vue b/webapp/pages/settings/my-social-media.vue
index b53df6170..948e77407 100644
--- a/webapp/pages/settings/my-social-media.vue
+++ b/webapp/pages/settings/my-social-media.vue
@@ -4,12 +4,7 @@
-
+
{{ link.url }}
@@ -44,12 +39,8 @@