Skip to content

Commit

Permalink
feat: use Casdoor code to support delete-after-sort (#49)
Browse files Browse the repository at this point in the history
* fix: fix refresh and delete in cert and site after sort

* Update cert.go

* Update site.go

* Update ormer_session.go

* Update SiteListPage.js

* Update CertListPage.js

* CertListPage.js

* fix: modify format

---------

Co-authored-by: Gucheng <[email protected]>
  • Loading branch information
chatiti and nomeguy authored Aug 3, 2024
1 parent dc05abe commit 7132267
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 80 deletions.
48 changes: 35 additions & 13 deletions controllers/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ package controllers
import (
"encoding/json"

"github.com/beego/beego/utils/pagination"
"github.com/casbin/caswaf/object"
"github.com/casbin/caswaf/util"
)

func (c *ApiController) GetGlobalCerts() {
Expand All @@ -44,13 +46,38 @@ func (c *ApiController) GetCerts() {
owner = ""
}

certs, err := object.GetCerts(owner)
if err != nil {
c.ResponseError(err.Error())
return
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")

if limit == "" || page == "" {
certs, err := object.GetCerts(owner)
if err != nil {
c.ResponseError(err.Error())
return
}

c.ResponseOk(object.GetMaskedCerts(certs))
} else {
limit := util.ParseInt(limit)
count, err := object.GetCertCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}

paginator := pagination.SetPaginator(c.Ctx, limit, count)
certs, err := object.GetPaginationCerts(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}

c.ResponseOk(object.GetMaskedCerts(certs), paginator.Nums())
}

c.ResponseOk(object.GetMaskedCerts(certs))
}

func (c *ApiController) GetCert() {
Expand Down Expand Up @@ -142,11 +169,6 @@ func (c *ApiController) UpdateCertDomainExpire() {
}
cert.DomainExpireTime = domainExpireTime

_, err = object.UpdateCert(id, cert)
if err != nil {
c.ResponseError(err.Error())
return
}

c.ResponseOk(object.GetMaskedCert(cert))
c.Data["json"] = wrapActionResponse(object.UpdateCert(id, cert))
c.ServeJSON()
}
30 changes: 28 additions & 2 deletions controllers/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package controllers
import (
"encoding/json"

"github.com/beego/beego/utils/pagination"
"github.com/casbin/caswaf/object"
"github.com/casbin/caswaf/util"
)
Expand Down Expand Up @@ -45,13 +46,38 @@ func (c *ApiController) GetSites() {
owner = ""
}

sites, err := object.GetSites(owner)
limit := c.Input().Get("pageSize")
page := c.Input().Get("p")
field := c.Input().Get("field")
value := c.Input().Get("value")
sortField := c.Input().Get("sortField")
sortOrder := c.Input().Get("sortOrder")

if limit == "" || page == "" {
sites, err := object.GetSites(owner)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(object.GetMaskedSites(sites, util.GetHostname()))
return
}

limitInt := util.ParseInt(limit)
count, err := object.GetSiteCount(owner, field, value)
if err != nil {
c.ResponseError(err.Error())
return
}

c.ResponseOk(object.GetMaskedSites(sites, util.GetHostname()))
paginator := pagination.SetPaginator(c.Ctx, limitInt, count)
sites, err := object.GetPaginationSites(owner, paginator.Offset(), limitInt, field, value, sortField, sortOrder)
if err != nil {
c.ResponseError(err.Error())
return
}

c.ResponseOk(object.GetMaskedSites(sites, util.GetHostname()), paginator.Nums())
}

func (c *ApiController) GetSite() {
Expand Down
16 changes: 16 additions & 0 deletions object/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,19 @@ func (cert *Cert) isCertNearExpire() (bool, error) {

return res, nil
}

func GetCertCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Cert{})
}

func GetPaginationCerts(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Cert, error) {
certs := []*Cert{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Where("owner = ? or owner = ?", "admin", owner).Find(&certs)
if err != nil {
return certs, err
}

return certs, nil
}
46 changes: 46 additions & 0 deletions object/ormer_session.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2023 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package object

import (
"fmt"

"github.com/casbin/caswaf/util"
"github.com/xorm-io/xorm"
)

func GetSession(owner string, offset, limit int, field, value, sortField, sortOrder string) *xorm.Session {
session := ormer.Engine.Prepare()
if offset != -1 && limit != -1 {
session.Limit(limit, offset)
}
if owner != "" {
session = session.And("owner=?", owner)
}
if field != "" && value != "" {
if util.FilterField(field) {
session = session.And(fmt.Sprintf("%s like ?", util.SnakeString(field)), fmt.Sprintf("%%%s%%", value))
}
}
if sortField == "" || sortOrder == "" {
sortField = "created_time"
}
if sortOrder == "ascend" {
session = session.Asc(util.SnakeString(sortField))
} else {
session = session.Desc(util.SnakeString(sortField))
}
return session
}
16 changes: 16 additions & 0 deletions object/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,19 @@ func (site *Site) checkNodes() error {

return nil
}

func GetSiteCount(owner, field, value string) (int64, error) {
session := GetSession(owner, -1, -1, field, value, "", "")
return session.Count(&Site{})
}

func GetPaginationSites(owner string, offset, limit int, field, value, sortField, sortOrder string) ([]*Site, error) {
sites := []*Site{}
session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
err := session.Where("owner = ? or owner = ?", "admin", owner).Find(&sites)
if err != nil {
return sites, err
}

return sites, nil
}
18 changes: 18 additions & 0 deletions util/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,21 @@ func GenerateTwoUniqueRandomStrings() (string, string, error) {
}
return str1, str2, nil
}

