Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

Updated profile page #233

Merged
merged 32 commits into from
Sep 25, 2018
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
af8325f
Update UI of profile page.
vidya-ram Mar 7, 2018
fa5d26b
Add config.rb for lastuser_ui folder.
vidya-ram Mar 12, 2018
5d38d9d
added method to make email address primary for a user
Apr 19, 2018
2412ee8
added helper method to mask email address
Apr 19, 2018
df80c6a
added views to make email address primary and delete external IDs
Apr 19, 2018
c2f3f8d
Added some comments
Apr 19, 2018
342f1fe
moved mask_email to utils.py
Apr 19, 2018
31c2a54
using fixed number of masking character
Apr 20, 2018
3f25ad2
Minor UI fix.
vidya-ram Apr 20, 2018
38ca4db
Update btn text.
vidya-ram Apr 20, 2018
e3bc165
Merge branch 'profile_page' of https://github.com/hasgeek/lastuser in…
vidya-ram Apr 20, 2018
ff98b7e
Add EmailPrimaryForm and radio buttons to select email.
vidya-ram Apr 24, 2018
4b5fa36
Update the profile page UI.
vidya-ram Apr 25, 2018
76ebe6d
added option to add external ID
May 23, 2018
61d64f9
simplified mask_email()
Jun 20, 2018
9243fb2
moved non-existent extid handling to postcallback
Jun 20, 2018
1c021bc
removed the nopasswd flag, flashing directly
Jun 20, 2018
316586f
removed model method to make email primary
Jun 20, 2018
9a91373
replaced flask.ext.assets with flask_assets
Jun 20, 2018
79674ce
fixed test for making email primary
Jun 20, 2018
94087e5
added endpoint to resend verification email
Aug 13, 2018
88680ef
Merge branch 'master' into profile_page
jace Sep 18, 2018
177f082
Fix active session display and remove PK from extid removal route
jace Sep 18, 2018
5086a53
Hide orgs and apps in profile page
jace Sep 20, 2018
4472cdc
Rename 'profile' to 'account'
jace Sep 20, 2018
33fb9b3
Cleanup account page and phone handling
jace Sep 20, 2018
9df117e
Remove OpenID in tests
jace Sep 20, 2018
ac9524b
Send phone update notifications; support old verification links
jace Sep 25, 2018
61e083b
Merge stylesheets
jace Sep 25, 2018
10420a2
Remove phone type field
jace Sep 25, 2018
dcd04f2
Review account merge handling
jace Sep 25, 2018
f4fbfce
Remove unnecessary Compass config file
jace Sep 25, 2018
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ baseframe-packed.js
secrets.dev
secrets.test
*/.well-known/acme-challenge
ghostdriver.log
.pytest_cache
.vscode
6 changes: 6 additions & 0 deletions lastuser_core/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,12 @@ def get(cls, service, userid=None, username=None):
param, value = require_one_of(True, userid=userid, username=username)
return cls.query.filter_by(**{param: value, 'service': service}).one_or_none()

def permissions(self, user, inherited=None):
perms = super(UserExternalId, self).permissions(user, inherited)
if user and user == self.user:
perms.add('delete_extid')
return perms


add_primary_relationship(User, 'primary_email', UserEmail, 'user', 'user_id')
add_primary_relationship(User, 'primary_phone', UserPhone, 'user', 'user_id')
Expand Down
14 changes: 14 additions & 0 deletions lastuser_core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,17 @@ def get_gravatar_md5sum(url):
if len(md5sum) != 32:
return None
return md5sum


def mask_email(email):
"""
Masks an email address

>>> mask_email(u'foobar@example.com')
u'f****@e****'

"""
if '@' not in email:
return email
username, domain = email.split('@')
return u'{u}****@{d}****'.format(u=username[0], d=domain[0])
43 changes: 21 additions & 22 deletions lastuser_oauth/views/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,27 @@ def get_user_extid(service, userdata):
def login_service_postcallback(service, userdata):
user, extid, useremail = get_user_extid(service, userdata)

if user is None:
if current_auth:
# Attach this id to currently logged-in user
user = current_auth.user
jace marked this conversation as resolved.
Show resolved Hide resolved
else:
# Register a new user
user = register_internal(None, userdata.get('fullname'), None)
if userdata.get('username'):
if valid_username(userdata['username']) and user.is_valid_username(userdata['username']):
# Set a username for this user if it's available
user.username = userdata['username']
else: # This id is attached to a user
if current_auth and current_auth.user != user:
# Woah! Account merger handler required
# Always confirm with user before doing an account merger
session['merge_buid'] = user.buid
elif useremail and useremail.user != user:
session['merge_buid'] = useremail.user.buid

