ribose 0.3.1 → 0.5.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.
@@ -23,7 +23,7 @@ module Ribose
23
23
  end
24
24
 
25
25
  def request_body(attributes)
26
- custom_option.merge(resource_key.to_sym => validate(attributes))
26
+ custom_option.merge(resource_key.to_sym => validate(**attributes))
27
27
  end
28
28
 
29
29
  def create_resource
data/lib/ribose/client.rb CHANGED
@@ -1,25 +1,35 @@
1
1
  module Ribose
2
2
  class Client
3
- attr_reader :api_token, :user_email
3
+ attr_accessor :api_email, :api_token, :access_token, :uid, :client_id
4
4
 
5
5
  def initialize(options = {})
6
- @api_token = options.fetch(:token, configuration.api_token).to_s
7
- @user_email = options.fetch(:email, configuration.user_email).to_s
6
+ initialize_client_details(options)
8
7
  end
9
8
 
10
9
  # Initiate a ribose client
11
10
  #
12
- # This interface takes email and password and then it will
13
- # do all the underlying work to find out the authentication
14
- # token and retrun a ribose client.
11
+ # This interface takes email, password, api_email and api_token
12
+ # Then it will do all the underlying work to find out client id and uid
13
+ # Finally it will return a ribose client.
15
14
  #
16
15
  # @param :email [String] The email for your Ribose account
17
16
  # @param :password [String] The password for your account
17
+ # @param :api_email [String] The email for your API account
18
+ # @param :api_token [String] The authentication token for your API account
18
19
  # @return [Ribose::Client] A new client with your details
19
20
  #
20
21
  def self.from_login(email:, password:)
21
- session = Session.create(username: email, password: password)
22
- new(email: email, token: session["authentication_token"])
22
+ session = Ribose::Session.create(
23
+ username: email, password: password,
24
+ )
25
+
26
+ new(
27
+ api_email: email,
28
+ uid: session.uid,
29
+ client_id: session.client,
30
+ api_token: session["access-token"],
31
+ access_token: session["access-token"],
32
+ )
23
33
  end
24
34
 
25
35
  private
@@ -27,5 +37,13 @@ module Ribose
27
37
  def configuration
28
38
  Ribose.configuration
29
39
  end
40
+
41
+ def initialize_client_details(options)
42
+ @uid = options.fetch(:uid, nil)
43
+ @client_id = options.fetch(:client_id, nil)
44
+ @access_token = options.fetch(:access_token, nil)
45
+ @api_email = options.fetch(:api_email, configuration.api_email)
46
+ @api_token = options.fetch(:api_token, configuration.api_token)
47
+ end
30
48
  end
31
49
  end
@@ -2,10 +2,12 @@ require "ribose/response/raise_error"
2
2
 
3
3
  module Ribose
4
4
  class Configuration
5
- attr_accessor :api_host, :api_token, :user_email, :debug_mode
5
+ attr_accessor :api_email, :verify_ssl, :client, :api_host,
6
+ :api_token, :user_email, :user_password, :debug_mode
6
7
 
7
8
  def initialize
8
9
  @debug_mode = false
10
+ @verify_ssl = true
9
11
  @api_host ||= "www.ribose.com"
10
12
  end
11
13
 
@@ -13,13 +15,28 @@ module Ribose
13
15
  debug_mode == true
14
16
  end
15
17
 
16
- def web_url
17
- ["https", api_host].join("://")
18
+ def verify_ssl?
19
+ !!verify_ssl
18
20
  end
21
+
22
+ def api_email
23
+ @user_email || @api_email
24
+ end
25
+
26
+ def client
27
+ @client ||= Ribose::Client.from_login(
28
+ email: api_email, password: user_password,
29
+ )
30
+ end
31
+
19
32
  def add_default_middleware(builder)
20
33
  builder.use(Ribose::Response::RaiseError)
21
34
  builder.response(:logger, nil, bodies: true) if debug_mode?
22
35
  builder.adapter(Faraday.default_adapter)
23
36
  end
37
+
38
+ def ssl_verification_mode
39
+ verify_ssl? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
40
+ end
24
41
  end
25
42
  end
@@ -1,6 +1,7 @@
1
1
  module Ribose
2
2
  class Connection < Ribose::Base
3
3
  include Ribose::Actions::All
4
+ include Ribose::Actions::Delete
4
5
 
5
6
  # List Connections
6
7
  #
@@ -26,6 +27,20 @@ module Ribose
26
27
  suggested_connection
27
28
  end
28
29
 
30
+ # Disconnect
31
+ #
32
+ # Disconnect connection / contact with the provided
33
+ # connection id. This will return nothing for successful
34
+ # request, but if disconnect fails then it will raise an
35
+ # Error for the client.
36
+ #
37
+ # @params resource_id [Integer] Connection Id
38
+ # @return nil
39
+ #
40
+ def self.disconnect(resource_id, options = {})
41
+ delete(resource_id, options)
42
+ end
43
+
29
44
  private
30
45
 
31
46
  def resource
data/lib/ribose/event.rb CHANGED
@@ -12,7 +12,7 @@ module Ribose
12
12
  # @return [Sawyer::Resource] Calendar Events
13
13
  #
14
14
  def self.all(calendar_id, options = {})
15
- Ribose::Calendar.fetch(calendar_id, options)
15
+ Ribose::Calendar.fetch(calendar_id, **options)
16
16
  end
17
17
 
18
18
  # Fetch a calendar event
@@ -1,4 +1,6 @@
1
+ require "json"
1
2
  require "faraday"
3
+ require "ostruct"
2
4
 
3
5
  module Ribose
4
6
  class FileUploader
@@ -29,7 +31,7 @@ module Ribose
29
31
  # @param attributes [Hash] Attributes as a Hash
30
32
  # @return [Sawyer::Resource] File upload response.
31
33
  def self.upload(space_id, file:, **attributes)
32
- new(space_id, attributes.merge(file: file)).create
34
+ new(space_id, **attributes.merge(file: file)).create
33
35
  end
34
36
 
35
37
  private
@@ -49,7 +51,10 @@ module Ribose
49
51
 
50
52
  def notify_ribose_file_upload_endpoint(response, key)
51
53
  if response.status.to_i == 200
52
- Ribose::Request.post(space_file_path, file_attributes.merge(key: key))
54
+ attributes = notifiable_attributes(file_attributes, key)
55
+
56
+ content = Request.post(space_file_path, attributes)
57
+ content.is_a?(Sawyer::Resource) ? content : parse_to_ribose_os(content)
53
58
  end
54
59
  end
55
60
 
@@ -67,7 +72,16 @@ module Ribose
67
72
 
68
73
  def content_type_form_file
69
74
  require "mime/types"
70
- MIME::Types.type_for(file.path).first.content_type
75
+ mime = MIME::Types.type_for(file.path).first
76
+ mime ? mime.content_type : "application/octet-stream"
77
+ end
78
+
79
+ def parse_to_ribose_os(content)
80
+ JSON.parse(content, object_class: Ribose::OpenStruct)
81
+ end
82
+
83
+ def notifiable_attributes(attributes, key)
84
+ attributes.merge(key: key)
71
85
  end
72
86
 
73
87
  def file_attributes
@@ -90,4 +104,8 @@ module Ribose
90
104
  end
91
105
  end
92
106
  end
107
+
108
+ class OpenStruct < ::OpenStruct
109
+ alias :read_attribute_for_serialization :send
110
+ end
93
111
  end
@@ -1,7 +1,13 @@
1
+ require "ribose/version_uploader"
2
+
1
3
  module Ribose
2
4
  class FileVersion < Ribose::Base
3
5
  include Ribose::Actions::Fetch
4
6
 
7
+ def download
8
+ download_file || raise(Ribose::BadRequest)
9
+ end
10
+
5
11
  # Fetch file version
6
12
  #
7
13
  # @params :space_id [UUID] The space Id
@@ -10,23 +16,52 @@ module Ribose
10
16
  # @returns [Sawyer::Resource] The file version
11
17
  #
12
18
  def self.fetch(space_id:, file_id:, version_id:, **options)
13
- new(
14
- file_id: file_id,
15
- space_id: space_id,
16
- resource_id: version_id,
17
- **options,
18
- ).fetch
19
+ options = options.merge(
20
+ file_id: file_id, space_id: space_id, resource_id: version_id,
21
+ )
22
+
23
+ new(options).fetch
24
+ end
25
+
26
+ # Download file version
27
+ #
28
+ # @param space_id [UUID] The space Id
29
+ # @param file_id [Integer] The file Id
30
+ # @param version_id [Hash] The file version Id
31
+ # @param options [Hash] Options as key and value pair
32
+ #
33
+ def self.download(space_id, file_id, version_id:, **options)
34
+ options = options.merge(
35
+ file_id: file_id,space_id: space_id, resource_id: version_id,
36
+ )
37
+
38
+ new(options).download
39
+ end
40
+
41
+ # Create a new file version
42
+ #
43
+ # @params space_id [UUID] The space UUID
44
+ # @params file_id [Integer] The space file ID
45
+ # @params file [File] The new version for file
46
+ # @params attributes [Hash] Other file attributes
47
+ # @return [Sawyer::Resource] Newly updated version
48
+ #
49
+ def self.create(space_id, file_id, file:, **attributes)
50
+ attributes = attributes.merge(file: file)
51
+ upload = VersionUploader.upload(space_id, file_id, **attributes)
52
+ upload[:attachment]
19
53
  end
20
54
 
21
55
  private
22
56
 
23
- attr_reader :file_id, :space_id
57
+ attr_reader :output, :file_id, :space_id
24
58
 
25
59
  def resource
26
60
  nil
27
61
  end
28
62
 
29
63
  def extract_local_attributes
64
+ @output = attributes.delete(:output)
30
65
  @file_id = attributes.delete(:file_id)
31
66
  @space_id = attributes.delete(:space_id)
32
67
  end
@@ -38,5 +73,21 @@ module Ribose
38
73
  def files_path
39
74
  ["spaces", space_id, "file", "files"].join("/")
40
75
  end
76
+
77
+ def download_file
78
+ data = Ribose::Request.get(
79
+ resource_path, parse: false, headers: { accept: "text/html" }
80
+ )
81
+
82
+ if data.headers["status"].match?(/^30[12]/)
83
+ fetch_and_write_to_file(data)
84
+ end
85
+ end
86
+
87
+ def fetch_and_write_to_file(data)
88
+ File.open(output || "download", "w") do |file|
89
+ file << data.agent.call(:get, data.headers["location"]).data
90
+ end
91
+ end
41
92
  end
42
93
  end
@@ -1,5 +1,7 @@
1
1
  module Ribose
2
2
  class Request
3
+ DEFAULT_CONTENT_TYPE = "application/json"
4
+
3
5
  # Initialize a Request
4
6
  #
5
7
  # @param http_method [Symbol] HTTP verb as sysmbol
@@ -7,7 +9,7 @@ module Ribose
7
9
  # @param data [Hash] Attributes / Options as a Hash
8
10
  # @return [Ribose::Request]
9
11
  #
10
- def initialize(http_method, endpoint, **data)
12
+ def initialize(http_method, endpoint, data = {})
11
13
  @data = data
12
14
  @endpoint = endpoint
13
15
  @http_method = http_method
@@ -20,8 +22,13 @@ module Ribose
20
22
  # @return [Sawyer::Resource]
21
23
  #
22
24
  def request(options = {})
25
+ parsable = extract_config_option(:parse) != false
23
26
  options[:query] = extract_config_option(:query) || {}
24
- agent.call(http_method, api_endpoint, data, options).data
27
+
28
+ response = agent.call(http_method, api_endpoint, data, options)
29
+ update_client_headers(response.headers)
30
+
31
+ parsable == true ? response.data : response
25
32
  end
26
33
 
27
34
  # Make a HTTP GET Request
@@ -78,13 +85,16 @@ module Ribose
78
85
  end
79
86
 
80
87
  def find_suitable_client
81
- client = extract_config_option(:client) || Ribose::Client.new
82
- client.is_a?(Ribose::Client) ? client: raise(Ribose::Unauthorized)
88
+ client = extract_config_option(:client) || Ribose.configuration.client
89
+ client.is_a?(Ribose::Client) ? client : raise(Ribose::Unauthorized)
83
90
  end
84
91
 
85
92
  def require_auth_headers?
86
- auth_header = extract_config_option(:auth_header)
87
- auth_header == false ? false : true
93
+ extract_config_option(:auth_header) != false
94
+ end
95
+
96
+ def custom_content_headers
97
+ extract_config_option(:headers) || {}
88
98
  end
89
99
 
90
100
  def api_endpoint
@@ -95,9 +105,16 @@ module Ribose
95
105
  end
96
106
 
97
107
  def sawyer_options
108
+ faraday_options = { builder: custom_rack_builder }
109
+ unless Ribose.configuration.verify_ssl?
110
+ faraday_options.merge!(ssl: Faraday::SSLOptions.new(
111
+ false, nil, nil, OpenSSL::SSL::VERIFY_NONE
112
+ ))
113
+ end
114
+
98
115
  {
116
+ faraday: Faraday.new(faraday_options),
99
117
  links_parser: Sawyer::LinkParsers::Simple.new,
100
- faraday: Faraday.new(builder: custom_rack_builder),
101
118
  }
102
119
  end
103
120
 
@@ -109,14 +126,33 @@ module Ribose
109
126
 
110
127
  def agent
111
128
  @agent ||= Sawyer::Agent.new(ribose_host, sawyer_options) do |http|
112
- http.headers[:accept] = "application/json"
113
- http.headers[:content_type] = "application/json"
129
+ set_content_type(http.headers)
130
+ set_devise_specific_headers(http.headers)
114
131
 
115
132
  if require_auth_headers?
116
133
  http.headers["X-Indigo-Token"] = client.api_token
117
- http.headers["X-Indigo-Email"] = client.user_email
134
+ http.headers["X-Indigo-Email"] = client.api_email
118
135
  end
119
136
  end
120
137
  end
138
+
139
+ def update_client_headers(headers)
140
+ client.uid = headers["uid"]
141
+ client.client_id = headers["client"]
142
+ client.access_token = headers["access-token"]
143
+ end
144
+
145
+ def set_content_type(headers)
146
+ headers[:content_type] = DEFAULT_CONTENT_TYPE
147
+ headers[:accept] = custom_content_headers.fetch(
148
+ :accept, DEFAULT_CONTENT_TYPE
149
+ )
150
+ end
151
+
152
+ def set_devise_specific_headers(headers)
153
+ headers["uid"] = client.uid
154
+ headers["client"] = client.client_id
155
+ headers["access-token"] = client.access_token
156
+ end
121
157
  end
122
158
  end
@@ -3,8 +3,6 @@ require "ribose/error"
3
3
  module Ribose
4
4
  module Response
5
5
  class RaiseError < Faraday::Response::Middleware
6
- private
7
-
8
6
  def on_complete(response)
9
7
  if error = Ribose::Error.from_response(response)
10
8
  raise error
@@ -1,6 +1,6 @@
1
- require "json"
2
- require "mechanize"
3
- require "ribose/config"
1
+ require "uri"
2
+ require "ostruct"
3
+ require "net/http"
4
4
 
5
5
  module Ribose
6
6
  class Session
@@ -10,7 +10,7 @@ module Ribose
10
10
  end
11
11
 
12
12
  def create
13
- JSON.parse(authenticate_user)
13
+ authenticate_user
14
14
  rescue NoMethodError, JSON::ParserError
15
15
  raise Ribose::Unauthorized
16
16
  end
@@ -24,25 +24,49 @@ module Ribose
24
24
  attr_reader :username, :password
25
25
 
26
26
  def authenticate_user
27
- page = agent.get(ribose_url_for("login"))
28
- find_and_submit_the_user_login_form(page)
29
- agent.get(ribose_url_for(["settings", "general", "info"])).body
27
+ response = submit_user_login_request
28
+
29
+ case response
30
+ when Net::HTTPSuccess
31
+ build_session_data(response.each_header.to_h)
32
+ when Net::HTTPForbidden
33
+ raise(Ribose::Unauthorized)
34
+ end
35
+ end
36
+
37
+ def submit_user_login_request
38
+ Net::HTTP.start(login_uri.host, login_uri.port, http_options) do |http|
39
+ request = Net::HTTP::Post.new(login_uri)
40
+
41
+ request["Content-Type"] = "application/json"
42
+ request.set_form_data(username: username, password: password)
43
+
44
+ http.request(request)
45
+ end
30
46
  end
31
47
 
32
- def find_and_submit_the_user_login_form(page)
33
- login_form = page.form_with(id: "new_user")
34
- login_form.field_with(id: "loginEmail").value = username
35
- login_form.field_with(id: "loginPassword").value = password
48
+ def api_host
49
+ api_host = Ribose.configuration.api_host
36
50
 
37
- login_form.submit
51
+ unless api_host[/\Ahttp:\/\//] || api_host[/\Ahttps:\/\//]
52
+ "https://#{api_host}"
53
+ end
38
54
  end
39
55
 
40
- def agent
41
- @agent ||= Mechanize.new
56
+ def login_uri
57
+ @login_uri ||= URI.parse([api_host, "api/v2/auth/sign_in"].join("/"))
42
58
  end
43
59
 
44
- def ribose_url_for(*endpoint)
45
- [Ribose.configuration.web_url, *endpoint].join("/")
60
+ def http_options
61
+ { use_ssl: true, verify_ssl: Ribose.configuration.ssl_verification_mode }
46
62
  end
63
+
64
+ def build_session_data(headers)
65
+ SessionData.new(headers.slice("uid", "expiry", "client", "access-token"))
66
+ end
67
+ end
68
+
69
+ class SessionData < ::OpenStruct
70
+ alias :read_attribute_for_serialization :send
47
71
  end
48
72
  end
data/lib/ribose/space.rb CHANGED
@@ -15,6 +15,10 @@ module Ribose
15
15
  Ribose::Request.post("spaces/#{space_uuid}/freeze", options)
16
16
  end
17
17
 
18
+ def self.delete(space_uuid, confirmation:, **options)
19
+ remove(space_uuid, options.merge(password_confirmation: confirmation))
20
+ end
21
+
18
22
  private
19
23
 
20
24
  attr_reader :space
@@ -34,6 +34,21 @@ module Ribose
34
34
  new(space_id: space_id, resource_id: file_id, **options).fetch
35
35
  end
36
36
 
37
+ # Download a space file
38
+ #
39
+ # @param space_id [UUID] The Space UUID
40
+ # @param file_id [Integer] The File Id
41
+ # @param options [Hash] Options as key and value pair.
42
+ #
43
+ # Two important keys are :version_id, and :output and
44
+ # if these are provided then it will use those otherwise
45
+ # it will do additional request to retirve those details
46
+ #
47
+ def self.download(space_id, file_id, options = {})
48
+ options[:version_id] ||= fetch(space_id, file_id).current_version_id
49
+ Ribose::FileVersion.download(space_id, file_id, **options)
50
+ end
51
+
37
52
  # Create a new file upload
38
53
  #
39
54
  # @param space_id [String] The Space UUID
@@ -42,7 +57,7 @@ module Ribose
42
57
  # @return [Sawyer::Resource] The file upload response.
43
58
  #
44
59
  def self.create(space_id, file:, **attributes)
45
- upload = FileUploader.upload(space_id, attributes.merge(file: file))
60
+ upload = FileUploader.upload(space_id, **attributes.merge(file: file))
46
61
  upload[:attachment]
47
62
  end
48
63
 
data/lib/ribose/user.rb CHANGED
@@ -8,8 +8,12 @@ module Ribose
8
8
 
9
9
  def activate
10
10
  Ribose::Request.post(
11
- "signup.user",
12
- custom_option.merge(user: attributes, auth_header: false),
11
+ "api/v2/auth",
12
+ custom_option.merge(
13
+ user: attributes,
14
+ auth_header: false,
15
+ client: Ribose::Client.new
16
+ ),
13
17
  )
14
18
  end
15
19
 
@@ -17,12 +21,12 @@ module Ribose
17
21
  #
18
22
  # @param email [String] The registering user email
19
23
  # @param password [String] A strong password for login
20
- # @param otp [String] The OTP received via the email
24
+ # @param edata [String] The OTP received via the email
21
25
  # @param attributes [Hash] The other attributes as Hash.
22
26
  # @return [Sawyer::Resoruce] The newly activated user
23
27
  #
24
- def self.activate(email:, password:, otp:, **attributes)
25
- new(attributes.merge(email: email, password: password, otp: otp)).activate
28
+ def self.activate(email:, password:, edata:, **attributes)
29
+ new(attributes.merge(email: email, password: password, edata: edata)).activate
26
30
  end
27
31
 
28
32
  private
@@ -1,3 +1,3 @@
1
1
  module Ribose
2
- VERSION = "0.3.1".freeze
2
+ VERSION = "0.5.0".freeze
3
3
  end
@@ -0,0 +1,27 @@
1
+ require "ribose/file_uploader"
2
+
3
+ module Ribose
4
+ class VersionUploader < Ribose::FileUploader
5
+ def initialize(space_id, file_id, file:, **attributes)
6
+ @file_id = file_id
7
+ super(space_id, file: file, **attributes)
8
+ end
9
+
10
+ def self.upload(space_id, file_id, file:, **attributes)
11
+ new(space_id, file_id, **attributes.merge(file: file)).create
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :file_id
17
+
18
+ def notifiable_attributes(attributes, key)
19
+ attributes[:file_info_version] = attributes.delete(:file_info)
20
+ attributes.merge(key: key)
21
+ end
22
+
23
+ def space_file_path
24
+ ["spaces", space_id, "file", "files", file_id, "versions"].join("/")
25
+ end
26
+ end
27
+ end
data/ribose.gemspec CHANGED
@@ -21,13 +21,12 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = Gem::Requirement.new(">= 2.1.9")
22
22
 
23
23
  spec.add_dependency "id_pack", "~> 1.0.1"
24
- spec.add_dependency "mechanize", "~> 2.7.5"
25
24
  spec.add_dependency "mime-types", "~> 3.1"
26
25
  spec.add_dependency "sawyer", "~> 0.8.1"
27
26
 
28
- spec.add_development_dependency "bundler", "~> 1.14"
29
- spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "bundler"
28
+ spec.add_development_dependency "rake"
30
29
  spec.add_development_dependency "rspec", "~> 3.0"
31
- spec.add_development_dependency "pry", "~> 0.10.4"
32
- spec.add_development_dependency "webmock", "~> 2.0"
30
+ spec.add_development_dependency "pry"
31
+ spec.add_development_dependency "webmock", "~> 3.0"
33
32
  end