[Bio] / FigKernelPackages / UserData.pm Repository:
ViewVC logotype

Annotation of /FigKernelPackages/UserData.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (view) (download) (as text)

1 : parrello 1.1 #!/usr/bin/perl -w
2 : olson 1.3 #
3 :     # Copyright (c) 2003-2006 University of Chicago and Fellowship
4 :     # for Interpretations of Genomes. All Rights Reserved.
5 :     #
6 :     # This file is part of the SEED Toolkit.
7 : parrello 1.6 #
8 : olson 1.3 # The SEED Toolkit is free software. You can redistribute
9 :     # it and/or modify it under the terms of the SEED Toolkit
10 : parrello 1.6 # Public License.
11 : olson 1.3 #
12 :     # You should have received a copy of the SEED Toolkit Public License
13 :     # along with this program; if not write to the University of Chicago
14 :     # at info@ci.uchicago.edu or the Fellowship for Interpretation of
15 :     # Genomes at veronika@thefig.info or download a copy from
16 :     # http://www.theseed.org/LICENSE.TXT.
17 :     #
18 :    
19 : parrello 1.1
20 :     package UserData;
21 :    
22 :     require Exporter;
23 :     @ISA = ('Exporter');
24 :     @EXPORT = qw();
25 :     @EXPORT_OK = qw();
26 :    
27 :     use strict;
28 :     use Tracer;
29 :     use PageBuilder;
30 :    
31 :     =head1 FIG User Configuration Module
32 :    
33 :     =head2 Introduction
34 :    
35 :     The user data object allows the SEED to determine the privileges and
36 :     preferences of SEED users. This is not intended as an ironclad security
37 :     system; rather, its goal is to prevent one group stepping on another group's
38 :     work and to allow individual users to customize the look and feel of the
39 :     SEED.
40 :    
41 :     =head3 Capabilities
42 :    
43 :     Capabilities provide three access levels-- C<RW> (read-write), C<RO> (read-only),
44 :     and C<NO> (no access). Capabilities are managed using arbitrary classes of genomes
45 :     and subsystems called I<groups>. Groups are stored globally. Each group has a
46 :     name and a default access level. The default group is called C<normal> and has
47 :     a default access level of C<RW>.
48 :    
49 :     Each user has a list of capabilities, each consisting of a group name and an
50 :     access level. A group name / access level pair is called a I<subscription>.
51 :     When a user attempts to access a subsystem or genome, we get the genome or
52 :     subsystem's group name and ask if the user has a subscription to the group.
53 :     If he does, the access level in the subscription is used. If he does not, the
54 :     default access level for the group is used.
55 :    
56 :     If the user name is not known, the default user-- C<basic>-- will be used.
57 :     Initially, this default user will have no subscriptions, and as a result
58 :     will have default access to all genome and subsystem groups; however, if this
59 :     is not desirable it can be changed by adding subscriptions to the basic user
60 :     record.
61 :    
62 :     =head3 Preferences
63 :    
64 :     Preferences are simple key-value pairs. For each key, there is a single string
65 :     value. The key name cannot contain any white space. The keys are treated like
66 :     simple unformatted keys; however, it is highly recommened that the colon
67 :     character (C<:>) be used to separate the name into a category and a subkey
68 :     name. For example, C<genomes:columnList> would indicate the column-list
69 :     preference for the B<genomes> category. If the number of keys becomes
70 :     large, the category concept will enable us to restructure the data to reduce
71 :     the memory footprint.
72 :    
73 : parrello 1.2 Every user has his own set of preferences. The default user C<basic> should
74 :     have a complete set of preferences; if a preference is not specified for a
75 :     particular user, the basic user's value will be used instead.
76 :    
77 : parrello 1.1 =head2 Access Objects
78 :    
79 :     This module does not access the actual data. Instead, it accepts as input
80 :     an I<access object>. The access object hides the details of data access
81 :     from the User Data object so that different data stores can be plugged
82 :     in. Currently, the access objects used by most of the SEED are the
83 :     B<FIG> and B<SFXlate> objects. FIG uses a combination of flat files and
84 :     database tables and supports both reads and updates. The SFXlate object
85 :     uses a pure database scheme and is mostly read-only.
86 :    
87 : parrello 1.5 #: Constructor UserData->new();
88 : parrello 1.1
89 :     =head2 Public Methods
90 :    
91 :     =head3 new
92 :    
93 : parrello 1.6 my $userData = UserData->new($user, $fig);
94 : parrello 1.1
95 :     Construct the capabilities object for a specified user.
96 :    
97 :     =over 4
98 :    
99 :     =item user
100 :    
101 :     Name of the current user.
102 :    
103 :     =item fig
104 :    
105 :     Access object for retrieving user data.
106 :    
107 :     =back
108 :    
109 :     =cut
110 :    
111 :     sub new {
112 :     # Get the parameters.
113 :     my ($class, $user, $fig) = @_;
114 : parrello 1.2 # Get the user's capabilities.
115 :     my $capable = $fig->GetCapabilities($user);
116 : parrello 1.1 # Create the userdata object.
117 :     my $retVal = {
118 : parrello 1.2 capable => $capable,
119 :     newCapable => { },
120 :     user => $user,
121 :     preferences => { },
122 :     newPreferences => { },
123 :     fig => $fig
124 : parrello 1.1 };
125 :     # Bless and return it.
126 : parrello 1.2 bless $retVal, $class;
127 : parrello 1.1 return $retVal;
128 :     }
129 :    
130 :     =head3 GetCapability
131 :    
132 : parrello 1.6 my $level = $userData->GetCapability($objectID, $objectType);
133 : parrello 1.1
134 :     Get this user's access level for the specified object-- either C<RW> (full access),
135 :     C<RO> (read-only), or C<NO> (no access).
136 :    
137 :     =over 4
138 :    
139 :     =item objectID
140 :    
141 :     ID of the relevant object.
142 :    
143 :     =item objectType
144 :    
145 :     Type of the relevant object. This should be the Sprout entity name for the
146 :     object type. Currently, only C<Subsystem> and C<Genome> are supported.
147 :    
148 :     =item RETURN
149 :    
150 : parrello 1.2 Returns C<RW> if the user has full access, C<RO> if the user has read-only
151 : parrello 1.1 access, and C<NO> if the user should not have any access to the object.
152 :    
153 :     =back
154 :    
155 :     =cut
156 :    
157 :     sub GetCapability {
158 : parrello 1.2 # Get the parameters.
159 :     my ($self, $objectID, $objectType) = @_;
160 :     # Look for the group and default access level of the target object.
161 :     my ($group, $level) = $self->{fig}->GetDefault($objectID, $objectType);
162 :     # If it wasn't found, the group is 'normal' and the access level is RW.
163 :     if (! $group) {
164 :     ($group, $level) = ('normal', 'RW');
165 :     }
166 :     # If this group is in the user's capability hash, we use the result to
167 :     # override the level.
168 :     if (exists $self->{capable}->{$group}) {
169 :     $level = $self->{capable}->{$group};
170 :     }
171 :     # Return the level.
172 :     return $level;
173 : parrello 1.1 }
174 :    
175 :     =head3 GetPreference
176 :    
177 : parrello 1.6 my $value = $userData->GetPreference($key);
178 : parrello 1.1
179 :     Return the user's preference value for the specified key.
180 :    
181 :     =over 4
182 :    
183 :     =item key
184 :    
185 :     Fully-qualified key for the preference value.
186 :    
187 :     =item RETURN
188 :    
189 :     Returns the preference value for the key. If the user has no explicit preference
190 :     value for that key, returns the corresponding value for the default user.
191 :    
192 :     =back
193 :    
194 :     =cut
195 :    
196 :     sub GetPreference {
197 : parrello 1.2 # Get the parameters.
198 :     my ($self, $key) = @_;
199 :     # Extract the category name.
200 :     my $category = ParseCategory($key);
201 :     # Insure this category is in memory.
202 :     my $categoryHash = $self->GetCategoryHash($category);
203 :     # Return the value for the specified preference key.
204 :     my $retVal = $categoryHash->{$key};
205 :     return $retVal;
206 : parrello 1.1 }
207 :    
208 :     =head3 SetCapabilities
209 :    
210 : parrello 1.6 $userData->SetCapabilities(\%groupMap);
211 : parrello 1.1
212 :     Set capabilities for this user. This does not replace all existing capabilities.
213 :     Instead, the capabilities specified in the group map are updated or deleted,
214 : parrello 1.2 and any capabilities not specified are unchanged. Note that the actual changes
215 :     are cached in memory, and are not written until the L</SaveChanges> method is
216 :     called.
217 : parrello 1.1
218 :     =over 4
219 :    
220 :     =item groupMap
221 :    
222 :     Reference to a hash mapping group names to access levels (C<RW> full access,
223 :     C<RO> read-only access, C<NO> no access) or an undefined value if the user
224 :     is to have default access to the specified group.
225 :    
226 :     =back
227 :    
228 :     =cut
229 :    
230 :     sub SetCapabilities {
231 : parrello 1.2 # Get the parameters.
232 :     my ($self, $groupMap) = @_;
233 :     # Loop through the settings, adding them to the update hash and the actual
234 :     # hash. The update hash is used when we save changes. The actual hash
235 :     # needs to be updated as well so that the new values are retrieved when
236 :     # the client asks for capability data.
237 :     my $accessMap = $self->{capable};
238 :     my $changeMap = $self->{newCapable};
239 :     for my $group (keys %{$groupMap}) {
240 :     $accessMap->{$group} = $groupMap->{$group};
241 :     $changeMap->{$group} = $groupMap->{$group};
242 :     }
243 : parrello 1.1 }
244 :    
245 : parrello 1.2 =head3 SetPreferences
246 :    
247 : parrello 1.6 $userData->SetPreferences(\%preferences);
248 : parrello 1.1
249 :     Set preferences for this user. This does not replace all existing preferences.
250 :     Instead, the preferences specified in the map are updated or deleted, and any
251 : parrello 1.2 preferences not specified are unchanged. Note that the settings are not changed.
252 :     Instead, the changes are cached in memory until the L</SaveChanges> method is
253 :     called.
254 : parrello 1.1
255 :     =over 4
256 :    
257 :     =item preferences
258 :    
259 :     Reference to a hash mapping key names to preference values. Mapping a key
260 :     name to an undefined value indicates that the default preference value
261 :     should be used.
262 :    
263 :     =back
264 :    
265 :     =cut
266 :    
267 :     sub SetPreferences {
268 : parrello 1.2 # Get the parameters.
269 :     my ($self, $preferences) = @_;
270 :     # Loop through the settings. Each one is added to the main hash and then
271 :     # cached in the update hash.
272 :     my $changeMap = $self->{newPreferences};
273 :     for my $key (keys %{$preferences}) {
274 :     # Extract the category name from the key.
275 :     my $category = ParseCategory($key);
276 :     # Insure we have the category in memory.
277 :     my $hash = $self->GetCategoryHash($category);
278 :     # Add the new value to the category hash.
279 :     $hash->{$key} = $preferences->{$key};
280 :     # Add it to the update hash.
281 :     $changeMap->{$key} = $preferences->{$key};
282 :     }
283 : parrello 1.1 }
284 :    
285 :     =head3 SetDefault
286 :    
287 : parrello 1.6 $userData->SetDefault($objectID, $objectType, $group, $level);
288 : parrello 1.1
289 : parrello 1.2 Set the group and default access level for the specified object. This update
290 :     takes place immediately.
291 : parrello 1.1
292 :     =over 4
293 :    
294 :     =item objectID
295 :    
296 :     ID of the object whose access level and group are to be set.
297 :    
298 :     =item objectType
299 :    
300 :     Type of the relevant object. This should be expressed as a Sprout entity name.
301 :     Currently, only C<Genome> and C<Subsystem> are supported.
302 :    
303 :     =item group
304 :    
305 :     Name of the group to which the object will belong. A user's access level for
306 :     this group will override the default access level.
307 :    
308 :     =item level
309 :    
310 :     Default access level. This is the access level used for user's who do not have
311 :     an explicit capability specified for the object's group.
312 :    
313 :     =back
314 :    
315 :     =cut
316 :    
317 :     sub SetDefault {
318 : parrello 1.2 # Get the parameters.
319 :     my ($self, $objectID, $objectType, $group, $level) = @_;
320 :     # Call the access method.
321 :     $self->{fig}->SetDefault($objectID, $objectType, $group, $level);
322 :     }
323 :    
324 :     =head3 SaveChanges
325 :    
326 : parrello 1.6 $userData->SaveChanges();
327 : parrello 1.2
328 :     Store accumulated preference and capability changes.
329 :    
330 :     =cut
331 :    
332 :     sub SaveChanges {
333 :     # Get the parameters.
334 :     my ($self) = @_;
335 :     # Check for capability updates.
336 :     my $capabilityUpdates = $self->{newCapable};
337 :     if (keys %{$capabilityUpdates}) {
338 :     $self->{fig}->SetCapabilities($self->{user}, $capabilityUpdates);
339 :     }
340 :     # Check for preference updates.
341 :     my $preferenceUpdates = $self->{newPreferences};
342 :     if (keys %{$preferenceUpdates}) {
343 :     $self->{fig}->SetPreferences($self->{user}, $preferenceUpdates);
344 :     }
345 : parrello 1.1 }
346 :    
347 : parrello 1.2 =head3 ParseCategory
348 :    
349 : parrello 1.6 my $category = UserData::ParseCategory($key);
350 : parrello 1.2
351 :     Return the category name from the specified preference key. If no category is
352 :     specified, an error will occur.
353 :    
354 :     =over 4
355 :    
356 :     =item key
357 :    
358 :     Preference key, which consists of alphanumeric characters with colons separating
359 :     the sections.
360 :    
361 :     =item RETURN
362 :    
363 :     Returns the category name from the specified key.
364 :    
365 :     =back
366 :    
367 :     =cut
368 :    
369 :     sub ParseCategory {
370 :     # Get the parameters.
371 :     my ($key) = @_;
372 :     # Declare the return variable.
373 :     my $retVal;
374 :     # Try to parse out the category.
375 :     if ($key =~ /([^:]+):/) {
376 :     # Return the category.
377 :     $retVal = $1;
378 :     } else {
379 :     # Here we have no category, so it's an error.
380 :     Confess("No category specified on preference key \"$key\".");
381 :     }
382 :     return $retVal;
383 :     }
384 :    
385 :     =head3 GetCategoryHash
386 :    
387 : parrello 1.6 my $categoryHash = $self->GetCategoryHash($category);
388 : parrello 1.2
389 :     Return the hash for the specified category. If it is not in memory, it
390 :     will be read in.
391 :    
392 :     =over 4
393 :    
394 :     =item key
395 :    
396 :     Preference key, which consists of alphanumeric characters with colons separating
397 :     the sections.
398 :    
399 :     =item RETURN
400 :    
401 :     Returns the category name from the specified key.
402 :    
403 :     =back
404 :    
405 :     =cut
406 :    
407 :     sub GetCategoryHash {
408 :     # Get the parameters.
409 :     my ($self, $category) = @_;
410 :     # Declare the return variable.
411 :     my $retVal;
412 :     # Check to see if we have preferences for this category. If not, we need
413 :     # to read them in.
414 :     if (! exists $self->{preferences}->{$category}) {
415 :     # Get the default preferences if this is not the default user.
416 :     my $defaults = {};
417 :     if ($self->{user} ne 'basic') {
418 :     $defaults = $self->{fig}->GetPreferences('basic', $category);
419 :     }
420 :     # Get the user's preferences and merge them in.
421 :     my $overrides = $self->{fig}->GetPreferences($self->{user}, $category);
422 :     for my $key0 (%{$overrides}) {
423 :     $defaults->{$key0} = $overrides->{$key0};
424 :     }
425 :     # Add the new hash to the preferences hash.
426 :     $self->{preferences}->{$category} = $defaults;
427 :     # Return it.
428 :     $retVal = $defaults;
429 :     } else {
430 :     # Here the hash is already in memory.
431 :     $retVal = $self->{preferences}->{$category};
432 :     }
433 :     # Return the category hash.
434 :     return $retVal;
435 :     }
436 : parrello 1.1
437 : parrello 1.5 =head2 Access Object Methods
438 :    
439 :     The following methods must be implemented by the access object (e.g. I<$fig>) passed
440 :     to the constructor.
441 :    
442 :     =head3 GetDefault
443 :    
444 : parrello 1.6 my ($group, $level) = $fig->GetDefault($objectID, $objectType);
445 : parrello 1.5
446 :     Return the group name and default access level for the specified object.
447 :    
448 :     =over 4
449 :    
450 :     =item objectID
451 :    
452 :     ID of the object whose capabilities data is desired.
453 :    
454 :     =item objectType
455 :    
456 :     Type of the object whose capabilities data is desired. This should be expressed
457 :     as a Sprout entity name. Currently, the only types supported are C<Genome>
458 :     and C<Subsystem>.
459 :    
460 :     =item RETURN
461 :    
462 :     Returns a two-element list. The first element is the name of the group
463 :     to witch the object belongs; the second is the default access level
464 :     (C<RW>, C<RO>, or C<NO>). If the object is not found, an empty list
465 :     should be returned.
466 :    
467 :     =back
468 :    
469 :     =head3 GetPreferences
470 :    
471 : parrello 1.6 my $preferences = $fig->GetPreferences($userID, $category);
472 : parrello 1.5
473 :     Return a map of preference keys to values for the specified user in the
474 :     specified category.
475 :    
476 :     =over 4
477 :    
478 :     =item userID
479 :    
480 :     ID of the user whose preferences are desired.
481 :    
482 :     =item category (optional)
483 :    
484 :     Name of the category whose preferences are desired. If omitted, all
485 :     preferences should be returned.
486 :    
487 :     =item RETURN
488 :    
489 :     Returns a reference to a hash mapping each preference key to a value. The
490 :     keys are fully-qualified; in other words, the category name is included.
491 :     It is acceptable for the hash to contain key-value pairs outside the
492 :     category. In other words, if it's easier for you to read the entire
493 :     preference set into memory, you can return that one set every time
494 :     this method is called without worrying about the extra keys.
495 :    
496 :     =back
497 :    
498 :     =head3 GetCapabilities
499 :    
500 : parrello 1.6 my $level = $fig->GetCapabilities($userID);
501 : parrello 1.5
502 :     Return a map of group names to access levels (C<RW>, C<RO>, or C<NO>) for the
503 :     specified user.
504 :    
505 :     =over 4
506 :    
507 :     =item userID
508 :    
509 :     ID of the user whose access level is desired.
510 :    
511 :     =item RETURN
512 :    
513 :     Returns a reference to a hash mapping group names to the user's access level
514 :     for that group.
515 :    
516 :     =back
517 :    
518 :     =head3 AllowsUpdates
519 :    
520 : parrello 1.6 my $flag = $fig->AllowsUpdates();
521 : parrello 1.5
522 :     Return TRUE if this access object supports updates, else FALSE. If the access object
523 :     does not support updates, none of the B<SetXXXX> methods will be called.
524 :    
525 :     =head3 SetDefault
526 :    
527 : parrello 1.6 $fig->SetDefault($objectID, $objectType, $group, $level);
528 : parrello 1.5
529 :     Set the group and default access level for the specified object.
530 :    
531 :     =over 4
532 :    
533 :     =item objectID
534 :    
535 :     ID of the object whose access level and group are to be set.
536 :    
537 :     =item objectType
538 :    
539 :     Type of the relevant object. This should be expressed as a Sprout entity name.
540 :     Currently, only C<Genome> and C<Subsystem> are supported.
541 :    
542 :     =item group
543 :    
544 :     Name of the group to which the object will belong. A user's access level for
545 :     this group will override the default access level.
546 :    
547 :     =item level
548 :    
549 :     Default access level. This is the access level used for user's who do not have
550 :     an explicit capability specified for the object's group.
551 :    
552 :     =back
553 :    
554 :     =head3 SetCapabilities
555 :    
556 : parrello 1.6 $fig->SetCapabilities($userID, \%groupLevelMap);
557 : parrello 1.5
558 :     Set the access levels by the specified user for the specified groups.
559 :    
560 :     =over 4
561 :    
562 :     =item userID
563 :    
564 :     ID of the user whose capabilities are to be updated.
565 :    
566 :     =item groupLevelMap
567 :    
568 :     Reference to a hash that maps group names to access levels. The legal
569 :     access levels are C<RW> (read-write), C<RO> (read-only), and C<NO> (no
570 :     access). An undefined value for the access level indicates the default
571 :     level should be used for that group. The map will not replace all of
572 :     the user's capability date; instead, it overrides existing data, with
573 :     the undefined values indicating the specified group should be deleted
574 :     from the list.
575 :    
576 :     =back
577 :    
578 :     =head3 SetPreferences
579 :    
580 : parrello 1.6 $fig->SetPreferences($userID, \%preferenceMap);
581 : parrello 1.5
582 :     Set the preferences for the specified user.
583 :    
584 :     =over 4
585 :    
586 :     =item userID
587 :    
588 :     ID of the user whose preferences are to be udpated.
589 :    
590 :     =item preferenceMap
591 :    
592 :     Reference to a hash that maps each preference key to its value. The
593 :     keys should be fully-qualified (that is, they should include the
594 :     category name). A preference key mapped to an undefined value will
595 :     use the default preference value for that key. The map will not
596 :     replace all of the user's preference data; instead, it overrides
597 :     existing data, with the undefined values indicating the specified
598 :     preference should be deleted from the list.
599 :    
600 :     =back
601 :    
602 :     =head3 CleanupUserData
603 :    
604 : parrello 1.6 $fig->CleanupUserData();
605 : parrello 1.5
606 :     Release any data being held in memory for use by the UserData object.
607 :    
608 :     =head2 Fields
609 :    
610 :     The user data object contains the following fields.
611 :    
612 :     =over 4
613 :    
614 :     =item capable
615 :    
616 :     Reference to a hash containing all the user's capability data.
617 :    
618 :     =item preferences
619 :    
620 :     Reference to a hash of hashes. The key of the large hash is the preference
621 :     category, and the value is a small hash mapping preferences from that
622 :     category to values.
623 :    
624 :     =item userID
625 :    
626 :     Current user's ID.
627 :    
628 :     =item fig
629 :    
630 :     Fig-like object for accessing the data.
631 :    
632 :     =item newCapable
633 :    
634 :     Hash containing updated capabilities.
635 :    
636 :     =item newPreferences
637 :    
638 :     Hash containing updated preferences.
639 :    
640 :     =back
641 :    
642 :     =cut
643 :    
644 : golsen 1.4 1;

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3