openstax_api 0.1.0 → 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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/openstax/api/v1/api_controller.rb +9 -145
  3. data/app/controllers/openstax/api/v1/oauth_based_api_controller.rb +0 -2
  4. data/app/models/openstax/api/api_user.rb +5 -4
  5. data/lib/openstax/api/apipie.rb +51 -0
  6. data/lib/{openstax_api → openstax/api}/constraints.rb +0 -0
  7. data/lib/{openstax_api → openstax/api}/doorkeeper_extensions.rb +0 -0
  8. data/lib/{openstax_api → openstax/api}/engine.rb +0 -0
  9. data/lib/openstax/api/representable_schema_printer.rb +83 -0
  10. data/lib/openstax/api/roar.rb +132 -0
  11. data/lib/{openstax_api → openstax/api}/route_extensions.rb +1 -1
  12. data/lib/{openstax_api → openstax/api}/version.rb +1 -1
  13. data/lib/openstax_api.rb +20 -3
  14. data/spec/app/models/openstax/api/api_user_spec.rb +1 -1
  15. data/spec/app/representers/openstax/api/v1/representable_schema_printer_spec.rb +1 -1
  16. data/spec/dummy/app/models/dummy_user.rb +2 -0
  17. data/spec/dummy/app/representers/{user_representer.rb → dummy_user_representer.rb} +1 -1
  18. data/spec/dummy/config/initializers/openstax_api.rb +3 -0
  19. data/spec/dummy/db/development.sqlite3 +0 -0
  20. data/spec/dummy/db/migrate/{1_create_users.rb → 1_create_dummy_users.rb} +2 -2
  21. data/spec/dummy/db/schema.rb +7 -7
  22. data/spec/dummy/db/test.sqlite3 +0 -0
  23. data/spec/dummy/log/development.log +101 -597
  24. data/spec/dummy/log/test.log +62 -3216
  25. data/spec/lib/openstax/api/apipie.rb +11 -0
  26. data/spec/lib/{openstax_api → openstax/api}/constraints_spec.rb +0 -0
  27. data/spec/lib/{openstax_api → openstax/api}/doorkeeper_extensions_spec.rb +0 -0
  28. data/spec/lib/openstax/api/roar.rb +11 -0
  29. data/spec/lib/{openstax_api → openstax/api}/route_extensions_spec.rb +0 -0
  30. metadata +42 -20
  31. data/app/representers/openstax/api/v1/representable_schema_printer.rb +0 -85
  32. data/spec/dummy/app/models/user.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cce40c843b8d217abd9a7474b34217a10f380468
4
- data.tar.gz: ae159bd0eda6a2191a5dfb3d8ac6b14f504b1df3
3
+ metadata.gz: 0182a7fe7cdaf9adbe7a8719473cd4546c2f3bcb
4
+ data.tar.gz: be4936d879e58990235b59857c65892fc1711456
5
5
  SHA512:
6
- metadata.gz: 7416764ded4187e6dde991c812339d9c370a426ef7ca928807edbb9be0d86aa591d12b01660868066527c2dfb2df84322bdb2da1acbecddc6dade5e218cf4860
7
- data.tar.gz: b714b80dbd734dd882eeb2a28442835f66372d9f5b32e920258e7291b90e536154c9e883de04b72b1a913991d6082763479e4a87dfabc3950527894e03d6b72f
6
+ metadata.gz: 2948208fe965b6e01bc5e67615b48058d52998fb40e4f2db620e4ee646f6559b19c0725439956f2107dc171b698b718b9252703a267a484ff324dcb7208949aa
7
+ data.tar.gz: 433bd360c6317cde8864ad9933877605387eaf3a8d92ee3267836abdce5e143663b2cb65acdec7f7ce735b0b4adb266ab5f97e04020c14496f9c7daaed6b9b3a
@@ -1,4 +1,7 @@
1
1
  require 'roar-rails'
2
+ require 'exception_notification'
3
+ require 'openstax/api/roar'
4
+ require 'openstax/api/apipie'
2
5
 
3
6
  module OpenStax
4
7
  module Api
@@ -6,7 +9,9 @@ module OpenStax
6
9
 
7
10
  class ApiController < ::ApplicationController
8
11
 
9
- include Roar::Rails::ControllerAdditions
12
+ include ::Roar::Rails::ControllerAdditions
13
+ include OpenStax::Api::Roar
14
+ include OpenStax::Api::Apipie
10
15
 
