Skip to content
This repository has been archived by the owner on Mar 22, 2019. It is now read-only.

[WIP] #198 Online Status #244

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/middleware/includedFieldsMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ const includeFieldsRecursively = (includedFields) => {
}

export default {
Query: includeFieldsRecursively(['id', 'disabled', 'deleted']),
Mutation: includeFieldsRecursively(['id', 'disabled', 'deleted'])
Query: includeFieldsRecursively(['id', 'disabled', 'deleted', 'preferences']),
Mutation: includeFieldsRecursively(['id', 'disabled', 'deleted', 'preferences'])
}
4 changes: 3 additions & 1 deletion src/middleware/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import xssMiddleware from './xssMiddleware'
import permissionsMiddleware from './permissionsMiddleware'
import userMiddleware from './userMiddleware'
import includedFieldsMiddleware from './includedFieldsMiddleware'
import lastActiveMiddleware from './lastActiveMiddleware'

export default schema => {
let middleware = [
Expand All @@ -20,7 +21,8 @@ export default schema => {
fixImageUrlsMiddleware,
softDeleteMiddleware,
userMiddleware,
includedFieldsMiddleware
includedFieldsMiddleware,
lastActiveMiddleware
]

// add permisions middleware at the first position (unless we're seeding)
Expand Down
40 changes: 40 additions & 0 deletions src/middleware/lastActiveMiddleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import values from 'lodash/values'

const queue = {
users: {},
driver: null,
add: (context, lastActiveAt) => {
queue.driver = context.driver
queue.users[context.user.id] = {
id: context.user.id,
lastActiveAt
}
},
run: async () => {
if (!queue.driver || !values(queue.users).length) return

const users = { ...queue.users }
queue.users = {}

const session = queue.driver.session()
await session.run(`
UNWIND $users AS user
MATCH(u:User {id: user.id})
SET u.lastActiveAt = user.lastActiveAt`, {
users: values(users)
})
session.close()
}
}
setInterval(queue.run, 10000)

export default {
Mutation: async (resolve, root, args, context, info) => {
if (context.user) queue.add(context, (new Date()).toISOString())
return resolve(root, args, context, info)
},
Query: async (resolve, root, args, context, info) => {
if (context.user) queue.add(context, (new Date()).toISOString())
return resolve(root, args, context, info)
}
}
9 changes: 8 additions & 1 deletion src/middleware/permissionsMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ const isAuthor = rule({ cache: 'no_cache' })(async (parent, args, { user, driver
return authorId === user.id
})

const wantsToShowOnlineStatus = rule({ cache: 'no_cache' })(async (parent, args, { user, driver }) => {
const preferences = parent.preferences || []
return preferences.indexOf('hideOnlineStatus') < 0
})

// Permissions
const permissions = shield({
Query: {
Expand Down Expand Up @@ -68,7 +73,9 @@ const permissions = shield({
},
User: {
email: isMyOwn,
password: isMyOwn
password: isMyOwn,
preferences: or(isMyOwn, isAdmin),
lastActiveAt: or(wantsToShowOnlineStatus, isModerator)
}
})

Expand Down
9 changes: 9 additions & 0 deletions src/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ type User {

createdAt: String
updatedAt: String
"Date of last interaction with the system"
lastActiveAt: String

"User preferences like 'hideOnlineStatus'"
preferences: [UserPreferenceEnum]

friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)")
Expand Down Expand Up @@ -167,6 +172,10 @@ type User {
badgesCount: Int! @cypher(statement: "MATCH (this)<-[:REWARDED]-(r:Badge) RETURN COUNT(r)")
}

enum UserPreferenceEnum {
hideOnlineStatus
}

type Post {
id: ID!
activityId: String
Expand Down
11 changes: 10 additions & 1 deletion src/seed/factories/users.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import faker from 'faker'
import uuid from 'uuid/v4'
import helpers from '../seed-helpers'

// random preferences, chance 1 to 3
const preferences = [
'null',
'[hideOnlineStatus]',
'null'
]

export default function create (params) {
const {
Expand All @@ -25,7 +33,8 @@ export default function create (params) {
about: "${about}",
role: ${role},
disabled: ${disabled},
deleted: ${deleted}
deleted: ${deleted},
preferences: ${helpers.random(preferences)}
) {
id
name
Expand Down