Newer
Older
Thesis_System / app.rb
@Fumichan Fumichan on 13 Nov 2019 5 KB First Commit
require 'bundler/setup'
Bundler.require
require 'sinatra/reloader' #if development?
require 'sinatra-websocket'
require 'active_support'
require 'active_support/core_ext'
require 'active_support/all'
require 'sqlite3'
require 'active_record'
require 'json'
require 'bcrypt'
require 'openssl'
require 'logger'
require 'rotp'
require 'rqrcode'
require 'rqrcode_png'
require 'chunky_png'
require_relative 'models/user'
require_relative 'models/authorization'
require_relative 'models/tweet'

set :sessions,
  secret: 'sessions_secret_key'

logger = Logger.new(STDOUT)

#メインページ
get '/' do
  #ログインOK
  if session[:current_user_id]
    user=User.user_check(session[:current_user_id])
    if user
      @active_home="active"
      @username=user.name
      @lastlogin=user.updated_datetime
      erb :index
    else
      redirect '/logout'
    end
  #2要素認証のみ未認証
  elsif session[:user_id]
    #該当するユーザのチェック
    @active_login="active"
    user=User.user_check(session[:user_id])
    #2要素認証用トークン登録済み
    if user && user.rotp_key.present?
      erb :confirm_otp
    #2要素認証用トークン未登録の場合は登録してもらう
    elsif user && user.rotp_key.blank?
      session[:rotp_key]=User.generate_rotp_key
      logger.debug(session[:rotp_key])
      @qr_base64=User.make_qrcode(user.email, session[:rotp_key])
      @account=user.email
      @rotp_key=session[:rotp_key]
      erb :generate_rotp_key
    #そもそもユーザいなかったらセッションをクリアする
    else
      redirect '/logout'
    end
  #ログインNG
  else
    redirect '/login'
  end
end

get '/tweet' do
  #ログインOK
  if session[:current_user_id]
    user=User.user_check(session[:current_user_id])
    authorization=Authorization.confirm_authorized(session[:current_user_id], "Twitter")
    logger.debug(authorization)
    if user && authorization
      @active_home="active"
      @username=user.name
      erb :tweet
    elsif user
      erb :error
    else
      redirect '/logout'
    end
  else
    redirect '/login'
  end
end

#サインアップ(新規登録)
get '/signup' do
  logger.debug(session[:user_id])
  #条件式判定のため、未定義ならnilを代入
  session[:current_user_id] ||= nil
  #ログインされてるならセッションクリアしてもらう
  if session[:current_user_id].present?
    redirect '/logout'
  end
  @active_signup="active"
  erb :signup
end

#ログインページ
get '/login' do
  #認証済みならメインページへ
  if session[:current_user_id]
    redirect '/'
  end
  @active_login="active"
  erb :login
end



#user作成
post '/create' do
  #登録パスワードが不一致したら登録しなおし
  if params[:password] != params[:confirm_password]
    redirect '/signup'
  end
  #Userクラスより新規データを追加しインスタンス作成
  user = User.new(email: params[:email], name: params[:name], created_datetime: Time.now, updated_datetime: Time.now)
  #bcryptでパスワードをハッシュ値にしてデータ追加
  user.encrypt_password(params[:password])
  #正常にデータベースに登録できれば、セッションにidを入れて2要素認証の登録へ
  if user.save!
    session[:user_id] = user.id
  end
  redirect "/"
end

#rotp_keyを生成する
post '/generate_rotp_key' do
  #rotp_keyが登録されたトークンと同じものかを確認
  rotp_at = User.confirm_generated_rotp_key(session[:rotp_key], params[:otp])
  #同じものだと確認できたらusersテーブルのrotp_keyに登録し、ログイン成功のセッション情報を入れる
  if rotp_at
    User.update(session[:user_id], rotp_key: session[:rotp_key])
    session[:current_user_id] = session[:user_id]
  end
  #念の為、登録したrotp_keyのセッション情報は削除
  session[:rotp_key]=nil
  redirect '/'
end

#ログインID・パスワードチェック
post '/check' do
  #もしログイン認証済みならメインページへリダイレクト
  if session[:current_user_id]
    {login: "already"}.to_json
  #Ajaxでemailが送られてきた場合(第1段階)
  elsif params[:email]
    #次の処理のためにemailをsessionに入れておく
    session[:email] = params[:email]
    #サーバ側でsaltを生成
    session[:salt] = BCrypt::Engine.generate_salt
    logger.debug(session[:salt])
    #usersテーブルのpassword_saltとサーバ側で生成したsaltをクライアント側に送る
    salts=User.send_salt(params[:email], session[:salt])
  #Ajaxでハッシュ化したpasswordとクライアント側で生成したsaltが送られてきた場合(第2段階)
  elsif params[:password] && params[:salt]
    logger.debug(params[:password])
    logger.debug(params[:salt])
    #ログイン認証
    user = User.authenticate(session[:email], params[:password], session[:salt], params[:salt])
    logger.debug(user)
    #認証OKなら2段階認証するために一旦セッションにidを格納しておく
    if user
      session[:user_id] = user.id
      redirect '/'
    #認証NGならログインしなおし
    else
      {login: "error"}.to_json
      redirect '/'
    end
  end
end

#rotp_keyを生成する
post '/confirm_otp' do
  #ワンタイムパスワード認証
  user = User.confirm_otp(session[:user_id], params[:otp])
  #ワンタイムパスワードで認証できたらログイン成功のセッション情報を入れる
  Time.zone = 'Tokyo'
  if user
    User.update(user.id, updated_datetime: Time.now)
    session[:current_user_id] = user.id
  end
  #念の為、登録したrotp_keyのセッション情報は削除
  session[:rotp_key]=nil
  session[:user_id]=nil
  redirect '/'
end

#ログアウト
get '/logout' do
  session[:current_user_id] = nil
  session[:user_id] = nil
  erb :logout
end

#ログアウト
delete '/session' do
  session[:current_user_id] = nil
  session[:user_id] = nil
  redirect '/login'
end

post '/send_tweet' do
  Tweet.new.comment_tweet(params[:comment])
  erb :tweet_successful
end