if extid is not None:
extid.user = user
extid.oauth_token = userdata.get('oauth_token')
extid.oauth_token_secret = userdata.get('oauth_token_secret')
extid.oauth_token_type = userdata.get('oauth_token_type')
Expand All @@ -104,7 +124,7 @@ def login_service_postcallback(service, userdata):
else:
# New external id. Register it.
extid = UserExternalId(
user=user, # This may be None right now. Will be handled below
user=user,
service=service,
userid=userdata['userid'],
username=userdata.get('username'),
Expand All @@ -115,27 +135,6 @@ def login_service_postcallback(service, userdata):
)
db.session.add(extid)

if user is None:
if current_auth.is_authenticated:
# Attach this id to currently logged-in user
user = current_auth.user
extid.user = user
else:
# Register a new user
user = register_internal(None, userdata.get('fullname'), None)
extid.user = user
if userdata.get('username'):
if valid_username(userdata['username']) and user.is_valid_username(userdata['username']):
# Set a username for this user if it's available
user.username = userdata['username']
else: # This id is attached to a user
if current_auth.is_authenticated and current_auth.user != user:
# Woah! Account merger handler required
# Always confirm with user before doing an account merger
session['merge_buid'] = user.buid
elif useremail and useremail.user != user:
session['merge_buid'] = useremail.user.buid

# Check for new email addresses
if userdata.get('email') and not useremail:
user.add_email(userdata['email'])
Expand Down
9 changes: 6 additions & 3 deletions lastuser_oauth/views/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from .. import lastuser_oauth
from ..mailclient import send_email_verify_link, send_password_reset_link
from lastuser_core.models import db, User, UserEmailClaim, PasswordResetRequest, ClientCredential, UserSession
from lastuser_core.utils import mask_email
from ..forms import LoginForm, RegisterForm, PasswordResetForm, PasswordResetRequestForm, LoginPasswordResetException
from .helpers import login_internal, logout_internal, register_internal, set_loginmethod_cookie

