splent-feature-github 0.1.0__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- splent_feature_github-0.2.1/PKG-INFO +123 -0
- splent_feature_github-0.2.1/README.md +113 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/pyproject.toml +15 -10
- splent_feature_github-0.2.1/src/splent_feature_github.egg-info/PKG-INFO +123 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_feature_github.egg-info/SOURCES.txt +1 -2
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/__init__.py +4 -10
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/config.py +5 -2
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/hooks.py +9 -11
- splent_feature_github-0.2.1/src/splent_io/splent_feature_github/migrations/versions/github0002_into_ext_identity.py +245 -0
- splent_feature_github-0.2.1/src/splent_io/splent_feature_github/models.py +7 -0
- splent_feature_github-0.2.1/src/splent_io/splent_feature_github/routes.py +30 -0
- splent_feature_github-0.2.1/src/splent_io/splent_feature_github/services.py +97 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/templates/hooks/github_profile_row.html +9 -4
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/translations/es/LC_MESSAGES/messages.mo +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/translations/es/LC_MESSAGES/messages.po +8 -3
- splent_feature_github-0.1.0/PKG-INFO +0 -99
- splent_feature_github-0.1.0/README.md +0 -89
- splent_feature_github-0.1.0/src/splent_feature_github.egg-info/PKG-INFO +0 -99
- splent_feature_github-0.1.0/src/splent_io/splent_feature_github/models.py +0 -31
- splent_feature_github-0.1.0/src/splent_io/splent_feature_github/repositories.py +0 -11
- splent_feature_github-0.1.0/src/splent_io/splent_feature_github/routes.py +0 -110
- splent_feature_github-0.1.0/src/splent_io/splent_feature_github/services.py +0 -305
- splent_feature_github-0.1.0/src/splent_io/splent_feature_github/signals.py +0 -14
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/COPYING +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/COPYING.LESSER +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/MANIFEST.in +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/setup.cfg +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_feature_github.egg-info/dependency_links.txt +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_feature_github.egg-info/top_level.txt +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/assets/css/github.css +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/migrations/alembic.ini +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/migrations/env.py +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/migrations/script.py.mako +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/migrations/versions/7ace6050fb3f_splent_feature_github.py +0 -0
- {splent_feature_github-0.1.0 → splent_feature_github-0.2.1}/src/splent_io/splent_feature_github/templates/hooks/github_login_button.html +0 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: splent_feature_github
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
License-Expression: LGPL-3.0-or-later
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: COPYING
|
|
8
|
+
License-File: COPYING.LESSER
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# splent_feature_github
|
|
12
|
+
|
|
13
|
+
The `github` feature of a [SPLENT](https://splent.io) product line.
|
|
14
|
+
|
|
15
|
+
Sign in and sign up with GitHub, and connect a GitHub account to an account
|
|
16
|
+
from its profile. identities runs the sign-in for every provider, and this
|
|
17
|
+
feature describes GitHub to it: its endpoints, its scope (`GITHUB_SCOPE`),
|
|
18
|
+
and how to read who signed in from its API, the verified address included.
|
|
19
|
+
A new account takes an address GitHub verified (from `/user/emails`, the
|
|
20
|
+
primary one first, never the public one on `/user`) and the name it gives,
|
|
21
|
+
and the person adds the surname before it is opened. A GitHub account
|
|
22
|
+
always signs in to the account it is linked to, and never to an existing
|
|
23
|
+
account because the email matches. It needs `auth`, `profile` and
|
|
24
|
+
`identities`, which keeps the linked accounts.
|
|
25
|
+
|
|
26
|
+
A SPLENT feature is a Python package that a product composes with others.
|
|
27
|
+
Its models, routes, services, templates and hooks are registered when the
|
|
28
|
+
product starts. What this feature provides and requires is listed in the
|
|
29
|
+
`[tool.splent.contract]` section of `pyproject.toml`, which
|
|
30
|
+
`splent feature:contract --write` keeps in sync with the source.
|
|
31
|
+
|
|
32
|
+
## Settings
|
|
33
|
+
|
|
34
|
+
| Setting | Default | What it is |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `GITHUB_CLIENT_ID` | empty | The client id of the OAuth app registered at https://github.com/settings/developers |
|
|
37
|
+
| `GITHUB_CLIENT_SECRET` | empty | Its secret |
|
|
38
|
+
| `GITHUB_SCOPE` | `user:email` | What the sign-in asks GitHub for. `user:email` lets `/user/emails` say which addresses GitHub verified; without it every new account asks for an address, which then has to be confirmed by mail |
|
|
39
|
+
|
|
40
|
+
Without both, GitHub sign-in is off: the app logs a warning at start, and
|
|
41
|
+
whoever tries is told it is not available. The callback registered with
|
|
42
|
+
GitHub is `<OAUTH_REDIRECT_BASE_URL>/github/authorize` (identities' setting).
|
|
43
|
+
|
|
44
|
+
## Where it shows
|
|
45
|
+
|
|
46
|
+
It fills the slots other features open, by name, so it composes with
|
|
47
|
+
whatever the product has and overrides nothing.
|
|
48
|
+
|
|
49
|
+
| Slot | Opened by | What GitHub draws |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `auth.login.providers` | auth | The GitHub button, under "or continue with" |
|
|
52
|
+
| `signup.providers` | signup, when the product has it | The same button, after the sign-up form |
|
|
53
|
+
| `profile.edit.sections` | profile | The linked account, as a link to it on GitHub, with a disconnect button, or a "Connect GitHub" link |
|
|
54
|
+
| `layout.head.css` | the product's app shell | Its stylesheet, `assets/css/github.css` |
|
|
55
|
+
|
|
56
|
+
It takes order 10 in the first three, before ORCID's 20. The button carries
|
|
57
|
+
where the reader was heading (`?next=`), and only a path on this site. The
|
|
58
|
+
disconnect button opens identities' modal.
|
|
59
|
+
|
|
60
|
+
GitHub's dark grey is in `assets/css/github.css`, never on the elements. The
|
|
61
|
+
public shell loads the file from the asset registry (`register_asset`), and
|
|
62
|
+
the app shell, which does not render the registry, through
|
|
63
|
+
`layout.head.css`. A product that wants another look overrides
|
|
64
|
+
`.btn.btn-github` and the `github-identity__*` classes in a stylesheet of its
|
|
65
|
+
own.
|
|
66
|
+
|
|
67
|
+
## A product without signup
|
|
68
|
+
|
|
69
|
+
A product that does not install `splent_feature_signup` is closed, and its
|
|
70
|
+
accounts are opened by an administrator. GitHub follows the rule identities
|
|
71
|
+
holds for every provider.
|
|
72
|
+
|
|
73
|
+
| Visitor | With signup | Without signup |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| Signs in with a GitHub account already linked | Signed in | Signed in |
|
|
76
|
+
| Connects GitHub from their profile | Linked | Linked |
|
|
77
|
+
| Signs in with a GitHub account linked to nobody | Asked for the details of a new account, which opens at once with GitHub's verified address, or, when GitHub verified none and the person typed one, once the person follows the link mailed to it and signs in with GitHub again, if the product confirms addresses | Sent back to the login page with a translated message that asks them to request access from an administrator, or to connect GitHub from their profile if they have an account |
|
|
78
|
+
|
|
79
|
+
## The github table
|
|
80
|
+
|
|
81
|
+
Earlier versions kept every linked GitHub account twice: in
|
|
82
|
+
`external_identity`, which signs people in, and in a `github` table keyed by
|
|
83
|
+
profile, which only `get_github()` read and nothing called.
|
|
84
|
+
`github0002_into_ext_identity` folds the table into `external_identity` and
|
|
85
|
+
drops it, and `get_github()` goes with it. Each row becomes the account's
|
|
86
|
+
GitHub identity (its numeric id as text, its login as the username), or
|
|
87
|
+
completes the one it already has. A row that would lose a link or give it to
|
|
88
|
+
another account stops the migration before anything changes, and the
|
|
89
|
+
message names the rows. The downgrade puts the table back with a row for
|
|
90
|
+
every GitHub identity of an account with a profile.
|
|
91
|
+
|
|
92
|
+
## Translations
|
|
93
|
+
|
|
94
|
+
The edit-profile row and the messages about GitHub's answers ship with a
|
|
95
|
+
Spanish catalog.
|
|
96
|
+
|
|
97
|
+
## Use it in a product
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
splent feature:add splent_feature_github
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Develop
|
|
104
|
+
|
|
105
|
+
The tests simulate GitHub (`tests/conftest.py`): the flow's OAuth client
|
|
106
|
+
answers the token exchange, `/user` and `/user/emails` as each test chooses.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
splent feature:test splent_feature_github --with identities --with orcid
|
|
110
|
+
splent feature:contract splent_feature_github
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Release
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
splent feature:release splent_feature_github --dry-run --bump patch
|
|
117
|
+
splent feature:release splent_feature_github
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The first command rehearses the release and changes nothing. The second
|
|
121
|
+
publishes it to the git forge and to PyPI, and a PyPI version is permanent.
|
|
122
|
+
This version needs the identities that brings the shared flow and
|
|
123
|
+
`provider_email_verified`, so the two are released together.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# splent_feature_github
|
|
2
|
+
|
|
3
|
+
The `github` feature of a [SPLENT](https://splent.io) product line.
|
|
4
|
+
|
|
5
|
+
Sign in and sign up with GitHub, and connect a GitHub account to an account
|
|
6
|
+
from its profile. identities runs the sign-in for every provider, and this
|
|
7
|
+
feature describes GitHub to it: its endpoints, its scope (`GITHUB_SCOPE`),
|
|
8
|
+
and how to read who signed in from its API, the verified address included.
|
|
9
|
+
A new account takes an address GitHub verified (from `/user/emails`, the
|
|
10
|
+
primary one first, never the public one on `/user`) and the name it gives,
|
|
11
|
+
and the person adds the surname before it is opened. A GitHub account
|
|
12
|
+
always signs in to the account it is linked to, and never to an existing
|
|
13
|
+
account because the email matches. It needs `auth`, `profile` and
|
|
14
|
+
`identities`, which keeps the linked accounts.
|
|
15
|
+
|
|
16
|
+
A SPLENT feature is a Python package that a product composes with others.
|
|
17
|
+
Its models, routes, services, templates and hooks are registered when the
|
|
18
|
+
product starts. What this feature provides and requires is listed in the
|
|
19
|
+
`[tool.splent.contract]` section of `pyproject.toml`, which
|
|
20
|
+
`splent feature:contract --write` keeps in sync with the source.
|
|
21
|
+
|
|
22
|
+
## Settings
|
|
23
|
+
|
|
24
|
+
| Setting | Default | What it is |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `GITHUB_CLIENT_ID` | empty | The client id of the OAuth app registered at https://github.com/settings/developers |
|
|
27
|
+
| `GITHUB_CLIENT_SECRET` | empty | Its secret |
|
|
28
|
+
| `GITHUB_SCOPE` | `user:email` | What the sign-in asks GitHub for. `user:email` lets `/user/emails` say which addresses GitHub verified; without it every new account asks for an address, which then has to be confirmed by mail |
|
|
29
|
+
|
|
30
|
+
Without both, GitHub sign-in is off: the app logs a warning at start, and
|
|
31
|
+
whoever tries is told it is not available. The callback registered with
|
|
32
|
+
GitHub is `<OAUTH_REDIRECT_BASE_URL>/github/authorize` (identities' setting).
|
|
33
|
+
|
|
34
|
+
## Where it shows
|
|
35
|
+
|
|
36
|
+
It fills the slots other features open, by name, so it composes with
|
|
37
|
+
whatever the product has and overrides nothing.
|
|
38
|
+
|
|
39
|
+
| Slot | Opened by | What GitHub draws |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `auth.login.providers` | auth | The GitHub button, under "or continue with" |
|
|
42
|
+
| `signup.providers` | signup, when the product has it | The same button, after the sign-up form |
|
|
43
|
+
| `profile.edit.sections` | profile | The linked account, as a link to it on GitHub, with a disconnect button, or a "Connect GitHub" link |
|
|
44
|
+
| `layout.head.css` | the product's app shell | Its stylesheet, `assets/css/github.css` |
|
|
45
|
+
|
|
46
|
+
It takes order 10 in the first three, before ORCID's 20. The button carries
|
|
47
|
+
where the reader was heading (`?next=`), and only a path on this site. The
|
|
48
|
+
disconnect button opens identities' modal.
|
|
49
|
+
|
|
50
|
+
GitHub's dark grey is in `assets/css/github.css`, never on the elements. The
|
|
51
|
+
public shell loads the file from the asset registry (`register_asset`), and
|
|
52
|
+
the app shell, which does not render the registry, through
|
|
53
|
+
`layout.head.css`. A product that wants another look overrides
|
|
54
|
+
`.btn.btn-github` and the `github-identity__*` classes in a stylesheet of its
|
|
55
|
+
own.
|
|
56
|
+
|
|
57
|
+
## A product without signup
|
|
58
|
+
|
|
59
|
+
A product that does not install `splent_feature_signup` is closed, and its
|
|
60
|
+
accounts are opened by an administrator. GitHub follows the rule identities
|
|
61
|
+
holds for every provider.
|
|
62
|
+
|
|
63
|
+
| Visitor | With signup | Without signup |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| Signs in with a GitHub account already linked | Signed in | Signed in |
|
|
66
|
+
| Connects GitHub from their profile | Linked | Linked |
|
|
67
|
+
| Signs in with a GitHub account linked to nobody | Asked for the details of a new account, which opens at once with GitHub's verified address, or, when GitHub verified none and the person typed one, once the person follows the link mailed to it and signs in with GitHub again, if the product confirms addresses | Sent back to the login page with a translated message that asks them to request access from an administrator, or to connect GitHub from their profile if they have an account |
|
|
68
|
+
|
|
69
|
+
## The github table
|
|
70
|
+
|
|
71
|
+
Earlier versions kept every linked GitHub account twice: in
|
|
72
|
+
`external_identity`, which signs people in, and in a `github` table keyed by
|
|
73
|
+
profile, which only `get_github()` read and nothing called.
|
|
74
|
+
`github0002_into_ext_identity` folds the table into `external_identity` and
|
|
75
|
+
drops it, and `get_github()` goes with it. Each row becomes the account's
|
|
76
|
+
GitHub identity (its numeric id as text, its login as the username), or
|
|
77
|
+
completes the one it already has. A row that would lose a link or give it to
|
|
78
|
+
another account stops the migration before anything changes, and the
|
|
79
|
+
message names the rows. The downgrade puts the table back with a row for
|
|
80
|
+
every GitHub identity of an account with a profile.
|
|
81
|
+
|
|
82
|
+
## Translations
|
|
83
|
+
|
|
84
|
+
The edit-profile row and the messages about GitHub's answers ship with a
|
|
85
|
+
Spanish catalog.
|
|
86
|
+
|
|
87
|
+
## Use it in a product
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
splent feature:add splent_feature_github
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Develop
|
|
94
|
+
|
|
95
|
+
The tests simulate GitHub (`tests/conftest.py`): the flow's OAuth client
|
|
96
|
+
answers the token exchange, `/user` and `/user/emails` as each test chooses.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
splent feature:test splent_feature_github --with identities --with orcid
|
|
100
|
+
splent feature:contract splent_feature_github
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Release
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
splent feature:release splent_feature_github --dry-run --bump patch
|
|
107
|
+
splent feature:release splent_feature_github
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The first command rehearses the release and changes nothing. The second
|
|
111
|
+
publishes it to the git forge and to PyPI, and a PyPI version is permanent.
|
|
112
|
+
This version needs the identities that brings the shared flow and
|
|
113
|
+
`provider_email_verified`, so the two are released together.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "splent_feature_github"
|
|
7
|
-
version = "0.1
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
requires-python = ">=3.13"
|
|
10
10
|
license = "LGPL-3.0-or-later"
|
|
@@ -34,29 +34,30 @@ cli_version = "1.25.1"
|
|
|
34
34
|
# registration time, which have no literal path to find in source).
|
|
35
35
|
[tool.splent.contract]
|
|
36
36
|
description = "Sign in and sign up with GitHub, and connect a GitHub account to an account from its profile"
|
|
37
|
-
archetype = "
|
|
37
|
+
archetype = "light"
|
|
38
38
|
|
|
39
39
|
[tool.splent.contract.provides]
|
|
40
40
|
routes = ["/account/connect/github", "/github/authorize", "/github/login"]
|
|
41
41
|
blueprints = ["github_bp"]
|
|
42
|
-
models = [
|
|
42
|
+
models = []
|
|
43
43
|
commands = []
|
|
44
44
|
hooks = ["auth.login.providers", "layout.head.css", "profile.edit.sections", "signup.providers"]
|
|
45
|
-
services = [
|
|
45
|
+
services = []
|
|
46
46
|
signals = []
|
|
47
47
|
translations = ["es"]
|
|
48
48
|
docker = []
|
|
49
49
|
|
|
50
50
|
[tool.splent.contract.requires]
|
|
51
51
|
features = ["auth", "identities", "profile"]
|
|
52
|
+
features_manual = ["profile"]
|
|
52
53
|
features_optional = ["signup"]
|
|
53
|
-
env_vars = ["GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET"]
|
|
54
|
-
signals = [
|
|
54
|
+
env_vars = ["GITHUB_CLIENT_ID", "GITHUB_CLIENT_SECRET", "GITHUB_SCOPE"]
|
|
55
|
+
signals = []
|
|
55
56
|
|
|
56
57
|
[tool.splent.contract.extensible]
|
|
57
|
-
services = [
|
|
58
|
+
services = []
|
|
58
59
|
templates = ["hooks/github_login_button.html", "hooks/github_profile_row.html"]
|
|
59
|
-
models = [
|
|
60
|
+
models = []
|
|
60
61
|
hooks = ["auth.login.providers", "layout.head.css", "profile.edit.sections", "signup.providers"]
|
|
61
62
|
routes = true
|
|
62
63
|
|
|
@@ -76,7 +77,11 @@ routes = true
|
|
|
76
77
|
# product's port offset, so two products can run at once.
|
|
77
78
|
[tool.splent.config]
|
|
78
79
|
# The OAuth app registered at https://github.com/settings/developers.
|
|
79
|
-
# Without both values GitHub sign-in
|
|
80
|
-
#
|
|
80
|
+
# Without both values GitHub sign-in is off: the app logs a warning at start,
|
|
81
|
+
# and whoever tries is told it is not available.
|
|
81
82
|
GITHUB_CLIENT_ID = ""
|
|
82
83
|
GITHUB_CLIENT_SECRET = ""
|
|
84
|
+
# What the sign-in asks GitHub for. user:email lets GitHub say which of the
|
|
85
|
+
# person's addresses it verified; without it every new account asks for an
|
|
86
|
+
# address, which then has to be confirmed by mail.
|
|
87
|
+
GITHUB_SCOPE = "user:email"
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: splent_feature_github
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
License-Expression: LGPL-3.0-or-later
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: COPYING
|
|
8
|
+
License-File: COPYING.LESSER
|
|
9
|
+
Dynamic: license-file
|
|
10
|
+
|
|
11
|
+
# splent_feature_github
|
|
12
|
+
|
|
13
|
+
The `github` feature of a [SPLENT](https://splent.io) product line.
|
|
14
|
+
|
|
15
|
+
Sign in and sign up with GitHub, and connect a GitHub account to an account
|
|
16
|
+
from its profile. identities runs the sign-in for every provider, and this
|
|
17
|
+
feature describes GitHub to it: its endpoints, its scope (`GITHUB_SCOPE`),
|
|
18
|
+
and how to read who signed in from its API, the verified address included.
|
|
19
|
+
A new account takes an address GitHub verified (from `/user/emails`, the
|
|
20
|
+
primary one first, never the public one on `/user`) and the name it gives,
|
|
21
|
+
and the person adds the surname before it is opened. A GitHub account
|
|
22
|
+
always signs in to the account it is linked to, and never to an existing
|
|
23
|
+
account because the email matches. It needs `auth`, `profile` and
|
|
24
|
+
`identities`, which keeps the linked accounts.
|
|
25
|
+
|
|
26
|
+
A SPLENT feature is a Python package that a product composes with others.
|
|
27
|
+
Its models, routes, services, templates and hooks are registered when the
|
|
28
|
+
product starts. What this feature provides and requires is listed in the
|
|
29
|
+
`[tool.splent.contract]` section of `pyproject.toml`, which
|
|
30
|
+
`splent feature:contract --write` keeps in sync with the source.
|
|
31
|
+
|
|
32
|
+
## Settings
|
|
33
|
+
|
|
34
|
+
| Setting | Default | What it is |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `GITHUB_CLIENT_ID` | empty | The client id of the OAuth app registered at https://github.com/settings/developers |
|
|
37
|
+
| `GITHUB_CLIENT_SECRET` | empty | Its secret |
|
|
38
|
+
| `GITHUB_SCOPE` | `user:email` | What the sign-in asks GitHub for. `user:email` lets `/user/emails` say which addresses GitHub verified; without it every new account asks for an address, which then has to be confirmed by mail |
|
|
39
|
+
|
|
40
|
+
Without both, GitHub sign-in is off: the app logs a warning at start, and
|
|
41
|
+
whoever tries is told it is not available. The callback registered with
|
|
42
|
+
GitHub is `<OAUTH_REDIRECT_BASE_URL>/github/authorize` (identities' setting).
|
|
43
|
+
|
|
44
|
+
## Where it shows
|
|
45
|
+
|
|
46
|
+
It fills the slots other features open, by name, so it composes with
|
|
47
|
+
whatever the product has and overrides nothing.
|
|
48
|
+
|
|
49
|
+
| Slot | Opened by | What GitHub draws |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `auth.login.providers` | auth | The GitHub button, under "or continue with" |
|
|
52
|
+
| `signup.providers` | signup, when the product has it | The same button, after the sign-up form |
|
|
53
|
+
| `profile.edit.sections` | profile | The linked account, as a link to it on GitHub, with a disconnect button, or a "Connect GitHub" link |
|
|
54
|
+
| `layout.head.css` | the product's app shell | Its stylesheet, `assets/css/github.css` |
|
|
55
|
+
|
|
56
|
+
It takes order 10 in the first three, before ORCID's 20. The button carries
|
|
57
|
+
where the reader was heading (`?next=`), and only a path on this site. The
|
|
58
|
+
disconnect button opens identities' modal.
|
|
59
|
+
|
|
60
|
+
GitHub's dark grey is in `assets/css/github.css`, never on the elements. The
|
|
61
|
+
public shell loads the file from the asset registry (`register_asset`), and
|
|
62
|
+
the app shell, which does not render the registry, through
|
|
63
|
+
`layout.head.css`. A product that wants another look overrides
|
|
64
|
+
`.btn.btn-github` and the `github-identity__*` classes in a stylesheet of its
|
|
65
|
+
own.
|
|
66
|
+
|
|
67
|
+
## A product without signup
|
|
68
|
+
|
|
69
|
+
A product that does not install `splent_feature_signup` is closed, and its
|
|
70
|
+
accounts are opened by an administrator. GitHub follows the rule identities
|
|
71
|
+
holds for every provider.
|
|
72
|
+
|
|
73
|
+
| Visitor | With signup | Without signup |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| Signs in with a GitHub account already linked | Signed in | Signed in |
|
|
76
|
+
| Connects GitHub from their profile | Linked | Linked |
|
|
77
|
+
| Signs in with a GitHub account linked to nobody | Asked for the details of a new account, which opens at once with GitHub's verified address, or, when GitHub verified none and the person typed one, once the person follows the link mailed to it and signs in with GitHub again, if the product confirms addresses | Sent back to the login page with a translated message that asks them to request access from an administrator, or to connect GitHub from their profile if they have an account |
|
|
78
|
+
|
|
79
|
+
## The github table
|
|
80
|
+
|
|
81
|
+
Earlier versions kept every linked GitHub account twice: in
|
|
82
|
+
`external_identity`, which signs people in, and in a `github` table keyed by
|
|
83
|
+
profile, which only `get_github()` read and nothing called.
|
|
84
|
+
`github0002_into_ext_identity` folds the table into `external_identity` and
|
|
85
|
+
drops it, and `get_github()` goes with it. Each row becomes the account's
|
|
86
|
+
GitHub identity (its numeric id as text, its login as the username), or
|
|
87
|
+
completes the one it already has. A row that would lose a link or give it to
|
|
88
|
+
another account stops the migration before anything changes, and the
|
|
89
|
+
message names the rows. The downgrade puts the table back with a row for
|
|
90
|
+
every GitHub identity of an account with a profile.
|
|
91
|
+
|
|
92
|
+
## Translations
|
|
93
|
+
|
|
94
|
+
The edit-profile row and the messages about GitHub's answers ship with a
|
|
95
|
+
Spanish catalog.
|
|
96
|
+
|
|
97
|
+
## Use it in a product
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
splent feature:add splent_feature_github
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Develop
|
|
104
|
+
|
|
105
|
+
The tests simulate GitHub (`tests/conftest.py`): the flow's OAuth client
|
|
106
|
+
answers the token exchange, `/user` and `/user/emails` as each test chooses.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
splent feature:test splent_feature_github --with identities --with orcid
|
|
110
|
+
splent feature:contract splent_feature_github
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Release
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
splent feature:release splent_feature_github --dry-run --bump patch
|
|
117
|
+
splent feature:release splent_feature_github
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The first command rehearses the release and changes nothing. The second
|
|
121
|
+
publishes it to the git forge and to PyPI, and a PyPI version is permanent.
|
|
122
|
+
This version needs the identities that brings the shared flow and
|
|
123
|
+
`provider_email_verified`, so the two are released together.
|
|
@@ -11,15 +11,14 @@ src/splent_io/splent_feature_github/__init__.py
|
|
|
11
11
|
src/splent_io/splent_feature_github/config.py
|
|
12
12
|
src/splent_io/splent_feature_github/hooks.py
|
|
13
13
|
src/splent_io/splent_feature_github/models.py
|
|
14
|
-
src/splent_io/splent_feature_github/repositories.py
|
|
15
14
|
src/splent_io/splent_feature_github/routes.py
|
|
16
15
|
src/splent_io/splent_feature_github/services.py
|
|
17
|
-
src/splent_io/splent_feature_github/signals.py
|
|
18
16
|
src/splent_io/splent_feature_github/assets/css/github.css
|
|
19
17
|
src/splent_io/splent_feature_github/migrations/alembic.ini
|
|
20
18
|
src/splent_io/splent_feature_github/migrations/env.py
|
|
21
19
|
src/splent_io/splent_feature_github/migrations/script.py.mako
|
|
22
20
|
src/splent_io/splent_feature_github/migrations/versions/7ace6050fb3f_splent_feature_github.py
|
|
21
|
+
src/splent_io/splent_feature_github/migrations/versions/github0002_into_ext_identity.py
|
|
23
22
|
src/splent_io/splent_feature_github/templates/hooks/github_login_button.html
|
|
24
23
|
src/splent_io/splent_feature_github/templates/hooks/github_profile_row.html
|
|
25
24
|
src/splent_io/splent_feature_github/translations/es/LC_MESSAGES/messages.mo
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
from splent_framework.assets.asset_registry import register_asset
|
|
2
2
|
from splent_framework.blueprints.base_blueprint import create_blueprint
|
|
3
|
-
from splent_framework.refinement import refine_model
|
|
4
|
-
from splent_framework.services.service_locator import register_service
|
|
5
3
|
|
|
6
|
-
from splent_io.splent_feature_github.
|
|
7
|
-
from splent_io.splent_feature_github.services import (
|
|
8
|
-
GithubService,
|
|
9
|
-
register_github_client,
|
|
10
|
-
)
|
|
4
|
+
from splent_io.splent_feature_github.services import register_github
|
|
11
5
|
|
|
12
6
|
github_bp = create_blueprint(__name__)
|
|
13
7
|
|
|
@@ -16,9 +10,9 @@ def init_feature(app):
|
|
|
16
10
|
from splent_io.splent_feature_github.config import inject_config
|
|
17
11
|
|
|
18
12
|
inject_config(app)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
# GitHub on identities' registry: identities runs the sign-in, the
|
|
14
|
+
# callback, the connect and the opening of new accounts.
|
|
15
|
+
register_github(app)
|
|
22
16
|
# GitHub's colours on its button and its profile row, for the public
|
|
23
17
|
# shell. The app shell gets the same file through layout.head.css.
|
|
24
18
|
register_asset(
|
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
github feature configuration.
|
|
3
3
|
|
|
4
4
|
The OAuth app registered at https://github.com/settings/developers.
|
|
5
|
-
Without both values GitHub sign-in is
|
|
6
|
-
|
|
5
|
+
Without both values GitHub sign-in is off: the app logs a warning at start,
|
|
6
|
+
and whoever tries is told it is not available.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import os
|
|
10
10
|
|
|
11
|
+
from splent_io.splent_feature_github.services import DEFAULT_SCOPE
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
def inject_config(app):
|
|
13
15
|
app.config.update(
|
|
14
16
|
{
|
|
15
17
|
"GITHUB_CLIENT_ID": os.getenv("GITHUB_CLIENT_ID", ""),
|
|
16
18
|
"GITHUB_CLIENT_SECRET": os.getenv("GITHUB_CLIENT_SECRET", ""),
|
|
19
|
+
"GITHUB_SCOPE": os.getenv("GITHUB_SCOPE", "").strip() or DEFAULT_SCOPE,
|
|
17
20
|
}
|
|
18
21
|
)
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
GitHub offers itself first on the login page (auth's auth.login.providers)
|
|
4
4
|
and on the sign-up page when the product has one (signup's
|
|
5
|
-
signup.providers). On the edit-profile page it shows the linked account,
|
|
6
|
-
a "Connect GitHub" link, first among the sections
|
|
7
|
-
(profile's profile.edit.sections).
|
|
5
|
+
signup.providers). On the edit-profile page it shows the linked account, as a
|
|
6
|
+
link to it on GitHub, or a "Connect GitHub" link, first among the sections
|
|
7
|
+
below the form (profile's profile.edit.sections).
|
|
8
8
|
|
|
9
9
|
Every slot is filled by name, so a product without signup simply has no
|
|
10
10
|
sign-up page to show the button on.
|
|
@@ -34,17 +34,15 @@ def github_login_button():
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def github_profile_row():
|
|
37
|
+
from splent_io.splent_feature_github.services import PROVIDER, github_url
|
|
37
38
|
from splent_io.splent_feature_identities.services import IdentitiesService
|
|
38
39
|
|
|
39
|
-
identity =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
),
|
|
45
|
-
None,
|
|
40
|
+
identity = IdentitiesService().identity_of(current_user.id, PROVIDER)
|
|
41
|
+
return render_template(
|
|
42
|
+
"hooks/github_profile_row.html",
|
|
43
|
+
identity=identity,
|
|
44
|
+
github_url=github_url(identity) if identity else None,
|
|
46
45
|
)
|
|
47
|
-
return render_template("hooks/github_profile_row.html", identity=identity)
|
|
48
46
|
|
|
49
47
|
|
|
50
48
|
def github_stylesheet():
|