Использование deepstream.io для голосования в реальном времени

Я сделал прототип системы голосования в реальном времени, используя deepstream.io и rethinkdb в качестве хранилища постоянства. Пока что это работает, и несколько браузеров могут синхронизироваться, получая последнее количество подсчетов голосов (см. снимок экрана ниже), однако одна вещь, которая мне не нравится, это то, что vote count увеличивается в браузере, который отправляется в deepstream.io удаленный сервер.

код JS, встроенный в браузер клиента:

/**
        * Login to deepstream as Frank
        */
        var ds = deepstream( 'localhost:6020' ).login({ username: 'Frank'});
        var name = 'upvote';
        var upVotes;
        var voteText = $('.streaming-prices .vote');
        var record = ds.record.getRecord(name);
        $('#upvote_btn').click(function() {
            // on button click, increment the vote counts
            // set the record stored in the rethinkdb storage
            record.set({
                count: ++upVotes
            });
        });

        record.subscribe('count', function(newVal) {
            console.info('count updated, newVal: ', newVal);
            upVotes = newVal;
            voteText.text(newVal);
        });

код server.js:

var PermissionHandler = require( './permission-handler' );

var DeepstreamServer = require( 'deepstream.io' ),
    RdbC = require( 'deepstream.io-storage-rethinkdb' ),
    server = new DeepstreamServer();

server.set('host', '0.0.0.0');
server.set('port', 6020);
server.set( 'tcpHost', '0.0.0.0' );
server.set( 'tcpPort', '6022' );
server.set( 'permissionHandler', new PermissionHandler() );

server.set( 'storage', new RdbC({
    port: 28015,
    host: '127.0.0.1',
    splitChar: '/',
    database: 'votings',
    defaultTable: 'question'
}));

server.start();

Таким образом, вы можете видеть, что код js в клиенте напрямую увеличивает количество голосов и обновляет запись, которая должна быть отправлена ​​​​на сервер deepstream.io для обновления базы данных. Мне не нравится эта часть, потому что я не хочу, чтобы пользователь мог испортить общее количество голосов. Вместо этого я хотел бы, чтобы клиент просто отправлял что-то вроде +1 на сервер и позволял серверу обновлять общее количество для сохранения. Я не уверен, возможно ли это, может кто-нибудь пролить свет? Я ценю это

Снимок экрана для голосования и отображения подсчета голосов


person TonyGW    schedule 10.03.2016    source источник


Ответы (1)


Хорошо, что предоставление клиентам возможности манипулировать голосами может не сработать!

Я бы сделал это с помощью rpc, чтобы в браузере можно было разрешить доверенный провайдер увеличивает запись от имени пользователя.

Три вещи, которые вам нужно сделать, это:

  1. запросить rpc через браузер
  2. ответить на него от поставщика rpc (доверенный клиент, который может ответить на rpc)
  3. добавить разрешения для отклонения любых попыток изменить запись от не-провайдеров

Код будет выглядеть примерно так:

JS-код в браузере

/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6020' ).login( { username: 'Frank'} );

var voteText = $('.streaming-prices .vote');
var name = 'vote';
var record = ds.record.getRecord( name );

$('#upvote_btn').click(function() {
    // on button click, increment the vote counts
    // set the record stored in the rethinkdb storage
    ds.rpc.make( 'upvote', {}, function( error, response ){
        //notify user when upvote succesfull
    });
});

record.subscribe('count', function( newVal ) {
    console.info( 'count updated, newVal: ', newVal);
    voteText.text(newVal);
});

Поставщик RPC, который обрабатывает голоса "за"

/**
* Login to deepstream as Frank
*/
var ds = deepstream( 'localhost:6021' ).login( { username: 'upvote-provider' } );

var name = 'vote';
var record = ds.record.getRecord( name );

ds.rpc.provide( 'upvote', function( data, response ){
    record.set( 'count', record.get( 'count' ) + 1 );
    response.send();
});

Сервер также должен иметь разрешения, позволяющие изменять голоса только поставщику голосов.

canPerformAction: function( username, message, callback ) {
    /**
     * If the user is a provider, it has all permissions
     */
    if( username === 'upvote-provider' ) {
        callback( null, true );
    }
    /**
     * Otherwise the client request is valid unless it's trying to change the score
     */
     else {
        var messageObj = Deepstream.readMessage( message );
        var isAllowed = messageObj.name !== 'vote' || messageObj.isRead;
        var errorMessage = isAllowed ? null : 'Can\'t change votes via client, use \'upvote\' rpc instead';
        callback( errorMessage, isAllowed );
    }
}
person yasserf    schedule 10.03.2016
comment
Спасибо, попробую предложенный подход, когда вернусь домой, ценю это. - person TonyGW; 10.03.2016