Expand Down Expand Up @@ -58,7 +59,9 @@ def login():
return set_loginmethod_cookie(render_redirect(get_next_url(session=True), code=303),
'password')
except LoginPasswordResetException:
return render_redirect(url_for('.reset', expired=1, username=loginform.username.data))
flash(_(u"Your account does not have a password set. Please enter your username "
"or email address to request a reset code and set a new password"), category='danger')
return render_redirect(url_for('.reset', username=loginform.username.data))
elif request.method == 'POST' and formid in service_forms:
form = service_forms[formid]['form']
if form.validate():
Expand Down Expand Up @@ -212,11 +215,11 @@ def reset():
send_password_reset_link(email=email, user=user, secret=resetreq.reset_code)
db.session.commit()
return render_message(title=_("Reset password"), message=_(u"""
We sent you an email with a link to reset your password.
We sent a link to reset your password to your email address: {masked_email}.
Please check your email. If it doesn’t arrive in a few minutes,
it may have landed in your spam or junk folder.
The reset link is valid for 24 hours.
"""))
""".format(masked_email=mask_email(email))))

return render_form(form=form, title=_("Reset password"), message=message, submit=_("Send reset code"), ajax=False)

Expand Down
4 changes: 2 additions & 2 deletions lastuser_oauth/views/notify.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


user_changes_to_notify = set(['merge', 'profile', 'email', 'email-claim', 'email-delete',
'phone', 'phone-claim', 'phone-delete', 'team-membership'])
'email-update-primary', 'phone', 'phone-claim', 'phone-delete', 'team-membership'])


@session_revoked.connect
Expand Down Expand Up @@ -39,7 +39,7 @@ def notify_user_data_changed(user, changes):
for change in changes:
if change in ['merge', 'profile']:
notify_changes.append(change)
elif change in ['email', 'email-claim', 'email-delete']:
elif change in ['email', 'email-claim', 'email-delete', 'email-update-primary']:
if 'email' in tokenscope or 'email/*' in tokenscope:
notify_changes.append(change)
elif change in ['phone', 'phone-claim', 'phone-delete']:
Expand Down
3 changes: 3 additions & 0 deletions lastuser_ui/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-

from flask import Blueprint
from flask_assets import Bundle

lastuser_ui = Blueprint('lastuser_ui', __name__,
static_folder='static',
static_url_path='/static/ui',
template_folder='templates')

lastuser_ui_css = Bundle('lastuser_ui/css/app.css')


from . import forms, views # NOQA
10 changes: 10 additions & 0 deletions lastuser_ui/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Require any additional compass plugins here.
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "/static/css"
sass_dir = "/static/sass"
images_dir = "/static/img"
javascripts_dir = "/static/js"
line_comments = false
# To enable relative paths to assets via compass helper functions. Uncomment:
relative_assets = true
7 changes: 6 additions & 1 deletion lastuser_ui/forms/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from lastuser_core.utils import strip_phone, valid_phone
from lastuser_core.models import UserEmail, UserEmailClaim, UserPhone, UserPhoneClaim

__all__ = ['NewEmailAddressForm', 'NewPhoneForm', 'VerifyPhoneForm']
__all__ = ['NewEmailAddressForm', 'EmailPrimaryForm', 'NewPhoneForm', 'VerifyPhoneForm']


class NewEmailAddressForm(forms.Form):
Expand All @@ -33,6 +33,11 @@ def validate_email(self, field):
raise forms.ValidationError(_("This email address is pending verification"))


class EmailPrimaryForm(forms.Form):
email = forms.EmailField(__("Email address"), validators=[forms.validators.DataRequired(), forms.ValidEmail()],
widget_attrs={'autocorrect': 'none', 'autocapitalize': 'none'})


class NewPhoneForm(forms.Form):
phone = forms.TelField(__("Phone number"), default='+91',
validators=[forms.validators.DataRequired()],
Expand Down
77 changes: 77 additions & 0 deletions lastuser_ui/static/css/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.detail-box {
margin: 10px;
border-bottom: 1px solid #ddd;
margin: 0 -15px;
padding: 15px;
}
.detail-box .heading, .detail-box .heading-special {
margin: 0;
}
.detail-box .heading-special {
cursor: pointer;
}
.detail-box .para {
margin: 0;
}
.detail-box .button-box {
margin: 12px auto 0;
}
.detail-box .button-box-button {
margin-bottom: 12px;
}
.detail-box .detail-box-form {
padding: 12px 0 0;
}
.detail-box .detail-box-form .well {
margin-bottom: 0;
}
.detail-box .detail-box-panel {
margin-bottom: 0;
margin-top: 5px;
}
.detail-box .detail-box-table {
margin-bottom: 0;
}
.detail-box .detail-box-table tr:first-child > td {
border-top: 0;
}
.detail-box .detail-box-table td:first-child {
padding-left: 0;
}
.detail-box .detail-box-table .listwidget ul input {
top: 3px;
}

@media screen and (min-width: 768px) {
.detail > div {
display: inline-block;
float: none;
vertical-align: top;
margin: 0 -1px 30px;
}

.detail-box {
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 10px rgba(0, 0, 0, 0.1) inset;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 0 10px rgba(0, 0, 0, 0.1) inset;
padding: 15px;
margin: 0;
border: 1px solid #ddd;
border-radius: 4px;
}
.detail-box .button-box {
float: right;
}
.detail-box .button-box-button {
margin-bottom: 0;
}
.detail-box .detail-box-form {
clear: both;
}
}
@media (min-width: 992px) and (max-width: 1199px) {
.detail-box .form-horizontal .help-required {
position: absolute;
right: -10px;
bottom: 0;
}
}
Binary file added lastuser_ui/static/img/banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions lastuser_ui/static/sass/app.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
.detail-box
margin: 10px
border-bottom: 1px solid #ddd
margin: 0 -15px
padding: 15px

.heading
margin : 0

.heading-special
@extend .heading
cursor: pointer

.para
margin: 0

.button-box
margin: 12px auto 0

.button-box-button
margin-bottom: 12px

.detail-box-form
padding: 12px 0 0

.well
margin-bottom: 0


.detail-box-panel
margin-bottom: 0
margin-top: 5px

.detail-box-table
margin-bottom: 0

tr:first-child>td
border-top: 0

td:first-child
padding-left: 0

.listwidget ul input
top: 3px


@media screen and (min-width:768px)
.detail > div
display: inline-block
float: none
vertical-align: top
margin: 0 -1px 30px

.detail-box
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.1), 0 0 10px rgba(0,0,0,0.1) inset
box-shadow: 0 1px 2px rgba(0,0,0,0.1), 0 0 10px rgba(0,0,0,0.1) inset
padding: 15px
margin: 0
border: 1px solid #ddd
border-radius: 4px

.button-box
float: right

.button-box-button
margin-bottom: 0

.detail-box-form
clear: both

@media (min-width:992px) and (max-width:1199px)
.detail-box .form-horizontal .help-required
position: absolute
right: -10px
bottom: 0

1 change: 1 addition & 0 deletions lastuser_ui/static/sass/app.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@import "compass";
Loading