Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
anandrgitnirman authored and anandrgitnirman committed Oct 13, 2021
1 parent 76b67d9 commit b15b534
Show file tree
Hide file tree
Showing 8 changed files with 468 additions and 90 deletions.
7 changes: 4 additions & 3 deletions license_server/license_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (

type LicenseService interface {
GetLicenseUsage(key LicenseUsageTrackerKey) (*LicenseUsageTrackerData, bool, error)
UpdateLicenseUsage(channelId *big.Int, serviceId string, revisedUsage *big.Int, updateUsageType string, licenseType string) error
GetLicenseForChannel(key LicenseDetailsKey) (*LicenseDetailsData, bool, error)
UpdateLicenseForChannel(channelId *big.Int, serviceId string, license License) error
CreateOrUpdateLicenseUsage(channelId *big.Int, serviceId string, revisedUsage *big.Int,
updateUsageType string, licenseId string) error
GetLicenseDetailsForChannel(key LicenseDetailsKey) (*LicenseDetailsData, bool, error)
CreateOrUpdateLicenseDetails(channelId *big.Int, serviceId string, license License) error
}

type LicenseFilterCriteria struct {
Expand Down
189 changes: 189 additions & 0 deletions license_server/license_contract.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package license_server

import (
"github.com/singnet/snet-daemon/authutils"
"github.com/singnet/snet-daemon/blockchain"
"github.com/singnet/snet-daemon/escrow"
"golang.org/x/net/context"
"math/big"
"strings"
)

type LicenseContract struct {
serviceMetaData *blockchain.ServiceMetadata
orgMetaData *blockchain.OrganizationMetaData
allowedBlockNumberCheck func(blockNumber *big.Int) (err error)
service LicenseService
channelService escrow.PaymentChannelService
}

//Will be used in the components to create a new instance of LicenseService
func NewLicenseContract(
channelService escrow.PaymentChannelService, licenseService LicenseService, orgData *blockchain.OrganizationMetaData,
servMetaData *blockchain.ServiceMetadata) *LicenseContract {
return &LicenseContract{
channelService: channelService,
service: licenseService,
orgMetaData: orgData,
serviceMetaData: servMetaData,
}
}

type BlockChainDisabledLicenseContract struct {
}

func (b BlockChainDisabledLicenseContract) CreateLicense(c context.Context, request *LicenseCreateRequest) (*LicenseDataResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) CreateAddOns(c context.Context, request *AddOnCreateRequest) (*AddOnDataResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) GetLicenseForChannel(c context.Context, request *LicenseReadRequest) (*LicenseDataResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) RenewLicense(c context.Context, request *LicenseUpdateRequest) (*LicenseDataResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) CancelLicense(c context.Context, request *LicenseUpdateRequest) (*LicenseDataResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) GetAllLicensesForUser(c context.Context, authentication *CallerAuthentication) (*AllLicensesResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) GetLicensesSupportedByProvider(c context.Context, request *LicenseProviderReadRequest) (*LicenseTypesSupportedResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) GetAllLicenseByServiceIds(c context.Context, request *LicenseProviderReadRequest) (*AllLicensesResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) GetLicenseUsage(c context.Context, request *LicenseReadRequest) (*UsageResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) CheckEligibilityAndIncrementUsage(c context.Context, request *CheckLicenseUsageRequest) (*UsageResponse, error) {
return nil, nil
}

func (b BlockChainDisabledLicenseContract) DecrementUsage(c context.Context, request *CheckLicenseUsageRequest) (*UsageResponse, error) {
return nil, nil
}

func (licenseContract *LicenseContract) verifySignerForCreateLicense(request *LicenseCreateRequest) error {
return nil
}

func (licenseContract *LicenseContract) GetFixedPriceFromServiceMetadata(license License) (fixedPricingDetails ServiceMethodCostDetails, err error) {
fixedPricingDetails = ServiceMethodCostDetails{}
serviceMetadata := licenseContract.serviceMetaData
fixedPricingDetails.Price = serviceMetadata.GetDefaultPricing().PriceInCogs
fixedPricingDetails.PlanName = serviceMetadata.GetDefaultPricing().PriceModel
return
}

func (licenseContract *LicenseContract) verifyLicenseDetailsFromRequest(request *LicenseCreateRequest) (license License, err error) {
//Get the associated fixed Pricing details
fixedPricingDetails, err := licenseContract.GetFixedPriceFromServiceMetadata(license)
if err != nil {
return nil, err
}
if strings.Compare(request.GetLicenseType(), SUBSCRIPTION) == 0 {
subscription := &Subscription{}
subscription.FixedPricing = fixedPricingDetails
license = subscription
} else if strings.Compare(request.GetLicenseType(), TIER) == 0 {
tier := &Tier{}
tier.FixedPricing = fixedPricingDetails
license = tier
} else if strings.Compare(request.GetLicenseType(), ADD_ON) == 0 {
addOn := &AddOn{}
addOn.FixedPricing = fixedPricingDetails
license = addOn
} else {
return nil, nil
}

return license, nil
}

func (licenseContract *LicenseContract) CreateLicense(ctx context.Context, request *LicenseCreateRequest) (*LicenseDataResponse, error) {
//Check if the block number is within the permissible limits
if err := authutils.CompareWithLatestBlockNumber(big.NewInt(int64(request.GetAuth().GetCurrentBlock()))); err != nil {
return nil, err
}
//Check if the signer is valid
if err := licenseContract.verifySignerForCreateLicense(request); err != nil {
return nil, err
}

//Check if all license creation details are provided correctly
license, err := licenseContract.verifyLicenseDetailsFromRequest(request)
if err != nil {
return nil, err
}
channelId := big.NewInt(int64(request.GetChannelId()))
serviceId := request.ServiceId
//First persist the License Details , this is to stamp the License that was created.
//todo , for upgrade or downgrade , we need to keep track of audit trail
err = licenseContract.service.CreateOrUpdateLicenseDetails(channelId, serviceId, license)
if err != nil {
return nil, err
}
//todo , get the planned amount
licenseContract.service.CreateOrUpdateLicenseUsage(channelId, serviceId, big.NewInt(10), PLANNED, license.GetID())
return nil, nil
}
func (licenseContract *LicenseContract) CreateAddOns(context.Context, *AddOnCreateRequest) (*AddOnDataResponse, error) {
return nil, nil
}

// You need to pass the ChannelId
func (licenseContract *LicenseContract) GetLicenseForChannel(context.Context, *LicenseReadRequest) (*LicenseDataResponse, error) {
return nil, nil
}

// this is to renew the License
func (licenseContract *LicenseContract) RenewLicense(context.Context, *LicenseUpdateRequest) (*LicenseDataResponse, error) {
return nil, nil
}
func (licenseContract *LicenseContract) CancelLicense(context.Context, *LicenseUpdateRequest) (*LicenseDataResponse, error) {
return nil, nil
}

// All license_server associated with this user will be sent back
func (licenseContract *LicenseContract) GetAllLicensesForUser(context.Context, *CallerAuthentication) (*AllLicensesResponse, error) {
return nil, nil
}

// this is to only tell you the types of licenses supported by provider , we will start with subscription
// and then scale this up to Tier Pricing
func (licenseContract *LicenseContract) GetLicensesSupportedByProvider(context.Context, *LicenseProviderReadRequest) (*LicenseTypesSupportedResponse, error) {
return nil, nil
}

// filter by licenses created for given service Id
func (licenseContract *LicenseContract) GetAllLicenseByServiceIds(context.Context, *LicenseProviderReadRequest) (*AllLicensesResponse, error) {
return nil, nil
}
func (licenseContract *LicenseContract) GetLicenseUsage(context.Context, *LicenseReadRequest) (*UsageResponse, error) {
return nil, nil
}

// To Be called By Daemon ONLY, Daemons's address is listed in service metadata, this will be used by the licensing server
// to check for authorizations on Signature.
func (licenseContract *LicenseContract) CheckEligibilityAndIncrementUsage(context.Context, *CheckLicenseUsageRequest) (*UsageResponse, error) {
return nil, nil
}

// To Be called By Daemon ONLY, Daemons's address is listed in service metadata, this will be used by the licensing server
// to check for authorizations on Signature.
func (licenseContract *LicenseContract) DecrementUsage(context.Context, *CheckLicenseUsageRequest) (*UsageResponse, error) {
return nil, nil
}
65 changes: 31 additions & 34 deletions license_server/license_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,13 @@ func NewLicenseService(

func (h *LockingLicenseService) CreateLicenseDetails(channelId *big.Int, serviceId string,
license License) (err error) {
key := LicenseDetailsKey{ServiceID: serviceId, ChannelID: channelId}
//Get the associated fixed Pricing details
fixedPricingDetails, err := h.getFixedPriceFromServiceMetadata(license)
if err != nil {
return err
}
data := LicenseDetailsData{License: license, FixedPricing: fixedPricingDetails}
key := LicenseDetailsKey{ServiceID: serviceId, ChannelID: channelId, LicenseID: license.GetID()}
data := LicenseDetailsData{License: license}
return h.LicenseDetailsStorage.Put(key, data)
}

func (h *LockingLicenseService) getFixedPriceFromServiceMetadata(license License) (fixedPricingDetails ServiceMethodCostDetails, err error) {
fixedPricingDetails = ServiceMethodCostDetails{}
serviceMetadata := h.ServiceMetaData
fixedPricingDetails.Price = serviceMetadata.GetDefaultPricing().PriceInCogs
fixedPricingDetails.PlanName = serviceMetadata.GetDefaultPricing().PriceModel
return
}

func (h *LockingLicenseService) CreateOrUpdateLicense(channelId *big.Int, serviceId string) (err error) {
return h.UpdateLicenseUsage(channelId, serviceId, nil, PLANNED, SUBSCRIPTION)
return h.CreateOrUpdateLicenseUsage(channelId, serviceId, nil, PLANNED, SUBSCRIPTION)
}

func (h *LockingLicenseService) GetLicenseUsage(key LicenseUsageTrackerKey) (*LicenseUsageTrackerData, bool, error) {
Expand All @@ -61,25 +48,28 @@ func (h *LockingLicenseService) GetLicenseUsage(key LicenseUsageTrackerKey) (*Li

}

func (h *LockingLicenseService) GetLicenseForChannel(key LicenseDetailsKey) (*LicenseDetailsData, bool, error) {
func (h *LockingLicenseService) GetLicenseDetailsForChannel(key LicenseDetailsKey) (*LicenseDetailsData, bool, error) {
value, ok, err := h.LicenseDetailsStorage.Get(key)
if err != nil || !ok {
return nil, ok, err
}
return value.(*LicenseDetailsData), ok, err
}

func (h *LockingLicenseService) UpdateLicenseForChannel(channelId *big.Int, serviceId string, license License) error {
return h.LicenseDetailsStorage.Put(LicenseDetailsKey{ServiceID: serviceId, ChannelID: channelId}, &LicenseDetailsData{License: license})
func (h *LockingLicenseService) CreateOrUpdateLicenseDetails(channelId *big.Int,
serviceId string, license License) error {
return h.LicenseDetailsStorage.Put(LicenseDetailsKey{ServiceID: serviceId,
ChannelID: channelId, LicenseID: license.GetID()}, &LicenseDetailsData{License: license})
}

//Defines the condition that needs to be met, it generates the respective typed Data when
//conditions are satisfied, you define your own validations in here
//It takes in the latest typed values read.
type ConditionFuncForLicense func(conditionValues []storage.TypedKeyValueData,
incrementUsage *big.Int, channelId *big.Int, serviceId string) ([]storage.TypedKeyValueData, error)
incrementUsage *big.Int, channelId *big.Int, serviceId string, licenseId string) ([]storage.TypedKeyValueData, error)

func (h *LockingLicenseService) UpdateLicenseUsage(channelId *big.Int, serviceId string, incrementUsage *big.Int, updateUsageType string, licenseType string) error {
func (h *LockingLicenseService) CreateOrUpdateLicenseUsage(channelId *big.Int, serviceId string,
incrementUsage *big.Int, updateUsageType string, licenseId string) error {
var conditionFunc ConditionFuncForLicense = nil

switch updateUsageType {
Expand All @@ -98,12 +88,12 @@ func (h *LockingLicenseService) UpdateLicenseUsage(channelId *big.Int, serviceId

typedUpdateFunc := func(conditionValues []storage.TypedKeyValueData) (update []storage.TypedKeyValueData, ok bool, err error) {
var newValues []storage.TypedKeyValueData
if newValues, err = conditionFunc(conditionValues, incrementUsage, channelId, serviceId); err != nil {
if newValues, err = conditionFunc(conditionValues, incrementUsage, channelId, serviceId, licenseId); err != nil {
return nil, false, err
}
return newValues, true, nil
}
typedKeys := getAllLicenseKeys(channelId, serviceId)
typedKeys := getAllLicenseKeys(channelId, serviceId, licenseId)
request := storage.TypedCASRequest{
Update: typedUpdateFunc,
RetryTillSuccessOrError: true,
Expand All @@ -119,10 +109,10 @@ func (h *LockingLicenseService) UpdateLicenseUsage(channelId *big.Int, serviceId
}
return nil
}
func getAllLicenseKeys(channelId *big.Int, serviceId string) []interface{} {
func getAllLicenseKeys(channelId *big.Int, serviceId string, licenseId string) []interface{} {
keys := make([]interface{}, 3)
for i, usageType := range []string{REFUND, PLANNED, USED} {
keys[i] = LicenseUsageTrackerKey{ChannelID: channelId, ServiceID: serviceId, UsageType: usageType}
keys[i] = LicenseUsageTrackerKey{ChannelID: channelId, ServiceID: serviceId, LicenseID: licenseId, UsageType: usageType}
}
return keys
}
Expand Down Expand Up @@ -157,9 +147,9 @@ func convertTypedDataToLicenseDataUsage(data []storage.TypedKeyValueData) (new *
}

func BuildOldAndNewLicenseUsageValuesForCAS(data *LicenseUsageData) (newValues []storage.TypedKeyValueData, err error) {
updateUsageData := &LicenseUsageTrackerData{ChannelID: data.ChannelID, ServiceID: data.ServiceID}
updateUsageData := &LicenseUsageTrackerData{ChannelID: data.ChannelID, ServiceID: data.ServiceID, LicenseID: data.LicenseID}
updateUsageKey := LicenseUsageTrackerKey{ChannelID: data.ChannelID, ServiceID: data.ServiceID,
UsageType: data.UpdateUsageType}
LicenseID: data.LicenseID, UsageType: data.UpdateUsageType}
if usage, err := data.GetUsageForUsageType(); err != nil {
return nil, err
} else {
Expand All @@ -174,18 +164,21 @@ func BuildOldAndNewLicenseUsageValuesForCAS(data *LicenseUsageData) (newValues [

var (
IncrementUsedUsage ConditionFuncForLicense = func(conditionValues []storage.TypedKeyValueData, incrementUsage *big.Int,
channelId *big.Int, serviceId string) (newValues []storage.TypedKeyValueData, err error) {
channelId *big.Int, serviceId string, licenseId string) (newValues []storage.TypedKeyValueData, err error) {
oldState, err := convertTypedDataToLicenseDataUsage(conditionValues)
if err != nil {
return nil, err
}
oldState.ChannelID = channelId
oldState.ServiceID = serviceId
oldState.LicenseID = licenseId
newState := oldState.Clone()
usageKey := LicenseUsageTrackerKey{UsageType: USED, ChannelID: oldState.ChannelID, ServiceID: serviceId}
usageKey := LicenseUsageTrackerKey{UsageType: USED, ChannelID: oldState.ChannelID, ServiceID: serviceId,
LicenseID: licenseId}
if incrementUsage.Cmp(big.NewInt(0)) > 0 {
updateLicenseUsageData(newState, usageKey, incrementUsage)
if newState.Used.GetUsage().Cmp(oldState.Planned.GetUsage().Add(oldState.Planned.GetUsage(), oldState.Refund.GetUsage())) > 0 {
if newState.Used.GetUsage().Cmp(oldState.Planned.GetUsage().Add(oldState.Planned.GetUsage(),
oldState.Refund.GetUsage())) > 0 {
return nil, fmt.Errorf("usage exceeded on channel Id %v", oldState.ChannelID)
}
} else {
Expand All @@ -197,7 +190,7 @@ var (
}
//Make sure you update the planned amount ONLY when the new value is greater than what was last persisted
UpdatePlannedUsage ConditionFuncForLicense = func(conditionValues []storage.TypedKeyValueData, incrementUsage *big.Int,
channelId *big.Int, serviceId string) (newValues []storage.TypedKeyValueData, err error) {
channelId *big.Int, serviceId string, licenseId string) (newValues []storage.TypedKeyValueData, err error) {
oldState, err := convertTypedDataToLicenseDataUsage(conditionValues)
if err != nil {
return nil, err
Expand All @@ -206,22 +199,26 @@ var (
//function and pick it from there
oldState.ChannelID = channelId
oldState.ServiceID = serviceId
oldState.LicenseID = licenseId
newState := oldState.Clone()
usageKey := LicenseUsageTrackerKey{UsageType: PLANNED, ChannelID: oldState.ChannelID, ServiceID: serviceId}
usageKey := LicenseUsageTrackerKey{UsageType: PLANNED, ChannelID: oldState.ChannelID, ServiceID: serviceId,
LicenseID: licenseId}
updateLicenseUsageData(newState, usageKey, incrementUsage)
return BuildOldAndNewLicenseUsageValuesForCAS(newState)

}
//If there is no refund amount yet, put it , else add latest value in DB with the additional refund to be done
IncrementRefundUsage ConditionFuncForLicense = func(conditionValues []storage.TypedKeyValueData, incrementUsage *big.Int,
channelId *big.Int, serviceId string) (newValues []storage.TypedKeyValueData, err error) {
channelId *big.Int, serviceId string, licenseId string) (newValues []storage.TypedKeyValueData, err error) {
newState, err := convertTypedDataToLicenseDataUsage(conditionValues)
if err != nil {
return nil, err
}
newState.ChannelID = channelId
newState.ServiceID = serviceId
usageKey := LicenseUsageTrackerKey{UsageType: REFUND, ChannelID: channelId, ServiceID: serviceId}
newState.LicenseID = licenseId
usageKey := LicenseUsageTrackerKey{UsageType: REFUND, ChannelID: channelId, ServiceID: serviceId,
LicenseID: licenseId}
if incrementUsage.Cmp(big.NewInt(0)) > 0 {
updateLicenseUsageData(newState, usageKey, incrementUsage)
} else {
Expand Down
Loading

0 comments on commit b15b534

Please sign in to comment.