Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autolab API V1 #850

Merged
merged 137 commits into from Apr 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
137 commits
Select commit Hold shift + click to select a range
0aa1e09
add doorkeeper to gemfile
zyx-billy Feb 11, 2017
1709112
install and configure doorkeeper
zyx-billy Feb 11, 2017
4e9f9d0
update database for doorkeeper
zyx-billy Feb 11, 2017
15793eb
add v1 base api controller
zyx-billy Feb 11, 2017
5219a3e
add first version of courses api controller
zyx-billy Feb 11, 2017
a6e3d4d
Finalize doorkeeper configuration:
zyx-billy Feb 11, 2017
f17f500
implement api error handling
zyx-billy Feb 15, 2017
76aa55c
extend course index method with optional state param
zyx-billy Feb 15, 2017
0f7fbdf
limit course attributes in response
zyx-billy Feb 15, 2017
e01c667
implement cud and course check for api routes
zyx-billy Feb 19, 2017
f2302b0
add user auth_level to response
zyx-billy Feb 19, 2017
09f501f
implement assessment index endpoint
zyx-billy Feb 19, 2017
a81e2c8
implement user info endpoint
zyx-billy Feb 19, 2017
60caaf6
add has_autograder field to assessment response
zyx-billy Feb 19, 2017
cb48b3a
Implement submissions index endpoint
zyx-billy Feb 23, 2017
50b3c5e
implement assessment problems endpoint
zyx-billy Feb 23, 2017
4290e85
fix type issue
zyx-billy Mar 22, 2017
8083c43
add custom 404 handler that returns json
zyx-billy Mar 22, 2017
b1b2edf
implement submission feedback endpoint
zyx-billy Mar 22, 2017
9329ca2
prepare submission endpoint
zyx-billy Mar 31, 2017
bc13b03
refactor handin helpers into separate helper
zyx-billy Mar 29, 2017
aaea17d
refactor autograde helpers into separate helper
zyx-billy Mar 29, 2017
42a4a27
switch to using more expressive error_codes/hashes
zyx-billy Mar 31, 2017
add2fac
fix return values
zyx-billy Mar 31, 2017
78d35ff
set response to json always
zyx-billy Apr 5, 2017
dde8994
remove symbolize_keys hack
zyx-billy Apr 5, 2017
6a80bf1
initial testing framework
zyx-billy Feb 15, 2017
8f908ac
add course index test
zyx-billy Apr 5, 2017
a8b8569
add user info endpoint test
zyx-billy Apr 5, 2017
dc3d2a7
add assessments test
zyx-billy Apr 5, 2017
beb55d6
add failure cases to course test
zyx-billy Apr 5, 2017
a6fd5ef
rename helpers to core
zyx-billy Apr 6, 2017
9943ab9
move batch submission logic into autograde core
zyx-billy Apr 6, 2017
ce5f848
add explanation for sendJob param
zyx-billy Apr 6, 2017
f0b0c0f
minor syntax error fix
zyx-billy Apr 6, 2017
501f287
make explicit autogradeSubmissions may raise errors
zyx-billy Apr 7, 2017
f295dd8
handle errors from autogradeSubmissions
zyx-billy Apr 7, 2017
d4944c9
give autogradeSubmissions a correct name
zyx-billy Apr 7, 2017
d88b449
update comment for handin handler function
zyx-billy Apr 7, 2017
26c3991
rename wrapper functions and add docs
zyx-billy Apr 7, 2017
c68e724
Merge branch 'generic_handin_and_autograde_helpers' into api_v1
zyx-billy Apr 12, 2017
d6debe7
implement submit endpoint to allow submission over api
zyx-billy Apr 12, 2017
4dc2b4b
implement assessment writeup endpoint
zyx-billy Apr 12, 2017
9927c83
use respond_with_hash in submit endpoint
zyx-billy Apr 12, 2017
7a5f8b8
implement assessment handout endpoint
zyx-billy Apr 12, 2017
69cc61b
configure scopes with doorkeeper
zyx-billy Apr 12, 2017
01d66a1
set scope requirements for each action
zyx-billy Apr 12, 2017
7aafc08
add rack-attack to gemfile
zyx-billy Apr 13, 2017
4a05914
initial rack-attack config
zyx-billy Apr 13, 2017
e297b5d
throttle using user id instead of ip
zyx-billy Apr 13, 2017
4b8b28f
Merge branch 'api_v1_throttle_using_rack-attack' into api_v1
zyx-billy Apr 13, 2017
d4d80bf
import doorkeeper views
zyx-billy Apr 19, 2017
f3b6091
modify authorized applications page
zyx-billy Apr 19, 2017
ac09841
modify authorization page
zyx-billy Apr 19, 2017
8fe7e1a
Merge branch 'api_v1_test' into api_v1
zyx-billy Apr 26, 2017
e67b838
update rspec tests to include scopes
zyx-billy Apr 26, 2017
e1a7d1c
add nonexistent course test
zyx-billy Apr 26, 2017
0bda2f2
make tests DRY with shared_context
zyx-billy Apr 26, 2017
507ee8e
add assessment#submit endpoint tests
zyx-billy May 3, 2017
89aaef0
handle cases where file param missing from submission
zyx-billy May 3, 2017
9adfbbd
More descriptive error messages for unexpected errors
zyx-billy May 3, 2017
dffe042
add roundtrip test for submission over api
zyx-billy May 4, 2017
5cf0ad5
install webmock
zyx-billy May 16, 2017
91475d6
implement device flow routes
zyx-billy Aug 15, 2017
f38628e
implement rate limiting for device_flow routes
zyx-billy Aug 15, 2017
c6d17a6
create db tables
zyx-billy Aug 15, 2017
f79b03e
add manage applications link to manage_autolab page
zyx-billy Dec 25, 2017
47171bb
remove non-null requirements on user id and resolved_at columns
zyx-billy Dec 26, 2017
5afc2df
create activerecord model for device_flow_requests
zyx-billy Dec 26, 2017
d6c621f
implement device_flow_init
zyx-billy Dec 26, 2017
b2cd329
implement device_flow_authorize
zyx-billy Dec 27, 2017
caf113d
add field for access_code in device_flow table
zyx-billy Dec 28, 2017
1dfd6b2
fix private method calling issue
zyx-billy Dec 28, 2017
77d4ecd
device_flow issues access_code instead of token
zyx-billy Dec 28, 2017
02ee76c
implement device_flow activation pages and endpoints
zyx-billy Dec 28, 2017
53934ab
implement tests for device_flow api endpoints
zyx-billy Dec 28, 2017
671c7bb
Merge branch 'device_flow' into api_v1
zyx-billy Dec 28, 2017
8228f9a
add column to record submitter application in submissions table
zyx-billy Dec 28, 2017
cad4c01
update roundtrip test to test for submitted_by_app_id attribute
zyx-billy Dec 28, 2017
b7b79fd
store submitter app id during submission
zyx-billy Dec 28, 2017
7f385db
update submissions api controller to filter by submitter app_id
zyx-billy Dec 28, 2017
59513d5
implement mock for tango open
zyx-billy Dec 31, 2017
ac8e0df
rack-attack handle access_token not found
zyx-billy Dec 31, 2017
e0cd3f2
fix activation page form bug
zyx-billy Dec 31, 2017
f0aba3c
add instructor and admin scopes
zyx-billy Jan 2, 2018
5a5e7c3
add api-related links to user account page
zyx-billy Jan 2, 2018
5714a46
implement course#create route
zyx-billy Jan 2, 2018
fcc5c2c
implement tests for course#create route
zyx-billy Jan 2, 2018
3886d04
Merge branch 'develop' into api_v1
zyx-billy Jan 3, 2018
f5d6e70
fix getting message from error
zyx-billy Jan 3, 2018
b9cc787
set assessment dates to make sure they can be submitted to in test cases
zyx-billy Jan 3, 2018
b018494
create logger
zyx-billy Jan 3, 2018
a408b2e
finish tango_mock
zyx-billy Jan 3, 2018
e2a0076
use tango_mock in roundtrip test
zyx-billy Jan 3, 2018
71c2dc1
Merge branch 'use_webmock' into api_v1
zyx-billy Jan 3, 2018
aa88620
use tango_mock in assessment controller test
zyx-billy Jan 3, 2018
3438e7a
extract vars used for handin-related tests into separate context
zyx-billy Jan 3, 2018
77f3a9d
run api tests in travis
zyx-billy Jan 3, 2018
bcdc82c
remove request_stubs after each test case
zyx-billy Jan 3, 2018
c99bd31
allow all unstubbed network requests
zyx-billy Jan 3, 2018
5b8111a
only count released asmts in test
zyx-billy Jan 3, 2018
ecb8d3b
streamline responses on success
zyx-billy Jan 4, 2018
d561eb8
add verification uri to device_flow_init response
zyx-billy Jan 4, 2018
dd6550e
do not return handout and writeup with each assessment
zyx-billy Jan 4, 2018
7efa53e
do not return visible_at with each assessment
zyx-billy Jan 4, 2018
f8e51f8
return error json for rate-limited responses
zyx-billy Jan 5, 2018
020706b
create assessment#show path, and refactor assessment#index
zyx-billy Jan 13, 2018
04419ac
don't return error when handout or writeup non-existent
zyx-billy Jan 13, 2018
429f90c
add version number to footer
zyx-billy Jan 24, 2018
8a28fca
Merge branch 'version_number_in_footer' into api_v1
zyx-billy Jan 24, 2018
79fd034
streamline privilege checking
zyx-billy Feb 22, 2018
3ffa9b4
add course_user_data index route
zyx-billy Feb 23, 2018
acf4ce3
add tests for course_user_data index route
zyx-billy Feb 23, 2018
c509592
implement cud create route
zyx-billy Feb 23, 2018
483009c
add tests for cud create route
zyx-billy Feb 23, 2018
3a81de8
update cud test cases to use correct http method
zyx-billy Feb 23, 2018
011866a
implement cud update route
zyx-billy Feb 23, 2018
019e334
add tests for cud update route
zyx-billy Feb 23, 2018
e1f02bb
implement cud destroy route
zyx-billy Feb 23, 2018
26fd0d5
add tests for cud destroy route
zyx-billy Feb 23, 2018
204eb49
implement cud show route
zyx-billy Feb 23, 2018
39acac1
add tests for cud show route
zyx-billy Feb 23, 2018
140c7f9
streamline data setting in cud routes
zyx-billy Feb 24, 2018
f32e62f
add grade_policy to cud response
zyx-billy Feb 24, 2018
ca8a84b
modify error description for invalid scope
zyx-billy Feb 24, 2018
5618744
allow periods in cud email param
zyx-billy Feb 25, 2018
0241664
turn off browser autocomplete on the activation form
zyx-billy Feb 25, 2018
99e3a34
fix activation page not returning after redirect
zyx-billy Feb 25, 2018
6f9b28d
update new authorization page icon
zyx-billy Feb 25, 2018
1ad20b9
Merge branch 'develop' into api_v1
zyx-billy Feb 26, 2018
617b5cc
set loggers in api_base
zyx-billy Feb 27, 2018
7a798c5
handle disabled course
zyx-billy Feb 28, 2018
9db8216
clarify autograding failure message
zyx-billy Feb 28, 2018
c94abf2
allow specifying start and end dates for course create
zyx-billy Mar 9, 2018
89ed5b7
better error messages for course create
zyx-billy Mar 9, 2018
3a9513e
make course create route consistent with CRUD
zyx-billy Mar 9, 2018
8be09b9
fix rate limit error response
zyx-billy Apr 1, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -21,7 +21,7 @@ before_script:
- RAILS_ENV=test bundle exec rake autolab:populate
script:
- RAILS_ENV=test CODECLIMATE_REPO_TOKEN=d37a8b9e09642cb73cfcf4ecfb4115fc3d6a55a7714110187ac59856ae4ab5ad
bundle exec rspec ./spec/features/
bundle exec rspec ./spec/features/ ./spec/api/v1/
notifications:
slack:
secure: GXcycaSBFaOYI6Ge0vhqCYK1xxixwjASOMkV2bkfE6PNIGkDEEQdTpOkohPGoKuz2W9KCGrXC38sbu4npMtonz0/sISydG+g7V33XkLqPaW8oUcdYhwJyBUEB/Ds17U/FJ4IhT9oOrhl17Sm0rm92Mhu6O2eeZYAclGqJgZNLvg=
7 changes: 7 additions & 0 deletions Gemfile
Expand Up @@ -58,6 +58,12 @@ gem 'omniauth-facebook', '>=2.0.0'
gem 'omniauth-google-oauth2', '>=0.2.5'
gem 'omniauth-shibboleth', '>=1.1.2'

