mumuki-classroom 9.22.0 → 9.23.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e69915472d5d00dbff99a60c08be0f0ba39ac528031fed66d8dc15197209166b
4
- data.tar.gz: 7ea3bf7cb8a2d6d8d914f91a0a4e9f5d5d6d3c65fd3a0a8d88096d1b1bc3fded
3
+ metadata.gz: cabe7b354830abd76c73425df9e9ff2c4f7fa806bb6dbc0cac68a319bd12e231
4
+ data.tar.gz: acc653411dc6f1a809d0439d93de48d02a64020bd2c446b32ab25afeaff7dd06
5
5
  SHA512:
6
- metadata.gz: 78e0556dbb3d7dad7df7f09acb8bc2675f06788d995801a14489761199746a3b84669fbb9bf82ad0ef2b09958d595fbbd9a2e54064c72d472cc9be7d850717e3
7
- data.tar.gz: 29fa6f708867854dbc987969ca766612d5f2e9e74692d80b5f7c5e8a4e964f78430cf1202587f0500a4b74440a07fec88b16709deb5e54111d836e8c321b6712
6
+ metadata.gz: 0f0c793f1362ca34c185acd9cd92dfc7bdc660ad84f79fcb96b564d88eba59e05270163ff78dcb1bb56aa7cb16b1eb08914316fff37fdcb4ca02dc1611f4cee1
7
+ data.tar.gz: 041020d946aaece5a110f039050486c0983401b6f42f67d899a328896222b6ab9debaeb6c6c6ec1b8b11940d26f0dcbf5c35ec5e69eee18ddacf0429195cc8c8
@@ -29,8 +29,11 @@ class Mumuki::Classroom::Event::UserChanged
29
29
  if students.exists?
30
30
  students.first.attach!
31
31
  else
32
- student = Mumuki::Classroom::Student.attributes_from_uid uid
33
- Mumuki::Classroom::Student.create! student.merge(organization: organization, course: granted_slug.to_s)
32
+ student = Mumuki::Classroom::Student.new(
33
+ Mumuki::Classroom::Student
34
+ .attributes_from_uid(uid)
35
+ .merge(organization: organization, course: granted_slug.to_s))
36
+ student.save! validate: false
34
37
  end
35
38
  end
36
39
 
@@ -41,8 +44,9 @@ class Mumuki::Classroom::Event::UserChanged
41
44
 
42
45
  def teacher_added(organization, user, granted_slug)
43
46
  uid = user[:uid]
44
- teacher = Mumuki::Classroom::Teacher.find_or_create_by!(organization: organization, course: granted_slug.to_s, uid: uid)
45
- teacher.update_attributes!(Mumuki::Classroom::Teacher.attributes_from_uid(uid))
47
+ teacher = Mumuki::Classroom::Teacher.find_or_initialize_by(organization: organization, course: granted_slug.to_s, uid: uid)
48
+ teacher.assign_attributes(Mumuki::Classroom::Teacher.attributes_from_uid(uid))
49
+ teacher.save! validate: false
46
50
  end
47
51
 
48
52
  def teacher_removed(organization, user, granted_slug)
@@ -0,0 +1,15 @@
1
+ class Mumuki::Classroom::Certificate < Mumuki::Classroom::Document
2
+ include Mongoid::Timestamps
3
+
4
+ field :pg_id, type: Integer
5
+ field :code, type: String
6
+ field :certificate_program_id, type: Integer
7
+ field :organization, type: String
8
+ field :student, type: Hash
9
+ field :started_at, type: Time
10
+ field :ended_at, type: Time
11
+
12
+ create_index(pg_id: 1)
13
+ create_index(organization: 1, 'student.course': 1, 'student.uid': 1)
14
+ create_index(certificate_program_id: 1)
15
+ end
@@ -1,6 +1,8 @@
1
1
  module CourseMember
2
2
  extend ActiveSupport::Concern
3
3
 
4
+ MANDATORY_FIELDS = %w(uid first_name last_name email)
5
+
4
6
  included do
5
7
  include Mongoid::Timestamps
6
8
 
@@ -15,6 +17,9 @@ module CourseMember
15
17
  field :course, type: Mumukit::Auth::Slug
16
18
 
17
19
  create_index({organization: 1, course: 1, uid: 1}, {unique: true})
20
+
21
+ validates_presence_of(*MANDATORY_FIELDS)
22
+ validates :email, email: true
18
23
  end
19
24
 
20
25
  def as_user(verified: true)
@@ -23,6 +28,10 @@ module CourseMember
23
28
  end
