summaryrefslogtreecommitdiffstats
path: root/extensions/BugmailFilter/lib
diff options
context:
space:
mode:
authorByron Jones <glob@mozilla.com>2014-07-08 10:40:14 +0200
committerByron Jones <glob@mozilla.com>2014-07-08 10:40:14 +0200
commit2f3b5dd7df3e131af6aef3cd5ccf7e8523c1780e (patch)
treee71ea56398621e038df3c27cc5b87accf7a04968 /extensions/BugmailFilter/lib
parentd74129306d8d5a903af6fe3957046feb36affdd1 (diff)
downloadbugzilla-2f3b5dd7df3e131af6aef3cd5ccf7e8523c1780e.tar.gz
bugzilla-2f3b5dd7df3e131af6aef3cd5ccf7e8523c1780e.tar.xz
Bug 990980: create an extension for server-side filtering of bugmail
Diffstat (limited to 'extensions/BugmailFilter/lib')
-rw-r--r--extensions/BugmailFilter/lib/Constants.pm113
-rw-r--r--extensions/BugmailFilter/lib/FakeField.pm57
-rw-r--r--extensions/BugmailFilter/lib/Filter.pm169
3 files changed, 339 insertions, 0 deletions
diff --git a/extensions/BugmailFilter/lib/Constants.pm b/extensions/BugmailFilter/lib/Constants.pm
new file mode 100644
index 000000000..98b5793af
--- /dev/null
+++ b/extensions/BugmailFilter/lib/Constants.pm
@@ -0,0 +1,113 @@
+# 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::BugmailFilter::Constants;
+use strict;
+
+use base qw(Exporter);
+
+our @EXPORT = qw(
+ FAKE_FIELD_NAMES
+ IGNORE_FIELDS
+ FIELD_DESCRIPTION_OVERRIDE
+ FILTER_RELATIONSHIPS
+);
+
+use Bugzilla::Constants;
+
+# these are field names which are inserted into X-Bugzilla-Changed-Field-Names
+# header but are not real fields
+
+use constant FAKE_FIELD_NAMES => [
+ {
+ name => 'comment.created',
+ description => 'Comment created',
+ },
+ {
+ name => 'attachment.created',
+ description => 'Attachment created',
+ },
+];
+
+# these fields don't make any sense to filter on
+
+use constant IGNORE_FIELDS => qw(
+ attach_data.thedata
+ attachments.submitter
+ comment_tag
+ days_elapsed
+ delta_ts
+ everconfirmed
+ longdesc
+ longdescs.count
+ owner_idle_time
+ reporter
+ reporter_accessible
+ tag
+);
+
+# override the description of some fields
+
+use constant FIELD_DESCRIPTION_OVERRIDE => {
+ bug_id => 'Bug Created',
+};
+
+# relationship / int mappings
+# _should_drop() also needs updating when this const is changed
+
+use constant FILTER_RELATIONSHIPS => [
+ {
+ name => 'Assignee',
+ value => 1,
+ },
+ {
+ name => 'Not Assignee',
+ value => 2,
+ },
+ {
+ name => 'Reporter',
+ value => 3,
+ },
+ {
+ name => 'Not Reporter',
+ value => 4,
+ },
+ {
+ name => 'QA Contact',
+ value => 5,
+ },
+ {
+ name => 'Not QA Contact',
+ value => 6,
+ },
+ {
+ name => "CC'ed",
+ value => 7,
+ },
+ {
+ name => "Not CC'ed",
+ value => 8,
+ },
+ {
+ name => 'Watching',
+ value => 9,
+ },
+ {
+ name => 'Not Watching',
+ value => 10,
+ },
+ {
+ name => 'Mentoring',
+ value => 11,
+ },
+ {
+ name => 'Not Mentoring',
+ value => 12,
+ },
+];
+
+1;
diff --git a/extensions/BugmailFilter/lib/FakeField.pm b/extensions/BugmailFilter/lib/FakeField.pm
new file mode 100644
index 000000000..88e4ac1ca
--- /dev/null
+++ b/extensions/BugmailFilter/lib/FakeField.pm
@@ -0,0 +1,57 @@
+# 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::BugmailFilter::FakeField;
+
+use strict;
+use warnings;
+
+use Bugzilla::Extension::BugmailFilter::Constants;
+
+# object
+
+sub new {
+ my ($class, $params) = @_;
+ return bless($params, $class);
+}
+
+sub name { $_[0]->{name} }
+sub description { $_[0]->{description} }
+
+# static methods
+
+sub fake_fields {
+ my $cache = Bugzilla->request_cache->{bugmail_filter};
+ if (!$cache->{fake_fields}) {
+ my @fields;
+ foreach my $rh (@{ FAKE_FIELD_NAMES() }) {
+ push @fields, Bugzilla::Extension::BugmailFilter::FakeField->new($rh);
+ }
+ $cache->{fake_fields} = \@fields;
+ }
+ return $cache->{fake_fields};
+}
+
+sub tracking_flag_fields {
+ my $cache = Bugzilla->request_cache->{bugmail_filter};
+ if (!$cache->{tracking_flag_fields}) {
+ require Bugzilla::Extension::TrackingFlags::Constants;
+ my @fields;
+ my $tracking_types = Bugzilla::Extension::TrackingFlags::Constants::FLAG_TYPES();
+ foreach my $tracking_type (@$tracking_types) {
+ push @fields, Bugzilla::Extension::BugmailFilter::FakeField->new({
+ name => 'tracking.' . $tracking_type->{name},
+ description => $tracking_type->{description},
+ sortkey => $tracking_type->{sortkey},
+ });
+ }
+ $cache->{tracking_flag_fields} = \@fields;
+ }
+ return $cache->{tracking_flag_fields};
+}
+
+1;
diff --git a/extensions/BugmailFilter/lib/Filter.pm b/extensions/BugmailFilter/lib/Filter.pm
new file mode 100644
index 000000000..9a0d0f89a
--- /dev/null
+++ b/extensions/BugmailFilter/lib/Filter.pm
@@ -0,0 +1,169 @@
+# 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::BugmailFilter::Filter;
+
+use base qw(Bugzilla::Object);
+
+use strict;
+use warnings;
+
+use Bugzilla::Component;
+use Bugzilla::Error;
+use Bugzilla::Extension::BugmailFilter::Constants;
+use Bugzilla::Extension::BugmailFilter::FakeField;
+use Bugzilla::Field;
+use Bugzilla::Product;
+use Bugzilla::User;
+
+use constant DB_TABLE => 'bugmail_filters';
+
+use constant DB_COLUMNS => qw(
+ id
+ user_id
+ product_id
+ component_id
+ field_name
+ relationship
+ action
+);
+
+use constant LIST_ORDER => 'id';
+
+use constant UPDATE_COLUMNS => ();
+
+use constant VALIDATORS => {
+ user_id => \&_check_user,
+ field_name => \&_check_field_name,
+ action => \&Bugzilla::Object::check_boolean,
+};
+use constant VALIDATOR_DEPENDENCIES => {
+ component_id => [ 'product_id' ],
+};
+
+use constant AUDIT_CREATES => 0;
+use constant AUDIT_UPDATES => 0;
+use constant AUDIT_REMOVES => 0;
+use constant USE_MEMCACHED => 0;
+
+# getters
+
+sub user {
+ my ($self) = @_;
+ return Bugzilla::User->new({ id => $self->{user_id}, cache => 1 });
+}
+
+sub product {
+ my ($self) = @_;
+ return $self->{product_id}
+ ? Bugzilla::Product->new({ id => $self->{product_id}, cache => 1 })
+ : undef;
+}
+
+sub product_name {
+ my ($self) = @_;
+ return $self->{product_name} //= $self->{product_id} ? $self->product->name : '';
+}
+
+sub component {
+ my ($self) = @_;
+ return $self->{component_id}
+ ? Bugzilla::Component->new({ id => $self->{component_id}, cache => 1 })
+ : undef;
+}
+
+sub component_name {
+ my ($self) = @_;
+ return $self->{component_name} //= $self->{component_id} ? $self->component->name : '';
+}
+
+sub field_name {
+ return $_[0]->{field_name} //= '';
+}
+
+sub field {
+ my ($self) = @_;
+ return unless $self->{field_name};
+ if (!$self->{field}) {
+ foreach my $field (
+ @{ Bugzilla::Extension::BugmailFilter::FakeField->fake_fields() },
+ @{ Bugzilla::Extension::BugmailFilter::FakeField->tracking_flag_fields() },
+ ) {
+ if ($field->{name} eq $self->{field_name}) {
+ return $self->{field} = $field;
+ }
+ }
+ $self->{field} = Bugzilla::Field->new({ name => $self->{field_name}, cache => 1 });
+ }
+ return $self->{field};
+}
+
+sub relationship {
+ return $_[0]->{relationship};
+}
+
+sub relationship_name {
+ my ($self) = @_;
+ foreach my $rel (@{ FILTER_RELATIONSHIPS() }) {
+ return $rel->{name}
+ if $rel->{value} == $self->{relationship};
+ }
+ return '?';
+}
+
+sub is_exclude {
+ return $_[0]->{action} == 1;
+}
+
+sub is_include {
+ return $_[0]->{action} == 0;
+}
+
+# validators
+
+sub _check_user {
+ my ($class, $user) = @_;
+ $user || ThrowCodeError('param_required', { param => 'user' });
+}
+
+sub _check_field_name {
+ my ($class, $field_name) = @_;
+ return undef unless $field_name;
+ foreach my $rh (@{ FAKE_FIELD_NAMES() }) {
+ return $field_name if $rh->{name} eq $field_name;
+ }
+ return $field_name
+ if $field_name =~ /^tracking\./;
+ Bugzilla::Field->check({ name => $field_name, cache => 1});
+ return $field_name;
+}
+
+# methods
+
+sub matches {
+ my ($self, $args) = @_;
+
+ if ($self->{field_name} && $self->{field_name} ne $args->{field_name}) {
+ return 0;
+ }
+
+ if ($self->{product_id} && $self->{product_id} != $args->{product_id}) {
+ return 0;
+ }
+
+ if ($self->{component_id} && $self->{component_id} != $args->{component_id}) {
+ return 0;
+ }
+
+ if ($self->{relationship} && !$args->{rel_map}->[$self->{relationship}]) {
+ return 0;
+ }
+
+ return 1;
+}
+
+1;