From 2e2333e83fb9d78cc98654256b9d122ae2337418 Mon Sep 17 00:00:00 2001 From: Peter Sanchez Date: Thu, 14 Nov 2024 07:15:57 -0600 Subject: [PATCH] Updating deleteLink to use link hash instead of ID --- api/api_test.go | 7 +++---- api/graph/generated.go | 18 +++++++++--------- api/graph/schema.graphqls | 2 +- api/graph/schema.resolvers.go | 9 ++++----- core/routes.go | 20 ++++++++++---------- core/routes_test.go | 6 +++--- templates/link_list.html | 2 +- 7 files changed, 31 insertions(+), 33 deletions(-) diff --git a/api/api_test.go b/api/api_test.go index 71545f2..d1487d4 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -897,17 +897,16 @@ func TestAPI(t *testing.T) { var result GraphQLResponse op := gqlclient.NewOperation( - `mutation DeleteLink($id: Int!) { - deleteLink(id: $id) { + `mutation DeleteLink($hash: String!) { + deleteLink(hash: $hash) { success objectId } }`) - op.Var("id", orgLink.ID) + op.Var("hash", orgLink.Hash) err = links.Execute(ctx, op, &result) c.NoError(err) c.Equal(true, result.DeleteLink.Success) - }) t.Run("add domain error", func(t *testing.T) { diff --git a/api/graph/generated.go b/api/graph/generated.go index d975068..383320c 100644 --- a/api/graph/generated.go +++ b/api/graph/generated.go @@ -225,7 +225,7 @@ type ComplexityRoot struct { CompleteRegister func(childComplexity int, input *model.CompleteRegisterInput) int ConfirmMember func(childComplexity int, key string) int DeleteDomain func(childComplexity int, id int) int - DeleteLink func(childComplexity int, id int) int + DeleteLink func(childComplexity int, hash string) int DeleteLinkShort func(childComplexity int, id int) int DeleteListing func(childComplexity int, id int) int DeleteListingLink func(childComplexity int, id int) int @@ -438,7 +438,7 @@ type MutationResolver interface { AddOrganization(ctx context.Context, input model.OrganizationInput) (*models.Organization, error) AddLink(ctx context.Context, input *model.LinkInput) (*models.OrgLink, error) UpdateLink(ctx context.Context, input *model.UpdateLinkInput) (*models.OrgLink, error) - DeleteLink(ctx context.Context, id int) (*model.DeletePayload, error) + DeleteLink(ctx context.Context, hash string) (*model.DeletePayload, error) AddNote(ctx context.Context, input *model.NoteInput) (*models.OrgLink, error) AddMember(ctx context.Context, input *model.MemberInput) (*model.AddMemberPayload, error) DeleteMember(ctx context.Context, orgSlug string, email string) (*model.AddMemberPayload, error) @@ -1364,7 +1364,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Mutation.DeleteLink(childComplexity, args["id"].(int)), true + return e.complexity.Mutation.DeleteLink(childComplexity, args["hash"].(string)), true case "Mutation.deleteLinkShort": if e.complexity.Mutation.DeleteLinkShort == nil { @@ -2972,15 +2972,15 @@ func (ec *executionContext) field_Mutation_deleteLinkShort_args(ctx context.Cont func (ec *executionContext) field_Mutation_deleteLink_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 int - if tmp, ok := rawArgs["id"]; ok { - ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNInt2int(ctx, tmp) + var arg0 string + if tmp, ok := rawArgs["hash"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hash")) + arg0, err = ec.unmarshalNString2string(ctx, tmp) if err != nil { return nil, err } } - args["id"] = arg0 + args["hash"] = arg0 return args, nil } @@ -9236,7 +9236,7 @@ func (ec *executionContext) _Mutation_deleteLink(ctx context.Context, field grap resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { directive0 := func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().DeleteLink(rctx, fc.Args["id"].(int)) + return ec.resolvers.Mutation().DeleteLink(rctx, fc.Args["hash"].(string)) } directive1 := func(ctx context.Context) (interface{}, error) { scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LINKS") diff --git a/api/graph/schema.graphqls b/api/graph/schema.graphqls index 2fb0f5f..74ae393 100644 --- a/api/graph/schema.graphqls +++ b/api/graph/schema.graphqls @@ -751,7 +751,7 @@ type Mutation { "Add/Edit/Delete organization link. Also used edit/delete notes" addLink(input: LinkInput): OrgLink! @access(scope: LINKS, kind: RW) updateLink(input: UpdateLinkInput): OrgLink! @access(scope: LINKS, kind: RW) - deleteLink(id: Int!): DeletePayload! @access(scope: LINKS, kind: RW) + deleteLink(hash: String!): DeletePayload! @access(scope: LINKS, kind: RW) "Add organization note" addNote(input: NoteInput): OrgLink! @access(scope: LINKS, kind: RW) diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index 19053ea..247833c 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -515,7 +515,7 @@ func (r *mutationResolver) UpdateLink(ctx context.Context, input *model.UpdateLi } // DeleteLink is the resolver for the deleteLink field. -func (r *mutationResolver) DeleteLink(ctx context.Context, id int) (*model.DeletePayload, error) { +func (r *mutationResolver) DeleteLink(ctx context.Context, hash string) (*model.DeletePayload, error) { tokenUser := oauth2.ForContext(ctx) if tokenUser == nil { return nil, valid.ErrAuthorization @@ -528,7 +528,7 @@ func (r *mutationResolver) DeleteLink(ctx context.Context, id int) (*model.Delet } opts := &database.FilterOptions{ Filter: sq.And{ - sq.Expr("ol.id = ?", id), + sq.Expr("ol.hash = ?", hash), }, Limit: 1, } @@ -546,8 +546,7 @@ func (r *mutationResolver) DeleteLink(ctx context.Context, id int) (*model.Delet } link := orgLinks[0] - // If the user is not the link creator, check - // if it's the org owner + // If the user is not the link creator, verify org write permissions if link.UserID != int(user.ID) { opts = &database.FilterOptions{ Filter: sq.And{ @@ -576,7 +575,7 @@ func (r *mutationResolver) DeleteLink(ctx context.Context, id int) (*model.Delet } } - deletedID := strconv.Itoa(link.ID) + deletedID := link.Hash visibility := link.Visibility baseURLID := int(link.BaseURLID.Int64) err = link.Delete(ctx) diff --git a/core/routes.go b/core/routes.go index 45fafc6..ec1476b 100644 --- a/core/routes.go +++ b/core/routes.go @@ -89,8 +89,8 @@ func (s *Service) RegisterRoutes() { s.Group.POST("/add", s.OrgLinksCreate).Name = s.RouteName("link_create_post") s.Group.GET("/read/:id", s.OrgLinkAsReadToggle).Name = s.RouteName("link_mark_as_read") s.Group.GET("/star/:id", s.OrgLinkStarToggle).Name = s.RouteName("link_star_toggle") - s.Group.GET("/link/:id/delete", s.OrgLinkDelete).Name = s.RouteName("link_delete") - s.Group.POST("/link/:id/delete", s.OrgLinkDelete).Name = s.RouteName("link_delete") + s.Group.GET("/link/:hash/delete", s.OrgLinkDelete).Name = s.RouteName("link_delete") + s.Group.POST("/link/:hash/delete", s.OrgLinkDelete).Name = s.RouteName("link_delete") s.Group.GET("/link/:id/edit", s.OrgLinkUpdate).Name = s.RouteName("link_edit") s.Group.POST("/link/:id/edit", s.OrgLinkUpdate).Name = s.RouteName("link_edit_post") s.Group.GET("/qr/:hash/detail", s.QRManageDetail).Name = s.RouteName("qr_manage_detail") @@ -2320,8 +2320,8 @@ func (s *Service) OrgLinkDetail(c echo.Context) error { // OrgLinkDelete ... func (s *Service) OrgLinkDelete(c echo.Context) error { - id, err := strconv.Atoi(c.Param("id")) - if err != nil { + hash := c.Param("hash") + if hash == "" { return echo.NotFoundHandler(c) } gctx := c.(*server.Context) @@ -2339,14 +2339,14 @@ func (s *Service) OrgLinkDelete(c echo.Context) error { var result GraphQLResponse op := gqlclient.NewOperation( - `mutation DeleteLink($id: Int!) { - deleteLink(id: $id) { + `mutation DeleteLink($hash: String!) { + deleteLink(hash: $hash) { success objectId } }`) - op.Var("id", id) - err = links.Execute(c.Request().Context(), op, &result) + op.Var("hash", hash) + err := links.Execute(c.Request().Context(), op, &result) if err != nil { return err } @@ -2367,7 +2367,7 @@ func (s *Service) OrgLinkDelete(c echo.Context) error { // NOTE: All these validations already happen in the resolver for the POST request opts := &database.FilterOptions{ Filter: sq.And{ - sq.Expr("ol.id = ?", id), + sq.Expr("ol.hash = ?", hash), }, Limit: 1, } @@ -2400,7 +2400,7 @@ func (s *Service) OrgLinkDelete(c echo.Context) error { pd.Data["message"] = lt.Translate("Do you really whant to delete this bookmark?") gmap := gobwebs.Map{ "pd": pd, - "url": c.Echo().Reverse(s.RouteName("link_delete"), link.ID), + "url": c.Echo().Reverse(s.RouteName("link_delete"), link.Hash), "back": c.Echo().Reverse(s.RouteName("home_link_list")), } return s.Render(c, http.StatusOK, "element_delete.html", gmap) diff --git a/core/routes_test.go b/core/routes_test.go index a84872d..0c97291 100644 --- a/core/routes_test.go +++ b/core/routes_test.go @@ -328,9 +328,9 @@ func TestHandlers(t *testing.T) { Context: e.NewContext(request, recorder), User: loggedInUser, } - ctx.SetPath("/link/:id/delete") - ctx.SetParamNames("id") - ctx.SetParamValues("1") + ctx.SetPath("/link/:hash/delete") + ctx.SetParamNames("hash") + ctx.SetParamValues("ABCDEFG") err = test.MakeRequestWithDomain(srv, coreService.OrgLinkDelete, ctx, domains[0]) c.NoError(err) c.Equal(http.StatusMovedPermanently, recorder.Code) diff --git a/templates/link_list.html b/templates/link_list.html index f020995..c73be97 100644 --- a/templates/link_list.html +++ b/templates/link_list.html @@ -137,7 +137,7 @@ - + -- 2.45.2