├── log └── .keep ├── tmp └── .keep ├── vendor └── .keep ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── favicon.ico ├── apple-touch-icon.png ├── apple-touch-icon-precomposed.png ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── test ├── helpers │ └── .keep ├── mailers │ └── .keep ├── models │ └── .keep ├── system │ └── .keep ├── controllers │ └── .keep ├── fixtures │ ├── .keep │ └── files │ │ └── .keep ├── integration │ └── .keep ├── application_system_test_case.rb └── test_helper.rb ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ ├── channels │ │ │ └── .keep │ │ ├── cable.js │ │ ├── admin │ │ │ └── custom_admin.js │ │ ├── application.js │ │ └── admin.js │ ├── config │ │ └── manifest.js │ └── stylesheets │ │ ├── application.scss │ │ ├── admin.scss │ │ └── admin │ │ └── sb-admin.min.css ├── models │ ├── concerns │ │ └── .keep │ ├── application_record.rb │ ├── admin.rb │ ├── access_token.rb │ └── user.rb ├── controllers │ ├── concerns │ │ └── .keep │ ├── home_controller.rb │ ├── users_controller.rb │ ├── admin │ │ ├── base_controller.rb │ │ ├── dashboard_controller.rb │ │ └── admins_controller.rb │ ├── api │ │ ├── v1 │ │ │ ├── helpers │ │ │ │ └── authentication_helpers.rb │ │ │ ├── base.rb │ │ │ └── users.rb │ │ ├── v2 │ │ │ ├── helpers │ │ │ │ └── authentication_helpers.rb │ │ │ ├── users.rb │ │ │ └── base.rb │ │ ├── base.rb │ │ └── defaults.rb │ └── application_controller.rb ├── views │ ├── layouts │ │ ├── mailer.text.haml │ │ ├── mailer.html.haml │ │ ├── admin │ │ │ ├── _footer.html.haml │ │ │ ├── _logout_modal.html.haml │ │ │ └── _navigation.html.haml │ │ ├── application.html.haml │ │ ├── _meta_tags.html.haml │ │ └── admin.html.haml │ ├── api │ │ └── users │ │ │ ├── get_user.json.jbuilder │ │ │ └── _details.json.jbuilder │ ├── home │ │ └── index.html.haml │ ├── users │ │ └── show.html.haml │ └── admin │ │ ├── dashboard │ │ ├── _card.html.haml │ │ └── index.html.haml │ │ ├── sessions │ │ └── new.html.haml │ │ └── admins │ │ └── change_password.html.haml ├── jobs │ └── application_job.rb ├── lib │ └── constant.rb ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── mailers │ └── application_mailer.rb ├── serializers │ └── user_serializer.rb └── helpers │ ├── application_helper.rb │ ├── meta_tags_helper.rb │ └── flash_helper.rb ├── .ruby-version ├── _config.yml ├── package.json ├── bin ├── bundle ├── rake ├── rails ├── yarn ├── spring ├── update └── setup ├── config ├── initializers │ ├── default_meta.rb │ ├── swagger.rb │ ├── mime_types.rb │ ├── filter_parameter_logging.rb │ ├── application_controller_renderer.rb │ ├── cookies_serializer.rb │ ├── backtrace_silencers.rb │ ├── wrap_parameters.rb │ ├── assets.rb │ ├── inflections.rb │ ├── content_security_policy.rb │ └── devise.rb ├── spring.rb ├── environment.rb ├── meta.yml ├── boot.rb ├── cable.yml ├── routes.rb ├── credentials.yml.enc ├── database.yml ├── database.yml.example ├── application.rb ├── locales │ ├── en.yml │ └── devise.en.yml ├── storage.yml ├── puma.rb └── environments │ ├── test.rb │ ├── development.rb │ └── production.rb ├── Rakefile ├── config.ru ├── db ├── migrate │ ├── 20180424083654_create_access_tokens.rb │ ├── 20190218131410_devise_create_admins.rb │ └── 20180424071905_devise_create_users.rb ├── seeds.rb └── schema.rb ├── .gitignore ├── Gemfile ├── README.md └── Gemfile.lock /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/files/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.6.3@ror_plus 2 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/javascripts/channels/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.haml: -------------------------------------------------------------------------------- 1 | = yield 2 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "RorPlus", 3 | "private": true, 4 | "dependencies": {} 5 | } 6 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /app/views/api/users/get_user.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.partial! 'users/details', user: @user 4 | -------------------------------------------------------------------------------- /app/lib/constant.rb: -------------------------------------------------------------------------------- 1 | module Constant 2 | TOKEN_EXPIRY_IN_DAYS = 7 3 | AUTH_DESCRIPTION = 'Authorization key'.freeze 4 | end 5 | -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/views/home/index.html.haml: -------------------------------------------------------------------------------- 1 | - if current_user.blank? 2 | = link_to 'User Login', new_user_session_path, class: 'btn btn-success' 3 | -------------------------------------------------------------------------------- /app/views/users/show.html.haml: -------------------------------------------------------------------------------- 1 | = 'Hi User' 2 | = link_to 'Logout', destroy_user_session_path, class: 'btn btn-danger', method: :delete 3 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../javascripts .js 3 | //= link_directory ../stylesheets .css 4 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /config/initializers/default_meta.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | DEFAULT_META = YAML.load_file(Rails.root.join('config/meta.yml')) 4 | -------------------------------------------------------------------------------- /app/controllers/home_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HomeController < ApplicationController 4 | def index; end 5 | end 6 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | %w[ 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ].each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /app/views/api/users/_details.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.user do 4 | json.call(user, :id, :email, :first_name) 5 | end 6 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | self.abstract_class = true 5 | end 6 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UsersController < ApplicationController 4 | before_action :authenticate_user! 5 | 6 | def show; end 7 | end 8 | -------------------------------------------------------------------------------- /config/initializers/swagger.rb: -------------------------------------------------------------------------------- 1 | GrapeSwaggerRails.options.url = '/api/api_docs.json' 2 | GrapeSwaggerRails.options.app_name = 'RorPlus' 3 | GrapeSwaggerRails.options.app_url = $secret[:base_url] 4 | -------------------------------------------------------------------------------- /app/controllers/admin/base_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Admin::BaseController < ApplicationController 4 | before_action :authenticate_admin! 5 | layout 'admin' 6 | end 7 | -------------------------------------------------------------------------------- /app/serializers/user_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UserSerializer 4 | include FastJsonapi::ObjectSerializer 5 | attributes :id, :email, :first_name, :last_name 6 | end 7 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /config/meta.yml: -------------------------------------------------------------------------------- 1 | meta_title: "RoR Plus" 2 | meta_description: "Production ready boilerplate for RoR web application, Rails boilerplate" 3 | meta_image: "https://drive.google.com/uc?id=1HAGX3lPk2W46XrMcg0vpdUB5ejmpa-bC" 4 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %meta{content: 'text/html; charset=UTF-8', 'http-equiv': 'Content-Type'} 5 | :css 6 | /* Email styles need to be inline */ 7 | %body 8 | = yield 9 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /app/views/layouts/admin/_footer.html.haml: -------------------------------------------------------------------------------- 1 | %footer.sticky-footer 2 | .container 3 | .text-center 4 | %small 5 | Copyright © 6 | / Scroll to Top Button 7 | %a.scroll-to-top.rounded{:href => '#page-top'} 8 | %i.fa.fa-angle-up 9 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | def show_error(object, attribute_name) 5 | object.errors.full_messages_for(attribute_name).join(',') if object.errors.any? 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: RoRPlus_production 11 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/controllers/admin/dashboard_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Admin::DashboardController < Admin::BaseController 4 | before_action :authenticate_admin! 5 | 6 | def index 7 | @users = User.all 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | require_relative '../config/boot' 8 | require 'rake' 9 | Rake.application.run 10 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | use Rack::Config do |env| 6 | env['api.tilt.root'] = "#{Rails.root}/app/views/api/" 7 | end 8 | 9 | run Rails.application 10 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | APP_PATH = File.expand_path('../config/application', __dir__) 8 | require_relative '../config/boot' 9 | require 'rails/commands' 10 | -------------------------------------------------------------------------------- /app/models/admin.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Admin < ApplicationRecord 4 | # Include default devise modules. Others available are: 5 | # :confirmable, :lockable, :timeoutable and :omniauthable 6 | devise :database_authenticatable, :registerable, 7 | :recoverable, :rememberable, :trackable, :validatable 8 | end 9 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RAILS_ENV'] ||= 'test' 2 | require_relative '../config/environment' 3 | require 'rails/test_help' 4 | 5 | class ActiveSupport::TestCase 6 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 7 | fixtures :all 8 | 9 | # Add more helper methods to be used by all tests here... 10 | end 11 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/api/v1/helpers/authentication_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API::V1::Helpers::AuthenticationHelpers 4 | extend Grape::API::Helpers 5 | 6 | params :authentication_params do 7 | requires :user, type: Hash do 8 | requires :access_token, type: String, desc: 'Access Token' 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/api/v2/helpers/authentication_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API::V2::Helpers::AuthenticationHelpers 4 | extend Grape::API::Helpers 5 | 6 | params :authentication_params do 7 | requires :user, type: Hash do 8 | requires :access_token, type: String, desc: 'Access Token' 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20180424083654_create_access_tokens.rb: -------------------------------------------------------------------------------- 1 | class CreateAccessTokens < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :access_tokens do |t| 4 | t.string :token, null: false 5 | t.boolean :active, null: false, default: true 6 | t.integer :user_id, null: false 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | -------------------------------------------------------------------------------- /app/assets/javascripts/cable.js: -------------------------------------------------------------------------------- 1 | // Action Cable provides the framework to deal with WebSockets in Rails. 2 | // You can generate new channels where WebSocket features live using the `rails generate channel` command. 3 | // 4 | //= require action_cable 5 | //= require_self 6 | //= require_tree ./channels 7 | 8 | (function() { 9 | this.App || (this.App = {}); 10 | 11 | App.cable = ActionCable.createConsumer(); 12 | 13 | }).call(this); 14 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationController < ActionController::Base 4 | def after_sign_in_path_for(_resource_or_scope) 5 | current_user.present? ? user_path(current_user) : admin_dashboard_index_path 6 | end 7 | 8 | def after_sign_out_path_for(resource_or_scope) 9 | resource_or_scope.to_s == 'user' ? new_user_session_path : new_admin_session_path 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %meta{content: 'text/html; charset=UTF-8', 'http-equiv': 'Content-Type'} 5 | = render 'layouts/meta_tags' 6 | %title RorPlus 7 | = csrf_meta_tags 8 | = csp_meta_tag 9 | = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' 10 | = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' 11 | %body 12 | = yield 13 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /app/views/admin/dashboard/_card.html.haml: -------------------------------------------------------------------------------- 1 | .row 2 | .col-xl-3.col-sm-6.mb-3 3 | .card.text-white.bg-primary.o-hidden.h-100 4 | .card-body 5 | .card-body-icon 6 | %i.fa.fa-fw.fa-user 7 | .mr-5 8 | = User.count 9 | User 10 | = link_to "javascript:void(0)", {class: 'card-footer text-white clearfix small z-1'} do 11 | %span.float-left View Details 12 | %span.float-right 13 | %i.fa.fa-angle-right 14 | -------------------------------------------------------------------------------- /app/helpers/meta_tags_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module MetaTagsHelper 4 | def meta_title 5 | content_for(:meta_title) || DEFAULT_META['meta_title'] 6 | end 7 | 8 | def meta_description 9 | content_for(:meta_description) || DEFAULT_META['meta_description'] 10 | end 11 | 12 | def meta_image 13 | meta_image = content_for(:meta_image) || DEFAULT_META['meta_image'] 14 | meta_image.starts_with?('http') ? meta_image : image_url(meta_image) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/controllers/api/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API 4 | class Base < Grape::API 5 | mount API::V1::Base 6 | mount API::V2::Base 7 | 8 | add_swagger_documentation mount_path: '/api_docs', 9 | api_version: 'v1', 10 | info: { 11 | title: "RorPlus API's", 12 | description: "API's available for RorPlus users" 13 | } 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Rails.application.routes.draw do 4 | devise_for :admin 5 | root 'home#index' 6 | 7 | devise_for :users 8 | 9 | mount API::Base => '/api' 10 | mount GrapeSwaggerRails::Engine => '/swagger' 11 | 12 | resources :users, only: [:show] 13 | 14 | namespace :admin do 15 | resources :dashboard, only: [:index] 16 | resources :admins, only: [], path: '' do 17 | get :change_password 18 | patch :update_password 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/assets/javascripts/admin/custom_admin.js: -------------------------------------------------------------------------------- 1 | $( document ).on('turbolinks:load', function() { 2 | $(".alert" ).fadeOut(7000); 3 | $("#sidenavToggler").click(function(e) { 4 | e.preventDefault(); 5 | $("body").toggleClass("sidenav-toggled"); 6 | $(".navbar-sidenav .nav-link-collapse").addClass("collapsed"); 7 | $(".navbar-sidenav .sidenav-second-level, .navbar-sidenav .sidenav-third-level").removeClass("show"); 8 | }); 9 | $(".form-control").on("change",function(){ 10 | $(this.closest(".form-group")).find(".server-validation").hide() 11 | }) 12 | }); 13 | -------------------------------------------------------------------------------- /app/models/access_token.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AccessToken < ApplicationRecord 4 | # Associations 5 | belongs_to :user 6 | 7 | before_create :generate_token 8 | 9 | private 10 | 11 | def generate_token 12 | begin 13 | exp = Time.zone.now.to_i + Constant::TOKEN_EXPIRY_IN_DAYS.days.to_i 14 | exp_payload = { data: 'ror-plus-api', exp: exp } 15 | token = JWT.encode exp_payload, $secret[:api_hmac_secret], 'HS256' 16 | self.token = token 17 | end while self.class.exists?(token: token) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) 11 | spring = lockfile.specs.detect { |spec| spec.name == "spring" } 12 | if spring 13 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path 14 | gem 'spring', spring.version 15 | require 'spring/binstub' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class User < ApplicationRecord 4 | # Include default devise modules. Others available are: 5 | # :confirmable, :lockable, :timeoutable and :omniauthable 6 | devise :database_authenticatable, :registerable, 7 | :recoverable, :rememberable, :trackable, :validatable 8 | 9 | # Associations 10 | has_many :access_tokens, dependent: :destroy 11 | 12 | def generate_access_token 13 | access_tokens.create 14 | end 15 | 16 | def new_access_token 17 | access_tokens.destroy_all 18 | generate_access_token 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | Pjvv9q//ASONxhPjqm+4J2YjhGJeLVkKSaVyZVBLZeb88HlNtsFEHpLT5fT+Fh6YPG4bF2HmOCfq5D2x3Im+7S+WxbqL3xn7ykGwccu9kSccoB0wemt0VT0yagOAbXVPNcRStR6wA3oXCGws39gwOTID9zdtOvxJ3EefdbmR3DyPTIA3J7WGEDTKePxeG+8Ufa4Hr803j9UZgeSNcVwEC38QG3SrfxBjUvS31CWcl0a5W7m1AWd9JWrRIpd1os78SzCcQMkXTKBDKqayYuFjaP+P8yhF0u1NA+XiP/9pYP3OdtOEbiF/6KlXO805UkUjT1ImCiHhZIsuKS5YGs15IOpFuS0WI6T4GSUUA926IGP027NUOTJanTnmSYTTVV3S+FaIUo2LBx9uCHnrSyOlhoh/lU5qhS4XDyidfUxb0uEuwzfZicZdyiwIvh0e9LaiIbw3oK9u54MmgLn84I9M9mW5jer21TgjIoJVzFdIaV7v4zrxWRNE9fcxeHcXqaPFO+UVbpiu9t8Xazy7nCZy8FqH9yjWk+zRseLSZG57H5CndnWWAh78686ylaEbYuo3vmUYDEhnOY2hlw+jPaRsIh0+fc2Wz7Co--6d0mYnLji3uKPvXA--9bHhDkkK0qrqpe1st+PRIg== -------------------------------------------------------------------------------- /app/controllers/api/v2/users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API 4 | module V2 5 | class Users < API::V2::Base 6 | include API::Defaults 7 | 8 | resource :users do 9 | desc 'Get a user', 10 | headers: { 11 | 'Authorization' => { description: Constant::AUTH_DESCRIPTION, required: true } 12 | } 13 | params do 14 | use :authentication_params 15 | end 16 | get ':id' do 17 | authenticate! 18 | user = User.find(params[:id]) 19 | respond(200, UserSerializer.new(user).serializable_hash) 20 | end 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | # Add Yarn node_modules folder to the asset load path. 9 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | Rails.application.config.assets.precompile += %w( admin.js admin.css ) 15 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | default: &default 2 | adapter: postgresql 3 | host: localhost 4 | encoding: utf8 5 | username: postgres # Change it to your username 6 | password: postgres # Change it to your password 7 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 8 | timeout: 5000 9 | 10 | development: 11 | <<: *default 12 | database: ror_plus_development 13 | 14 | # Warning: The database defined as "test" will be erased and 15 | # re-generated from your development database when you run "rake". 16 | # Do not set this db to the same as development or production. 17 | test: 18 | <<: *default 19 | database: ror_plus_test 20 | 21 | production: 22 | <<: *default 23 | database: ror_plus_production 24 | -------------------------------------------------------------------------------- /config/database.yml.example: -------------------------------------------------------------------------------- 1 | default: &default 2 | adapter: postgresql 3 | host: localhost 4 | encoding: utf8 5 | username: postgres # Change it to your username 6 | password: 123456 # Change it to your password 7 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 8 | timeout: 5000 9 | 10 | development: 11 | <<: *default 12 | database: ror_plus_development 13 | 14 | # Warning: The database defined as "test" will be erased and 15 | # re-generated from your development database when you run "rake". 16 | # Do not set this db to the same as development or production. 17 | test: 18 | <<: *default 19 | database: ror_plus_test 20 | 21 | production: 22 | <<: *default 23 | database: ror_plus_production 24 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /app/views/layouts/admin/_logout_modal.html.haml: -------------------------------------------------------------------------------- 1 | #logoutModal.modal.fade{'aria-hidden' => 'true', 'aria-labelledby' => 'exampleModalLabel', role: 'dialog', tabindex: '-1'} 2 | .modal-dialog{:role => 'document'} 3 | .modal-content 4 | .modal-header 5 | %h5#exampleModalLabel.modal-title 6 | = I18n.t('admin.navigation.logout_title') 7 | %button.close{'aria-label' => 'Close', 'data-dismiss' => 'modal', type: 'button'} 8 | %span{'aria-hidden' => 'true'} × 9 | .modal-body 10 | = I18n.t('admin.navigation.logout_message') 11 | .modal-footer 12 | %button.btn.btn-secondary{'data-dismiss' => 'modal', type: 'button'} Cancel 13 | = link_to 'Logout', destroy_admin_session_path ,{class: 'btn btn-primary', method: 'delete'} 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | @import "bootstrap"; 17 | -------------------------------------------------------------------------------- /app/views/layouts/_meta_tags.html.haml: -------------------------------------------------------------------------------- 1 | %title= meta_title 2 | 3 | %meta{name: 'description', content: "#{meta_description}"} 4 | 5 | / Facebook Open Graph data 6 | %meta{property: 'og:title', content: "#{meta_title}"} 7 | %meta{property: 'og:type', content: 'website'} 8 | %meta{property: 'og:url', content: "#{request.original_url}"} 9 | %meta{property: 'og:image', content: "#{meta_image}"} 10 | %meta{property: 'og:description', content: "#{meta_description}"} 11 | %meta{property: 'og:site_name', content: "#{meta_title}"} 12 | 13 | / Twitter Card data 14 | %meta{property: 'twitter:card', content: 'summary_large_image'} 15 | %meta{property: 'twitter:title', content: "#{meta_title}"} 16 | %meta{property: 'twitter:description', content: "#{meta_description}"} 17 | %meta{property: 'twitter:image:src', content: "#{meta_image}"} 18 | -------------------------------------------------------------------------------- /app/assets/stylesheets/admin.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree ./admin/ 14 | *= require_self 15 | 16 | */ 17 | @import "bootstrap"; 18 | @import "font-awesome"; 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | /tmp/* 17 | !/log/.keep 18 | !/tmp/.keep 19 | 20 | # Ignore uploaded files in development 21 | /storage/* 22 | 23 | /node_modules 24 | /yarn-error.log 25 | 26 | /public/assets 27 | .byebug_history 28 | 29 | # Ignore master key for decrypting credentials and more. 30 | /config/master.key 31 | /config/database.yml 32 | .scannerwork 33 | .rubocop.yml 34 | .vscode 35 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's 5 | // vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require rails-ujs 14 | //= require activestorage 15 | //= require turbolinks 16 | //= require jquery3 17 | //= require popper 18 | //= require bootstrap 19 | //= require_tree . 20 | -------------------------------------------------------------------------------- /app/views/admin/dashboard/index.html.haml: -------------------------------------------------------------------------------- 1 | .container-fluid 2 | / Breadcrumbs 3 | %ol.breadcrumb 4 | %li.breadcrumb-item 5 | %a{href: '#'} Admin 6 | %li.breadcrumb-item.active My Dashboard 7 | = render 'card' 8 | / Example DataTables Card 9 | .card.mb-3 10 | .card-header 11 | %i.fa.fa-table 12 | Active Users 13 | .card-body 14 | .table-responsive 15 | %table#dataTable.table.table-bordered{:cellspacing => '0', :width => '100%'} 16 | %thead 17 | %tr 18 | %th First Name 19 | %th Last Name 20 | %th Email 21 | %tbody 22 | - @users.each do |user| 23 | %tr 24 | %td 25 | = user.first_name 26 | %td 27 | = user.last_name 28 | %td 29 | = user.email 30 | -------------------------------------------------------------------------------- /app/assets/javascripts/admin.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's 5 | // vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require rails-ujs 14 | //= require activestorage 15 | //= require turbolinks 16 | //= require jquery3 17 | //= require popper 18 | //= require bootstrap 19 | //= require jquery_ujs 20 | //= require_tree ./admin -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | require 'rails/all' 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | module RorPlus 10 | class Application < Rails::Application 11 | # Initialize configuration defaults for originally generated Rails version. 12 | config.load_defaults 5.2 13 | config.autoload_paths += %W[#{config.root}/lib] 14 | 15 | # Settings in config/environments/* take precedence over those specified here. 16 | # Application configuration can go into files in config/initializers 17 | # -- all .rb files in that directory are automatically loaded after loading 18 | # the framework and any gems in your application. 19 | config.before_initialize do 20 | $secret = eval("Rails.application.credentials.#{Rails.env}") 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a way to update your development environment automatically. 14 | # Add necessary update steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies if using Yarn 21 | # system('bin/yarn') 22 | 23 | puts "\n== Updating database ==" 24 | system! 'bin/rails db:migrate' 25 | 26 | puts "\n== Removing old logs and tempfiles ==" 27 | system! 'bin/rails log:clear tmp:clear' 28 | 29 | puts "\n== Restarting application server ==" 30 | system! 'bin/rails restart' 31 | end 32 | -------------------------------------------------------------------------------- /app/helpers/flash_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module FlashHelper 4 | ALERT_TYPES = %i[danger info success warning error].freeze unless const_defined?(:ALERT_TYPES) 5 | 6 | def bootstrap_flash 7 | flash_messages = [] 8 | flash.each do |type, message| 9 | # Skip empty messages, e.g. for devise messages set to nothing in a locale file. 10 | next if message.blank? 11 | 12 | type = type.to_sym 13 | type = :success if type == :notice 14 | type = :danger if %i[alert error].include?(type) 15 | next unless ALERT_TYPES.include?(type) 16 | 17 | Array(message).each do |msg| 18 | text = content_tag( 19 | :div, 20 | content_tag(:button, raw('×'), :class => 'close', 'data-dismiss' => 'alert') + 21 | msg.html_safe, class: "alert alert-#{type}" 22 | ) 23 | flash_messages << text if msg 24 | end 25 | end 26 | flash_messages.join("\n").html_safe 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /app/controllers/admin/admins_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Admin::AdminsController < Admin::BaseController 4 | before_action :set_admin 5 | 6 | def change_password; end 7 | 8 | def update_password 9 | if @admin.update_with_password(admin_params) 10 | flash[:notice] = 'Password successfully updated!' 11 | sign_in @admin, bypass: true 12 | redirect_to admin_dashboard_index_path 13 | else 14 | Rails.logger.debug("===========#{@admin.errors.full_messages.join(', ')}===========") 15 | flash[:error] = @admin.errors.full_messages.join(', ') 16 | redirect_back fallback_location: { action: 'change_password', id: @admin.id } 17 | end 18 | end 19 | 20 | private 21 | 22 | def admin_params 23 | params.require(:admin).permit(:current_password, :password, :password_confirmation) 24 | end 25 | 26 | def set_admin 27 | @admin = Admin.find_by_id(params[:admin_id]) 28 | return false if @admin.blank? 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /app/controllers/api/v1/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API 4 | module V1 5 | class Base < API::Base 6 | formatter :json, Grape::Formatter::Jbuilder 7 | helpers API::V1::Helpers::AuthenticationHelpers 8 | 9 | rescue_from ActiveRecord::RecordNotFound do 10 | error!('Record not found.', 404) 11 | end 12 | 13 | rescue_from ActiveRecord::InvalidForeignKey do 14 | error!('Unprocessable entity.', 422) 15 | end 16 | 17 | rescue_from ArgumentError do |e| 18 | error!(e.message.remove("'"), 422) 19 | end 20 | 21 | before do 22 | error!('Unauthorized request.', 401) unless authorized 23 | end 24 | 25 | helpers do 26 | def authorized 27 | authorization_key = Base64.strict_decode64(request.headers['Authorization']) rescue nil 28 | authorization_key == "#{$secret[:api_client_id]}:#{$secret[:api_client_secret]}" 29 | end 30 | end 31 | 32 | version 'v1' 33 | 34 | mount API::V1::Users 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /app/controllers/api/v2/base.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API 4 | module V2 5 | class Base < API::Base 6 | formatter :json, Grape::Formatter::Jbuilder 7 | helpers API::V1::Helpers::AuthenticationHelpers 8 | 9 | rescue_from ActiveRecord::RecordNotFound do 10 | error!('Record not found.', 404) 11 | end 12 | 13 | rescue_from ActiveRecord::InvalidForeignKey do 14 | error!('Unprocessable entity.', 422) 15 | end 16 | 17 | rescue_from ArgumentError do |e| 18 | error!(e.message.remove("'"), 422) 19 | end 20 | 21 | before do 22 | error!('Unauthorized request.', 401) unless authorized 23 | end 24 | 25 | helpers do 26 | def authorized 27 | authorization_key = Base64.strict_decode64(request.headers['Authorization']) rescue nil 28 | authorization_key == "#{$secret[:api_client_id]}:#{$secret[:api_client_secret]}" 29 | end 30 | end 31 | 32 | version 'v2' 33 | 34 | mount API::V2::Users 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /app/views/layouts/admin.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %meta{content: 'text/html; charset=UTF-8', 'http-equiv': 'Content-Type'} 5 | %meta{content: 'IE=edge', 'http-equiv': 'X-UA-Compatible'} 6 | %meta{content: 'width=device-width, initial-scale=1, shrink-to-fit=no', name: 'viewport'} 7 | = render 'layouts/meta_tags' 8 | = csrf_meta_tags 9 | = csp_meta_tag 10 | = stylesheet_link_tag 'admin', media: 'all', 'data-turbolinks-track': 'reload' 11 | = javascript_include_tag 'admin', 'data-turbolinks-track': 'reload' 12 | %link{href: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css', rel: 'stylesheet'} 13 | %script{src: 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js'} 14 | %script{async: '', src: 'https://cdn.ywxi.net/js/1.js', type: 'text/javascript'} 15 | %body.fixed-nav.sticky-footer.bg-dark#page-top 16 | = render 'layouts/admin/navigation' 17 | .content-wrapper 18 | .flash_messages_div 19 | = bootstrap_flash 20 | = yield 21 | = render 'layouts/admin/footer' 22 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a starting point to setup your application. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies if using Yarn 21 | # system('bin/yarn') 22 | 23 | # puts "\n== Copying sample files ==" 24 | # unless File.exist?('config/database.yml') 25 | # cp 'config/database.yml.sample', 'config/database.yml' 26 | # end 27 | 28 | puts "\n== Preparing database ==" 29 | system! 'bin/rails db:setup' 30 | 31 | puts "\n== Removing old logs and tempfiles ==" 32 | system! 'bin/rails log:clear tmp:clear' 33 | 34 | puts "\n== Restarting application server ==" 35 | system! 'bin/rails restart' 36 | end 37 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at http://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | admin: 35 | navigation: 36 | logout_title: "Ready to Leave?" 37 | logout_message: "Select 'Logout' below if you are ready to end your current session." 38 | -------------------------------------------------------------------------------- /app/views/admin/sessions/new.html.haml: -------------------------------------------------------------------------------- 1 | %body.bg-dark 2 | .container 3 | .card.card-login.mx-auto.mt-3 4 | .card-header Login 5 | .card-body 6 | = form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| 7 | .form-group 8 | = f.label :email, 'Email address', for: 'exampleInputEmail1' 9 | = f.email_field :email, autofocus: true, autocomplete: 'email', class: 'form-control', id: 'exampleInputEmail1', 'aria-describedby': 'emailHelp', placeholder: 'Enter email' 10 | .form-group 11 | = f.label :password, for: 'exampleInputPassword1' 12 | = f.password_field :password, autocomplete: 'off', id: 'exampleInputPassword1', placeholder: 'Password', class: 'form-control' 13 | - if devise_mapping.rememberable? 14 | .form-group 15 | .form-check 16 | = f.check_box :remember_me, class: 'form-check-input' 17 | = f.label :remember_me, 'Remember Password', class: 'form-check-label' 18 | .actions 19 | = f.submit 'Log in', class: 'btn btn-primary btn-block' 20 | :javascript 21 | $(".alert" ).fadeOut(5000); 22 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | 19 | # If you are using UJS then enable automatic nonce generation 20 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 21 | 22 | # Report CSP violations to a specified URI 23 | # For further information see the following documentation: 24 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 25 | # Rails.application.config.content_security_policy_report_only = true 26 | -------------------------------------------------------------------------------- /app/views/admin/admins/change_password.html.haml: -------------------------------------------------------------------------------- 1 | = form_for @admin, url: admin_admin_update_password_path(@admin.id), html: {class: 'center reset-password-form'} do |f| 2 | .container.user_details 3 | %h3= 'Change Password' 4 | .card 5 | .card-body 6 | .row 7 | .col-md-12 8 | .form-group 9 | %label.pull-left.col-md-4 10 | Current Password 11 | = f.password_field :current_password, class: 'form-control col-md-4' 12 | .field-error.server-validation 13 | = show_error(f.object, :password) 14 | .form-group 15 | %label.pull-left.col-md-4 16 | New Password 17 | = f.password_field :password, class: 'form-control col-md-4' 18 | .field-error.server-validation 19 | = show_error(f.object, :new_password) 20 | .form-group 21 | %label.pull-left.col-md-4 22 | Password Confirmation 23 | = f.password_field :password_confirmation, class: 'form-control col-md-4' 24 | %center 25 | .form-group 26 | .actions 27 | = f.submit 'Save', class: 'btn btn-primary' 28 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | threads_count = ENV.fetch('RAILS_MAX_THREADS') { 5 } 2 | threads threads_count, threads_count 3 | 4 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 5 | port ENV.fetch('PORT') { 3000 } 6 | 7 | # Specifies the `environment` that Puma will run in. 8 | environment ENV.fetch('RAILS_ENV') { 'development' } 9 | 10 | unless ENV.fetch('RAILS_ENV') == 'development' 11 | workers 2 12 | app_dir = File.expand_path('../..', __FILE__) 13 | 14 | daemonize true 15 | shared_dir = "#{app_dir}/shared/" 16 | 17 | # Set up socket location 18 | bind "unix://#{shared_dir}tmp/sockets/puma.sock" 19 | 20 | # Logging 21 | stdout_redirect "#{shared_dir}log/puma.stdout.log", "#{shared_dir}log/puma.stderr.log", true 22 | 23 | # Set master PID and state locations 24 | pidfile "#{shared_dir}tmp/pids/puma.pid" 25 | state_path "#{shared_dir}tmp/pids/puma.state" 26 | 27 | activate_control_app 28 | end 29 | 30 | # Allow puma to be restarted by `rails restart` command. 31 | plugin :tmp_restart 32 | 33 | unless ENV.fetch('RAILS_ENV') == 'development' 34 | on_worker_boot do 35 | require 'active_record' 36 | ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished 37 | ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[ENV.fetch('RAILS_ENV')]) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /app/controllers/api/defaults.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module API 4 | module Defaults 5 | extend ActiveSupport::Concern 6 | 7 | included do 8 | helpers do 9 | def authenticate! 10 | begin 11 | JWT.decode(params[:user][:access_token], $secret[:api_hmac_secret], true, { :algorithm => 'HS256' }) 12 | @access_token = AccessToken.where(token: params[:user][:access_token]).first 13 | if @access_token.present? 14 | @current_user = @access_token.user 15 | else 16 | respond_error(401, 'Invalid session.') 17 | end 18 | rescue JWT::ExpiredSignature 19 | access_token = AccessToken.where(token: params[:user][:access_token]).first 20 | access_token.destroy if access_token.present? 21 | respond_error(401, 'Session expired.') 22 | rescue 23 | respond_error(401, 'Invalid session.') 24 | end 25 | end 26 | 27 | def error_message(object) 28 | object.errors.full_messages.uniq.join(",") 29 | end 30 | 31 | def respond(code = nil, data = nil) 32 | status code if code 33 | body data if data 34 | end 35 | 36 | def respond_error(code = nil, message = '') 37 | error!(message, code) 38 | end 39 | end 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /db/migrate/20190218131410_devise_create_admins.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DeviseCreateAdmins < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :admins do |t| 6 | ## Database authenticatable 7 | t.string :email, null: false, default: "" 8 | t.string :encrypted_password, null: false, default: "" 9 | 10 | ## Recoverable 11 | t.string :reset_password_token 12 | t.datetime :reset_password_sent_at 13 | 14 | ## Rememberable 15 | t.datetime :remember_created_at 16 | 17 | ## Trackable 18 | t.integer :sign_in_count, default: 0, null: false 19 | t.datetime :current_sign_in_at 20 | t.datetime :last_sign_in_at 21 | t.inet :current_sign_in_ip 22 | t.inet :last_sign_in_ip 23 | 24 | ## Confirmable 25 | # t.string :confirmation_token 26 | # t.datetime :confirmed_at 27 | # t.datetime :confirmation_sent_at 28 | # t.string :unconfirmed_email # Only if using reconfirmable 29 | 30 | ## Lockable 31 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 32 | # t.string :unlock_token # Only if unlock strategy is :email or :both 33 | # t.datetime :locked_at 34 | 35 | 36 | t.timestamps null: false 37 | end 38 | 39 | add_index :admins, :email, unique: true 40 | add_index :admins, :reset_password_token, unique: true 41 | # add_index :admins, :confirmation_token, unique: true 42 | # add_index :admins, :unlock_token, unique: true 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /db/migrate/20180424071905_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DeviseCreateUsers < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :users do |t| 6 | ## Database authenticatable 7 | t.string :email, null: false, default: "" 8 | t.string :encrypted_password, null: false, default: "" 9 | 10 | ## Recoverable 11 | t.string :reset_password_token 12 | t.datetime :reset_password_sent_at 13 | 14 | ## Rememberable 15 | t.datetime :remember_created_at 16 | 17 | ## Trackable 18 | t.integer :sign_in_count, default: 0, null: false 19 | t.datetime :current_sign_in_at 20 | t.datetime :last_sign_in_at 21 | t.inet :current_sign_in_ip 22 | t.inet :last_sign_in_ip 23 | 24 | ## Confirmable 25 | # t.string :confirmation_token 26 | # t.datetime :confirmed_at 27 | # t.datetime :confirmation_sent_at 28 | # t.string :unconfirmed_email # Only if using reconfirmable 29 | 30 | ## Lockable 31 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 32 | # t.string :unlock_token # Only if unlock strategy is :email or :both 33 | # t.datetime :locked_at 34 | 35 | t.string :first_name 36 | t.string :last_name 37 | 38 | 39 | t.timestamps null: false 40 | end 41 | 42 | add_index :users, :email, unique: true 43 | add_index :users, :reset_password_token, unique: true 44 | # add_index :users, :confirmation_token, unique: true 45 | # add_index :users, :unlock_token, unique: true 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |If you are the application owner check the logs for more information.
63 |Maybe you tried to change something you didn't have access to.
62 |If you are the application owner check the logs for more information.
64 |You may have mistyped the address or the page may have moved.
62 |If you are the application owner check the logs for more information.
64 |