quiz_proctor_engine 1.2.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/proctor_conversations_controller.rb +6 -26
- data/app/controllers/proctored_exams_controller.rb +68 -10
- data/app/views/layouts/quiz_proctor.erb +25 -0
- data/app/views/quiz_proctor_engine/_plugin_settings.erb +2 -2
- data/config/routes.rb +1 -0
- data/lib/quiz_proctor_engine/version.rb +1 -1
- metadata +13 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e5df57adf4234792d236a87510ee85444fc55f8
|
4
|
+
data.tar.gz: 3a88e2002d1eaf1a8a7ff78de745bd50bce01a85
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8ea44bebfd87bc789163e001fe530ff81a30887a93fae3a884d69b343f61b9822902755f5b2f4e8de01a5f65222b824011146dc7cb442c3e35918da967a9aee8
|
7
|
+
data.tar.gz: 06c20e9eed5c091faf8024a5e78c9aca27102f96859873b479f053ba40a4e3882abad082843f337ab36c1d05016efc74dcefcd65b01622a51a6f78297eb51813
|
@@ -12,14 +12,17 @@
|
|
12
12
|
|
13
13
|
# You should have received a copy of the GNU Affero General Public License
|
14
14
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
-
require "httparty"
|
16
15
|
|
17
16
|
class ProctorConversationsController < ApplicationController
|
18
|
-
|
19
|
-
before_action :verify_messageable
|
17
|
+
skip_before_action :verify_authenticity_token
|
20
18
|
|
21
19
|
def initiate_conversation
|
22
20
|
proctor = User.find(params[:proctor_id])
|
21
|
+
cd = CustomData.find_by(user: proctor, namespace: "edu.au.exam")
|
22
|
+
if cd.nil? || params[:proctor_code] != cd.data["d"]["exam"]["proctor_code"]
|
23
|
+
render json: { error: "Unauthorized" }
|
24
|
+
return
|
25
|
+
end
|
23
26
|
student = User.find(params[:student_id])
|
24
27
|
message = Conversation.build_message(proctor, params[:body])
|
25
28
|
conversation = proctor.initiate_conversation([student], true, subject: params[:subject])
|
@@ -27,27 +30,4 @@ class ProctorConversationsController < ApplicationController
|
|
27
30
|
render json: { status: :ok }
|
28
31
|
end
|
29
32
|
|
30
|
-
private
|
31
|
-
|
32
|
-
def verify_messageable
|
33
|
-
headers = {
|
34
|
-
"Content-Type" => "application/json",
|
35
|
-
}
|
36
|
-
plugin = PluginSetting.find_by(name: "quiz_proctor")
|
37
|
-
|
38
|
-
query = {
|
39
|
-
student_id: params[:student_id],
|
40
|
-
proctor_code: params[:proctor_code],
|
41
|
-
unstarted: true,
|
42
|
-
}.to_query
|
43
|
-
|
44
|
-
quiz = HTTParty.get(
|
45
|
-
"#{plugin.settings[:adhesion_url]}/api/proctored_exams?#{query}",
|
46
|
-
headers: headers,
|
47
|
-
# verify: false,
|
48
|
-
)
|
49
|
-
if quiz.parsed_response["error"].present?
|
50
|
-
render json: { error: "Unauthorized" }
|
51
|
-
end
|
52
|
-
end
|
53
33
|
end
|
@@ -32,19 +32,77 @@ class ProctoredExamsController < ApplicationController
|
|
32
32
|
proctor_code: params[:proctor_code],
|
33
33
|
}.to_query
|
34
34
|
|
35
|
-
|
36
|
-
"#{plugin.settings[:
|
35
|
+
exam_request = HTTParty.get(
|
36
|
+
"#{plugin.settings[:adhesion_proctor_url]}/api/proctored_exams?#{query}",
|
37
37
|
headers: headers,
|
38
38
|
# verify: false,
|
39
|
-
)
|
40
|
-
|
41
|
-
|
39
|
+
).parsed_response["exam_request"]
|
40
|
+
|
41
|
+
if exam_request.nil?
|
42
|
+
flash[:error] = "You do not have an exam that is ready to start."
|
43
|
+
redirect_to proctored_exams_path
|
44
|
+
return
|
45
|
+
end
|
46
|
+
|
47
|
+
matched_code = false
|
48
|
+
proctor_id = nil
|
49
|
+
proctor_name = nil
|
50
|
+
code = params[:proctor_code]
|
51
|
+
users = Account.find(exam_request["testing_center_id"]).users
|
52
|
+
CustomData.where(user: users, namespace: "edu.au.exam").find_each do |cd|
|
53
|
+
user = users.detect { |u| u.id == cd.user_id }
|
54
|
+
if cd.data["d"]["exam"]["proctor_code"] == code
|
55
|
+
matched_code = true
|
56
|
+
proctor_id = user.id
|
57
|
+
proctor_name = user.name
|
58
|
+
break
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
if !matched_code
|
63
|
+
flash[:error] = "Invalid proctor code."
|
42
64
|
redirect_to proctored_exams_path
|
43
|
-
|
44
|
-
quiz = quiz.parsed_response
|
45
|
-
session[:is_proctored] = true
|
46
|
-
session[:proctor_access_code] = quiz["proctor_access_code"]
|
47
|
-
redirect_to course_quiz_take_path quiz["quiz"]["course_id"], quiz["quiz"]["exam_id"]
|
65
|
+
return
|
48
66
|
end
|
67
|
+
|
68
|
+
query = {
|
69
|
+
proctor_id: proctor_id,
|
70
|
+
proctor_name: proctor_name,
|
71
|
+
}.to_query
|
72
|
+
|
73
|
+
# HTTParty is really bad and sends the put body wrong, so i send everything in the params
|
74
|
+
# RestClient does this better but I dont have RestClient so HTTParty it is.
|
75
|
+
HTTParty.put(
|
76
|
+
"#{plugin.settings[:adhesion_proctor_url]}/api/proctored_exams/#{exam_request['id']}?#{query}",
|
77
|
+
body: {},
|
78
|
+
headers: headers,
|
79
|
+
)
|
80
|
+
canvas_quiz = Quizzes::Quiz.find(exam_request["exam_id"])
|
81
|
+
|
82
|
+
session[:is_proctored] = true
|
83
|
+
session[:proctor_access_code] = canvas_quiz.access_code
|
84
|
+
redirect_to course_quiz_take_path exam_request["course_id"], exam_request["exam_id"]
|
85
|
+
end
|
86
|
+
|
87
|
+
def finish_quiz
|
88
|
+
headers = {
|
89
|
+
"Content-Type" => "application/json",
|
90
|
+
}
|
91
|
+
plugin = PluginSetting.find_by(name: "quiz_proctor")
|
92
|
+
|
93
|
+
query = {
|
94
|
+
student_id: @current_user.id,
|
95
|
+
update: true,
|
96
|
+
}.to_query
|
97
|
+
|
98
|
+
HTTParty.get(
|
99
|
+
"#{plugin.settings[:adhesion_proctor_url]}/api/proctored_exams?#{query}",
|
100
|
+
headers: headers,
|
101
|
+
# verify: false
|
102
|
+
)
|
103
|
+
# we wont need to handle the response for this anyway, hence the hardcoded ok value
|
104
|
+
# if it fails we will probably never know because the JavaScript
|
105
|
+
# that will handle the response will have been reloaded by the time this finishes.
|
106
|
+
render json: { status: "ok" }
|
49
107
|
end
|
50
108
|
end
|
@@ -32,6 +32,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
32
32
|
removePreviousAndNext(0, false, false);
|
33
33
|
})();
|
34
34
|
|
35
|
+
(function(){
|
36
|
+
addCustomEventListenerToSubmit(0, false);
|
37
|
+
})();
|
38
|
+
|
35
39
|
function removePreviousAndNext(tries, nextAlreadyRemoved, previousAlreadyRemoved){
|
36
40
|
|
37
41
|
if(tries > 100 || (nextAlreadyRemoved && previousAlreadyRemoved)) {
|
@@ -57,4 +61,25 @@ function removePreviousAndNext(tries, nextAlreadyRemoved, previousAlreadyRemoved
|
|
57
61
|
|
58
62
|
}
|
59
63
|
|
64
|
+
function addCustomEventListenerToSubmit(tries, finished) {
|
65
|
+
|
66
|
+
if (tries > 100 || finished) {
|
67
|
+
return;
|
68
|
+
}
|
69
|
+
var foundButton = false;
|
70
|
+
var button = document.getElementById("submit_quiz_button");
|
71
|
+
if(button) {
|
72
|
+
foundButton = true;
|
73
|
+
button.addEventListener('click', function(){
|
74
|
+
$.ajax({
|
75
|
+
type: 'PUT',
|
76
|
+
url: '/proctored_exams',
|
77
|
+
})
|
78
|
+
});
|
79
|
+
}
|
80
|
+
setTimeout(function(){
|
81
|
+
addCustomEventListenerToSubmit(tries + 1, foundButton);
|
82
|
+
}, 100)
|
83
|
+
}
|
84
|
+
|
60
85
|
</script>
|
@@ -22,8 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
22
22
|
<td><%= f.text_field :proctor_secret %></td>
|
23
23
|
</tr>
|
24
24
|
<tr>
|
25
|
-
<td><%= f.blabel :
|
26
|
-
<td><%= f.text_field :
|
25
|
+
<td><%= f.blabel :adhesion_proctor_url, en: "Adhesion Proctor Url" %></td>
|
26
|
+
<td><%= f.text_field :adhesion_proctor_url %></td>
|
27
27
|
</tr>
|
28
28
|
</table>
|
29
29
|
<% end %>
|
data/config/routes.rb
CHANGED
@@ -17,5 +17,6 @@ Rails.application.routes.draw do
|
|
17
17
|
get "proctor_login" => "proctor_login#login"
|
18
18
|
get "proctored_exams" => "proctored_exams#show"
|
19
19
|
post "proctored_exams" => "proctored_exams#start_quiz"
|
20
|
+
put "proctored_exams" => "proctored_exams#finish_quiz"
|
20
21
|
post "proctor_conversations" => "proctor_conversations#initiate_conversation"
|
21
22
|
end
|
metadata
CHANGED
@@ -1,29 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quiz_proctor_engine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dittonjs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.2
|
19
|
+
version: '4.2'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.1'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
|
-
- - "
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.2'
|
30
|
+
- - "<"
|
25
31
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
32
|
+
version: '5.1'
|
27
33
|
description: Allows students to take canvas quizzes in a chromeless view, as well
|
28
34
|
as allow proctors to enter answers on behalf of a student
|
29
35
|
email:
|
@@ -71,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
77
|
version: '0'
|
72
78
|
requirements: []
|
73
79
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.6.
|
80
|
+
rubygems_version: 2.6.11
|
75
81
|
signing_key:
|
76
82
|
specification_version: 4
|
77
83
|
summary: Allows students to take canvas quizzes in a chromeless view, as well as allow
|