Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move API Keys to Admin from settings file. #1993

Open
wants to merge 92 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
37f83f0
Delete current migrations
jleclanche Jun 28, 2023
ef97824
Add 3.0.0 changelog to start tracking
jleclanche Jun 28, 2023
6d803ff
Remove DJSTRIPE_WEBHOOK_TOLERANCE
jleclanche Jun 28, 2023
470924b
Fix error creating WebhookEndpoint in admin panel
PabloCastellano Aug 7, 2023
6021f91
Update settings.md to reference webhook retries that actually work
chenatlas Aug 10, 2023
07b1b73
Use for default tolerance stripe.Webhook.DEFAULT_TOLERANCE
KvyatkovskyAleksey Aug 13, 2023
e9c55b5
Pass down kwargs to `Invoice.pay()` (#1968)
arnav13081994 Aug 15, 2023
ee04b2e
Handled AuthenticationError in WebhookEndpointAdmin Create and update…
arnav13081994 Aug 17, 2023
71d6064
Update PaymentMethodType enum with new payment methods
jleclanche Aug 29, 2023
ac1cc35
Remove legacy Customer.add_card() method
jleclanche Aug 29, 2023
8f2f30c
Update decimal places and max digits
jleclanche Aug 29, 2023
0c29bd7
Make admin read-only by default
jleclanche Aug 29, 2023
bfab770
Fix minor typing errors
jleclanche Aug 29, 2023
5b4621b
Remove Plan from admin list and from subscription admin
jleclanche Aug 29, 2023
a3a33ed
Remove some superfluous fields from CheckoutSession
jleclanche Aug 29, 2023
2296c77
Add index on Session.client_reference_id and .customer_email
jleclanche Aug 29, 2023
0acf98e
Set StripeEnumField max length to 255
jleclanche Aug 29, 2023
36f463d
Remove superfluous fields from Account
jleclanche Aug 29, 2023
c9698c2
Remove various usage record fields
jleclanche Aug 29, 2023
d2c2615
Remove subscription schedule actions
jleclanche Aug 29, 2023
9588706
Fix typing error
arnav13081994 Sep 2, 2023
4606de9
Formatting fixes
arnav13081994 Sep 2, 2023
080434c
Remove unneeded imports
arnav13081994 Sep 2, 2023
1bd157c
Remove incorrect defaults
arnav13081994 Sep 2, 2023
edbc910
Remove incorrect tests
arnav13081994 Sep 2, 2023
0382277
Remove incorrect field in SessionAdmin.select_related
arnav13081994 Sep 2, 2023
91e899a
Fixed incorrect Usage Record Summary Test
arnav13081994 Sep 2, 2023
281eb5d
Fixed failing Usage Record test
arnav13081994 Sep 2, 2023
e65bfdf
Added missing expand params to upcoming invoices
arnav13081994 Sep 2, 2023
41cd066
Added missing expand params to Tax ids
arnav13081994 Sep 2, 2023
1bf0645
Fixed incorrect webhooks test
arnav13081994 Sep 2, 2023
a04f2ba
Fixed failing Usage Record test
arnav13081994 Sep 2, 2023
6d90c2d
Remove a variety of subscription fields
jleclanche Sep 2, 2023
d87f609
Remove support for non-id foreign keys
jleclanche Sep 2, 2023
647bd60
Remove unnecessary fields in DiscountAdmin.list_display
arnav13081994 Sep 4, 2023
317ee92
Remove unnecessary fields in DiscountAdmin.list_filter
arnav13081994 Sep 4, 2023
d1fbb87
Remove unnecessary field in SubscriptionAdmin.list_display
arnav13081994 Sep 4, 2023
81e35b9
Remove unnecessary SubscriptionAdmin.list_filter
arnav13081994 Sep 4, 2023
eb0f269
Removed old style webhooks (#1980)
arnav13081994 Sep 5, 2023
a2bcce2
Renamed tolerance to djstripe_tolerance as it's a Djstripe specific f…
arnav13081994 Sep 6, 2023
9f70923
Added WebhookEndpointAdminBaseForm.add_endpoint_tolerance
arnav13081994 Sep 6, 2023
598a986
Updated WebhookEndpoint._attach_objects_hook to correctly populate dj…
arnav13081994 Sep 6, 2023
d5b09f7
Updated webhooks module to use webhookendpoint's tolerance
arnav13081994 Sep 6, 2023
5ccd32b
Minor Refactoring
arnav13081994 Sep 6, 2023
4518f11
Removed deprecated DJSTRIPE_WEBHOOK_SECRET setting
arnav13081994 Sep 7, 2023
448f891
Removed unnecessary check for non-existent DJSTRIPE_WEBHOOK_SECRET se…
arnav13081994 Sep 7, 2023
e00acf9
Added djstripe_data JSON field
arnav13081994 Sep 4, 2023
4f3908c
Updated _stripe_object_to_record() to add all stripe data to djstrip…
arnav13081994 Sep 2, 2023
f9d2f40
Minor fixes to make Account model work with djstripe_data field
arnav13081994 Sep 2, 2023
938b321
Updated changelog
arnav13081994 Sep 5, 2023
bda5e20
Updated changelog
arnav13081994 Sep 6, 2023
b0a4981
Fix error in CustomerSubscriptionStatusListFilter
arnav13081994 Sep 6, 2023
09ec0f8
Renamed StripeModel.djstripe_data to stripe_data
arnav13081994 Sep 7, 2023
5446a86
Added stripe_data to ignore_fiels to avoid infinite recursion
arnav13081994 Sep 7, 2023
6b8eae5
Removed deprecated DJSTRIPE_WEBHOOK_URL setting
arnav13081994 Sep 7, 2023
23f7177
Removed unnecessary test
arnav13081994 Sep 7, 2023
a92cb9f
Added WebhookEndpointValidation enum to track webhook endpoint valida…
arnav13081994 Sep 7, 2023
0dee624
Removed depreacted DJSTRIPE_WEBHOOK_VALIDATION setting
arnav13081994 Sep 7, 2023
d5a47e3
Removed unncessary checks for global webhook endpoint validation setting
arnav13081994 Sep 7, 2023
3a5ba79
Added djstripe_validation_method model field
arnav13081994 Sep 7, 2023
7d66705
Added djstripe_validation_method field to admin and forms
arnav13081994 Sep 7, 2023
242c36f
Added WebhookEndpointAdminBaseForm.add_endpoint_validation_method to …
arnav13081994 Sep 7, 2023
32d557d
Updated WebhookEventTrigger.validate to use endpoint validation metho…
arnav13081994 Sep 7, 2023
fefe269
Updated WebhookEndpoint._attach_objects_hook to correctly update the …
arnav13081994 Sep 7, 2023
8b8f601
Updated changelog
arnav13081994 Sep 7, 2023
74b3d20
Updated docs with info on DJSTRIPE_SUBSCRIBER_MODEL_REQUEST_CALLBACK …
arnav13081994 Sep 16, 2023
f4f930f
Minor code refactoring
arnav13081994 Sep 19, 2023
71f6d8f
Formatting Fixes
arnav13081994 Sep 29, 2023
5eca33e
Updated admin to use .get to access dictionary values instead of []
arnav13081994 Oct 1, 2023
c54fc32
Updated admin to use .get to access dictionary values instead of [] w…
arnav13081994 Oct 1, 2023
e1fcf90
Fixed failing tests in python 3.11
arnav13081994 Oct 2, 2023
34717a1
Added system check to warn the user if they have set stripe.api_key i…
arnav13081994 Sep 29, 2023
bf3b7e9
Added `djstripe_is_account_default` to the APIKey model
arnav13081994 Sep 29, 2023
2df3982
Removed deprecated Stripe Key settings from the settings file
arnav13081994 Sep 29, 2023
e142d20
Added setting GET_DEFAULT_STRIPE_SECRET_KEY
arnav13081994 Sep 29, 2023
3f0e9f2
Updated setting get_default_api_key to reuse the newly added GET_DEFA…
arnav13081994 Sep 29, 2023
da9dc9d
Moved api_key param with default to inside the function body
arnav13081994 Sep 29, 2023
e29978c
Updated example app to use the GET_DEFAULT_STRIPE_SECRET_KEY() setting
arnav13081994 Sep 29, 2023
a5eb9b6
Updated APIkey.refresh_account to raise_exceptions. Defaults to False
arnav13081994 Sep 29, 2023
c856b46
Added djstripe_is_account_default to APIKey Admin.
arnav13081994 Sep 29, 2023
f87314c
Added APIKeyAdminBaseForm admin form
arnav13081994 Sep 29, 2023
594facb
Added APIKeyAdminEditForm admin form
arnav13081994 Sep 29, 2023
b2ac50c
Set djstripe_is_account_default to True for adding new API Keys
arnav13081994 Sep 29, 2023
196ca39
python set order is not deterministic so sorted admin fields to make …
arnav13081994 Oct 3, 2023
13f77af
Explicitly mentioning the defaults
arnav13081994 Oct 3, 2023
ec57708
Updated APIKeyAdminCreateForm._post_clean to handle violation of uniq…
arnav13081994 Oct 3, 2023
24437be
Updated APIKeyAdminCreateForm._post_clean to handle violation of djst…
arnav13081994 Oct 3, 2023
ffbd7ea
Updated APIKeyAdmin.save_model() to correctly populate key name
arnav13081994 Oct 3, 2023
6391f12
Updated APIKeyAdmin.save_model() to correctly djstripe_is_account_def…
arnav13081994 Oct 3, 2023
916a86e
Updated WebhookCreateAdmin to default Stripe API version to the one i…
arnav13081994 Oct 3, 2023
5b8b9e5
Passed missing required positional arg djstripe_owner_account
arnav13081994 Oct 3, 2023
b986116
Moved construct_custom_error_message to a helper function
arnav13081994 Oct 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file added dist/dj_stripe-2.8.0-py3-none-any.whl
Binary file not shown.
Binary file added dist/dj_stripe-2.8.0.tar.gz
Binary file not shown.
172 changes: 59 additions & 113 deletions djstripe/admin/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from stripe.error import InvalidRequestError

from djstripe import models
from djstripe.settings import djstripe_settings

from .actions import CustomActionMixin
from .admin_inline import (
Expand All @@ -22,6 +23,7 @@
from .filters import CustomerHasSourceListFilter, CustomerSubscriptionStatusListFilter
from .forms import (
APIKeyAdminCreateForm,
APIKeyAdminEditForm,
CustomActionForm,
WebhookEndpointAdminCreateForm,
WebhookEndpointAdminEditForm,
Expand Down Expand Up @@ -83,19 +85,22 @@ def __init__(self, *args, **kwargs):

def get_list_display(self, request):
return (
("__str__", "id", "djstripe_owner_account")
+ self.list_display
+ ("created", "livemode")
"__str__",
"id",
"djstripe_owner_account",
*self.list_display,
"created",
"livemode",
)

def get_list_filter(self, request):
return self.list_filter + ("created", "livemode")
return (*self.list_filter, "created", "livemode")

def get_readonly_fields(self, request, obj=None):
return self.readonly_fields + ("id", "djstripe_owner_account", "created")
return (*self.readonly_fields, "id", "djstripe_owner_account", "created")

def get_search_fields(self, request):
return self.search_fields + ("id",)
return (*self.search_fields, "id")

def get_fieldsets(self, request, obj=None):
common_fields = ("livemode", "id", "djstripe_owner_account", "created")
Expand All @@ -114,16 +119,20 @@ def get_queryset(self, request):
@admin.register(models.Account)
class AccountAdmin(StripeModelAdmin):
list_display = ("business_url", "country", "default_currency")
list_filter = ("details_submitted",)
search_fields = ("settings", "business_profile")


@admin.register(models.APIKey)
class APIKeyAdmin(admin.ModelAdmin):
add_form_template = "djstripe/admin/add_form.html"
change_form_template = "djstripe/admin/change_form.html"

list_display = ("__str__", "type", "djstripe_owner_account", "livemode")
list_display = (
"__str__",
"djstripe_is_account_default",
"type",
"djstripe_owner_account",
"livemode",
)
readonly_fields = ("djstripe_owner_account", "livemode", "type", "secret")
search_fields = ("name",)

Expand All @@ -135,12 +144,19 @@ def get_readonly_fields(self, request, obj=None):
def get_fields(self, request, obj=None):
if obj is None:
return APIKeyAdminCreateForm.Meta.fields
return ["type", "djstripe_owner_account", "livemode", "name", "secret"]
return [
"type",
"djstripe_is_account_default",
"djstripe_owner_account",
"livemode",
"name",
"secret",
]

def get_form(self, request, obj=None, **kwargs):
if obj is None:
return APIKeyAdminCreateForm
return super().get_form(request, obj, **kwargs)
return APIKeyAdminEditForm

def get_queryset(self, request):
return super().get_queryset(request).select_related("djstripe_owner_account")
Expand All @@ -154,7 +170,24 @@ def save_model(self, request: Any, obj, form: Any, change: Any) -> None:
with transaction.atomic():
obj.save()
except IntegrityError:
pass
# Get the name and djstripe_is_account_default from the form
name = form.cleaned_data.get("name", "")
djstripe_is_account_default = form.cleaned_data.get(
"djstripe_is_account_default"
)

# Get APIKey from DB
instance = self.model.objects.get(secret=obj.secret)

# Update name and djstripe_is_account_default of APIKey
instance.name = name
instance.djstripe_is_account_default = djstripe_is_account_default
instance.save()

def get_changeform_initial_data(self, request) -> Dict[str, str]:
ret = super().get_changeform_initial_data(request)
ret.setdefault("djstripe_is_account_default", True)
return ret


@admin.register(models.BalanceTransaction)
Expand Down Expand Up @@ -252,12 +285,13 @@ def get_queryset(self, request):
class DiscountAdmin(ReadOnlyMixin, StripeModelAdmin):
list_display = (
"customer",
"coupon",
"invoice_item",
"promotion_code",
"subscription",
)
list_filter = ("customer", "start", "end", "promotion_code", "coupon")
list_filter = (
"customer",
"promotion_code",
)

def get_actions(self, request):
"""
Expand Down Expand Up @@ -402,7 +436,7 @@ class SessionAdmin(StripeModelAdmin):
search_fields = ("customer__id", "customer_email")

def get_queryset(self, request):
return super().get_queryset(request).select_related("customer", "subscription")
return super().get_queryset(request).select_related("customer")


@admin.register(models.Invoice)
Expand Down Expand Up @@ -478,34 +512,6 @@ def get_actions(self, request):
return actions


@admin.register(models.Plan)
class PlanAdmin(StripeModelAdmin):
radio_fields = {"interval": admin.HORIZONTAL}

def get_readonly_fields(self, request, obj=None):
"""Return extra readonly_fields."""
readonly_fields = super().get_readonly_fields(request, obj)

if obj:
readonly_fields += (
"amount",
"currency",
"interval",
"interval_count",
"trial_period_days",
)

return readonly_fields

def get_queryset(self, request):
return (
super()
.get_queryset(request)
.select_related("product")
.prefetch_related("subscriptions")
)


@admin.register(models.Price)
class PriceAdmin(StripeModelAdmin):
list_display = ("product", "currency", "active")
Expand Down Expand Up @@ -641,8 +647,7 @@ class ShippingRateAdmin(StripeModelAdmin):

@admin.register(models.Subscription)
class SubscriptionAdmin(StripeModelAdmin):
list_display = ("customer", "status", "get_product_name", "get_default_tax_rates")
list_filter = ("status", "cancel_at_period_end")
list_display = ("customer",)

inlines = (SubscriptionItemInline, SubscriptionScheduleInline, LineItemInline)

Expand All @@ -658,68 +663,13 @@ def _cancel(self, request, queryset):
context = self.get_admin_action_context(queryset, "_cancel", CustomActionForm)
return render(request, "djstripe/admin/confirm_action.html", context)

def get_queryset(self, request):
return (
super()
.get_queryset(request)
.select_related(
"customer",
"plan",
"plan__product",
)
.prefetch_related(
"customer__subscriptions",
"customer__subscriptions__plan",
"customer__subscriptions__plan__product",
"default_tax_rates",
)
)

@admin.display(description="Default Tax Rates")
def get_default_tax_rates(self, obj):
result = [str(tax_rate) for tax_rate in obj.default_tax_rates.all()]
if result:
return ", ".join(result)

@admin.display(description="Product Name")
def get_product_name(self, obj):
if obj.plan and obj.plan.product:
return obj.plan.product.name


@admin.register(models.SubscriptionSchedule)
class SubscriptionScheduleAdmin(StripeModelAdmin):
list_display = ("status", "subscription", "current_phase", "customer")
list_filter = ("status", "subscription", "customer")
list_select_related = ("customer", "customer__subscriber", "subscription")

@admin.display(description="Release Selected Subscription Schedules")
def _release_subscription_schedule(self, request, queryset):
"""Release a SubscriptionSchedule."""
context = self.get_admin_action_context(
queryset, "_release_subscription_schedule", CustomActionForm
)
return render(request, "djstripe/admin/confirm_action.html", context)

@admin.display(description="Cancel Selected Subscription Schedules")
def _cancel_subscription_schedule(self, request, queryset):
"""Cancel a SubscriptionSchedule."""
context = self.get_admin_action_context(
queryset, "_cancel_subscription_schedule", CustomActionForm
)
return render(request, "djstripe/admin/confirm_action.html", context)

def get_actions(self, request):
# get all actions
actions = super().get_actions(request)
actions["_release_subscription_schedule"] = self.get_action(
"_release_subscription_schedule"
)
actions["_cancel_subscription_schedule"] = self.get_action(
"_cancel_subscription_schedule"
)
return actions


@admin.register(models.TaxCode)
class TaxCodeAdmin(StripeModelAdmin):
Expand Down Expand Up @@ -775,12 +725,7 @@ def get_actions(self, request):

@admin.register(models.UsageRecordSummary)
class UsageRecordSummaryAdmin(StripeModelAdmin):
list_display = ("invoice", "subscription_item", "total_usage")

def get_queryset(self, request):
return (
super().get_queryset(request).select_related("invoice", "subscription_item")
)
pass


@admin.register(models.WebhookEndpoint)
Expand Down Expand Up @@ -835,7 +780,8 @@ def get_fieldsets(self, request, obj=None):
"metadata",
"api_version",
"djstripe_uuid",
"tolerance",
"djstripe_tolerance",
"djstripe_validation_method",
]
if obj.djstripe_uuid:
core_fields = [
Expand All @@ -855,7 +801,8 @@ def get_fieldsets(self, request, obj=None):
"metadata",
"api_version",
"enabled_events",
"tolerance",
"djstripe_tolerance",
"djstripe_validation_method",
]

return [
Expand All @@ -871,16 +818,15 @@ def get_changeform_initial_data(self, request) -> Dict[str, str]:
ret = super().get_changeform_initial_data(request)
base_url = f"{request.scheme}://{request.get_host()}"
ret.setdefault("base_url", base_url)
ret.setdefault("api_version", djstripe_settings.STRIPE_API_VERSION)
return ret

def delete_model(self, request, obj: models.WebhookEndpoint):
try:
obj._api_delete()
except InvalidRequestError as e:
if e.user_message.startswith("No such webhook endpoint: "):
# Webhook was already deleted in Stripe
pass
else:
# Error other than Webhook was already deleted in Stripe
if not e.user_message.startswith("No such webhook endpoint: "):
raise

return super().delete_model(request, obj)
Expand Down
2 changes: 1 addition & 1 deletion djstripe/admin/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def lookups(self, request, model_admin):
statuses = [
[x, x.replace("_", " ").title()]
for x in models.Subscription.objects.values_list(
"status", flat=True
"stripe_data__status", flat=True
).distinct()
]
statuses.append(["none", "No Subscription"])
Expand Down