reivt 1.6.0 → 1.6.1
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 +4 -4
- data/Gemfile +11 -11
- data/README.md +5 -2
- data/Rakefile +22 -22
- data/bin/console +9 -9
- data/exe/revit +5 -5
- data/lib/reivt/api/mutations/document_create.mutation.rb +50 -50
- data/lib/reivt/api/mutations/document_delete.mutation.rb +36 -36
- data/lib/reivt/api/mutations/rev_create.mutation.rb +38 -38
- data/lib/reivt/api/mutations/rev_delete.mutation.rb +36 -36
- data/lib/reivt/api/mutations/user_create.mutation.rb +32 -32
- data/lib/reivt/api/mutations/user_signin.mutation.rb +39 -39
- data/lib/reivt/api.rb +64 -64
- data/lib/reivt/auth.rb +94 -96
- data/lib/reivt/cli.rb +167 -167
- data/lib/reivt/document.rb +67 -67
- data/lib/reivt/exception.rb +52 -48
- data/lib/reivt/util.rb +113 -112
- data/lib/reivt/version.rb +3 -3
- data/lib/reivt.rb +42 -42
- data/revit.gemspec +44 -44
- metadata +2 -2
data/lib/reivt/api.rb
CHANGED
@@ -1,64 +1,64 @@
|
|
1
|
-
require 'graphql/client'
|
2
|
-
require 'graphql/client/http'
|
3
|
-
|
4
|
-
require 'pp'
|
5
|
-
|
6
|
-
# An extension of our main module Reivt
|
7
|
-
#
|
8
|
-
# @author [brwnrclse]
|
9
|
-
#
|
10
|
-
module Reivt
|
11
|
-
# Intrface for rev API, connects local changes with our remote.
|
12
|
-
#
|
13
|
-
# @author [brwnrclse]
|
14
|
-
#
|
15
|
-
module RevAPI
|
16
|
-
SCHEMA_PATH = "#{Dir.pwd}/lib/reivt/schema/schema.json".freeze
|
17
|
-
ENDPOINT_URL = 'https://api.graph.cool/simple/v1/revwver'.freeze
|
18
|
-
ENDPOINT = GraphQL::Client::HTTP.new(ENDPOINT_URL) do
|
19
|
-
def headers(_context)
|
20
|
-
auth_token = Reivt::REIVT_STORE.transaction do |store|
|
21
|
-
store.fetch(:auth0_id, nil)
|
22
|
-
end
|
23
|
-
|
24
|
-
{ 'Authorization': "Bearer #{auth_token}" }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
ID_TOKEN = Reivt::REIVT_STORE.transaction do |store|
|
29
|
-
store.fetch(:user_id, nil)
|
30
|
-
end
|
31
|
-
|
32
|
-
unless File.exist?(SCHEMA_PATH)
|
33
|
-
GraphQL::Client.dump_schema(ENDPOINT, SCHEMA_PATH)
|
34
|
-
end
|
35
|
-
|
36
|
-
SCHEMA = GraphQL::Client.load_schema(SCHEMA_PATH)
|
37
|
-
CLIENT = GraphQL::Client.new(schema: SCHEMA, execute: ENDPOINT)
|
38
|
-
|
39
|
-
# Raise any errors in the response data or simply return the data
|
40
|
-
#
|
41
|
-
# @param api_response [Obj] A nested object containing either data or errors
|
42
|
-
#
|
43
|
-
# @return [Array] A list containing the data and error object from the req
|
44
|
-
#
|
45
|
-
def self.retrieve(api_response)
|
46
|
-
errors = api_response.errors
|
47
|
-
data = api_response.data
|
48
|
-
|
49
|
-
if data.nil?
|
50
|
-
msg = errors.details[:data].map { |error| error['message'] }
|
51
|
-
raise Reivt::GraphQLDataException, msg.join(",\n")
|
52
|
-
else
|
53
|
-
data
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
require_relative 'api/mutations/document_create.mutation'
|
60
|
-
require_relative 'api/mutations/document_delete.mutation'
|
61
|
-
require_relative 'api/mutations/rev_create.mutation'
|
62
|
-
require_relative 'api/mutations/rev_delete.mutation'
|
63
|
-
require_relative 'api/mutations/user_create.mutation'
|
64
|
-
require_relative 'api/mutations/user_signin.mutation'
|
1
|
+
require 'graphql/client'
|
2
|
+
require 'graphql/client/http'
|
3
|
+
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
# An extension of our main module Reivt
|
7
|
+
#
|
8
|
+
# @author [brwnrclse]
|
9
|
+
#
|
10
|
+
module Reivt
|
11
|
+
# Intrface for rev API, connects local changes with our remote.
|
12
|
+
#
|
13
|
+
# @author [brwnrclse]
|
14
|
+
#
|
15
|
+
module RevAPI
|
16
|
+
SCHEMA_PATH = "#{Dir.pwd}/lib/reivt/schema/schema.json".freeze
|
17
|
+
ENDPOINT_URL = 'https://api.graph.cool/simple/v1/revwver'.freeze
|
18
|
+
ENDPOINT = GraphQL::Client::HTTP.new(ENDPOINT_URL) do
|
19
|
+
def headers(_context)
|
20
|
+
auth_token = Reivt::REIVT_STORE.transaction do |store|
|
21
|
+
store.fetch(:auth0_id, nil)
|
22
|
+
end
|
23
|
+
|
24
|
+
{ 'Authorization': "Bearer #{auth_token}" }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ID_TOKEN = Reivt::REIVT_STORE.transaction do |store|
|
29
|
+
store.fetch(:user_id, nil)
|
30
|
+
end
|
31
|
+
|
32
|
+
unless File.exist?(SCHEMA_PATH)
|
33
|
+
GraphQL::Client.dump_schema(ENDPOINT, SCHEMA_PATH)
|
34
|
+
end
|
35
|
+
|
36
|
+
SCHEMA = GraphQL::Client.load_schema(SCHEMA_PATH)
|
37
|
+
CLIENT = GraphQL::Client.new(schema: SCHEMA, execute: ENDPOINT)
|
38
|
+
|
39
|
+
# Raise any errors in the response data or simply return the data
|
40
|
+
#
|
41
|
+
# @param api_response [Obj] A nested object containing either data or errors
|
42
|
+
#
|
43
|
+
# @return [Array] A list containing the data and error object from the req
|
44
|
+
#
|
45
|
+
def self.retrieve(api_response)
|
46
|
+
errors = api_response.errors
|
47
|
+
data = api_response.data
|
48
|
+
|
49
|
+
if data.nil?
|
50
|
+
msg = errors.details[:data].map { |error| error['message'] }
|
51
|
+
raise Reivt::GraphQLDataException, msg.join(",\n")
|
52
|
+
else
|
53
|
+
data
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
require_relative 'api/mutations/document_create.mutation'
|
60
|
+
require_relative 'api/mutations/document_delete.mutation'
|
61
|
+
require_relative 'api/mutations/rev_create.mutation'
|
62
|
+
require_relative 'api/mutations/rev_delete.mutation'
|
63
|
+
require_relative 'api/mutations/user_create.mutation'
|
64
|
+
require_relative 'api/mutations/user_signin.mutation'
|
data/lib/reivt/auth.rb
CHANGED
@@ -1,96 +1,94 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'bcrypt'
|
3
|
-
require 'digest'
|
4
|
-
require 'json'
|
5
|
-
require 'net/http'
|
6
|
-
require 'sysrandom'
|
7
|
-
require 'uri'
|
8
|
-
|
9
|
-
# An extension of our main module
|
10
|
-
#
|
11
|
-
# @author [brwnrclse]
|
12
|
-
#
|
13
|
-
module Reivt
|
14
|
-
# Convience module for handling our authentication actions and talking to
|
15
|
-
# Auth0
|
16
|
-
#
|
17
|
-
# @author [brwnrclse]
|
18
|
-
#
|
19
|
-
module Auth
|
20
|
-
AUTH_CALLBACK_URL = 'https://rev.vaemoi.co/login_success'.freeze
|
21
|
-
AUTH_CLIENT_ID = 'Q1fRDQ9u3oN33ok0ciIi9Vww5kV8U8MA'.freeze
|
22
|
-
AUTH0_ID = Reivt::REIVT_STORE.transaction do
|
23
|
-
Reivt::REIVT_STORE.fetch(:auth0_id, nil)
|
24
|
-
end
|
25
|
-
AUTH_STORE_ACCESS_TOKEN = Reivt::REIVT_STORE.transaction do
|
26
|
-
Reivt::REIVT_STORE.fetch(:access_token, nil)
|
27
|
-
end
|
28
|
-
AUTH_URL = 'https://vaemoi.auth0.com'.freeze
|
29
|
-
VERIFIER = Sysrandom.urlsafe_base64(32)
|
30
|
-
|
31
|
-
# Provides the user with a means to obtain an authorization code for
|
32
|
-
# accessing rev's api by opening a browser to our Auth0 login page
|
33
|
-
#
|
34
|
-
# @return [nil]
|
35
|
-
#
|
36
|
-
def self.auth_code_url
|
37
|
-
verifier_challenge = Sysrandom.urlsafe_base64(
|
38
|
-
Digest::SHA256.new.update(VERIFIER).digest.to_i
|
39
|
-
)
|
40
|
-
|
41
|
-
auth_code_url = AUTH_URL +
|
42
|
-
'/authorize?response_type=code&scope=openid%20profile' \
|
43
|
-
'&client_id=' + AUTH_CLIENT_ID +
|
44
|
-
'&redirect_uri=' + AUTH_CALLBACK_URL +
|
45
|
-
'&code_challenge=' + verifier_challenge +
|
46
|
-
'&code_challenge_method=S256'
|
47
|
-
|
48
|
-
auth_code_url
|
49
|
-
end
|
50
|
-
|
51
|
-
# Exchanges the auth code obtained for a token used to access rev's api
|
52
|
-
#
|
53
|
-
# @param auth_code [String] The auth code obtained from logging in
|
54
|
-
#
|
55
|
-
# @return [String] The auth token used for accessing rev's api
|
56
|
-
#
|
57
|
-
def self.auth_token(auth_code)
|
58
|
-
auth_token_uri = URI.parse('https://vaemoi.auth0.com/oauth/token')
|
59
|
-
body = {
|
60
|
-
grant_type: 'authorization_code',
|
61
|
-
client_id: AUTH_CLIENT_ID,
|
62
|
-
code_verifier: VERIFIER,
|
63
|
-
code: auth_code,
|
64
|
-
redirect_uri: AUTH_CALLBACK_URL
|
65
|
-
}
|
66
|
-
http = Net::HTTP.new(auth_token_uri.host, auth_token_uri.port)
|
67
|
-
http.use_ssl = true
|
68
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
69
|
-
req = Net::HTTP::Post.new(auth_token_uri)
|
70
|
-
req.content_type = 'application/json'
|
71
|
-
req.body = body.to_json
|
72
|
-
|
73
|
-
res = http.request(req)
|
74
|
-
token = {}
|
75
|
-
token[:access_token] = JSON.parse(res.body)['access_token']
|
76
|
-
token[:auth0_id] = JSON.parse(res.body)['id_token']
|
77
|
-
token[:expires] = Time.now.to_i + JSON.parse(res.body)['expires'].to_i
|
78
|
-
|
79
|
-
token
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
end
|
1
|
+
require 'base64'
|
2
|
+
require 'bcrypt'
|
3
|
+
require 'digest'
|
4
|
+
require 'json'
|
5
|
+
require 'net/http'
|
6
|
+
require 'sysrandom'
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
# An extension of our main module
|
10
|
+
#
|
11
|
+
# @author [brwnrclse]
|
12
|
+
#
|
13
|
+
module Reivt
|
14
|
+
# Convience module for handling our authentication actions and talking to
|
15
|
+
# Auth0
|
16
|
+
#
|
17
|
+
# @author [brwnrclse]
|
18
|
+
#
|
19
|
+
module Auth
|
20
|
+
AUTH_CALLBACK_URL = 'https://rev.vaemoi.co/login_success'.freeze
|
21
|
+
AUTH_CLIENT_ID = 'Q1fRDQ9u3oN33ok0ciIi9Vww5kV8U8MA'.freeze
|
22
|
+
AUTH0_ID = Reivt::REIVT_STORE.transaction do
|
23
|
+
Reivt::REIVT_STORE.fetch(:auth0_id, nil)
|
24
|
+
end
|
25
|
+
AUTH_STORE_ACCESS_TOKEN = Reivt::REIVT_STORE.transaction do
|
26
|
+
Reivt::REIVT_STORE.fetch(:access_token, nil)
|
27
|
+
end
|
28
|
+
AUTH_URL = 'https://vaemoi.auth0.com'.freeze
|
29
|
+
VERIFIER = Sysrandom.urlsafe_base64(32)
|
30
|
+
|
31
|
+
# Provides the user with a means to obtain an authorization code for
|
32
|
+
# accessing rev's api by opening a browser to our Auth0 login page
|
33
|
+
#
|
34
|
+
# @return [nil]
|
35
|
+
#
|
36
|
+
def self.auth_code_url
|
37
|
+
verifier_challenge = Sysrandom.urlsafe_base64(
|
38
|
+
Digest::SHA256.new.update(VERIFIER).digest.to_i
|
39
|
+
)
|
40
|
+
|
41
|
+
auth_code_url = AUTH_URL +
|
42
|
+
'/authorize?response_type=code&scope=openid%20profile' \
|
43
|
+
'&client_id=' + AUTH_CLIENT_ID +
|
44
|
+
'&redirect_uri=' + AUTH_CALLBACK_URL +
|
45
|
+
'&code_challenge=' + verifier_challenge +
|
46
|
+
'&code_challenge_method=S256'
|
47
|
+
|
48
|
+
auth_code_url
|
49
|
+
end
|
50
|
+
|
51
|
+
# Exchanges the auth code obtained for a token used to access rev's api
|
52
|
+
#
|
53
|
+
# @param auth_code [String] The auth code obtained from logging in
|
54
|
+
#
|
55
|
+
# @return [String] The auth token used for accessing rev's api
|
56
|
+
#
|
57
|
+
def self.auth_token(auth_code)
|
58
|
+
auth_token_uri = URI.parse('https://vaemoi.auth0.com/oauth/token')
|
59
|
+
body = {
|
60
|
+
grant_type: 'authorization_code',
|
61
|
+
client_id: AUTH_CLIENT_ID,
|
62
|
+
code_verifier: VERIFIER,
|
63
|
+
code: auth_code,
|
64
|
+
redirect_uri: AUTH_CALLBACK_URL
|
65
|
+
}
|
66
|
+
http = Net::HTTP.new(auth_token_uri.host, auth_token_uri.port)
|
67
|
+
http.use_ssl = true
|
68
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
69
|
+
req = Net::HTTP::Post.new(auth_token_uri)
|
70
|
+
req.content_type = 'application/json'
|
71
|
+
req.body = body.to_json
|
72
|
+
|
73
|
+
res = http.request(req)
|
74
|
+
token = {}
|
75
|
+
token[:access_token] = JSON.parse(res.body)['access_token']
|
76
|
+
token[:auth0_id] = JSON.parse(res.body)['id_token']
|
77
|
+
token[:expires] = Time.now.to_i + JSON.parse(res.body)['expires'].to_i
|
78
|
+
|
79
|
+
token
|
80
|
+
end
|
81
|
+
|
82
|
+
# Checks if the user has an Authentication token for accessing the API
|
83
|
+
#
|
84
|
+
# @return [Bool] true if token found
|
85
|
+
# raises an exception otherwise
|
86
|
+
def self.logged_in
|
87
|
+
if AUTH_STORE_ACCESS_TOKEN.nil? || AUTH_STORE_ACCESS_TOKEN.empty?
|
88
|
+
raise Reivt::LoginException
|
89
|
+
end
|
90
|
+
|
91
|
+
true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/reivt/cli.rb
CHANGED
@@ -1,167 +1,167 @@
|
|
1
|
-
# rubocop: disable Metrics/AbcSize, Metrics/MethodLength, Metrics/ClassLength
|
2
|
-
require 'paint'
|
3
|
-
require 'thor'
|
4
|
-
require 'tty-spinner'
|
5
|
-
|
6
|
-
#
|
7
|
-
# An extension of our main module
|
8
|
-
#
|
9
|
-
# @author [brwnrclse]
|
10
|
-
#
|
11
|
-
module Reivt
|
12
|
-
#
|
13
|
-
# Rev's cli
|
14
|
-
#
|
15
|
-
# @author [brwnrclse]
|
16
|
-
#
|
17
|
-
class CLI < Thor
|
18
|
-
namespace :revit
|
19
|
-
|
20
|
-
map %w(--version -v) => :__print_version
|
21
|
-
desc '--version, -v', 'print the version'
|
22
|
-
def __print_version
|
23
|
-
puts VERSION
|
24
|
-
end
|
25
|
-
|
26
|
-
method_option :description, type: :string, aliases: '-d', lazy_default: '',
|
27
|
-
desc: 'A short summary of the changes'
|
28
|
-
method_option :list_files, type: :array, aliases: '-l',
|
29
|
-
desc: 'A list of files to add to the rev'
|
30
|
-
method_option :title, type: :string, aliases: '-t', lazy_default: '',
|
31
|
-
desc: 'A title for the rev'
|
32
|
-
desc 'create PATH', 'Make a new rev and populate with documents'
|
33
|
-
long_desc <<-LONGDESC
|
34
|
-
`Initiates a flow for creating a new rev. To bypass the prompts users can use the provided flags.
|
35
|
-
If using git the title, description and files will be retrieved from git via the git repo name, latest commit msg and latest commit file list respectively.
|
36
|
-
|
37
|
-
`revit create ./Bucket/repo` # Create a new rev from the provided path
|
38
|
-
`revit create ./Bucket/repo --title, -t "Test Repo"` # Create a new revo with a title of Test Repo
|
39
|
-
`revit create ./Bucket/repo --description, -d "A test repo."` # Create a new revo with a description of "a test repo"
|
40
|
-
`revit create ./Bucket/repo --list_files, -l ~/Bucket/oneoffs/help.js` # Create a new rev with a list of files, ignoring the current folder
|
41
|
-
LONGDESC
|
42
|
-
def create(path)
|
43
|
-
doc_set = Set.new
|
44
|
-
doc_ids = Set.new
|
45
|
-
paths = path.split
|
46
|
-
paths += options[:list_files] if options[:list_files]
|
47
|
-
rev_id = nil
|
48
|
-
spinner = TTY::Spinner.new('[:spinner] :msg', format: :bouncing_ball)
|
49
|
-
|
50
|
-
Reivt::Auth.logged_in
|
51
|
-
|
52
|
-
spinner.update(msg: 'Creating a rev...')
|
53
|
-
spinner.run do
|
54
|
-
rev_id = RevAPI.create_rev(options[:title], options[:description])
|
55
|
-
end
|
56
|
-
spinner.success(Paint['rev created', :green])
|
57
|
-
|
58
|
-
paths.each do |x|
|
59
|
-
type = File.exist?(x) ? File.ftype(x) : 'other'
|
60
|
-
|
61
|
-
if type == 'file'
|
62
|
-
spinner.update(msg: "#{Paint['Adding', nil, '#e3b505']} #{x}")
|
63
|
-
spinner.run do
|
64
|
-
doc_set.add(Util.doc_from_path(x))
|
65
|
-
end
|
66
|
-
spinner.success(Paint['document created', :green])
|
67
|
-
elsif type == 'directory'
|
68
|
-
spinner.update(msg: "#{Paint['Adding', nil, '#e3b505']} docs from " \
|
69
|
-
"#{Paint[path, '#2de1fc']}")
|
70
|
-
|
71
|
-
if Dir.entries(x).include?('.git')
|
72
|
-
spinner.run do
|
73
|
-
doc_set.merge(Util.docs_from_repo(x, spinner))
|
74
|
-
end
|
75
|
-
spinner.success(Paint['repo docs created', :green])
|
76
|
-
else
|
77
|
-
spinner.run do
|
78
|
-
doc_set.merge(Util.docs_from_dir(x))
|
79
|
-
end
|
80
|
-
spinner.success(Paint['dir docs created', :green])
|
81
|
-
end
|
82
|
-
else
|
83
|
-
spinner.error("#{Paint['Unsupported file type:']} #{path}")
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
spinner.update(msg: 'Uploading docs to rev api')
|
88
|
-
spinner.run do
|
89
|
-
doc_set.each do |doc|
|
90
|
-
doc_id = RevAPI.create_doc(doc.blob, doc.content_type, doc.doc_name,
|
91
|
-
doc.has_diff, rev_id)
|
92
|
-
doc_ids.add(doc_id)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
spinner.success(Paint['docs uploaded to api', :green])
|
96
|
-
|
97
|
-
Reivt::LOGGER.info(
|
98
|
-
"Login at #{Paint['wver.vaemoi.co/home', :green]} to start your rev!"
|
99
|
-
)
|
100
|
-
rescue Errno::ECONNRESET, Errno::EINVAL, EOFError, Net::HTTPBadResponse,
|
101
|
-
Net::HTTPHeaderSyntaxError, Net::OpenTimeout, Net::ProtocolError,
|
102
|
-
Reivt::BaemptyException, Reivt::GraphQLDataException,
|
103
|
-
Reivt::GraphQLValidationException => e
|
104
|
-
|
105
|
-
Reivt::DEVLOGGER.error(e.message)
|
106
|
-
Reivt::LOGGER.error(e.message)
|
107
|
-
|
108
|
-
unless doc_ids.empty?
|
109
|
-
doc_ids.each do |id|
|
110
|
-
RevAPI.delete_doc(id)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
unless rev_id.nil?
|
115
|
-
RevAPI.delete_rev(rev_id) unless rev_id.nil?
|
116
|
-
end
|
117
|
-
Reivt::LOGGER.info('Done!')
|
118
|
-
end
|
119
|
-
|
120
|
-
desc 'login', 'Get an auth token for accessing the rev api'
|
121
|
-
long_desc <<-LONGDESC
|
122
|
-
Sends a request for a valid auth token (jwt) to use for accessing the API.
|
123
|
-
Refresh is handled automatically as along as the user keeps on using rev otherwise it'll expire after about a week.
|
124
|
-
|
125
|
-
`rev login --username brwnrclse`
|
126
|
-
|
127
|
-
`rev login -u brwnrclse`
|
128
|
-
LONGDESC
|
129
|
-
def login
|
130
|
-
Reivt::LOGGER.info('Login here for your token:')
|
131
|
-
Reivt::LOGGER.info(Paint[Auth.auth_code_url, :green])
|
132
|
-
|
133
|
-
auth_code = Thor::Shell::Basic.new.ask("\nEnter your auth code => ")
|
134
|
-
spinner = TTY::Spinner.new('[:spinner] :msg', format: :bouncing_ball)
|
135
|
-
|
136
|
-
spinner.update(msg: 'Logging in')
|
137
|
-
spinner.run do
|
138
|
-
begin
|
139
|
-
auth_token = Auth.auth_token(auth_code)
|
140
|
-
user_id = RevAPI.signin_user(auth_token[:auth0_id])
|
141
|
-
|
142
|
-
if user_id.nil?
|
143
|
-
spinner.update(msg: 'User not found! Creating...')
|
144
|
-
user_id = RevAPI.create_user(auth_token[:auth0_id])
|
145
|
-
spinner.success(Paint['User created', :green])
|
146
|
-
end
|
147
|
-
|
148
|
-
Reivt::REIVT_STORE.transaction do |store|
|
149
|
-
store[:access_token] = auth_token[:access_token].strip
|
150
|
-
store[:expires] = auth_token[:expires]
|
151
|
-
store[:auth0_id] = auth_token[:auth0_id].strip
|
152
|
-
store[:user_id] = user_id
|
153
|
-
end
|
154
|
-
spinner.success(Paint['Login successful :)', :green])
|
155
|
-
rescue Errno::ECONNRESET, Errno::EINVAL, EOFError,
|
156
|
-
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
157
|
-
Net::OpenTimeout, Net::ProtocolError,
|
158
|
-
Reivt::GraphQLDataException,
|
159
|
-
Reivt::GraphQLValidationException => e
|
160
|
-
|
161
|
-
Reivt::DEVLOGGER.error(e.message)
|
162
|
-
Reivt::DEVLOGGER.error(e.message)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
1
|
+
# rubocop: disable Metrics/AbcSize, Metrics/MethodLength, Metrics/ClassLength
|
2
|
+
require 'paint'
|
3
|
+
require 'thor'
|
4
|
+
require 'tty-spinner'
|
5
|
+
|
6
|
+
#
|
7
|
+
# An extension of our main module
|
8
|
+
#
|
9
|
+
# @author [brwnrclse]
|
10
|
+
#
|
11
|
+
module Reivt
|
12
|
+
#
|
13
|
+
# Rev's cli
|
14
|
+
#
|
15
|
+
# @author [brwnrclse]
|
16
|
+
#
|
17
|
+
class CLI < Thor
|
18
|
+
namespace :revit
|
19
|
+
|
20
|
+
map %w(--version -v) => :__print_version
|
21
|
+
desc '--version, -v', 'print the version'
|
22
|
+
def __print_version
|
23
|
+
puts VERSION
|
24
|
+
end
|
25
|
+
|
26
|
+
method_option :description, type: :string, aliases: '-d', lazy_default: '',
|
27
|
+
desc: 'A short summary of the changes'
|
28
|
+
method_option :list_files, type: :array, aliases: '-l',
|
29
|
+
desc: 'A list of files to add to the rev'
|
30
|
+
method_option :title, type: :string, aliases: '-t', lazy_default: '',
|
31
|
+
desc: 'A title for the rev'
|
32
|
+
desc 'create PATH', 'Make a new rev and populate with documents'
|
33
|
+
long_desc <<-LONGDESC
|
34
|
+
`Initiates a flow for creating a new rev. To bypass the prompts users can use the provided flags.
|
35
|
+
If using git the title, description and files will be retrieved from git via the git repo name, latest commit msg and latest commit file list respectively.
|
36
|
+
|
37
|
+
`revit create ./Bucket/repo` # Create a new rev from the provided path
|
38
|
+
`revit create ./Bucket/repo --title, -t "Test Repo"` # Create a new revo with a title of Test Repo
|
39
|
+
`revit create ./Bucket/repo --description, -d "A test repo."` # Create a new revo with a description of "a test repo"
|
40
|
+
`revit create ./Bucket/repo --list_files, -l ~/Bucket/oneoffs/help.js` # Create a new rev with a list of files, ignoring the current folder
|
41
|
+
LONGDESC
|
42
|
+
def create(path)
|
43
|
+
doc_set = Set.new
|
44
|
+
doc_ids = Set.new
|
45
|
+
paths = path.split
|
46
|
+
paths += options[:list_files] if options[:list_files]
|
47
|
+
rev_id = nil
|
48
|
+
spinner = TTY::Spinner.new('[:spinner] :msg', format: :bouncing_ball)
|
49
|
+
|
50
|
+
Reivt::Auth.logged_in
|
51
|
+
|
52
|
+
spinner.update(msg: 'Creating a rev...')
|
53
|
+
spinner.run do
|
54
|
+
rev_id = RevAPI.create_rev(options[:title], options[:description])
|
55
|
+
end
|
56
|
+
spinner.success(Paint['rev created', :green])
|
57
|
+
|
58
|
+
paths.each do |x|
|
59
|
+
type = File.exist?(x) ? File.ftype(x) : 'other'
|
60
|
+
|
61
|
+
if type == 'file'
|
62
|
+
spinner.update(msg: "#{Paint['Adding', nil, '#e3b505']} #{x}")
|
63
|
+
spinner.run do
|
64
|
+
doc_set.add(Util.doc_from_path(x))
|
65
|
+
end
|
66
|
+
spinner.success(Paint['document created', :green])
|
67
|
+
elsif type == 'directory'
|
68
|
+
spinner.update(msg: "#{Paint['Adding', nil, '#e3b505']} docs from " \
|
69
|
+
"#{Paint[path, '#2de1fc']}")
|
70
|
+
|
71
|
+
if Dir.entries(x).include?('.git')
|
72
|
+
spinner.run do
|
73
|
+
doc_set.merge(Util.docs_from_repo(x, spinner))
|
74
|
+
end
|
75
|
+
spinner.success(Paint['repo docs created', :green])
|
76
|
+
else
|
77
|
+
spinner.run do
|
78
|
+
doc_set.merge(Util.docs_from_dir(x))
|
79
|
+
end
|
80
|
+
spinner.success(Paint['dir docs created', :green])
|
81
|
+
end
|
82
|
+
else
|
83
|
+
spinner.error("#{Paint['Unsupported file type:']} #{path}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
spinner.update(msg: 'Uploading docs to rev api')
|
88
|
+
spinner.run do
|
89
|
+
doc_set.each do |doc|
|
90
|
+
doc_id = RevAPI.create_doc(doc.blob, doc.content_type, doc.doc_name,
|
91
|
+
doc.has_diff, rev_id)
|
92
|
+
doc_ids.add(doc_id)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
spinner.success(Paint['docs uploaded to api', :green])
|
96
|
+
|
97
|
+
Reivt::LOGGER.info(
|
98
|
+
"Login at #{Paint['wver.vaemoi.co/home', :green]} to start your rev!"
|
99
|
+
)
|
100
|
+
rescue Errno::ECONNRESET, Errno::EINVAL, EOFError, Net::HTTPBadResponse,
|
101
|
+
Net::HTTPHeaderSyntaxError, Net::OpenTimeout, Net::ProtocolError,
|
102
|
+
Reivt::BaemptyException, Reivt::GraphQLDataException,
|
103
|
+
Reivt::GraphQLValidationException => e
|
104
|
+
|
105
|
+
Reivt::DEVLOGGER.error(e.message)
|
106
|
+
Reivt::LOGGER.error(e.message)
|
107
|
+
|
108
|
+
unless doc_ids.empty?
|
109
|
+
doc_ids.each do |id|
|
110
|
+
RevAPI.delete_doc(id)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
unless rev_id.nil?
|
115
|
+
RevAPI.delete_rev(rev_id) unless rev_id.nil?
|
116
|
+
end
|
117
|
+
Reivt::LOGGER.info('Done!')
|
118
|
+
end
|
119
|
+
|
120
|
+
desc 'login', 'Get an auth token for accessing the rev api'
|
121
|
+
long_desc <<-LONGDESC
|
122
|
+
Sends a request for a valid auth token (jwt) to use for accessing the API.
|
123
|
+
Refresh is handled automatically as along as the user keeps on using rev otherwise it'll expire after about a week.
|
124
|
+
|
125
|
+
`rev login --username brwnrclse`
|
126
|
+
|
127
|
+
`rev login -u brwnrclse`
|
128
|
+
LONGDESC
|
129
|
+
def login
|
130
|
+
Reivt::LOGGER.info('Login here for your token:')
|
131
|
+
Reivt::LOGGER.info(Paint[Auth.auth_code_url, :green])
|
132
|
+
|
133
|
+
auth_code = Thor::Shell::Basic.new.ask("\nEnter your auth code => ")
|
134
|
+
spinner = TTY::Spinner.new('[:spinner] :msg', format: :bouncing_ball)
|
135
|
+
|
136
|
+
spinner.update(msg: 'Logging in')
|
137
|
+
spinner.run do
|
138
|
+
begin
|
139
|
+
auth_token = Auth.auth_token(auth_code)
|
140
|
+
user_id = RevAPI.signin_user(auth_token[:auth0_id])
|
141
|
+
|
142
|
+
if user_id.nil?
|
143
|
+
spinner.update(msg: 'User not found! Creating...')
|
144
|
+
user_id = RevAPI.create_user(auth_token[:auth0_id])
|
145
|
+
spinner.success(Paint['User created', :green])
|
146
|
+
end
|
147
|
+
|
148
|
+
Reivt::REIVT_STORE.transaction do |store|
|
149
|
+
store[:access_token] = auth_token[:access_token].strip
|
150
|
+
store[:expires] = auth_token[:expires]
|
151
|
+
store[:auth0_id] = auth_token[:auth0_id].strip
|
152
|
+
store[:user_id] = user_id
|
153
|
+
end
|
154
|
+
spinner.success(Paint['Login successful :)', :green])
|
155
|
+
rescue Errno::ECONNRESET, Errno::EINVAL, EOFError,
|
156
|
+
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
157
|
+
Net::OpenTimeout, Net::ProtocolError,
|
158
|
+
Reivt::GraphQLDataException,
|
159
|
+
Reivt::GraphQLValidationException => e
|
160
|
+
|
161
|
+
Reivt::DEVLOGGER.error(e.message)
|
162
|
+
Reivt::DEVLOGGER.error(e.message)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|