diff options
Diffstat (limited to 'extensions')
23 files changed, 1023 insertions, 0 deletions
diff --git a/extensions/Mageia/Config.pm b/extensions/Mageia/Config.pm new file mode 100644 index 000000000..94f2da811 --- /dev/null +++ b/extensions/Mageia/Config.pm @@ -0,0 +1,28 @@ +# 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::Mageia; + +use 5.16.0; +use strict; +use warnings; + +use constant NAME => 'Mageia'; + +use constant REQUIRED_MODULES => [ + # Required to sync LDAP groups with Bugzilla groups. + { + package => 'perl-ldap', + module => 'Net::LDAP', + version => 0 + } +]; + +use constant OPTIONAL_MODULES => [ +]; + +__PACKAGE__->NAME; diff --git a/extensions/Mageia/Extension.pm b/extensions/Mageia/Extension.pm new file mode 100644 index 000000000..257e7782a --- /dev/null +++ b/extensions/Mageia/Extension.pm @@ -0,0 +1,201 @@ +# 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::Mageia; + +use 5.16.0; +use strict; +use warnings; + +use parent qw(Bugzilla::Extension); + +use Bugzilla::Constants qw(EVT_CC REL_GLOBAL_WATCHER); +use Bugzilla::Bug qw(LogActivityEntry); +use Bugzilla::Field qw(get_field_id); +use Bugzilla::User qw(); +use Bugzilla::User::Setting qw(add_setting); +use Bugzilla::Extension::Mageia::Util qw(compare_datetimes sync_ldap_groups_check); + +use Email::Address; +use Encode qw(encode); + +# Let's match the Bugzilla version it's written for. +our $VERSION = '5.0'; + +# sysadmin-bugs@ml.mageia.org user ID = 175. +use constant SYSADMIN_USER_ID => 175; + +use constant MGA_SETTINGS => { + mga_inline_history => { options => ['on', 'off'], default => 'on' }, +}; + +sub bug_end_of_create_validators { + my ($self, $args) = @_; + + # If a user enters 'validated_update' as keyword, + # automatically CC sysadmin-bugs@ml.mageia.org. + my $keywords = $args->{params}->{keywords}; + + if (grep { $_->name eq 'validated_update' } @$keywords) { + my $cc_list = $args->{params}->{cc}; + if (!grep { $_ == SYSADMIN_USER_ID } @$cc_list) { + push(@$cc_list, SYSADMIN_USER_ID); + } + } +} + +sub bug_end_of_update { + my ($self, $args) = @_; + my $bug = $args->{bug}; + my $dbh = Bugzilla->dbh; + my $user = Bugzilla->user; + + my $new_keywords_str; + # Call exists to avoid autovivification of $args->{changes} if it does not exist. + # Else $bug->update() always sees the bug as being edited. + if (exists $args->{changes} && exists $args->{changes}->{keywords}) { + $new_keywords_str = $args->{changes}->{keywords}->[1]; + } + + # If a user enters 'validated_update' as keyword, automatically + # CC sysadmin-bugs@ml.mageia.org. + if ($new_keywords_str) { + my @new_keywords = split(/[,\s]+/, $new_keywords_str); + if (grep { $_ eq 'validated_update' } @new_keywords + and !grep { $_->id == SYSADMIN_USER_ID } @{$bug->cc_users}) + { + # Safer to clear the cache and let Bugzilla regenerate them if needed. + delete $bug->{cc_users}; + delete $bug->{cc}; + $dbh->do('INSERT INTO cc (bug_id, who) VALUES (?, ?)', + undef, ($bug->id, SYSADMIN_USER_ID)); + + # We also have to update the bug history to reflect this change. + my $changed_cc = $args->{changes}->{cc}; + my $sysadmin_login = Bugzilla::User->new(SYSADMIN_USER_ID)->login; + + if ($changed_cc->[1]) { + $changed_cc->[1] .= ", $sysadmin_login"; + } + else { + $changed_cc->[1] = $sysadmin_login; + } + + my $field_id = get_field_id('cc'); + $dbh->do('DELETE FROM bugs_activity + WHERE bug_id = ? AND bug_when = ? AND fieldid = ?', + undef, ($bug->id, $args->{timestamp}, $field_id)); + + LogActivityEntry($bug->id, 'cc', $changed_cc->[0] // '', $changed_cc->[1], + $user->id, $args->{timestamp}); + } + } +} + +sub bug_format_comment { + my ($self, $args) = @_; + my $regexes = $args->{'regexes'}; + # The Mageia DB was initially using SQL_ASCII as encoding (which means "no encoding"). + # The move to UTF8 caused some characters to be badly decoded, which we fix here. + # Convert "é" into "é". + push(@$regexes, { match => qr/\xc3\xa9/, replace => "\xe9" }); +} + +sub enter_bug_entrydefaultvars { + my ($self, $vars) = @_; + my $cgi = Bugzilla->cgi; + + # By default, users should get the guided form when reporting a new bug. + # Pass &normal=1 to the URL to get the official bug form. + my $format = $cgi->param('normal') ? '' : 'guided'; + $cgi->param('format', $format); +} + +sub install_before_final_checks { + # A hook in Bugzilla::Install::SETTINGS() would be much cleaner. :( + my %settings = %{MGA_SETTINGS()}; + foreach my $setting (keys %settings) { + add_setting($setting, $settings{$setting}->{options}, $settings{$setting}->{default}); + } +} + +sub mailer_before_send { + my ($self, $args) = @_; + my $email = $args->{email}; + + # Include the changer's name in the "From:" field. + if (my $changer = $email->header('X-Bugzilla-Who')) { + $changer = Bugzilla::User->new({ name => $changer }); + return unless $changer; + my $address = Email::Address->new($changer->name, $email->header('From')); + $email->header_set('From', encode('MIME-Header', $address->format)); + } +} + +sub sanitycheck_check { + my ($self, $args) = @_; + &{$args->{status}}('ldap_check_group_membership'); + sync_ldap_groups_check($args->{status}); +} + +sub sanitycheck_repair { + my ($self, $args) = @_; + if (Bugzilla->cgi->param('sync_ldap_groups')) { + &{$args->{status}}('ldap_repair_start'); + sync_ldap_groups_check($args->{status}, 1); + &{$args->{status}}('ldap_repair_end'); + } +} + +sub template_before_process { + my ($self, $args) = @_; + _inline_history($args) if $args->{file} eq 'bug/comments.html.tmpl'; +} + +sub _inline_history { + my $args = shift; + my $user = Bugzilla->user; + return if $user->setting('mga_inline_history') eq 'off'; + # Only display the bug history in chronological order. + return if $user->setting('comment_sort_order') ne 'oldest_to_newest'; + + my $bug = $args->{vars}->{bug}; + my ($history) = $bug->get_activity(); + # Filter private comments that the user is not allowed to see. + my @comments = grep { !$_->is_private || $user->is_insider || $user->id == $_->author->id } @{ $bug->comments }; + my %h_times = map { $_->{when} => $_ } @$history; + my %c_times = map { $_->creation_ts => $_ } @comments; + my @all_times = sort { compare_datetimes($a, $b) } (keys %c_times, keys %h_times); + my $curr_comment; + + foreach my $time (@all_times) { + if ($c_times{$time}) { + $curr_comment = $c_times{$time}; + $curr_comment->{inline_history} //= []; + } + if (my $activity = $h_times{$time}) { + # If we have no visible comment to attach the activity to, then ignore it. + # This can happen if the initial comment (comment 0) is private. + next unless $curr_comment; + $activity->{after} = compare_datetimes($time, $curr_comment->creation_ts); + $activity->{who} = new Bugzilla::User({ name => $activity->{who}, cache => 1 }); + push(@{ $curr_comment->{inline_history} }, $activity); + } + } +} + +sub user_wants_mail { + my ($self, $args) = @_; + return unless $args->{relationship} == REL_GLOBAL_WATCHER; + + my $wants_mail = $args->{wants_mail}; + my @events = @{ $args->{events} }; + # Do not email global watchers if the single change is about the CC list. + $$wants_mail = (scalar(@events) == 1 && $events[0] == EVT_CC) ? 0 : 1; +} + +__PACKAGE__->NAME; diff --git a/extensions/Mageia/lib/Util.pm b/extensions/Mageia/lib/Util.pm new file mode 100644 index 000000000..b70d39818 --- /dev/null +++ b/extensions/Mageia/lib/Util.pm @@ -0,0 +1,146 @@ +# 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::Mageia::Util; + +use 5.16.0; # required to use fc() for string comparison. +use strict; +use warnings; + +use Bugzilla::Auth::Verify::LDAP; +use Bugzilla::Group; +use Bugzilla::User; +use Bugzilla::Util qw(diff_arrays); + +use parent qw(Exporter); + +our @EXPORT = qw(compare_datetimes sync_ldap_groups_check); + +# Use Mageia Robot user ID = 2122 for LDAP groups sync. +use constant LDAP_SYNC_USER_ID => 2122; + +# This file can be loaded by your extension via +# "use Bugzilla::Extension::Mageia::Util". You can put functions +# used by your extension in here. (Make sure you also list them in +# @EXPORT.) + +# Return -1 if $t1 < $t2, 0 if $t1 == $t2, 1 if $t1 > $t2, undef if a date is invalid. +sub compare_datetimes { + my ($t1, $t2) = @_; + my (@time1, @time2); + if ($t1 =~ /^(\d{4})[\.-](\d{2})[\.-](\d{2})(?: (\d{2}):(\d{2}):(\d{2}))?$/) { + @time1 = ($1, $2, $3, $4, $5, $6); + } + if ($t2 =~ /^(\d{4})[\.-](\d{2})[\.-](\d{2})(?: (\d{2}):(\d{2}):(\d{2}))?$/) { + @time2 = ($1, $2, $3, $4, $5, $6); + } + return undef unless scalar(@time1) && scalar(@time2); + + for my $i (0..5) { + $t1 = $time1[$i] // 0; + $t2 = $time2[$i] // 0; + next if $t1 == $t2; + return $t1 <=> $t2; + } + return 0; +} + +sub sync_ldap_groups_check { + my ($status, $repair) = @_; + my $ldap = Bugzilla::Auth::Verify::LDAP->new(); + $ldap->_bind_ldap_for_search; + + my $result = $ldap->ldap->search( + base => 'ou=Group,dc=mageia,dc=org', + filter => '(objectClass=groupOfNames)', + attrs => ['cn', 'member'] + ); + + if ($result->is_error) { + &$status('ldap_sync_alert', { ldap_error => $result->error }, 'alert'); + return; + } + + my (%groups, %users); + my $dbh = Bugzilla->dbh; + + my %bz_groups = map { $_->name => $_ } grep { $_->name =~ /^mga-/ } Bugzilla::Group->get_all; + + foreach my $ldap_group ($result->entries) { + my $group = $ldap_group->get_value('cn'); + next unless $bz_groups{$group}; + + $groups{$group} = {}; + + foreach my $user ($ldap_group->get_value('member')) { + unless (exists $users{$user}) { + my $result = $ldap->ldap->search( + base => $user, + scope => 'base', + filter => '(objectClass=inetOrgPerson)', + attrs => ['uid', 'mail'] + ); + if ($result->is_error) { + &$status('ldap_sync_alert', { ldap_error => $result->error }, 'alert'); + next; + } + + # Some entries are not valid user accounts. + my $ldap_user = $result->entry(0) or next; + my $uid = $ldap_user->get_value('uid'); + my $mail = $ldap_user->get_value('mail'); + # Some accounts lack an email address. They cannot log into Bugzilla. + next unless $uid && $mail; + + # Ignore the LDAP account if it does not exist in Bugzilla. + # extern_id may differ from UID as UID is always lowercase, + # so we also check the email address to validate the account. + my $bz_user = Bugzilla::User->new({ extern_id => $uid }) + || Bugzilla::User->new({ name => $mail }); + next unless $bz_user && fc($bz_user->extern_id) eq fc($uid); + $users{$user} = $bz_user; + } + $groups{$group}->{$users{$user}->extern_id} = $users{$user}; + } + } + + my $current_user = Bugzilla->user; + my $ldap_sync_needs_repair = 0; + + if ($repair) { + # We need to log in as a super user in order to update group memberships. + # Bugzilla needs a valid user ID to log changes, though. + my $super_user = Bugzilla::User->super_user; + $super_user->{userid} = LDAP_SYNC_USER_ID; + Bugzilla->set_user($super_user); + } + + foreach my $group (sort keys %groups) { + my %members = map { $_->extern_id => $_ } @{$bz_groups{$group}->members_direct}; + my ($removed, $added) = diff_arrays([keys %members], [keys %{$groups{$group}}]); + if ($repair) { + foreach my $old_user (@$removed) { + $members{$old_user}->set_groups({ remove => [$group] }); + $members{$old_user}->update; + } + + foreach my $new_user (@$added) { + $groups{$group}->{$new_user}->set_groups({ add => [$group] }); + $groups{$group}->{$new_user}->update; + } + } + elsif (@$removed || @$added) { + &$status('ldap_sync_group_mismatch_alert', { group => $group, old_users => $removed, new_users => $added }, 'alert'); + $ldap_sync_needs_repair = 1; + } + } + # Restore the original user. + Bugzilla->set_user($current_user) if $repair; + &$status('ldap_sync_repair_link') if $ldap_sync_needs_repair; +} + +1; diff --git a/extensions/Mageia/sync_LDAP_groups.pl b/extensions/Mageia/sync_LDAP_groups.pl new file mode 100755 index 000000000..77a99ee9a --- /dev/null +++ b/extensions/Mageia/sync_LDAP_groups.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl -T +# 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. + +use 5.14.0; +use strict; +use warnings; + +use lib qw(. lib); + +use Bugzilla; +BEGIN { Bugzilla->extensions() } +use Bugzilla::Extension::Mageia::Util qw(sync_ldap_groups_check); + +# See Status() in sanitycheck.cgi. +sub status { + my ($san_tag, $vars, $alert) = @_; + return unless $alert && $san_tag eq 'ldap_sync_alert'; + + say 'LDAP error: ' . $vars->{ldap_error}; +} + +sync_ldap_groups_check(\&status, 1); diff --git a/extensions/Mageia/template/en/default/bug/create/comment-guided.txt.tmpl b/extensions/Mageia/template/en/default/bug/create/comment-guided.txt.tmpl new file mode 100644 index 000000000..7b5018e6d --- /dev/null +++ b/extensions/Mageia/template/en/default/bug/create/comment-guided.txt.tmpl @@ -0,0 +1,10 @@ +[%# 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. + #%] + +[% USE Bugzilla %] +[% Bugzilla.cgi.param("comment") %] diff --git a/extensions/Mageia/template/en/default/bug/create/create-guided.html.tmpl b/extensions/Mageia/template/en/default/bug/create/create-guided.html.tmpl new file mode 100644 index 000000000..c672a4cf5 --- /dev/null +++ b/extensions/Mageia/template/en/default/bug/create/create-guided.html.tmpl @@ -0,0 +1,299 @@ +[%# 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. + #%] + +[%# INTERFACE: + # This template has the same interface as create.html.tmpl + #%] + +[% PROCESS global/header.html.tmpl + title = "Enter $terms.ABug" + onload = "PutDescription()" + style_urls = ['skins/standard/bug.css'] + javascript_urls = ['js/util.js', 'js/field.js'] + yui = ['autocomplete'] + %] + +[% defaultcontent = "Description of problem:\n\n\n" _ + "Version-Release number of selected component (if applicable):\n\n\n" _ + "How reproducible:\n\n\nSteps to Reproduce:\n1.\n2.\n3.\n" %] + +[%# This script displays the descriptions for selected components. %] +<script type="text/javascript"> +var descriptions = [ +[% FOREACH c = product.components %] + [% NEXT IF NOT c.is_active %] + '[% c.description FILTER js %]', +[% END %] +]; + +function PutDescription() { + var description = document.getElementById('description'); + var componentIndex = document.getElementById('component').selectedIndex; + YAHOO.util.Dom.removeClass("description", "bz_default_hidden"); + if (componentIndex != -1) { + description.innerHTML = descriptions[componentIndex]; + } +} + +function CheckDetails(e) { + if (e.form.comment.value == '[% defaultcontent FILTER js FILTER html %]') { + alert('Please enter some details about this [% terms.bug %].'); + e.form.comment.focus(); + return false; + } + return true; +} +</script> + +<p> + Submit [% terms.abug %] using the + <a href="enter_bug.cgi?product=[% product.name FILTER html %]&normal=1">expert [% terms.bug %] form</a>. +</p> + +<form id="guided_form" method="post" action="post_bug.cgi"> + <input type="hidden" name="format" value="guided"> + <input type="hidden" name="priority" value="[% default.priority FILTER html %]"> + <input type="hidden" name="token" value="[% token FILTER html %]"> + +<table> + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.product %] + <td> + <input type="hidden" name="product" value="[% product.name FILTER html %]"> + [% product.name FILTER html %] + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.component editable = 1 %] + <td> + <select name="component" id="component" size="5" onchange="PutDescription()" + aria-required="true" class="required" required> + [% IF NOT default.component_ %] + [% default.component_ = "RPM Packages" %] + [% END %] + [% FOREACH c = product.components %] + [% NEXT IF NOT c.is_active %] + <option value="[% c.name FILTER html %]" + [%+ 'selected="selected"' IF c.name == default.component_ %]> + [% c.name FILTER html %] + </option> + [% END %] + </select> + + <div id="description" class="comment bz_default_hidden"> + Select a component to see its description here. + </div> + + <p> + The area where the problem occurs. + To pick the right component, you could use the same one as + similar [% terms.bugs %] you found in your search, or read the full list of + <a href="describecomponents.cgi?product=[% product.name FILTER uri %]" + target="_blank" >component descriptions</a> (opens in new window) if + you need more help. + </p> + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.version editable = 1 %] + <td> + <select name="version" id="version" size="5" aria-required="true" class="required" required> + [% FOREACH v = version %] + [% NEXT IF NOT v.is_active %] + <option value="[% v.name FILTER html %]" + [% ' selected="selected"' IF v.name == default.version %]>[% v.name FILTER html -%] + </option> + [% END %] + </select> + + <p> + The version in which the problem occurs. + </p> + </td> + </tr> + + <tr> + [% INCLUDE bug/field.html.tmpl + bug = default, field = bug_fields.rep_platform, editable = 1, + value = default.rep_platform %] + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.cf_rpmpkg editable = 1 %] + <td> + <input size="80" name="cf_rpmpkg" id="cf_rpmpkg" value="[% default.cf_rpmpkg FILTER html %]"> + <p> + This is where you can identify exactly which RPM package is involved in + this [% terms.bug %] report. For instance, if you know the problem you + are having is with the program <tt>mysqld</tt>, then execute + <tt>rpm -qif /usr/sbin/mysqld</tt>. This will tell you the name and version + of the RPM package (i.e. mariadb-core-10.1.24-1.mga6) as well as other + information. In particular, you are looking for the "Source RPM" field + (i.e. mariadb-10.1.24-1.mga6.src.rpm) -- this is the information you should + provide here. Alternatively, you may use + <tt>rpm -qf /usr/sbin/mysqld --qf '%{SOURCERPM}\n'</tt> to obtain the + information. If you do not know the location of the program in question, + use <tt>rpm -qif `which mysqld`</tt>. Please enter that information above. + </p> + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.bug_file_loc editable = 1 %] + <td> + <input id="bug_file_loc" name="bug_file_loc" placeholder="https://" size="80" + [% IF bug_file_loc != "http://" %] value="[% bug_file_loc FILTER html %]"[% END %]> + <p> + URL that demonstrates the problem you are submitting (optional). + </p> + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.short_desc editable = 1 %] + <td> + <input name="short_desc" id="short_desc" size="80" maxlength="255" + value="[% short_desc FILTER html %]" spellcheck="true" + aria-required="true" class="required" required> + <p> + A sentence which summarizes the problem. + Please be descriptive and use lots of keywords. + </p> + <p> + <kbd> + <span class="bad">Bad example</span>: mail crashed + </kbd> + <br> + <kbd> + <span class="good">Good example</span>: + crash in Evolution while checking for new POP mail + </kbd> + </p> + </td> + </tr> + + <tr> + <th id="field_label_details" class="field_label required">Details</th> + <td> + [% INCLUDE global/textarea.html.tmpl + id = 'comment' + name = 'comment' + minrows = 13 + cols = constants.COMMENT_COLS + mandatory = 1 + defaultcontent = comment || defaultcontent + %] + + [% IF user.is_insider %] + <br> + <input type="checkbox" id="comment_is_private" name="comment_is_private" + [% ' checked="checked"' IF comment_is_private %] + onClick="updateCommentTagControl(this, 'comment')"> + <label for="comment_is_private"> + Initial description is private (visible only to members + of the <strong>[% Param('insidergroup') FILTER html %]</strong> group) + </label> + <script> + updateCommentTagControl(document.getElementById('comment_is_private'), 'comment'); + </script> + [% END %] + <p> + Expand on the Summary. Please be as specific as possible about what is wrong. + </p> + <p> + <kbd> + <span class="bad">Bad example</span>: I can't seem to login to the system. Please help! + </kbd> + <br> + <kbd> + <span class="good">Good example</span>: Description of problem: + <br><br> + I'm unable to login to the system via ssh. The /var/log/messages log + indicates there is a problem with the pam module pam_ldap, but the + /etc/pam.d/system-auth file doesn't contain that module and I'm not + using LDAP. I looked at /etc/pam.d/sshd and it does contain that module + but I'm not sure how it got there, unless it was due to the super-spiffy + super-ldap-mojo package I installed yesterday. + <br><br> + Version-Release number of selected component (if applicable): + <br><br> + openldap-2.4.45-2.mga6, pam-1.3.0-5.mga6 + <br><br> + How reproducible: + <br><br> + Every time I attempt to login. + <br><br> + Steps to Reproduce:<br> + 1. ssh user@host<br> + 2. see the rejection + </kbd> + </p> + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.bug_severity editable = 1 %] + <td> + <select name="bug_severity"> + <option name="critical" value="critical"> + Critical: The software crashes, hangs, or causes you to + lose data. + </option> + <option name="major" value="major"> + Major: A major feature is broken. + </option> + <option name="normal" value="normal" selected="selected"> + Normal: It's [% terms.abug %] that should be fixed. + </option> + <option name="minor" value="minor"> + Minor: Minor loss of function, and there's an easy workaround. + </option> + <option name="enhancement" value="enhancement"> + Enhancement: Request for new feature or enhancement. + </option> + </select> + <p> + Indicate how serious the problem is, or if your [% terms.bug %] is a + request for a new feature. + </p> + </td> + </tr> + + <tr> + [% INCLUDE "bug/field-label.html.tmpl" field = bug_fields.assigned_to editable = 1 %] + <td> + [% INCLUDE global/userselect.html.tmpl + id => "assigned_to" + name => "assigned_to" + value => assigned_to + disabled => assigned_to_disabled + size => 30 + emptyok => 1 + %] + <p>Leave blank to assign to the default component owner.</p> + </td> + </tr> + + [% Hook.process('form') %] +</table> + +<p> + <input type="submit" id="report" value="Submit [% terms.Bug %] Report" + onclick="var res = CheckDetails(this); return res"> +</p> + +<p> + That's it! Thanks very much. You'll be notified by email about any progress + that is made on fixing your [% terms.bug %]. Thank you for choosing Mageia! +</p> + +</form> + +[% PROCESS global/footer.html.tmpl %] diff --git a/extensions/Mageia/template/en/default/global/banner.html.tmpl b/extensions/Mageia/template/en/default/global/banner.html.tmpl new file mode 100644 index 000000000..76f1d123e --- /dev/null +++ b/extensions/Mageia/template/en/default/global/banner.html.tmpl @@ -0,0 +1,11 @@ +[%# 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. + #%] + +<script src="https://nav.mageia.org/js/" type="text/javascript"></script> + +<div id="banner"></div> diff --git a/extensions/Mageia/template/en/default/hook/README b/extensions/Mageia/template/en/default/hook/README new file mode 100644 index 000000000..e6c4add58 --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/README @@ -0,0 +1,5 @@ +Template hooks go in this directory. Template hooks are called in normal +Bugzilla templates like [% Hook.process('some-hook') %]. +More information about them can be found in the documentation of +Bugzilla::Extension. (Do "perldoc Bugzilla::Extension" from the main +Bugzilla directory to see that documentation.)
\ No newline at end of file diff --git a/extensions/Mageia/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl b/extensions/Mageia/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl new file mode 100644 index 000000000..675af49f1 --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl @@ -0,0 +1,23 @@ +[%# 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. + #%] + +[% UNLESS user.id %] + [% UNLESS Param('createemailregexp') AND user.authorizer.user_can_create_account %] + <li id="new_account_container[% qs_suffix FILTER html %]"> + <span class="separator">| </span> + <a href="https://identity.mageia.org/register">New Account</a> + </li> + [% END %] + + [% UNLESS user.authorizer.can_change_password %] + <li id="forgot_container[% qs_suffix FILTER html %]"> + <span class="separator">| </span> + <a href="https://identity.mageia.org/forgot_password">Forgot Password</a> + </li> + [% END %] +[% END %] diff --git a/extensions/Mageia/template/en/default/hook/account/prefs/account-field.html.tmpl b/extensions/Mageia/template/en/default/hook/account/prefs/account-field.html.tmpl new file mode 100644 index 000000000..700f06a69 --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/account/prefs/account-field.html.tmpl @@ -0,0 +1,10 @@ +[% IF Param('user_verify_class') == "LDAP" %] + <tr> + <th></th> + <td>(Changes will be undone when you log out. Use the link below for permanent changes.)</td> + </tr> + <tr> + <th>Edit account (email address, password, real name):</th> + <td><a href="https://identity.mageia.org" target="_blank">Visit identity.mageia.org</a></td> + </tr> +[% END %] diff --git a/extensions/Mageia/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl b/extensions/Mageia/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl new file mode 100644 index 000000000..19155048b --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl @@ -0,0 +1,27 @@ +[%# 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. + #%] + +[% IF san_tag == "ldap_check_group_membership" %] + Checking group membership for LDAP groups. +[% ELSIF san_tag == "ldap_repair_start" %] + OK, now fixing Bugzilla group memberships based on LDAP groups. +[% ELSIF san_tag == "ldap_repair_end" %] + Bugzilla group memberships synchronization completed. +[% ELSIF san_tag == "ldap_sync_alert" %] + LDAP error: [% ldap_error FILTER html %] +[% ELSIF san_tag == "ldap_sync_group_mismatch_alert" %] + Group [% group FILTER html %] is out of sync:<br> + - [% old_users.size %] users are no longer in this group and should be removed: + [%+ old_users.join(", ") FILTER html %].<br> + - [% new_users.size %] users are not yet in this group and should be added: + [%+ new_users.join(", ") FILTER html %]. +[% ELSIF san_tag == "ldap_sync_repair_link" %] + <a href="sanitycheck.cgi?sync_ldap_groups=1&token= + [%- issue_hash_token(['sanitycheck']) FILTER uri %]">Synchronize Bugzilla groups + with LDAP groups (LDAP -> Bugzilla).</a> +[% END %] diff --git a/extensions/Mageia/template/en/default/hook/bug/comments-a_comment-end.html.tmpl b/extensions/Mageia/template/en/default/hook/bug/comments-a_comment-end.html.tmpl new file mode 100644 index 000000000..cbe11b4ca --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/bug/comments-a_comment-end.html.tmpl @@ -0,0 +1,76 @@ +[%# 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. + #%] + +[% RETURN IF user.setting('mga_inline_history') == 'off' %] + +[% FOREACH activity = comment.inline_history %] + [% IF activity.after %] + </div> + <div class="bz_comment bz_inline_history"> + <div class="bz_comment_head"> + <span class="bz_comment_user"> + [%# No need to recreate the exact same template if we already have it. %] + [% who_id = activity.who.id %] + [% UNLESS user_cache.$who_id %] + [% user_cache.$who_id = BLOCK %] + [% INCLUDE global/user.html.tmpl who = activity.who %] + [% END %] + [% END %] + [% user_cache.$who_id FILTER none %] + </span> + + <span class="bz_comment_user_images"> + [% FOREACH group = activity.who.groups_with_icon %] + <img src="[% group.icon_url FILTER html %]" + alt="[% group.name FILTER html %]" + title="[% group.name FILTER html %] - [% group.description FILTER html %]"> + [% END %] + </span> + + <span class="bz_comment_time"> + [%+ activity.when FILTER time %] + </span> + </div> + [% ELSE %] + <hr> + [% END %] + + <p class="bz_inline_history"> + [% FOREACH change = activity.changes %] + [% IF change.attachid AND field_descs.${change.fieldname}.match('^Attachment') %] + <a href="attachment.cgi?id=[% change.attachid FILTER html %]&action=edit"> + [% field_descs.${change.fieldname}.replace('^Attachment', "Attachment ${change.attachid}</a>") FILTER none %]: + [% ELSIF activity.comment_id AND field_descs.${change.fieldname}.match('^Comment') %] + [% comment_num = change.comment.count %] + <a href="show_bug.cgi?id=[% bug.id FILTER html %]#c[% comment_num FILTER html %]" + onclick="document.getElementById('c[% comment_num FILTER html %]').classList.add('bz_comment_hilite')"> + [% field_descs.${change.fieldname}.replace('^Comment', "Comment $comment_num</a>") FILTER none %]: + [% ELSE %] + [% field_descs.${change.fieldname} FILTER html %]: + [% END %] + <span class="change_removed">[% PROCESS format_field_value value = change.removed %]</span> => + <span class="change_added">[% PROCESS format_field_value value = change.added %]</span><br> + [% END %] + </p> +[% END %] + +[% BLOCK format_field_value %] + [% IF value.length %] + [% IF change.fieldname == 'assigned_to' || + change.fieldname == 'reporter' || + change.fieldname == 'qa_contact' || + change.fieldname == 'cc' || + change.fieldname == 'flagtypes.name' %] + [% display_value(change.fieldname, value) FILTER email FILTER html %] + [% ELSE %] + [% display_value(change.fieldname, value) FILTER html FILTER html_line_break %] + [% END %] + [% ELSE %] + (none) + [% END %] +[% END %] diff --git a/extensions/Mageia/template/en/default/hook/global/header-start.html.tmpl b/extensions/Mageia/template/en/default/hook/global/header-start.html.tmpl new file mode 100644 index 000000000..01fab7fab --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/global/header-start.html.tmpl @@ -0,0 +1,10 @@ +[%# 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. + #%] + +[% favicon_url = "https://www.mageia.org/g/favicon.png" %] +[% style_urls.push("extensions/Mageia/web/style.css") %] diff --git a/extensions/Mageia/template/en/default/hook/global/setting-descs-settings.none.tmpl b/extensions/Mageia/template/en/default/hook/global/setting-descs-settings.none.tmpl new file mode 100644 index 000000000..5b1da08aa --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/global/setting-descs-settings.none.tmpl @@ -0,0 +1,9 @@ +[%# 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. + #%] + +[% setting_descs.mga_inline_history = "Display inline history in $terms.bug reports" %] diff --git a/extensions/Mageia/template/en/default/hook/global/variables-end.none.tmpl b/extensions/Mageia/template/en/default/hook/global/variables-end.none.tmpl new file mode 100644 index 000000000..4f651a5ae --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/global/variables-end.none.tmpl @@ -0,0 +1,9 @@ +[%# 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. + #%] + +[% terms.Bugzilla = "Mageia Bugzilla" %] diff --git a/extensions/Mageia/template/en/default/hook/index-additional_links.html.tmpl b/extensions/Mageia/template/en/default/hook/index-additional_links.html.tmpl new file mode 100644 index 000000000..3c2585887 --- /dev/null +++ b/extensions/Mageia/template/en/default/hook/index-additional_links.html.tmpl @@ -0,0 +1,14 @@ +[%# 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. + #%] + +[% UNLESS user.id %] + <p id="create_account"> + Don't have an account on [% terms.Bugzilla %]? + <a href="https://identity.mageia.org/register">Create one</a>. + </p> +[% END %] diff --git a/extensions/Mageia/template/en/default/mageia/README b/extensions/Mageia/template/en/default/mageia/README new file mode 100644 index 000000000..099d1a41a --- /dev/null +++ b/extensions/Mageia/template/en/default/mageia/README @@ -0,0 +1,16 @@ +Normal templates go in this directory. You can load them in your +code like this: + +use Bugzilla::Error; +my $template = Bugzilla->template; +$template->process('mageia/some-template.html.tmpl') + or ThrowTemplateError($template->error()); + +That would be how to load a file called some-template.html.tmpl that +was in this directory. + +Note that you have to be careful that the full path of your template +never conflicts with a template that exists in Bugzilla or in +another extension, or your template might override that template. That's why +we created this directory called 'mageia' for you, so you +can put your templates in here to help avoid conflicts.
\ No newline at end of file diff --git a/extensions/Mageia/web/README b/extensions/Mageia/web/README new file mode 100644 index 000000000..c3c41862f --- /dev/null +++ b/extensions/Mageia/web/README @@ -0,0 +1,7 @@ +Web-accessible files, like JavaScript, CSS, and images go in this +directory. You can reference them directly in your HTML. For example, +if you have a file called "style.css" and your extension is called +"Mageia", you would put it in "extensions/Mageia/web/style.css", and then +you could link to it in HTML like: + +<link href="extensions/Mageia/web/style.css" rel="stylesheet" type="text/css"> diff --git a/extensions/Mageia/web/style.css b/extensions/Mageia/web/style.css new file mode 100644 index 000000000..daffc088a --- /dev/null +++ b/extensions/Mageia/web/style.css @@ -0,0 +1,52 @@ +/* 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. + */ + +body { + margin: 0; + padding-top: 0; + background-color: #fff !important; +} + +#create_account { + border: solid 1px; + background-color: #ffd386; + color: #9b1a1a; + padding: 1em; + text-align: center; + max-width: 30em; + margin: 1em auto; +} + +#guided_form { + padding: 1em; +} + +#guided_form .field_label { + white-space: nowrap; +} + +.bz_inline_history { + font-style: italic; + background-color: #fff !important; +} + +div.bz_comment_hilite { + border: solid 3px; +} + +.bz_comment_hilite pre { + background-color: inherit; +} + +.change_removed { + color: darkred; +} + +.change_added { + color: darkgreen; +} diff --git a/extensions/MoreBugUrl/Extension.pm b/extensions/MoreBugUrl/Extension.pm index 18507f8d1..0a4223e19 100644 --- a/extensions/MoreBugUrl/Extension.pm +++ b/extensions/MoreBugUrl/Extension.pm @@ -22,6 +22,7 @@ use constant MORE_SUB_CLASSES => qw( Bugzilla::Extension::MoreBugUrl::PHP Bugzilla::Extension::MoreBugUrl::Redmine Bugzilla::Extension::MoreBugUrl::Savane + Bugzilla::Extension::MoreBugUrl::Phabricator ); # We need to update bug_see_also table because both diff --git a/extensions/MoreBugUrl/disabled b/extensions/MoreBugUrl/disabled deleted file mode 100644 index e69de29bb..000000000 --- a/extensions/MoreBugUrl/disabled +++ /dev/null diff --git a/extensions/MoreBugUrl/lib/Phabricator.pm b/extensions/MoreBugUrl/lib/Phabricator.pm new file mode 100644 index 000000000..818d9af8f --- /dev/null +++ b/extensions/MoreBugUrl/lib/Phabricator.pm @@ -0,0 +1,41 @@ +# 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::MoreBugUrl::Phabricator; + +use 5.10.1; +use strict; +use warnings; + +use parent qw(Bugzilla::BugUrl); + +############################### +#### Methods #### +############################### + +sub should_handle { + my ($class, $uri) = @_; + return ($uri->path =~ m|^/T\d+$|) ? 1 : 0; +} + +sub _check_value { + my $class = shift; + + my $uri = $class->SUPER::_check_value(@_); + + # Phabricator URLs have only one form: + # http://example.com/T111 + + # Make sure there are no query parameters. + $uri->query(undef); + # And remove any # part if there is one. + $uri->fragment(undef); + + return $uri; +} + +1; diff --git a/extensions/MoreBugUrl/template/en/default/hook/global/user-error-bug_url_invalid_tracker.html.tmpl b/extensions/MoreBugUrl/template/en/default/hook/global/user-error-bug_url_invalid_tracker.html.tmpl index 7e544ef21..2ac6f89a5 100644 --- a/extensions/MoreBugUrl/template/en/default/hook/global/user-error-bug_url_invalid_tracker.html.tmpl +++ b/extensions/MoreBugUrl/template/en/default/hook/global/user-error-bug_url_invalid_tracker.html.tmpl @@ -14,3 +14,4 @@ <li>A b[% %]ug on b[% %]ugs.php.net.</li> <li>An issue in a Redmine installation.</li> <li>A b[% %]ug in a Savane installation.</li> +<li>A task in a Phabricator installation.</li> |