gaku_api 0.3.0.pre.4
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|