diff --git a/docs/openapi.json b/docs/openapi.json index 8a8a7c7..b9e1d54 100644 --- a/docs/openapi.json +++ b/docs/openapi.json @@ -1 +1 @@ -{"openapi":"3.0.1","info":{"title":"Gists","description":"","version":"1.0.0"},"tags":[],"paths":{"/user/me":{"get":{"summary":"Retrieve user informations","deprecated":false,"description":"Retrieve your personnal information such as your email, profile picture...","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"picture":{"type":"string"}},"required":["id","name","email","picture"]},"examples":{"1":{"summary":"Success","value":{"id":"8","name":"","email":"radulescutristan@gmail.com","picture":"https://lh3.googleusercontent.com/a-/ALV-UjVFT4VKCiYyND2v4fPS323_CZN0EE7zwHdQ1jFwdah3Sv5FspPa=s96-c"}}}}}}},"security":[{"bearer":[]}]}},"/gists":{"post":{"summary":"Create a gist","deprecated":false,"description":"Create a gist and link it to an organization as an option","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"},"content":{"type":"string"},"org_id":{"type":"string"}},"required":["name","content"]},"example":{"name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat."}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Gist"},"examples":{"1":{"summary":"Success","value":{"id":"10","name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat.","owner_id":"4"}}}}}}},"security":[{"bearer":[]}]},"get":{"summary":"Get all gists","deprecated":false,"description":"Retrieve all your gists","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Gist"}},"examples":{"1":{"summary":"Fetch all gists","value":[{"id":"4","name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat.","owner_id":"4","org_id":"3"},{"id":"9","name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat.","owner_id":"4"}]}}}}}},"security":[{"bearer":[]}]}},"/gists/{id}/name":{"patch":{"summary":"Update gist's name","deprecated":false,"description":"","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"1","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"}},"required":["name"]},"example":{"name":"doloremque dolorum nobis"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"string"}}}}},"security":[{"bearer":[]}]}},"/gists/{id}/content":{"patch":{"summary":"Update gist's content","deprecated":false,"description":"","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"1","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"}},"required":["name"]},"example":{"content":"ezaeeza"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"string"}}}}},"security":[{"bearer":[]}]}},"/gists/{id}":{"get":{"summary":"Get a gist","deprecated":false,"description":"","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"4","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Gist"}}}}},"security":[{"bearer":[]}]},"delete":{"summary":"Delete a gist","deprecated":false,"description":"Delete a gist","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"1","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"*/*":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":"Gist deleted successfully"}}}}}},"security":[{"bearer":[]}]}},"/auth/local/begin":{"post":{"summary":"Authenticate to the application wth a token","deprecated":false,"description":"Request a one time code by email and get registered or authenticated automatically","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}},"example":{"email":"radulescutristan@gmail.com"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"email":"radulescutristan@gmail.com"}}}}}}},"security":[]}},"/auth/local/verify":{"post":{"summary":"Confirm local authentication request","deprecated":false,"description":"Once you received your one time code, get your auth cookie with this route. It will be named `gists.access_token`","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"token":{"type":"string"}},"required":["email","token"]},"example":{"email":"radulescutristan@gmail.com","token":"234244"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"message":"You are now logged in"}}}}}}},"security":[]}},"/auth/google":{"get":{"summary":"Authenticate with google","deprecated":false,"description":"Authenticate with google, and get redirected directly to gists's frontend","tags":[],"parameters":[],"responses":{"302":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}},"security":[]}},"/auth/github":{"get":{"summary":"Authenticate with github","deprecated":false,"description":"Authenticate with github, and get redirected directly to gists's frontend","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}},"security":[]}},"/orgs":{"post":{"summary":"Create an organization","deprecated":false,"description":"Create an organization by providing its name","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]},"example":{"name":"Test organization 2"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"id":"8","name":"Test organization 2"}}}}}}},"security":[{"bearer":[]}]}},"/orgs/":{"get":{"summary":"get all orgs of user","deprecated":false,"description":"Get all your organizations (not the gists)","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":[{"id":"3","name":"Test organization 2"},{"id":"8","name":"Test organization 2"}]}}}}}},"security":[{"bearer":[]}]}},"/orgs/3":{"get":{"summary":"Get all gists ids from organization","deprecated":false,"description":"Get all the gists created in your organization.","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"id":"3","name":"Test organization 2","gists":["4"]}}}}}}},"security":[{"bearer":[]}]}}},"components":{"schemas":{"Gist":{"type":"object","properties":{"id":{"type":"string","description":"ID"},"name":{"type":"string","description":"name"},"content":{"type":"string","description":"content"}},"required":["id","name","content"]}},"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}}},"servers":[]} \ No newline at end of file +{"openapi":"3.0.1","info":{"title":"Gists","description":"","version":"1.0.0"},"tags":[],"paths":{"/user/me":{"get":{"summary":"Retrieve user informations","deprecated":false,"description":"Retrieve your personnal information such as your email, profile picture...","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"picture":{"type":"string"}},"required":["id","name","email","picture"]},"examples":{"1":{"summary":"Success","value":{"id":"8","name":"","email":"radulescutristan@gmail.com","picture":"https://lh3.googleusercontent.com/a-/ALV-UjVFT4VKCiYyND2v4fPS323_CZN0EE7zwHdQ1jFwdah3Sv5FspPa=s96-c"}}}}},"headers":{}}},"security":[{"bearer":[]}]}},"/gists":{"post":{"summary":"Create a gist","deprecated":false,"description":"Create a gist and link it to an organization as an option","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"},"content":{"type":"string"},"org_id":{"type":"string"}},"required":["name","content"]},"example":{"name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat."}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Gist"},"examples":{"1":{"summary":"Success","value":{"id":"10","name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat.","owner_id":"4"}}}}},"headers":{}}},"security":[{"bearer":[]}]},"get":{"summary":"Get all gists","deprecated":false,"description":"Retrieve all your gists","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Gist"}},"examples":{"1":{"summary":"Fetch all gists","value":[{"id":"4","name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat.","owner_id":"4","org_id":"3"},{"id":"9","name":"temporibus sit amet","content":"Similique veniam illum laudantium sit. Officiis vitae esse accusantium. Deserunt hic distinctio dolores eos delectus enim reprehenderit sunt. Saepe doloremque iusto accusamus praesentium. Non deserunt aspernatur voluptate dolorem voluptas repellat quo nam modi. Nihil perferendis sapiente officiis quam voluptas ducimus tempora velit quaerat.","owner_id":"4"}]}}}},"headers":{}}},"security":[{"bearer":[]}]}},"/gists/{id}/name":{"patch":{"summary":"Update gist's name","deprecated":false,"description":"","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"1","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"}},"required":["name"]},"example":{"name":"doloremque dolorum nobis"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"string"}}},"headers":{}}},"security":[{"bearer":[]}]}},"/gists/{id}/content":{"patch":{"summary":"Update gist's content","deprecated":false,"description":"","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"1","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"}},"required":["name"]},"example":{"content":"ezaeeza"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"string"}}},"headers":{}}},"security":[{"bearer":[]}]}},"/gists/{id}":{"get":{"summary":"Get a gist","deprecated":false,"description":"","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"4","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Gist"}}},"headers":{}}},"security":[{"bearer":[]}]},"delete":{"summary":"Delete a gist","deprecated":false,"description":"Delete a gist","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"example":"1","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"*/*":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":"Gist deleted successfully"}}}},"headers":{}}},"security":[{"bearer":[]}]}},"/auth/local/begin":{"post":{"summary":"Authenticate to the application wth a token","deprecated":false,"description":"Request a one time code by email and get registered or authenticated automatically","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}},"example":{"email":"radulescutristan@gmail.com"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"email":"radulescutristan@gmail.com"}}}}},"headers":{}}},"security":[]}},"/auth/local/verify":{"post":{"summary":"Confirm local authentication request","deprecated":false,"description":"Once you received your one time code, get your auth cookie with this route. It will be named `gists.access_token`","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"token":{"type":"string"}},"required":["email","token"]},"example":{"email":"radulescutristan@gmail.com","token":"234244"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"message":"You are now logged in"}}}}},"headers":{}}},"security":[]}},"/auth/google":{"get":{"summary":"Authenticate with google","deprecated":false,"description":"Authenticate with google, and get redirected directly to gists's frontend","tags":[],"parameters":[],"responses":{"302":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{}}}},"headers":{}}},"security":[]}},"/auth/github":{"get":{"summary":"Authenticate with github","deprecated":false,"description":"Authenticate with github, and get redirected directly to gists's frontend","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}}}},"headers":{}}},"security":[]}},"/orgs":{"post":{"summary":"Create an organization","deprecated":false,"description":"Create an organization by providing its name","tags":[],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]},"example":{"name":"Test organization 2"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"id":"8","name":"Test organization 2"}}}}},"headers":{}}},"security":[{"bearer":[]}]}},"/orgs/":{"get":{"summary":"get all orgs of user","deprecated":false,"description":"Get all your organizations (not the gists)","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":[{"id":"3","name":"Test organization 2"},{"id":"8","name":"Test organization 2"}]}}}},"headers":{}}},"security":[{"bearer":[]}]}},"/orgs/3":{"get":{"summary":"Get all gists ids from organization","deprecated":false,"description":"Get all the gists created in your organization.","tags":[],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{}},"examples":{"1":{"summary":"Success","value":{"id":"3","name":"Test organization 2","gists":["4"]}}}}},"headers":{}}},"security":[{"bearer":[]}]}},"/orgs/{id}":{"delete":{"summary":"Delete an organization","deprecated":false,"description":"Delete an organization. Fails if not owner","tags":[],"parameters":[{"name":"id","in":"path","description":"","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No Content","content":{"application/json":{"schema":{"type":"object","properties":{}}}},"headers":{}}},"security":[{"bearer":[]}]}}},"components":{"schemas":{"Gist":{"type":"object","properties":{"id":{"type":"string","description":"ID"},"name":{"type":"string","description":"name"},"content":{"type":"string","description":"content"}},"required":["id","name","content"]}},"securitySchemes":{"bearer":{"type":"http","scheme":"bearer"}}},"servers":[]} \ No newline at end of file diff --git a/organizations/controller.go b/organizations/controller.go index f5d793d..306c2ff 100644 --- a/organizations/controller.go +++ b/organizations/controller.go @@ -52,3 +52,18 @@ func (c *OrganizationControllerImpl) GetByID() fiber.Handler { return c.JSON(org) } } + +func (c *OrganizationControllerImpl) Delete() fiber.Handler { + return func(c *fiber.Ctx) error { + org_id := c.Params("id") + user_id := c.Locals("pub").(string) + err := OrganizationService.Delete(org_id, user_id) + if err != nil { + if err == ErrUserNotOwner { + return c.Status(401).SendString(err.Error()) + } + return c.Status(400).SendString(err.Error()) + } + return c.SendStatus(204) + } +} diff --git a/organizations/member_model.go b/organizations/member_model.go new file mode 100644 index 0000000..6dcb505 --- /dev/null +++ b/organizations/member_model.go @@ -0,0 +1,43 @@ +package organizations + +import ( + "database/sql" + + "github.com/gistapp/api/storage" + "github.com/gofiber/fiber/v2/log" +) + +type MemberSQL struct { + MemberID sql.NullInt32 + OrgID sql.NullInt32 + UserID sql.NullInt32 + Role sql.NullString +} + +type Member struct { + MemberID int `json:"member_id"` + OrgID int `json:"org_id"` + UserID int `json:"user_id"` + Role Role `json:"role"` +} + +func (m *MemberSQL) Get() (*Member, error) { + row, err := storage.Database.Query("SELECT member_id, org_id, user_id, role FROM member WHERE org_id = $1 AND user_id = $2", m.OrgID.Int32, m.UserID.Int32) + if err != nil { + log.Error(err) + return nil, err + } + + row.Next() + + var member Member + + err = row.Scan(&member.MemberID, &member.OrgID, &member.UserID, &member.Role) + + if err != nil { + log.Error(err) + return nil, err + } + + return &member, nil +} diff --git a/organizations/model.go b/organizations/model.go index 5ffcafa..7a1fd5d 100644 --- a/organizations/model.go +++ b/organizations/model.go @@ -129,3 +129,26 @@ func (o *OrganizationSQL) GetByID(user_id string, org_id string) (*Organization, Gists: gists_ids, }, nil } + +func (o *OrganizationSQL) Get() (*Organization, error) { + query := "SELECT org_id, name FROM organization WHERE org_id = $1" + + row, err := storage.Database.Query(query, o.ID.Int32) + + if err != nil { + return nil, errors.New("couldn't find organization") + } + + row.Next() + + var organization Organization + + err = row.Scan(&organization.ID, &organization.Name) + + if err != nil { + return nil, errors.New("couldn't find organization") + } + + return &organization, nil + +} diff --git a/organizations/router.go b/organizations/router.go index a819096..1e82b80 100644 --- a/organizations/router.go +++ b/organizations/router.go @@ -15,4 +15,5 @@ func (r *OrganizationRouter) SubscribeRoutes(app *fiber.Router) { organizations_router.Post("/", r.Controller.Save()) organizations_router.Get("/", r.Controller.GetAsMember()) organizations_router.Get("/:id", r.Controller.GetByID()) + organizations_router.Delete("/:id", r.Controller.Delete()) } diff --git a/organizations/service.go b/organizations/service.go index c3784a0..da35c02 100644 --- a/organizations/service.go +++ b/organizations/service.go @@ -3,6 +3,8 @@ package organizations import ( "database/sql" "errors" + "fmt" + "strconv" "github.com/gofiber/fiber/v2/log" ) @@ -30,6 +32,26 @@ func (g *OrganizationServiceImpl) Save(name string, owner_id string) (*Organizat return organization, nil } +func (g *OrganizationServiceImpl) IsOwner(org_id int, user_id int) bool { + member_sql := MemberSQL{ + OrgID: sql.NullInt32{ + Int32: int32(org_id), + Valid: true, + }, + UserID: sql.NullInt32{ + Int32: int32(user_id), + Valid: true, + }, + } + + member, err := member_sql.Get() + if err != nil { + return false + } + + return member.Role == Owner +} + // returns a list of organizations that the user is a member of func (g *OrganizationServiceImpl) GetAsMember(user_id string) ([]Organization, error) { m := OrganizationSQL{ @@ -67,4 +89,41 @@ func (g *OrganizationServiceImpl) GetByID(org_id string, user_id string) (*Organ return organization, nil } +func (g *OrganizationServiceImpl) Delete(org_id string, user_id string) error { + i_org_id, err := strconv.Atoi(org_id) + + if err != nil { + return errors.New("organization ID must be an integer") + } + + i_user_id, err := strconv.Atoi(user_id) + + if err != nil { + return errors.New("user ID must be an integer") + } + + if !g.IsOwner(i_org_id, i_user_id) { + return errors.New("user is not the owner of the organization") + } + + m := OrganizationSQL{ + ID: sql.NullInt32{ + Valid: true, + Int32: int32(i_org_id), + }, + Name: sql.NullString{ + String: "", + Valid: false, + }, + } + fmt.Printf("org_id: %d\n", i_org_id) + err = m.Delete() + if err != nil { + fmt.Println(err) + return errors.New("couldn't delete organization") + } + return nil +} + var OrganizationService *OrganizationServiceImpl = &OrganizationServiceImpl{} +var ErrUserNotOwner = errors.New("user is not the owner of the organization") diff --git a/tests/gists_test.go b/tests/gists_test.go index b9fb569..540c7ca 100644 --- a/tests/gists_test.go +++ b/tests/gists_test.go @@ -53,20 +53,20 @@ func InitServerGists() *fiber.App { func TestCreateGists(t *testing.T) { t.Run("Create a new personal gist", func(t *testing.T) { app := InitServerGists() - authToken := GetAuthToken(t, app) + auth_token := GetAuthToken(t, app) - body, req := utils.MakeRequest("POST", t, app, "/gists", map[string]string{ + _, req := utils.MakeRequest("POST", t, app, "/gists", map[string]string{ "name": "Test Gist", "content": "Test content", }, map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", authToken), + "Authorization": fmt.Sprintf("Bearer %s", auth_token), }) if req.StatusCode != 201 { t.Fatalf("Expected status code 201, got %d", req.StatusCode) } - fmt.Println(body) + DeleteAuthUser(t, auth_token) }) @@ -102,7 +102,7 @@ func TestCreateGists(t *testing.T) { } fmt.Println(body) - + DeleteOrganization(t, org.ID) DeleteAuthUser(t, auth_token) }) diff --git a/tests/organization_test.go b/tests/organization_test.go index 70370dc..15b8de4 100644 --- a/tests/organization_test.go +++ b/tests/organization_test.go @@ -66,7 +66,6 @@ func TestCreateOrganization(t *testing.T) { org_payload := map[string]string{ "name": "Test Organization", } - fmt.Println(org_payload) // body, _ := utils.MakeRequest("POST", t, app, "/orgs", org_payload, map[string]string{ "Authorization": "Bearer " + auth_token, @@ -77,21 +76,68 @@ func TestCreateOrganization(t *testing.T) { } // cleanup - id, err := strconv.ParseInt(body["id"], 10, 32) + DeleteOrganization(t, body["id"]) + DeleteAuthUser(t, auth_token) + }) + +} + +func DeleteOrganization(t *testing.T, org_id string) { + id, err := strconv.ParseInt(org_id, 10, 32) + + if err != nil { + t.Errorf("Failed to parse organization ID: %v", err) + } + + org := organizations.OrganizationSQL{ + ID: sql.NullInt32{ + Int32: int32(id), + Valid: true, + }, + } + if err = org.Delete(); err != nil { + t.Errorf("Failed to delete organization: %v", err) + return + } + +} + +func TestDeleteOrganization(t *testing.T) { + t.Run("Delete organization", func(t *testing.T) { + app := InitServerOrgs() + if app == nil { + t.Fatal("Failed to initialize the application") + } + + auth_token := GetAuthToken(t, app) - if err != nil { - t.Errorf("Failed to parse organization ID: %v", err) + org_payload := map[string]string{ + "name": "Test Organization", } - org := organizations.OrganizationSQL{ + body, _ := utils.MakeRequest("POST", t, app, "/orgs", org_payload, map[string]string{ + "Authorization": "Bearer " + auth_token, + }) //before previous test tests the creation, we should be pretty sure that the creation works + + id, _ := strconv.ParseInt(body["id"], 10, 32) + + body, _ = utils.MakeRequest("DELETE", t, app, fmt.Sprintf("/orgs/%d", id), nil, map[string]string{ + "Authorization": "Bearer " + auth_token, + }) + + org_dto := organizations.OrganizationSQL{ ID: sql.NullInt32{ Int32: int32(id), Valid: true, }, } - if err = org.Delete(); err != nil { - t.Errorf("Failed to delete organization: %v", err) + + _, err := org_dto.Get() + + if err == nil { + t.Fatal("Organization was not deleted") } + DeleteAuthUser(t, auth_token) }) } diff --git a/tests/users_test.go b/tests/users_test.go index 187996d..99eb5ed 100644 --- a/tests/users_test.go +++ b/tests/users_test.go @@ -77,5 +77,7 @@ func TestRetreiveUser(t *testing.T) { } log.Info(body) + + DeleteAuthUser(t, auth_token) }) } diff --git a/utils/http_testing.go b/utils/http_testing.go index dc03c40..10fe759 100644 --- a/utils/http_testing.go +++ b/utils/http_testing.go @@ -21,7 +21,7 @@ func MakeRequest(method string, t *testing.T, app *fiber.App, url string, payloa if method == "GET" { req, err = http.NewRequest("GET", url, nil) } else { - req, err = http.NewRequest("POST", url, strings.NewReader(string(jsonPayload))) + req, err = http.NewRequest(method, url, strings.NewReader(string(jsonPayload))) req.Header.Add("Content-Type", "application/json") } @@ -39,8 +39,8 @@ func MakeRequest(method string, t *testing.T, app *fiber.App, url string, payloa t.Fatalf("Failed to execute request: %v", err) } - if resp.StatusCode != 200 && resp.StatusCode != 201 { - t.Errorf("Expected status code 200 or 201, got %d", resp.StatusCode) + if resp.StatusCode == 204 { + return nil, resp } // Decode the response body into a map @@ -49,5 +49,9 @@ func MakeRequest(method string, t *testing.T, app *fiber.App, url string, payloa t.Fatalf("Failed to decode response: %v", err) } + if resp.StatusCode != 200 && resp.StatusCode != 201 { + t.Errorf("Expected status code 200 or 201, got %d with body %v", resp.StatusCode, respBody) + } + return respBody, resp }