11
16
  fine_print_skip_signatures(:general_terms_of_use,
12
17
  :privacy_policy) \
@@ -19,18 +24,7 @@ module OpenStax
19
24
  respond_to :json
20
25
  rescue_from Exception, :with => :rescue_from_exception
21
26
 
22
- def self.api_example(options={})
23
- return if Rails.env.test?
24
- raise IllegalArgument, "must supply a :url parameter" if !options[:url_base]
25
-
26
- url_base = options[:url_base].is_a?(Symbol) ?
27
- UrlGenerator.new.send(options[:url_base], protocol: 'https') :
28
- options[:url_base].to_s
29
-
30
- "#{url_base}/#{options[:url_end] || ''}"
31
- end
32
-
33
- # TODO doorkeeper users (or rather users who have doorkeeper
27
+ # TODO: doorkeeper users (or rather users who have doorkeeper
34
28
  # applications) need to agree to API terms of use (need to have agreed
35
29
  # to it at one time, can't require them to agree when terms change since
36
30
  # their apps are doing the talking) -- this needs more thought
@@ -39,13 +33,11 @@ module OpenStax
39
33
  @current_user ||= doorkeeper_token ?
40
34
  User.find(doorkeeper_token.resource_owner_id) :
41
35
  super
42
- # TODO maybe freak out if current user is anonymous (require we know
36
+ # TODO: maybe freak out if current user is anonymous (require we know
43
37
  # who person/app is so we can do things like throttling, API terms
44
38
  # agreement, etc)
45
39
  end
46
40
 
47
-
48
-
49
41
  protected
50
42
 
51
43
  def rescue_from_exception(exception)
@@ -66,147 +58,19 @@ module OpenStax
66
58
  end
67
59
 
68
60
  if notify
69
- # TODO: Not yet in OSU
70
- =begin
71
61
  ExceptionNotifier.notify_exception(
72
62
  exception,
73
63
  env: request.env,
74
64
  data: { message: "An exception occurred" }
75
65
  )
76
- =end
66
+
77
67
  Rails.logger.error("An exception occurred: #{exception.message}\n\n#{exception.backtrace.join("\n")}") \
78
68
  end
79
69
 
80
70
  head error
81
71
  end
82
72
 
83
- def self.json_schema(representer, options={})
84
- RepresentableSchemaPrinter.json(representer, options)
85
- end
86
-
87
- # A hack at a conversion from a Representer to a series of Apipie declarations
88
- # Can call it like any Apipie DSL method,
89
- #
90
- # example "blah"
91
- # representer Api::V1::ExerciseRepresenter
92
- # def update ...
93
- #
94
- def self.representer(representer)
95
- representer.representable_attrs.each do |attr|
96
- schema_info = attr.options[:schema_info] || {}
97
- param attr.name, (attr.options[:type] || Object), required: schema_info[:required]
98
- end
99
- end
100
73
 
