Websites/app/controllers/yiff_rest/apikeys_controller.rb
2024-05-02 22:04:43 -05:00

157 lines
5.9 KiB
Ruby

# frozen_string_literal: true
module YiffRest
class ApikeysController < ApplicationController
include ::ApplicationController::ReadonlyMethods
before_action :validate_discord, except: %i[logout]
before_action :handle_ratelimit, except: %i[index logout]
before_action :prepare_user, except: %i[logout]
before_action :load_apikey, except: %i[index new create logout]
before_action :manager_only, only: %i[disable]
before_action :admin_only, only: %i[edit]
before_action :check_can_create_apikeys, only: %i[new create]
before_action -> { check_apikey_access(:can_edit?) }, only: %i[update]
before_action -> { check_apikey_access(:can_delete?) }, only: %i[destroy]
before_action -> { check_apikey_access(:can_disable?) }, only: %i[disable enable]
before_action -> { check_apikey_access(:can_deactivate?) }, only: %i[deactivate reactivate]
before_action -> { check_apikey_access(:can_regenerate?) }, only: %i[regenerate]
protect_from_forgery with: :exception
def index
@apikeys = APIKey.all
@apikeys = @apikeys.where(owner_id: CurrentUser.id) unless CurrentUser.is_manager?
@apikeys = @apikeys.search(search_params)
end
def new
@apikey = APIKey.new(owner_id: CurrentUser.id)
end
def edit
end
def create
allowed_params = apikey_params
allowed_params[:owner_id] ||= CurrentUser.id
apiuser = APIUser.find_by(id: allowed_params[:owner_id])
APIUser.create!(id: allowed_params[:owner_id], name: "User#{allowed_params[:owner_id]}") if apiuser.nil?
@apikey = APIKey.create(allowed_params)
if @apikey.errors.any?
redirect_back(fallback_location: new_yiff_rest_apikey_path, notice: @apikey.errors.full_messages.join("; "))
else
redirect_to(yiff_rest_apikeys_path, notice: "API Key created. You can view the documentation via the link in the top bar. Click \"View\" to see your apikey.")
end
end
def update
@apikey.update(apikey_params)
return redirect_back(fallback_location: edit_yiff_rest_apikey_path(@apikey), notice: @apikey.errors.full_messages.join("; ")) if @apikey.errors.any?
redirect_to(yiff_rest_apikeys_path, notice: "API Key Updated.")
end
def destroy
@apikey.destroy
redirect_back(fallback_location: yiff_rest_apikeys_path)
end
def disable
@apikey.update(disabled: true, disabled_reason: disable_params[:disabled_reason])
redirect_back(fallback_location: yiff_rest_apikeys_path, notice: @apikey.errors.any? ? @apikey.errors.full_messages : "API Key disabled.")
end
def enable
@apikey.update(disabled: false, disabled_reason: nil)
redirect_back(fallback_location: yiff_rest_apikeys_path, notice: @apikey.errors.any? ? @apikey.errors.full_messages : "API Key enabled.")
end
def deactivate
@apikey.update(active: false)
redirect_back(fallback_location: yiff_rest_apikeys_path, notice: @apikey.errors.any? ? @apikey.errors.full_messages : "API Key deactivated.")
end
def reactivate
@apikey.update(active: true)
redirect_back(fallback_location: yiff_rest_apikeys_path, notice: @apikey.errors.any? ? @apikey.errors.full_messages : "API Key reactivated.")
end
def regenerate
@apikey.regenerate!
redirect_back(fallback_location: yiff_rest_apikeys_path, notice: @apikey.errors.any? ? @apikey.errors.full_messages : "API Key regenerated.")
end
def logout
session.delete("discord_user")
CurrentUser.user = nil
redirect_to(yiff_rest_root_path, notice: "You have been logged out.")
end
private
def site_domain
YiffRestRoutes::DOMAIN
end
def site_title
"YiffyAPI - API Keys"
end
def assets_path
YiffMediaRoutes::DOMAIN
end
def validate_discord
redirect_to(Websites.config.yiffyapi_discord_redirect("apikey"), allow_other_host: true) if session[:discord_user].blank?
end
def apikey_params
permitted_params = %i[application_name usage]
permitted_params += %i[super unlimited bulk_limit limit_long limit_short window_long window_short flags_images flags_thumbs flags_shortener flags_images_bulk owner_id] if CurrentUser.is_admin?
params.require(:api_key).permit(permitted_params)
end
def disable_params
params.require(:api_key).permit(:disabled_reason)
end
def search_params
permitted_params = %i[]
permitted_params += %i[owner_id application_name usage active disabled disabled_reason] if CurrentUser.is_manager?
permit_search_params(permitted_params)
end
def handle_ratelimit
info, body, rlheaders = RateLimiter.process(request, ignore_auth: true)
headers.merge!(rlheaders)
return if info.nil?
# noinspection RubyCaseWithoutElseBlockInspection
case info
when :RATELIMIT_SHORT
render_error(YiffyAPIErrorCodes::RATELIMIT_ROUTE, error: "Request Limit Exceeded", info: body)
when :RATELIMIT_LONG
render_error(YiffyAPIErrorCodes::RATELIMIT_GLOBAL, error: "Request Limit Exceeded", info: body)
end
end
def prepare_user
name = session.dig("discord_user", "global_name") || "#{session.dig('discord_user', 'username')}#{@session.dig('discord_user', 'discriminator')}"
CurrentUser.user = APIUser.find_or_create_by(id: session.dig("discord_user", "id"))
CurrentUser.update!(name: name, discord_data: session["discord_user"])
CurrentUser.update_avatar(session.dig("discord_user", "avatar"))
end
def load_apikey
@apikey = APIKey.find(params[:id])
end
def check_apikey_access(method)
return if @apikey.nil?
access_denied(message: "You don't have access to that.") unless @apikey.send(method, CurrentUser)
end
def check_can_create_apikeys
return if CurrentUser.is_admin?
access_denied(message: "You already have the maximum amount of apikeys.") unless CurrentUser.can_create_apikey?
end
end
end