summaryrefslogtreecommitdiffstats
path: root/Bugzilla/User.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/User.pm')
-rw-r--r--Bugzilla/User.pm148
1 files changed, 131 insertions, 17 deletions
diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm
index 0bc49d9b1..1c6e68078 100644
--- a/Bugzilla/User.pm
+++ b/Bugzilla/User.pm
@@ -50,6 +50,7 @@ use Bugzilla::Product;
use Bugzilla::Classification;
use Bugzilla::Field;
use Bugzilla::Group;
+use Bugzilla::Hook;
use DateTime::TimeZone;
use List::Util qw(max);
@@ -91,16 +92,21 @@ use constant DB_TABLE => 'profiles';
# that you passed in for "name" to new(). That's because historically
# Bugzilla::User used "name" for the realname field. This should be
# fixed one day.
-use constant DB_COLUMNS => (
- 'profiles.userid',
- 'profiles.login_name',
- 'profiles.realname',
- 'profiles.mybugslink AS showmybugslink',
- 'profiles.disabledtext',
- 'profiles.disable_mail',
- 'profiles.extern_id',
- 'profiles.is_enabled',
-);
+sub DB_COLUMNS {
+ my $dbh = Bugzilla->dbh;
+ return (
+ 'profiles.userid',
+ 'profiles.login_name',
+ 'profiles.realname',
+ 'profiles.mybugslink AS showmybugslink',
+ 'profiles.disabledtext',
+ 'profiles.disable_mail',
+ 'profiles.extern_id',
+ 'profiles.is_enabled',
+ $dbh->sql_date_format('last_seen_date', '%Y-%m-%d') . ' AS last_seen_date',
+ ),
+}
+
use constant NAME_FIELD => 'login_name';
use constant ID_FIELD => 'userid';
use constant LIST_ORDER => NAME_FIELD;
@@ -144,7 +150,7 @@ sub new {
my $class = ref($invocant) || $invocant;
my ($param) = @_;
- my $user = DEFAULT_USER;
+ my $user = { %{ DEFAULT_USER() } };
bless ($user, $class);
return $user unless $param;
@@ -162,7 +168,7 @@ sub super_user {
my $class = ref($invocant) || $invocant;
my ($param) = @_;
- my $user = dclone(DEFAULT_USER);
+ my $user = { %{ DEFAULT_USER() } };
$user->{groups} = [Bugzilla::Group->get_all];
$user->{bless_groups} = [Bugzilla::Group->get_all];
bless $user, $class;
@@ -285,6 +291,23 @@ sub set_disabledtext {
$_[0]->set('is_enabled', $_[1] ? 0 : 1);
}
+sub update_last_seen_date {
+ my $self = shift;
+ return unless $self->id;
+ my $dbh = Bugzilla->dbh;
+ my $date = $dbh->selectrow_array(
+ 'SELECT ' . $dbh->sql_date_format('NOW()', '%Y-%m-%d'));
+
+ if (!$self->last_seen_date or $date ne $self->last_seen_date) {
+ $self->{last_seen_date} = $date;
+ # We don't use the normal update() routine here as we only
+ # want to update the last_seen_date column, not any other
+ # pending changes
+ $dbh->do("UPDATE profiles SET last_seen_date = ? WHERE userid = ?",
+ undef, $date, $self->id);
+ }
+}
+
################################################################################
# Methods
################################################################################
@@ -299,6 +322,7 @@ sub is_enabled { $_[0]->{'is_enabled'} ? 1 : 0; }
sub showmybugslink { $_[0]->{showmybugslink}; }
sub email_disabled { $_[0]->{disable_mail}; }
sub email_enabled { !($_[0]->{disable_mail}); }
+sub last_seen_date { $_[0]->{last_seen_date}; }
sub cryptpassword {
my $self = shift;
# We don't store it because we never want it in the object (we
@@ -431,6 +455,31 @@ sub tags {
return $self->{tags};
}
+sub bugs_ignored {
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ if (!defined $self->{'bugs_ignored'}) {
+ $self->{'bugs_ignored'} = $dbh->selectall_arrayref(
+ 'SELECT bugs.bug_id AS id,
+ bugs.bug_status AS status,
+ bugs.short_desc AS summary
+ FROM bugs
+ INNER JOIN email_bug_ignore
+ ON bugs.bug_id = email_bug_ignore.bug_id
+ WHERE user_id = ?',
+ { Slice => {} }, $self->id);
+ # Go ahead and load these into the visible bugs cache
+ # to speed up can_see_bug checks later
+ $self->visible_bugs([ map { $_->{'id'} } @{ $self->{'bugs_ignored'} } ]);
+ }
+ return $self->{'bugs_ignored'};
+}
+
+sub is_bug_ignored {
+ my ($self, $bug_id) = @_;
+ return (grep {$_->{'id'} == $bug_id} @{$self->bugs_ignored}) ? 1 : 0;
+}
+
##########################
# Saved Recent Bug Lists #
##########################
@@ -707,8 +756,8 @@ sub bless_groups {
return $self->{'bless_groups'} if defined $self->{'bless_groups'};
return [] unless $self->id;
- if ($self->in_group('editusers')) {
- # Users having editusers permissions may bless all groups.
+ if ($self->in_group('admin')) {
+ # Users having admin permissions may bless all groups.
$self->{'bless_groups'} = [Bugzilla::Group->get_all];
return $self->{'bless_groups'};
}
@@ -778,6 +827,13 @@ sub in_group_id {
return grep($_->id == $id, @{ $self->groups }) ? 1 : 0;
}
+# This is a helper to get all groups which have an icon to be displayed
+# besides the name of the commenter.
+sub groups_with_icon {
+ my $self = shift;
+ return $self->{groups_with_icon} //= [grep { $_->icon_url } @{ $self->direct_group_membership }];
+}
+
sub get_products_by_permission {
my ($self, $group) = @_;
# Make sure $group exists on a per-product basis.
@@ -857,6 +913,14 @@ sub visible_bugs {
if (@check_ids) {
my $dbh = Bugzilla->dbh;
my $user_id = $self->id;
+
+ foreach my $id (@check_ids) {
+ my $orig_id = $id;
+ detaint_natural($id)
+ || ThrowCodeError('param_must_be_numeric', { param => $orig_id,
+ function => 'Bugzilla::User->visible_bugs'});
+ }
+
my $sth;
# Speed up the can_see_bug case.
if (scalar(@check_ids) == 1) {
@@ -1635,7 +1699,9 @@ our %names_to_events = (
'attachments.mimetype' => EVT_ATTACHMENT_DATA,
'attachments.ispatch' => EVT_ATTACHMENT_DATA,
'dependson' => EVT_DEPEND_BLOCK,
- 'blocked' => EVT_DEPEND_BLOCK);
+ 'blocked' => EVT_DEPEND_BLOCK,
+ 'product' => EVT_COMPONENT,
+ 'component' => EVT_COMPONENT);
# Returns true if the user wants mail for a given bug change.
# Note: the "+" signs before the constants suppress bareword quoting.
@@ -1654,7 +1720,7 @@ sub wants_bug_mail {
}
else {
# Catch-all for any change not caught by a more specific event
- $events{+EVT_OTHER} = 1;
+ $events{+EVT_OTHER} = 1;
}
# If the user is in a particular role and the value of that role
@@ -1810,6 +1876,17 @@ sub is_timetracker {
return $self->{'is_timetracker'};
}
+sub can_tag_comments {
+ my $self = shift;
+
+ if (!defined $self->{'can_tag_comments'}) {
+ my $group = Bugzilla->params->{'comment_taggers_group'};
+ $self->{'can_tag_comments'} =
+ ($group && $self->in_group($group)) ? 1 : 0;
+ }
+ return $self->{'can_tag_comments'};
+}
+
sub get_userlist {
my $self = shift;
@@ -2008,6 +2085,9 @@ sub check_and_send_account_creation_confirmation {
ThrowUserError('account_creation_restricted');
}
+ # BMO - add a hook to allow extra validation prior to account creation.
+ Bugzilla::Hook::process("user_verify_login", { login => $login });
+
# Create and send a token for this new account.
require Bugzilla::Token;
Bugzilla::Token::issue_new_user_account_token($login);
@@ -2199,6 +2279,34 @@ groups.
Returns a hashref with tag IDs as key, and a hashref with tag 'id',
'name' and 'bug_count' as value.
+=item C<bugs_ignored>
+
+Returns an array of hashrefs containing information about bugs currently
+being ignored by the user.
+
+Each hashref contains the following information:
+
+=over
+
+=item C<id>
+
+C<int> The id of the bug.
+
+=item C<status>
+
+C<string> The current status of the bug.
+
+=item C<summary>
+
+C<string> The current summary of the bug.
+
+=back
+
+=item C<is_bug_ignored>
+
+Returns true if the user does not want email notifications for the
+specified bug ID, else returns false.
+
=back
=head2 Saved Recent Bug Lists
@@ -2363,7 +2471,7 @@ Determines whether or not a user is in the given group by id.
Returns an arrayref of L<Bugzilla::Group> objects.
The arrayref consists of the groups the user can bless, taking into account
-that having editusers permissions means that you can bless all groups, and
+that having admin permissions means that you can bless all groups, and
that you need to be able to see a group in order to bless it.
=item C<get_products_by_permission($group)>
@@ -2569,6 +2677,12 @@ i.e. if the 'insidergroup' parameter is set and the user belongs to this group.
Returns true if the user is a global watcher,
i.e. if the 'globalwatchers' parameter contains the user.
+=item C<can_tag_comments>
+
+Returns true if the user can attach tags to comments.
+i.e. if the 'comment_taggers_group' parameter is set and the user belongs to
+this group.
+
=back
=head1 CLASS FUNCTIONS