diff --git a/public/style.css b/public/style.css index 1a014ce..8b7e8f1 100644 --- a/public/style.css +++ b/public/style.css @@ -89,4 +89,23 @@ pre { } .dir-header a { text-decoration: none; +} + +.fancy-button { + outline: 0; + border: none; + background-color: var(--accent-color); + color: #000; + font-size: 1.2rem; + padding: 0.4em 0.8em; + margin: 0.5em; + border-radius: 16px; + + cursor: pointer; + + transition: 0.1s background-color; +} + +.fancy-button:hover { + background-color: var(--accent-color-bri); } \ No newline at end of file diff --git a/public/template/account_management.ecr b/public/template/account_management.ecr index a4d22ba..5ada715 100644 --- a/public/template/account_management.ecr +++ b/public/template/account_management.ecr @@ -6,9 +6,20 @@ Account Management + - -

Account Management

- hewwo + + hewwo, <%= username %>!

+ +
  • Nothing is implemented right now for account management
  • +
  • This is just a test list
  • +
  • Did you know your account ID is <%= account_id %>?
  • +
    diff --git a/public/template/login.ecr b/public/template/login.ecr new file mode 100644 index 0000000..7b3ac50 --- /dev/null +++ b/public/template/login.ecr @@ -0,0 +1,51 @@ + + + + + + + + Login + + + +
    + +
    + + + + + + <%- if error -%> +
    <%= error %>
    + <%- end -%> + + +
    + + diff --git a/shard.lock b/shard.lock index a259202..d071c03 100644 --- a/shard.lock +++ b/shard.lock @@ -8,6 +8,10 @@ shards: git: https://github.com/gdotdesign/cr-dotenv.git version: 1.0.0 + http-session: + git: https://github.com/straight-shoota/http-session.git + version: 0.2.0+git.commit.7bd278a5567f89cdc348e3d468bd25d561319492 + migrate: git: https://github.com/oatmealine/migrate.cr.git version: 0.5.0+git.commit.a4a24df3d05d0481c76ccd42e45cc48fa3fc1e73 diff --git a/shard.yml b/shard.yml index c9e5b4b..d351ad7 100644 --- a/shard.yml +++ b/shard.yml @@ -21,6 +21,8 @@ dependencies: toml: github: crystal-community/toml.cr branch: master + http-session: + github: straight-shoota/http-session crystal: 1.6.2 diff --git a/src/lib/templates.cr b/src/lib/templates.cr index 6dd0999..2a3c99c 100644 --- a/src/lib/templates.cr +++ b/src/lib/templates.cr @@ -1,3 +1,5 @@ +require "http-session" + module CrystalGauntlet::Templates extend self @@ -14,3 +16,22 @@ module CrystalGauntlet::Templates ) end end + +module CrystalGauntlet + record UserSession, username : String, account_id : Int32, user_id : Int32 + + # todo: replace memory storage with sqlite maybe? has to be hand-written but oh well + @@session_storage = HTTPSession::Storage::Memory(UserSession).new + @@sessions : HTTPSession::Manager(UserSession) = HTTPSession::Manager.new(@@session_storage, HTTP::Cookie.new("surveillance_device", "", secure: false, http_only: true, max_age: 365.days)) + + spawn do + session_storage.run_gc_loop + end + + def self.session_storage + @@session_storage + end + def self.sessions + @@sessions + end +end diff --git a/src/template_endpoints/account_management.cr b/src/template_endpoints/account_management.cr index e5371ee..3b62329 100644 --- a/src/template_endpoints/account_management.cr +++ b/src/template_endpoints/account_management.cr @@ -1,5 +1,5 @@ require "uri" -require "compress/gzip" +require "http-session" include CrystalGauntlet @@ -10,5 +10,55 @@ CrystalGauntlet.template_endpoints["/#{config_get("general.append_path").as(Stri CrystalGauntlet.template_endpoints["/accounts"] = ->(context : HTTP::Server::Context) { context.response.content_type = "text/html" - ECR.embed("./public/template/account_management.ecr", context.response) + + if session = CrystalGauntlet.sessions.get(context) + logged_in = true + account_id = session.account_id + user_id = session.user_id + username = session.username + else + logged_in = false + account_id = nil + user_id = nil + username = nil + end + + body = context.request.body + if body + begin + params = URI::Params.parse(body.gets_to_end) + username = params["username"].strip + password = params["password"].strip + + if username.empty? || password.empty? + raise "Invalid username or password" + end + + # todo: dedup this code with the login account endpoint maybe + result = DATABASE.query_all("select id, password from accounts where username = ?", username, as: {Int32, String}) + if result.size > 0 + account_id, hash = result[0] + bcrypt = Crypto::Bcrypt::Password.new(hash) + + if bcrypt.verify(password) + user_id = Accounts.get_user_id(account_id) + logged_in = true + LOG.debug { "#{username} logged in" } + CrystalGauntlet.sessions.set(context, UserSession.new(username, account_id, user_id)) + else + raise "Invalid password" + end + else + raise "No such user exists" + end + rescue error + LOG.error(exception: error) {"whar...."} + end + end + + if logged_in + ECR.embed("./public/template/account_management.ecr", context.response) + else + ECR.embed("./public/template/login.ecr", context.response) + end }