# Autolab API OAuth Service
gem 'doorkeeper'

# For block and throttling abusive requests
gem 'rack-attack'

# Adds It also adds f.error_messages and f.error_message_on to form builders
gem 'dynamic_form'

Expand All @@ -73,6 +79,7 @@ gem 'rack-test'
gem 'capybara', group: [:development, :test]
gem 'factory_girl_rails', group: [:development, :test]
gem 'database_cleaner', group: [:development, :test]
gem 'webmock', group: [:development, :test]
gem 'codeclimate-test-reporter', group: :test, require: nil
gem 'newrelic_rpm'

Expand Down
15 changes: 15 additions & 0 deletions Gemfile.lock
Expand Up @@ -80,6 +80,8 @@ GEM
execjs
coffee-script-source (1.12.2)
concurrent-ruby (1.0.4)
crack (0.4.3)
safe_yaml (~> 1.0.0)
daemons (1.2.4)
database_cleaner (1.5.3)
debug_inspector (0.0.2)
Expand All @@ -92,6 +94,8 @@ GEM
warden (~> 1.2.3)
diff-lcs (1.2.5)
docile (1.1.5)
doorkeeper (4.2.0)
railties (>= 4.2)
dynamic_form (1.1.4)
erubis (2.7.0)
eventmachine (1.2.1)
Expand All @@ -108,6 +112,7 @@ GEM
multipart-post (>= 1.2, < 3)
globalid (0.3.7)
activesupport (>= 4.1.0)
hashdiff (0.3.4)
hashery (2.1.2)
hashie (3.4.6)
httparty (0.14.0)
Expand Down Expand Up @@ -187,6 +192,8 @@ GEM
ttfunk (~> 1.0.3)
public_suffix (2.0.5)
rack (1.6.5)
rack-attack (5.0.1)
rack
rack-ssl-enforcer (0.2.9)
rack-test (0.6.3)
rack (>= 1.0)
Expand Down Expand Up @@ -246,6 +253,7 @@ GEM
ruby-progressbar (1.8.1)
ruby-rc4 (0.1.5)
rubyzip (1.2.0)
safe_yaml (1.0.4)
sass (3.4.23)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
Expand Down Expand Up @@ -293,6 +301,10 @@ GEM
unicode-display_width (1.1.2)
warden (1.2.6)
rack (>= 1.0)
webmock (3.0.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
xpath (2.0.0)
nokogiri (~> 1.3)
yard (0.9.8)
Expand All @@ -312,6 +324,7 @@ DEPENDENCIES
coffee-rails (>= 4.0.0)
database_cleaner
devise (= 3.4.0)
doorkeeper
dynamic_form
exception_notification (>= 4.1.0)
factory_girl_rails
Expand All @@ -330,6 +343,7 @@ DEPENDENCIES
omniauth-shibboleth (>= 1.1.2)
populator (>= 1.0.0)
prawn (= 0.13.0)
rack-attack
rack-ssl-enforcer
rack-test
rails (= 4.2.1)
Expand All @@ -347,6 +361,7 @@ DEPENDENCIES
thin
turbolinks
uglifier (>= 1.3.0)
webmock
yard

BUNDLED WITH
Expand Down
7 changes: 6 additions & 1 deletion app/assets/stylesheets/style.css.scss
Expand Up @@ -414,12 +414,17 @@ div#footer .right {
padding-top: 14px;
}

