xporter_on_demand 0.1.4 → 0.2.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 +48 -0
- data/lib/xporter_on_demand/registration.rb +110 -0
- data/lib/xporter_on_demand/token.rb +14 -0
- data/lib/xporter_on_demand/utils.rb +8 -1
- data/lib/xporter_on_demand/version.rb +1 -1
- data/lib/xporter_on_demand.rb +5 -3
- metadata +8 -8
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2650748b5f2276cc4f3b0be0eeea8b7f7ce2e3c95ca22ecde37521d5863e53d4
         | 
| 4 | 
            +
              data.tar.gz: 6e2e16eb2a12043f080cb67ce7c29ec495796193cbd3acef48ef2493b19e0a3b
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: a1c2e2f64d3fb7fa4b6a7aa9809820531d6668688b14cd0b34efcef969d280c1bc016844988325a87167574b46a2c33894926df84433625c9e02269c4540afc4
         | 
| 7 | 
            +
              data.tar.gz: 8fb6f4e7fbc24cca17be7788757151a99729db6afcdd481450c73f5fb99c7bec189838205d86aac9120d6a2889398c9d4720d52b26b2e1268ccf4b2f0243051c
         | 
    
        data/README.md
    CHANGED
    
    | @@ -26,3 +26,51 @@ student_results = client.query(students_endpoint) | |
| 26 26 | 
             
            # Retrieve all pages
         | 
| 27 27 | 
             
            student_results.fetch_all
         | 
| 28 28 | 
             
            ```
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            ## Using the Invitation API
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            ```ruby
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            # Create your registration object
         | 
| 35 | 
            +
            reg = XporterOnDemand::Registration.new do |r|
         | 
| 36 | 
            +
              r.registration_type     = 'Test' # Defaults to 'Live'
         | 
| 37 | 
            +
              r.partner_id            = 'your-partner-id'
         | 
| 38 | 
            +
              r.app_management_secret = 'your-app-management-secret'
         | 
| 39 | 
            +
            end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            # Build your school with at the required parameters
         | 
| 42 | 
            +
            school = {
         | 
| 43 | 
            +
              lea_code: 123,                                          # Required
         | 
| 44 | 
            +
              dfes_code: 4567,                                        # Required
         | 
| 45 | 
            +
              school_name: 'Test School',                             # Required
         | 
| 46 | 
            +
              school_contact_first_name: 'Joe',                       # Required
         | 
| 47 | 
            +
              school_contact_last_name: 'Bloggs',                     # Required
         | 
| 48 | 
            +
              school_contact_email: 'joe.bloggs@email.com',           # Required
         | 
| 49 | 
            +
              school_contact_phone: '01234 567890',                   # Required
         | 
| 50 | 
            +
              school_contact: 'Joe Bloggs',
         | 
| 51 | 
            +
              school_technical_contact_name: 'Jim Bloggs',
         | 
| 52 | 
            +
              school_technical_contact_email: 'jim.bloggs@email.com',
         | 
| 53 | 
            +
              school_technical_contact_phone: '01234 567890',
         | 
| 54 | 
            +
              partner_application_id: 'your-partner-id',              # Required
         | 
| 55 | 
            +
              partner_name: 'your-registered-name',                   # Required
         | 
| 56 | 
            +
              partner_registered_email: 'your-registered-email',      # Required
         | 
| 57 | 
            +
              we_accept_groupcall_usage_policy: true,                 # Required
         | 
| 58 | 
            +
            }
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            # Add school to the registration object. Multiple schools can be added
         | 
| 61 | 
            +
            reg.add_school(school)
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            # Send registrations
         | 
| 64 | 
            +
            reg.register
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            # Will return a boolean outlining whether or not ALL registrations were successful.
         | 
| 67 | 
            +
            # Any error messages will be assigned to the registration object or the
         | 
| 68 | 
            +
            # individual schools eg.
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            reg.message
         | 
