M api/api_test.go => api/api_test.go +3 -4
@@ 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) {
M api/graph/generated.go => api/graph/generated.go +9 -9
@@ 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")
M api/graph/schema.graphqls => api/graph/schema.graphqls +1 -1
@@ 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)
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +4 -5
@@ 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)
M core/routes.go => core/routes.go +10 -10
@@ 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)
M core/routes_test.go => core/routes_test.go +3 -3
@@ 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)
M templates/link_list.html => templates/link_list.html +1 -1
@@ 137,7 137,7 @@
</a>
<!-- Delete -->
- <a class="icon-link tooltip-link" href="{{reverse "core:link_delete" .ID}}" data-tooltip="{{$.pd.Data.delete}}">
+ <a class="icon-link tooltip-link" href="{{reverse "core:link_delete" .Hash}}" data-tooltip="{{$.pd.Data.delete}}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6" style="width:20px;">
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
</svg>