div#footer a {
div#footer a,
div#footer span.site_version {
display: inline-block;
padding: 12px;
color: #666;
}

div#footer span.site_version {
float: right;
}

div#footer div.fb-like.fb_iframe_widget {
vertical-align: top;
margin-left: 8px;
Expand Down
189 changes: 189 additions & 0 deletions app/controllers/api/v1/assessments_controller.rb
@@ -0,0 +1,189 @@
class Api::V1::AssessmentsController < Api::V1::BaseApiController

include AssessmentHandinCore
include AssessmentAutogradeCore

before_action -> {require_privilege :user_courses}, only: [:index, :problems, :writeup, :handout]
before_action -> {require_privilege :user_submit}, only: [:submit]

before_action :set_assessment, except: [:index]

def index
asmts = @course.assessments.ordered
allowed = [:name, :display_name, :start_at, :due_at, :end_at, :category_name]
if @cud.student?
asmts = asmts.released
else
allowed += [:grading_deadline]
end

respond_with asmts, only: allowed
end

def show
allowed = [:name, :display_name, :description, :start_at, :due_at, :end_at, :updated_at, :max_grace_days, :max_submissions,
:disable_handins, :category_name, :group_size, :writeup_format, :handout_format, :has_scoreboard, :has_autograder]
if not @cud.student?
allowed += [:grading_deadline]
end

