Skip to content

Conversation

@StorytellerCZ
Copy link
Member

Adds isInRole function (and its async equivalent) as per #56

TODO: tests

@StorytellerCZ StorytellerCZ linked an issue Feb 3, 2024 that may be closed by this pull request
@StorytellerCZ StorytellerCZ marked this pull request as ready for review July 22, 2024 16:14
@StorytellerCZ
Copy link
Member Author

Just need to add the tests and then we are good to go.

Copy link
Member

@jankapunkt jankapunkt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally approve, since it technically works. My comments a mostly nitpicking.
One thing, though: the majority of the functions could be extracted into a single fn (DRY):

const getIsInRole = (role, scope, fn) => {
  const userId = Meteor.userId()
  const comma = (role || '').indexOf(',')
  let roles

  if (!userId) return false
  if (!Match.test(role, String)) return false

  if (comma !== -1) {
    roles = role.split(',').reduce(function (memo, r) {
      if (!r) {
        return memo
      }
      memo.push(r)
      return memo
    }, [])
  } else {
    roles = [role]
  }

return Match.test(scope, String)
  ? fn(userId, roles, scope)
  : fn(userId, roles)
}
 

// ...

isInRole: function (role, scope) {
  return getIsInRole(role, scope, this.userIsInRole)
}

isInRoleAsync: function (role, scope) {
  return getIsInRole(role, scope, this.userIsInRoleAsync)
}

Just a potential saving of lines and potential bugs etc.

what do you think? Am I overengineering?

return memo
}
memo.push(r)
return memo
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be simplified:

if (r) {
  memo.push(r)
}
return memo

return this.userIsInRole(userId, roles, scope)
}

return this.userIsInRole(userId, roles)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a conditional return:

return Match.test(scope, String)
  ? this.userIsInRole(userId, roles, scope)
  : this.userIsInRole(userId, roles)

return await this.userIsInRoleAsync(userId, roles, scope)
}

return await this.userIsInRoleAsync(userId, roles)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically you don't need to await before returning and also don't need to make the function async, because it will return a promise anyway.

If you resolve the promise before returning, there will be one more microtask execution than if returning the promise directly:

isInRoleAsync: function (role, scope) {
  // ...

  return this.userIsInRoleAsync(userId, roles) // always returns Promise
}

does not affect anything by itself but might be measurable when requests / operations do in the millions haha

@StorytellerCZ
Copy link
Member Author

Yes, I agree with all the simplifications and improvements. The original code is pretty old.

@jankapunkt
Copy link
Member

@StorytellerCZ is this still active or superseded by release 4.0.4

@StorytellerCZ
Copy link
Member Author

Still, active. Have to find the time to check this again and get it merged, but I think that will be into the official package instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Add isInRole to JS API as well

3 participants