Indefero

Indefero Commit Details


Date:2008-07-31 15:50:21 (16 years 4 months ago)
Author:Loic d'Anterroches
Branch:dev, develop, feature-issue_links, feature.better-home, feature.content-md5, feature.diff-whitespace, feature.download-md5, feature.issue-links, feature.issue-of-others, feature.issue-summary, feature.search-filter, feature.webrepos, feature.wiki-default-page, master, newdiff, release-1.1, release-1.2, release-1.3, svn
Commit:1b3a42940d30abb342d9c4b8ff166a586701b784
Parents: 416d13e249da7d8717ebb15966b9dbbd5c0188ba
Message:Added the registration procedure.

Changes:

File differences

src/IDF/Form/Register.php
107107
108108
109109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
110141
111142
if (!$this->isValid()) {
throw new Exception(__('Cannot save the model from an invalid form.'));
}
$user = new Pluf_User();
$user->first_name = '---'; // with both this set and
// active==false we can find later
// on, all the unconfirmed accounts
// that could be purged.
$user->last_name = $this->cleaned_data['login'];
$user->login = $this->cleaned_data['login'];
$user->email = $this->cleaned_data['email'];
$user->active = false;
$user->create();
$from_email = Pluf::f('from_email');
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
$encrypted = trim($cr->encrypt($user->email.':'.$user->id), '~');
$key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
$url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::registerConfirmation', array($key), array(), false);
$urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey', array(), array(), false);
$context = new Pluf_Template_Context(
array('key' => $key,
'url' => $url,
'urlik' => $urlik,
'user'=> $user,
)
);
$tmpl = new Pluf_Template('register/confirmation-email.txt');
$text_email = $tmpl->render($context);
$email = new Pluf_Mail($from_email, $user->email,
__('Confirm the creation of your account.'));
$email->addTextMessage($text_email);
$email->sendMail();
return $user;
}
}
src/IDF/Form/RegisterConfirmation.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 CĂ©ondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
/**
* Confirmation of the form.
*
*/
class IDF_Form_RegisterConfirmation extends Pluf_Form
{
public $_user = null;
public function initFields($extra=array())
{
$this->_user = $extra['user'];
$this->fields['key'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Your confirmation key'),
'initial' => $extra['key'],
'widget' => 'Pluf_Form_Widget_HiddenInput',
'widget_attrs' => array(
'readonly' => 'readonly',
),
));
$this->fields['first_name'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('First name'),
'initial' => '',
'widget_attrs' => array(
'maxlength' => 50,
'size' => 15,
),
));
$this->fields['last_name'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Last name'),
'initial' => '',
'widget_attrs' => array(
'maxlength' => 50,
'size' => 15,
),
));
$this->fields['password'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Your password'),
'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput',
'help_text' => __('Your password must be hard for other people to find it, but easy for you to remember.'),
'widget_attrs' => array(
'maxlength' => 50,
'size' => 15,
),
));
$this->fields['password2'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Confirm your password'),
'initial' => '',
'widget' => 'Pluf_Form_Widget_PasswordInput',
'widget_attrs' => array(
'maxlength' => 50,
'size' => 15,
),
));
}
/**
* Just a simple control.
*/
public function clean_key()
{
$this->cleaned_data['key'] = trim($this->cleaned_data['key']);
$error = __('We are sorry but this confirmation key is not valid. Maybe you should directly copy/paste it from your confirmation email.');
if (false === ($email_id=IDF_Form_RegisterInputKey::checkKeyHash($this->cleaned_data['key']))) {
throw new Pluf_Form_Invalid($error);
}
$guser = new Pluf_User();
$sql = new Pluf_SQL('email=%s AND id=%s', $email_id);
$users = $guser->getList(array('filter' => $sql->gen()));
if ($users->count() != 1) {
throw new Pluf_Form_Invalid($error);
}
if ($users[0]->active) {
throw new Pluf_Form_Invalid(__('This account has already been confirmed. Maybe should you try to recover your password using the help link.'));
}
$this->_user_id = $email_id[1];
return $this->cleaned_data['key'];
}
/**
* Check the passwords.
*/
public function clean()
{
if ($this->cleaned_data['password'] != $this->cleaned_data['password2']) {
throw new Pluf_Form_Invalid(__('The two passwords must be the same.'));
}
return $this->cleaned_data;
}
/**
* Save the model in the database.
*
* @param bool Commit in the database or not. If not, the object
* is returned but not saved in the database.
* @return Object Model with data set from the form.
*/
function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save an invalid form.'));
}
$this->_user->setFromFormData($this->cleaned_data);
$this->_user->active = true;
$this->_user->administrator = false;
$this->_user->staff = false;
if ($commit) {
$this->_user->update();
}
return $this->_user;
}
}
src/IDF/Form/RegisterInputKey.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 CĂ©ondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
Pluf::loadFunction('Pluf_HTTP_URL_urlForView');
/**
* Check the validity of a confirmation key.
*
*/
class IDF_Form_RegisterInputKey extends Pluf_Form
{
public function initFields($extra=array())
{
$this->fields['key'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Your confirmation key'),
'initial' => '',
'widget_attrs' => array(
'size' => 50,
),
));
}
/**
* Validate the key.
*/
public function clean_key()
{
$this->cleaned_data['key'] = trim($this->cleaned_data['key']);
$error = __('We are sorry but this confirmation key is not valid. Maybe you should directly copy/paste it from your confirmation email.');
if (false === ($email_id=self::checkKeyHash($this->cleaned_data['key']))) {
throw new Pluf_Form_Invalid($error);
}
$guser = new Pluf_User();
$sql = new Pluf_SQL('email=%s AND id=%s', $email_id);
if ($guser->getCount(array('filter' => $sql->gen())) != 1) {
throw new Pluf_Form_Invalid($error);
}
return $this->cleaned_data['key'];
}
/**
* Save the model in the database.
*
* @param bool Commit in the database or not. If not, the object
* is returned but not saved in the database.
* @return string Url to redirect to the form.
*/
function save($commit=true)
{
if (!$this->isValid()) {
throw new Exception(__('Cannot save an invalid form.'));
}
return Pluf_HTTP_URL_urlForView('IDF_Views::registerConfirmation',
array($this->cleaned_data['key']));
}
/**
* Return false or an array with the email and id.
*
* This is a static function to be reused by other forms.
*
* @param string Confirmation key
* @return mixed Either false or array(email, id)
*/
public static function checkKeyHash($key)
{
$hash = substr($key, 0, 2);
$encrypted = substr($key, 2);
if ($hash != substr(md5(Pluf::f('secret_key').$encrypted), 0, 2)) {
return false;
}
$cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
return split(':', $cr->decrypt($encrypted), 2);
}
}
src/IDF/Views.php
8282
8383
8484
85
86
85
86
8787
8888
8989
9090
9191
9292
93
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
94161
162
95163
96164
97165
if ($request->method == 'POST') {
$form = new IDF_Form_Register($request->POST);
if ($form->isValid()) {
$user = $form->save();
$url = Pluf_HTTP_URL_urlForView('IDF_Views::registerConfirmation');
$user = $form->save(); // It is sending the confirmation email
$url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$init = (isset($request->GET['login'])) ? array('initial' => array('login' => $request->GET['login'])) : array();
$form = new IDF_Form_Register(null, $init);
}
return Pluf_Shortcuts_RenderToResponse('register.html',
return Pluf_Shortcuts_RenderToResponse('register/index.html',
array('page_title' => $title,
'form' => $form),
$request);
}
/**
* Input the registration confirmation key.
*
* Very simple view just to redirect to the register confirmation
* views to input the password.
*/
function registerInputKey($request, $match)
{
$title = __('Confirm Your Account Creation');
if ($request->method == 'POST') {
$form = new IDF_Form_RegisterInputKey($request->POST);
if ($form->isValid()) {
$url = $form->save();
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_RegisterInputKey();
}
return Pluf_Shortcuts_RenderToResponse('register/inputkey.html',
array('page_title' => $title,
'form' => $form),
$request);
}
/**
* Registration confirmation.
*
* Input first/last name, password and sign in the user.
*
* Maybe in the future send the user to its personal page for
* customization.
*/
function registerConfirmation($request, $match)
{
$title = __('Confirm Your Account Creation');
$key = $match[1];
// first "check", full check is done in the form.
$email_id = IDF_Form_RegisterInputKey::checkKeyHash($key);
if (false == $email_id) {
$url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey');
return new Pluf_HTTP_Response_Redirect($url);
}
$user = new Pluf_User($email_id[1]);
$extra = array('key' => $key,
'user' => $user);
if ($request->method == 'POST') {
$form = new IDF_Form_RegisterConfirmation($request->POST, $extra);
if ($form->isValid()) {
$user = $form->save();
$request->user = $user;
$request->session->clear();
$request->session->setData('login_time', gmdate('Y-m-d H:i:s'));
$user->last_login = gmdate('Y-m-d H:i:s');
$user->update();
$request->user->setMessage(__('Welcome! You can now participate in the life of your project of choice.'));
$url = Pluf_HTTP_URL_urlForView('IDF_Views::index');
return new Pluf_HTTP_Response_Redirect($url);
}
} else {
$form = new IDF_Form_RegisterConfirmation(null, $extra);
}
return Pluf_Shortcuts_RenderToResponse('register/confirmation.html',
array('page_title' => $title,
'new_user' => $user,
'form' => $form),
$request);
}
src/IDF/conf/views.php
4242
4343
4444
45
46
47
48
49
50
51
52
53
54
55
56
4557
4658
4759
'model' => 'IDF_Views',
'method' => 'register');
$ctl[] = array('regex' => '#^/register/k/(.*)/$#',
'base' => $base,
'priority' => 4,
'model' => 'IDF_Views',
'method' => 'registerConfirmation');
$ctl[] = array('regex' => '#^/register/ik/$#',
'base' => $base,
'priority' => 4,
'model' => 'IDF_Views',
'method' => 'registerInputKey');
$ctl[] = array('regex' => '#^/logout/$#',
'base' => $base,
'priority' => 4,
src/IDF/templates/register.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
{extends "base-simple.html"}
{block body}
{if $form.errors}
<div class="px-message-error">
<p>{trans 'Oups, please check the provided login and email address to register.'}</p>
{if $form.get_top_errors}
{$form.render_top_errors|unsafe}
{/if}
</div>
{/if}
<form method="post" action=".">
<table class="form" summary="">
<tr>
<th><strong>{$form.f.login.labelTag}:</strong></th>
<td>{if $form.f.login.errors}{$form.f.login.fieldErrors}{/if}
{$form.f.login|unsafe}<br />
<span class="helptext">{$form.f.login.help_text}</span>
</td>
</tr>
<tr>
<th><strong>{$form.f.email.labelTag}:</strong></th>
<td>{if $form.f.email.errors}{$form.f.email.fieldErrors}{/if}
{$form.f.email|unsafe}<br />
<span class="helptext">{$form.f.email.help_text}</span>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
{if $form.f.terms.errors}{$form.f.terms.fieldErrors}{/if}
{$form.f.terms|unsafe} <strong>{$form.f.terms.labelTag}</strong><br />
<span class="helptext">{blocktrans}Read the <a href="#">terms and conditions</a> (basically <em>"Please be nice, we respect you.")</em>{/blocktrans}</span>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="{trans 'Create Your Account'}" name="submit" /> | <a href="{url 'IDF_Views::index'}">{trans 'Cancel'}</a>
</td>
</tr>
</table>
</form>
{/block}
{block context}
<div class="issue-submit-info">
<p>{trans 'Be sure to provide a valid email address, as we are sending a validation link by email.'}</p>
<p><strong>{trans 'Did you know?'}</strong><br />
{aurl 'url', 'IDF_Views::faq'}
{blocktrans}With your account, you will able to participate in the life of all the projects hosted here. Participating in a software project must be fun, so if you have troubles, you can <a href="{$url}">let us know about your issues at anytime</a>!{/blocktrans}
</div>
<script type="text/javascript">
document.getElementById('id_login').focus()
</script>
{/block}
{block javascript}{include 'issues/js-autocomplete.html'}{/block}
src/IDF/templates/register/confirmation-email.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{blocktrans}Hello,
You have requested the creation of an account to
participate in the life of a software project.
To confirm the account please follow this link:
{$url|safe}
Alternatively, go on this page:
{$urlik|safe}
and provide the following confirmation key:
{$key}
If you are not interested any longer in getting
part in the life of the software project or if
you can't remember having requested the creation
of an accout, please excuse us and simply ignore
this email.
Yours faithfully,
The development team.
{/blocktrans}
src/IDF/templates/register/confirmation.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{extends "base-simple.html"}
{block body}
{if $form.errors}
<div class="px-message-error">
<p>{trans 'Oups, please check the form for errors.'}</p>
{if $form.get_top_errors}
{$form.render_top_errors|unsafe}
{/if}
{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if}
</div>
{/if}
<form method="post" action=".">
<table class="form" summary="">
<tr>
<th><strong>{trans 'Login:'}</strong></th>
<td>{$new_user.login}</td>
</tr>
<tr>
<th><strong>{trans 'Email:'}</strong></th>
<td>{$new_user.email}</td>
</tr>
<tr>
<th>{$form.f.first_name.labelTag}:</th>
<td>{if $form.f.first_name.errors}{$form.f.first_name.fieldErrors}{/if}
{$form.f.first_name|unsafe}
</td>
</tr>
<tr>
<th><strong>{$form.f.last_name.labelTag}:</strong></th>
<td>{if $form.f.last_name.errors}{$form.f.last_name.fieldErrors}{/if}
{$form.f.last_name|unsafe}
</td>
</tr>
<tr>
<th><strong>{$form.f.password.labelTag}:</strong></th>
<td>{if $form.f.password.errors}{$form.f.password.fieldErrors}{/if}
{$form.f.password|unsafe}<br />
<span class="helptext">{$form.f.password.help_text}</span>
</td>
</tr>
<tr>
<th><strong>{$form.f.password2.labelTag}:</strong></th>
<td>{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if}
{$form.f.password2|unsafe}
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="{trans 'Enable Your Account'}" name="submit" /> | <a href="{url 'IDF_Views::index'}">{trans 'Cancel'}</a>
</td>
</tr>
</table>{$form.f.key|unsafe}
</form>
{/block}
{block context}
<div class="issue-submit-info">
<p>{trans 'This is the last step, but just <strong>be sure to have the cookies enabled</strong> to log in afterwards.'}</p>
</div>
{/block}
{block javascript}<script type="text/javascript">
document.getElementById('id_first_name').focus()
</script>
{include 'issues/js-autocomplete.html'}{/block}
src/IDF/templates/register/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
{extends "base-simple.html"}
{block body}
{if $form.errors}
<div class="px-message-error">
<p>{trans 'Oups, please check the provided login and email address to register.'}</p>
{if $form.get_top_errors}
{$form.render_top_errors|unsafe}
{/if}
</div>
{/if}
<form method="post" action=".">
<table class="form" summary="">
<tr>
<th><strong>{$form.f.login.labelTag}:</strong></th>
<td>{if $form.f.login.errors}{$form.f.login.fieldErrors}{/if}
{$form.f.login|unsafe}<br />
<span class="helptext">{$form.f.login.help_text}</span>
</td>
</tr>
<tr>
<th><strong>{$form.f.email.labelTag}:</strong></th>
<td>{if $form.f.email.errors}{$form.f.email.fieldErrors}{/if}
{$form.f.email|unsafe}<br />
<span class="helptext">{$form.f.email.help_text}</span>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
{if $form.f.terms.errors}{$form.f.terms.fieldErrors}{/if}
{$form.f.terms|unsafe} <strong>{$form.f.terms.labelTag}</strong><br />
<span class="helptext">{blocktrans}Read the <a href="#">terms and conditions</a> &ndash; basically <em>"Please be nice, we respect you"</em>.{/blocktrans}</span>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="{trans 'Create Your Account'}" name="submit" /> | <a href="{url 'IDF_Views::index'}">{trans 'Cancel'}</a>
</td>
</tr>
</table>
</form>
{/block}
{block context}
<div class="issue-submit-info">
<p>{trans 'Be sure to provide a valid email address, as we are sending a validation link by email.'}</p>
<p><strong>{trans 'Did you know?'}</strong><br />
{aurl 'url', 'IDF_Views::faq'}
{blocktrans}With your account, you will able to participate in the life of all the projects hosted here. Participating in a software project must be fun, so if you have troubles, you can <a href="{$url}">let us know about your issues at anytime</a>!{/blocktrans}
</div>
{/block}
{block javascript}<script type="text/javascript">
document.getElementById('id_login').focus()
</script>
{include 'issues/js-autocomplete.html'}{/block}
src/IDF/templates/register/inputkey.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{extends "base-simple.html"}
{block body}
{if $form.errors}
<div class="px-message-error">
<p>{trans 'Oups, we found an error in the form.'}</p>
{if $form.get_top_errors}
{$form.render_top_errors|unsafe}
{/if}
</div>
{/if}
<form method="post" action=".">
<table class="form" summary="">
<tr>
<td>&nbsp;</td>
<td><strong>{$form.f.key.labelTag}:</strong><br />
{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if}
{$form.f.key|unsafe}
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><input type="submit" value="{trans 'Confirm Your Account'}" name="submit" /> | <a href="{url 'IDF_Views::index'}">{trans 'Cancel'}</a>
</td>
</tr>
</table>
</form>
{/block}
{block context}
<div class="issue-submit-info">
<h2>{trans 'Instructions'}</h2>
<p>{trans 'Use your email software to read your emails and open your confirmation email. Either click directly on the confirmation link or copy/paste the confirmation key in the box and submit the form.'}</p>
<p>{trans 'Just after providing the confirmation key, you will be able to set your password and start using this website fully.'}</p>
</div>
{/block}
{block javascript}<script type="text/javascript">
document.getElementById('id_key').focus()
</script>
{include 'issues/js-autocomplete.html'}{/block}
www/media/idf/css/style.css
174174
175175
176176
177
178
179
180
177181
178182
179183
margin-bottom: 1em;
}
div.issue-submit-info h2 {
margin-top: 0;
}
span.label {
color: #204a87;
padding-left: 0.5em;

Archive Download the corresponding diff file

Page rendered in 0.11241s using 13 queries.