smbcloud-auth 0.3.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Cargo.toml ADDED
@@ -0,0 +1,7 @@
1
+ # This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is
2
+ # a Rust project. Your extensions dependencies should be added to the Cargo.toml
3
+ # in the ext/ directory.
4
+
5
+ [workspace]
6
+ members = ["./ext/auth"]
7
+ resolver = "2"
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # smbcloud-auth Gem
2
+
3
+ Ruby bindings for the smbCloud Auth SDK.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ gem install smbcloud-auth
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ruby
14
+ require "auth"
15
+
16
+ client = SmbCloud::Auth::Client.new(
17
+ environment: SmbCloud::Auth::Environment::PRODUCTION,
18
+ app_id: "app-id",
19
+ app_secret: "app-secret"
20
+ )
21
+
22
+ signup = client.signup(
23
+ email: "name@example.com",
24
+ password: "password123"
25
+ )
26
+
27
+ login = client.login(
28
+ email: "name@example.com",
29
+ password: "password123"
30
+ )
31
+
32
+ me = client.me(access_token: login[:access_token])
33
+ ```
34
+
35
+ ## API
36
+
37
+ `SmbCloud::Auth::Client` exposes:
38
+
39
+ - `signup(email:, password:)`
40
+ - `login(email:, password:)`
41
+ - `me(access_token:)`
42
+ - `logout(access_token:)`
43
+ - `remove(access_token:)`
44
+
45
+ For simple scripting, module-level convenience wrappers are also available:
46
+
47
+ - `SmbCloud::Auth.signup_with_client(...)`
48
+ - `SmbCloud::Auth.login_with_client(...)`
49
+ - `SmbCloud::Auth.me_with_client(...)`
50
+ - `SmbCloud::Auth.logout_with_client(...)`
51
+ - `SmbCloud::Auth.remove_with_client(...)`
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rb_sys/extensiontask'
5
+
6
+ task build: :compile
7
+
8
+ GEMSPEC = Gem::Specification.load('auth.gemspec')
9
+
10
+ RbSys::ExtensionTask.new('auth', GEMSPEC) do |ext|
11
+ ext.lib_dir = 'lib/auth'
12
+ end
13
+
14
+ task default: :compile
data/ext/.keep ADDED
File without changes
@@ -0,0 +1,19 @@
1
+ [package]
2
+ name = "auth"
3
+ version = "0.3.33"
4
+ edition = "2024"
5
+ authors = ["Seto Elkahfi <hej@setoelkahfi.se>"]
6
+ publish = false
7
+
8
+ [lib]
9
+ crate-type = ["cdylib"]
10
+
11
+ [dependencies]
12
+ magnus = { version = "0.7.1" }
13
+ serde = { version = "1", features = ["derive"] }
14
+ serde_json = "1"
15
+ tokio = { version = "1", features = ["rt-multi-thread"] }
16
+ smbcloud-auth = { path = "./../../../../../crates/smbcloud-auth" }
17
+ smbcloud-model = { path = "./../../../../../crates/smbcloud-model" }
18
+ smbcloud-network = { path = "./../../../../../crates/smbcloud-network" }
19
+ smbcloud-networking = { path = "./../../../../../crates/smbcloud-networking" }
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mkmf'
4
+ require 'rb_sys/mkmf'
5
+
6
+ create_rust_makefile('auth/auth')
@@ -0,0 +1,209 @@
1
+ use magnus::{Error, Ruby, function, prelude::*};
2
+ use serde::Serialize;
3
+ use smbcloud_auth::{
4
+ client_credentials::ClientCredentials, login::login_with_client, logout::logout_with_client,
5
+ me::me_with_client, remove::remove_with_client, signup::signup_with_client,
6
+ };
7
+ use smbcloud_model::{error_codes::ErrorResponse, login::AccountStatus, signup::SignupResult};
8
+ use smbcloud_network::environment::Environment;
9
+ use tokio::runtime::Runtime;
10
+
11
+ #[derive(Serialize)]
12
+ struct LoginPayload {
13
+ status: &'static str,
14
+ access_token: Option<String>,
15
+ error_code: Option<i32>,
16
+ message: Option<String>,
17
+ }
18
+
19
+ fn parse_environment(value: String) -> Result<Environment, Error> {
20
+ value.parse().map_err(|_| {
21
+ Error::new(
22
+ magnus::exception::arg_error(),
23
+ format!("invalid environment `{value}`, expected `dev` or `production`"),
24
+ )
25
+ })
26
+ }
27
+
28
+ fn with_runtime<T, F>(f: F) -> Result<T, Error>
29
+ where
30
+ F: FnOnce(&Runtime) -> Result<T, Error>,
31
+ {
32
+ let runtime = Runtime::new().map_err(|err| {
33
+ Error::new(
34
+ magnus::exception::runtime_error(),
35
+ format!("failed to initialize tokio runtime: {err}"),
36
+ )
37
+ })?;
38
+ f(&runtime)
39
+ }
40
+
41
+ fn to_json<T: Serialize>(value: &T) -> Result<String, Error> {
42
+ serde_json::to_string(value).map_err(|err| {
43
+ Error::new(
44
+ magnus::exception::runtime_error(),
45
+ format!("failed to serialize response: {err}"),
46
+ )
47
+ })
48
+ }
49
+
50
+ fn raise_error_response(error: ErrorResponse) -> Error {
51
+ let payload = serde_json::to_string(&error).unwrap_or_else(|_| {
52
+ "{\"error\":{\"error_code\":0,\"message\":\"Unknown error.\"}}".to_string()
53
+ });
54
+ Error::new(magnus::exception::runtime_error(), payload)
55
+ }
56
+
57
+ fn login_payload(status: AccountStatus) -> LoginPayload {
58
+ match status {
59
+ AccountStatus::NotFound => LoginPayload {
60
+ status: "not_found",
61
+ access_token: None,
62
+ error_code: None,
63
+ message: None,
64
+ },
65
+ AccountStatus::Ready { access_token } => LoginPayload {
66
+ status: "ready",
67
+ access_token: Some(access_token),
68
+ error_code: None,
69
+ message: None,
70
+ },
71
+ AccountStatus::Incomplete { status } => LoginPayload {
72
+ status: "incomplete",
73
+ access_token: None,
74
+ error_code: Some(status as i32),
75
+ message: Some(status.to_string()),
76
+ },
77
+ }
78
+ }
79
+
80
+ fn credentials<'a>(app_id: &'a str, app_secret: &'a str) -> ClientCredentials<'a> {
81
+ ClientCredentials { app_id, app_secret }
82
+ }
83
+
84
+ fn signup_with_client_json(
85
+ environment: String,
86
+ app_id: String,
87
+ app_secret: String,
88
+ email: String,
89
+ password: String,
90
+ ) -> Result<String, Error> {
91
+ let env = parse_environment(environment)?;
92
+ with_runtime(|runtime| {
93
+ let result: Result<SignupResult, ErrorResponse> = runtime.block_on(signup_with_client(
94
+ env,
95
+ credentials(&app_id, &app_secret),
96
+ email,
97
+ password,
98
+ ));
99
+ match result {
100
+ Ok(result) => to_json(&result),
101
+ Err(error) => Err(raise_error_response(error)),
102
+ }
103
+ })
104
+ }
105
+
106
+ fn login_with_client_json(
107
+ environment: String,
108
+ app_id: String,
109
+ app_secret: String,
110
+ email: String,
111
+ password: String,
112
+ ) -> Result<String, Error> {
113
+ let env = parse_environment(environment)?;
114
+ with_runtime(|runtime| {
115
+ let result: Result<AccountStatus, ErrorResponse> = runtime.block_on(login_with_client(
116
+ env,
117
+ credentials(&app_id, &app_secret),
118
+ email,
119
+ password,
120
+ ));
121
+ match result {
122
+ Ok(result) => to_json(&login_payload(result)),
123
+ Err(error) => Err(raise_error_response(error)),
124
+ }
125
+ })
126
+ }
127
+
128
+ fn me_with_client_json(
129
+ environment: String,
130
+ app_id: String,
131
+ app_secret: String,
132
+ access_token: String,
133
+ ) -> Result<String, Error> {
134
+ let env = parse_environment(environment)?;
135
+ with_runtime(|runtime| {
136
+ let result = runtime.block_on(me_with_client(
137
+ env,
138
+ credentials(&app_id, &app_secret),
139
+ &access_token,
140
+ ));
141
+ match result {
142
+ Ok(result) => to_json(&result),
143
+ Err(error) => Err(raise_error_response(error)),
144
+ }
145
+ })
146
+ }
147
+
148
+ fn logout_with_client_json(
149
+ environment: String,
150
+ app_id: String,
151
+ app_secret: String,
152
+ access_token: String,
153
+ ) -> Result<bool, Error> {
154
+ let env = parse_environment(environment)?;
155
+ with_runtime(|runtime| {
156
+ let result = runtime.block_on(logout_with_client(
157
+ env,
158
+ credentials(&app_id, &app_secret),
159
+ access_token,
160
+ ));
161
+ match result {
162
+ Ok(()) => Ok(true),
163
+ Err(error) => Err(raise_error_response(error)),
164
+ }
165
+ })
166
+ }
167
+
168
+ fn remove_with_client_json(
169
+ environment: String,
170
+ app_id: String,
171
+ app_secret: String,
172
+ access_token: String,
173
+ ) -> Result<bool, Error> {
174
+ let env = parse_environment(environment)?;
175
+ with_runtime(|runtime| {
176
+ let result = runtime.block_on(remove_with_client(
177
+ env,
178
+ credentials(&app_id, &app_secret),
179
+ &access_token,
180
+ ));
181
+ match result {
182
+ Ok(()) => Ok(true),
183
+ Err(error) => Err(raise_error_response(error)),
184
+ }
185
+ })
186
+ }
187
+
188
+ #[magnus::init]
189
+ fn init(ruby: &Ruby) -> Result<(), Error> {
190
+ let smbcloud = ruby.define_module("SmbCloud")?;
191
+ let auth = smbcloud.define_module("Auth")?;
192
+
193
+ auth.define_singleton_method(
194
+ "__signup_with_client",
195
+ function!(signup_with_client_json, 5),
196
+ )?;
197
+ auth.define_singleton_method("__login_with_client", function!(login_with_client_json, 5))?;
198
+ auth.define_singleton_method("__me_with_client", function!(me_with_client_json, 4))?;
199
+ auth.define_singleton_method(
200
+ "__logout_with_client",
201
+ function!(logout_with_client_json, 4),
202
+ )?;
203
+ auth.define_singleton_method(
204
+ "__remove_with_client",
205
+ function!(remove_with_client_json, 4),
206
+ )?;
207
+
208
+ Ok(())
209
+ }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Auth
4
+ VERSION = '0.3.33'
5
+ end
data/lib/auth.rb ADDED
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative 'auth/version'
5
+ require_relative 'auth/auth'
6
+
7
+ module Auth
8
+ end
9
+
10
+ module SmbCloud
11
+ module Auth
12
+ class Error < StandardError
13
+ attr_reader :error_code, :payload
14
+
15
+ def initialize(message = nil, error_code: nil, payload: nil)
16
+ super(message)
17
+ @error_code = error_code
18
+ @payload = payload
19
+ end
20
+ end
21
+
22
+ module Environment
23
+ DEV = 'dev'
24
+ PRODUCTION = 'production'
25
+ end
26
+
27
+ class Client
28
+ attr_reader :environment, :app_id, :app_secret
29
+
30
+ def initialize(environment:, app_id:, app_secret:)
31
+ @environment = environment
32
+ @app_id = app_id
33
+ @app_secret = app_secret
34
+ end
35
+
36
+ def signup(email:, password:)
37
+ Auth.send(:parse_json, Auth.__signup_with_client(environment, app_id, app_secret, email, password))
38
+ rescue RuntimeError => e
39
+ raise Auth.send(:normalize_error, e)
40
+ end
41
+
42
+ def login(email:, password:)
43
+ Auth.send(:parse_json, Auth.__login_with_client(environment, app_id, app_secret, email, password))
44
+ rescue RuntimeError => e
45
+ raise Auth.send(:normalize_error, e)
46
+ end
47
+
48
+ def me(access_token:)
49
+ Auth.send(:parse_json, Auth.__me_with_client(environment, app_id, app_secret, access_token))
50
+ rescue RuntimeError => e
51
+ raise Auth.send(:normalize_error, e)
52
+ end
53
+
54
+ def logout(access_token:)
55
+ Auth.__logout_with_client(environment, app_id, app_secret, access_token)
56
+ rescue RuntimeError => e
57
+ raise Auth.send(:normalize_error, e)
58
+ end
59
+
60
+ def remove(access_token:)
61
+ Auth.__remove_with_client(environment, app_id, app_secret, access_token)
62
+ rescue RuntimeError => e
63
+ raise Auth.send(:normalize_error, e)
64
+ end
65
+ end
66
+
67
+ class << self
68
+ def client(environment:, app_id:, app_secret:)
69
+ Client.new(environment:, app_id:, app_secret:)
70
+ end
71
+
72
+ def signup_with_client(environment:, app_id:, app_secret:, email:, password:)
73
+ client(environment:, app_id:, app_secret:).signup(email:, password:)
74
+ end
75
+
76
+ def login_with_client(environment:, app_id:, app_secret:, email:, password:)
77
+ client(environment:, app_id:, app_secret:).login(email:, password:)
78
+ end
79
+
80
+ def me_with_client(environment:, app_id:, app_secret:, access_token:)
81
+ client(environment:, app_id:, app_secret:).me(access_token:)
82
+ end
83
+
84
+ def logout_with_client(environment:, app_id:, app_secret:, access_token:)
85
+ client(environment:, app_id:, app_secret:).logout(access_token:)
86
+ end
87
+
88
+ def remove_with_client(environment:, app_id:, app_secret:, access_token:)
89
+ client(environment:, app_id:, app_secret:).remove(access_token:)
90
+ end
91
+
92
+ private
93
+
94
+ def parse_json(payload)
95
+ return payload unless payload.is_a?(String)
96
+
97
+ JSON.parse(payload, symbolize_names: true)
98
+ end
99
+
100
+ def normalize_error(error)
101
+ payload = parse_json(error.message)
102
+ error_hash = payload[:error] || payload
103
+ message = error_hash[:message] || error.message
104
+ error_code = error_hash[:error_code]
105
+ Error.new(message, error_code: error_code, payload: payload)
106
+ rescue JSON::ParserError, NoMethodError, TypeError
107
+ Error.new(error.message)
108
+ end
109
+ end
110
+ end
111
+ end
data/sig/auth.rbs ADDED
@@ -0,0 +1,37 @@
1
+ module Auth
2
+ VERSION: String
3
+ end
4
+
5
+ module SmbCloud
6
+ module Auth
7
+ class Error < StandardError
8
+ attr_reader error_code: Integer?
9
+ attr_reader payload: untyped
10
+ end
11
+
12
+ module Environment
13
+ DEV: String
14
+ PRODUCTION: String
15
+ end
16
+
17
+ class Client
18
+ attr_reader environment: String
19
+ attr_reader app_id: String
20
+ attr_reader app_secret: String
21
+
22
+ def initialize: (environment: String, app_id: String, app_secret: String) -> void
23
+ def signup: (email: String, password: String) -> Hash[Symbol, untyped]
24
+ def login: (email: String, password: String) -> Hash[Symbol, untyped]
25
+ def me: (access_token: String) -> Hash[Symbol, untyped]
26
+ def logout: (access_token: String) -> bool
27
+ def remove: (access_token: String) -> bool
28
+ end
29
+
30
+ def self.client: (environment: String, app_id: String, app_secret: String) -> Client
31
+ def self.signup_with_client: (environment: String, app_id: String, app_secret: String, email: String, password: String) -> Hash[Symbol, untyped]
32
+ def self.login_with_client: (environment: String, app_id: String, app_secret: String, email: String, password: String) -> Hash[Symbol, untyped]
33
+ def self.me_with_client: (environment: String, app_id: String, app_secret: String, access_token: String) -> Hash[Symbol, untyped]
34
+ def self.logout_with_client: (environment: String, app_id: String, app_secret: String, access_token: String) -> bool
35
+ def self.remove_with_client: (environment: String, app_id: String, app_secret: String, access_token: String) -> bool
36
+ end
37
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smbcloud-auth
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.33
5
+ platform: ruby
6
+ authors:
7
+ - Seto Elkahfi
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: json
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rb_sys
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.91
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.9.91
40
+ description: Ruby bindings for smbCloud Auth, powered by the shared Rust SDK and a
41
+ native Magnus extension.
42
+ email:
43
+ - hej@setoelkahfi.se
44
+ executables: []
45
+ extensions:
46
+ - ext/auth/extconf.rb
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".ruby-version"
50
+ - CHANGELOG.md
51
+ - Cargo.lock
52
+ - Cargo.toml
53
+ - README.md
54
+ - Rakefile
55
+ - ext/.keep
56
+ - ext/auth/Cargo.toml
57
+ - ext/auth/extconf.rb
58
+ - ext/auth/src/lib.rs
59
+ - lib/auth.rb
60
+ - lib/auth/version.rb
61
+ - sig/auth.rbs
62
+ homepage: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/auth
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ allowed_push_host: https://rubygems.org
67
+ homepage_uri: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/auth
68
+ source_code_uri: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/auth
69
+ changelog_uri: https://github.com/smbcloudXYZ/smbcloud-cli/tree/main/sdk/gems/auth/CHANGELOG.md
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 3.1.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 3.3.11
83
+ requirements: []
84
+ rubygems_version: 3.7.2
85
+ specification_version: 4
86
+ summary: Ruby bindings for the smbCloud Auth SDK.
87
+ test_files: []