Backend: add Subscription CRUD

This commit is contained in:
Alex
2025-02-12 20:30:59 +01:00
parent 8787c8c2c1
commit 743493517b
8 changed files with 345 additions and 21 deletions

View File

@@ -84,10 +84,9 @@ func (mc *MembershipController) UpdateHandler(c *gin.Context) {
return
}
// Register Subscription
logger.Info.Printf("Registering subscription %v", regData.Subscription.Name)
// id, err := mc.Service.UpdateSubscription(&regData.Subscription)
id := 1
// update Subscription
logger.Info.Printf("Updating subscription %v", regData.Subscription.Name)
id, err := mc.Service.UpdateSubscription(&regData.Subscription)
if err != nil {
logger.Error.Printf("Couldn't update Membershipmodel: %v", err)
if strings.Contains(err.Error(), "UNIQUE constraint failed") {
@@ -103,6 +102,33 @@ func (mc *MembershipController) UpdateHandler(c *gin.Context) {
"id": id,
})
}
func (mc *MembershipController) DeleteSubscription(c *gin.Context) {
var membershipdata MembershipData
requestUser, err := mc.UserController.ExtractUserFromContext(c)
if err != nil {
utils.RespondWithError(c, err, "Error extracting user from context in subscription UpdateHandler", http.StatusBadRequest, "general", "server.validation.no_auth_tokenw")
return
}
if !utils.HasPrivilige(requestUser, constants.Priviliges.Update) {
utils.RespondWithError(c, errors.ErrNotAuthorized, "Not allowed to update subscription", http.StatusForbidden, "user", "server.error.unauthorized")
return
}
if err := c.ShouldBindJSON(&membershipdata); err != nil {
utils.HandleValidationError(c, err)
return
}
if err := mc.Service.DeleteSubscription(&membershipdata.Subscription); err != nil {
utils.RespondWithError(c, err, "Error during subscription Deletion", http.StatusExpectationFailed, "subscription", "server.error.not_possible")
return
}
c.JSON(http.StatusOK, gin.H{"message": "Subscription deleted successfully"})
}
func (mc *MembershipController) GetSubscriptions(c *gin.Context) {
subscriptions, err := mc.Service.GetSubscriptions(nil)
if err != nil {

View File

@@ -21,6 +21,22 @@ type RegisterSubscriptionTest struct {
Assert bool
}
type UpdateSubscriptionTest struct {
WantDBData map[string]interface{}
Input string
Name string
WantResponse int
Assert bool
}
type DeleteSubscriptionTest struct {
WantDBData map[string]interface{}
Input string
Name string
WantResponse int
Assert bool
}
type MockUserController struct {
UserController // Embed the UserController
}
@@ -44,7 +60,7 @@ func setupMockAuth() {
func testMembershipController(t *testing.T) {
setupMockAuth()
tests := getSubscriptionData()
tests := getSubscriptionRegistrationData()
for _, tt := range tests {
logger.Error.Print("==============================================================")
logger.Error.Printf("MembershipController : %v", tt.Name)
@@ -55,6 +71,28 @@ func testMembershipController(t *testing.T) {
}
})
}
updateTests := getSubscriptionUpdateData()
for _, tt := range updateTests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Update SubscriptionData : %v", tt.Name)
logger.Error.Print("==============================================================")
t.Run(tt.Name, func(t *testing.T) {
if err := runSingleTest(&tt); err != nil {
t.Errorf("Test failed: %v", err.Error())
}
})
}
deleteTests := getSubscriptionDeleteData()
for _, tt := range deleteTests {
logger.Error.Print("==============================================================")
logger.Error.Printf("Delete SubscriptionData : %v", tt.Name)
logger.Error.Print("==============================================================")
t.Run(tt.Name, func(t *testing.T) {
if err := runSingleTest(&tt); err != nil {
t.Errorf("Test failed: %v", err.Error())
}
})
}
}
func (rt *RegisterSubscriptionTest) SetupContext() (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) {
@@ -87,6 +125,44 @@ func validateSubscription(assert bool, wantDBData map[string]interface{}) error
return nil
}
func (ut *UpdateSubscriptionTest) SetupContext() (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) {
return GetMockedJSONContext([]byte(ut.Input), "api/subscription/upsert")
}
func (ut *UpdateSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) {
Mc.UpdateHandler(c)
}
func (ut *UpdateSubscriptionTest) ValidateResponse(w *httptest.ResponseRecorder) error {
if w.Code != ut.WantResponse {
return fmt.Errorf("Didn't get the expected response code: got: %v; expected: %v", w.Code, ut.WantResponse)
}
return nil
}
func (ut *UpdateSubscriptionTest) ValidateResult() error {
return validateSubscription(ut.Assert, ut.WantDBData)
}
func (dt *DeleteSubscriptionTest) SetupContext() (*gin.Context, *httptest.ResponseRecorder, *gin.Engine) {
return GetMockedJSONContext([]byte(dt.Input), "api/subscription/delete")
}
func (dt *DeleteSubscriptionTest) RunHandler(c *gin.Context, router *gin.Engine) {
Mc.DeleteSubscription(c)
}
func (dt *DeleteSubscriptionTest) ValidateResponse(w *httptest.ResponseRecorder) error {
if w.Code != dt.WantResponse {
return fmt.Errorf("Didn't get the expected response code: got: %v; expected: %v", w.Code, dt.WantResponse)
}
return nil
}
func (dt *DeleteSubscriptionTest) ValidateResult() error {
return validateSubscription(dt.Assert, dt.WantDBData)
}
func getBaseSubscription() MembershipData {
return MembershipData{
// APIKey: config.Auth.APIKEY,
@@ -103,7 +179,7 @@ func customizeSubscription(customize func(MembershipData) MembershipData) Member
return customize(subscription)
}
func getSubscriptionData() []RegisterSubscriptionTest {
func getSubscriptionRegistrationData() []RegisterSubscriptionTest {
return []RegisterSubscriptionTest{
{
Name: "Missing details should fail",
@@ -169,3 +245,137 @@ func getSubscriptionData() []RegisterSubscriptionTest {
},
}
}
func getSubscriptionUpdateData() []UpdateSubscriptionTest {
return []UpdateSubscriptionTest{
{
Name: "Modified Monthly Fee, should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"name": "Premium", "monthly_fee": "12"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.MonthlyFee = 123.0
return subscription
})),
},
{
Name: "Missing ID, should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"name": "Premium"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.ID = 0
return subscription
})),
},
{
Name: "Modified Hourly Rate, should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"name": "Premium", "hourly_rate": "14"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.HourlyRate = 3254.0
return subscription
})),
},
{
Name: "IncludedPerYear changed, should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"name": "Premium", "included_per_year": "0"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.IncludedPerYear = 9873.0
return subscription
})),
},
{
Name: "IncludedPerMonth changed, should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"name": "Premium", "included_per_month": "1"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.IncludedPerMonth = 23415.0
return subscription
})),
},
{
Name: "Update non-existent subscription should fail",
WantResponse: http.StatusNotAcceptable,
WantDBData: map[string]interface{}{"name": "NonExistentSubscription"},
Assert: false,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Name = "NonExistentSubscription"
return subscription
})),
},
{
Name: "Correct Update should pass",
WantResponse: http.StatusAccepted,
WantDBData: map[string]interface{}{"name": "Premium", "details": "Altered Details"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Details = "Altered Details"
subscription.Subscription.Conditions = "Some Condition"
subscription.Subscription.IncludedPerYear = 0
subscription.Subscription.IncludedPerMonth = 1
return subscription
})),
},
}
}
func getSubscriptionDeleteData() []DeleteSubscriptionTest {
return []DeleteSubscriptionTest{
{
Name: "Delete non-existent subscription should fail",
WantResponse: http.StatusExpectationFailed,
WantDBData: map[string]interface{}{"name": "NonExistentSubscription"},
Assert: false,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Name = "NonExistentSubscription"
return subscription
})),
},
{
Name: "Delete subscription without name should fail",
WantResponse: http.StatusBadRequest,
WantDBData: map[string]interface{}{"name": ""},
Assert: false,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Name = ""
return subscription
})),
},
{
Name: "Delete subscription with users should fail",
WantResponse: http.StatusExpectationFailed,
WantDBData: map[string]interface{}{"name": "Basic"},
Assert: true,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Name = "Basic"
return subscription
})),
},
{
Name: "Delete valid subscription should succeed",
WantResponse: http.StatusOK,
WantDBData: map[string]interface{}{"name": "Premium"},
Assert: false,
Input: GenerateInputJSON(
customizeSubscription(func(subscription MembershipData) MembershipData {
subscription.Subscription.Name = "Premium"
return subscription
})),
},
}
}

View File

@@ -212,7 +212,7 @@ func (uc *UserController) RegisterUser(c *gin.Context) {
}
logger.Info.Printf("Registering user %v", regData.User.Email)
selectedModel, err := uc.MembershipService.GetModelByName(&regData.User.Membership.SubscriptionModel.Name)
selectedModel, err := uc.MembershipService.GetSubscriptionByName(&regData.User.Membership.SubscriptionModel.Name)
if err != nil {
utils.RespondWithError(c, err, "Error in Registeruser, couldn't get selected model", http.StatusNotFound, "subscription_model", "server.validation.subscription_model_not_found")
return