From 8fc71ed17881ac4048f20b2fd3c64363bdbeacc7 Mon Sep 17 00:00:00 2001
From: Sam 
Date: Sat, 31 Aug 2019 14:11:00 +0200
Subject: [PATCH] API & Client: set file size limit for upload - fix #33
---
 Makefile.custom.config.example                |  2 +
 docs/api/activities.html                      |  1 +
 docs/api/auth.html                            |  1 +
 docs/searchindex.js                           |  2 +-
 .../fittrackee_api/activities/activities.py   |  9 +++--
 fittrackee_api/fittrackee_api/config.py       | 10 +++++
 fittrackee_api/fittrackee_api/users/auth.py   | 26 ++++++++++--
 fittrackee_api/fittrackee_api/users/utils.py  | 40 +++++++++++++++----
 .../Activity/ActivityForms/FormWithGpx.jsx    | 31 +++++++++++---
 .../src/components/User/Profile.jsx           |  5 ++-
 fittrackee_client/src/utils/index.js          | 15 +++++++
 11 files changed, 120 insertions(+), 22 deletions(-)
diff --git a/Makefile.custom.config.example b/Makefile.custom.config.example
index 8767e9e1..fa6b9968 100644
--- a/Makefile.custom.config.example
+++ b/Makefile.custom.config.example
@@ -1,6 +1,8 @@
 export REACT_APP_API_URL = http://$(HOST):$(API_PORT)
 export REACT_APP_THUNDERFOREST_API_KEY=
 export REACT_APP_GPX_LIMIT_IMPORT=10
+export REACT_APP_MAX_SINGLE_FILE_SIZE=1048576
+export REACT_APP_MAX_ZIP_FILE_SIZE=10485760
 export REACT_APP_ALLOW_REGISTRATION=true
 export WEATHER_API=
 
diff --git a/docs/api/activities.html b/docs/api/activities.html
index 514f4483..032fe64b 100644
--- a/docs/api/activities.html
+++ b/docs/api/activities.html
@@ -498,6 +498,7 @@
 Invalid token. Please log in again.
 
 
+413 Request Entity Too Large – Error during picture update: file size exceeds 1.0MB.
 500 Internal Server Error – 
 
 
diff --git a/docs/api/auth.html b/docs/api/auth.html
index bed40a95..a536dec3 100644
--- a/docs/api/auth.html
+++ b/docs/api/auth.html
@@ -488,6 +488,7 @@
 Invalid token. Please log in again.
 
 
+413 Request Entity Too Large – Error during picture update: file size exceeds 1.0MB.
 500 Internal Server Error – Error during picture update.
 
 
