Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

users: create user record on registration #235

Merged
merged 1 commit into from
Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sonar/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def _(x):

# User profiles
# =============
USERPROFILES_EXTEND_SECURITY_FORMS = True
USERPROFILES = False

# Celery configuration
# ====================
Expand Down
9 changes: 8 additions & 1 deletion sonar/modules/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
import jinja2
from flask_assets import Bundle, Environment
from flask_bootstrap import Bootstrap
from flask_security import user_registered
from flask_wiki import Wiki

from sonar.modules.permissions import has_admin_access, has_publisher_access, \
has_superuser_access
from sonar.modules.users.api import current_user_record
from sonar.modules.users.signals import user_registered_handler
from sonar.modules.utils import get_switch_aai_providers, get_view_code

from . import config
Expand All @@ -39,7 +42,8 @@ def utility_processor():
has_superuser_access=has_superuser_access,
ui_version=config.SONAR_APP_UI_VERSION,
aai_providers=get_switch_aai_providers,
view_code=get_view_code())
view_code=get_view_code(),
current_user_record=current_user_record)


class Sonar(object):
Expand Down Expand Up @@ -82,6 +86,9 @@ def init_app(self, app):

app.context_processor(utility_processor)

# Connect to signal sent when a user is created in Flask-Security.
user_registered.connect(user_registered_handler, weak=False)

def init_config(self, app):
"""Initialize configuration."""
for k in dir(config):
Expand Down
10 changes: 8 additions & 2 deletions sonar/modules/users/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,15 @@ def import_users(infile):
password = hash_password(password)
del user_data['password']

if not user_data.get('roles'):
user_data['roles'] = [UserRecord.ROLE_USER]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not having the roles in the fixtures file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally it's the case, it's just to insure that the user as at least the role "user".


roles = user_data.get('roles', []).copy()
if not roles or not isinstance(roles, list):
roles = []

for role in roles:
if not datastore.find_role(role):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this take while it can be afterward with a unique list of collected roles.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really sure, because we need the roles to create user account just after. But maybe yes, we can collect all roles before and create them before creating users.

datastore.create_role(name=role)
datastore.commit()

# Create account and activate it
datastore.create_user(email=email, password=password, roles=roles)
Expand Down
1 change: 0 additions & 1 deletion sonar/modules/users/jsonschemas/users/user-v1.0.0.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@
"full_name",
"email",
"roles",
"organisation",
"$schema"
]
}
44 changes: 44 additions & 0 deletions sonar/modules/users/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
#
# Swiss Open Access Repository
# Copyright (C) 2019 RERO
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Signals for users."""

from sonar.modules.users.api import UserRecord, datastore


def user_registered_handler(app, user, confirm_token):
"""Called when a new user is registered.

