Skip to content

Commit b8daa52

Browse files
authored
Merge pull request doubtfire-lms#448 from DudeUnleashed/courseflow
feature/Courseflow-api
2 parents d750c61 + 99dc3c8 commit b8daa52

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1778
-42
lines changed

Gemfile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ source 'https://rubygems.org'
44

55
# Ruby versions for various enviornments
66
ruby_versions = {
7-
development: '~>3.1.0',
8-
test: '~>3.1.0',
9-
staging: '~>3.1.0',
10-
production: '~>3.1.0'
7+
development: '~>3.3.0',
8+
test: '~>3.3.0',
9+
staging: '~>3.3.0',
10+
production: '~>3.3.0'
1111
}
1212
# Get the ruby version for the current enviornment
1313
ruby ruby_versions[(ENV['RAILS_ENV'] || 'development').to_sym]
@@ -112,3 +112,5 @@ gem 'shellwords'
112112

113113
# PDF reader for validating PDF file submissions
114114
gem 'pdf-reader'
115+
116+
gem 'csv'

Gemfile.lock

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ GEM
113113
bigdecimal
114114
rexml
115115
crass (1.0.6)
116+
csv (3.3.0)
116117
database_cleaner-active_record (2.1.0)
117118
activerecord (>= 5.a)
118119
database_cleaner-core (~> 2.0.0)
@@ -168,7 +169,15 @@ GEM
168169
faraday-net_http (3.1.0)
169170
net-http
170171
ffi (1.17.0-aarch64-linux-gnu)
172+
ffi (1.17.0-aarch64-linux-musl)
173+
ffi (1.17.0-arm-linux-gnu)
174+
ffi (1.17.0-arm-linux-musl)
175+
ffi (1.17.0-arm64-darwin)
176+
ffi (1.17.0-x86-linux-gnu)
177+
ffi (1.17.0-x86-linux-musl)
178+
ffi (1.17.0-x86_64-darwin)
171179
ffi (1.17.0-x86_64-linux-gnu)
180+
ffi (1.17.0-x86_64-linux-musl)
172181
fugit (1.11.0)
173182
et-orbi (~> 1, >= 1.2.11)
174183
raabro (~> 1.4)
@@ -267,6 +276,16 @@ GEM
267276
racc (~> 1.4)
268277
nokogiri (1.16.6-x86_64-linux)
269278
racc (~> 1.4)
279+
nokogiri (1.16.5-arm-linux)
280+
racc (~> 1.4)
281+
nokogiri (1.16.5-arm64-darwin)
282+
racc (~> 1.4)
283+
nokogiri (1.16.5-x86-linux)
284+
racc (~> 1.4)
285+
nokogiri (1.16.5-x86_64-darwin)
286+
racc (~> 1.4)
287+
nokogiri (1.16.5-x86_64-linux)
288+
racc (~> 1.4)
270289
observer (0.1.2)
271290
orm_adapter (0.5.0)
272291
parallel (1.25.1)
@@ -497,8 +516,20 @@ GEM
497516
zeitwerk (2.6.16)
498517

499518
PLATFORMS
500-
aarch64-linux
519+
aarch64-linux-gnu
520+
aarch64-linux-musl
521+
arm-linux
522+
arm-linux-gnu
523+
arm-linux-musl
524+
arm64-darwin
525+
x86-linux
526+
x86-linux-gnu
527+
x86-linux-musl
528+
x86_64-darwin
501529
x86_64-linux
530+
x86_64-linux-gnu
531+
x86_64-linux-musl
532+
aarch64-linux
502533

503534
DEPENDENCIES
504535
better_errors
@@ -507,6 +538,7 @@ DEPENDENCIES
507538
byebug
508539
ci_reporter
509540
coderay
541+
csv
510542
database_cleaner-active_record
511543
devise
512544
devise_ldap_authenticatable
@@ -560,7 +592,7 @@ DEPENDENCIES
560592
webmock
561593

562594
RUBY VERSION
563-
ruby 3.1.4p223
595+
ruby 3.3.2p78
564596

565597
BUNDLED WITH
566-
2.4.22
598+
2.5.11

app/api/api_root.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ class ApiRoot < Grape::API
9292
mount WebcalApi
9393
mount WebcalPublicApi
9494

