WIP: track changes with token-access

This commit is contained in:
Shane Kilkelly 2017-10-25 10:34:18 +01:00
parent b32088ee6b
commit 74c231826d
16 changed files with 134 additions and 31 deletions

View file

@ -38,3 +38,13 @@ module.exports = CollaboratorsController =
logger.err {projectId}, "error getting members for project"
return next(err)
res.json({members: members})
getTokenMembers: (req, res, next) ->
projectId = req.params.Project_id
logger.log {projectId}, "getting token members for project"
CollaboratorsHandler.getTokenMembers projectId, (err, tokenMembers) ->
tokenMembers = tokenMembers.slice(0, 100)
if err?
logger.err {projectId}, "error getting token members for project"
return next(err)
res.json({tokenMembers})

View file

@ -11,6 +11,7 @@ Errors = require "../Errors/Errors"
EmailHelper = require "../Helpers/EmailHelper"
ProjectEditorHandler = require "../Project/ProjectEditorHandler"
Sources = require "../Authorization/Sources"
ObjectId = require('mongojs').ObjectId
module.exports = CollaboratorsHandler =
@ -232,3 +233,31 @@ module.exports = CollaboratorsHandler =
return callback(error)
{owner, members} = ProjectEditorHandler.buildOwnerAndMembersViews(rawMembers)
callback(null, members)
getTokenMembers: (projectId, callback=(err, members)->) ->
logger.log {projectId}, "fetching all token members"
CollaboratorsHandler.getTokenMembersWithPrivilegeLevels projectId, (error, rawTokenMembers) ->
if error?
logger.err {projectId, error}, "error getting token members for project"
return callback(error)
{_owner, tokenMembers} = ProjectEditorHandler.buildOwnerAndMembersViews(
null,
rawTokenMembers
)
callback(null, tokenMembers)
userIsTokenMember: (userId, projectId, callback=(err, isTokenMember)->) ->
userId = ObjectId(userId.toString())
projectId = ObjectId(projectId.toString())
Project.findOne {
_id: projectId,
$or: [
{tokenAccessReadOnly_refs: userId},
{tokenAccessReadAndWrite_refs: userId}
]
}, {
_id: 1
}, (err, project) ->
if err?
return callback(err)
callback(null, project?)

View file

@ -17,6 +17,13 @@ module.exports =
CollaboratorsController.getAllMembers
)
webRouter.get(
'/project/:Project_id/token_members',
AuthenticationController.requireLogin(),
AuthorizationMiddlewear.ensureUserCanAdminProject,
CollaboratorsController.getTokenMembers
)
# invites
webRouter.post(
'/project/:Project_id/invite',

View file

@ -23,6 +23,7 @@ PackageVersions = require("../../infrastructure/PackageVersions")
AnalyticsManager = require "../Analytics/AnalyticsManager"
Sources = require "../Authorization/Sources"
TokenAccessHandler = require '../TokenAccess/TokenAccessHandler'
CollaboratorsHandler = require '../Collaborators/CollaboratorsHandler'
module.exports = ProjectController =
@ -247,6 +248,11 @@ module.exports = ProjectController =
return cb(null, false)
else
return cb(null, true)
isTokenMember: (cb) ->
cb = underscore.once(cb)
if !user_id?
return cb()
CollaboratorsHandler.userIsTokenMember user_id, project_id, cb
}, (err, results)->
if err?
logger.err err:err, "error getting details for project page"
@ -260,6 +266,7 @@ module.exports = ProjectController =
logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor"
token = TokenAccessHandler.getRequestToken(req, project_id)
isTokenMember = results.isTokenMember
AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, token, (error, privilegeLevel)->
return next(error) if error?
if !privilegeLevel? or privilegeLevel == PrivilegeLevels.NONE
@ -304,6 +311,7 @@ module.exports = ProjectController =
chatUrl: Settings.apis.chat.url
anonymous: anonymous
anonymousAccessToken: req._anonymousAccessToken
isTokenMember: isTokenMember
languages: Settings.languages
themes: THEME_LIST
maxDocLength: Settings.max_doc_length

View file

