Skip to content

Commit

Permalink
feat: entitlements list API (#1051)
Browse files Browse the repository at this point in the history
* feat: entitlements list API

* fix: expose handlers through openmeter

* chore: remove misformatted comments

* fix: fix api example
  • Loading branch information
GAlexIHU authored Jun 24, 2024
1 parent e26d642 commit 2bf475c
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 383 deletions.
351 changes: 171 additions & 180 deletions api/api.gen.go

Large diffs are not rendered by default.

351 changes: 171 additions & 180 deletions api/client/go/client.gen.go

Large diffs are not rendered by default.

17 changes: 1 addition & 16 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1192,11 +1192,10 @@ components:
example: "2023-01-01T00:00:00Z"
deletedAt:
type: string
nullable: true
format: date-time
description: The date and time the resource was deleted.
readOnly: true
example: null
example: "2023-01-01T00:00:00Z"
ConflictProblem:
description: Conflict
type: object
Expand Down Expand Up @@ -1734,25 +1733,11 @@ components:
List of pre-defined periods that can be used for recurring & scheduling.
DAY: Every day
# MONDAY: Every Monday
# TUESDAY: Every Tuesday
# WEDNESDAY: Every Wednesday
# THURSDAY: Every Thursday
# FRIDAY: Every Friday
# SATURDAY: Every Saturday
# SUNDAY: Every Sunday
WEEK: Every week
MONTH: Every month
YEAR: Every year
enum:
- DAY
# - MONDAY
# - TUESDAY
# - WEDNESDAY
# - THURSDAY
# - FRIDAY
# - SATURDAY
# - SUNDAY
- WEEK
- MONTH
- YEAR
Expand Down
2 changes: 2 additions & 0 deletions internal/entitlement/db_connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type EntitlementRepo interface {
CreateEntitlement(ctx context.Context, entitlement EntitlementRepoCreateEntitlementInputs) (*Entitlement, error)
GetEntitlement(ctx context.Context, entitlementID models.NamespacedID) (*Entitlement, error)

ListEntitlements(ctx context.Context, params ListEntitlementsParams) ([]Entitlement, error)

//FIXME: This is a terrbile hack
LockEntitlementForTx(ctx context.Context, entitlementID models.NamespacedID) error

Expand Down
20 changes: 20 additions & 0 deletions internal/entitlement/entitlement_connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,27 @@ import (
"github.com/openmeterio/openmeter/pkg/models"
)

type ListEntitlementsOrderBy string

const (
ListEntitlementsOrderByCreatedAt ListEntitlementsOrderBy = "created_at"
ListEntitlementsOrderByUpdatedAt ListEntitlementsOrderBy = "updated_at"
)

type ListEntitlementsParams struct {
Namespace string
Limit int
Offset int
OrderBy ListEntitlementsOrderBy
}

type EntitlementConnector interface {
// Entitlement Management
CreateEntitlement(ctx context.Context, input CreateEntitlementInputs) (Entitlement, error)
GetEntitlementsOfSubject(ctx context.Context, namespace string, subjectKey models.SubjectKey) ([]Entitlement, error)
GetEntitlementValue(ctx context.Context, entitlementId models.NamespacedID, at time.Time) (EntitlementValue, error)

ListEntitlements(ctx context.Context, params ListEntitlementsParams) ([]Entitlement, error)
}

type entitlementConnector struct {
Expand Down Expand Up @@ -78,3 +94,7 @@ func (c *entitlementConnector) GetEntitlementValue(ctx context.Context, entitlem
Overage: balance.Overage,
}, nil
}

func (c *entitlementConnector) ListEntitlements(ctx context.Context, params ListEntitlementsParams) ([]Entitlement, error) {
return c.entitlementRepo.ListEntitlements(ctx, params)
}
64 changes: 64 additions & 0 deletions internal/entitlement/httpdriver/entitlement.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type EntitlementHandler interface {
CreateEntitlement() CreateEntitlementHandler
GetEntitlementValue() GetEntitlementValueHandler
GetEntitlementsOfSubjectHandler() GetEntitlementsOfSubjectHandler
ListEntitlements() ListEntitlementsHandler
}

type entitlementHandler struct {
Expand Down Expand Up @@ -244,6 +245,69 @@ func (h *entitlementHandler) GetEntitlementsOfSubjectHandler() GetEntitlementsOf
)
}

type ListEntitlementsHandlerRequest = entitlement.ListEntitlementsParams
type ListEntitlementsHandlerResponse = []APIEntitlementResponse
type ListEntitlementsHandlerParams = api.ListEntitlementsParams

type ListEntitlementsHandler httptransport.HandlerWithArgs[ListEntitlementsHandlerRequest, ListEntitlementsHandlerResponse, ListEntitlementsHandlerParams]

func (h *entitlementHandler) ListEntitlements() ListEntitlementsHandler {
return httptransport.NewHandlerWithArgs(
func(ctx context.Context, r *http.Request, params ListEntitlementsHandlerParams) (entitlement.ListEntitlementsParams, error) {
ns, err := h.resolveNamespace(ctx)
if err != nil {
return entitlement.ListEntitlementsParams{}, err
}

p := entitlement.ListEntitlementsParams{
Namespace: ns,
Limit: defaultx.WithDefault(params.Limit, 1000),
Offset: defaultx.WithDefault(params.Offset, 0),
}

switch defaultx.WithDefault(params.OrderBy, "") {
case "createdAt":
p.OrderBy = entitlement.ListEntitlementsOrderByCreatedAt
case "updatedAt":
p.OrderBy = entitlement.ListEntitlementsOrderByUpdatedAt
default:
p.OrderBy = entitlement.ListEntitlementsOrderByCreatedAt
}

return p, nil
},
func(ctx context.Context, request ListEntitlementsHandlerRequest) ([]APIEntitlementResponse, error) {
entitlements, err := h.connector.ListEntitlements(ctx, request)
if err != nil {
return nil, err
}

res := make([]APIEntitlementResponse, len(entitlements))
for i, ent := range entitlements {
res[i] = APIEntitlementResponse{
EntitlementMetered: api.EntitlementMetered{
Id: &ent.ID,
FeatureId: ent.FeatureID,
CreatedAt: &ent.CreatedAt,
UpdatedAt: &ent.UpdatedAt,
DeletedAt: ent.DeletedAt,
SubjectKey: ent.SubjectKey,
Type: "metered",
},
UsagePeriod: nil,
}
}

return res, nil
},
commonhttp.JSONResponseEncoder[[]APIEntitlementResponse],
httptransport.AppendOptions(
h.options,
httptransport.WithOperationName("listEntitlements"),
)...,
)
}

func (h *entitlementHandler) resolveNamespace(ctx context.Context) (string, error) {
ns, ok := h.namespaceDecoder.GetNamespace(ctx)
if !ok {
Expand Down
32 changes: 32 additions & 0 deletions internal/entitlement/postgresadapter/entitlement.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,38 @@ func (a *entitlementDBAdapter) GetEntitlementsOfSubject(ctx context.Context, nam

}

func (a *entitlementDBAdapter) ListEntitlements(ctx context.Context, params entitlement.ListEntitlementsParams) ([]entitlement.Entitlement, error) {
query := a.db.Entitlement.Query().
Where(db_entitlement.Namespace(params.Namespace))

if params.Limit > 0 {
query = query.Limit(params.Limit)
}
if params.Offset > 0 {
query = query.Offset(params.Offset)
}

switch params.OrderBy {
case entitlement.ListEntitlementsOrderByCreatedAt:
query = query.Order(db_entitlement.ByCreatedAt())
case entitlement.ListEntitlementsOrderByUpdatedAt:
query = query.Order(db_entitlement.ByUpdatedAt())
}

entities, err := query.All(ctx)
if err != nil {
return nil, err
}

result := make([]entitlement.Entitlement, 0, len(entities))
for _, e := range entities {
result = append(result, *mapEntitlementEntity(e))
}

return result, nil

}

func mapEntitlementEntity(e *db.Entitlement) *entitlement.Entitlement {
return &entitlement.Entitlement{
NamespacedModel: models.NamespacedModel{
Expand Down
10 changes: 10 additions & 0 deletions internal/server/router/entitlement.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,13 @@ func (a *Router) GetEntitlementHistory(w http.ResponseWriter, r *http.Request, s
Params: params,
}).ServeHTTP(w, r)
}

// List entitlements
// (GET /api/v1/entitlements)
func (a *Router) ListEntitlements(w http.ResponseWriter, r *http.Request, params api.ListEntitlementsParams) {
if !a.config.EntitlementsEnabled {
unimplemented.ListEntitlements(w, r, params)
return
}
a.entitlementHandler.ListEntitlements().With(params).ServeHTTP(w, r)
}
6 changes: 0 additions & 6 deletions internal/server/router/noop.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@ import (

var unimplemented api.ServerInterface = api.Unimplemented{}

// List entitlements
// (GET /api/v1/entitlements)
func (a *Router) ListEntitlements(w http.ResponseWriter, r *http.Request, params api.ListEntitlementsParams) {
commonhttp.NewHTTPError(http.StatusNotImplemented, fmt.Errorf("not implemented")).EncodeError(context.TODO(), w)
}

// Delete entitlement
// (DELETE /api/v1/subjects/{subjectIdOrKey}/entitlements/{entitlementId})
func (a *Router) DeleteEntitlement(w http.ResponseWriter, r *http.Request, subjectIdOrKey api.SubjectIdOrKey, entitlementId api.EntitlementId) {
Expand Down
1 change: 1 addition & 0 deletions openmeter/entitlement/httpdriver/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type GetEntitlementValueHandler = httpdriver.GetEntitlementValueHandler
type GetEntitlementsOfSubjectHandler = httpdriver.GetEntitlementsOfSubjectHandler
type ListEntitlementGrantsHandler = httpdriver.ListEntitlementGrantsHandler
type ResetEntitlementUsageHandler = httpdriver.ResetEntitlementUsageHandler
type ListEntitlementsHandler = httpdriver.ListEntitlementsHandler

func NewEntitlementHandler(
connector entitlement.EntitlementConnector,
Expand Down
3 changes: 3 additions & 0 deletions openmeter/entitlement/httpdriver/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type GetEntitlementValueHandlerRequest = httpdriver.GetEntitlementValueHandlerRe
type GetEntitlementsOfSubjectHandlerRequest = httpdriver.GetEntitlementsOfSubjectHandlerRequest
type ListEntitlementGrantHandlerRequest = httpdriver.ListEntitlementGrantHandlerRequest
type ResetEntitlementUsageHandlerRequest = httpdriver.ResetEntitlementUsageHandlerRequest
type ListEntitlementsHandlerRequest = httpdriver.ListEntitlementsHandlerRequest

// responses
type CreateEntitlementHandlerResponse = httpdriver.CreateEntitlementHandlerResponse
Expand All @@ -19,6 +20,7 @@ type GetEntitlementValueHandlerResponse = httpdriver.GetEntitlementValueHandlerR
type GetEntitlementsOfSubjectHandlerResponse = httpdriver.GetEntitlementsOfSubjectHandlerResponse
type ListEntitlementGrantHandlerResponse = httpdriver.ListEntitlementGrantHandlerResponse
type ResetEntitlementUsageHandlerResponse = httpdriver.ResetEntitlementUsageHandlerResponse
type ListEntitlementsHandlerResponse = httpdriver.ListEntitlementsHandlerResponse

// params
type CreateEntitlementHandlerParams = httpdriver.CreateEntitlementHandlerParams
Expand All @@ -28,3 +30,4 @@ type GetEntitlementValueHandlerParams = httpdriver.GetEntitlementValueHandlerPar
type GetEntitlementsOfSubjectHandlerParams = httpdriver.GetEntitlementsOfSubjectHandlerParams
type ListEntitlementGrantsHandlerParams = httpdriver.ListEntitlementGrantsHandlerParams
type ResetEntitlementUsageHandlerParams = httpdriver.ResetEntitlementUsageHandlerParams
type ListEntitlementsHandlerParams = httpdriver.ListEntitlementsHandlerParams
2 changes: 1 addition & 1 deletion pkg/models/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type ManagedModel struct {
// After creation the entity is considered updated.
UpdatedAt time.Time `json:"updatedAt"`
// Time of soft delete. If not null, the entity is considered deleted.
DeletedAt *time.Time `json:"deletedAt"`
DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

type NamespacedModel struct {
Expand Down

0 comments on commit 2bf475c

Please sign in to comment.