Update - permissions and lex files - still WIP

This commit is contained in:
Brian Read 2025-05-23 08:27:55 +01:00
parent e57170ba11
commit 47852015f0
4 changed files with 171 additions and 467 deletions

View File

@ -199,50 +199,17 @@ my $ddb;
}
sub get_data_for_panel_PERMISSIONS {
# Return a hash with the fields required which will be loaded into the shared data
# Return a hash with the fields required which will be loaded into the shared data
my $c = shift;
my $name = $c->param('Selected');
$adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
my $rec = $adb->get($name) || die("Share $name is not in DB ");
my %ret = (
'Data1'=>'Data for PERMISSIONS', #Example
# fields from Inputs in PERMISSIONS $fields['PERMISSIONS']
'writegroup'=>'writegroup contents',
'readgroup'=>'readgroup contents',
'writegroup'=>'writegroup contents',
'readgroup'=>'readgroup contents',
'writegroup'=>'writegroup contents',
'readgroup'=>'readgroup contents',
'writegroup'=>'writegroup contents',
'readgroup'=>'readgroup contents',
'writegroup'=>'writegroup contents',
'readgroup'=>'readgroup contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'writeuser'=>'writeuser contents',
'readuser'=>'readuser contents',
'Data1'=>'Data for MODIFY', #Example
# fields from Inputs in MODIFY $fields['MODIFY']
'name' => $name,
'description'=>$rec->prop('Name'),
);
return %ret;
}
@ -326,10 +293,10 @@ sub get_Table1 {
# Define a constant hash for field name mapping
use constant Table2_FIELD_MAPPING => (
'Table2-Groups' => 'Source-for-Table2-Groups',
'Table2-Description' => 'Source-for-Table2-Description',
'Table2-Read / Write' => 'Source-for-Table2-Read / Write',
'Table2-Read Only' => 'Source-for-Table2-Read Only'
'Table2_Groups' => 'Username',
'Table2_Description' => 'Description',
'Table2_Read / Write' => 'WritePerms',
'Table2_Read Only' => 'ReadPerms'
#'target_field2' => 'source_field2',
# Add more mappings as needed
);
@ -337,8 +304,10 @@ sub get_Table1 {
sub actual_Table2 {
my $c = shift;
my @ret = ();
# Actual code for extracting Table2
return @ret;
# Actual code for extracting Table2, Table3
my $groups_ref = $c->acl_list('groups');
my @groups = @$groups_ref;
return @groups;
}
sub get_Table2 {
@ -364,6 +333,48 @@ sub get_Table2 {
return \@transformed_records;
}
# Define a constant hash for field name mapping
use constant Table3_FIELD_MAPPING => (
'Table3_Users' => 'Username',
'Table3_Description' => 'Description',
'Table3_Read / Write' => 'WritePerms',
'Table3_Read Only' => 'ReadPerms'
#'target_field3' => 'source_field3',
# Add more mappings as needed
);
sub actual_Table3 {
my $c = shift;
my @ret = ();
# Actual code for extracting Table3, Table3 - this is called twice - by table 2 and table 3 processiong (!)
my $users_ref = $c->acl_list('users');
my @users = @$users_ref;
return @users;
}
sub get_Table3 {
# Return an array of hashes of the contents for each row and column for Table3
my $c = shift;
my @source_records = $c->actual_Table3();
my @transformed_records;
my %Field_Mapping = Table3_FIELD_MAPPING();
# Iterate over each record in the source array
for my $source_record (@source_records) {
my %transformed_record;
# Iterate over each key-value pair in the $Field_Mapping constant
while (my ($target, $source) = each %Field_Mapping) {
# Check if the source field exists in the source record
if (exists $source_record->{$source}) {
# Assign the source field value to the target field in the transformed record
$transformed_record{$target} = $source_record->{$source};
}
}
# Add transformed record to the array if it's not empty
push @transformed_records, \%transformed_record if %transformed_record;
}
return \@transformed_records;
}
# Return hash with values from row in which link clicked on table
@ -541,7 +552,7 @@ sub get_Table2 {
my $db = $cdb; #maybe one of the others
my $dbkey = 'ChangeThis';
# To make it write to DB as comment, delete this (regex) string in each if statement "TRUE\) \#copy or perform with value: .* e.g."
$ret = $c->remove_share();
if ($ret eq "") {$ret = 'ok';}
return $ret;
}
@ -556,116 +567,9 @@ sub create_link{
# Create a new shared folder
#sub create_share {
#my $c = shift;
#my $name = $c->param('name');
#my $encryption = $c->param('encryption') || 'disabled';
#my $password = $c->param('password');
#my $password2 = $c->param('password2');
#my $msg = $c->validate_name($name);
#unless ($msg eq "OK") {
#return $c->error($msg);
#}
#$msg = $c->max_share_name_length($name);
#unless ($msg eq "OK") {
#return $c->error($msg);
#}
#$msg = $c->conflict_check($name);
#unless ($msg eq "OK") {
#return $c->error($msg);
#}
#$msg = ($encryption eq 'enabled') ? $c->confirm_password($password,$password2) : 'OK';
#unless ($msg eq "OK") {
#return $c->error($msg);
#}
#if (my $acct = $a->new_record($name, {
#Name => $c->param('description'),
#Encryption => $encryption,
#InactivityTimeOut => ($c->param('inactivity') || ''),
#RecycleBin => $c->param('recyclebin'),
#RecycleBinRetention => $c->param('retention'),
#smbAccess => $c->param('smbaccess'),
#httpAccess => $c->param('httpaccess'),
#WebDav => $c->param('webdav'),
#Pydio => ($c->param('pydio') || 'disabled'),
#RequireSSL => $c->param('requireSSL'),
#Indexes => $c->param('indexes'),
#DynamicContent => $c->param('dynamic'),
#type => 'share',
#}) ) {
## Untaint $name before use in system()
#$name =~ /(.+)/; $name = $1;
#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);
#mkdir $dest;
#open(DIR, "| /usr/bin/encfs -S --public -o nonempty,umask=000 $source $dest > /dev/null 2>&1");
#print DIR "\n$password";
#close DIR;
#$c->error("ERROR_WITH_ENCRYPTION") unless(
#system("/bin/fusermount -uz $dest") == 0
#);
#}
#if (system ("/sbin/e-smith/signal-event", "share-create", $name) == 0) {
#$c->success("SUCCESSFULLY_CREATED_SHARE", "Permissions");
#}
#else {
#$c->error("ERROR_WHILE_CREATING_SHARE");
#}
#}
#else {
#$c->error('CANT_CREATE_SHARE');
#}
#}
## Modify a share.
## This sub shares a lot of code with create share
## It should be merged
#sub modify_share {
#my $c = shift;
#my $name = $c->param('name');
#my $acct = $a->get($name);
#return $c->error('CANT_FIND_SHARE') unless($acct && $acct->prop('type') eq 'share');
#$acct->merge_props(
#Name => $c->param('description'),
#InactivityTimeOut => ($c->param('inactivity') || ''),
#RecycleBin => $c->param('recyclebin'),
#RecycleBinRetention => $c->param('retention'),
#smbAccess => $c->param('smbaccess'),
#httpAccess => $c->param('httpaccess'),
#WebDav => $c->param('webdav'),
#Pydio => ($c->param('pydio') || 'disabled'),
#RequireSSL => $c->param('requireSSL'),
#Indexes => $c->param('indexes'),
#DynamicContent => $c->param('dynamic'),
#);
## Untaint $name before use in system()
#$name =~ /(.+)/; $name = $1;
#if (system ("/sbin/e-smith/signal-event", "share-modify", $name) == 0) {
#$c->success("SUCCESSFULLY_MODIFIED_SHARE");
#}
#else {
#$c->error("ERROR_WHILE_MODIFYING_SHARE");
#}
#return undef;
#}
sub save_share {
#
# Merged the two subs
# Merged the two subs from SM1
#
my $c = shift;
my $name = $c->param('name');
@ -819,7 +723,7 @@ sub modify_perm {
sub remove_share {
my $c = shift;
$adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
my $name = $c->param('name');
my $name = $c->param('Selected');
my $acct = $adb->get($name);
return $c->l('sf_CANCELED','First') if ($c->param('cancel'));
return $c->l('sf_CANT_FIND_SHARE') unless ($acct && $acct->prop('type') eq 'share');
@ -938,5 +842,68 @@ sub max_share_name_length {
}
}
#Get arrays of users and gtroups who have read only or read/write access
sub acl_list {
my ($c, $which) = @_;
my $sharename = $c->param('Selected');
my $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db");
my $share = $adb->get($sharename);
return $c->l('sf_SHARE_NOT_FOUND') unless ($share);
if ($which eq 'groups') {
my $WriteGroups = $share->prop('WriteGroups') || '';
my $ReadGroups = $share->prop('ReadGroups') || '';
my (%WriteGroups, %ReadGroups);
$WriteGroups{$_} = 1 for grep { $_ } split /[,;]/, $WriteGroups;
$ReadGroups{$_} = 1 for grep { $_ } split /[,;]/, $ReadGroups;
my @groups;
# The "shared" pseudo-group (Everyone)
push @groups, {
Username => 'shared',
Description => 'Everyone',
WritePerms => $WriteGroups{'shared'} ? 1 : 0,
ReadPerms => $ReadGroups{'shared'} ? 1 : 0
};
foreach my $group (sort { $a->key cmp $b->key } $adb->groups) {
my $name = $group->key;
my $desc = $group->prop('Description') || '';
push @groups, {
Username => $name,
Description => $desc,
WritePerms => $WriteGroups{$name} ? 1 : 0,
ReadPerms => $ReadGroups{$name} ? 1 : 0
};
}
return \@groups;
}
elsif ($which eq 'users') {
my $WriteUsers = $share->prop('WriteUsers') || '';
my $ReadUsers = $share->prop('ReadUsers') || '';
my (%WriteUsers, %ReadUsers);
$WriteUsers{$_} = 1 for grep { $_ } split /[,;]/, $WriteUsers;
$ReadUsers{$_} = 1 for grep { $_ } split /[,;]/, $ReadUsers;
my @users;
foreach my $user (sort { $a->key cmp $b->key } $adb->users) {
my $name = $user->key;
my $desc = join(' ', grep { $_ } ($user->prop('FirstName'), $user->prop('LastName')));
push @users, {
Username => $name,
Description => $desc,
WritePerms => $WriteUsers{$name} ? 1 : 0,
ReadPerms => $ReadUsers{$name} ? 1 : 0
};
}
return \@users;
}
else {
die "Invalid parameter to acl_list: must be 'groups' or 'users'";
}
}
1;

View File

@ -385,6 +385,7 @@ sub do_display {
# and table control fields
$c->stash(Table1=>$c->get_Table1());
$c->stash(Table2=>$c->get_Table2());
$c->stash(Table3=>$c->get_Table3());
# Data for panel

View File

@ -3,6 +3,10 @@
#
'sf_readgroup' => 'regroup',
'sf_Description' => 'Description',
'sf_Users' => 'Users',
'sf_name' => 'Name of Shared Area',
'sf_Permisssions' => 'Permissions',
'sf_Modify' => 'Modify',
'sf_dynamic' => 'Dynamic',
'sf_description' => 'Description',
'sf_The_following_settings_control_the' => 'The following settings control the access of this shared folder using the HTTP/HTTPS protocol',
@ -43,4 +47,4 @@
'sf_Read_/_Write' => 'Read / Write',
'sf_Create_or_modify_a_shared' => 'Create or modify a shared folder',
'sf_The_following_settings_control_the' => 'The following settings control the access of this shared folder from the local network Using the SMB/CIFS protocol',
'sf_recyclebin' => 'Recyclebin',
'sf_recyclebin' => 'Recyclebin',

View File

@ -28,6 +28,21 @@
<p class='paragraph para10'>
%=l('sf_You_can_use_this_matrix')
</p>
<p><span class=label>
%=l('sf_name')
</span><span class=data>
% param 'name' => $sf_data->{name} unless param 'name';
%= text_field 'name', size => '50', class => 'textinput name' , pattern=>'.*' , placeholder=>'name', title =>'Pattern regex mismatch', id => 'name_text', readonly => 1
<br></span></p>
<p><span class=label>
%=l('sf_description')
</span><span class=data>
% param 'description' => $sf_data->{description} unless param 'description';
%= text_field 'description', size => '50', class => 'textinput description' , pattern=>'.*' , placeholder=>'description', title =>'Pattern regex mismatch', id => 'description_text', readonly => 1
<br></span></p>
<br /><table class="sme-border TableSort sme-table tabl2 ">
<thead class='tabl2'>
@ -42,319 +57,36 @@
% my $control_data = $c->stash('Table2');
% foreach my $row (@$control_data) {
<tr class='table-row'>
<td class='sme-border table-col table-col-Table2-Groups'><%=$c->render_to_string(inline=>$row->{'Table2-Groups'})%></td>
<td class='sme-border table-col table-col-Table2-Description'><%=$c->render_to_string(inline=>$row->{'Table2-Description'})%></td>
<td class='sme-border table-col table-col-Table2-Read / Write'><%=$c->render_to_string(inline=>$row->{'Table2-Read / Write'})%></td>
<td class='sme-border table-col table-col-Table2-Read Only'><%=$c->render_to_string(inline=>$row->{'Table2-Read Only'})%></td>
<td class='sme-border table-col table-col-Table2_Groups'><%=$c->render_to_string(inline=>$row->{'Table2_Groups'})%></td>
<td class='sme-border table-col table-col-Table2_Description'><%=$c->render_to_string(inline=>$row->{'Table2_Description'})%></td>
<td class='sme-border table-col table-col-Table3_Read / Write'><%=check_box 'writegroup',($row->{'Table2_Read / Write'} ? ('checked' => 1) : ())%></td>
<td class='sme-border table-col table-col-Table3_Read Only'><%=check_box 'readgroup',($row->{'Table2_Read Only'} ? ('checked' => 1) : ())%></td>
</tr>
%}
</tbody>
</table>
<br /><table class="sme-border TableSort sme-table tabl3 ">
<thead class='tabl2'>
<tr table-head-row>
<th class='sme-border table-head-col table-head-col-Groups '><%=l('sf_Users')%></th>
<th class='sme-border table-head-col table-head-col-Description '><%=l('sf_Description')%></th>
<th class='sme-border table-head-col table-head-col-Read / Write '><%=l('sf_Read_/_Write')%></th>
<th class='sme-border table-head-col table-head-col-Read Only '><%=l('sf_Read_Only')%></th>
</tr>
</thead>
<tbody class='tabl2'>
% my $control_data = $c->stash('Table3');
% foreach my $row (@$control_data) {
<tr class='table-row'>
<td class='sme-border table-col table-col-Table3_Groups'><%=$c->render_to_string(inline=>$row->{'Table3_Users'})%></td>
<td class='sme-border table-col table-col-Table3_Description'><%=$c->render_to_string(inline=>$row->{'Table3_Description'})%></td>
<td class='sme-border table-col table-col-Table3_Read / Write'><%=check_box 'writeuser',($row->{'Table3_Read / Write'} ? ('checked' => 1) : ())%></td>
<td class='sme-border table-col table-col-Table3_Read Only'><%=check_box 'readuser',($row->{'Table3_Read Only'} ? ('checked' => 1) : ())%></td>
</tr>
%}
</tbody>
</table>
<p><span class='label'>
%=l('sf_writegroup')
</span><span class=data>
% param 'writegroup' => $sf_data->{writegroup} unless param 'writegroup';
%=checkbox_field 'writegroup', class => 'chec110'
</span></p>
<p><span class='label'>
%=l('sf_readgroup')
</span><span class=data>
% param 'readgroup' => $sf_data->{readgroup} unless param 'readgroup';
%=checkbox_field 'readgroup', class => 'chec111'
</span></p>
<p><span class='label'>
%=l('sf_writegroup')
</span><span class=data>
% param 'writegroup' => $sf_data->{writegroup} unless param 'writegroup';
%=checkbox_field 'writegroup', class => 'chec112'
</span></p>
<p><span class='label'>
%=l('sf_readgroup')
</span><span class=data>
% param 'readgroup' => $sf_data->{readgroup} unless param 'readgroup';
%=checkbox_field 'readgroup', class => 'chec113'
</span></p>
<p><span class='label'>
%=l('sf_writegroup')
</span><span class=data>
% param 'writegroup' => $sf_data->{writegroup} unless param 'writegroup';
%=checkbox_field 'writegroup', class => 'chec114'
</span></p>
<p><span class='label'>
%=l('sf_readgroup')
</span><span class=data>
% param 'readgroup' => $sf_data->{readgroup} unless param 'readgroup';
%=checkbox_field 'readgroup', class => 'chec115'
</span></p>
<p><span class='label'>
%=l('sf_writegroup')
</span><span class=data>
% param 'writegroup' => $sf_data->{writegroup} unless param 'writegroup';
%=checkbox_field 'writegroup', class => 'chec116'
</span></p>
<p><span class='label'>
%=l('sf_readgroup')
</span><span class=data>
% param 'readgroup' => $sf_data->{readgroup} unless param 'readgroup';
%=checkbox_field 'readgroup', class => 'chec117'
</span></p>
<p><span class='label'>
%=l('sf_writegroup')
</span><span class=data>
% param 'writegroup' => $sf_data->{writegroup} unless param 'writegroup';
%=checkbox_field 'writegroup', class => 'chec118'
</span></p>
<p><span class='label'>
%=l('sf_readgroup')
</span><span class=data>
% param 'readgroup' => $sf_data->{readgroup} unless param 'readgroup';
%=checkbox_field 'readgroup', class => 'chec119'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec120'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec121'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec122'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec123'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec124'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec125'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec126'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec127'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec128'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec129'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec130'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec131'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec132'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec133'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec134'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec135'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec136'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec137'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec138'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec139'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec140'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec141'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec142'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec143'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec144'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec145'
</span></p>
<p><span class='label'>
%=l('sf_writeuser')
</span><span class=data>
% param 'writeuser' => $sf_data->{writeuser} unless param 'writeuser';
%=checkbox_field 'writeuser', class => 'chec146'
</span></p>
<p><span class='label'>
%=l('sf_readuser')
</span><span class=data>
% param 'readuser' => $sf_data->{readuser} unless param 'readuser';
%=checkbox_field 'readuser', class => 'chec147'
</span></p>
<span class='data'>
%= submit_button l('sf_Save'), class => 'action subm148'