school21_api_sdk 0.4.0 → 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.
- checksums.yaml +4 -4
- data/README.md +12 -7
- data/lib/school21/api/auth_api.rb +4 -1
- data/lib/school21/api/base_api.rb +13 -8
- data/lib/school21/api/campuses_api.rb +7 -10
- data/lib/school21/api/clusters_api.rb +3 -3
- data/lib/school21/api/graph_api.rb +11 -0
- data/lib/school21/api/participants_api.rb +6 -6
- data/lib/school21/api/projects_api.rb +7 -6
- data/lib/school21/auth/access_token.rb +1 -1
- data/lib/school21/auth/authenticator.rb +23 -0
- data/lib/school21/auth/authorization_header.rb +2 -5
- data/lib/school21/config/global_config.rb +26 -2
- data/lib/school21/version.rb +1 -1
- data/lib/school21.rb +34 -1
- data/test/auth_api_test.rb +33 -0
- data/test/configuration_test.rb +17 -0
- data/test/participants_api_test.rb +37 -0
- data/test/support/shared_data.rb +7 -0
- data/test/support/stubs/auth_stub.rb +9 -10
- data/test/support/stubs/base_stub.rb +5 -0
- data/test/support/stubs/participants_stub.rb +18 -0
- data/test/test_helper.rb +21 -0
- metadata +9 -4
- data/lib/school21/client.rb +0 -111
- data/test/client_test.rb +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c369d9fa76c0c36cb3142d0807256d9be76d9b706aedc32207899f355721d0b
|
4
|
+
data.tar.gz: 3b314e7f8a1235eadfe9ce7cd5147bc0889c4926169a3a29740613f72f2aeb94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ddaecba86f46485941eb2a9d508ff6a2961db296657bbc28cf3b31dee962af1986648d1226cf1e46425475ef48935b2716810d4d74b34a627eba5e637d00cb4c
|
7
|
+
data.tar.gz: cf9e4fc8918d2b64e4361cf45a19bc8a6fc6f6e2c520f476e71b3e8c5025222bea1074a303971ff3f24ddd00e9c57b2e5d04f032bfd650c269b358e137fc9ebc
|
data/README.md
CHANGED
@@ -4,6 +4,16 @@
|
|
4
4
|
[](https://codecov.io/github/ikael21/school21_api_sdk)
|
5
5
|

|
6
6
|
|
7
|
+
> [!NOTE]
|
8
|
+
> Development is still in progress, implementation may change in future versions.
|
9
|
+
|
10
|
+
> [!WARNING]
|
11
|
+
> **Do not store your login and password as raw string values, use environment variables instead!**
|
12
|
+
> Currently platform provides only one way to authorize API calls with `login:password` pair
|
13
|
+
> you're using for the school everyday tasks.
|
14
|
+
> As soon as other types of authorization will be added (such as using API token), they'll be implemented for this gem as well.
|
15
|
+
|
16
|
+
|
7
17
|
## Installation
|
8
18
|
|
9
19
|
Install the gem and add to the application's Gemfile by executing:
|
@@ -30,23 +40,18 @@ require 'school21'
|
|
30
40
|
login = 'your_login_here'
|
31
41
|
password = 'your_password_here'
|
32
42
|
|
33
|
-
|
43
|
+
School21.configure do |config|
|
34
44
|
config.credentials = { login: login, password: password }
|
35
45
|
|
36
46
|
# If you want to log client's requests and responses (turned off by default)
|
37
47
|
config.enable_logging = true
|
38
48
|
end
|
39
|
-
|
40
|
-
# Request access token from the API server.
|
41
|
-
# Access token is stored inside client object and reused for API requests.
|
42
|
-
# If access token is expired client will automatically request a new one.
|
43
|
-
client.authenticate!
|
44
49
|
```
|
45
50
|
|
46
51
|
- Select the domain specific API that you want to use. This API has all endpoints related to that domain. Here's an example of `Participant API` and a call to `/participants/:login`
|
47
52
|
|
48
53
|
```ruby
|
49
|
-
participants_api =
|
54
|
+
participants_api = School21.participants_api
|
50
55
|
response = participants_api.participant('peer_nickname')
|
51
56
|
|
52
57
|
if response.success?
|
@@ -9,7 +9,10 @@ module School21
|
|
9
9
|
.form_param(new_parameter('password', key: :grant_type))
|
10
10
|
.form_param(new_parameter('s21-open-api', key: :client_id))
|
11
11
|
|
12
|
-
|
12
|
+
new_api_call_builder
|
13
|
+
.request(new_request)
|
14
|
+
.response(new_response_handler)
|
15
|
+
.execute
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -4,7 +4,7 @@ module School21
|
|
4
4
|
class BaseApi
|
5
5
|
include CoreLibrary
|
6
6
|
|
7
|
-
|
7
|
+
PLATFORM_AUTH_PARTICIPANT = :platform
|
8
8
|
|
9
9
|
def self.base_uri(server)
|
10
10
|
case server
|
@@ -16,6 +16,8 @@ module School21
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.response_convertor(api_response)
|
19
|
+
return api_response unless api_response.data.present? && api_response.data.is_a?(Hash)
|
20
|
+
|
19
21
|
api_response.data.deep_transform_keys! do |key|
|
20
22
|
key.underscore.to_sym
|
21
23
|
end
|
@@ -23,12 +25,13 @@ module School21
|
|
23
25
|
api_response
|
24
26
|
end
|
25
27
|
|
26
|
-
def initialize
|
27
|
-
@
|
28
|
-
@api_call = ApiCall.new(@global_configuration)
|
28
|
+
def initialize
|
29
|
+
@api_call = ApiCall.new(School21.config)
|
29
30
|
end
|
30
31
|
|
31
|
-
def new_api_call_builder
|
32
|
+
def new_api_call_builder
|
33
|
+
@api_call.new_builder
|
34
|
+
end
|
32
35
|
|
33
36
|
def new_response_handler
|
34
37
|
ResponseHandler.new
|
@@ -50,13 +53,15 @@ module School21
|
|
50
53
|
.value(value)
|
51
54
|
end
|
52
55
|
|
53
|
-
def
|
54
|
-
auth_participant = CoreLibrary::Single.new(
|
56
|
+
def request_with_auth_participant(http_method, path, server)
|
57
|
+
auth_participant = CoreLibrary::Single.new(PLATFORM_AUTH_PARTICIPANT)
|
55
58
|
|
56
|
-
new_request_builder(
|
59
|
+
new_request_builder(http_method, path, server).auth(auth_participant)
|
57
60
|
end
|
58
61
|
|
59
62
|
def execute_request(new_request)
|
63
|
+
Authenticator.call
|
64
|
+
|
60
65
|
new_api_call_builder
|
61
66
|
.request(new_request)
|
62
67
|
.response(new_response_handler)
|
@@ -3,16 +3,13 @@
|
|
3
3
|
module School21
|
4
4
|
class CampusesApi < BaseApi
|
5
5
|
def campuses
|
6
|
-
|
7
|
-
new_request = authenticated_request(HttpMethod::GET, path, :api_v1)
|
8
|
-
|
9
|
-
execute_request(new_request)
|
6
|
+
execute_request(request_with_auth_participant(HttpMethod::GET, '/campuses', :api_v1))
|
10
7
|
end
|
11
8
|
|
12
9
|
def campus_participants(campus_id, options: {})
|
13
|
-
path =
|
10
|
+
path = ['/campuses/', campus_id, '/participants'].join
|
14
11
|
default_options = { limit: 50, offset: 0 }.merge(options)
|
15
|
-
new_request =
|
12
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
16
13
|
|
17
14
|
default_options.each do |key, value|
|
18
15
|
new_request.query_param(new_parameter(value, key:))
|
@@ -22,9 +19,9 @@ module School21
|
|
22
19
|
end
|
23
20
|
|
24
21
|
def campus_coalitions(campus_id, options: {})
|
25
|
-
path =
|
22
|
+
path = ['/campuses/', campus_id, '/coalitions'].join
|
26
23
|
default_options = { limit: 50, offset: 0 }.merge(options)
|
27
|
-
new_request =
|
24
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
28
25
|
|
29
26
|
default_options.each do |key, value|
|
30
27
|
new_request.query_param(new_parameter(value, key:))
|
@@ -34,9 +31,9 @@ module School21
|
|
34
31
|
end
|
35
32
|
|
36
33
|
def campus_clusters(campus_id, options: {})
|
37
|
-
path =
|
34
|
+
path = ['/campuses/', campus_id, '/clusters'].join
|
38
35
|
default_options = { limit: 50, offset: 0 }.merge(options)
|
39
|
-
new_request =
|
36
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
40
37
|
|
41
38
|
default_options.each do |key, value|
|
42
39
|
new_request.query_param(new_parameter(value, key:))
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module School21
|
4
4
|
class ClustersApi < BaseApi
|
5
|
-
def
|
6
|
-
path =
|
5
|
+
def map(cluster_id, options: {})
|
6
|
+
path = ['/clusters/', cluster_id, '/map'].join
|
7
7
|
default_options = { limit: 50, offset: 0 }.merge(options)
|
8
|
-
new_request =
|
8
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
9
9
|
|
10
10
|
default_options.each do |key, value|
|
11
11
|
new_request.query_param(new_parameter(value, key:))
|
@@ -3,16 +3,16 @@
|
|
3
3
|
module School21
|
4
4
|
class ParticipantsApi < BaseApi
|
5
5
|
def participant(login)
|
6
|
-
path =
|
7
|
-
new_request =
|
6
|
+
path = ['/participants/', login].join
|
7
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
8
8
|
|
9
9
|
execute_request(new_request)
|
10
10
|
end
|
11
11
|
|
12
12
|
def participant_projects(login, options: {})
|
13
|
-
path =
|
13
|
+
path = ['/participants/', login, '/projects'].join
|
14
14
|
default_options = { limit: 10, offset: 0 }.merge(options)
|
15
|
-
new_request =
|
15
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
16
16
|
|
17
17
|
default_options.each do |key, value|
|
18
18
|
new_request.query_param(new_parameter(value, key:))
|
@@ -22,8 +22,8 @@ module School21
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def participant_project(login, project_id)
|
25
|
-
path =
|
26
|
-
new_request =
|
25
|
+
path = ['/participants/', login, '/projects/', project_id].join
|
26
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
27
27
|
|
28
28
|
execute_request(new_request)
|
29
29
|
end
|
@@ -3,18 +3,19 @@
|
|
3
3
|
module School21
|
4
4
|
class ProjectsApi < BaseApi
|
5
5
|
def project(project_id)
|
6
|
-
path =
|
7
|
-
new_request =
|
6
|
+
path = ['/projects/', project_id].join
|
7
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
8
8
|
|
9
9
|
execute_request(new_request)
|
10
10
|
end
|
11
11
|
|
12
12
|
def project_participants(project_id, options: {})
|
13
|
-
path =
|
14
|
-
default_options = { limit: 10, offset: 0 }
|
15
|
-
new_request =
|
13
|
+
path = ['/projects/', project_id, '/participants'].join
|
14
|
+
default_options = { limit: 10, offset: 0 }
|
15
|
+
new_request = request_with_auth_participant(HttpMethod::GET, path, :api_v1)
|
16
16
|
|
17
|
-
default_options
|
17
|
+
options.reverse_merge!(default_options)
|
18
|
+
options.each do |key, value|
|
18
19
|
new_request.query_param(new_parameter(value, key:))
|
19
20
|
end
|
20
21
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
module Authenticator
|
5
|
+
def self.call
|
6
|
+
return unless School21.config.access_token.expired?
|
7
|
+
|
8
|
+
auth_api_response = School21.auth_api.token(
|
9
|
+
login: School21.config.credentials[:login],
|
10
|
+
password: School21.config.credentials[:password]
|
11
|
+
)
|
12
|
+
|
13
|
+
raise 'Access Token Error' unless auth_api_response.success?
|
14
|
+
|
15
|
+
access_token = AccessToken.new(*auth_api_response.data.values_at(:access_token, :expires_in))
|
16
|
+
bearer_auth_credentials = BearerAuthCredentials.new(access_token:)
|
17
|
+
auth_header = AuthorizationHeader.new(bearer_auth_credentials)
|
18
|
+
|
19
|
+
School21.config.access_token = access_token
|
20
|
+
School21.config.auth_managers[BaseApi::PLATFORM_AUTH_PARTICIPANT] = auth_header
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -7,12 +7,9 @@ module School21
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def initialize(bearer_auth_credentials)
|
10
|
+
access_token = bearer_auth_credentials.access_token
|
10
11
|
auth_params = {}
|
11
|
-
|
12
|
-
@access_token = bearer_auth_credentials.access_token unless
|
13
|
-
bearer_auth_credentials.nil? || bearer_auth_credentials.access_token.nil?
|
14
|
-
|
15
|
-
auth_params['Authorization'] = "Bearer #{@access_token}" unless @access_token.nil?
|
12
|
+
auth_params['Authorization'] = "Bearer #{access_token}"
|
16
13
|
|
17
14
|
super(auth_params)
|
18
15
|
end
|
@@ -2,14 +2,38 @@
|
|
2
2
|
|
3
3
|
module School21
|
4
4
|
class GlobalConfig < CoreLibrary::GlobalConfiguration
|
5
|
-
attr_accessor :auth_managers, :enable_logging, :credentials, :logger
|
6
|
-
attr_writer :client_configuration
|
5
|
+
attr_accessor :auth_managers, :enable_logging, :credentials, :logger, :access_token
|
7
6
|
|
8
7
|
def initialize(client_configuration: ClientConfig.new)
|
9
8
|
super
|
10
9
|
|
11
10
|
@enable_logging = false
|
12
11
|
@credentials = {}
|
12
|
+
@access_token = AccessToken.new(nil, 0)
|
13
|
+
|
14
|
+
http_client = CoreLibrary::FaradayClient.new(client_configuration)
|
15
|
+
client_configuration.set_http_client(http_client)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize_logger
|
19
|
+
logger ||= semantic_logger
|
20
|
+
|
21
|
+
excluded_headers = ['Authorization']
|
22
|
+
api_logging_config = School21::ApiLoggingConfig.new(logger, nil, nil, nil, false)
|
23
|
+
api_logging_config.request_logging_config =
|
24
|
+
CoreLibrary::ApiRequestLoggingConfiguration.new(true, true, excluded_headers, nil, nil, true)
|
25
|
+
api_logging_config.response_logging_config =
|
26
|
+
CoreLibrary::ApiResponseLoggingConfiguration.new(true, true, nil, nil, nil)
|
27
|
+
client_configuration.logging_configuration = api_logging_config
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def semantic_logger
|
33
|
+
SemanticLogger.default_level = :trace
|
34
|
+
SemanticLogger.add_appender(io: $stdout, formatter: :color)
|
35
|
+
|
36
|
+
SemanticLogger[School21.name]
|
13
37
|
end
|
14
38
|
end
|
15
39
|
end
|
data/lib/school21/version.rb
CHANGED
data/lib/school21.rb
CHANGED
@@ -9,6 +9,7 @@ require 'active_support/all'
|
|
9
9
|
require_relative 'school21/auth/access_token'
|
10
10
|
require_relative 'school21/auth/authorization_header'
|
11
11
|
require_relative 'school21/auth/bearer_auth_credentials'
|
12
|
+
require_relative 'school21/auth/authenticator'
|
12
13
|
|
13
14
|
require_relative 'school21/api/base_api'
|
14
15
|
require_relative 'school21/api/participants_api'
|
@@ -16,9 +17,41 @@ require_relative 'school21/api/auth_api'
|
|
16
17
|
require_relative 'school21/api/projects_api'
|
17
18
|
require_relative 'school21/api/campuses_api'
|
18
19
|
require_relative 'school21/api/clusters_api'
|
20
|
+
require_relative 'school21/api/graph_api'
|
19
21
|
|
20
22
|
require_relative 'school21/config/api_logging_config'
|
21
23
|
require_relative 'school21/config/client_config'
|
22
24
|
require_relative 'school21/config/global_config'
|
23
25
|
|
24
|
-
|
26
|
+
module School21
|
27
|
+
class << self
|
28
|
+
def configure
|
29
|
+
yield config
|
30
|
+
config.initialize_logger if config.enable_logging
|
31
|
+
config
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
@config ||= GlobalConfig.new.base_uri_executor(BaseApi.method(:base_uri))
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset!
|
39
|
+
@config = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
API_CLASSES = {
|
43
|
+
auth: AuthApi,
|
44
|
+
participants: ParticipantsApi,
|
45
|
+
projects: ProjectsApi,
|
46
|
+
campuses: CampusesApi,
|
47
|
+
clusters: ClustersApi,
|
48
|
+
graph: GraphApi
|
49
|
+
}.freeze
|
50
|
+
|
51
|
+
API_CLASSES.each do |name, klass|
|
52
|
+
define_method("#{name}_api") do
|
53
|
+
klass.new
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe 'Auth API Test' do
|
6
|
+
include AuthStub
|
7
|
+
|
8
|
+
with_configured_client do
|
9
|
+
let(:auth_api_call) do
|
10
|
+
School21.auth_api.token(
|
11
|
+
login: School21.config.credentials[:login],
|
12
|
+
password: School21.config.credentials[:password]
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'calls stub token success' do
|
17
|
+
stub = stub_token_success
|
18
|
+
|
19
|
+
auth_api_call
|
20
|
+
|
21
|
+
assert_requested(stub)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'calls stub token fail' do
|
25
|
+
stub = stub_token_fail
|
26
|
+
|
27
|
+
response = auth_api_call
|
28
|
+
|
29
|
+
assert_requested(stub)
|
30
|
+
assert_equal(500, response.status_code)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe 'Configuration test' do
|
6
|
+
include SharedData
|
7
|
+
|
8
|
+
it 'successfully configures client' do
|
9
|
+
School21.configure do |config|
|
10
|
+
config.credentials = credentials_fixtures
|
11
|
+
config.enable_logging = false
|
12
|
+
end
|
13
|
+
|
14
|
+
assert_equal credentials_fixtures, School21.config.credentials
|
15
|
+
refute School21.config.enable_logging
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
describe 'Participants API Test' do
|
6
|
+
include AuthStub
|
7
|
+
include ParticipantsStub
|
8
|
+
|
9
|
+
with_configured_client do
|
10
|
+
let(:login) { 'test_login' }
|
11
|
+
let(:participants_api_call) do
|
12
|
+
School21.participants_api.participant(login)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'calls stub participant success' do
|
16
|
+
stubs = [
|
17
|
+
stub_token_success,
|
18
|
+
stub_participant_success
|
19
|
+
]
|
20
|
+
|
21
|
+
participants_api_call
|
22
|
+
|
23
|
+
stubs.each { |stub| assert_requested(stub) }
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'calls stub participant fail' do
|
27
|
+
stubs = [
|
28
|
+
stub_token_success,
|
29
|
+
stub_participant_fail
|
30
|
+
]
|
31
|
+
|
32
|
+
participants_api_call
|
33
|
+
|
34
|
+
stubs.each { |stub| assert_requested(stub) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -3,18 +3,17 @@
|
|
3
3
|
module AuthStub
|
4
4
|
include BaseStub
|
5
5
|
|
6
|
-
|
7
|
-
body = {
|
8
|
-
access_token: 'access_token',
|
9
|
-
expires_in: 36_000
|
10
|
-
}
|
6
|
+
STUBBED_AUTH_URL = [BASE_AUTH_URL, '/auth/realms/EduPowerKeycloak/protocol/openid-connect/token'].join
|
11
7
|
|
12
|
-
|
8
|
+
def stub_token_success
|
9
|
+
stub_request(:post, STUBBED_AUTH_URL)
|
10
|
+
.to_return_json(body: {
|
11
|
+
access_token: 'access_token',
|
12
|
+
expires_in: 36_000
|
13
|
+
})
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
def stubbed_auth_url
|
18
|
-
[BASE_AUTH_URL, '/auth/realms/EduPowerKeycloak/protocol/openid-connect/token'].join
|
16
|
+
def stub_token_fail
|
17
|
+
base_stub_fail(:post, STUBBED_AUTH_URL)
|
19
18
|
end
|
20
19
|
end
|
@@ -3,4 +3,9 @@
|
|
3
3
|
module BaseStub
|
4
4
|
BASE_AUTH_URL = 'https://auth.sberclass.ru'
|
5
5
|
BASE_API_V1_URL = 'https://edu-api.21-school.ru/services/21-school/api/v1'
|
6
|
+
|
7
|
+
def base_stub_fail(http_method, url)
|
8
|
+
stub_request(http_method, url)
|
9
|
+
.to_return(status: [500, 'Internal Server Error'])
|
10
|
+
end
|
6
11
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ParticipantsStub
|
4
|
+
include BaseStub
|
5
|
+
|
6
|
+
TEST_LOGIN = 'test_login'
|
7
|
+
STUBBED_PARTICIPANT_URL = [BASE_API_V1_URL, '/participants/', TEST_LOGIN].join
|
8
|
+
|
9
|
+
def stub_participant_success
|
10
|
+
stub_request(:get, STUBBED_PARTICIPANT_URL)
|
11
|
+
.to_return_json(body: { login: TEST_LOGIN })
|
12
|
+
end
|
13
|
+
|
14
|
+
def stub_participant_fail
|
15
|
+
stub_request(:get, STUBBED_PARTICIPANT_URL)
|
16
|
+
.to_return(status: [500, 'Internal Server Error'])
|
17
|
+
end
|
18
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -3,9 +3,13 @@
|
|
3
3
|
require 'simplecov'
|
4
4
|
require 'simplecov-cobertura'
|
5
5
|
require 'webmock/minitest'
|
6
|
+
require 'debug'
|
7
|
+
|
8
|
+
require_relative 'support/shared_data'
|
6
9
|
|
7
10
|
require_relative 'support/stubs/base_stub'
|
8
11
|
require_relative 'support/stubs/auth_stub'
|
12
|
+
require_relative 'support/stubs/participants_stub'
|
9
13
|
|
10
14
|
SimpleCov.start
|
11
15
|
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
@@ -17,3 +21,20 @@ require 'minitest/autorun'
|
|
17
21
|
require 'minitest/reporters'
|
18
22
|
|
19
23
|
Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]
|
24
|
+
|
25
|
+
module Minitest
|
26
|
+
class Spec
|
27
|
+
include SharedData
|
28
|
+
|
29
|
+
def self.with_configured_client(&block)
|
30
|
+
describe 'with configured client' do
|
31
|
+
before do
|
32
|
+
School21.reset!
|
33
|
+
School21.configure { |c| c.credentials = credentials_fixtures }
|
34
|
+
end
|
35
|
+
|
36
|
+
class_eval(&block)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: school21_api_sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Yudin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -110,19 +110,24 @@ files:
|
|
110
110
|
- lib/school21/api/base_api.rb
|
111
111
|
- lib/school21/api/campuses_api.rb
|
112
112
|
- lib/school21/api/clusters_api.rb
|
113
|
+
- lib/school21/api/graph_api.rb
|
113
114
|
- lib/school21/api/participants_api.rb
|
114
115
|
- lib/school21/api/projects_api.rb
|
115
116
|
- lib/school21/auth/access_token.rb
|
117
|
+
- lib/school21/auth/authenticator.rb
|
116
118
|
- lib/school21/auth/authorization_header.rb
|
117
119
|
- lib/school21/auth/bearer_auth_credentials.rb
|
118
|
-
- lib/school21/client.rb
|
119
120
|
- lib/school21/config/api_logging_config.rb
|
120
121
|
- lib/school21/config/client_config.rb
|
121
122
|
- lib/school21/config/global_config.rb
|
122
123
|
- lib/school21/version.rb
|
123
|
-
- test/
|
124
|
+
- test/auth_api_test.rb
|
125
|
+
- test/configuration_test.rb
|
126
|
+
- test/participants_api_test.rb
|
127
|
+
- test/support/shared_data.rb
|
124
128
|
- test/support/stubs/auth_stub.rb
|
125
129
|
- test/support/stubs/base_stub.rb
|
130
|
+
- test/support/stubs/participants_stub.rb
|
126
131
|
- test/test_helper.rb
|
127
132
|
homepage: https://github.com/ikael21/school21_api_sdk
|
128
133
|
licenses:
|
data/lib/school21/client.rb
DELETED
@@ -1,111 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module School21
|
4
|
-
class Client
|
5
|
-
include CoreLibrary
|
6
|
-
|
7
|
-
attr_reader :config, :access_token
|
8
|
-
|
9
|
-
class << self
|
10
|
-
def configure(&) = new(&)
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize(&block)
|
14
|
-
raise 'A block must be given' unless block_given?
|
15
|
-
raise 'You must provide block argument that represents config instance' if block.arity != 1
|
16
|
-
|
17
|
-
@config = GlobalConfig.new.base_uri_executor(BaseApi.method(:base_uri))
|
18
|
-
|
19
|
-
yield(@config)
|
20
|
-
|
21
|
-
validate_credentials!
|
22
|
-
|
23
|
-
initialize_logging if @config.enable_logging
|
24
|
-
|
25
|
-
http_client = FaradayClient.new(@config.client_configuration)
|
26
|
-
@config.client_configuration.set_http_client(http_client)
|
27
|
-
end
|
28
|
-
|
29
|
-
def authenticate!
|
30
|
-
@access_token = request_access_token!
|
31
|
-
|
32
|
-
initialize_auth_managers
|
33
|
-
end
|
34
|
-
|
35
|
-
def auth_api
|
36
|
-
@auth_api ||= AuthApi.new(config)
|
37
|
-
end
|
38
|
-
|
39
|
-
def participants_api
|
40
|
-
authenticate! if access_token.expired?
|
41
|
-
ParticipantsApi.new(config)
|
42
|
-
end
|
43
|
-
|
44
|
-
def projects_api
|
45
|
-
authenticate! if access_token.expired?
|
46
|
-
ProjectsApi.new(config)
|
47
|
-
end
|
48
|
-
|
49
|
-
def campuses_api
|
50
|
-
authenticate! if access_token.expired?
|
51
|
-
CampusesApi.new(config)
|
52
|
-
end
|
53
|
-
|
54
|
-
def clusters_api
|
55
|
-
authenticate! if access_token.expired?
|
56
|
-
ClustersApi.new(config)
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def validate_credentials!
|
62
|
-
login = config.credentials[:login]
|
63
|
-
password = config.credentials[:password]
|
64
|
-
|
65
|
-
raise "Login can't be nil or empty" if login.nil? || login.empty?
|
66
|
-
raise "Password can't be nil or empty" if password.nil? || password.empty?
|
67
|
-
end
|
68
|
-
|
69
|
-
def initialize_auth_managers
|
70
|
-
auth_managers = {}
|
71
|
-
creds = BearerAuthCredentials.new(access_token:)
|
72
|
-
auth_managers[BaseApi::SINGLE_AUTH_PARTICIPANT] = AuthorizationHeader.new(creds)
|
73
|
-
|
74
|
-
config.auth_managers = auth_managers
|
75
|
-
end
|
76
|
-
|
77
|
-
def request_access_token!
|
78
|
-
auth_api_response = auth_api.token(
|
79
|
-
login: config.credentials[:login],
|
80
|
-
password: config.credentials[:password]
|
81
|
-
)
|
82
|
-
|
83
|
-
raise 'Access Token Error' unless auth_api_response.success?
|
84
|
-
|
85
|
-
AccessToken.new(*auth_api_response.data.values_at(:access_token, :expires_in))
|
86
|
-
end
|
87
|
-
|
88
|
-
def semantic_logger
|
89
|
-
SemanticLogger.default_level = :trace
|
90
|
-
SemanticLogger.add_appender(io: $stdout, formatter: :color)
|
91
|
-
|
92
|
-
SemanticLogger[self.class.to_s]
|
93
|
-
end
|
94
|
-
|
95
|
-
def initialize_logging
|
96
|
-
logger = if config.logger.nil?
|
97
|
-
semantic_logger
|
98
|
-
else
|
99
|
-
config.logger
|
100
|
-
end
|
101
|
-
|
102
|
-
headers_to_exclude = ['Authorization']
|
103
|
-
api_logging_config = ApiLoggingConfig.new(logger, nil, nil, nil, false)
|
104
|
-
api_logging_config.request_logging_config = ApiRequestLoggingConfiguration.new(true, true, headers_to_exclude,
|
105
|
-
nil, nil, true)
|
106
|
-
api_logging_config.response_logging_config = ApiResponseLoggingConfiguration.new(true, true, nil, nil, nil)
|
107
|
-
|
108
|
-
config.client_configuration.logging_configuration = api_logging_config
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
data/test/client_test.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
describe 'Client Test' do
|
6
|
-
include AuthStub
|
7
|
-
|
8
|
-
before do
|
9
|
-
@login = 'login'
|
10
|
-
@password = 'password'
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:valid_init_client) do
|
14
|
-
School21::Client.configure do |config|
|
15
|
-
config.credentials = { login: @login, password: @password }
|
16
|
-
config.enable_logging = false
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
let(:init_client_without_login) do
|
21
|
-
School21::Client.configure do |config|
|
22
|
-
config.credentials = { login: nil, password: @password }
|
23
|
-
config.enable_logging = false
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
let(:init_client_without_password) do
|
28
|
-
School21::Client.configure do |config|
|
29
|
-
config.credentials = { login: @login, password: nil }
|
30
|
-
config.enable_logging = false
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'successfully stubs client auth' do
|
35
|
-
stub = stub_token
|
36
|
-
|
37
|
-
valid_init_client.authenticate!
|
38
|
-
|
39
|
-
assert_requested(stub)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'raises an exception without login' do
|
43
|
-
stub = stub_token
|
44
|
-
|
45
|
-
assert_raises(RuntimeError, "Login can't be nil or empty") do
|
46
|
-
init_client_without_login
|
47
|
-
end
|
48
|
-
|
49
|
-
refute_requested(stub)
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'raises an exception without password' do
|
53
|
-
stub = stub_token
|
54
|
-
|
55
|
-
assert_raises(RuntimeError, "Password can't be nil or empty") do
|
56
|
-
init_client_without_password
|
57
|
-
end
|
58
|
-
|
59
|
-
refute_requested(stub)
|
60
|
-
end
|
61
|
-
end
|