in frontend/pkg/frontend/middleware_validatesubscription.go [35:114]
func MiddlewareValidateSubscriptionState(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
ctx := r.Context()
logger := LoggerFromContext(ctx)
dbClient, err := DBClientFromContext(ctx)
if err != nil {
logger.Error(err.Error())
arm.WriteInternalServerError(w)
return
}
subscriptionId := r.PathValue(PathSegmentSubscriptionID)
if subscriptionId == "" {
arm.WriteError(
w, http.StatusBadRequest,
arm.CloudErrorCodeInvalidParameter, "",
SubscriptionMissingMessage,
PathSegmentSubscriptionID)
return
}
// TODO: Ideally, we don't want to have to hit the database in this middleware
// Currently, we are using the database to retrieve the subscription's tenantID and state
subscription, err := dbClient.GetSubscriptionDoc(ctx, subscriptionId)
if err != nil {
arm.WriteError(
w, http.StatusBadRequest,
arm.CloudErrorCodeInvalidSubscriptionState, "",
UnregisteredSubscriptionStateMessage,
subscriptionId)
return
}
// For subscription-scoped requests, ARM will provide the tenant ID
// in a "x-ms-home-tenant-id" header. But in test environments this
// header may not be present, in which case we can try to fudge it
// from the SubscriptionDocument.
if r.Header.Get(arm.HeaderNameHomeTenantID) == "" {
if subscription.Properties != nil &&
subscription.Properties.TenantId != nil {
r.Header.Set(
arm.HeaderNameHomeTenantID,
*subscription.Properties.TenantId)
}
}
span := trace.SpanFromContext(ctx)
span.SetAttributes(
tracing.SubscriptionStateKey.String(string(subscription.State)),
)
switch subscription.State {
case arm.SubscriptionStateRegistered:
next(w, r)
case arm.SubscriptionStateUnregistered:
arm.WriteError(
w, http.StatusBadRequest,
arm.CloudErrorCodeInvalidSubscriptionState, "",
UnregisteredSubscriptionStateMessage,
subscriptionId)
case arm.SubscriptionStateWarned, arm.SubscriptionStateSuspended:
if r.Method != http.MethodGet && r.Method != http.MethodDelete {
arm.WriteError(w, http.StatusConflict,
arm.CloudErrorCodeInvalidSubscriptionState, "",
InvalidSubscriptionStateMessage,
subscription.State)
return
}
next(w, r)
case arm.SubscriptionStateDeleted:
arm.WriteError(
w, http.StatusBadRequest,
arm.CloudErrorCodeInvalidSubscriptionState, "",
InvalidSubscriptionStateMessage,
subscription.State)
default:
logger.Error(fmt.Sprintf("unsupported subscription state %q", subscription.State))
arm.WriteInternalServerError(w)
}
}