diff -Nur smeserver-shared-folders-0.1/createlinks smeserver-shared-folders-0.1_mod/createlinks --- smeserver-shared-folders-0.1/createlinks 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/createlinks 2012-02-17 17:28:33.000000000 +0100 @@ -11,12 +11,12 @@ panel_link("userpanel-encfs", $panel); #-------------------------------------------------- -# actions for group-delete event +# actions for group-delete and user-delete events #-------------------------------------------------- -$event = "group-delete"; - -event_link("group-share-modify", $event, "10"); +foreach my $event (qw/group-delete user-delete/) { + event_link("group-share-modify", $event, "10"); +} #-------------------------------------------------- # actions for share-delete event diff -Nur smeserver-shared-folders-0.1/root/etc/e-smith/events/actions/group-share-modify smeserver-shared-folders-0.1_mod/root/etc/e-smith/events/actions/group-share-modify --- smeserver-shared-folders-0.1/root/etc/e-smith/events/actions/group-share-modify 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/root/etc/e-smith/events/actions/group-share-modify 2012-02-17 17:28:33.000000000 +0100 @@ -7,40 +7,47 @@ my $accounts = esmith::AccountsDB->open() or die "Unable to open accounts db: $!"; -my ($self, $groupName) = @ARGV; +my ($event, $name) = @ARGV; + +my $type = 'Groups'; + +if ($event eq 'user-delete'){ + $type = 'Users'; +} # Find all "shared folder" entries in the e-smith accounts database and -# if the group matches one listed in ACL, remove it. +# if the group or a user matches one listed in ACL, remove it. my @modified_shares; foreach my $share ( $accounts->get_all_by_prop(type => 'share' ) ) { my $modified = 0; - my @OldReadGroups = split (/[,;]/,$share->prop('ReadGroups')); - my @NewReadGroups = (); - foreach (@OldReadGroups){ - if ( $_ eq $groupName ) { + my @OldRead = split (/[,;]/,$share->prop('Read'.$type)); + my @NewRead = (); + foreach (@OldRead){ + if ( $_ eq $name ) { $modified = 1; } else{ - push @NewReadGroups, $_; + push @NewRead, $_; } } - $share->set_prop( 'ReadGroups', join( "," , @NewReadGroups ) ); + $share->set_prop('Read'.$type, join("," , @NewRead)); - my @OldWriteGroups = split (/[,;]/,$share->prop('WriteGroups')); - my @NewWriteGroups = (); - foreach (@OldWriteGroups){ - if ( $_ eq $groupName ) { + my @OldWrite = split (/[,;]/,$share->prop('Write'.$type)); + my @NewWrite = (); + foreach (@OldWrite){ + if ( $_ eq $name ) { $modified = 1; } else{ - push @NewWriteGroups, $_; + push @NewWrite, $_; } } - $share->set_prop( 'WriteGroups', join( "," , @NewWriteGroups ) ); + $share->set_prop('Write'.$type, join("," , @NewWrite)); - # If a group has been removed, either from Read or Write, re-apply the ACLs + # If a group or a user has been removed, either from Read or Write, re-apply the ACLs if ($modified){ + push @modified_shares, $share->key; event_signal("share-modify-files", $share->key) or die ("Error occurred while updating shared folder.\n"); } diff -Nur smeserver-shared-folders-0.1/root/etc/e-smith/events/actions/share-modify smeserver-shared-folders-0.1_mod/root/etc/e-smith/events/actions/share-modify --- smeserver-shared-folders-0.1/root/etc/e-smith/events/actions/share-modify 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/root/etc/e-smith/events/actions/share-modify 2012-02-17 17:28:33.000000000 +0100 @@ -90,8 +90,10 @@ #-------------------------------------------------- my %properties = $share->props; -my @write = split(/[;,]/,($properties {'WriteGroups'} || 'admin')); -my @read = split(/[;,]/,($properties {'ReadGroups'} || 'admin')); +my @writegroups = split(/[;,]/,($properties {'WriteGroups'} || 'admin')); +my @readgroups = split(/[;,]/,($properties {'ReadGroups'} || 'admin')); +my @writeusers = split(/[;,]/,($properties {'WriteUsers'} || '')); +my @readusers = split(/[;,]/,($properties {'ReadUsers'} || '')); # Don't reset permissions if ManualPermissions is set to 'yes' @@ -111,12 +113,18 @@ '.'); my $acl = 'u::rwX,g::rwX,o:---,'; - foreach my $group (@write){ + foreach my $group (@writegroups){ $acl .= 'g:'.$group.':rwX,'; } - foreach my $group (@read){ + foreach my $group (@readgroups){ $acl .= 'g:'.$group.':rX,'; } + foreach my $user (@writeusers){ + $acl .= 'u:'.$user.':rwX,'; + } + foreach my $user (@readusers){ + $acl .= 'u:'.$user.':rX,'; + } # Set the effective ACLs system($setfacl, @@ -144,9 +152,12 @@ '--remove-default', '.'); - foreach my $group (@write,@read){ + foreach my $group (@writegroups,@readgroups){ $acl .= 'g:'.$group.':rX,'; } + foreach my $user (@writeusers,@readusers){ + $acl .= 'g:'.$user.':rX,'; + } system($setfacl, '-m', diff -Nur smeserver-shared-folders-0.1/root/etc/e-smith/locale/en-us/etc/e-smith/web/functions/shares smeserver-shared-folders-0.1_mod/root/etc/e-smith/locale/en-us/etc/e-smith/web/functions/shares --- smeserver-shared-folders-0.1/root/etc/e-smith/locale/en-us/etc/e-smith/web/functions/shares 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/root/etc/e-smith/locale/en-us/etc/e-smith/web/functions/shares 2012-02-17 17:28:33.000000000 +0100 @@ -155,7 +155,7 @@ DESC_PERMISSIONS - You can use this matrix to define groups access permissions. + You can use this matrix to define groups and users access permissions. @@ -510,4 +510,16 @@ + + TITLE_PERMISSIONS + + Access right management + + + + + USERS + Utilisateurs + + diff -Nur smeserver-shared-folders-0.1/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/90e-smithAccess50shares smeserver-shared-folders-0.1_mod/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/90e-smithAccess50shares --- smeserver-shared-folders-0.1/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/90e-smithAccess50shares 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/root/etc/e-smith/templates/etc/httpd/conf/httpd.conf/90e-smithAccess50shares 2012-02-17 17:28:33.000000000 +0100 @@ -16,7 +16,7 @@ my $satisfy; my $webdav = (($properties{'WebDav'} || 'disabled') =~ m/^(enabled|on|yes)$/i) ? 1 : 0; - # Find which users has at least read access + # Find which users have read or write access my @writers = ('admin'); my @readers = (); if ($properties{'WriteGroups'}) { @@ -26,10 +26,14 @@ my $members = $adb->get_prop($group, 'Members') || ""; if (length($members) > 0) { push @writers, split (/[;,]/, $members); - } + } } } + if ($properties{'WriteUsers'}) { + my @users = split (/[;,]/, $properties{'WriteUsers'}); + push @writers, @users; + } if ($properties{'ReadGroups'}) { my @groups = split (/[;,]/, $properties{'ReadGroups'}); @@ -37,10 +41,14 @@ my $members = $adb->get_prop($group, 'Members') || ""; if (length($members) > 0) { push @readers, split (/[;,]/, $members); - } + } } } + if ($properties{'ReadUsers'}) { + my @users = split (/[;,]/, $properties{'ReadUsers'}); + push @readers, @users; + } my %seen = (); @readers = sort (grep { ! $seen{ $_ }++ } (@readers,@writers)); diff -Nur smeserver-shared-folders-0.1/root/etc/e-smith/web/functions/shares smeserver-shared-folders-0.1_mod/root/etc/e-smith/web/functions/shares --- smeserver-shared-folders-0.1/root/etc/e-smith/web/functions/shares 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/root/etc/e-smith/web/functions/shares 2012-02-17 17:28:33.000000000 +0100 @@ -51,16 +51,6 @@ - DESC_PERMISSIONS - - - - - - DESC_SMB_SETTINGS @@ -128,5 +118,13 @@ REMOVE_DESC + + TITLE_PERMISSIONS + + DESC_PERMISSIONS + + + + diff -Nur smeserver-shared-folders-0.1/root/usr/lib/perl5/site_perl/esmith/FormMagick/Panel/shares.pm smeserver-shared-folders-0.1_mod/root/usr/lib/perl5/site_perl/esmith/FormMagick/Panel/shares.pm --- smeserver-shared-folders-0.1/root/usr/lib/perl5/site_perl/esmith/FormMagick/Panel/shares.pm 2012-02-17 18:12:49.000000000 +0100 +++ smeserver-shared-folders-0.1_mod/root/usr/lib/perl5/site_perl/esmith/FormMagick/Panel/shares.pm 2012-02-17 18:13:09.000000000 +0100 @@ -26,7 +26,7 @@ print_share_name_field print_encryption_fields print_ajaxplorer_fields - genGroupAccess + acl_list smbAccess_list httpAccess_list max_share_name_length @@ -40,8 +40,8 @@ our $VERSION = sprintf '%d.%03d', q$Revision: 1.8 $ =~ /: (\d+).(\d+)/; -our $accountdb = esmith::AccountsDB->open(); -our $configdb = esmith::ConfigDB->open(); +our $a = esmith::AccountsDB->open(); +our $c = esmith::ConfigDB->open(); *wherenext = \&CGI::FormMagick::wherenext; @@ -62,12 +62,12 @@ my $name = $self->localise('NAME'); my $description = $self->localise('DESCRIPTION'); my $modify = $self->localise('MODIFY'); + my $perm = $self->localise('PERMISSIONS'); my $remove = $self->localise('REMOVE'); my $action_h = $self->localise('ACTION'); - my @shares = $accountdb->get_all_by_prop(type => 'share'); + my @shares = $a->get_all_by_prop(type => 'share'); - unless ( scalar @shares ) - { + unless ( scalar @shares ) { print $q->Tr($q->td($self->localise('NO_SHARES'))); return ""; } @@ -81,22 +81,25 @@ my $scriptname = basename($0); - foreach my $i (@shares) - { - my $sharename = $i->key(); - my $sharedesc = $i->prop('Name'); + foreach my $share (@shares) { + my $sharename = $share->key(); + my $sharedesc = $share->prop('Name'); my $href = "shares?page=;page_stack=;wherenext="; my $actionModify = $q->a({href => "${href}CreateModify&action=modify&name=$sharename"},$modify) . ' '; + my $actionPerm = $q->a({href => "${href}Permissions&action=permissions&name=$sharename"},$perm) + . ' '; + my $actionRemove .= $q->a({href => "${href}Remove&name=$sharename&description=$sharedesc"}, $remove) . ' '; print $q->Tr ( esmith::cgi::genSmallCell($q, $sharename,"normal"), esmith::cgi::genSmallCell($q, $sharedesc,"normal"), + esmith::cgi::genSmallCell($q, $actionPerm,"normal"), esmith::cgi::genSmallCell($q, $actionModify,"normal"), esmith::cgi::genSmallCell($q, $actionRemove,"normal") ); @@ -109,58 +112,55 @@ sub print_custom_button{ - my ($fm,$desc,$url) = @_; - my $q = $fm->{cgi}; - $url="shares?page=0&page_stack=&Next=Next&wherenext=".$url; + my ($self,$desc,$url) = @_; + my $q = $self->{cgi}; + $url = "shares?page=0&page_stack=&Next=Next&wherenext=" . $url; print " \n \n"; print $q->p($q->a({href => $url, -class => "button-like"}, - $fm->localise($desc))); + $self->localise($desc))); print qq(\n); return undef; } sub print_share_to_remove{ - my ($fm) = @_; - my $q = $fm->{cgi}; + my $self = shift; + my $q = $self->{cgi}; my $sharename = $q->param('name'); my $desc = $q->param('description'); print $q->Tr( $q->td( { -class => 'sme-noborders-label' }, - $fm->localise('NAME') + $self->localise('NAME') ), $q->td( { -class => 'sme-noborders-content' }, $sharename ) - ), - "\n"; + ), "\n"; print $q->Tr( $q->td( { -class => 'sme-noborders-label' }, - $fm->localise('DESCRIPTION') + $self->localise('DESCRIPTION') ), $q->td( { -class => 'sme-noborders-content' }, $desc ) - ), - "\n"; + ), "\n"; - print $q->table( + print $q->table( { -width => '100%' }, $q->Tr( $q->th( { -class => 'sme-layout' }, $q->submit( -name => 'cancel', - -value => $fm->localise('CANCEL') + -value => $self->localise('CANCEL') ), ' ', $q->submit( -name => 'remove', - -value => $fm->localise('REMOVE') + -value => $self->localise('REMOVE') ) ) ) - ), - "\n"; + ), "\n"; # Clear these values to prevent collisions when the page reloads. $q->delete("cancel"); @@ -172,12 +172,13 @@ sub print_share_name_field { my $self = shift; - my $in = $self->{cgi}->param('name') || ''; - my $action = $self->{cgi}->param('action') || ''; - my $maxLength = $configdb->get('maxShareNameLength')->value || '12'; + my $q = $self->{cgi}; + my $in = $q->param('name') || ''; + my $action = $q->param('action') || ''; + my $maxLength = $c->get('maxShareNameLength')->value || '12'; # Set default value - my $q = $self->{cgi}; + $q->param(-name=>'encryption',-value=>'disabled'); $q->param(-name=>'inactivity',-value=>'30'); $q->param(-name=>'smbaccess',-value=>'browseable'); @@ -204,7 +205,7 @@ # Read the values for each field from the accounts db and store # them in the cgi object so our form will have the correct # info displayed. - my $rec = $accountdb->get($in); + my $rec = $a->get($in); if ($rec) { $q->param(-name=>'description',-value=> @@ -213,10 +214,6 @@ ($rec->prop('Encryption') || 'disabled')); $q->param(-name=>'inactivity',-value=> ($rec->prop('InactivityTimeOut') || '30')); - $q->param(-name=>'ReadGroups',-value=> - $rec->prop('ReadGroups')); - $q->param(-name=>'WriteGroups',-value=> - $rec->prop('WriteGroups')); $q->param(-name=>'smbaccess',-value=> ($rec->prop('smbAccess') || 'enabled')); $q->param(-name=>'recyclebin',-value=> @@ -233,8 +230,6 @@ ($rec->prop('Indexes') || 'enabled')); $q->param(-name=>'dynamic',-value=> ($rec->prop('DynamicContent') || 'disabled')); - $q->param(-name=>'manualPerm',-value=> - ($rec->prop('ManualPermissions') || 'no')); } } else { @@ -253,18 +248,19 @@ # If EncFS is available, print encryptions options sub print_encryption_fields { my $self = shift; + my $q = $self->{cgi}; return undef unless(system('rpm -q fuse-encfs 2>&1 > /dev/null') == 0); - my $encryption = $self->{cgi}->param('encryption') || 'disabled'; - my $action = $self->{cgi}->param('action') || ''; + my $encryption = $q->param('encryption') || 'disabled'; + my $action = $q->param('action') || ''; - my $sharename = $self->{cgi}->param('name') || ''; + my $sharename = $q->param('name') || ''; return undef if ($action eq 'modify' && $encryption ne 'enabled'); - my $inactivity = (($sharename ne '') && ($accountdb->get($sharename))) ? - ($accountdb->get($sharename)->prop('InactivityTimeOut') || '30'):'30'; + my $inactivity = (($sharename ne '') && ($a->get($sharename))) ? + ($a->get($sharename)->prop('InactivityTimeOut') || '30'):'30'; print_section_bar(); @@ -316,13 +312,13 @@ # If ajaxplorer is enabled: sub print_ajaxplorer_fields { - my ($self) = @_; - my $ajaxplorer = $configdb->get('ajaxplorer') || return undef; + my $self = shift; + my $ajaxplorer = $c->get('ajaxplorer') || return undef; if (($ajaxplorer->prop('status') || 'disabled') eq 'enabled'){ print_section_bar(); my ($enabled,$disabled) = ('',''); my $sharename = $self->{cgi}->param('name') || ''; - my $share = $accountdb->get($sharename); + my $share = $a->get($sharename); # If share exists and Ajxplorer is enabled if ($share){ if (($share->prop('Ajaxplorer') || 'disabled') eq 'enabled'){ @@ -345,24 +341,31 @@ return undef; } -# Takes a comma delimited list of groups and returns a string of -# html checkboxes for all system groups with the groups having write and read access. - -sub genGroupAccess () { - my $fm = shift; - my $q = $fm->{cgi}; - my $WriteGroups = $q->param('WriteGroups') || ''; - my $ReadGroups = $q->param('ReadGroups') || ''; - my $share = $q->param('share'); - my $manualPerm = $q->param('manualPerm') || ''; +# Print a table of users and groups +# having read only or read/write access +sub acl_list () { + my $self = shift; + my $q = $self->{cgi}; + my $sharename = $q->param('name'); my $out = ''; + my $share = $a->get($sharename); + return $self->error('SHARE_NOT_FOUND') unless ($share); + + my $WriteGroups = $share->prop('WriteGroups') || ''; + my $ReadGroups = $share->prop('ReadGroups') || ''; + my $WriteUsers = $share->prop('WriteUsers') || ''; + my $ReadUsers = $share->prop('ReadUsers') || ''; + my $manualPerm = $share->prop('ManualPermissions') || 'no'; + if (($manualPerm eq 'yes') || ($manualPerm eq 'enabled')){ - $out .= $fm->localise('MANUAL_PERMS'); + $out .= $self->localise('MANUAL_PERMS'); } my %WriteGroups; my %ReadGroups; + my %WriteUsers; + my %ReadUsers; foreach my $group ( split ( /[,;]/, $WriteGroups ) ) { $WriteGroups{$group} = 1; @@ -370,22 +373,31 @@ foreach my $group ( split ( /[,;]/, $ReadGroups ) ) { $ReadGroups{$group} = 1; } - my @groups = sort { $a->key() cmp $b->key() } $accountdb->groups(); + foreach my $user ( split ( /[,;]/, $WriteUsers ) ) { + $WriteUsers{$user} = 1; + } + foreach my $user ( split ( /[,;]/, $ReadUsers ) ) { + $ReadUsers{$user} = 1; + } + my @groups = sort { $a->key() cmp $b->key() } $a->groups(); + my @users = sort { $a->key() cmp $b->key() } $a->users(); $out .= "" . - $fm->localise('PERMISSIONS') . + $self->localise('PERMISSIONS') . "\n". $q->start_table({-class => "sme-border"})."\n". $q->Tr( - esmith::cgi::genSmallCell($q, $fm->localise('GROUPS'),"header"), - esmith::cgi::genSmallCell($q, $fm->localise('WRITE_PERM'),"header"), - esmith::cgi::genSmallCell($q, $fm->localise('READ_PERM'),"header") + esmith::cgi::genSmallCell($q, $self->localise('GROUPS'),"header"), + esmith::cgi::genSmallCell($q, $self->localise('DESCRIPTION'),"header"), + esmith::cgi::genSmallCell($q, $self->localise('WRITE_PERM'),"header"), + esmith::cgi::genSmallCell($q, $self->localise('READ_PERM'),"header") ); foreach my $group (@groups) { my $write = ""; my $read = ""; my $name = $group->key(); + my $desc = $group->prop('Description'); if ( $WriteGroups{$name} ) { $write = "checked"; } @@ -395,23 +407,56 @@ $out .= $q->Tr( esmith::cgi::genSmallCell($q, $name, "normal"), + esmith::cgi::genSmallCell($q, $desc, "normal"), esmith::cgi::genSmallCell($q,"", "normal"), esmith::cgi::genSmallCell($q,"", "normal") ); } + $out .= $q->Tr( + esmith::cgi::genSmallCell($q, $self->localise('USERS'),"header"), + esmith::cgi::genSmallCell($q, $self->localise('DESCRIPTION'),"header"), + esmith::cgi::genSmallCell($q, $self->localise('WRITE_PERM'),"header"), + esmith::cgi::genSmallCell($q, $self->localise('READ_PERM'),"header") + ); + + foreach my $user (@users) { + my $write = ""; + my $read = ""; + my $name = $user->key(); + my $desc = $user->prop('FirstName') . ' ' . $user->prop('LastName'); + if ( $WriteUsers{$name} ) { + $write = "checked"; + } + if ( $ReadUsers{$name} ) { + $read = "checked"; + } + + $out .= $q->Tr( + esmith::cgi::genSmallCell($q, $name, "normal"), + esmith::cgi::genSmallCell($q, $desc, "normal"), + + esmith::cgi::genSmallCell($q,"", "normal"), + esmith::cgi::genSmallCell($q,"", "normal") + ); + } + $out .= "\n"; return $out; } # Print a section bar sub print_section_bar{ - my ($fm) = @_; + my $self = shift; print " \n \n"; print "
\n"; return undef; @@ -423,8 +468,8 @@ sub smbAccess_list { return { - 'none' => 'NONE', - 'browseable' => 'ENABLED_BROWSEABLE', + 'none' => 'NONE', + 'browseable' => 'ENABLED_BROWSEABLE', 'non-browseable' => 'ENABLED_NON_BROWSEABLE', }; } @@ -453,12 +498,13 @@ sub max_share_name_length { my ($self, $data) = @_; - $configdb->reload(); - my $max = $configdb->get('maxShareNameLength')->value || '12'; + $c->reload(); + my $max = $c->get('maxShareNameLength')->value || '12'; if (length($data) <= $max) { return "OK"; - } else { + } + else { return $self->localise("MAX_SHARE_NAME_LENGTH_ERROR", {acctName => $data, maxShareNameLength => $max, @@ -466,46 +512,20 @@ } } - -# Check the proposed name for clashes with existing pseudonyms or other -# accounts of any type. - -sub conflict_check -{ - my ($self, $name) = @_; - my $rec = $accountdb->get($name); - - my $type; - if (defined $rec){ - my $type = $rec->prop('type'); - if ($type eq "pseudonym"){ - my $acct = $rec->prop("Account"); - my $acct_type = $accountdb->get($acct)->prop('type'); - - return $self->localise('ACCT_CLASHES_WITH_PSEUDONYM', - {acctName => $name, acctType => $acct_type, acct => $acct}); - } - } - elsif (defined getpwnam($name) || defined getgrnam($name)){ - $type = 'system'; - } - else{ - # No account record and no account - return 'OK'; - } - return $self->localise('ACCOUNT_EXISTS', - {acctName => $name, acctType => $type}); -} - # Call the create or modify routine sub handle_shares { - my ($self) = @_; - + my $self = shift; + my $q = $self->{cgi}; + my $action = $q->param("action") || ''; - if ($self->cgi->param("action") eq "create") { + if ($action eq "create") { $self->create_share(); - } else { + } + elsif ($action eq 'permissions'){ + $self->modify_perm(); + } + else { $self->modify_share(); } } @@ -513,12 +533,13 @@ # Print save or add button sub print_save_or_add_button { - my ($self) = @_; + my $self = shift; my $action = $self->cgi->param("action") || ''; if ($action eq "modify") { $self->print_button("SAVE"); - } else { + } + else { $self->print_button("ADD"); } @@ -527,79 +548,54 @@ # Create a new shared folder sub create_share { - my ($self) = @_; - my $name = $self->cgi->param('name'); - my $encryption = $self->cgi->param('encryption') || 'disabled'; - my $password = $self->cgi->param('password'); - my $password2 = $self->cgi->param('password2'); + my $self = shift; + my $q = $self->{cgi}; + my $name = $q->param('name'); + my $encryption = $q->param('encryption') || 'disabled'; + my $password = $q->param('password'); + my $password2 = $q->param('password2'); my $msg = $self->validate_name($name); - unless ($msg eq "OK") - { + + unless ($msg eq "OK") { return $self->error($msg); } $msg = $self->max_share_name_length($name); - unless ($msg eq "OK") - { + + unless ($msg eq "OK") { return $self->error($msg); } $msg = $self->conflict_check($name); - unless ($msg eq "OK") - { + unless ($msg eq "OK") { return $self->error($msg); } $msg = ($encryption eq 'enabled') ? $self->confirm_password($password,$password2) : 'OK'; - unless ($msg eq "OK") - { + unless ($msg eq "OK") { return $self->error($msg); } - my @WriteGroups = $self->cgi->param('write'); - my $WriteGroups = join(",",@WriteGroups); - my @ReadGroups = $self->cgi->param('read'); - my @CleanReadGroups = (); - - # EncFS doesn't expose underlying ACLs - # So, just remove any read only groups - # Read Only is not supported with encryption - if ($encryption ne 'enabled'){ - # Remove from ReadGroups the groups in WriteGroups - # So ACL are consistent - foreach my $read (@ReadGroups){ - my $isInWrite = 0; - foreach (@WriteGroups){ - $isInWrite = 1 if ($_ eq $read); - } - push (@CleanReadGroups, $read) unless ($isInWrite); - } - } - my $ReadGroups = join(",",@CleanReadGroups); - - if (my $acct = $accountdb->new_record($name, { - Name => $self->cgi->param('description'), + if (my $acct = $a->new_record($name, { + Name => $q->param('description'), Encryption => $encryption, - InactivityTimeOut => ($self->cgi->param('inactivity') || ''), - WriteGroups => $WriteGroups, - ReadGroups => $ReadGroups, - RecycleBin => $self->cgi->param('recyclebin'), - RecycleBinRetention => $self->cgi->param('retention'), - smbAccess => $self->cgi->param('smbaccess'), - httpAccess => $self->cgi->param('httpaccess'), - WebDav => $self->cgi->param('webdav'), - Ajaxplorer => ($self->cgi->param('ajaxplorer') || 'disabled'), - RequireSSL => $self->cgi->param('requireSSL'), - Indexes => $self->cgi->param('indexes'), - DynamicContent => $self->cgi->param('dynamic'), + InactivityTimeOut => ($q->param('inactivity') || ''), + RecycleBin => $q->param('recyclebin'), + RecycleBinRetention => $q->param('retention'), + smbAccess => $q->param('smbaccess'), + httpAccess => $q->param('httpaccess'), + WebDav => $q->param('webdav'), + Ajaxplorer => ($q->param('ajaxplorer') || 'disabled'), + RequireSSL => $q->param('requireSSL'), + Indexes => $q->param('indexes'), + DynamicContent => $q->param('dynamic'), type => 'share', - }) ) - { + }) ) { # Untaint $name before use in system() $name =~ /(.+)/; $name = $1; - if ($encryption eq 'enabled'){ + if ($encryption eq 'enabled') { my $source = '/home/e-smith/files/shares/' . $name . '/.store'; my $dest = '/home/e-smith/files/shares/' . $name . '/files'; File::Path::mkpath ($source); @@ -614,10 +610,12 @@ if (system ("/sbin/e-smith/signal-event", "share-create", $name) == 0) { $self->success("SUCCESSFULLY_CREATED_SHARE"); - } else { + } + else { $self->error("ERROR_WHILE_CREATING_SHARE"); } - } else { + } + else { $self->error('CANT_CREATE_SHARE'); } } @@ -625,118 +623,155 @@ # Modify a share. # This sub shares a lot of code with create share # It should be merged - sub modify_share { - my ($self) = @_; - my $name = $self->cgi->param('name'); - if (my $acct = $accountdb->get($name)) { - if ($acct->prop('type') eq 'share') { - my $encryption = $self->cgi->param('encryption'); - my @WriteGroups = $self->cgi->param('write'); - my $WriteGroups = join(",",@WriteGroups); - my @ReadGroups = $self->cgi->param('read'); - my @CleanReadGroups = (); - - # EncFS doesn't expose underlying ACLs - # So, just remove any read only groups - # Read Only is not supported with encryption - if ($encryption ne 'enabled'){ - foreach my $read (@ReadGroups){ - my $isInWrite = 0; - foreach (@WriteGroups){ - $isInWrite = 1 if ($_ eq $read); - } - push (@CleanReadGroups, $read) unless ($isInWrite); - } - } - my $ReadGroups = join(",",@CleanReadGroups); + my $self = shift; + my $q = $self->{cgi}; + my $name = $q->param('name'); + my $acct = $a->get($name); - $acct->merge_props( - Name => $self->cgi->param('description'), - InactivityTimeOut => ($self->cgi->param('inactivity') || ''), - WriteGroups => $WriteGroups, - ReadGroups => $ReadGroups, - RecycleBin => $self->cgi->param('recyclebin'), - RecycleBinRetention => $self->cgi->param('retention'), - smbAccess => $self->cgi->param('smbaccess'), - httpAccess => $self->cgi->param('httpaccess'), - WebDav => $self->cgi->param('webdav'), - Ajaxplorer => ($self->cgi->param('ajaxplorer') || 'disabled'), - RequireSSL => $self->cgi->param('requireSSL'), - Indexes => $self->cgi->param('indexes'), - DynamicContent => $self->cgi->param('dynamic'), - ); + return $self->error('CANT_FIND_SHARE') unless($acct && $acct->prop('type') eq 'share'); - # Untaint $name before use in system() - $name =~ /(.+)/; $name = $1; - if (system ("/sbin/e-smith/signal-event", "share-modify", - $name) == 0) - { - $self->success("SUCCESSFULLY_MODIFIED_SHARE"); - } else { - $self->error("ERROR_WHILE_MODIFYING_SHARE"); - } - } else { - $self->error('CANT_FIND_SHARE'); - } - } else { - $self->error('CANT_FIND_SHARE'); + $acct->merge_props( + Name => $q->param('description'), + InactivityTimeOut => ($q->param('inactivity') || ''), + RecycleBin => $q->param('recyclebin'), + RecycleBinRetention => $q->param('retention'), + smbAccess => $q->param('smbaccess'), + httpAccess => $q->param('httpaccess'), + WebDav => $q->param('webdav'), + Ajaxplorer => ($q->param('ajaxplorer') || 'disabled'), + RequireSSL => $q->param('requireSSL'), + Indexes => $q->param('indexes'), + DynamicContent => $q->param('dynamic'), + ); + + # Untaint $name before use in system() + $name =~ /(.+)/; $name = $1; + if (system ("/sbin/e-smith/signal-event", "share-modify", $name) == 0) { + $self->success("SUCCESSFULLY_MODIFIED_SHARE"); } + else { + $self->error("ERROR_WHILE_MODIFYING_SHARE"); + } + return undef; } -# Remove a share +sub modify_perm { + my $self = shift; + my $q = $self->{cgi}; + my $name = $q->param('name'); + my $acct = $a->get($name); -sub remove_share { - my ($self) = @_; - my $name = $self->cgi->param('name'); - unless ($self->cgi->param('cancel')){ - if (my $acct = $accountdb->get($name)) { - if ($acct->prop('type') eq 'share') { - # Untaint $name before use in system() - $name =~ /(.+)/; $name = $1; - my $encryption = $acct->prop('Encryption') || 'disabled'; - my $mountstatus = `/bin/mount | grep /home/e-smith/files/shares/$name/ | grep -c fuse`; - chomp($mountstatus); - if (($encryption eq 'enabled') && ($mountstatus eq '1')){ - $self->error("ERROR_ENCRYPTED_ENABLED"); - return undef; - } - - $acct->set_prop('type', 'share-deleted'); - - if (system ("/sbin/e-smith/signal-event", "share-delete", $name) == 0) { - $self->success("SUCCESSFULLY_DELETED_SHARE"); - $acct->delete(); - } - else { - $self->error("ERROR_WHILE_DELETING_SHARE"); - } - } - else { - $self->error('CANT_FIND_SHARE'); - } + return $self->error('CANT_FIND_SHARE') unless($acct && $acct->prop('type') eq 'share'); + + my $encryption = $acct->prop('Encryption') || 'disabled'; + + my $WriteGroups = join(",", $q->param('writegroup')); + my $WriteUsers = join(",", $q->param('writeuser')); + my @CleanReadGroups = (); + my @CleanReadUsers = (); + + # EncFS doesn't expose underlying ACLs + # So, just remove any read only groups + # Read Only is not supported with encryption + if ($encryption ne 'enabled'){ + # No need to have read access if write is already granted + foreach my $group ($q->param('readgroup')){ + push (@CleanReadGroups, $group) unless (grep { $_ eq $group } $q->param('writegroup')); } - else { - $self->error('CANT_FIND_SHARE'); + foreach my $user ($q->param('readuser')){ + push (@CleanReadUsers, $user) unless (grep { $_ eq $user } $q->param('writeuser')); } } - else{ - $self->error('CANCELED','First'); + my $ReadGroups = join(",",@CleanReadGroups); + my $ReadUsers = join(",",@CleanReadUsers); + + $acct->merge_props( + WriteGroups => $WriteGroups, + ReadGroups => $ReadGroups, + WriteUsers => $WriteUsers, + ReadUsers => $ReadUsers, + ); + + # Untaint $name before use in system() + $name =~ /(.+)/; $name = $1; + if (system ("/sbin/e-smith/signal-event", "share-modify", $name) == 0) { + $self->success("SUCCESSFULLY_MODIFIED_SHARE"); + } + else { + $self->error("ERROR_WHILE_MODIFYING_SHARE"); } return undef; } +# Remove a share +sub remove_share { + my $self = shift; + my $q = $self->{cgi}; + my $name = $q->param('name'); + my $acct = $a->get($name); + return $self->error('CANCELED','First') if ($q->param('cancel')); + return $self->error('CANT_FIND_SHARE') unless ($acct && $acct->prop('type') eq 'share'); + + # Untaint $name before use in system() + $name =~ /(.+)/; $name = $1; + my $encryption = $acct->prop('Encryption') || 'disabled'; + my $mountstatus = `/bin/mount | grep /home/e-smith/files/shares/$name/ | grep -c fuse`; + chomp($mountstatus); + + if (($encryption eq 'enabled') && ($mountstatus eq '1')){ + $self->error("ERROR_ENCRYPTED_ENABLED"); + return undef; + } + + $acct->set_prop('type', 'share-deleted'); + + if (system ("/sbin/e-smith/signal-event", "share-delete", $name) == 0) { + $self->success("SUCCESSFULLY_DELETED_SHARE"); + $acct->delete(); + } + else { + $self->error("ERROR_WHILE_DELETING_SHARE"); + } + return undef; +} + +# Check the proposed name for clashes with existing pseudonyms or other +# accounts of any type. + +sub conflict_check { + my ($self, $name) = @_; + my $rec = $a->get($name); + + my $type; + if (defined $rec){ + my $type = $rec->prop('type'); + if ($type eq "pseudonym"){ + my $acct = $rec->prop("Account"); + my $acct_type = $a->get($acct)->prop('type'); + + return $self->localise('ACCT_CLASHES_WITH_PSEUDONYM', + {acctName => $name, acctType => $acct_type, acct => $acct}); + } + } + elsif (defined getpwnam($name) || defined getgrnam($name)){ + $type = 'system'; + } + else{ + # No account record and no account + return 'OK'; + } + return $self->localise('ACCOUNT_EXISTS', + {acctName => $name, acctType => $type}); +} # Checks that the name supplied does not contain any unacceptable chars. # Returns OK on success or a localised error message otherwise. - -sub validate_name -{ +sub validate_name { my ($self, $acctName) = @_; - unless ($acctName =~ /^([a-z][\_\.\-a-z0-9]*)$/) - { + unless ($acctName =~ /^([a-z][\_\.\-a-z0-9]*)$/){ return $self->localise('ACCT_NAME_HAS_INVALID_CHARS', {acctName => $acctName}); } @@ -744,13 +779,10 @@ } # Check if inactivity is a number - -sub validate_inactivity -{ +sub validate_inactivity { my ($self, $inac) = @_; - unless ($inac =~ /^\d+$/) - { + unless ($inac =~ /^\d+$/){ return $self->localise('INVALID_INACTIVITY', {inactivity => $inac}); } @@ -759,9 +791,7 @@ # Check if both passwords match # and are more than 8 chars - -sub confirm_password -{ +sub confirm_password { my ($self, $pass1, $pass2) = @_;