diff --git a/docs/searchindex.js b/docs/searchindex.js
index a5265cc6..65a1b835 100644
--- a/docs/searchindex.js
+++ b/docs/searchindex.js
@@ -1 +1 @@
-Search.setIndex({docnames:["api/activities","api/auth","api/index","api/records","api/sports","api/stats","api/users","changelog","features","index","installation","troubleshooting/administrator","troubleshooting/index","troubleshooting/user"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:56},filenames:["api/activities.rst","api/auth.rst","api/index.rst","api/records.rst","api/sports.rst","api/stats.rst","api/users.rst","changelog.md","features.rst","index.rst","installation.rst","troubleshooting/administrator.rst","troubleshooting/index.rst","troubleshooting/user.rst"],objects:{"":{"/api/activities":[0,1,1,"post--api-activities"],"/api/activities/(int:activity_id)":[0,3,1,"patch--api-activities-(int-activity_id)"],"/api/activities/(int:activity_id)/chart_data":[0,0,1,"get--api-activities-(int-activity_id)-chart_data"],"/api/activities/(int:activity_id)/chart_data/segment/(int:segment_id)":[0,0,1,"get--api-activities-(int-activity_id)-chart_data-segment-(int-segment_id)"],"/api/activities/(int:activity_id)/gpx":[0,0,1,"get--api-activities-(int-activity_id)-gpx"],"/api/activities/(int:activity_id)/gpx/segment/(int:segment_id)":[0,0,1,"get--api-activities-(int-activity_id)-gpx-segment-(int-segment_id)"],"/api/activities/map/(map_id)":[0,0,1,"get--api-activities-map-(map_id)"],"/api/activities/no_gpx":[0,1,1,"post--api-activities-no_gpx"],"/api/auth/login":[1,1,1,"post--api-auth-login"],"/api/auth/logout":[1,0,1,"get--api-auth-logout"],"/api/auth/picture":[1,1,1,"post--api-auth-picture"],"/api/auth/profile":[1,0,1,"get--api-auth-profile"],"/api/auth/profile/edit":[1,1,1,"post--api-auth-profile-edit"],"/api/auth/register":[1,1,1,"post--api-auth-register"],"/api/ping":[6,0,1,"get--api-ping"],"/api/records":[3,0,1,"get--api-records"],"/api/sports":[4,0,1,"get--api-sports"],"/api/sports/(int:sport_id)":[4,0,1,"get--api-sports-(int-sport_id)"],"/api/stats/(int:user_id)/by_sport":[5,0,1,"get--api-stats-(int-user_id)-by_sport"],"/api/stats/(int:user_id)/by_time":[5,0,1,"get--api-stats-(int-user_id)-by_time"],"/api/users":[6,0,1,"get--api-users"],"/api/users/(user_id)":[6,0,1,"get--api-users-(user_id)"],"/api/users/(user_id)/picture":[6,0,1,"get--api-users-(user_id)-picture"]}},objnames:{"0":["http","get","HTTP get"],"1":["http","post","HTTP post"],"2":["http","delete","HTTP delete"],"3":["http","patch","HTTP patch"]},objtypes:{"0":"http:get","1":"http:post","2":"http:delete","3":"http:patch"},terms:{"default":[0,5],"export":9,"float":0,"int":[0,4,5],"null":[0,1,6],"return":[0,3],"static":10,"true":6,"try":[0,1],NOT:[0,1,4],Not:[0,1,4,5,6],That:1,The:10,Use:7,_can_be_delet:4,accord:9,account:8,acit:0,activ:[2,5,7,9],activity_d:[0,3],activity_id:[0,3],adapt:10,add:[7,8,9],admin:[1,6,8,10],administr:[0,1,8,9,12],again:[0,1,3,4,5,6],all:[3,4,5,6,10],allow:[0,1,9],alpinequest:9,alreadi:1,also:[9,10],android:9,anymor:7,api:[0,1,3,4,5,6,7,8,9,10,11],app:9,applic:[0,1,3,4,5,6,9,10],arch:10,archiv:10,ascent:0,auth:[0,1,3,4,5,6],auth_token:1,auth_user_id:[0,3,4,5,6],authent:[0,2,3,4,5,6,9],author:[0,1,3,4,5,6],avail:3,ave_spe:0,ave_speed_from:0,ave_speed_to:0,averag:[0,3,8],backup:10,bad:[0,1],bearer:[0,1,3,4,5,6],befor:10,beta:10,bike:[0,4,8],bio:[1,6],biographi:1,birth:1,birth_dat:[1,6],bound:0,build:10,by_sport:5,by_tim:5,calcul:7,calendar:[7,8],can:[8,9,10],chang:[9,10],charact:[1,12],chart:[0,7,8,10],chart_data:0,check:[6,11],client:[10,11],clone:10,code:[0,1,3,4,5,6],column:12,com:[1,6,10],config:[10,11],confirm:1,contact:[0,1],content:[0,1,3,4,5,6],coordin:10,copi:10,correctli:[7,11],coverag:9,creat:[0,1,8],created_at:[1,6],creation:8,creation_d:0,credenti:1,current:7,custom:[10,11],cycl:[4,8],dark:10,darkski:8,dashboard:[7,9],data:[0,1,3,4,5,6,9,10,12],databas:10,date:[0,1,5,8],debian:10,delet:[0,1,8],depend:7,desc:0,descent:0,describ:10,detail:[6,7,9],develop:9,directori:10,disabl:[1,7,8,10],displai:[0,7,8,9,10],distanc:[0,3,7,8],distance_from:0,distance_to:0,document:[7,9],doe:[0,5,6],don:1,download:10,durat:[0,3,7,8],duration_from:0,duration_to:0,dure:1,edit:[1,8],elev:[0,8,10],email:[1,6,10],encount:10,end:[0,5],endpoint:[2,6,12],enter:8,environn:11,error:[0,1,7],europ:[1,6],even:8,exampl:[0,1,3,4,5,6,9,10,11],exist:[0,1,5,6,9,11],exodu:9,expir:[0,1,3,4,5,6],extens:[0,1],fa33f4d996844a5c73ecd1ae24456ab8:0,fals:[0,1,4,6],farest:[3,8],featur:9,fetch:10,file:[0,1,7,8,9,10,11],filter:[7,8],first:1,first_nam:[1,6],fittracke:10,fittrackee_api:10,fix:9,flask:10,flaticon:10,follow:[3,10],forbidden:[0,1],forecast:10,form:[0,1],format:[0,1,5],former:10,forrunn:9,found:[0,1,4,5,6],frame:5,freepik:10,fri:0,from:[0,3,4,5,6,9,10],gener:10,get:[0,1,3,4,5,6],gif:1,git:10,github:10,gmt:[0,1,3,6],gpl:9,gpx:[0,7,8,9,10],gpxpy:10,have:0,header:[0,1,3,4,5,6],health:6,hike:[4,8],his:8,http:[0,1,3,4,5,6,10,11],icon:10,imag:[0,1,6,10],img:4,improv:9,incorrect:7,info:1,inform:[7,9],initi:[10,11],instal:9,instanc:10,integ:[0,3,4,5,6],intern:[0,1],invalid:[0,1,3,4,5,6],issu:[9,10],jan:0,javascript:10,jpeg:6,jpg:1,json:[0,1,3,4,5,6,12],jul:[0,1,3,6],keep:9,kei:[8,10],label:4,last:[1,10],last_nam:[1,6],latitud:0,leaflet:[0,10],least:0,line:12,linux:10,list:9,local:9,localhost:[10,11],locat:[1,6],log:[0,1,3,4,5,6,9,10],login:[1,10],logout:1,longest:[3,8],longitud:0,made:[10,11],mai:10,make:10,makefil:[10,11],mandatori:[0,10],map:[0,7,8,9,10],map_id:0,match:1,max:0,max_alt:0,max_spe:0,max_speed_from:0,max_speed_to:0,maxim:0,maximum:[3,8],mean:11,messag:[0,1,6],min_alt:0,minim:[0,9],mobil:9,modification_d:0,mon:0,mondai:5,montain:8,month:[5,7,8],more:9,morn:0,mountain:4,mous:7,move:[0,7],mpwoadmin:10,multipart:[0,1],must:[1,8],name:1,nb_activ:[1,5,6],nb_sport:[1,6],necessari:10,need:10,network:11,next_act:0,no_gpx:0,note:[0,7,8,9,10],now:[8,10],number:0,oauth:[0,1,3,4,5,6],object:[0,1],one:0,onli:[0,8,9],open:[9,10],order:0,other:10,out:1,outdoor:9,over:7,own:9,owner:8,packag:10,page:0,pagin:0,paramet:[0,1,3,4,5,6],pari:[1,6],pars:[10,12],part:[0,1],password:[1,10],password_conf:1,past:10,patch:0,paus:[0,7],payload:[0,1],per:0,per_pag:0,permiss:0,pg_dump:10,pictur:[1,6],ping:6,pleas:[0,1,3,4,5,6],png:[0,1,4],point:7,pong:6,possibl:9,post:[0,1],postgresql:10,prerequisit:9,previous_act:0,privai:9,product:[9,10],profil:1,proprietari:9,provid:[0,1,3,4,5,6,8],pull:10,python:[9,10],queri:[0,5],react:10,react_app_api_url:11,readi:[9,10],rebuild:11,rechart:[0,10],record:[0,2,7,8,9],record_typ:[0,3],redux:10,regist:[1,10],registr:[1,7,8,10],reinstal:10,relat:10,releas:[7,10],repo:10,report:9,repositori:10,request:[0,1,3,4,5,6,11],requir:1,respons:[0,1,3,4,5,6],restart:10,run:[4,8,10],runner:9,sam:[1,6],samr1:10,sat:6,search:7,second:0,see:[8,9,10,11],segment:[0,7,8],segment_id:0,select:[0,1],serv:10,server:[0,1,9,10],sever:9,show:7,signatur:[0,1,3,4,5,6],singl:6,sky:10,some:[0,7,10],sorri:1,sort:0,speed:[0,3,8,10],sport:[0,2,5,8,9,10],sport_id:[0,3,4,5],standard:8,start:[0,5,10],stat:[5,7],staticmap:10,statist:[2,9],statu:[0,1,3,4,5,6],step:10,still:9,stop:10,store:9,street:9,string:[0,1,5],success:[0,1,3,4,5,6],successfulli:1,sun:[0,1,3,6],sundai:[0,5],support:[7,8],system:10,tab:11,tar:10,test:[9,10],them:9,thi:[0,7,9,10],thunderforest:10,time:[0,1,5,8],timezon:[1,6,7],titl:0,todo:[10,13],token:[0,1,3,4,5,6],tooltip:7,total:7,total_dist:[1,5,6],total_dur:[1,5,6],track:9,tracker:9,transport:[4,8],troubleshoot:9,type:[0,1,3,4,5,6],unauthor:[0,1,3,4,5,6],undefin:11,under:9,unexpect:12,updat:[0,1,7,10],upgrad:9,upload:[7,8,10],user:[0,1,2,3,4,5,7,9,10,12],user_id:[0,3,5,6],usernam:[1,6],using:[0,9],valid:[0,1,3,4,5,6],valu:[0,3,10],variabl:11,version:9,view:7,virtualenv:10,walk:[4,8],weather:[7,8,10],weather_end:0,weather_start:0,web:[0,1,3,4,5,6,9],week:5,weekm:5,were:7,wget:10,when:7,with_gpx:0,without:[0,5,8,9],workout:9,written:10,www:10,xzf:10,yarn:10,year:5,yet:[9,10],you:[0,9],your:9,zip:0,zone:1},titles:["Activities","Authentication","API documentation","Records","Sports","Statistics","Users","Change log","Features","FitTrackee","Installation","Administrator","Troubleshooting","User"],titleterms:{"new":7,activ:[0,8],administr:11,api:2,authent:1,bug:7,chang:7,charact:11,close:7,column:11,content:9,dashboard:8,data:11,detail:8,dev:10,document:2,environ:10,featur:[7,8],fittracke:9,fix:7,improv:7,instal:10,issu:7,json:11,line:11,list:8,log:7,minim:7,misc:7,pars:11,prerequisit:10,prod:10,record:3,sport:4,statist:[5,7,8],tabl:9,troubleshoot:12,unexpect:11,upgrad:10,user:[6,8,13],version:7,workout:8}})
\ No newline at end of file
+Search.setIndex({docnames:["api/activities","api/auth","api/index","api/records","api/sports","api/stats","api/users","changelog","features","index","installation","troubleshooting/administrator","troubleshooting/index","troubleshooting/user"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:56},filenames:["api/activities.rst","api/auth.rst","api/index.rst","api/records.rst","api/sports.rst","api/stats.rst","api/users.rst","changelog.md","features.rst","index.rst","installation.rst","troubleshooting/administrator.rst","troubleshooting/index.rst","troubleshooting/user.rst"],objects:{"":{"/api/activities":[0,1,1,"post--api-activities"],"/api/activities/(int:activity_id)":[0,3,1,"patch--api-activities-(int-activity_id)"],"/api/activities/(int:activity_id)/chart_data":[0,0,1,"get--api-activities-(int-activity_id)-chart_data"],"/api/activities/(int:activity_id)/chart_data/segment/(int:segment_id)":[0,0,1,"get--api-activities-(int-activity_id)-chart_data-segment-(int-segment_id)"],"/api/activities/(int:activity_id)/gpx":[0,0,1,"get--api-activities-(int-activity_id)-gpx"],"/api/activities/(int:activity_id)/gpx/segment/(int:segment_id)":[0,0,1,"get--api-activities-(int-activity_id)-gpx-segment-(int-segment_id)"],"/api/activities/map/(map_id)":[0,0,1,"get--api-activities-map-(map_id)"],"/api/activities/no_gpx":[0,1,1,"post--api-activities-no_gpx"],"/api/auth/login":[1,1,1,"post--api-auth-login"],"/api/auth/logout":[1,0,1,"get--api-auth-logout"],"/api/auth/picture":[1,1,1,"post--api-auth-picture"],"/api/auth/profile":[1,0,1,"get--api-auth-profile"],"/api/auth/profile/edit":[1,1,1,"post--api-auth-profile-edit"],"/api/auth/register":[1,1,1,"post--api-auth-register"],"/api/ping":[6,0,1,"get--api-ping"],"/api/records":[3,0,1,"get--api-records"],"/api/sports":[4,0,1,"get--api-sports"],"/api/sports/(int:sport_id)":[4,0,1,"get--api-sports-(int-sport_id)"],"/api/stats/(int:user_id)/by_sport":[5,0,1,"get--api-stats-(int-user_id)-by_sport"],"/api/stats/(int:user_id)/by_time":[5,0,1,"get--api-stats-(int-user_id)-by_time"],"/api/users":[6,0,1,"get--api-users"],"/api/users/(user_id)":[6,0,1,"get--api-users-(user_id)"],"/api/users/(user_id)/picture":[6,0,1,"get--api-users-(user_id)-picture"]}},objnames:{"0":["http","get","HTTP get"],"1":["http","post","HTTP post"],"2":["http","delete","HTTP delete"],"3":["http","patch","HTTP patch"]},objtypes:{"0":"http:get","1":"http:post","2":"http:delete","3":"http:patch"},terms:{"0mb":[0,1],"default":[0,5],"export":9,"float":0,"int":[0,4,5],"null":[0,1,6],"return":[0,3],"static":10,"true":6,"try":[0,1],NOT:[0,1,4],Not:[0,1,4,5,6],That:1,The:10,Use:7,_can_be_delet:4,accord:9,account:8,acit:0,activ:[2,5,7,9],activity_d:[0,3],activity_id:[0,3],adapt:10,add:[7,8,9],admin:[1,6,8,10],administr:[0,1,8,9,12],again:[0,1,3,4,5,6],all:[3,4,5,6,10],allow:[0,1,9],alpinequest:9,alreadi:1,also:[9,10],android:9,anymor:7,api:[0,1,3,4,5,6,7,8,9,10,11],app:9,applic:[0,1,3,4,5,6,9,10],arch:10,archiv:10,ascent:0,auth:[0,1,3,4,5,6],auth_token:1,auth_user_id:[0,3,4,5,6],authent:[0,2,3,4,5,6,9],author:[0,1,3,4,5,6],avail:3,ave_spe:0,ave_speed_from:0,ave_speed_to:0,averag:[0,3,8],backup:10,bad:[0,1],bearer:[0,1,3,4,5,6],befor:10,beta:10,bike:[0,4,8],bio:[1,6],biographi:1,birth:1,birth_dat:[1,6],bound:0,build:10,by_sport:5,by_tim:5,calcul:7,calendar:[7,8],can:[8,9,10],chang:[9,10],charact:[1,12],chart:[0,7,8,10],chart_data:0,check:[6,11],client:[10,11],clone:10,code:[0,1,3,4,5,6],column:12,com:[1,6,10],config:[10,11],confirm:1,contact:[0,1],content:[0,1,3,4,5,6],coordin:10,copi:10,correctli:[7,11],coverag:9,creat:[0,1,8],created_at:[1,6],creation:8,creation_d:0,credenti:1,current:7,custom:[10,11],cycl:[4,8],dark:10,darkski:8,dashboard:[7,9],data:[0,1,3,4,5,6,9,10,12],databas:10,date:[0,1,5,8],debian:10,delet:[0,1,8],depend:7,desc:0,descent:0,describ:10,detail:[6,7,9],develop:9,directori:10,disabl:[1,7,8,10],displai:[0,7,8,9,10],distanc:[0,3,7,8],distance_from:0,distance_to:0,document:[7,9],doe:[0,5,6],don:1,download:10,durat:[0,3,7,8],duration_from:0,duration_to:0,dure:[0,1],edit:[1,8],elev:[0,8,10],email:[1,6,10],encount:10,end:[0,5],endpoint:[2,6,12],enter:8,entiti:[0,1],environn:11,error:[0,1,7],europ:[1,6],even:8,exampl:[0,1,3,4,5,6,9,10,11],exce:[0,1],exist:[0,1,5,6,9,11],exodu:9,expir:[0,1,3,4,5,6],extens:[0,1],fa33f4d996844a5c73ecd1ae24456ab8:0,fals:[0,1,4,6],farest:[3,8],featur:9,fetch:10,file:[0,1,7,8,9,10,11],filter:[7,8],first:1,first_nam:[1,6],fittracke:10,fittrackee_api:10,fix:9,flask:10,flaticon:10,follow:[3,10],forbidden:[0,1],forecast:10,form:[0,1],format:[0,1,5],former:10,forrunn:9,found:[0,1,4,5,6],frame:5,freepik:10,fri:0,from:[0,3,4,5,6,9,10],gener:10,get:[0,1,3,4,5,6],gif:1,git:10,github:10,gmt:[0,1,3,6],gpl:9,gpx:[0,7,8,9,10],gpxpy:10,have:0,header:[0,1,3,4,5,6],health:6,hike:[4,8],his:8,http:[0,1,3,4,5,6,10,11],icon:10,imag:[0,1,6,10],img:4,improv:9,incorrect:7,info:1,inform:[7,9],initi:[10,11],instal:9,instanc:10,integ:[0,3,4,5,6],intern:[0,1],invalid:[0,1,3,4,5,6],issu:[9,10],jan:0,javascript:10,jpeg:6,jpg:1,json:[0,1,3,4,5,6,12],jul:[0,1,3,6],keep:9,kei:[8,10],label:4,larg:[0,1],last:[1,10],last_nam:[1,6],latitud:0,leaflet:[0,10],least:0,line:12,linux:10,list:9,local:9,localhost:[10,11],locat:[1,6],log:[0,1,3,4,5,6,9,10],login:[1,10],logout:1,longest:[3,8],longitud:0,made:[10,11],mai:10,make:10,makefil:[10,11],mandatori:[0,10],map:[0,7,8,9,10],map_id:0,match:1,max:0,max_alt:0,max_spe:0,max_speed_from:0,max_speed_to:0,maxim:0,maximum:[3,8],mean:11,messag:[0,1,6],min_alt:0,minim:[0,9],mobil:9,modification_d:0,mon:0,mondai:5,montain:8,month:[5,7,8],more:9,morn:0,mountain:4,mous:7,move:[0,7],mpwoadmin:10,multipart:[0,1],must:[1,8],name:1,nb_activ:[1,5,6],nb_sport:[1,6],necessari:10,need:10,network:11,next_act:0,no_gpx:0,note:[0,7,8,9,10],now:[8,10],number:0,oauth:[0,1,3,4,5,6],object:[0,1],one:0,onli:[0,8,9],open:[9,10],order:0,other:10,out:1,outdoor:9,over:7,own:9,owner:8,packag:10,page:0,pagin:0,paramet:[0,1,3,4,5,6],pari:[1,6],pars:[10,12],part:[0,1],password:[1,10],password_conf:1,past:10,patch:0,paus:[0,7],payload:[0,1],per:0,per_pag:0,permiss:0,pg_dump:10,pictur:[0,1,6],ping:6,pleas:[0,1,3,4,5,6],png:[0,1,4],point:7,pong:6,possibl:9,post:[0,1],postgresql:10,prerequisit:9,previous_act:0,privai:9,product:[9,10],profil:1,proprietari:9,provid:[0,1,3,4,5,6,8],pull:10,python:[9,10],queri:[0,5],react:10,react_app_api_url:11,readi:[9,10],rebuild:11,rechart:[0,10],record:[0,2,7,8,9],record_typ:[0,3],redux:10,regist:[1,10],registr:[1,7,8,10],reinstal:10,relat:10,releas:[7,10],repo:10,report:9,repositori:10,request:[0,1,3,4,5,6,11],requir:1,respons:[0,1,3,4,5,6],restart:10,run:[4,8,10],runner:9,sam:[1,6],samr1:10,sat:6,search:7,second:0,see:[8,9,10,11],segment:[0,7,8],segment_id:0,select:[0,1],serv:10,server:[0,1,9,10],sever:9,show:7,signatur:[0,1,3,4,5,6],singl:6,size:[0,1],sky:10,some:[0,7,10],sorri:1,sort:0,speed:[0,3,8,10],sport:[0,2,5,8,9,10],sport_id:[0,3,4,5],standard:8,start:[0,5,10],stat:[5,7],staticmap:10,statist:[2,9],statu:[0,1,3,4,5,6],step:10,still:9,stop:10,store:9,street:9,string:[0,1,5],success:[0,1,3,4,5,6],successfulli:1,sun:[0,1,3,6],sundai:[0,5],support:[7,8],system:10,tab:11,tar:10,test:[9,10],them:9,thi:[0,7,9,10],thunderforest:10,time:[0,1,5,8],timezon:[1,6,7],titl:0,todo:[10,13],token:[0,1,3,4,5,6],too:[0,1],tooltip:7,total:7,total_dist:[1,5,6],total_dur:[1,5,6],track:9,tracker:9,transport:[4,8],troubleshoot:9,type:[0,1,3,4,5,6],unauthor:[0,1,3,4,5,6],undefin:11,under:9,unexpect:12,updat:[0,1,7,10],upgrad:9,upload:[7,8,10],user:[0,1,2,3,4,5,7,9,10,12],user_id:[0,3,5,6],usernam:[1,6],using:[0,9],valid:[0,1,3,4,5,6],valu:[0,3,10],variabl:11,version:9,view:7,virtualenv:10,walk:[4,8],weather:[7,8,10],weather_end:0,weather_start:0,web:[0,1,3,4,5,6,9],week:5,weekm:5,were:7,wget:10,when:7,with_gpx:0,without:[0,5,8,9],workout:9,written:10,www:10,xzf:10,yarn:10,year:5,yet:[9,10],you:[0,9],your:9,zip:0,zone:1},titles:["Activities","Authentication","API documentation","Records","Sports","Statistics","Users","Change log","Features","FitTrackee","Installation","Administrator","Troubleshooting","User"],titleterms:{"new":7,activ:[0,8],administr:11,api:2,authent:1,bug:7,chang:7,charact:11,close:7,column:11,content:9,dashboard:8,data:11,detail:8,dev:10,document:2,environ:10,featur:[7,8],fittracke:9,fix:7,improv:7,instal:10,issu:7,json:11,line:11,list:8,log:7,minim:7,misc:7,pars:11,prerequisit:10,prod:10,record:3,sport:4,statist:[5,7,8],tabl:9,troubleshoot:12,unexpect:11,upgrad:10,user:[6,8,13],version:7,workout:8}})
\ No newline at end of file
diff --git a/fittrackee_api/fittrackee_api/activities/activities.py b/fittrackee_api/fittrackee_api/activities/activities.py
index f2cb5388..6c80ee62 100644
--- a/fittrackee_api/fittrackee_api/activities/activities.py
+++ b/fittrackee_api/fittrackee_api/activities/activities.py
@@ -11,7 +11,7 @@ from ..users.utils import (
     User,
     authenticate,
     can_view_activity,
-    verify_extension,
+    verify_extension_and_size,
 )
 from .models import Activity
 from .utils import (
@@ -818,12 +818,15 @@ def post_activity(auth_user_id):
         - Provide a valid auth token.
         - Signature expired. Please log in again.
         - Invalid token. Please log in again.
+    :statuscode 413: Error during picture update: file size exceeds 1.0MB.
     :statuscode 500:
 
     """
-    response_object = verify_extension('activity', request)
+    response_object, response_code = verify_extension_and_size(
+        'activity', request
+    )
     if response_object['status'] != 'success':
-        return jsonify(response_object), 400
+        return jsonify(response_object), response_code
 
     activity_data = json.loads(request.form["data"])
     if not activity_data or activity_data.get('sport_id') is None:
diff --git a/fittrackee_api/fittrackee_api/config.py b/fittrackee_api/fittrackee_api/config.py
index edd85d7b..7a3e4f38 100644
--- a/fittrackee_api/fittrackee_api/config.py
+++ b/fittrackee_api/fittrackee_api/config.py
@@ -2,6 +2,8 @@ import os
 
 from flask import current_app
 
+MAX_FILE_SIZE = 1 * 1024 * 1024  # 1MB
+
 
 class BaseConfig:
     """Base configuration"""
@@ -13,6 +15,14 @@ class BaseConfig:
     TOKEN_EXPIRATION_DAYS = 30
     TOKEN_EXPIRATION_SECONDS = 0
     UPLOAD_FOLDER = os.path.join(current_app.root_path, 'uploads')
+    # for gpx zip
+    MAX_CONTENT_LENGTH = int(
+        os.environ.get('REACT_APP_MAX_ZIP_FILE_SIZE', MAX_FILE_SIZE * 10)
+    )
+    # for single file (gpx or picture)
+    MAX_SINGLE_FILE = int(
+        os.environ.get('REACT_APP_MAX_SINGLE_FILE_SIZE', MAX_FILE_SIZE)
+    )
     PICTURE_ALLOWED_EXTENSIONS = {'jpg', 'png', 'gif'}
     ACTIVITY_ALLOWED_EXTENSIONS = {'gpx', 'zip'}
     REGISTRATION_ALLOWED = (
diff --git a/fittrackee_api/fittrackee_api/users/auth.py b/fittrackee_api/fittrackee_api/users/auth.py
index b524d5e1..f9f3460c 100644
--- a/fittrackee_api/fittrackee_api/users/auth.py
+++ b/fittrackee_api/fittrackee_api/users/auth.py
@@ -4,11 +4,17 @@ import os
 from fittrackee_api import appLog, bcrypt, db
 from flask import Blueprint, current_app, jsonify, request
 from sqlalchemy import exc, or_
+from werkzeug.exceptions import RequestEntityTooLarge
 from werkzeug.utils import secure_filename
 
 from ..activities.utils_files import get_absolute_file_path
 from .models import User
-from .utils import authenticate, register_controls, verify_extension
+from .utils import (
+    authenticate,
+    display_readable_file_size,
+    register_controls,
+    verify_extension_and_size,
+)
 
 auth_blueprint = Blueprint('auth', __name__)
 
@@ -529,13 +535,25 @@ def edit_picture(user_id):
         - Provide a valid auth token.
         - Signature expired. Please log in again.
         - Invalid token. Please log in again.
+    :statuscode 413: Error during picture update: file size exceeds 1.0MB.
     :statuscode 500: Error during picture update.
 
     """
-    code = 400
-    response_object = verify_extension('picture', request)
+    try:
+        response_object, response_code = verify_extension_and_size(
+            'picture', request
+        )
+    except RequestEntityTooLarge as e:
+        appLog.error(e)
+        max_file_size = current_app.config['MAX_CONTENT_LENGTH']
+        response_object = {
+            'status': 'fail',
+            'message': 'Error during picture update: file size exceeds '
+            f'{display_readable_file_size(max_file_size)}.',
+        }
+        return jsonify(response_object), 413
     if response_object['status'] != 'success':
-        return jsonify(response_object), code
+        return jsonify(response_object), response_code
 
     file = request.files['file']
     filename = secure_filename(file.filename)
diff --git a/fittrackee_api/fittrackee_api/users/utils.py b/fittrackee_api/fittrackee_api/users/utils.py
index 3c0eaa1d..2e4656b2 100644
--- a/fittrackee_api/fittrackee_api/users/utils.py
+++ b/fittrackee_api/fittrackee_api/users/utils.py
@@ -29,17 +29,18 @@ def register_controls(username, email, password, password_conf):
     return ret
 
 
-def verify_extension(file_type, req):
+def verify_extension_and_size(file_type, req):
     response_object = {'status': 'success'}
+    code = 400
 
     if 'file' not in req.files:
         response_object = {'status': 'fail', 'message': 'No file part.'}
-        return response_object
+        return response_object, code
 
     file = req.files['file']
     if file.filename == '':
         response_object = {'status': 'fail', 'message': 'No selected file.'}
-        return response_object
+        return response_object, code
 
     allowed_extensions = (
         'ACTIVITY_ALLOWED_EXTENSIONS'
@@ -47,17 +48,30 @@ def verify_extension(file_type, req):
         else 'PICTURE_ALLOWED_EXTENSIONS'
     )
 
+    file_extension = (
+        file.filename.rsplit('.', 1)[1].lower()
+        if '.' in file.filename
+        else None
+    )
+    max_file_size = current_app.config['MAX_SINGLE_FILE']
+
     if not (
-        '.' in file.filename
-        and file.filename.rsplit('.', 1)[1].lower()
-        in current_app.config.get(allowed_extensions)
+        file_extension
+        and file_extension in current_app.config.get(allowed_extensions)
     ):
         response_object = {
             'status': 'fail',
             'message': 'File extension not allowed.',
         }
+    elif file_extension != 'zip' and req.content_length > max_file_size:
+        response_object = {
+            'status': 'fail',
+            'message': 'Error during picture update: file size exceeds '
+            f'{display_readable_file_size(max_file_size)}.',
+        }
+        code = 413
 
-    return response_object
+    return response_object, code
 
 
 def verify_user(current_request, verify_admin):
@@ -116,3 +130,15 @@ def can_view_activity(auth_user_id, activity_user_id):
         }
         return response_object, 403
     return None, None
