No project description provided
Project description
python-admin-sdk
Install
pip install pluginlab_admin
Getting started
Get started by initializing the Pluginlab app:
from pluginlab_admin import App
app = App(
secret_key="<PLUGIN_SECRET>",
plugin_id="<PLUGIN_ID>",
)
# to manage auth-related stuff, mostly members
auth = app.get_auth()
The SDK secret should be generated from your Pluginlab dashboard.
Verify the user token
Everytime ChatGPT will talk to your backend through the PluginLab proxy, it will send the user token in the Authorization header as a bearer token.
You can verify the integrity of such token by using the verify_token
method:
auth = app.get_auth()
# usually you'd get the token from the Authorization header of the HTTP request, formatted as `Bearer <token>`
token = "eyJhbGc...dQssw5c"
try:
payload = auth.verify_token(token)
# from that point we know the information in the token hasn't been tampered with
# we could, for instance, check if the user has a given plan and take specific action based on that
premium_plan_id = 'KWsmKyJnHBF2Dz1mETDF'
plan_id = payload.user.plan_id
if plan_id:
if plan_id == premium_plan_id:
do_something_special()
else
do_other_stuff()
print(payload.uid)
except Exception as e:
print(f"An error occurred while verifying the token: {e}")
The verified token payload is represented by the following typings:
class TokenPayloadUser:
id: str
email: str
name: Optional[str] = None
given_name: Optional[str] = None
plan_id: Optional[str] = None
price_id: Optional[str] = None
class TokenPayload:
uid: str
iss: str
aud: str
iat: int
exp: int
user: TokenPayloadUser
Get a member by id or email
By email
member = auth.get_member_by_email('johndoe@example.com')
if member is None:
print('No such member.')
else
print(f'Member with email {member.auth.email} signed up with method "{member.auth.sign_in_method}"')
By id
member = auth.get_member_by_id('mem_ec9fd884f7fc81fc9e5576d213b6e826d3109d26')
if member is None:
print('No such member.')
else
print(f'Member with id {member.id} (email={member.auth.email}) signed up with method "{member.auth.sign_in_method}"')
A member is represented with the following typings:
class SignInMethodId(Enum):
EMAIL_AND_PASSWORD = 'email-and-password'
MAGIC_EMAIL_CODE = 'magic-email-code'
GOOGLE = 'google'
class MemberAuth:
is_verified: bool;
email: str;
has_password: bool;
sign_in_method: SignInMethodId;
class Member:
id: str;
auth: MemberAuth;
name: Optional[str]
given_name: Optional[str]
family_name: Optional[str]
picture_url: Optional[str]
custom_fields: dict[str, str];
metadata: dict[str, str];
created_at_ms: int;
updated_at_ms: int;
Get member identities
Once a user logs in to your PluginLab portal using a third-party authentication provider, they get assigned an identity for that specific provider.
An identity might contain what you need to interact with the service on behalf of your user such as an access token or a refresh token.
To retrieve all the identities for a given user, use the auth.get_member_identities
method:
identities = auth.get_member_identities("mem_66c72702dfd9c9a34e80cae434a4bf7e6d3d37df")
if identities.google is not None:
print("Google identity found, access token is ", identities.google.access_token)
if identities.github is not None:
# do your stuff
# This applies to every third-party auth provider supported by PluginLab although each might give or not give some information.
Here is the class used to represent an identity:
@dataclass
class IdentityProviderData:
provider: str;
provider_user_id: str;
access_token_expires_at_ms: int | None;
refresh_token_expires_at_ms: int | None;
last_used_at_ms: int | None;
access_token: str | None;
refresh_token: str | None;
List members
Basic
paginated_result = auth.get_members()
for member in paginated_result.items:
print(member.id)
With adjustable limit and pagination
You can request up to 100 members at a time and get a specific page by providing a cursor obtained from a previous call.
paginated_result1 = auth.get_members(50)
cursor = paginated_result1.next_page_cursor
if not cursor is None:
paginated_result2 = auth.get_members(50, cursor)
Create a member
created_member = auth.create_member(
email='johndoe@example.com',
password='12345',
is_verified=True,
metadata={
'origin': 'backend-sdk'
}
)
print(created_member)
As the typings show, both is_verified
and metadata
fields are optional to create a user.
Update a member
auth.update_member(
id='mem_ec9fd884f7fc81fc9e5576d213b6e826d3109d26',
given_name="John the king of examples",
family_name="Doe",
name="John Doe",
picture_url="https://example.com/john-doe.png",
metadata={}
)
Except the id
field that is used to identify the user to update, all the other updatable fields are optional in this function call.
Delete a member
auth.delete_member(
id='mem_ec9fd884f7fc81fc9e5576d213b6e826d3109d26',
)
Note that the member ID is derived from the email the user used to sign up. Therefore recreating an account with the same email will NOT reset usage quotas.
Get user quota information
Since version 0.4.0
you can retrieve the current quota usage of a plugin member thanks to the monetization module:
monetization = app.get_monetization();
quota_usage = monetization.get_member_quota_usage(member_id);
if quota_usage.is_over_limit:
print(f'User exceeded their quota, it will be reset in {quota_usage.reset_in_days} days.')
Dealing with webhooks
Pluginlab signs each webhook payload it sends you using a secret key you can retrieve from your webhooks settings on the Pluginlab dashboard.
This package provides facilities to easiliy verifiy the payload of a webhook.
Here is how, using a flask handler as an example:
import os
from pluginlab_admin import WebhookHeaders, Webhook
webhook_secret = os.getenv('WEBHOOK_SECRET')
webhook = Webhook(webhook_secret)
@app.route('/webhook', methods=['POST'])
def api():
sig = request.headers.get(WebhookHeaders.Signature.value)
raw_body = request.get_data(as_text=True)
if not sig:
return jsonify({'message': 'No signature was found.'})
if not webhook.is_signature_valid(raw_body, sig):
return jsonify({'message': 'Invalid signature.'})
// process the payload as you like
Make sure you are providing the is_signature_valid
method with the raw body of the request, as it was originally sent.
Events
On PluginLab, an event is used as a representaiton of a plugin request and is traditionally generated on each request made by ChatGPT. The SDK offers limited but useful utilities to deal with events.
To get started, you need to leverage the event service by calling the app.get_event
method.
// assuming app was previously initialized as showed above
event = app.get_event();
Create a custom event
If you want to create custom events that will appear in your PluginLab dashboard and count as part of your users' quota, you can rely on the create_custom
method.
This is especially useful if your service is accessible from other means that ChatGPT but you still want to account for usage using PluginLab.
from pluginlab_admin import EventLocation
location = EventLocation(
country_code="US",
subdivision_code="CA", # optional
)
event.create_custom(
# case insensitive, max. 10 chars
event_source="WEB_UI",
# optional, quota ignored if not present
member_id="mem_fd9a1ba5e385e3d97412cdfbd7b8284c4f0c8e18",
# optional
location=location,
# optional, defaults to true
is_in_quota=True
)
Assuming the provided member_id
refers to a valid plugin member then a new event will get created once the above code runs. It will appear in your PluginLab dashboard's event section.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for pluginlab_admin-0.4.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | def3fdf1b0ff76d0ec1733626695ecf138833dc151f26fb78a3479ea29ac8655 |
|
MD5 | 6d2f71359f08dc8169381e6264d78aee |
|
BLAKE2b-256 | 6e9f4468cae0b75372d36b9ae53e4a818e728c67295f55d2db500a702169e694 |