func SnakeString(s string) string {
data := make([]byte, 0, len(s)*2)
j := false
num := len(s)
for i := 0; i < num; i++ {
d := s[i]
if i > 0 && d >= 'A' && d <= 'Z' && j {
data = append(data, '_')
}
if d != '_' {
j = true
}
data = append(data, d)
}
result := strings.ToLower(string(data[:]))
return strings.ReplaceAll(result, " ", "")
}
17 changes: 17 additions & 0 deletions util/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package util

import "regexp"

var (
ReWhiteSpace *regexp.Regexp
ReFieldWhiteList *regexp.Regexp
)

func init() {
ReWhiteSpace, _ = regexp.Compile(`\s`)
ReFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
}

func FilterField(field string) bool {
return ReFieldWhiteList.MatchString(field)
}
14 changes: 11 additions & 3 deletions web/src/BaseListPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@ class BaseListPage extends React.Component {
}

UNSAFE_componentWillMount() {
this.fetch();
const {pagination} = this.state;
this.fetch({pagination});
}

handleTableChange = () => {
this.fetch();
handleTableChange = (pagination, filters, sorter) => {
this.fetch({
sortField: sorter.field,
sortOrder: sorter.order,
pagination,
...filters,
searchText: this.state.searchText,
searchedColumn: this.state.searchedColumn,
});
};

render() {
Expand Down
65 changes: 39 additions & 26 deletions web/src/CertListPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,14 @@ import copy from "copy-to-clipboard";
import BaseListPage from "./BaseListPage";

class CertListPage extends BaseListPage {
constructor(props) {
super(props);
}

UNSAFE_componentWillMount() {
this.fetch();
}

fetch = (params = {}) => {
this.setState({loading: true});
CertBackend.getCerts(this.props.account.name)
.then((res) => {
this.setState({
loading: false,
});
if (res.status === "ok") {
this.setState({
data: res.data,
});
} else {
Setting.showMessage("error", `Failed to get certs: ${res.msg}`);
}
});
};

newCert() {
const randomName = Setting.getRandomName();
return {
Expand Down Expand Up @@ -105,11 +91,7 @@ class CertListPage extends BaseListPage {
Setting.showMessage("error", `Failed to refresh domain expire: ${res.msg}`);
} else {
Setting.showMessage("success", "Domain expire refresh successfully");
const newData = [...this.state.data];
newData[i] = res.data;
this.setState({
data: newData,
});
this.fetch();
}
}
)
Expand Down Expand Up @@ -263,9 +245,8 @@ class CertListPage extends BaseListPage {
width: "260px",
render: (text, record, index) => {
return (
<div>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="default" onClick={() => this.refreshCert(index)}>
{i18next.t("general:Refresh")}
<div style={{display: "flex", alignItems: "center", flexWrap: "nowrap"}}>
<Button style={{margin: "10px 10px 10px 0"}} type="default" onClick={() => this.refreshCert(index)}>{i18next.t("general:Refresh")}
</Button>
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/certs/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
<Popconfirm
Expand All @@ -284,7 +265,8 @@ class CertListPage extends BaseListPage {

return (
<div>
<Table columns={columns} dataSource={data} rowKey="name" size="middle" bordered pagination={{pageSize: 100}}
<Table
columns={columns} dataSource={data} rowKey="name" size="middle" bordered pagination={this.state.pagination}
title={() => (
<div>
{i18next.t("general:Certs")}&nbsp;&nbsp;&nbsp;&nbsp;
Expand All @@ -297,6 +279,37 @@ class CertListPage extends BaseListPage {
</div>
);
}

fetch = (params = {}) => {
const field = params.searchedColumn, value = params.searchText;
const sortField = params.sortField, sortOrder = params.sortOrder;
if (!params.pagination) {
params.pagination = {current: 1, pageSize: 10};
}
this.setState({loading: true});
CertBackend.getCerts(this.props.account.name, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
.then((res) => {
this.setState({
loading: false,
});
if (res.status === "ok") {
this.setState({
data: res.data,
pagination: {
...params.pagination,
total: res.data2,
},
searchText: params.searchText,
searchedColumn: params.searchedColumn,
sortField: sortField,
sortOrder: sortOrder,
});
} else {
Setting.showMessage("error", `Failed to get certs: ${res.msg}`);
}
});
};

}

export default CertListPage;
Loading

0 comments on commit 7132267

Please sign in to comment.