##// END OF EJS Templates
authomatic: do not show social buttons if not enabled
ergo -
Show More
@@ -1,82 +1,89 b''
1 {% extends "/layout.jinja2" %}
1 {% extends "/layout.jinja2" %}
2 {% block ng_app %}{% endblock %}
2 {% block ng_app %}{% endblock %}
3 {% block ng_controller %} data-ng-controller="RegisterController as
3 {% block ng_controller %} data-ng-controller="RegisterController as
4 register" {% endblock %}
4 register" {% endblock %}
5 {% block content_class %}two-col equal{% endblock %}
5 {% block content_class %}two-col equal{% endblock %}
6 {% block section_name %}register-section{% endblock %}
6 {% block section_name %}register-section{% endblock %}
7
7
8 {% block page_title %}{% endblock %}
8 {% block page_title %}{% endblock %}
9
9
10 {% block content %}
10 {% block content %}
11 <div class="container">
11 <div class="container">
12
12
13 <div class="m-t-1 row">
13 <div class="m-t-1 row">
14 {{ widgets.render_flash_messages(flash_msgs) }}
14 {{ widgets.render_flash_messages(flash_msgs) }}
15 </div>
15 </div>
16
16 {% if social_plugins %}
17 <div class="row">
17 <div class="row">
18
18
19 <div class="col-sm-12 text-center" id="social-form">
19 <div class="col-sm-12 text-center" id="social-form">
20
20
21 <h2>Log in or register using</h2>
21 <h2>Log in or register using</h2>
22
22 {% if social_plugins.get('google') %}
23 <a href="{{ request.route_url('social_auth', provider='google') }}"
23 <a href="{{ request.route_url('social_auth', provider='google') }}"
24 class="btn btn-default social" id="btn-google">
24 class="btn btn-default social" id="btn-google">
25 <span class="fa fa-google-plus-square fa-2x"></span> {{ _('Google') }}
25 <span class="fa fa-google-plus-square fa-2x"></span> {{ _('Google') }}
26 </a>
26 </a>
27 {% endif %}
28 {% if social_plugins.get('twitter') %}
27 <a href="{{ request.route_url('social_auth', provider='twitter') }}"
29 <a href="{{ request.route_url('social_auth', provider='twitter') }}"
28 class="btn btn-default social" id="btn-twitter">
30 class="btn btn-default social" id="btn-twitter">
29 <span class="fa fa-twitter fa-2x"></span> {{ _('Twitter') }}
31 <span class="fa fa-twitter fa-2x"></span> {{ _('Twitter') }}
30 </a>
32 </a>
33 {% endif %}
34 {% if social_plugins.get('bitbucket') %}
31 <a href="{{ request.route_url('social_auth', provider='bitbucket') }}"
35 <a href="{{ request.route_url('social_auth', provider='bitbucket') }}"
32 class="btn btn-default social" id="btn-bitbucket">
36 class="btn btn-default social" id="btn-bitbucket">
33 <span class="fa fa-bitbucket fa-2x"></span> {{ _(' Bitbucket') }}
37 <span class="fa fa-bitbucket fa-2x"></span> {{ _(' Bitbucket') }}
34 </a>
38 </a>
39 {% endif %}
40 {% if social_plugins.get('github') %}
35 <a tooltip-placement="bottom"
41 <a tooltip-placement="bottom"
36 data-uib-tooltip="Why do you ask private repository permissions?
42 data-uib-tooltip="Why do you ask private repository permissions?
37 Unfortunately Github doesn't allow issue tracker integration
43 Unfortunately Github doesn't allow issue tracker integration
38 to send issues to private repositories without full repo access"
44 to send issues to private repositories without full repo access"
39 href="{{ request.route_url('social_auth', provider='github') }}"
45 href="{{ request.route_url('social_auth', provider='github') }}"
40 class="btn btn-default social" id="btn-github">
46 class="btn btn-default social" id="btn-github">
41 <span class="fa fa-github fa-2x"></span> {{ _('Github') }}
47 <span class="fa fa-github fa-2x"></span> {{ _('Github') }}
42 </a>
48 </a>
49 {% endif %}
43
50
44 </div>
51 </div>
45 </div>
52 </div>
46
47 <div class="row">
48
49 <hr/>
53 <hr/>
50
54
55 {% endif %}
56
57 <div class="row">
51
58
52 <div class="col-sm-5">
59 <div class="col-sm-5">
53 <div id="sign-in-form">
60 <div id="sign-in-form">
54 <h2 class="">Log in</h2>
61 <h2 class="">Log in</h2>
55 <form action="{{ request.route_url('ziggurat.routes.sign_in') }}"
62 <form action="{{ request.route_url('ziggurat.routes.sign_in') }}"
56 method="post">
63 method="post">
57 {{ widgets.render_form(sign_in_form) }}
64 {{ widgets.render_form(sign_in_form) }}
58 <input type="submit" class="btn btn-primary"
65 <input type="submit" class="btn btn-primary"
59 value="Sign In">
66 value="Sign In">
60 <a href="{{ request.route_url('lost_password') }}"
67 <a href="{{ request.route_url('lost_password') }}"
61 class="btn btn-info">{{ _('Lost password') }}</a>
68 class="btn btn-info">{{ _('Lost password') }}</a>
62 </form>
69 </form>
63 </div>
70 </div>
64
71
65 </div>
72 </div>
66
73
67
74
68 <div class="col-sm-6 col-sm-offset-1">
75 <div class="col-sm-6 col-sm-offset-1">
69 <div id="sign-up-form">
76 <div id="sign-up-form">
70 <h2>Register here</h2>
77 <h2>Register here</h2>
71 <form action="{{ request.route_url('register') }}"
78 <form action="{{ request.route_url('register') }}"
72 method="post" id="register_user">
79 method="post" id="register_user">
73 {{ widgets.render_form(form) }}
80 {{ widgets.render_form(form) }}
74 <input type="submit" class="btn btn-primary"
81 <input type="submit" class="btn btn-primary"
75 value="Register">
82 value="Register">
76 </form>
83 </form>
77 </div>
84 </div>
78 </div>
85 </div>
79
86
80 </div>
87 </div>
81 </div>
88 </div>
82 {% endblock %}
89 {% endblock %}
@@ -1,243 +1,255 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # App Enlight Enterprise Edition, including its added features, Support
18 # App Enlight Enterprise Edition, including its added features, Support
19 # services, and proprietary license terms, please see
19 # services, and proprietary license terms, please see
20 # https://rhodecode.com/licenses/
20 # https://rhodecode.com/licenses/
21
21
22 import datetime
22 import datetime
23 import logging
23 import logging
24 import uuid
24 import uuid
25
25
26 import pyramid.security as security
26 import pyramid.security as security
27
27
28 from pyramid.view import view_config
28 from pyramid.view import view_config
29 from pyramid.httpexceptions import HTTPFound
29 from pyramid.httpexceptions import HTTPFound
30 from pyramid.response import Response
30 from pyramid.response import Response
31 from pyramid.security import NO_PERMISSION_REQUIRED
31 from pyramid.security import NO_PERMISSION_REQUIRED
32 from ziggurat_foundations.ext.pyramid.sign_in import ZigguratSignInSuccess
32 from ziggurat_foundations.ext.pyramid.sign_in import ZigguratSignInSuccess
33 from ziggurat_foundations.ext.pyramid.sign_in import ZigguratSignInBadAuth
33 from ziggurat_foundations.ext.pyramid.sign_in import ZigguratSignInBadAuth
34 from ziggurat_foundations.ext.pyramid.sign_in import ZigguratSignOut
34 from ziggurat_foundations.ext.pyramid.sign_in import ZigguratSignOut
35
35
36 from appenlight.lib.social import handle_social_data
36 from appenlight.lib.social import handle_social_data
37 from appenlight.models import DBSession
37 from appenlight.models import DBSession
38 from appenlight.models.user import User
38 from appenlight.models.user import User
39 from appenlight.models.services.user import UserService
39 from appenlight.models.services.user import UserService
40 from appenlight.subscribers import _
40 from appenlight.subscribers import _
41 from appenlight import forms
41 from appenlight import forms
42 from webob.multidict import MultiDict
42 from webob.multidict import MultiDict
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46
46
47 @view_config(context=ZigguratSignInSuccess, permission=NO_PERMISSION_REQUIRED)
47 @view_config(context=ZigguratSignInSuccess, permission=NO_PERMISSION_REQUIRED)
48 def sign_in(request):
48 def sign_in(request):
49 """
49 """
50 Performs sign in by sending proper user identification headers
50 Performs sign in by sending proper user identification headers
51 Regenerates CSRF token
51 Regenerates CSRF token
52 """
52 """
53 user = request.context.user
53 user = request.context.user
54 if user.status == 1:
54 if user.status == 1:
55 request.session.new_csrf_token()
55 request.session.new_csrf_token()
56 user.last_login_date = datetime.datetime.utcnow()
56 user.last_login_date = datetime.datetime.utcnow()
57 social_data = request.session.get('zigg.social_auth')
57 social_data = request.session.get('zigg.social_auth')
58 if social_data:
58 if social_data:
59 handle_social_data(request, user, social_data)
59 handle_social_data(request, user, social_data)
60 else:
60 else:
61 request.session.flash(_('Account got disabled'))
61 request.session.flash(_('Account got disabled'))
62
62
63 if request.context.came_from != '/':
63 if request.context.came_from != '/':
64 return HTTPFound(location=request.context.came_from,
64 return HTTPFound(location=request.context.came_from,
65 headers=request.context.headers)
65 headers=request.context.headers)
66 else:
66 else:
67 return HTTPFound(location=request.route_url('/'),
67 return HTTPFound(location=request.route_url('/'),
68 headers=request.context.headers)
68 headers=request.context.headers)
69
69
70
70
71 @view_config(context=ZigguratSignInBadAuth, permission=NO_PERMISSION_REQUIRED)
71 @view_config(context=ZigguratSignInBadAuth, permission=NO_PERMISSION_REQUIRED)
72 def bad_auth(request):
72 def bad_auth(request):
73 """
73 """
74 Handles incorrect login flow
74 Handles incorrect login flow
75 """
75 """
76 request.session.flash(_('Incorrect username or password'), 'warning')
76 request.session.flash(_('Incorrect username or password'), 'warning')
77 return HTTPFound(location=request.route_url('register'),
77 return HTTPFound(location=request.route_url('register'),
78 headers=request.context.headers)
78 headers=request.context.headers)
79
79
80
80
81 @view_config(context=ZigguratSignOut, permission=NO_PERMISSION_REQUIRED)
81 @view_config(context=ZigguratSignOut, permission=NO_PERMISSION_REQUIRED)
82 def sign_out(request):
82 def sign_out(request):
83 """
83 """
84 Removes user identification cookie
84 Removes user identification cookie
85 """
85 """
86 return HTTPFound(location=request.route_url('register'),
86 return HTTPFound(location=request.route_url('register'),
87 headers=request.context.headers)
87 headers=request.context.headers)
88
88
89
89
90 @view_config(route_name='lost_password',
90 @view_config(route_name='lost_password',
91 renderer='appenlight:templates/user/lost_password.jinja2',
91 renderer='appenlight:templates/user/lost_password.jinja2',
92 permission=NO_PERMISSION_REQUIRED)
92 permission=NO_PERMISSION_REQUIRED)
93 def lost_password(request):
93 def lost_password(request):
94 """
94 """
95 Presents lost password page - sends password reset link to
95 Presents lost password page - sends password reset link to
96 specified email address.
96 specified email address.
97 This link is valid only for 10 minutes
97 This link is valid only for 10 minutes
98 """
98 """
99 form = forms.LostPasswordForm(request.POST, csrf_context=request)
99 form = forms.LostPasswordForm(request.POST, csrf_context=request)
100 if request.method == 'POST' and form.validate():
100 if request.method == 'POST' and form.validate():
101 user = User.by_email(form.email.data)
101 user = User.by_email(form.email.data)
102 if user:
102 if user:
103 user.regenerate_security_code()
103 user.regenerate_security_code()
104 user.security_code_date = datetime.datetime.utcnow()
104 user.security_code_date = datetime.datetime.utcnow()
105 email_vars = {
105 email_vars = {
106 'user': user,
106 'user': user,
107 'request': request,
107 'request': request,
108 'email_title': "App Enlight :: New password request"
108 'email_title': "App Enlight :: New password request"
109 }
109 }
110 UserService.send_email(
110 UserService.send_email(
111 request, recipients=[user.email],
111 request, recipients=[user.email],
112 variables=email_vars,
112 variables=email_vars,
113 template='/email_templates/lost_password.jinja2')
113 template='/email_templates/lost_password.jinja2')
114 msg = 'Password reset email had been sent. ' \
114 msg = 'Password reset email had been sent. ' \
115 'Please check your mailbox for further instructions.'
115 'Please check your mailbox for further instructions.'
116 request.session.flash(_(msg))
116 request.session.flash(_(msg))
117 return HTTPFound(location=request.route_url('lost_password'))
117 return HTTPFound(location=request.route_url('lost_password'))
118 return {"form": form}
118 return {"form": form}
119
119
120
120
121 @view_config(route_name='lost_password_generate',
121 @view_config(route_name='lost_password_generate',
122 permission=NO_PERMISSION_REQUIRED,
122 permission=NO_PERMISSION_REQUIRED,
123 renderer='appenlight:templates/user/lost_password_generate.jinja2')
123 renderer='appenlight:templates/user/lost_password_generate.jinja2')
124 def lost_password_generate(request):
124 def lost_password_generate(request):
125 """
125 """
126 Shows new password form - perform time check and set new password for user
126 Shows new password form - perform time check and set new password for user
127 """
127 """
128 user = User.by_user_name_and_security_code(
128 user = User.by_user_name_and_security_code(
129 request.GET.get('user_name'), request.GET.get('security_code'))
129 request.GET.get('user_name'), request.GET.get('security_code'))
130 if user:
130 if user:
131 delta = datetime.datetime.utcnow() - user.security_code_date
131 delta = datetime.datetime.utcnow() - user.security_code_date
132
132
133 if user and delta.total_seconds() < 600:
133 if user and delta.total_seconds() < 600:
134 form = forms.NewPasswordForm(request.POST, csrf_context=request)
134 form = forms.NewPasswordForm(request.POST, csrf_context=request)
135 if request.method == "POST" and form.validate():
135 if request.method == "POST" and form.validate():
136 user.set_password(form.new_password.data)
136 user.set_password(form.new_password.data)
137 request.session.flash(_('You can sign in with your new password.'))
137 request.session.flash(_('You can sign in with your new password.'))
138 return HTTPFound(location=request.route_url('register'))
138 return HTTPFound(location=request.route_url('register'))
139 else:
139 else:
140 return {"form": form}
140 return {"form": form}
141 else:
141 else:
142 return Response('Security code expired')
142 return Response('Security code expired')
143
143
144
144
145 @view_config(route_name='register',
145 @view_config(route_name='register',
146 renderer='appenlight:templates/user/register.jinja2',
146 renderer='appenlight:templates/user/register.jinja2',
147 permission=NO_PERMISSION_REQUIRED)
147 permission=NO_PERMISSION_REQUIRED)
148 def register(request):
148 def register(request):
149 """
149 """
150 Render register page with form
150 Render register page with form
151 Also handles oAuth flow for registration
151 Also handles oAuth flow for registration
152 """
152 """
153 login_url = request.route_url('ziggurat.routes.sign_in')
153 login_url = request.route_url('ziggurat.routes.sign_in')
154 if request.query_string:
154 if request.query_string:
155 query_string = '?%s' % request.query_string
155 query_string = '?%s' % request.query_string
156 else:
156 else:
157 query_string = ''
157 query_string = ''
158 referrer = '%s%s' % (request.path, query_string)
158 referrer = '%s%s' % (request.path, query_string)
159
159
160 if referrer in [login_url, '/register', '/register?sign_in=1']:
160 if referrer in [login_url, '/register', '/register?sign_in=1']:
161 referrer = '/' # never use the login form itself as came_from
161 referrer = '/' # never use the login form itself as came_from
162 sign_in_form = forms.SignInForm(
162 sign_in_form = forms.SignInForm(
163 came_from=request.params.get('came_from', referrer),
163 came_from=request.params.get('came_from', referrer),
164 csrf_context=request)
164 csrf_context=request)
165
165
166 # populate form from oAuth session data returned by authomatic
166 # populate form from oAuth session data returned by authomatic
167 social_data = request.session.get('zigg.social_auth')
167 social_data = request.session.get('zigg.social_auth')
168 if request.method != 'POST' and social_data:
168 if request.method != 'POST' and social_data:
169 log.debug(social_data)
169 log.debug(social_data)
170 user_name = social_data['user'].get('user_name', '').split('@')[0]
170 user_name = social_data['user'].get('user_name', '').split('@')[0]
171 form_data = {
171 form_data = {
172 'user_name': user_name,
172 'user_name': user_name,
173 'email': social_data['user'].get('email')
173 'email': social_data['user'].get('email')
174 }
174 }
175 form_data['user_password'] = str(uuid.uuid4())
175 form_data['user_password'] = str(uuid.uuid4())
176 form = forms.UserRegisterForm(MultiDict(form_data),
176 form = forms.UserRegisterForm(MultiDict(form_data),
177 csrf_context=request)
177 csrf_context=request)
178 form.user_password.widget.hide_value = False
178 form.user_password.widget.hide_value = False
179 else:
179 else:
180 form = forms.UserRegisterForm(request.POST, csrf_context=request)
180 form = forms.UserRegisterForm(request.POST, csrf_context=request)
181 if request.method == 'POST' and form.validate():
181 if request.method == 'POST' and form.validate():
182 log.info('registering user')
182 log.info('registering user')
183 # insert new user here
183 # insert new user here
184 new_user = User()
184 new_user = User()
185 DBSession.add(new_user)
185 DBSession.add(new_user)
186 form.populate_obj(new_user)
186 form.populate_obj(new_user)
187 new_user.regenerate_security_code()
187 new_user.regenerate_security_code()
188 new_user.status = 1
188 new_user.status = 1
189 new_user.set_password(new_user.user_password)
189 new_user.set_password(new_user.user_password)
190 new_user.registration_ip = request.environ.get('REMOTE_ADDR')
190 new_user.registration_ip = request.environ.get('REMOTE_ADDR')
191
191
192 if social_data:
192 if social_data:
193 handle_social_data(request, new_user, social_data)
193 handle_social_data(request, new_user, social_data)
194
194
195 email_vars = {'user': new_user,
195 email_vars = {'user': new_user,
196 'request': request,
196 'request': request,
197 'email_title': "App Enlight :: Start information"}
197 'email_title': "App Enlight :: Start information"}
198 UserService.send_email(
198 UserService.send_email(
199 request, recipients=[new_user.email], variables=email_vars,
199 request, recipients=[new_user.email], variables=email_vars,
200 template='/email_templates/registered.jinja2')
200 template='/email_templates/registered.jinja2')
201 request.session.flash(_('You have successfully registered.'))
201 request.session.flash(_('You have successfully registered.'))
202 DBSession.flush()
202 DBSession.flush()
203 headers = security.remember(request, new_user.id)
203 headers = security.remember(request, new_user.id)
204 return HTTPFound(location=request.route_url('/'),
204 return HTTPFound(location=request.route_url('/'),
205 headers=headers)
205 headers=headers)
206 settings = request.registry.settings
207 social_plugins = {}
208 if settings.get('authomatic.pr.twitter.key', ''):
209 social_plugins['twitter'] = True
210 if settings.get('authomatic.pr.google.key', ''):
211 social_plugins['google'] = True
212 if settings.get('authomatic.pr.github.key', ''):
213 social_plugins['github'] = True
214 if settings.get('authomatic.pr.bitbucket.key', ''):
215 social_plugins['bitbucket'] = True
216
206 return {
217 return {
207 "form": form,
218 "form": form,
208 "sign_in_form": sign_in_form
219 "sign_in_form": sign_in_form,
220 "social_plugins": social_plugins
209 }
221 }
210
222
211
223
212 @view_config(route_name='/',
224 @view_config(route_name='/',
213 renderer='appenlight:templates/dashboard/index.jinja2',
225 renderer='appenlight:templates/dashboard/index.jinja2',
214 permission=NO_PERMISSION_REQUIRED)
226 permission=NO_PERMISSION_REQUIRED)
215 @view_config(route_name='angular_app_ui',
227 @view_config(route_name='angular_app_ui',
216 renderer='appenlight:templates/dashboard/index.jinja2',
228 renderer='appenlight:templates/dashboard/index.jinja2',
217 permission=NO_PERMISSION_REQUIRED)
229 permission=NO_PERMISSION_REQUIRED)
218 @view_config(route_name='angular_app_ui_ix',
230 @view_config(route_name='angular_app_ui_ix',
219 renderer='appenlight:templates/dashboard/index.jinja2',
231 renderer='appenlight:templates/dashboard/index.jinja2',
220 permission=NO_PERMISSION_REQUIRED)
232 permission=NO_PERMISSION_REQUIRED)
221 def app_main_index(request):
233 def app_main_index(request):
222 """
234 """
223 Render dashoard/report browser page page along with:
235 Render dashoard/report browser page page along with:
224 - flash messages
236 - flash messages
225 - application list
237 - application list
226 - assigned reports
238 - assigned reports
227 - latest events
239 - latest events
228 (those last two come from subscribers.py that sets global renderer variables)
240 (those last two come from subscribers.py that sets global renderer variables)
229 """
241 """
230
242
231 if request.user:
243 if request.user:
232 request.user.last_login_date = datetime.datetime.utcnow()
244 request.user.last_login_date = datetime.datetime.utcnow()
233 applications = request.user.resources_with_perms(
245 applications = request.user.resources_with_perms(
234 ['view'], resource_types=['application'])
246 ['view'], resource_types=['application'])
235 # convert for angular
247 # convert for angular
236 applications = dict(
248 applications = dict(
237 [(a.resource_id, a.resource_name) for a in applications.all()]
249 [(a.resource_id, a.resource_name) for a in applications.all()]
238 )
250 )
239 else:
251 else:
240 applications = {}
252 applications = {}
241 return {
253 return {
242 'applications': applications
254 'applications': applications
243 }
255 }
General Comments 0
You need to be logged in to leave comments. Login now