ribose 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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