95+
mount Courseflow::CourseApi
96+
mount Courseflow::CourseMapApi
97+
mount Courseflow::CourseMapUnitApi
98+
mount Courseflow::SpecializationApi
99+
mount Courseflow::RequirementSetApi
100+
mount UnitDefinitionApi
101+
95102
#
96103
# Add auth details to all end points
97104
#
@@ -128,6 +135,13 @@ class ApiRoot < Grape::API
128135
AuthenticationHelpers.add_auth_to UnitsApi
129136
AuthenticationHelpers.add_auth_to WebcalApi
130137

138+
AuthenticationHelpers.add_auth_to Courseflow::CourseApi
139+
AuthenticationHelpers.add_auth_to Courseflow::CourseMapApi
140+
AuthenticationHelpers.add_auth_to Courseflow::CourseMapUnitApi
141+
AuthenticationHelpers.add_auth_to Courseflow::SpecializationApi
142+
AuthenticationHelpers.add_auth_to Courseflow::RequirementSetApi
143+
AuthenticationHelpers.add_auth_to UnitDefinitionApi
144+
131145
add_swagger_documentation \
132146
base_path: nil,
133147
api_version: 'v1',

app/api/courseflow/course_api.rb

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
require 'grape'
2+
module Courseflow
3+
class CourseApi < Grape::API
4+
5+
format :json
6+
helpers AuthenticationHelpers
7+
helpers AuthorisationHelpers
8+
9+
before do
10+
authenticated?
11+
end
12+
13+
desc "Get all course data"
14+
get '/course' do
15+
courses = Course.all # get all courses in the database
16+
present courses, with: Entities::CourseEntity # present the courses using the CourseEntity
17+
end
18+
19+
desc "Get course by ID"
20+
params do
21+
requires :courseId, type: Integer, desc: "Course ID"
22+
end
23+
get '/course/courseId/:courseId' do
24+
course = Course.find(params[:courseId]) # find the course by ID
25+
present course, with: Entities::CourseEntity # present the course using the CourseEntity
26+
end
27+
28+
desc "Get courses that partially match the search params"
29+
params do # define the parameters that can be used to filter the courses, all optional, if none given it'll return every course
30+
optional :name, type: String, desc: "Course name"
31+
optional :code, type: String, desc: "Course code"
32+
optional :year, type: Integer, desc: "Course year"
33+
end
34+
get '/course/search' do
35+
courses = Course.all # gets all courses initially
36+
37+
courses = courses.where("name LIKE :name", name: "%#{params[:name]}%") if params[:name].present? # if name is provided, filter by name, even partially
38+
courses = courses.where("code LIKE :code", code: "%#{params[:code]}%") if params[:code].present? # if code is provided, filter by code, (can do things like SIT to get all SIT courses)
39+
courses = courses.where(year: params[:year]) if params[:year].present? # if year is provided, filter by year
40+
41+
present courses, with: Entities::CourseEntity # return the filtered courses
42+
end
43+
44+
desc "Add a new course"
45+
params do # define the parameters required to create a new course
46+
requires :name, type: String
47+
requires :code, type: String
48+
requires :year, type: Integer
49+
requires :version, type: String
50+
requires :url, type: String
51+
end
52+
post '/course' do
53+
unless authorise? current_user, User, :handle_courseflow
54+
error!({ error: 'Not authorised to create a course' }, 403)
55+
end
56+
course = Course.new(params) # create a new course with the provided params
57+
if course.save
58+
present course, with: Entities::CourseEntity # if the course is saved, present the course using the CourseEntity
59+
else
60+
error!({ error: "Failed to create course", details: course.errors.full_messages }, 400) # if the course is not saved, return an error with the full error messages
61+
end
62+
end
63+
64+
desc "Update an existing course via its ID"
65+
params do # define the parameters required to update a course
66+
requires :courseId, type: Integer, desc: "Course ID"
67+
requires :name, type: String
68+
requires :code, type: String
69+
requires :year, type: Integer
70+
requires :version, type: String
71+
requires :url, type: String
72+
end
73+
put '/course/courseId/:courseId' do
74+
unless authorise? current_user, User, :handle_courseflow
75+
error!({ error: 'Not authorised to update a course' }, 403)
76+
end
77+
course = Course.find(params[:courseId]) # find the course by ID
78+
error!({ error: "Course not found" }, 404) unless course # return an error if the course is not found
79+
80+
if course.update(name: params[:name], code: params[:code], year: params[:year], version: params[:version], url: params[:url]) # update the course with the provided params
81+
present course, with: Entities::CourseEntity # if the course is updated, present the course using the CourseEntity
82+
else
83+
error!({ error: "Failed to update course", details: course.errors.full_messages }, 400) # if the course is not updated, return an error with the full error messages
84+
end
85+
end
86+
87+
desc "Deletes an existing course via its ID"
88+
params do
89+
requires :courseId, type: Integer, desc: "Course ID"
90+
end
91+
delete '/course/courseId/:courseId' do
92+
unless authorise? current_user, User, :handle_courseflow
93+
error!({ error: 'Not authorised to delete a course' }, 403)
94+
end
95+
course = Course.find(params[:courseId]) # find the course by ID
96+
course.destroy
97+
{ message: "Course with ID #{params[:courseId]} has been deleted" } # return a message saying the course was deleted
98+
end
99+
end
100+
end
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
require 'grape'
2+
module Courseflow
3+
class CourseMapApi < Grape::API
4+
5+
format :json
6+
helpers AuthenticationHelpers
7+
helpers AuthorisationHelpers
8+
9+
before do
10+
authenticated?
11+
end
12+
13+
desc "Get course map via user ID"
14+
params do
15+
requires :userId, type: Integer, desc: "User ID"
16+
end
17+
get '/coursemap/userId/:userId' do
18+
course_map = CourseMap.find_by(userId: params[:userId])
19+
if course_map
20+
present course_map, with: Entities::CourseMapEntity
21+
else
22+
error!({ error: "Course map #{params[:userId]} not found" }, 404)
23+
end
24+
end
25+
26+
desc "Get course map via course ID"
27+
params do
28+
requires :courseId, type: Integer, desc: "Course ID"
29+
end
30+
get '/coursemap/courseId/:courseId' do
31+
course_map = CourseMap.where(courseId: params[:courseId])
32+
if course_map
33+
present course_map, with: Entities::CourseMapEntity
34+
else
35+
error!({ error: "Course map #{params[:courseId]} not found" }, 404)
36+
end
37+
end
38+
39+
desc "Add a new course map"
40+
params do
41+
requires :userId, type: Integer
42+
requires :courseId, type: Integer
43+
end
44+
post '/coursemap' do
45+
unless authorise? current_user, User, :handle_courseflow
46+
error!({ error: 'Not authorised to add a new course map' }, 403)
47+
end
48+
course_map = CourseMap.new(params)
49+
if course_map.save
50+
present course_map, with: Entities::CourseMapEntity
51+
else
52+
error!({ error: "Failed to create course map", details: coursemap.errors.full_messages }, 400)
53+
end
54+
end
55+
56+
desc "Update an existing course map via its ID"
57+
params do
58+
requires :courseMapId, type: Integer, desc: "Course map ID"
59+
requires :userId, type: Integer
60+
requires :courseId, type: Integer
61+
end
62+
put '/coursemap/courseMapId/:courseMapId' do
63+
unless authorise? current_user, User, :handle_courseflow
64+
error!({ error: 'Not authorised to update course maps' }, 403)
65+
end
66+
course_map = CourseMap.find(params[:courseMapId])
67+
if course_map.update(params.except(:courseMapId))
68+
present course_map, with: Entities::CourseMapEntity
69+
else
70+
error!({ error: "Failed to update course map", details: course_map.errors.full_messages }, 400)
71+
end
72+
end
73+
74+
desc "Delete all course maps via its associated course map ID"
75+
params do
76+
requires :courseMapId, type: Integer, desc: "Course map ID"
77+
end
78+
delete '/coursemap/courseMapId/:courseMapId' do
79+
unless authorise? current_user, User, :handle_courseflow
80+
error!({ error: 'Not authorised to delete course maps' }, 403)
81+
end
82+
course_map = CourseMap.find(params[:courseMapId])
83+
if course_map
84+
course_map.destroy
85+
else
86+
error!({ error: "Course map #{params[:courseMapId]} not found" }, 404)
87+
end
88+
end
89+
90+
desc "Delete all course maps via its associated user ID"
91+
params do
92+
requires :userId, type: Integer, desc: "User ID"
93+
end
94+
delete '/coursemap/userId/:userId' do
95+
unless authorise? current_user, User, :handle_courseflow
96+
error!({ error: 'Not authorised to delete course maps' }, 403)
97+
end
98+
course_map = CourseMap.find(params[:userId])
99+
if course_map
100+
course_map.destroy
101+
else
102+
error!({ error: "Course map #{params[:userId]} not found" }, 404)
103+
end
104+
end
105+
end
106+
end

0 commit comments

Comments
 (0)