summaryrefslogtreecommitdiffstats
path: root/extensions/TellUsMore/lib/Process.pm
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/TellUsMore/lib/Process.pm')
-rw-r--r--extensions/TellUsMore/lib/Process.pm263
1 files changed, 263 insertions, 0 deletions
diff --git a/extensions/TellUsMore/lib/Process.pm b/extensions/TellUsMore/lib/Process.pm
new file mode 100644
index 000000000..a73866468
--- /dev/null
+++ b/extensions/TellUsMore/lib/Process.pm
@@ -0,0 +1,263 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Extension::TellUsMore::Process;
+
+use strict;
+use warnings;
+
+use Bugzilla::Bug;
+use Bugzilla::Component;
+use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Hook;
+use Bugzilla::Product;
+use Bugzilla::User;
+use Bugzilla::Util;
+use Bugzilla::Version;
+
+use Bugzilla::Extension::TellUsMore::Constants;
+
+use Data::Dumper;
+use File::Basename;
+use MIME::Base64;
+use Safe;
+
+sub new {
+ my $invocant = shift;
+ my $class = ref($invocant) || $invocant;
+ my $object = {};
+ bless($object, $class);
+ return $object;
+}
+
+sub execute {
+ my ($self, $token) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my ($bug, $user, $is_new_user);
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+ eval {
+ $self->_delete_stale_issues();
+ my ($mail, $params) = $self->_deserialise_token($token);
+
+ $dbh->bz_start_transaction();
+
+ $self->_fix_invalid_params($params);
+
+ ($user, $is_new_user) = $self->_get_user($mail, $params);
+
+ $bug = $self->_create_bug($user, $params);
+ $self->_post_bug_hook($bug);
+
+ $self->_delete_token($token);
+ $dbh->bz_commit_transaction();
+
+ $self->_send_mail($bug, $user);
+ };
+ $self->{error} = $@;
+ Bugzilla->error_mode(ERROR_MODE_WEBPAGE);
+ return $self->{error} ? undef : ($bug, $is_new_user);
+}
+
+sub error {
+ my ($self) = @_;
+ return $self->{error};
+}
+
+sub _delete_stale_issues {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ # delete issues older than TOKEN_EXPIRY_DAYS
+
+ $dbh->do("
+ DELETE FROM tell_us_more
+ WHERE creation_ts < NOW() - " .
+ $dbh->sql_interval(TOKEN_EXPIRY_DAYS, 'DAY')
+ );
+}
+
+sub _deserialise_token {
+ my ($self, $token) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ # validate token
+
+ trick_taint($token);
+ my ($mail, $params) = $dbh->selectrow_array(
+ "SELECT mail,content FROM tell_us_more WHERE token=?",
+ undef, $token
+ );
+ ThrowUserError('token_does_not_exist') unless $mail;
+
+ # deserialise, return ($mail, $params)
+
+ my $compartment = Safe->new();
+ $compartment->reval($params)
+ || ThrowUserError('token_does_not_exist');
+ $params = ${$compartment->varglob('VAR1')};
+
+ return ($mail, $params);
+}
+
+sub _fix_invalid_params {
+ my ($self, $params) = @_;
+
+ # silently adjust any params which are no longer valid
+ # so we don't lose the submission
+
+ my $product = Bugzilla::Product->new({ name => TARGET_PRODUCT })
+ || ThrowUserError('invalid_product_name', { product => TARGET_PRODUCT });
+
+ # component --> general
+
+ my $component = Bugzilla::Component->new({ product => $product, name => $params->{component} })
+ || Bugzilla::Component->new({ product => $product, name => DEFAULT_COMPONENT })
+ || ThrowUserError('tum_invalid_component', { product => TARGET_PRODUCT, name => DEFAULT_COMPONENT });
+ $params->{component} = $component->name;
+
+ # version --> unspecified
+
+ my $version = Bugzilla::Version->new({ product => $product, name => $params->{version} })
+ || Bugzilla::Version->new({ product => $product, name => DEFAULT_VERSION });
+ $params->{version} = $version->name;
+}
+
+sub _get_user {
+ my ($self, $mail, $params) = @_;
+
+ # return existing bmo user
+
+ my $user = Bugzilla::User->new({ name => $mail });
+ return ($user, 0) if $user;
+
+ # or create new user
+
+ $user = Bugzilla::User->create({
+ login_name => $mail,
+ cryptpassword => '*',
+ realname => $params->{creator_name},
+ });
+ return ($user, 1);
+}
+
+sub _create_bug {
+ my ($self, $user, $params) = @_;
+ my $template = Bugzilla->template;
+ my $vars = {};
+
+ # login as the user
+
+ Bugzilla->set_user($user);
+
+ # create the bug
+
+ my $create = {
+ product => $params->{product},
+ component => $params->{component},
+ short_desc => $params->{summary},
+ comment => $params->{description},
+ version => $params->{version},
+ rep_platform => $params->{rep_platform},
+ op_sys => $params->{op_sys},
+ bug_severity => $params->{bug_severity},
+ priority => $params->{priority},
+ bug_file_loc => $params->{bug_file_loc},
+ };
+ if ($params->{group}) {
+ $create->{groups} = [ $params->{group} ];
+ };
+
+ my $bug = Bugzilla::Bug->create($create);
+
+ # add attachments
+
+ foreach my $attachment (@{$params->{attachments}}) {
+ $self->_add_attachment($bug, $attachment);
+ }
+ if (scalar @{$params->{attachments}}) {
+ $bug->update();
+ }
+
+ return $bug;
+}
+
+sub _add_attachment {
+ my ($self, $bug, $params) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ # init
+
+ my $timestamp = $dbh->selectrow_array('SELECT creation_ts FROM bugs WHERE bug_id=?', undef, $bug->bug_id);
+ my $data = decode_base64($params->{content});
+
+ my $description;
+ if ($params->{description}) {
+ $description = $params->{description};
+ } else {
+ $description = $params->{filename};
+ $description =~ s/\\/\//g;
+ $description = basename($description);
+ }
+
+ # trigger content-type auto detection
+
+ Bugzilla->input_params->{'contenttypemethod'} = 'autodetect';
+
+ # add attachment
+
+ my $attachment = Bugzilla::Attachment->create({
+ bug => $bug,
+ creation_ts => $timestamp,
+ data => $data,
+ description => $description,
+ filename => $params->{filename},
+ mimetype => $params->{content_type},
+ });
+
+ # add comment
+
+ $bug->add_comment('', {
+ isprivate => 0,
+ type => CMT_ATTACHMENT_CREATED,
+ extra_data => $attachment->id,
+ });
+}
+
+sub _post_bug_hook {
+ my ($self, $bug) = @_;
+
+ # trigger post_bug_after_creation hook
+
+ my $vars = {
+ id => $bug->bug_id,
+ bug => $bug,
+ };
+ Bugzilla::Hook::process('post_bug_after_creation', { vars => $vars });
+}
+
+sub _send_mail {
+ my ($self, $bug, $user) = @_;
+
+ # send new-bug email
+
+ Bugzilla::BugMail::Send($bug->bug_id, { changer => $user });
+}
+
+sub _delete_token {
+ my ($self, $token) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ # delete token
+
+ trick_taint($token);
+ $dbh->do('DELETE FROM tell_us_more WHERE token=?', undef, $token);
+}
+
+1;
+