result = @assessment.attributes.symbolize_keys
result.merge!(:has_scoreboard => @assessment.has_scoreboard?)
result.merge!(:has_autograder => @assessment.has_autograder?)
if @assessment.writeup_is_file?
result.merge!(:writeup_format => "file")
elsif @assessment.writeup_is_url?
result.merge!(:writeup_format => "url")
else
result.merge!(:writeup_format => "none")
end
if @assessment.overwrites_method?(:handout) or @assessment.handout_is_file?
result.merge!(:handout_format => "file")
elsif @assessment.handout_is_url?
result.merge!(:handout_format => "url")
else
result.merge!(:handout_format => "none")
end

respond_with result, only: allowed
end

# endpoint for obtaining details about all problems of an assessment
def problems
problems = @assessment.problems

respond_with problems, only: [:name, :description, :max_score, :optional]
end

# endpoint for obtaining the writeup
def writeup
if @assessment.writeup_is_url?
respond_with_hash({:url => @assessment.writeup}) and return
end

if @assessment.writeup_is_file?
filename = @assessment.writeup_path
send_file(filename,
disposition: "inline",
file: File.basename(filename))
return
end

respond_with_hash({:writeup => "none"})
end

# endpoint for obtaining the handout
def handout
extend_config_module(@assessment, nil, @cud)

