Skip to content

Commit

Permalink
Merge pull request #304 from gobitfly/BIDS-3049/stripe-integration
Browse files Browse the repository at this point in the history
api: add structs for products and userinfo
  • Loading branch information
guybrush authored May 15, 2024
2 parents 605dd45 + 377a3a7 commit f895ded
Show file tree
Hide file tree
Showing 10 changed files with 515 additions and 33 deletions.
9 changes: 7 additions & 2 deletions backend/pkg/api/data_access/data_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,14 @@ type DataAccessor interface {

GetLatestSlot() (uint64, error)
GetLatestExchangeRates() ([]t.EthConversionRate, error)
GetValidatorsFromSlices(indices []uint64, publicKeys []string) ([]t.VDBValidator, error)

GetProductSummary() (*t.ProductSummary, error)
// TODO: move to user repository
GetUserInfo(email string) (*t.User, error)
GetUser(email string) (*t.User, error)

GetValidatorsFromSlices(indices []uint64, publicKeys []string) ([]t.VDBValidator, error)

GetUserInfo(id uint64) (*t.UserInfo, error)
GetUserDashboards(userId uint64) (*t.UserDashboardsData, error)
}

Expand Down
14 changes: 13 additions & 1 deletion backend/pkg/api/data_access/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,24 @@ func (d *DummyService) GetLatestExchangeRates() ([]t.EthConversionRate, error) {
return r, err
}

