source: OpenWorkouts-current/ow/views/user.py @ 0be1b0d

currentfeature/docs
Last change on this file since 0be1b0d was 0be1b0d, checked in by borja <borja@…>, 5 years ago

Marked the password recover view as "no coverage in tests",

as it is far from finished yet.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1from calendar import month_name
2
3from pyramid.httpexceptions import HTTPFound
4from pyramid.view import view_config
5from pyramid.security import remember, forget
6from pyramid.response import Response
7from pyramid.i18n import TranslationStringFactory
8from pyramid_simpleform import Form, State
9from pytz import common_timezones
10
11from ..models.user import User
12from ..schemas.user import (
13    UserProfileSchema,
14    ChangePasswordSchema,
15    SignUpSchema,
16)
17from ..models.root import OpenWorkouts
18from ..views.renderers import OWFormRenderer
19
20_ = TranslationStringFactory('OpenWorkouts')
21
22
23@view_config(context=OpenWorkouts)
24def dashboard_redirect(context, request):
25    """
26    Send the user to his dashboard when accesing the root object,
27    send to the login page if the user is not logged in.
28    """
29    if request.authenticated_userid:
30        user = request.root.get_user_by_uid(request.authenticated_userid)
31        if user:
32            return HTTPFound(location=request.resource_url(user))
33        else:
34            # an authenticated user session, for an user that does not exist
35            # anymore, logout!
36            return HTTPFound(location=request.resource_url(context, 'logout'))
37    return HTTPFound(location=request.resource_url(context, 'login'))
38
39
40@view_config(
41    context=OpenWorkouts,
42    name='login',
43    renderer='ow:templates/login.pt')
44def login(context, request):
45    message = ''
46    email = ''
47    password = ''
48    return_to = request.params.get('return_to')
49    redirect_url = return_to or request.resource_url(request.root)
50
51    if 'submit' in request.POST:
52        email = request.POST.get('email', None)
53        user = context.get_user_by_email(email)
54        if user:
55            password = request.POST.get('password', None)
56            if password is not None and user.check_password(password):
57                headers = remember(request, str(user.uid))
58                redirect_url = return_to or request.resource_url(user)
59                return HTTPFound(location=redirect_url, headers=headers)
60            else:
61                message = _('Wrong password')
62        else:
63            message = _('Wrong email address')
64
65    return {
66        'message': message,
67        'email': email,
68        'password': password,
69        'redirect_url': redirect_url
70    }
71
72
73@view_config(context=OpenWorkouts, name='logout')
74def logout(context, request):
75    headers = forget(request)
76    return HTTPFound(location=request.resource_url(context), headers=headers)
77
78
79@view_config(
80    context=OpenWorkouts,
81    name='signup',
82    renderer='ow:templates/signup.pt')
83def signup(context, request):
84    state = State(emails=context.lowercase_emails,
85                  names=context.lowercase_nicknames)
86    form = Form(request, schema=SignUpSchema(), state=state)
87
88    if 'submit' in request.POST and form.validate():
89        user = form.bind(User(), exclude=['password_confirm'])
90        context.add_user(user)
91        # Send to login
92        return HTTPFound(location=request.resource_url(context))
93
94    return {
95        'form': OWFormRenderer(form)
96    }
97
98
99@view_config(
100    context=OpenWorkouts,
101    name='forgot-password',
102    renderer='ow:templates/forgot_password.pt')
103def recover_password(context, request):  # pragma: no cover
104    # WIP
105    Form(request)
106
107
108@view_config(
109    context=User,
110    permission='view',
111    renderer='ow:templates/dashboard.pt')
112def dashboard(context, request):
113    """
114    Render a dashboard for the current user
115    """
116    # Look at the year we are viewing, if none is passed in the request,
117    # pick up the latest/newer available with activity
118    viewing_year = request.GET.get('year', None)
119    if viewing_year is None:
120        available_years = context.activity_years
121        if available_years:
122            viewing_year = available_years[0]
123    else:
124        # ensure this is an integer
125        viewing_year = int(viewing_year)
126
127    # Same for the month, if there is a year set
128    viewing_month = None
129    if viewing_year:
130        viewing_month = request.GET.get('month', None)
131        if viewing_month is None:
132            available_months = context.activity_months(viewing_year)
133            if available_months:
134                # we pick up the latest month available for the year,
135                # which means the current month in the current year
136                viewing_month = available_months[-1]
137        else:
138            # ensure this is an integer
139            viewing_month = int(viewing_month)
140
141    # pick up the workouts to be shown in the dashboard
142    workouts = context.workouts(viewing_year, viewing_month)
143
144    return {
145        'month_name': month_name,
146        'viewing_year': viewing_year,
147        'viewing_month': viewing_month,
148        'workouts': workouts
149    }
150
151
152@view_config(
153    context=User,
154    permission='view',
155    name='profile',
156    renderer='ow:templates/profile.pt')
157def profile(context, request):
158    """
159    "public" profile view, showing some workouts from this user, her
160    basic info, stats, etc
161    """
162    return {}
163
164
165@view_config(
166    context=User,
167    name='picture',
168    permission='view')
169def profile_picture(context, request):
170    return Response(
171        content_type='image',
172        body_file=context.picture.open())
173
174
175@view_config(
176    context=User,
177    permission='edit',
178    name='edit',
179    renderer='ow:templates/edit_profile.pt')
180def edit_profile(context, request):
181    # if not given a file there is an empty byte in POST, which breaks
182    # our blob storage validator.
183    # dirty fix until formencode fixes its api.is_empty method
184    if isinstance(request.POST.get('picture', None), bytes):
185        request.POST['picture'] = ''
186
187    nicknames = request.root.lowercase_nicknames
188    if context.nickname:
189        # remove the current user nickname from the list, preventing form
190        # validation error
191        nicknames.remove(context.nickname.lower())
192    state = State(emails=request.root.lowercase_emails, names=nicknames)
193    form = Form(request, schema=UserProfileSchema(), state=state, obj=context)
194
195    if 'submit' in request.POST and form.validate():
196        # No picture? do not override it
197        if not form.data['picture']:
198            del form.data['picture']
199        form.bind(context)
200        # reindex
201        request.root.reindex(context)
202        # Saved, send the user to the public view of her profile
203        return HTTPFound(location=request.resource_url(context, 'profile'))
204
205    # prevent crashes on the form
206    if 'picture' in form.data:
207        del form.data['picture']
208
209    return {'form': OWFormRenderer(form),
210            'timezones': common_timezones}
211
212
213@view_config(
214    context=User,
215    permission='edit',
216    name='passwd',
217    renderer='ow:templates/change_password.pt')
218def change_password(context, request):
219    form = Form(request, schema=ChangePasswordSchema(),
220                state=State(user=context))
221    if 'submit' in request.POST and form.validate():
222        context.password = form.data['password']
223        return HTTPFound(location=request.resource_url(context, 'profile'))
224    return {'form': OWFormRenderer(form)}
Note: See TracBrowser for help on using the repository browser.