mirror of
https://github.com/simple-login/app.git
synced 2024-09-28 04:41:28 +02:00
Add /api/v4/alias/options
This commit is contained in:
parent
56967e7a38
commit
72e9b52b29
21
README.md
21
README.md
@ -659,7 +659,7 @@ Output: if api key is correct, return a json with user name and whether user is
|
|||||||
If api key is incorrect, return 401.
|
If api key is incorrect, return 401.
|
||||||
|
|
||||||
|
|
||||||
#### GET /api/v3/alias/options
|
#### GET /api/v4/alias/options
|
||||||
|
|
||||||
User alias info and suggestion. Used by the first extension screen when user opens the extension.
|
User alias info and suggestion. Used by the first extension screen when user opens the extension.
|
||||||
|
|
||||||
@ -669,7 +669,7 @@ Input:
|
|||||||
|
|
||||||
Output: a json with the following field:
|
Output: a json with the following field:
|
||||||
- can_create: boolean. Whether user can create new alias
|
- can_create: boolean. Whether user can create new alias
|
||||||
- suffixes: list of string. List of alias `suffix` that user can use. If user doesn't have custom domain, this list has a single element which is the alias default domain (simplelogin.co).
|
- suffixes: list of `[suffix, signed-suffix]`. List of alias `suffix` that user can use. The `signed-suffix` is necessary to avoid request tampering.
|
||||||
- prefix_suggestion: string. Suggestion for the `alias prefix`. Usually this is the website name extracted from `hostname`. If no `hostname`, then the `prefix_suggestion` is empty.
|
- prefix_suggestion: string. Suggestion for the `alias prefix`. Usually this is the website name extracted from `hostname`. If no `hostname`, then the `prefix_suggestion` is empty.
|
||||||
- recommendation: optional field, dictionary. If an alias is already used for this website, the recommendation will be returned. There are 2 subfields in `recommendation`: `alias` which is the recommended alias and `hostname` is the website on which this alias is used before.
|
- recommendation: optional field, dictionary. If an alias is already used for this website, the recommendation will be returned. There are 2 subfields in `recommendation`: `alias` which is the recommended alias and `hostname` is the website on which this alias is used before.
|
||||||
|
|
||||||
@ -677,15 +677,16 @@ For ex:
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"can_create": true,
|
"can_create": true,
|
||||||
"prefix_suggestion": "test",
|
"prefix_suggestion": "",
|
||||||
"recommendation": {
|
|
||||||
"alias": "e1.cat@sl.local",
|
|
||||||
"hostname": "www.test.com"
|
|
||||||
},
|
|
||||||
"suffixes": [
|
"suffixes": [
|
||||||
"@very-long-domain.com.net.org",
|
[
|
||||||
"@ab.cd",
|
"@ab.cd",
|
||||||
".cat@sl.local"
|
"@ab.cd.Xq2BOA.zBebBB-QYikFkbPZ9CPKGpJ2-PU"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
".yeah@local1.localhost",
|
||||||
|
".yeah@local1.localhost.Xq2BOA.dM9gyHyHcSXuJ8ps4i3wpJZ_Frw"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -4,6 +4,7 @@ from sqlalchemy import desc
|
|||||||
|
|
||||||
from app.api.base import api_bp, require_api_auth
|
from app.api.base import api_bp, require_api_auth
|
||||||
from app.config import ALIAS_DOMAINS, DISABLE_ALIAS_SUFFIX
|
from app.config import ALIAS_DOMAINS, DISABLE_ALIAS_SUFFIX
|
||||||
|
from app.dashboard.views.custom_alias import available_suffixes
|
||||||
from app.extensions import db
|
from app.extensions import db
|
||||||
from app.log import LOG
|
from app.log import LOG
|
||||||
from app.models import AliasUsedOn, Alias, User
|
from app.models import AliasUsedOn, Alias, User
|
||||||
@ -239,3 +240,71 @@ def options_v3():
|
|||||||
ret["suffixes"] = list(reversed(ret["suffixes"]))
|
ret["suffixes"] = list(reversed(ret["suffixes"]))
|
||||||
|
|
||||||
return jsonify(ret)
|
return jsonify(ret)
|
||||||
|
|
||||||
|
|
||||||
|
@api_bp.route("/v4/alias/options")
|
||||||
|
@cross_origin()
|
||||||
|
@require_api_auth
|
||||||
|
def options_v4():
|
||||||
|
"""
|
||||||
|
Return what options user has when creating new alias.
|
||||||
|
Same as v3 but return time-based signed-suffix in addition to suffix. To be used with /v2/alias/custom/new
|
||||||
|
Input:
|
||||||
|
a valid api-key in "Authentication" header and
|
||||||
|
optional "hostname" in args
|
||||||
|
Output: cf README
|
||||||
|
can_create: bool
|
||||||
|
suffixes: [[suffix, signed_suffix]]
|
||||||
|
prefix_suggestion: str
|
||||||
|
recommendation: Optional dict
|
||||||
|
alias: str
|
||||||
|
hostname: str
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
user = g.user
|
||||||
|
hostname = request.args.get("hostname")
|
||||||
|
|
||||||
|
ret = {
|
||||||
|
"can_create": user.can_create_new_alias(),
|
||||||
|
"suffixes": [],
|
||||||
|
"prefix_suggestion": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
# recommendation alias if exist
|
||||||
|
if hostname:
|
||||||
|
# put the latest used alias first
|
||||||
|
q = (
|
||||||
|
db.session.query(AliasUsedOn, Alias, User)
|
||||||
|
.filter(
|
||||||
|
AliasUsedOn.alias_id == Alias.id,
|
||||||
|
Alias.user_id == user.id,
|
||||||
|
AliasUsedOn.hostname == hostname,
|
||||||
|
)
|
||||||
|
.order_by(desc(AliasUsedOn.created_at))
|
||||||
|
)
|
||||||
|
|
||||||
|
r = q.first()
|
||||||
|
if r:
|
||||||
|
_, alias, _ = r
|
||||||
|
LOG.d("found alias %s %s %s", alias, hostname, user)
|
||||||
|
ret["recommendation"] = {"alias": alias.email, "hostname": hostname}
|
||||||
|
|
||||||
|
# custom alias suggestion and suffix
|
||||||
|
if hostname:
|
||||||
|
# keep only the domain name of hostname, ignore TLD and subdomain
|
||||||
|
# for ex www.groupon.com -> groupon
|
||||||
|
domain_name = hostname
|
||||||
|
if "." in hostname:
|
||||||
|
parts = hostname.split(".")
|
||||||
|
domain_name = parts[-2]
|
||||||
|
domain_name = convert_to_id(domain_name)
|
||||||
|
ret["prefix_suggestion"] = domain_name
|
||||||
|
|
||||||
|
# List of (is_custom_domain, alias-suffix, time-signed alias-suffix)
|
||||||
|
suffixes = available_suffixes(user)
|
||||||
|
|
||||||
|
# custom domain should be put first
|
||||||
|
ret["suffixes"] = list([suffix[1], suffix[2]] for suffix in suffixes)
|
||||||
|
|
||||||
|
return jsonify(ret)
|
||||||
|
@ -143,3 +143,51 @@ def test_different_scenarios_v3(flask_client):
|
|||||||
)
|
)
|
||||||
assert r.json["recommendation"]["alias"] == alias.email
|
assert r.json["recommendation"]["alias"] == alias.email
|
||||||
assert r.json["recommendation"]["hostname"] == "www.test.com"
|
assert r.json["recommendation"]["hostname"] == "www.test.com"
|
||||||
|
|
||||||
|
|
||||||
|
def test_different_scenarios_v4(flask_client):
|
||||||
|
user = User.create(
|
||||||
|
email="a@b.c", password="password", name="Test User", activated=True
|
||||||
|
)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# create api_key
|
||||||
|
api_key = ApiKey.create(user.id, "for test")
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# <<< without hostname >>>
|
||||||
|
r = flask_client.get(
|
||||||
|
url_for("api.options_v4"), headers={"Authentication": api_key.code}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert r.status_code == 200
|
||||||
|
|
||||||
|
assert r.json["can_create"]
|
||||||
|
assert r.json["suffixes"]
|
||||||
|
assert r.json["prefix_suggestion"] == "" # no hostname => no suggestion
|
||||||
|
|
||||||
|
for (suffix, signed_suffix) in r.json["suffixes"]:
|
||||||
|
assert signed_suffix.startswith(suffix)
|
||||||
|
|
||||||
|
# <<< with hostname >>>
|
||||||
|
r = flask_client.get(
|
||||||
|
url_for("api.options_v4", hostname="www.test.com"),
|
||||||
|
headers={"Authentication": api_key.code},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert r.json["prefix_suggestion"] == "test"
|
||||||
|
|
||||||
|
# <<< with recommendation >>>
|
||||||
|
alias = Alias.create_new(user, prefix="test")
|
||||||
|
db.session.commit()
|
||||||
|
AliasUsedOn.create(
|
||||||
|
alias_id=alias.id, hostname="www.test.com", user_id=alias.user_id
|
||||||
|
)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
r = flask_client.get(
|
||||||
|
url_for("api.options_v4", hostname="www.test.com"),
|
||||||
|
headers={"Authentication": api_key.code},
|
||||||
|
)
|
||||||
|
assert r.json["recommendation"]["alias"] == alias.email
|
||||||
|
assert r.json["recommendation"]["hostname"] == "www.test.com"
|
||||||
|
Loading…
Reference in New Issue
Block a user