101
- def get_representer(represent_with, model=nil)
102
- return nil if represent_with.nil?
103
- if represent_with.is_a? Proc
104
- represent_with.call(model)
105
- else
106
- represent_with
107
- end
108
- end
109
-
110
- def rest_get(model_klass, id, represent_with=nil)
111
- @model = model_klass.find(id)
112
- raise SecurityTransgression unless current_user.can_read?(@model)
113
- respond_with @model, represent_with: get_representer(represent_with, @model)
114
- end
115
-
116
- def rest_update(model_klass, id, represent_with=nil)
117
- @model = model_klass.find(id)
118
- raise SecurityTransgression unless current_user.can_update?(@model)
119
- consume!(@model, represent_with: get_representer(represent_with, @model))
120
-
121
- if @model.save
122
- head :no_content
123
- else
124
- render json: @model.errors, status: :unprocessable_entity
125
- end
126
- end
127
-
128
- def rest_create(model_klass)
129
- @model = model_klass.new()
130
-
131
- # Unlike the implications of the representable README, "consume!" can
132
- # actually make changes to the database. See http://goo.gl/WVLBqA.
133
- # We do want to consume before checking the permissions so we can know
134
- # what we're dealing with, but if user doesn't have permission we don't
135
- # want to have changed the DB. Wrap in a transaction to protect ourselves.
136
-
137
- model_klass.transaction do
138
- consume!(@model)
139
- raise SecurityTransgression unless current_user.can_create?(@model)
140
- end
141
-
142
- if @model.save
143
- respond_with @model
144
- else
145
- render json: @model.errors, status: :unprocessable_entity
146
- end
147
- end
148
-
149
- def rest_destroy(model_klass, id)
150
- @model = model_klass.find(id)
151
- raise SecurityTransgression unless current_user.can_destroy?(@model)
152
-
153
- if @model.destroy
154
- head :no_content
155
- else
156
- render json: @model.errors, status: :unprocessable_entity
157
- end
158
- end
159
-
160
- def standard_sort(model_klass)
161
- # take array of all IDs or hash of id => position,
162
- # regardless build up an array of all IDs in the right order and pass those to sort
163
-
164
- new_positions = params['newPositions']
165
- return head :no_content if new_positions.length == 0
166
-
167
- # Can't have duplicate positions or IDs
168
- unique_ids = new_positions.collect{|np| np['id']}.uniq
169
- unique_positions = new_positions.collect{|np| np['position']}.uniq
170
-
171
- return head :bad_request if unique_ids.length != new_positions.length
172
- return head :bad_request if unique_positions.length != new_positions.length
173
-
174
- first = model_klass.where(:id => new_positions[0]['id']).first
175
-
176
- return head :not_found if first.blank?
177
-
178
- originalOrdered = first.me_and_peers.ordered.all
179
-
180
- originalOrdered.each do |item|
181
- raise SecurityTransgression unless item.send(:container_column) == originalOrdered[0].send(:container_column) \
182
- if item.respond_to?(:container_column)
183
- raise SecurityTransgression unless current_user.can_sort?(item)
184
- end
185
-
186
- originalOrderedIds = originalOrdered.collect{|sc| sc.id}
187
-
188
- newOrderedIds = Array.new(originalOrderedIds.size)
189
-
190
- new_positions.each do |newPosition|
191
- id = newPosition['id'].to_i
192
- newOrderedIds[newPosition['position']] = id
193
- originalOrderedIds.delete(id)
194
- end
195
-
196
- ptr = 0
197
- for oldId in originalOrderedIds
198
- while !newOrderedIds[ptr].nil?; ptr += 1; end
199
- newOrderedIds[ptr] = oldId
200
- end
201
-
202
- begin
203
- model_klass.sort!(newOrderedIds)
204
- rescue Exception => e
205
- return head :internal_server_error
206
- end
207
-
208
- head :no_content
209
- end
210
74
 
211
75
  end
212
76
 
@@ -4,8 +4,6 @@ module OpenStax
4
4
 
5
5
  class OauthBasedApiController < ApiController
6
6
 
7
- respond_to :json
8
-
9
7
  def current_user
10
8
  @current_api_user ||= ApiUser.new(doorkeeper_token, lambda { super })
11
9
  end
@@ -11,6 +11,8 @@
11
11
  # This API class gives us a way to abstract out these cases and also
12
12
  # gives us accessors to get the Application and User objects, if available.
13
13
 
14
+ require 'openstax_utilities'
15
+
14
16
  module OpenStax
15
17
  module Api
16
18
  class ApiUser
@@ -25,10 +27,11 @@ module OpenStax
25
27
  # procs that can get it for us. This could save us some queries.
26
28
 
27
29
  if doorkeeper_token
30
+ user_class = OpenStax::Api.configuration.user_class_name.classify.constantize
28
31
  @application_proc = lambda { doorkeeper_token.application }
29
32
  @user_proc = lambda {
30
33
  doorkeeper_token.resource_owner_id ?
31
- User.find(doorkeeper_token.resource_owner_id) :
34
+ user_class.find(doorkeeper_token.resource_owner_id) :
32
35
  nil
33
36
  }
34
37
  else
@@ -37,9 +40,7 @@ module OpenStax
37
40
  end
38
41
  end
39
42
 
40
- # Returns a Doorkeeper::Application or nil
41
- # TODO should we have a NoApplication like NoUser (or maybe should
42
- # NoUser just be replaced with nil)
43
+ # Returns a Doorkeeper::Application or nil
43
44
  def application
44
45
  @application ||= @application_proc.call
45
46
  end
