mirror of
https://github.com/System-End/stickers.git
synced 2026-04-19 20:55:13 +00:00
first pass at backend!
This commit is contained in:
commit
3665af1041
12 changed files with 389 additions and 0 deletions
1
backend/.gitignore
vendored
Normal file
1
backend/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
.env
|
||||
23
backend/Gemfile
Normal file
23
backend/Gemfile
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# gem "rails"
|
||||
|
||||
gem 'grape'
|
||||
|
||||
gem 'airctiverecord', '~> 0.2.1'
|
||||
|
||||
gem 'dotenv', '~> 3.2'
|
||||
|
||||
gem 'zeitwerk', '~> 2.6'
|
||||
|
||||
gem 'rackup'
|
||||
|
||||
gem 'puma', '~> 7.1'
|
||||
|
||||
gem 'rack', '~> 3.2'
|
||||
|
||||
gem 'omniauth'
|
||||
gem 'omniauth_openid_connect'
|
||||
gem 'rack-session'
|
||||
196
backend/Gemfile.lock
Normal file
196
backend/Gemfile.lock
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel (8.1.1)
|
||||
activesupport (= 8.1.1)
|
||||
activesupport (8.1.1)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
json
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
uri (>= 0.13.1)
|
||||
aes_key_wrap (1.1.0)
|
||||
airctiverecord (0.2.1)
|
||||
activemodel (>= 6.0)
|
||||
activesupport (>= 6.0)
|
||||
airrel (>= 0.2.0)
|
||||
norairrecord (~> 0.5)
|
||||
airrel (0.2.1)
|
||||
norairrecord (>= 0.1.0)
|
||||
attr_required (1.0.2)
|
||||
base64 (0.3.0)
|
||||
bigdecimal (3.3.1)
|
||||
bindata (2.5.1)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.5)
|
||||
date (3.5.0)
|
||||
dotenv (3.2.0)
|
||||
drb (2.2.3)
|
||||
dry-configurable (1.3.0)
|
||||
dry-core (~> 1.1)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-core (1.1.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
logger
|
||||
zeitwerk (~> 2.6)
|
||||
dry-inflector (1.2.0)
|
||||
dry-logic (1.6.0)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.1)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-types (1.8.3)
|
||||
bigdecimal (~> 3.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.0)
|
||||
dry-inflector (~> 1.0)
|
||||
dry-logic (~> 1.4)
|
||||
zeitwerk (~> 2.6)
|
||||
email_validator (2.2.4)
|
||||
activemodel
|
||||
faraday (2.14.0)
|
||||
faraday-net_http (>= 2.0, < 3.5)
|
||||
json
|
||||
logger
|
||||
faraday-follow_redirects (0.4.0)
|
||||
faraday (>= 1, < 3)
|
||||
faraday-net_http (3.4.2)
|
||||
net-http (~> 0.5)
|
||||
faraday-net_http_persistent (2.3.1)
|
||||
faraday (~> 2.5)
|
||||
net-http-persistent (>= 4.0.4, < 5)
|
||||
grape (3.0.1)
|
||||
activesupport (>= 7.0)
|
||||
dry-configurable
|
||||
dry-types (>= 1.1)
|
||||
mustermann-grape (~> 1.1.0)
|
||||
rack (>= 2)
|
||||
zeitwerk
|
||||
hashie (5.0.0)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.17.1)
|
||||
json-jwt (1.17.0)
|
||||
activesupport (>= 4.2)
|
||||
aes_key_wrap
|
||||
base64
|
||||
bindata
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
logger (1.7.0)
|
||||
mail (2.9.0)
|
||||
logger
|
||||
mini_mime (>= 0.1.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.26.2)
|
||||
mustermann (3.0.4)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
mustermann-grape (1.1.0)
|
||||
mustermann (>= 1.0.0)
|
||||
net-http (0.8.0)
|
||||
uri (>= 0.11.1)
|
||||
net-http-persistent (4.0.6)
|
||||
connection_pool (~> 2.2, >= 2.2.4)
|
||||
net-imap (0.5.12)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
net-protocol
|
||||
net-protocol (0.2.2)
|
||||
timeout
|
||||
net-smtp (0.5.1)
|
||||
net-protocol
|
||||
nio4r (2.7.5)
|
||||
norairrecord (0.5.1)
|
||||
faraday (>= 1.0, < 3.0)
|
||||
faraday-net_http_persistent
|
||||
net-http-persistent
|
||||
omniauth (2.1.4)
|
||||
hashie (>= 3.4.6)
|
||||
logger
|
||||
rack (>= 2.2.3)
|
||||
rack-protection
|
||||
omniauth_openid_connect (0.8.0)
|
||||
omniauth (>= 1.9, < 3)
|
||||
openid_connect (~> 2.2)
|
||||
openid_connect (2.3.1)
|
||||
activemodel
|
||||
attr_required (>= 1.0.0)
|
||||
email_validator
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
json-jwt (>= 1.16)
|
||||
mail
|
||||
rack-oauth2 (~> 2.2)
|
||||
swd (~> 2.0)
|
||||
tzinfo
|
||||
validate_url
|
||||
webfinger (~> 2.0)
|
||||
public_suffix (7.0.0)
|
||||
puma (7.1.0)
|
||||
nio4r (~> 2.0)
|
||||
rack (3.2.4)
|
||||
rack-oauth2 (2.3.0)
|
||||
activesupport
|
||||
attr_required
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
json-jwt (>= 1.11.0)
|
||||
rack (>= 2.1.0)
|
||||
rack-protection (4.2.1)
|
||||
base64 (>= 0.1.0)
|
||||
logger (>= 1.6.0)
|
||||
rack (>= 3.0.0, < 4)
|
||||
rack-session (2.1.1)
|
||||
base64 (>= 0.1.0)
|
||||
rack (>= 3.0.0)
|
||||
rackup (2.3.1)
|
||||
rack (>= 3)
|
||||
ruby2_keywords (0.0.5)
|
||||
securerandom (0.4.1)
|
||||
swd (2.0.3)
|
||||
activesupport (>= 3)
|
||||
attr_required (>= 0.0.5)
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
timeout (0.4.4)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
uri (1.1.1)
|
||||
validate_url (1.0.15)
|
||||
activemodel (>= 3.0.0)
|
||||
public_suffix
|
||||
webfinger (2.1.3)
|
||||
activesupport
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
zeitwerk (2.7.3)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-24
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
airctiverecord (~> 0.2.1)
|
||||
dotenv (~> 3.2)
|
||||
grape
|
||||
omniauth
|
||||
omniauth_openid_connect
|
||||
puma (~> 7.1)
|
||||
rack (~> 3.2)
|
||||
rack-session
|
||||
rackup
|
||||
zeitwerk (~> 2.6)
|
||||
|
||||
BUNDLED WITH
|
||||
2.7.2
|
||||
8
backend/api/app.rb
Normal file
8
backend/api/app.rb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class App < Grape::API
|
||||
format :json
|
||||
|
||||
mount Auth
|
||||
mount Stickers
|
||||
end
|
||||
32
backend/api/auth.rb
Normal file
32
backend/api/auth.rb
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Auth < Grape::API
|
||||
format :json
|
||||
helpers SessionHelpers
|
||||
|
||||
namespace :auth do
|
||||
get :login do
|
||||
redirect '/auth/oidc'
|
||||
end
|
||||
|
||||
get 'oidc/callback' do
|
||||
auth = env['omniauth.auth']
|
||||
session[:user] = {
|
||||
id: auth.uid,
|
||||
email: auth.info.email,
|
||||
name: auth.info.name
|
||||
}
|
||||
redirect ENV.fetch('AUTH_SUCCESS_REDIRECT', '/')
|
||||
end
|
||||
|
||||
get :logout do
|
||||
session.clear
|
||||
redirect ENV.fetch('AUTH_LOGOUT_REDIRECT', '/')
|
||||
end
|
||||
|
||||
get :me do
|
||||
error!('Unauthorized', 401) unless current_user
|
||||
current_user
|
||||
end
|
||||
end
|
||||
end
|
||||
6
backend/api/base.rb
Normal file
6
backend/api/base.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Base < Grape::API
|
||||
format :json
|
||||
helpers SessionHelpers
|
||||
end
|
||||
15
backend/api/session_helpers.rb
Normal file
15
backend/api/session_helpers.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module SessionHelpers
|
||||
def session
|
||||
env['rack.session']
|
||||
end
|
||||
|
||||
def current_user
|
||||
session[:user]
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
error!('Unauthorized', 401) unless current_user
|
||||
end
|
||||
end
|
||||
25
backend/api/stickers.rb
Normal file
25
backend/api/stickers.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Stickers < Base
|
||||
helpers SessionHelpers
|
||||
|
||||
resource :stickers do
|
||||
get do
|
||||
Sticker.only_active.all.map(&:as_json) + [current_user: current_user]
|
||||
end
|
||||
|
||||
before do
|
||||
@sticker = Sticker.only_active.where(autonumber: params[:id]).first || error!('not found', 404)
|
||||
end
|
||||
|
||||
route_param :id, type: String do
|
||||
before { authenticate! }
|
||||
get do
|
||||
@sticker.as_json
|
||||
end
|
||||
get '/backwards' do
|
||||
@sticker.name.reverse
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
25
backend/boot.rb
Normal file
25
backend/boot.rb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'bundler/setup'
|
||||
|
||||
require 'dotenv'
|
||||
require 'zeitwerk'
|
||||
require 'airctiverecord'
|
||||
require 'grape'
|
||||
|
||||
Dotenv.load
|
||||
|
||||
Norairrecord.api_key = ENV['AIRTABLE_PAT']
|
||||
|
||||
loader = Zeitwerk::Loader.new
|
||||
loader.push_dir("#{__dir__}/models")
|
||||
loader.push_dir("#{__dir__}/api")
|
||||
loader.enable_reloading
|
||||
loader.setup
|
||||
loader.eager_load
|
||||
|
||||
def reload!
|
||||
loader.reload
|
||||
end
|
||||
|
||||
LOADER = loader
|
||||
38
backend/config.ru
Normal file
38
backend/config.ru
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dotenv'
|
||||
Dotenv.load
|
||||
|
||||
require_relative 'boot'
|
||||
require 'grape'
|
||||
require 'rack/session'
|
||||
require 'omniauth'
|
||||
require 'omniauth_openid_connect'
|
||||
|
||||
use Rack::Session::Cookie,
|
||||
key: 'stickers.session',
|
||||
secret: ENV.fetch('SESSION_SECRET'),
|
||||
same_site: :lax,
|
||||
expire_after: 86_400 * 7
|
||||
|
||||
OmniAuth.config.allowed_request_methods = %i[get post]
|
||||
|
||||
use OmniAuth::Builder do
|
||||
provider :openid_connect,
|
||||
name: :oidc,
|
||||
issuer: ENV.fetch('OIDC_ISSUER'),
|
||||
discovery: true,
|
||||
client_options: {
|
||||
identifier: ENV.fetch('OIDC_CLIENT_ID'),
|
||||
secret: ENV.fetch('OIDC_CLIENT_SECRET'),
|
||||
redirect_uri: ENV.fetch('OIDC_REDIRECT_URI'),
|
||||
host: 'auth.hackclub.com',
|
||||
scheme: 'https'
|
||||
},
|
||||
scope: %i[openid email profile name address]
|
||||
end
|
||||
|
||||
run lambda { |env|
|
||||
LOADER.reload
|
||||
App.call(env)
|
||||
}
|
||||
3
backend/models/application_record.rb
Normal file
3
backend/models/application_record.rb
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
class ApplicationRecord < AirctiveRecord::Base
|
||||
self.base_key = ENV['AIRTABLE_BASE']
|
||||
end
|
||||
17
backend/models/sticker.rb
Normal file
17
backend/models/sticker.rb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class Sticker < ApplicationRecord
|
||||
self.table_name = "tbl9kLyUrZNCJWf3L"
|
||||
|
||||
field :name, "Name"
|
||||
field :active, "active"
|
||||
field :autonumber, "id"
|
||||
field :image_attachment, "image"
|
||||
|
||||
scope :only_active, -> { where(active: true) }
|
||||
|
||||
def as_json(options = nil)
|
||||
{ id: autonumber, name: name, image: }
|
||||
end
|
||||
|
||||
def image = image_attachment&.dig(0, "url")
|
||||
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue