reivt 1.1.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.
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.3
data/.test-unit.yml ADDED
@@ -0,0 +1,12 @@
1
+ runner: tap
2
+ tap_options:
3
+ color_scheme: emphasis
4
+
5
+ color_schemes:
6
+ emphasis:
7
+ success:
8
+ name: green
9
+ failure:
10
+ name: red
11
+ bold: true
12
+ underline: true
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # gem dependencies go in revit.gemspec
4
+ gemspec
5
+
6
+ gem 'rugged', git: 'git://github.com/libgit2/rugged.git', submodules: true
7
+
8
+ group :test do
9
+ gem 'codeclimate-test-reporter', '~> 1.0.0'
10
+ gem 'simplecov'
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 vaemoi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,15 @@
1
+ [![Code Climate](https://codeclimate.com/repos/57d861ee01430a66ea000bed/badges/4d214cda256127c2391e/gpa.svg)](https://codeclimate.com/repos/57d861ee01430a66ea000bed/feed) [![Test Coverage](https://codeclimate.com/repos/57d861ee01430a66ea000bed/badges/4d214cda256127c2391e/coverage.svg)](https://codeclimate.com/repos/57d861ee01430a66ea000bed/coverage) [![Issue Count](https://codeclimate.com/repos/57d861ee01430a66ea000bed/badges/4d214cda256127c2391e/issue_count.svg)](https://codeclimate.com/repos/57d861ee01430a66ea000bed/feed)
2
+
3
+ # Rev
4
+ ---
5
+ Upload your documents/directories/git commits to rev for a code review session!
6
+
7
+ Conduct your code reviews with [rev](https://rev.vaemoi.co)!
8
+
9
+ [Bitbucket](https://bitbucket.org/vaemoi/revit)
10
+ [Docker Whale used for testing](https://hub.docker.com/r/vaemoi/revit-whale/)
11
+ [Issues](https://bitbucket.org/vaemoi/revit/issues)
12
+
13
+ ## License
14
+
15
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = '--format doc'
6
+ end
7
+
8
+ task :console do
9
+ require 'pry'
10
+ require 'gem_name'
11
+
12
+ def reload!
13
+ # Change 'gem_name' here too:
14
+ files = $LOADED_FEATURES.select { |feat| feat =~ %r{//gem_name} }
15
+ files.each { |file| load file }
16
+ end
17
+
18
+ ARGV.clear
19
+ Pry.start
20
+ end
21
+
22
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'paint'
5
+ require 'revit'
6
+
7
+ require 'irb'
8
+
9
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,9 @@
1
+ image: vaemoi/revit-whale # Specify the docker image to use
2
+
3
+ pipelines:
4
+ default:
5
+ - step:
6
+ script:
7
+ - bundle install --path ./vendor # Install deps
8
+ - bundle exec rake # Run tests
9
+ - bundle exec codeclimate-test-reporter # Test output to codeclimate
data/exe/revit ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'revit'
4
+
5
+ Revit::CLI.start(ARGV)
@@ -0,0 +1,31 @@
1
+ # baemptyError
2
+
3
+ This simply means you have passed rev either to an empty repo or a [bare repo](http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/).
4
+
5
+ If you still want to use the repo:
6
+
7
+
8
+ - create a commit
9
+ ``` bash
10
+
11
+ git add -A && git commit -m # Add every file in the repo
12
+
13
+ git add ./path/to/file.ext && git commit -m # Add a specific file or folder
14
+
15
+ ```
16
+
17
+ - Destroy the repo
18
+ ``` bash
19
+
20
+ rm -rf .git
21
+
22
+ ```
23
+
24
+
25
+ Then try revit again:
26
+
27
+ ``` bash
28
+
29
+ revit create ./path/to/repo
30
+
31
+ ```
@@ -0,0 +1,50 @@
1
+ # How to
2
+
3
+ ## Getting Started
4
+ ---
5
+ To get started with revit make sure you have the latest ruby installed or atleast version 2.3.3.
6
+
7
+ ``` bash
8
+
9
+ ruby -v
10
+
11
+ ```
12
+
13
+ Now let's install revit!
14
+
15
+ ``` bash
16
+
17
+ gem install revit
18
+
19
+ revit -v
20
+ revit --version
21
+
22
+ ```
23
+
24
+
25
+
26
+ ## Creating a revs
27
+ ---
28
+ revit only allows creating new rev at the moment, modifying them will come soong!
29
+
30
+ Get started by running revit ```create```
31
+
32
+ ``` bash
33
+
34
+ revit create ./path/to/docs # Path to a single file, directory or git repo
35
+
36
+ revit create -l ./path/file1 ./path/file2 # -l allows you to pass multiple files / docs / repos
37
+
38
+ revit create ./path/file1 -d "An example rev" # Add a description to your rev
39
+
40
+ revit create ./path/file1 -t "First Rev" # Add a title to your rev
41
+
42
+ ```
43
+
44
+ These commands will also be shown by running:
45
+
46
+ ``` bash
47
+
48
+ revit --help
49
+
50
+ ```
@@ -0,0 +1,5 @@
1
+ # GraphQLDataIssue
2
+
3
+ Hey, don't fret this just means that some error happened on our api! It's not your fault we swear!
4
+
5
+ Try running the same command again, and if you end up here again post an issue to our tracker on Bitbucket [here](https://bitbucket.org/vaemoi/revit/issues)
@@ -0,0 +1,5 @@
1
+ # GraphQLValidationError
2
+
3
+ Hey, don't fret this just means that some variable passed to our api wasn't in the correct format! It's not your fault we swear!
4
+
5
+ Try running the same command again, and if it fails post an issue to our tracker on Bitbucket [here](https://bitbucket.org/vaemoi/revit/issues)
@@ -0,0 +1,17 @@
1
+ # Logging In
2
+ Start an authentication workflow to receive an access token (allows you to access our api)
3
+
4
+ Running login will produce a url you need to follow in order to get your auth code from Auth0. Paste this code back into the terminal and you'll be authenticated. (If you want more security info checkout our wiki!)
5
+
6
+ ``` bash
7
+
8
+ revit login
9
+
10
+ "Login here for your token": https://vaemoi.auth0/login/stuff/to/login
11
+
12
+ "Enter your auth code here" => owfnoisjIAIO90w9JDOFIEF
13
+
14
+ Authentication successful :)
15
+ ```
16
+
17
+ Now you're ready to make some revs!
@@ -0,0 +1,50 @@
1
+ # An extension of our main module Revit
2
+ #
3
+ # @author [brwnrclse]
4
+ #
5
+ module Revit
6
+ # An extension of the RevAPI module
7
+ #
8
+ # @author [brwnrclse]
9
+ #
10
+ module RevAPI
11
+ CreateDocumentMutation = CLIENT.parse <<-'GRAPHQL'
12
+ mutation($blob: String!, $content_type: String!, $doc_name: String!, $has_diff: Boolean!, $rev_id: ID!) {
13
+ createDocument(blob: $blob, contentType: $content_type, name: $doc_name, hasDiff: $has_diff, revId: $rev_id) {
14
+ id
15
+ }
16
+ }
17
+ GRAPHQL
18
+
19
+ # API call to createDocument
20
+ # @param blob [String] The contents of the Document
21
+ # @param content_type [String] The kind of Document
22
+ # @param doc_name [String] The name of the Document
23
+ # @param rev_id [String] The id of the Rev this Document belongs to
24
+ #
25
+ # @return [String] The id of the Document
26
+ #
27
+ def self.create_doc(blob, content_type, doc_name, has_diff, rev_id)
28
+ blob = "That's all folks?" if blob.nil? || blob.strip.empty?
29
+ doc_name = 'Empty Doc' if doc_name.nil? || doc_name.strip.empty?
30
+ has_diff = false if has_diff.nil?
31
+
32
+ if content_type.nil? || content_type.strip.empty?
33
+ content_type = 'plain text'
34
+ end
35
+
36
+ if rev_id.length < 25
37
+ raise Revit::GraphQLValidationException, 'Missing rev id'
38
+ end
39
+
40
+ result = CLIENT.query(CreateDocumentMutation, variables: {
41
+ blob: blob, content_type: content_type,
42
+ doc_name: doc_name, has_diff: has_diff,
43
+ rev_id: rev_id
44
+ })
45
+ data = RevAPI.retrieve(result)
46
+
47
+ data.createDocument.id
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,36 @@
1
+ # An extension of our main module
2
+ #
3
+ # @author [brwnrclse]
4
+ #
5
+ module Revit
6
+ # An extension of the RevAPI module
7
+ #
8
+ # @author [brwnrclse]
9
+ #
10
+ module RevAPI
11
+ DeleteDocumentMutation = CLIENT.parse <<-'GRAPHQL'
12
+ mutation($id: ID!) {
13
+ deleteDocument(id: $id) {
14
+ id
15
+ }
16
+ }
17
+ GRAPHQL
18
+
19
+ # API call to deleteDocument
20
+ # @param id [String] The unique identifier of the Document
21
+ #
22
+ # @return [String, RevAPI::GraphQLValidationError] The id of the deleted
23
+ # Document or an error
24
+ #
25
+ def self.delete_doc(id)
26
+ if id.length < 25
27
+ raise raise Revit::GraphQLValidationException, 'Missing id to delete'
28
+ end
29
+
30
+ result = CLIENT.query(DeleteDocumentMutation, variables: { id: id })
31
+ data = RevAPI.retrieve(result)
32
+
33
+ data.deleteDocument.id
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # An extension of our main module
2
+ #
3
+ # @author [brwnrclse]
4
+ #
5
+ module Revit
6
+ # An extension of the RevAPI module
7
+ #
8
+ # @author [brwnrclse]
9
+ #
10
+ module RevAPI
11
+ CreateRevMutation = CLIENT.parse <<-'GRAPHQL'
12
+ mutation($description: String!, $title: String!, $user_id: ID!) {
13
+ createRev(description: $description, title: $title, userId: $user_id) {
14
+ id
15
+ }
16
+ }
17
+ GRAPHQL
18
+
19
+ # API call to createRev
20
+ # @param description [String] What the Rev is about
21
+ # @param title [String] The name of the Rev
22
+ #
23
+ # @return [String] The id of the created Rev
24
+ #
25
+ def self.create_rev(description, title)
26
+ description = 'Some rev' if description.nil? || description.strip.empty?
27
+ title = 'A rev, right?' if title.nil? || title.strip.empty?
28
+
29
+ result = CLIENT.query(RevAPI::CreateRevMutation, variables: {
30
+ description: description, title: title,
31
+ user_id: RevAPI::ID_TOKEN
32
+ })
33
+ data = RevAPI.retrieve(result)
34
+
35
+ data.createRev.id
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ # An extension of our main module Revit
2
+ #
3
+ # @author [brwnrclse]
4
+ #
5
+ module Revit
6
+ # An extension of the RevAPI module
7
+ #
8
+ # @author [brwnrclse]
9
+ #
10
+ module RevAPI
11
+ DeleteRevMutation = CLIENT.parse <<-'GRAPHQL'
12
+ mutation($id: ID!) {
13
+ deleteRev(id: $id) {
14
+ id
15
+ }
16
+ }
17
+ GRAPHQL
18
+
19
+ # API call to deleteRev
20
+ # @param id [String] The unique identifier of the Rev
21
+ #
22
+ # @return [String, RevAPI::GraphQLValidationError] The id of the deleted Rev
23
+ # or an error
24
+ #
25
+ def self.delete_rev(id)
26
+ if id.length < 25
27
+ raise Revit::GraphQLValidationException, 'Missing id to delete'
28
+ end
29
+
30
+ result = CLIENT.query(RevAPI::DeleteRevMutation, variables: { id: id })
31
+ data = RevAPI.retrieve(result)
32
+
33
+ data.deleteRev.id
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ # An extension of the main module, Revit
2
+ #
3
+ # @author [brwnrclse]
4
+ #
5
+ module Revit
6
+ # An extension of the RevAPI module
7
+ #
8
+ # @author [brwnrclse]
9
+ #
10
+ module RevAPI
11
+ CreateUserMutation = CLIENT.parse <<-'GRAPHQL'
12
+ mutation($auth0_id: String!) {
13
+ createUser(authProvider:{auth0: {idToken: $auth0_id}}) {
14
+ id
15
+ }
16
+ }
17
+ GRAPHQL
18
+
19
+ # Authenticate the user against the api to receive a user id
20
+ # @param id [String] The users's id from Auth0
21
+ #
22
+ # @return [String] The user's id in the rev api
23
+ #
24
+ def self.create_user(auth0_id)
25
+ result = CLIENT.query(RevAPI::CreateUserMutation,
26
+ variables: { auth0_id: auth0_id })
27
+ data = RevAPI.retrieve(result)
28
+
29
+ data.createUser.id
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,39 @@
1
+ # An extension of the main module, Revit
2
+ #
3
+ # @author [brwnrclse]
4
+ #
5
+ module Revit
6
+ # An extension of the RevAPI module
7
+ #
8
+ # @author [brwnrclse]
9
+ #
10
+ module RevAPI
11
+ SigninMutation = CLIENT.parse <<-'GRAPHQL'
12
+ mutation($auth0_id: String!) {
13
+ signinUser(auth0:{idToken: $auth0_id}) {
14
+ user {
15
+ id
16
+ }
17
+ }
18
+ }
19
+ GRAPHQL
20
+
21
+ # Authenticate the user against the api to receive a user id
22
+ # @param id [String] The users's id from Auth0
23
+ #
24
+ # @return [String] The user's id in the rev api
25
+ #
26
+ def self.signin_user(auth0_id)
27
+ result = CLIENT.query(RevAPI::SigninMutation,
28
+ variables: { auth0_id: auth0_id })
29
+
30
+ if result.data.nil?
31
+ nil
32
+ else
33
+ data = RevAPI.retrieve(result)
34
+
35
+ data.signinUser.user.id
36
+ end
37
+ end
38
+ end
39
+ end
data/lib/revit/api.rb ADDED
@@ -0,0 +1,65 @@
1
+ require 'graphql/client'
2
+ require 'graphql/client/http'
3
+
4
+ # An extension of our main module Revit
5
+ #
6
+ # @author [brwnrclse]
7
+ #
8
+ module Revit
9
+ # Intrface for rev API, connects local changes with our remote.
10
+ #
11
+ # @author [brwnrclse]
12
+ #
13
+ module RevAPI
14
+ SCHEMA_PATH = "#{Dir.pwd}/lib/revit/schema/schema.json".freeze
15
+ ENDPOINT_URL = 'https://api.graph.cool/simple/v1/revwver'.freeze
16
+ ENDPOINT = GraphQL::Client::HTTP.new(ENDPOINT_URL) do
17
+ def headers(_context)
18
+ auth_token = Revit::REVIT_STORE.transaction do |store|
19
+ store.fetch(:auth0_id, nil)
20
+ end
21
+
22
+ { 'Authorization': "Bearer #{auth_token}" }
23
+ end
24
+ end
25
+
26
+ ID_TOKEN = Revit::REVIT_STORE.transaction do |store|
27
+ store.fetch(:user_id, nil)
28
+ end
29
+
30
+ unless File.exist?(SCHEMA_PATH)
31
+ GraphQL::Client.dump_schema(ENDPOINT, SCHEMA_PATH)
32
+ end
33
+
34
+ SCHEMA = GraphQL::Client.load_schema(SCHEMA_PATH)
35
+ CLIENT = GraphQL::Client.new(schema: SCHEMA, execute: ENDPOINT)
36
+
37
+ # Raise any errors in the response data or simply return the data
38
+ #
39
+ # @param api_response [Obj] A nested object containing either data or errors
40
+ #
41
+ # @return [Array] A list containing the data and error object from the req
42
+ #
43
+ def self.retrieve(api_response)
44
+ errors = api_response.errors.messages
45
+ data = api_response.data
46
+
47
+ if errors.key?(:data)
48
+ raise Revit::GraphQLDataException, errors[:data].join(', ')
49
+ end
50
+
51
+ if data.errors.any?
52
+ raise Revit::GraphQLDataException, data.errors[:data].join(', ')
53
+ end
54
+
55
+ data
56
+ end
57
+ end
58
+ end
59
+
60
+ require_relative 'api/mutations/document_create.mutation'
61
+ require_relative 'api/mutations/document_delete.mutation'
62
+ require_relative 'api/mutations/rev_create.mutation'
63
+ require_relative 'api/mutations/rev_delete.mutation'
64
+ require_relative 'api/mutations/user_create.mutation'
65
+ require_relative 'api/mutations/user_signin.mutation'
data/lib/revit/auth.rb ADDED
@@ -0,0 +1,82 @@
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 Revit
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 = Revit::REVIT_STORE.transaction do
23
+ Revit::REVIT_STORE.fetch(:auth0_id, nil)
24
+ end
25
+ AUTH_STORE_ACCESS_TOKEN = Revit::REVIT_STORE.transaction do
26
+ Revit::REVIT_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
+ end
82
+ end