diff --git a/config/permissions.js b/config/permissions.js
new file mode 100644
index 0000000000000000000000000000000000000000..75124f38731da9f19dc308868e3de154b2daf7b3
--- /dev/null
+++ b/config/permissions.js
@@ -0,0 +1,39 @@
+const { rule, shield, and, or, not, allow, deny } = require('graphql-shield')
+
+const isAdmin = rule({ cache: 'contextual' })(
+  async (parent, args, ctx, info) => ctx.user.admin,
+)
+
+const isEditor = rule({ cache: 'contextual' })(
+  async (parent, args, ctx, info) => {
+    const rows = ctx.user
+      .$relatedQuery('teams')
+      .where({ role: 'seniorEditor' })
+      .orWhere({ role: 'handlingEditor' })
+      .resultSize()
+    return rows !== 0
+  },
+)
+
+const isAuthenticated = rule({ cache: 'contextual' })(
+  async (parent, args, ctx, info) => !!ctx.user,
+)
+
+const permissions = shield(
+  {
+    Query: {
+      paginatedManuscripts: isAdmin,
+    },
+    Mutation: {
+      createManuscript: isAuthenticated,
+    },
+    // Fruit: isAuthenticated,
+    // Customer: isAdmin,
+  },
+  {
+    allowExternalErrors: true,
+    fallbackRule: or(isAdmin, isEditor),
+  },
+)
+
+module.exports = permissions
diff --git a/server/app.js b/server/app.js
index 69912c4e7b66dff7217b4501c1b0654423bc8f39..ffe8cf9e1e2bc6b1415099d8a469cb0aacba626c 100644
--- a/server/app.js
+++ b/server/app.js
@@ -10,7 +10,7 @@ const helmet = require('helmet')
 const cookieParser = require('cookie-parser')
 const bodyParser = require('body-parser')
 const passport = require('passport')
-const gqlApi = require('pubsweet-server/src/graphql/api') // TODO: Fix import
+const gqlApi = require('./graphql')
 // const index = require('./routes/index')
 // const api = require('./routes/api')
 const logger = require('@pubsweet/logger')