@ -51,13 +51,13 @@ module.exports = ProjectEditorHandler =
ownerFeatures = null
filteredMembers = []
filteredTokenMembers = []
for member in members
for member in (members || [])
if member.privilegeLevel == "owner"
ownerFeatures = member.user.features
owner = @buildUserModelView member.user, "owner"
else
filteredMembers.push @buildUserModelView member.user, member.privilegeLevel
for tokenMember in tokenMembers
for tokenMember in (tokenMembers || [])
filteredTokenMembers.push @buildUserModelView tokenMember.user, tokenMember.privilegeLevel
return {
owner: owner,

View file

@ -1,6 +1,7 @@
ProjectController = require "../Project/ProjectController"
AuthenticationController = require '../Authentication/AuthenticationController'
TokenAccessHandler = require './TokenAccessHandler'
EditorRealTimeController = require "../Editor/EditorRealTimeController"
Errors = require '../Errors/Errors'
logger = require 'logger-sharelatex'
@ -61,6 +62,12 @@ module.exports = TokenAccessController =
logger.err {err, token, userId, projectId: project._id},
"error adding user to project with readAndWrite token"
return next(err)
setTimeout( () ->
EditorRealTimeController.emitToRoom(
'project:membership:changed',
{tokenMembers: true}
)
, 1000)
return TokenAccessController._loadEditor(project._id, req, res, next)
readOnlyToken: (req, res, next) ->
@ -96,4 +103,3 @@ module.exports = TokenAccessController =
return next(err)
return TokenAccessController._loadEditor(project._id, req, res, next)

View file

@ -346,3 +346,4 @@ module.exports = class Router
TokenAccessController.readAndWriteToken
webRouter.get '*', ErrorController.notFound

View file

@ -119,6 +119,7 @@ block requirejs
window.csrfToken = "!{csrfToken}";
window.anonymous = #{anonymous};
window.anonymousAccessToken = "#{anonymousAccessToken}";
window.isTokenMember = #{!!isTokenMember};
window.maxDocLength = #{maxDocLength};
window.trackChangesState = data.trackChangesState;
window.showTrackChangesOnboarding = #{!!showTrackChangesOnboarding};

View file

@ -80,18 +80,15 @@
on-toggle="toggleTrackChangesForUser(isOn, member.id);"
disabled="reviewPanel.trackChangesOnForEveryone || !project.features.trackChanges || !permissions.write"
)
li.rp-tc-state-separator
li.rp-tc-state-item(
ng-repeat="member in reviewPanel.formattedProjectTokenMembers"
)
span.rp-tc-state-item-name(
ng-class="{ 'rp-tc-state-item-name-disabled' : reviewPanel.trackChangesOnForEveryone}"
style="color: hsl({{ member.hue }}, 70%, 40%);"
) {{ member.name }}
li.rp-tc-state-item.rp-tc-state-item-guests
// span.rp-tc-state-item-name !{translate("tc_guests")}
span.rp-tc-state-item-name Guests
review-panel-toggle(
ng-model="reviewPanel.trackChangesState[member.id].value"
on-toggle="toggleTrackChangesForUser(isOn, member.id);"
disabled="reviewPanel.trackChangesOnForEveryone || !project.features.trackChanges || !permissions.write"
ng-model="reviewPanel.trackChangesOnForGuests"
on-toggle="toggleTrackChangesForGuests(isOn);"
disabled="!project.features.trackChanges || !permissions.write"
)
.rp-entry-list(

View file

@ -86,6 +86,7 @@ define [
$scope.settings = window.userSettings
$scope.anonymous = window.anonymous
$scope.isTokenMember = window.isTokenMember
$scope.chat = {}

View file

@ -25,6 +25,7 @@ define [
if @track_changes
update.meta ?= {}
update.meta.tc = @track_changes_id_seeds.inflight
# console.log ">> update", @doc_id, update
@socket.emit "applyOtUpdate", @doc_id, update, (error) =>
return @_handleError(error) if error?
state: "ok"

View file

@ -66,6 +66,7 @@ define [
for annotation in @$scope.highlights or []
do (annotation) =>
colorScheme = ColorManager.getColorScheme(annotation.hue, @element)
console.log ">> color", colorScheme
if annotation.cursor?
@labels.push {
text: annotation.label

View file

@ -6,6 +6,8 @@ define [
], (App, EventEmitter, ColorManager, RangesTracker) ->
App.controller "ReviewPanelController", ($scope, $element, ide, $timeout, $http, $modal, event_tracking, localStorage) ->
$reviewPanelEl = $element.find "#review-panel"
# TODO: remove debug code
window.S = $scope
$scope.SubViews =
CUR_FILE : "cur_file"
@ -18,6 +20,8 @@ define [
$scope.reviewPanel =
trackChangesState: {}
trackChangesOnForEveryone: false
trackChangesOnForGuests: false
trackChangesOnForThisGuestClient: false
entries: {}
resolvedComments: {}
hasEntries: false
@ -32,7 +36,6 @@ define [
resolvedThreadIds: {}
rendererData: {}
formattedProjectMembers: {}
formattedProjectTokenMembers: {}
fullTCStateCollapsed: true
loadingThreads: false
# All selected changes. If a aggregated change (insertion + deletion) is selection, the two ids
@ -78,14 +81,6 @@ define [
if member.privileges == "readAndWrite"
$scope.reviewPanel.formattedProjectMembers[member._id] = formatUser(member)
$scope.$watch "project.tokenMembers", (tokenMembers) ->
$scope.reviewPanel.formattedProjectTokenMembers = {}
if $scope.project?.tokenMembers?
for member in tokenMembers
if member.privileges == "readAndWrite"
if !_.find($scope.reviewPanel.formattedProjectMembers, (m) -> m.id == member._id)
$scope.reviewPanel.formattedProjectTokenMembers[member._id] = formatUser(member)
$scope.commentState =
adding: false
content: ""
@ -615,41 +610,67 @@ define [
else if isLocal
state.value = newValue
state.syncState = UserTCSyncState.PENDING
if userId == ide.$scope.user.id
$scope.editor.wantTrackChanges = newValue
$scope.editor.wantTrackChanges = newValue
_setEveryoneTCState = (newValue, isLocal = false) ->
$scope.reviewPanel.trackChangesOnForEveryone = newValue
project = $scope.project
for member in project.members.concat(project.tokenMembers)
for member in project.members
_setUserTCState(member._id, newValue, isLocal)
_setGuestsTCState(newValue, isLocal)
_setUserTCState(project.owner._id, newValue, isLocal)
_setGuestsTCState = (newValue, isLocal = false) ->
$scope.reviewPanel.trackChangesOnForGuests = newValue
if (
ide.$scope.project.publicAccesLevel == 'tokenBased' &&
ide.$scope.isTokenMember &&
ide.$scope?.user?.id?
)
$scope.trackChangesOnForThisGuestClient = newValue
_setUserTCState(ide.$scope.user.id, newValue, isLocal)
applyClientTrackChangesStateToServer = () ->
data = {}
if $scope.reviewPanel.trackChangesOnForGuests
data.on_for_guests = true
if $scope.reviewPanel.trackChangesOnForEveryone
data = {on : true}
data.on = true
else
data = {on_for: {}}
data.on_for = {}
for userId, userState of $scope.reviewPanel.trackChangesState
data.on_for[userId] = userState.value
if !(
$scope.reviewPanel.trackChangesOnForGuests &&
$scope.reviewPanel.trackChangesOnForThisGuestClient
)
data.on_for[userId] = userState.value
data._csrf = window.csrfToken
$http.post "/project/#{$scope.project_id}/track_changes", data
applyTrackChangesStateToClient = (state) ->
console.log ">> applying tc state to client", state
if typeof state is "boolean"
_setEveryoneTCState state
_setGuestsTCState state
else
project = $scope.project
$scope.reviewPanel.trackChangesOnForEveryone = false
for member in project.members.concat(project.tokenMembers)
_setGuestsTCState(state.__guests__ == true)
for member in project.members
_setUserTCState(member._id, state[member._id] ? false)
_setUserTCState($scope.project.owner._id, state[$scope.project.owner._id] ? false)
$scope.toggleTrackChangesForEveryone = (onForEveryone) ->
_setEveryoneTCState onForEveryone, true
_setGuestsTCState onForEveryone, true
applyClientTrackChangesStateToServer()
$scope.toggleTrackChangesForGuests = (onForGuests) ->
_setGuestsTCState onForGuests, true
applyClientTrackChangesStateToServer()
$scope.toggleTrackChangesForUser = (onForUser, userId) ->
_setUserTCState userId, onForUser, true
applyClientTrackChangesStateToServer()

View file

@ -39,4 +39,14 @@ define [
$scope.project.invites = data.invites
.catch () =>
console.error "Error fetching invites for project"
if data.tokenMembers
console.log ">> token members changed"
projectTokenMembers.getTokenMembers()
.then (response) =>
{ data } = response
console.log ">> got token members", data
if data.tokenMembers
$scope.project.tokenMembers = data.tokenMembers
.catch () =>
console.error "Error fetching tokenMembers for project"
]

View file

@ -25,5 +25,12 @@ define [
"X-Csrf-Token": window.csrfToken
})
getTokenMembers: () ->
$http.get("/project/#{ide.project_id}/token_members", {
json: true
headers:
"X-Csrf-Token": window.csrfToken
})
}
]

View file

@ -207,6 +207,9 @@
.rp-tc-state-item-name-disabled {
opacity: .35;
}
.rp-tc-state-item-guests {
color: @blue;
}
.rp-entry-list {
display: none;