Private
Public Access
1
0
Files
rowsandall/rowers/views/userviews.py
Sander Roosendaal bc715d14fe adding some privacy
2021-10-12 21:15:46 +02:00

770 lines
29 KiB
Python

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from rowers.views.statements import *
@login_required()
def deactivate_user(request):
pk = request.user.id
user = User.objects.get(pk=pk)
user_form = DeactivateUserForm(instance=user)
if request.user.is_authenticated and request.user.id == user.id:
if request.method == "POST":
user_form = DeactivateUserForm(request.POST, instance=user)
if user_form.is_valid():
if not user_form.cleaned_data['is_active']:
r = Rower.objects.get(user=user)
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
try:
subscriptions = braintreestuff.find_subscriptions(r)
for subscription in subscriptions:
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages:
messages.info(request,message)
except ProcessorCustomerError:
pass
r.paidplan = None
r.teamplanexpires = timezone.now()
r.planexpires = timezone.now()
r.clubsize = 0
r.rowerplan = 'basic'
r.save()
deactivate_user = user_form.save(commit=False)
user.is_active = False
user.save()
deactivate_user.save()
# url = reverse(auth_views.logout_then_login)
url = '/logout/?next=/login'
return HttpResponseRedirect(url)
return render(request, "userprofile_deactivate.html", {
"user_form": user_form,
})
else: # pragma: no cover
raise PermissionDenied
@login_required()
def user_gdpr_optin(request):
r = getrower(request.user)
r.gdproptin = False
r.gdproptindate = None
r.save()
nexturl = request.GET.get('next','/rowers/list-workouts/')
if r.gdproptin: # pragma: no cover
return HttpResponseRedirect(nexturl)
return render(request,'gdpr_optin.html',{
"next": nexturl
})
@login_required()
def user_gdpr_confirm(request):
r = getrower(request.user)
r.gdproptin = True
r.gdproptindate = timezone.now()
r.save()
nexturl = request.GET.get('next','/rowers/list-workouts/')
return HttpResponseRedirect(nexturl)
@login_required()
def remove_user(request):
pk = request.user.id
user = User.objects.get(pk=pk)
user_form = DeleteUserForm(instance=user)
if request.user.is_authenticated and request.user.id == user.id:
if request.method == "POST":
user_form = DeleteUserForm(request.POST,instance=user)
if user_form.is_valid():
cd = user_form.cleaned_data
name = user.first_name+' '+user.last_name
email = user.email
r = Rower.objects.get(user=user)
if r.paidplan is not None and r.paidplan.paymentprocessor == 'braintree': # pragma: no cover
try:
subscriptions = braintreestuff.find_subscriptions(r)
for subscription in subscriptions:
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages:
messages.info(request,message)
except:
pass
if cd['delete_user']:
# delete workouts
Workout.objects.filter(user=user.rower).delete()
# delete planned sessions
PlannedSession.objects.filter(manager=user).delete()
user.delete()
res = myqueue(queuehigh,
handle_sendemail_userdeleted,
name, email)
url = '/logout/?next=/login'
# url = reverse(auth_views.logout_then_login)
return HttpResponseRedirect(url)
return render(request, "userprofile_delete.html", {
"user_form": user_form,
})
else: # pragma: no cover
raise PermissionDenied
@login_required()
def survey(request): # pragma: no cover
r = getrower(request.user)
surveyform = SurveyForm()
if request.method == 'POST':
form = SurveyForm(request.POST)
r.surveydone = True
r.surveydonedate = timezone.now()
r.save()
nexturl = request.GET.get('next')
return HttpResponseRedirect(nexturl)
context = {
'teams':get_my_teams(request.user),
'rower':r,
'form':surveyform,
}
return render(request,'survey.html',context)
@login_required()
def start_trial_view(request):
r = getrower(request.user)
if not can_start_trial(request.user): # pragma: no cover
messages.error(request,'You do not qualify for a trial')
url = '/rowers/paidplans'
return HttpResponseRedirect(url)
r.protrialexpires = timezone.now()+datetime.timedelta(13)
r.save()
url = reverse('workouts_view')
messages.info(request,'We have started your 14 day trial period')
subject2 = "User started Pro Trial"
message2 = "User Started Pro Trial.\n"
message2 += request.user.email + "\n"
message2 += "User name: "+request.user.username
send_mail(subject2, message2,
'Rowsandall Server <info@rowsandall.com>',
['roosendaalsander@gmail.com'])
send_template_email('Rowsandall <info@rowsandall.com>',
[r.user.email],
'Welcome to the Rowsandall Pro Trial',
'protrialewelcome.html',
{'first_name':r.user.first_name,
'last_name':r.user.last_name})
return HttpResponseRedirect(url)
@login_required()
def start_plantrial_view(request):
r = getrower(request.user)
if not can_start_plantrial(request.user): # pragma: no cover
messages.error(request,'You do not qualify for a trial')
url = '/rowers/paidplans'
return HttpResponseRedirect(url)
r.plantrialexpires = timezone.now()+datetime.timedelta(13)
r.protrialexpires = timezone.now()+datetime.timedelta(13)
r.save()
url = reverse('workouts_view')
messages.info(request,'We have started your 14 day trial period')
subject2 = "User started Plan Trial"
message2 = "User Started Plan Trial.\n"
message2 += request.user.email + "\n"
message2 += "User name: "+request.user.username
send_mail(subject2, message2,
'Rowsandall Server <info@rowsandall.com>',
['roosendaalsander@gmail.com'])
send_template_email('Rowsandall <info@rowsandall.com>',
[r.user.email],
'Welcome to the Rowsandall Self-Coach Trial',
'plantrialwelcome.html',
{'first_name':r.user.first_name,
'last_name':r.user.last_name})
return HttpResponseRedirect(url)
# Page where user can manage his favorite charts
@login_required()
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def rower_favoritecharts_view(request,userid=0):
message = ''
successmessage = ''
r = getrequestrowercoachee(request,userid=userid,notpermanent=True)
staticchartform = StaticChartRowerForm(instance=r)
datasettingsform = DataRowerForm(instance=r)
favorites = FavoriteChart.objects.filter(user=r).order_by('id')
aantal = len(favorites)
favorites_data = [{'yparam1':f.yparam1,
'yparam2':f.yparam2,
'xparam':f.xparam,
'plottype':f.plottype,
'workouttype':f.workouttype,
'reststrokes':f.reststrokes,
'notes':f.notes,}
for f in favorites]
FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=0)
if aantal==0:
FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1)
if request.method == 'POST' and 'staticgrids' in request.POST: # pragma: no cover
staticchartform = StaticChartRowerForm(request.POST,instance=r)
if staticchartform.is_valid():
r.staticgrids = staticchartform.cleaned_data.get('staticgrids')
r.slowpaceerg = staticchartform.cleaned_data.get('slowpaceerg')
r.fastpaceerg = staticchartform.cleaned_data.get('fastpaceerg')
r.slowpaceotw = staticchartform.cleaned_data.get('slowpaceotw')
r.fastpaceotw = staticchartform.cleaned_data.get('fastpaceotw')
r.staticchartonupload = staticchartform.cleaned_data.get('staticchartonupload')
r.fav_analysis = staticchartform.cleaned_data.get('fav_analysis')
r.usersmooth = staticchartform.cleaned_data.get('usersmooth')
r.save()
if request.method == 'POST' and 'save_data' in request.POST: # pragma: no cover
datasettingsform = DataRowerForm(request.POST,instance=r)
if datasettingsform.is_valid():
cd = datasettingsform.cleaned_data
r.autojoin = cd.get('autojoin')
r.dosmooth = cd.get('dosmooth')
r.erg_recalculatepower = cd.get('erg_recalculatepower')
r.save()
messages.info(request,"We have updated your data settings")
if request.method == 'POST' and 'defaults_data' in request.POST: # pragma: no cover
defaultsmooth = Rower._meta.get_field('dosmooth').get_default()
defaultautojoin = Rower._meta.get_field('autojoin').get_default()
defaultergcalcpower = Rower._meta.get_field('erg_recalculatepower').get_default()
r.dosmooth = defaultsmooth
r.autojoin = defaultautojoin
r.erg_recalculatepower = defaultergcalcpower
r.save()
datasettingsform = DataRowerForm(instance=r)
messages.info(request,"We have reset your data settings to the default values")
if request.method == 'POST' and 'form-TOTAL_FORMS' in request.POST: # pragma: no cover
favorites_formset = FavoriteChartFormSet(request.POST)
if favorites_formset.is_valid():
new_instances = []
for favorites_form in favorites_formset:
yparam1 = favorites_form.cleaned_data.get('yparam1')
yparam2 = favorites_form.cleaned_data.get('yparam2')
xparam = favorites_form.cleaned_data.get('xparam')
plottype = favorites_form.cleaned_data.get('plottype')
workouttype = favorites_form.cleaned_data.get('workouttype')
reststrokes = favorites_form.cleaned_data.get('reststrokes')
notes = favorites_form.cleaned_data.get('notes')
new_instances.append(FavoriteChart(user=r,
yparam1=yparam1,
yparam2=yparam2,
xparam=xparam,
plottype=plottype,
notes=notes,
workouttype=workouttype,
reststrokes=reststrokes))
try:
with transaction.atomic():
FavoriteChart.objects.filter(user=r).delete()
FavoriteChart.objects.bulk_create(new_instances)
successmessage = "You have updated your favorites"
messages.info(request,message)
if len(new_instances)==0:
FavoriteChartFormSet=formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1)
favorites_formset = FavoriteChartFormSet()
except IntegrityError:
message = "something went wrong"
messages.error(request,message)
else:
favorites_formset = FavoriteChartFormSet(initial=favorites_data)
context = {
'favorites_formset':favorites_formset,
'teams':get_my_teams(request.user),
'rower':r,
'staticchartform':staticchartform,
'datasettingsform':datasettingsform,
}
return render(request,'favoritecharts.html',context)
# page where user sets his export settings
@login_required()
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def rower_exportsettings_view(request,userid=0):
attrtokens = {
'polar_auto_import':'polartoken',
'c2_auto_export':'c2token',
'c2_auto_import':'c2token',
'runkeeper_auto_export':'runkeepertoken',
'sporttracks_auto_export':'sporttrackstoken',
'strava_auto_export':'stravatoken',
'strava_auto_import':'stravatoken',
'strava_auto_delete':'stravatoken',
'trainingpeaks_auto_export':'tptoken',
'rp3_auto_import':'rp3token',
'nk_auto_import':'nktoken'
}
r = getrequestrowercoachee(request,userid=userid)
if request.method == 'POST':
form = RowerExportForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
if r.rowerplan == 'basic': # pragma: no cover
messages.error(request,'These settings can only be set if you are a user on one of the <a href="/rowers/paidplans">paid plans</a>.')
for attr, value in cd.items():
doset = True
try:
tokenname = attrtokens[attr]
if getattr(r, tokenname) == '' or getattr(r, tokenname) == None:
doset = False
except KeyError:
doset = True
if r.rowerplan == 'basic': # pragma: no cover
doset = False
if not doset:
before = getattr(r,attr)
if before == value:
doset = True
if doset:
setattr(r, attr, value)
else:
if r.rowerplan != 'basic':
messages.error(request,'Could not set '+attr+'. You need to create the connection first.')
r.save()
messages.info(request,'Settings saved')
else:
form = RowerExportForm(instance=r)
breadcrumbs = [
{
'url':'/rowers/me/edit/',
'name': 'Profile'
},
{
'url': reverse('rower_exportsettings_view'),
'name': 'Export Settings'
}
]
return render(request, 'rower_exportsettings.html',
{'form':form,
'rower':r,
'breadcrumbs': breadcrumbs,
})
# Page where user can set his details
# Add email address to form so user can change his email address
@login_required()
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def rower_edit_view(request,rowerid=0,userid=0,message=""):
r = getrequestrowercoachee(request,rowerid=rowerid,userid=userid,notpermanent=True)
if 'courseshare' in request.GET:
courseshare = request.GET.get('courseshare',"ok")
if courseshare == 'true':
r.share_course_results = True
r.save()
elif courseshare == 'false':
r.share_course_results = False
r.save()
rowerid = r.id
breadcrumbs = [
{
'url':'/rowers/me/edit/',
'name': 'Profile'
},
{
'url': reverse('rower_edit_view'),
'name': 'Account Settings'
}
]
if request.method == 'POST':
accountform = AccountRowerForm(request.POST, instance=r)
userform = UserForm(request.POST,instance=r.user)
if accountform.is_valid() and userform.is_valid():
# process
cd = accountform.cleaned_data
ucd = userform.cleaned_data
first_name = ucd['first_name']
last_name = ucd['last_name']
email = ucd['email']
sex = cd['sex']
try:
offercoaching = cd['offercoaching']
except KeyError: # pragma: no cover
offercoaching = False
autojoin = cd['autojoin']
adaptiveclass = cd['adaptiveclass']
defaultlandingpage = cd['defaultlandingpage']
weightcategory = cd['weightcategory']
birthdate = cd['birthdate']
showfavoritechartnotes = cd['showfavoritechartnotes']
getemailnotifications = cd['getemailnotifications']
getimportantemails = cd['getimportantemails']
share_course_results = cd['share_course_results']
defaulttimezone=cd['defaulttimezone']
fav_analysis = cd['fav_analysis']
usersmooth = cd['usersmooth']
u = r.user
if u.email != email and len(email): # pragma: no cover
resetbounce = True
else:
resetbounce = False
if len(first_name):
u.first_name = first_name
u.last_name = last_name
if len(email): ## and check_email_freeforuse(u,email):
u.email = email
resetbounce = True
emailalternatives = cd['emailalternatives']
u.save()
r.defaulttimezone=defaulttimezone
r.weightcategory = weightcategory
r.adaptiveclass = adaptiveclass
r.getemailnotifications = getemailnotifications
r.getimportantemails = getimportantemails
r.offercoaching = offercoaching
r.defaultlandingpage = defaultlandingpage
r.showfavoritechartnotes = showfavoritechartnotes
r.share_course_results = share_course_results
r.sex = sex
r.birthdate = birthdate
r.autojoin = autojoin
r.emailalternatives = emailalternatives
r.fav_analysis = fav_analysis
r.usersmooth = usersmooth
if resetbounce and r.emailbounced: # pragma: no cover
r.emailbounced = False
r.save()
accountform = AccountRowerForm(instance=r)
userform = UserForm(instance=u)
successmessage = 'Account Information changed'
messages.info(request,successmessage)
else:
accountform = AccountRowerForm(instance=r)
userform = UserForm(instance=r.user)
grants = AccessToken.objects.filter(user=request.user)
return render(request, 'rower_form.html',
{
'teams':get_my_teams(request.user),
'breadcrumbs':breadcrumbs,
'grants':grants,
'userform':userform,
'accountform':accountform,
'rower':r,
})
# Page where user can set his details
# Add email address to form so user can change his email address
@login_required()
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def rower_prefs_view(request,userid=0,message=""):
r = getrequestrowercoachee(request,userid=userid,notpermanent=True)
rowerid = r.id
breadcrumbs = [
{
'url':'/rowers/me/edit/',
'name': 'Profile'
},
{
'url': reverse('rower_prefs_view'),
'name': 'Zones'
}
]
form = RowerHRZonesForm(instance=r)
powerform = RowerPowerForm(instance=r)
powerzonesform = RowerPowerZonesForm(instance=r)
cpform = RowerCPForm(instance=r)
if request.method == 'POST' and "ut2" in request.POST:
form = RowerHRZonesForm(request.POST)
if form.is_valid():
# something
cd = form.cleaned_data
hrmax = cd['max']
ut2 = cd['ut2']
ut1 = cd['ut1']
at = cd['at']
tr = cd['tr']
an = cd['an']
rest = cd['rest']
hrrestname = cd['hrrestname']
hrut2name = cd['hrut2name']
hrut1name = cd['hrut1name']
hratname = cd['hratname']
hrtrname = cd['hrtrname']
hranname = cd['hranname']
hrmaxname = cd['hrmaxname']
hrzones = [hrrestname,hrut2name,hrut1name,hratname,hrtrname,hranname,hrmaxname]
r.max = max(min(hrmax,250),10)
r.ut2 = max(min(ut2,250),10)
r.ut1 = max(min(ut1,250),10)
r.at = max(min(at,250),10)
r.tr = max(min(tr,250),10)
r.an = max(min(an,250),10)
r.rest = max(min(rest,250),10)
r.hrzones = hrzones
r.save()
successmessage = "Your Heart Rate data were changed"
messages.info(request,successmessage)
elif request.method == 'POST' and "ftp" in request.POST:
powerform = RowerPowerForm(request.POST)
if powerform.is_valid():
cd = powerform.cleaned_data
hrftp = cd['hrftp']
if hrftp == 0: # pragma: no cover
hrftp = int((r.an+r.tr)/2.)
ftp = cd['ftp']
otwslack = cd['otwslack']
powerfrac = 100*np.array([r.pw_ut2,
r.pw_ut1,
r.pw_at,
r.pw_tr,r.pw_an])/r.ftp
r.ftp = max(min(ftp,650),50)
r.otwslack = max(min(otwslack,50),0)
ut2,ut1,at,tr,an = (r.ftp*powerfrac/100.).astype(int)
r.pw_ut2 = ut2
r.pw_ut1 = ut1
r.pw_at = at
r.pw_tr = tr
r.pw_an = an
r.hrftp = hrftp
r.save()
message = "FTP and/or OTW slack values changed."
messages.info(request,message)
elif request.method == 'POST' and "ut3name" in request.POST:
powerzonesform = RowerPowerZonesForm(request.POST)
if powerzonesform.is_valid():
cd = powerzonesform.cleaned_data
pw_ut2 = cd['pw_ut2']
pw_ut1 = cd['pw_ut1']
pw_at = cd['pw_at']
pw_tr = cd['pw_tr']
pw_an = cd['pw_an']
ut3name = cd['ut3name']
ut2name = cd['ut2name']
ut1name = cd['ut1name']
atname = cd['atname']
trname = cd['trname']
anname = cd['anname']
powerzones = [ut3name,ut2name,ut1name,atname,trname,anname]
r.pw_ut2 = pw_ut2
r.pw_ut1 = pw_ut1
r.pw_at = pw_at
r.pw_tr = pw_tr
r.pw_an = pw_an
r.powerzones = powerzones
r.save()
successmessage = "Your Power Zone data were changed"
messages.info(request,successmessage)
elif request.method == 'POST' and 'cprange' in request.POST: # pragma: no cover
cpform = RowerCPForm(request.POST)
if cpform.is_valid():
cd = cpform.cleaned_data
cprange = cd['cprange']
kfit = cd['kfit']
kfatigue = cd['kfatigue']
r.cprange = cprange
r.kfit = kfit
r.kfatigue = kfatigue
r.save()
messages.info(request,'Updated CP range and time decay constants')
success = dataprep.update_rolling_cp(r,mytypes.otwtypes,'water')
success = dataprep.update_rolling_cp(r,mytypes.otetypes,'erg')
return render(request, 'rower_preferences.html',
{
'form':form,
'teams':get_my_teams(request.user),
'powerform':powerform,
'powerzonesform':powerzonesform,
'breadcrumbs':breadcrumbs,
'cpform':cpform,
'rower':r,
})
# Revoke an app that you granted access through the API.
# this views is called when you press a button on the User edit page
# the button is only there when you have granted access to an app
@login_required()
def rower_revokeapp_view(request,id=0): # pragma: no cover
try:
tokens = AccessToken.objects.filter(user=request.user,application=id)
refreshtokens = AccessToken.objects.filter(user=request.user,application=id)
for token in tokens:
token.revoke()
for token in refreshtokens:
token.revoke()
r = getrower(request.user)
form = RowerForm(instance=r)
powerform = RowerPowerForm(instance=r)
grants = AccessToken.objects.filter(user=request.user)
url = reverse('rower_edit_view')
return HttpResponseRedirect(url)
except AccessToken.DoesNotExist:
raise Http404("Access token doesn't exist")
@login_required()
def rower_update_empower_view(
request,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now()
): # pragma: no cover
try:
r = getrower(request.user)
except Rower.DoesNotExist:
raise Http404("Rower doesn't exist")
if request.method == 'POST' and 'daterange' in request.POST:
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
startdate = dateform.cleaned_data['startdate']
enddate = dateform.cleaned_data['enddate']
startdatestring = startdate.strftime('%Y-%m-%d')
enddatestring = enddate.strftime('%Y-%m-%d')
request.session['startdate'] = startdatestring
request.session['enddate'] = enddatestring
else:
dateform = DateRangeForm(initial={
'startdate':startdate,
'enddate':enddate,
})
if request.method == 'POST' and 'workouts' in request.POST:
form = WorkoutMultipleCompareForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
workouts = cd['workouts']
workoutdicts = []
for w in workouts:
if w.user != r:
message = "You can only alter your own workouts"
messages.error(request,message)
if 'x' in w.boattype and w.oarlength is not None and w.oarlength > 3.30:
message = "Oarlength and boat type mismatch for workout "+str(w.id)+". Skipping workout"
messages.error(request,message)
elif 'x' not in w.boattype and w.oarlength is not None and w.oarlength <= 3.30:
message = "Oarlength and boat type mismatch for workout "+str(w.id)+". Skipping workout"
messages.error(request,message)
elif w.oarlength is None:
message = "Incorrect oarlength in workout "+str(w.id)+". Skipping workout"
messages.error(request,message)
else:
workoutdict = {
'id':w.id,
'boattype':w.boattype,
'filename':w.csvfilename,
'inboard':w.inboard,
'oarlength':w.oarlength
}
workoutdicts.append(workoutdict)
w.workoutsource = 'speedcoach2corrected'
w.save()
job = myqueue(queuelow,handle_update_empower,
request.user.email,workoutdicts,
debug=False,
emailbounced=r.emailbounced)
try:
request.session['async_tasks'] += [(job.id,'update_empower')]
except KeyError:
request.session['async_tasks'] = [(job.id,'update_empower')]
successmessage = 'Your workouts are being updated in the background. You will receive email when this is done. You can check the status of your calculations <a href="/rowers/jobs-status" target="_blank">here</a>'
messages.info(request,successmessage)
url = reverse('workouts_view')
return HttpResponseRedirect(url)
else:
workouts = Workout.objects.filter(
startdatetime__gte=startdate,
startdatetime__lte=enddate,
workoutsource='speedcoach2',
user=r,
).order_by("-date","-starttime")
form = WorkoutMultipleCompareForm()
form.fields["workouts"].queryset = workouts
# GET request = prepare form
return render(request, 'empower_fix.html',
{'workouts':workouts,
'active': 'nav-workouts',
'dateform':dateform,
'form':form,
'rower':r
})