24
29
 
25
30
  class_methods do
31
+ def valid_attributes?(json)
32
+ MANDATORY_FIELDS.all? { |it| json[it].present? } && EmailValidator.valid?(json[:email])
33
+ end
34
+
26
35
  def ensure_not_exists!(query)
27
36
  existing_members = where(query)
28
37
  raise Mumuki::Classroom::CourseMemberExistsError, {existing_members: existing_members.map(&:uid)}.to_json if existing_members.exists?
@@ -0,0 +1,12 @@
1
+ class Mumuki::Classroom::ExamAuthorization < Mumuki::Classroom::Document
2
+ field :pg_id, type: Integer
3
+ field :session_id, type: String
4
+ field :guide_slug, type: String
5
+ field :organization, type: String
6
+ field :student, type: Hash
7
+ field :started, type: Mongoid::Boolean
8
+ field :started_at, type: Time
9
+
10
+ create_index(pg_id: 1)
11
+ create_index(organization: 1, 'student.course': 1, guide_slug: 1, 'student.uid': 1)
12
+ end
@@ -0,0 +1,15 @@
1
+ class Mumuki::Classroom::ExamAuthorizationRequest < Mumuki::Classroom::Document
2
+ include Mongoid::Timestamps
3
+
4
+ field :pg_id, type: Integer
5
+ field :status, type: String
6
+ field :guide_slug, type: String
7
+ field :organization, type: String
8
+ field :exam_registration_id, type: Integer
9
+ field :student, type: Hash
10
+
11
+ create_index(pg_id: 1)
12
+ create_index(organization: 1, 'student.course': 1, guide_slug: 1, 'student.uid': 1)
13
+ create_index(exam_registration_id: 1)
14
+ create_index(organization: 1, 'student.course': 1, 'student.uid': 1)
15
+ end
@@ -16,6 +16,9 @@ require_relative './models/student'
16
16
  require_relative './models/teacher'
17
17
  require_relative './models/notification'
18
18
  require_relative './models/suggestion'
19
+ require_relative './models/certificate'
20
+ require_relative './models/exam_authorization'
21
+ require_relative './models/exam_authorization_request'
19
22
 
20
23
  require_relative './models/sorting'
21
24
  require_relative './models/searching'
@@ -37,13 +37,13 @@ class Mumuki::Classroom::App < Sinatra::Application
37
37
 
38
38
  post '/students/detach' do
39
39
  update_students! do |processed|
40
- update_students_at_course! :detach, :remove, processed
40
+ update_students_permissions_at_course! :detach, :remove, processed
41
41
  end
42
42
  end
43
43
 
44
44
  post '/students/attach' do
45
45
  update_students! do |processed|
46
- update_students_at_course! :attach, :add, processed
46
+ update_students_permissions_at_course! :attach, :add, processed
47
47
  end
48
48
  end
49
49
 
@@ -98,7 +98,7 @@ class Mumuki::Classroom::App < Sinatra::Application
98
98
  user = User.find_or_initialize_by(uid: member[:uid])
99
99
  user.assign_attributes user_from_member_json(member)
100
100
  user.add_permission! role, course_slug
101
- user.verify_name!
101
+ user.verify_name! force: true
102
102
  yield user if block_given?
103
103
  end
104
104
 
@@ -143,20 +143,39 @@ class Mumuki::Classroom::App < Sinatra::Application
143
143
 
144
144
  def create_members!(role, &block)
145
145
  members_collection = collection_for role
