diff --git a/src/jwt/decode.js b/src/jwt/decode.js index e8305a8..d49987b 100644 --- a/src/jwt/decode.js +++ b/src/jwt/decode.js @@ -7,7 +7,7 @@ export default async (driver, authorizationHeader) => { try { const decoded = await jwt.verify(token, process.env.JWT_SECRET) id = decoded.sub - } catch { + } catch (e) { return null } const session = driver.session() diff --git a/src/middleware/permissionsMiddleware.js b/src/middleware/permissionsMiddleware.js index 62999c2..2bc824d 100644 --- a/src/middleware/permissionsMiddleware.js +++ b/src/middleware/permissionsMiddleware.js @@ -56,6 +56,8 @@ const permissions = shield({ CreateBadge: isAdmin, UpdateBadge: isAdmin, DeleteBadge: isAdmin, + addSocialMedia: isAuthenticated, + // addFruitToBasket: isAuthenticated follow: isAuthenticated, unfollow: isAuthenticated, diff --git a/src/resolvers/user_management.js b/src/resolvers/user_management.js index 26dfb81..f241785 100644 --- a/src/resolvers/user_management.js +++ b/src/resolvers/user_management.js @@ -1,7 +1,7 @@ -import encode from '../jwt/encode' -import bcrypt from 'bcryptjs' -import { AuthenticationError } from 'apollo-server' -import { neo4jgraphql } from 'neo4j-graphql-js' +import encode from "../jwt/encode" +import bcrypt from "bcryptjs" +import { AuthenticationError } from "apollo-server" +import { neo4jgraphql } from "neo4j-graphql-js" export default { Query: { @@ -25,7 +25,7 @@ export default { return true }, - login: async (parent, { email, password }, { driver, req, user }) => { + login: async (_, { email, password }, { driver, req, user }) => { // if (user && user.id) { // throw new Error('Already logged in.') // } @@ -100,6 +100,25 @@ export default { return encode(currentUser) } + }, + addSocialMedia: async (_, { url }, { driver, user }) => { + const session = driver.session() + + const { email } = user + const result = await session.run( + `MATCH (user:User {email: $userEmail}) + SET user.socialMedia = [$url] + RETURN user {.socialMedia}`, + { + userEmail: email, + url + } + ) + session.close() + const [currentUser] = result.records.map(record => { + return record.get("user") + }) + return !!currentUser.socialMedia } } } diff --git a/src/resolvers/user_management.spec.js b/src/resolvers/user_management.spec.js index 1c21ada..9e474e1 100644 --- a/src/resolvers/user_management.spec.js +++ b/src/resolvers/user_management.spec.js @@ -1,9 +1,9 @@ -import Factory from '../seed/factories' -import { GraphQLClient, request } from 'graphql-request' -import jwt from 'jsonwebtoken' -import { host, login } from '../jest/helpers' +import Factory from "../seed/factories"; +import { GraphQLClient, request } from "graphql-request"; +import jwt from "jsonwebtoken"; +import { host, login } from "../jest/helpers"; -const factory = Factory() +const factory = Factory(); // here is the decoded JWT token: // { @@ -117,37 +117,37 @@ describe('currentUser', () => { email role } - }` + }`; - describe('unauthenticated', () => { - it('returns null', async () => { - const expected = { currentUser: null } - await expect(request(host, query)).resolves.toEqual(expected) - }) - }) + describe("unauthenticated", () => { + it("returns null", async () => { + const expected = { currentUser: null }; + await expect(request(host, query)).resolves.toEqual(expected); + }); + }); - describe('with valid JWT Bearer Token', () => { - let client - let headers + describe("with valid JWT Bearer Token", () => { + let client; + let headers; - describe('but no corresponding user in the database', () => { + describe("but no corresponding user in the database", () => { beforeEach(async () => { - client = new GraphQLClient(host, { headers: jennyRostocksHeaders }) - }) + client = new GraphQLClient(host, { headers: jennyRostocksHeaders }); + }); - it('returns null', async () => { - const expected = { currentUser: null } - await expect(client.request(query)).resolves.toEqual(expected) - }) - }) + it("returns null", async () => { + const expected = { currentUser: null }; + await expect(client.request(query)).resolves.toEqual(expected); + }); + }); - describe('and corresponding user in the database', () => { + describe("and corresponding user in the database", () => { beforeEach(async () => { - headers = await login({ email: 'test@example.org', password: '1234' }) - client = new GraphQLClient(host, { headers }) - }) + headers = await login({ email: "test@example.org", password: "1234" }); + client = new GraphQLClient(host, { headers }); + }); - it('returns the whole user object', async () => { + it("returns the whole user object", async () => { const expected = { currentUser: { avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/jimmuirhead/128.jpg', @@ -185,11 +185,11 @@ describe('login', () => { ) const token = data.login jwt.verify(token, process.env.JWT_SECRET, (err, data) => { - expect(data.email).toEqual('test@example.org') - expect(err).toBeNull() - }) - }) - }) + expect(data.email).toEqual("test@example.org"); + expect(err).toBeNull(); + }); + }); + }); describe('valid email/password but user is disabled', () => { it('responds with "Your account has been disabled."', async () => { diff --git a/src/schema.graphql b/src/schema.graphql index af7764f..7066f52 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -25,6 +25,7 @@ type Mutation { report(id: ID!, description: String): Report disable(id: ID!): ID enable(id: ID!): ID + addSocialMedia(url: String!): Boolean! "Shout the given Type and ID" shout(id: ID!, type: ShoutTypeEnum): Boolean! @cypher(statement: """ MATCH (n {id: $id})<-[:WROTE]-(wu:User), (u:User {id: $cypherParams.currentUserId}) @@ -118,6 +119,7 @@ type User { location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l") locationName: String about: String + socialMedia: [String] createdAt: String updatedAt: String @@ -298,3 +300,9 @@ type SharedInboxEndpoint { id: ID! uri: String } + +type socialMedia { + id: ID! + name: String! + icon: String! +} \ No newline at end of file