From 628f2f3e27eca0c69422183cfd4c57aeaac4286a Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 23 Sep 2019 20:30:34 +0200 Subject: [PATCH] API - add route to get application statistics --- docs/_sources/api/stats.rst.txt | 3 +- docs/api/stats.html | 48 ++++++++++ docs/http-routingtable.html | 5 ++ docs/objects.inv | Bin 793 -> 801 bytes docs/searchindex.js | 2 +- docsrc/source/api/stats.rst | 3 +- .../fittrackee_api/activities/stats.py | 64 ++++++++++++- .../fittrackee_api/tests/test_stats_api.py | 84 ++++++++++++++++++ 8 files changed, 204 insertions(+), 5 deletions(-) diff --git a/docs/_sources/api/stats.rst.txt b/docs/_sources/api/stats.rst.txt index 0621d298..17be2d6a 100644 --- a/docs/_sources/api/stats.rst.txt +++ b/docs/_sources/api/stats.rst.txt @@ -4,4 +4,5 @@ Statistics .. autoflask:: fittrackee_api:create_app() :endpoints: stats.get_activities_by_sport, - stats.get_activities_by_time + stats.get_activities_by_time, + stats.get_application_stats diff --git a/docs/api/stats.html b/docs/api/stats.html index 46690d57..c32eac1a 100644 --- a/docs/api/stats.html +++ b/docs/api/stats.html @@ -333,6 +333,54 @@ +
+
+GET /api/stats/all
+

Get all application statistics

+

Example requests:

+
GET /api/stats/all HTTP/1.1
+
+
+

Example responses:

+
HTTP/1.1 200 OK
+Content-Type: application/json
+
+{
+  "data": {
+    "activities": 3,
+    "sports": 3,
+    "users": 2
+  },
+  "status": "success"
+}
+
+
+
+
Parameters
+
    +
  • auth_user_id (integer) – authenticate user id (from JSON Web Token)

  • +
+
+
Request Headers
+
+
+
Status Codes
+
    +
  • 200 OK – success

  • +
  • 401 Unauthorized

      +
    • Provide a valid auth token.

    • +
    • Signature expired. Please log in again.

    • +
    • Invalid token. Please log in again.

    • +
    +

  • +
  • 403 Forbidden – You do not have permissions.

  • +