146
- massive_members = massive_members_for role
147
- existing_members = existing_members_in_course(members_collection, massive_members)
148
- existing_members_uids = existing_members.map { |it| it[:uid] }
149
- processed_members = massive_members.reject { |it| existing_members_uids.include? it[:uid] }.uniq { |it| it[:uid]}
150
- members_collection.collection.insert_many(processed_members.map { |member| with_organization_and_course member })
151
- upsert_users! role, processed_members, &block
152
- massive_response(processed_members, unprocessed_members_for(role), existing_members,
146
+
147
+ existing_members, non_existent_members = partion_existing_members_in_course(
148
+ members_collection,
149
+ massive_members_for(role))
150
+
151
+ valid_members, invalid_members = non_existent_members.partition do |member|
152
+ members_collection.valid_attributes? member
153
+ end
154
+
155
+ errored_members = existing_members + invalid_members
156
+
157
+ members_collection
158
+ .collection
159
+ .insert_many(valid_members.map { |member| with_organization_and_course member })
160
+ upsert_users! role, valid_members, &block
161
+
162
+ massive_response(valid_members, unprocessed_members_for(role), errored_members,
153
163
  "#{role.to_s.pluralize.titleize} already belong to current course", status: :created)
154
164
  end
155
165
 
156
- def existing_members_in_course(col, massive_members)
157
- col.where(with_organization_and_course)
166
+ def partion_existing_members_in_course(collection, massive_members)
167
+ existing_members = existing_members_in_course(collection, massive_members)
168
+ existing_members_uids = existing_members.map { |it| it[:uid] }
169
+ [
170
+ existing_members,
171
+ massive_members.reject { |it| existing_members_uids.include? it[:uid] }.uniq { |it| it[:uid] }
172
+ ]
173
+ end
174
+
175
+ def existing_members_in_course(collection, massive_members)
176
+ collection.where(with_organization_and_course)
158
177
  .in(uid: massive_members.map { |it| it[:uid] })
159
- .map { |it| col.normalized_attributes_from_json(it) }
178
+ .map { |it| collection.normalized_attributes_from_json(it) }
160
179
  end
161
180
 
162
181
  def update_students!
@@ -166,7 +185,7 @@ class Mumuki::Classroom::App < Sinatra::Application
166
185
  students_does_not_belong_msg, status: :updated
167
186
  end
168
187
 
169
- def update_students_at_course!(method, action, students_uids)
188
+ def update_students_permissions_at_course!(method, action, students_uids)
170
189
  Mumuki::Classroom::Student.send "#{method}_all_by!", students_uids, with_organization_and_course
171
190
  User.where(uid: students_uids).each do |user|
172
191
  user.send "#{action}_permission!", :student, course_slug
@@ -1,11 +1,5 @@
1
1
  class Mumuki::Classroom::App < Sinatra::Application
2
2
  helpers do
3
- def normalize_student!
4
- json_body[:email] = json_body[:email]&.downcase
5
- json_body[:last_name] = json_body[:last_name]&.downcase&.titleize
6
- json_body[:first_name] = json_body[:first_name]&.downcase&.titleize
7
- end
8
-
9
3
  def list_students(matcher)
10
4
  authorize! :teacher
11
5
  count, students = Sorting.aggregate(Mumuki::Classroom::Student, with_detached_and_search(matcher, Mumuki::Classroom::Student), paginated_params, query_params)
@@ -243,7 +243,12 @@ HTML
243
243
  json = JSON.parse(error_message.message)
244
244
  response.body = json.to_json
245
245
  rescue
246
- response.body = {message: error_message.message}.to_json
246
+ if error_message.is_a?(Mongoid::Errors::MongoidError)
247
+ message_text = error_message.summary
248
+ else
249
+ message_text = error_message.message
250
+ end
251
+ response.body = {message: message_text}.to_json
247
252
  end
248
253
  end
249
254
  end
@@ -256,6 +261,10 @@ HTML
256
261
  halt 400
257
262
  end
258
263
 
264
+ error Mongoid::Errors::Validations do
265
+ halt 400
266
+ end
267
+
259
268
  error ActiveRecord::RecordNotFound do
260
269
  halt 404
261
270
  end
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Classroom
3
- VERSION = '9.22.0'
3
+ VERSION = '9.23.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-classroom
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.22.0
4
+ version: 9.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-04 00:00:00.000000000 Z
11
+ date: 2021-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 9.22.0
89
+ version: 9.23.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 9.22.0
96
+ version: 9.23.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: mumukit-login
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -232,11 +232,14 @@ files:
232
232
  - lib/mumuki/classroom/locales/pt.yml
233
233
  - lib/mumuki/classroom/models.rb
234
234
  - lib/mumuki/classroom/models/assignment.rb
235
+ - lib/mumuki/classroom/models/certificate.rb
235
236
  - lib/mumuki/classroom/models/concerns/course_member.rb
236
237
  - lib/mumuki/classroom/models/concerns/extensions.rb
237
238
  - lib/mumuki/classroom/models/concerns/with_failed_submission_reprocess.rb
238
239
  - lib/mumuki/classroom/models/concerns/with_submission_process.rb
239
240
  - lib/mumuki/classroom/models/document.rb
241
+ - lib/mumuki/classroom/models/exam_authorization.rb
242
+ - lib/mumuki/classroom/models/exam_authorization_request.rb
240
243
  - lib/mumuki/classroom/models/exercise.rb
241
244
  - lib/mumuki/classroom/models/failed_submission.rb
242
245
  - lib/mumuki/classroom/models/follower.rb