# Copyright (c) 2006 bivio Software, Inc. All Rights Reserved. # # Visit http://www.bivio.biz for more info. # # This library is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 2.1 of the # License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; If not, you may get a copy from: # http://www.opensource.org/licenses/lgpl-license.html # # $Id: RoleBaseList.pm,v 1.19 2011/06/08 21:38:26 moeller Exp $ package Bivio::Biz::Model::RoleBaseList; use strict; use Bivio::Base 'Biz.ListModel'; our($VERSION) = sprintf('%d.%02d', q$Revision: 1.19 $ =~ /\d+/g); my($_C) = b_use('SQL.Connection'); my($_R) = b_use('Auth.Role'); b_die('v0: no longer supported') unless b_use('IO.Config')->if_version(1); my($_ROLES_ORDER) = [map($_R->unsafe_from_name($_) ? $_R->$_() : (), qw( ADMINISTRATOR ACCOUNTANT MEMBER GUEST WITHDRAWN FILE_WRITER MAIL_RECIPIENT UNAPPROVED_APPLICANT ))]; foreach my $r ($_R->get_non_zero_list) { push(@$_ROLES_ORDER, $r) unless grep($r == $_, @$_ROLES_ORDER); } my($i) = 1; my($_ROLES_ORDERING) = {map(($_ => $i++), @$_ROLES_ORDER)}; my($_CACHE) = {}; sub LOAD_ALL_SIZE { return 3000; } sub ROLES_ORDER { return [@{$_ROLES_ORDER}]; } sub internal_cache_key { my($self) = @_; return __PACKAGE__; } sub internal_initialize { my($self) = @_; return $self->merge_initialize_info($self->SUPER::internal_initialize, { can_iterate => 1, version => 1, other => [ 'RealmUser.role', 'RealmUser.creation_date_time', 'RealmUser.user_id', 'RealmUser.realm_id', { name => 'roles', type => 'String', constraint => 'NONE', b_use('ShellUtil.SQL')->is_oracle ? ( in_select => 1, select_value => q{(SELECT group_concat( CAST( MULTISET( SELECT role FROM realm_user_t ru WHERE ru.realm_id = realm_user_t.realm_id AND ru.user_id = realm_user_t.user_id ) AS t_string_list ) ) FROM realm_user_t ru WHERE ru.realm_id = realm_user_t.realm_id AND ru.user_id = realm_user_t.user_id GROUP BY realm_user_t.user_id ) AS roles}, ) : ( in_select => 1, select_value => q{(SELECT group_concat(ru.role || '') FROM realm_user_t ru WHERE ru.realm_id = realm_user_t.realm_id AND ru.user_id = realm_user_t.user_id ) AS roles}, ), }, ], where => [ 'RealmUser.role', '= (SELECT MIN(role) FROM realm_user_t ru WHERE', 'RealmUser.realm_id', '= ru.realm_id AND', 'RealmUser.user_id', '= ru.user_id)', ], }); } sub internal_post_load_row { my($self, $row) = @_; return 0 unless shift->SUPER::internal_post_load_row(@_); _roles($self, $row); return 1; } sub internal_prepare_statement { my($self) = shift; my($stmt) = @_; $self->internal_qualify_role($stmt); return $self->SUPER::internal_prepare_statement(@_); } sub internal_qualify_role { my($self, $stmt) = @_; my($r) = $self->internal_qualifying_roles; $stmt->where($stmt->IN('RealmUser.role', $r)) if $r && @$r; return; } sub internal_qualifying_roles { return []; } #could cache this, too sub roles_by_category { my($self, $roles) = @_; my($map) = {map(($_ => 1), @{$roles ||= $self->get('roles') || []})}; my($main) = []; foreach my $m (@{$_R->get_category_role_group('all_users')}) { push(@$main, $m) if delete($map->{$m}); } return ( $self->roles_in_order($main), $self->roles_in_order([grep($map->{$_}, @$roles)]), ); } #can be private sub roles_in_order { my($self, $roles) = @_; $roles ||= $self->get('roles'); return [sort({ $_ROLES_ORDERING->{$a} <=> $_ROLES_ORDERING->{$b}; } @$roles)]; } sub _roles { my($self, $row) = @_; my($res) = ($_CACHE->{$self->internal_cache_key} ||= {})->{$row->{roles}} ||= _roles_compute($self, $row); $row->{roles} = $res->[0]; $row->{'RealmUser.role'} = $res->[1]; return; } sub _roles_compute { my($self, $row) = @_; my($main, $aux) = $self->roles_by_category( [map($_R->from_sql_column($_), split(/,/, $row->{roles}))], ); my($roles) = [@$main, @$aux]; $main = $aux unless @$main; return [$roles, $main->[$#$main]]; } 1;