| 71 | 
            +
            # => 'Unauthorized: ApplicationId header missing or incorrect'
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            reg.schools.first.message
         | 
| 74 | 
            +
            # => 'School not found in EduBase'
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            ```
         | 
| @@ -0,0 +1,110 @@ | |
| 1 | 
            +
            require 'xporter_on_demand/utils'
         | 
| 2 | 
            +
            require 'base64'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module XporterOnDemand
         | 
| 5 | 
            +
              class Registration
         | 
| 6 | 
            +
                include XporterOnDemand::Utils
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_reader :schools, :message
         | 
| 9 | 
            +
                attr_accessor :registration_type, :partner_id, :app_management_secret
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                SCHOOL_ATTRIBUTES = %i(
         | 
| 12 | 
            +
                  lea_code
         | 
| 13 | 
            +
                  dfes_code
         | 
| 14 | 
            +
                  school_name
         | 
| 15 | 
            +
                  school_contact_first_name
         | 
| 16 | 
            +
                  school_contact_last_name
         | 
| 17 | 
            +
                  school_contact_email
         | 
| 18 | 
            +
                  school_contact_phone
         | 
| 19 | 
            +
                  school_contact
         | 
| 20 | 
            +
                  school_technical_contact_name
         | 
| 21 | 
            +
                  school_technical_contact_email
         | 
| 22 | 
            +
                  school_technical_contact_phone
         | 
| 23 | 
            +
                  partner_application_id
         | 
| 24 | 
            +
                  partner_name
         | 
| 25 | 
            +
                  partner_registered_email
         | 
| 26 | 
            +
                  scopes_to_authorise
         | 
| 27 | 
            +
                  we_accept_groupcall_usage_policy
         | 
| 28 | 
            +
                )
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                School = Struct.new(*SCHOOL_ATTRIBUTES) do
         | 
| 31 | 
            +
                  attr_accessor :status, :message
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  def camelize
         | 
| 34 | 
            +
                    to_h.transform_keys{ |k| k.to_s.camelcase }.reject{ |_k, v| v.nil? || (String === v && v.empty?) }
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def initialize(args = {})
         | 
| 39 | 
            +
                  @schools = Set.new
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  if block_given?
         | 
| 42 | 
            +
                    yield self
         | 
| 43 | 
            +
                  else
         | 
| 44 | 
            +
                    @registration_type     = args[:registration_type] || 'Live'
         | 
| 45 | 
            +
                    @partner_id            = args[:partner_id]
         | 
| 46 | 
            +
                    @app_management_secret = args[:app_management_secret]
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def add_school(param_hash = {})
         | 
| 51 | 
            +
                  attributes = SCHOOL_ATTRIBUTES.each_with_object({}) do |key, hash|
         | 
| 52 | 
            +
                    hash[key] = param_hash[key]
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  if School.const_defined? 'ActiveModel::Model'
         | 
| 56 | 
            +
                    @schools << School.new.tap{ |s| s.assign_attributes attributes }
         | 
| 57 | 
            +
                  else
         | 
| 58 | 
            +
                    @schools << School.new(*attributes.values)
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def register
         | 
| 63 | 
            +
                  timestamp = DateTime.current.strftime("%FT%T")
         | 
| 64 | 
            +
                  auth = generate_hash(timestamp: timestamp)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  args = {
         | 
| 67 | 
            +
                    url: REGISTRATION_PATH,
         | 
| 68 | 
            +
                    headers: {
         | 
| 69 | 
            +
                      'ApplicationId': @partner_id,
         | 
| 70 | 
            +
                      'DateTime': timestamp,
         | 
| 71 | 
            +
                      'Authorization': "Groupcall #{auth}",
         | 
| 72 | 
            +
                    },
         | 
| 73 | 
            +
                    body: to_json,
         | 
| 74 | 
            +
                  }
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  response = post(args)
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  if response['Schools']
         | 
| 79 | 
            +
                    response['Schools'].all? do |school|
         | 
| 80 | 
            +
                      s = get_school(school['LeaCode'], school['DfesCode'])
         | 
| 81 | 
            +
                      s.status = school['Status']
         | 
| 82 | 
            +
                      s.message = school['Message']
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                      school['Status'] == 'OK'
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
                  else
         | 
| 87 | 
            +
                    @message = response['Message']
         | 
| 88 | 
            +
                    false
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                def get_school(lea, dfes)
         | 
| 93 | 
            +
                  @schools.find{ |sch| sch.lea_code == lea && sch.dfes_code == dfes }
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                def to_json
         | 
| 97 | 
            +
                  { Schools: @schools.map(&:camelize), RegistrationType: @registration_type }.to_json
         | 
| 98 | 
            +
                end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                def generate_hash(secret: @app_management_secret, timestamp:, content: to_json)
         | 
| 101 | 
            +
                  raise ArgumentError, 'Must supply your App Management Secret' unless secret
         | 
| 102 | 
            +
                  raise ArgumentError, 'Must supply at least one school' if @schools.empty?
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  b64 = Base64.strict_encode64(content + timestamp + secret)
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                  sha256 = OpenSSL::Digest.new('sha256')
         | 
| 107 | 
            +
                  OpenSSL::HMAC.hexdigest(sha256, secret, b64).upcase
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
              end
         | 
| 110 | 
            +
            end
         | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            module XporterOnDemand
         | 
| 2 2 | 
             
              class Token < Client
         | 
| 3 3 | 
             
                def initialize(*args)
         | 
| 4 | 
            +
                  @loaded = false
         | 
| 4 5 | 
             
                  @options = args.last.is_a?(Hash) ? args.pop : {}
         | 
| 5 6 | 
             
                  @options[:url] ||= STS_PATH
         | 
| 6 7 |  | 
| @@ -14,7 +15,20 @@ module XporterOnDemand | |
| 14 15 | 
             
                def retrieve
         | 
| 15 16 | 
             
                  result = post(@options.merge(body: @request_body.to_json))
         | 
| 16 17 | 
             
                  assign_attributes(result)
         | 
| 18 | 
            +
                  @loaded =  true
         | 
| 17 19 | 
             
                  self
         | 
| 18 20 | 
             
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def validate
         | 
| 23 | 
            +
                  dont_raise_exception{ retrieve }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  if token
         | 
| 26 | 
            +
                    :valid
         | 
| 27 | 
            +
                  elsif try(:authorisation_paused)
         | 
| 28 | 
            +
                    :paused
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    :invalid
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 19 33 | 
             
              end
         | 
| 20 34 | 
             
            end
         | 
| @@ -18,7 +18,7 @@ module XporterOnDemand | |
| 18 18 |  | 
| 19 19 | 
             
                def handle_exceptions(response)
         | 
| 20 20 | 
             
                  response_body = JSON.parse(response.body || {})
         | 
| 21 | 
            -
                  raise response_body["ExceptionMessage"] if response_body["ExceptionMessage"]
         | 
| 21 | 
            +
                  raise response_body["ExceptionMessage"] if response_body["ExceptionMessage"] && !@dont_raise_exception
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 24 | 
             
                def parameterize(sym)
         | 
| @@ -68,5 +68,12 @@ module XporterOnDemand | |
| 68 68 | 
             
                    enum
         | 
| 69 69 | 
             
                  end
         | 
| 70 70 | 
             
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def dont_raise_exception
         | 
| 73 | 
            +
                  @dont_raise_exception = true
         | 
| 74 | 
            +
                  yield
         | 
| 75 | 
            +
                ensure
         | 
| 76 | 
            +
                  @dont_raise_exception = false
         | 
| 77 | 
            +
                end
         | 
| 71 78 | 
             
              end
         | 
| 72 79 | 
             
            end
         | 
    
        data/lib/xporter_on_demand.rb
    CHANGED
    
    | @@ -14,9 +14,11 @@ require 'xporter_on_demand/version' | |
| 14 14 | 
             
            require 'xporter_on_demand/result/base'
         | 
| 15 15 | 
             
            require 'xporter_on_demand/result/result_set'
         | 
| 16 16 | 
             
            require 'xporter_on_demand/result/serialiser'
         | 
| 17 | 
            +
            require 'xporter_on_demand/registration'
         | 
| 17 18 |  | 
| 18 19 | 
             
            module XporterOnDemand
         | 
| 19 | 
            -
              API_PATH | 
| 20 | 
            -
              STS_PATH | 
| 21 | 
            -
              META_KEYS | 
| 20 | 
            +
              API_PATH          = "https://xporter.groupcall.com/api/v1/"
         | 
| 21 | 
            +
              STS_PATH          = "https://login.groupcall.com/idaas/sts/STS/GetToken"
         | 
| 22 | 
            +
              META_KEYS         = %w(ChangedRows DbStatus Meta Pagination)
         | 
| 23 | 
            +
              REGISTRATION_PATH = "https://manage.groupcall.com/API/XporterOnDemand/SchoolRegister"
         | 
| 22 24 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: xporter_on_demand
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jordan Green
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2019-03-27 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: httpi
         | 
| @@ -28,20 +28,20 @@ dependencies: | |
| 28 28 | 
             
              name: httpclient
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 30 | 
             
                requirements:
         | 
| 31 | 
            -
                - - " | 
| 31 | 
            +
                - - ">="
         | 
| 32 32 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 33 | 
             
                    version: 2.8.3
         | 
| 34 | 
            -
                - - " | 
| 34 | 
            +
                - - "~>"
         | 
| 35 35 | 
             
                  - !ruby/object:Gem::Version
         | 
| 36 36 | 
             
                    version: 2.8.3
         | 
| 37 37 | 
             
              type: :runtime
         | 
| 38 38 | 
             
              prerelease: false
         | 
| 39 39 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 40 40 | 
             
                requirements:
         | 
| 41 | 
            -
                - - " | 
| 41 | 
            +
                - - ">="
         | 
| 42 42 | 
             
                  - !ruby/object:Gem::Version
         | 
| 43 43 | 
             
                    version: 2.8.3
         | 
| 44 | 
            -
                - - " | 
| 44 | 
            +
                - - "~>"
         | 
| 45 45 | 
             
                  - !ruby/object:Gem::Version
         | 
| 46 46 | 
             
                    version: 2.8.3
         | 
| 47 47 | 
             
            - !ruby/object:Gem::Dependency
         | 
| @@ -120,6 +120,7 @@ files: | |
| 120 120 | 
             
            - lib/xporter_on_demand/client.rb
         | 
| 121 121 | 
             
            - lib/xporter_on_demand/endpoint.rb
         | 
| 122 122 | 
             
            - lib/xporter_on_demand/factory.rb
         | 
| 123 | 
            +
            - lib/xporter_on_demand/registration.rb
         | 
| 123 124 | 
             
            - lib/xporter_on_demand/result/base.rb
         | 
| 124 125 | 
             
            - lib/xporter_on_demand/result/result_set.rb
         | 
| 125 126 | 
             
            - lib/xporter_on_demand/result/serialiser.rb
         | 
| @@ -146,8 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 146 147 | 
             
                - !ruby/object:Gem::Version
         | 
| 147 148 | 
             
                  version: '0'
         | 
| 148 149 | 
             
            requirements: []
         | 
| 149 | 
            -
             | 
| 150 | 
            -
            rubygems_version: 2.7.6
         | 
| 150 | 
            +
            rubygems_version: 3.0.1
         | 
| 151 151 | 
             
            signing_key: 
         | 
| 152 152 | 
             
            specification_version: 4
         | 
| 153 153 | 
             
            summary: Ruby client for the Xporter on Demand API.
         |