-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve security for queue settings #233
Conversation
This pull request is automatically deployed with Now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, can you add a changelog entry?
Thinking about how you chose to exclude the queue props, I think it'd be better to exclude it from the default Sequelize scope and then only explicitly include it for admins/course staff. That'll give us a sane default for whenever we have to read a queue out of the DB. |
How would this work when we need the |
By this I mean we'd only exclude the private config (admission control) by default; everything else would still be in there. Scopes apply to queries of whole collections too, so nothing would change for the "get 1" vs "get N" cases. |
Regarding my "get N" question, my confusion was how we'd inject the private config for only the correct queues with one single query. Although I realize now that the queue home page doesn't need that kind of information anyways so it's not particularly important in the "Get all open queues" endpoint The main thing I'm confused about is how we're supposed to apply the correct "admin" scope when making the queue query without already having queried the queue to see if the user is on course staff, which determines whether they're allowed to see the config or not. Is there another way to determine if a user is on course staff without querying the queue itself? Something that I was considering to get around this while still implementing the scoping method is to have a separate "settings" endpoint that we'd only query in the settings page that will contain all that private information. |
Ah, I see what you're getting at now. Yeah, I would say for a list, it's fine if we just unconditionally omit them for now. Regarding checking for course staff, that would indeed be not ideal, but DB queries are also super cheap - most requests are already doing several. I do like the idea of a settings endpoint - if we start adding more settings in the future, that'd be nice to only ever deliver them on the settings page. When I was first doing this, I actually thought about having a separate table for these sorts of settings, but ultimately decided that a 1-1 relationship like that felt weird. We could revisit that too. |
Sequelize v5 fixes an issue with scopes not properly merging attribute excludes when multiple scopes are in use. See sequelize/sequelize#9087
return queue | ||
}) | ||
const queuesResult = await Queue.scope( | ||
'defaultScope', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is specifying defaultScope
explicitly required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need defaultScope
so that the private attribute filtering gets applied, otherwise only questionCount
will be used.
queueId, | ||
askedById: askerId, | ||
}) | ||
const question = await Question.create( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify why there changes were necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We expect that the object returned from Question.build
contains the appropriate askedBy
model through association, but it doesn't do that anymore.
The docs suggest to use .create
to create with association.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking through the docs some more, it's possible to use .build()
to achieve the same effect, but since we're not doing anything special between .build()
and .save()
, I don't see a reason to use it over .create()
@@ -113,13 +113,25 @@ router.get( | |||
}, | |||
required: false, | |||
include: [User], | |||
attributes: ['startTime', 'endTime'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify why the changes in this file were necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't find the exact change from v5, but without attributes
, sequelize
will throw an error stating include.attributes.map is not a function
.
src/models/index.js
Outdated
@@ -38,8 +38,6 @@ module.exports.initSequelize = sequelize => { | |||
} | |||
|
|||
const sequelizeConfig = { | |||
// See http://docs.sequelizejs.com/manual/querying.html#operators-security |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify why this change was necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For security purposes, string-based operators ($or
, $and
, etc) have been deprecated and sequelize
will now show deprecation warnings, even though we're not using string operators anywhere.
I was reading through sequelize/sequelize#8417 and it seems like the general consensus was to set operatorsAliases
to false
to completely disable string-based operators, but that will also trigger a warning as seen here.
Removing the option altogether has the same effect as setting it to false
, but without the warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
The queue settings page can now only be viewed by course staff or queue admins, and will 403 otherwise.
I also noticed
admissionControlUrl
is not being filtered out on queue GET requests - is this something we want to hide from regular users?