@@ -0,0 +1,51 @@
1
+ # Copyright 2011-2014 Rice University. Licensed under the Affero General Public
2
+ # License version 3 or later. See the COPYRIGHT file for details.
3
+
4
+ require 'openstax/api/representable_schema_printer'
5
+
6
+ module OpenStax
7
+ module Api
8
+
9
+ module Apipie
10
+
11
+ def self.included(base)
12
+ base.send :extend, ClassMethods
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ def api_example(options={})
18
+ return if Rails.env.test?
19
+ raise IllegalArgument, "must supply a :url parameter" if !options[:url_base]
20
+
21
+ url_base = options[:url_base].is_a?(Symbol) ?
22
+ UrlGenerator.new.send(options[:url_base], protocol: 'https') :
23
+ options[:url_base].to_s
24
+
25
+ "#{url_base}/#{options[:url_end] || ''}"
26
+ end
27
+
28
+ def json_schema(representer, options={})
29
+ RepresentableSchemaPrinter.json(representer, options)
30
+ end
31
+
32
+ # A hack at a conversion from a Representer to a series of Apipie declarations
33
+ # Can call it like any Apipie DSL method,
34
+ #
35
+ # example "blah"
36
+ # representer Api::V1::ExerciseRepresenter
37
+ # def update ...
38
+ #
39
+ def representer(representer)
40
+ representer.representable_attrs.each do |attr|
41
+ schema_info = attr.options[:schema_info] || {}
42
+ param attr.name, (attr.options[:type] || Object), required: schema_info[:required]
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
File without changes
File without changes
@@ -0,0 +1,83 @@
1
+ module OpenStax
2
+ module Api
3
+ class RepresentableSchemaPrinter
4
+
5
+ def self.json(representer, options={})
6
+ options[:include] ||= [:readable, :writeable]
7
+ options[:indent] ||= ' '
8
+
9
+ definitions = {}
10
+
11
+ schema = json_schema(representer, definitions, options)
12
+ schema[:definitions] = definitions
13
+
14
+ json_string = JSON.pretty_generate(schema, {indent: options[:indent]})
15
+
16
+ "\nSchema {##{SecureRandom.hex(4)} .schema}\n------\n" +
17
+ "<pre class='code'>\n#{json_string}\n</pre>\n"
18
+ end
19
+
20
+ protected
21
+
22
+ def self.json_schema(representer, definitions, options={})
23
+ schema = {
24
+ # id: schema_id(representer),
25
+ # title: schema_title(representer),
26
+ type: "object",
27
+ properties: {},
28
+ required: []
29
+ # :$schema => "http://json-schema.org/draft-04/schema#"
30
+ }
31
+
32
+ representer.representable_attrs.each do |attr|
33
+ schema_info = attr.options[:schema_info] || {}
34
+
35
+ schema[:required].push(attr.name) if schema_info[:required]
36
+
37
+ next unless [options[:include]].flatten.any?{|inc| attr.send(inc.to_s+"?") || schema_info[:required]}
38
+
39
+ attr_info = {}
40
+
41
+ if attr.options[:collection]
42
+ attr_info[:type] = "array"
43
+ else
44
+ attr_info[:type] = attr.options[:type].to_s.downcase if attr.options[:type]
45
+ end
46
+
47
+ schema_info.each do |key, value|
48
+ next if [:required].include?(key)
49
+ value = value.to_s.downcase if key == :type
50
+ attr_info[key] = value
51
+ end
52
+
53
+ decorator = attr.options[:decorator].try(:is_a?, Proc) ? nil : attr.options[:decorator]
54
+
55
+ if decorator
56
+ relative_schema_id(decorator).tap do |id|
57
+ attr_info[:$ref] = "#/definitions/#{id}"
58
+ definitions[id] ||= json_schema(decorator, definitions, options)
59
+ end
60
+ end
61
+
62
+ schema[:properties][attr.name.to_sym] = attr_info
63
+ end
64
+
65
+ schema
66
+ end
67
+
68
+ def self.schema_title(representer)
69
+ representer.name.gsub(/Representer/,'')
70
+ end
71
+
72
+ def self.schema_id(representer)
73
+ "http://#{OpenStax::Api::Engine::MAIN_APP_NAME.to_s}.openstax.org/" +
74
+ "#{schema_title(representer).downcase.gsub(/::/,'/')}"
75
+ end
76
+
77
+ def self.relative_schema_id(representer)
78
+ representer.name.gsub(/Representer/,'').downcase.gsub(/::/,'/')
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,132 @@
1
+ # Copyright 2011-2014 Rice University. Licensed under the Affero General Public
2
+ # License version 3 or later. See the COPYRIGHT file for details.
3
+
4
+ module OpenStax
5
+ module Api
6
+
7
+ module Roar
8
+
9
+ def get_representer(represent_with, model=nil)
10
+ return nil if represent_with.nil?
11
+ if represent_with.is_a? Proc
12
+ represent_with.call(model)
13
+ else
14
+ represent_with
15
+ end
16
+ end
17
+
18
+ def standard_read(model_klass, id, represent_with=nil)
19
+ @model = model_klass.find(id)
20
+ raise SecurityTransgression unless current_user.can_read?(@model)
21
+ respond_with @model, represent_with: get_representer(represent_with, @model)
22
+ end
23
+
24
+ def standard_update(model_klass, id, represent_with=nil)
25
+ @model = model_klass.find(id)
26
+ raise SecurityTransgression unless current_user.can_update?(@model)
27
+ consume!(@model, represent_with: get_representer(represent_with, @model))
28
+
29
+ if @model.save
30
+ head :no_content
31
+ else
32
+ render json: @model.errors, status: :unprocessable_entity
33
+ end
34
+ end
35
+
36
+ def standard_create(model_klass, represent_with=nil)
37
+ standard_nested_create(model_klass, nil, nil, represent_with)
38
+ end
39
+
40
+ def standard_nested_create(model_klass, container_association=nil, container_id=nil, represent_with=nil)
41
+ @model = model_klass.new()
42
+
43
+ if container_association && container_id
44
+ foreign_key = model_klass.reflect_on_association(container_association).association_foreign_key
45
+ @model.send(foreign_key + '=', container_id)
46
+ end
47
+
48
+ # Unlike the implications of the representable README, "consume!" can
49
+ # actually make changes to the database. See http://goo.gl/WVLBqA.
50
+ # We do want to consume before checking the permissions so we can know
51
+ # what we're dealing with, but if user doesn't have permission we don't
52
+ # want to have changed the DB. Wrap in a transaction to protect ourselves.
53
+
54
+ model_klass.transaction do
55
+ consume!(@model, represent_with: get_representer(represent_with, @model))
56
+ yield @model if block_given?
57
+ raise SecurityTransgression unless current_user.can_create?(@model)
58
+ end
59
+
60
+ if @model.save
61
+ respond_with @model, represent_with: get_representer(represent_with, @model), status: :created
62
+ else
63
+ render json: @model.errors, status: :unprocessable_entity
64
+ end
65
+ end
66
+
67
+ def standard_destroy(model_klass, id)
68
+ @model = model_klass.find(id)
69
+ raise SecurityTransgression unless current_user.can_destroy?(@model)
70
+
71
+ if @model.destroy
72
+ head :no_content
73
+ else
74
+ render json: @model.errors, status: :unprocessable_entity
75
+ end
76
+ end
77
+
78
+ def standard_sort(model_klass)
79
+ # Take array of all IDs or hash of id => position,
80
+ # Regardless, build up an array of all IDs in the right order and pass those to sort
81
+
82
+ new_positions = params['newPositions']
83
+ return head :no_content if new_positions.length == 0
84
+
85
+ # Can't have duplicate positions or IDs
86
+ unique_ids = new_positions.collect{|np| np['id']}.uniq
87
+ unique_positions = new_positions.collect{|np| np['position']}.uniq
88
+
89
+ return head :bad_request if unique_ids.length != new_positions.length
90
+ return head :bad_request if unique_positions.length != new_positions.length
91
+
92
+ first = model_klass.where(:id => new_positions[0]['id']).first
93
+
94
+ return head :not_found if first.blank?
95
+
96
+ originalOrdered = first.me_and_peers.ordered.all
97
+
98
+ originalOrdered.each do |item|
99
+ raise SecurityTransgression unless item.send(:container_column) == originalOrdered[0].send(:container_column) \
100
+ if item.respond_to?(:container_column)
101
+ raise SecurityTransgression unless current_user.can_sort?(item)
102
+ end
103
+
104
+ originalOrderedIds = originalOrdered.collect{|sc| sc.id}
105
+
106
+ newOrderedIds = Array.new(originalOrderedIds.size)
107
+
108
+ new_positions.each do |newPosition|
109
+ id = newPosition['id'].to_i
110
+ newOrderedIds[newPosition['position']] = id
111
+ originalOrderedIds.delete(id)
112
+ end
113
+
114
+ ptr = 0
115
+ for oldId in originalOrderedIds
116
+ while !newOrderedIds[ptr].nil?; ptr += 1; end
117
+ newOrderedIds[ptr] = oldId
118
+ end
119
+
120
+ begin
121
+ model_klass.sort!(newOrderedIds)
122
+ rescue Exception => e
123
+ return head :internal_server_error
124
+ end
125
+
126
+ head :no_content
127
+ end
128
+
129
+ end
130
+
131
+ end
132
+ end
@@ -1,4 +1,4 @@
1
- require 'openstax_api/constraints'
1
+ require 'openstax/api/constraints'
2
2
 
