school21_api_sdk 0.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.
- checksums.yaml +7 -0
- data/LICENSE +8 -0
- data/README.md +48 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/lib/school21/api/auth_api.rb +18 -0
- data/lib/school21/api/base_api.rb +53 -0
- data/lib/school21/api/participants_api.rb +37 -0
- data/lib/school21/api/projects_api.rb +37 -0
- data/lib/school21/auth/access_token.rb +16 -0
- data/lib/school21/auth/authorization_header.rb +20 -0
- data/lib/school21/auth/bearer_auth_credentials.rb +13 -0
- data/lib/school21/client.rb +71 -0
- data/lib/school21/version.rb +5 -0
- data/lib/school21.rb +17 -0
- data/test/test_helper.rb +12 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2f53a4ed9751f4ad38c62dff08811e164694e1b84903847ce98392aa39ae9234
|
4
|
+
data.tar.gz: 46344c76969f24f6cd33d4b7ef9e1983e36e133c6bb258162b94dcb7ded7cc88
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d7bf6101d76b1a93a5510335e0f69a39eac1b8643eb0bbebd716a9b1dace589a1443bc4ef7ee6576c4b1b8e721746bf0b01eaf2888e21c541804bf7b58cfc43e
|
7
|
+
data.tar.gz: fb4698307bc50ef4b896bda5277f556b5146e293042e9dbfec3a52b3a773792514d558c9f2235975813adace83d2ab3e426a250a9bcd1e1d7025b308c4e4ec59
|
data/LICENSE
ADDED
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# School21 API SDK
|
2
|
+
|
3
|
+

