diff --git a/casdoorsdk/transaction.go b/casdoorsdk/transaction.go new file mode 100644 index 0000000..461c5e0 --- /dev/null +++ b/casdoorsdk/transaction.go @@ -0,0 +1,144 @@ +// Copyright 2024 The Casdoor 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 casdoorsdk + +import ( + "encoding/json" + "errors" + "fmt" + "strconv" +) + +// Transaction has the same definition as https://github.com/casdoor/casdoor/blob/master/object/transaction.go#L24 +type Transaction struct { + Owner string `xorm:"varchar(100) notnull pk" json:"owner"` + Name string `xorm:"varchar(100) notnull pk" json:"name"` + CreatedTime string `xorm:"varchar(100)" json:"createdTime"` + DisplayName string `xorm:"varchar(100)" json:"displayName"` + // Transaction Provider Info + Provider string `xorm:"varchar(100)" json:"provider"` + Category string `xorm:"varchar(100)" json:"category"` + Type string `xorm:"varchar(100)" json:"type"` + // Product Info + ProductName string `xorm:"varchar(100)" json:"productName"` + ProductDisplayName string `xorm:"varchar(100)" json:"productDisplayName"` + Detail string `xorm:"varchar(255)" json:"detail"` + Tag string `xorm:"varchar(100)" json:"tag"` + Currency string `xorm:"varchar(100)" json:"currency"` + Amount float64 `json:"amount"` + ReturnUrl string `xorm:"varchar(1000)" json:"returnUrl"` + // User Info + User string `xorm:"varchar(100)" json:"user"` + Application string `xorm:"varchar(100)" json:"application"` + Payment string `xorm:"varchar(100)" json:"payment"` + + State string `xorm:"varchar(100)" json:"state"` +} + +func (c *Client) GetTransactions() ([]*Transaction, error) { + queryMap := map[string]string{ + "owner": c.OrganizationName, + } + + url := c.GetUrl("get-transactions", queryMap) + + bytes, err := c.DoGetBytes(url) + if err != nil { + return nil, err + } + + var transactions []*Transaction + err = json.Unmarshal(bytes, &transactions) + if err != nil { + return nil, err + } + return transactions, nil +} + +func (c *Client) GetPaginationTransactions(p int, pageSize int, queryMap map[string]string) ([]*Transaction, int, error) { + queryMap["owner"] = c.OrganizationName + queryMap["p"] = strconv.Itoa(p) + queryMap["pageSize"] = strconv.Itoa(pageSize) + + url := c.GetUrl("get-transactions", queryMap) + + response, err := c.DoGetResponse(url) + if err != nil { + return nil, 0, err + } + + transactions, ok := response.Data.([]*Transaction) + if !ok { + return nil, 0, errors.New("response data format is incorrect") + } + + return transactions, int(response.Data2.(float64)), nil +} + +func (c *Client) GetTransaction(name string) (*Transaction, error) { + queryMap := map[string]string{ + "id": fmt.Sprintf("%s/%s", c.OrganizationName, name), + } + + url := c.GetUrl("get-transaction", queryMap) + + bytes, err := c.DoGetBytes(url) + if err != nil { + return nil, err + } + + var transaction *Transaction + err = json.Unmarshal(bytes, &transaction) + if err != nil { + return nil, err + } + return transaction, nil +} + +func (c *Client) GetUserTransactions(userName string) ([]*Transaction, error) { + queryMap := map[string]string{ + "owner": c.OrganizationName, + "user": userName, + } + + url := c.GetUrl("get-user-transactions", queryMap) + + bytes, err := c.DoGetBytes(url) + if err != nil { + return nil, err + } + + var transactions []*Transaction + err = json.Unmarshal(bytes, &transactions) + if err != nil { + return nil, err + } + return transactions, nil +} + +func (c *Client) UpdateTransaction(transaction *Transaction) (bool, error) { + _, affected, err := c.modifyTransaction("update-transaction", transaction, nil) + return affected, err +} + +func (c *Client) AddTransaction(transaction *Transaction) (bool, error) { + _, affected, err := c.modifyTransaction("add-transaction", transaction, nil) + return affected, err +} + +func (c *Client) DeleteTransaction(transaction *Transaction) (bool, error) { + _, affected, err := c.modifyTransaction("delete-transaction", transaction, nil) + return affected, err +} diff --git a/casdoorsdk/transaction_global.go b/casdoorsdk/transaction_global.go new file mode 100644 index 0000000..d87edfe --- /dev/null +++ b/casdoorsdk/transaction_global.go @@ -0,0 +1,43 @@ +// Copyright 2024 The Casdoor 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 casdoorsdk + +func GetTransactions() ([]*Transaction, error) { + return globalClient.GetTransactions() +} + +func GetPaginationTransactions(p int, pageSize int, queryMap map[string]string) ([]*Transaction, int, error) { + return globalClient.GetPaginationTransactions(p, pageSize, queryMap) +} + +func GetTransaction(name string) (*Transaction, error) { + return globalClient.GetTransaction(name) +} + +func GetUserTransactions(userName string) ([]*Transaction, error) { + return globalClient.GetUserTransactions(userName) +} + +func UpdateTransaction(transaction *Transaction) (bool, error) { + return globalClient.UpdateTransaction(transaction) +} + +func AddTransaction(transaction *Transaction) (bool, error) { + return globalClient.AddTransaction(transaction) +} + +func DeleteTransaction(transaction *Transaction) (bool, error) { + return globalClient.DeleteTransaction(transaction) +} diff --git a/casdoorsdk/transaction_test.go b/casdoorsdk/transaction_test.go new file mode 100644 index 0000000..c08f552 --- /dev/null +++ b/casdoorsdk/transaction_test.go @@ -0,0 +1,76 @@ +package casdoorsdk + +import "testing" + +func TestTransaction(t *testing.T) { + InitConfig(TestCasdoorEndpoint, TestClientId, TestClientSecret, TestJwtPublicKey, TestCasdoorOrganization, TestCasdoorApplication) + + name := getRandomName("Transaction") + + // Add a new object + transaction := &Transaction{ + Owner: "admin", + Name: name, + CreatedTime: GetCurrentTime(), + DisplayName: name, + ProductName: "casbin", + } + _, err := AddTransaction(transaction) + if err != nil { + t.Fatalf("Failed to add object: %v", err) + } + + // Get all objects, check if our added object is inside the list + transactions, err := GetTransactions() + if err != nil { + t.Fatalf("Failed to get objects: %v", err) + } + found := false + for _, item := range transactions { + if item.Name == name { + found = true + break + } + } + if !found { + t.Fatalf("Added object not found in list") + } + + // Get the object + transaction, err = GetTransaction(name) + if err != nil { + t.Fatalf("Failed to get object: %v", err) + } + if transaction.Name != name { + t.Fatalf("Retrieved object does not match added object: %s != %s", transaction.Name, name) + } + + // Update the object + updatedProductName := "Updated Casdoor Website" + transaction.ProductName = updatedProductName + _, err = UpdateTransaction(transaction) + if err != nil { + t.Fatalf("Failed to update object: %v", err) + } + + // Validate the update + updatedTransaction, err := GetTransaction(name) + if err != nil { + t.Fatalf("Failed to get updated object: %v", err) + } + if updatedTransaction.ProductName != updatedProductName { + t.Fatalf("Failed to update object, description mismatch: %s != %s", updatedTransaction.ProductName, updatedProductName) + } + + // Delete the object + _, err = DeleteTransaction(transaction) + if err != nil { + t.Fatalf("Failed to delete object: %v", err) + } + + // Validate the deletion + deletedTransaction, err := GetTransaction(name) + if err != nil || deletedTransaction != nil { + t.Fatalf("Failed to delete object, it's still retrievable") + } +} diff --git a/casdoorsdk/util_modify.go b/casdoorsdk/util_modify.go index 570c1a5..8fe6ccf 100644 --- a/casdoorsdk/util_modify.go +++ b/casdoorsdk/util_modify.go @@ -475,6 +475,31 @@ func (c *Client) modifySyncer(action string, syncer *Syncer, columns []string) ( return resp, resp.Data == "Affected", nil } +// modifyTransaction is an encapsulation of cert CUD(Create, Update, Delete) operations. +// possible actions are `add-transaction`, `update-transaction`, `delete-transaction`, +func (c *Client) modifyTransaction(action string, transaction *Transaction, columns []string) (*Response, bool, error) { + queryMap := map[string]string{ + "id": fmt.Sprintf("%s/%s", transaction.Owner, transaction.Name), + } + + if len(columns) != 0 { + queryMap["columns"] = strings.Join(columns, ",") + } + + transaction.Owner = c.OrganizationName + postBytes, err := json.Marshal(transaction) + if err != nil { + return nil, false, err + } + + resp, err := c.DoPost(action, queryMap, postBytes, false, false) + if err != nil { + return nil, false, err + } + + return resp, resp.Data == "Affected", nil +} + // modifyWebhook is an encapsulation of cert CUD(Create, Update, Delete) operations. // possible actions are `add-webhook`, `update-webhook`, `delete-webhook`, func (c *Client) modifyWebhook(action string, webhook *Webhook, columns []string) (*Response, bool, error) {