Report invalid fields on the site. For example, field that displays email address or telephone number has wrong address/number. This module allows user to report that field as invalid. If registered user report field, it will be automatically marked as invalid, displaying text entered in configuration form. For anonymous users, email with confirmation link will be sent.
Project page:
https://www.drupal.org/sandbox/dkolarevic/2675342
Similar modules:
Flag (https://www.drupal.org/project/flag). Differences: With flag module user can report content on node level. With report_field module content can be reported on field level.
Installation and usage:
1. Ensure JavaScript is enabled.
2. Put "report_field" module folder in "sites/all/modules".
3. Go to "admin/modules" and enable "Report Field" module.
4. After enabling module configuration page will be available (admin/config/content/report_field).
5. First tab, FIELD LIST, displays all fields for each content type available on site. By clicking checkbox next to field name, report field will be available next to that field. Fill in 'Label' and 'Reported' textboxes and optionally check 'Message' field checkbox. 'Label' field defines text displayed next to checkbox rendered below the field. 'Reported' field defines text that is displayed after field is reported. Finally if checked 'Message' field will allow user to enter some comment when reporting invalid field.
6. Second tab, REPORTED FIELDS, lists all fields that are reported by users, both anonymous and registered.
Pareview.sh:
http://pareview.sh/pareview/httpgitdrupalorgsandboxdkolarevic2675342git
Git clone:
git clone --branch 7.x-1.x https://git.drupal.org/sandbox/dkolarevic/2675342.git report_field
Manual review of other projects:
https://www.drupal.org/node/2502503#comment-11085805
https://www.drupal.org/node/2596375#comment-11086103
https://www.drupal.org/node/2678646#comment-11086541
https://www.drupal.org/node/2693535#comment-11085989
https://www.drupal.org/node/2706799#comment-11090939
https://www.drupal.org/node/2709679#comment-11105995
Comments
Comment #2
dkolarevic commentedComment #3
nimek commentedManual code check result
1.1 Ensure your application contains a repository and project page link.
OK
1.2 Ensure your project is not a duplication.
It is not.
2.1 Ensure the repository actually contains code.
OK
3.1 Ensure the project does not contain any security issues.
hmm I am not a security expert but you could consider two things
- use db_select instead of db_query line 72 $query = 'SELECT COUNT(*) FROM {report_field_invalid_fields}';
- use checkPlain() for $_POST vars esp line 104 and 105 where user can submit content
4.1 Ensure the repository does not contain a ‘LICENSE.txt’ file.
OK
4.2 Ensure the repository does not contain any 3rd party (non-GPL) code.
OK
5 and 6 are ok to me
7 API check
line 144 you should use drupal_goto instead of header("location:index.php");
line 150 function report_field_form($form, &$form_state) { you should not build table manuallly use theme table function
line 393 you should use t() for text strings
You should not add html tags to variables. You should use apropirate theme function instead.
Comment #4
braindrift commentedHi dkolarevic,
the constant
REPORT_FIELD_SECRET_HASHis not secret anymore, when you define it in your (open source) module. You shoud generate secret tokens by usingdrupal_get_token(). (This is an application blocker for me).The wrapper in your
report_fiel.jsis missing one parameter. You define the anonymous function with three parameters, but you are calling it with four arguments. So the parameterdocumentgets the value ofthis(the window object).It works but it may be confusing.
You should at least print the content of your README in hook_help().
You should consider to move your admin setting forms / callbacks to a separate
report_field.admin.incfile.In
report_field_submit_form():468you are checking for the not existence of$form['#attributes']['class']and then you set$form['#attributes'] = array('class' => 'field-flag-submit-form');. In the case wehn only the 'class' is not set but other attributes, you would remove all the other attributes. Since you do it in your own form, its OK but if you would do it in e.g.hook_form_alter()I would have counted it as an application blocker. (The same inreport_field_error_checkbox_form():422)The menu item
$items['callback']that you define in yourhook_menu()is very general. You should make it more specific to your module to avoid conflicts with other modules. The same for$items['mail_confirm'].Just a note: Why are you using nested if's instead combining their conditions in one if in
report_field_preprocess_field()?Best regards
Comment #5
braindrift commentedComment #6
xaiwant commented@dkolarevic just a casual check which could be helpful in UI perspective.
Spelling -> Typo Error
README.txt
Typo: In word 'Simular' (at line 11)report_field.module
Unused Variable
report_field.module
Unused parameter 'logged'. The value of the parameter is not used anywhere. (at line 433)Don't you have hook_permission inside your module. ?
Don't we need it.
Comment #7
dkolarevic commentedComment #8
dkolarevic commentedHi guys,
changes made:
@nimek
- db_query removed
- checkPlain() added for user submitted content
- drupal_goto() used insted header()
- table built using theme table
- used t() for translatable strings
- typos corrected
@braindrift
- REPORT_FIELD_SECRET_HASH generated by drupal_get_token()
- report_field.js modified
- hook_help() modified
- setting forms/callbacks moved to report_field.admin.inc
- menu items renamed
- combined nested ifs
@xaiwant
- typos corrected
- added hook_permission()
Comment #9
nimek commented@dkolarevic
Well done :). Nothing to add from my side.
Comment #10
josebc commentedHello
Here are few notes about the module
report_field.module
missing t() on form labels in report_field_submit_form()
cache_clear_all() might cause performance issues in report_field_preprocess_field() maybe another way?
report_field.js
$(document).ready() please consider drupal behaviors , here is a useful link https://www.lullabot.com/articles/understanding-javascript-behaviors-in-...
Comment #11
dkolarevic commentedComment #12
dkolarevic commentedHi josebc,
thanks for review. I made changes based on your suggestions.
Comment #13
feyp commentedAutomated Review
The automated review by pareview.sh looks good. No automated test cases were found, but this is not a requirement.
Manual Review
<IMG SRC=/ onerror="alert(String.fromCharCode(88,83,83))"></img>as value of the Reported field.XSS.administer site configurationis already defined by thesystemmodule of Drupal core. Since there is only one permission name space, as a best practice put your module name into every permission name you define. A common name for a permission like this would beadminister report fields. Currently, your implementation ofhook_permission()results in the permission being listed under your module name instead of the system module name, which might confuse users. It might make them inadvertently think that the permission only applies to your module. So this is a security issue. Either change the permission name (recommended) or, if you really want to do that, just remove yourhook_permission()implementation and reuse the permission defined by the coresystemmodule (discouraged).theme_table(), but you might want to do more validation. E.g. field name and node title are passed on to the email as is and I can set any email address I want. I leave the rest to your imagination. To try it yourself, you could e.g. use curl like this:curl --data "passedEmail=Hi there, how are you?&passedMessage=Okay, this is just some text.&passedFieldName=The field name is not validated.&passedContentType=I can add anything I like here.&passedNodeId=0&passedNodeTitle=Reviewing the field_report module" http://example.org/report_field_callback. To fix this, perform more validation on the fields and implement Drupal AJAX API for your form (see below). You could then get rid of the hidden fields and rely on form state to pass these values around (recommended). Or calculate an hmac on the hidden fields and validate that (see below for a Drupal API function to do that, but discouraged).report_field_page_callback_function(): You're usingopenssl_encrypt()to generate a hash value to send as part of a one-time url. Depending on what you intended to do here, this might be a security issue or not. If you intended to securely encrypt the data, it will not work. E.g. your initialization vector should be random (and unique), but you are using the same string every time. Also, strings returned byopenssl_encrypt()are not neccessarily safe to use in URLs without proper treatment. Encryption can be difficult to get right. So why not instead rely on the API of Drupal core, which is supported by the Drupal security team? E.g. one option is to use drupal_hmac_base64() to get a url safe hmac value.drupal_add_js()ordrupal_add_css(), but use #attached instead) or specify thestylesheetsandscriptsoptions in your .info file (see Writing module .info files (Drupal 7.x)).FieldsorUser interface.report_field_form(): Please prefix all variable names (I refer to variable names used withvariable_get()andvariable_set()here, not to regular variables) with your module name to avoid clashes with variable names used by other modules. Also note, that it is common practice to use underscores instead of dashes as a separator in variable names.report_field_form_reading_db(): Why are you usingsystem_settings_form()here? No need to save all the form values usingvariable_set()for this form, since you already store them in your own table. For performance reasons, please don't do that. In Drupal 7, every variable present in the system will be loaded on each page request, so the less variables you set, the better.report_field_preprocess_field(): You're including the admin.inc file here and load your settings form. Then you loop through the form to get the settings. Please don't do that for performance reasons. Instead, first check, if$vars['element']['#entity_type']equalsnode, since you only support fields attached to nodes currently. Next, get the content type from$vars['element']['#bundle']and the field name from$vars['element']['#field_name']and prepare the name of your variable. Then usevariable_get()to get the settings for that field and act on them accordingly.report_field_page_callback_function(): Since this page callback is unrelated to your admin pages, consider moving it into your module file for clarity.report_field_form(): If a system has a lot of fields attached to nodes, a lot of variables might be added by your module. Since Drupal 7 will load every variable for each page request, fewer variables are better. Consider using a separate table for your settings for performance reasons.report_field_form(): Since the settings are stored by node type, consider removing unused variables/settings upon deletion of a node type (e.g. by implementing hook_node_type_delete()).report_field_form(): Consider adding some explanation text to the form that describes, what the different fields (Label, Reported and Message field?) do or add it to your documentation (README/project page). It might not be obvious for users not familiar with your module._report_field_form_validate(): A better approach would be to name this functionreport_field_form_reading_db_validate, so that Form API will call it automatically for your form.hook_menu(): To give admins more fine grained control over permissions, consider adding a permission to use your module and use that instead ofaccess content.classattribute is an array containing one value per class. Note that there are more places in your module, where this should be changed.report_field_render_form(): Instead of callingdrupal_render()twice, you might want to create a render array containing both forms and calldrupal_render()only once on that render array.report_field_render_form(): Is there a specific reason why you are using two different forms? Why not just combine the two forms into one? If you did so, you could use the #states option of Form API to hide a field initially and only show it, if the checkbox has been checked by the user instead of writing your own JS for that.report_field_submit_form(): Instead of using your own JS file to submit the form via Ajax using jQuery, why don't you use the Drupal AJAX API? See Ajax Forms in Drupal 7 and the AJAX example module for more information on how to implement it for your form. If implemented properly, you would automatically gain support for people having JS disabled to mention just one benefit of using Drupal Core APIs over custom solutions.report_field_preprocess_field(): The DocBlock should readImplements hook_preprocess_HOOK() for field.tpl.php.report_field_preprocess_field(): Instead of adding the email address of the user as a JS setting here, why don't you check in the form building function, if the user is logged in and prefill the email field there by adding it as a default value? From your JS, it looks like you don't want the user to change the email address, since you set it to readonly. Note, that a malicious user could still change her email address, since you rely on the data in the form to be accurate. For a more secure approach, why not hide the email field for logged in users entirely by setting#access => FALSEfor the email form element in the form building function and using$user->mailfor logged in users when you insert the values into the database?report_field_preprocess_field(): If you want to keep the JS setting, as a best practice, add your setting in a bucket containing your module name to avoid clashes with other modules and use#attachedlike this:To get your setting in your JS file, use
Drupal.settings.report_field.currentUserEmail.report_field_preprocess_field(): There is a comment regarding support for field collection fields. Why don't you add a setting for fields referecing field collections, so that admins can enable this in your settings form?report_field_mail_confirm_function(): A user might pass an invalid hash, which is not present in the database (e.g. if another user already confirmed her report for the same field or the admin deleted a pending report). You might want to check for that case.report_field_mail_confirm_function(): Consider passing the hash as a parameter to the menu callback using thepage argumentsoption ofhook_menu()instead of relying on$_GET.report_field_mail_confirm_function(): If you want to redirect to the front page, usedrupal_goto('<front>');.report_field_mail_confirm_function(): A confirmation message to the user might be a good idea, so that the user knows, that the field was successfully reported.report_field_mail(): Instead of using$base_urlto construct the URL, consider using url() with theabsoluteandqueryoptions.attachproperty of your behaviour). You need to pass that as the second parameter to some of your jQuery calls to make sure, that you only act on stuff present in the context parameter. Also, you should make sure to process every element you target only once, e.g. by using jQuery Once (bundled with Drupal Core), since a behaviour might be called multiple times for the same page.@paramand@returnwhere missing).The starred items (*) are fairly big issues and warrant going back to Needs Work. Items marked with a plus sign (+) are important and should be addressed before a stable project release. The rest of the comments in the code walkthrough are recommendations.
Revision reviewed: 74378d3
If added, please don't remove the security tag, we keep that for statistics and to show examples of security problems.
This review uses the Project Application Review Template.
Comment #14
dkolarevic commentedHi FeyP,
thanks for the detailed analysis of the project. I made changes based on items marked with (*) and (+) from your review. Items 12, 13, 19, 21, 22, 23, 24, 25, 26, 30 and 33 have been changed on the fly. I'll also actively work on the rest of the items.
Comment #15
dkolarevic commentedComment #16
feyp commentedHi dkolarevic,
thank you for your work on this, very good job! The code looks a lot better now.
I did not do a full review this time, but instead looked at the commits you made
since my last review.
As far as I can see, the following items have been resolved:
1., 2., 3., 4., 5., 6., 7., 9., 10., 11., 12., 13., 17., 20., 21., 22., 23., 24., 25., 26., 30., 33.
For the record, the following items are still open. While not required to pass
the review, I really appreciate your intention to work on these as well:
8., 14., 15., 16., 18., 19., 27., 28., 29., 31., 32., 34., 35., 36.
Regarding item 19., it is now on line 66 of the module file.
Also, there are a few new observations, which you might want to consider working on:
report_field_form(): You're attaching a CSS file to the form, but you have since removed the file from the repository. It's nice that you used#attachedinstead ofdrupal_add_css(), though.report_field_error_form(): Please uset()for the value of your submit button.report_field_form(): No need to explicitly specify the validation handler, since it should be called automatically by Form API based on the function name. Doesn't hurt, though ;).None of the new observations are blockers, though the first two items should be
fixed before a stable project release.
Bottom line: I verify that all blocker issues and especially the security issues
identified in my original review have been fixed. In my view,
this module is RTBC! :)
Revision reviewed: 7fc0b61
Comment #17
dkolarevic commentedComment #18
dkolarevic commentedComment #19
damienmckennaThanks for your contribution, Dragan!
I updated your account so you can promote this to a full project and also create new projects as either a sandbox or a "full" project.
Here are some recommended readings to help with excellent maintainership:
You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and stay involved!
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.
Thanks to the dedicated reviewer(s) as well.