|
4
|
+
[](https://codecov.io/github/ikael21/school21_api_sdk)
|
5
|
+

|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem and add to the application's Gemfile by executing:
|
10
|
+
|
11
|
+
$ bundle add school21_api_sdk
|
12
|
+
|
13
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
14
|
+
|
15
|
+
$ gem install school21_api_sdk
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
There are multiple API's method according to School21 OpenAPI Specification. Check https://edu.21-school.ru/docs
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'school21'
|
23
|
+
|
24
|
+
login = 'your_login_here'
|
25
|
+
password = 'your_password_here'
|
26
|
+
|
27
|
+
client = School21::Client.new(login: login, password: password)
|
28
|
+
|
29
|
+
# Example of getting base info about specific School21 participant
|
30
|
+
participants_api = client.participants_api
|
31
|
+
response = participants_api.participants('ikael@student.21-school.ru')
|
32
|
+
|
33
|
+
if response.success?
|
34
|
+
puts response.data
|
35
|
+
else
|
36
|
+
# Error handling
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Development
|
41
|
+
|
42
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
43
|
+
|
44
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
45
|
+
|
46
|
+
## Contributing
|
47
|
+
|
48
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ikael21/school21_api_sdk.
|
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'school21'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require 'irb'
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class AuthApi < BaseApi
|
5
|
+
def token(login:, password:)
|
6
|
+
new_request = new_request_builder(HttpMethod::POST, '/token', :auth)
|
7
|
+
.form_param(new_parameter(login, key: :username))
|
8
|
+
.form_param(new_parameter(password, key: :password))
|
9
|
+
.form_param(new_parameter('password', key: :grant_type))
|
10
|
+
.form_param(new_parameter('s21-open-api', key: :client_id))
|
11
|
+
|
12
|
+
new_api_call_builder
|
13
|
+
.request(new_request)
|
14
|
+
.response(new_response_handler)
|
15
|
+
.execute
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class BaseApi
|
5
|
+
include CoreLibrary
|
6
|
+
|
7
|
+
SINGLE_AUTH_PARTICIPANT = :global
|
8
|
+
|
9
|
+
def self.base_uri(server)
|
10
|
+
case server
|
11
|
+
when :api_v1
|
12
|
+
'https://edu-api.21-school.ru/services/21-school/api/v1'
|
13
|
+
when :auth
|
14
|
+
'https://auth.sberclass.ru/auth/realms/EduPowerKeycloak/protocol/openid-connect'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.response_convertor(api_response)
|
19
|
+
api_response.data.deep_transform_keys! do |key|
|
20
|
+
key.underscore.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
api_response
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(global_configuration)
|
27
|
+
@global_configuration = global_configuration
|
28
|
+
@api_call = ApiCall.new(@global_configuration)
|
29
|
+
end
|
30
|
+
|
31
|
+
def new_api_call_builder = @api_call.new_builder
|
32
|
+
|
33
|
+
def new_response_handler
|
34
|
+
ResponseHandler.new
|
35
|
+
.deserializer(ApiHelper.method(:json_deserialize))
|
36
|
+
.is_api_response(true)
|
37
|
+
.convertor(self.class.method(:response_convertor))
|
38
|
+
end
|
39
|
+
|
40
|
+
def new_request_builder(http_method, path, server)
|
41
|
+
RequestBuilder.new
|
42
|
+
.http_method(http_method)
|
43
|
+
.path(path)
|
44
|
+
.server(server)
|
45
|
+
end
|
46
|
+
|
47
|
+
def new_parameter(value, key: nil)
|
48
|
+
Parameter.new
|
49
|
+
.key(key)
|
50
|
+
.value(value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class ParticipantsApi < BaseApi
|
5
|
+
def participants(login)
|
6
|
+
path = "/participants/#{login}"
|
7
|
+
new_request = new_request_builder(HttpMethod::GET, path, :api_v1)
|
8
|
+
.auth(CoreLibrary::Single.new(SINGLE_AUTH_PARTICIPANT))
|
9
|
+
|
10
|
+
new_api_call_builder
|
11
|
+
.request(new_request)
|
12
|
+
.response(new_response_handler)
|
13
|
+
.execute
|
14
|
+
end
|
15
|
+
|
16
|
+
def participants_projects(login, options: {})
|
17
|
+
path = "/participants/#{login}/projects"
|
18
|
+
default_options = { limit: 1000, offset: 0 }.merge(options)
|
19
|
+
|
20
|
+
parameters = default_options.map do |key, value|
|
21
|
+
new_parameter(value, key:)
|
22
|
+
end
|
23
|
+
|
24
|
+
new_request = new_request_builder(HttpMethod::GET, path, :api_v1)
|
25
|
+
.auth(CoreLibrary::Single.new(SINGLE_AUTH_PARTICIPANT))
|
26
|
+
|
27
|
+
parameters.each do |parameter|
|
28
|
+
new_request.query_param(parameter)
|
29
|
+
end
|
30
|
+
|
31
|
+
new_api_call_builder
|
32
|
+
.request(new_request)
|
33
|
+
.response(new_response_handler)
|
34
|
+
.execute
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class ProjectsApi < BaseApi
|
5
|
+
def projects(project_id)
|
6
|
+
path = "/projects/#{project_id}"
|
7
|
+
new_request = new_request_builder(HttpMethod::GET, path, :api_v1)
|
8
|
+
.auth(CoreLibrary::Single.new(SINGLE_AUTH_PARTICIPANT))
|
9
|
+
|
10
|
+
new_api_call_builder
|
11
|
+
.request(new_request)
|
12
|
+
.response(new_response_handler)
|
13
|
+
.execute
|
14
|
+
end
|
15
|
+
|
16
|
+
def projects_participants(project_id, options: {})
|
17
|
+
path = "/projects/#{project_id}/participants"
|
18
|
+
default_options = { limit: 1000, offset: 0 }.merge(options)
|
19
|
+
|
20
|
+
parameters = default_options.map do |key, value|
|
21
|
+
new_parameter(value, key:)
|
22
|
+
end
|
23
|
+
|
24
|
+
new_request = new_request_builder(HttpMethod::GET, path, :api_v1)
|
25
|
+
.auth(CoreLibrary::Single.new(SINGLE_AUTH_PARTICIPANT))
|
26
|
+
|
27
|
+
parameters.each do |parameter|
|
28
|
+
new_request.query_param(parameter)
|
29
|
+
end
|
30
|
+
|
31
|
+
new_api_call_builder
|
32
|
+
.request(new_request)
|
33
|
+
.response(new_response_handler)
|
34
|
+
.execute
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class AccessToken
|
5
|
+
attr_reader :access_token
|
6
|
+
|
7
|
+
def initialize(access_token, expires_in)
|
8
|
+
@access_token = access_token
|
9
|
+
@expires_at = Time.now + expires_in
|
10
|
+
end
|
11
|
+
|
12
|
+
def expired?
|
13
|
+
Time.now >= @expires_at
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class AuthorizationHeader < CoreLibrary::HeaderAuth
|
5
|
+
def error_message
|
6
|
+
'BearerAuth: access_token is undefined.'
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(bearer_auth_credentials)
|
10
|
+
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?
|
16
|
+
|
17
|
+
super(auth_params)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class BearerAuthCredentials
|
5
|
+
attr_reader :access_token
|
6
|
+
|
7
|
+
def initialize(access_token:)
|
8
|
+
raise ArgumentError, 'access_token cannot be nil' if access_token.nil?
|
9
|
+
|
10
|
+
@access_token = access_token.access_token
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module School21
|
4
|
+
class Client
|
5
|
+
include CoreLibrary
|
6
|
+
|
7
|
+
def initialize(login:, password:)
|
8
|
+
raise ArgumentError, "login can't be nil or empty" if login.nil? || login.empty?
|
9
|
+
raise ArgumentError, "password can't be nil or empty" if password.nil? || password.empty?
|
10
|
+
|
11
|
+
client_configuration = HttpClientConfiguration.new(logging_configuration:)
|
12
|
+
http_client = FaradayClient.new(client_configuration)
|
13
|
+
client_configuration.set_http_client(http_client)
|
14
|
+
|
15
|
+
@login = login
|
16
|
+
@password = password
|
17
|
+
|
18
|
+
@config = GlobalConfiguration
|
19
|
+
.new(client_configuration:)
|
20
|
+
.base_uri_executor(BaseApi.method(:base_uri))
|
21
|
+
|
22
|
+
initialize_auth!
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth_api = @auth_api ||= AuthApi.new(@config)
|
26
|
+
|
27
|
+
def participants_api
|
28
|
+
initialize_auth! if @access_token.expired?
|
29
|
+
|
30
|
+
ParticipantsApi.new(@config)
|
31
|
+
end
|
32
|
+
|
33
|
+
def projects_api
|
34
|
+
initialize_auth! if @access_token.expired?
|
35
|
+
|
36
|
+
ProjectsApi.new(@config)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def initialize_auth!
|
42
|
+
@access_token = request_access_token!
|
43
|
+
|
44
|
+
initialize_auth_managers
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize_auth_managers
|
48
|
+
auth_managers = {}
|
49
|
+
|
50
|
+
creds = BearerAuthCredentials.new(access_token: @access_token)
|
51
|
+
auth_managers[BaseApi::SINGLE_AUTH_PARTICIPANT] = AuthorizationHeader.new(creds)
|
52
|
+
|
53
|
+
@config.auth_managers(auth_managers)
|
54
|
+
end
|
55
|
+
|
56
|
+
def request_access_token!
|
57
|
+
auth_api_response = auth_api.token(login: @login, password: @password)
|
58
|
+
raise 'Access Token Error' unless auth_api_response.success?
|
59
|
+
|
60
|
+
AccessToken.new(*auth_api_response.data.values_at(:access_token, :expires_in))
|
61
|
+
end
|
62
|
+
|
63
|
+
def logging_configuration
|
64
|
+
headers_to_exclude = ['Authorization']
|
65
|
+
api_request_config = ApiRequestLoggingConfiguration.new(true, true, headers_to_exclude, nil, nil, true)
|
66
|
+
api_response_config = ApiResponseLoggingConfiguration.new(true, true, nil, nil, nil)
|
67
|
+
|
68
|
+
ApiLoggingConfiguration.new(nil, nil, api_request_config, api_response_config, false)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/school21.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apimatic_core'
|
4
|
+
require 'apimatic_faraday_client_adapter'
|
5
|
+
|
6
|
+
require 'active_support/all'
|
7
|
+
|
8
|
+
require_relative 'school21/auth/access_token'
|
9
|
+
require_relative 'school21/auth/authorization_header'
|
10
|
+
require_relative 'school21/auth/bearer_auth_credentials'
|
11
|
+
|
12
|
+
require_relative 'school21/api/base_api'
|
13
|
+
require_relative 'school21/api/participants_api'
|
14
|
+
require_relative 'school21/api/auth_api'
|
15
|
+
require_relative 'school21/api/projects_api'
|
16
|
+
|
17
|
+
require_relative 'school21/client'
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
require 'simplecov-cobertura'
|
5
|
+
|
6
|
+
SimpleCov.start
|
7
|
+
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
10
|
+
|
11
|
+
require 'school21'
|
12
|
+
require 'minitest/autorun'
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: school21_api_sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anton Yudin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-08-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: apimatic_core
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: apimatic_core_interfaces
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: apimatic_faraday_client_adapter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: base64
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: ''
|
84
|
+
email:
|
85
|
+
- ikael.fess@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- LICENSE
|
91
|
+
- README.md
|
92
|
+
- bin/console
|
93
|
+
- bin/setup
|
94
|
+
- lib/school21.rb
|
95
|
+
- lib/school21/api/auth_api.rb
|
96
|
+
- lib/school21/api/base_api.rb
|
97
|
+
- lib/school21/api/participants_api.rb
|
98
|
+
- lib/school21/api/projects_api.rb
|
99
|
+
- lib/school21/auth/access_token.rb
|
100
|
+
- lib/school21/auth/authorization_header.rb
|
101
|
+
- lib/school21/auth/bearer_auth_credentials.rb
|
102
|
+
- lib/school21/client.rb
|
103
|
+
- lib/school21/version.rb
|
104
|
+
- test/test_helper.rb
|
105
|
+
homepage: https://github.com/ikael21/school21_api_sdk
|
106
|
+
licenses:
|
107
|
+
- Nonstandard
|
108
|
+
metadata:
|
109
|
+
rubygems_mfa_required: 'true'
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '3.3'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubygems_version: 3.5.11
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: School21 API SDK
|
129
|
+
test_files: []
|