Skip to main content

casdoor_rust_sdk/
product.rs

1// Copyright 2026 The Casdoor Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::HashMap;
16
17use serde::{Deserialize, Serialize};
18
19use crate::client::{get_owner, Client, Response};
20use crate::error::Result;
21use crate::provider::Provider;
22use crate::serde_util::null_to_default;
23
24/// Product has the same definition as
25/// <https://github.com/casdoor/casdoor/blob/master/object/product.go>.
26#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase", default)]
28pub struct Product {
29    pub owner: String,
30    pub name: String,
31    pub created_time: String,
32    pub display_name: String,
33
34    pub image: String,
35    pub detail: String,
36    pub description: String,
37    pub tag: String,
38    pub currency: String,
39    pub price: f64,
40    pub quantity: i32,
41    pub sold: i32,
42    pub is_recharge: bool,
43    #[serde(deserialize_with = "null_to_default")]
44    pub recharge_options: Vec<f64>,
45    pub disable_custom_recharge: bool,
46    #[serde(deserialize_with = "null_to_default")]
47    pub providers: Vec<String>,
48    pub success_url: String,
49
50    pub state: String,
51
52    #[serde(deserialize_with = "null_to_default")]
53    pub properties: HashMap<String, String>,
54
55    #[serde(deserialize_with = "null_to_default")]
56    pub provider_objs: Vec<Provider>,
57}
58
59impl Client {
60    /// Get the products of the client's organization.
61    pub async fn get_products(&self) -> Result<Vec<Product>> {
62        self.get_list("get-products", &[("owner", &self.config.organization_name)])
63            .await
64    }
65
66    /// Get one page of the products of the client's organization, together with the total
67    /// number of the products.
68    pub async fn get_pagination_products(
69        &self,
70        p: i32,
71        page_size: i32,
72        query: &[(&str, &str)],
73    ) -> Result<(Vec<Product>, i32)> {
74        self.get_pagination(
75            "get-products",
76            &self.config.organization_name,
77            p,
78            page_size,
79            query,
80        )
81        .await
82    }
83
84    /// Get one product by name.
85    pub async fn get_product(&self, name: &str) -> Result<Option<Product>> {
86        self.get_object("get-product", &[("id", &self.get_id(name))])
87            .await
88    }
89
90    /// Add a product.
91    pub async fn add_product(&self, product: &Product) -> Result<bool> {
92        Ok(self.modify_product("add-product", product, &[]).await?.1)
93    }
94
95    /// Update a product.
96    pub async fn update_product(&self, product: &Product) -> Result<bool> {
97        Ok(self.modify_product("update-product", product, &[]).await?.1)
98    }
99
100    /// Delete a product.
101    pub async fn delete_product(&self, product: &Product) -> Result<bool> {
102        Ok(self.modify_product("delete-product", product, &[]).await?.1)
103    }
104
105    async fn modify_product(
106        &self,
107        action: &str,
108        product: &Product,
109        columns: &[&str],
110    ) -> Result<(Response, bool)> {
111        let mut product = product.clone();
112        product.owner = get_owner(&product.owner, &self.config.organization_name);
113
114        let id = format!("{}/{}", product.owner, product.name);
115        self.modify_object(action, &id, &product, columns).await
116    }
117}