Compare commits
8 Commits
cca1aa4604
...
c66d4676e3
Author | SHA1 | Date | |
---|---|---|---|
c66d4676e3
|
|||
a93cab4de5
|
|||
b2e4fcbce1
|
|||
86ba2e6c1a
|
|||
3a78bf5d03
|
|||
fde1dd14b5
|
|||
a4955d35fa
|
|||
aa907dfa5f
|
@ -69,4 +69,4 @@ jobs:
|
|||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
tags: git.kill0.net/ryanc/kipunji:latest
|
tags: git.kill0.net/ryanc/kubernaut:latest
|
||||||
|
111
app.rb
111
app.rb
@ -13,9 +13,14 @@ require "anyflake"
|
|||||||
|
|
||||||
require "jwt"
|
require "jwt"
|
||||||
|
|
||||||
SESSION_SECRET_HEX_LENGTH = 64
|
$LOAD_PATH.unshift File.dirname(__FILE__) + "/lib"
|
||||||
|
|
||||||
set :session_secret, ENV.fetch("SESSION_SECRET") { SecureRandom.hex(SESSION_SECRET_HEX_LENGTH) }
|
require "config"
|
||||||
|
|
||||||
|
SESSION_SECRET_HEX_LENGTH = 64
|
||||||
|
JWT_SECRET_HEX_LENGTH = 64
|
||||||
|
|
||||||
|
ENV_PREFIX = "KUBERNAUT"
|
||||||
|
|
||||||
CLK_TCK = 100
|
CLK_TCK = 100
|
||||||
PID_FILE_PATH = "/run/app/pid".freeze
|
PID_FILE_PATH = "/run/app/pid".freeze
|
||||||
@ -38,7 +43,9 @@ DURATION_PARTS = [
|
|||||||
[1, "second", "s"]
|
[1, "second", "s"]
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
JWT_SECRET = SecureRandom.bytes(64).freeze
|
config = Config.new
|
||||||
|
|
||||||
|
set :session_secret, config.session_secret.unwrap
|
||||||
|
|
||||||
module Sinatra
|
module Sinatra
|
||||||
module RequestHeadersHelper
|
module RequestHeadersHelper
|
||||||
@ -209,12 +216,13 @@ before do
|
|||||||
end
|
end
|
||||||
|
|
||||||
helpers do
|
helpers do
|
||||||
def json(obj, opts: nil, pretty: false)
|
def jsonify(obj, opts: nil, pretty: false)
|
||||||
if pretty
|
buf = if pretty
|
||||||
JSON.pretty_generate obj, opts:
|
JSON.pretty_generate obj, opts:
|
||||||
else
|
else
|
||||||
JSON.generate(obj, opts:)
|
JSON.generate(obj, opts:)
|
||||||
end
|
end
|
||||||
|
"#{buf}\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
def protected! hidden = false
|
def protected! hidden = false
|
||||||
@ -244,14 +252,14 @@ end
|
|||||||
get "/env", provides: "json" do
|
get "/env", provides: "json" do
|
||||||
pretty = params.key? :pretty
|
pretty = params.key? :pretty
|
||||||
|
|
||||||
json ENV.sort.to_h, pretty:
|
jsonify ENV.sort.to_h, pretty:
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/headers", provides: "json" do
|
get "/headers", provides: "json" do
|
||||||
pretty = params.key? :pretty
|
pretty = params.key? :pretty
|
||||||
h = req_headers
|
h = req_headers
|
||||||
|
|
||||||
json h, pretty:
|
jsonify h, pretty:
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/livez" do
|
get "/livez" do
|
||||||
@ -266,7 +274,7 @@ get "/livez/uptime" do
|
|||||||
tt = TickTock.new
|
tt = TickTock.new
|
||||||
x = {started_at: tt.started_at, seconds: tt.uptime.to_i, human: human_time(tt.uptime.to_i)}
|
x = {started_at: tt.started_at, seconds: tt.uptime.to_i, human: human_time(tt.uptime.to_i)}
|
||||||
|
|
||||||
json x
|
jsonify x
|
||||||
end
|
end
|
||||||
|
|
||||||
post "/livez/toggle" do
|
post "/livez/toggle" do
|
||||||
@ -330,7 +338,7 @@ end
|
|||||||
get "/pid" do
|
get "/pid" do
|
||||||
pretty = params.key? :pretty
|
pretty = params.key? :pretty
|
||||||
|
|
||||||
json({puma: master_pid, pid: Process.pid}, pretty:)
|
jsonify({puma: master_pid, pid: Process.pid}, pretty:)
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/token" do
|
get "/token" do
|
||||||
@ -340,31 +348,37 @@ get "/token" do
|
|||||||
token = JWT.encode payload, JWT_SECRET, "HS256"
|
token = JWT.encode payload, JWT_SECRET, "HS256"
|
||||||
x = {token: token, expires_at: expires_at}
|
x = {token: token, expires_at: expires_at}
|
||||||
|
|
||||||
json x
|
jsonify x
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/token/validate" do
|
get "/token/validate" do
|
||||||
token = req_headers["authorization"].split[1]
|
token = req_headers["authorization"].split[1]
|
||||||
payload = JWT.decode token, JWT_SECRET, true, algorithm: "HS256"
|
payload = JWT.decode token, JWT_SECRET, true, algorithm: "HS256"
|
||||||
|
|
||||||
json payload
|
jsonify payload
|
||||||
end
|
end
|
||||||
|
|
||||||
post "/session" do
|
post "/session" do
|
||||||
session.merge! params
|
session.merge! params
|
||||||
|
|
||||||
json session.to_hash
|
jsonify session.to_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/session" do
|
get "/session" do
|
||||||
j = session.to_hash
|
j = session.to_hash
|
||||||
j[:hostname] = ENV["HOSTNAME"]
|
j[:hostname] = ENV["HOSTNAME"]
|
||||||
|
|
||||||
json j
|
jsonify j
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/cookies" do
|
get "/cookies" do
|
||||||
json response.headers
|
jsonify response.headers
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/config", provides: "json" do
|
||||||
|
pretty = params.key? :pretty
|
||||||
|
|
||||||
|
jsonify config.as_json, pretty:
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/_cat/headers" do
|
get "/_cat/headers" do
|
||||||
@ -391,6 +405,21 @@ get "/_cat/cookies" do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get "/_cat/config" do
|
||||||
|
stream do |out|
|
||||||
|
config.instance_variables.each do |k|
|
||||||
|
k = k.to_s.delete_prefix "@"
|
||||||
|
begin
|
||||||
|
v = config.send(k)
|
||||||
|
rescue NoMethodError
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
out << "#{k}(#{v.to_s.length})=#{v}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
route :delete, :get, :patch, :post, :put, "/status/:code" do
|
route :delete, :get, :patch, :post, :put, "/status/:code" do
|
||||||
# hello
|
# hello
|
||||||
code = Integer(params[:code])
|
code = Integer(params[:code])
|
||||||
@ -398,11 +427,14 @@ route :delete, :get, :patch, :post, :put, "/status/:code" do
|
|||||||
end
|
end
|
||||||
|
|
||||||
get "/chunked/:delay" do
|
get "/chunked/:delay" do
|
||||||
|
content_type "application/x-ndjson"
|
||||||
|
|
||||||
delay = Float(params[:delay])
|
delay = Float(params[:delay])
|
||||||
stream do |out|
|
stream do |out|
|
||||||
out << "Hello, world!\n"
|
30.times do |i|
|
||||||
|
out << jsonify({id: i, message: i % 2 == 0 ? "tick" : "tock"})
|
||||||
sleep delay
|
sleep delay
|
||||||
out << "Hello, world!\n"
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -415,5 +447,50 @@ route :delete, :get, :patch, :post, :put, "/auth/basic", provides: "json" do
|
|||||||
protected!
|
protected!
|
||||||
end
|
end
|
||||||
|
|
||||||
json({authenticated: true, user: @auth.username}, pretty:)
|
jsonify({authenticated: true, user: @auth.username}, pretty:)
|
||||||
|
end
|
||||||
|
|
||||||
|
def human_size_to_bytes(size)
|
||||||
|
units = %i[b kb mb gb tb pb eb zb yb rb qb]
|
||||||
|
|
||||||
|
number, unit = size.split(/(?<=\d)(?=[A-Za-z])/)
|
||||||
|
|
||||||
|
raise ArgumentError, "the unit is not recognized" if unit.nil?
|
||||||
|
|
||||||
|
number = Float(number)
|
||||||
|
unit = unit.downcase.to_sym
|
||||||
|
|
||||||
|
exponent = units.find_index(unit)
|
||||||
|
|
||||||
|
number *= (1024**exponent)
|
||||||
|
Integer(number.ceil)
|
||||||
|
end
|
||||||
|
|
||||||
|
MAX_DOWNLOAD_SIZE = "1GB"
|
||||||
|
|
||||||
|
get "/bytes/:size" do
|
||||||
|
size = params[:size]
|
||||||
|
n = [human_size_to_bytes(size), human_size_to_bytes(MAX_DOWNLOAD_SIZE)].min
|
||||||
|
|
||||||
|
headers["content-type"] = "application/octet-stream"
|
||||||
|
headers["content-length"] = n
|
||||||
|
|
||||||
|
headers["content-disposition"] = "attachment; filename=\"#{params[:f]}\"" if params.key? :f
|
||||||
|
|
||||||
|
def generate_bytes(number, byte = "\x00", block_size = 4096)
|
||||||
|
raise ArgumentError, "'byte' must be 1 byte" unless byte.b.length == 1
|
||||||
|
|
||||||
|
bytes_written = 0
|
||||||
|
block = byte * block_size
|
||||||
|
Enumerator.new do |g|
|
||||||
|
while bytes_written < number
|
||||||
|
remaining_bytes = number - bytes_written
|
||||||
|
bytes_to_write = [block_size, remaining_bytes].min
|
||||||
|
g.yield block[0, bytes_to_write]
|
||||||
|
bytes_written += bytes_to_write
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
generate_bytes(Integer(n))
|
||||||
end
|
end
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji-configmap
|
name: kubernaut-configmap
|
||||||
namespace: kipunji
|
namespace: kubernaut
|
||||||
data:
|
data:
|
||||||
KIPUNJI_CAT: kilwin
|
KUBERNAUT_CAT: kilwin
|
||||||
|
@ -2,22 +2,22 @@
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji
|
name: kubernaut
|
||||||
annotations:
|
annotations:
|
||||||
reloader.stakater.com/auto: "true"
|
reloader.stakater.com/auto: "true"
|
||||||
spec:
|
spec:
|
||||||
replicas: 5
|
replicas: 5
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: kipunji
|
app: kubernaut
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: kipunji
|
app: kubernaut
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: kipunji
|
- name: kubernaut
|
||||||
image: git.kill0.net/ryanc/kipunji:latest
|
image: git.kill0.net/ryanc/kubernaut:latest
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- name: sinatra-web
|
- name: sinatra-web
|
||||||
@ -26,12 +26,12 @@ spec:
|
|||||||
- name: SESSION_SECRET
|
- name: SESSION_SECRET
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: kipunji-session-secret
|
name: kubernaut-session-secret
|
||||||
key: session_secret
|
key: session_secret
|
||||||
optional: true
|
optional: true
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: kipunji-configmap
|
name: kubernaut-configmap
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /livez
|
path: /livez
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
namespace: kipunji
|
namespace: kubernaut
|
||||||
resources:
|
resources:
|
||||||
- secret.yaml
|
- secret.yaml
|
||||||
- configmap.yaml
|
- configmap.yaml
|
||||||
|
@ -3,13 +3,13 @@ apiVersion: bitnami.com/v1alpha1
|
|||||||
kind: SealedSecret
|
kind: SealedSecret
|
||||||
metadata:
|
metadata:
|
||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
name: kipunji-session-secret
|
name: kubernaut-session-secret
|
||||||
namespace: kipunji
|
namespace: kubernaut
|
||||||
spec:
|
spec:
|
||||||
encryptedData:
|
encryptedData:
|
||||||
session_secret: AgCY08t0AU418znEZt5d252J+lH+fwYki2g6jdJpfdRfVQjnA+b52P0KWrs/x5pB0PKab6Z3JY/Tz0SQCaoIsCR4IzUO3a095aulRqb6Qr1Lz8udBVta4JJMZLmo26tuUfVHlpD1d6J8rkBSm8vzckFLkOA1Wfl/9rS3K4qwiDogA5pI0ULghFkeEx1yKdRwPq0k8PuvOvLUJ6oNq3e5n+B/BrVWdQ+7XQxUq/AMANJrDbe+RD33f99LArHYA7bFMbY8YRazXSTAkeunpTlxTjuGZKYvJKupo29LHz2OVbZVX/hI0nZkdVpcgqvbxF6Vw9CuCeAmtKYl7A3qsAWqDLUdP3hRLsk2P9RDNhEzYWh4ml8APzziWzihdJbGEjwLy7HsHgKslM0XbBnRQDlxp/JtvcWdjQp33A+QOON32zOKHi+qJjDYyGebS1+xkPbnyb1MPSJVAtFpj7dlLbFekLFDZEbXuJYUl1wKdFOIjJHmNK/MTEV2kOhtiVj/aeKgSXwor9hR7Uxzs5ZSawp9uWw+hpr58EX6I+RtfO4yjFC6FjnagiU6SlI1Q2F7/nv82g1UWTYMpNN5bduS1YFWmsnXvK+W7YQHpSForr5ndtCSHmclbXb5Fc33sywC5u6Bi2Gu5/MW6d73BOog5BC3QtOuEQ044Q+cuU3RIlKADBqKLzZmHlmukyyGuZfXJnGjlWGKp3J1KecucTo6XC9QHpUkjXEKdlE63mOI1VuOGyBIHl60v4bnWiBg+aDZVHipz4JLKsVB0HOgBBK7+tOX6tr1GDG/F7Nz/i9ebzUV6i8Ec1jHf+2ZcTtBkNXBIkHc84+4Qd33/gOuP+lizLfIhfQ3DFWbwyfYumpVbeapyYhB0CE=
|
session_secret: AgCY08t0AU418znEZt5d252J+lH+fwYki2g6jdJpfdRfVQjnA+b52P0KWrs/x5pB0PKab6Z3JY/Tz0SQCaoIsCR4IzUO3a095aulRqb6Qr1Lz8udBVta4JJMZLmo26tuUfVHlpD1d6J8rkBSm8vzckFLkOA1Wfl/9rS3K4qwiDogA5pI0ULghFkeEx1yKdRwPq0k8PuvOvLUJ6oNq3e5n+B/BrVWdQ+7XQxUq/AMANJrDbe+RD33f99LArHYA7bFMbY8YRazXSTAkeunpTlxTjuGZKYvJKupo29LHz2OVbZVX/hI0nZkdVpcgqvbxF6Vw9CuCeAmtKYl7A3qsAWqDLUdP3hRLsk2P9RDNhEzYWh4ml8APzziWzihdJbGEjwLy7HsHgKslM0XbBnRQDlxp/JtvcWdjQp33A+QOON32zOKHi+qJjDYyGebS1+xkPbnyb1MPSJVAtFpj7dlLbFekLFDZEbXuJYUl1wKdFOIjJHmNK/MTEV2kOhtiVj/aeKgSXwor9hR7Uxzs5ZSawp9uWw+hpr58EX6I+RtfO4yjFC6FjnagiU6SlI1Q2F7/nv82g1UWTYMpNN5bduS1YFWmsnXvK+W7YQHpSForr5ndtCSHmclbXb5Fc33sywC5u6Bi2Gu5/MW6d73BOog5BC3QtOuEQ044Q+cuU3RIlKADBqKLzZmHlmukyyGuZfXJnGjlWGKp3J1KecucTo6XC9QHpUkjXEKdlE63mOI1VuOGyBIHl60v4bnWiBg+aDZVHipz4JLKsVB0HOgBBK7+tOX6tr1GDG/F7Nz/i9ebzUV6i8Ec1jHf+2ZcTtBkNXBIkHc84+4Qd33/gOuP+lizLfIhfQ3DFWbwyfYumpVbeapyYhB0CE=
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
creationTimestamp: null
|
creationTimestamp: null
|
||||||
name: kipunji-session-secret
|
name: kubernaut-session-secret
|
||||||
namespace: kipunji
|
namespace: kubernaut
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji
|
name: kubernaut
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- name: web
|
- name: web
|
||||||
port: 80
|
port: 80
|
||||||
targetPort: sinatra-web
|
targetPort: sinatra-web
|
||||||
selector:
|
selector:
|
||||||
app: kipunji
|
app: kubernaut
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji
|
name: kubernaut
|
||||||
namespace: kipunji
|
|
||||||
resources:
|
resources:
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- ./app
|
- ./app
|
||||||
|
@ -2,19 +2,19 @@
|
|||||||
kind: Deployment
|
kind: Deployment
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji-memcached
|
name: kubernaut-memcached
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: kipunji-memcached
|
app: kubernaut-memcached
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: kipunji-memcached
|
app: kubernaut-memcached
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: kipunji-memcached
|
- name: kubernaut-memcached
|
||||||
image: memcached:latest
|
image: memcached:latest
|
||||||
ports:
|
ports:
|
||||||
- name: memcached
|
- name: memcached
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
namespace: kipunji
|
namespace: kubernaut
|
||||||
resources:
|
resources:
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- services.yaml
|
- services.yaml
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji-memcached
|
name: kubernaut-memcached
|
||||||
|
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
@ -10,4 +10,4 @@ spec:
|
|||||||
port: 11211
|
port: 11211
|
||||||
targetPort: memcached
|
targetPort: memcached
|
||||||
selector:
|
selector:
|
||||||
app: kipunji-memcached
|
app: kubernaut-memcached
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: kipunji
|
name: kubernaut
|
||||||
labels: {}
|
labels: {}
|
||||||
|
|
||||||
|
50
lib/config.rb
Normal file
50
lib/config.rb
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
require "sensitive"
|
||||||
|
|
||||||
|
class Config
|
||||||
|
attr_accessor :cat
|
||||||
|
|
||||||
|
attr_reader :jwt_secret, :session_secret
|
||||||
|
|
||||||
|
def initialize(prefix = ENV_PREFIX, jwt_secret = nil, session_secret = nil, cat = nil)
|
||||||
|
@prefix = prefix
|
||||||
|
@cat = cat
|
||||||
|
|
||||||
|
session_secret ||= ENV.fetch "SESSION_SECRET" do
|
||||||
|
SecureRandom.hex SESSION_SECRET_HEX_LENGTH
|
||||||
|
end
|
||||||
|
|
||||||
|
jwt_secret ||= fetch_env "JWT_SECRET" do
|
||||||
|
SecureRandom.hex JWT_SECRET_HEX_LENGTH
|
||||||
|
end
|
||||||
|
|
||||||
|
@session_secret = Sensitive.new session_secret
|
||||||
|
@jwt_secret = Sensitive.new jwt_secret
|
||||||
|
@cat ||= ENV.fetch "#{@prefix}_CAT", nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_env(name, &)
|
||||||
|
ENV.fetch "#{@prefix}_#{name}", &
|
||||||
|
end
|
||||||
|
|
||||||
|
def as_json(options = nil)
|
||||||
|
{jwt_secret: jwt_secret, session_secret: @session_secret, cat: @cat}
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_json(options = nil)
|
||||||
|
if options &&
|
||||||
|
options.key?(:pretty) &&
|
||||||
|
options[:pretty] == true
|
||||||
|
JSON.pretty_generate as_json(options)
|
||||||
|
else
|
||||||
|
JSON.generate as_json(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def session_secret=(v)
|
||||||
|
@session_secret = Sensitive.new v
|
||||||
|
end
|
||||||
|
|
||||||
|
def jwt_secret=(v)
|
||||||
|
@jwt_secret = Sensitive.new v
|
||||||
|
end
|
||||||
|
end
|
39
lib/sensitive.rb
Normal file
39
lib/sensitive.rb
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
class Sensitive
|
||||||
|
alias_method :eql?, :==
|
||||||
|
alias_method :equal?, :==
|
||||||
|
|
||||||
|
def initialize(v, ch: "*", head: 2, tail: 2)
|
||||||
|
@v = v
|
||||||
|
@ch = ch
|
||||||
|
@head = head
|
||||||
|
@tail = tail
|
||||||
|
end
|
||||||
|
|
||||||
|
def mask(v)
|
||||||
|
"".concat(v[0, @head], @ch * (v.length - (@head + @tail)), v[-@tail, @tail])
|
||||||
|
end
|
||||||
|
|
||||||
|
def unwrap
|
||||||
|
@v
|
||||||
|
end
|
||||||
|
|
||||||
|
def length
|
||||||
|
@v.length
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
mask @v
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"#<#{self.class.name} @v=#{wrap}>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def hash
|
||||||
|
@v.hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
other.is_a?(Sensitive) && other.hash == hash
|
||||||
|
end
|
||||||
|
end
|
26
spec/sensitive_spec.rb
Normal file
26
spec/sensitive_spec.rb
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require "minitest/autorun"
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
|
||||||
|
|
||||||
|
require "sensitive"
|
||||||
|
|
||||||
|
ALPHABET = ('a' .. 'z').reduce(:concat)
|
||||||
|
|
||||||
|
describe "Sensitive" do
|
||||||
|
before do
|
||||||
|
@s = Sensitive.new ALPHABET
|
||||||
|
end
|
||||||
|
|
||||||
|
it "test initialize" do
|
||||||
|
_(@s.to_s).must_equal "ab" + "*" * 22 + "yz"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "test initialize" do
|
||||||
|
_(@s.unwrap).must_equal ALPHABET
|
||||||
|
end
|
||||||
|
|
||||||
|
it "test using different mask character" do
|
||||||
|
s = Sensitive.new ALPHABET, ch: "x"
|
||||||
|
_(s.to_s).must_equal "x"
|
||||||
|
end
|
||||||
|
end
|
26
test/test_sensitive.rb
Normal file
26
test/test_sensitive.rb
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
require "minitest/autorun"
|
||||||
|
|
||||||
|
$LOAD_PATH.unshift File.dirname(__FILE__) + "/../lib"
|
||||||
|
|
||||||
|
require "sensitive"
|
||||||
|
|
||||||
|
ALPHABET = ("a".."z").reduce(:concat)
|
||||||
|
|
||||||
|
class TestSensitive < Minitest::Test
|
||||||
|
def setup
|
||||||
|
@s = Sensitive.new ALPHABET
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_initialize
|
||||||
|
assert_equal @s.to_s, "ab" + "*" * 22 + "yz"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unwrap
|
||||||
|
assert_equal @s.unwrap, ALPHABET
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_using_a_different_mask_character
|
||||||
|
s = Sensitive.new ALPHABET, ch: "x"
|
||||||
|
assert_equal s.to_s, "ab" + "x" * 22 + "yz"
|
||||||
|
end
|
||||||
|
end
|
Reference in New Issue
Block a user