Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions bin/bulk_layout_permissions.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/perl

use FindBin;
use lib "$FindBin::Bin/../lib";

use Dancer2;
use Dancer2::Plugin::DBIC;
use Getopt::Long;
use Text::CSV;
use feature 'say';

my ($action);

GetOptions(
'action=s' => \$action
) or exit;

$action or die "ERROR: Please state if you want to import/export group permissions with --action";

if ($action eq 'import') {
Import_permissions();
}
elsif ($action eq 'export') {
Export_permissions();
}
else {
die "ERROR: You must either import or export within --action";
}

sub Import_permissions {
say "Enter the file you want to import from:";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe set up the option to allow for logging here as well? Output information to a log file to show what's been done? Otherwise there's no audit trail and if something goes wrong we won't easily know what's borken.

my $file = <STDIN>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this not be a script argument?

chomp($file);

-f $file or die "ERROR: File '$file' does not exist";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use error rather than die here (remember to import logreport)


$file or die "Usage: $0 filename";
my $csv = Text::CSV->new({ binary => 1 })
or die "Cannot use CSV: ".Text::CSV->error_diag ();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use error rather than die here

open my $fh, "<:encoding(utf8)", $file or die "$file: $!";
my $guard = schema->txn_scope_guard;

while (my $row = $csv->getline($fh)) {
my ($layout_id, $group_id, $permission) = @$row;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assumes CSV is set up correctly - you can import the rows as a hash containing {column1 => value, column2 => value ... } where column1, column2, etc are the header of the file which would mitigate if the file data is in the incorrect order (currently, it will assume it's correct and at worst, import the data incorrectly, at best, die)

my $RowCount = $csv->record_number;

unless (defined $layout_id && $layout_id =~ /^\d+$/) {
die "ERROR: Invalid Layout ID '$layout_id' on row $RowCount.\n";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use error here - also can be (defined $layout_id && $layout_id =~ /^\d+$/) || error ... - the second point is more of a symantic difference and down to code-style and preference.

}
unless (defined $group_id && $group_id =~ /^\d+$/) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

die "ERROR: Invalid Group ID '$group_id' on row $RowCount.\n";
}
unless (defined $permission && $permission =~ /^(?:read|write_new|write_existing|write_existing_no_approval|write_new_no_approval)$/) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above

die "ERROR: Invalid Permission '$permission' on row $RowCount. Value must be read, write_new, write_existing, or write_existing_no_approval.\n";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would write_new_no_approval be included too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That permission is a left over from GADS 1.0 and is no longer used

}

rset('Layout')->find($layout_id) or die "ERROR: Layout ID '$layout_id' does not exist\n";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be error, not die

rset('Group')->find($group_id) or die "ERROR: Group ID '$group_id' does not exist\n";

my $existing = rset('LayoutGroup')->find({
layout_id => $layout_id,
group_id => $group_id,
permission => $permission
});

if ($existing) {
say "Skipping permission '$permission' for group '$group_id' on layout '$layout_id' because this permission already exists";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to say anything here? Could just put next if $existing

next;
}

rset('LayoutGroup')->create({
layout_id => $layout_id,
group_id => $group_id,
permission => $permission,
});
say "Will add permission '$permission' to group '$group_id' for layout '$layout_id'";
}
$guard->commit;
say "Import complete";
}

sub Export_permissions {
my $export_file = './Group_permission_export.csv';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be beneficial for the filename to be unique? E.g. it could have the group IDs or the current datetime appended.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parameter? use --file or something and only set this if it's not set as a parameter (i.e. $export_file //= './Group_permission_export.csv'

! -f $export_file or die "ERROR: $export_file already exists, unable to overwrite file!";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be error rather than die

say "Enter the group IDs you're looking to export (e.g. 1,2,3): ";
my $input = <STDIN>;
chomp($input);

if (!$input || $input !~ /^\s*\d+(?:\s*,\s*\d+)*\s*$/) {
die "Error: You need to enter a number or a comma-separated list of numbers.\n";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be error rather than die

}

my @groups = split(/\s*,\s*/, $input);

my $csv = Text::CSV->new({ binary => 1, auto_diag => 1 });
open my $fh, ">:encoding(utf8)", $export_file or die "$export_file: $!";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fault rather than die - this will also remove the need for $!


my @layout_groups = rset('LayoutGroup')->search(
{
'me.group_id' => { '-in' => \@groups },
},
{
prefetch => [ 'layout' ],
}
)->all;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worth moving the $guard->commit; to below this search, just in case any exceptions are thrown?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No - we want the guard to fall out of scope and therefore roll back any and all changes, rather than doing a partial commit if only some changes are made before the error.


$csv->say($fh, [ 'Instance ID','Layout Name','Layout ID', 'Group ID','Permission' ]);

foreach my $lg (@layout_groups) {
my $layout = $lg->layout;
my $instance_id = $layout->instance_id;
my $layout_name = $layout->name ;
my $group_id = $lg->group_id;
my $layout_id = $lg->layout_id;
my $permission = $lg->permission;

$csv->say($fh, [ $instance_id, $layout_name, $layout_id, $group_id, $permission ]);
}
close($fh);
say "Successfully exported permissions to '$export_file'";
}
Loading