~netlandish/links

2f482fe69b8cc19726d9ce2d9a8f18db8814c77e — Peter Sanchez 4 months ago 1f483e4
Completing org member removal.

Implements: https://todo.code.netlandish.com/~netlandish/links/79
3 files changed, 121 insertions(+), 19 deletions(-)

M api/graph/schema.resolvers.go
M core/routes.go
M templates/member_list.html
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +6 -0
@@ 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")
	}

M core/routes.go => core/routes.go +114 -18
@@ 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),

M templates/member_list.html => templates/member_list.html +1 -1
@@ 29,7 29,7 @@
              <tr>
                  <td>{{.Name}}</td>
                  <td>{{.Email}}</td>
                  <td></td>
                  <td><a class="button primary is-small" href="{{ reverse "core:org_member_delete" $.slug .ID }}">{{ $.pd.Data.delete }}</a></td>
              </tr>
              {{end}}
              {{else}}