Changeset 861
- Timestamp:
- 12/02/11 11:42:17 (12 years ago)
- Files:
-
- 108 added
- 104 edited
Legend:
- Unmodified
- Added
- Removed
-
LATMOS-Accounts-Web/Changes
r94 r861 1 1 This file documents the revision history for Perl extension LATMOS::Accounts::Web. 2 2 3 2.0.0 4 - add support of nethost/netzone object 5 6 - add a "My" page in user page listing object they own 7 8 - add icons to quickly identify user's account status in list (temporary, 9 expired, unexported) 10 11 - add a department page in group page with a realistic view of the current 12 people in the department. The section appear only when group have 13 sutype=dpmt 14 15 - add link to objects when attributes have reference 16 3 17 0.01 2009-05-12 03:23:51 4 18 - initial revision, generated by Catalyst -
LATMOS-Accounts-Web/MANIFEST
r757 r861 1 1 Changes 2 MANIFEST 3 MANIFEST.skip 2 4 Makefile.PL 3 5 README 4 6 etc/httpd/latmos-accounts-web.conf 5 7 etc/init.d/latmos-accounts-web 6 inc/Module/AutoInstall.pm7 inc/Module/Install/AutoInstall.pm8 inc/Module/Install/Base.pm9 inc/Module/Install/Can.pm10 inc/Module/Install/Catalyst.pm11 inc/Module/Install/Fetch.pm12 inc/Module/Install/Include.pm13 inc/Module/Install/Makefile.pm14 inc/Module/Install/Metadata.pm15 inc/Module/Install/Scripts.pm16 inc/Module/Install/Win32.pm17 inc/Module/Install/WriteAll.pm18 inc/Module/Install.pm19 8 latmos-accounts-web.spec.in 20 9 latmos_accounts_web.yml.in 21 10 lib/Catalyst/Authentication/Credential/La.pm 11 lib/LATMOS/Accounts/Web/Controller/About.pm 22 12 lib/LATMOS/Accounts/Web/Controller/Ajax.pm 23 13 lib/LATMOS/Accounts/Web/Controller/Aliases.pm 24 14 lib/LATMOS/Accounts/Web/Controller/Create.pm 25 15 lib/LATMOS/Accounts/Web/Controller/Groups.pm 26 lib/LATMOS/Accounts/Web/Controller/MassEdit.pm 16 lib/LATMOS/Accounts/Web/Controller/NetHosts.pm 17 lib/LATMOS/Accounts/Web/Controller/NetZones.pm 27 18 lib/LATMOS/Accounts/Web/Controller/Root.pm 28 19 lib/LATMOS/Accounts/Web/Controller/Sites.pm … … 36 27 lib/LATMOS/Accounts/Web.pm 37 28 root/favicon.ico 29 root/html/about/index.tt 38 30 root/html/ajax/attrvalues.tt 39 31 root/html/ajax/check_new_name.tt 40 32 root/html/ajax/check_ug_validity.tt 41 33 root/html/ajax/cracklib.tt 34 root/html/ajax/displayattr.tt 42 35 root/html/ajax/objattrexist.tt 43 36 root/html/ajax/objexist.tt 44 37 root/html/ajax/rawattr.tt 38 root/html/ajax/select_freeip_select.tt 45 39 root/html/aliases/index.tt 46 root/html/create/group.tt 47 root/html/create/user.tt 40 root/html/create/default.tt 48 41 root/html/default.tt 49 42 root/html/departments/default.tt … … 51 44 root/html/departments/menu.tt 52 45 root/html/groups/default.tt 46 root/html/groups/dpmt.tt 53 47 root/html/groups/index.tt 54 48 root/html/groups/menu.tt … … 61 55 root/html/login.tt 62 56 root/html/logout.tt 63 root/html/massedit/index.tt 57 root/html/nethosts/default.tt 58 root/html/nethosts/index.tt 59 root/html/nethosts/menu.tt 60 root/html/netzones/default.tt 61 root/html/netzones/index.tt 62 root/html/netzones/menu.tt 64 63 root/html/no_object.tt 65 64 root/html/sites/default.tt … … 75 74 root/html/users/mail.tt 76 75 root/html/users/menu.tt 76 root/html/users/my.tt 77 77 root/html/users/passwd.tt 78 root/static/icons/add.png 79 root/static/icons/appointment-new.png 80 root/static/icons/appointment-soon.png 78 81 root/static/icons/arrow-right.png 82 root/static/icons/avatar-default.png 83 root/static/icons/changes-prevent.png 79 84 root/static/icons/dialog-cancel.png 85 root/static/icons/dialog-password.png 86 root/static/icons/document-save-as.png 87 root/static/icons/document-save.png 88 root/static/icons/emblem-urgent.png 89 root/static/icons/icon_edit.png 90 root/static/icons/expired.png 91 root/static/icons/gnome-session-logout.png 92 root/static/icons/gnome-stock-mail-snd.png 93 root/static/icons/gtk-about.png 94 root/static/icons/gtk-cancel.png 95 root/static/icons/gtk-close.png 96 root/static/icons/gtk-delete.png 97 root/static/icons/gtk-go-back-ltr.png 98 root/static/icons/gtk-go-back-rtl.png 99 root/static/icons/gtk-goto-first-ltr.png 100 root/static/icons/gtk-goto-first-rtl.png 101 root/static/icons/gtk-home.png 102 root/static/icons/gtk-jump-to-rtl.png 103 root/static/icons/locked.png 104 root/static/icons/mail_forward.png 105 root/static/icons/network-workgroup.png 106 root/static/icons/preferences-desktop-wallpaper.png 107 root/static/icons/stock_smiley-22.png 108 root/static/icons/system-config-users.png 109 root/static/icons/system-users.png 80 110 root/static/icons/user-group-delete.png 81 111 root/static/icons/user-group-new.png 82 112 root/static/icons/user-group-properties.png 113 root/static/icons/user-info.png 114 root/static/icons/user-invisible.png 83 115 root/static/icons/user-properties.png 116 root/static/icons/video-display.png 84 117 root/static/icons/view-calendar-day.png 118 root/static/icons/view-media-artist.png 119 root/static/icons/xfce-internet.png 85 120 root/static/images/btn_120x50_built.png 86 121 root/static/images/btn_120x50_built_shadow.png … … 98 133 root/static/images/mail-mark-important.png 99 134 root/static/images/process-stop.png 100 root/static/images/view-media-artist.png101 135 root/static/images/view-pim-contacts.png 102 136 root/static/js/CalendarPopup.js … … 114 148 t/02pod.t 115 149 t/03podcoverage.t 150 t/controller_About.t 116 151 t/controller_Ajax.t 117 152 t/controller_Aliases.t … … 119 154 t/controller_Groups.t 120 155 t/controller_MassEdit.t 156 t/controller_NetHost.t 121 157 t/controller_Sites.t 122 158 t/controller_Users.t -
LATMOS-Accounts-Web/Makefile.PL
r552 r861 4 4 all_from 'lib/LATMOS/Accounts/Web.pm'; 5 5 6 requires 'Catalyst' => '5.7015';6 #requires 'Catalyst' => '5.7015'; 7 7 requires 'Catalyst::Plugin::ConfigLoader'; 8 8 requires 'Catalyst::Plugin::Static::Simple'; … … 20 20 21 21 install_script glob('script/*.pl'); 22 auto_install; 23 WriteAll; 22 #auto_install; 23 WriteMakefile( 24 macro => { 25 DESTRPMDIR => '$(shell pwd)', 26 }, 27 ); 24 28 25 29 package MY; … … 27 31 sub postamble { 28 32 <<EOF; 29 .PHONY .= svnmanifest33 # .PHONY .= svnmanifest 30 34 31 35 svnmanifest: … … 39 43 40 44 rpm: \$(DISTVNAME).tar.gz latmos-accounts-web.spec 41 \tmkdir ./noarch || :45 \tmkdir \$(DESTRPMDIR)/noarch || : 42 46 \trpmbuild -ba --clean\\ 43 47 \t --define "_sourcedir `pwd`" \\ 44 48 \t --define "_specdir `pwd`" \\ 45 \t --define "_srcrpmdir `pwd`" \\ 46 \t --define "_rpmdir `pwd`" \\ 49 \t --define "_srcrpmdir \$(DESTRPMDIR)" \\ 50 \t --define "_rpmdir \$(DESTRPMDIR)" \\ 51 \t latmos-accounts-web.spec 52 53 svnrpm: \$(DISTVNAME).tar.gz latmos-accounts-web.spec 54 \tmkdir \$(DESTRPMDIR)/noarch || : 55 \trpmbuild -ba --clean\\ 56 \t --define "_sourcedir `pwd`" \\ 57 \t --define "_specdir `pwd`" \\ 58 \t --define "_srcrpmdir \$(DESTRPMDIR)" \\ 59 \t --define "_rpmdir \$(DESTRPMDIR)" \\ 60 \t --define "svnrelease `LC_ALL=C svn info | grep '^Revision:' | sed 's/Revision: //'`" \\ 47 61 \t latmos-accounts-web.spec 48 62 -
LATMOS-Accounts-Web/latmos-accounts-web.spec.in
r737 r861 2 2 %define name latmos-accounts-web 3 3 %define version @VERSION@ 4 %define release %mkrel 14 %define release %mkrel %{?svnrelease:0.%{svnrelease}}%{?!svnrelease:1} 5 5 6 6 Name: %{name} … … 81 81 fi 82 82 83 %triggerpostun -- latmos-accounts 84 /sbin/service %name restart 85 83 86 %files 84 87 %defattr(-,root,root) -
LATMOS-Accounts-Web/latmos_accounts_web.yml.in
r97 r861 1 1 --- 2 2 name: LATMOS::Accounts::Web 3 # config: /etc/latmos-accounts/latmos-accounts.ini 4 # company: COMPANY NAME -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web.pm
r860 r861 24 24 /; 25 25 26 our $VERSION = ' 0.0.11';26 our $VERSION = '2.0.0'; 27 27 28 28 # Configure the application. 29 # 30 # Note that settings in LATMOS::Accounts::Web.yml (or other external 31 # configuration file that you set up manually) take precedence 32 # over this when using ConfigLoader. Thus configuration 33 # details given here can function as a default configuration, 34 # with a external configuration file acting as an override for 35 # local deployment. 29 30 my $config_file = '/etc/latmos-accounts/latmos-accounts-web.yml'; 31 if (-r $config_file ) { 32 __PACKAGE__->config( 'Plugin::ConfigLoader' => { 33 file => $config_file 34 } 35 ); 36 } 36 37 37 38 # http://stackoverflow.com/questions/1664816/is-there-a-way-to-force-c-urifor-in-catalyst-to-generate-a-uri-that-begins-wit -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller.pm
r718 r861 25 25 26 26 if (!$c->user_exists) { 27 if ($c->req->path ne 'login') { 28 $c->forward('/login'); 27 # No need to login for About section 28 if ($c->namespace ne 'about') { 29 if ($c->req->path ne 'login') { 30 $c->forward('/login'); 31 } 32 return; 29 33 } 30 34 } else { 31 $c->model('Accounts')->db->connect($c->user->{username}, 35 $c->model('Accounts')->db->connect( 36 $c->user->{username}, 32 37 $c->user->{password}); 33 38 } 34 35 my $menu = '';36 my @menus = (37 [ 'users' => 'Utilisateurs' ],38 ($c->model('Accounts')->db->check_acl('user', '@CREATE', 'w')39 ? [ 'create/user' => 'Nouvel Util.' ]40 : ()),41 [ 'groups' => 'Groupes' ],42 ($c->model('Accounts')->db->check_acl('group', '@CREATE', 'w')43 ? [ 'create/group' => 'Nouveau Groupe' ]44 : ()),45 [ 'sites' => 'Sites' ],46 [ 'aliases' => 'Alias Mail' ],47 );48 foreach(@menus) {49 $menu .= sprintf(50 q{<a href="%s"><span%s>%s</span></a>},51 $c->uri_for('/' . $_->[0]),52 ($c->req->path =~ m:^$_->[0]: ? ' id="actif"' : ''),53 $_->[1],54 );55 56 }57 $c->stash->{mainmenu} = $menu;58 39 } 59 40 -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller/Ajax.pm
r755 r861 45 45 } 46 46 47 sub displayattr : Local { 48 my ($self, $c, $otype) = @_; 49 my $attribute = $c->model('Accounts')->db->attribute($otype, 50 $c->req->param('attr')) or return; 51 $c->stash->{value} = $attribute->display($c->req->param('id')); 52 } 53 47 54 sub attrvalues : Local { 48 55 my ($self, $c, $otype, $attr) = @_; … … 63 70 64 71 $c->stash->{'exists'} = join(', ', $obj->get_attributes($c->req->param('attr') || 65 'displayName') ) if($obj);72 'displayName') || $obj->id) if($obj); 66 73 } 67 74 … … 88 95 my ($self, $c, $otype, $attr) = @_; 89 96 my $base = $c->model('Accounts')->db; 90 my $val = $c->req->param('val'); 97 my $attribute = $base->attribute($otype, $attr) or return; 98 my $val = $attribute->input($c->req->param('val')); 91 99 my @obj = $val ? $base->search_objects($otype, "$attr=$val") : (); 92 100 … … 125 133 } 126 134 135 sub select_freeip_select : Local { 136 my ($self, $c) = @_; 137 138 } 139 140 sub goto : Local { 141 my ($self, $c) = @_; 142 143 $c->res->redirect( 144 $c->uri_for('/' . $c->req->param('otype') . 's', $c->req->param('goto'), 145 $c->req->param('subform')) 146 ); 147 $c->stash->{template} = 'no_object.tt'; 148 } 149 150 127 151 sub end : Private { 128 152 my ( $self, $c ) = @_; -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller/Aliases.pm
r641 r861 29 29 my @name = $c->req->param('name'); 30 30 my @forward = $c->req->param('forward'); 31 $c->stash->{page}{title} = "Gestion des alias"; 31 32 foreach my $idx (0 .. scalar(@name) - 1) { 32 33 -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller/Create.pm
r765 r861 5 5 use base 'LATMOS::Accounts::Web::Controller'; 6 6 use LATMOS::Accounts::Utils; 7 use LATMOS::Accounts::Log; 7 8 8 9 =head1 NAME … … 29 30 } 30 31 31 sub user : Local { 32 my ( $self, $c ) = @_; 33 32 sub default : LocalPath { 33 my ($self, $c, undef, $otype ) = @_; 34 34 my $base = $c->model('Accounts')->db; 35 $c->stash->{form} = $c->model('AttrForms', undef, 'user', $base); 36 for ($c->req->param('step') || '') { 37 /^1$/ and do { 38 $c->stash->{step} = 2; 39 my $acc = $c->model('Accounts')->accounts; 40 foreach ($acc->Parameters('_defattr_')) { 41 if (/^user\.(.*)/) { 42 $c->req->params->{$1} ||= $acc->val('_defattr_', $_); 43 } 44 } 45 $c->req->params->{exported} = 1; 46 if (! $c->req->params->{id}) { 47 for (1) { 48 my $login; 49 if ($c->req->param('sn')) { 50 $login = lc(to_ascii($c->req->param('sn'))); 51 length($login) > 10 and $login = substr($login, 0, 8); 52 $base->get_object('user', $login) or do { 53 $c->req->params->{id} = $login; 54 last; 55 }; 56 if ($c->req->param('givenName')) { 57 length($login) > 8 and $login = substr($login, 0, 8); 58 $login .= substr(lc(to_ascii($c->req->param('givenName'))), 0, 1); 59 $base->get_object('user', $login) or do { 60 $c->req->params->{id} = $login; 61 last; 62 }; 63 } 64 } 65 } 66 67 my $mailid = $c->req->params->{givenName} && $c->req->params->{sn} 68 ? sprintf('%s.%s', 69 to_ascii(lc($c->req->params->{givenName})), 70 to_ascii(lc($c->req->params->{sn})),) 71 : undef; 72 73 if ($mailid && 74 $base->is_supported_object('aliases') && 75 ! $base->get_object('aliases', $mailid)) { 76 if ($base->get_field_name('user', 'mail', 'write')) { 77 if ($base->{defattr}{'user.maildomain'}) { 78 $c->req->params->{mail} ||= sprintf('%s@%s', 79 $mailid, 80 $base->{defattr}{'user.maildomain'}); 81 } 82 } 83 if ($base->get_field_name('user', 'aliases', 'write')) { 84 $c->req->params->{aliases} ||= $mailid; 85 } 86 warn $base->get_field_name('user', 'revaliases', 'write'); 87 if ($base->get_field_name('user', 'revaliases', 'write')) { 88 $c->req->params->{revaliases} ||= $mailid; 89 } 90 } 91 } 92 last; 93 }; 94 /^2$/ and do { 95 $c->stash->{step} = 2; 96 $c->req->params->{id} or return; 97 $base->get_object('user', $c->req->params->{id}) and do { 98 $c->stash->{idexists} = 1; 99 return; 100 }; 101 $base->create_c_object('user', $c->req->params->{id}, 102 %{ $c->req->params }, 103 exported => $c->req->param('exported') ? 1 : 0, 104 ) or return; 105 $base->commit; 106 $c->res->redirect($c->uri_for('/users', $c->req->params->{id})); 107 last; 108 }; 35 my ($step) = $c->req->param('step'); 36 my $form = $c->model('AttrForms', undef, $otype, $base); 37 my ($status, $info); 38 $c->stash->{page}{title} = "Ajouter un objet / $otype"; 39 if ($step) { 40 $info = $c->session->{ochelper}; 109 41 } 42 if ($info->{name}{ask}) { 43 $info->{name}{content} = $c->req->param('_name'); 44 } 45 foreach my $attr (@{$info->{ask} || []}) { 46 $info->{contents}{$attr} = $c->req->param($form->attr_field_name($attr)); 47 } 48 my $ochelper = $base->ochelper($otype); 49 ($status, $info) = $ochelper->step($info); 50 51 if ($status eq 'CREATED') { 52 $base->commit; 53 $c->res->redirect($c->uri_for('/' . $otype . 's', 54 $info->{name}{content})); 55 } elsif ($status eq 'ERROR') { 56 # On error, restart the process 57 $c->stash->{page}{error} = 58 'Erreur lors de la création de l\'objet: ' . 59 LATMOS::Accounts::Log::lastmessage(LA_ERR); 60 foreach my $attr (@{$info->{ask} || []}) { 61 $c->req->params->{$form->attr_field_name($attr)} = $info->{contents}{$attr}; 62 } 63 $info->{step} = 0; # reset 64 ($status, $info) = $ochelper->step($info); 65 } else { 66 foreach my $attr (@{$info->{ask} || []}) { 67 $c->req->params->{$form->attr_field_name($attr)} = $info->{contents}{$attr}; 68 } 69 } 70 $c->stash->{form} = $form; 71 $c->stash->{ochelper} = $info; 72 $c->session->{ochelper} = $info; 110 73 } 111 74 112 sub group : Local {113 my ( $self, $c ) = @_;114 115 my $base = $c->model('Accounts')->db;116 $c->stash->{form} = $c->model('AttrForms', undef, 'group', $base);117 if (!exists($c->req->params->{id})) {118 $c->req->params->{exported} = 1;119 }120 121 if ($c->req->params->{id}) {122 $base->get_object('group', $c->req->params->{id}) and do {123 $c->stash->{idexists} = 1;124 return;125 };126 $base->create_c_object('group', $c->req->params->{id},127 %{ $c->req->params },128 exported => $c->req->param('exported') ? 1 : 0,129 ) or return;130 $base->commit;131 $c->res->redirect($c->uri_for('/groups', $c->req->params->{id}));132 }133 }134 75 135 76 =head1 AUTHOR -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller/Groups.pm
r718 r861 27 27 $c->stash->{ofilter} = $c->model('AttrFilter', 'group'); 28 28 $c->stash->{groupslist} = [ map { $_->id } @{ $c->stash->{objectslist} } ]; 29 $c->stash->{page}{title} = "Liste des groupes"; 29 30 30 31 } … … 35 36 my $base = $c->model('Accounts')->db; 36 37 38 $c->stash->{page}{title} = "Groupe :: $groupname"; 37 39 $c->stash->{groupname} = $groupname; 38 40 $c->stash->{group} = $base->get_object('group', $groupname) or do { … … 65 67 last; 66 68 }; 69 /^dpmt$/ and do { 70 $c->stash->{template} = 'groups/dpmt.tt'; 71 my @filter = (); 72 push(@filter, 'active=*') if (!$c->req->param('inactive')); 73 push(@filter, 'mail=*') if ($c->req->param('mail')); 74 push(@filter, 'company=' . $c->req->param('company')) if 75 ($c->req->param('company')); 76 $c->stash->{dpmt} = $groupname; 77 $c->stash->{odpmt} = $c->stash->{group}; 78 $c->stash->{user} = [ $base->search_objects('user', 79 'department=' . $c->stash->{dpmt}, 80 @filter, 81 ) ]; 82 foreach my $u ($base->search_objects('user', 83 'memberOf=' . $c->stash->{dpmt}, 84 @filter, 85 )) { 86 push(@{$c->{stash}->{guser}}, $u) 87 unless(grep { $u eq $_ } @{$c->stash->{user}}); 88 } 89 last; 90 }; 67 91 68 92 $c->stash->{form} = $c->model('AttrForms', 'group' . $c->stash->{subform}, $c->stash->{group}); -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller/Sites.pm
r718 r861 27 27 $c->stash->{ofilter} = $c->model('AttrFilter', 'site'); 28 28 $c->stash->{siteslist} = [ map { $_->id } @{ $c->stash->{objectslist} } ]; 29 $c->stash->{page}{title} = "Liste des sites"; 29 30 } 30 31 … … 34 35 my $base = $c->model('Accounts')->db; 35 36 37 $c->stash->{page}{title} = "Site :: $sitename"; 36 38 $c->stash->{sitename} = $sitename; 37 39 $c->stash->{site} = $base->get_object('site', $sitename) or do { -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Controller/Users.pm
r759 r861 43 43 $c->stash->{initials} = [ sort keys %initials ]; 44 44 } 45 $c->stash->{page}{title} = 'Listes des utilisateurs (' . scalar(@{ 46 $c->stash->{objectslist} }) . ')'; 45 47 $c->stash->{userslist} = \@userlist; 46 48 } … … 51 53 my $base = $c->model('Accounts')->db; 52 54 55 $c->stash->{page}{title} = "Utilisateur :: $username"; 53 56 $c->stash->{username} = $username; 54 57 $c->stash->{user} = $base->get_object('user', $username) or do { … … 57 60 }; 58 61 $c->stash->{subform} = $subform || ''; 62 $c->stash->{page}{title} = "Utilisateur :: $username"; 59 63 60 64 for ($subform || '') { … … 155 159 last; 156 160 }; 161 /^my$/ and do { 162 $c->stash->{db} = $base; 163 $c->stash->{template} = 'users/my.tt'; 164 }; 157 165 /^dump$/ and do { 158 166 $c->stash->{db} = $base; -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Model/Accounts.pm
r791 r861 56 56 } 57 57 58 sub object_navigate { 59 my ($self, $otype, $id, @filter) = @_; 60 61 my @list = $self->db->search_objects($otype, @filter); 62 63 my $i = 0; 64 for($i = 0; $i <= $#list; $i++) { 65 $list[$i] eq $id and last; 66 } 67 68 my %ptr = (); 69 $ptr{oprev} = $list[$i-1] if ($i > 0); 70 $ptr{'onext'} = $list[$i+1] if ($i < $#list); 71 $ptr{ofirst} = $list[0] if ($i > 1); 72 $ptr{'olast'} = $list[$#list] if ($i < $#list -1); 73 $ptr{list} = \@list; 74 75 return \%ptr; 76 } 77 58 78 # Such function must not be here, but in LATMOS::Accounts 59 79 # But code does not allow this at time -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Model/AttrFilter.pm
r638 r861 19 19 group => [ qw(cn description gidNumber sutype) ], 20 20 site => [ qw(l) ], 21 nethost => [ qw(name cname otherName ip macaddr owner serialNumber) ], 22 netzone => [ qw(net group type site) ], 21 23 }; 22 24 -
LATMOS-Accounts-Web/lib/LATMOS/Accounts/Web/Model/AttrForms.pm
r804 r861 4 4 use warnings; 5 5 use base 'Catalyst::Model'; 6 use LATMOS::Accounts::Log; 6 7 7 8 =head1 NAME … … 39 40 sutype => [ 'Structure admin.', 'select-N:sutype' ], 40 41 exported => [ 'Propagé', 'label' ], 42 unexported => [ 'Caché' ], 41 43 locked => [ 'Vérouillé', 'checkbox:l' ], 42 44 isMainAddress => [ 'Adresse principale', 'checkbox' ], … … 54 56 contratType => [ 'Type de contrat', 'select-N:group/sutype=contrattype' ], 55 57 managerContact => [ 'Contact' ], 58 owner => [ 'Propriétaire' ], 59 description => [ 'Description' ], 60 name => [ 'Nom' ], 61 net => [ "Réseau" ], 62 macaddr => [ "Adresse Ethernet" ], 63 noDynamic => [ "Pas d'adressage dyn." ], 64 cname => [ "Alias (CName)" ], 65 type => [ "Type" ], 66 netExclude => [ "Réseau exclus" ], 67 output => [ "Sortie" ], 68 template => [ "ModÚle" ], 69 outputD => [ "Sortie" ], 70 templateD => [ "ModÚle" ], 71 group => [ "Groupe" ], 72 allow_dyn => [ "DHCP dynamique" ], 73 ipCount => [ "Nb d'IP" ], 74 freeIPCount => [ "Nb d'IP libres" ], 75 dnsRevision => [ "Révision DNS" ], 76 lastUpdate => [ "DerniÚre mise à jour "], 77 otherName => [ "Autres noms (A)" ], 78 'reverse' => [ "Forcer le reverse à " ], 79 dynFrom => [ 'Sans Ip depuis' ], 80 siteNick => [ 'Acronyme' ], 81 serialNumber => [ 'N° de série' ], 82 snNative => [ 'Nom d\'origine' ], 83 givenNameNative => [ 'Prénom d\'origine' ], 84 wWWHomePage => [ 'Site Web' ], 85 halReference => [ 'Référence HAL' ], 56 86 }; 57 87 … … 64 94 mail initials nickname 65 95 locked 66 exported67 96 create 68 97 date … … 76 105 ) ], 77 106 }, 78 userstatu s=> {79 name => 'Statu s',107 userstatut => { 108 name => 'Statut', 80 109 attrs => [ qw( 81 110 company … … 87 116 ) ], 88 117 }, 118 usermy => { 119 name => 'My', 120 attrs => [ qw( 121 snNative 122 givenNameNative 123 wWWHomePage 124 halReference 125 ) ], 126 }, 89 127 site => { 90 128 name => 'Site', 91 129 attrs => [ qw( 92 130 description 131 siteNick 93 132 streetAddress 94 133 postOfficeBox … … 115 154 site 116 155 co 117 exported156 unexported 118 157 description 119 158 ) ], … … 124 163 gidNumber description 125 164 managedBy 126 sutype exported165 sutype 127 166 create 128 167 date 168 ) ], 169 }, 170 nethost => { 171 name => 'Ordinateur', 172 attrs => [ qw( 173 name 174 description 175 serialNumber 176 owner 177 ip 178 macaddr 179 noDynamic 180 cname 181 otherName 182 reverse 183 create 184 date 185 unexported 186 ) ], 187 }, 188 netzone => { 189 name => 'Zone réseau', 190 attrs => [ qw( 191 name 192 description 193 type 194 net 195 netExclude 196 outputD 197 templateD 198 site 199 allow_dyn 200 dynFrom 201 domain 202 ipCount 203 freeIPCount 204 create 205 date 206 dnsRevision 207 lastUpdate 208 unexported 129 209 ) ], 130 210 }, … … 179 259 my ($self, $for) = @_; 180 260 grep { $_ } 181 grep { $self->base->check_acl($self->{object} || $self->otype, $_, 'r') } 182 grep { $self->base->get_field_name($self->otype, $_, $for || 'a') } 261 grep { $self->base->attribute($self->otype, $_) } 183 262 @{ $forms->{$self->{form}}->{attrs} }; 184 263 } … … 196 275 my ($self, $attr) = @_; 197 276 return $self->{c}->req->param($attr) || 198 ($self->{object} ? $self->{object}->get_c_field($attr) : '') 199 } 200 201 sub attr_field { 202 my ($self, $attr, $type) = @_; 203 my $modallow = $self->base->check_acl($self->{object} 204 ? ($self->{object}, $attr, 'w') 205 : ($self->otype, '@CREATE', 'w')); 206 $type ||= $attrs->{$attr}[1] || ''; 207 if (!($self->base->get_field_name($self->otype, $attr, 'w') && $modallow)) { 208 $type = 'label'; 209 } 210 # exception: gidNumber is used also in group, but we don't want 211 # group list here, really the number ! 212 $type = $modallow ? 'text-U:6' : 'label' if ($self->{otype} eq 'group' && $attr eq 'gidNumber'); 213 $type ||= 'text'; 214 215 my $htmlname = $self->escape(($self->{object} 277 ($self->{object} ? $self->{object}->get_attributes($attr) : '') 278 } 279 280 sub attr_field_name { 281 my ($self, $attr) = @_; 282 return ($self->{object} 216 283 ? $self->{object}->id . '_' 217 284 : '' 218 285 ) . $attr 219 ); 220 for ($type) { 221 /^textarea$/ and return sprintf( 222 '<textarea id="%s" name="%s" cols="40">%s</textarea>', 223 $self->escape($htmlname), 224 $self->escape($htmlname), 225 $self->escape($self->attr_raw_value($attr) || ''), 226 ); 227 /^label$/ and do { 228 my $field = $self->escape( 229 $self->attr_raw_value($attr) 230 ); 231 $field =~ s/\n/<br>/g; 232 return $field . sprintf('<input type="hidden" name="%s" value="%s">', 233 $self->escape($htmlname), ($self->attr_raw_value($attr) || '')); 234 }; 235 /^date$/ and do { 236 my ($date, $time) = split(/ /, $self->attr_raw_value($attr) || ''); 237 if ($date && $date =~ /^(\d+)-(\d+)-(\d+)$/) { 238 $date = "$3/$2/$1"; 239 } 240 my $html = "\n" . q{<SCRIPT LANGUAGE="JavaScript" ID="js13"> 241 var cal13 = new CalendarPopup(); 242 </SCRIPT>} . "\n"; 243 $html .= sprintf( 244 '<input type="text" id="%s" name="%s" value="%s" size="12">', 245 $self->escape($htmlname), 246 $self->escape($htmlname), 247 $self->escape($date) 248 ); 249 $html .= q{<DIV ID="testdiv1" STYLE="position:absolute;visibility:hidden;background-color:white;layer-background-color:white;"></DIV>}; 250 $html .= qq| 251 <A HREF="#" 252 onClick="cal13.select(document.forms[0].$htmlname,'${htmlname}_anc','dd/MM/yyyy');return false;" 253 TITLE="cal13.select(document.forms[0].$htmlname,'${htmlname}_anc','dd/MM/yyyy');return false;" 254 NAME="${htmlname}_anc" ID="${htmlname}_anc"> 255 <img src="| . $self->{c}->uri_for(qw(/static icons view-calendar-day.png)) 256 . qq{" style="ref"></A> 257 } . "\n"; 258 return $html; 259 }; 260 /^checkbox(?::(\w+))?$/ and do { 261 my $options = $1 || ''; 262 my $text = sprintf('<input type="checkbox" name="%s"%s>', 263 $self->escape($htmlname), 264 $self->attr_raw_value($attr) ? ' checked="yes"' : '' 265 ); 266 $text .= sprintf('<input type="hidden" name="%s">', 267 $self->escape($htmlname)); 268 if ($options =~ /l/) { 269 $text .= $self->attr_raw_value($attr) 270 ? ' ' . $self->attr_raw_value($attr) 271 : ''; 272 } 273 return $text; 274 }; 275 /^select(-\w+)?:([^:\/]+)(?:\/([^:]+))?(?::(.*))?/ and do { 276 my $options = $1 || ''; 277 my $otype = $2; 278 my $filter = $3; 279 my $keyfield = $4; 280 my $observe_keyfield = $keyfield || 'displayName'; 281 my $select = sprintf('<select id="%s" name="%s">', 282 $self->escape($htmlname), 283 $self->escape($htmlname)) . "\n"; 284 $select .= '<option value="">--</option>' . "\n" if ($options =~ /N/); 285 my $value = $self->attr_raw_value($attr) || ''; 286 my $initial_observed = ''; 287 foreach my $id (sort $filter 288 ? $self->base->search_objects($otype, $filter) 289 : $self->base->list_objects($otype)) { 290 my $val = $id; 291 if ($keyfield) { 292 my $obj = $self->base->get_object($otype, $id) or next; 293 $val = $obj->get_c_field($keyfield); 294 } 295 $select .= sprintf( 296 ' <option value="%s"%s>%s</option>', 297 $self->escape($val || ''), 298 $value eq $val ? ' selected="selected"' : '', 299 $self->escape($id || ''), 286 } 287 288 sub attr_field { 289 my ($self, $attr, $type) = @_; 290 291 my $attribute = ($self->{object} 292 ? $self->{object}->attribute($attr) 293 : $self->base->attribute($self->otype, $attr)) or return; 294 295 my $htmlname = $self->escape($self->attr_field_name($attr)); 296 297 my @html_fields; 298 foreach my $attr_raw_value ( 299 $attribute->{multiple} 300 ? ((grep { $_ } $self->attr_raw_value($attr)), 301 $attribute->readonly 302 ? () 303 : ('') 304 ) 305 : ($self->attr_raw_value($attr))) { 306 307 my $html_id = $htmlname . 308 (scalar(@html_fields) ? scalar(@html_fields) : ''); 309 310 my $html_field = ''; 311 for ($attribute->form_type) { 312 /^textarea$/i and do { 313 $html_field = sprintf( 314 '<textarea id="%s" name="%s" cols="40">%s</textarea>', 315 $self->escape($html_id), 316 $self->escape($htmlname), 317 $self->escape($attr_raw_value || ''), 300 318 ); 301 $select .= "\n"; 302 if($value eq $val) { 303 if (my $obj = $self->base->get_object($otype, $id)) { 304 $initial_observed = $obj->get_c_field($observe_keyfield) 305 || ''; 306 } 307 } 308 } 309 $select .= "</select>\n"; 310 $select .= $self->{c}->prototype->observe_field( $htmlname, { 311 update => "${htmlname}_span", 312 url => $self->{c}->uri_for('/ajax', 'rawattr', $otype), 313 frequency => 1, 314 with => "'attr=" . $observe_keyfield . 315 "&id='+element.options[element.selectedIndex].text", 316 }) . 317 qq|<span id="${htmlname}_span">$initial_observed</span>|; 318 return $select; 319 }; 320 /^text(-\w+)?(?::(\d+))?/ and do { 321 my $flag = $1 || ''; 322 if (my @allowed = $self->base->obj_attr_allowed_values( 323 $self->{otype}, $attr)) { 324 my $cvalue = $self->attr_raw_value($attr); 325 my $textf = sprintf('<select id="%s" name="%s">', 319 last; 320 }; 321 /^label$/i and do { 322 $attr_raw_value or last; 323 $html_field = $self->escape($attr_raw_value); 324 $html_field =~ s/\n/<br>/g; 325 $html_field .= sprintf('<input type="hidden" name="%s" value="%s">', 326 $self->escape($htmlname), ($attr_raw_value || '')); 327 last; 328 }; 329 /^date$/i and do { 330 my ($date, $time) = split(/ /, $self->attr_raw_value($attr) || ''); 331 if ($date && $date =~ /^(\d+)-(\d+)-(\d+)$/) { 332 $date = "$3/$2/$1"; 333 } 334 my $html = "\n" . q{<SCRIPT LANGUAGE="JavaScript" ID="js13"> 335 var cal13 = new CalendarPopup(); 336 </SCRIPT>} . "\n"; 337 $html .= sprintf( 338 '<input type="text" id="%s" name="%s" value="%s" size="12">', 339 $self->escape($html_id), 326 340 $self->escape($htmlname), 341 $self->escape($date) 342 ); 343 $html .= q{<DIV ID="testdiv1" STYLE="position:absolute;visibility:hidden;background-color:white;layer-background-color:white;"></DIV>}; 344 $html .= qq| 345 <A HREF="#" 346 onClick="cal13.select(document.getElementById('$html_id'),'${html_id}_anc','dd/MM/yyyy');return false;" 347 TITLE="Date" 348 NAME="${html_id}_anc" ID="${html_id}_anc"> 349 <img class="attr" src="| . $self->{c}->uri_for(qw(/static icons view-calendar-day.png)) 350 . qq{" style="ref"></A> 351 } . "\n"; 352 $html_field = $html; 353 last; 354 }; 355 /^checkbox(?::(\w+))?$/i and do { 356 my $options = $1 || ''; 357 $html_field = sprintf('<input type="checkbox" name="%s"%s>', 358 $self->escape($htmlname), 359 $attr_raw_value ? ' checked="yes"' : '' 360 ); 361 $html_field .= sprintf('<input type="hidden" name="%s">', 362 $self->escape($htmlname)); 363 if ($attribute->form_option('rawvalue')) { 364 $html_field .= $attr_raw_value 365 ? ' ' . $attr_raw_value 366 : ''; 367 } 368 last; 369 }; 370 /^LIST/ and do { 371 my $options = $1 || ''; 372 my $select = sprintf('<select id="%s" name="%s">', 373 $self->escape($html_id), 327 374 $self->escape($htmlname)) . "\n"; 328 $textf .= '<option value="">--</option>' . "\n"; 329 foreach (sort @allowed) { 330 $textf .= sprintf('<option value="%s"%s>%s</option>' . "\n", 331 $self->escape($_), 332 (($cvalue || '') eq $_ ? ' selected="selected"' : ''), 333 $self->escape($_), 375 $select .= '<option value="">--</option>' . "\n" 376 unless($attribute->mandatory); 377 my $value = $attr_raw_value || ''; 378 my $initial_observed = ''; 379 my @valslist; 380 foreach my $val (sort $attribute->can_values) { 381 push(@valslist, { 382 val => $val, 383 disp => $attribute->display($val || ''), 384 }); 385 } 386 foreach (sort { $a->{disp} cmp $b->{disp} } @valslist) { 387 $select .= sprintf( 388 ' <option value="%s"%s>%s</option>', 389 $self->escape($_->{val} || ''), 390 $value eq $_->{val} ? ' selected="selected"' : '', 391 $self->escape($_->{disp} || ''), 334 392 ); 335 } 336 $textf .= "</select>\n"; 337 return $textf; 338 } else { 339 my $textf = sprintf( 393 $select .= "\n"; 394 } 395 $select .= "</select>\n"; 396 397 $html_field = $select; 398 last; 399 }; 400 /^text(-\w+)?(?::(\d+))?/i and do { 401 my $flag = $1 || ''; 402 $html_field = sprintf( 340 403 '<input type="text" id="%s" name="%s" value="%s" size="%d">', 404 $self->escape($html_id), 341 405 $self->escape($htmlname), 342 $self->escape($htmlname), 343 $self->escape($self->attr_raw_value($attr)), 344 $2 || 30, 406 $self->escape($attr_raw_value), 407 $attribute->form_option('length') || 30, 345 408 ); 346 409 if ($flag =~ /A/) { 347 $textf .= qq|<span id="${htmlname}_auto_complete"></span>|; 348 $textf .= "\n"; 349 $textf .= $self->{c}->prototype->auto_complete_field( 350 $htmlname, 351 { 352 update => "${htmlname}_auto_complete", 353 url => $self->{c}->uri_for('/ajax', 'attrvalues', $self->otype, $attr), 354 indicator => "${htmlname}_stat", min_chars => 1, 355 with => "'val='+document.getElementById('$htmlname').value", 356 frequency => 2, 357 } 358 ); 359 } 360 if ($flag =~ /U/) { 361 $textf .= qq|<span id="${htmlname}_observer_uniq"></span>|; 362 $textf .= "\n"; 363 $textf .= $self->{c}->prototype->observe_field( 364 $htmlname, 365 { 366 update => "${htmlname}_observer_uniq", 367 url => $self->{c}->uri_for('/ajax', 'objattrexist', 368 $self->otype, $attr), 369 frequency => 2, 370 indicator => "${htmlname}_stat", min_chars => 1, 371 with => "'val='+document.getElementById('$htmlname').value" . 372 ($self->{object} ? "+'&exclude=" . $self->{object}->id . "'" : 373 ''), 374 } 375 ); 376 } 377 $textf .= qq|<span style="display:none" id="${htmlname}_stat">Searching...</span>|; 378 379 return $textf; 410 $html_field .= qq|<span id="${html_id}_auto_complete"></span>|; 411 $html_field .= "\n"; 412 $html_field .= $self->{c}->prototype->auto_complete_field( 413 $html_id, 414 { 415 update => "${html_id}_auto_complete", 416 url => $self->{c}->uri_for('/ajax', 'attrvalues', $self->otype, $attr), 417 indicator => "${html_id}_stat", min_chars => 1, 418 with => "'val='+document.getElementById('$html_id').value", 419 frequency => 2, 420 } 421 ); 422 } 423 if ($attribute->uniq) { 424 $html_field .= qq|<span class="inputvalidate" id="${html_id}_observer_uniq"></span>|; 425 $html_field .= "\n"; 426 $html_field .= $self->{c}->prototype->observe_field( 427 $html_id, 428 { 429 update => "${html_id}_observer_uniq", 430 url => $self->{c}->uri_for('/ajax', 'objattrexist', 431 $self->otype, $attr), 432 frequency => 2, 433 indicator => "${html_id}_stat", min_chars => 1, 434 with => "'val='+document.getElementById('$html_id').value" . 435 ($self->{object} ? "+'&exclude=" . $self->{object}->id . "'" : 436 ''), 437 } 438 ); 439 $html_field .= qq|<span style="display:none" id="${html_id}_stat">Searching...</span>|; 440 } 441 last; 442 }; 443 } 444 if (my $ref = $attribute->reference) { 445 my $uri_part= { 446 user => 'users', 447 group => 'groups', 448 nethost => 'nethosts', 449 netzone => 'netzones', 450 site => 'sites' 451 }->{$ref}; 452 my $text; 453 if ($self->base->attribute($ref, 'displayName')) { 454 if ($attr_raw_value && 455 (my $obj = $self->base->get_object($ref, $attr_raw_value))) 456 { 457 $text = $obj->get_attributes('displayName'); 458 } 459 460 $html_field .= $self->{c}->prototype->observe_field( $html_id, { 461 update => "${html_id}_span", 462 url => $self->{c}->uri_for('/ajax', 'rawattr', $ref), 463 frequency => 1, 464 with => "'attr=displayName" . 465 "&id=' + element.options[element.selectedIndex].text", 466 }) . "\n" if ($attribute->form_type =~ /list/i); 467 } elsif($attr_raw_value && $uri_part) { 468 $text = sprintf( 469 '<img class="attr" src="%s" title="%s">', 470 $self->{c}->uri_for('/static', 'icons', 'arrow-right.png'), 471 $attr_raw_value, 472 ) 380 473 } 381 }; 474 $html_field .= sprintf(qq{<span id="%s" style="margin-left: 1em">}, 475 "${html_id}_span"); 476 477 if (defined($text)) { 478 $html_field .= $uri_part 479 ? sprintf('<a href="%s">%s</a>', 480 $self->{c}->uri_for("/$uri_part", $attribute->display($attr_raw_value)), 481 $text,) 482 : $text; 483 } 484 485 $html_field .= "</span>\n"; 486 } 487 push(@html_fields, $html_field); 382 488 } 489 return join("<br>\n", @html_fields); 383 490 } 384 491 … … 391 498 } 392 499 500 sub write_attributes { 501 my ($self) = @_; 502 my @attrs; 503 foreach ($self->attributes) { 504 my $attr = ($self->{object} 505 ? $self->{object}->attribute($_) 506 : $self->base->attribute($self->otype, $_)) or next; 507 $attr->readonly and next; 508 push(@attrs, $_); 509 } 510 @attrs; 511 } 512 393 513 sub set_attrs { 394 514 my ($self) = @_; … … 396 516 my $prefix = $self->{object}->id . '_'; 397 517 my %fields; 398 foreach ( 399 grep { $self->base->get_field_name($self->otype, $_, 'w') } 400 $self->attributes) { 518 foreach ($self->write_attributes) { 519 my $attr = ($self->{object} 520 ? $self->{object}->attribute($_) 521 : $self->base->attribute($self->otype, $_)) or next; 401 522 if (($attrs->{$_}[1] || '') eq 'checkbox') { 402 523 $fields{$_} = $self->{c}->req->param("$prefix$_") ? 1 : 0; 524 } elsif ($attr->{multiple}) { 525 $fields{$_} = [ grep { $_ } $self->{c}->req->param("$prefix$_") ]; 403 526 } else { 404 527 $fields{$_} = $self->{c}->req->param("$prefix$_"); 405 528 } 406 529 } 407 $self->{object}->set_c_fields(%fields) or return; 530 $self->{object}->set_c_fields(%fields) or do { 531 $self->{c}->stash->{page}{error} = 532 LATMOS::Accounts::Log::lastmessage(LA_ERR); 533 $self->{object}->base->rollback; 534 return; 535 }; 408 536 $self->{object}->base->commit; 409 537 } -
LATMOS-Accounts-Web/root/html/ajax/objexist.tt
r500 r861 1 1 [% IF exists %] 2 <img src="[% c.uri_for('/static', 'images', 'dialog-cancel.png') %]">2 <img class="attr" src="[% c.uri_for('/static', 'images', 'dialog-cancel.png') %]"> 3 3 ([% exists %]) 4 4 [% ELSE %] 5 <img src="[% c.uri_for('/static', 'images', 'dialog-ok-apply.png') %]">5 <img class="attr" src="[% c.uri_for('/static', 'images', 'dialog-ok-apply.png') %]"> 6 6 [% END %] -
LATMOS-Accounts-Web/root/html/departments/default.tt
r148 r861 1 <!-- $Id: default.tt 432 2009-05-17 13:19:38Z nanardon $ -->1 <!-- $Id: default.tt 2800 2010-08-01 12:02:51Z nanardon $ --> 2 2 [% IF NOT department %] 3 3 No department [% departmentname | html %] found. -
LATMOS-Accounts-Web/root/html/departments/menu.tt
r148 r861 1 <!-- $Id: user_menu.tt 443 2009-05-18 03:52:21Z nanardon $ -->1 <!-- $Id: menu.tt 2800 2010-08-01 12:02:51Z nanardon $ --> 2 2 <div> 3 3 <table border="0"> -
LATMOS-Accounts-Web/root/html/groups/index.tt
r220 r861 10 10 <table border="0"> 11 11 <tr><td colspan="2">[% groupslist.size %] groupes</td></tr> 12 <tr><th>Nom</th><th>Description</th>< /tr>12 <tr><th>Nom</th><th>Description</th><th></th></tr> 13 13 [% FOREACH groupname = groupslist %] 14 14 [% group = db.get_object('group', groupname) %] 15 15 <tr> 16 <td>[% group.id | html %]</td> 17 <td>[% group.get_c_field('description') | truncate(30) | html %] 18 <a href="[% c.uri_for('/groups', groupname) %]"> 19 <img src="[% c.uri_for('/static', 'icons', 'arrow-right.png') %]" 16 <td><a href="[% c.uri_for('/groups', groupname) %]"> 17 <img src="[% c.uri_for('/static', 'icons', 'icon_edit.png') %]" 20 18 height="16" width="16" 21 19 alt="[% "edit " _ groupname | html %]"> 22 </a></td> 20 </a> [% group.id | html %]</td> 21 <td> 22 <span title="[% group.get_c_field('description') | html %]"> 23 [% group.get_c_field('description') | truncate(30) | html %] 24 </span> 25 </td> 23 26 </tr> 24 27 [% END %] -
LATMOS-Accounts-Web/root/html/groups/menu.tt
r544 r861 1 1 <!-- $Id$ --> 2 <div id="o menu">2 <div id="oinfo"> 3 3 [% INCLUDE 'includes/obj_prev_next.tt' objtype='group' objname=groupname %] 4 <table border="0"> 5 < tr><td>4 5 <div> 6 6 <img src="[% c.uri_for('/static', 'icons', 'user-group-properties.png') %]" 7 7 alt="[% "Groupe " _ groupname %]"> 8 </td> 9 <td> 10 [% groupname | html %]<br> 8 </div> 9 10 <div> 11 <p id="oname">[% groupname | html %]</p> 11 12 [% group.get_c_field('description') | html %] 12 </table> 13 <div style="clear: both;"></div> 13 </div> 14 15 </div> 16 <div style="clear: both;"></div> 17 <div id="omenu"> 14 18 <a href="[% c.uri_for(groupname) %]"><span [% 'id="oactive"' IF subform == '' %]>SystÚme</span></a> 15 19 <a href="[% c.uri_for(groupname, 'users') %]"><span [% 'id="oactive"' IF subform == 'users' %]>Utilisateurs</span></a> 20 [% IF group.get_attributes('sutype') == 'dpmt' %] 21 <a href="[% c.uri_for(groupname, 'dpmt') %]"><span [% 'id="oactive"' IF subform == 'dpmt' %]>Département</span></a> 22 [% END %] 16 23 </div> 24 <div style="clear: both;"></div> -
LATMOS-Accounts-Web/root/html/groups/users.tt
r756 r861 4 4 [% ELSE %] 5 5 6 [% modallow = c.model('Accounts').db.check_acl(group, 'memberUID', 'w') %] 6 [% modallow = c.model('Accounts').db.check_acl(group, 'memberUID', 'w') AND 7 NOT group.attribute('memberUID').ro %] 7 8 8 9 <div class="objectform" id="objectform"> … … 19 20 <b>Membres primaire:</b><br> 20 21 [% END %] 21 <a href="[% c.uri_for('/users', uid) %]">[% uid | html %]</a><br> 22 <a href="[% c.uri_for('/users', uid) %]">[% uid | html %]</a> 23 [% ouser = c.model('Accounts').db.get_object('user', uid) %] 24 [% INCLUDE user_flag ouser=ouser %] 25 <br> 22 26 [% END %] 23 27 24 28 [% FOREACH uid = group.get_c_field('member').sort %] 29 [% ouser = c.model('Accounts').db.get_object('user', uid) %] 25 30 [% IF loop.first %] 26 31 <b>Membres</b><br> 27 32 [% END %] 28 33 [% IF modallow %] 29 <form action="[% c.uri_for(groupname, subform) %]" method="POST"> 34 [% IF ouser.get_attributes('department') == group.id OR 35 ouser.get_attributes('contratType') == group.id %] 36 <img src="[% c.uri_for('/static', 'icons', 'changes-prevent.png') %]" 37 width="24" height="24" title="Ce groupe est géré via un autre attribut"> 38 [% ELSE %] 39 <form action="[% c.uri_for(groupname, subform) %]" method="POST" style="display: inline"> 30 40 <input type="hidden" name="deluser" value="[% uid | html %]"> 31 41 <input type="image" src="[% c.uri_for('/static', 'icons', 'user-group-delete.png') %]" width="24" height="24"> 42 </form> 32 43 [% END %] 33 <a href="[% c.uri_for('/users', uid) %]">[% uid | html %] 34 ([% c.model('Accounts').db.get_object('user', uid).get_attributes('displayName') | html %])</a><br> 44 [% END %] 45 <a href="[% c.uri_for('/users', uid, 'statut') %]">[% uid | html %] 46 ([% ouser.get_attributes('displayName') | html %])</a> 47 [% INCLUDE user_flag ouser=ouser %] 48 <br> 35 49 [% IF modallow %] 36 </form>37 50 [% END %] 38 51 [% IF loop.last %] -
LATMOS-Accounts-Web/root/html/includes/form.tt
r507 r861 1 1 <!-- $Id$ --> 2 <div id="oform" >2 <div id="oform" class="oform"> 3 3 [% attributes = form.attributes() %] 4 4 [% IF attributes.0 %] … … 13 13 <tr><th>[% form.attr_label(attr) %]</th><td>[% form.attr_field(attr) %]</td> 14 14 [% IF loop.last %] 15 [% IF form.write_attributes %] 15 16 <tr><td colspan=2>[% form.submit %]</td></tr> 17 [% END %] 16 18 </table> 17 19 </form> -
LATMOS-Accounts-Web/root/html/includes/header.tt
r689 r861 2 2 <html> 3 3 <head> 4 <title> [% page.title %]</title>4 <title>LATMOS::Accounts / [% page.title %]</title> 5 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 6 6 <link rel="stylesheet" href="[% c.uri_for('/static', 'style.css') %]?" type="text/css"> … … 12 12 <script type="text/javascript" language="JavaScript" src="[% c.uri_for('/static', 'js', 'dragdrop.js') %]"></script> 13 13 <script type="text/javascript" language="JavaScript" src="[% c.uri_for('/static', 'js', 'controls.js') %]"></script> 14 <script type="text/javascript" language="JavaScript"> 15 function resetmenu() { 16 document.getElementById('menui').innerHTML = '[% page.title | html %]'; 17 } 18 19 [% IF page.error %] 20 window.onload = analert; 21 22 function analert () { 23 alert('[% page.error | replace('\'', '\\\'') %]'); 24 } 25 [% END %] 26 </script> 14 27 </head> 15 28 … … 20 33 [% END %] 21 34 35 [% BLOCK user_flag %] 36 [% INCLUDE object_flag object = ouser %] 37 [% END %] 38 39 [% BLOCK object_flag %] 40 [% IF object.type == 'user' %] 41 [% IF object.get_attributes('unexported') %] 42 <img src="[% c.uri_for('/static', 'icons', 'gtk-delete.png') %]" 43 class="notice" title="Ce compte est désactivé" alt="disable"> 44 [% ELSIF object.get_attributes('expired') %] 45 <img src="[% c.uri_for('/static', 'icons', 'emblem-urgent.png') %]" 46 class="notice" title="Ce compte est expiré ([% object.get_attributes('expired') %])" alt="expired"> 47 [% ELSIF object.get_attributes('expire') %] 48 <img src="[% c.uri_for('/static', 'icons', 'appointment-new.png') %]" 49 class="notice" title="Ce compte est temporaire ([% object.get_attributes('expire') %])" alt="temporary"> 50 [% END %] 51 [% ELSE %] 52 [% IF object.get_attributes('unexported') %] 53 <img src="[% c.uri_for('/static', 'icons', 'gtk-delete.png') %]" 54 class="notice" title="Cette entrée est désactivés" alt="disable"> 55 [% END %] 56 [% END %] 57 [% END %] 58 22 59 <body> 23 60 <!-- $Id$ --> 24 <div id="head" class="pmenu"> 25 Gestion des Utilisateurs du LATMOS 26 [% IF c.user.username %] 27 <span style="float:right; font-size: 0.5em;"> 28 Vous êtes [% c.user.username | html %] 29 </span> 30 [% END %] 61 <div id="head"> 62 <div class="pmenu"> 63 [% IF c.config.company %] 64 Gestion informatique - [% c.config.company | html %] 65 [% ELSE %] 66 Gestion informatique 67 [% END %] 68 [% IF c.user.username %] 69 <span style="float:right; font-size: 0.5em;"> 70 Vous êtes [% c.user.username | html %] 71 </span> 72 [% END %] 73 </div> 74 75 <div id="mainmenu" style="float: left"> 76 <span> 77 <a href="[% c.uri_for('/users') %]" 78 onMouseOver="document.getElementById('menui').innerHTML='Liste des utilisateurs';" 79 onMouseOut="resetmenu();" 80 > 81 <img title="Utilisateurs" src="[% c.uri_for('/static', 'icons', 'avatar-default.png') %]"></a> 82 [% IF c.model('Accounts').db.check_acl('user', '@CREATE', 'w') %] 83 <a href="[% c.uri_for('/create', 'user') %]" 84 onMouseOver="document.getElementById('menui').innerHTML='Créer un utilisateur';" 85 onMouseOut="resetmenu();" 86 > 87 <img title="Ajouter un utilisateurs" src="[% c.uri_for('/static', 'icons', 'add.png') %]"></a> 88 [% END %] 89 </span> 90 <span> 91 <a href="[% c.uri_for('/groups') %]" 92 onMouseOver="document.getElementById('menui').innerHTML='Liste des groupes';" 93 onMouseOut="resetmenu();" 94 > 95 <img title="Groupes" src="[% c.uri_for('/static', 'icons', 'system-users.png') %]"></a> 96 [% IF c.model('Accounts').db.check_acl('group', '@CREATE', 'w') %] 97 <a href="[% c.uri_for('/create', 'group') %]" 98 onMouseOver="document.getElementById('menui').innerHTML='Créer un groupe';" 99 onMouseOut="resetmenu();" 100 > 101 <img title="Ajouter un groupe" src="[% c.uri_for('/static', 'icons', 'add.png') %]"></a> 102 [% END %] 103 </span> 104 <span> 105 <a href="[% c.uri_for('/sites') %]" 106 onMouseOver="document.getElementById('menui').innerHTML='Liste des sites';" 107 onMouseOut="resetmenu();" 108 > 109 <img title="Sites" src="[% c.uri_for('/static', 'icons', 'xfce-internet.png') %]"></a> 110 </span> 111 [% # On cache volontairement les alias si l'utilisateur ne doit pas y 112 toucher %] 113 [% IF c.model('Accounts').db.check_acl('aliases', '@CREATE', 'w') %] 114 <span> 115 <a href="[% c.uri_for('/aliases') %]" 116 onMouseOver="document.getElementById('menui').innerHTML= 117 'Alias mail sans utilisateur';" 118 onMouseOut="resetmenu();" 119 > 120 <img title="Alias mail" src="[% c.uri_for('/static', 'icons', 'mail_forward.png') %]"></a> 121 </span> 122 [% END %] 123 <span> 124 <a href="[% c.uri_for('/nethosts') %]" 125 onMouseOver="document.getElementById('menui').innerHTML='Liste des hÃŽtes réseau';" 126 onMouseOut="resetmenu();" 127 > 128 <img title="HÃŽtes réseau" src="[% c.uri_for('/static', 'icons', 'video-display.png') %]"></a> 129 [% IF c.model('Accounts').db.check_acl('nethost', '@CREATE', 'w') %] 130 <a href="[% c.uri_for('/create', 'nethost') %]" 131 onMouseOver="document.getElementById('menui').innerHTML='Ajouter un hote réseau';" 132 onMouseOut="resetmenu();" 133 > 134 <img title="Ajouter un hÃŽte réseau" src="[% c.uri_for('/static', 'icons', 'add.png') %]"></a> 135 [% END %] 136 </span> 137 [% # On cache volontaire les zones si l'utilisateur ne doit pas y 138 toucher %] 139 [% IF c.model('Accounts').db.check_acl('netzone', '@CREATE', 'w') %] 140 <span> 141 <a href="[% c.uri_for('/netzones') %]" 142 onMouseOver="document.getElementById('menui').innerHTML='Liste des zones réseaux';" 143 onMouseOut="resetmenu();" 144 > 145 <img title="Gestion Réseau" src="[% c.uri_for('/static', 'icons', 'network-workgroup.png') %]"></a> 146 <a href="[% c.uri_for('/create', 'netzone') %]" 147 onMouseOver="document.getElementById('menui').innerHTML='Ajouter une zones réseau';" 148 onMouseOut="resetmenu();" 149 ><img title="Ajouter une zone" src="[% c.uri_for('/static', 'icons', 'add.png') %]"></a> 150 </span> 151 [% END %] 152 <span> 153 <a href="[% c.uri_for('/about') %]" 154 onMouseOver="document.getElementById('menui').innerHTML='A propos...';" 155 onMouseOut="resetmenu();" 156 > 157 <img title="A propos..." src="[% c.uri_for('/static', 'icons', 'gtk-about.png') %]"></a> 158 </span> 159 </div> 160 161 [% IF c.user.username %] 162 <div style="float: right"> 163 <span> 164 <a href="[% c.uri_for('/users', c.user.username) %]" 165 onMouseOver="document.getElementById('menui').innerHTML='Mon profile';" 166 onMouseOut="resetmenu();" 167 > 168 <img title="Mon profile" src="[% c.uri_for('/static', 'icons', 'gtk-home.png') %]"></a> 169 </span> 170 <span> 171 <a href="[% c.uri_for('/users', c.user.username, 'passwd') %]" 172 onMouseOver="document.getElementById('menui').innerHTML='Changer mon mot de passe';" 173 onMouseOut="resetmenu();" 174 > 175 <img title="Changer mon mot de passe" src="[% c.uri_for('/static', 176 'icons', 'dialog-password.png') %]"></a> 177 </span> 178 <span> 179 <a href="[% c.uri_for('/logout') %]" 180 onMouseOver="document.getElementById('menui').innerHTML='Se déconnecter';" 181 onMouseOut="resetmenu();" 182 > 183 <img title="Se déconnecter" src="[% c.uri_for('/static', 184 'icons', 'gtk-close.png') %]"></a> 185 </span> 186 </div> 187 [% END %] 188 189 <div style="clear: both"></div> 190 191 <p>> <span id="menui">[% page.title | html %]</span></p> 31 192 </div> 32 <div id="mainmenu" class="pmenu">33 <div style="float: left">[% mainmenu %]</div>34 [% IF c.user.username %]35 <div style="float: right">36 <a href="[% c.uri_for('/users', c.user.username) %]"><span>Mon profile</span></a>37 <a href="[% c.uri_for('/users', c.user.username, 'passwd') %]"><span>Mon mot de passe</span></a>38 <a href="[% c.uri_for('/logout') %]"><span>Se déconnecter</span></a>39 </div>40 [% END %]41 <div style="clear: both"></div>42 </div> -
LATMOS-Accounts-Web/root/html/includes/obj_prev_next.tt
r544 r861 1 1 <!-- $Id$ --> 2 2 3 <p style="float: right"> 4 [% prev_next = c.model('Accounts').object_prev_next(objtype, objname) %] 5 [% IF prev_next.0 %] 6 <a href="[% c.uri_for(prev_next.0, subform) %]" title="[% prev_next.0 | html 7 %]">Prec.</a> 8 [% ELSE %] 9 Prec. 10 [% END %] 11 [% IF prev_next.1 %] 12 <a href="[% c.uri_for(prev_next.1, subform) %]" title="[% prev_next.1 | html 13 %]">Suiv.</a> 14 [% ELSE %] 15 Suiv. 16 [% END %] 17 </p> 3 <div id="navigate" style="float: right"> 4 <p> 5 [% nav = c.model('Accounts').object_navigate(objtype, objname) %] 6 7 [% IF nav.ofirst %] 8 <a href="[% c.uri_for(nav.ofirst, subform) %]"> 9 <img src="[% c.uri_for('/static', 'icons/gtk-goto-first-ltr.png') %]" title="[% 10 nav.ofirst | html %]" alt="first"> 11 </a> 12 [% END %] 13 14 [% IF nav.oprev %] 15 <a href="[% c.uri_for(nav.oprev, subform) %]"> 16 <img src="[% c.uri_for('/static', 'icons/gtk-go-back-ltr.png') %]" title="[% 17 nav.oprev | html %]" alt="previous"> 18 </a> 19 [% END %] 20 21 [% IF nav.onext %] 22 <a href="[% c.uri_for(nav.onext, subform) %]"> 23 <img src="[% c.uri_for('/static', 'icons/gtk-go-back-rtl.png') %]" title="[% 24 nav.onext | html %]" alt="next"> 25 </a> 26 [% END %] 27 28 [% IF nav.olast %] 29 <a href="[% c.uri_for(nav.olast, subform) %]"> 30 <img src="[% c.uri_for('/static', 'icons/gtk-goto-first-rtl.png') %]" title="[% 31 nav.olast | html %]" alt="last"> 32 </a> 33 [% END %] 34 </p> 35 36 [% IF nav.list %] 37 <form action="[% c.uri_for('/ajax/goto') %]"> 38 <p> 39 <input type="hidden" name="otype" value="[% objtype | html %]"> 40 <input type="hidden" name="subform" value="[% subform | html %]"> 41 <select name="goto"> 42 [% FOREACH item = nav.list %] 43 <option value="[% item | html %]" [% 'selected="selected"' IF item == objname 44 %]>[% item | html %]</option> 45 [% END %] 46 </select> 47 <input type="image" alt="Go To" title="Aller à " src="[% 48 c.uri_for('/static', 'icons', 'gtk-jump-to-rtl.png') %]"> 49 </p> 50 </form> 51 [% END %] 52 53 </div> -
LATMOS-Accounts-Web/root/html/sites/default.tt
r214 r861 1 <!-- $Id: default.tt 432 2009-05-17 13:19:38Z nanardon $ -->1 <!-- $Id: default.tt 2800 2010-08-01 12:02:51Z nanardon $ --> 2 2 [% IF NOT site %] 3 3 No site [% sitename | html %] found. -
LATMOS-Accounts-Web/root/html/sites/menu.tt
r214 r861 1 <!-- $Id: user_menu.tt 443 2009-05-18 03:52:21Z nanardon $ --> 2 <div id="omenu"> 3 <table border="0"> 4 <tr><td> 1 <!-- $Id: menu.tt 3103 2010-08-26 12:47:15Z nanardon $ --> 2 <div id="oinfo"> 3 4 [% INCLUDE 'includes/obj_prev_next.tt' objtype='site' objname=sitename %] 5 6 <div> 5 7 <img src="[% c.uri_for('/static', 'icons', 'user-properties.png') %]" 6 8 alt="[% "User " _ sitename %]"> 7 </ td>8 < td>9 [% sitename | html %]<br>9 </div> 10 <div> 11 <p id="oname">[% sitename | html %]</p> 10 12 [% user.get_c_field('l') | html %] 11 </td></tr> 12 </table> 13 </div> 13 14 </div> 15 <div style="clear: both;"></div> -
LATMOS-Accounts-Web/root/html/users/address.tt
r686 r861 20 20 </form> 21 21 22 [% IF address.base.check_acl(address, '@DELETE', 'w') %] 22 23 <table border=1><tr><td align="center"> 23 24 <form action="[% c.uri_for(username, subform) %]" method="POST"> … … 28 29 </form> 29 30 </td></tr></table> 31 [% END %] 30 32 31 33 </div> -
LATMOS-Accounts-Web/root/html/users/address_form.tt
r760 r861 63 63 <td>[% form.attr_field('co', fieldtype) %]</td> 64 64 </tr> 65 [% IF form.write_attributes %] 65 66 <tr> 66 67 <th></th> 67 <td>[% form.submit %]</td> 68 <td> 69 [% form.submit %] 70 </td> 68 71 </tr> 72 [% END %] 69 73 </table> -
LATMOS-Accounts-Web/root/html/users/groups.tt
r508 r861 20 20 [% FOREACH g = user.get_c_field('memberOf') %] 21 21 [% IF modallow %] 22 <form action="[% c.uri_for(username, subform) %]" method="POST"> 22 [% IF user.get_attributes('department') == g OR 23 user.get_attributes('contratType') == g %] 24 <img src="[% c.uri_for('/static', 'icons', 'changes-prevent.png') %]" 25 width="24" height="24" title="Ce groupe est géré via un autre attribut"> 26 [% ELSE %] 27 <form action="[% c.uri_for(username, subform) %]" method="POST" style="display: inline"> 23 28 <input type="hidden" name="delgroup" value="[% g | html %]"> 24 29 <input type="image" src="[% c.uri_for('/static', 'icons', 'user-group-delete.png') %]" width="24" height="24"> 30 </form> 31 [% END %] 25 32 [% END %] 26 33 <a href="[% c.uri_for('/groups', g) %]">[% g | html %]</a><br> 27 34 [% IF modallow %] 28 </form>29 35 [% END %] 30 36 [% END %] -
LATMOS-Accounts-Web/root/html/users/index.tt
r682 r861 9 9 10 10 <table border="0"> 11 <tr><td colspan=" 2">[% objectslist.size %] Utilisateurs<br>11 <tr><td colspan="5"> 12 12 [% IF initials %] 13 13 Pages: … … 22 22 [% END %] 23 23 </td></tr> 24 <tr><t h>Login</th><th>Nom</th></tr>24 <tr><td></td><th>Login</th><th>Nom</th><th>Description</th><th>Mail</th></tr> 25 25 [% FOREACH username = userslist %] 26 26 [% user = db.get_object('user', username) %] 27 27 <tr> 28 <td>[% username | html %]</td> 28 <td> 29 [% INCLUDE 'user_flag' ouser=user %] 30 </td> 31 <td><a href="[% c.uri_for('/users', username) %]"> 32 <img src="[% c.uri_for('/static', 'icons', 'icon_edit.png') %]" 33 height="16" width="16" 34 alt="[% "edit " _ username | html %]"> 35 </a>[% username | html %]</td> 29 36 <td> 30 37 [% user.get_c_field('sn') | html %] 31 38 [% user.get_c_field('givenName') | html %] 32 [% user.get_c_field('description') | truncate(20) | html %] 33 <a href="[% c.uri_for('/users', username) %]"> 34 <img src="[% c.uri_for('/static', 'icons', 'arrow-right.png') %]" 35 height="16" width="16" 36 alt="[% "edit " _ username | html %]"> 37 </a></td> 39 </td> 40 <td> 41 <span title="[% user.get_c_field('description') | html %]"> 42 [% user.get_c_field('description') | truncate(20) | html %] 43 </span> 44 </td> 45 <td><span title="[% user.get_c_field('mail') | html %]"> 46 [% user.get_c_field('mail') | truncate(20) | html %]</span> 47 </td> 38 48 </tr> 39 49 [% END %] -
LATMOS-Accounts-Web/root/html/users/menu.tt
r730 r861 1 1 <!-- $Id$ --> 2 <div id="omenu"> 3 2 <div id="oinfo"> 4 3 [% INCLUDE 'includes/obj_prev_next.tt' objtype='user' objname=username %] 5 4 6 <table border="0"> 7 <tr><td> 8 [% IF NOT user.get_c_field('exported') OR user.get_c_field('locked') %] 9 <img src="[% c.uri_for('/static', 'icons', 'view-media-artist.png') %]" 10 [% ELSE %] 11 <img src="[% c.uri_for('/static', 'icons', 'user-properties.png') %]" 12 [% END %] 13 alt="[% "User " _ username %]"> 14 </td> 15 <td> 16 [% username | html %]<br> 17 [% user.get_c_field('displayName') | html %] 18 </td> 19 </tr> 20 </table> 5 <div> 6 [% IF NOT user.get_c_field('exported') %] 7 <img src="[% c.uri_for('/static', 'icons', 'gtk-delete.png') %]" 8 alt="[% "User " _ username %]" title="le compte est désactivé"> 9 [% ELSE %] 10 <img src="[% c.uri_for('/static', 'icons', 'user-properties.png') %]" 11 alt="[% "User " _ username %]"> 12 [% END %] 13 </div> 14 15 <div> 16 [% IF user.get_c_field('locked') %] 17 <img src="[% c.uri_for('/static', 'icons', 'locked.png') %]" 18 alt="le compte est vérrouillé" title="le compte est vérrouillé"> 19 [% END %] 20 </div> 21 22 <div> 23 <p id="oname">[% username | html %] 24 [% INCLUDE user_flag ouser = user %]</span></p> 25 [% user.get_c_field('displayName') | html %] 26 </div> 27 </div> 21 28 <div style="clear: both;"></div> 29 <div id="omenu"> 22 30 <a href="[% c.uri_for(username) %]"><span [% 'id="oactive"' IF subform == '' %]>SystÚme</span></a> 23 <a href="[% c.uri_for(username, 'statu s') %]"><span [% 'id="oactive"' IF subform == 'status' %]>Status</span></a>31 <a href="[% c.uri_for(username, 'statut') %]"><span [% 'id="oactive"' IF subform == 'statut' %]>Statut</span></a> 24 32 <a href="[% c.uri_for(username, 'groups') %]"><span [% 'id="oactive"' IF subform == 'groups' %]>Groupes</span></a> 25 33 <a href="[% c.uri_for(username, 'address') %]"><span [% 'id="oactive"' IF subform == 'address' %]>Adresses</span></a> 26 34 <a href="[% c.uri_for(username, 'mail') %]"><span [% 'id="oactive"' IF subform == 'mail' %]>eMail</span></a> 35 <a href="[% c.uri_for(username, 'my') %]"><span [% 'id="oactive"' IF subform == 'my' %]>My</span></a> 27 36 [% IF c.model('Accounts').db.check_acl(user, 'userPasswd', 'r') %] 28 37 <a href="[% c.uri_for(username, 'passwd') %]"><span [% 'id="oactive"' IF subform == 'passwd' %]>Mot de passe</span></a> 29 38 [% END %] 30 39 </div> 40 <div style="clear:both"></div> -
LATMOS-Accounts-Web/root/html/users/passwd.tt
r667 r861 3 3 [% INCLUDE 'users/menu.tt' %] 4 4 5 <script type="text/javascript"> 6 function check_passwd() { 7 new Ajax.Updater( 8 'perror', 9 '[% c.uri_for('/ajax', 'cracklib', username) %]', 10 { parameters: 'passwd=' + document.getElementById("passwd").value + 11 '&cpasswd=' + document.getElementById("cpasswd").value } 12 ) 13 } 14 </script> 15 5 16 <div id="oform"> 6 17 [% IF c.model('Accounts').db.check_acl(user, 'userPassword', 'w') %] 7 18 <form id="fpasswd" action="[% c.uri_for(username, subform) %]" method="POST"> 8 [% c.prototype.observe_form('fpasswd', {9 url => c.uri_for('/ajax', 'cracklib', username),10 update => 'perror',11 frequency => 1,12 }) %]13 19 <table border="1"> 14 20 <tr> 15 21 <th>Nouveau mot de passe:</th> 16 <td><input type="password" name="passwd" ></td>22 <td><input type="password" name="passwd" id="passwd" onkeyup="check_passwd()"></td> 17 23 </tr> 18 24 <tr> 19 25 <th>Confirmation:</th> 20 <td><input type="password" name="cpasswd" ></td>26 <td><input type="password" name="cpasswd" id="cpasswd" onkeyup="check_passwd()"></td> 21 27 </tr> 22 28 <tr><td colspan="2"><span id="perror">[% pmerror | html %]</span></td></tr> -
LATMOS-Accounts-Web/root/static/style.css
r507 r861 2 2 border: none; 3 3 vertical-align: middle; 4 padding: 0em 4 5 } 5 6 6 7 .pmenu { 8 padding: 0.5em; 9 font-size: 2em; 10 } 11 12 .permdenied { 13 padding: 0.5em; 14 } 15 16 #head { 7 17 background-color: #7DB4D8; 8 padding: 0.5em; 9 } 10 11 .permdenied { 12 padding: 0.5em; 13 } 14 15 #head { 16 font-size: 2em; 18 padding-bottom: 0.2em; 19 padding-top: 0.2em; 17 20 } 18 21 19 22 #mainmenu a { 20 font-size: 80%;23 font-size: 50px; 21 24 overflow: hidden; 22 25 text-decoration: none; … … 24 27 25 28 #mainmenu span { 29 padding-left: 1em; 30 padding-right: 1em; 31 text-decoration: none; 32 } 33 34 #mainmenu span#actif { 26 35 border-style: outset; 27 36 padding-left: 1em; 28 37 padding-right: 1em; 29 38 text-decoration: none; 30 } 31 32 #mainmenu span#actif { 33 border-style: inset; 34 border-size: 1px; 35 padding-left: 1em; 36 padding-right: 1em; 37 text-decoration: none; 39 height: 32px; 38 40 } 39 41 40 42 #mainmenu a:hover { 41 border: solid; 42 } 43 44 div#objectform { 43 /* border: solid;*/ 44 background-color: #7DB4D8; 45 } 46 47 #oinfo div { 48 float: left; 49 padding: 0.5em; 50 } 51 52 #oname { 53 font-size: 1.2em; 54 padding: 0em; 55 margin: 0em; 56 } 57 58 #omenu a { 59 text-decoration: none; 60 color: black; 61 } 62 63 #omenu div { 64 float: left; 65 padding-top: 0.5em; 66 padding-bottom: 0.5em; 67 } 68 69 70 #omenu span { 71 padding-left: 1em; 72 padding-right: 1em; 73 margin: 0; 74 border: groove thin; 75 text-decoration: none; 76 float: left; 77 background-color: #DDDDD9; 78 color: black; 79 } 80 81 #omenu span#oactive { 82 padding-left: 1em; 83 padding-right: 1em; 84 margin: 0; 85 border: groove thin; 86 text-decoration: none; 87 float: left; 88 background-color: #7DB4D8; 89 color: black; 90 } 91 92 #omenu a:hover { 93 /* border: inset; */ 94 text-color blue; 95 } 96 97 div.objectform { 45 98 border-style: outset; 46 99 width: 60%; … … 49 102 } 50 103 51 #objectform table {104 .objectform table { 52 105 margin-left: auto; 53 106 margin-right: auto; … … 56 109 } 57 110 58 #omenu a { 59 text-decoration: none; 60 } 61 62 #omenu td { 63 padding-left: 0.5em; 64 padding-right: 0.5em; 65 } 66 67 #omenu table { 111 div.objectformleft { 112 /* border-style: outset; */ 113 width: 60%; 114 margin-left: auto; 115 margin-right: auto; 116 } 117 118 .objectformleft table { 119 /* 120 margin-top: 1em; 121 margin-bottom: 1em; 122 */ 123 } 124 125 .objectformleft #oform { 126 /*border: inset;*/ 127 float: left; 128 } 129 130 .oform { 131 /* border: inset; */ 68 132 margin: 0.5em; 69 133 } 70 134 71 72 #omenu span { 73 padding-left: 1em; 74 padding-right: 1em; 75 margin: 0; 76 border: groove thin; 77 text-decoration: none; 78 } 79 80 #omenu span#oactive { 81 margin: 0; 82 padding-left: 1em; 83 padding-right: 1em; 84 border: outset; 85 border-bottom-style: none; 86 text-decoration: none; 87 font-weight:bold; 88 } 89 90 #omenu a:hover { 91 border: inset; 92 } 93 94 #oform { 95 border: inset; 96 } 97 98 table#oform { 99 margin-left: 20%; 100 margin-right: 20%; 135 .oform table { 136 /* margin-left: 20%; 137 margin-right: 20%; */ 138 } 139 140 .oform td { 141 vertical-align: top; 142 } 143 144 .oform p { 145 margin: 0.5em; 146 font-weight: bold; 147 } 148 149 .oform ul { 150 padding: 0.5em; 151 } 152 153 .oform li { 154 list-style-type: none; 155 padding-left: 0.2em; 156 } 157 158 .inputvalidate img { 159 width: 1em; 160 height:1em; 161 } 162 163 #navigate { 164 } 165 166 #navigate p { 167 margin: 0em; 168 text-align: center; 169 } 170 171 #navigate input { 172 width: 3em; 173 height:3em; 174 vertical-align: middle; 175 } 176 177 #navigate img { 178 width: 2em; 179 height:2em; 180 vertical-align: middle; 181 } 182 183 img.notice { 184 width: 1em; 185 height:1em; 186 vertical-align: middle; 187 } 188 189 img.attr { 190 width: 1.5em; 191 height:1.5em; 192 vertical-align: middle; 101 193 } 102 194 -
LATMOS-Accounts/Changes
r1 r861 1 1 Revision history for Perl extension LATMOS::Accounts. 2 3 2.0.0 4 - attributes are now object with possible properties: 5 * hide: attributes is still availlable but not listed 6 * ro: attributes can only be read 7 * can_values: list of possible values, other are rejected 8 * mandatory: cannot be empty or not set 9 * reference: the attribute point to this object type 10 11 - add support of network management 12 * object nethost and netzone 13 * BuildNet objects 14 * associated tools 15 16 - la-sync-manager can now manage multiples task: each task is an object 17 and la-sync-manager.ini control task to run 18 19 - all configurations files are now located in /etc/latmos-accounts and all 20 files have a fixed name. --config is no longer the main configuration file 21 but the directory containing theses files 22 23 - configuration files are now more or less documented (man section 5) 24 25 - exported attributes is replace by unexported attributes (reverse meaning), 26 unlike exported which is true/false, unexported is set or not. 27 28 - some optimization, especially for SQL base 29 30 - add la-cli tools: interactive command line with completion 2 31 3 32 0.01 Wed Feb 25 17:58:38 2009 -
LATMOS-Accounts/MANIFEST
r859 r861 7 7 bin/la-acls 8 8 bin/la-attributes 9 bin/la-buildnet 9 10 bin/la-cli 10 11 bin/la-config … … 13 14 bin/la-delete 14 15 bin/la-edit 16 bin/la-exchange-ip 17 bin/la-expired-reminder 18 bin/la-find-expired 19 bin/la-freeip 15 20 bin/la-graph.pl 16 21 bin/la-group … … 21 26 bin/la-query 22 27 bin/la-rename 28 bin/la-rename-host 23 29 bin/la-rev 24 30 bin/la-search 31 bin/la-sql-loadatt 32 bin/la-sql-regatt 25 33 bin/la-sync 26 34 bin/la-sync-list … … 40 48 lib/LATMOS/Accounts/Bases/Dummy/User.pm 41 49 lib/LATMOS/Accounts/Bases/Dummy.pm 50 lib/LATMOS/Accounts/Bases/Heimdal/User.pm 51 lib/LATMOS/Accounts/Bases/Heimdal.pm 42 52 lib/LATMOS/Accounts/Bases/Ldap/Group.pm 43 53 lib/LATMOS/Accounts/Bases/Ldap/Onlyaddress.pm … … 49 59 lib/LATMOS/Accounts/Bases/Mail/objects.pm 50 60 lib/LATMOS/Accounts/Bases/Mail.pm 61 lib/LATMOS/Accounts/Bases/OCHelper/User.pm 62 lib/LATMOS/Accounts/Bases/OCHelper.pm 51 63 lib/LATMOS/Accounts/Bases/Objects.pm 64 lib/LATMOS/Accounts/Bases/Sql/Accreq.pm 52 65 lib/LATMOS/Accounts/Bases/Sql/Address.pm 53 66 lib/LATMOS/Accounts/Bases/Sql/Aliases.pm 54 67 lib/LATMOS/Accounts/Bases/Sql/Group.pm 68 lib/LATMOS/Accounts/Bases/Sql/Nethost.pm 69 lib/LATMOS/Accounts/Bases/Sql/Netzone.pm 70 lib/LATMOS/Accounts/Bases/Sql/OCHelper/Accreq.pm 55 71 lib/LATMOS/Accounts/Bases/Sql/Onlyaddress.pm 56 72 lib/LATMOS/Accounts/Bases/Sql/Revaliases.pm … … 64 80 lib/LATMOS/Accounts/Bases/Unix.pm 65 81 lib/LATMOS/Accounts/Bases.pm 82 lib/LATMOS/Accounts/BuildNet.pm 66 83 lib/LATMOS/Accounts/Cli.pm 67 84 lib/LATMOS/Accounts/Log.pm 68 85 lib/LATMOS/Accounts/Maintenance.pm 86 lib/LATMOS/Accounts/SyncManager.pm 69 87 lib/LATMOS/Accounts/SynchAccess/Objects.pm 70 88 lib/LATMOS/Accounts/SynchAccess/base.pm 71 89 lib/LATMOS/Accounts/SynchAccess.pm 72 90 lib/LATMOS/Accounts/Synchro.pm 91 lib/LATMOS/Accounts/Task/Basessynchro.pm 92 lib/LATMOS/Accounts/Task/Buildlistes.pm 93 lib/LATMOS/Accounts/Task/Buildnet.pm 94 lib/LATMOS/Accounts/Task/Dummy.pm 95 lib/LATMOS/Accounts/Task/Refreshexpired.pm 96 lib/LATMOS/Accounts/Task.pm 73 97 lib/LATMOS/Accounts/Utils.pm 74 98 lib/LATMOS/Accounts.pm 99 man/la-allowed-values.ini.5.pod 100 man/la-sync-list.ini.5.pod 101 man/la-sync-manager.ini.5.pod 102 man/latmos-accounts.ini.5.pod 75 103 patchset/no_useless_load.patch 76 sample/allowed_values.ini 77 sample/latmos-account.ini 78 sample/list.cfg 104 sample/la-allowed-values.ini 105 sample/la-sync-list.ini 106 sample/la-sync-manager.ini 107 sample/latmos-accounts.ini 108 scripts/la-sw-net 109 scripts/ochelper 110 sqldata/attributes.csv 111 sqldata/base.sql 79 112 t/05_utils.t 80 113 t/06_cli.t … … 88 121 t/21_acls.t 89 122 t/22_accounts_attributes.t 123 t/23_ochelper.t 90 124 t/25_la_synchro.t 91 125 t/26_la_synchaccess.t 126 t/30_la_task.t 92 127 t/LATMOS-Accounts.t 93 128 templates/mail/account_expire.mail 129 templates/mail/account_expired_reminder.mail 94 130 testdata/acls1 95 131 testdata/acls2 96 132 testdata/aliases 97 testdata/config 133 testdata/configdir/latmos-accounts.ini 98 134 testdata/group 99 135 testdata/gshadow -
LATMOS-Accounts/Makefile.PL
r860 r861 5 5 WriteMakefile( 6 6 NAME => 'LATMOS::Accounts', 7 VERSION => ' 0.0.25', # finds $VERSION7 VERSION => '2.0.5', # finds $VERSION 8 8 PREREQ_PM => { 9 9 'Net::LDAP' => undef, … … 21 21 'Unicode::String' => undef, 22 22 'Crypt::Cracklib' => undef, 23 'Net::IP' => undef, 23 24 }, # e.g., Module::Name => 1.1 24 25 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 … … 35 36 bin/la-delete 36 37 bin/la-edit 38 bin/la-find-expired 37 39 bin/la-group 38 40 bin/la-guser … … 40 42 bin/la-query 41 43 bin/la-rename 44 bin/la-rename-host 45 bin/la-exchange-ip 42 46 bin/la-rev 43 47 bin/la-search … … 47 51 bin/la-warn-expire 48 52 bin/la-web-directory 53 bin/la-freeip 54 bin/la-buildnet 55 bin/la-expired-reminder 56 bin/la-sql-regatt 57 bin/la-sql-loadatt 49 58 ) ], 59 macro => { 60 INSTALLMAN5DIR => '$(PERLPREFIX)/share/man/man5', 61 DESTINSTALLMAN5DIR => '$(DESTDIR)$(INSTALLMAN5DIR)', 62 INST_MAN5DIR => 'blib/man5', 63 DESTRPMDIR => '$(shell pwd)' 64 }, 65 MAN1PODS => { 66 map { 67 my $targ = $_; 68 $targ =~ s{^man/}{}; 69 $targ =~ s{^bin/}{}; 70 $targ =~ s/\.(\d)\.pod$//; 71 my $section = $1 || 1; 72 ( $_ => 73 "\$(INST_MAN${section}DIR)/$targ.$section" ); 74 } <man/*.pod>, (grep { ! /~$/ } <bin/*>) 75 }, 76 50 77 ); 51 78 … … 54 81 sub postamble { 55 82 <<EOF; 56 .PHONY .= svnmanifest83 #.PHONY .= svnmanifest 57 84 58 85 svnmanifest: … … 70 97 \t --define "_sourcedir `pwd`" \\ 71 98 \t --define "_specdir `pwd`" \\ 72 \t --define "_srcrpmdir `pwd`" \\ 73 \t --define "_rpmdir `pwd`" \\ 99 \t --define "_srcrpmdir \$(DESTRPMDIR)" \\ 100 \t --define "_rpmdir \$(DESTRPMDIR)" \\ 101 \t latmos-accounts.spec 102 103 svnrpm: \$(DISTVNAME).tar.gz latmos-accounts.spec 104 \tmkdir \$(DESTRPMDIR)/noarch || : 105 \trpmbuild -ba --clean\\ 106 \t --define "_sourcedir `pwd`" \\ 107 \t --define "_specdir `pwd`" \\ 108 \t --define "_srcrpmdir \$(DESTRPMDIR)" \\ 109 \t --define "_rpmdir \$(DESTRPMDIR)" \\ 110 \t --define "svnrelease `LC_ALL=C svn info | grep '^Revision:' | sed 's/Revision: //'`" \\ 74 111 \t latmos-accounts.spec 75 112 76 113 EOF 114 } 115 116 sub installbin { 117 my $self = shift; 118 my $inherited = $self->SUPER::installbin(@_); 119 my $s = join '|', map quotemeta, @sbin_scripts; 120 # how to create needed directories under blib 121 $inherited .= $self->dir_target("\$(INST_$_)") for qw(MAN5DIR); 122 $inherited; 123 } 124 125 sub top_targets { 126 my $inherited = shift->SUPER::top_targets(@_); 127 $inherited =~ s/^config ::/$& \$(INST_MAN5DIR)\$(DIRFILESEP).exists/m; 128 $inherited; 77 129 } 78 130 … … 82 134 83 135 $section =~ s/(^install ::.*)/$1 install_config install_templates/m; 136 $section =~ s/\$\(INST_BIN\) \$\(DESTINSTALL(\w*)BIN\)/$& \$(INST_MAN5DIR) \$(DESTINSTALLMAN5DIR)/g; 84 137 85 138 $section .= q[ 86 139 install_config :: 87 140 install -d $(DESTDIR)/etc 88 install sample/latmos-account.ini $(DESTDIR)/etc/latmos-account.ini 141 install -d $(DESTDIR)/etc/latmos-accounts 142 install sample/latmos-accounts.ini $(DESTDIR)/etc/latmos-accounts/latmos-accounts.ini 143 install sample/la-sync-list.ini $(DESTDIR)/etc/latmos-accounts/la-sync-list.ini 144 install sample/la-allowed-values.ini $(DESTDIR)/etc/latmos-accounts/la-allowed-values.ini 145 install sample/la-sync-manager.ini $(DESTDIR)/etc/latmos-accounts/la-sync-manager.ini 89 146 90 147 install_templates :: -
LATMOS-Accounts/TODO
r282 r861 1 1 $Id$ 2 2 3 Having a way to requires: 4 perl(IO::Socket::SSL) (need by LDAP for SSL) 5 perl(Unicode::Map8) (Need by AD module) 6 3 - fix la-rename when one of base don't support the object type -
LATMOS-Accounts/bin/la-attributes
r594 r861 28 28 =head1 OPTIONS 29 29 30 = item -c|--config configfile30 =over 4 31 31 32 Use this configuration file instead of thr default one. 32 =item -c|--config configdir 33 34 Use this configuration directory instead of thr default one. 33 35 34 36 =item -b|--base basename 35 37 36 38 Perform query on this base(s) (can be set multiple times). 39 40 =back 37 41 38 42 =cut … … 55 59 }; 56 60 foreach($labase->list_canonical_fields($otype, 'a')) { 57 $supported{$_}{$basename} = sprintf('%s%s',58 ($labase->get_field_name($otype, $_, 'r') ? 'r' : ' '),59 ($labase->get_field_name($otype, $_, 'w') ? 'w' : ' '),61 my $attr = $labase->attribute($otype, $_); 62 $supported{$_}{$basename} = sprintf('%s', 63 $attr ? ($attr->ro ? 'r ' : 'rw') : ' ' 60 64 ); 61 65 } -
LATMOS-Accounts/bin/la-cli
r849 r861 30 30 =over 4 31 31 32 =item -c|--config config file32 =item -c|--config configdir 33 33 34 Use this configuration fileinstead of the default one.34 Use this configuration directory instead of the default one. 35 35 36 36 =item -b|--base basename -
LATMOS-Accounts/bin/la-config
r594 r861 29 29 =head1 OPTIONS 30 30 31 =item -c|--config config file31 =item -c|--config configdir 32 32 33 Use this configuration fileinstead of the default one.33 Use this configuration directory instead of the default one. 34 34 35 35 =item -b|--base basename … … 78 78 $otype, 79 79 $base ? $base : $LA->default_base_name; 80 printf( 81 " %s (%s%s)\n", $_, 82 ($labase->get_field_name($otype, $_, 'r') ? 'r' : ' '), 83 ($labase->get_field_name($otype, $_, 'w') ? 'w' : ' '), 84 ) foreach($labase->list_canonical_fields($otype, 'a')); 80 foreach($labase->list_canonical_fields($otype, 'a')) { 81 my $attr = $labase->attribute($otype, $_); 82 printf( 83 " %s (%s%s)\n", $_, 84 'r', 85 ($attr->readonly ? 'w' : ' '), 86 ) 87 } 85 88 } else { 86 89 my $labase = $base ? $LA->base($base) : $LA->default_base … … 89 92 printf "Supported object type by base %s\n", 90 93 $base ? $base : $LA->default_base_name; 91 print " $_\n" foreach($labase-> list_supported_objects);94 print " $_\n" foreach($labase->ordered_objects); 92 95 } 93 96 } -
LATMOS-Accounts/bin/la-create
r672 r861 34 34 =over 4 35 35 36 =item -c|--config config file36 =item -c|--config configdir 37 37 38 Use this configuration fileinstead of the default one.38 Use this configuration directory instead of the default one. 39 39 40 40 =item -b|--base basename -
LATMOS-Accounts/bin/la-crypt-passwd
r664 r861 3 3 use strict; 4 4 use warnings; 5 use LATMOS::Accounts ::Maintenance;5 use LATMOS::Accounts; 6 6 use Getopt::Long; 7 7 use Pod::Usage; … … 25 25 'regen' => \my $regen, 26 26 'set=s' => \my $set, 27 'base=s' => \my $base, 27 28 ) or pod2usage(); 28 29 … … 31 32 =over 4 32 33 33 =item -c|--config config file34 =item -c|--config configdir 34 35 35 Use this configuration fileinstead of the default one.36 Use this configuration directory instead of the default one. 36 37 37 38 =item --genkey … … 46 47 Stored password will be read and encrypted again using the new key. 47 48 49 =item --base base 50 51 Work on this specific base instead default one 52 48 53 =item --set BASE 49 54 … … 55 60 =cut 56 61 57 my $LA = LATMOS::Accounts::Maintenance->new($config); 58 $LA->wexported(1); 62 my $LA = LATMOS::Accounts->new($config, noacl => 1); 63 my $labase = $base ? $LA->base($base) : $LA->default_base; 64 $labase && $labase->load or die "Cannot load base"; 65 $labase->wexported(1); 59 66 60 67 my $clear; … … 62 69 sub get_clear_password { 63 70 $clear and return $clear; 64 my %encpasswd = $ LA->get_rsa_password;71 my %encpasswd = $labase->get_rsa_password; 65 72 scalar(keys %encpasswd) or return {}; 66 73 ReadMode('noecho'); … … 69 76 ReadMode 0; 70 77 print "\n"; 71 my $private_key = $ LA->private_key($password) or78 my $private_key = $labase->private_key($password) or 72 79 die "Cannot get private key\n"; 73 80 my $rsa = new Crypt::RSA ES => 'PKCS1v15'; … … 89 96 90 97 if ($set) { 91 if (!$ LA->_base->get_global_value('rsa_private_key')) {98 if (!$labase->get_global_value('rsa_private_key')) { 92 99 warn "No rsa key found in database\n"; 93 100 } … … 104 111 $destbase->commit; 105 112 } elsif ($regen || $genkey) { 106 if ($ LA->_base->get_global_value('rsa_private_key') && !$regen) {113 if ($labase->get_global_value('rsa_private_key') && !$regen) { 107 114 die <<EOF; 108 115 A rsa key were found in database please use --regen to force a new key … … 118 125 ReadMode 0; 119 126 print "\n"; 120 my ($public, $private) = $ LA->generate_rsa_key($password);127 my ($public, $private) = $labase->generate_rsa_key($password); 121 128 122 $LA->store_rsa_key($public, $private); 123 my $base = $LA->_base; 124 $base->wexported(1); 129 $labase->store_rsa_key($public, $private); 125 130 foreach (keys %$clearpasswd) { 126 my $obj = $ base->get_object('user', $_);131 my $obj = $labase->get_object('user', $_); 127 132 $obj->set_password($clearpasswd->{$_}); 128 133 } 129 $ base->commit;134 $labase->commit; 130 135 } else { 131 if ($ LA->_base->get_global_value('rsa_private_key')) {136 if ($labase->get_global_value('rsa_private_key')) { 132 137 my $clearpasswd = get_clear_password(); 133 138 foreach (keys %$clearpasswd) { -
LATMOS-Accounts/bin/la-delete
r685 r861 31 31 =over 4 32 32 33 =item -c|--config config file33 =item -c|--config configdir 34 34 35 Use this configuration fileinstead of the default one.35 Use this configuration directory instead of the default one. 36 36 37 37 =item -b|--base basename -
LATMOS-Accounts/bin/la-edit
r664 r861 33 33 =over 4 34 34 35 =item -c|--config config file35 =item -c|--config configdir 36 36 37 Use this configuration fileinstead of the default one.37 Use this configuration directory instead of the default one. 38 38 39 39 =item -b|--base basename -
LATMOS-Accounts/bin/la-graph.pl
r457 r861 30 30 =over 4 31 31 32 =item -c|--config config file32 =item -c|--config configdir 33 33 34 Use this configuration fileinstead the default one34 Use this configuration directory instead the default one 35 35 36 36 =item -b|--base basename … … 47 47 48 48 my $g = GraphViz->new( 49 layout => ' neato',50 concentrate => 1,51 overlap => 'compress',52 ratio => 'compress',49 layout => 'dot', 50 overlap => 'false', 51 rankdir => 1, 52 width => 10, height => 8, 53 53 ); 54 54 … … 60 60 61 61 my %users; 62 my %cluster; 62 63 64 sub add_user { 65 my ($user) = @_; 66 $users{$user} and return; 67 my $ou = $labase->get_object('user', $user) or return; 68 my $dpmt = $ou->get_attributes('department'); 69 if ($dpmt) { 70 $cluster{$dpmt} ||= { 71 name => $dpmt, 72 }; 73 } 74 $g->add_node($user, ($dpmt ? (cluster => $cluster{$dpmt}) : ())); 75 1; 76 } 77 78 $g->add_node('latmos'); 63 79 foreach my $gr ($labase->list_objects('group')) { 64 80 my $o = $labase->get_object('group', $gr); 65 ($o->get_c_field('sutype') || '') =~ /^(dpmt|cell)$/ or next; 66 $g->add_node($gr,fillcolor => 'red', style => 'filled'); 81 my $sutype = $o->get_c_field('sutype'); 82 ($sutype || '') =~ /^(dpmt|cell)$/ or next; 83 $g->add_node($gr,fillcolor => ($sutype eq 'dpmt' ? 'red' : 'green'), style => 'filled'); 84 my $manager = $o->get_attributes('managedBy') || ''; 85 warn "MANAGER $manager"; 86 if ($manager) { 87 add_user($manager); 88 $g->add_edge('latmos', $gr); 89 $g->add_edge($manager => $gr, weight => 3); 90 } 67 91 foreach ($o->get_attributes('member')) { 68 $users{$_} or do { 69 $users{$_} = 1; 70 $g->add_node($_); 71 }; 92 $_ eq $manager and next; 93 add_user($_); 72 94 warn "$_ => $gr"; 73 $g->add_edge($ _ => $gr);95 $g->add_edge($gr => $_, weight => 1); 74 96 } 75 97 } -
LATMOS-Accounts/bin/la-group
r849 r861 41 41 =over 4 42 42 43 =item -c|--config config file43 =item -c|--config configdir 44 44 45 Use this configuration fileinstead of the default one.45 Use this configuration directory instead of the default one. 46 46 47 47 =item -b|--base basename -
LATMOS-Accounts/bin/la-guser
r849 r861 41 41 =over 4 42 42 43 =item -c|--config config file43 =item -c|--config configdir 44 44 45 Use this configuration fileinstead of the default one.45 Use this configuration directory instead of the default one. 46 46 47 47 =item -b|--base basename -
LATMOS-Accounts/bin/la-log-test
r594 r861 20 20 'c|config=s' => \my $config, 21 21 'l|level=s' => \my $level, 22 ' list' => \my $list,22 'mail=s' => \my $mail, 23 23 'help' => sub { pod2usage(0) }, 24 24 ) or pod2usage(); … … 28 28 =over 4 29 29 30 =item -c|--config config file30 =item -c|--config configdir 31 31 32 Use this configuration fileinstead of the default one.32 Use this configuration directory instead of the default one. 33 33 34 34 =item -l|--level level … … 36 36 Set the log level 37 37 38 =item --mail email 39 40 Setup log error sent to email at end of execution 41 38 42 =cut 39 43 40 44 $level ||= 'LA_INFO'; 41 45 46 if ($mail) { 47 la_set_log(mail => $mail); 48 } 49 42 50 my $numlevel = eval "LATMOS::Accounts::Log::$level()"; 43 51 -
LATMOS-Accounts/bin/la-passwd
r773 r861 20 20 =over 4 21 21 22 =item -c|--config config file22 =item -c|--config configdir 23 23 24 Use this configuration fileinstead of the default one.24 Use this configuration directory instead of the default one. 25 25 26 26 =item -b|--base basename -
LATMOS-Accounts/bin/la-qacls
r849 r861 36 36 =head1 OPTIONS 37 37 38 =item -c|--config config file38 =item -c|--config configdir 39 39 40 Use this configuration fileinstead of the default one.40 Use this configuration directory instead of the default one. 41 41 42 42 =item -b|--base basename -
LATMOS-Accounts/bin/la-query
r849 r861 43 43 =over 4 44 44 45 =item -c|--config config file45 =item -c|--config configdir 46 46 47 Use this configuration fileinstead of the default one.47 Use this configuration directory instead of the default one. 48 48 49 49 =item -b|--base basename -
LATMOS-Accounts/bin/la-rename
r715 r861 20 20 =over 4 21 21 22 =item -c|--config config file22 =item -c|--config configdir 23 23 24 Use this configuration fileinstead of the default one.24 Use this configuration directory instead of the default one. 25 25 26 26 =item -b|--base basename -
LATMOS-Accounts/bin/la-rev
r837 r861 27 27 =over 4 28 28 29 =item -c|--config config file29 =item -c|--config configdir 30 30 31 Use this configuration fileinstead of the default one.31 Use this configuration directory instead of the default one. 32 32 33 33 =item -b|--base basename -
LATMOS-Accounts/bin/la-search
r849 r861 19 19 =over 4 20 20 21 =item --config config file21 =item --config configdir 22 22 23 Use this configuration fileinstead default23 Use this configuration directory instead default 24 24 25 25 =item --base basename … … 91 91 $otype ||= 'user'; 92 92 93 my $LA = LATMOS::Accounts->new($config );93 my $LA = LATMOS::Accounts->new($config, noacl => 1); 94 94 my $labase = $base ? $LA->base($base) : $LA->default_base; 95 95 $labase && $labase->load or die "Cannot load base"; -
LATMOS-Accounts/bin/la-sync
r777 r861 26 26 'to=s' => \my @to, 27 27 'nocreate' => \my $nocreate, 28 'nodelete' => \my $nodelete, 28 29 'test' => \my $test, 29 30 'o|object=s' => \my $otype, 30 31 's|syncname=s' => \my $syncname, 31 'b|batch' => \my $batch, 32 'b|batch' => \my $batch, 33 'unexp' => \my $unexp, 32 34 ) or pod2usage(); 33 35 34 36 =head1 OPTIONS 35 37 36 =item -c|--config config file38 =item -c|--config configdir 37 39 38 Use this configuration fileinstead of the default one.40 Use this configuration directory instead of the default one. 39 41 40 42 =item --from basename … … 68 70 to perform immediate synchronisation. 69 71 72 =item --unexp 73 74 Sync unexported objects in source base 75 70 76 =cut 71 77 … … 80 86 from => $from, 81 87 to => (@to ? [ @to ] : undef), 82 nocreate => $nocreate,83 88 test => $test, 89 unexported => $unexp, 84 90 ) or die "cannot create sync object\n"; 85 91 $sync->load_dest and return; … … 93 99 } 94 100 } else { 95 $sync->process() or warn "Sync has failed\n"; 101 $sync->process( 102 test => $test, 103 nodelete => $nodelete, 104 nocreate => $nocreate, 105 ) or warn "Sync has failed\n"; 96 106 } 97 107 -
LATMOS-Accounts/bin/la-sync-list
r834 r861 3 3 use strict; 4 4 use warnings; 5 use LATMOS::Accounts ;5 use LATMOS::Accounts::Task; 6 6 use Getopt::Long; 7 7 use Pod::Usage; 8 use Config::IniFiles;9 8 10 9 =head1 NAME … … 20 19 =over 4 21 20 22 =item --config config file21 =item --config configdir 23 22 24 Use this configuration fileinstead default23 Use this configuration directory instead default 25 24 26 25 =item --base basename … … 30 29 =item --lc cfg 31 30 32 la-list-sync config file 31 la-list-sync config file, defaults to la-sync-list.ini in config directory. 33 32 34 33 =back … … 43 42 ) or pod2usage(); 44 43 45 my $listcfg = Config::IniFiles->new(46 -file => $listconfig,47 -default => '_default_',48 ) or die "Cannot open list config file\n";49 44 50 my $LA = LATMOS::Accounts->new($config); 51 my $labase = $base ? $LA->base($base) : $LA->default_base; 52 $labase && $labase->load or die "Cannot load base"; 45 my $task = LATMOS::Accounts::Task->new( 46 'buildlistes', 47 listconfig => $listconfig, 48 base => $base, 49 config => $config, 50 ); 53 51 54 my %cache; 52 $task->init || die "Can't instanciate\n"; 53 exit($task->run ? 0 : 1); 55 54 56 foreach my $list ($listcfg->Sections) {57 my %content = ();58 $list eq '_default_' and next;59 $listcfg->val($list, 'ignore') and next;60 my $fmt = $listcfg->val($list, 'fmt', '%{mail}');61 my $otype = $listcfg->val($list, 'objects', 'user');62 foreach (grep { $_ } $listcfg->val($list, 'addtolist')) {63 $content{$_} = 1;64 }65 my %ids;66 foreach my $param ($listcfg->Parameters($list)) {67 $param =~ /^filter/ or next;68 69 foreach my $id (sort $labase->search_objects(70 $listcfg->val($list, 'objects', 'user'),71 $listcfg->val($list, $param),)) {72 $ids{$id} = 1;73 }74 }75 foreach my $id (sort keys %ids) {76 if (!$cache{$otype}{$fmt}{$id}) {77 my $obj = $labase->get_object(78 $otype,79 $id,80 );81 82 $cache{$otype}{$fmt}{$id} = $obj->queryformat($fmt);83 }84 $content{ $cache{$otype}{$fmt}{$id} } = 1;85 }86 my $cmd = $listcfg->val($list, 'cmd', 'cat');87 $cmd =~ s/%%/$list/g;88 if (open(my $handle, '|' . $cmd)) {89 foreach (keys %content) {90 print $handle $_ ."\n";91 }92 close($handle);93 }94 }95 96 exit(0); -
LATMOS-Accounts/bin/la-sync-manager
r816 r861 5 5 use Getopt::Long; 6 6 use Pod::Usage; 7 use Config::IniFiles; 7 8 use LATMOS::Accounts; 9 use LATMOS::Accounts::SyncManager; 8 10 use LATMOS::Accounts::Log; 11 use LATMOS::Accounts::Task; 9 12 10 13 GetOptions( … … 13 16 'help' => sub { pod2usage(0) }, 14 17 'test' => \my $test, 15 's|syncname=s' => \my $syncname, 18 'wait=i' => \my $wait, 19 'r|run=s' => \my $run, 16 20 ) or pod2usage(); 17 21 18 my $needsync = 0;22 my $needsync = 2; 19 23 my $pidfile = undef; 24 $wait ||= 5; # default in minutes 25 26 my $syncm = LATMOS::Accounts::SyncManager->new($config) or do { 27 la_log LA_ERR, "Cannot instanciate Sync Manager"; 28 exit(1); 29 }; 30 31 if ($run) { 32 my $res = $syncm->process_module($run); 33 exit($res ? 0 : 1); 34 } 20 35 21 36 la_set_log( … … 24 39 ); 25 40 41 26 42 { 27 43 my $LA = LATMOS::Accounts->new($config, noacl => 1); 28 44 if ($LA->val('_default_', 'state_dir')) { 29 45 $pidfile = $LA->val('_default_', 'state_dir') . '/sync-manager.pid'; 46 } 47 if (my $mail = $LA->val('_network_', 'maillog')) { 48 la_set_log(mail => $mail); 30 49 } 31 50 } … … 46 65 } 47 66 48 sub sync {49 50 la_log LA_NOTICE, "Starting synchronisation";51 my $LA = LATMOS::Accounts->new($config, noacl => 1) or do {52 la_log LA_ERR, "Cannot instantiate LA";53 return 1;54 };55 56 my $sync = $LA->create_synchro(57 $syncname || $LA->default_synchro_name,58 test => $test,59 ) or do {60 la_log LA_ERR, "cannot create sync object";61 return 2;62 };63 64 $sync->load_dest and do {65 la_log LA_ERR, "Cannot load destination";66 return 3;67 };68 69 $sync->process() or do {70 la_log LA_ERR, "Sync has failed\n";71 return 4;72 };73 la_log LA_NOTICE, "Ending synchronisation";74 75 return 0;76 }77 78 67 $SIG{INT} = sub { 79 68 unlink($pidfile) if ($pidfile); … … 86 75 }; 87 76 77 sub process { 78 my ($module, $baserev) = @_; 79 my $pid = fork; 80 if ($pid == 0) { 81 $SIG{INT} = 'DEFAULT'; 82 my $res = $syncm->process_module($module, $baserev); 83 exit($res ? 0 : 1); 84 } 85 my $retpid; 86 while(($retpid = waitpid(-1, 0)) <= 0) {} 87 local $SIG{HUP} = 'IGNORE'; 88 if ($retpid) { 89 my $res = $? << 8; 90 if ($res) { 91 la_log LA_ERR, "Sync process exit with $res"; 92 return; 93 } 94 } 95 return 1; 96 } 97 98 my $lasttout; 99 my %revs; 88 100 while (1) { 89 101 if ($needsync) { 102 my $levelsync = $needsync; 90 103 $needsync = 0; 91 my $pid = fork; 92 if ($pid == 0) { 93 $SIG{INT} = undef; 94 exit sync(); 104 { 105 local $SIG{HUP} = 'IGNORE'; 106 $syncm->updrev; 107 # listing module to run in this loop 108 $lasttout = scalar(time) if ($levelsync == 2); 95 109 } 96 my $retpid; 97 while(($retpid = waitpid(-1, 0)) <= 0) {} 98 if ($retpid) { 99 my $res = $? << 8; 110 foreach my $module ($syncm->list_modules()) { 111 next if ($syncm->ini->val($module, 'lazy') && $levelsync < 2); 112 my $res = process($module, $revs{$module} || 0); 100 113 if ($res) { 101 la_log LA_ERR, "Sync process exit with $res"; 102 } 103 next; 114 $revs{$module} = $syncm->dbrev; 115 } 104 116 } 105 117 } 106 118 107 119 # waiting, to perform next sync 108 sleep(60 * 15); 109 $needsync = 1; 120 sleep(15) unless($needsync); 121 # if it is not time yet: 122 next if($lasttout + ($wait * 60) > scalar(time)); 123 $needsync = 2; 110 124 } 111 125 -
LATMOS-Accounts/bin/la-warn-expire
r778 r861 33 33 =over 4 34 34 35 =item -c|--config config file35 =item -c|--config configdir 36 36 37 Use this configuration fileinstead of the default one.37 Use this configuration directory instead of the default one. 38 38 39 39 =item -m|mail … … 69 69 =head1 CONFIGURATION 70 70 71 Some variables are taken from configuration file:71 Some variables are taken from configuration directory: 72 72 73 73 =over 4 -
LATMOS-Accounts/bin/la-web-directory
r849 r861 10 10 =head1 NAME 11 11 12 la- query - Tools to query base in LATMOS::Accounts system12 la-web-directory - Generate directory file for website 13 13 14 14 =head1 SYNOPSIS 15 15 16 la-query [options] [obj_id] 17 18 =item [obj_id] : If present, all set attributes (rw) will be displayed for that obj_id. 19 If none is given, all obj_ids will be printed. 20 21 For the default object_type (user), obj_id = login. 22 23 Example : la-query lambda 16 la-web-directory 24 17 25 18 =cut … … 39 32 =over 4 40 33 41 =item -c|--config config file34 =item -c|--config configdir 42 35 43 Use this configuration fileinstead of the default one.36 Use this configuration directory instead of the default one. 44 37 45 38 =item -b|--base basename … … 73 66 foreach my $user (sort $labase->search_objects('user', 74 67 @filters ? @filters : 'sn=*')) { 75 my $ouser = $labase->get_object('user', $user) ;68 my $ouser = $labase->get_object('user', $user) or next; 76 69 $ouser->get_attributes('sn') or next; 77 70 if ($noexpire && (my $expdate = $ouser->get_attributes('expireText'))) { … … 84 77 85 78 my $company = $ouser->get_attributes('company'); 86 my $contrat = $ouser->get_attributes('contratType') ;79 my $contrat = $ouser->get_attributes('contratType') || ''; 87 80 if ($company){ 88 81 if (($company ne "LATMOS")&&($contrat ne "heberges")) { … … 101 94 102 95 if ($labase->is_supported_object('address')) { 103 @oaddress = 96 @oaddress = 97 sort { $a->get_attributes('isMainAddress') ? 0 : 1 } 104 98 grep { $_ } ( 105 99 map { $labase->get_object('address', $_) } … … 125 119 $department = join(' ', @userdepts); 126 120 } 127 128 my $line = join(';', map { $_ || '' } ( 121 122 my @fmtaddr; 123 foreach (0, 1) { 124 if ($oaddress[$_]) { 125 126 my $city; 127 if (my $site = $oaddress[$_]->get_attributes('site')) { 128 $city = $labase->get_object('site', 129 $site)->get_attributes('siteNick'); 130 } 131 if (!$city) { 132 $city = $oaddress[$_]->get_attributes('l') || ''; 133 $city =~s/Paris */PAR/g; 134 $city =~s/Guyancourt */GUY/g; 135 $city =~s/Vélizy-Villacoublay */VEL/g; 136 $city =~s/VerriÚres le Buisson */VLB/g; 137 $city =~s/St Maur des Fossés */STM/g; 138 } 139 my $office = $oaddress[$_]->get_attributes('physicalDeliveryOfficeName'); 140 push(@fmtaddr, join('-', grep { defined($_) } ($city || '', $office))); 141 } 142 } 143 144 my $line = join('|', map { $_ || '' } ( 129 145 $ouser->get_attributes('sn'), 130 146 $ouser->get_attributes('givenName'), 131 147 $department, 132 ($oaddress[0] ? join(' ', map { $_ || '' } 133 $oaddress[0]->get_attributes('l'), grep { $_ } 134 $oaddress[0]->get_attributes('physicalDeliveryOfficeName'), 135 ) : ''), 136 ($oaddress[1] ? join(' ', map { $_ || '' } grep { $_ } 137 $oaddress[1]->get_attributes('l'), 138 $oaddress[1]->get_attributes('physicalDeliveryOfficeName'), 139 ) : ''), 140 ($oaddress[0] ? $oaddress[0]->get_attributes('telephoneNumber') : ''), 141 ($oaddress[1] ? $oaddress[1]->get_attributes('telephoneNumber') : ''), 148 $fmtaddr[0] || '', 149 $fmtaddr[1] || '', 150 map { 151 my $l = $_ || ''; 152 $l =~s/ *([0-9])/$1/g; 153 $l =~s/\(//g; 154 $l =~s/\)//g; 155 $l =~s/\+33//g; 156 $l 157 } ( 158 ($oaddress[0] ? $oaddress[0]->get_attributes('telephoneNumber') : ''), 159 ($oaddress[1] ? $oaddress[1]->get_attributes('telephoneNumber') : ''), 160 ), 142 161 $ouser->get_attributes('mail'), 143 162 $ouser->get_attributes('nickname'), 163 $ouser->get_attributes('snNative') || '', 164 $ouser->get_attributes('givenNameNative') || '', 165 $ouser->get_attributes('wWWHomePage') || '', 166 $ouser->get_attributes('halReference') || '', 144 167 )); 145 $line =~s/Paris */PAR-/g; 146 $line =~s/Guyancourt */GUY-/g; 147 $line =~s/Vélizy-Villacoublay */VEL-/g; 148 $line =~s/VerriÚres le Buisson */VLB-/g; 149 $line =~s/St Maur des Fossés */STM-/g; 150 $line =~s/\+ *33 *1 *//g; 168 $line =~s/:1/:01/g; 151 169 152 170 $users{$ouser->get_attributes('sn')}{$ouser->get_attributes('givenName')} = $line; -
LATMOS-Accounts/etc/init.d/la-sync-manager
r603 r861 11 11 export LANG 12 12 13 USER= apache13 USER=nobody 14 14 [ -f /etc/sysconfig/latmos-accounts ] && \ 15 15 . /etc/sysconfig/latmos-accounts -
LATMOS-Accounts/latmos-accounts.spec.in
r841 r861 1 1 %define realname LATMOS-Accounts 2 2 %define version @VERSION@ 3 %define release %mkrel 13 %define release %mkrel %{?svnrelease:0.%{svnrelease}}%{?!svnrelease:1} 4 4 5 5 Name: latmos-accounts … … 24 24 BuildRequires: perl(Net::DNS) 25 25 BuildRequires: perl(Template) 26 BuildRequires: perl(Net::IP) 27 BuildRequires: perl(Text::CSV_XS) 28 BuildRequires: perl(Heimdal::Kadm5) 26 29 27 30 Requires: perl(Mail::Sendmail) … … 30 33 Requires: perl(DBD::Pg) 31 34 Requires: perl(IO::Socket::SSL) 35 Requires: perl-Term-ReadLine-Gnu 32 36 33 37 %description … … 77 81 %config(noreplace) %_sysconfdir/sysconfig/latmos-accounts 78 82 %config(noreplace) %_sysconfdir/cron.d/latmos-accounts 79 %attr(0600, root,root) %config(noreplace) %_sysconfdir/latmos-account.ini83 %attr(0600,nobody,nobody) %config(noreplace) %_sysconfdir/latmos-accounts/* 80 84 %_bindir/* 85 %{_mandir}/man1/* 81 86 %{_mandir}/man3/* 82 %{_mandir}/man 1/*87 %{_mandir}/man5/* 83 88 %perl_vendorlib/* 84 89 %_datadir/latmos-accounts -
LATMOS-Accounts/lib/LATMOS/Accounts.pm
r684 r861 21 21 =cut 22 22 23 sub _configdir { 24 my ($self) = @_; 25 ($self || {})->{_configdir} || '/etc/latmos-accounts' 26 } 27 23 28 =head1 FUNCTION 24 29 25 =head2 new($config file)30 =head2 new($configdir) 26 31 27 32 Instanciate a new LATMOS::Accounts object. 28 33 29 $config file if defined is the Config::IniFiles formatted fileto use,30 default to F</etc/latmos-account .ini>.34 $configdir if defined is the directory containing files to use, 35 default to F</etc/latmos-accounts/>. 31 36 32 37 =cut … … 35 40 my ($class, $config, %options) = @_; 36 41 37 $config ||= '/etc/latmos-account.ini'; 42 $config ||= _configdir(); 43 my $oldconfig ||= '/etc/latmos-account.ini'; 44 45 # If config file not found, fallback to old one 46 my $configfile = -f join('/', $config, 'latmos-accounts.ini') 47 ? join('/', $config, 'latmos-accounts.ini') 48 : '/etc/latmos-account.ini'; 38 49 39 50 my $self = Config::IniFiles->new( 40 -file => $config ,51 -file => $configfile, 41 52 '-default' => '_default_', 42 ); 43 if ((!$options{noacl}) && $self->val('_default_', 'acls')) { 44 my $acls = LATMOS::Accounts::Acls->new( 45 $self->val('_default_', 'acls') 46 ) or do { 47 return; 48 }; 49 $self->{_acls} = $acls; 53 ) or do { 54 la_log(LA_ERR, 'Can\'t open main config file %s', $configfile); 55 return; 56 }; 57 58 $self->{_configdir} = $config; 59 bless($self, $class); 60 61 if (!$options{noacl}) { 62 if ($self->val('_default_', 'acls')) { 63 $self->{_acls} = LATMOS::Accounts::Acls->new( 64 $self->val('_default_', 'acls') 65 ) or do { 66 la_log(LA_ERR, 67 'Cannot load ACL file %s', $self->val('_default_', 'acls') 68 ); 69 return; 70 }; 71 } elsif (-f (my $aclf = join('/', $self->_configdir, 'la-acls.ini'))) { 72 $self->{_acls} = LATMOS::Accounts::Acls->new($aclf) or do { 73 la_log(LA_ERR, 'Cannot load ACL file %s', $aclf); 74 return; 75 }; 76 } 50 77 } 51 78 … … 53 80 $self->{_allowed_values} = Config::IniFiles->new( 54 81 -file => $self->val('_default_', 'allowed_values'), 55 -allowempty => 1,56 82 ) or do { 83 la_log(LA_ERR, 'Cannot load ALLOWED VALUES %s', 84 $self->val('_default_', 'allowed_values')); 57 85 return; 58 86 }; 59 } 60 61 bless($self, $class) 87 } elsif (-f (my $allowf = join('/', $self->_configdir, 88 'la-allowed-values.ini'))) { 89 $self->{_allowed_values} = Config::IniFiles->new( 90 -file => $allowf, 91 ) or do { 92 la_log(LA_ERR, 'Cannot load ALLOWED VALUES %s', $allowf); 93 return; 94 }; 95 } 96 97 $self 62 98 } 63 99 … … 153 189 acls => $self->{_acls}, 154 190 allowed_values => $self->{_allowed_values}, 191 configdir => $self->_configdir, 155 192 ) or do { 156 193 la_log(LA_WARN, "Cannot instanciate base $section ($type)"); -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases.pm
r856 r861 67 67 } 68 68 69 =head2 log($level, $msg, $arg) 70 71 Log a message prefixed by database information 72 73 =cut 74 69 75 sub log { 70 76 my ($self, $level, $msg, @args) = @_; … … 73 79 } 74 80 81 =head2 label 82 83 Return the database label 84 85 =cut 86 75 87 sub label { 76 88 $_[0]->{_label} || 'NoLabel'; … … 81 93 } 82 94 83 sub allowed_values { 84 $_[0]->{_allowed_values} 85 } 86 87 sub obj_attr_allowed_values { 88 my ($self, $otype, $attr) = @_; 89 if ($self->allowed_values) { 90 return $self->allowed_values->val("$otype.$attr", 'allowed'); 91 } 92 return(); 93 } 94 95 sub check_allowed_values { 96 my ($self, $otype, $attr, $attrvalues) = @_; 97 $self->allowed_values or return 1; 98 my @values = ref $attrvalues ? @{ $attrvalues } : $attrvalues; 99 foreach my $value (@values) { 100 $value or next; 101 if (my @allowed = $self->allowed_values->val("$otype.$attr", 'allowed')) { 102 grep { $value eq $_ } @allowed or do { 103 $self->log(LA_ERR, 104 "value `%s' is not allow for %s.%s per configuration (allowed_values)", 105 $value, $otype, $attr 106 ); 107 return; 108 }; 109 } 110 } 111 return 1; 112 } 113 114 sub _load_obj_class { 115 my ($self, $otype) = @_; 116 117 # finding perl class: 118 my $pclass = ref $self; 119 $pclass .= '::' . ucfirst(lc($otype)); 120 eval "require $pclass;"; 121 if ($@) { 122 $self->log(LA_DEBUG, 'Cannot load perl class %s', $pclass); 123 return 124 } # error message ? 125 return $pclass; 126 } 127 128 =head2 list_canonical_fields($otype, $for) 129 130 Return the list of supported fields by the database for object type $otype. 131 132 Optionnal $for specify the goal for which the list is requested, only supported 133 fields will be returns 134 135 =cut 136 137 sub list_canonical_fields { 138 my ($self, $otype, $for) = @_; 139 $for ||= 'rw'; 140 my $pclass = $self->_load_obj_class($otype) or return; 141 sort $pclass->_canonical_fields($self, $for); 142 } 143 144 sub get_attr_schema { 145 my ($self, $otype, $attribute) = @_; 146 my $pclass = $self->_load_obj_class($otype) or return; 147 if ($pclass->can('_get_attr_schema')) { 148 my $info = $pclass->_get_attr_schema($self, $attribute); 149 return $info if ($info); 150 } 151 if ($self->can('_get_attr_schema')) { 152 my $info = $self->_get_attr_schema($otype, $attribute); 153 return $info if($info); 154 } 155 return {} 156 } 157 158 sub attribute { 159 my ($self, $otype, $attribute) = @_; 160 return LATMOS::Accounts::Bases::Attributes->new( 161 $attribute, 162 $self, 163 $otype, 164 ); 165 } 166 167 sub delayed_fields { 168 my ($self, $otype, $for) = @_; 169 $for ||= 'rw'; 170 my $pclass = $self->_load_obj_class($otype) or return; 171 $pclass->_delayed_fields($self, $for); 172 } 173 174 =head2 get_field_name($otype, $c_fields, $for) 175 176 Return the internal fields name for $otype object for 177 canonical fields $c_fields 178 179 =cut 180 181 sub get_field_name { 182 my ($self, $otype, $c_fields, $for) = @_; 183 $for ||= 'rw'; 184 my $pclass = $self->_load_obj_class($otype) or return; 185 $pclass->_get_field_name($c_fields, $self, $for); 95 sub options { 96 my ($self, $opt) = @_; 97 return $self->{_options}{$opt}; 186 98 } 187 99 … … 212 124 } 213 125 126 sub ordered_objects { 127 my ($self) = @_; 128 129 my %deps; 130 my %maxdeps; 131 my @objs = sort { $b cmp $a } $self->list_supported_objects; 132 foreach my $obj (@objs) { 133 foreach my $at ($self->list_canonical_fields($obj)) { 134 my $attr = $self->attribute($obj, $at); 135 $attr->ro and next; 136 $attr->{delayed} and next; 137 if (my $res = $attr->reference) { 138 $deps{$obj}{$res} ||= 1; 139 if ($attr->mandatory) { 140 $deps{$obj}{$res} = 2; 141 $maxdeps{$res} = 1; 142 } 143 } 144 } 145 } 146 147 sort { 148 if (keys %{$deps{$a} || {}}) { 149 if (keys %{$deps{$b} || {}}) { 150 return ( 151 ($deps{$a}{$b} || 0) > ($deps{$b}{$a} || 0) ? 1 : 152 ($deps{$b}{$a} || 0) > ($deps{$a}{$b} || 0) ? -1 : 153 ($maxdeps{$b} || 0) - ($maxdeps{$a} || 0) 154 ); 155 } else { 156 return 1; 157 } 158 } elsif (keys %{$deps{$b} || {}}) { 159 return -1; 160 } else { 161 return ($maxdeps{$b} || 0) - ($maxdeps{$a} || 0) 162 } 163 } @objs; 164 } 165 166 sub _load_obj_class { 167 my ($self, $otype) = @_; 168 169 # finding perl class: 170 my $pclass = ref $self; 171 $pclass .= '::' . ucfirst(lc($otype)); 172 eval "require $pclass;"; 173 if ($@) { 174 $self->log(LA_DEBUG, 'Cannot load perl class %s', $pclass); 175 return 176 } # error message ? 177 return $pclass; 178 } 179 180 214 181 =head2 is_supported_object($otype) 215 182 … … 259 226 sub create_object { 260 227 my ($self, $otype, $id, %data) = @_; 228 "$id" or do { 229 $self->log(LA_ERR, "Cannot create %s object with empty id", 230 $otype); 231 return; 232 }; 261 233 my $pclass = $self->_load_obj_class($otype); 262 234 if ($pclass->_create($self, $id, %data)) { … … 289 261 return; 290 262 }; 291 if (my $chk = (lc($otype) eq 'user' || lc($otype) eq 'group') 263 264 $self->_create_c_object($otype, $id, %cdata); 265 } 266 267 sub _create_c_object { 268 my ($self, $otype, $id, %cdata) = @_; 269 270 if (my $chk = ( 271 lc($otype) eq 'user' || lc($otype) eq 'group') 292 272 ? LATMOS::Accounts::Utils::check_ug_validity($id) 293 273 : LATMOS::Accounts::Utils::check_oid_validity($id)) { … … 301 281 }; 302 282 } 303 304 $self->_create_c_object($otype, $id, %cdata);305 }306 307 sub _create_c_object {308 my ($self, $otype, $id, %cdata) = @_;309 283 310 284 # populating default value … … 324 298 to_ascii(lc($cdata{sn})),) 325 299 : undef; 300 $mailid =~ s/\s*//g if($mailid); 326 301 327 302 if ($mailid && 328 303 $self->is_supported_object('aliases') && 329 304 ! $self->get_object('aliases', $mailid)) { 330 if ( $self->get_field_name($otype, 'mail', 'write')) {331 if ( $self->{defattr}{'user.maildomain'}) {305 if (my $attr = $self->attribute($otype, 'mail')) { 306 if ((!$attr->ro) && $self->{defattr}{'user.maildomain'}) { 332 307 $cdata{mail} ||= sprintf('%s@%s', 333 308 $mailid, … … 335 310 } 336 311 } 337 if ( $self->get_field_name($otype, 'aliases', 'write')) {338 $cdata{aliases} ||= $mailid ;312 if (my $attr = $self->attribute($otype, 'aliases')) { 313 $cdata{aliases} ||= $mailid unless ($attr->ro); 339 314 } 340 if ( $self->get_field_name($otype, 'revaliases', 'write')) {341 $cdata{revaliases} ||= $mailid ;315 if (my $attr = $self->attribute($otype, 'revaliases')) { 316 $cdata{revaliases} ||= $mailid unless ($attr->ro); 342 317 } 343 318 } … … 348 323 my %data; 349 324 foreach my $cfield (keys %cdata) { 350 my $field = $self->get_field_name($otype, $cfield, 'write') or next; 351 $data{$field} = $cdata{$cfield}; 352 } 353 keys %data or return 0; # TODO: return an error ? 325 my $attribute = $self->attribute($otype, $cfield) or next; 326 $attribute->ro and next; 327 $data{$attribute->iname} = $cdata{$cfield}; 328 } 329 #keys %data or return 0; # TODO: return an error ? 354 330 $self->create_object($otype, $id, %data); 331 } 332 333 334 sub _allowed_values { 335 $_[0]->{_allowed_values} 336 } 337 338 sub obj_attr_allowed_values { 339 my ($self, $otype, $attr) = @_; 340 if ($self->_allowed_values && 341 $self->_allowed_values->SectionExists("$otype.$attr")) { 342 return grep { defined($_) } $self->_allowed_values->val("$otype.$attr", 'allowed'); 343 } 344 return(); 345 } 346 347 sub check_allowed_values { 348 my ($self, $otype, $attr, $attrvalues) = @_; 349 $self->_allowed_values or return 1; 350 my @values = ref $attrvalues ? @{ $attrvalues } : $attrvalues; 351 foreach my $value (@values) { 352 $value or next; 353 if (my @allowed = $self->obj_attr_allowed_values($otype, $attr)) { 354 grep { $value eq $_ } @allowed or do { 355 $self->log(LA_ERR, 356 "value `%s' is not allow for %s.%s per configuration (allowed_values)", 357 $value, $otype, $attr 358 ); 359 return; 360 }; 361 } 362 } 363 return 1; 364 } 365 366 =head2 list_canonical_fields($otype, $for) 367 368 Return the list of supported fields by the database for object type $otype. 369 370 Optionnal $for specify the goal for which the list is requested, only supported 371 fields will be returns 372 373 =cut 374 375 sub list_canonical_fields { 376 my ($self, $otype, $for) = @_; 377 $for ||= 'rw'; 378 my $pclass = $self->_load_obj_class($otype) or return; 379 sort $pclass->_canonical_fields($self, $for); 380 } 381 382 sub _get_attr_schema { 383 my ($self, $otype) = @_; 384 my $pclass = $self->_load_obj_class($otype) or return; 385 return $pclass->_get_attr_schema($self); 386 } 387 388 sub get_attr_schema { 389 my ($self, $otype, $attribute) = @_; 390 my $info = $self->_get_attr_schema($otype); 391 if ($info->{$attribute}) { 392 return $info->{$attribute}; 393 } else { 394 return; 395 } 396 } 397 398 sub attribute { 399 my ($self, $otype, $attribute) = @_; 400 return LATMOS::Accounts::Bases::Attributes->new( 401 $attribute, 402 $self, 403 $otype, 404 ); 405 } 406 407 sub delayed_fields { 408 my ($self, $otype, $for) = @_; 409 $self->log(LA_WARN, "calling DEPRECATED delayed_fields " . join(',', 410 caller)); 411 $for ||= 'rw'; 412 my @attrs; 413 foreach ($self->list_canonical_fields($otype, $for)) { 414 my $attr = $self->attribute($otype, $_) or next; 415 $for =~ /w/ && $attr->ro and next; 416 $attr->delayed or next; 417 push(@attrs, $_); 418 } 419 @attrs 420 } 421 422 sub ochelper { 423 my ($self, $otype) = @_; 424 my $pclass = ucfirst(lc($otype)); 425 foreach my $class ( 426 ref($self) . '::OCHelper::' . $pclass, 427 ref($self) . '::OCHelper', 428 "LATMOS::Accounts::Bases::OCHelper::$pclass", 429 'LATMOS::Accounts::Bases::OCHelper' ) { 430 eval "require $class;"; 431 if ($@) { next } # error message ? 432 my $ochelper = "$class"->new($self, $otype); 433 return $ochelper; 434 } 435 return; 355 436 } 356 437 … … 463 544 } 464 545 } 546 547 $self->postcommit(); 548 465 549 return 1; 550 } 551 552 sub postcommit { 553 my ($self) = @_; 554 555 if ($self->{_options}{postcommit}) { 556 exec_command($self->{_options}{postcommit}, 557 { 558 BASE => $self->label, 559 BASETYPE => $self->type, 560 HOOK_TYPE => 'POST', 561 CONFIG => $self->{_options}{configdir}, 562 } 563 ); 564 } else { 565 return 1; 566 } 466 567 } 467 568 … … 541 642 : $self->list_canonical_fields($srcobj->type, 'w'); 542 643 my %data; 543 my %delayed = map { $_ => 1 } $self->delayed_fields($srcobj->type);544 644 foreach (@fields) { 545 $srcobj->get_field_name($_, 'r') or next; 645 # check attribute exists in source: 646 my $attr = $srcobj->attribute($_) or next; 546 647 if (! $options{onepass}) { 547 648 if ($options{firstpass}) { 548 $ delayed{$_}and next;649 $attr->delayed and next; 549 650 } else { 550 $ delayed{$_}or next;651 $attr->delayed or next; 551 652 } 552 653 } 553 654 $data{$_} = $srcobj->_get_c_field($_); 554 655 } 555 keys %data or return '';556 656 if (my $dstobj = $self->get_object($srcobj->type, $srcobj->id)) { 657 keys %data or return 'SYNCED'; 658 foreach (keys %data) { 659 if (!$dstobj->attribute($_) || 660 $dstobj->attribute($_)->ro) { 661 delete($data{$_}); 662 } 663 } 557 664 my $res = $dstobj->_set_c_fields(%data); 558 665 if (defined $res) { … … 615 722 }; 616 723 617 if ($self-> get_field_name('user', 'exported', 'r')) {724 if ($self->attribute('user', 'exported')) { 618 725 if (!$uobj->_get_c_field('exported')) { 619 726 la_log(LA_ERR, "User $username found but currently unexported"); … … 622 729 } 623 730 624 if (my $expire = $uobj->_get_c_field('shadowExpire')) { 625 if ($expire > 0 && $expire < int(time / ( 3600 * 24 ))) { 626 la_log(LA_ERR, "Account $username has expired (%d / %d)", 627 $expire, int(time / ( 3600 * 24 ))); 628 return; 629 } 731 if ($uobj->_get_c_field('expired')) { 732 la_log(LA_ERR, "Account $username has expired (%s)", 733 $uobj->_get_c_field('expired')); 734 return; 630 735 } 631 736 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ad/Group.pm
r821 r861 42 42 sub _my_ldap_classes { qw(top group) } 43 43 44 sub _delayed_fields { 45 my ($self)= @_; 46 return qw(memberUID member managedBy); 47 } 48 49 sub _canonical_fields { 50 my ($self, $base, $mode) = @_; 51 ( 52 qw(gidNumber description member memberUID sAMAccountName managedBy), 53 ($mode !~ /w/ 54 ? qw(cn dn objectClass) 55 : () 56 ) 57 ) 44 sub _get_attr_schema { 45 my ($class, $base) = @_; 46 { 47 gidNumber => { uniq => 1, }, 48 description => { }, 49 member => { 50 delayed => 1, 51 can_values => sub { $base->list_objects('user') }, 52 }, 53 memberUID => { delayed => 1, }, 54 sAMAccountName => { }, 55 managedBy => { 56 delayed => 1, 57 can_values => sub { $base->list_objects('user') }, 58 }, 59 cn => { ro => 1, }, 60 dn => { ro => 1, }, 61 objectClass => { ro => 1, }, 62 msSFU30NisDomain => { }, 63 msSFU30Name => { }, 64 65 } 58 66 } 59 67 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ad/User.pm
r810 r861 43 43 sub _my_ldap_classes { qw(top person organizationalPerson user) } 44 44 45 sub _delayed_fields { 46 my ($self)= @_; 47 return qw(memberOf manager); 48 } 49 50 sub _canonical_fields { 51 my ($self, $base, $mode) = @_; 52 ( 53 qw( 54 sn name givenName 55 sAMAccountName uid gecos 56 homeDirectory loginShell 57 uidNumber gidNumber 58 shadowLastChange shadowMin shadowMax 59 shadowWarning shadowInactive shadowExpire 60 shadowFlag 61 description 62 mail 63 telephoneNumber 64 ipPhone otherTelephone department 65 title mobile homePhone 66 accountExpires 67 streetAddress postalCode postOfficeBox l 68 physicalDeliveryOfficeName 69 company st 70 displayName 71 initials 72 manager 73 userAccountControl 74 locked 75 memberOf 76 winhomeDirectory 77 facsimileTelephoneNumber 78 ), 79 ($mode !~ /w/ 80 ? qw(cn dn uSNCreated uSNChanged directReports objectClass) 81 : () 82 ) 83 ) 45 sub _get_attr_schema { 46 my ($class, $base) = @_; 47 { 48 sn => { }, 49 name => { }, 50 givenName => { }, 51 sAMAccountName => { }, 52 uid => { uniq => 1, }, 53 gecos => { }, 54 homeDirectory => { }, 55 loginShell => { }, 56 uidNumber => { uniq => 1, }, 57 gidNumber => { 58 mandatory => 1, 59 can_values => sub { 60 map { $base->get_object('group', 61 $_)->get_attributes('gidNumber') } 62 $base->list_objects('group') 63 }, 64 display => sub { 65 my ($self, $val) = @_; 66 my ($gr) = $self->base->search_objects('group', "gidNumber=$val") 67 or return; 68 return $gr; 69 }, 70 reference => 'group', 71 }, 72 shadowLastChange => { }, 73 shadowMin => { }, 74 shadowMax => { }, 75 shadowWarning => { }, 76 shadowInactive => { }, 77 shadowExpire => { }, 78 shadowFlag => { }, 79 description => { }, 80 mail => { }, 81 telephoneNumber => { }, 82 ipPhone => { }, 83 otherTelephone => { }, 84 department => { }, 85 title => { }, 86 mobile => { }, 87 homePhone => { }, 88 accountExpires => { }, 89 streetAddress => { }, 90 postalCode => { }, 91 postOfficeBox => { }, 92 l => { }, 93 physicalDeliveryOfficeName => { }, 94 company => { }, 95 st => { }, 96 displayName => { }, 97 initials => { }, 98 manager => { 99 delayed => 1, 100 can_values => sub { $base->list_objects('user') }, 101 }, 102 userAccountControl => { }, 103 locked => { }, 104 memberOf => { delayed => 1, }, 105 winhomeDirectory => { }, 106 facsimileTelephoneNumber => { }, 107 cn => { ro => 1, }, 108 dn => { ro => 1, }, 109 uSNCreated => { ro => 1, }, 110 uSNChanged => { ro => 1, }, 111 directReports => { ro => 1, }, 112 objectClass => { ro => 1, }, 113 msSFU30NisDomain => { }, 114 msSFU30Name => { }, 115 labeledURI => {}, 116 wWWHomePage => {}, 117 } 84 118 } 85 119 … … 206 240 }; 207 241 /^manager$/ && $value and do { 208 my $user = $base->get_object('user', $value) or next; 242 my $user = $base->get_object('user', $value) or do { 243 $value = undef; 244 next; 245 }; 209 246 $value = $user->get_field('dn'); 210 247 next; 211 248 }; 212 249 /^locked$/ and do { 213 my $uac = $entry->get_value('userAccountControl') ;250 my $uac = $entry->get_value('userAccountControl') || 0; 214 251 if ($value) { 215 252 $uac |= 0x00000002; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Attributes.pm
r857 r861 25 25 : (undef, $base_or_object, $maybe_otype); 26 26 27 my $attr_info = $base->get_attr_schema($otype, $attributes) ;27 my $attr_info = $base->get_attr_schema($otype, $attributes) or return; 28 28 29 29 $attr_info->{_base} = $base; … … 38 38 sub name { $_[0]->{_name} } 39 39 sub otype { $_[0]->{_otype} } 40 sub mandatory { $_[0]->{mandatory} || 0 } 41 sub object { $_[0]->{_object} } 42 43 =head2 reference 44 45 A object type this attribute refer to 46 47 =cut 48 49 sub reference { 50 my ($self) = @_; 51 if ($self->{reference} && 52 $self->base->is_supported_object($self->{reference})) { 53 return $self->{reference}; 54 } else { 55 return; 56 } 57 } 40 58 41 59 =head2 … … 49 67 sub label { $_[0]->{label} || $_[0]->{_name} } 50 68 69 sub has_values_list { 70 my ($self) = @_; 71 if ($self->base->obj_attr_allowed_values( 72 $self->otype, 73 $self->name) || 74 $self->{can_values} || 75 $self->reference) { 76 return 1; 77 } else { 78 return 0; 79 } 80 } 81 51 82 sub can_values { 52 83 my ($self) = @_; … … 59 90 return @{$self->{can_values}}; 60 91 } elsif (ref $self->{can_values} eq 'CODE') { 61 $self->{can_values}->($self );92 $self->{can_values}->($self, $self->object); 62 93 } else { 63 94 return; 64 95 } 96 } elsif (my $ref = $self->reference) { 97 return $self->base->list_objects($ref); 65 98 } else { return } 66 99 } 67 100 68 sub ro { $_[0]->{ro} || 0 } 101 sub display { 102 my ($self, $value) = @_; 103 if ($self->{display}) { 104 return $self->{display}->($self, $value); 105 } else { 106 return $value; 107 } 108 } 109 110 sub input { 111 my ($self, $value) = @_; 112 if ($self->{input}) { 113 return $self->{input}->($value); 114 } else { 115 return $value; 116 } 117 } 118 119 sub ro { 120 my ($self) = @_; 121 if (ref $self->{ro} eq 'CODE') { 122 return $self->{ro}->($self->object) || 0; 123 } else { 124 return $_[0]->{ro} || 0 125 } 126 } 69 127 70 128 sub readonly { … … 72 130 return 1 if ($self->ro); 73 131 74 return ! $self->base->check_acl($self->object 75 ? ($self->object, $self->name, 'w') 76 : ($self->otype, '@CREATE', 'w')); 132 return ! $self->check_acl('w'); 133 } 134 135 sub check_acl { 136 my ($self, $mode) = @_; 137 return $self->base->check_acl($self->object 138 ? ($self->object, $self->name, $mode) 139 : ($self->otype, '@CREATE', $mode)); 77 140 } 78 141 79 142 =head2 form_type 80 143 81 Return the way the fields must be show in GUI: 144 Return the way the fields must be show in GUI. 145 For each type option maybe given by from_option 146 147 =head3 LABEL 82 148 83 149 =over 4 84 150 85 =item LABEL151 =item length 86 152 87 =item TEXT 153 The length to use to show the attribute 88 154 89 = item DATE155 =back 90 156 91 = item LIST157 =head3 TEXT 92 158 93 =item CHECKBOX 159 =head3 TEXTAREA 160 161 =head3 DATE 162 163 =head3 LIST 164 165 =head3 CHECKBOX 166 167 =over 4 168 169 =item rawvalue 170 171 The real value of the attribute must be show 94 172 95 173 =back … … 97 175 =cut 98 176 99 sub form_type { $_[0]->ro ? 'LABEL' : ($_[0]->{formtype} || 'TEXT') } 177 sub real_form_type { $_[0]->{formtype} || 'TEXT' } 178 179 sub form_type { 180 $_[0]->readonly ? 'LABEL' : 181 $_[0]->{formtype} ? $_[0]->{formtype} : 182 $_[0]->has_values_list ? 'LIST' : 183 $_[0]->real_form_type 184 } 185 186 sub form_option { 187 my ($self, $option) = @_; 188 return $self->{formopts}{$option} 189 } 100 190 101 191 sub uniq { $_[0]->{uniq} || 0 } … … 103 193 sub multiple { $_[0]->{multiple} || 0 } 104 194 195 sub hidden { $_[0]->{hide} || 0 } 196 197 sub delayed { $_[0]->{delayed} || 0 } 198 105 199 1; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Dummy/User.pm
r679 r861 7 7 our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0]; 8 8 9 my %fields_map = ( 10 username => 'username', 11 homeDirectory => 'home', 12 ); 9 sub _get_attr_schema { 10 { 11 username => {}, 12 homeDirectory => { iname => 'home' }, 13 } 14 } 15 16 sub list { 17 return (); 18 } 13 19 14 20 sub new { … … 22 28 } 23 29 24 sub _canonical_fields {25 my ($self) = @_;26 return keys %fields_map;27 }28 29 sub _get_field_name {30 my ($self, $field) = @_;31 return $fields_map{$field};32 }33 34 30 1; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ldap/Group.pm
r766 r861 42 42 sub _my_ldap_classes { qw(top posixGroup) } 43 43 44 sub _delayed_fields { 45 my ($self)= @_; 46 return qw(memberUID); 47 } 48 49 sub _canonical_fields { 50 my ($self, $base, $mode) = @_; 51 ( 52 qw(gidNumber description memberUID), 53 ($mode !~ /w/ 54 ? qw(cn dn objectClass) 55 : () 56 ) 57 ) 44 sub _get_attr_schema { 45 my ($class, $base) = @_; 46 $class->SUPER::_get_attr_schema($base, 47 { 48 gidNumber => { uniq => 1, }, 49 description => { }, 50 memberUID => { multiple => 1, delayed => 1, }, 51 cn => { ro => 1 }, 52 dn => { ro => 1 }, 53 objectClass => { ro => 1 }, 54 } 55 ); 58 56 } 59 57 … … 69 67 $entry->replace(objectClass => [ $class->_my_ldap_classes ],); 70 68 my %delayed; 69 $data{cn} = $id; 71 70 foreach (keys %data) { 72 71 /^(memberUID)$/ and do { -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ldap/Onlyaddress.pm
r678 r861 47 47 ) } 48 48 49 sub _delayed_fields { 50 my ($self)= @_; 51 return qw(); 52 } 53 54 sub _canonical_fields { 55 my ($self, $base, $mode) = @_; 56 ( 57 qw(displayName givenName 58 initials mail sn 59 mobile o uid facsimileTelephoneNumber), # inetOrgPerson 60 qw(street postOfficeBox postalCode postalAddress streetAddress 61 physicalDeliveryOfficeName ou st l telephoneNumber), # organizationalPerson 62 ($mode 63 !~ /w/ 64 ? qw(cn dn objectClass) 65 : () 66 ) 67 ) 49 sub _get_attr_schema { 50 my ($class, $base) = @_; 51 { 52 # inetOrgPerson 53 displayName => {}, 54 givenName => {}, 55 initials => {}, 56 mail => {}, 57 sn => {}, 58 mobile => {}, 59 o => {}, 60 uid => {}, 61 facsimileTelephoneNumber => {}, 62 # organizationalPerson 63 street => {}, 64 postOfficeBox => {}, 65 postalCode => {}, 66 postalAddress => {}, 67 streetAddress => {}, 68 physicalDeliveryOfficeName => {}, 69 ou => {}, 70 st => {}, 71 l => {}, 72 telephoneNumber => {}, 73 cn => { ro => 1 }, 74 dn => { ro => 1 }, 75 objectClass => { ro => 1 }, 76 } 68 77 } 69 78 … … 80 89 [ $class->_my_ldap_classes ],); 81 90 $data{sn} ||= $id; # sn is mandatory 91 $data{cn} = $id; 82 92 foreach (keys %data) { 83 93 $class->_populate_entry($entry, -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ldap/User.pm
r767 r861 49 49 ) } 50 50 51 sub _delayed_fields { 52 my ($self)= @_; 53 return qw(memberOf manager); 54 } 55 56 sub _canonical_fields { 57 my ($self, $base, $mode) = @_; 58 ( 59 qw(displayName givenName homePhone homePostalAddress 60 initials mail sn 61 mobile o uid manager facsimileTelephoneNumber), # inetOrgPerson 62 qw(uidNumber gidNumber homeDirectory 63 userPassword loginShell 64 gecos description), # posixAccount 65 qw(shadowLastChange 66 shadowMin shadowMax 67 shadowWarning 68 shadowInactive 69 shadowExpire 70 shadowFlag), # shadowAccount 71 qw(street postOfficeBox postalCode postalAddress streetAddress 72 physicalDeliveryOfficeName ou st l telephoneNumber), # organizationalPerson 73 ('memberOf'), 74 ($mode 75 !~ /w/ 76 ? qw(cn dn objectClass) 77 : () 78 ) 79 ) 51 sub _get_attr_schema { 52 my ($class, $base) = @_; 53 $class->SUPER::_get_attr_schema($base, 54 { 55 displayName => { }, 56 givenName => { }, 57 homePhone => { }, 58 homePostalAddress => { }, 59 initials => { }, 60 mail => { }, 61 sn => { }, 62 mobile => { }, 63 o => { }, 64 uid => { }, 65 manager => { 66 delayed => 1, 67 can_values => sub { $base->list_objects('user') }, 68 }, 69 facsimileTelephoneNumber => { }, 70 uidNumber => { uniq => 1, }, 71 gidNumber => { 72 reference => 'group', 73 mandatory => 1, 74 can_values => sub { 75 map { $base->get_object('group', 76 $_)->get_attributes('gidNumber') } 77 $base->list_objects('group') 78 }, 79 display => sub { 80 my ($self, $val) = @_; 81 my ($gr) = $self->base->search_objects('group', "gidNumber=$val") 82 or return; 83 return $gr; 84 }, 85 86 }, 87 homeDirectory => { }, 88 userPassword => { }, 89 loginShell => { }, 90 gecos => { }, 91 description => { }, 92 shadowLastChange => { }, 93 shadowMin => { }, 94 shadowMax => { }, 95 shadowWarning => { }, 96 shadowInactive => { }, 97 shadowExpire => { }, 98 shadowFlag => { }, 99 street => { }, 100 postOfficeBox => { }, 101 postalCode => { }, 102 postalAddress => { }, 103 streetAddress => { }, 104 physicalDeliveryOfficeName => { }, 105 ou => { }, 106 st => { }, 107 l => { }, 108 telephoneNumber => { }, 109 memberOf => { delayed => 1, }, 110 111 cn => { ro => 1, }, 112 dn => { ro => 1, }, 113 objectClass => { ro => 1, }, 114 pwdAccountLockedTime => {}, 115 pwdPolicySubentry => {}, 116 pwdChangedTime => { ro => 1 }, 117 labeledURI => {}, 118 } 119 ); 80 120 } 81 121 … … 91 131 $entry->replace(objectClass => 92 132 [ $class->_my_ldap_classes ],); 133 $data{cn} = $id; 93 134 $data{sn} ||= $id; # sn is mandatory 94 135 $data{homeDirectory} ||= '/dev/null'; # homeDirectory is mandatory … … 153 194 $field eq 'manager' and do { 154 195 my $dn = $self->SUPER::get_field($field) or return; 155 return $self->base->_get_object_from_dn($dn)->get_value('cn'); 196 my $manager = $self->base->_get_object_from_dn($dn) or return; 197 return $manager->get_value('cn'); 156 198 }; 157 199 $self->SUPER::get_field($field); … … 195 237 }; 196 238 /^manager$/ && $val and do { 197 my $user = $base->get_object('user', $val) or 198 next; 239 my $user = $base->get_object('user', $val) or do { 240 $val = undef; 241 next; 242 }; 199 243 $val = $user->get_field('dn'); 200 244 next; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Ldap/objects.pm
r715 r861 35 35 36 36 =cut 37 38 sub _get_attr_schema { 39 my ($class, $base, $info) = @_; 40 $info ||= {}; 41 42 foreach (qw( 43 createTimestamp 44 creatorsName 45 entryUUID 46 modifiersName 47 modifyTimestamp 48 entryCSN 49 )) { 50 $info->{$_} = { ro => 1 }; 51 } 52 53 return $info; 54 } 37 55 38 56 sub list { … … 59 77 } 60 78 61 sub _get_field_name {62 my ($self, $field, $base, $for) = @_;63 64 my %fields = map { $_ => 1 } $self->_canonical_fields($base, $for);65 66 return $fields{$field} ? $field : undef;67 }68 69 79 sub new { 70 80 my ($class, $base, $uid) = @_; … … 78 88 ), 79 89 base => $base->object_base_dn($class->type), 90 attrs => [ $class->_canonical_fields($base, 'r') ], 80 91 ); 81 92 … … 135 146 sub _populate_entry { 136 147 my ($self, $entry, $field, $value, $base) = @_; 137 my $val = $entry->get_value($field);148 my $val = ref $self ? $self->get_field($field) : undef; 138 149 my $tr = join(', ', map { $_ || '' } ($field, $val, $value)); 139 150 if ($value) { … … 159 170 } 160 171 foreach (keys %fields) { 161 $self->get_field_name($_, 'w') or next; 172 my $attr = $self->attribute($_) or do { 173 $self->base->log(LA_ERR, "Unknow attribute %s (%s)", 174 $_, $self->type); 175 return; 176 }; 177 $attr->ro and next; 162 178 $self->_populate_entry($self->{entry}, $_, $fields{$_}); 163 179 } -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Mail.pm
r817 r861 15 15 16 16 my $base = { 17 file => { 18 aliases => $options{aliases} || '/etc/aliases', 19 revaliases => $options{revaliases} || '/etc/revaliases', 20 }, 17 file => {}, 21 18 aliases => {}, 22 19 revaliases => {}, 23 20 }; 21 22 foreach (qw(aliases revaliases)) { 23 if ($options{$_}) { 24 $base->{file}{$_} = $options{$_}; 25 } elsif ($options{directory}) { 26 $base->{file}{$_} = $options{directory} . '/' . $_; 27 } else { 28 $base->{file}{$_} = "/etc/$_"; 29 } 30 } 31 24 32 25 33 bless($base, $class); -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Mail/Aliases.pm
r812 r861 16 16 } 17 17 18 sub _canonical_fields { 19 my ($self, $for) = @_; 20 return (qw(forward)); 21 } 22 23 sub _get_field_name { 24 my ($self, $c_field, $base, $for) = @_; 25 for ($c_field) { 26 /^forward$/ and last; 27 return; 18 sub _get_attr_schema { 19 my ($class, $base) = @_; 20 { 21 forward => {}, 28 22 } 29 return $c_field;30 23 } 31 24 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Mail/Revaliases.pm
r351 r861 16 16 } 17 17 18 sub _canonical_fields { 19 my ($self, $for) = @_; 20 return (qw(as)); 21 } 22 23 sub _get_field_name { 24 my ($self, $c_field, $base, $for) = @_; 25 for ($c_field) { 26 /^as$/ and last; 27 return; 18 sub _get_attr_schema { 19 my ($class, $base) = @_; 20 { 21 as => {}, 28 22 } 29 return $c_field;30 23 } 31 24 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Mail/objects.pm
r305 r861 9 9 our $VERSION = (q$Rev: 641 $ =~ /^Rev: (\d+) /)[0]; 10 10 11 #sub list_canonical_fields {12 # my ($self, $for) = @_;13 #} -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Objects.pm
r852 r861 126 126 sub list_canonical_fields { 127 127 my ($self, $for) = @_; 128 $self->base->list_canonical_fields($self->type, $for); 128 $for ||= 'rw'; 129 $self->_canonical_fields($for); 129 130 } 130 131 … … 137 138 } 138 139 139 =head2 get_field_name($field, $for) 140 141 Object shortcut to get the field name supported by the object. 142 143 =cut 144 145 sub get_field_name { 146 my ($self, $field, $for) = @_; 147 $self->base->get_field_name($self->type, $field, $for); 148 } 149 150 =head2 _canonical_fields 151 152 Must return the list of field supported by the object. 153 154 Notice this query will always come from the upstream data base, 155 this function is just a facility to store data in the module, but the 156 underling database can reply themself. 157 158 Is call if underling base doesn't override list_canonical_fields() 159 160 See list_canonical_fields(). 161 162 sub _canonical_fields { 163 my ($self) = @_; 164 } 165 166 =cut 167 168 sub _delayed_fields { 169 my ($self)= @_; 170 return (); 171 } 172 173 =head2 _get_fields_name($field, $for) 174 175 Return the fields name for canonical field $field. 176 $for, if set, is a string containing 'r' for read, 'w' for write, 177 depending usage context. 178 179 sub _get_field_name { 180 my ($self, $field, $for) = @_; 181 } 182 183 =cut 140 sub _canonical_fields { 141 my ($class, $base, $for) = @_; 142 $for ||= 'rw'; 143 my $info = $base->_get_attr_schema($class->type); 144 my @attrs = map { $base->attribute($class->type, $_) } keys %{$info || {}}; 145 @attrs = grep { ! $_->ro } @attrs if($for =~ /w/); 146 map { $_->name } grep { !$_->hidden } @attrs; 147 } 184 148 185 149 =head2 get_field($field) … … 197 161 Return the value for canonical field $cfield. 198 162 199 Call driver specific get_field _name() and get_field()163 Call driver specific get_field() 200 164 201 165 =cut … … 231 195 } 232 196 197 sub get_state { 198 my ($self, $state) = @_; 199 # hum... 200 if (defined(my $res = $self->_get_state($state))) { 201 return $res; 202 } 203 for ($state) { 204 } 205 return; 206 } 207 208 sub _get_state { 209 my ($self, $state) = @_; 210 return; 211 } 212 233 213 sub _get_c_field { 234 214 my ($self, $cfield) = @_; 235 215 my $return; 236 my $ field = $self->base->get_field_name($self->type, $cfield, 'r') or do {216 my $attribute = $self->attribute($cfield) or do { 237 217 $self->base->log(LA_WARN, "Unknow attribute $cfield"); 238 218 return; 239 219 }; 240 $return = $self->get_field($ field);220 $return = $self->get_field($attribute->iname); 241 221 } 242 222 … … 307 287 my %data; 308 288 foreach my $cfield (keys %cdata) { 309 my $ field = $self->base->get_field_name($self->type, $cfield, 'w') or do {289 my $attribute = $self->attribute($cfield) or do { 310 290 $self->base->log(LA_ERR, 311 291 "Cannot set unsupported attribute %s to %s (%s)", … … 314 294 return; 315 295 }; 316 $data{$field} = $cdata{$cfield}; 296 $attribute->ro and do { 297 $self->base->log(LA_ERR, 298 "Cannot set read-only attribute %s to %s (%s)", 299 $cfield, $self->id, $self->type 300 ); 301 return; 302 }; 303 $attribute->mandatory && 304 (!(defined($cdata{$cfield})) || $cdata{$cfield} eq '') and do { 305 $self->base->log(LA_ERR, 306 "%s attribute cannot be empty, ignoring for object %s/%s", 307 $cfield, 308 $self->type, 309 $self->id, 310 ); 311 return 0; 312 }; 313 if (ref $cdata{$cfield}) { 314 $data{$attribute->iname} = []; # ensure hash entry exists 315 foreach (@{$cdata{$cfield}}) { 316 push(@{$data{$attribute->iname}}, defined($_) 317 ? $attribute->input($_) 318 : undef 319 ); 320 } 321 } else { 322 $data{$attribute->iname} = defined($cdata{$cfield}) 323 ? $attribute->input($cdata{$cfield}) 324 : undef; 325 } 317 326 } 318 327 keys %data or return 0; # TODO: return an error ? … … 346 355 sub _set_password { 347 356 my ($self, $clear_pass) = @_; 348 if (my $ field = $self->base->get_field_name($self->type, 'userPassword')) {357 if (my $attribute = $self->base->attribute($self->type, 'userPassword')) { 349 358 my @salt_char = (('a' .. 'z'), ('A' .. 'Z'), (0 .. 9), '/', '.'); 350 359 my $salt = join('', map { $salt_char[rand(scalar(@salt_char))] } (1 .. 8)); 351 my $res = $self->set_fields($field, crypt($clear_pass, '$1$' . $salt)); 352 $self->base->log(LA_NOTICE, 'Mot de passe changé pour %s', $self->id); 360 my $res = $self->set_fields($attribute->iname, crypt($clear_pass, '$1$' . $salt)); 361 $self->base->log(LA_NOTICE, 'Mot de passe changé pour %s', $self->id) 362 if($res); 353 363 return $res; 354 364 } else { … … 390 400 my $match = 1; 391 401 foreach my $field (keys %parsed_filter) { 392 $base-> get_field_name($class->type, $field, 'r') or die393 "Unsupported attribute $field\n";402 $base->attribute($class->type, $field) or 403 la_log LA_WARN "Unsupported attribute $field"; 394 404 my $tmatch = 0; 395 405 foreach (@{$parsed_filter{$field}}) { … … 447 457 sub find_next_numeric_id { 448 458 my ($class, $base, $field, $min, $max) = @_; 449 $base-> get_field_name($class->type, $field) or return;459 $base->attribute($class->type, $field) or return; 450 460 $min ||= 451 461 $field eq 'uidNumber' ? 500 : … … 492 502 foreach my $attr (sort { $a cmp $b } $base->list_canonical_fields($otype, 493 503 $options->{only_rw} ? 'rw' : 'r')) { 494 my $ wok = $base->get_field_name($otype, $attr, 'w');504 my $oattr = $base->attribute($otype, $attr); 495 505 if (ref $self) { 496 506 my $val = $self->get_c_field($attr); 497 507 if ($val || $options->{empty_attr}) { 498 508 if (my @allowed = $base->obj_attr_allowed_values($otype, $attr)) { 499 $dump .= sprintf("# %s must be empty or either: %s\n",509 $dump .= sprintf("# %s must be%s: %s\n", 500 510 $attr, 511 ($oattr->mandatory ? '' : ' empty or either'), 501 512 join(', ', @allowed) 502 513 ); … … 507 518 s/\r?\n/\\n/g; 508 519 $dump .= sprintf("%s%s:%s\n", 509 $ wok ? '' : '# (ro)',520 $oattr->ro ? '# (ro) ' : '', 510 521 $attr, $_ ? " $_" : ''); 511 522 } … … 519 530 } 520 531 $dump .= sprintf("%s%s: %s\n", 521 $ wok ? '' : '# (ro)',532 $oattr->ro ? '# (ro) ' : '', 522 533 $attr, ''); 523 534 } -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql.pm
r850 r861 8 8 use LATMOS::Accounts::Log; 9 9 use DBI; 10 use Crypt::RSA; 11 use Crypt::RSA::Key::Public::SSH; 12 use Crypt::RSA::Key::Private::SSH; 13 use MIME::Base64; 10 14 11 15 our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0]; … … 64 68 undef, undef, 65 69 { 66 RaiseError => 1,70 RaiseError => 0, 67 71 AutoCommit => 0, 68 72 PrintWarn => 1, … … 70 74 } 71 75 ) or do { 72 $self->log(LA_ERR, "Cannot connect to database ");76 $self->log(LA_ERR, "Cannot connect to database: %s", $DBI::errstr); 73 77 return; 74 78 }; … … 92 96 } 93 97 94 sub commit {98 sub _commit { 95 99 my ($self) = @_; 96 100 if ($ENV{LA_NO_COMMIT}) { … … 104 108 } 105 109 106 sub rollback {110 sub _rollback { 107 111 my ($self) = @_; 108 112 if ($ENV{LA_NO_COMMIT}) { … … 131 135 return ($res->{max}); 132 136 } 137 138 139 # Extra non standard functions 133 140 134 141 sub get_global_value { … … 156 163 }; 157 164 } 165 166 sub generate_rsa_key { 167 my ($self, $password) = @_; 168 169 my $rsa = new Crypt::RSA ES => 'PKCS1v15'; 170 my ($public, $private) = $rsa->keygen ( 171 Identity => 'LATMOS-Accounts', 172 Size => 768, 173 Password => $password, 174 Verbosity => 0, 175 KF=>'SSH', 176 ) or die $rsa->errstr(); # TODO avoid die 177 return ($public, $private); 178 } 179 180 sub private_key { 181 my ($self, $password) = @_; 182 my $base = $self; 183 my $serialize = $base->get_global_value('rsa_private_key') or return; 184 my $privkey = Crypt::RSA::Key::Private::SSH->new; 185 $privkey->deserialize(String => [ decode_base64($serialize) ], 186 Passphrase => $password); 187 $privkey 188 } 189 190 sub get_rsa_password { 191 my ($self) = @_; 192 my $base = $self; 193 my $sth = $base->db->prepare(q{ 194 select "name", value from "user" join user_attributes_base 195 on "user".ikey = user_attributes_base.okey 196 where user_attributes_base.attr = 'encryptedPassword' 197 }); 198 $sth->execute; 199 my %users; 200 while (my $res = $sth->fetchrow_hashref) { 201 $users{$res->{name}} = $res->{value}; 202 } 203 %users 204 } 205 206 sub store_rsa_key { 207 my ($self, $public, $private) = @_; 208 my $base = $self; 209 $base->set_global_value('rsa_private_key', 210 encode_base64($private->serialize)); 211 $base->set_global_value('rsa_public_key', 212 $public->serialize); 213 return; 214 } 215 158 216 159 217 sub find_next_expire_users { … … 196 254 } 197 255 256 sub rename_nethost { 257 my ($self, $nethostname, $to, %options) = @_; 258 { 259 my $obj = $self->get_object('nethost', $nethostname); 260 my @cname = grep { $_ && $_ ne $to} 261 $obj->get_attributes('cname'); 262 $obj->set_c_fields(cname => [ @cname ]) or return; 263 } 264 $self->rename_object('nethost', $nethostname, $to) or return; 265 if ($options{'addcname'}) { 266 my $obj = $self->get_object('nethost', $to); 267 my @cname = grep { $_ } $obj->get_attributes('cname'); 268 $obj->set_c_fields(cname => [ @cname, $nethostname ]); 269 } 270 return 1; 271 } 272 273 sub nethost_exchange_ip { 274 my ($self, $ip1, $ip2) = @_; 275 my ($obj1, $obj2); 276 if (my ($host1) = $self->search_objects('nethost', "ip=$ip1")) { 277 $obj1 = $self->get_object('nethost', $host1); 278 } else { 279 $self->la_log(LA_ERR, "Cannot find host having $ip1"); 280 return; 281 } 282 if (my ($host2) = $self->search_objects('nethost', "ip=$ip2")) { 283 $obj2 = $self->get_object('nethost', $host2); 284 } else { 285 $self->la_log(LA_ERR, "Cannot find host having $ip2"); 286 return; 287 } 288 if ($obj1->id eq $obj2->id) { 289 $self->la_log(LA_ERR, "Both ip belong to same host (%s)", $obj1->id); 290 return; 291 } 292 293 my @ip1 = grep { $_ && $_ ne $ip1 } $obj1->get_attributes('ip'); 294 $obj1->set_c_fields(ip => [ @ip1 ]); 295 my @ip2 = grep { $_ && $_ ne $ip2 } $obj2->get_attributes('ip'); 296 $obj2->set_c_fields(ip => [ @ip2, $ip1 ]) or return; 297 $obj1->set_c_fields(ip => [ @ip1, $ip2 ]) or return; 298 return 1; 299 } 300 301 sub register_attribute { 302 my ($self, $otype, $attribute, $comment) = @_; 303 my $pclass = $self->_load_obj_class($otype) or return; 304 $pclass->register_attribute($self, $attribute, $comment); 305 } 306 307 sub get_attribute_comment { 308 my ($self, $otype, $attribute) = @_; 309 my $pclass = $self->_load_obj_class($otype) or return; 310 $pclass->get_attribute_comment($self, $attribute); 311 } 312 313 sub set_attribute_comment { 314 my ($self, $otype, $attribute, $comment) = @_; 315 my $pclass = $self->_load_obj_class($otype) or return; 316 $pclass->set_attribute_comment($self, $attribute, $comment); 317 } 318 198 319 1; 199 320 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Address.pm
r809 r861 43 43 sub has_extended_attributes { 1 } 44 44 45 sub _ inline_fields{46 my ($ self, $for, $base) = @_;45 sub _get_attr_schema { 46 my ($class, $base) = @_; 47 47 48 my %fields = ( 49 name => 'name', 50 exported => 'exported', 51 user => 'user', 48 $class->SUPER::_get_attr_schema($base, 49 { 50 name => { inline => 1, }, 51 exported => { inline => 1, }, 52 user => { inline => 1, 53 reference => 'user', 54 }, 55 site => { 56 reference => 'site', 57 }, 58 sn => { ro => 1, }, 59 mail => { ro => 1, }, 60 givenName => { ro => 1, }, 61 postalAddress => { ro => 1, }, 62 displayName => { ro => 1, }, 63 co => { 64 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 65 }, 66 l => { 67 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 68 }, 69 postalCode => { 70 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 71 }, 72 streetAddress => { 73 formtype => 'TEXTAREA', 74 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 75 }, 76 postOfficeBox => { 77 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 78 }, 79 st => { 80 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 81 }, 82 facsimileTelephoneNumber => { 83 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 84 }, 85 o => { 86 ro => sub { $_[0] && $_[0]->get_attributes('site') ? 1 : 0 }, 87 }, 88 isMainAddress => { formtype => 'CHECKBOX', }, 89 } 52 90 ); 53 %fields54 }55 56 sub _managed_fields {57 my ($self, $for, $base) = @_;58 (site => 'site'),59 $for !~ /w/ ? (60 sn => 'sn',61 mail => 'mail',62 givenName => 'givenName',63 postalAddress => 'postalAddress',64 displayName => 'displayName',65 ) : ()66 }67 68 sub _delayed_fields {69 my ($self)= @_;70 return qw();71 91 } 72 92 … … 75 95 $data{user} or return; 76 96 my $user = $base->get_object('user', $data{user}); 97 $user or return; 77 98 if (!$user->get_c_field('otheraddress')) { 78 99 $data{isMainAddress} = 1; … … 83 104 sub get_field { 84 105 my ($self, $field) = @_; 85 if ((grep { $field eq $_ } __PACKAGE__->_address_fields()) 86 && (my $fsite = $self->get_c_field('site'))) { 106 if ((grep { $field eq $_ } (qw( 107 co l 108 postalCode streetAddress 109 postOfficeBox st 110 facsimileTelephoneNumber o 111 ))) && (my $fsite = $self->get_c_field('site'))) { 87 112 my $site = $self->base->get_object('site', $fsite); 88 113 if ($site) { … … 90 115 } 91 116 } elsif ($field =~ /^(sn|givenName|mail)$/) { 92 my $user = $self->base->get_object('user', $self->_get_c_field('user')); 117 my $user = $self->base->get_object('user', $self->_get_c_field('user')) 118 or return; 93 119 return $user->_get_c_field($field); 94 120 } elsif ($field eq 'postalAddress' ) { … … 125 151 $data{$attr}); 126 152 if ($site) { 127 foreach (__PACKAGE__->_address_fields()) { 153 foreach (qw(co l postalCode streetAddress postOfficeBox st 154 facsimileTelephoneNumber o)) { 128 155 $fdata{$_} = undef; 129 156 $data{$_} = undef; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Aliases.pm
r499 r861 42 42 sub key_field { 'name' } 43 43 44 sub has_extended_attributes { 0}44 sub has_extended_attributes { 1 } 45 45 46 sub _managed_fields { 47 my ($class, $for, $base) = @_; 48 return( 49 $for !~ /w/ 50 ? ( 51 finalpoint => 'finalpoint', 52 parents => 'parents', 53 anyparents => 'anyparents', 54 sameforward => 'sameforward', 55 samedestination => 'samedestination', 56 ) 57 : () 58 ); 46 sub _get_attr_schema { 47 my ($class, $base) = @_; 48 49 $class->SUPER::_get_attr_schema($base, 50 { 51 name => { 52 ro => 1, 53 }, 54 forward => { 55 mandatory => 1, 56 multiple => 1, 57 }, 58 finalpoint => { ro => 1, }, 59 parents => { ro => 1, }, 60 anyparents => { ro => 1, }, 61 sameforward => { ro => 1, }, 62 samedestination => { ro => 1, }, 63 user => { 64 ro => 1, 65 reference => 'user', 66 }, 67 } 68 ) 59 69 } 60 70 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Group.pm
r768 r861 44 44 sub has_extended_attributes { 1 } 45 45 46 sub _inline_fields { 47 my ($self, $for, $base) = @_; 48 return ( 49 gidNumber => 'gidnumber', 50 exported => 'exported', 51 ($for !~ /w/) ? ( 52 name => 'name', 53 cn => 'name', 54 create => 'create', 55 date => 'date', 56 ) : (), 57 ); 58 } 46 sub _get_attr_schema { 47 my ($class, $base) = @_; 59 48 60 sub _managed_fields { 61 my ($self, $for, $base) = @_; 62 63 my %fields = ( 64 memberUID => 'memberUID', 65 member => 'member', 66 $for !~ /w/ ? ( 67 sAMAccountName => 'name', 68 groupname => 'name', 69 ) : (), 70 ); 71 %fields; 72 } 73 74 sub _delayed_fields { 75 my ($self)= @_; 76 return qw(memberUID member); 49 $class->SUPER::_get_attr_schema($base, 50 { 51 gidNumber => { inline => 1, uniq => 1, iname => 'gidnumber', 52 mandatory => 1, }, 53 gidnumber => { inline => 1, uniq => 1, hide => 1, }, 54 exported => { inline => 1, }, 55 name => { inline => 1, ro => 1 }, 56 cn => { inline => 1, ro => 1, iname => 'name', }, 57 create => { inline => 1, ro => 1 }, 58 date => { inline => 1, ro => 1 }, 59 memberUID => { 60 reference => 'user', 61 multiple => 1, 62 delayed => 1, 63 ro => sub { 64 $_[0] && 65 ($_[0]->_get_c_field('sutype') ||'') =~ /^(jobtype|contrattype)$/ 66 ? 1 : 0 67 }, 68 }, 69 member => { 70 reference => 'user', 71 multiple => 1, 72 delayed => 1, 73 can_values => sub { $base->list_objects('user') }, 74 ro => sub { 75 $_[0] && 76 ($_[0]->_get_c_field('sutype') ||'') =~ /^(jobtype|contrattype)$/ 77 ? 1 : 0 78 }, 79 }, 80 sAMAccountName => { iname => 'name', ro => 1 }, 81 groupname => { ro => 1 }, 82 managedBy => { 83 reference => 'user', 84 can_values => sub { 85 my %uniq = map { $_ => 1 } grep { $_ } 86 ($_[1] ? $_[1]->get_attributes('manager') : ()), 87 $base->search_objects('user', 'active=*'); 88 sort keys %uniq; 89 }, 90 }, 91 sutype => { 92 reference => 'sutype', 93 }, 94 } 95 ) 77 96 } 78 97 … … 130 149 $res++; 131 150 } elsif ($member{$_}{c}) { 151 if (($user->get_c_field('department') || '') eq $self->id) { 152 $self->base->log(LA_WARN, 153 "Don't removing user %s from group %s: is it's department", 154 $user->id, $self->id); 155 next; 156 } 132 157 my $sth = $self->db->prepare_cached( 133 158 q{delete from group_attributes_users where value = ? and attr = ? and okey = ?} … … 142 167 } 143 168 if (keys %fdata) { 144 return $res + $self->SUPER::set_fields(%fdata); 169 my $setres = $self->SUPER::set_fields(%fdata); 170 if (defined($setres)) { return $res + $setres; } 171 else { return; } 145 172 } else { 146 173 $res -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Revaliases.pm
r353 r861 44 44 sub has_extended_attributes { 0 } 45 45 46 sub _get_attr_schema { 47 my ($class, $base) = @_; 48 49 $class->SUPER::_get_attr_schema($base, 50 { 51 name => { reference => 'user', inline => 1, }, 52 } 53 ) 54 } 55 46 56 sub _create { 47 57 my ($class, $base, $id, %data) = @_; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Site.pm
r769 r861 43 43 sub has_extended_attributes { 1 } 44 44 45 sub _inline_fields { 46 my ($class, $for, $base) = @_; 47 return ( 48 expire => 'expire', 49 ($for !~ /w/) ? ( 50 name => 'name', 51 cn => 'name', 52 create => 'create', 53 date => 'date', 54 ) : (), 55 ); 56 } 45 sub _get_attr_schema { 46 my ($class, $base) = @_; 57 47 58 sub _managed_fields { 59 my ($self, $for, $base) = @_;60 $for !~ /w/ ? (61 postalAddress => 'postalAddress',62 ) : ()63 } 64 65 66 sub _delayed_fields { 67 my ($self)= @_;68 return qw();48 $class->SUPER::_get_attr_schema($base, 49 { 50 name => { ro => 1, inline => 1, }, 51 cn => { ro => 1, inline => 1, iname => 'name' }, 52 date => { ro => 1, inline => 1, }, 53 create => { ro => 1, inline => 1, }, 54 streetAddress => { formtype => 'TEXTAREA' }, 55 postalAddress => { ro => 1, }, 56 siteNick => { uniq => 1 }, 57 } 58 ) 69 59 } 70 60 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Sutype.pm
r165 r861 43 43 sub has_extended_attributes { 0 } 44 44 45 sub _delayed_fields {46 my ($self)= @_;47 return qw();48 }49 50 45 1; 51 46 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/User.pm
r840 r861 45 45 sub has_extended_attributes { 1 } 46 46 47 sub _delayed_fields { 48 my ($self)= @_; 49 return qw(memberOf manager directReports department); 50 } 51 52 sub _office_address_fields { qw(telephoneNumber physicalDeliveryOfficeName site) } 53 54 sub _inline_fields { 55 my ($class, $for, $base) = @_; 56 return ( 57 uidNumber => 'uidnumber', 58 gidNumber => 'gidnumber', 59 exported => 'exported', 60 expire => 'expire', 61 ($for !~ /w/) ? ( 62 name => 'name', 63 cn => 'name', 64 create => 'create', 65 date => 'date', 66 ) : (), 67 ); 68 } 69 70 sub _managed_fields { 71 my ($self, $for, $base) = @_; 72 return ( 73 memberOf => 'memberOf', 74 forward => 'forward', 75 aliases => 'aliases', 76 revaliases => 'revaliases', 77 (map { $_ => $_ } $self->_address_fields), 78 (map { $_ => $_ } $self->_office_address_fields), 79 (($for !~ /w/) ? ( 80 uid => 'name', 81 cn => 'name', 82 gecos => 'gecos', 83 displayName => 'displayName', 84 sAMAccountName => 'sAMAccountName', 85 accountExpires => 'accountExpires', 86 shadowExpire => 'shadowExpire', 87 directReports => 'directReports', 88 managedObjects => 'managedObjects', 89 otheraddress => 'otheraddress', 90 mainaddress => 'mainaddress', 91 postalAddress => 'postalAddress', 92 facsimileTelephoneNumber => 'facsimileTelephoneNumber', 93 allsite => 'allsite', 94 managerContact => 'managerContact', 95 expireText => 'expireText', 96 cells => 'cells', 97 departments => 'departments', 98 ) : ()), 47 sub _get_attr_schema { 48 my ($class, $base) = @_; 49 50 $class->SUPER::_get_attr_schema($base, 51 { 52 uidNumber => { inline => 1, iname => 'uidnumber', uniq => 1, 53 mandatory => 1, }, 54 uidnumber => { inline => 1, hide => 1, }, 55 gidNumber => { 56 inline => 1, 57 iname => 'gidnumber', 58 mandatory => 1, 59 can_values => sub { 60 map { $base->get_object('group', 61 $_)->get_attributes('gidNumber') } 62 $base->list_objects('group') 63 }, 64 display => sub { 65 my ($self, $val) = @_; 66 my ($gr) = $self->base->search_objects('group', "gidNumber=$val") 67 or return; 68 return $gr; 69 }, 70 reference => 'group', 71 }, 72 loginShell => { mandatory => 1 }, 73 gidnumber => { inline => 1, hide => 1, 74 can_values => sub { 75 map { $_->get_attributes('gidNumber') } 76 map { $base->get_object('group', $_) } 77 $base->list_objects('group') 78 }, 79 mandatory => 1, 80 reference => 'group', 81 }, 82 exported => { 83 inline => 1, 84 formtype => 'CHECKBOX', 85 }, 86 locked => { 87 formtype => 'CHECKBOX', 88 formopts => { rawvalue => 1, }, 89 }, 90 expire => { inline => 1, formtype => 'DATE', }, 91 name => { inline => 1, ro => 1, }, 92 cn => { inline => 1, ro => 1, iname => 'name' }, 93 create => { inline => 1, ro => 1, }, 94 date => { inline => 1, ro => 1, }, 95 memberOf => { multiple => 1, delayed => 1, }, 96 forward => {}, 97 aliases => { 98 reference => 'aliases', 99 formtype => 'TEXT', 100 multiple => 1, 101 }, 102 revaliases => { 103 reference => 'revaliases', 104 formtype => 'TEXT', 105 }, 106 manager => { 107 delayed => 1, 108 can_values => sub { 109 my %uniq = map { $_ => 1 } grep { $_ } 110 ($_[1] ? $_[1]->get_attributes('manager') : ()), 111 $base->search_objects('user', 'active=*'); 112 sort keys %uniq; 113 }, 114 reference => 'user', 115 }, 116 department => { 117 reference => 'group', 118 can_values => sub { 119 $base->search_objects('group', 'sutype=dpmt') 120 } 121 }, 122 contratType => { 123 reference => 'group', 124 can_values => sub { 125 $base->search_objects('group', 'sutype=contrattype') 126 } 127 }, 128 site => { 129 reference => 'site', 130 can_values => sub { 131 $base->search_objects('site') 132 } 133 }, 134 co => { }, 135 l => { }, 136 postalCode => { }, 137 streetAddress => { formtype => 'TEXTAREA', }, 138 postOfficeBox => { }, 139 st => { }, 140 facsimileTelephoneNumber => { }, 141 o => { }, 142 telephoneNumber => { }, 143 physicalDeliveryOfficeName => { }, 144 uid => { iname => 'name', ro => 1 }, 145 cn => { iname => 'name', ro => 1 }, 146 gecos => { ro => 1, }, 147 displayName => { ro => 1, managed => 1, }, 148 sAMAccountName => { ro => 1, managed => 1 }, 149 accountExpires => { ro => 1, managed => 1 }, 150 shadowExpire => { ro => 1, managed => 1 }, 151 directReports => { 152 reference => 'user', 153 ro => 1, 154 delayed => 1, 155 }, 156 managedObjects => { ro => 1, reference => 'group', }, 157 otheraddress => { ro => 1, reference => 'address', }, 158 mainaddress => { ro => 1, reference => 'address', }, 159 postalAddress => { ro => 1, }, 160 facsimileTelephoneNumber => { ro => 1, }, 161 allsite => { 162 ro => 1, 163 reference => 'site', 164 }, 165 managerContact => { 166 ro => 1, 167 reference => 'user', 168 }, 169 expireText => { ro => 1, }, 170 krb5ValidEnd => { ro => 1, }, 171 cells => { 172 ro => 1, 173 reference => 'group', 174 }, 175 departments => { 176 reference => 'group', 177 delayed => 1, 178 ro => 1, 179 }, 180 arrivalDate => { }, 181 expired => { ro => 1 }, 182 active => { ro => 1 }, 183 pwdAccountLockedTime => { managed => 1, ro => 1 } 184 } 99 185 ) 100 186 } … … 177 263 $res->{expire} =~ /(\d+) days\s*(\w)?/; 178 264 return $1 + ($2 ? 1 : 0); 265 } elsif ($field eq 'krb5ValidEnd') { 266 my $sth = $self->db->prepare_cached( 267 sprintf( 268 q{select date_part('epoch', expire)::int as expire 269 from %s where %s = ?}, 270 $self->db->quote_identifier($self->object_table), 271 $self->db->quote_identifier($self->key_field), 272 ) 273 ); 274 $sth->execute($self->id); 275 my $res = $sth->fetchrow_hashref; 276 $sth->finish; 277 return $res->{expire} 179 278 } elsif ($field eq 'expireText') { 180 279 my $sth = $self->db->prepare_cached( … … 190 289 $sth->finish; 191 290 return $res->{expire} 291 } elsif ($field eq 'pwdAccountLockedTime') { 292 if ($self->_get_c_field('locked')) { 293 return '000001010000Z'; 294 } else { 295 my $sth = $self->db->prepare_cached( 296 sprintf( 297 q{select to_char(expire AT TIME ZONE 'Z', 'YYYYMMDDHH24MISSZ') as expire 298 from %s where %s = ? and expire < now()}, 299 $self->db->quote_identifier($self->object_table), 300 $self->db->quote_identifier($self->key_field), 301 ) 302 ); 303 $sth->execute($self->id); 304 my $res = $sth->fetchrow_hashref; 305 $sth->finish; 306 return $res->{expire} 307 } 192 308 } elsif ($field eq 'otheraddress') { 193 309 my $sth = $self->db->prepare_cached(q{ … … 209 325 $sth->finish; 210 326 return $res->{name}; 211 } elsif (grep { $field eq $_ } __PACKAGE__->_address_fields(), 212 $self->_office_address_fields, 'postalAddress') { 327 } elsif (grep { $field eq $_ } qw(postalAddress 328 co l postalCode streetAddress 329 postOfficeBox st 330 facsimileTelephoneNumber 331 o telephoneNumber 332 physicalDeliveryOfficeName 333 site 334 )) { 213 335 if (my $fmainaddress = $self->_get_c_field('mainaddress')) { 214 336 my $address = $self->base->get_object('address', $fmainaddress); … … 262 384 } 263 385 386 sub _get_state { 387 my ($self, $state) = @_; 388 for ($state) { 389 /^expired$/ and do { 390 my $attribute = $self->attribute('expire'); 391 $attribute->check_acl('r') or return; 392 my $sth = $self->db->prepare_cached( 393 q{ select coalesce(expire < now(), false) as exp from "user" 394 where "user".name = ?} 395 ); 396 $sth->execute($self->id); 397 my $res = $sth->fetchrow_hashref; 398 $sth->finish; 399 return $res->{exp} ? 1 : 0; 400 }; 401 } 402 } 403 264 404 sub set_fields { 265 405 my ($self, %data) = @_; … … 267 407 my $res = 0; 268 408 foreach my $attr (keys %data) { 409 $attr eq 'gidnumber' && $data{$attr} !~ /^\d+$/ and do { 410 my $group = $self->base->get_object('group', $data{$attr}) or do { 411 $self->base->log(LA_ERROR, 412 "Can't set gidNumber to %s: no such group", $data{$attr}); 413 return; 414 }; 415 $data{$attr} = $group->get_attributes('gidNumber'); 416 }; 269 417 $attr =~ /^memberOf$/ and do { 270 418 my %member; … … 287 435 $res++; 288 436 } elsif ($member{$_}{c}) { 437 if (($self->get_c_field('department') || '') eq $group->id) { 438 $self->base->log(LA_WARN, 439 "Don't removing user %s from group %s: is it's department", 440 $self->id, $group->id); 441 next; 442 } 289 443 my $sth = $self->db->prepare_cached( 290 444 q{delete from group_attributes_users where value = ? and attr = ? and okey = ?} … … 421 575 } 422 576 }; 423 grep { $attr eq $_ } (__PACKAGE__->_office_address_fields, __PACKAGE__->_address_fields()) and do { 577 grep { $attr eq $_ } (qw(co l postalCode streetAddress 578 postOfficeBox st facsimileTelephoneNumber 579 o telephoneNumber physicalDeliveryOfficeName site)) and do { 424 580 my $fmainaddress = $self->_get_c_field('mainaddress'); 425 581 # set address attribute => create address object on the fly … … 439 595 if ($fmainaddress && 440 596 (my $address = $self->base->get_object('address', $fmainaddress))) { 441 $res += $address->set_c_fields($attr => $data{$attr}) ||0; 597 if ($address->attribute($attr) && 598 !$address->attribute($attr)->ro) { 599 $res += $address->set_c_fields($attr => $data{$attr}) ||0; 600 } 442 601 } 443 602 next; … … 446 605 } 447 606 if (keys %fdata) { 448 return $self->SUPER::set_fields(%fdata) + $res; 607 if (defined(my $res2 = $self->SUPER::set_fields(%fdata))) { 608 return $res2 + $res; 609 } else { 610 return; 611 } 449 612 } else { return $res; } 450 613 } -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/objects.pm
r764 r861 28 28 =cut 29 29 30 # This fields are special in sense they may come from site field31 sub _address_fields { qw(co l postalCode streetAddress postOfficeBox st32 facsimileTelephoneNumber o) }33 34 30 =head1 FUNCTIONS 35 31 … … 45 41 46 42 =cut 43 44 sub attributes_table { $_[0]->object_table . '_attributes_list' } 47 45 48 46 sub list { … … 87 85 sub has_extended_attributes { 0 } 88 86 89 # Work only for very simple case, must be override 90 91 sub _inline_fields { 92 my ($self, $for, $base) = @_; 93 if ($base->{__cache}{$self->object_table}) { 94 return %{$base->{__cache}{$self->object_table}}; 95 } 96 my @res; 97 my $sth = $base->db->prepare( 98 q{SELECT column_name FROM information_schema.columns 99 WHERE table_name = ?} 100 ); 101 $sth->execute($self->object_table); 102 while (my $res = $sth->fetchrow_hashref) { 103 if ($for =~ 'w') { 104 next if($res->{column_name} =~ /^(rev|date|create|ikey)$/); 105 next if($res->{column_name} eq $self->key_field); 106 } 107 push(@res, $res->{column_name}); 108 } 109 my %fields = map { $_ => $_ } @res; 110 $base->{__cache}{$self->object_table} = \%fields; 111 %fields 87 sub _get_attr_schema { 88 my ($class, $base, $info) = @_; 89 $info ||= {}; 90 if (!$base->{__cache}{$class->object_table}{inline}) { 91 $base->{__cache}{$class->object_table}{inline} = []; 92 my $sth = $base->db->prepare( 93 q{SELECT column_name FROM information_schema.columns 94 WHERE table_name = ?} 95 ); 96 $sth->execute($class->object_table); 97 while (my $res = $sth->fetchrow_hashref) { 98 push(@{$base->{__cache}{$class->object_table}{inline}}, 99 $res->{column_name}); 100 } 101 } 102 foreach (@{$base->{__cache}{$class->object_table}{inline}}) { 103 $info->{$_}{inline} = 1; 104 if (m/^(rev|date|create|ikey)$/) { 105 $info->{$_}{ro} = 1 106 } 107 } 108 if ($class->has_extended_attributes) { 109 if (!$base->{__cache}{$class->object_table}{extend}) { 110 $base->{__cache}{$class->object_table}{extend} = []; 111 my $sth = $base->db->prepare_cached( 112 sprintf( 113 q{select canonical from %s order by canonical}, 114 $base->db->quote_identifier($class->attributes_table), 115 ) 116 ); 117 $sth->execute; 118 while (my $res = $sth->fetchrow_hashref) { 119 push(@{$base->{__cache}{$class->object_table}{extend}}, 120 $res->{canonical}); 121 } 122 } 123 foreach (@{$base->{__cache}{$class->object_table}{extend}}) { 124 $info->{$_} ||= {}; 125 } 126 } 127 $info->{exported} = { inline => 1, formtype => 'CHECKBOX', hide => 1, }; 128 $info->{unexported} = { inline => 1, formtype => 'CHECKBOX', }; 129 130 $info 112 131 } 113 132 … … 117 136 my ($class, $for, $base) = @_; 118 137 return(); 119 }120 121 # Everything from attributes_list table122 # $for is uneeded here as all this attributes are rw123 124 sub _extended_field {125 my ($class, $for, $base) = @_;126 my @attr;127 if ($class->has_extended_attributes) {128 if ($base->{__cache}{_extended_field}{$class}) {129 return map { $_ => $_ }130 @{$base->{__cache}{_extended_field}{$class}};131 }132 my $sth = $base->db->prepare_cached(133 sprintf(134 q{select canonical from %s order by canonical},135 $base->db->quote_identifier($class->object_table . '_attributes_list'),136 )137 );138 $sth->execute;139 while (my $res = $sth->fetchrow_hashref) {140 push(@attr, $res->{canonical});141 }142 $base->{__cache}{_extended_field}{$class} = \@attr;143 return map { $_ => $_ } @attr;144 } else {145 return ()146 }147 }148 149 sub _canonical_fields {150 my ($class, $base, $for) = @_;151 $for ||= 'rw';152 my %inl = (153 ($class->_inline_fields($for, $base)),154 ($class->_managed_fields($for, $base)),155 ($class->_extended_field($for, $base)),156 );157 return sort keys %inl;158 }159 160 sub _get_field_name_db {161 my ($class, $c_field, $base) = @_;162 $class->has_extended_attributes or return;163 $class->object_table or return;164 my $sth = $base->db->prepare_cached(165 sprintf(166 q{select ikey from %s where canonical = ?},167 $base->db->quote_identifier($class->object_table . '_attributes_list'),168 )169 );170 $sth->execute($c_field);171 172 my $res = $sth->fetchrow_hashref;173 $sth->finish;174 return $c_field if($res->{ikey});175 }176 177 sub _get_field_name {178 my ($class, $c_field, $base, $for) = @_;179 $c_field or return;180 $for ||= 'rw';181 my %fields = $class->_managed_fields($for, $base);182 return $fields{$c_field} if ($fields{$c_field});183 %fields = $class->_inline_fields($for, $base);184 return $fields{$c_field} if ($fields{$c_field});185 %fields = $class->_extended_field($for, $base);186 return $fields{$c_field}187 138 } 188 139 … … 198 149 my $count = $sth->execute($id); 199 150 $sth->finish; 200 $count== 1 or return;151 ($count || 0) == 1 or return; 201 152 $class->SUPER::new($base, $id); 202 153 } … … 223 174 224 175 # splitting inline from extended 225 my %inlined = $class->_inline_fields('w', $base);226 my %inl = map { $_ => 1 } values %inlined;227 176 my (%first, %second); 177 # Ensure object is exported if not specified 178 $data{exported} = 1 if (!exists($data{exported})); 179 if (exists $data{unexported}) { 180 $data{exported} = $data{unexported} ? 0 : 1; 181 delete $data{unexported} 182 } 228 183 foreach (keys %data) { 229 $_ =~ /exported/ and $data{$_} = $data{$_} ? 1 : 0; 230 if ($inl{$_}) { 184 my $attr = $base->attribute($class->type, $_) or next; 185 $_ =~ /^exported$/ and $data{$_} = $data{$_} ? 1 : 0; 186 if ($attr->{inline}) { 231 187 $first{$_} = $data{$_}; 232 188 } else { … … 276 232 ); 277 233 278 if ( $sthr->execute($newid, $id) != 1) {234 if (($sthr->execute($newid, $id) || 0) != 1) { 279 235 $base->log(LA_ERR, "Erreur renaming %s %s to %s", 280 236 $class->type, … … 303 259 sub get_field { 304 260 my ($self, $field) = @_; 305 my %inl = $self->_inline_fields('r', $self->base); 306 my %inline = map { $_ => 1 } values %inl; 307 if ($inline{$field}) { 261 if ($field eq 'unexported') { 262 return $self->get_field('exported') ? undef : 1; 263 } 264 my $attr = $self->attribute($field) or return; 265 if ($attr->{inline}) { 308 266 my $sth = $self->db->prepare_cached( 309 267 sprintf( … … 335 293 ) 336 294 ); 337 $sth->execute($self->id); #, $field);295 $sth->execute($self->id); 338 296 delete($__cache->{$self->id}); 339 297 $__cache->{$self->id}{__time} = time; … … 354 312 my @vals; 355 313 my %ext; 356 my %inl = $self->_inline_fields('w', $self->base); 357 my %inline = map { $_ => 1 } values %inl; 314 if (exists($data{unexported})) { 315 $data{exported} = $data{unexported} ? 0 : 1; 316 } 358 317 foreach my $field (keys %data) { 359 $data{$field} = $data{$field} ? 1 : 0 if($field eq 'exported'); 318 my $attr = $self->attribute($field); 319 next if ($field eq 'unexported'); 360 320 my $oldval = $self->get_field($field); 361 321 next if (($data{$field} || '') eq ($oldval || '')); 362 if ($ inline{$field}) {322 if ($attr->{inline}) { 363 323 # TODO check fields exists ! 364 324 push(@fields, sprintf("%s = ?", $self->db->quote_identifier($field))); … … 378 338 ); 379 339 $sth->execute(@vals, $self->id) or do { 380 $self->base->log(LA_ERR, "Cannot update inline field %s" . 381 $self->base->db->strerr); 340 $self->base->log(LA_ERR, 341 "Cannot update inline field for object %s, %s: %s", 342 $self->type, 343 $self->id, 344 $self->base->db->errstr); 382 345 return; 383 346 }; … … 392 355 ), 393 356 ); 357 my $sthd1 = $self->db->prepare_cached( 358 sprintf( 359 q{delete from %s where okey = ? and attr = ? and value = ?}, 360 $self->db->quote_identifier($self->object_table. '_attributes'), 361 ), 362 ); 394 363 my $sthx = $self->db->prepare_cached( 395 364 sprintf( … … 406 375 407 376 my $okey = $self->_get_ikey($self->base, $self->id); 408 foreach (keys %ext) { 409 if ($ext{$_}) { 410 my $res = $sthu->execute($ext{$_}, $okey, $_); 411 defined($res) or do { 412 $self->base->log(LA_ERR, 413 "Error while udapting attributes: %s", 414 $self->base->db->strerr 415 ); 416 return; 417 }; 418 if ($res == 0) { 419 $res = $sthx->execute($okey, $_, $ext{$_}); 377 foreach my $uattr (keys %ext) { 378 my $attr = $self->attribute($uattr); 379 if ($ext{$uattr}) { 380 if ($attr->{multiple}) { 381 my $updated = 0; 382 my $oldvalue = $self->get_field($uattr); 383 my %newvalues = map { $_ => 1 } (ref $ext{$uattr} 384 ? @{$ext{$uattr}} 385 : $ext{$uattr}); 386 foreach (grep { $_ } ref $oldvalue ? @{$oldvalue} : $oldvalue) { 387 if(exists($newvalues{$_})) { 388 $newvalues{$_} = 0; 389 } else { 390 defined($sthd1->execute($okey, $uattr, $_)) or do { 391 $self->base->log(LA_ERR, 392 "Error while updating attributes on %s/%s %s: %s", 393 $self->type, 394 $self->id, 395 $uattr, 396 $self->base->db->errstr 397 ); 398 return; 399 }; 400 $updated++; 401 } 402 } 403 foreach (grep { $newvalues{$_} } keys %newvalues) { 404 $sthx->execute($okey, $uattr, $_) or do { 405 $self->base->log(LA_ERR, 406 "Error while updating attributes: %s/%s %s: %s", 407 $self->type, 408 $self->id, 409 $uattr, 410 $self->base->db->errstr 411 ); 412 return; 413 }; 414 $updated++; 415 } 416 $updated_attributes++ if ($updated); 417 } else { 418 my $res = $sthu->execute($ext{$uattr}, $okey, $uattr); 420 419 defined($res) or do { 421 420 $self->base->log(LA_ERR, 422 "Error while udapting attributes: %s", 423 $self->base->db->strerr 421 "Error while udapting attributes: %s/%s %s: %s", 422 $self->type, 423 $self->id, 424 $uattr, 425 $self->base->db->errstr 424 426 ); 427 $updated_attributes++; 425 428 return; 426 429 }; 430 if ($res == 0) { 431 $res = $sthx->execute($okey, $uattr, $ext{$uattr}); 432 defined($res) or do { 433 $self->base->log(LA_ERR, 434 "Error while updating attributes: %s/%s %s: %s", 435 $self->type, 436 $self->id, 437 $uattr, 438 $self->base->db->errstr 439 ); 440 $updated_attributes++; 441 return; 442 }; 443 } 427 444 } 428 445 } else { 429 defined($sthd->execute($okey, $ _)) or do {446 defined($sthd->execute($okey, $uattr)) or do { 430 447 $self->base->log(LA_ERR, 431 "Error while deleting attributes: %s", 432 $self->base->db->strerr 448 "Error while deleting attributes: %s/%s %s: %s", 449 $self->otype, 450 $self->id, 451 $uattr, 452 $self->base->db->errstr 433 453 ); 434 454 return; … … 445 465 sub attributes_summary { 446 466 my ($class, $base, $attribute) = @_; 447 $class->has_extended_attributes && $class->object_table or 467 my $attr = $base->attribute($class->type, $attribute); 468 if ($attr->{managed}) { 448 469 return $class->SUPER::attributes_summary($base, $attribute); 470 } 449 471 my $sth = $base->db->prepare_cached( 450 sprintf( 451 q{select value from %s where attr = ? group by value}, 452 $base->db->quote_identifier($class->object_table . 453 '_attributes'), 454 ) 455 ); 456 $sth->execute($attribute); 472 $attr->{inline} 473 ? sprintf( 474 q{select %s as value from %s}, 475 $base->db->quote_identifier($attr->iname), 476 $base->db->quote_identifier($class->object_table), 477 ) 478 : sprintf( 479 q{select value from %s where attr = ? group by value}, 480 $base->db->quote_identifier($class->object_table . 481 '_attributes'), 482 ) 483 ); 484 $sth->execute($attr->{inline} ? () : ($attribute)); 457 485 458 486 my @values; … … 465 493 sub _set_password { 466 494 my ($self, $clear_pass) = @_; 467 if (my $field = $self->base->get_field_name($self->type, 'userPassword')) { 495 if (my $attr = $self->base->attribute($self->type, 'userPassword')) { 496 my $field = $attr->iname; 468 497 my @salt_char = (('a' .. 'z'), ('A' .. 'Z'), (0 .. 9), '/', '.'); 469 498 my $salt = join('', map { $salt_char[rand(scalar(@salt_char))] } (1 .. 8)); 470 499 my $res = $self->set_fields($field, crypt($clear_pass, '$1$' . $salt)); 500 if (!$res) { 501 return; 502 } 471 503 472 504 if (my $serialize = $self->base->get_global_value('rsa_public_key')) { … … 479 511 Armour => 1, 480 512 ) || die $self->poll->rsa->errstr(); 481 $self->set_c_fields('encryptedPassword', $rsa_password); 513 return $self->set_c_fields('encryptedPassword', $rsa_password); 514 } else { 515 return 1; 482 516 } 483 517 } else { … … 490 524 my ($class, $base, @filter) = @_; 491 525 492 if ($class->has_extended_attributes) { 493 my %attrsql; 494 my %attrbind; 495 while (my $item = shift(@filter)) { 496 # attr=foo => no extra white space ! 497 # \W is false, it is possible to have two char 498 my ($attr, $mode, $val) = $item =~ /^(\w+)(?:(\W)(.+))?$/ or next; 499 if (!$mode) { 500 $mode = '~'; 501 $val = shift(@filter); 502 } 503 $val ||= ''; 504 push(@{ $attrsql{$attr} }, 505 sprintf("\n\t" . q{select okey from %s where attr=? %s} . "\n", 506 $base->db->quote_identifier($class->object_table . 507 '_attributes'), 508 $val eq '*' 509 ? '' 510 : ($mode eq '~' 511 ? q{and value ILIKE ?} 512 : q{and value = ?} ) 513 ) 526 my %attrsql; 527 my %attrbind; 528 529 while (my $item = shift(@filter)) { 530 # attr=foo => no extra white space ! 531 # \W is false, it is possible to have two char 532 my ($attr, $mode, $val) = $item =~ /^(\w+)(?:(\W)(.+))?$/ or next; 533 if (!$mode) { 534 $mode = '~'; 535 $val = shift(@filter); 536 } 537 my $attribute = $base->attribute($class->type, $attr) or do { 538 $base->log(LA_ERR, "Unknown attribute $attr"); 539 next; 540 }; 541 defined($val) or $val = ''; 542 $val = $attribute->input($val); 543 544 my $sql; 545 546 # Specific case for unexported attribute, comming from exported value 547 if ($attribute->iname eq 'unexported') { 548 $sql = sprintf( 549 q{select ikey from %s where %s}, 550 $base->db->quote_identifier($class->object_table), 551 $val ? q{exported='f'} : q{exported='t'} 552 ) 553 } elsif ($attribute->{inline}) { 554 $sql = sprintf( 555 q{select ikey from %s where %s %s}, 556 $base->db->quote_identifier($class->object_table), 557 $base->db->quote_identifier($attribute->iname), 558 $val eq '*' 559 ? 'is not NULL' 560 : $mode eq '~' 561 ? 'ILIKE ?' 562 : '= ?' 514 563 ); 515 push(@{$attrbind{$attr}}, $base->get_field_name($class->type, $attr, 'r'));516 564 push(@{$attrbind{$attr}}, $mode eq '~' ? '%' . $val . '%' : $val) unless($val eq '*'); 517 } 518 # building the query 519 my @sqlintersec; 520 if (!$base->{wexported}) { 521 push(@sqlintersec, sprintf( 522 q{select ikey from %s where exported = true}, 523 $base->db->quote_identifier($class->object_table) 524 ) 525 ); 526 } 527 my @bind; 528 foreach (keys %attrsql) { 529 push(@sqlintersec, '(' . join(" union ", @{$attrsql{$_}}) . ")\n"); 530 push(@bind, @{$attrbind{$_}}); 531 } 532 my $sth = $base->db->prepare( 533 sprintf(q{ 534 select name from %s 535 %s 536 }, 537 $base->db->quote_identifier($class->object_table), 538 @sqlintersec 539 ? "where ikey in (\n" . join("\n intersect\n", @sqlintersec) . ")\n" 540 : '', 541 ) 542 ); 543 $sth->execute(@bind); 544 my @results; 545 while (my $res = $sth->fetchrow_hashref) { 546 push(@results, $res->{name}); 547 } 548 return(@results); 565 } else { 566 $sql = sprintf( 567 q{select okey from %s where attr = ? %s}, 568 $base->db->quote_identifier( 569 $class->object_table . '_attributes' 570 ), 571 $val eq '*' 572 ? '' 573 : $mode eq '~' 574 ? q{and value ILIKE ?} 575 : q{and value = ?} 576 577 ); 578 push(@{$attrbind{$attr}}, $attribute->iname); 579 push(@{$attrbind{$attr}}, $mode eq '~' ? '%' . $val . '%' : $val) unless($val eq '*'); 580 } 581 582 push(@{ $attrsql{$attr} }, $sql); 583 } 584 # building the query 585 my @sqlintersec; 586 if (!$base->{wexported}) { 587 push(@sqlintersec, sprintf( 588 q{select ikey from %s where exported = true}, 589 $base->db->quote_identifier($class->object_table) 590 ) 591 ); 592 } 593 my @bind; 594 foreach (keys %attrsql) { 595 push(@sqlintersec, '(' . join(" union ", @{$attrsql{$_}}) . ")\n"); 596 push(@bind, @{$attrbind{$_} || []}); 597 } 598 my $sth = $base->db->prepare( 599 sprintf(q{ 600 select name from %s 601 %s 602 order by name 603 }, 604 $base->db->quote_identifier($class->object_table), 605 @sqlintersec 606 ? "where ikey in (\n" . join("\n intersect\n", @sqlintersec) . ")\n" 607 : '', 608 ) 609 ); 610 $sth->execute(@bind); 611 my @results; 612 while (my $res = $sth->fetchrow_hashref) { 613 push(@results, $res->{name}); 614 } 615 return(@results); 616 } 617 618 sub register_attribute { 619 my ($class, $base, $attribute, $comment) = @_; 620 621 $base->attribute($class->type, $attribute) and do { 622 $base->log(LA_ERR, "The attribute $attribute already exists"); 623 return; 624 }; 625 my $sth = $base->db->prepare( 626 sprintf(q{ 627 insert into %s (canonical, description) 628 values (?,?) 629 }, $class->attributes_table) 630 ); 631 my $res = $sth->execute($attribute, $comment); 632 } 633 634 sub get_attribute_comment { 635 my ($class, $base, $attribute) = @_; 636 $base->attribute($class->type, $attribute) or do { 637 $base->log(LA_ERR, "The attribute $attribute does not exists"); 638 return; 639 }; 640 my $sth = $base->db->prepare( 641 sprintf(q{ 642 select description from %s 643 where canonical = ? 644 }, $class->attributes_table) 645 ); 646 $sth->execute($attribute); 647 if (my $res = $sth->fetchrow_hashref) { 648 $sth->finish; 649 return $res->{description}; 549 650 } else { 550 my @bind; 551 my @where; 552 while (my $item = shift(@filter)) { 553 # attr=foo => no extra white space ! 554 # \W is false, it is possible to have two char 555 my ($attr, $mode, $val) = $item =~ /^(\w+)(?:(\W)(.+))?$/ or next; 556 if (!$mode) { 557 $mode = '~'; 558 $val = shift(@filter); 559 } 560 if ($val eq '*') { 561 push(@where, sprintf("%s is not NULL", 562 $base->db->quote_identifier($base->get_field_name($class->type, 563 $attr, 'r')) 564 ) 565 ); 566 } else { 567 push(@where, sprintf("%s %s ?", 568 $base->db->quote_identifier( 569 $base->get_field_name($class->type, $attr, 'r') 570 ), 571 $mode eq '~' ? 'ILIKE' : '=', 572 )); 573 push(@bind, lc($val)); 574 } 575 } 576 my $sth = $base->db->prepare( 577 sprintf(q{select name from %s where %s}, 578 $base->db->quote_identifier($class->object_table), 579 join(' and ', @where), 580 ) 581 ); 582 $sth->execute(@bind); 583 my @results; 584 while (my $res = $sth->fetchrow_hashref) { 585 push(@results, $res->{name}); 586 } 587 return(@results); 588 } 589 } 651 return; 652 } 653 } 654 655 sub set_attribute_comment { 656 my ($class, $base, $attribute, $comment) = @_; 657 658 my $attr = $base->attribute($class->type, $attribute) or do { 659 $base->log(LA_ERR, "The attribute $attribute does not exists"); 660 return; 661 }; 662 $attr->{inline} and do { 663 $base->log(LA_ERR, 664 "Cannot set comment to inline attribute, sorry, blame the author !" 665 ); 666 return; 667 }; 668 my $sth = $base->db->prepare( 669 sprintf(q{ 670 update %s set description = ? 671 where canonical = ? 672 }, $class->attributes_table) 673 ); 674 my $res = $sth->execute($comment, $attribute); 675 } 676 677 590 678 591 679 1; -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Unix.pm
r815 r861 43 43 44 44 my $base = { 45 passwd => $options{passwd} || '/etc/passwd',46 shadow => $options{shadow} || '/etc/shadow',47 group => $options{group} || '/etc/group',48 gshadow => $options{gshadow} || '/etc/gshadow',49 45 # are we using shadow, default to yes 50 46 use_shadow => (defined($options{use_shadow}) ? $options{use_shadow} : 1), … … 56 52 }; 57 53 54 foreach (qw(passwd shadow group gshadow)) { 55 if ($options{$_}) { 56 $base->{$_} = $options{$_}; 57 } elsif ($options{directory}) { 58 $base->{$_} = $options{directory} . '/' . $_; 59 } else { 60 $base->{$_} = "/etc/$_"; 61 } 62 } 63 64 58 65 bless($base, $class); 59 }60 61 sub _canonicals_fields {62 my ($self, $type, $for) = @_;63 $type = lc($type);64 {65 user => {66 uidNumber => 'uid',67 gidNumber => 'gid',68 gecos => 'gecos',69 homeDirectory => 'home',70 loginShell => 'shell',71 userPassword => ($self->{use_shadow} ? 'spassword' : 'password'),72 memberOf => 'memberOf',73 locked => 'locked',74 ($for !~ /w/ ? (75 givenName => 'givenName',76 sn => 'sn',77 uid => 'login',78 sAMAccountName => 'login',79 ) : ()),80 $self->{use_shadow} ?81 (82 shadowLastChange => 'last_changed',83 shadowMin => 'before_ch',84 shadowMax => 'after_ch',85 shadowWarning => 'exp_warn',86 shadowInactive => 'exp_disable',87 shadowExpire => 'disable',88 shadowFlag => 'res',89 ) : (),90 # description => not supported91 },92 group => {93 ($for !~ /w/ ? (94 sAMAccountName => 'group_name',95 ) : ()),96 gidNumber => 'gid',97 memberUID => 'user_list',98 },99 }->{$type}100 }101 102 sub list_canonical_fields {103 my ($self, $type, $for) = @_;104 $for ||= 'rw';105 keys %{ $self->_canonicals_fields($type, $for) || {} }106 }107 108 sub get_field_name {109 my ($self, $type, $cfield, $for) = @_;110 $for ||= 'rw';111 ($self->_canonicals_fields($type, $for) || {})->{$cfield}112 66 } 113 67 … … 248 202 truncate($handle, 0); 249 203 foreach my $line (@data) { 250 print $handle join(':', map { defined($_) ? $_ : '' } @$line) . "\n";204 print $handle join(':', map { my $f = $_; $f =~ s/:/;/g; $f } map { defined($_) ? $_ : '' } @$line) . "\n"; 251 205 } 252 206 close($handle); -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Unix/Group.pm
r807 r861 28 28 =cut 29 29 30 sub _get_attr_schema { 31 my ($class, $base) = @_; 32 { 33 sAMAccountName => { 34 iname => 'group_name', 35 ro => 1, 36 }, 37 gidNumber => { 38 iname => 'gid', 39 }, 40 memberUID => { 41 iname => 'user_list', 42 multiple => 1, 43 delayed => 1, 44 }, 45 }; 46 } 47 30 48 =head2 new(%options) 31 49 … … 47 65 return bless($base->{groups}{$id}, $class); 48 66 } else { return } 49 }50 51 sub _delayed_fields {52 my ($self)= @_;53 return qw(memberUID);54 67 } 55 68 -
LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Unix/User.pm
r806 r861 28 28 =cut 29 29 30 sub _get_attr_schema { 31 my ($class, $base) = @_; 32 { 33 uidNumber => { iname => 'uid', uniq => 1, }, 34 gidNumber => { iname => 'gid', 35 can_values => sub { 36 map { $_->get_attributes('gidNumber') } 37 map { $base->get_object('group', $_) } 38 $base->list_objects('group') 39 }, 40 reference => 'group', 41 mandatory => 1, 42 }, 43 gecos => { }, 44 homeDirectory => { iname => 'home' }, 45 loginShell => { iname => 'shell' }, 46 userPassword => { 47 iname => ($base->{use_shadow} ? 'spassword' : 'password') 48 }, 49 memberOf => { delayed => 1, }, 50 locked => {}, 51 givenName => { ro => 1 }, 52 sn => { ro => 1 }, 53 uid => { iname => 'login', ro => 1 }, 54 sAMAccountName => { iname => 'login', ro => 1 }, 55 $base->{use_shadow} ? 56 ( 57 shadowLastChange => { iname => 'last_changed' }, 58 shadowMin => { iname => 'before_ch' }, 59 shadowMax => { iname => 'after_ch' }, 60 shadowWarning => { iname => 'exp_warn' }, 61 shadowInactive => { iname => 'exp_disable' }, 62 shadowExpire => { iname => 'disable' }, 63 shadowFlag => { iname => 'res' }, 64 ) : (), 65 }; 66 } 67 30 68 =head2 new(%options) 31 32 Create a new LATMOS::Ad object for windows AD $domain.33 34 domain / server: either the Ad domain or directly the server35 36 ldap_args is an optionnal list of arguments to pass to L<Net::LDAP>.37 69 38 70 =cut … … 47 79 return bless($base->{users}{$id}, $class); 48 80 } else { return } 49 }50 51 sub _delayed_fields {52 my ($self)= @_;53 return qw(memberOf);54 81 } 55 82 -
LATMOS-Accounts/lib/LATMOS/Accounts/Cli.pm
r851 r861 9 9 use Term::ReadLine; 10 10 use Text::ParseWords; 11 use Getopt::Long; 12 13 { 14 open (my $fh, "/dev/tty" ) 15 or eval 'sub Term::ReadLine::findConsole { ("&STDIN", "&STDERR") }'; 16 die $@ if $@; 17 close ($fh); 18 } 11 19 12 20 my $term = Term::ReadLine->new('LA CLI'); 21 $term->MinLine(99999); 13 22 my $OUT = $term->OUT || \*STDOUT; 23 24 my $trans_mode = 0; 14 25 15 26 sub globalenv { … … 29 40 if ($arg eq 'yes') { 30 41 $env->base->unexported(1); 31 print $OUT "Unexported are now show ";42 print $OUT "Unexported are now show\n"; 32 43 } elsif ($arg eq 'no') { 33 44 $env->base->unexported(0); 34 print $OUT "Unexported are no longer show ";45 print $OUT "Unexported are no longer show\n"; 35 46 } elsif ($arg eq 'show') { 36 print $OUT "Unexported objects " . $env->base->unexported ?37 "enable" : "disable" ;47 print $OUT "Unexported objects " . ($env->base->unexported ? 48 "enable" : "disable") . "\n"; 38 49 } else { 39 print $OUT "wrong argument ";50 print $OUT "wrong argument\n"; 40 51 } 41 52 }, … … 52 63 print $OUT map { "$_\n" } $_[0]->base->list_objects($_[1]); 53 64 } else { 54 print $OUT "Object type missing ";65 print $OUT "Object type missing\n"; 55 66 } 56 67 }, … … 71 82 $env->{_lastsearchtype} = $args[0]; 72 83 } else { 73 print $OUT "Object type missing ";84 print $OUT "Object type missing\n"; 74 85 } 75 86 }, … … 112 123 @ids = @{$env->{_lastsearch}}; 113 124 } else { 114 print $OUT "No results store from previous search ";125 print $OUT "No results store from previous search\n"; 115 126 return; 116 127 } 117 128 } 118 129 if (!@ids) { 119 print $OUT 'not enough arguments' ;130 print $OUT 'not enough arguments' . "\n"; 120 131 return; 121 132 } 122 133 foreach (@ids) { 123 134 my $obj = $env->base->get_object($otype, $_) or do { 124 print $OUT "Cannot get $otype $_ ";135 print $OUT "Cannot get $otype $_\n"; 125 136 return; 126 137 }; 127 138 push(@objs, $obj); 128 139 } 129 print $OUT "Selecting $otype " . join(', ', @ids) ;140 print $OUT "Selecting $otype " . join(', ', @ids) . "\n"; 130 141 objenv($_[0]->base, $otype, @objs)->cli(); 131 142 }, 132 143 }); 144 $env->add_func('create', { 145 code => sub { 146 my ($env, $otype) = @_; 147 my $helper = $env->base->ochelper($otype); 148 my $info = undef; 149 while (1) { 150 my $status; 151 ($status, $info) = $helper->step($info); 152 153 if ($status ne 'NEEDINFO') { 154 if ($status eq 'CREATED') { 155 print $OUT "Object created\n"; 156 $env->commit; 157 } else { 158 print $OUT "Nothing done\n"; 159 $env->rollback; 160 } 161 return; 162 } 163 164 if ($info->{name}{ask}) { 165 my $line = $term->readline("Name of the object ?"); 166 $info->{name}{content} = $line; 167 } 168 foreach my $attr (@{$info->{ask} || []}) { 169 $term->Attribs->{completion_function} = sub { 170 $info->{contents}{$attr} 171 }; 172 my $line = $term->readline(sprintf(' %s %s? ', 173 $attr, 174 $info->{contents}{$attr} 175 ? '(' . $info->{contents}{$attr} . ') ' 176 : '' 177 )); 178 $info->{contents}{$attr} = $line if($line); 179 } 180 } 181 }, 182 } 183 ); 184 $env->add_func('exchangeip', 185 { 186 help => 'Exchange two IP on host', 187 code => sub { 188 my ($env, @args) = @_; 189 my ($ip1, $ip2) = 190 grep { $_ && $_ =~ /\d+\.\d+\.\d+\.\d+/ } @args; 191 if (!$ip2) { 192 print $OUT "Need two ip to exchange\n"; 193 return; 194 } 195 if ($env->base->nethost_exchange_ip($ip1, $ip2)) { 196 print $OUT "$ip1 and $ip2 get exchange\n"; 197 $env->commit; 198 } else { 199 $env->rollback; 200 } 201 }, 202 completion => sub { 203 my ($env, $carg, @args) = @_; 204 if ($args[-1] && $args[-1] !~ m/\d+\.\d+\.\d+\.\d+/) { 205 if (my $obj = $env->base->get_object('nethost', $args[-1])) { 206 return $obj->get_attributes('ip'); 207 } 208 } else { 209 my @list = 210 ($env->base->attributes_summary('nethost', 'ip'), 211 $env->base->list_objects('nethost')); 212 return @list; 213 } 214 }, 215 } 216 ); 133 217 $env->add_func('user', { alias => [qw'select user' ] }); 134 218 $env->add_func('group', { alias => [qw'select group'] }); … … 153 237 $objenv->{_otype} = $otype; 154 238 $objenv->{_objects} = [ @objs ]; 239 $objenv->add_func('+', { 240 help => 'add item to selection', 241 code => sub { 242 my ($env, @ids) = @_; 243 my %ids = map { $_->id => 1 } @{$env->{_objects}}; 244 foreach (@ids) { 245 $ids{$_} and next; 246 my $o = $env->base->get_object($env->{_otype}, $_) or next; 247 push(@{$env->{_objects}}, $o); 248 } 249 printf $OUT "select is now %s: %s\n", $env->{_otype}, join(', ', map { 250 $_->id } @{$env->{_objects}}); 251 }, 252 completion => sub { 253 my ($env, undef, @ids) = @_; 254 my %ids = map { $_->id => 1 } @{$env->{_objects}}; 255 return ( grep { ! $ids{$_} } $env->base->list_objects($env->{_otype})); 256 }, 257 } 258 ); 259 $objenv->add_func('-', { 260 help => 'add item to selection', 261 code => sub { 262 my ($env, @ids) = @_; 263 my %ids = map { $_ => 1 } @ids; 264 my @newobjs = grep { !$ids{$_->id} } @{$env->{_objects}}; 265 266 if (!@newobjs) { 267 print $OUT "This would remove all objects from the list...\n"; 268 return; 269 } else { 270 @{$env->{_objects}} = @newobjs; 271 } 272 printf $OUT "select is now %s: %s\n", $env->{_otype}, join(', ', map { 273 $_->id } @{$env->{_objects}}); 274 }, 275 completion => sub { 276 my ($env, undef, @ids) = @_; 277 my %ids = map { $_ => 1 } @ids; 278 grep { !$ids{$_} } map { $_->id } @{$env->{_objects}}; 279 }, 280 } 281 ); 155 282 $objenv->add_func('show', { 156 283 help => 'show attributes - show an attributes of object', … … 177 304 code => sub { 178 305 my ($env, $fmt) = @_; 306 if (!defined($fmt)) { 307 print $OUT "no format given"; 308 return; 309 } 179 310 foreach (@{$env->{_objects}}) { 180 311 print $OUT $_->queryformat($fmt) . "\n"; … … 192 323 foreach (@{$env->{_objects}}) { 193 324 defined $_->set_c_fields($attr => undef) or do { 194 print $OUT "cannot unset attributes $attr for " . $_->id; 325 print $OUT "cannot unset attributes $attr for " . $_->id . 326 "\n"; 195 327 return; 196 328 }; 197 329 } 198 $env-> base->commit;199 print $OUT "Changes applied ";330 $env->commit; 331 print $OUT "Changes applied\n"; 200 332 }, 201 333 completion => sub { … … 211 343 my ($env, $attr, @value) = @_; 212 344 @value or do { 213 print $OUT "attribute and value must be specified ";345 print $OUT "attribute and value must be specified\n"; 214 346 return; 215 347 }; … … 218 350 \@value) or do { 219 351 $_->base->rollback; 220 printf $OUT "Cannot set $attr to %s for %s ", join(', ',352 printf $OUT "Cannot set $attr to %s for %s\n", join(', ', 221 353 @value), $_->id; 222 354 return; 223 355 }; 224 356 } 225 $env-> base->commit;226 print $OUT " done";357 $env->commit; 358 print $OUT "Done.\n"; 227 359 }, 228 360 completion => sub { … … 231 363 return $env->base->list_canonical_fields($env->{_otype}, 'w') 232 364 } else { 233 if ($env->base->obj_attr_allowed_values($env->{_otype}, $args[0])) { 234 return $env->base->obj_attr_allowed_values($env->{_otype}, $args[0]) 235 } 236 for ($args[0]) { 237 /^manager|managedBy$/ and return 238 $env->base->search_objects('user'); 239 /^department$/ and return 240 $env->base->search_objects('group', 'sutype=dpmt'); 241 /^contratType$/ and return 242 $env->base->search_objects('group', 'sutype=contrattype'); 243 /^site$/ and return 244 $env->base->search_objects('site'); 245 if (@{$env->{_objects}} == 1) { 246 return $env->{_objects}[0]->get_attributes($args[0]); 247 } 365 my $attr = $env->base->attribute($env->{_otype}, $args[0]); 366 if ($attr->has_values_list) { 367 $attr->can_values; 368 } elsif (@{$env->{_objects}} == 1) { 369 return 370 $env->{_objects}[0]->get_attributes($args[0]); 371 } 372 } 373 }, 374 }); 375 $objenv->add_func('add', { 376 help => 'add a value to an attribute', 377 code => sub { 378 my ($env, $attr, @value) = @_; 379 @value or do { 380 print $OUT "attribute and value must be specified\n"; 381 return; 382 }; 383 foreach (@{$env->{_objects}}) { 384 my @attrv = grep { $_ } $_->get_attributes($attr); 385 defined $_->set_c_fields($attr => [ @attrv, @value ]) or do { 386 $_->rollback; 387 printf $OUT "Cannot set $attr to %s for %s\n", join(', ', 388 @value), $_->id; 389 return; 390 }; 391 } 392 $env->commit; 393 print $OUT "done\n"; 394 }, 395 completion => sub { 396 my ($env, $lastw, @args) = @_; 397 if (!$args[0]) { 398 return grep { 399 $env->base->attribute($env->{_otype}, $_)->{multiple} 400 } $env->base->list_canonical_fields($env->{_otype}, 'w') 401 } else { 402 my $attr = $env->base->attribute($env->{_otype}, $args[0]); 403 if ($attr->has_values_list) { 404 $attr->can_values; 405 } elsif (@{$env->{_objects}} == 1) { 406 return 407 $env->{_objects}[0]->get_attributes($args[0]); 408 } 409 } 410 }, 411 }); 412 $objenv->add_func('remove', { 413 help => 'remove a value from an attribute', 414 code => sub { 415 my ($env, $attr, @value) = @_; 416 @value or do { 417 print $OUT "attribute and value must be specified\n"; 418 return; 419 }; 420 foreach (@{$env->{_objects}}) { 421 my @attrv = grep { $_ } $_->get_attributes($attr); 422 foreach my $r (@value) { 423 @attrv = grep { $_ ne $r } @attrv; 424 } 425 defined $_->set_c_fields($attr => @attrv ? [ @attrv ] : undef) or do { 426 $_->rollback; 427 printf $OUT "Cannot set $attr to %s for %s\n", join(', ', 428 @value), $_->id; 429 return; 430 }; 431 } 432 $env->commit; 433 print $OUT "done\n"; 434 }, 435 completion => sub { 436 my ($env, $lastw, @args) = @_; 437 if (!$args[0]) { 438 return grep { 439 $env->base->attribute($env->{_otype}, $_)->{multiple} 440 } $env->base->list_canonical_fields($env->{_otype}, 'w') 441 } else { 442 my $attr = $env->base->attribute($env->{_otype}, $args[0]); 443 if (@{$env->{_objects}} == 1) { 444 return 445 $env->{_objects}[0]->get_attributes($args[0]); 248 446 } 249 447 } … … 253 451 help => 'list current selected objects', 254 452 code => sub { 255 printf $OUT "%s: %s ", $_[0]->{_otype}, join(', ', map { $_->id }453 printf $OUT "%s: %s\n", $_[0]->{_otype}, join(', ', map { $_->id } 256 454 @{$_[0]->{_objects}}); 257 455 } … … 267 465 if ($id) { 268 466 $obj = grep { $_->id = $id } @{$env->{_objects}} or do { 269 print $OUT "$id is not part of selected objects ";467 print $OUT "$id is not part of selected objects\n"; 270 468 return; 271 469 }; … … 274 472 } else { 275 473 print $OUT "multiple objects selected but can edit only one," 276 . "please specify which one ";474 . "please specify which one\n"; 277 475 return; 278 476 } … … 292 490 my $res = $obj->set_c_fields(%attr); 293 491 if ($res) { 294 print $OUT "Changes applied ";295 $env-> base->commit;492 print $OUT "Changes applied\n"; 493 $env->commit; 296 494 } 297 else { print $OUT "Error applying changes " }495 else { print $OUT "Error applying changes\n" } 298 496 return $res ? 1 : 0; 299 497 } … … 305 503 code => sub { 306 504 my ($env) = @_; 307 printf $OUT "%s: %s\ndelete selected objects ? (yes/NO) 505 printf $OUT "%s: %s\ndelete selected objects ? (yes/NO)\n", 308 506 $env->{_otype}, join(', ', map { $_->id } @{$env->{_objects}}); 309 507 my $reply = <STDIN> || ''; chomp($reply); … … 311 509 foreach (@{$env->{_objects}}) { 312 510 $env->base->delete_object($env->{_otype}, $_->id) or do { 313 print $OUT "Cannot delete " . $_->id ;511 print $OUT "Cannot delete " . $_->id . "\n"; 314 512 return; 315 513 }; 316 514 } 317 $env-> base->commit;515 $env->commit; 318 516 return "EXIT"; 319 517 } else { 320 print $OUT "cancel !" 321 } 322 }, 323 }); 518 print $OUT "cancel !\n" 519 } 520 }, 521 }); 522 if (grep { $objenv->base->attribute($otype, $_)->reference } 523 $objenv->base->list_canonical_fields($otype, 'r')) { 524 $objenv->add_func('select', { 525 help => 'select attribute [object]', 526 code => sub { 527 my ($env, $attrname, @objects) = @_; 528 my $totype = $env->base->attribute($env->{_otype}, 529 $attrname)->reference or return; 530 531 if (! @objects) { 532 @objects = grep { $_ } 533 map { $_->get_attributes($attrname) } @{$env->{_objects}}; 534 } 535 { 536 my %uniq = map { $_ => 1 } @objects; 537 @objects = keys %uniq; 538 } 539 my @objs = (grep { $_ } map { $env->base->get_object($totype, $_) } 540 @objects); 541 return if (!@objs); 542 print $OUT "Selecting $otype " . join(', ', map { $_->id } @objs) . "\n"; 543 objenv($_[0]->base, $totype, @objs)->cli(); 544 }, 545 completion => sub { 546 if ($_[2]) { 547 my $totype = $_[0]->base->attribute($_[0]->{_otype}, 548 $_[2])->reference or return; 549 return grep { $_ } 550 map { $_->get_attributes($_[2]) } 551 @{$_[0]->{_objects}}; 552 } else { 553 return grep { $_[0]->base->attribute($otype, $_)->reference } 554 $_[0]->base->list_canonical_fields($otype, 'r'); 555 } 556 }, 557 } 558 ); 559 } 324 560 325 561 if (lc($otype) eq 'user') { … … 334 570 my $gobj = $env->base->get_object('group', $gid) or 335 571 do { 336 print $OUT "Cannot find group $gid ";572 print $OUT "Cannot find group $gid\n"; 337 573 return; 338 574 }; … … 350 586 delete($gr{$_}) foreach(@groups); 351 587 } else { 352 print $OUT 'invalid action' ;588 print $OUT 'invalid action' . "\n"; 353 589 return; 354 590 } 355 591 defined $obj->set_c_fields('memberOf' => [ keys %gr ]) or do { 356 592 print $OUT "cannot set memberOf attributes for " . 357 $obj->id ;593 $obj->id . "\n"; 358 594 return; 359 595 }; 360 596 } 361 597 } 362 $env-> base->commit;598 $env->commit; 363 599 }, 364 600 completion => sub { … … 366 602 return (qw(add remove primary)); 367 603 } else { 368 return $_[0]->base->search_objects('group'); 604 if ($_[2] eq 'remove') { 605 my %uniq = map { $_ => 1 } 606 grep { $_ } 607 map { $_->get_attributes('memberOf') } 608 @{$_[0]->{_objects}}; 609 return sort keys %uniq; 610 } else { 611 return $_[0]->base->search_objects('group'); 612 } 369 613 } 370 614 }, … … 385 629 delete($gr{$_}) foreach(@groups); 386 630 } else { 387 print $OUT 'invalid action' ;631 print $OUT 'invalid action' . "\n"; 388 632 return; 389 633 } 390 634 defined $obj->set_c_fields('memberUID' => [ keys %gr ]) or do { 391 635 print $OUT "cannot set memberUID attributes for " . 392 $obj->id ;636 $obj->id . "\n"; 393 637 return; 394 638 }; 395 639 } 396 $env-> base->commit;640 $env->commit; 397 641 }, 398 642 completion => sub { … … 400 644 return (qw(add remove)); 401 645 } else { 402 return $_[0]->base->search_objects('user'); 646 if ($_[2] eq 'remove') { 647 my %uniq = map { $_ => 1 } 648 grep { $_ } 649 map { $_->get_attributes('member') } 650 @{$_[0]->{_objects}}; 651 return sort keys %uniq; 652 } else { 653 return $_[0]->base->search_objects('user'); 654 } 403 655 } 404 656 }, … … 413 665 bless($env, $class); 414 666 $env->{_labase} = $labase; 667 668 if ($labase->is_transactionnal) { 669 $env->add_func( 670 'transaction', { 671 help => 'change transaction mode', 672 code => sub { 673 $trans_mode = $_[1] eq 'on' ? 1 : 0; 674 }, 675 completion => sub { 676 $trans_mode == 0 ? 'on' : 'off'; 677 }, 678 } 679 ); 680 $env->add_func( 681 'commit', { 682 help => 'commit pending change', 683 code => sub { 684 $_[0]->_commit; 685 }, 686 } 687 ); 688 $env->add_func( 689 'rollback', { 690 help => 'commit pending change', 691 code => sub { 692 $_[0]->_rollback; 693 }, 694 } 695 ); 696 } 415 697 $env->add_func('quit', { help => 'quit - exit the tool', 416 698 code => sub { print "\n"; exit(0) }, }); … … 425 707 my ($self, $name) = @_; 426 708 if (!$name) { 427 print $OUT join(', ', sort keys %{ $self->{funcs} || {}}) ;709 print $OUT join(', ', sort keys %{ $self->{funcs} || {}}) . "\n"; 428 710 } elsif ($self->{funcs}{$name}{alias}) { 429 711 print $OUT "$name is an alias for " . join(' ', 430 @{$self->{funcs}{$name}{alias}}) ;712 @{$self->{funcs}{$name}{alias}}) . "\n"; 431 713 } elsif ($self->{funcs}{$name}{help}) { 432 print $OUT $self->{funcs}{$name}{help} ;714 print $OUT $self->{funcs}{$name}{help} . "\n"; 433 715 } else { 434 print $OUT "No help availlable ";716 print $OUT "No help availlable\n"; 435 717 } 436 718 }, … … 448 730 $self->complete($_[0], shellwords(substr($_[1], 0, $_[2]))); 449 731 }; 450 defined (my $line = $term->readline($self->prompt)) or return; 732 defined (my $line = $term->readline($self->prompt)) or do { 733 print $OUT "\n"; 734 return; 735 }; 736 $term->addhistory($line); 451 737 my $res = $self->run(shellwords($line)); 452 $self-> base->rollback;453 if ($res && $res eq 'EXIT') { return }738 $self->rollback if (!$trans_mode); 739 if ($res && $res eq 'EXIT') { print $OUT "\n"; return } 454 740 } 455 741 } … … 469 755 } 470 756 757 sub getoption { 758 my ($self, $opt, @args) = @_; 759 local @ARGV = @args; 760 Getopt::Long::Configure("pass_through"); 761 GetOptions(%{ $opt }); 762 763 return @ARGV; 764 } 765 471 766 sub parse_arg { 472 767 my ($self, $name, @args) = @_; 473 if ($self->{funcs}{$name}{opt}) { 474 @ARGV = @args; 475 } else { 476 return @args; 477 } 478 return @ARGV; 768 return @args; 479 769 } 480 770 … … 497 787 my ($self, $name, @args) = @_; 498 788 return if (!$name); 499 if ($self->{funcs}{$name}{alias}) { 789 if (!exists($self->{funcs}{$name})) { 790 print $OUT "No command $name found\n"; 791 } elsif ($self->{funcs}{$name}{alias}) { 500 792 $self->run(@{$self->{funcs}{$name}{alias}}, @args); 501 793 } elsif ($self->{funcs}{$name}{code}) { 502 794 my @pargs = $self->parse_arg($name, @args); 503 795 $self->{funcs}{$name}{code}->($self, @args); 796 } else { 797 print $OUT "No command $name found\n"; 504 798 } 505 799 } 506 800 801 sub commit { 802 my ($self) = @_; 803 if ($trans_mode) { 804 } else { 805 $self->_commit; 806 } 807 } 808 809 sub _commit { 810 my ($self) = @_; 811 $self->base->commit; 812 } 813 814 sub rollback { 815 my ($self) = @_; 816 if ($trans_mode) { 817 print $OUT "All pending changes get rollback\n"; 818 } 819 $self->_rollback; 820 } 821 822 sub _rollback { 823 my ($self) = @_; 824 $self->base->rollback; 825 } 826 507 827 1; -
LATMOS-Accounts/lib/LATMOS/Accounts/Log.pm
r476 r861 5 5 use Sys::Syslog qw(:standard :macros); 6 6 use Exporter (); 7 use Mail::Sendmail; 7 8 8 9 =head1 NAME … … 113 114 console => LA_NOTICE, 114 115 callback => undef, 116 mail => undef, 115 117 ); 118 119 my @maillog = (); 116 120 117 121 =head1 FUNCTIONS … … 154 158 sub lastmessage { 155 159 my ($level) = @_; 156 return $lastmessages{$level };160 return $lastmessages{$level || LA_ERROR}; 157 161 } 158 162 … … 186 190 $log_method{callback}->($level, $msg, @args); 187 191 } 192 if ($log_method{mail}) { 193 # store error to send it later, only ERROR 194 push(@maillog, sprintf($msg, @args)) if ($level <= LA_ERROR); 195 } 188 196 1; 189 197 } 190 198 199 sub _flush_mail { 200 @maillog = (); 201 } 202 203 sub _send_mail_log { 204 @maillog or return; 205 sendmail( 206 Subject => "LATMOS::Accounts error from $0", 207 To => $log_method{mail}, 208 From => 'LATMOS-Accounts@latmos.ipsl.fr', 209 Message => join("\n", @maillog), 210 ) or la_log(LA_ERR, "Cannot sent mail: " . $Mail::Sendmail::error); 211 _flush_mail(); 212 } 213 214 END { 215 _send_mail_log() if($log_method{mail}); 216 } 217 191 218 1; -
LATMOS-Accounts/lib/LATMOS/Accounts/Maintenance.pm
r850 r861 6 6 use LATMOS::Accounts::Log; 7 7 use FindBin qw($Bin); 8 use Crypt::RSA;9 use Crypt::RSA::Key::Public::SSH;10 use Crypt::RSA::Key::Private::SSH;11 use MIME::Base64;12 8 13 9 sub _base { 14 10 my ($self) = @_; 11 return $self->{_maintenance_base} if ($self->{_maintenance_base}); 15 12 my $base = $self->SUPER::default_base; 16 13 $base->type eq 'sql' or die "This module work only with SQL base type\n"; 17 $base14 return $self->{_maintenance_base} = $base 18 15 } 19 16 20 17 sub find_next_expire_users { 21 18 # Do not replace this code by $base->find_next_expire_users 22 # it does not ex ctly the same thing19 # it does not exactly the same thing 23 20 my ($self, $expire) = @_; 24 21 my $base = $self->_base; … … 184 181 } 185 182 183 sub expired_account_reminder { 184 my ($self, %options) = @_; 185 $options{delay} ||= '6 month'; 186 187 require Mail::Sendmail; 188 require Template; 189 190 my $template = Template->new( 191 INCLUDE_PATH => [ 192 ($self->val('_default_', 'templatespath') 193 ? $self->val('_default_', 'templatespath') . '/mail' 194 : ()), 195 "$FindBin::Bin/../templates" . '/mail', 196 '/usr/share/latmos-accounts/templates/mail', 197 ], 198 POST_CHOMP => 1, 199 EXTENSION => '.mail', 200 ); 201 202 my @users = $self->_base->find_expired_users($options{delay}); 203 204 my %managers; 205 foreach my $user (@users) { 206 my $uobj = $self->_base->get_object('user', $user); 207 $uobj->get_attributes('unexported') and next; # can't happend 208 my $manager = $uobj->get_attributes('managerContact') || 'N/A'; 209 push(@{$managers{$manager}{users}}, $uobj); 210 } 211 212 foreach (keys %managers) { 213 my $oman = $self->_base->get_object('user', $_) or next; # can't happend 214 $managers{$_}{manager} = $oman; 215 my $mail = $oman->get_attributes('mail') or next; 216 217 my %mail = ( 218 From => $self->val('_default_', 'mailFrom', 'nomail@localhost'), 219 Subject => 'LATMOS expired account', 220 smtp => $self->val('_default_', 'smtp'), 221 'Content-Type' => 'text/plain; charset=utf-8', 222 'X-LATMOS-Accounts' => '$Rev$', 223 'X-LATMOS-Reason' => 'Account expiration', 224 ); 225 $mail{to} = $options{to} || $mail; 226 my $message; 227 $template->process('account_expired_reminder.mail', $managers{$oman->id}, \$message) 228 or do { 229 la_log(LA_ERR, "Cannot send expiration mail: %s, exiting", 230 $template->error()); 231 exit(1); 232 }; 233 234 if (!$options{test}) { 235 if (Mail::Sendmail::sendmail( 236 %mail, 237 Message => $message, 238 )) { 239 la_log(LA_NOTICE, 240 "Expired account reminder mail for %s sent to %s (cc: %s) for %s", 241 $oman->id, 242 $mail{to}, 243 ($mail{cc} || ''), 244 join(', ', map { $_->id } @{$managers{$oman->id}{users}}) 245 ); 246 } else { 247 la_log(LA_ERR, "Cannot send mail: %s", $Mail::Sendmail::error); 248 } 249 } 250 } 251 my @summary; 252 foreach my $manager (sort keys %managers) { 253 push(@summary, "\n" . ( 254 $managers{$manager}{manager} 255 ? $managers{$manager}{manager}->get_attributes('displayName') 256 : $manager) . "\n"); 257 foreach (@{$managers{$manager}{users}}) { 258 push(@summary, sprintf(" %s - %s (%s)\n", 259 $_->id, 260 $_->get_attributes('displayName'), 261 $_->get_attributes('expireText'), 262 )); 263 } 264 } 265 266 if (@summary) { 267 if ($options{test}) { 268 print join('', @summary); 269 } else { 270 if ($self->val('_default_', 'expire_summary_to')) { 271 my %mail = ( 272 From => $self->val('_default_', 'mailFrom', 'nomail@localhost'), 273 Subject => 'LATMOS expired account (to disable)', 274 smtp => $self->val('_default_', 'smtp'), 275 'Content-Type' => 'text/plain; charset=utf-8', 276 'X-LATMOS-Accounts' => '$Rev$', 277 'X-LATMOS-Reason' => 'Account expiration', 278 To => $self->val('_default_', 'expire_summary_to'), 279 ); 280 if (Mail::Sendmail::sendmail( 281 %mail, 282 Message => join('', @summary), 283 )) { 284 la_log(LA_NOTICE, "Expiration summary mail sent to %s", 285 $self->val('_default_', 'expire_summary_to'), 286 ); 287 } else { 288 la_log(LA_ERR, "Cannot send mail: %s", $Mail::Sendmail::error); 289 } 290 } 291 } 292 } 293 } 294 186 295 sub generate_rsa_key { 296 # compat functions 187 297 my ($self, $password) = @_; 188 189 my $rsa = new Crypt::RSA ES => 'PKCS1v15'; 190 my ($public, $private) = $rsa->keygen ( 191 Identity => 'LATMOS-Accounts', 192 Size => 768, 193 Password => $password, 194 Verbosity => 0, 195 KF=>'SSH', 196 ) or die 197 $self->rsa->errstr(); # TODO avoid die 198 return ($public, $private); 199 } 298 $self->_base->generate_rsa_key($password); 299 } 300 200 301 201 302 sub store_rsa_key { 303 # compat functions 202 304 my ($self, $public, $private) = @_; 203 my $base = $self->_base; 204 $base->set_global_value('rsa_private_key', 205 encode_base64($private->serialize)); 206 $base->set_global_value('rsa_public_key', 207 $public->serialize); 208 return; 305 $self->_base->store_rsa_key($public, $private); 209 306 } 210 307 211 308 sub private_key { 309 # compat functions 212 310 my ($self, $password) = @_; 213 my $base = $self->_base; 214 my $serialize = $base->get_global_value('rsa_private_key') or return; 215 my $privkey = Crypt::RSA::Key::Private::SSH->new; 216 $privkey->deserialize(String => [ decode_base64($serialize) ], 217 Passphrase => $password); 218 $privkey 311 $self->_base->private_key($password); 219 312 } 220 313 221 314 sub get_rsa_password { 315 # compat functions 222 316 my ($self) = @_; 223 my $base = $self->_base; 224 my $sth = $base->db->prepare(q{ 225 select "name", value from "user" join user_attributes_base 226 on "user".ikey = user_attributes_base.okey 227 where user_attributes_base.attr = 'encryptedPassword' 228 }); 229 $sth->execute; 230 my %users; 231 while (my $res = $sth->fetchrow_hashref) { 232 $users{$res->{name}} = $res->{value}; 233 } 234 %users 317 $self->_base->get_rsa_password; 235 318 } 236 319 -
LATMOS-Accounts/lib/LATMOS/Accounts/SynchAccess/base.pm
r715 r861 24 24 my ($class, $bases) = @_; 25 25 bless { 26 bases => [ @{ $bases } ],26 bases => [ @{ $bases } ], 27 27 }, $class; 28 28 } -
LATMOS-Accounts/lib/LATMOS/Accounts/Synchro.pm
r819 r861 124 124 $self->load_dest and return; 125 125 my %state = (); 126 $state{$self->from->label} = $self->from->wexported(0); 126 $state{$self->from->label} = $self->from->wexported( 127 $self->{options}{unexported} ? 1 : 0 128 ); 127 129 foreach ($self->to) { 128 130 $state{$_->label} = $_->wexported(1); … … 137 139 la_log(LA_DEBUG, "Leaving synch mode"); 138 140 $self->from->wexported($state{$self->from->label}); 139 foreach ($self->to) {140 $ _->commit;141 $ _->wexported($state{$_->label});141 foreach my $base (grep { $_ } $self->to) { 142 $base->commit; 143 $base->wexported($state{$base->label}); 142 144 } 143 145 } … … 205 207 206 208 $self->lock or return; 209 210 if (!(my $res = $self->run_pre_synchro({}))) { 211 la_log(LA_ERR, "Pre synchro script failed, aborting"); 212 $self->unlock; 213 return; 214 } 207 215 208 216 my %state = $self->enter_synch_mode; … … 230 238 $self->from->label, $otype, $_, $destbase->label, $res, 231 239 ); 240 if ($destbase->is_transactionnal) { 241 $destbase->commit; 242 } 232 243 $updated = 1; 244 } else { 245 if ($destbase->is_transactionnal) { 246 $destbase->rollback; 247 } 233 248 } 234 249 } … … 241 256 } 242 257 foreach my $pass (1, 0) { 243 foreach my $otype ( 244 sort { $a eq 'user' ? 1 : -1 } # user in last because gidNumber needed 245 keys %objlist) { 246 next if (!$pass && !$destbase->delayed_fields($otype)); 258 foreach my $otype ($destbase->ordered_objects) { 259 exists($objlist{$otype}) or next; 247 260 foreach (@{$objlist{$otype} || []}) { 248 261 my $res = $destbase->sync_object_from($self->from, $otype, $_, … … 254 267 $destbase->label, $res, 255 268 ); 269 if ($destbase->is_transactionnal) { 270 $destbase->commit; 271 } 256 272 $updated = 1; 257 273 } … … 262 278 ); 263 279 $desterror{$destbase->label} = 1; 280 if ($destbase->is_transactionnal) { 281 $destbase->rollback; 282 } 264 283 } 265 284 … … 272 291 my $res = $self->run_post_synchro( 273 292 { 274 UPDATED => $updated ,293 UPDATED => $updated || undef, 275 294 } 276 295 ); … … 313 332 } 314 333 334 sub run_pre_synchro { 335 my ($self, $env) = @_; 336 337 $env ||= {}; 338 $env->{HOOK_TYPE} = 'PRE'; 339 340 foreach my $base ($self->to) { 341 if ($base->options('presynchro')) { 342 la_log LA_DEBUG, "Executing base pre synchro `%s' for %s", 343 $base->options('presynchro'), $base->label; 344 exec_command( 345 $base->options('presynchro'), 346 { 347 BASE => $base->label, 348 BASETYPE => $base->type, 349 %{ $env }, 350 } 351 ); 352 } 353 } 354 355 $self->{options}{pre} or return 1; 356 357 la_log(LA_DEBUG, "Running post synchro `%s'", $self->{options}{pre}); 358 359 exec_command($self->{options}{post}, $env); 360 } 361 315 362 sub run_post_synchro { 316 363 my ($self, $env) = @_; 364 365 $env ||= {}; 366 $env->{HOOK_TYPE} = 'PRE'; 367 368 foreach my $base ($self->to) { 369 if ($base->options('postsynchro')) { 370 la_log LA_DEBUG, "Executing base post synchro `%s' for %s", 371 $base->options('postsynchro'), $base->label; 372 exec_command( 373 $base->options('postsynchro'), 374 { 375 BASE => $base->label, 376 BASETYPE => $base->type, 377 %{ $env }, 378 } 379 ); 380 } 381 } 317 382 318 383 $self->{options}{post} or return 1; 319 384 320 la_log(LA_ INFO, "Running post synchro `%s'", $self->{options}{post});321 385 la_log(LA_DEBUG, "Running post synchro `%s'", $self->{options}{post}); 386 322 387 exec_command($self->{options}{post}, $env); 323 388 } -
LATMOS-Accounts/lib/LATMOS/Accounts/Utils.pm
r818 r861 12 12 13 13 @ISA = qw(Exporter); 14 @EXPORT = qw(to_ascii exec_command );15 @EXPORT_OK = qw(to_ascii exec_command );14 @EXPORT = qw(to_ascii exec_command switch_user run_via_sudo); 15 @EXPORT_OK = qw(to_ascii exec_command switch_user run_via_sudo); 16 16 17 17 sub to_ascii { … … 21 21 $text =~ s/Å/oe/g; 22 22 $text =~ s/Ê/ae/g; 23 $text =~ tr {uà âÀÃÃÃçéÚêëÃÃÃÃïîÃÃÞöÎÃÃÌûÃà }24 {uaaaAAAceeeeEEEEiiIIoooOOuuUU };23 $text =~ tr {uà âÀÃÃÃçéÚêëÃÃÃÃïîÃÃÞöÎÃÃÌûÃÃÄ} 24 {uaaaAAAceeeeEEEEiiIIoooOOuuUUc}; 25 25 $text =~ s/([^[:ascii:]])/_/g; 26 26 $text … … 29 29 sub exec_command { 30 30 my ($command, $env) = @_; 31 my $rout = undef; 32 $rout = \$_[2] if(@_ > 2); 31 33 32 34 my @exec = ref $command … … 35 37 la_log(LA_DEBUG, 'running command `%s\'', join(' ', @exec)); 36 38 39 pipe(my $rh, my $wh); 37 40 my $pid = fork; 38 41 if (!defined($pid)) { … … 40 43 } elsif ($pid) { 41 44 # Father 45 close($wh); 46 my $header; 47 while (<$rh>) { 48 if ($rout) { 49 $$rout .= $_; 50 } else { 51 chomp; 52 if (!$header) { 53 $header = 1; 54 la_log(LA_NOTICE, "exec `%s'", join(' ', @exec)); 55 } 56 la_log(LA_NOTICE, "output: %s", $_); 57 } 58 } 42 59 waitpid($pid, 0); 43 60 if (my $exitstatus = $?) { … … 50 67 } else { 51 68 # Child 69 close($rh); 70 ( $ENV{LA_MODULE} ) = caller(); 52 71 foreach (keys %{ $env || {} }) { 53 72 $ENV{"LA_$_"} = $env->{$_}; 54 73 } 74 open(STDOUT, ">&=" . fileno($wh)); 75 open(STDERR, ">&=" . fileno($wh)); 55 76 exec(@exec); 56 77 exit($!); … … 78 99 } 79 100 } else { 80 $attributes{$attr} = $value || undef; 81 $attr eq 'exported' && !defined $attributes{$attr} and $attributes{$attr} = 1; 101 $attributes{$attr} = $value eq '' ? undef : $value; 102 # Don't remember why this is here 103 #$attr eq 'exported' && !defined $attributes{$attr} and $attributes{$attr} = 1; 82 104 } 83 105 } … … 129 151 if ($name !~ /^[a-z]/); 130 152 return "must contain only a-z,0-9" 131 if ($name !~ /^[a-z,0-9 ]+$/);153 if ($name !~ /^[a-z,0-9,_,-]+$/); 132 154 133 155 return check_oid_validity($name); 134 156 } 135 157 158 sub switch_user { 159 my ($runas) = @_; 160 161 if ($< == 0 || $> == 0) { 162 my @info = getpwnam($runas) or do { 163 warn "Can find user $runas"; 164 return; 165 }; 166 $> = $info[3]; 167 return; 168 } else { 169 warn "we are not root"; 170 } 171 } 172 173 sub run_via_sudo { 174 my ($runas) = @_; 175 176 my @info = getpwnam($runas) or do { 177 warn "Can find user $runas"; 178 return; 179 }; 180 if ($< != $info[3]) { 181 exec('sudo', '-u', $runas, $0, @ARGV) or "Can run $!"; 182 } 183 } 184 136 185 1; -
LATMOS-Accounts/t/10_bases.t
r679 r861 20 20 [qw(username homeDirectory) ], 21 21 ), "Can get canonicals fields"); 22 is( $dummyb-> get_field_name('user', 'homeDirectory'), "home", "can call get_fields_name");22 is( $dummyb->attribute('user', 'homeDirectory')->iname, "home", "can call get_fields_name"); 23 23 ok(!$dummyb->is_transactionnal, 'Dummy driver is not transactionnal'); 24 24 -
LATMOS-Accounts/t/11_bases_unix.t
r715 r861 27 27 ok($unixb->load, "Can load unix base"); 28 28 29 is( $unixb-> get_field_name('user', 'homeDirectory'), "home", "can call get_fields_name");29 is( $unixb->attribute('user', 'homeDirectory')->iname, "home", "can call get_fields_name"); 30 30 31 31 ok(my $user = $unixb->get_object('user', 'root'), "Can get root user"); -
LATMOS-Accounts/t/12_bases_sql.t
r445 r861 1 1 use strict; 2 2 use warnings; 3 use Test::More tests => 1 0;3 use Test::More tests => 12; 4 4 5 5 use_ok('LATMOS::Accounts::Bases'); … … 13 13 use_ok('LATMOS::Accounts::Bases::Sql::Address'); 14 14 use_ok('LATMOS::Accounts::Bases::Sql::Onlyaddress'); 15 use_ok('LATMOS::Accounts::Bases::Sql::Accreq'); 15 16 17 use_ok('LATMOS::Accounts::Bases::Sql::OCHelper::Accreq'); -
LATMOS-Accounts/t/15_bases_mail.t
r305 r861 26 26 ok($mailb->load, "Can load mail base"); 27 27 28 is( $mailb-> get_field_name('aliases', 'forward'), "forward", "can call get_field_name");28 is( $mailb->attribute('aliases', 'forward')->iname, "forward", "can call get_field_name"); 29 29 30 30 ok(my $alias = $mailb->get_object('aliases', 'name'), "Can get root user"); -
LATMOS-Accounts/t/20_accounts.t
r410 r861 8 8 9 9 isa_ok( 10 my $accounts = LATMOS::Accounts->new('testdata/config '),10 my $accounts = LATMOS::Accounts->new('testdata/configdir'), 11 11 'LATMOS::Accounts' 12 12 ); -
LATMOS-Accounts/t/22_accounts_attributes.t
r852 r861 8 8 9 9 isa_ok( 10 my $accounts = LATMOS::Accounts->new('testdata/config '),10 my $accounts = LATMOS::Accounts->new('testdata/configdir'), 11 11 'LATMOS::Accounts' 12 12 ); … … 14 14 ok(my $base = $accounts->base('unix'), "Can get base"); 15 15 16 my $attr = LATMOS::Accounts::Bases::Attributes->new(' sn', $base, 'user');16 my $attr = LATMOS::Accounts::Bases::Attributes->new('memberUID', $base, 'group'); -
LATMOS-Accounts/t/25_la_synchro.t
r54 r861 26 26 } 27 27 28 ok($config->WriteConfig("$workdir/ config.ini"), "can write config file for test");28 ok($config->WriteConfig("$workdir/latmos-accounts.ini"), "can write config file for test"); 29 29 30 30 diag("Write test done in $workdir/"); 31 31 32 32 isa_ok( 33 my $accounts = LATMOS::Accounts->new( "$workdir/config.ini"),33 my $accounts = LATMOS::Accounts->new($workdir), 34 34 'LATMOS::Accounts' 35 35 ); -
LATMOS-Accounts/t/26_la_synchaccess.t
r56 r861 30 30 } 31 31 32 ok($config->WriteConfig("$workdir/ config.ini"), "can write config file for test");32 ok($config->WriteConfig("$workdir/latmos-accounts.ini"), "can write config file for test"); 33 33 34 34 diag("Write test done in $workdir/"); 35 35 36 36 isa_ok( 37 my $accounts = LATMOS::Accounts->new( "$workdir/config.ini"),37 my $accounts = LATMOS::Accounts->new($workdir), 38 38 'LATMOS::Accounts' 39 39 ); -
LATMOS-Accounts/templates/mail/account_expire.mail
r786 r861 5 5 sauf erreur ou ommission de notre part votre compte [% obj.id %] expire 6 6 dans [% delay %] jours ([% obj.get_c_field('expire') %]). 7 En aucun cas vos fichiers ne seront détruit 7 En aucun cas vos fichiers ne seront détruits. 8 8 9 Si ce dernier devai s être prolongémerci de dire à votre responsable9 Si ce dernier devait être prolongé, merci de dire à votre responsable 10 10 de contacter svp@latmos.ipsl.fr afin de nous donner la nouvelle date. 11 11 … … 22 22 23 23 If it had to be extended, please ask your manager to contact 24 svp@latmos.ipsl.fr to give us withthe new date of expiry.24 svp@latmos.ipsl.fr to give us the new date of expiry. 25 25 26 26 Best regards.
Note: See TracChangeset
for help on using the changeset viewer.