updates and cleanup.
This commit is contained in:
@@ -37,9 +37,7 @@
|
||||
runtimeInputs = [ ruby ];
|
||||
text = ''
|
||||
set -euo pipefail
|
||||
data_dir="''${INFINSWEEPER_DATA_DIR:-/var/lib/infinsweeper}"
|
||||
DB="$data_dir/infinsweeper.db"
|
||||
mkdir -p "$data_dir"
|
||||
export DB="''${INFINSWEEPER_DB:-/var/lib/infinsweeper.db}"
|
||||
exec ruby ${app}/main.rb
|
||||
'';
|
||||
};
|
||||
@@ -57,6 +55,8 @@
|
||||
ruby
|
||||
pkgs.sqlite
|
||||
];
|
||||
|
||||
env.INFINSWEEPER_DB = "./infinsweeper.db";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
/>
|
||||
</a>
|
||||
<div class="header-right">
|
||||
<button class="account-button" id="reset-button">RESET GAME</button>
|
||||
<button class="account-button" id="logout-button">LOGOUT</button>
|
||||
<button class="account-button" id="login-button">LOGIN</button>
|
||||
<button class="account-button" id="signup-button">SIGN UP</button>
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
# Mailer module
|
||||
|
||||
# Not to actually be used. proof of concept.
|
||||
|
||||
module Mail
|
||||
def send(to, subject, body)
|
||||
raise "Can't send email."
|
||||
|
||||
from_email = "infinsweeper@domain.com"
|
||||
from_name = "InfinSweeper"
|
||||
to = Array(to).map { |addr| { email_address: { address: addr, name: "" } } }
|
||||
@@ -32,5 +28,6 @@ module Mail
|
||||
|
||||
return if response.is_a?(Net::HTTPSuccess)
|
||||
Logman.imp "[ZeptoMail ERROR] #{response.body}"
|
||||
raise "Email failed."
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,17 +9,11 @@ require "zlib"
|
||||
|
||||
ALPHANUM = [*"0".."9", *"A".."Z", *"a".."z", "-", "_"].freeze
|
||||
|
||||
env_data = File.exist?(".env") ? File.read(".env") : ""
|
||||
|
||||
env_data.each_line do |line|
|
||||
next unless (match = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/))
|
||||
ENV[match[1]] = match[2]
|
||||
end
|
||||
|
||||
load "logman.rb"
|
||||
# Logman.log ENV.inspect
|
||||
|
||||
db_file = ENV.fetch("INFINSWEEPER_DB", File.expand_path("infinsweeper.db", __dir__))
|
||||
db_file = File.expand_path(ENV.fetch("INFINSWEEPER_DB", "infinsweeper.db"))
|
||||
puts db_file
|
||||
DB = Sequel.connect("sqlite:///#{db_file}", single_threaded: false)
|
||||
DB.run("PRAGMA foreign_keys = ON;")
|
||||
DB.create_table? :Players do
|
||||
@@ -45,6 +39,8 @@ load "players.rb"
|
||||
load "session.rb"
|
||||
|
||||
set :port, ENV.fetch("PORT", 5161)
|
||||
set :bind, '0.0.0.0'
|
||||
set :host_authorization, { permitted_hosts: ["infinsweeper.syedm.dev"] }
|
||||
set :public_folder, "public"
|
||||
|
||||
get "/" do
|
||||
@@ -72,6 +68,8 @@ post "/signup" do
|
||||
return { "message" => "Unauthorized (invalid CSRF token)!" }.to_json
|
||||
end
|
||||
session["csrf_token"] = Array.new(32) { ALPHANUM.sample }.join
|
||||
status 401
|
||||
return { "message" => "New signups are disabled right now.", "csrf_token" => session["csrf_token"] }.to_json
|
||||
if data["email"].nil? || data["pass"].nil? || data["username"].nil?
|
||||
status 400
|
||||
return { "message" => "Bad request made!", "csrf_token" => session["csrf_token"] }.to_json
|
||||
@@ -119,11 +117,10 @@ post "/login" do
|
||||
return { "message" => "Bad request made!", "csrf_token" => session["csrf_token"] }.to_json
|
||||
end
|
||||
login_status = session.login(data["username"], data["pass"])
|
||||
status login_status[0]
|
||||
if login_status[0] == 200
|
||||
status 200
|
||||
return { "message" => login_status[1], "success" => "true", "csrf_token" => session["csrf_token"] }.to_json
|
||||
else
|
||||
status login_status[0]
|
||||
return { "message" => login_status[1], "csrf_token" => session["csrf_token"] }.to_json
|
||||
end
|
||||
end
|
||||
|
||||
+45
-2
@@ -51,9 +51,9 @@ module Players
|
||||
|
||||
Logman.log "Pass req: #{email} & #{code}"
|
||||
|
||||
true
|
||||
|
||||
send_email(:pass_req, email, code)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def self.pass_reset(pass, code)
|
||||
@@ -90,6 +90,49 @@ module Players
|
||||
player && player[:activation_code] == "!"
|
||||
end
|
||||
|
||||
def self.send_email(type, email, *args)
|
||||
case type
|
||||
when :new
|
||||
username, code = args
|
||||
|
||||
Mail.send(
|
||||
email,
|
||||
"Verify your InfinSweeper account",
|
||||
<<~HTML
|
||||
<h2>Welcome to InfinSweeper, #{ERB::Util.html_escape(username)}!</h2>
|
||||
<p>Thanks for signing up.</p>
|
||||
<p>
|
||||
Please verify your email by clicking
|
||||
<a href="https://your-domain.com/verify/#{ERB::Util.url_encode(code)}">
|
||||
this link
|
||||
</a>.
|
||||
</p>
|
||||
HTML
|
||||
)
|
||||
|
||||
when :pass_req
|
||||
code = args.first
|
||||
|
||||
Mail.send(
|
||||
email,
|
||||
"Reset your InfinSweeper password",
|
||||
<<~HTML
|
||||
<h2>Password reset</h2>
|
||||
<p>You requested a password reset for your InfinSweeper account.</p>
|
||||
<p>
|
||||
<a href="https://your-domain.com/reset_password/#{ERB::Util.url_encode(code)}">
|
||||
Click here to reset your password
|
||||
</a>
|
||||
</p>
|
||||
<p>If you didn't request this, you can safely ignore this email.</p>
|
||||
HTML
|
||||
)
|
||||
|
||||
else
|
||||
raise ArgumentError, "Unknown email type: #{type.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
Thread.new do
|
||||
loop do
|
||||
unverified.each do |player|
|
||||
|
||||
@@ -18,4 +18,8 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
*/
|
||||
window.game = new GameController();
|
||||
window.game.init();
|
||||
|
||||
document.getElementById("reset-button").addEventListener("click", () => {
|
||||
window.game.reset();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -147,6 +147,7 @@ export default class GameController {
|
||||
* @param {number} tries - Number of times the game has been reset
|
||||
*/
|
||||
async reset(tries = 0) {
|
||||
this.bus.emit("clear_save");
|
||||
this._clearGameState();
|
||||
this._generateNewSeed();
|
||||
await this.start(tries);
|
||||
|
||||
@@ -39,6 +39,8 @@ export default class Saver {
|
||||
this.bus.on("load_save", this.load.bind(this));
|
||||
/** @listens EventBus#delete_save */
|
||||
this.bus.on("delete_save", this.deleteSave.bind(this));
|
||||
/** @listens EventBus#clear_save */
|
||||
this.bus.on("clear_save", this.clearSave.bind(this));
|
||||
/** @listens EventBus#start_autosaver */
|
||||
this.bus.on("start_autosaver", this.startAutosaver.bind(this));
|
||||
/** @listens EventBus#stop_autosaver */
|
||||
@@ -154,6 +156,14 @@ export default class Saver {
|
||||
this.delete_save = true;
|
||||
this.stopAutosaver();
|
||||
}
|
||||
/**
|
||||
* @function clearSave
|
||||
* @description clears the save
|
||||
*/
|
||||
clearSave() {
|
||||
localStorage.removeItem("save");
|
||||
this.delete_save = false;
|
||||
}
|
||||
/**
|
||||
* @function loadFromFile
|
||||
* @description Loads the game data from a file
|
||||
|
||||
+43
-52
@@ -3,6 +3,36 @@ class Sessions
|
||||
def initialize(request, response)
|
||||
@request = request
|
||||
@response = response
|
||||
@session = load_session
|
||||
end
|
||||
|
||||
def save
|
||||
compressed = Zlib::Deflate.deflate(JSON.generate(@session))
|
||||
encoded = Base64.strict_encode64(compressed)
|
||||
@response.set_cookie(
|
||||
"session",
|
||||
value: encoded,
|
||||
path: "/",
|
||||
expires: Time.now + 360 * 24 * 60 * 60,
|
||||
httponly: true,
|
||||
secure: ENV["ENV"] == "prod",
|
||||
samesite: :strict
|
||||
)
|
||||
uid = @session["user"]
|
||||
if uid
|
||||
DB["UPDATE SignedInUsers SET last_used_at = CURRENT_TIMESTAMP WHERE code = ?", uid].update
|
||||
end
|
||||
rescue Sequel::Error => e
|
||||
Logman.log "DB Error: #{e.message} when updating last_used_at for #{uid}"
|
||||
end
|
||||
|
||||
def load_session
|
||||
cookie = @request.cookies["session"]
|
||||
return {} unless cookie
|
||||
JSON.parse(Zlib::Inflate.inflate(Base64.strict_decode64(cookie)))
|
||||
rescue JSON::ParserError, Zlib::Error, ArgumentError
|
||||
@response.delete_cookie("session")
|
||||
{}
|
||||
end
|
||||
|
||||
def signed_in?
|
||||
@@ -35,38 +65,21 @@ class Sessions
|
||||
return [200, "Remember to verify your email!"] unless Players.verified?(username)
|
||||
[200, "Signed in successfully!"]
|
||||
else
|
||||
[200, "Couldn't sign you in (Username or password incorrect)!"]
|
||||
[401, "Couldn't sign you in (Username or password incorrect)!"]
|
||||
end
|
||||
end
|
||||
|
||||
def []=(key, val)
|
||||
session = all
|
||||
session[key] = val
|
||||
Logman.log "Updated: #{key} to #{val}"
|
||||
compressed = Zlib::Deflate.deflate(JSON.generate(session))
|
||||
encoded = Base64.encode64(compressed)
|
||||
@response.set_cookie("session",
|
||||
value: encoded,
|
||||
path: "/",
|
||||
expires: Time.now + 360 * 24 * 60 * 60,
|
||||
httponly: true,
|
||||
secure: ENV_HASH["ENV"] == "prod",
|
||||
samesite: :strict)
|
||||
uid = session["user"]
|
||||
DB["UPDATE SignedInUsers SET last_used_at = CURRENT_TIMESTAMP WHERE code = ?", uid].update if uid
|
||||
rescue Sequel::Error => e
|
||||
Logman.log "DB Error: #{e.message} when updating last_used_at for #{uid}"
|
||||
end
|
||||
|
||||
def [](key)
|
||||
session = all
|
||||
begin
|
||||
uid = session["user"]
|
||||
DB["UPDATE SignedInUsers SET last_used_at = CURRENT_TIMESTAMP WHERE code = ?", uid].update if uid
|
||||
rescue Sequel::Error => e
|
||||
Logman.log "DB Error: #{e.message} when updating last_used_at for #{uid}"
|
||||
end
|
||||
session[key]
|
||||
@session[key]
|
||||
end
|
||||
|
||||
def []=(key, val)
|
||||
@session[key] = val
|
||||
save
|
||||
end
|
||||
|
||||
def all
|
||||
@session
|
||||
end
|
||||
|
||||
def message=(val)
|
||||
@@ -86,31 +99,9 @@ class Sessions
|
||||
@request.env["HTTP_X_CSRF_TOKEN"] == self["csrf_token"]
|
||||
end
|
||||
|
||||
def all
|
||||
session = @request.cookies["session"]
|
||||
session = session.nil? ? "{}" : Zlib::Inflate.inflate(Base64.decode64(session))
|
||||
JSON.parse(session)
|
||||
rescue JSON::ParserError, Zlib::Error
|
||||
@response.delete_cookie("session")
|
||||
{}
|
||||
end
|
||||
|
||||
def delete(key)
|
||||
session = all
|
||||
session.delete(key)
|
||||
Logman.log "Deleted: #{key}"
|
||||
Logman.log session.inspect
|
||||
compressed = Zlib::Deflate.deflate(JSON.generate(session))
|
||||
encoded = Base64.encode64(compressed)
|
||||
@response.set_cookie("session",
|
||||
value: encoded,
|
||||
path: "/",
|
||||
expires: Time.now + 360 * 24 * 60 * 60,
|
||||
httponly: true,
|
||||
secure: ENV["ENV"] == "prod",
|
||||
samesite: :strict)
|
||||
rescue JSON::ParserError, Zlib::Error
|
||||
@response.delete_cookie("session")
|
||||
@session.delete(key)
|
||||
save
|
||||
end
|
||||
|
||||
Thread.new do
|
||||
|
||||
Reference in New Issue
Block a user