Including a field on an Editor form, but preventing updates to it on the backend

Including a field on an Editor form, but preventing updates to it on the backend

TooManyTablesTooManyTables Posts: 23Questions: 7Answers: 1
edited June 2017 in Free community support

I have a working Datatables editor instance, designed to allow selected users to edit certain fields of a set of data. There is a field (loanNumberBorrowed) I would like to include on the editor form (it is important that it's visible for reference during the editing process), but the requirement is that these users not be able to modify the value in this field in any way, shape or form.

I have already set the field type to readonly and used .disable(), but if I go into the browser console (E.g. Inspect element in Firefox) and remove the readonly and disabled classes, I can change the value in loanNumberBorrowed as I please, submit the update and it will end up in the database.

Is there some way to:

  • [Frontend] Not send through the value for the given field (but still display it on the form); or
  • [Backend] Ignore updates to this particular field entirely; or
  • [Backend] Add some sort of validation check that compares the value that has been sent through by the user to the value that is in the database for loanNumberBorrowed, and return an error if the two are not the same;
  • [Other] Something else I haven't thought of that neatly solves my problem.

Server-side PHP Code:

Editor::inst($db, 'Loans', 'loanID' )
        ->debug(true)
        ->field(
            Field::inst( 'Loans.loanID' ),
            Field::inst( 'Users.userID' ),
            Field::inst( 'Users.userFullName' ),
            Field::inst( 'Equipment.equipmentID' ),
            Field::inst( 'Equipment.equipmentName' ),
            Field::inst( 'Equipment.equipmentAssetNumber' ),
            Field::inst( 'Loans.loanNumberBorrowed'),
            Field::inst( 'Loans.loanNumberReturned'),
            Field::inst( 'Loans.loanDateDue' )
                ->validator( 'Validate::notEmpty' ),
            Field::inst( 'Loans.loanDateBorrowed' )
                ->getFormatter( 
                    function ( $val, $data, $opts ) {
                        return date( 'Y-m-d', strtotime( $val ) );
                    } 
                ),
            Field::inst( 'Loans.loanDateReturned' )
                ->getFormatter( 
                    function ( $val, $data, $opts ) {
                        if(!empty($val)) {
                            return date( 'Y-m-d', strtotime( $val ) );
                        } else {
                            return null;
                        }
                    } 
                ),
            Field::inst( 'Loans.loanStatus' ),
            Field::inst( 'Equipment.equipmentArea' ),
            Field::inst( 'Loans.loanLocation' ),
            Field::inst( 'Loans.loanComment' )
        )
    ->leftJoin( 'Users', 'Loans.loanedTo', '=', 'Users.userID' )
    ->leftJoin( 'Equipment', 'Loans.equipmentID', '=', 'Equipment.equipmentID' )
    ->where(function($q) use ($userID) {
                $q->where( 'Equipment.equipmentArea', '(SELECT unitID FROM IndependentUserRole WHERE unitType = ' . "'Area'" . ' AND userID = :userID)', 'IN', false)
                        ->or_where(function($r) use ($userID) {
                            $r->where('Equipment.equipmentArea', '(SELECT DISTINCT equipmentArea FROM Equipment WHERE (:userID2 IN 
                                    (SELECT userID FROM IndependentUserRole WHERE (unitType = ' . "'Department'" . '))))', 'IN', false);
                            $r->bind(':userID2', $userID);
                        });
                $q->bind(':userID', $userID); 
            }
        )
    ->process($_POST)
    ->json();

Front-end editor code:

var editor = new $.fn.dataTable.Editor( {
            ajax: {
                edit: {
                    url: equipPath + '/Controllers/UpdateLoan.php'
                }
            },
            table: '#area-loans-table',
            idSrc: 'Loans.loanID',
            fields: [ {
                    label: 'Loaned To:',
                    name: 'Users.userFullName',
                    type: "readonly"
                }, {
                    label: 'Equipment:',
                    name: 'Equipment.equipmentName',
                    type: "readonly"
                }, {
                    label: 'Borrowed:',
                    name: 'Loans.loanNumberBorrowed',
                    type: "readonly"
                }, {
                    label: 'Date Due:',
                    name: 'Loans.loanDateDue',
                    type: "date"
                    }
                }, {
                    label: 'Location:',
                    name: 'Loans.loanLocation',
                    type: 'textarea'
                }, {
                    label: 'Comment:',
                    name: 'Loans.loanComment',
                    type: 'textarea'

                }
            ]
        } );

This question has an accepted answers - jump to answer

Answers

  • tangerinetangerine Posts: 3,350Questions: 37Answers: 394
    edited June 2017

    Try type: "display" instead of "readonly". Note that it requires editor.display.js to be included.

    EDIT: I just took another look at this to refresh my memory, and although I was able to edit the "display" item in the console, it had no effect on the database.
    There may be better answers, but this appears to work for me.

  • allanallan Posts: 61,863Questions: 1Answers: 10,136 Site admin
    Answer ✓

    Option 2 is going to be the best way. You can add all the validation and confirmation you want on the client-side, but it will always be possible for someone to send an "attack" request with that parameter set.

    To do that, use:

     Field::inst( 'Loans.loanNumberBorrowed')->set( false )
    

    That will prevent the Loans.loanNumberBorrowed field from ever being updated by the Editor instance.

    Allan

  • TooManyTablesTooManyTables Posts: 23Questions: 7Answers: 1

    Thanks allan, that looks like it'll do the trick.

    And thanks too to you tangerine - I'd forgotten about type: display. That will come in handy.

This discussion has been closed.