3
3
  module OpenStax
4
4
  module Api
@@ -1,5 +1,5 @@
1
1
  module OpenStax
2
2
  module Api
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
data/lib/openstax_api.rb CHANGED
@@ -1,8 +1,25 @@
1
- require 'openstax_api/engine'
2
- require 'openstax_api/doorkeeper_extensions'
3
- require 'openstax_api/route_extensions'
1
+ require 'openstax/api/engine'
2
+ require 'openstax/api/doorkeeper_extensions'
3
+ require 'openstax/api/route_extensions'
4
4
 
5
5
  module OpenStax
6
6
  module Api
7
+
8
+ def self.configure
9
+ yield configuration
10
+ end
11
+
12
+ def self.configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ class Configuration
17
+ attr_accessor :user_class_name
18
+
19
+ def initialize
20
+ @user_class_name = 'User'
21
+ end
22
+ end
23
+
7
24
  end
8
25
  end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  module OpenStax
4
4
  module Api
5
5
  describe ApiUser do
6
- let(:user) { User.create }
6
+ let(:user) { DummyUser.create }
7
7
  let(:application) { double('Doorkeeper::Application') }
8
8
  let(:doorkeeper_token) { double('Doorkeeper::AccessToken') }
9
9
  let(:non_doorkeeper_user_proc) { lambda { user } }
