[Freeipa-devel] [PATCH] 028 Code cleanup of HBAC, Sudo rules

Adam Young ayoung at redhat.com
Thu Oct 27 23:39:07 UTC 2011


On 10/27/2011 05:51 PM, Endi Sukma Dewata wrote:
> On 10/27/2011 8:39 AM, Petr Vobornik wrote:
>> But still I think it would be better to be able to get container
>> (facet/dialog) for a widget. As you wrote, that.entity.get_facet() may
>> not always be what we want.
>
> One possibility is to convert the facet & dialog into subclasses of an 
> abstract container class. The container needs to provide functions 
> such as refresh() so the widget doesn't need to know whether it's a 
> facet or dialog.
>
>>>> Btw similar topic could be: "How to get current entity's pkey?'.
>>>> Dependancy on facet.get_primary_key() or
>>>> IPA.nav.get_state(that.entity.name+'-pkey') seems wrong too.
>>>
>>> Yes. Ideally we should have a path (REST-style URL) instead of the
>>> current parameter-based URL. We should get the pkey from that path.
>>
>>  From dependency point of view, widgets would be still dependant on the
>> implementation of navigation (IMHO bad).
>>
>> But it seems that using entity.get_primary key partially solves the
>> problem.
>


> It could be argued that since this is a web app everything will have a 
> path, but for now getting primary key from entity is fine since 
> everything also has an associated entity.
>
>> Maybe it would be better if navigation would inject pkey to entity.
>> Entity wouldn't be that much dependant on navigation implementation.
>
> We might need to distinguish 2 different usages of 'entity'. The first 
> one represents a collection of entries:

Call that an instance.  Entity is the  term that is the analogue of  Class

So we want to distinguish getting the primary key field for the entity, 
as opposed to the primary key of the instance.

>
>   var users = IPA.get_entity('user');
>   users.add([ 'test' ], { givenName: 'Test', ... });
>   var result = users.find('t*');
>
> The second one represents individual entry:
>
>   var user = result.result[0];
>   user.update({ sn: 'User' });
>
> The entity collection should be 'stateless', it will be used in search 
> pages. The individual entity will be 'stateful', it contains the pkey 
> and the values of its attributes, and it will be used in the details 
> page.
>
> The entity.get_primary_key() is an interface to get the primary keys 
> for a particular entity from the current path. So when you open a URL 
> for an entry's details facet, it will execute the following command:
>
>   var pkeys = entity.get_primary_key();
>   var object = entity.get(pkeys);
>
> Then the facet will use the object to populate the page.
>
>> The priority could be part of update info. As there is a field_info we
>> can create a command_info: { command, priority }.

I'm a little unclear on the usage of priority.
>
>> Before adding commands to batch_command, array of command_info objects
>> would joined with 'mod' command with default priority and then sorted by
>> priority.
>>
>> If the priority was set on each widget, priority management will be on
>> facet level, which may be fine. There can be some corner case like
>> dynamic change of priority.
>
> I'd have to see how it's implemented.
>
>>> One other solution is to split widgets into non-visual fields and 
>>> purely
>>> HTML components. Then in the facet we use separate lists for the fields
>>> and HTML components. The fields will have a reference to the
>>> corresponding HTML components. There can be more HTML components than
>>> fields. But this will require a significant restructuring.
>>
>> Maybe we can use hybrid solution: html widgets would be simple object
>> with some properties and create() method. They should not be called
>> widgets. They would not be part of sections fields. Rendering would be
>> done in widgets/sections create() method (as it is now).

I think this is  not quite right.  Widget is just a generic term for an 
element of the UI object model.  It is intentionally generic.  A Widget 
can be just about anything.  Some bind down to the individual fields, or 
in somcses, even smaller, but widget could easily be the base class for 
Facets, sections and the widget we have now.

>
> I'm not very clear, we could be talking about the same thing. The 
> (non-HTML) fields could be defined like this:
>
>   fields: [
>       {
>           name: 'cn',
>           widget: 'identity.cn'
>       },
>       {
>           name: 'email',
>           widget: 'identity.email'
>       },
>       {
>           factory: IPA.password_field,
>           name: 'userpassword',
>           widgets: [ 'account.password1', 'account.password2' ]
>       }
>   ]
>
> The specs above will be used to create IPA.field objects (not widget) 
> to assist loading/saving attributes. Then we could also define the 
> HTML components (let's call it widget) separately:
>
>   widgets: [
>       {
>           factory: IPA.table_section,
>           name: 'identity',
>           label: 'Identity'
>           widgets: [
>               {
>                   factory: IPA.text_widget,
>                   name: 'cn'
>               },
>               {
>                   factory: IPA.multivalued_widget,
>                   name: 'email',
>                   widget: IPA.text_widget
>               }
>           ]
>       }
>   ]
>
> The specs above will be used to create IPA.widget objects to generate 
> the HTML content. If there is no widget specs specified, we could 
> generate it automatically from the field specs.
>
>> Pros:
>> - reusable layouts, headers...
>> - not polluting field names
>> Cons:
>> - not so declarative - need to override update method, create custom
>> section/widget factories - same as now
>
> The above example should be quite declarative.
>
>> Question:
>> - what with widget nesting? rule_details_section is in fact a composite
>> widget. I would like to keep the concept, because it offers better code
>> reuse.
>
> As shown above, widget (not field) nesting is possible.
>
> A section is a composite widget with a specific layout: it has a 
> header, it's collapsible, and it has nested widgets.
>
> A table section is a section that uses 2 columns to display the nested 
> widgets: one for the field label and the other for the widget itself.
>
> A multivalued widget is a composite widget with one type of nested 
> widgets and it has an Add and Undo All links.
>
> The rule_details_section is a section with radio buttons (for the 
> category) and some tables.
>
>>> I think the decision to use mod or batch should be separate from 
>>> details
>>> facet. I'm thinking to create a separate class IPA.client which we can
>>> add commands into it and execute them either individually or as a 
>>> batch.
>>
>> What would be the IPA.client's responsibilities? It'll be only a
>> container for commands with different executing strategies?
>
> The IPA.client will represent a connection to the IPA server. In a 
> browser IPA.client can only connect to the server it's loaded from:

>
>   var client = IPA.client();
>
> but in a JS engine like Rhino the IPA.client can connect to any IPA 
> server:
>
>    var client = IPA.client('ipa.example.com');

This will work now, but you will not be able to see the results of the 
command.  Integrations like this are how  the Like buttons from Facebook 
work.  Cross site posting is tricky, but permitted, and might be useful 
in some cases.  Possibly we should call it connection.
>
> The IPA.client can be used to execute commands:
>
>    var command = IPA.command(...);
>    client.execute(command);
>
> or start a batch:
>
>    client.start_batch();
>    client.execute(command1);
>    client.execute(command2);
>    client.end_batch();
>
> or get the entities:
>
>    var users = client.get_entity('user');
>




More information about the Freeipa-devel mailing list