mirror of
https://github.com/simple-login/app.git
synced 2024-09-27 20:31:30 +02:00
Stats endpoint (#1716)
* update some dependencies: newrelic, gevent that isn't compatible with python 3.11 on mac * update package-lock using npm 9.6.4 and node 20.0 * Add GET /api/stats * update pytest --------- Co-authored-by: Son Nguyen Kim <son@Sons-MacBook-Air-2.local>
This commit is contained in:
parent
66c3a07c92
commit
6276ad4419
@ -1,4 +1,5 @@
|
|||||||
import base64
|
import base64
|
||||||
|
import dataclasses
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
@ -7,6 +8,7 @@ from flask import jsonify, g, request, make_response
|
|||||||
from app import s3, config
|
from app import s3, config
|
||||||
from app.api.base import api_bp, require_api_auth
|
from app.api.base import api_bp, require_api_auth
|
||||||
from app.config import SESSION_COOKIE_NAME
|
from app.config import SESSION_COOKIE_NAME
|
||||||
|
from app.dashboard.views.index import get_stats
|
||||||
from app.db import Session
|
from app.db import Session
|
||||||
from app.models import ApiKey, File, PartnerUser, User
|
from app.models import ApiKey, File, PartnerUser, User
|
||||||
from app.proton.utils import get_proton_partner
|
from app.proton.utils import get_proton_partner
|
||||||
@ -136,3 +138,22 @@ def logout():
|
|||||||
response.delete_cookie(SESSION_COOKIE_NAME)
|
response.delete_cookie(SESSION_COOKIE_NAME)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@api_bp.route("/stats")
|
||||||
|
@require_api_auth
|
||||||
|
def user_stats():
|
||||||
|
"""
|
||||||
|
Return stats
|
||||||
|
|
||||||
|
Output as json
|
||||||
|
- nb_alias
|
||||||
|
- nb_forward
|
||||||
|
- nb_reply
|
||||||
|
- nb_block
|
||||||
|
|
||||||
|
"""
|
||||||
|
user = g.user
|
||||||
|
stats = get_stats(user)
|
||||||
|
|
||||||
|
return jsonify(dataclasses.asdict(stats))
|
||||||
|
17
docs/api.md
17
docs/api.md
@ -15,6 +15,7 @@
|
|||||||
- [GET /api/user/cookie_token](#get-apiusercookie_token): Get a one time use token to exchange it for a valid cookie
|
- [GET /api/user/cookie_token](#get-apiusercookie_token): Get a one time use token to exchange it for a valid cookie
|
||||||
- [PATCH /api/user_info](#patch-apiuser_info): Update user's information.
|
- [PATCH /api/user_info](#patch-apiuser_info): Update user's information.
|
||||||
- [POST /api/api_key](#post-apiapi_key): Create a new API key.
|
- [POST /api/api_key](#post-apiapi_key): Create a new API key.
|
||||||
|
- [GET /api/stats](#get-apistats): Get user's stats.
|
||||||
- [GET /api/logout](#get-apilogout): Log out.
|
- [GET /api/logout](#get-apilogout): Log out.
|
||||||
|
|
||||||
[Alias endpoints](#alias-endpoints)
|
[Alias endpoints](#alias-endpoints)
|
||||||
@ -226,6 +227,22 @@ Input:
|
|||||||
|
|
||||||
Output: same as GET /api/user_info
|
Output: same as GET /api/user_info
|
||||||
|
|
||||||
|
#### GET /api/stats
|
||||||
|
|
||||||
|
Given the API Key, return stats about the number of aliases, number of emails forwarded/replied/blocked
|
||||||
|
|
||||||
|
Input:
|
||||||
|
|
||||||
|
- `Authentication` header that contains the api key
|
||||||
|
|
||||||
|
Output: if api key is correct, return a json with the following fields:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"nb_alias": 1, "nb_block": 0, "nb_forward": 0, "nb_reply": 0}
|
||||||
|
```
|
||||||
|
|
||||||
|
If api key is incorrect, return 401.
|
||||||
|
|
||||||
#### PATCH /api/sudo
|
#### PATCH /api/sudo
|
||||||
|
|
||||||
Enable sudo mode
|
Enable sudo mode
|
||||||
|
55
poetry.lock
generated
55
poetry.lock
generated
@ -265,18 +265,6 @@ files = [
|
|||||||
{file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"},
|
{file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atomicwrites"
|
|
||||||
version = "1.4.0"
|
|
||||||
description = "Atomic file writes."
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
files = [
|
|
||||||
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
|
|
||||||
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atpublic"
|
name = "atpublic"
|
||||||
version = "2.0"
|
version = "2.0"
|
||||||
@ -900,6 +888,21 @@ files = [
|
|||||||
dnspython = ">=1.15.0"
|
dnspython = ">=1.15.0"
|
||||||
idna = ">=2.0.0"
|
idna = ">=2.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exceptiongroup"
|
||||||
|
version = "1.1.1"
|
||||||
|
description = "Backport of PEP 654 (exception groups)"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
|
||||||
|
{file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["pytest (>=6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "facebook-sdk"
|
name = "facebook-sdk"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
@ -2381,18 +2384,6 @@ files = [
|
|||||||
{file = "ptyprocess-0.6.0.tar.gz", hash = "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0"},
|
{file = "ptyprocess-0.6.0.tar.gz", hash = "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "py"
|
|
||||||
version = "1.10.0"
|
|
||||||
description = "library with cross-python path, ini-parsing, io, code, log facilities"
|
|
||||||
category = "dev"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
|
||||||
files = [
|
|
||||||
{file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"},
|
|
||||||
{file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyasn1"
|
name = "pyasn1"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
@ -2633,29 +2624,27 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "7.0.0"
|
version = "7.3.1"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pytest-7.0.0-py3-none-any.whl", hash = "sha256:42901e6bd4bd4a0e533358a86e848427a49005a3256f657c5c8f8dd35ef137a9"},
|
{file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
|
||||||
{file = "pytest-7.0.0.tar.gz", hash = "sha256:dad48ffda394e5ad9aa3b7d7ddf339ed502e5e365b1350e0af65f4a602344b11"},
|
{file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
|
|
||||||
attrs = ">=19.2.0"
|
|
||||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
||||||
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
|
||||||
iniconfig = "*"
|
iniconfig = "*"
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
pluggy = ">=0.12,<2.0"
|
pluggy = ">=0.12,<2.0"
|
||||||
py = ">=1.8.2"
|
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
||||||
tomli = ">=1.0.0"
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest-cov"
|
name = "pytest-cov"
|
||||||
|
@ -129,3 +129,12 @@ def test_change_name(flask_client):
|
|||||||
assert r.json["name"] == "new name"
|
assert r.json["name"] == "new name"
|
||||||
|
|
||||||
assert user.name == "new name"
|
assert user.name == "new name"
|
||||||
|
|
||||||
|
|
||||||
|
def test_stats(flask_client):
|
||||||
|
login(flask_client)
|
||||||
|
|
||||||
|
r = flask_client.get("/api/stats")
|
||||||
|
|
||||||
|
assert r.status_code == 200
|
||||||
|
assert r.json == {"nb_alias": 1, "nb_block": 0, "nb_forward": 0, "nb_reply": 0}
|
||||||
|
Loading…
Reference in New Issue
Block a user