:param app: App context.
:param user: User account.
"""
# Add a default role to user
role = datastore.find_role(UserRecord.ROLE_USER)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not doing this in the UserRecord class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not related to UserRecord, but to Flask account created, which has no role.

datastore.add_role_to_user(user, role)
datastore.commit()

# Create user record
user_record = UserRecord.get_user_by_email(user.email)
if not user_record:
user_record = UserRecord.create(
{
'full_name': user.email,
'email': user.email,
'roles': [UserRecord.ROLE_USER]
},
dbcommit=True)
user_record.reindex()
25 changes: 4 additions & 21 deletions sonar/theme/assets/scss/common/_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,8 @@ img.logo {
@extend .text-light
}

// CSS code to allow `ng-csp="no-inline-css"`
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak,
.ng-hide:not(.ng-hide-animate) {
display: none !important;
}

ng\:form {
display: block;
}

.ng-animate-shim {
visibility:hidden;
}

.ng-anchor {
position:absolute;
.standalone-editor {
legend, button.btn-outline-danger {
display: none;
}
}
36 changes: 36 additions & 0 deletions sonar/theme/templates/sonar/accounts/profile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{# -*- coding: utf-8 -*-
Swiss Open Access Repository
Copyright (C) 2019 RERO

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License.

This program 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
#}

{% extends 'sonar/page_settings.html' %}

{%- block settings_body scoped %}
<div class="standalone-editor">
<sonar-root></sonar-root>
</div>
{%- endblock settings_body %}

{%- block javascript %}
<script src="/static/sonar-ui/runtime.js?{{ ui_version }}"></script>
<script src="/static/sonar-ui/polyfills.js?{{ ui_version }}"></script>
<script src="/static/sonar-ui/main.js?{{ ui_version }}"></script>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
{%- endblock javascript %}
2 changes: 0 additions & 2 deletions sonar/theme/templates/sonar/accounts/#.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ <h4 class="text-center mb-4">
<form action="{{ url_for_security('register') }}" method="POST" name="register_user_form">
{{ form_errors(form) }}
{{ form.hidden_tag() }}
{{ render_field(form.profile.full_name, errormsg=False) }}
{{ render_field(form.profile.username, errormsg=False) }}
{{ render_field(form.email, autofocus=True, errormsg=False) }}
{{ render_field(form.password, errormsg=False) }}
{%- if form.password_confirm %}
Expand Down
69 changes: 32 additions & 37 deletions sonar/theme/templates/sonar/page_settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,48 +20,43 @@
{%- block body scoped %}
<div class="container">
<div class="row">
<div class="col-sm-3 col-md-3 col-pad-left-0">
{%- block settings_menu scoped %}
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading"><strong>{{ _('Settings') }}</strong></div>
<ul class="list-group">
{%- for item in current_menu.submenu('settings').children if item.visible %}
{%- block settings_menu_item scoped %}
<a href="{{ item.url }}" class="list-group-item{% if item.active %} active{% endif %}">
{{ item.text|safe }}
</a>
<div class="col-sm-3 col-md-3 col-pad-left-0">
{%- block settings_menu scoped %}
<ul class="list-group">
{%- for item in current_menu.submenu('settings').children if item.visible %}
{%- block settings_menu_item scoped %}
<a href="{{ item.url }}" class="list-group-item{% if item.active %} active{% endif %}">
{{ item.text|safe }}
</a>
{%- endblock %}
{%- endfor %}
</ul>
{%- endblock %}
</div>
<div class="col-sm-9 col-md-9 col-pad-right-0">
{%- block settings_content scoped %}
<div class="panel-group panel-bot-margin">
<div class="panel panel-default">
<div class="panel-heading">
{%- block settings_content_title scoped %}
{%- if panel_icon %}
{%- block settings_content_title_icon scoped %}
<i class="{{panel_icon}}"></i>
{%- endblock %}
{%- endif %}
<strong>{{ panel_title|default("") }}</strong>
{%- endblock %}
{%- endfor %}
</ul>
</div>
</div>
{%- endblock %}
</div>
<div class="col-sm-9 col-md-9 col-pad-right-0">
{%- block settings_content scoped %}
<div class="panel-group panel-bot-margin">
<div class="panel panel-default">
<div class="panel-heading">
{%- block settings_content_title scoped %}
{%- if panel_icon %}
{%- block settings_content_title_icon scoped %}
<i class="{{panel_icon}}"></i>
{%- endblock %}
{%- endif %}
<strong>{{ panel_title|default("") }}</strong>
{%- endblock %}
</div>
{%- block settings_body scoped %}
<div class="panel-body">
{%- block settings_form scoped %}
{%- endblock settings_form %}
</div>
{%- endblock settings_body %}
{%- block settings_body scoped %}
<div class="panel-body">
{%- block settings_form scoped %}
{%- endblock settings_form %}
</div>
{%- endblock settings_body %}
</div>
{%- endblock %}
</div>
{%- endblock %}
</div>
</div>
</div>
{%- endblock %}
6 changes: 2 additions & 4 deletions sonar/theme/templates/sonar/partial/dropdown_user.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@
#}

<div class="dropdown-menu dropdown-menu-right" aria-labelledby="{{dropdownId}}">
<h6 class="dropdown-header">{{current_user.email}}</h6>
{%- if config.USERPROFILES %}
<a class="dropdown-item" href="{{ url_for('invenio_userprofiles.profile')}}">
<h6 class="dropdown-header">{{current_user_record.email}}</h6>
<a class="dropdown-item" href="{{ url_for('sonar.profile')}}">
{{_('Profile')}}
</a>
{% endif %}
{% if has_superuser_access() %}
<a class="dropdown-item" href="{{ url_for('admin.index')}}">
{{_('Super administration')}}
Expand Down
2 changes: 1 addition & 1 deletion sonar/theme/templates/sonar/partial/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
<a class="nav-link text-uppercase" href="#" id="{{ dropdownId }}" role="button" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
<i class="fa fa-user mr-2"></i>
{{ current_user.profile.full_name if current_user.profile.full_name else current_user.email }}
{{ current_user_record.full_name }}
</a>
{% include 'sonar/partial/dropdown_user.html' %}
{% endwith %}
Expand Down
37 changes: 34 additions & 3 deletions sonar/theme/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@

import re

from flask import Blueprint, abort, current_app, jsonify, render_template, \
request
from flask_login import current_user
from flask import Blueprint, abort, current_app, jsonify, redirect, \
render_template, request, url_for
from flask_babelex import lazy_gettext as _
from flask_breadcrumbs import register_breadcrumb
from flask_login import current_user, login_required
from flask_menu import current_menu, register_menu
from invenio_jsonschemas import current_jsonschemas
from invenio_jsonschemas.errors import JSONSchemaNotFound

Expand All @@ -46,6 +49,34 @@
static_folder='static')


@blueprint.before_app_request
def init_view():
"""Do some stuff before rendering any view."""
current_menu.submenu('settings').submenu('security').hide()
current_menu.submenu('settings').submenu('applications').hide()


@blueprint.route('/users/profile')
@blueprint.route('/users/profile/<pid>')
@login_required
@register_menu(blueprint, 'settings.profile',
_('%(icon)s Profile', icon='<i class="fa fa-user fa-fw"></i>'))
@register_breadcrumb(blueprint, 'breadcrumbs.profile', _('Profile'))
def profile(pid=None):
"""Logged user profile edition page.

