When I visit a route in my browser I expect Iron Router to call onBeforeAction once before loading the route. But it looks like it is being called 3 times when first loading the route.
This is an issue for me because I want to put code that redirects the user if they do not have access to that document.
onBeforeAction: ->
console.log 'called once' #Called 3 times when first loading the route!
thread = Research.findOne(@params._id)
console.log thread # This is undefined at first run
thread = Research.findOne(@params._id)
if thread?
Meteor.subscribe 'collabUsers', @params._id
else
Router.go '/research'
Since it is called multiple times, it causes issues with redirecting. First users that do have access are also redirected because at first thread is undefined.
What I am trying to do if check if the user has access to the data the route depends on, if not then I need to redirect the user. So that is why in onBeforeAction I am trying to pull a document from database and if it exists then I will load the page or else I will redirect or throw and error message at the user.
But I notice that the console.log statement in onBeforeAction is called 3 times when the route is first loaded. And also on the first run the user does not have access to any research threads for some reason (I believe the subscription has not been setup and documents are not accessible on first run) So that causes issues with my trying to see if they have access to the document because on first run nobody has access.
Here is the entire router.coffee code
appendUserData = (array) ->
_.each array, (item) ->
user = Meteor.users.findOne(item.userId)
if user?.profile.firstName? && user?.profile.lastName?
item.firstName = user.profile.firstName
item.lastName = user.profile.lastName
item.username = user.username
userEnabled = () ->
if Meteor.user()
if $(window).width() > 768
if !$('.show-left').hasClass 'active'
Meteor.defer ->
$('.show-left').click()
requireLogin = (pause) ->
if !Meteor.user()
@setLayout 'layoutLoggedOut'
if Meteor.loggingIn()
@render @loadingTemplate
else
@render 'login'
pause()
else
@setLayout 'layout'
if window.location.pathname is '/' or undefined
Router.go('addAndSearchPosts')
else
Router.go(window.location.pathname)
Router.configure
layoutTemplate: 'layout'
loadingTemplate: 'loading'
onBeforeAction: ->
#this code get which ids we need to get data from to render template. Here we need to get data to notification of collab
params = {}
params.threadIds = []
params.userIds = []
notifications = Notifications.find {userId: Meteor.userId()}
notifications.forEach (notification) ->
params.threadIds.push notification.threadId
params.userIds.push notification.requesterId
@subscribe('notificationDataCollab', params).wait()
waitOn: ->
[
Meteor.subscribe 'myResearch', Meteor.userId()
Meteor.subscribe "notifications"
]
Router.onAfterAction userEnabled
Router.onBeforeAction requireLogin,
except: 'template1'
Router.onBeforeAction 'loading'
Router.onBeforeAction ->
Errors.clearSeen()
Router.map ->
@route 'posts_page',
path: '/posts',
@route 'template1',
path: '/template1',
@route 'login',
path: '/',
@route 'addAndSearchPosts',
path: '/bookmarks',
waitOn: ->
Meteor.subscribe 'myBookmarks', Meteor.userId()
data: ->
bookmarks: Bookmarks.find
_userId: Meteor.userId()
@route 'research',
path: '/research/:_id',
waitOn: ->
[
Meteor.subscribe 'threadNotes', @params._id, Meteor.userId()
Meteor.subscribe 'collabUsers', @params._id
]
onBeforeAction: ->
console.log 'called once'
#Meteor.subscribe 'collabUsers', @params._id
# thread = Research.findOne(@params._id)
# console.log thread
#thread = Research.findOne(@params._id)
# if thread?
# Meteor.subscribe 'collabUsers', @params._id
# else
# Router.go '/research'
#Errors.throw('Thread does not exist or you do not have access', false)
data: ->
# this code is for appending the user data to pending and current collaborators for this thread
thread = Research.findOne(@params._id)
if thread?.pending?.collaborators?.length > 0
appendUserData(thread.pending.collaborators)
if thread?.collaborators?.length > 0
appendUserData(thread.collaborators)
data =
researchThread: thread,
notes: Notes.find
_threadId: @params._id
,
sort:
date: -1
data
@route 'researchHome',
path: '/research'
@route 'profileEdit',
path: '/editprofile'
Here is publications.coffee
Meteor.publish 'myResearch', (id) ->
Research.find({$or: [{_userId: id}, {'collaborators.userId': id}] })
Meteor.publish 'threadNotes', (threadId) ->
Notes.find({_threadId: threadId})
Meteor.publish 'myBookmarks', (userId) ->
Bookmarks.find({_userId: userId})
Meteor.publish 'collabUsers', (threadId) ->
Meteor.users.find({}, {fields: {profile: 1, username: 1}})
Meteor.publish 'notifications', ->
Notifications.find()
Meteor.publish 'notificationDataCollab', (params) ->
[
Meteor.users.find({_id: {$in: params.userIds}}, {fields: {username: 1}})
Research.find({_id: {$in: params.threadIds}}, {fields: {name: 1}})
]
Any advice on how to handle this is appreciated.
onBeforeAction
is run and rerun reactively. You probably want onRun
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With