using Inversion; using Statum; using Spry.Authentication; namespace Spry.Actions { /** * Verifies the `username`/`password` form fields and establishes the * SESSION `auth` slot via {@link Spry.SpryAuth.login}, then navigates to * {@link landing_uri}. * * Unknown usernames and wrong passwords both answer the generic * {@link invalid_credentials_message} notify, so the response leaks no * account existence. */ public class LoginAction : StatumAction { private UserService users = inject(); /** URI navigated to after a successful login. */ protected virtual string landing_uri { get { return "/"; } } /** Notification shown when the credentials do not match an account. */ protected virtual string invalid_credentials_message { get { return "Invalid username or password"; } } public override async DirectiveBuilder handle() throws GLib.Error { string username = ""; string password = ""; if (request.form != null) { username = request.form.get_field("username") ?? ""; password = request.form.get_field("password") ?? ""; } var user = yield users.authenticate_user(username, password); if (user == null) { return directives().notify("error", invalid_credentials_message); } return SpryAuth.login(directives(), (!)user, action_registry).navigate(landing_uri); } } }