@@ -56,6 +56,8 @@ const configureApp = app => {
   app.use(helmet())
   app.use(express.static(path.resolve('.', '_build')))
 
+  app.use('/public', express.static(path.resolve(__dirname, '../public')))
+
   if (config.has('pubsweet-server.uploads')) {
     app.use(
       '/uploads',
@@ -82,18 +84,6 @@ const configureApp = app => {
   // GraphQL API
   gqlApi(app)
 
-  // SSE update stream
-  // if (_.get('pubsweet-server.sse', config)) {
-  //   sse.setAuthsome(authsome)
-  //   app.get(
-  //     '/updates',
-  //     passport.authenticate('bearer', { session: false }),
-  //     sse.connect,
-  //   )
-
-  //   app.locals.sse = sse
-  // }
-
   // Serve the index page for front end
   // app.use('/', index)
   app.use('/healthcheck', (req, res) => res.send('All good!'))
diff --git a/server/auth-orcid/orcid.js b/server/auth-orcid/orcid.js
index d0ef6cb5d2e49ae10bd076a9af84ac2489b02a6c..01f7dee59295d0f9319d31d4b431abf736394e87 100644
--- a/server/auth-orcid/orcid.js
+++ b/server/auth-orcid/orcid.js
@@ -35,6 +35,7 @@ module.exports = app => {
           }
         }
 
+        // TODO: Update the user details on every login, asynchronously
         try {
           if (!user) {
             user = await new User({
diff --git a/server/graphql.js b/server/graphql.js
new file mode 100644
index 0000000000000000000000000000000000000000..0edd731f92ac7155400e72a181431e5d0868da11
--- /dev/null
+++ b/server/graphql.js
@@ -0,0 +1,74 @@
+const passport = require('passport')
+const { ApolloServer } = require('apollo-server-express')
+const isEmpty = require('lodash/isEmpty')
+const logger = require('@pubsweet/logger')
+const errors = require('@pubsweet/errors')
+const config = require('config')
+const { applyMiddleware } = require('graphql-middleware')
+
+const schema = require('pubsweet-server/src/graphql/schema') // TODO: Fix import
+const loaders = require('pubsweet-server/src/graphql/loaders') // TODO: Fix import
+
+const authBearerAndPublic = passport.authenticate(['bearer', 'anonymous'], {
+  session: false,
+})
+
+const helpers = require('pubsweet-server/src/helpers/authorization')
+
+const hostname = config.has('pubsweet-server.hostname')
+  ? config.get('pubsweet-server.hostname')
+  : 'localhost'
+
+const extraApolloConfig = config.has('pubsweet-server.apollo')
+  ? config.get('pubsweet-server.apollo')
+  : {}
+
+const getUser = async userId => {
+  const { User } = require('@pubsweet/models')
+  return userId ? User.query().findById(userId) : undefined
+}
+
+const permissions = require('../config/permissions')
+
+const api = app => {
+  app.use('/graphql', authBearerAndPublic)
+  const server = new ApolloServer({
+    schema: applyMiddleware(schema, permissions),
+    context: async ({ req, res }) => ({
+      helpers,
+      user: await getUser(req.user),
+      loaders: loaders(),
+      models: require('@pubsweet/models'),
+    }),
+    formatError: err => {
+      const error = isEmpty(err.originalError) ? err : err.originalError
+
+      logger.error(error.message, { error })
+
+      const isPubsweetDefinedError = Object.values(errors).some(
+        pubsweetError => error instanceof pubsweetError,
+      )
+      // err is always a GraphQLError which should be passed to the client
+      if (!isEmpty(err.originalError) && !isPubsweetDefinedError)
+        return {
+          name: 'Server Error',
+          message: 'Something went wrong! Please contact your administrator',
+        }
+
+      return {
+        name: error.name || 'GraphQLError',
+        message: error.message,
+        extensions: {
+          code: err.extensions.code,
+        },
+      }
+    },
+    playground: {
+      subscriptionEndpoint: `ws://${hostname}:3000/subscriptions`,
+    },
+    ...extraApolloConfig,
+  })
+  server.applyMiddleware({ app })
+}
+
+module.exports = api
diff --git a/server/model-manuscript/src/graphql.js b/server/model-manuscript/src/graphql.js
index 9ee042fe075a094368d5c92e8fdccec58bec7e60..e615f43bea6c281801fcd8f1e8f7ae9cd7eadf0a 100644
--- a/server/model-manuscript/src/graphql.js
+++ b/server/model-manuscript/src/graphql.js
@@ -30,22 +30,22 @@ const resolvers = {
         }),
         status: 'new',
         submission,
-        submitterId: ctx.user,
+        submitterId: ctx.user.id,
       }
 
       // eslint-disable-next-line
-      const manuscript = await new ctx.connectors.Manuscript.model(
+      const manuscript = await new ctx.models.Manuscript(
         emptyManuscript,
       ).saveGraph()
 
       // Create two channels: 1. free for all involved, 2. editorial
-      const allChannel = new ctx.connectors.Channel.model({
+      const allChannel = new ctx.models.Channel({
         manuscriptId: manuscript.id,
         topic: 'Manuscript discussion',
         type: 'all',
       }).save()
 
-      const editorialChannel = new ctx.connectors.Channel.model({
+      const editorialChannel = new ctx.models.Channel({
         manuscriptId: manuscript.id,
         topic: 'Editorial discussion',
         type: 'editorial',
@@ -61,7 +61,7 @@ const resolvers = {
         })
         manuscript.files.push(
           // eslint-disable-next-line
-          await new ctx.connectors.File.model(newFile).save(),
+          await new ctx.models.File(newFile).save(),
         )
       })
 
@@ -73,7 +73,7 @@ const resolvers = {
           name: 'Author',
           objectId: manuscript.id,
           objectType: 'Manuscript',
-          members: [{ user: { id: ctx.user } }],
+          members: [{ user: { id: ctx.user.id } }],
         },
         { relate: true },
       )
@@ -84,11 +84,11 @@ const resolvers = {
     },
     async deleteManuscript(_, { id }, ctx) {
       const deleteManuscript = []
-      const manuscript = await ctx.connectors.Manuscript.model.find(id)
+      const manuscript = await ctx.models.Manuscript.find(id)
 
       deleteManuscript.push(manuscript.id)
       if (manuscript.parentId) {
-        const parentManuscripts = await ctx.connectors.Manuscript.model.findByField(
+        const parentManuscripts = await ctx.models.Manuscript.findByField(
           'parent_id',
           manuscript.parentId,
         )
@@ -101,7 +101,7 @@ const resolvers = {
       // Delete Manuscript
       if (deleteManuscript.length > 0) {
         deleteManuscript.forEach(async manuscript => {
-          await ctx.connectors.Manuscript.delete(manuscript, ctx)
+          await ctx.models.Manuscript.query().deleteById(manuscript)
         })
       }
       return id
@@ -143,12 +143,12 @@ const resolvers = {
     },
     async updateManuscript(_, { id, input }, ctx) {
       const data = JSON.parse(input)
-      const manuscript = await ctx.connectors.Manuscript.fetchOne(id, ctx)
+      const manuscript = await ctx.models.Manuscript.findById(id)
       const update = merge({}, manuscript, data)
-      return ctx.connectors.Manuscript.update(id, update, ctx)
+      return ctx.models.Manuscript.update(id, update, ctx)
     },
     async makeDecision(_, { id, decision }, ctx) {
-      const manuscript = await ctx.connectors.Manuscript.fetchOne(id, ctx)
+      const manuscript = await ctx.models.Manuscript.findById(id)
       manuscript.decision = decision
 
       manuscript.status = decision
@@ -178,7 +178,7 @@ const resolvers = {
         },
       ]
       manuscript.decision = ''
-      manuscript.files = await ctx.connectors.File.model.findByObject({
+      manuscript.files = await ctx.models.File.findByObject({
         object: 'Manuscript',
         object_id: manuscript.id,
       })
@@ -190,12 +190,10 @@ const resolvers = {
       return manuscript
     },
     async manuscripts(_, { where }, ctx) {
-      return ctx.connectors.Manuscript.fetchAll(where, ctx, {
-        eager: '[teams, reviews]',
-      })
+      return ctx.models.Manuscript.query().eager('[teams, reviews]')
     },
     async paginatedManuscripts(_, { sort, offset, limit, filter }, ctx) {
-      const query = ctx.connectors.Manuscript.model.query().eager('submitter')
+      const query = ctx.models.Manuscript.query().eager('submitter')
 
       if (filter && filter.status) {
         query.where({ status: filter.status })
@@ -391,24 +389,6 @@ const typeDefs = `
     notesType: String
     content: String
   }
-
-  # type reviewerStatus {
-  #   user: ID!
-  #   status: String
-  # }
-
-  # input reviewerStatusUpdate {
-  #   user: ID!
-  #   status: String
-  # }
-
-  # extend type Team {
-  #   status: [reviewerStatus]
-  # }
-
-  # extend input TeamInput {
-  #   status: [reviewerStatusUpdate]
-  # }
 `
 
 module.exports = {
diff --git a/server/model-message/src/graphql.js b/server/model-message/src/graphql.js
index c5cb8146aa27c575cbbe774774bfd67bbd8a291b..6b6a362311e49d3659170d09767f540efd7333fc 100644
--- a/server/model-message/src/graphql.js
+++ b/server/model-message/src/graphql.js
@@ -43,7 +43,8 @@ const resolvers = {
   Mutation: {
     createMessage: async (_, { content, channelId }, context) => {
       const pubsub = await getPubsub()
-      const userId = context.user
+      const userId = context.user.id
+      console.log(userId, context.user)
       const savedMessage = await new Message({
         content,
         userId,
diff --git a/server/model-message/src/migrations/1585344885-add-messages.sql b/server/model-message/src/migrations/1585344885-add-messages.sql
index caad7a3ba769d1e8cf3f9988b9e675b75923317a..3ac17266a2fb24ae2d51b92a20a4fecbc292d3dd 100644
--- a/server/model-message/src/migrations/1585344885-add-messages.sql
+++ b/server/model-message/src/migrations/1585344885-add-messages.sql
@@ -1,7 +1,7 @@
 CREATE TABLE messages (
   id UUID PRIMARY KEY,
-  user_id uuid NOT NULL REFERENCES users(id),
-  channel_id uuid NOT NULL REFERENCES channels(id),
+  user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+  channel_id uuid NOT NULL REFERENCES channels(id) ON DELETE CASCADE,
   created TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT current_timestamp,
   updated TIMESTAMP WITH TIME ZONE,
   content TEXT
diff --git a/server/model-review/src/resolvers.js b/server/model-review/src/resolvers.js
index ab90a6ecc39cf9fcf15ea91d2aadeaafa155e49c..90b611e5b4d76d6fc766d058016f5618cd776adb 100644
--- a/server/model-review/src/resolvers.js
+++ b/server/model-review/src/resolvers.js
@@ -14,7 +14,7 @@ const resolvers = {
 
         return rvw
       }
-      input.userId = ctx.user
+      input.userId = ctx.user.id
       const review = await new Review(input)
       await review.save()
       review.comments = await review.getComments()
diff --git a/server/model-team/src/graphql.js b/server/model-team/src/graphql.js
index 830133ce8eec65a5bd53b772952c011a632f1a20..0f1b08e636c84e1152f854635976f1877c67c873 100644
--- a/server/model-team/src/graphql.js
+++ b/server/model-team/src/graphql.js
@@ -3,28 +3,32 @@ const eager = '[members.[user, alias]]'
 const resolvers = {
   Query: {
     team(_, { id }, ctx) {
-      return ctx.connectors.Team.fetchOne(id, ctx, { eager })
+      return ctx.models.Team.query()
+        .findById(id)
+        .eager(eager)
     },
     teams(_, { where }, ctx) {
       where = where || {}
-      if (where.users) {
-        const { users } = where
-        delete where.users
-        where._relations = [{ relation: 'users', ids: users }]
-      }
-
-      if (where.alias) {
-        const { alias } = where
-        delete where.alias
-        where._relations = [{ relation: 'aliases', object: alias }]
-      }
-
-      return ctx.connectors.Team.fetchAll(where, ctx, { eager })
+      // if (where.users) {
+      //   const { users } = where
+      //   delete where.users
+      //   where._relations = [{ relation: 'users', ids: users }]
+      // }
+
+      // if (where.alias) {
+      //   const { alias } = where
+      //   delete where.alias
+      //   where._relations = [{ relation: 'aliases', object: alias }]
+      // }
+
+      return ctx.models.Team.query()
+        .where(where)
+        .eager(eager)
     },
   },
   Mutation: {
     deleteTeam(_, { id }, ctx) {
-      return ctx.connectors.Team.delete(id, ctx)
+      return ctx.models.Team.query().deleteById(id)
     },
     createTeam(_, { input }, ctx) {
       const options = {
@@ -33,22 +37,29 @@ const resolvers = {
         allowUpsert: '[members, members.alias]',
         eager: '[members.[user.teams, alias]]',
       }
-      return ctx.connectors.Team.create(input, ctx, options)
+      return ctx.models.Team.query().insertGraphAndFetch(input, options)
     },
     updateTeam(_, { id, input }, ctx) {
-      return ctx.connectors.Team.update(id, input, ctx, {
-        unrelate: false,
-        eager: 'members.user.teams',
-      })
+      return ctx.models.Team.query().upsertGraphAndFetch(
+        {
+          id,
+          ...input,
+        },
+        {
+          unrelate: false,
+          eager: 'members.user.teams',
+        },
+      )
     },
   },
   User: {
     teams: (parent, _, ctx) =>
-      ctx.connectors.User.fetchRelated(parent.id, 'teams', undefined, ctx),
+      ctx.models.User.relatedQuery('teams').for(parent.id),
   },
   Team: {
-    members(team, { where }, ctx) {
-      return ctx.connectors.Team.fetchRelated(team.id, 'members', where, ctx)
+    async members(team, { where }, ctx) {
+      const t = await ctx.models.Team.query().findById(team.id)
+      return t.$relatedQuery('members')
     },
     object(team, vars, ctx) {
       const { objectId, objectType } = team
@@ -56,21 +67,13 @@ const resolvers = {
     },
   },
   TeamMember: {
-    user(teamMember, vars, ctx) {
-      return ctx.connectors.TeamMember.fetchRelated(
-        teamMember.id,
-        'user',
-        undefined,
-        ctx,
-      )
+    async user(teamMember, vars, ctx) {
+      const member = await ctx.models.TeamMember.query().findById(teamMember.id)
+      return member.$relatedQuery('user')
     },
-    alias(teamMember, vars, ctx) {
-      return ctx.connectors.TeamMember.fetchRelated(
-        teamMember.id,
-        'alias',
-        undefined,
-        ctx,
-      )
+    async alias(teamMember, vars, ctx) {
+      const member = await ctx.models.TeamMember.query().findById(teamMember.id)
+      return member.$relatedQuery('alias')
     },
   },
 }
diff --git a/server/model-user/src/graphql.js b/server/model-user/src/graphql.js
index 2cc0698de92cfbc0edc5032069d04eae2d7138f8..56565dd4a4645070bf9d86913cd82d012e87b102 100644
--- a/server/model-user/src/graphql.js
+++ b/server/model-user/src/graphql.js
@@ -1,18 +1,16 @@
 const logger = require('@pubsweet/logger')
 const { AuthorizationError, ConflictError } = require('@pubsweet/errors')
 
-const eager = undefined
-
 const resolvers = {
   Query: {
     user(_, { id }, ctx) {
-      return ctx.connectors.User.fetchOne(id, ctx, { eager })
+      return ctx.models.User.query().findById(id)
     },
     async users(_, vars, ctx) {
-      return ctx.connectors.User.model.query()
+      return ctx.models.User.query()
     },
     async paginatedUsers(_, { sort, offset, limit, filter }, ctx) {
-      const query = ctx.connectors.User.model.query()
+      const query = ctx.models.User.query()
 
       if (filter && filter.admin) {
         query.where({ admin: true })
@@ -39,21 +37,23 @@ const resolvers = {
         users,
       }
 
-      // return ctx.connectors.User.fetchAll(where, ctx, { eager })
+      // return ctx.models.User.fetchAll(where, ctx, { eager })
     },
     // Authentication
-    currentUser(_, vars, ctx) {
+    async currentUser(_, vars, ctx) {
       if (!ctx.user) return null
-      return ctx.connectors.User.model.find(ctx.user, { eager })
+      const user = await ctx.models.User.find(ctx.user.id)
+      user._currentRoles = await user.currentRoles()
+      return user
     },
     searchUsers(_, { teamId, query }, ctx) {
       if (teamId) {
-        return ctx.connectors.User.model
+        return ctx.models.User.model
           .query()
           .where({ teamId })
           .where('username', 'ilike', `${query}%`)
       }
-      return ctx.connectors.User.model
+      return ctx.models.User.model
         .query()
         .where('username', 'ilike', `${query}%`)
     },
@@ -63,9 +63,7 @@ const resolvers = {
       const user = {
         username: input.username,
         email: input.email,
-        passwordHash: await ctx.connectors.User.model.hashPassword(
-          input.password,
-        ),
+        passwordHash: await ctx.models.User.hashPassword(input.password),
       }
 
       const identity = {
@@ -77,7 +75,7 @@ const resolvers = {
       user.defaultIdentity = identity
 
       try {
-        const result = await ctx.connectors.User.create(user, ctx, {
+        const result = await ctx.models.User.create(user, ctx, {
           eager: 'defaultIdentity',
         })
 
@@ -93,17 +91,15 @@ const resolvers = {
       }
     },
     deleteUser(_, { id }, ctx) {
-      return ctx.connectors.User.delete(id, ctx)
+      return ctx.models.User.delete(id, ctx)
     },
     async updateUser(_, { id, input }, ctx) {
       if (input.password) {
-        input.passwordHash = await ctx.connectors.User.model.hashPassword(
-          input.password,
-        )
+        input.passwordHash = await ctx.models.User.hashPassword(input.password)
         delete input.password
       }
 
-      return ctx.connectors.User.update(id, input, ctx)
+      return ctx.models.User.update(id, input, ctx)
     },
     // Authentication
     async loginUser(_, { input }, ctx) {
@@ -112,7 +108,7 @@ const resolvers = {
       let isValid = false
       let user
       try {
-        user = await ctx.connectors.User.model.findByUsername(input.username)
+        user = await ctx.models.User.findByUsername(input.username)
         isValid = await user.validPassword(input.password)
       } catch (err) {
         logger.debug(err)
@@ -126,7 +122,7 @@ const resolvers = {
       }
     },
     async updateCurrentUsername(_, { username }, ctx) {
-      const user = await ctx.connectors.User.model.find(ctx.user)
+      const user = await ctx.models.User.find(ctx.user)
       user.username = username
       await user.save()
       return user
@@ -134,16 +130,15 @@ const resolvers = {
   },
   User: {
     async defaultIdentity(parent, args, ctx) {
-      const identity = await ctx.connectors.Identity.model
-        .query()
+      const identity = await ctx.models.Identity.query()
         .where({ userId: parent.id, isDefault: true })
         .first()
       return identity
     },
     async identities(parent, args, ctx) {
-      const identities = await ctx.connectors.Identity.model
-        .query()
-        .where({ userId: parent.id })
+      const identities = await ctx.models.Identity.query().where({
+        userId: parent.id,
+      })
       return identities
     },
   },
@@ -205,9 +200,17 @@ const typeDefs = `
     defaultIdentity: Identity
     profilePicture: String
     online: Boolean
+    _currentRoles: [CurrentRole]
+    _currentGlobalRoles: [String]
+  }
+
+  type CurrentRole {
+    id: ID
+    roles: [String]
   }
 
   interface Identity {
+    id: ID
     name: String
     aff: String # JATS <aff>
     email: String # JATS <aff>
@@ -218,6 +221,7 @@ const typeDefs = `
 
   # local identity (not from ORCID, etc.)
   type LocalIdentity implements Identity {
+    id: ID
     name: String
     email: String
     aff: String
@@ -225,6 +229,7 @@ const typeDefs = `
   }
 
   type ExternalIdentity implements Identity {
+    id: ID
     name: String
     identifier: String
     email: String
diff --git a/server/model-user/src/user.js b/server/model-user/src/user.js
index 468f9d470f6af4a510a59ec609a7cc467bc97136..fd8b6986db9db2826cfd01a66419c5f3f4686e72 100644
--- a/server/model-user/src/user.js
+++ b/server/model-user/src/user.js
@@ -53,6 +53,7 @@ class User extends BaseModel {
             modelClass: TeamMember,
             from: 'team_members.userId',
             to: 'team_members.teamId',
+            extra: ['status'],
           },
           to: 'teams.id',
         },
@@ -78,12 +79,38 @@ class User extends BaseModel {
     }
   }
 
-  // eslint-disable-next-line class-methods-use-this
-  setOwners() {
-    // FIXME: this is overriden to be a no-op, because setOwners() is called by
-    // the API on create for all entity types and setting `owners` on a User is
-    // not allowed. This should instead be solved by having separate code paths
-    // in the API for different entity types.
+  // // eslint-disable-next-line class-methods-use-this
+  // setOwners() {
+  //   // FIXME: this is overriden to be a no-op, because setOwners() is called by
+  //   // the API on create for all entity types and setting `owners` on a User is
+  //   // not allowed. This should instead be solved by having separate code paths
+  //   // in the API for different entity types.
+  // }
+
+  // This gives a view of the teams and team member structure to reflect
+  // the current roles the user is performing. E.g. if they are a member
+  // of a reviewer team and have the status of 'accepted', they will
+  // have a 'accepted:reviewer' role present in the returned object
+  async currentRoles(object) {
+    let teams
+    if (object && object.id) {
+      teams = await this.$relatedQuery('teams').where('objectId', object.id)
+    } else {
+      teams = await this.$relatedQuery('teams')
+    }
+    const roles = {}
+
+    teams.forEach(t => {
+      const role = `${t.status ? `${t.status}:` : ''}${t.role}`
+
+      // If there's an existing role for this object, add to the list
+      if (t.objectId && Array.isArray(roles[t.objectId])) {
+        roles[t.objectId].push(role)
+      } else if (t.objectId) {
+        roles[t.objectId] = [role]
+      }
+    })
+    return Object.keys(roles).map(id => ({ id, roles: roles[id] }))
   }
 
   async save() {
diff --git a/server/subscriptions.js b/server/subscriptions.js
index f2a234b6bda4cb6893e30699948a3b7d9e713a59..18a3454ec2d38d79a02f9b0c6f007b34072c0475 100644
--- a/server/subscriptions.js
+++ b/server/subscriptions.js
@@ -11,7 +11,7 @@ const { token } = require('pubsweet-server/src/authentication') // TODO: Fix imp
 
 module.exports = {
   addSubscriptions: server => {
-    const connectors = require('pubsweet-server/src/connectors')
+    const models = require('@pubsweet/models')
     const helpers = require('pubsweet-server/src/helpers/authorization')
 
     const { User } = require('@pubsweet/models')
@@ -31,23 +31,26 @@ module.exports = {
                 reject(new Error('Bad auth token'))
               }
 
-              resolve({ user: id, connectors, helpers })
+              resolve({ userId: id, models, helpers })
             })
           })
           console.log('I AM ALIVE!')
           // Record a user's online status
-          await User.query()
-            .update({ online: true })
-            .where('id', addTocontext.user)
+          const user = await User.query().updateAndFetchById(
+            addTocontext.userId,
+            { online: true },
+          )
+
+          addTocontext.user = user
           return addTocontext
         },
         onDisconnect: async (webSocket, context) => {
           const initialContext = await context.initPromise
           // Record that a user is no longer online
-          if (initialContext.user) {
+          if (initialContext.user && initialContext.user.id) {
             await User.query()
               .update({ online: false })
-              .where('id', initialContext.user)
+              .where('id', initialContext.user.id)
           }
         },
       },