Add OAuth2 config flow scaffold (#28220)

* Add OAuth2 scaffold

* Generate integration if non-existing domain specified

* Update URL
This commit is contained in:
Paulus Schoutsen
2019-10-29 20:34:03 -07:00
committed by GitHub
parent e700384cce
commit 24c29f9227
13 changed files with 567 additions and 209 deletions

View File

@ -13,36 +13,14 @@ CHECK_EMPTY = ["Cannot be empty", lambda value: value]
def gather_info(arguments) -> Info:
"""Gather info."""
existing = arguments.template != "integration"
if arguments.develop:
if arguments.integration:
info = {"domain": arguments.integration}
elif arguments.develop:
print("Running in developer mode. Automatically filling in info.")
print()
if existing:
if arguments.develop:
return _load_existing_integration("develop")
if arguments.integration:
return _load_existing_integration(arguments.integration)
return gather_existing_integration()
if arguments.develop:
return Info(
domain="develop",
name="Develop Hub",
codeowner="@developer",
requirement="aiodevelop==1.2.3",
)
return gather_new_integration()
def gather_new_integration() -> Info:
"""Gather info about new integration from user."""
return Info(
**_gather_info(
info = {"domain": "develop"}
else:
info = _gather_info(
{
"domain": {
"prompt": "What is the domain?",
@ -52,84 +30,87 @@ def gather_new_integration() -> Info:
"Domains cannot contain spaces or special characters.",
lambda value: value == slugify(value),
],
[
"There already is an integration with this domain.",
lambda value: not (COMPONENT_DIR / value).exists(),
],
],
},
"name": {
"prompt": "What is the name of your integration?",
"validators": [CHECK_EMPTY],
},
"codeowner": {
"prompt": "What is your GitHub handle?",
"validators": [
CHECK_EMPTY,
[
'GitHub handles need to start with an "@"',
lambda value: value.startswith("@"),
],
],
},
"requirement": {
"prompt": "What PyPI package and version do you depend on? Leave blank for none.",
"validators": [
[
"Versions should be pinned using '=='.",
lambda value: not value or "==" in value,
]
],
},
}
}
)
info["is_new"] = not (COMPONENT_DIR / info["domain"] / "manifest.json").exists()
if not info["is_new"]:
return _load_existing_integration(info["domain"])
if arguments.develop:
info.update(
{
"name": "Develop Hub",
"codeowner": "@developer",
"requirement": "aiodevelop==1.2.3",
"oauth2": True,
}
)
else:
info.update(gather_new_integration(arguments.template == "integration"))
return Info(**info)
YES_NO = {
"validators": [["Type either 'yes' or 'no'", lambda value: value in ("yes", "no")]],
"convertor": lambda value: value == "yes",
}
def gather_new_integration(determine_auth: bool) -> Info:
"""Gather info about new integration from user."""
fields = {
"name": {
"prompt": "What is the name of your integration?",
"validators": [CHECK_EMPTY],
},
"codeowner": {
"prompt": "What is your GitHub handle?",
"validators": [
CHECK_EMPTY,
[
'GitHub handles need to start with an "@"',
lambda value: value.startswith("@"),
],
],
},
"requirement": {
"prompt": "What PyPI package and version do you depend on? Leave blank for none.",
"validators": [
[
"Versions should be pinned using '=='.",
lambda value: not value or "==" in value,
]
],
},
}
if determine_auth:
fields.update(
{
"authentication": {
"prompt": "Does Home Assistant need the user to authenticate to control the device/service? (yes/no)",
"default": "yes",
"validators": [
[
"Type either 'yes' or 'no'",
lambda value: value in ("yes", "no"),
]
],
"convertor": lambda value: value == "yes",
**YES_NO,
},
"discoverable": {
"prompt": "Is the device/service discoverable on the local network? (yes/no)",
"default": "no",
"validators": [
[
"Type either 'yes' or 'no'",
lambda value: value in ("yes", "no"),
]
],
"convertor": lambda value: value == "yes",
**YES_NO,
},
"oauth2": {
"prompt": "Can the user authenticate the device using OAuth2? (yes/no)",
"default": "no",
**YES_NO,
},
}
)
)
def gather_existing_integration() -> Info:
"""Gather info about existing integration from user."""
answers = _gather_info(
{
"domain": {
"prompt": "What is the domain?",
"validators": [
CHECK_EMPTY,
[
"Domains cannot contain spaces or special characters.",
lambda value: value == slugify(value),
],
[
"This integration does not exist.",
lambda value: (COMPONENT_DIR / value).exists(),
],
],
}
}
)
return _load_existing_integration(answers["domain"])
return _gather_info(fields)
def _load_existing_integration(domain) -> Info:
@ -179,5 +160,4 @@ def _gather_info(fields) -> dict:
value = info["convertor"](value)
answers[key] = value
print()
return answers