@@ -5,7 +5,7 @@ module OpenStax
5
5
  module V1
6
6
  describe RepresentableSchemaPrinter do
7
7
  it 'must print model schemas' do
8
- schema = RepresentableSchemaPrinter.json(UserRepresenter)
8
+ schema = RepresentableSchemaPrinter.json(DummyUserRepresenter)
9
9
  expect(schema).to include('Schema')
10
10
  expect(schema).to include('.schema')
11
11
  expect(schema).to include('------')
@@ -0,0 +1,2 @@
1
+ class DummyUser < ActiveRecord::Base
2
+ end
@@ -1,6 +1,6 @@
1
1
  require 'representable/json'
2
2
 
3
- module UserRepresenter
3
+ module DummyUserRepresenter
4
4
  include Roar::Representer::JSON
5
5
 
6
6
  property :username
@@ -0,0 +1,3 @@
1
+ OpenStax::Api.configure do |config|
2
+ config.user_class_name = 'DummyUser'
3
+ end
Binary file
@@ -1,6 +1,6 @@
1
- class CreateUsers < ActiveRecord::Migration
1
+ class CreateDummyUsers < ActiveRecord::Migration
2
2
  def change
3
- create_table :users do |t|
3
+ create_table :dummy_users do |t|
4
4
  t.string :username
5
5
  t.string :password_hash
6
6
 
@@ -13,6 +13,13 @@
13
13
 
14
14
  ActiveRecord::Schema.define(:version => 1) do
15
15
 
16
+ create_table "dummy_users", :force => true do |t|
17
+ t.string "username"
18
+ t.string "password_hash"
19
+ t.datetime "created_at", :null => false
20
+ t.datetime "updated_at", :null => false
21
+ end
22
+
16
23
  create_table "oauth_access_grants", :force => true do |t|
17
24
  t.integer "resource_owner_id", :null => false
18
25
  t.integer "application_id", :null => false
@@ -52,11 +59,4 @@ ActiveRecord::Schema.define(:version => 1) do
52
59
 
53
60
  add_index "oauth_applications", ["uid"], :name => "index_oauth_applications_on_uid", :unique => true
54
61
 
55
- create_table "users", :force => true do |t|
56
- t.string "username"
57
- t.string "password_hash"
58
- t.datetime "created_at", :null => false
59
- t.datetime "updated_at", :null => false
60
- end
61
-
62
62
  end
Binary file