datasette-secrets 0.1a1__py3-none-any.whl → 0.1a2__py3-none-any.whl
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.
Potentially problematic release.
This version of datasette-secrets might be problematic. Click here for more details.
- datasette_secrets/__init__.py +19 -12
- datasette_secrets/templates/secrets_index.html +5 -2
- datasette_secrets/templates/secrets_update.html +4 -2
- {datasette_secrets-0.1a1.dist-info → datasette_secrets-0.1a2.dist-info}/METADATA +18 -3
- datasette_secrets-0.1a2.dist-info/RECORD +10 -0
- datasette_secrets-0.1a1.dist-info/RECORD +0 -10
- {datasette_secrets-0.1a1.dist-info → datasette_secrets-0.1a2.dist-info}/LICENSE +0 -0
- {datasette_secrets-0.1a1.dist-info → datasette_secrets-0.1a2.dist-info}/WHEEL +0 -0
- {datasette_secrets-0.1a1.dist-info → datasette_secrets-0.1a2.dist-info}/entry_points.txt +0 -0
- {datasette_secrets-0.1a1.dist-info → datasette_secrets-0.1a2.dist-info}/top_level.txt +0 -0
datasette_secrets/__init__.py
CHANGED
|
@@ -55,7 +55,9 @@ async def get_secret(datasette, secret_name, actor_id=None):
|
|
|
55
55
|
@dataclasses.dataclass
|
|
56
56
|
class Secret:
|
|
57
57
|
name: str
|
|
58
|
-
|
|
58
|
+
description: Optional[str] = None
|
|
59
|
+
obtain_url: Optional[str] = None
|
|
60
|
+
obtain_label: Optional[str] = None
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
SCHEMA = """
|
|
@@ -114,25 +116,20 @@ def register_permissions(datasette):
|
|
|
114
116
|
|
|
115
117
|
async def get_secrets(datasette):
|
|
116
118
|
secrets = []
|
|
119
|
+
seen = set()
|
|
117
120
|
for result in pm.hook.register_secrets(datasette=datasette):
|
|
118
121
|
result = await await_me_maybe(result)
|
|
119
|
-
|
|
122
|
+
for secret in result:
|
|
123
|
+
if secret.name in seen:
|
|
124
|
+
continue # Skip duplicates
|
|
125
|
+
seen.add(secret.name)
|
|
126
|
+
secrets.append(secret)
|
|
120
127
|
# if not secrets:
|
|
121
128
|
secrets.append(Secret("EXAMPLE_SECRET", "An example secret"))
|
|
122
129
|
|
|
123
130
|
return secrets
|
|
124
131
|
|
|
125
132
|
|
|
126
|
-
@hookimpl
|
|
127
|
-
def register_secrets():
|
|
128
|
-
return [
|
|
129
|
-
Secret(
|
|
130
|
-
"OPENAI_API_KEY",
|
|
131
|
-
'An OpenAI API key. Get them from <a href="https://platform.openai.com/api-keys">here</a>.',
|
|
132
|
-
),
|
|
133
|
-
]
|
|
134
|
-
|
|
135
|
-
|
|
136
133
|
@hookimpl
|
|
137
134
|
def register_commands(cli):
|
|
138
135
|
@cli.group()
|
|
@@ -183,6 +180,16 @@ async def secrets_index(datasette, request):
|
|
|
183
180
|
list(environment_secrets_names),
|
|
184
181
|
)
|
|
185
182
|
existing_secrets = {row["name"]: dict(row) for row in existing_secrets_result.rows}
|
|
183
|
+
# Try to turn updated_by into actors
|
|
184
|
+
actors = await datasette.actors_from_ids(
|
|
185
|
+
{row["updated_by"] for row in existing_secrets.values() if row["updated_by"]}
|
|
186
|
+
)
|
|
187
|
+
for secret in existing_secrets.values():
|
|
188
|
+
if secret["updated_by"]:
|
|
189
|
+
actor = actors.get(secret["updated_by"])
|
|
190
|
+
if actor:
|
|
191
|
+
display = actor.get("username") or actor.get("name") or actor.get("id")
|
|
192
|
+
secret["updated_by"] = display
|
|
186
193
|
unset_secrets = [
|
|
187
194
|
secret
|
|
188
195
|
for secret in all_secrets
|
|
@@ -25,7 +25,10 @@
|
|
|
25
25
|
<ul>
|
|
26
26
|
{% for secret in unset_secrets %}
|
|
27
27
|
<li><strong><a href="{{ urls.path("/-/secrets/") }}{{ secret.name }}">{{ secret.name }}</a></strong>
|
|
28
|
-
{% if secret.
|
|
28
|
+
{% if secret.description or secret.obtain_label %}
|
|
29
|
+
- {{ secret.description or "" }}{% if secret.description and secret.obtain_label %}, {% endif %}
|
|
30
|
+
{% if secret.obtain_label %}<a href="{{ secret.obtain_url }}">{{ secret.obtain_label }}</a>{% endif %}
|
|
31
|
+
{% endif %}</li>
|
|
29
32
|
{% endfor %}
|
|
30
33
|
</ul>
|
|
31
34
|
{% endif %}
|
|
@@ -34,7 +37,7 @@
|
|
|
34
37
|
<p style="margin-top: 2em">The following secret{% if environment_secrets|length == 1 %} is{% else %}s are{% endif %} set using environment variables:</p>
|
|
35
38
|
<ul>
|
|
36
39
|
{% for secret in environment_secrets %}
|
|
37
|
-
<li><strong>{{ secret.name }}</a></strong
|
|
40
|
+
<li><strong>{{ secret.name }}</a></strong>{% if secret.description %} - {{ secret.description }}{% endif %}<br>
|
|
38
41
|
<span style="font-size: 0.8 em">Set by <code>DATASETTE_SECRETS_{{ secret.name }}</code></span></li>
|
|
39
42
|
{% endfor %}
|
|
40
43
|
</ul>
|
|
@@ -9,8 +9,10 @@
|
|
|
9
9
|
{% block content %}
|
|
10
10
|
<h1>{% if current_secret %}Update{% else %}Add{% endif %} secret: {{ secret_name }}</h1>
|
|
11
11
|
|
|
12
|
-
{% if secret_details
|
|
13
|
-
<p>{{ secret_details.
|
|
12
|
+
{% if secret_details.description or secret_details.obtain_label %}
|
|
13
|
+
<p>{{ secret_details.description or "" }}{% if secret_details.description and secret_details.obtain_label %}. {% endif %}
|
|
14
|
+
{% if secret_details.obtain_label %}<a href="{{ secret_details.obtain_url }}">{{ secret_details.obtain_label }}</a>{% endif %}
|
|
15
|
+
</p>
|
|
14
16
|
{% endif %}
|
|
15
17
|
|
|
16
18
|
{% if error %}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: datasette-secrets
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1a2
|
|
4
4
|
Summary: Manage secrets such as API keys for use with other Datasette plugins
|
|
5
5
|
Author: Datasette
|
|
6
6
|
License: Apache-2.0
|
|
@@ -105,6 +105,8 @@ datasette data.db --internal internal.db \
|
|
|
105
105
|
|
|
106
106
|
users with the `manage-secrets` permission will see a new "Manage secrets" link in the Datasette navigation menu. This interface can also be accessed at `/-/secrets`.
|
|
107
107
|
|
|
108
|
+
The page with the list of secrets will show the user who last updated each secret. This will use the [actors_from_ids()](https://docs.datasette.io/en/latest/plugin_hooks.html#actors-from-ids-datasette-actor-ids) mechanism, displaying the actor's `username` if available, otherwise the `name`, otherwise the `id`.
|
|
109
|
+
|
|
108
110
|
## For plugin authors
|
|
109
111
|
|
|
110
112
|
Plugins can depend on this plugin if they want to implement secrets.
|
|
@@ -121,11 +123,24 @@ from datasette_secrets import Secret
|
|
|
121
123
|
def register_secrets():
|
|
122
124
|
return [
|
|
123
125
|
Secret(
|
|
124
|
-
"OPENAI_API_KEY",
|
|
125
|
-
|
|
126
|
+
name="OPENAI_API_KEY",
|
|
127
|
+
description="An OpenAI API key"
|
|
128
|
+
),
|
|
129
|
+
]
|
|
130
|
+
```
|
|
131
|
+
You can also provide optional `obtain_url` and `obtain_label` fields to link to a page where a user can obtain an API key:
|
|
132
|
+
```python
|
|
133
|
+
@hookimpl
|
|
134
|
+
def register_secrets():
|
|
135
|
+
return [
|
|
136
|
+
Secret(
|
|
137
|
+
name="OPENAI_API_KEY",
|
|
138
|
+
obtain_url="https://platform.openai.com/api-keys",
|
|
139
|
+
obtain_label="Get an OpenAI API key"
|
|
126
140
|
),
|
|
127
141
|
]
|
|
128
142
|
```
|
|
143
|
+
|
|
129
144
|
The hook can take an optional `datasette` argument. It can return a list or an `async def` function that, when awaited, returns a list.
|
|
130
145
|
|
|
131
146
|
The list should consist of `Secret()` instances, each with a name and an optional description. The description can contain HTML.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
datasette_secrets/__init__.py,sha256=QFIh9c--SqVDhv-5WXfmI40-UqyyZrngdzYJ9t_hVE4,10409
|
|
2
|
+
datasette_secrets/hookspecs.py,sha256=57v14e2Y4o5eZyAgCLpuzp1KZn7CjwLXeKwfq6Zvux8,205
|
|
3
|
+
datasette_secrets/templates/secrets_index.html,sha256=ZgIy_huFZQfnI6GjO0qauWEkTWhkBCM5WrT73Nqq4BY,1737
|
|
4
|
+
datasette_secrets/templates/secrets_update.html,sha256=qMPLVCuKKslqw_In0aSCVobB3maPw9oaYZDQQImdRIU,1678
|
|
5
|
+
datasette_secrets-0.1a2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
6
|
+
datasette_secrets-0.1a2.dist-info/METADATA,sha256=h-UZ9xZYyvTXjwJBNntAqhPp90OY5Y-INqedW2iqLuU,7040
|
|
7
|
+
datasette_secrets-0.1a2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
8
|
+
datasette_secrets-0.1a2.dist-info/entry_points.txt,sha256=2083uWbPpGntxRulh8_hVaelQO-xdtjedG6rGzwPUH0,40
|
|
9
|
+
datasette_secrets-0.1a2.dist-info/top_level.txt,sha256=ZBJKQk-DdDU9Vnwu4x79X9aaEulwGJMoLx62IZJPDaQ,18
|
|
10
|
+
datasette_secrets-0.1a2.dist-info/RECORD,,
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
datasette_secrets/__init__.py,sha256=u5Hu7mYtbszNmzTyBmsQoyg2V0aS9rJs_NdanZQmgGg,9923
|
|
2
|
-
datasette_secrets/hookspecs.py,sha256=57v14e2Y4o5eZyAgCLpuzp1KZn7CjwLXeKwfq6Zvux8,205
|
|
3
|
-
datasette_secrets/templates/secrets_index.html,sha256=Zr8wmVngxzABB69hM052W8IOHgGIlJLM9KKnDxAYmQI,1510
|
|
4
|
-
datasette_secrets/templates/secrets_update.html,sha256=SQs_TmrCw-eanePGiEnRiqH6OKy_G5iJJcEfg_z6RFg,1463
|
|
5
|
-
datasette_secrets-0.1a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
6
|
-
datasette_secrets-0.1a1.dist-info/METADATA,sha256=UneJmupjhs_jQAB20WaCsQvAWqfH0YIMombKkjQXN50,6417
|
|
7
|
-
datasette_secrets-0.1a1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
8
|
-
datasette_secrets-0.1a1.dist-info/entry_points.txt,sha256=2083uWbPpGntxRulh8_hVaelQO-xdtjedG6rGzwPUH0,40
|
|
9
|
-
datasette_secrets-0.1a1.dist-info/top_level.txt,sha256=ZBJKQk-DdDU9Vnwu4x79X9aaEulwGJMoLx62IZJPDaQ,18
|
|
10
|
-
datasette_secrets-0.1a1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|