Description
This module provides an additional authentication step during the login process. It very similar to how most banks have you enter your username, then take you to a page where they either show you a picture, or ask you a question. The module allows admins to create multiple questions and set how many questions they want the user to have answers for. During the registration process, users are shown a fieldset of questions where they can select what question they want to answer and allows them to enter their answer.
The module also allows users who are logged in to view and change their answers via a user page tab.
The only similar project that i found is Riddler (http://drupal.org/project/riddler).
Riddler is a sub module of Captcha and therefor requires it. This has no external dependencies, and only works on the log in / register forms. In addition, Riddler uses admin configured questions and answer pairs. Security questions lets the admin come up with questions, and then lets the user submit their own answer to the question.
Project Page Link
http://drupal.org/sandbox/chertzog/1414168
Git Repository
git clone --branch 7.x-1.x chertzog@git.drupal.org:sandbox/chertzog/1414168.git
http://git.drupal.org/sandbox/chertzog/1414168.git
Drupal version
Currently this is for Drupal 7. If requested, will probably back port.
Comments
Comment #1
chertzogAdding PAReview Bonus Tag
Comment #1.0
chertzogAdding reviews of other project links
Comment #1.1
chertzogAdded git link instead of just having the git clone command
Comment #2
chertzogHere is a link to the PAReview:
http://ventral.org/pareview/httpgitdrupalorgsandboxchertzog1414168git
Review of the 7.x-1.x branch:
This automated report was generated with PAReview.sh, your friendly project application review script. You can also use the online version to check your project. Get a review bonus and we will come back to your application sooner.
Source: http://ventral.org/pareview - PAReview.sh online service
Comment #3
klausiRemoving review bonus tag, you did not do manual reviews as required in #1410826: [META] Review bonus.
Comment #4
chertzogSetting to major. 3 weeks now.
Comment #5
rudiedirkx commented1. You're defining a very generic constant:
Prefix your constants with your module name.
2. When you go to
admin/config/people/security_questions, you see the settings (just 1 field). More sensible IMO would be to have the questions tab be the default:admin/config/people/security_questions/questions.3. In hook_menu:
The
%can be%userand then you can remove this nasty piece of code fromsecurity_questions_user_edit_form:You can then change the function definition to
security_questions_user_edit_form($form, &$form_state, $user)if you add apage argumentselement to the menu item inhook_menu. See http://api.drupal.org/api/drupal/modules%21system%21system.api.php/funct...4. Overriding
$items['user']['page callback']inhook_menu_alteris very brutal andsecurity_questions_user_pageis a mess. If you're logged in, it logs you in... Weird...Check out
user_page()anduser_view_page()(inmodules/user/user.pages.inc) to see what Drupal does withuser....
Now it's failing for me completely. No idea what happened, but Chrome returns a
net::ERR_EMPTY_RESPONSEerror for me when the module is enabled. Authenticated and anonymous alike. When I disable the module with drush, everything works again.Comment #6
rudiedirkx commentedObviously this is not gonna work:
You're passing
$formasNULL.$formdoesn't exist.$form_statedoesn't exist.What is it you're trying to do here?
Comment #7
rudiedirkx commentedIf I comment out the
hook_menu_alter, the crashes stop (but the module doesn't do its login thing).There's something very wrong. I'm pretty sure it's in
security_questions_login. Maybe callingdrupal_bootstrap(DRUPAL_BOOTSTRAP_FULL)... I'm not sure.Did you take it from Drupal 7's IP Login? Do you know what it does? Don't mindelessly copy and paste.
I give up. It's up to you to debug and fix. Drupal doesn't save any error messages, so it happens before watchdog is ready, I think. All I get is:
It would be best if you could fit this module into existing user login. You can form alter the login form and remove elements (step 1: remove password) or make them
#type => hidden(step 2: hide username). You can add validation to check the security question. I don't think overriding this much and callingdrupal_bootstrapis necessary.Comment #8
rudiedirkx commentedIt's well possible without overriding so much and calling bootstrap functions etc.
This might help:
Don't copy and paste it. Understand it and use it.
Comment #9
chertzogThanks for this. I will start reworking the module tonight. I have thought of some other things i want to implement, so i will have some stuff to work on. Like I said, this was my first module from scratch. Its a learning experience. Ive been using drupal for a couple years now, and finally have something worth contributing back.
Comment #10
chertzog@rudiedirkx Thanks for the help. I have taken the code above, reworked the module, and have committed it.
My biggest problem was not being sure how the $form_state variable works and not being sure of the user_page overriding but after reviewing the code above i think ive got it down.
Comment #11
chrisroane commentedMANUAL REVIEW
--------------
1. .module Line 233 and others: Include the $i variable in the t() call using a placemarker.
2. .module Line 218: You will want to send the question through these functions t(check_plain()).
3. .module Line 298: Send the question also through t(). Make sure all text that is displayed goes though this function.
AUTO REVIEW
------------
1. Coder returned quite a few minor errors. Please fix these.
2. PAReview online tool didn't return any results.
Comment #12
chrisroane commentedChanged status to needs work.
Comment #13
chertzogI have run the module through coder, and fixed all of the issues. I have also replaced the table html with the appropriate theme functions.
Comment #14
chertzogI have added a number of new functions that allow for when users have not yet answered questions (if the module is added after users have registered). I have also run the module through coder and PAReview, both come up clean.
As for sending the question through check_plain, doing so double encodes special characters like apostrophes because they are being used as options, which means they are already passed through check_plain during form_select_options().
Comment #15
rudiedirkx commentedCode looks good!
1.
You forgot a few
check_plains. I won't spoil it. What I usually do is enter something with<textarea>in the name (question and answer both) and then check everywhere it's used.2.
If I don't have a security question set, I can log in without answering anything. Is that intended?
3.
If I have 1 of 2 required of 5 available questions answerered, I can't answer my second. Is that intended?
4.
On admin/config/people/security_questions you put the entire table inside a #markup element. Nothing wrong with that, but what if I want to write a module to add a column to that table? E.g. with the number of users that have that question answered. You should allow other modules to do that. Two methods I know:
$tablebefore passing it to theme_table5.
Why do you use drupal_write_record and not db_insert?
6.
It's always good to put (submit) buttons in an "actions" form element.
Like so:
7.
Just FYI. The result of a db_query is an Iterable, which means you can read its results with foreach and no
->fetchObject()is required.Just curious:
What does this do?
Comment #16
rudiedirkx commented8.
Oops:
Whenever you type something in English, it must be translated. Sometimes indirectly (menu item titles) and sometimes directly (this, form element titles, help texts etc).
Comment #17
chertzog1. I think I've got them all.
2. I changed it so that if someone doesn't have any questions answered, the form to answer the questions is added to the login process.
3. Not sure what you are asking here, but whenever someone either registered or logged in, they had to answer the required number of questions.
4. I have passed the table through drupal_alter.
5. Changed to db_insert.
6. Buttons have been added to the actions form element.
7. Noted.
8. Fixed.
On the curious note, removed it, as it is no longer needed.
Coder and PAReview both come back clean.
I believe that its ready.
Comment #18
rudiedirkx commented3. I meant that if somehow I have 1 of 2 required questions answered (somehow), I can't answer the 2nd required question, so I'll only have 1 even though 2 are actually required. (The "somehow" is important: a user should never have too few qustions answered.)
I'll check out the rest tonight.
Comment #19
chertzogOk. i will look into adding something for this.
Comment #20
chertzogI have added functions to handle the situation in comment 18. Now if user only has 1 of 3 answered, during log in they are asked to answer their one question, as well as select and answer two more questions, so that they have enough questions answered.
I also added a bunch of inline documentation, to keep thing organized.
Coder and PAReview again, both come up clean.
Comment #21
rudiedirkx commented1.
This is weird (and wrong):
If a user has no questions answered, the page is blank (there's no return value, so Drupal renders nothing).
I see from the diff (
bff6be5..71a4d87) you've explicitly removed this:Why? That was good, wasn't it?
Comment #22
rudiedirkx commented2.
No underscore needed (better if you don't):
Comment #23
rudiedirkx commented3.
This is dangerous:
You're counting on the output column to be called "count(security_question_id)" while you call it "COUNT(security_question_id)" in the query. To fetch a single column value, you can use
db_query()->fetchField().See this comment on the Drupal DBAL page.
PS. Happens in
security_questions_user_login_questions_validatetoo. And insecurity_questions_user_login_questions_submittoo.Comment #24
rudiedirkx commented4.
From element somewhere in
security_questions_form_user_login_alter(I'm reading the diff):Translate form element labels. Think about every English literal you type: where will it be translated? Think about every variable you 'print': where will it be escaped/encoded?
Comment #25
rudiedirkx commented5.
Let's not translate a full HTML table =)
On a side note: don't ever put variables inside t() directly:
t($something). Reason: Drupal translation server reads those literals from code to be translated by users. Every t() call starts witht('ort(".Related:
You're translating a variable, which is 'bad' AND it's a user string. You sure you want to translate those? (It might. If you force admins to insert questions in English and users can read them in another language, it might be necessary.)
6.
What happens if the user doesn't exist? "Notice: Trying to get property of non-object in security_questions_user_login_validate_name()" You don't need
$questionbefore checking the user. You can call it after theif.7.
You might want to punt this in a helper function:
The
trimanddrupal_strtolowerI mean. The DRYer, the better.Comment #26
patrickd commented@rudiedirkx
please don't put each issue you find into a new comment, this makes the issue long and confusing
Comment #27
chertzogI have addressed all of the issues, and did a MAJOR rewrite of the way forms are handled in the module. It's now just one form that gets modified depending on the context.
I'm pretty sure i have accounted for any and all of the possibilities where a user doesn't exist, or doesn't have the required number of questions answered, etc.
Again, both Coder and PAReview come back clean.
Comment #27.0
chertzogAdded Demo site
Comment #28
chertzogAdding review bonus. Here are some of the reviews.
http://drupal.org/node/1485382#comment-5741568
http://drupal.org/node/1483744#comment-5742194
http://drupal.org/node/1487522#comment-5745116
Comment #29
rudiedirkx commented1.
There's something deeply wrong again... The site keeps crashing if the module is enabled. I'm thinking it has to do with the by reference arguments. Do you know what a
&$vardoes when it's not in a function argument?Specifically: you're calling
drupal_retrieve_form:With
&vars. Why? If you want form_state to be (able to be) altered, you don't have to change the input, only the function argument (indrupal_retrieve_form, which you can't change).Removing the & in three locations fixes the problem. Maybe these pages help.
(You might not be feeling this, because I'm running PHP 5.3 on Linux and you're not?)
2.
This feels a little strange to me:
This allows translated strings to contain HTML, but not untranslated (English?) strings. More sensible IMO would be the other way around: translate first and then html encode. But it's up to you obviously. It's not wrong.
3.
Inside
security_questions_user_insert, you might want to check if the answers exist in$edit:$edit['security_question_id_' . $i]. You don't know where a user insert is called or who might've altered the user form.The last two aren't really bugs. The first one is.
Comment #30
patrickd commentedregarding
t(check_plain($result->security_question))it is wrong in fact as t() already checkplain's all input of the first parameter.
Comment #31
chertzogIve addressed the issues and committed the code. As for php version, I have been developing locally on my macbook with MAMP pro with php 5.3.6.
I wasnt seeing any issues.
Comment #32
chertzoghttp://drupal.org/node/1294332#comment-5752282
http://drupal.org/node/1435294#comment-5746132
http://drupal.org/node/1488328#comment-5752138
Comment #33
chertzogAdded Review Bonus, for review links in #32.
Comment #34
ceardach commentedNice reviews you gave to those other people!
Nice module. This is definitely something needed and will probably be well used by the community. This was quite a lot to tackle, and I'm impressed with how far you've dived in.
You have shown you have done your due diligence to research existing modules, and it is great that you are explaining this on the project page. I think that there can be an argument made to help improve the riddler project rather than make a new module, but an argument can also be made that it is perfectly valid to have something similar but different. I also don't believe this should be a blocker for being a contributor because what we're really trying to figure out here is if you understand the Drupal community and the standards we all try to follow. Clearly, you are following the community standards by having done prior research on other modules.
We shouldn't let design decisions and bugs be a blocker for contributor approval. Most certainly, understanding how the translation system works is really important to grasp, but that is a Drupal-specific thing. Programming-specific critiques (hmm, this would silently fail) shouldn't be blockers. I think it is great that you have been working so hard to reflect upon these critiques and improve your work. You'll definitely get a lot of these critiques in your project issue queues!
Good README.
I agree with rudiedirkx that you really should be using
%userin your hook_menu() call instead of just%and then exploding the path and extracting the UID. Otherwise, you get the whole$userobject available to you insecurity_questions_list_user()which is awesome. You'll love it. Not a blocker, though.Love your liberal use of comments.
I saw a couple bugs, but not blockers. This is a big thing and will need a bunch of debugging. You won't want to make an official release of this until it is completely debugged. Hopefully more eyes will get involved and help you out with it!
So, I think chertzog is doing a great job and has demonstrated he is a valuable asset to the Drupal contributor community. Let's get you on board :)
Comment #35
mlncn commentedHi chertzdog, you are doing a great job, and especially thank you for doing other reviews, and you'll definitely be brought on board but i'd like to see the module a little more polished. Leaving at RTBC because i think you should get the ability to promote projects to full, but it doesn't seem urgent as this one isn't ready yet -- at least i get two functionally-major bugs when trying out the 7.x-1.x branch:
I'm thinking there might have been some regressions while doing fixes, anyhow, your style is great and looking forward to it being ready for release!
Comment #36
chertzogThanks for the comments. This has been a great learning opportunity for me. So much so that i have actually started helping out with "Novice" issues. I have had a number of patches now committed to core, as well as helping out with patches on a number of other modules.
@ceardach I have updated hook_menu, and changed the permissions around a little. The comments were almost more for my use than for other peoples. I needed to document what is was doing, and why so i could keep things straight in my own head.
What other bugs did you see? I want to follow best practices as much as I can.
@mlncn There is a permission to bypass the security question challenge. So if you just download the module, enable it create some questions, and log out, and you are the administrator, you automatically have the "Bypass security questions" permission, and will just be presented with the normal log in form. Create a new account and test with that account, or remove the bypass permission from the administrator role.
What else should be done to "polish" this module? I have a list of future development ideas for later, but as of now, the module is completely functional as is.
I have also updated my project page and added screenshots.
Comment #37
klausiThanks for your contribution, chertzog! Welcome to the community of project contributors on drupal.org.
I've granted you the git vetted user role which will let you promote this to a full project and also create new projects as either sandbox or "full" projects depending on which you feel is best.
Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.
As you continue to work on your module, keep in mind: Commit messages - providing history and credit and Release naming conventions.
Thanks to the dedicated reviewer(s) as well.
Comment #38
chertzogThanks @klausi, this has definitely been a learning experience, and i plan on continuing to help review applications.
Comment #39
rudiedirkx commentedCongratz @chertzog! I knew it, ofcourse. Let's fill that issue queue wil cool feature requests =)
Comment #40
chertzogAlready had a bug report (fixed - needed some more error checking) and a feature request (also -fixed - user supplied questions). Though i have been struggling to try and make it work with the login block. I am open for any ideas...
Comment #41.0
(not verified) commentedremoved demo site, and comment links