+
+
+
+ diff --git a/docs/http-routingtable.html b/docs/http-routingtable.html index d2d96cc8..2c199a5e 100644 --- a/docs/http-routingtable.html +++ b/docs/http-routingtable.html @@ -199,6 +199,11 @@ GET /api/stats/(int:user_id)/by_time + + + + GET /api/stats/all + diff --git a/docs/objects.inv b/docs/objects.inv index 5279ff5974bb8999af1c8b81369ae0859373267a..6eb13caa65b49afe82df8717db82d8f4644ea432 100644 GIT binary patch delta 640 zcmV-`0)PFP2B8L!tbfY(yzk@j;E&B&&vRBF|I3lXKx)MPSOJpnWEuHZW7~XD5lU5n z1{Rv-Ymi=F{=ss*W=|Yh#X3eJCd<3YFr^sLd6FJ zxg9k*9H!@86@M>i96-jK(CC~;LLp?CJaKL~GJ3J|4!w|=SnX)!bkc><9b?^IJ407E z?s!hl_p#wK5`u##Gq9%F z&eLM&Hd|@S{<6Z*l^=XcoBedQtdo}az%F8NBSe4F27fG%r6>qpy=}?e)X)6MOf3Gi zk~`H>&j&9Ua?u$B?@D-!9cIv39v_H`jQZJ`UH;fbzVM8aU$&D4=Q5H9+nzj`b~b(b zL_6&V@}v_P)GDmpe%nYsmz@08%}o8v=qgZ;K&YGst@4NI64lRMf$7h&;QBEuzIVN> zf^IHi!+Bny(PBSp#SglfCAAI|_Z*)kEB*i|nObbqm})Q8^SH;(BUvlTl|1@0^#SYo zDauhj8#bc>m@Mk0!;ZO9+xR1^AVVp}mj;Gf2vpZ~&dQc|>N`k=LWX%>6}nv&4khHI aPOAb-dR~SSmfi^0P&z*Elk6XclhS0!?LpcA delta 632 zcmV-;0*C#f2AKwstbYp6yzk@jV4KZZ&vRBF|I3lXKx)MPSOJpnWSRL^W7~XD8A?@x z1{Rv-Ymi+$jxL=Gj#9mQA|HLegRq2dFA z+>V+Y4%73lihmb04j|)AXmrjap%Ai6K5;G_8NJwfhh9ibtTq}sopfPz$5=nFouMln zcRVNO``GX^5`u$I$aOR_Pu3kZH`2@bWOPa4S{v7`W0vjxbn;)H19=M{n8MiI3}!QI z*&$XKy7GgEZuZmJvQAo_FMrA1G|v3lN-X}okvsLIJ^;L6 z$VF!iyer`?c9@{EJU$SW8TE%_cKL%7`NC61e%V15oUBM5Y+UkWp0jB)B-&|*kSATp zpjKh!_T5JEx#i@ye$3SWgsuX0jfcu9Xq7+Akf?F?3QWI_1=q){_}-1O3c9(84SRt` zi+$9JA93_!mh?JM+;e=EtoQ?LkT(Q)2hIdo|mbF Sr8mMgl+MrlB>M;DpS<7D13*#$ diff --git a/docs/searchindex.js b/docs/searchindex.js index 3e6105bd..813c66c3 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,3,1,"patch--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],"10mb":10,"1mb":10,"default":[0,5,10],"export":9,"float":0,"int":[0,4,5],"null":[0,1,6],"return":[0,3],"static":10,"true":[1,4,6,10],"try":[0,1],For:10,NOT:[0,1,4],Not:[0,1,4,5,6],That:1,The:[7,10],Use:7,accord:9,account:[7,8],acit:0,activ:[2,4,5,7,9],activity_d:[0,3],activity_id:[0,3],adapt:10,add:[7,8,9],admin:[1,4,6,7,8,10],administr:[0,1,7,8,9,12],again:[0,1,3,4,5,6],all:[3,4,5,6,10],allow:[0,1,9,10],alpinequest:9,alreadi:1,also:9,android:9,anymor:7,api:[0,1,3,4,5,6,7,8,9,10,11],app:[9,10],applic:[0,1,3,4,5,6,9,10],arch:10,archiv:10,archlinux: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,7,8],backup:10,bad:[0,1,4],bearer:[0,1,3,4,5,6],befor:10,beta:10,bike:[0,4,7,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:[7,8,9,10],chang:[9,10],charact:[1,12],chart:[0,7,8,10],chart_data:0,check:[6,11],choos:7,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],creat:[0,1,7,8],created_at:[1,6],creation:[7,8],creation_d:0,credenti:1,current:7,custom:[10,11],cycl:[4,7,8],dai:7,dark:10,darkski:[7,8,10],dashboard:[7,9],data:[0,1,3,4,5,6,9,10,12],databas:10,date:[0,1,5,7,8],debian:10,defaut:10,defin:10,delet:[0,1,7,8],depend:7,desc:0,descent:0,describ:10,descript:10,detail:[6,7,9],develop:9,directori:10,disabl:[1,7,8],displai:[0,7,8,9,10],distanc:[0,3,7,8],distance_from:0,distance_to:0,document:[7,9,10],doe:[0,1,5,6],don:1,download:10,durat:[0,3,7,8],duration_from:0,duration_to:0,dure:[0,1],edit:[1,7,8],elev:[0,7,8,10],email:[1,6,10],encount:10,end:[0,5],endpoint:[2,6,12],enter:[7,8],entiti:[0,1],environ:9,environn:11,error:[0,1,4,7],europ:[1,6],even:[7,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,7,8],featur:9,fetch:10,file:[0,1,7,8,9,10,11],filter:[7,8],first:[1,9],first_nam:[1,6],fittracke:10,fittrackee_api:10,fix:9,flask:10,flaticon:10,follow:[3,10],forbidden:[0,1,4],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,has_act:4,have:[0,4],header:[0,1,3,4,5,6],health:6,hike:[4,7,8],his:[7,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,4],invalid:[0,1,3,4,5,6],is_act:4,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:[7,8,10],label:4,languag:1,larg:[0,1],last:[1,10],last_nam:[1,6],latitud:0,leaflet:[0,10],least:0,limit:7,line:12,linux:10,list:[7,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,7,8],longitud:0,made:[10,11],mai:10,make:10,makefil:[10,11],manag:7,mandatori:[0,10],map:[0,7,8,9,10],map_id:0,match:1,max:[0,10],max_alt:0,max_spe:0,max_speed_from:0,max_speed_to:0,maxim:0,maximum:[3,7,8],mean:11,messag:[0,1,6],min_alt:0,minim:0,mobil:9,modification_d:0,mon:0,mondai:[1,5],montain:[7,8],month:[5,7,8],more:[7,9],morn:0,mountain:4,mous:7,move:[0,7],mpwoadmin:10,multipart:[0,1],must:[1,4,7,8,10],name:1,nb_activ:[1,5,6],nb_sport:[1,6],necessari:10,need:10,network:11,next_act:0,no_gpx:0,non:4,note:[0,7,8,10],now:[7,8,10],number:[0,10],oauth:[0,1,3,4,5,6],object:[0,1,4],one:0,onli:[0,7,8],open:[9,10],option:10,order:0,other:10,out:1,outdoor:9,over:7,own:9,owner:[7,8],packag:[7,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,4],paus:[0,7],payload:[0,1,4],per:0,per_pag:0,permiss:[0,4],pg_dump:10,pictur:[0,1,6,10],ping:6,pipenv:7,pleas:[0,1,3,4,5,6],png:[0,1,4],poetri:[7,10],point:7,pong:6,possibl:9,post:[0,1],postgresql:10,prefer:1,prerequisit:9,previous_act:0,privai:9,product:[9,10],profil:1,project:10,proprietari:9,provid:[0,1,3,4,5,6,7,8],pull:10,python:[7,10],queri:[0,5],react:10,react_app_allow_registr:10,react_app_api_url:11,react_app_gpx_limit_import:10,react_app_max_single_file_s:10,react_app_max_zip_file_s:10,react_app_thunderforest_api_kei:10,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],relat:10,releas:[9,10],replac:7,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,7,8,10],runner:9,sam:[1,6],samr1:10,sat:6,search:7,second:0,see:[7,8,9,10,11],segment:[0,7,8],segment_id:0,select:[0,1],serv:10,server:[0,1,4,9,10],set:10,sever:9,show:7,signatur:[0,1,3,4,5,6],sinc:10,singl:6,size:[0,1,7,10],sky:10,some:[0,7,10],sorri:1,sort:0,speed:[0,3,7,8,10],sport:[0,2,5,7,8,9,10],sport_id:[0,3,4,5],sports_list:[1,6],standard:[7,8],start:[0,1,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,4,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:10,them:9,thi:[0,7,9,10],thunderforest:10,time:[0,1,5,7,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,7,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,4,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],usernanm:1,using:[0,9],valid:[0,1,3,4,5,6],valu:[0,3,10],variabl:[9,11],version:[9,10],view:7,virtualenv:10,walk:[4,7,8],weather:[7,8,10],weather_api:10,weather_end:0,weather_start:0,web:[0,1,3,4,5,6,9],week:[1,5,7],weekm:[1,5],were:7,wget:10,when:7,wiki:7,with_gpx:0,without:[0,5,7,8,9],workout:9,written:10,www:10,xzf:10,yaourt:10,yarn:10,year:5,yet:[9,10],you:[0,4,9],your:9,zip:[0,10],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],first:7,fittracke:9,fix:7,improv:7,instal:10,issu:7,json:11,line:11,list:8,log:7,misc:7,pars:11,prerequisit:10,prod:10,record:3,releas:7,sport:4,statist:[5,7,8],tabl:9,troubleshoot:12,unexpect:11,upgrad:10,user:[6,8,13],variabl:10,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,3,1,"patch--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/stats/all":[5,0,1,"get--api-stats-all"],"/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],"10mb":10,"1mb":10,"default":[0,5,10],"export":9,"float":0,"int":[0,4,5],"null":[0,1,6],"return":[0,3],"static":10,"true":[1,4,6,10],"try":[0,1],For:10,NOT:[0,1,4],Not:[0,1,4,5,6],That:1,The:[7,10],Use:7,accord:9,account:[7,8],acit:0,activ:[2,4,5,7,9],activity_d:[0,3],activity_id:[0,3],adapt:10,add:[7,8,9],admin:[1,4,6,7,8,10],administr:[0,1,7,8,9,12],again:[0,1,3,4,5,6],all:[3,4,5,6,10],allow:[0,1,9,10],alpinequest:9,alreadi:1,also:9,android:9,anymor:7,api:[0,1,3,4,5,6,7,8,9,10,11],app:[9,10],applic:[0,1,3,4,5,6,9,10],arch:10,archiv:10,archlinux: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,7,8],backup:10,bad:[0,1,4],bearer:[0,1,3,4,5,6],befor:10,beta:10,bike:[0,4,7,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:[7,8,9,10],chang:[9,10],charact:[1,12],chart:[0,7,8,10],chart_data:0,check:[6,11],choos:7,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],creat:[0,1,7,8],created_at:[1,6],creation:[7,8],creation_d:0,credenti:1,current:7,custom:[10,11],cycl:[4,7,8],dai:7,dark:10,darkski:[7,8,10],dashboard:[7,9],data:[0,1,3,4,5,6,9,10,12],databas:10,date:[0,1,5,7,8],debian:10,defaut:10,defin:10,delet:[0,1,7,8],depend:7,desc:0,descent:0,describ:10,descript:10,detail:[6,7,9],develop:9,directori:10,disabl:[1,7,8],displai:[0,7,8,9,10],distanc:[0,3,7,8],distance_from:0,distance_to:0,document:[7,9,10],doe:[0,1,5,6],don:1,download:10,durat:[0,3,7,8],duration_from:0,duration_to:0,dure:[0,1],edit:[1,7,8],elev:[0,7,8,10],email:[1,6,10],encount:10,end:[0,5],endpoint:[2,6,12],enter:[7,8],entiti:[0,1],environ:9,environn:11,error:[0,1,4,7],europ:[1,6],even:[7,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,7,8],featur:9,fetch:10,file:[0,1,7,8,9,10,11],filter:[7,8],first:[1,9],first_nam:[1,6],fittracke:10,fittrackee_api:10,fix:9,flask:10,flaticon:10,follow:[3,10],forbidden:[0,1,4,5],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,has_act:4,have:[0,4,5],header:[0,1,3,4,5,6],health:6,hike:[4,7,8],his:[7,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,4],invalid:[0,1,3,4,5,6],is_act:4,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:[7,8,10],label:4,languag:1,larg:[0,1],last:[1,10],last_nam:[1,6],latitud:0,leaflet:[0,10],least:0,limit:7,line:12,linux:10,list:[7,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,7,8],longitud:0,made:[10,11],mai:10,make:10,makefil:[10,11],manag:7,mandatori:[0,10],map:[0,7,8,9,10],map_id:0,match:1,max:[0,10],max_alt:0,max_spe:0,max_speed_from:0,max_speed_to:0,maxim:0,maximum:[3,7,8],mean:11,messag:[0,1,6],min_alt:0,minim:0,mobil:9,modification_d:0,mon:0,mondai:[1,5],montain:[7,8],month:[5,7,8],more:[7,9],morn:0,mountain:4,mous:7,move:[0,7],mpwoadmin:10,multipart:[0,1],must:[1,4,7,8,10],name:1,nb_activ:[1,5,6],nb_sport:[1,6],necessari:10,need:10,network:11,next_act:0,no_gpx:0,non:4,note:[0,7,8,10],now:[7,8,10],number:[0,10],oauth:[0,1,3,4,5,6],object:[0,1,4],one:0,onli:[0,7,8],open:[9,10],option:10,order:0,other:10,out:1,outdoor:9,over:7,own:9,owner:[7,8],packag:[7,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,4],paus:[0,7],payload:[0,1,4],per:0,per_pag:0,permiss:[0,4,5],pg_dump:10,pictur:[0,1,6,10],ping:6,pipenv:7,pleas:[0,1,3,4,5,6],png:[0,1,4],poetri:[7,10],point:7,pong:6,possibl:9,post:[0,1],postgresql:10,prefer:1,prerequisit:9,previous_act:0,privai:9,product:[9,10],profil:1,project:10,proprietari:9,provid:[0,1,3,4,5,6,7,8],pull:10,python:[7,10],queri:[0,5],react:10,react_app_allow_registr:10,react_app_api_url:11,react_app_gpx_limit_import:10,react_app_max_single_file_s:10,react_app_max_zip_file_s:10,react_app_thunderforest_api_kei:10,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],relat:10,releas:[9,10],replac:7,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,7,8,10],runner:9,sam:[1,6],samr1:10,sat:6,search:7,second:0,see:[7,8,9,10,11],segment:[0,7,8],segment_id:0,select:[0,1],serv:10,server:[0,1,4,9,10],set:10,sever:9,show:7,signatur:[0,1,3,4,5,6],sinc:10,singl:6,size:[0,1,7,10],sky:10,some:[0,7,10],sorri:1,sort:0,speed:[0,3,7,8,10],sport:[0,2,5,7,8,9,10],sport_id:[0,3,4,5],sports_list:[1,6],standard:[7,8],start:[0,1,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,4,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:10,them:9,thi:[0,7,9,10],thunderforest:10,time:[0,1,5,7,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,7,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,4,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],usernanm:1,using:[0,9],valid:[0,1,3,4,5,6],valu:[0,3,10],variabl:[9,11],version:[9,10],view:7,virtualenv:10,walk:[4,7,8],weather:[7,8,10],weather_api:10,weather_end:0,weather_start:0,web:[0,1,3,4,5,6,9],week:[1,5,7],weekm:[1,5],were:7,wget:10,when:7,wiki:7,with_gpx:0,without:[0,5,7,8,9],workout:9,written:10,www:10,xzf:10,yaourt:10,yarn:10,year:5,yet:[9,10],you:[0,4,5,9],your:9,zip:[0,10],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],first:7,fittracke:9,fix:7,improv:7,instal:10,issu:7,json:11,line:11,list:8,log:7,misc:7,pars:11,prerequisit:10,prod:10,record:3,releas:7,sport:4,statist:[5,7,8],tabl:9,troubleshoot:12,unexpect:11,upgrad:10,user:[6,8,13],variabl:10,version:7,workout:8}}) \ No newline at end of file diff --git a/docsrc/source/api/stats.rst b/docsrc/source/api/stats.rst index 0621d298..17be2d6a 100644 --- a/docsrc/source/api/stats.rst +++ b/docsrc/source/api/stats.rst @@ -4,4 +4,5 @@ Statistics .. autoflask:: fittrackee_api:create_app() :endpoints: stats.get_activities_by_sport, - stats.get_activities_by_time + stats.get_activities_by_time, + stats.get_application_stats diff --git a/fittrackee_api/fittrackee_api/activities/stats.py b/fittrackee_api/fittrackee_api/activities/stats.py index 97071087..fb1b7826 100644 --- a/fittrackee_api/fittrackee_api/activities/stats.py +++ b/fittrackee_api/fittrackee_api/activities/stats.py @@ -1,10 +1,11 @@ from datetime import datetime, timedelta -from fittrackee_api import appLog +from fittrackee_api import appLog, db from flask import Blueprint, jsonify, request +from sqlalchemy import func from ..users.models import User -from ..users.utils import authenticate +from ..users.utils import authenticate, authenticate_as_admin from .models import Activity, Sport from .utils import get_datetime_with_tz from .utils_format import convert_timedelta_to_integer @@ -319,3 +320,62 @@ def get_activities_by_sport(auth_user_id, user_id): """ return get_activities(user_id, 'by_sport') + + +@stats_blueprint.route('/stats/all', methods=['GET']) +@authenticate_as_admin +def get_application_stats(auth_user_id): + """ + Get all application statistics + + **Example requests**: + + .. sourcecode:: http + + GET /api/stats/all HTTP/1.1 + + + **Example responses**: + + .. sourcecode:: http + + HTTP/1.1 200 OK + Content-Type: application/json + + { + "data": { + "activities": 3, + "sports": 3, + "users": 2 + }, + "status": "success" + } + + :param integer auth_user_id: authenticate user id (from JSON Web Token) + + :reqheader Authorization: OAuth 2.0 Bearer Token + + :statuscode 200: success + :statuscode 401: + - Provide a valid auth token. + - Signature expired. Please log in again. + - Invalid token. Please log in again. + :statuscode 403: You do not have permissions. + """ + + nb_activities = Activity.query.filter().count() + nb_users = User.query.filter().count() + nb_sports = ( + db.session.query(func.count(Activity.sport_id)) + .group_by(Activity.sport_id) + .count() + ) + response_object = { + 'status': 'success', + 'data': { + 'activities': nb_activities, + 'sports': nb_sports, + 'users': nb_users, + }, + } + return jsonify(response_object), 200 diff --git a/fittrackee_api/fittrackee_api/tests/test_stats_api.py b/fittrackee_api/fittrackee_api/tests/test_stats_api.py index 122db13b..d7b01207 100644 --- a/fittrackee_api/fittrackee_api/tests/test_stats_api.py +++ b/fittrackee_api/fittrackee_api/tests/test_stats_api.py @@ -947,3 +947,87 @@ def test_get_stats_by_sport_all_activities_error( 'Error. Please try again or contact the administrator.' in data['message'] ) + + +def test_get_app_stats_without_activities(app, user_1_admin): + client = app.test_client() + resp_login = client.post( + '/api/auth/login', + data=json.dumps(dict(email='admin@example.com', password='12345678')), + content_type='application/json', + ) + response = client.get( + '/api/stats/all', + headers=dict( + Authorization='Bearer ' + + json.loads(resp_login.data.decode())['auth_token'] + ), + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data'] == {'activities': 0, 'sports': 0, 'users': 1} + + +def test_get_app_stats_with_activities( + app, + user_1_admin, + user_2, + user_3, + sport_1_cycling, + sport_2_running, + activity_cycling_user_1, + activity_cycling_user_2, + activity_running_user_1, +): + client = app.test_client() + resp_login = client.post( + '/api/auth/login', + data=json.dumps(dict(email='admin@example.com', password='12345678')), + content_type='application/json', + ) + response = client.get( + '/api/stats/all', + headers=dict( + Authorization='Bearer ' + + json.loads(resp_login.data.decode())['auth_token'] + ), + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 200 + assert 'success' in data['status'] + assert data['data'] == {'activities': 3, 'sports': 2, 'users': 3} + + +def test_get_app_stats_no_admin( + app, + user_1, + user_2, + user_3, + sport_1_cycling, + sport_2_running, + activity_cycling_user_1, + activity_cycling_user_2, + activity_running_user_1, +): + client = app.test_client() + resp_login = client.post( + '/api/auth/login', + data=json.dumps(dict(email='test@test.com', password='12345678')), + content_type='application/json', + ) + response = client.get( + '/api/stats/all', + headers=dict( + Authorization='Bearer ' + + json.loads(resp_login.data.decode())['auth_token'] + ), + ) + data = json.loads(response.data.decode()) + + assert response.status_code == 403 + assert 'success' not in data['status'] + assert 'error' in data['status'] + assert 'You do not have permissions.' in data['message']