:param pid: Logged user PID.
"""
if pid and pid != current_user_record['pid']:
abort(403)

if not pid:
return redirect(
url_for('sonar.profile', pid=current_user_record['pid']))

return render_template('sonar/accounts/profile.html')


@blueprint.route('/error')
def error():
"""Error to generate exception for test purposes."""
Expand Down
12 changes: 8 additions & 4 deletions sonar/translations/de/LC_MESSAGES/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sonar 0.4.0\n"
"Report-Msgid-Bugs-To: software@rero.ch\n"
"POT-Creation-Date: 2020-06-05 10:30+0200\n"
"POT-Creation-Date: 2020-06-05 10:32+0200\n"
"PO-Revision-Date: 2020-05-13 05:58+0000\n"
"Last-Translator: Nicolas Prongué <n.prongue@outlook.com>, 2020\n"
"Language: de\n"
Expand All @@ -20,6 +20,10 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.8.0\n"

#, python-format
msgid "%(icon)s Profile"
msgstr ""

msgid "Abstract"
msgstr ""

Expand Down Expand Up @@ -514,9 +518,6 @@ msgstr ""
msgid "Series to which belongs the resource."
msgstr ""

msgid "Settings"
msgstr ""

msgid "#"
msgstr ""

Expand Down Expand Up @@ -2747,3 +2748,6 @@ msgstr ""
msgid "vol."
msgstr ""

#~ msgid "Settings"
#~ msgstr ""

Loading