From 2f482fe69b8cc19726d9ce2d9a8f18db8814c77e Mon Sep 17 00:00:00 2001 From: Peter Sanchez Date: Wed, 5 Jun 2024 08:02:06 -0600 Subject: [PATCH] Completing org member removal. Implements: https://todo.code.netlandish.com/~netlandish/links/79 --- api/graph/schema.resolvers.go | 6 ++ core/routes.go | 132 +++++++++++++++++++++++++++++----- templates/member_list.html | 2 +- 3 files changed, 121 insertions(+), 19 deletions(-) diff --git a/api/graph/schema.resolvers.go b/api/graph/schema.resolvers.go index 7aa5704..9830fe9 100644 --- a/api/graph/schema.resolvers.go +++ b/api/graph/schema.resolvers.go @@ -972,6 +972,12 @@ func (r *mutationResolver) DeleteMember(ctx context.Context, orgSlug string, ema addMemberPayload.Success = false addMemberPayload.Message = lt.Translate("The user for given email is not a member of given organization") } else { + for _, ou := range ousers { + err = ou.Delete(ctx) + if err != nil { + return nil, err + } + } addMemberPayload.Success = true addMemberPayload.Message = lt.Translate("The member was removed successfully") } diff --git a/core/routes.go b/core/routes.go index 19f3636..d3a2e65 100644 --- a/core/routes.go +++ b/core/routes.go @@ -88,7 +88,9 @@ func (s *Service) RegisterRoutes() { s.eg.POST("/:slug/edit", s.OrgUpdate).Name = s.RouteName("org_edit_post") s.eg.GET("/:slug/members", s.OrgMembersList).Name = s.RouteName("org_member_list") s.eg.GET("/:slug/members/add", s.OrgMembersAdd).Name = s.RouteName("org_member_add") - s.eg.POST("/:slug/members/add", s.OrgMembersAdd).Name = s.RouteName("org_member_add") + s.eg.POST("/:slug/members/add", s.OrgMembersAdd).Name = s.RouteName("org_member_add_post") + s.eg.GET("/:slug/members/delete/:id", s.OrgMembersDelete).Name = s.RouteName("org_member_delete") + s.eg.POST("/:slug/members/delete/:id", s.OrgMembersDelete).Name = s.RouteName("org_member_delete_post") s.eg.GET("/:slug/export", s.ExportData).Name = s.RouteName("export_data") s.eg.POST("/:slug/export", s.ExportData).Name = s.RouteName("export_data_post") s.eg.GET("/:slug/import", s.ImportData).Name = s.RouteName("import_data") @@ -1105,6 +1107,107 @@ func (s *Service) OrgMembersAdd(c echo.Context) error { return links.Render(c, http.StatusOK, "member_add.html", gmap) } +// OrgMembersDelete ... +func (s *Service) OrgMembersDelete(c echo.Context) error { + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + return echo.NotFoundHandler(c) + } + slug := c.Param("slug") + if slug == "" { + return echo.NotFoundHandler(c) + } + + gctx := c.(*server.Context) + user := gctx.User.(*models.User) + + req := c.Request() + org, err := user.GetOrgsSlug(req.Context(), models.OrgUserPermissionAdminWrite, slug) + if err != nil { + return err + } + if org == nil { + return echo.NotFoundHandler(c) + } + + opts := &database.FilterOptions{ + Filter: sq.And{ + sq.Eq{"org_id": org.ID}, + sq.Eq{"user_id": id}, + sq.Eq{"is_active": true}, + }, + Limit: 1, + } + ousers, err := models.GetOrgUsers(req.Context(), opts) + if err != nil { + return err + } + if len(ousers) == 0 { + return echo.NotFoundHandler(c) + } + orgUser := ousers[0] + + ouser, err := models.GetUser(req.Context(), orgUser.UserID, false) + if err != nil { + if err == sql.ErrNoRows { + return echo.NotFoundHandler(c) + } + return err + } + + lt := localizer.GetSessionLocalizer(c) + pd := localizer.NewPageData(lt.Translate("Delete Org Member")) + + if req.Method == http.MethodPost { + type GraphQLResponse struct { + DeleteMember struct { + Success bool `json:"success"` + Message string `json:"message"` + } `json:"deleteMember"` + } + + var result GraphQLResponse + op := gqlclient.NewOperation( + `mutation DeleteMember($orgSlug: String!, $email: String!) { + deleteMember(orgSlug: $orgSlug, email: $email) { + success + message + } + }`) + op.Var("orgSlug", slug) + op.Var("email", strings.ToLower(ouser.Email)) + err = links.Execute(c.Request().Context(), op, &result) + if err != nil { + return err + } + if !result.DeleteMember.Success { + messages.Error( + c, + lt.Translate( + "Something went wrong. This member could not be deleted: %s", + result.DeleteMember.Message, + ), + ) + } else { + messages.Success(c, lt.Translate("Member successfully deleted")) + } + return c.Redirect(http.StatusMovedPermanently, + c.Echo().Reverse(s.RouteName("org_member_list"), slug)) + } + + pd.Data["message"] = lt.Translate( + "Delete member %s (%s) from Organization %s?", ouser.Name, ouser.Email, slug) + pd.Data["yes"] = lt.Translate("Yes") + pd.Data["cancel"] = lt.Translate("Cancel") + + gmap := gobwebs.Map{ + "pd": pd, + "url": c.Echo().Reverse(s.RouteName("org_member_delete"), slug, id), + "back": c.Echo().Reverse(s.RouteName("org_member_list"), slug), + } + return links.Render(c, http.StatusOK, "element_delete.html", gmap) +} + // OrgMemberConfirmation ... func (s *Service) OrgMemberConfirmation(c echo.Context) error { key := c.QueryParam("key") @@ -1204,6 +1307,7 @@ func (s *Service) OrgMembersList(c echo.Context) error { pd.Data["no_member"] = lt.Translate("No members") pd.Data["add"] = lt.Translate("Add") pd.Data["back"] = lt.Translate("Back") + pd.Data["delete"] = lt.Translate("Delete") pd.Data["restricted"] = lt.Translate("Please upgrade to a Business organization to add members") pd.Data["continue_to_upgrade"] = lt.Translate("Continue to Upgrade") gmap := gobwebs.Map{ @@ -2218,7 +2322,7 @@ func (s *Service) OrgLinkDelete(c echo.Context) error { return err } if !result.DeleteLink.Success { - messages.Error(c, lt.Translate("Something went wrong. This element could not be deleted.")) + messages.Error(c, lt.Translate("Something went wrong. This bookmark could not be deleted.")) redirect := c.Request().Header.Get("Referer") if redirect == "" { redirect = c.Echo().Reverse(s.RouteName("home_link_list")) @@ -2226,7 +2330,7 @@ func (s *Service) OrgLinkDelete(c echo.Context) error { return c.Redirect(http.StatusMovedPermanently, redirect) } - messages.Success(c, lt.Translate("Element successfully deleted")) + messages.Success(c, lt.Translate("Bookmark successfully deleted")) return c.Redirect(http.StatusMovedPermanently, c.Echo().Reverse(s.RouteName("home_link_list"))) } @@ -2248,31 +2352,23 @@ func (s *Service) OrgLinkDelete(c echo.Context) error { } 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, check that the user + //has admin write permissions. user := gctx.User.(*models.User) if link.UserID != int(user.ID) { - opts = &database.FilterOptions{ - Filter: sq.And{ - sq.Expr("o.id = ?", link.OrgID), - sq.Expr("o.owner_id = ?", user.ID), - sq.Expr("o.is_active = true"), - }, - Limit: 1, - } - - orgs, err := models.GetOrganizations(c.Request().Context(), opts) + org, err := user.GetOrgsID( + c.Request().Context(), models.OrgUserPermissionWrite, link.OrgID) if err != nil { return err } - - if len(orgs) == 0 { + if org == nil { return echo.NotFoundHandler(c) } } pd.Data["yes"] = lt.Translate("Yes") pd.Data["cancel"] = lt.Translate("Cancel") - pd.Data["message"] = lt.Translate("Do you really whant to delete this element") + 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), diff --git a/templates/member_list.html b/templates/member_list.html index 0d12d0b..6a4b2bc 100644 --- a/templates/member_list.html +++ b/templates/member_list.html @@ -29,7 +29,7 @@ {{.Name}} {{.Email}} - + {{ $.pd.Data.delete }} {{end}} {{else}} -- 2.45.2