Mercurial > moin > 2.0
changeset 2228:c992a1dda217
Merged thomaswaldmann/moin-2.0 into default
author | Ashutosh Singla <ashu1461@gmail.com> |
---|---|
date | Mon, 22 Jul 2013 22:51:34 +0530 |
parents | 00debb5be61a (current diff) 78ed0ce6b718 (diff) |
children | 63bc1dd3d321 |
files | MoinMoin/apps/frontend/views.py MoinMoin/constants/keys.py MoinMoin/items/__init__.py MoinMoin/templates/common.js MoinMoin/templates/ticket.html |
diffstat | 19 files changed, 196 insertions(+), 117 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Sat Jul 20 23:54:16 2013 +0530 +++ b/.hgignore Mon Jul 22 22:51:34 2013 +0530 @@ -8,6 +8,8 @@ ^moin.egg-info/ ^MoinMoin/_tests/wiki/data/cache/ ^wiki/data/cache/ +^wiki/data/default/data/ +^wiki/data/default/meta/ ^wiki/data/content/ ^wiki/data/userprofiles/ ^wiki/index/
--- a/MoinMoin/apps/frontend/views.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/apps/frontend/views.py Mon Jul 22 22:51:34 2013 +0530 @@ -1168,12 +1168,29 @@ if 'username' in request.values and 'token' in request.values: u = user.User(auth_username=request.values['username']) token = request.values['token'] - if u and u.disabled and token and u.validate_recovery_token(token): - u.profile[DISABLED] = False + success = False + if u and token and u.validate_recovery_token(token): + unvalidated_email = u.profile[EMAIL_UNVALIDATED] + if (app.cfg.user_email_unique and + user.search_users(**{EMAIL: unvalidated_email})): + msg = _('This email is already in use.') + else: + if u.disabled: + u.profile[DISABLED] = False + msg = _('Your account has been activated, you can log in now.') + else: + msg = _('Your new email address has been confirmed.') + u.profile[EMAIL] = unvalidated_email + del u.profile[EMAIL_UNVALIDATED] + del u.profile[RECOVERPASS_KEY] + success = True + else: + msg = _('Your username and/or token is invalid!') + if success: u.save() - flash(_("Your account has been activated, you can log in now."), "info") + flash(msg, 'info') else: - flash(_('Your username and/or token is invalid!'), "error") + flash(msg, 'error') return redirect(url_for('.show_root')) @@ -1539,21 +1556,19 @@ flaskg.user.profile[k] = v if (part == 'notification' and app.cfg.user_email_verification and form['email'].value != user_old_email): - # disable account - flaskg.user.profile[DISABLED] = True + flaskg.user.profile[EMAIL] = user_old_email + flaskg.user.profile[EMAIL_UNVALIDATED] = form['email'].value # send verification mail is_ok, msg = flaskg.user.mail_email_verification() if is_ok: - flaskg.user.logout_session() - response['flash'].append((_('Your account has been disabled because you changed your ' - 'email address. Please see the email we sent to your ' - 'address to reactivate it.'), "info")) + response['flash'].append( + (_('A confirmation email has been sent to your ' + 'newly configured email address.'), "info")) response['redirect'] = url_for('.show_root') else: - # sending the verification email didn't work. reset email change and alert the user. - flaskg.user.profile[DISABLED] = False - flaskg.user.profile[EMAIL] = user_old_email - flaskg.user.save() + # sending the verification email didn't work. + # delete the unvalidated email and alert the user. + del flaskg.user.profile[EMAIL_UNVALIDATED] response['flash'].append((_('Your email address was not changed because sending the ' 'verification email failed. Please try again later.'), "error"))
--- a/MoinMoin/config/default.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/config/default.py Mon Jul 22 22:51:34 2013 +0530 @@ -502,6 +502,7 @@ RESULTS_PER_PAGE: 0, LOCALE: None, # None -> do browser language detection, otherwise just use this locale TIMEZONE: None, # None -> use cfg.timezone_default + EMAIL_UNVALIDATED: None, }, 'Default attributes of the user object'), )), # ==========================================================================
--- a/MoinMoin/constants/keys.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/constants/keys.py Mon Jul 22 22:51:34 2013 +0530 @@ -71,7 +71,7 @@ QUICKLINKS = u"quicklinks" SESSION_KEY = u"session_key" SESSION_TOKEN = u"session_token" -RECOVERPASS_KEY = u"recoverpass_key" +RECOVERPASS_KEY = u"recoverpass_key" # TODO: this is used for email confirmation as well, maybe it needs better name EDIT_ON_DOUBLECLICK = u"edit_on_doubleclick" SCROLL_PAGE_AFTER_EDIT = u"scroll_page_after_edit" SHOW_COMMENTS = u"show_comments" @@ -82,6 +82,7 @@ WANT_TRIVIAL = u"want_trivial" EMAIL_SUBSCRIBED_EVENTS = u"email_subscribed_events" DISABLED = u"disabled" +EMAIL_UNVALIDATED = u"email_unvalidated" # in which backend is some revision stored? BACKENDNAME = u"backendname"
--- a/MoinMoin/converter/_tests/test_docbook_in.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/converter/_tests/test_docbook_in.py Mon Jul 22 22:51:34 2013 +0530 @@ -256,13 +256,13 @@ def test_link(self): data = [ # Normal link, with conversion of all the xlink attributes - ('<article><para><link xlink:href="uri:test" xlink:title="title">link</link></para></article>', - # <page><body><div html:class="article"><p><a xlink:href="uri:test" xlink:title="title">link</a></p></div></body></page> - '/page/body/div/p/a[@xlink:href="uri:test"][@xlink:title="title"][text()="link"]'), + ('<article><para><link xlink:href="http:test" xlink:title="title">link</link></para></article>', + # <page><body><div html:class="article"><p><a xlink:href="http:test" xlink:title="title">link</a></p></div></body></page> + '/page/body/div/p/a[@xlink:href="http:test"][@xlink:title="title"][text()="link"]'), # Old link from DocBook v.4.X for backward compatibility - ('<article><para><ulink url="url:test">link</ulink></para></article>', - # <page><body><div html:class="article"><p><a xlink:href="url:test">link</a></p></div></body></page> - '/page/body/div/p/a[@xlink:href="url:test"][text()="link"]'), + ('<article><para><ulink url="http:test">link</ulink></para></article>', + # <page><body><div html:class="article"><p><a xlink:href="http:test">link</a></p></div></body></page> + '/page/body/div/p/a[@xlink:href="http:test"][text()="link"]'), # Normal link, with linkend attribute ('<article><para><link linkend="anchor">link</link></para></article>', # <page><body><div html:class="article"><p><a xlink:href="#anchor">link</a></p></div></body></page> @@ -273,8 +273,10 @@ '/page/body/div/p/a[@xlink:href="uri#anchor"][text()="link"]'), # Link w/ javascript: scheme ('<article><para><ulink url="javascript:alert(\'xss\')">link</ulink></para></article>', - # <page><body><div html:class="article"><p><a xlink:href="url:test">link</a></p></div></body></page> - '/page/body/div/p/a[@xlink:href=""][text()="link"]'), + # the href attribute will default to None because javascript is not an allowed url scheme + # we don't care how it gets rendered as long as the javascript doesn't show up + # <page><body><div html:class="article"><p><a xlink:href="None">link</a></p></div></body></page> + '/page/body/div/p/a[@xlink:href="None"][text()="link"]'), ] for i in data: yield (self.do, ) + i
--- a/MoinMoin/items/__init__.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/items/__init__.py Mon Jul 22 22:51:34 2013 +0530 @@ -442,11 +442,11 @@ # just destroy this revision self.rev.item.destroy_revision(self.rev.revid) - def modify(self, meta, data, comment=u'', contenttype_guessed=None, contenttype_qs=None): - if contenttype_qs: - # we use querystring param to FORCE content type - meta[CONTENTTYPE] = contenttype_qs - + def modify(self, meta, data, comment=u'', contenttype_guessed=None, **update_meta): + meta = dict(meta) # we may get a read-only dict-like, copy it + # get rid of None values + update_meta = {key:value for key, value in update_meta.items() if value is not None} + meta.update(update_meta) return self._save(meta, data, contenttype_guessed=contenttype_guessed, comment=comment) class _ModifyForm(BaseModifyForm): @@ -790,7 +790,7 @@ meta, data, contenttype_guessed, comment = form._dump(self) contenttype_qs = request.values.get('contenttype') try: - self.modify(meta, data, comment, contenttype_guessed, contenttype_qs) + self.modify(meta, data, comment, contenttype_guessed, **{CONTENTTYPE: contenttype_qs}) except AccessDenied: abort(403) else:
--- a/MoinMoin/items/_tests/test_Item.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/items/_tests/test_Item.py Mon Jul 22 22:51:34 2013 +0530 @@ -352,6 +352,25 @@ item.meta['test_key'] assert item.meta['another_test_key'] == another_meta['another_test_key'] assert item.content.data == another_data + # add/update meta + another_meta = { + 'test_key': 'test_value', + 'another_test_key': 'another_test_value', + } + item.modify(another_meta, another_data) + item = Item.create(name) + update_meta = { + 'another_test_key': 'updated_test_value', + 'new_test_key': 'new_test_value', + 'none_test_key': None, + } + item.modify(another_meta, another_data, **update_meta) + item = Item.create(name) + assert item.name == u'Test_Item' + assert item.meta['test_key'] == another_meta['test_key'] + assert item.meta['another_test_key'] == update_meta['another_test_key'] + assert item.meta['new_test_key'] == update_meta['new_test_key'] + assert 'none_test_key' not in item.meta coverage_modules = ['MoinMoin.items']
--- a/MoinMoin/items/ticket.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/items/ticket.py Mon Jul 22 22:51:34 2013 +0530 @@ -138,7 +138,8 @@ itemtype = ITEMTYPE_TICKET display_name = L_('Ticket') description = L_('Ticket item') - modify_template = 'ticket.html' + submit_template = 'ticket/submit.html' + modify_template = 'ticket/modify.html' def do_show(self, revid): if revid != CURRENT: @@ -169,7 +170,7 @@ # XXX When creating new item, suppress the "foo doesn't exist. Create it?" dummy content data_rendered = None if is_new else Markup(self.content._render_data()) - return render_template(self.modify_template, + return render_template(self.submit_template if is_new else self.modify_template, is_new=is_new, closed=closed, item_name=self.name,
--- a/MoinMoin/templates/base.html Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/templates/base.html Mon Jul 22 22:51:34 2013 +0530 @@ -41,6 +41,11 @@ {% endblock %} {% block head_links %} + + {% block bootstrap_stylesheet %} + <link rel="stylesheet" href="{{ url_for('serve.files', name='bootstrap', filename='bootstrap/css/bootstrap.css') }}" /> + {% endblock %} + <link rel="shortcut icon" href="{{ url_for('static', filename='logos/favicon.ico') }}" /> {% block theme_stylesheets %}
--- a/MoinMoin/templates/common.js Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/templates/common.js Mon Jul 22 22:51:34 2013 +0530 @@ -587,7 +587,7 @@ // is option to scroll page after edit set? if (document.getElementById('moin-scroll-page-after-edit')) { // add click handler to OK (save) button to capture position of caret in textarea - $("#f_submit").click(function () { + $("#moin-save-text-button").click(function () { caretLineno = getCaretLineno(document.getElementById('f_content_form_data_text')); // save lineno for use in "show" page load if (caretLineno > 0) { sessionStorage.moinCaretLineNo = caretLineno; }
--- a/MoinMoin/templates/mail/account_verification.txt Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/templates/mail/account_verification.txt Mon Jul 22 22:51:34 2013 +0530 @@ -1,10 +1,11 @@ {{ _("""\ -Somebody has created an account with this email address. +An account with this email address has been created or +an existing account has been changed to use this email address. Please use the link below to verify your email address: %(link)s -If you didn't create this account, please ignore this email. +Please ignore this email if you didn't initiate this action. -""", link=link) }} \ No newline at end of file +""", link=link) }}
--- a/MoinMoin/templates/modify.html Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/templates/modify.html Mon Jul 22 22:51:34 2013 +0530 @@ -40,7 +40,7 @@ POSTs originate from their respective applets. #} {% if not form['content_form'].is_draw %} - {{ forms.render_submit(form) }} + {{ forms.render_submit(form, id='moin-save-text-button') }} <dl> {{ forms.render_textcha(gen, form) }} {{ forms.render(form['comment']) }}
--- a/MoinMoin/templates/ticket.html Sat Jul 20 23:54:16 2013 +0530 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -{% import "forms.html" as forms %} -{% extends theme("layout.html") %} - -{% if is_new %} - {% set title = _("Creating new ticket: '%(item_name)s'", item_name=item_name) %} -{% else %} - {% set title = _("Ticket: '%(item_name)s'", item_name=item_name) %} -{% endif %} - -{% block head %} - {{ super() }} - <link media="all" rel="stylesheet" href="{{ url_for('static', filename='css/ticket.css') }}" /> -{% endblock %} - -{% block content %} -<h1> - {{ title }} - {% if closed %} - {# TODO style .moin-ticket-closed #} - <span class="moin-ticket-closed">{{ _("(Closed)") }}</span> - {% endif %} -</h1> -<div class="moin-form" id="moin-ticket-form"> - {{ gen.form.open(form, method='post', enctype='multipart/form-data') }} - - {% if data_rendered %} - <div id="moin-content-data"> - {{ data_rendered }} - </div> - {% endif %} - - {% if is_new %} - <h2>Describe the ticket</h2> - {% else %} - <h2>Add comment</h2> - {% endif %} - <dl> - {{ forms.render(form['message']) }} - </dl> - - <h2>Edit metadata</h2> - <dl> - {{ forms.render_errors(form) }} - {% for e in [ - 'summary', - 'effort', - 'difficulty', - 'severity', - 'priority', - 'tags', - 'assigned_to', - 'superseded_by', - 'depends_on', - ] %} - {{ forms.render(form['meta'][e]) }} - {% endfor %} - </dl> - - {# see comments concerning the submit button within TicketForm in items/ticket.py #} - {% if is_new %} - {{ forms.render_submit(form) }} - {% else %} - {{ forms.render(form['submit']) }} - {% endif %} - - <h2>Back references</h2> - <dl> - {% for e in [ - 'supersedes', - 'required_by', - 'subscribers', - ] %} - {{ forms.render(form['backrefs'][e]) }} - {% endfor %} - - {{ gen.form.close() }} -</div> -{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MoinMoin/templates/ticket/base.html Mon Jul 22 22:51:34 2013 +0530 @@ -0,0 +1,58 @@ +{% import "forms.html" as forms %} +{% extends theme("layout.html") %} + +{% macro render_meta() %} + {% for e in [ + 'summary', + 'effort', + 'difficulty', + 'severity', + 'priority', + 'tags', + 'assigned_to', + 'superseded_by', + 'depends_on', + ] %} + {{ forms.render(form['meta'][e]) }} + {% endfor %} +{% endmacro %} + +{% macro render_backref() %} + {% for e in [ + 'supersedes', + 'required_by', + 'subscribers', + ] %} + {{ forms.render(form['backrefs'][e]) }} + {% endfor %} +{% endmacro %} + +{% block head %} + {{ super() }} + <link media="all" rel="stylesheet" href="{{ url_for('static', filename='css/ticket.css') }}" /> +{% endblock %} + +{% block content %} +<h1> + {% block title_text %} + {% endblock %} + {% if closed %} + {# TODO style .moin-ticket-closed #} + <span class="moin-ticket-closed">{{ _("(Closed)") }}</span> + {% endif %} +</h1> +<div class="moin-form" id="moin-ticket-form"> + {{ gen.form.open(form, method='post', enctype='multipart/form-data') }} + + {% if data_rendered %} + <div id="moin-content-data"> + {{ data_rendered }} + </div> + {% endif %} + + {% block form_controls %} + {% endblock %} + + {{ gen.form.close() }} +</div> +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MoinMoin/templates/ticket/modify.html Mon Jul 22 22:51:34 2013 +0530 @@ -0,0 +1,25 @@ +{% extends "ticket/base.html" %} + +{% block title_text %} + {{ _("Ticket: '%(item_name)s'", item_name=item_name) }} +{% endblock %} + +{% block form_controls %} + <h2>{{ _("Add comment") }}</h2> + <dl> + {{ forms.render(form['message']) }} + </dl> + + <h2>{{ _("Edit metadata") }}</h2> + <dl> + {{ forms.render_errors(form) }} + {{ render_meta() }} + </dl> + + {{ forms.render(form['submit']) }} + + <h2>{{ _("Back references") }}</h2> + <dl> + {{ render_backref() }} + </dl> +{% endblock %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MoinMoin/templates/ticket/submit.html Mon Jul 22 22:51:34 2013 +0530 @@ -0,0 +1,21 @@ +{% extends "ticket/base.html" %} + +{% block title_text %} + {{ _("Creating new ticket: '%(item_name)s'", item_name=item_name) }} +{% endblock %} + +{% block form_controls %} + <h2>{{ _("Describe the ticket") }}</h2> + + <dl> + {{ forms.render(form['message']) }} + </dl> + + <h2>{{ _("Provide metadata") }}</h2> + <dl> + {{ forms.render_errors(form) }} + {{ render_meta() }} + </dl> + + {{ forms.render_submit(form) }} +{% endblock %}
--- a/MoinMoin/user.py Sat Jul 20 23:54:16 2013 +0530 +++ b/MoinMoin/user.py Mon Jul 22 22:51:34 2013 +0530 @@ -81,8 +81,9 @@ if validate and email and app.cfg.user_email_unique: if search_users(email=email): return _("This email already belongs to somebody else.") - - theuser.profile[EMAIL] = email + theuser.profile[EMAIL_UNVALIDATED] = email + else: + theuser.profile[EMAIL] = email # Openid should be unique if validate and openid and search_users(openid=openid): @@ -786,5 +787,8 @@ subject = _('[%(sitename)s] Please verify your email address', sitename=self._cfg.sitename or "Wiki") - mailok, msg = sendmail.sendmail(subject, text, to=[self.email], mail_from=self._cfg.mail_from) + email = self.profile[EMAIL_UNVALIDATED] + mailok, msg = sendmail.sendmail(subject, text, to=[email], mail_from=self._cfg.mail_from) return mailok, msg + + self._mail_email_verification(email=self.email)
--- a/setup.py Sat Jul 20 23:54:16 2013 +0530 +++ b/setup.py Mon Jul 22 22:51:34 2013 +0530 @@ -107,6 +107,7 @@ 'pdfminer', # pdf -> text/plain conversion 'passlib>=1.6.0', # strong password hashing (1.6 needed for consteq) 'XStatic>=0.0.2', # support for static file pypi packages + 'XStatic-Bootstrap>=2.1.0.1', 'XStatic-CKEditor>=3.6.1.2', 'XStatic-jQuery>=1.8.2', 'XStatic-jQuery-File-Upload>=4.4.2',