+
+
+def display_readable_file_size(size_in_bytes):
+    if size_in_bytes == 0:
+        return '0 bytes'
+    if size_in_bytes == 1:
+        return '1 byte'
+    for unit in [' bytes', 'KB', 'MB', 'GB', 'TB']:
+        if abs(size_in_bytes) < 1024.0:
+            return f"{size_in_bytes:3.1f}{unit}"
+        size_in_bytes /= 1024.0
+    return f"{size_in_bytes} bytes"
diff --git a/fittrackee_client/src/components/Activity/ActivityForms/FormWithGpx.jsx b/fittrackee_client/src/components/Activity/ActivityForms/FormWithGpx.jsx
index d9b792fd..f16f26fa 100644
--- a/fittrackee_client/src/components/Activity/ActivityForms/FormWithGpx.jsx
+++ b/fittrackee_client/src/components/Activity/ActivityForms/FormWithGpx.jsx
@@ -4,11 +4,14 @@ import { connect } from 'react-redux'
 import { setLoading } from '../../../actions/index'
 import { addActivity, editActivity } from '../../../actions/activities'
 import { history } from '../../../index'
-import { gpxLimit } from '../../../utils'
+import { fileSizeLimit, gpxLimit, zipSizeLimit } from '../../../utils'
 
 function FormWithGpx(props) {
   const { activity, loading, onAddActivity, onEditActivity, sports } = props
   const sportId = activity ? activity.sport_id : ''
+  // prettier-ignore
+  const zipTooltip =
+    `no folder inside, ${gpxLimit} files max, max size: ${zipSizeLimit}`
   return (
     
                   
                 
diff --git a/fittrackee_client/src/utils/index.js b/fittrackee_client/src/utils/index.js
index 6cb893de..7c57c2a0 100644
--- a/fittrackee_client/src/utils/index.js
+++ b/fittrackee_client/src/utils/index.js
@@ -1,6 +1,15 @@
 import { format, parse } from 'date-fns'
 import { DateTime } from 'luxon'
 
+const suffixes = ['bytes', 'KB', 'MB', 'GB', 'TB']
+const getFileSize = fileSize => {
+  const i = Math.floor(Math.log(fileSize) / Math.log(1024))
+  return (
+    (!fileSize && '0 bytes') ||
+    `${(fileSize / Math.pow(1024, i)).toFixed(1)}${suffixes[i]}`
+  )
+}
+
 export const version = '0.2.1-beta' // version stored in 'utils' for now
 export const apiUrl = `${process.env.REACT_APP_API_URL}/api/`
 /* prettier-ignore */
@@ -8,6 +17,12 @@ export const thunderforestApiKey = `${
   process.env.REACT_APP_THUNDERFOREST_API_KEY
 }`
 export const gpxLimit = `${process.env.REACT_APP_GPX_LIMIT_IMPORT}`
+export const fileSizeLimit = getFileSize(
+  +process.env.REACT_APP_MAX_SINGLE_FILE_SIZE
+)
+export const zipSizeLimit = getFileSize(
+  +process.env.REACT_APP_MAX_ZIP_FILE_SIZE
+)
 export const isRegistrationAllowed =
   process.env.REACT_APP_ALLOW_REGISTRATION !== 'false'