High or low exposure to risk
No edit summary
No edit summary
(2 intermediate revisions by the same user not shown)
Line 38: Line 38:


Given this model:
Given this model:
 
[[File:01.png|none|thumb|423x423px]]
 


In the simplified model above I want one user interface to browse videos – but under no circumstances should this ability expose anyway to change the Genre or check who Viewed the film in the past.
In the simplified model above I want one user interface to browse videos – but under no circumstances should this ability expose anyway to change the Genre or check who Viewed the film in the past.


Declaratively I do this viewmodel and test it out in the prototyper:
Declaratively I do this viewmodel and test it out in the prototyper:
[[File:02.png|none|thumb|603x603px]]


In angualarJS I need to do a few things to use this viewmodel:
In angualarJS I need to do a few things to use this viewmodel:
Line 49: Line 49:
1. I define a controller
1. I define a controller


<html>
<pre class="code"><span style="background: white; color: black;">phonecatControllers.controller(</span><span style="background: white; color: #a31515;">'BrowseVideos'</span><span style="background: white; color: black;">, [</span><span style="background: white; color: #a31515;">'$scope'</span><span style="background: white; color: black;">,
<pre class="code"><span style="background: white; color: black;">phonecatControllers.controller(</span><span style="background: white; color: #a31515;">'BrowseVideos'</span><span style="background: white; color: black;">, [</span><span style="background: white; color: #a31515;">'$scope'</span><span style="background: white; color: black;">,
   </span><span style="background: white; color: blue;">function </span><span style="background: white; color: black;">($scope) {
   </span><span style="background: white; color: blue;">function </span><span style="background: white; color: black;">($scope) {
Line 58: Line 59:
     });
     });
   }]);
   }]);
</span></pre>
</span></pre> </html>


I here make use of the StreamingViewModelClient that automatically will handle all the messaging to the StreamingViewModelServer. It will also automatically make all the data in the viewmodel available on the client side as normal javascript objects.
I here make use of the StreamingViewModelClient that automatically will handle all the messaging to the StreamingViewModelServer. It will also automatically make all the data in the viewmodel available on the client side as normal javascript objects.
Line 64: Line 65:
2. I need to tell AngualarJS when to use this controller :
2. I need to tell AngualarJS when to use this controller :


<html>
<pre class="code"><span style="background: white; color: black;">      when(</span><span style="background: white; color: #a31515;">'/BrowseVideos'</span><span style="background: white; color: black;">, {
<pre class="code"><span style="background: white; color: black;">      when(</span><span style="background: white; color: #a31515;">'/BrowseVideos'</span><span style="background: white; color: black;">, {
         templateUrl: </span><span style="background: white; color: #a31515;">'partials/BrowseVideos.html'</span><span style="background: white; color: black;">,
         templateUrl: </span><span style="background: white; color: #a31515;">'partials/BrowseVideos.html'</span><span style="background: white; color: black;">,
Line 69: Line 71:
       </span><span style="background: white; color: black;">}).
       </span><span style="background: white; color: black;">}).
</span></pre>
</span></pre>
</html>


3. I need to construct a UI that use angualarJS to display the viewmodel now available in local memory:
3. I need to construct a UI that use angualarJS to display the viewmodel now available in local memory:


<html>
<pre class="code"><span style="background: white; color: blue;">&lt;</span><span style="background: white; color: maroon;">div </span><span style="background: white; color: red;">class</span><span style="background: white; color: blue;">="container-fluid"&gt;
<pre class="code"><span style="background: white; color: blue;">&lt;</span><span style="background: white; color: maroon;">div </span><span style="background: white; color: red;">class</span><span style="background: white; color: blue;">="container-fluid"&gt;
   &lt;</span><span style="background: white; color: maroon;">div </span><span style="background: white; color: red;">class</span><span style="background: white; color: blue;">="row"&gt;
   &lt;</span><span style="background: white; color: maroon;">div </span><span style="background: white; color: red;">class</span><span style="background: white; color: blue;">="row"&gt;
Line 88: Line 92:
     &lt;/</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">&gt;
     &lt;/</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">&gt;
   &lt;/</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">&gt;
   &lt;/</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">&gt;
&lt;/</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">&gt;</span></pre>
&lt;/</span><span style="background: white; color: maroon;">div</span><span style="background: white; color: blue;">&gt;</span></pre> </html>




Using only information from the model – and using very much standard front end angualarJS programming I have now done everything that is required to get this functionality:
Using only information from the model – and using very much standard front end angualarJS programming I have now done everything that is required to get this functionality:
[[File:03.png|none|thumb]]
[[File:04.png|none|thumb]]


What happens as the user writes in the filter box is this:
What happens as the user writes in the filter box is this:

Revision as of 18:05, 28 November 2018

The dilemma – secure information requires low system exposure, rich functionality requires high system exposure.

It is natural to want to protect your system. The system contains your intellectual property and also information that your users has collected or created.

Building rich clients almost always means that large parts of the system must reside close to the user. The thing is that we can never be sure that any given user will not try to reverse the application.

In the reversed application  the user may find intellectual property (ip) we would rather not give away.

