monitorsys-tortoise 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a22b515d2230d4ac946ff83c32959e1134c75fdc195d8f0cef84bdb996188094
4
+ data.tar.gz: ca75ae43d89a6269ca8ac0b0c141f1c31d3560d44398f0829428fb5e0e5629be
5
+ SHA512:
6
+ metadata.gz: b8dd9736b5ae0aec278e9956ac467ac692b250807314653dcb20fb76dfda0a74a319d864752c60bc023109cbb73cd578bc9847791e191c9d2bd97ffea406da0b
7
+ data.tar.gz: 5800935537a43d9018965d222565a6af0415626a7e48023cad1eab9c541d2a779789098e509ab820b33248b7d4b677d0a54c76df58afcd7484cbd11d320b2241
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /bin/setup
10
+ tortoise_production
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in tortoise.gemspec
4
+ gemspec
5
+
6
+ gem 'rake', '~> 12.0'
7
+
8
+ gem 'listen'
9
+ gem 'rest-client'
10
+ gem 'sqlite3'
11
+ gem 'activerecord'
12
+ gem 'fileutils'
13
+ gem 'mini_cache'
14
+ gem 'honeybadger'
@@ -0,0 +1,72 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tortoise (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ activemodel (6.1.0)
10
+ activesupport (= 6.1.0)
11
+ activerecord (6.1.0)
12
+ activemodel (= 6.1.0)
13
+ activesupport (= 6.1.0)
14
+ activesupport (6.1.0)
15
+ concurrent-ruby (~> 1.0, >= 1.0.2)
16
+ i18n (>= 1.6, < 2)
17
+ minitest (>= 5.1)
18
+ tzinfo (~> 2.0)
19
+ zeitwerk (~> 2.3)
20
+ concurrent-ruby (1.1.7)
21
+ domain_name (0.5.20190701)
22
+ unf (>= 0.0.5, < 1.0.0)
23
+ ffi (1.14.1)
24
+ fileutils (1.4.1)
25
+ honeybadger (4.7.2)
26
+ http-accept (1.7.0)
27
+ http-cookie (1.0.3)
28
+ domain_name (~> 0.5)
29
+ i18n (1.8.5)
30
+ concurrent-ruby (~> 1.0)
31
+ listen (3.3.3)
32
+ rb-fsevent (~> 0.10, >= 0.10.3)
33
+ rb-inotify (~> 0.9, >= 0.9.10)
34
+ mime-types (3.3.1)
35
+ mime-types-data (~> 3.2015)
36
+ mime-types-data (3.2020.1104)
37
+ mini_cache (1.1.0)
38
+ minitest (5.14.2)
39
+ netrc (0.11.0)
40
+ rake (12.3.3)
41
+ rb-fsevent (0.10.4)
42
+ rb-inotify (0.10.1)
43
+ ffi (~> 1.0)
44
+ rest-client (2.1.0)
45
+ http-accept (>= 1.7.0, < 2.0)
46
+ http-cookie (>= 1.0.2, < 2.0)
47
+ mime-types (>= 1.16, < 4.0)
48
+ netrc (~> 0.8)
49
+ sqlite3 (1.4.2)
50
+ tzinfo (2.0.4)
51
+ concurrent-ruby (~> 1.0)
52
+ unf (0.1.4)
53
+ unf_ext
54
+ unf_ext (0.0.7.7)
55
+ zeitwerk (2.4.2)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ activerecord
62
+ fileutils
63
+ honeybadger
64
+ listen
65
+ mini_cache
66
+ rake (~> 12.0)
67
+ rest-client
68
+ sqlite3
69
+ tortoise!
70
+
71
+ BUNDLED WITH
72
+ 2.1.4
@@ -0,0 +1,36 @@
1
+ # Tortoise
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/tortoise`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'tortoise'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install tortoise
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/joaomangilli/tortoise.
36
+
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ import 'lib/tasks/migrate.rake'
3
+
4
+ task :default => :spec
@@ -0,0 +1,43 @@
1
+ require 'bundler/setup'
2
+ require 'irb'
3
+ require 'tortoise'
4
+ require 'io/console'
5
+
6
+ def get_response(answer, default: nil, password: false)
7
+ puts "#{answer} (#{default || 'n/a'}): "
8
+ chomp(password).presence || default
9
+ end
10
+
11
+ def chomp(password)
12
+ password ? STDIN.noecho(&:gets).chomp : gets.chomp
13
+ end
14
+
15
+ def create_directory
16
+ Tortoise::Directory.create!(folder_path: get_response('Digite o diretorio da pasta'))
17
+
18
+ create_directory if get_response('Deseja cadastrar outro diretorio?(S/N)').to_s.upcase == 'S'
19
+ end
20
+
21
+ def create_configuration
22
+ Tortoise::Configuration.create!(
23
+ api_path: ENV['TORTOISE_API_PATH'].to_s.strip,
24
+ token_path: ENV['TORTOISE_TOKEN_PATH'].to_s.strip,
25
+ upload_path: ENV['TORTOISE_UPLOAD_PATH'].to_s.strip,
26
+ public_informations_path: ENV['TORTOISE_PUBLIC_INFORMATIONS_PATH'].to_s.strip,
27
+ user: get_response('Digite o usuario'),
28
+ password: get_response('Digite a senha', password: true),
29
+ retry_time: ENV['TORTOISE_RETRY_TIME'].to_s.strip,
30
+ app_user: ENV['TORTOISE_APP_USER'].to_s.strip,
31
+ app_password: ENV['TORTOISE_APP_PASSWORD'].to_s.strip
32
+ )
33
+
34
+ Tortoise::InitialLoader.new.load
35
+ end
36
+
37
+ create_directory unless Tortoise::Configuration.exists?
38
+ create_configuration unless Tortoise::Configuration.exists?
39
+
40
+ Tortoise::Listener.new.start
41
+
42
+ # IRB.start(__FILE__)
43
+ sleep
@@ -0,0 +1,9 @@
1
+ require 'sqlite3'
2
+ require 'active_record'
3
+
4
+ ActiveRecord::Base.establish_connection(
5
+ adapter: 'sqlite3',
6
+ database: 'tortoise_production',
7
+ pool: 100,
8
+ timeout: 50000
9
+ )
@@ -0,0 +1,31 @@
1
+ require_relative '../../config/sqllite3'
2
+
3
+ namespace :tortoise do
4
+ namespace :db do
5
+ task :migrate do
6
+ ActiveRecord::Schema.define do
7
+ create_table :directories do |t|
8
+ t.string :folder_path
9
+ t.timestamps
10
+ end
11
+ create_table :configurations do |t|
12
+ t.string :api_path
13
+ t.string :token_path
14
+ t.string :upload_path
15
+ t.string :public_informations_path
16
+ t.string :user
17
+ t.string :password
18
+ t.integer :retry_time
19
+ t.string :app_user
20
+ t.string :app_password
21
+ t.timestamps
22
+ end
23
+ create_table :invoices do |t|
24
+ t.string :file
25
+ t.string :status
26
+ t.timestamps
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ require 'listen'
2
+ require 'rest-client'
3
+ require 'fileutils'
4
+ require 'mini_cache'
5
+ require 'honeybadger' unless ENV['HONEYBADGER_API_KEY'].to_s.empty?
6
+
7
+ require_relative '../config/sqllite3'
8
+ require_relative 'tortoise/jobs/upload_job'
9
+ require_relative 'tortoise/models/application_record'
10
+ require_relative 'tortoise/models/cache'
11
+ require_relative 'tortoise/models/configuration'
12
+ require_relative 'tortoise/models/directory'
13
+ require_relative 'tortoise/models/invoice'
14
+ require_relative 'tortoise/services/api_helper'
15
+ require_relative 'tortoise/services/bulk_loader'
16
+ require_relative 'tortoise/services/initial_loader'
17
+ require_relative 'tortoise/services/listener'
18
+ require_relative 'tortoise/services/loader'
19
+
20
+ module Tortoise
21
+
22
+ end
@@ -0,0 +1,37 @@
1
+ module Tortoise
2
+ class UploadJob
3
+ def perform(invoice_id, delay=0)
4
+ Thread.new do
5
+ sleep delay
6
+
7
+ invoice = Tortoise::Invoice.find(invoice_id)
8
+ invoice.update(status: Invoice::STARTED)
9
+
10
+ begin
11
+ api_helper.upload(invoice.file)
12
+ invoice.update(status: Invoice::DONE)
13
+
14
+ puts "A nota #{invoice.file} foi enviada com sucesso!"
15
+ rescue StandardError => e
16
+ puts "Um erro aconteceu!", e
17
+
18
+ Honeybadger.notify(e) unless ENV['HONEYBADGER_API_KEY'].to_s.empty?
19
+
20
+ invoice.update(status: Invoice::FAILED)
21
+
22
+ UploadJob.new.perform(invoice.id, configuration.default_retry_time)
23
+ end
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def api_helper
30
+ @api_helper ||= Tortoise::ApiHelper.new
31
+ end
32
+
33
+ def configuration
34
+ @configuration ||= Tortoise::Configuration.first_or_initialize
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,5 @@
1
+ module Tortoise
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Tortoise
2
+ class Cache
3
+ def self.get
4
+ @cache ||= MiniCache::Store.new
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,33 @@
1
+ module Tortoise
2
+ class Configuration < ApplicationRecord
3
+ def password=(password)
4
+ write_attribute(:password, crypt.encrypt_and_sign(password)) unless password.nil?
5
+ end
6
+
7
+ def password
8
+ crypt.decrypt_and_verify(read_attribute(:password)) unless read_attribute(:password).nil?
9
+ end
10
+
11
+ def app_password=(password)
12
+ write_attribute(:app_password, crypt.encrypt_and_sign(password)) unless password.nil?
13
+ end
14
+
15
+ def app_password
16
+ crypt.decrypt_and_verify(read_attribute(:app_password)) unless read_attribute(:app_password).nil?
17
+ end
18
+
19
+ def default_retry_time
20
+ (retry_time || 5).minutes
21
+ end
22
+
23
+ private
24
+
25
+ def crypt
26
+ @crypt ||= ActiveSupport::MessageEncryptor.new(crypt_key)
27
+ end
28
+
29
+ def crypt_key
30
+ [ENV['ENCRYPTOR_KEY'].to_s.strip].pack('H*')
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,15 @@
1
+ module Tortoise
2
+ class Directory < ApplicationRecord
3
+ after_save :create_folder
4
+
5
+ private
6
+
7
+ def create_folder
8
+ return if folder_path.nil?
9
+
10
+ unless File.directory?(folder_path)
11
+ FileUtils.mkdir_p(folder_path)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Tortoise
2
+ class Invoice < ApplicationRecord
3
+ STARTED = 'started'
4
+ DONE = 'done'
5
+ FAILED = 'failed'
6
+ end
7
+ end
@@ -0,0 +1,108 @@
1
+ module Tortoise
2
+ class ApiHelper
3
+ ACCESS_TOKEN_CACHE_KEY = 'access_token'
4
+ DATABASE_CACHE_KEY = 'database'
5
+ CACHE_EXPIRES = 60
6
+
7
+ def token
8
+ return cached_token unless cached_token.nil?
9
+ return if token_path.nil? || token_params.nil?
10
+
11
+ response = RestClient.post(
12
+ token_path,
13
+ token_params,
14
+ token_header
15
+ )
16
+
17
+ cache.set(
18
+ ACCESS_TOKEN_CACHE_KEY,
19
+ JSON.parse(response.body)['access_token'],
20
+ expires_in: CACHE_EXPIRES
21
+ )
22
+ end
23
+
24
+ def database
25
+ return cached_database unless cached_database.nil?
26
+ return if public_informations_path.nil?
27
+
28
+ response = RestClient.get(public_informations_path)
29
+ cache.set(
30
+ DATABASE_CACHE_KEY,
31
+ JSON.parse(response.body)['licensa']['database'],
32
+ expires_in: CACHE_EXPIRES
33
+ )
34
+ end
35
+
36
+ def upload(file)
37
+ return if upload_path.nil? || token.nil?
38
+
39
+ RestClient.post(
40
+ upload_path,
41
+ {
42
+ multipart: true,
43
+ file: File.new(file)
44
+ },
45
+ {
46
+ 'User-access' => database,
47
+ Authorization: "Bearer #{token}"
48
+ }
49
+ )
50
+ rescue RestClient::Exception => e
51
+ e.response
52
+ end
53
+
54
+ private
55
+
56
+ def cached_token
57
+ cache.get(ACCESS_TOKEN_CACHE_KEY)
58
+ end
59
+
60
+ def cached_database
61
+ cache.get(DATABASE_CACHE_KEY)
62
+ end
63
+
64
+ def cache
65
+ Tortoise::Cache.get
66
+ end
67
+
68
+ def token_params
69
+ return if configuration.user.nil? || configuration.password.nil?
70
+
71
+ {
72
+ username: configuration.user,
73
+ password: configuration.password,
74
+ grant_type: 'password'
75
+ }
76
+ end
77
+
78
+ def token_header
79
+ { Authorization: "Basic #{Base64::encode64(basic_auth)}" }
80
+ end
81
+
82
+ def basic_auth
83
+ "#{configuration.app_user}:#{configuration.app_password}"
84
+ end
85
+
86
+ def token_path
87
+ return if configuration.api_path.nil? || configuration.token_path.nil?
88
+
89
+ "#{configuration.api_path}#{configuration.token_path}"
90
+ end
91
+
92
+ def upload_path
93
+ return if configuration.api_path.nil? || configuration.upload_path.nil?
94
+
95
+ "#{configuration.api_path}#{configuration.upload_path}"
96
+ end
97
+
98
+ def public_informations_path
99
+ return if configuration.api_path.nil? || configuration.public_informations_path.nil?
100
+
101
+ "#{configuration.api_path}#{configuration.public_informations_path}"
102
+ end
103
+
104
+ def configuration
105
+ @configuration ||= Tortoise::Configuration.first_or_initialize
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,21 @@
1
+ module Tortoise
2
+ class BulkLoader
3
+ attr_reader :files
4
+
5
+ def initialize(files)
6
+ @files = files
7
+ end
8
+
9
+ def self.load(files)
10
+ new(files).load
11
+ rescue StandardError => e
12
+ Honeybadger.notify(e) unless ENV['HONEYBADGER_API_KEY'].to_s.empty?
13
+ end
14
+
15
+ def load
16
+ files.each do |file|
17
+ Tortoise::Loader.load(file)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Tortoise
2
+ class InitialLoader
3
+ def load
4
+ return if directories.empty?
5
+
6
+ Tortoise::BulkLoader.load(files)
7
+ end
8
+
9
+ private
10
+
11
+ def files
12
+ @files ||= directories.map do |directory|
13
+ Dir["#{directory}/*"].select { |f| File.file? f }
14
+ end.flatten.compact
15
+ end
16
+
17
+ def directories
18
+ @directories ||= Tortoise::Directory.pluck(:folder_path)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Tortoise
2
+ class Listener
3
+ def start
4
+ return if directories.empty?
5
+
6
+ listener.start
7
+ end
8
+
9
+ private
10
+
11
+ def listener
12
+ @listener ||= Listen.to(*directories) do |_m, added, _r|
13
+ Tortoise::BulkLoader.load(added)
14
+ end
15
+ end
16
+
17
+ def directories
18
+ @directories ||= Tortoise::Directory.pluck(:folder_path)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Tortoise
2
+ class Loader
3
+ attr_reader :file
4
+
5
+ def initialize(file)
6
+ @file = file
7
+ end
8
+
9
+ def self.load(file)
10
+ new(file).load
11
+ end
12
+
13
+ def load
14
+ return if exists?
15
+
16
+ Tortoise::UploadJob.new.perform(invoice.id)
17
+ end
18
+
19
+ private
20
+
21
+ def invoice
22
+ @invoice ||= Tortoise::Invoice.create!(file: file, status: Invoice::STARTED)
23
+ end
24
+
25
+ def exists?
26
+ Tortoise::Invoice.where(file: file).exists?
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module Tortoise
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'lib/tortoise/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'monitorsys-tortoise'
5
+ spec.version = Tortoise::VERSION
6
+ spec.authors = ['João Mangilli']
7
+ spec.email = ['joao-luis-mangilli@hotmail.com']
8
+
9
+ spec.summary = 'It is a gem for Fabio'
10
+ spec.homepage = 'http://monitorsys.com.br'
11
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
12
+
13
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
14
+
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
17
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monitorsys-tortoise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - João Mangilli
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-01-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - joao-luis-mangilli@hotmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - Gemfile
22
+ - Gemfile.lock
23
+ - README.md
24
+ - Rakefile
25
+ - bin/console
26
+ - config/sqllite3.rb
27
+ - lib/tasks/migrate.rake
28
+ - lib/tortoise.rb
29
+ - lib/tortoise/jobs/upload_job.rb
30
+ - lib/tortoise/models/application_record.rb
31
+ - lib/tortoise/models/cache.rb
32
+ - lib/tortoise/models/configuration.rb
33
+ - lib/tortoise/models/directory.rb
34
+ - lib/tortoise/models/invoice.rb
35
+ - lib/tortoise/services/api_helper.rb
36
+ - lib/tortoise/services/bulk_loader.rb
37
+ - lib/tortoise/services/initial_loader.rb
38
+ - lib/tortoise/services/listener.rb
39
+ - lib/tortoise/services/loader.rb
40
+ - lib/tortoise/version.rb
41
+ - tortoise.gemspec
42
+ homepage: http://monitorsys.com.br
43
+ licenses: []
44
+ metadata:
45
+ homepage_uri: http://monitorsys.com.br
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.3.0
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.1.4
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: It is a gem for Fabio
65
+ test_files: []