Skip to main content

casdoor_rust_sdk/
config.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::fs;
16
17use serde::{Deserialize, Serialize};
18
19use crate::error::{CasdoorError, Result};
20
21/// AuthConfig is the core configuration of the SDK, it has the same fields as the
22/// `AuthConfig` struct of the Casdoor Go SDK.
23///
24/// The `organization_name` and `application_name` fields can also be written as
25/// `org_name` and `app_name` in a TOML file, so that the config files of the 1.x
26/// versions of this SDK keep working.
27#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
28pub struct AuthConfig {
29    /// Casdoor server URL, such as `http://localhost:8000`.
30    pub endpoint: String,
31    /// Client ID of the Casdoor application.
32    pub client_id: String,
33    /// Client secret of the Casdoor application.
34    pub client_secret: String,
35    /// The x509 certificate content of the Casdoor application, it's only used by
36    /// [`crate::Client::parse_jwt_token()`].
37    #[serde(default)]
38    pub certificate: String,
39    /// The name of the Casdoor organization.
40    #[serde(alias = "org_name")]
41    pub organization_name: String,
42    /// The name of the Casdoor application.
43    #[serde(default, alias = "app_name")]
44    pub application_name: String,
45}
46
47impl AuthConfig {
48    /// Create a new AuthConfig.
49    pub fn new(
50        endpoint: impl Into<String>,
51        client_id: impl Into<String>,
52        client_secret: impl Into<String>,
53        certificate: impl Into<String>,
54        organization_name: impl Into<String>,
55        application_name: impl Into<String>,
56    ) -> Self {
57        Self {
58            endpoint: endpoint.into(),
59            client_id: client_id.into(),
60            client_secret: client_secret.into(),
61            certificate: certificate.into(),
62            organization_name: organization_name.into(),
63            application_name: application_name.into(),
64        }
65    }
66
67    /// Create a new AuthConfig from a TOML file, the path should be an absolute path.
68    ///
69    /// ```toml
70    /// endpoint = "http://localhost:8000"
71    /// client_id = "0e5b3fdbc2ba7b04a000"
72    /// client_secret = "1b5b3fdbc2ba7b04a0000f5b3fdbc2ba7b04a000"
73    /// certificate = """
74    /// -----BEGIN CERTIFICATE-----
75    /// ...
76    /// -----END CERTIFICATE-----
77    /// """
78    /// organization_name = "built-in"
79    /// application_name = "app-built-in"
80    /// ```
81    pub fn from_toml(path: &str) -> Result<Self> {
82        let content =
83            fs::read_to_string(path).map_err(|e| CasdoorError::Config(format!("{path}: {e}")))?;
84
85        toml::from_str(&content).map_err(|e| CasdoorError::Config(format!("{path}: {e}")))
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use std::fs;
92
93    use super::*;
94
95    fn write_config(name: &str, content: &str) -> String {
96        let path = std::env::temp_dir().join(name);
97        fs::write(&path, content).unwrap();
98
99        path.to_str().unwrap().to_string()
100    }
101
102    #[test]
103    fn from_toml_reads_the_config_file() {
104        let path = write_config(
105            "casdoor-rust-sdk-config.toml",
106            r#"
107            endpoint = "http://localhost:8000"
108            client_id = "client-id"
109            client_secret = "client-secret"
110            certificate = "certificate"
111            organization_name = "built-in"
112            application_name = "app-built-in"
113            "#,
114        );
115
116        let config = AuthConfig::from_toml(&path).unwrap();
117
118        assert_eq!(config.endpoint, "http://localhost:8000");
119        assert_eq!(config.organization_name, "built-in");
120        assert_eq!(config.application_name, "app-built-in");
121    }
122
123    #[test]
124    fn from_toml_still_reads_the_config_file_of_the_1_x_versions() {
125        let path = write_config(
126            "casdoor-rust-sdk-legacy-config.toml",
127            r#"
128            endpoint = "http://localhost:8000"
129            client_id = "client-id"
130            client_secret = "client-secret"
131            certificate = "certificate"
132            org_name = "built-in"
133            app_name = "app-built-in"
134            "#,
135        );
136
137        let config = AuthConfig::from_toml(&path).unwrap();
138
139        assert_eq!(config.organization_name, "built-in");
140        assert_eq!(config.application_name, "app-built-in");
141    }
142
143    #[test]
144    fn from_toml_reports_the_path_of_a_missing_config_file() {
145        let error = AuthConfig::from_toml("no-such-conf.toml").unwrap_err();
146        assert!(error.to_string().contains("no-such-conf.toml"));
147    }
148}