The user may also try to mock the application calls in order to trick our server to believe it is dealing with a legitimate application that is expected to behave fairly and respect rules of access.

These concerns has driven many system producers back to browser based applications rather that client side frameworks.

The problem is that the rich client has been creeping back into the browser  - as javascript – executing locally, holding lots of ip-knowledge and thus the key to mock the server into believing that it is dealing with the well behaving application.

This means that we now have languages less suited for complex systems due to their lack of compile time type checking used to implement the rules of the system in a very open environment in the users browsers.

I have always felt that there must be a better way.

I am all for rich applications but I understand that the risk often can be considered unacceptable.

This is what I propose to address this dilemma.

The streaming viewmodel

The ViewModel is a great way to section of perspective on information for a specific need. Doing this sectioning ensures that we do not reveal anything more that the bare necessities when exposing information to a client. There still may be issues with actions in the viewmodel needing logic to check and perform – logic we need to let the user know is there but not necessarily want the user to see the implementation of.

To solve this we only expose the names of the actions to the client. If the client wants to execute an action it must ask the server to do so. The action will change state in our system and likely that will show as changed state of some attributes in our viewmodel. This means that the client must retrieve any resulting news from the server once the server is done.

In the normal non-ajax web-page approach the whole viewmodel is re-rendered on such an update. The way I propose to solve this is to only stream back the actual changes of the viewmodel – and then have client side logic to update the client side viewmodel instance – triggering update of bound user interface as a consequence.

Further on: the user may change the clients state by checking boxes and filling in strings etc. These changes of the local data might result in side effects like a list being filtered or a warning light being lit. These changes must be sent back to the server as they happen – the server must mix them in with the server side state – this might trigger updates of viewmodel attributes that must go back to client.

And we have a round trip. But a round trip that only send diff grams of changed data – not all data.

The concept test

I constructed a server side generic streaming viewmodel that is able to receive and send changes. I also wrote a generic client side viewmodel in typescript – that transforms into javascript. Both these generic viewmodels are controlled entirely from MDriven viewmodel definitions.

I have chosen to work with AngualarJS on the client side – as the way to bind user interface to data – but that is just my choice – this strategy will work with any client side framework.

Given this model:

01.png

In the simplified model above I want one user interface to browse videos – but under no circumstances should this ability expose anyway to change the Genre or check who Viewed the film in the past.

Declaratively I do this viewmodel and test it out in the prototyper:

02.png

In angualarJS I need to do a few things to use this viewmodel:

1. I define a controller

phonecatControllers.controller('BrowseVideos', ['$scope',
  function ($scope) {
    var x = new StreamingViewModelClient("BrowseVideos", "$null$");
    $scope.root = x.Root();
    x.ExecuteAfterServerAppliedChanges = function () { $scope.$apply(); }
    $scope.$apply(function ($scope) {
      $scope.x.ConsumeServerMessage();
    });
  }]);

I here make use of the StreamingViewModelClient that automatically will handle all the messaging to the StreamingViewModelServer. It will also automatically make all the data in the viewmodel available on the client side as normal javascript objects.

2. I need to tell AngualarJS when to use this controller :

      when('/BrowseVideos', {
        templateUrl: 'partials/BrowseVideos.html',
        controller: 'BrowseVideos'
      }).

3. I need to construct a UI that use angualarJS to display the viewmodel now available in local memory:

<div class="container-fluid">
  <div class="row">
    <div class="col-md-10">
      <!--Body content-->

      <p>Filter videos:</p>
      <input type="text" name="input" ng-model="root.Filter">

      <ul >
        <li ng-repeat="video in root.AllVideo" class="thumbnail">
          <p> {{video.Name}} {{video.Length}} minutes  {{video.Genre}} </p>
        </li>
      </ul>

    </div>
  </div>
</div>


Using only information from the model – and using very much standard front end angualarJS programming I have now done everything that is required to get this functionality:

03.png
04.png

What happens as the user writes in the filter box is this:

1. Local viewmodels property named Filter is updated

2. Changes discovered by MDriven StreamingViewModelClient and posted to server as an Attribute_Update_Message

3. Message is received by MDriven StreamingViewModelServer and corresponding server viewmodel is updated

4. The server side change triggers subscription changes on the OCL expressions that build up the ViewModel

5. The outdated dependencies are re-evaluated – in this case the AllVideo expression is run.

6. The change of the AllVideo list on the server generates a few Collection_Remove_Object messages

7. The client receives the messages about the collection_remove object and removes accordingly.

8- Roundtrip is finished – all this is done with ajax calls – so user keeps on working

Summing up

I have only just started this concept work of a streaming viewmodel that sends messages on changes back and forth – but I think it is the correct way to go. And not only for javascript but also for WPF. This way of isolating the client from all the IP contained in the model and all the possible attack vectors that may exists if we expose to much seems perfect.

It is also a good mix of keeping all the rule evaluation in a robust type checked server environment instead of being left out to javascript. At the same time it enables me to build UI in javascript – with full databind and thus being able to execute on any client platform.

Do you have thoughts on these problems discussed here? Let me know – maybe we can help out.

This page was edited 47 days ago on 02/10/2024. What links here