if @assessment.overwrites_method?(:handout)
hash = @assessment.config_module.handout
send_file(hash["fullpath"],
disposition: "inline",
filename: hash["filename"])
return
end

if @assessment.handout_is_url?
respond_with_hash({:url => @assessment.handout}) and return
end

if @assessment.handout_is_file?
filename = @assessment.handout_path
send_file(filename,
disposition: "inline",
file: File.basename(filename))
return
end

respond_with_hash({:handout => "none"})
end

# endpoint for submitting to assessments
# Does not support embedded quizzes.
# Potential Errors:
# Submission Rejected:
# - Assessment is an embedded quiz
# - Handins disabled
# - Submitting late without submit-late flag
# - Past assessment end time
# - Before assessment start time
# - Exceeded max submission count
# - Exceeded max handin file size
# - Submission was blank
# - Submission failed file type check
# - Cannot submit until all group members confirm their group membership
# - A member of your group has reached the submission limit for this assessment
# Autograding Failed:
# - No autograding properties
# - Error submitting job
# - Error uploading submission file
# - Submission rejected by autograder
# - One or more files in the Autograder module don't exist.
# - Encountered unexpected exception
def submit
if @assessment.embedded_quiz
raise ApiError.new("Assessment is an embedded quiz", :bad_request)
end

if not params.has_key?(:submission)
raise ApiError.new("Required parameter 'submission' not found", :bad_request)
end

if not params[:submission].has_key?("file")
raise ApiError.new("Required parameter 'submission['file']' not found", :bad_request)
end

# validate Handin
validity = validateHandin(params[:submission]["file"].size,
params[:submission]["file"].content_type,
params[:submission]["file"].original_filename)
case validity
when :valid
when :handin_disabled
raise ApiError.new("Handins for this assessment is disabled", :forbidden)
when :submission_empty
raise ApiError.new("Submission was blank", :forbidden)
when :file_too_large
msg = "Submission is larger than the max allowed " \
"size (#{@assessment.max_size} MB) - please remove any " \
"unnecessary logfiles and binaries."
raise ApiError.new(msg, :forbidden)
when :fail_type_check
raise ApiError.new("Submission failed Filetype Check", :forbidden)
else
raise ApiError.new("Unexpected error during handin validation", :forbidden)
end

group_validity = validateHandinForGroups()
case group_validity
when :valid
when :awaiting_member_confirmation
raise ApiError.new("Submission not allowed until all group members confirm their group membership", :forbidden)
when :group_submission_limit_exceeded
raise ApiError.new("A member of your group has reached the submission limit for this assessment", :forbidden)
else
raise ApiError.new("Unexpected error during handin validation for groups", :forbidden)
end

# attempt to save the submission
begin
submissions = saveHandin(params[:submission], current_app.id)
rescue StandardError => e
# TODO: log error
raise ApiError.new("Unexpected error during submission handin.\nDetails: #{e.message}", :internal_server_error)
end

# autograde the submission
if @assessment.has_autograder?
begin
sendJob(@course, @assessment, submissions, @cud)
rescue AssessmentAutogradeCore::AutogradeError => e
raise ApiError.new("Submission accepted, but autograding failed: " + e.message, :internal_server_error)
end
end

respond_with_hash({version: submissions[0].version, filename: submissions[0].filename})
end

end