mirror of
https://github.com/SigNoz/signoz.git
synced 2026-09-13 23:10:41 +01:00
#### Description - Adds a `subscription` domain: `POST`, `PUT`, and `GET /api/v1/subscriptions`, wired with `CheckResources` + `ResourceDef`s on the `subscription` metaresource (`create`, `list` + `update`, `read`). Community gets a noop implementation; enterprise talks to Zeus. - Migration `125_add_subscription_tuples` backfills the admin subscription tuples for existing organizations. - The legacy `/api/v1/checkout`, `/api/v1/billing`, and `/api/v1/portal` routes are untouched; they are deleted once the frontend has moved. #### Additional Information Part of SigNoz/platform-pod#3091.
96 lines
2.9 KiB
Go
96 lines
2.9 KiB
Go
package httpsubscription
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/SigNoz/signoz/pkg/errors"
|
|
"github.com/SigNoz/signoz/pkg/licensing"
|
|
"github.com/SigNoz/signoz/pkg/subscription"
|
|
"github.com/SigNoz/signoz/pkg/types/subscriptiontypes"
|
|
"github.com/SigNoz/signoz/pkg/valuer"
|
|
"github.com/SigNoz/signoz/pkg/zeus"
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
const upstreamTimeout = 10 * time.Second
|
|
|
|
type provider struct {
|
|
zeus zeus.Zeus
|
|
licensing licensing.Licensing
|
|
}
|
|
|
|
func New(zeus zeus.Zeus, licensing licensing.Licensing) subscription.Subscription {
|
|
return &provider{
|
|
zeus: zeus,
|
|
licensing: licensing,
|
|
}
|
|
}
|
|
|
|
func (provider *provider) Create(ctx context.Context, organizationID valuer.UUID, postableSubscription *subscriptiontypes.PostableSubscription) (*subscriptiontypes.GettableSubscription, error) {
|
|
ctx, cancel := context.WithTimeout(ctx, upstreamTimeout)
|
|
defer cancel()
|
|
|
|
license, err := provider.licensing.GetActive(ctx, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
body, err := json.Marshal(postableSubscription)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, errors.TypeInvalidInput, errors.CodeInvalidInput, "failed to marshal subscription payload")
|
|
}
|
|
|
|
response, err := provider.zeus.GetCheckoutURL(ctx, license.Key, body)
|
|
if err != nil {
|
|
if errors.Ast(err, errors.TypeAlreadyExists) {
|
|
return nil, errors.WithAdditionalf(err, "checkout has already been completed for this account. Please click 'Refresh Status' to sync your subscription")
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
return &subscriptiontypes.GettableSubscription{RedirectURL: gjson.GetBytes(response, "url").String()}, nil
|
|
}
|
|
|
|
func (provider *provider) Update(ctx context.Context, organizationID valuer.UUID, postableSubscription *subscriptiontypes.PostableSubscription) (*subscriptiontypes.GettableSubscription, error) {
|
|
ctx, cancel := context.WithTimeout(ctx, upstreamTimeout)
|
|
defer cancel()
|
|
|
|
license, err := provider.licensing.GetActive(ctx, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
body, err := json.Marshal(postableSubscription)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, errors.TypeInvalidInput, errors.CodeInvalidInput, "failed to marshal subscription payload")
|
|
}
|
|
|
|
response, err := provider.zeus.GetPortalURL(ctx, license.Key, body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &subscriptiontypes.GettableSubscription{RedirectURL: gjson.GetBytes(response, "url").String()}, nil
|
|
}
|
|
|
|
func (provider *provider) Get(ctx context.Context, organizationID valuer.UUID) (*subscriptiontypes.GettableSubscriptionUsage, error) {
|
|
license, err := provider.licensing.GetActive(ctx, organizationID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data, err := provider.zeus.GetMeters(ctx, license.Key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
usage, err := subscriptiontypes.NewGettableSubscriptionUsage(data)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, errors.TypeInternal, zeus.ErrCodeResponseMalformed, "failed to unmarshal subscription usage")
|
|
}
|
|
|
|
return usage, nil
|
|
}
|