[Jifty-commit] r3996 - in apps/CASPlus/trunk: lib/CASPlus
lib/CASPlus/Model lib/CASPlus/Util t
jifty-commit at lists.jifty.org
jifty-commit at lists.jifty.org
Wed Aug 29 12:48:42 EDT 2007
Author: sterling
Date: Wed Aug 29 12:48:41 2007
New Revision: 3996
Added:
apps/CASPlus/trunk/t/40-many-to-one_relationships-explicit.t
Modified:
apps/CASPlus/trunk/ (props changed)
apps/CASPlus/trunk/lib/CASPlus/Model/Profile.pm
apps/CASPlus/trunk/lib/CASPlus/Model/ProfileRelationship.pm
apps/CASPlus/trunk/lib/CASPlus/ProfileMixin.pm
apps/CASPlus/trunk/lib/CASPlus/ProfileRelationshipMixin.pm
apps/CASPlus/trunk/lib/CASPlus/Util/Relationship.pm
Log:
r8962 at riddle: andrew | 2007-08-25 19:31:51 -0500
Added the tests for role calculation in many-parents/one-child relationships.
Modified: apps/CASPlus/trunk/lib/CASPlus/Model/Profile.pm
==============================================================================
--- apps/CASPlus/trunk/lib/CASPlus/Model/Profile.pm (original)
+++ apps/CASPlus/trunk/lib/CASPlus/Model/Profile.pm Wed Aug 29 12:48:41 2007
@@ -191,6 +191,7 @@
else {
$ret->as_error(
+ errno => 1,
message => "$qualified_class object does not have a model class (searched for $class_name).",
);
}
Modified: apps/CASPlus/trunk/lib/CASPlus/Model/ProfileRelationship.pm
==============================================================================
--- apps/CASPlus/trunk/lib/CASPlus/Model/ProfileRelationship.pm (original)
+++ apps/CASPlus/trunk/lib/CASPlus/Model/ProfileRelationship.pm Wed Aug 29 12:48:41 2007
@@ -82,7 +82,7 @@
Calculated column. Do not modify.
-This column is setup by the class itself during creation. A new column will be created in the parent table according to the given L</parent_name> and L</relation_child>. This will be set to the L<Jifty::Model::ModelClassColumn> object created.
+This column is setup by the class itself during creation. A new column will be created in the child table according to the given L</parent_name> and L</relation_child>. This will be set to the L<Jifty::Model::ModelClassColumn> object created.
=head2 link_table
@@ -421,7 +421,19 @@
# Handle one-to-one and one-to-many relationships
else {
- # TODO XXX FIXME Add more triggers here...
+
+ # This has to be called specially because
+ # register_triggers_for_column gets called too early when the model
+ # class column is created, but the profile relationship does not
+ # yet exist.
+ CASPlus::ProfileMixin::register_triggers_for_column(
+ $args->{relation_child}->record_class,
+ $args->{child_column}->name,
+ );
+ CASPlus::ProfileMixin::register_triggers_for_column(
+ $args->{relation_parent}->record_class,
+ $args->{parent_column}->name,
+ );
}
}
Modified: apps/CASPlus/trunk/lib/CASPlus/ProfileMixin.pm
==============================================================================
--- apps/CASPlus/trunk/lib/CASPlus/ProfileMixin.pm (original)
+++ apps/CASPlus/trunk/lib/CASPlus/ProfileMixin.pm Wed Aug 29 12:48:41 2007
@@ -4,6 +4,8 @@
package CASPlus::ProfileMixin;
use base qw/ Jifty::DBI::Record::Plugin /;
+use Scalar::Util qw/ looks_like_number /;
+
use Jifty::DBI::Schema;
use CASPlus::Record schema {
};
@@ -18,105 +20,224 @@
=cut
-# =head2 register_triggers
-#
-# This is run automatically while the profile is being constructed. It adds a C<after_set_column_name> trigger for each relationship the profile belongs to. This trigger is used to recalculate user role caches when a relationship is added or removed.
-#
-# =cut
-#
-# sub register_triggers {
-# my $self = shift;
-#
-# my $profile = CASPlus::Model::Profile->new;
-# $profile->load_by_profile_object($self);
-#
-# my $parent_relationships = $profile->parent_relationships;
-# while (my $relationship = $parent_relationships->next) {
-# if ($relationship->roles_propagate_to_children
-# and !$relationship->many_children) {
-#
-# $self->add_trigger(
-# name => 'after_' . $relationship->child_column->name,
-# callback => \&after_set_child_relationship,
-# );
-# }
-# }
-#
-# my $child_relationships = $profile->child_relationships;
-# while (my $relationship = $child_relationships->next) {
-# if ($relationship->roles_propagate_to_children
-# and !$relationship->many_parents) {
-#
-# $self->add_trigger(
-# name => 'after_' . $relationship->parent_column->name,
-# callback => \&after_set_parent_relationship,
-# );
-# }
-# }
-# }
-#
-# =head2 after_set_child_relationship
-#
-# This is a hook that is called automatically before modifying a column that points to a child in a relationship. This makes sure that the roles of all children, grandchildren, great-grandchildren, etc. are modified to start inheriting from this object and it's predecessors if the relationship is being added or stop if the relationship is being set to C<undef>.
-#
-# =cut
-#
-# sub after_set_child_relationship {
-# my $self = shift;
-# my $args = shift;
-#
-# my $column = $args->{column};
-# my $new_value = $args->{value};
-# my $old_value = $self->$column;
-#
-# $new_value = (ref $new_value ? $new_value->id : $new_value) || 0;
-# $old_value = (ref $old_value ? $old_value->id : $old_value) || 0;
-#
-# return unless $new_value != $old_value;
-#
-# my $profile = CASPlus::Model::Profile->new;
-# $profile->load_by_profile_object($self);
-#
-# my $relationship = CASPlus::Model::ProfileRelationship->new;
-# $relationship->load_by_cols(
-# relation_parent => $profile,
-# child_column => $column,
-# );
-#
-# if ($new_value) {
-# my $new_child = $relationship->relation_child->record_class->new;
-# $new_child->load($new_value);
-#
-# $new_child->_add_roles_to_child_cache($self);
-# }
-#
-# if ($old_value) {
-# my $old_child = $relationship->relation_child->record_class->new;
-# $old_child->load($old_value);
-#
-# $self->_remove_roles_from_child_cache($self);
-# }
-# }
-#
-# =head2 after_set_parent_relationship
-#
-# This is a hook that is called automatically before modifying a column that points to a parent in a relationship. This makes sure that the roles of this object, it's children, grandchildren, great-grandchildren, etc. are modified to start inheriting from the parent object and it's predecessors if the relationship is being added or stop if the relationship is being set to C<undef>.
-#
-# =cut
-#
-# sub after_set_parent_relationship {
-# my $self = shift;
-# my $args = shift;
-#
-# my $column = $args->{column};
-# my $new_value = $args->{value};
-# my $old_value = $self->$column;
-#
-# $new_value = (ref $new_value ? $new_value->id : $new_value) || 0;
-# $old_value = (ref $old_value ? $old_value->id : $old_value) || 0;
-#
-# $self->_replace_roles_in_child_cache($old_value => $new_value)
-# if $new_value != $old_value;
-# }
+=head2 register_triggers_for_column
+
+This is run automatically while the profile is being constructed. It adds a C<after_set_column_name> trigger for each relationship the profile belongs to. This trigger is used to recalculate user role caches when a relationship is added or removed.
+
+=cut
+
+sub register_triggers_for_column {
+ my $self = shift;
+ my $column = shift;
+
+ # Load the profile definition for this object
+ my $profile = CASPlus::Model::Profile->new;
+ $profile->load_by_profile_object($self);
+
+ # Load the model class column record for the column being registered
+ my $model_class_column = Jifty::Model::ModelClassColumn->new;
+ $model_class_column->load_by_cols(
+ model_class => $profile->model_class,
+ name => $column,
+ );
+ return unless $model_class_column->id; # don't continue if not found
+
+ # Load the parent relationship to see if this is a child column
+ my $parent_relationship = CASPlus::Model::ProfileRelationship->new;
+ $parent_relationship->load_by_cols(
+ relation_child => $profile,
+ child_column => $model_class_column,
+ );
+
+ # Did we find a relationship? Does it need to track roles? Is this the
+ # one-to-X end of the relationship?
+ if ($parent_relationship->id
+ and $parent_relationship->roles_propagate_to_children
+ and !$parent_relationship->many_parents) {
+
+ $self->add_trigger(
+ name => 'before_set_' . $column,
+ callback => \&before_set_child_relationship,
+ );
+ $self->add_trigger(
+ name => 'after_set_' . $column,
+ callback => \&after_set_child_relationship,
+ );
+ }
+
+ # Load the child relationship to see if this is a parent column
+ my $child_relationship = CASPlus::Model::ProfileRelationship->new;
+ $child_relationship->load_by_cols(
+ relation_parent => $profile,
+ parent_column => $model_class_column,
+ );
+
+ # Did we find a relationship? Does it need to track roles? Is this the
+ # one-to-X end of the relationships?
+ if ($child_relationship->id
+ and $child_relationship->roles_propagate_to_children
+ and !$child_relationship->many_children) {
+
+ $self->add_trigger(
+ name => 'before_set_' . $column,
+ callback => \&before_set_parent_relationship,
+ );
+ $self->add_trigger(
+ name => 'after_set_' . $column,
+ callback => \&after_set_parent_relationship,
+ );
+ }
+}
+
+=head2 before_set_child_relationship
+
+Triggered before setting the child of this object. Saves the old value for reference in L</after_set_child_relationship>.
+
+=cut
+
+sub before_set_child_relationship {
+ my $self = shift;
+ my $args = shift;
+
+ my $column = $args->{column};
+ my $old_value = $self->$column;
+
+ $self->{"__set_${column}_relationship_old"} = $old_value;
+
+ return 1;
+}
+
+=head2 after_set_child_relationship
+
+Handles updating the role membership cache for the column.
+
+=cut
+
+sub after_set_child_relationship {
+ my $self = shift;
+ my $args = shift;
+
+ my $column = $args->{column};
+ my $new_value = $args->{value};
+ my $old_value = delete $self->{"__set_${column}_relationship_old"};
+
+ my $profile = CASPlus::Model::Profile->new;
+ $profile->load_by_profile_object($self);
+
+ my $model_class_column = Jifty::Model::ModelClassColumn->new;
+ $model_class_column->load_by_cols(
+ model_class => $profile->model_class,
+ name => $column,
+ );
+
+ my $relationship = CASPlus::Model::ProfileRelationship->new;
+ $relationship->load_by_cols(
+ relation_child => $profile,
+ child_column => $model_class_column,
+ );
+
+ if (looks_like_number($new_value)) {
+ my $object = $relationship->relation_child->record_class->new;
+ $object->load($new_value);
+ $new_value = $object;
+ }
+
+ if (defined $old_value and $old_value->id) {
+# Test::More::diag("CHILD DEL :@{[$old_value->unique_id]}:\@@{[$relationship->id]}:@{[$self->unique_id]}:");
+ CASPlus::Util::Relationship->remove_relationship(
+ child => $self,
+ relationship => $relationship,
+ parent => $old_value,
+ );
+ }
+
+ if (defined $new_value and $new_value->id) {
+# Test::More::diag("CHILD ADD :@{[$new_value->unique_id]}:\@@{[$relationship->id]}:@{[$self->unique_id]}:");
+ CASPlus::Util::Relationship->add_relationship(
+ child => $self,
+ relationship => $relationship,
+ parent => $new_value,
+ );
+ }
+}
+
+=head2 before_set_parent_relationship
+
+Triggered before setting the child of this object. Saves the old value for reference in L</after_set_parent_relationship>.
+
+=cut
+
+sub before_set_parent_relationship {
+ my $self = shift;
+ my $args = shift;
+
+ my $column = $args->{column};
+ my $old_value = $self->$column;
+
+ Test::More::diag("new_value = @{[$args->{value}]}");
+
+ $self->{"__set_${column}_relationship_old"} = $old_value;
+
+ return 1;
+}
+
+
+=head2 after_set_parent_relationship
+
+Handles updating the role membership cache for the column.
+
+=cut
+
+sub after_set_parent_relationship {
+ my $self = shift;
+ my $args = shift;
+
+ my $column = $args->{column};
+ my $new_value = $args->{value};
+ my $old_value = delete $self->{"__set_${column}_relationship_old"};
+
+ Test::More::diag("self = @{[$self->id.'/'.$self->unique_id]}");
+
+ my $profile = CASPlus::Model::Profile->new;
+ $profile->load_by_profile_object($self);
+
+ my $model_class_column = Jifty::Model::ModelClassColumn->new;
+ $model_class_column->load_by_cols(
+ model_class => $profile->model_class,
+ name => $column,
+ );
+
+ my $relationship = CASPlus::Model::ProfileRelationship->new;
+ $relationship->load_by_cols(
+ relation_parent => $profile,
+ parent_column => $model_class_column,
+ );
+
+ if (looks_like_number($new_value)) {
+ my $object = $relationship->relation_parent->record_class->new;
+ $object->load($new_value);
+ $new_value = $object;
+ }
+
+ Test::More::diag("new_value = @{[$new_value->id.'/'.$new_value->unique_id]}");
+
+ if (defined $old_value and $old_value->id) {
+# Test::More::diag("PARENT DEL :@{[$self->unique_id]}:\@@{[$relationship->id]}:@{[$old_value->unique_id]}:");
+ CASPlus::Util::Relationship->remove_relationship(
+ child => $old_value,
+ relationship => $relationship,
+ parent => $self,
+ );
+ }
+
+ if (defined $new_value and $new_value->id) {
+# Test::More::diag("PARENT ADD :@{[$self->unique_id]}:\@@{[$relationship->id]}:@{[$new_value->unique_id]}:");
+ CASPlus::Util::Relationship->add_relationship(
+ child => $new_value,
+ relationship => $relationship,
+ parent => $self,
+ );
+ }
+}
1;
Modified: apps/CASPlus/trunk/lib/CASPlus/ProfileRelationshipMixin.pm
==============================================================================
--- apps/CASPlus/trunk/lib/CASPlus/ProfileRelationshipMixin.pm (original)
+++ apps/CASPlus/trunk/lib/CASPlus/ProfileRelationshipMixin.pm Wed Aug 29 12:48:41 2007
@@ -132,47 +132,12 @@
my ($child, $relationship, $parent)
= @{ delete $self->{__delete_relationship} };
- # Create abbreviated names for the IDs in the cache path
- my $cid = $self->child->unique_id;
- my $rid = $relationship->id;
- my $pid = $self->parent->unique_id;
-
- # Build the cache path matcher
- my $cache_path = ":$cid:\@$rid:$pid:";
-
- # Load the cache paths that are affected
- my $cache_paths = CASPlus::Model::RoleMemberPathCacheCollection->new;
- $cache_paths->limit(
- column => 'cache_path',
- operator => 'MATCHES',
- value => $cache_path,
+ # Remove the relationship
+ CASPlus::Util::Relationship->remove_relationship(
+ child => $child,
+ relationship => $relationship,
+ parent => $parent,
);
-
- # Delete them, these are all removed
- while (my $path_cache = $cache_paths->next) {
- $path_cache->delete;
- }
-
- # Load the role memberships that now have an empty cache path
- my $role_members = CASPlus::Model::RoleMemberCollection->new;
- $cache_paths = $role_members->join(
- column1 => 'id',
- table2 => 'CASPlus::Model::RoleMemberPathCache',
- column2 => 'role_member',
- );
- $role_members->group_by({
- column => 'id',
- });
- $cache_paths->limit(
- 'column' => 'cache_path',
- 'function' => 'COUNT',
- 'value' => 0,
- );
-
- # Delete these role memberships, they no longer hold
- while (my $role_member = $role_members->next) {
- $role_member->delete;
- }
}
# Delete wasn't carried out, but still clear the cached info
Modified: apps/CASPlus/trunk/lib/CASPlus/Util/Relationship.pm
==============================================================================
--- apps/CASPlus/trunk/lib/CASPlus/Util/Relationship.pm (original)
+++ apps/CASPlus/trunk/lib/CASPlus/Util/Relationship.pm Wed Aug 29 12:48:41 2007
@@ -31,6 +31,8 @@
my $class = shift;
my %args = @_;
+ Test::More::diag("ADDING :@{[$args{parent}->unique_id]}:\@@{[$args{relationship}->id]}:@{[$args{child}->unique_id]}:");
+
$class->add_immediate_relationship(%args);
$class->add_append_relationships(%args);
$class->add_prepend_relationships(%args);
@@ -202,6 +204,69 @@
}
}
+=head2 remove_relationship
+
+ CASPlus::Util::Relationship->remove_relationship(
+ parent => $parent,
+ relationship => $relationship,
+ child => $child,
+ );
+
+Breaks the relationship between the given parent and child objects that are linked by the given relationship.
+
+=cut
+
+sub remove_relationship {
+ my $class = shift;
+ my %args = @_;
+
+ my ($child, $relationship, $parent)
+ = @args{qw/ child relationship parent /};
+
+ # Create abbreviated names for the IDs in the cache path
+ my $cid = $child->unique_id;
+ my $rid = $relationship->id;
+ my $pid = $parent->unique_id;
+
+ # Build the cache path matcher
+ my $cache_path = ":$cid:\@$rid:$pid:";
+
+ # Load the cache paths that are affected
+ my $cache_paths = CASPlus::Model::RoleMemberPathCacheCollection->new;
+ $cache_paths->limit(
+ column => 'cache_path',
+ operator => 'MATCHES',
+ value => $cache_path,
+ );
+
+ # Delete them, these are all removed
+ while (my $path_cache = $cache_paths->next) {
+ $path_cache->delete;
+ }
+
+ # Load the role memberships that now have an empty cache path
+ my $role_members = CASPlus::Model::RoleMemberCollection->new;
+ $cache_paths = $role_members->join(
+ column1 => 'id',
+ table2 => CASPlus::Model::RoleMemberPathCache->table,
+ column2 => 'role_member',
+ );
+ $role_members->group_by({
+ column => 'id',
+ });
+ $role_members->limit(
+ 'alias' => $cache_paths,
+ 'column' => 'cache_path',
+ 'function' => 'COUNT',
+ 'value' => 0,
+ );
+
+ # Delete these role memberships, they no longer hold
+ while (my $role_member = $role_members->next) {
+ $role_member->delete;
+ }
+}
+
=head2 recalculate_role_cache_for_object
CASPlus::Util::Relationship->recalculate_role_cache_for_object($object);
Added: apps/CASPlus/trunk/t/40-many-to-one_relationships-explicit.t
==============================================================================
--- (empty file)
+++ apps/CASPlus/trunk/t/40-many-to-one_relationships-explicit.t Wed Aug 29 12:48:41 2007
@@ -0,0 +1,652 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use List::Util qw/ sum /;
+use Jifty::Test tests => 128;
+
+my $system_user = CASPlus::CurrentUser->superuser;
+
+my $role_profile = CASPlus::Model::Profile->new(current_user => $system_user);
+$role_profile->create(
+ name => 'generic role',
+ profile_type => 'role',
+);
+ok($role_profile->id, 'created a role profile');
+
+my $other_profile = CASPlus::Model::Profile->new(current_user => $system_user);
+$other_profile->create(
+ name => 'generic other',
+ profile_type => 'other',
+);
+ok($other_profile->id, 'created an other profile');
+
+my $user_profile = CASPlus::Model::Profile->new(current_user => $system_user);
+$user_profile->create(
+ name => 'generic user',
+ profile_type => 'user',
+);
+ok($user_profile->id, 'created a user profile');
+
+my $ur_relationship = CASPlus::Model::ProfileRelationship->new(current_user => $system_user);
+$ur_relationship->create(
+ name => 'user-role',
+ parent_name => 'my_roles',
+ child_name => 'my_user',
+ relation_parent => $role_profile,
+ relation_child => $user_profile,
+ many_parents => 1,
+ many_children => 0,
+ roles_propagate_to_children => 1,
+);
+ok($ur_relationship->id, 'created a user-role relationship');
+
+my $uo_relationship = CASPlus::Model::ProfileRelationship->new(current_user => $system_user);
+$uo_relationship->create(
+ name => 'user-other',
+ parent_name => 'my_others',
+ child_name => 'my_user',
+ relation_parent => $other_profile,
+ relation_child => $user_profile,
+ many_parents => 1,
+ many_children => 0,
+ roles_propagate_to_children => 1,
+);
+ok($ur_relationship->id, 'created a user-other relationship');
+
+my $rr_relationship = CASPlus::Model::ProfileRelationship->new(current_user => $system_user);
+$rr_relationship->create(
+ name => 'role-role',
+ parent_name => 'my_parent_roles',
+ child_name => 'my_child_role',
+ relation_parent => $role_profile,
+ relation_child => $role_profile,
+ many_parents => 1,
+ many_children => 0,
+ roles_propagate_to_children => 1,
+);
+ok($rr_relationship->id, 'created a role-role relationship');
+
+my $or_relationship = CASPlus::Model::ProfileRelationship->new(current_user => $system_user);
+$or_relationship->create(
+ name => 'other-role',
+ parent_name => 'my_roles',
+ child_name => 'my_other',
+ relation_parent => $role_profile,
+ relation_child => $other_profile,
+ many_parents => 1,
+ many_children => 0,
+ roles_propagate_to_children => 1,
+);
+ok($or_relationship->id, 'created a other-role relationship');
+
+my $user = CASPlus::Model::User->new(current_user => $system_user);
+my $role = CASPlus::Model::Role->new(current_user => $system_user);
+my $permission = CASPlus::Model::ProfilePermission->new(current_user => $system_user);
+
+my $user_class = $user_profile->record_class;
+my $other_class = $other_profile->record_class;
+my $role_class = $role_profile->record_class;
+
+my $ur_class = $ur_relationship->record_class;
+my $uo_class = $uo_relationship->record_class;
+my $or_class = $or_relationship->record_class;
+my $rr_class = $rr_relationship->record_class;
+
+# Create some test objects
+
+{ # user-1 : unique ID 1
+ $user->create(
+ username => 'user-1',
+ password => 'test',
+ );
+ ok($user->id, 'created user-1');
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->create(
+ user_object => $user,
+ );
+ ok($user->id, 'created user-1 profile');
+ is($user_obj->unique_id, 1, 'created user-1 unique ID');
+}
+
+{ # role-1 : unique ID 2
+ $role->create(
+ name => 'role-1',
+ );
+ ok($role->id, 'created role-1');
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->create(
+ role_object => $role,
+ );
+ ok($role_obj->id, 'created role-1 profile');
+ is($role_obj->unique_id, 2, 'created role-1 unique ID');
+}
+
+{ # role-2 : unique ID 3
+ $role->create(
+ name => 'role-2',
+ );
+ ok($role->id, 'created role-2');
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->create(
+ role_object => $role,
+ );
+ ok($role_obj->id, 'created role-2 profile');
+ is($role_obj->unique_id, 3, 'created role-2 unique ID');
+}
+
+{ # first <other> : unique ID 4
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->create();
+ ok($other_obj->id, 'created first <other> profile');
+ is($other_obj->unique_id, 4, 'created first <other> unique ID');
+}
+
+{ # user-2 : unique ID 5
+ $user->create(
+ username => 'user-2',
+ password => 'test',
+ );
+ ok($user->id, 'created user-2');
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->create(
+ user_object => $user,
+ );
+ ok($user_obj->id, 'created user-2 profile');
+ is($user_obj->unique_id, 5, 'created user-2 unique ID');
+}
+
+{ # second <other> : unique ID 6
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->create();
+ ok($other_obj->id, 'created second <other> profile');
+ is($other_obj->unique_id, 6, 'created second <other> unique ID');
+}
+
+{ # role-3 : unique ID 7
+ $role->create(
+ name => 'role-3',
+ );
+ ok($role->id, 'created role-3');
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->create(
+ role_object => $role,
+ );
+ ok($role_obj->id, 'created role-3 profile');
+ is($role_obj->unique_id, 7, 'created role-3 unique ID');
+}
+
+{ # user-3 : unique ID 8
+ $user->create(
+ username => 'user-3',
+ password => 'test',
+ );
+ ok($user->id, 'created user-3');
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->create(
+ user_object => $user,
+ );
+ ok($user_obj->id, 'created user-3 profile');
+ is($user_obj->unique_id, 8, 'created user-3 unique ID');
+}
+
+{ # role-4 : unique ID 9
+ $role->create(
+ name => 'role-4',
+ );
+ ok($role->id, 'created role-4');
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->create(
+ role_object => $role,
+ );
+ ok($role_obj->id, 'created role-4 profile');
+ is($role_obj->unique_id, 9, 'created role-4 unique ID');
+}
+
+{ # user-4 : unique ID 10
+ $user->create(
+ username => 'user-4',
+ password => 'test',
+ );
+ ok($user->id, 'created user-4');
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->create(
+ user_object => $user,
+ );
+ ok($user_obj->id, 'created user-4 profile');
+ is($user_obj->unique_id, 10, 'created user-4 unique ID');
+}
+
+{ # role-5 : unique ID 11
+ $role->create(
+ name => 'role-5',
+ );
+ ok($role->id, 'created role-5');
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->create(
+ role_object => $role,
+ );
+ ok($role_obj->id, 'created role-5 profile');
+ is($role_obj->unique_id, 11, 'created role-5 unique ID');
+}
+
+# Create the relationships
+
+{ # user-2 - first <other> relationshifirstp
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->load(2);
+ ok($user_obj->id, 'loaded user-2');
+
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->load(1);
+ ok($other_obj->id, 'loaded first <other>');
+
+ is($user_obj->unique_id, 5);
+ is($other_obj->unique_id, 4);
+
+ $other_obj->set_my_user($user_obj);
+
+ $other_obj->load(1);
+ $user_obj->load(2);
+
+ is($other_obj->my_user->id, 2, 'other side of user-2 - first <other> relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $user_obj->my_others->items_array_ref } ],
+ [ 1 ],
+ 'user side of user-2 - first <other> relationship'
+ );
+}
+
+{ # first <other> - role-2 relationship
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->load(2);
+ ok($role_obj->id, 'loaded role-2');
+
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->load(1);
+ ok($other_obj->id, 'loaded first <other>');
+
+ $role_obj->set_my_other($other_obj);
+
+ $role_obj->load(2);
+ $other_obj->load(1);
+
+ is($role_obj->my_other->id, 1, 'other side of first <other> - role-2 relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $other_obj->my_roles->items_array_ref } ],
+ [ 2 ],
+ 'user side of first <other> - role-2 relationship'
+ );
+}
+
+{ # user-4 - second <other> relationship
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->load(4);
+ ok($user_obj->id, 'loaded user-4');
+
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->load(2);
+ ok($other_obj->id, 'loaded second <other>');
+
+ $other_obj->set_my_user($user_obj);
+
+ $user_obj->load(4);
+ $other_obj->load(2);
+
+ is($other_obj->my_user->id, 4, 'other side of user-4 - second <other> relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $user_obj->my_others->items_array_ref } ],
+ [ 2 ],
+ 'user side of user-4 - second <other> relationship'
+ );
+}
+
+{ # role-1 - role-3 relationship
+ my $parent_role_obj = $role_class->new(current_user => $system_user);
+ $parent_role_obj->load(3);
+ ok($parent_role_obj->id, 'loaded role-3');
+
+ my $child_role_obj = $role_class->new(current_user => $system_user);
+ $child_role_obj->load(1);
+ ok($child_role_obj->id, 'loaded role-1');
+
+ $parent_role_obj->set_my_child_role($child_role_obj);
+
+ $parent_role_obj->load(3);
+ $child_role_obj->load(1);
+
+ is($parent_role_obj->my_child_role->id, 1, 'parent side of role-1 - role-3 relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $child_role_obj->my_parent_roles->items_array_ref } ],
+ [ 3 ],
+ 'user side of user-1 - role-3 relationship'
+ );
+}
+
+{ # user-3 - role-1 relationship
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->load(3);
+ ok($user_obj->id, 'loaded user-3');
+
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->load(1);
+ ok($role_obj->id, 'loaded role-1');
+
+ $role_obj->set_my_user($user_obj);
+
+ $user_obj->load(3);
+ $role_obj->load(1);
+
+ is($role_obj->my_user->id, 3, 'role side of user-3 - role-1 relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $user_obj->my_roles->items_array_ref } ],
+ [ 1 ],
+ 'user side of user-3 - role-1 relationship'
+ );
+}
+
+{ # first <other> - role-4 relationship
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->load(4);
+ ok($role_obj->id, 'loaded role-4');
+
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->load(1);
+ ok($other_obj->id, 'loaded first <other>');
+
+ $role_obj->set_my_other($other_obj);
+
+ $role_obj->load(4);
+ $other_obj->load(1);
+
+ is($role_obj->my_other->id, 1, 'other side of first <other> - role-4 relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $other_obj->my_roles->items_array_ref } ],
+ [ 2, 4 ],
+ 'user side of first <other> - role-4 relationship'
+ );
+}
+
+{ # user-1 - role-1 relationship
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->load(1);
+ ok($user_obj->id, 'loaded user-1');
+
+ my $role_obj = $role_class->new(current_user => $system_user);
+ $role_obj->load(1);
+ ok($role_obj->id, 'loaded role-1');
+
+ $role_obj->set_my_user($user_obj);
+
+ $role_obj->load(1);
+ $user_obj->load(1);
+
+ is($role_obj->my_user->id, 1, 'role side of user-1 - role-1 relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $user_obj->my_roles->items_array_ref } ],
+ [ 1 ],
+ 'user side of user-1 - role-1 relationship'
+ );
+}
+
+{ # user-3 - first <other> relationship
+ my $user_obj = $user_class->new(current_user => $system_user);
+ $user_obj->load(3);
+ ok($user_obj->id, 'loaded user-3');
+
+ my $other_obj = $other_class->new(current_user => $system_user);
+ $other_obj->load(1);
+ ok($other_obj->id, 'loaded first <other>');
+
+ $other_obj->set_my_user($user_obj);
+
+ $user_obj->load(3);
+ $other_obj->load(1);
+
+ is($other_obj->my_user->id, 3, 'other side of user-3 - first <other> relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $user_obj->my_others->items_array_ref } ],
+ [ 1 ],
+ 'user side of user-4 - second <other> relationship'
+ );
+}
+
+{ # role-1 - role-2 relationship
+ my $parent_role_obj = $role_class->new(current_user => $system_user);
+ $parent_role_obj->load(2);
+ ok($parent_role_obj->id, 'loaded role-2');
+
+ my $child_role_obj = $role_class->new(current_user => $system_user);
+ $child_role_obj->load(1);
+ ok($child_role_obj->id, 'loaded role-1');
+
+ $parent_role_obj->set_my_child_role($child_role_obj);
+
+ $parent_role_obj->load(2);
+ $child_role_obj->load(1);
+
+ is($parent_role_obj->my_child_role->id, 1, 'parent side of role-1 - role-2 relationship');
+ is_deeply(
+ [ sort map { $_->id } @{ $child_role_obj->my_parent_roles->items_array_ref } ],
+ [ 2, 3 ],
+ 'user side of user-1 - role-2 relationship'
+ );
+}
+
+# Create the permissions
+
+{ # permissions for role-1
+ $role->load(1);
+ is($role->id, 1, 'loaded role-1');
+
+ my $profile_obj = CASPlus->get_profile_object_by_unique_id(int(rand(11)) + 1);
+ ok($profile_obj->id, 'loaded a random profile object');
+
+ $permission->create(
+ the_role => $role,
+ profile => $profile_obj,
+ may_create => int(rand(1)),
+ may_create_my_own => int(rand(1)),
+ may_read => int(rand(1)),
+ may_read_my_own => int(rand(1)),
+ may_write => int(rand(1)),
+ may_write_my_own => int(rand(1)),
+ may_delete => int(rand(1)),
+ may_delete_my_own => int(rand(1)),
+ );
+ ok($permission->id, "created a permission for role-1");
+}
+
+{ # permissions for role-2
+ $role->load(2);
+ is($role->id, 2, 'loaded role-2');
+
+ for ( 1 .. 3 ) {
+ my $profile_obj = CASPlus->get_profile_object_by_unique_id(int(rand(11)) + 1);
+ ok($profile_obj->id, 'loaded a random profile object');
+
+ $permission->create(
+ the_role => $role,
+ profile => $profile_obj,
+ may_create => int(rand(1)),
+ may_create_my_own => int(rand(1)),
+ may_read => int(rand(1)),
+ may_read_my_own => int(rand(1)),
+ may_write => int(rand(1)),
+ may_write_my_own => int(rand(1)),
+ may_delete => int(rand(1)),
+ may_delete_my_own => int(rand(1)),
+ );
+ ok($permission->id, "created a permission for role-2");
+ }
+}
+
+{ # permissions for role-3
+ $role->load(3);
+ is($role->id, 3, 'loaded role-3');
+
+ for ( 1 .. 3 ) {
+ my $profile_obj = CASPlus->get_profile_object_by_unique_id(int(rand(11)) + 1);
+ ok($profile_obj->id, 'loaded a random profile object');
+
+ $permission->create(
+ the_role => $role,
+ profile => $profile_obj,
+ may_create => int(rand(1)),
+ may_create_my_own => int(rand(1)),
+ may_read => int(rand(1)),
+ may_read_my_own => int(rand(1)),
+ may_write => int(rand(1)),
+ may_write_my_own => int(rand(1)),
+ may_delete => int(rand(1)),
+ may_delete_my_own => int(rand(1)),
+ );
+ ok($permission->id, "created a permission for role-3");
+ }
+}
+
+{ # permissions for role-4
+ $role->load(4);
+ is($role->id, 4, 'loaded role-4');
+
+ for ( 1 .. 3 ) {
+ my $profile_obj = CASPlus->get_profile_object_by_unique_id(int(rand(11)) + 1);
+ ok($profile_obj->id, 'loaded a random profile object');
+
+ $permission->create(
+ the_role => $role,
+ profile => $profile_obj,
+ may_create => int(rand(1)),
+ may_create_my_own => int(rand(1)),
+ may_read => int(rand(1)),
+ may_read_my_own => int(rand(1)),
+ may_write => int(rand(1)),
+ may_write_my_own => int(rand(1)),
+ may_delete => int(rand(1)),
+ may_delete_my_own => int(rand(1)),
+ );
+ ok($permission->id, "created a permission for role-4");
+ }
+}
+
+{ # permissions for role-5
+ $role->load(5);
+ is($role->id, 5, 'loaded role-4');
+
+ for ( 1 .. 3 ) {
+ my $profile_obj = CASPlus->get_profile_object_by_unique_id(int(rand(11) + 1));
+ ok($profile_obj->id, 'loaded a random profile object');
+
+ $permission->create(
+ the_role => $role,
+ profile => $profile_obj,
+ may_create => int(rand(1)),
+ may_create_my_own => int(rand(1)),
+ may_read => int(rand(1)),
+ may_read_my_own => int(rand(1)),
+ may_write => int(rand(1)),
+ may_write_my_own => int(rand(1)),
+ may_delete => int(rand(1)),
+ may_delete_my_own => int(rand(1)),
+ );
+ ok($permission->id, "created a permission for role-5");
+ }
+}
+
+my %user_results = (
+ 1 => {
+ roles => [ 1, 2, 3 ],
+ perms => [ 1, 2, 3, 4, 5, 6, 7 ],
+ },
+ 2 => {
+ roles => [ 2, 4 ],
+ perms => [ 2, 3, 4, 8, 9, 10 ],
+ },
+ 3 => {
+ roles => [ 1, 2, 3, 4 ],
+ perms => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ],
+ },
+ 4 => {
+ roles => [ ],
+ perms => [ ],
+ },
+);
+
+my %role_members = (
+ '' => [
+ ':5:@2:4:',
+ ':4:@4:3:',
+ ':10:@2:6:',
+ ':2:@3:7:',
+ ':4:@4:9:',
+ ':8:@2:4:',
+ ':2:@3:3:',
+ ],
+ 1 => [
+ ':5:@2:4:@4:3:',
+ ],
+ 2 => [
+ ':8:@1:2:',
+ ],
+ 3 => [
+ ':8:@1:2:@3:7:',
+ ],
+ 4 => [
+ ':5:@2:4:@4:9:',
+ ],
+ 5 => [
+ ':1:@1:2:',
+ ],
+ 6 => [
+ ':1:@1:2:@3:7:',
+ ],
+ 7 => [
+ ':8:@2:4:@4:3:',
+ ':8:@1:2:@3:3:',
+ ],
+ 8 => [
+ ':8:@2:4:@4:9:',
+ ],
+ 9 => [
+ ':1:@1:2:@3:3:',
+ ],
+);
+
+# Run the tests on the role cache built on-the-fly
+my $role_members = CASPlus::Model::RoleMemberCollection->new(current_user => $system_user);
+$role_members->unlimit;
+is($role_members->count_all, (scalar keys %role_members) - 1, 'there are the right number of role members');
+
+my $cache_paths = CASPlus::Model::RoleMemberPathCacheCollection->new(current_user => $system_user);
+$cache_paths->unlimit;
+is($cache_paths->count_all, (sum map { scalar @$_ } values %role_members), 'there are the right number of cache paths');
+
+while (my $path_cache = $cache_paths->next) {
+ diag($path_cache->cache_path);
+}
+
+my $profiles = CASPlus::Model::ProfileCollection->new(current_user => $system_user);
+$profiles->unlimit;
+while (my $profile = $profiles->next) {
+ my $collection_class = $profile->record_class->collection_class;
+ my $objects = $collection_class->new(current_user => $system_user);
+ $objects->unlimit;
+ while (my $object = $objects->next) {
+ $object->recalculate_role_cache;
+
+ # Run the tests on the role cache built by total recalculation
+ $role_members = CASPlus::Model::RoleMemberCollection->new(current_user => $system_user);
+ $role_members->unlimit;
+ is($role_members->count_all, (scalar keys %role_members) - 1, 'there are the right number of role members');
+
+ $cache_paths = CASPlus::Model::RoleMemberPathCacheCollection->new(current_user => $system_user);
+ $cache_paths->unlimit;
+ is($cache_paths->count_all, (sum map { scalar @$_ } values %role_members), 'there are the right number of cache paths');
+ }
+
+}
+
+
+#while (my $path_cache = $cache_paths->next) {
+# diag($path_cache->cache_path);
+#}
More information about the Jifty-commit
mailing list