gaku_api 0.3.0.pre.4
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 +7 -0
- data/Rakefile +17 -0
- data/app/controllers/gaku/api/application_controller.rb +3 -0
- data/app/controllers/gaku/api/v1/authentication_controller.rb +34 -0
- data/app/controllers/gaku/api/v1/base_controller.rb +53 -0
- data/app/controllers/gaku/api/v1/class_groups/enrollments_controller.rb +44 -0
- data/app/controllers/gaku/api/v1/class_groups/students_controller.rb +22 -0
- data/app/controllers/gaku/api/v1/courses/enrollments_controller.rb +44 -0
- data/app/controllers/gaku/api/v1/courses/students_controller.rb +22 -0
- data/app/controllers/gaku/api/v1/courses_controller.rb +54 -0
- data/app/controllers/gaku/api/v1/enrollments_controller.rb +22 -0
- data/app/controllers/gaku/api/v1/statuses_controller.rb +24 -0
- data/app/controllers/gaku/api/v1/students/class_groups_controller.rb +27 -0
- data/app/controllers/gaku/api/v1/students/courses_controller.rb +27 -0
- data/app/controllers/gaku/api/v1/students/exam_sessions_controller.rb +27 -0
- data/app/controllers/gaku/api/v1/students/extracurricular_activities_controller.rb +27 -0
- data/app/controllers/gaku/api/v1/students/guardians_controller.rb +27 -0
- data/app/controllers/gaku/api/v1/students/student_guardians_controller.rb +29 -0
- data/app/controllers/gaku/api/v1/students_controller.rb +67 -0
- data/app/controllers/gaku/api/v1/syllabuses_controller.rb +54 -0
- data/app/serializers/gaku/class_group_serializer.rb +6 -0
- data/app/serializers/gaku/course_serializer.rb +7 -0
- data/app/serializers/gaku/enrollment_serializer.rb +14 -0
- data/app/serializers/gaku/exam_session_serializer.rb +5 -0
- data/app/serializers/gaku/extracurricular_activity_serializer.rb +5 -0
- data/app/serializers/gaku/guardian_serializer.rb +9 -0
- data/app/serializers/gaku/student_serializer.rb +12 -0
- data/app/serializers/gaku/syllabus_serializer.rb +5 -0
- data/app/services/gaku/api/authenticate_user.rb +42 -0
- data/app/services/gaku/api/authorize_api_request.rb +39 -0
- data/app/services/gaku/api/refresh_authenticate_user.rb +50 -0
- data/config/initializers/kaminari.rb +3 -0
- data/config/initializers/mime_types.rb +1 -0
- data/config/routes.rb +31 -0
- data/gaku_api.gemspec +25 -0
- data/lib/gaku/api/engine.rb +28 -0
- data/lib/gaku/api/version.rb +5 -0
- data/lib/gaku/api.rb +15 -0
- data/lib/gaku_api.rb +1 -0
- data/lib/json_web_token.rb +24 -0
- data/lib/tasks/api_tasks.rake +4 -0
- metadata +184 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2022049a291ae30871d7cb99cd7e634c4793337a99da7b223b88247cc12da3a4
|
4
|
+
data.tar.gz: 539d9b8910f2ae44c1c315bb77121170bdb5940f664d3a7a0a60c5fc2ac8ab80
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d705d970e7707a30c5ac0ed92f9bcec973fff85c7a5bc01fa1cbb2efa2d6e105db378f28266643ddb4936bf64aaadfe7facf8a80159effab92b182b5bca0ddba
|
7
|
+
data.tar.gz: b8487fb3e71bc6467425a4fc9e32230cf1ba182bbfeca0a5450fbc034c05aaa61f43e289af118ab5e15c3fe31dddba1ca90c0bab170a4ff0b6ab241afa32c483
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rubygems/package_task'
|
7
|
+
require 'gaku/testing/common_rake'
|
8
|
+
|
9
|
+
Bundler::GemHelper.install_tasks
|
10
|
+
|
11
|
+
task default: :spec
|
12
|
+
|
13
|
+
desc 'Generates a dummy app for testing'
|
14
|
+
task :test_app do
|
15
|
+
ENV['LIB_NAME'] = 'gaku/api'
|
16
|
+
Rake::Task['common:test_app'].invoke
|
17
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class AuthenticationController < BaseController
|
5
|
+
skip_before_action :authenticate_request
|
6
|
+
|
7
|
+
def authenticate
|
8
|
+
command = Gaku::Api::AuthenticateUser.call(
|
9
|
+
username: params[:username],
|
10
|
+
password: params[:password]
|
11
|
+
)
|
12
|
+
|
13
|
+
if command.success?
|
14
|
+
render(respond_format => { tokens: command.result })
|
15
|
+
else
|
16
|
+
render(respond_format => { error: command.errors }, status: :unauthorized)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def refresh
|
21
|
+
refresh_token = params[:refresh_token]
|
22
|
+
command = Gaku::Api::RefreshAuthenticateUser.call(params[:refresh_token])
|
23
|
+
|
24
|
+
if command.success?
|
25
|
+
render respond_format => { tokens: command.result }
|
26
|
+
else
|
27
|
+
render respond_format => { error: command.errors }, status: :unauthorized
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class Gaku::Api::V1::BaseController < Gaku::Api::ApplicationController
|
2
|
+
include ActionController::MimeResponds
|
3
|
+
attr_reader :current_user
|
4
|
+
|
5
|
+
before_action :set_default_format
|
6
|
+
before_action :authenticate_request
|
7
|
+
|
8
|
+
# rescue_from StandardError do |exception|
|
9
|
+
# render respond_format => { error: exception.message }, status: 500
|
10
|
+
# end
|
11
|
+
|
12
|
+
# rescue_from ActiveRecord::RecordNotFound, with: :render_not_found_response
|
13
|
+
# rescue_from ActiveRecord::RecordInvalid, with: :render_unprocessable_entity_response
|
14
|
+
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def respond_format
|
19
|
+
request.format.to_sym
|
20
|
+
end
|
21
|
+
|
22
|
+
def member_respond_to(object, options = {})
|
23
|
+
render({respond_format => object, root: false, adapter: :attributes }.merge!(options))
|
24
|
+
end
|
25
|
+
|
26
|
+
def collection_respond_to(collection, options = {})
|
27
|
+
render({respond_format => collection, root: false, adapter: :json, meta: meta_for(collection)}.merge!(options))
|
28
|
+
end
|
29
|
+
|
30
|
+
def meta_for(collection)
|
31
|
+
{ count: collection.size , total_count: collection.total_count, page: collection.current_page }
|
32
|
+
end
|
33
|
+
|
34
|
+
def authenticate_request
|
35
|
+
@current_user = Gaku::Api::AuthorizeApiRequest.call(request.headers).result
|
36
|
+
render respond_format => { error: 'Not Authorized' }, status: 401 unless @current_user
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_default_format
|
40
|
+
unless [:json, :msgpack].include? request.format.symbol
|
41
|
+
request.format = :json
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def render_unprocessable_entity_response(exception)
|
46
|
+
render(respond_format => exception.record.errors, status: :unprocessable_entity)
|
47
|
+
end
|
48
|
+
|
49
|
+
def render_not_found_response(exception)
|
50
|
+
render(respond_format => { error: "record not found" }, status: :not_found)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module ClassGroups
|
5
|
+
class EnrollmentsController < BaseController
|
6
|
+
before_action :set_class_group
|
7
|
+
|
8
|
+
def index
|
9
|
+
@enrollments = @class_group.enrollments.page(params[:page ])
|
10
|
+
collection_respond_to @enrollments, root: :enrollments
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@enrollment = @class_group.enrollments.create(create_enrollment_params)
|
16
|
+
member_respond_to @enrollment
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
@enrollment = Enrollment.find(params[:id])
|
21
|
+
@enrollment.update!(update_enrollment_params)
|
22
|
+
member_respond_to @enrollment
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_enrollment_params
|
28
|
+
params.require(:student_id)
|
29
|
+
params.permit(:student_id, :seat_number)
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_enrollment_params
|
33
|
+
params.permit(:seat_number)
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_class_group
|
37
|
+
@class_group = ClassGroup.find(params[:class_group_id])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module ClassGroups
|
5
|
+
class StudentsController < BaseController
|
6
|
+
before_action :set_class_group
|
7
|
+
|
8
|
+
def index
|
9
|
+
@students = @class_group.students.page(params[:page ])
|
10
|
+
collection_respond_to @students, root: :students
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def set_class_group
|
16
|
+
@class_group = ClassGroup.find(params[:class_group_id])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Courses
|
5
|
+
class EnrollmentsController < BaseController
|
6
|
+
before_action :set_course
|
7
|
+
|
8
|
+
def index
|
9
|
+
@enrollments = @course.enrollments.page(params[:page ])
|
10
|
+
collection_respond_to @enrollments, root: :enrollments
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@enrollment = @course.enrollments.create(create_enrollment_params)
|
16
|
+
member_respond_to @enrollment
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
@enrollment = Enrollment.find(params[:id])
|
21
|
+
@enrollment.update!(update_enrollment_params)
|
22
|
+
member_respond_to @enrollment
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_enrollment_params
|
28
|
+
params.require(:student_id)
|
29
|
+
params.permit(:student_id, :seat_number)
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_enrollment_params
|
33
|
+
params.permit(:seat_number)
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_course
|
37
|
+
@course = Course.find(params[:course_id])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Courses
|
5
|
+
class StudentsController < BaseController
|
6
|
+
before_action :set_course
|
7
|
+
|
8
|
+
def index
|
9
|
+
@students = @course.students.page(params[:page ])
|
10
|
+
collection_respond_to @students, root: :students
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def set_course
|
16
|
+
@course = Course.find(params[:course_id])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class CoursesController < BaseController
|
5
|
+
|
6
|
+
before_action :set_course, only: %i( show update destroy )
|
7
|
+
|
8
|
+
def index
|
9
|
+
@courses = Course.all.page(params[:page ])
|
10
|
+
collection_respond_to @courses, root: :courses
|
11
|
+
end
|
12
|
+
|
13
|
+
def show
|
14
|
+
member_respond_to @course
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
@course = Course.new(course_params)
|
19
|
+
if @course.save!
|
20
|
+
member_respond_to @course
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update
|
25
|
+
if @course.update!(course_params)
|
26
|
+
member_respond_to @course
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
if @course.destroy!
|
32
|
+
member_respond_to @course
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def set_course
|
39
|
+
@course = Course.find(params[:id])
|
40
|
+
end
|
41
|
+
|
42
|
+
def course_params
|
43
|
+
params.require(:code)
|
44
|
+
params.permit(course_attrs)
|
45
|
+
end
|
46
|
+
|
47
|
+
def course_attrs
|
48
|
+
%i( syllabus_id code )
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class EnrollmentsController < BaseController
|
5
|
+
skip_before_action :authenticate_request
|
6
|
+
before_action :set_enrollable
|
7
|
+
|
8
|
+
def index
|
9
|
+
@enrollments = @enrollable.enrollments.page(params[:page])
|
10
|
+
collection_respond_to @enrollments, root: :enrollments
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def set_enrollable
|
16
|
+
resource, id = request.path.split('/').values_at(3,4)
|
17
|
+
@enrollable = "gaku/#{resource}".pluralize.classify.constantize.find(id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class StatusesController < ActionController::API
|
5
|
+
|
6
|
+
def show
|
7
|
+
if msgpack_request?
|
8
|
+
render msgpack: { status: :running }
|
9
|
+
|
10
|
+
else
|
11
|
+
render json: { status: :running }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def msgpack_request?
|
18
|
+
request.format.to_sym == :msgpack
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Students
|
5
|
+
class ClassGroupsController < BaseController
|
6
|
+
|
7
|
+
before_action :set_student
|
8
|
+
|
9
|
+
def index
|
10
|
+
@class_groups = @student.class_groups
|
11
|
+
respond_to do |format|
|
12
|
+
format.json { render json: @class_groups, root: :class_groups, adapter: :json }
|
13
|
+
format.msgpack { render msgpack: @class_groups, root: :class_groups, adapter: :json }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_student
|
20
|
+
@student = Gaku::Student.find(params[:student_id])
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Students
|
5
|
+
class CoursesController < BaseController
|
6
|
+
|
7
|
+
before_action :set_student
|
8
|
+
|
9
|
+
def index
|
10
|
+
@courses = @student.courses
|
11
|
+
respond_to do |format|
|
12
|
+
format.json { render json: @courses, root: :courses, adapter: :json }
|
13
|
+
format.msgpack { render msgpack: @courses, root: :courses, adapter: :json }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_student
|
20
|
+
@student = Gaku::Student.find(params[:student_id])
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Students
|
5
|
+
class ExamSessionsController < BaseController
|
6
|
+
|
7
|
+
before_action :set_student
|
8
|
+
|
9
|
+
def index
|
10
|
+
@exam_sessions = @student.exam_sessions
|
11
|
+
respond_to do |format|
|
12
|
+
format.json { render json: @exam_sessions, root: :exam_sessions, adapter: :json }
|
13
|
+
format.msgpack { render msgpack: @exam_sessions, root: :exam_sessions, adapter: :json }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_student
|
20
|
+
@student = Gaku::Student.find(params[:student_id])
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Students
|
5
|
+
class ExtracurricularActivitiesController < BaseController
|
6
|
+
|
7
|
+
before_action :set_student
|
8
|
+
|
9
|
+
def index
|
10
|
+
@extracurricular_activities = @student.extracurricular_activities
|
11
|
+
respond_to do |format|
|
12
|
+
format.json { render json: @extracurricular_activities, root: :extracurricular_activities, adapter: :json }
|
13
|
+
format.msgpack { render msgpack: @extracurricular_activities, root: :extracurricular_activities, adapter: :json }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_student
|
20
|
+
@student = Gaku::Student.find(params[:student_id])
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Students
|
5
|
+
class GuardiansController < BaseController
|
6
|
+
|
7
|
+
before_action :set_student
|
8
|
+
|
9
|
+
def index
|
10
|
+
@guardians = @student.guardians
|
11
|
+
respond_to do |format|
|
12
|
+
format.json { render json: @guardians, root: :guardians, adapter: :json }
|
13
|
+
format.msgpack { render msgpack: @guardians, root: :guardians, adapter: :json }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def set_student
|
20
|
+
@student = Gaku::Student.find(params[:student_id])
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
module Students
|
5
|
+
class StudentGuardiansController < BaseController
|
6
|
+
|
7
|
+
before_action :set_guardian
|
8
|
+
before_action :set_student
|
9
|
+
|
10
|
+
def create
|
11
|
+
@student.guardians << @guardian
|
12
|
+
member_respond_to @guardian
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_guardian
|
18
|
+
@guardian = Guardian.find(params[:guardian_id])
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_student
|
22
|
+
@student = Student.find(params[:student_id])
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class StudentsController < BaseController
|
5
|
+
|
6
|
+
skip_before_action :authenticate_request
|
7
|
+
before_action :set_student, except: %i( index create )
|
8
|
+
|
9
|
+
def index
|
10
|
+
@q = Student.includes(:primary_contact, :primary_address).search(params[:q])
|
11
|
+
@students = @q.result.page(params[:page])
|
12
|
+
collection_respond_to @students, root: :students
|
13
|
+
end
|
14
|
+
|
15
|
+
def show
|
16
|
+
member_respond_to @student
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@student = Student.new(create_student_params)
|
21
|
+
if @student.save!
|
22
|
+
member_respond_to @student
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def update
|
27
|
+
if @student.update!(update_student_params)
|
28
|
+
member_respond_to @student
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def destroy
|
33
|
+
if @student.destroy!
|
34
|
+
member_respond_to @student
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def set_student
|
41
|
+
@student = Student.find(params[:id])
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_student_params
|
45
|
+
params.require(required_student_attributes)
|
46
|
+
params.permit(student_attributes)
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_student_params
|
50
|
+
params.permit(student_attributes)
|
51
|
+
end
|
52
|
+
|
53
|
+
def required_student_attributes
|
54
|
+
%i( name surname )
|
55
|
+
end
|
56
|
+
|
57
|
+
def student_attributes
|
58
|
+
%i(
|
59
|
+
name surname name_reading surname_reading birth_date gender scholarship_status_id,
|
60
|
+
enrollment_status_code commute_method_type_id admitted graduated picture
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
module V1
|
4
|
+
class SyllabusesController < BaseController
|
5
|
+
|
6
|
+
before_action :set_syllabus, only: %i( show update destroy )
|
7
|
+
|
8
|
+
def index
|
9
|
+
@syllabuses = Syllabus.all.page(params[:page ])
|
10
|
+
collection_respond_to @syllabuses, root: :syllabuses
|
11
|
+
end
|
12
|
+
|
13
|
+
def show
|
14
|
+
member_respond_to @syllabus
|
15
|
+
end
|
16
|
+
|
17
|
+
def create
|
18
|
+
@syllabus = Syllabus.new(syllabus_params)
|
19
|
+
if @syllabus.save!
|
20
|
+
member_respond_to @syllabus
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def update
|
25
|
+
if @syllabus.update!(syllabus_params)
|
26
|
+
member_respond_to @syllabus
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy
|
31
|
+
if @syllabus.destroy!
|
32
|
+
member_respond_to @syllabus
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def set_syllabus
|
39
|
+
@syllabus = Syllabus.find(params[:id])
|
40
|
+
end
|
41
|
+
|
42
|
+
def syllabus_params
|
43
|
+
params.require(syllabus_attrs)
|
44
|
+
params.permit(syllabus_attrs)
|
45
|
+
end
|
46
|
+
|
47
|
+
def syllabus_attrs
|
48
|
+
%i( name code )
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Gaku
|
2
|
+
class EnrollmentSerializer < ActiveModel::Serializer
|
3
|
+
attributes %i( id student_id seat_number )
|
4
|
+
attribute :course_id, if: :course_enrollment?
|
5
|
+
|
6
|
+
def course_id
|
7
|
+
object.enrollable_id
|
8
|
+
end
|
9
|
+
|
10
|
+
def course_enrollment?
|
11
|
+
object.course_type?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Gaku
|
2
|
+
class GuardianSerializer < ActiveModel::Serializer
|
3
|
+
attributes %i( id name surname middle_name name_reading middle_name_reading surname_reading
|
4
|
+
gender birth_date relationship picture_file_name picture_content_type picture_file_size
|
5
|
+
picture_updated_at primary_address primary_contact addresses_count contacts_count user_id
|
6
|
+
created_at updated_at
|
7
|
+
)
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Gaku
|
2
|
+
class StudentSerializer < ActiveModel::Serializer
|
3
|
+
attributes %i( id name surname middle_name name_reading middle_name_reading surname_reading
|
4
|
+
gender birth_date admitted graduated code serial_id foreign_id_code national_registration_code
|
5
|
+
enrollment_status_code picture_file_name picture_content_type picture_file_size
|
6
|
+
picture_updated_at addresses_count contacts_count notes_count courses_count guardians_count
|
7
|
+
external_school_records_count badges_count primary_address primary_contact class_and_number
|
8
|
+
user_id faculty_id commute_method_type_id scholarship_status_id created_at updated_at
|
9
|
+
extracurricular_activities_count class_groups_count )
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'json_web_token'
|
2
|
+
module Gaku
|
3
|
+
module Api
|
4
|
+
class AuthenticateUser
|
5
|
+
prepend SimpleCommand
|
6
|
+
|
7
|
+
attr_accessor :username, :password
|
8
|
+
|
9
|
+
def initialize(username:, password:)
|
10
|
+
@username = username
|
11
|
+
@password = password
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
if user
|
16
|
+
secret = SecureRandom.hex(64)
|
17
|
+
$redis.set("token:#{jti}", secret, ex: 20.minutes)
|
18
|
+
{
|
19
|
+
auth_token: JsonWebToken.encode({user_id: user.id}, exp: 3.minutes.from_now, jti: jti, secret: secret),
|
20
|
+
refresh_token: JsonWebToken.encode({user_id: user.id}, exp: 20.minutes.from_now, jti: jti, secret: secret)
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def jti
|
28
|
+
@jti ||= SecureRandom.uuid
|
29
|
+
end
|
30
|
+
|
31
|
+
def user
|
32
|
+
user = Gaku::User.find_by(username: username)
|
33
|
+
return user if user && user.valid_password?(password)
|
34
|
+
|
35
|
+
errors.add(:user_authentication, 'invalid credentials')
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'json_web_token'
|
2
|
+
|
3
|
+
module Gaku
|
4
|
+
module Api
|
5
|
+
class AuthorizeApiRequest
|
6
|
+
prepend SimpleCommand
|
7
|
+
|
8
|
+
def initialize(headers = {})
|
9
|
+
@headers = headers
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
user
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :headers
|
19
|
+
|
20
|
+
def user
|
21
|
+
@user ||= User.find(decoded_auth_token[:user_id]) if decoded_auth_token
|
22
|
+
@user || errors.add(:token, 'Invalid token') && nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def decoded_auth_token
|
26
|
+
@decoded_auth_token ||= JsonWebToken.decode(http_auth_header)
|
27
|
+
end
|
28
|
+
|
29
|
+
def http_auth_header
|
30
|
+
if headers['Authorization'].present?
|
31
|
+
return headers['Authorization'].split(' ').last
|
32
|
+
else
|
33
|
+
errors.add(:token, 'Missing token')
|
34
|
+
end
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'json_web_token'
|
2
|
+
module Gaku
|
3
|
+
module Api
|
4
|
+
class RefreshAuthenticateUser
|
5
|
+
prepend SimpleCommand
|
6
|
+
|
7
|
+
attr_accessor :refresh_token
|
8
|
+
|
9
|
+
def initialize(refresh_token)
|
10
|
+
@refresh_token = refresh_token
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
if user
|
15
|
+
secret = SecureRandom.hex(64)
|
16
|
+
$redis.set("token:#{jti}", secret, ex: 20.minutes)
|
17
|
+
{
|
18
|
+
auth_token: JsonWebToken.encode({user_id: user.id}, exp: 3.minutes.from_now, jti: jti, secret: secret),
|
19
|
+
refresh_token: JsonWebToken.encode({user_id: user.id}, exp: 20.minutes.from_now, jti: jti, secret: secret)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def jti
|
27
|
+
@jti ||= SecureRandom.uuid
|
28
|
+
end
|
29
|
+
|
30
|
+
def user
|
31
|
+
@user ||= User.find(decoded_refresh_token[:user_id]) if decoded_refresh_token
|
32
|
+
@user || errors.add(:token, 'Invalid expire token') && nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def decoded_refresh_token
|
36
|
+
@decoded_refresh_token ||= JsonWebToken.decode(refresh_token, refresh: true)
|
37
|
+
end
|
38
|
+
|
39
|
+
# def user
|
40
|
+
# user = Gaku::User.find_by(email: email)
|
41
|
+
# return user if user && user.valid_password?(password)
|
42
|
+
#
|
43
|
+
# errors.add(:user_authentication, 'invalid credentials')
|
44
|
+
# nil
|
45
|
+
# end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Mime::Type.register "application/msgpack", :msgpack
|
data/config/routes.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
Gaku::Core::Engine.routes.draw do
|
2
|
+
namespace :api do
|
3
|
+
namespace :v1 do
|
4
|
+
resource :status
|
5
|
+
|
6
|
+
post 'authenticate', to: 'authentication#authenticate'
|
7
|
+
post 'authenticate/refresh', to: 'authentication#refresh'
|
8
|
+
|
9
|
+
resources :students do
|
10
|
+
resources :guardians, controller: 'students/guardians'
|
11
|
+
resources :student_guardians, controller: 'students/student_guardians', only: %i(create destroy)
|
12
|
+
resources :courses, controller: 'students/courses'
|
13
|
+
resources :class_groups, controller: 'students/class_groups'
|
14
|
+
resources :extracurricular_activities, controller: 'students/extracurricular_activities'
|
15
|
+
resources :exam_sessions, controller: 'students/exam_sessions'
|
16
|
+
end
|
17
|
+
|
18
|
+
resources :courses do
|
19
|
+
resources :students, controller: 'courses/students'
|
20
|
+
resources :enrollments, controller: 'courses/enrollments'
|
21
|
+
end
|
22
|
+
|
23
|
+
resources :class_groups do
|
24
|
+
resources :students, controller: 'class_groups/students'
|
25
|
+
resources :enrollments, controller: 'class_groups/enrollments'
|
26
|
+
end
|
27
|
+
|
28
|
+
resources :syllabuses
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/gaku_api.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../common_gaku_gemspec_mixin'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
set_gaku_gemspec_shared s
|
5
|
+
|
6
|
+
s.name = 'gaku_api'
|
7
|
+
s.summary = 'GAKU Engine API module'
|
8
|
+
s.description = 'API functionality for GAKU Engine. See https://github.com/GAKUEngine/gaku'
|
9
|
+
|
10
|
+
s.files = Dir.glob("{app,config,db,lib}/**/*") +
|
11
|
+
[
|
12
|
+
'Rakefile',
|
13
|
+
'gaku_api.gemspec'
|
14
|
+
]
|
15
|
+
|
16
|
+
s.add_dependency 'simple_command'
|
17
|
+
s.add_dependency 'jwt'
|
18
|
+
s.add_dependency 'active_model_serializers'
|
19
|
+
s.add_dependency 'msgpack_rails'
|
20
|
+
s.add_dependency 'kaminari'
|
21
|
+
|
22
|
+
s.add_dependency 'gaku_core', s.version
|
23
|
+
|
24
|
+
s.add_development_dependency 'gaku_testing', s.version
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Gaku
|
2
|
+
module Api
|
3
|
+
class Engine < ::Rails::Engine
|
4
|
+
engine_name 'gaku_api'
|
5
|
+
config.generators.api_only = true
|
6
|
+
|
7
|
+
initializer 'actionpack-msgpack_parser.configure' do
|
8
|
+
ActionDispatch::Request.parameter_parsers[:msgpack] = -> (raw_post) do
|
9
|
+
ActiveSupport::MessagePack.decode(raw_post) || {}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
config.after_initialize do
|
14
|
+
ActionController.add_renderer :msgpack do |resource, options|
|
15
|
+
MessagePack::DefaultFactory.register_type(0x00, Symbol)
|
16
|
+
resource_serializer = ActiveModelSerializers::SerializableResource.new(resource, options)
|
17
|
+
self.content_type = Mime[:msgpack]
|
18
|
+
if resource_serializer.serializer?
|
19
|
+
self.response_body = resource_serializer.serializable_hash.msgpack_to_msgpack
|
20
|
+
else
|
21
|
+
self.response_body = resource.msgpack_to_msgpack
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/gaku/api.rb
ADDED
data/lib/gaku_api.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'gaku/api'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class JsonWebToken
|
2
|
+
class << self
|
3
|
+
def encode(payload, exp:, jti:, secret:)
|
4
|
+
payload[:exp] = exp.to_i
|
5
|
+
payload[:jti] = jti
|
6
|
+
JWT.encode(payload, secret)
|
7
|
+
end
|
8
|
+
|
9
|
+
def decode(token, refresh: false)
|
10
|
+
secret = extract_secret(token, refresh: refresh)
|
11
|
+
body = JWT.decode(token, secret)[0]
|
12
|
+
HashWithIndifferentAccess.new body
|
13
|
+
rescue
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def extract_secret(token, refresh: false)
|
18
|
+
key = JSON.parse(Base64.decode64 token.split('.')[1])['jti']
|
19
|
+
$redis.get("token:#{key}").tap do
|
20
|
+
$redis.del("token:#{key}") if refresh
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gaku_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0.pre.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rei Kagetsuki
|
8
|
+
- Georgi Tapalilov
|
9
|
+
- Nakaya Yukiharu
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2018-02-26 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: simple_command
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: jwt
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: active_model_serializers
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: msgpack_rails
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
type: :runtime
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: kaminari
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :runtime
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: gaku_core
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 0.3.0.pre.4
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.3.0.pre.4
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: gaku_testing
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - '='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: 0.3.0.pre.4
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - '='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 0.3.0.pre.4
|
113
|
+
description: API functionality for GAKU Engine. See https://github.com/GAKUEngine/gaku
|
114
|
+
email: info@gakuengine.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- Rakefile
|
120
|
+
- app/controllers/gaku/api/application_controller.rb
|
121
|
+
- app/controllers/gaku/api/v1/authentication_controller.rb
|
122
|
+
- app/controllers/gaku/api/v1/base_controller.rb
|
123
|
+
- app/controllers/gaku/api/v1/class_groups/enrollments_controller.rb
|
124
|
+
- app/controllers/gaku/api/v1/class_groups/students_controller.rb
|
125
|
+
- app/controllers/gaku/api/v1/courses/enrollments_controller.rb
|
126
|
+
- app/controllers/gaku/api/v1/courses/students_controller.rb
|
127
|
+
- app/controllers/gaku/api/v1/courses_controller.rb
|
128
|
+
- app/controllers/gaku/api/v1/enrollments_controller.rb
|
129
|
+
- app/controllers/gaku/api/v1/statuses_controller.rb
|
130
|
+
- app/controllers/gaku/api/v1/students/class_groups_controller.rb
|
131
|
+
- app/controllers/gaku/api/v1/students/courses_controller.rb
|
132
|
+
- app/controllers/gaku/api/v1/students/exam_sessions_controller.rb
|
133
|
+
- app/controllers/gaku/api/v1/students/extracurricular_activities_controller.rb
|
134
|
+
- app/controllers/gaku/api/v1/students/guardians_controller.rb
|
135
|
+
- app/controllers/gaku/api/v1/students/student_guardians_controller.rb
|
136
|
+
- app/controllers/gaku/api/v1/students_controller.rb
|
137
|
+
- app/controllers/gaku/api/v1/syllabuses_controller.rb
|
138
|
+
- app/serializers/gaku/class_group_serializer.rb
|
139
|
+
- app/serializers/gaku/course_serializer.rb
|
140
|
+
- app/serializers/gaku/enrollment_serializer.rb
|
141
|
+
- app/serializers/gaku/exam_session_serializer.rb
|
142
|
+
- app/serializers/gaku/extracurricular_activity_serializer.rb
|
143
|
+
- app/serializers/gaku/guardian_serializer.rb
|
144
|
+
- app/serializers/gaku/student_serializer.rb
|
145
|
+
- app/serializers/gaku/syllabus_serializer.rb
|
146
|
+
- app/services/gaku/api/authenticate_user.rb
|
147
|
+
- app/services/gaku/api/authorize_api_request.rb
|
148
|
+
- app/services/gaku/api/refresh_authenticate_user.rb
|
149
|
+
- config/initializers/kaminari.rb
|
150
|
+
- config/initializers/mime_types.rb
|
151
|
+
- config/routes.rb
|
152
|
+
- gaku_api.gemspec
|
153
|
+
- lib/gaku/api.rb
|
154
|
+
- lib/gaku/api/engine.rb
|
155
|
+
- lib/gaku/api/version.rb
|
156
|
+
- lib/gaku_api.rb
|
157
|
+
- lib/json_web_token.rb
|
158
|
+
- lib/tasks/api_tasks.rake
|
159
|
+
homepage: http://www.gakuengine.com
|
160
|
+
licenses:
|
161
|
+
- GPL-3.0
|
162
|
+
- AGPL-3.0
|
163
|
+
metadata: {}
|
164
|
+
post_install_message:
|
165
|
+
rdoc_options: []
|
166
|
+
require_paths:
|
167
|
+
- lib
|
168
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - ">"
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: 1.3.1
|
178
|
+
requirements: []
|
179
|
+
rubyforge_project:
|
180
|
+
rubygems_version: 2.7.3
|
181
|
+
signing_key:
|
182
|
+
specification_version: 4
|
183
|
+
summary: GAKU Engine API module
|
184
|
+
test_files: []
|