func (d *DummyService) GetUserInfo(email string) (*t.User, error) {
func (d *DummyService) GetUserInfo(userId uint64) (*t.UserInfo, error) {
r := t.UserInfo{}
err := commonFakeData(&r)
return &r, err
}

func (d *DummyService) GetUser(email string) (*t.User, error) {
r := t.User{}
err := commonFakeData(&r)
return &r, err
}

func (d *DummyService) GetProductSummary() (*t.ProductSummary, error) {
r := t.ProductSummary{}
err := commonFakeData(&r)
return &r, err
}

func (d *DummyService) GetValidatorDashboardInfo(dashboardId t.VDBIdPrimary) (*t.DashboardInfo, error) {
r := t.DashboardInfo{}
err := commonFakeData(&r)
Expand Down
287 changes: 287 additions & 0 deletions backend/pkg/api/data_access/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
package dataaccess

import (
"database/sql"
"fmt"

t "github.com/gobitfly/beaconchain/pkg/api/types"
"github.com/pkg/errors"
)

func (d *DataAccessService) GetUser(email string) (*t.User, error) {
// TODO @recy21
result := &t.User{}
err := d.userReader.Get(result, `
WITH
latest_and_greatest_sub AS (
SELECT user_id, product_id FROM users_app_subscriptions
left join users on users.id = user_id
WHERE users.email = $1 AND active = true
ORDER BY CASE product_id
WHEN 'whale' THEN 1
WHEN 'goldfish' THEN 2
WHEN 'plankton' THEN 3
ELSE 4 -- For any other product_id values
END, users_app_subscriptions.created_at DESC LIMIT 1
)
SELECT users.id as id, password, COALESCE(product_id, '') as product_id, COALESCE(user_group, '') AS user_group
FROM users
left join latest_and_greatest_sub on latest_and_greatest_sub.user_id = users.id
WHERE email = $1`, email)
if errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("%w: user with email %s not found", ErrNotFound, email)
}
return result, err
}

func (d *DataAccessService) GetUserInfo(id uint64) (*t.UserInfo, error) {
// TODO patrick
// return d.dummy.GetUserInfo(id)
return &t.UserInfo{
Id: id,
Email: "[email protected]",
ApiKeys: []string{"dummykey1", "dummykey1"},
ApiPerks: t.ApiPerks{
UnitsPerSecond: 10,
UnitsPerMonth: 10,
ApiKeys: 4,
ConsensusLayerAPI: true,
ExecutionLayerAPI: true,
Layer2API: true,
NoAds: true,
DiscordSuport: false,
},
PremiumPerks: t.PremiumPerks{
AdFree: true,
ValidatorDasboards: 2,
ValidatorsPerDashboard: 1000,
ValidatorGroupsPerDashboard: 30,
ShareCustomDashboards: true,
ManageDashboardViaApi: true,
HeatmapHistorySeconds: 3600 * 24 * 365,
SummaryChartHistorySeconds: 3600 * 24 * 365,
EmailNotificationsPerDay: 50,
ConfigureNotificationsViaApi: true,
ValidatorGroupNotifications: 60,
WebhookEndpoints: 30,
MobileAppCustomThemes: true,
MobileAppWidget: true,
MonitorMachines: 10,
MachineMonitoringHistorySeconds: 3600 * 24 * 30,
CustomMachineAlerts: true,
},
Subscriptions: []t.UserSubscription{
{
ProductId: "orca",
ProductName: "Orca",
ProductCategory: t.ProductCategoryPremium,
Start: 1715768109,
End: 1718446509,
},
{
ProductId: "1k_extra_valis_per_dasboard",
ProductName: "+1000 Validators per Dasboard",
ProductCategory: t.ProductCategoryPremiumAddon,
Start: 1715768109,
End: 1718446509,
},
{
ProductId: "10k_extra_valis_per_dasboard",
ProductName: "+10,000 Validators per Dasboard",
ProductCategory: t.ProductCategoryPremiumAddon,
Start: 1715768109,
End: 1718446509,
},
},
}, nil
}

func (d *DataAccessService) GetProductSummary() (*t.ProductSummary, error) {
// TODO patrick
return &t.ProductSummary{
ApiProducts: []t.ApiProduct{
{
ProductId: "api_free",
ProductName: "Free",
PricePerMonthEur: 0,
PricePerYearEur: 0 * 12 * 0.9,
ApiPerks: t.ApiPerks{
UnitsPerSecond: 10,
UnitsPerMonth: 10_000_000,
ApiKeys: 2,
ConsensusLayerAPI: true,
ExecutionLayerAPI: true,
Layer2API: true,
NoAds: true,
DiscordSuport: false,
},
},
{
ProductId: "api_iron",
ProductName: "Iron",
PricePerMonthEur: 1.99,
PricePerYearEur: 1.99 * 12 * 0.9,
ApiPerks: t.ApiPerks{
UnitsPerSecond: 20,
UnitsPerMonth: 20_000_000,
ApiKeys: 10,
ConsensusLayerAPI: true,
ExecutionLayerAPI: true,
Layer2API: true,
NoAds: true,
DiscordSuport: false,
},
},
{
ProductId: "api_siler",
ProductName: "Silver",
PricePerMonthEur: 2.99,
PricePerYearEur: 2.99 * 12 * 0.9,
ApiPerks: t.ApiPerks{
UnitsPerSecond: 30,
UnitsPerMonth: 100_000_000,
ApiKeys: 20,
ConsensusLayerAPI: true,
ExecutionLayerAPI: true,
Layer2API: true,
NoAds: true,
DiscordSuport: false,
},
},
{
ProductId: "api_gold",
ProductName: "Gold",
PricePerMonthEur: 3.99,
PricePerYearEur: 3.99 * 12 * 0.9,
ApiPerks: t.ApiPerks{
UnitsPerSecond: 40,
UnitsPerMonth: 200_000_000,
ApiKeys: 40,
ConsensusLayerAPI: true,
ExecutionLayerAPI: true,
Layer2API: true,
NoAds: true,
DiscordSuport: false,
},
},
},
PremiumProducts: []t.PremiumProduct{
{
ProductId: "premium_free",
ProductName: "Free",
PremiumPerks: t.PremiumPerks{
AdFree: false,
ValidatorDasboards: 1,
ValidatorsPerDashboard: 20,
ValidatorGroupsPerDashboard: 1,
ShareCustomDashboards: false,
ManageDashboardViaApi: false,
HeatmapHistorySeconds: 0,
SummaryChartHistorySeconds: 3600 * 12,
EmailNotificationsPerDay: 5,
ConfigureNotificationsViaApi: false,
ValidatorGroupNotifications: 1,
WebhookEndpoints: 1,
MobileAppCustomThemes: false,
MobileAppWidget: false,
MonitorMachines: 1,
MachineMonitoringHistorySeconds: 3600 * 3,
CustomMachineAlerts: false,
},
PricePerMonthEur: 0,
PricePerYearEur: 0 * 12 * 0.9,
},
{
ProductId: "guppy",
ProductName: "Guppy",
PremiumPerks: t.PremiumPerks{
AdFree: true,
ValidatorDasboards: 1,
ValidatorsPerDashboard: 100,
ValidatorGroupsPerDashboard: 3,
ShareCustomDashboards: true,
ManageDashboardViaApi: false,
HeatmapHistorySeconds: 3600 * 24 * 7,
SummaryChartHistorySeconds: 3600 * 24 * 7,
EmailNotificationsPerDay: 15,
ConfigureNotificationsViaApi: false,
ValidatorGroupNotifications: 3,
WebhookEndpoints: 3,
MobileAppCustomThemes: true,
MobileAppWidget: true,
MonitorMachines: 2,
MachineMonitoringHistorySeconds: 3600 * 30,
CustomMachineAlerts: true,
},
PricePerMonthEur: 9.99,
PricePerYearEur: 9.99 * 12 * 0.9,
},
{
ProductId: "dolphin",
ProductName: "Dolphin",
PremiumPerks: t.PremiumPerks{
AdFree: true,
ValidatorDasboards: 1,
ValidatorsPerDashboard: 300,
ValidatorGroupsPerDashboard: 10,
ShareCustomDashboards: true,
ManageDashboardViaApi: false,
HeatmapHistorySeconds: 3600 * 24 * 30,
SummaryChartHistorySeconds: 3600 * 24 * 14,
EmailNotificationsPerDay: 20,
ConfigureNotificationsViaApi: false,
ValidatorGroupNotifications: 10,
WebhookEndpoints: 10,
MobileAppCustomThemes: false,
MobileAppWidget: false,
MonitorMachines: 10,
MachineMonitoringHistorySeconds: 3600 * 24 * 30,
CustomMachineAlerts: true,
},
PricePerMonthEur: 29.99,
PricePerYearEur: 29.99 * 12 * 0.9,
},
{
ProductId: "orca",
ProductName: "Orca",
PremiumPerks: t.PremiumPerks{
AdFree: true,
ValidatorDasboards: 2,
ValidatorsPerDashboard: 1000,
ValidatorGroupsPerDashboard: 30,
ShareCustomDashboards: true,
ManageDashboardViaApi: true,
HeatmapHistorySeconds: 3600 * 24 * 365,
SummaryChartHistorySeconds: 3600 * 24 * 365,
EmailNotificationsPerDay: 50,
ConfigureNotificationsViaApi: true,
ValidatorGroupNotifications: 60,
WebhookEndpoints: 30,
MobileAppCustomThemes: true,
MobileAppWidget: true,
MonitorMachines: 10,
MachineMonitoringHistorySeconds: 3600 * 24 * 30,
CustomMachineAlerts: true,
},
PricePerMonthEur: 49.99,
PricePerYearEur: 49.99 * 12 * 0.9,
},
},
ExtraDashboardValidatorsPremiumAddon: []t.ExtraDashboardValidatorsPremiumAddon{
{
ProductId: "1k_extra_valis_per_dasboard",
ProductName: "+1000 Validators per Dasboard",
ExtraDashboardValidators: 1000,
PricePerMonthEur: 9.99,
PricePerYearEur: 9.99 * 12 * 0.9,
},
{
ProductId: "10k_extra_valis_per_dasboard",
ProductName: "+10,000 Validators per Dasboard",
ExtraDashboardValidators: 10000,
PricePerMonthEur: 15.99,
PricePerYearEur: 15.99 * 12 * 0.9,
},
},
}, nil
}
26 changes: 0 additions & 26 deletions backend/pkg/api/data_access/vdb_management.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,6 @@ import (
"golang.org/x/sync/errgroup"
)

func (d *DataAccessService) GetUserInfo(email string) (*t.User, error) {
// TODO @recy21
result := &t.User{}
err := d.userReader.Get(result, `
WITH
latest_and_greatest_sub AS (
SELECT user_id, product_id FROM users_app_subscriptions
left join users on users.id = user_id
WHERE users.email = $1 AND active = true
ORDER BY CASE product_id
WHEN 'whale' THEN 1
WHEN 'goldfish' THEN 2
WHEN 'plankton' THEN 3
ELSE 4 -- For any other product_id values
END, users_app_subscriptions.created_at DESC LIMIT 1
)
SELECT users.id as id, password, COALESCE(product_id, '') as product_id, COALESCE(user_group, '') AS user_group
FROM users
left join latest_and_greatest_sub on latest_and_greatest_sub.user_id = users.id
WHERE email = $1`, email)
if errors.Is(err, sql.ErrNoRows) {
return nil, fmt.Errorf("%w: user with email %s not found", ErrNotFound, email)
}
return result, err
}

func (d *DataAccessService) GetValidatorDashboardInfo(dashboardId t.VDBIdPrimary) (*t.DashboardInfo, error) {
result := &t.DashboardInfo{}

Expand Down
2 changes: 1 addition & 1 deletion backend/pkg/api/handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (h *HandlerService) InternalPostLogin(w http.ResponseWriter, r *http.Reques

badCredentialsErr := newUnauthorizedErr("invalid email or password")
// fetch user
user, err := h.dai.GetUserInfo(email)
user, err := h.dai.GetUser(email)
if err != nil {
if errors.Is(err, dataaccess.ErrNotFound) {
err = badCredentialsErr
Expand Down
Loading

0 comments on commit f895ded

Please sign in to comment.