Skip to content

Edit profile [WIP] #1229

New issue

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

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

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
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
7 changes: 7 additions & 0 deletions tests/unit/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ def add_xmlrpc_endpoint(endpoint, pattern, header, domain=None):
traverse="/{username}",
domain=warehouse,
),
pretend.call(
"accounts.profile.edit",
"/user/{username}/edit",
factory="warehouse.accounts.models:UserFactory",
traverse="/{username}/edit",
domain=warehouse,
),
pretend.call("accounts.login", "/account/login/", domain=warehouse),
pretend.call("accounts.logout", "/account/logout/", domain=warehouse),
pretend.call(
Expand Down
44 changes: 44 additions & 0 deletions warehouse/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,47 @@ def validate_password(self, field):
if userid is not None:
if not self.user_service.check_password(userid, field.data):
raise wtforms.validators.ValidationError("Invalid password.")


class EditProfileForm(forms.Form):
username = wtforms.StringField(
validators=[
wtforms.validators.DataRequired(),
wtforms.validators.Length(max=50),
],
)

password = wtforms.PasswordField()

password_confirm = wtforms.PasswordField(
validators=[
wtforms.validators.EqualTo(
"password", "Passwords must match."
),
],
)

full_name = wtforms.StringField()

email = wtforms.fields.html5.EmailField(
validators=[
wtforms.validators.DataRequired(),
wtforms.validators.Email(),
],
)

def __init__(self, *args, user_service, **kwargs):
super().__init__(*args, **kwargs)
self.user_service = user_service

def validate_email(self, field):
if self.user_service.find_userid_by_email(field.data) is not None:
raise wtforms.validators.ValidationError("Email exists.")

def validate_password(self, field):
if field.data and not PWD_RE.match(field.data):
raise wtforms.validators.ValidationError(
"Password must contain an upper case letter, a lower case "
"letter, a number, a special character and be at least "
"%d characters in length" % PWD_MIN_LEN
)
1 change: 1 addition & 0 deletions warehouse/accounts/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def create_user(self, username, name, password, email,
def update_user(self, user_id, **changes):
user = self.get_user(user_id)
for attr, value in changes.items():
print('%s----%s', attr, value)
setattr(user, attr, value)
return user

Expand Down
33 changes: 33 additions & 0 deletions warehouse/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from warehouse.accounts import REDIRECT_FIELD_NAME
from warehouse.accounts import forms
from warehouse.accounts.interfaces import IUserService
from warehouse.accounts.models import Email
from warehouse.cache.origin import origin_cache
from warehouse.packaging.models import Project, Release
from warehouse.utils.http import is_safe_url
Expand Down Expand Up @@ -55,6 +56,38 @@ def profile(user, request):
return {"user": user, "projects": projects}


@view_config(
route_name="accounts.profile.edit",
renderer="accounts/edit.html",
uses_session=True,
require_methods=False,
)
def edit_profile(request, _form_class=forms.EditProfileForm):
if not request.user:
return HTTPSeeOther(request.route_path("accounts.login"))

user_service = request.find_service(IUserService, context=None)
form = _form_class(request.POST, user_service=user_service)

if request.method == "POST" and form.validate():
username = form.username.data
userid = user_service.find_userid(username)

if not form.password.data:
user = user_service.update_user(
userid, full_name=form.full_name.data
)
else:
user = user_service.update_user(
userid,
full_name=form.full_name.data, password=form.password.data
)

return HTTPSeeOther(request.route_path("accounts.profile"))

return {"user": request.user, "form": form}


@view_config(
route_name="accounts.login",
renderer="accounts/login.html",
Expand Down
5 changes: 5 additions & 0 deletions warehouse/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def includeme(config):
traverse="/{username}",
domain=warehouse,
)
config.add_route(
"accounts.profile.edit",
"/user/{username}/edit",
domain=warehouse,
)
config.add_route("accounts.login", "/account/login/", domain=warehouse)
config.add_route("accounts.logout", "/account/logout/", domain=warehouse)
config.add_route(
Expand Down
76 changes: 76 additions & 0 deletions warehouse/templates/accounts/edit.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{% extends "base.html" %}

{% block title %}{{ user.username }} | Edit profile {% endblock %}

{% block content %}
<form method="POST" action="{{ request.current_route_path() }}">
<input name="csrf_token" type="hidden" value="{{ request.session.get_csrf_token() }}">

<!-- Username -->
{% if form.username.errors %}
<ul class="errors">
{% for error in form.username.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="username">Username</label>
{{ form.username(placeholder="Username", autocorrect="off", autocapitalize="off", spellcheck="false", value=user.username) }}

<br>

<!-- Password -->
{% if form.password.errors %}
<ul class="errors">
{% for error in form.password.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="password">Password</label>
{{ form.password(placeholder="New Password") }}

<br>

<!-- Confirm password -->
{% if form.password_confirm.errors %}
<ul class="errors">
{% for error in form.password_confirm.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="confirm-password">Confirm Password</label>
{{ form.password_confirm(placeholder="Confirm password") }}

<br>

<!-- Full name -->
{% if form.full_name.errors %}
<ul class="errors">
{% for error in form.full_name.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="Name">Name</label>
{{ form.full_name(placeholder="Full name", value=user.name|default(user.username, true)) }}

<br>

<!-- Email -->
{% if form.email.errors %}
<ul class="errors">
{% for error in form.email.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<label for="email">Email</label>
{{ form.email(placeholder="Email", value=user.email) }}

<br>

<input type="submit" value="Submit">
</form>
{% endblock %}