licensemanager-sdk 1.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 109085116bb45d1e2904e64567d7cee70a75d80561956198efef6c26e56bf2a7
4
+ data.tar.gz: 668141b8e9c77be6c348933816f078c1388afbe5db0e5ce233aa5ab6e22f3125
5
+ SHA512:
6
+ metadata.gz: 8d9a4981a412d9106de85d1f9247048e3f10607f35b7ff8fc3bba0d9ac5b8adfbea4d8bb3ebfb75569ee84f50580db03f581cb112da7881177ef1cf0c8d0ee3a
7
+ data.tar.gz: db6b0b4878e914ccde9add2dfe77760fe202bfd2a4517eb8deeee118ef29c4bf4acfac33ba333b6e4dc8951f4a4609223218c13e7def0c703c07a7d3581e9bdb
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # licensemanager-sdk — Ruby
2
+
3
+ SDK cliente para a API de validação do LicenseManager. Compatível com Ruby 3.0+ e Ruby on Rails.
4
+
5
+ ## Instalação
6
+
7
+ ```ruby
8
+ # Gemfile
9
+ gem "licensemanager-sdk"
10
+ ```
11
+
12
+ ```bash
13
+ bundle install
14
+ ```
15
+
16
+ Ou diretamente:
17
+
18
+ ```bash
19
+ gem install licensemanager-sdk
20
+ ```
21
+
22
+ ## Uso (Ruby puro)
23
+
24
+ ```ruby
25
+ require "licensemanager_sdk"
26
+
27
+ client = LicenseManagerSdk::Client.new(
28
+ base_url: "https://licensemanager-api.enzojb.com.br",
29
+ token: "seu-token",
30
+ license_id: "guid-da-licenca"
31
+ )
32
+
33
+ login = client.login("usuario@empresa.com")
34
+ if login.authorized
35
+ client.heartbeat(login.session_id)
36
+ client.logout(login.session_id)
37
+ end
38
+
39
+ inst = client.validate_installation("MACHINE-001")
40
+ puts "Instalação: #{inst.installation_id}" if inst.authorized
41
+ ```
42
+
43
+ ## Uso (Rails — initializer)
44
+
45
+ ```ruby
46
+ # config/initializers/licensemanager.rb
47
+ require "licensemanager_sdk"
48
+
49
+ LICENSE_CLIENT = LicenseManagerSdk::Client.new(
50
+ base_url: ENV.fetch("LICENSE_API_URL"),
51
+ token: ENV.fetch("LICENSE_TOKEN"),
52
+ license_id: ENV.fetch("LICENSE_ID")
53
+ )
54
+ ```
55
+
56
+ ## Testes
57
+
58
+ ```bash
59
+ bundle exec rspec
60
+ ```
@@ -0,0 +1,124 @@
1
+ module LicenseManagerSdk
2
+ # Cliente para a API de validação do LicenseManager.
3
+ # Encapsula geração de HMAC-SHA256 e os 4 endpoints de validação.
4
+ #
5
+ # @example Uso básico
6
+ # client = LicenseManagerSdk::Client.new(
7
+ # base_url: "https://licensemanager-api.enzojb.com.br",
8
+ # token: "seu-token",
9
+ # license_id: "guid-da-licenca"
10
+ # )
11
+ # login = client.login("usuario@empresa.com")
12
+ # client.heartbeat(login.session_id) if login.authorized
13
+ class Client
14
+ MAX_RETRIES = 3
15
+
16
+ def initialize(base_url:, token:, license_id:, timeout: 30)
17
+ raise ArgumentError, "base_url é obrigatório" if base_url.nil? || base_url.strip.empty?
18
+ raise ArgumentError, "token é obrigatório" if token.nil? || token.strip.empty?
19
+ raise ArgumentError, "license_id é obrigatório" if license_id.nil? || license_id.strip.empty?
20
+
21
+ @base_url = base_url.chomp("/")
22
+ @token = token
23
+ @license_id = license_id
24
+ @timeout = timeout
25
+ end
26
+
27
+ # Valida login de um usuário numa licença.
28
+ # @param user_id [String] identificador único do usuário
29
+ # @return [LoginResult]
30
+ def login(user_id)
31
+ body = { idLicenca: @license_id, identificadorUsuario: user_id }
32
+ data = post("api/validacao/login", body)
33
+ LoginResult.new(
34
+ authorized: data["autorizado"] || false,
35
+ session_id: data["idSessao"]
36
+ )
37
+ end
38
+
39
+ # Envia heartbeat para manter a sessão ativa.
40
+ # @param session_id [String]
41
+ def heartbeat(session_id)
42
+ body = { idLicenca: @license_id, idSessao: session_id }
43
+ post("api/validacao/heartbeat", body)
44
+ nil
45
+ end
46
+
47
+ # Encerra a sessão (idempotente).
48
+ # @param session_id [String]
49
+ def logout(session_id)
50
+ body = { idLicenca: @license_id, idSessao: session_id }
51
+ post("api/validacao/logout", body)
52
+ nil
53
+ end
54
+
55
+ # Valida ou registra uma instalação da aplicação cliente.
56
+ # @param machine_id [String] identificador único da máquina
57
+ # @return [InstallationResult]
58
+ def validate_installation(machine_id)
59
+ body = { idLicenca: @license_id, identificadorMaquina: machine_id }
60
+ data = post("api/validacao/instalacao", body)
61
+ InstallationResult.new(
62
+ authorized: data["autorizado"] || false,
63
+ installation_id: data["idInstalacao"],
64
+ already_registered: data["jaRegistrada"] || false
65
+ )
66
+ end
67
+
68
+ # @api private
69
+ def compute_signature(license_id, timestamp, body_json)
70
+ payload = "#{license_id}:#{timestamp}:#{body_json}"
71
+ OpenSSL::HMAC.hexdigest("SHA256", @token, payload)
72
+ end
73
+
74
+ private
75
+
76
+ def post(path, body)
77
+ body_json = JSON.generate(body)
78
+ timestamp = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
79
+ nonce = SecureRandom.hex(16)
80
+ signature = compute_signature(@license_id, timestamp, body_json)
81
+
82
+ uri = URI.parse("#{@base_url}/#{path}")
83
+ headers = {
84
+ "Content-Type" => "application/json",
85
+ "X-Token" => @token,
86
+ "X-Timestamp" => timestamp,
87
+ "X-Nonce" => nonce,
88
+ "X-Signature" => signature
89
+ }
90
+
91
+ last_error = nil
92
+ MAX_RETRIES.times do |attempt|
93
+ begin
94
+ http = Net::HTTP.new(uri.host, uri.port)
95
+ http.use_ssl = uri.scheme == "https"
96
+ http.read_timeout = @timeout
97
+ http.open_timeout = @timeout
98
+
99
+ response = http.post(uri.request_uri, body_json, headers)
100
+ code = response.code.to_i
101
+
102
+ if (code == 429 || code >= 500) && attempt < MAX_RETRIES - 1
103
+ sleep(2**attempt)
104
+ next
105
+ end
106
+
107
+ unless response.is_a?(Net::HTTPSuccess)
108
+ raise LicenseManagerError.new(code, response.body.to_s)
109
+ end
110
+
111
+ body = response.body
112
+ return (body.nil? || body.empty?) ? {} : JSON.parse(body)
113
+ rescue LicenseManagerError
114
+ raise
115
+ rescue StandardError => e
116
+ last_error = e
117
+ sleep(2**attempt) if attempt < MAX_RETRIES - 1
118
+ end
119
+ end
120
+
121
+ raise LicenseManagerError.new(0, "Erro de rede: #{last_error&.message}")
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,11 @@
1
+ module LicenseManagerSdk
2
+ class LicenseManagerError < StandardError
3
+ attr_reader :status_code, :response_body
4
+
5
+ def initialize(status_code, response_body)
6
+ super("LicenseManager API error #{status_code}: #{response_body}")
7
+ @status_code = status_code
8
+ @response_body = response_body
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module LicenseManagerSdk
2
+ LoginResult = Struct.new(:authorized, :session_id, keyword_init: true)
3
+ InstallationResult = Struct.new(:authorized, :installation_id, :already_registered, keyword_init: true)
4
+ end
@@ -0,0 +1,3 @@
1
+ module LicenseManagerSdk
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,11 @@
1
+ require "net/http"
2
+ require "json"
3
+ require "openssl"
4
+ require "securerandom"
5
+ require "time"
6
+ require "uri"
7
+
8
+ require_relative "licensemanager_sdk/version"
9
+ require_relative "licensemanager_sdk/errors"
10
+ require_relative "licensemanager_sdk/models"
11
+ require_relative "licensemanager_sdk/client"
@@ -0,0 +1,13 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "licensemanager-sdk"
3
+ spec.version = "1.0.0"
4
+ spec.authors = ["LicenciamentoSoftware"]
5
+ spec.summary = "SDK cliente para a API de validação do LicenseManager"
6
+ spec.description = "Encapsula autenticação HMAC-SHA256 e os endpoints de validação de licença."
7
+ spec.homepage = "https://github.com/carloscampos2014/LicenciamentoSoftware"
8
+ spec.license = "MIT"
9
+ spec.required_ruby_version = ">= 3.0.0"
10
+
11
+ spec.files = Dir["lib/**/*.rb", "README.md", "licensemanager_sdk.gemspec"]
12
+ spec.require_paths = ["lib"]
13
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: licensemanager-sdk
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - LicenciamentoSoftware
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-08-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Encapsula autenticação HMAC-SHA256 e os endpoints de validação de licença.
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - README.md
20
+ - lib/licensemanager_sdk.rb
21
+ - lib/licensemanager_sdk/client.rb
22
+ - lib/licensemanager_sdk/errors.rb
23
+ - lib/licensemanager_sdk/models.rb
24
+ - lib/licensemanager_sdk/version.rb
25
+ - licensemanager_sdk.gemspec
26
+ homepage: https://github.com/carloscampos2014/LicenciamentoSoftware
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: 3.0.0
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubygems_version: 3.5.22
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: SDK cliente para a API de validação do LicenseManager
49
+ test_files: []