* Started working on moving user sessions to the new 'sessions' table. This is still a work in progress.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent e483d6e9a1
commit b2367bb90b
  1. 75
      Anvil/Tools/Account.pm
  2. 1
      share/words.xml
  3. 3
      tools/anvil-change-password
  4. 4
      tools/anvil-update-system
  5. 60
      tools/anvil.sql

@ -338,12 +338,14 @@ AND
{
my $query = "
UPDATE
users
sessions
SET
user_session_salt = ".$anvil->data->{sys}{database}{use_handle}->quote($session_salt).",
session_salt = ".$anvil->data->{sys}{database}{use_handle}->quote($session_salt).",
modified_date = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
user_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($user_uuid)."
session_user_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($user_uuid)."
AND
session_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)."
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({debug => $debug, query => $query, source => $THIS_FILE, line => __LINE__});
@ -379,7 +381,17 @@ WHERE
This deletes the user's UUID and hash cookies, which effectively logs them out.
This methods takes no parameters and always returns C<< 0 >>.
If there is no C<< user_uuid >>, this will return C<< 1 >>. Otherwise, C<< 0 >> is returned.
Parameters;
=head3 user_uuid (optional, default 'cookie::anvil_user_uuid')
This is the user to log out.
=head3 host_uuid (optional, default 'Get->host_uuid')
This is the host to log out of. This takes the special C<< all >> value which logs the user out of all hosts sessions.
=cut
sub logout
@ -392,23 +404,45 @@ sub logout
# Delete the user's cookie data. Sending nothing to '_write_cookies' does this.
$anvil->Account->_write_cookies({debug => $debug});
# Delete the user's session salt.
if ($anvil->data->{cookie}{anvil_user_uuid})
my $user_uuid = defined $parameter->{user_uuid} ? $parameter->{user_uuid} : $anvil->data->{cookie}{anvil_user_uuid};
my $host_uuid = defined $parameter->{host_uuid} ? $parameter->{host_uuid} : $anvil->Get->host_uuid;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
user_uuid => $user_uuid.
host_uuid => $host_uuid,
}});
# If I don't have a user UUID, we can't proceed.
if (not $user_uuid)
{
# User not found.
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "error_0040"});
$anvil->data->{form}{error_massage} = $anvil->Template->get({file => "main.html", name => "error_message", variables => { error_message => $anvil->Words->string({key => "error_0040"}) }});
return(1);
}
# If the host_uuid is 'all', we're logging out all sessions.
# Delete the user's session salt.
my $query = "
UPDATE
users
sessions
SET
user_session_salt = '',
session_salt = '',
modified_date = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{sys}{database}{timestamp})."
WHERE
user_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{cookie}{anvil_user_uuid})."
session_user_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($user_uuid)." ";
if ($host_uuid ne "all")
{
$query .= "
AND
session_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($host_uuid)." ";
}
$query .= "
;";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
$anvil->Database->write({debug => $debug, query => $query, source => $THIS_FILE, line => __LINE__});
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0198", variables => { user => $anvil->data->{cgi}{username}{value} }});
}
# Log that they're out
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0179"});
@ -489,7 +523,16 @@ sub read_cookies
}});
# Validate the cookie if there is a User UUID. Pick the random number up from the database.
my $query = "SELECT user_session_salt FROM users WHERE user_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{cookie}{anvil_user_uuid}).";";
my $query = "
SELECT
session_salt
FROM
sessions
WHERE
session_user_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->data->{cookie}{anvil_user_uuid})."
AND
session_host_uuid = ".$anvil->data->{sys}{database}{use_handle}->quote($anvil->Get->host_uuid)."
;";
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0124", variables => { query => $query }});
my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__});
my $count = @{$results};
@ -513,21 +556,21 @@ sub read_cookies
}
# Read in their "rand" value
$anvil->data->{users}{user_session_salt} = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->data->{users}{user_session_salt} = "" if not defined $anvil->data->{users}{user_session_salt};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "users::user_session_salt" => $anvil->data->{users}{user_session_salt} }});
$anvil->data->{sessions}{session_salt} = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
$anvil->data->{sessions}{session_salt} = "" if not defined $anvil->data->{sessions}{session_salt};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "sessions::session_salt" => $anvil->data->{sessions}{session_salt} }});
# Generate a hash using today and yesterday's date.
my ($today_hash) = $anvil->Account->_build_cookie_hash({
debug => $debug,
uuid => $anvil->data->{cookie}{anvil_user_uuid},
salt => $anvil->data->{users}{user_session_salt},
salt => $anvil->data->{sessions}{session_salt},
offset => 0,
});
my ($yesterday_hash) = $anvil->Account->_build_cookie_hash({
debug => $debug,
uuid => $anvil->data->{cookie}{anvil_user_uuid},
salt => $anvil->data->{users}{user_session_salt},
salt => $anvil->data->{sessions}{session_salt},
offset => -86400,
});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {

@ -576,6 +576,7 @@ The update appears to have not completed successfully. The output was:
<key name="error_0037"><![CDATA[In Words->parse_banged_string(), an infinite loop was detected while processing: [#!variable!message!#].]]></key>
<key name="error_0038">The TCP port: [#!variable!port!#] is not a valid.</key>
<key name="error_0039"><![CDATA[The password for the host was not provided by '--password-file' or in 'job_data' (as 'password=<secret>').]]></key>
<key name="error_0040">Logging out failed. The user's UUID wasn't passed and 'sys::users::user_uuid' wasn't set. Was the user already logged out?</key>
<!-- These are units, words and so on used when displaying information. -->
<key name="unit_0001">Yes</key>

@ -176,8 +176,9 @@ sub update_local_passwords
user_is_admin => 1,
user_is_experienced => 1,
user_is_trusted => 1,
user_session_salt => "", # Logs them out, effectively
});
# Log out any Striker sessions.
$anvil->Account->logout{host_uuid => "all"});
print $anvil->Words->string({key => "message_0025"})."\n";
# Validate

@ -270,7 +270,7 @@ sub run_os_update
if ($line =~ /Total download size: (.*)$/i)
{
my $update_size = $1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { update_size => $update_size }});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_size => $update_size }});
# Ready to install, update to 5%. The next step will count up to 95%.
update_progress($anvil, $progress, "message_0035,!!size!$update_size!!");
@ -282,7 +282,7 @@ sub run_os_update
$to_update *= 4;
$percent_step = $anvil->Convert->round({number => ($to_update / 90)});
$next_step = $percent_step;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
to_update => $to_update,
percent_step => $percent_step,
next_step => $next_step,

@ -44,7 +44,6 @@ CREATE TABLE users (
user_uuid uuid not null primary key, -- This is the single most important record in Anvil!. Everything links back to here.
user_name text not null,
user_password_hash text not null, -- A user without a password is disabled.
user_session_salt text not null, -- This is used when generating a session hash for a user when they log in.
user_salt text not null, -- This is used to enhance the security of the user's password.
user_algorithm text not null, -- This is the algorithm used to encrypt the password and salt.
user_hash_count text not null, -- This is the number of times that the password+salt was re-hashed through the algorithm.
@ -61,7 +60,6 @@ CREATE TABLE history.users (
user_uuid uuid,
user_name text,
user_password_hash text,
user_session_salt text,
user_salt text,
user_algorithm text,
user_hash_count text,
@ -83,7 +81,6 @@ BEGIN
(user_uuid,
user_name,
user_password_hash,
user_session_salt,
user_salt,
user_algorithm,
user_hash_count,
@ -96,7 +93,6 @@ BEGIN
(history_users.user_uuid,
history_users.user_name,
history_users.user_password_hash,
history_users.user_session_salt,
history_users.user_salt,
history_users.user_algorithm,
history_users.user_hash_count,
@ -116,6 +112,62 @@ CREATE TRIGGER trigger_users
FOR EACH ROW EXECUTE PROCEDURE history_users();
-- This stores user session information on a per-dashboard basis.
CREATE TABLE sessions (
session_uuid uuid not null primary key, -- This is the single most important record in Anvil!. Everything links back to here.
session_host_uuid uuid not null, -- This is the host uuid for this session.
session_user_uuid uuid not null, -- This is the user uuid for the user logging in.
session_session_salt text not null, -- This is used when generating a session hash for a session when they log in.
session_user_agent text,
modified_date timestamp with time zone not null
FOREIGN KEY(session_host_uuid) REFERENCES hosts(host_uuid),
FOREIGN KEY(session_user_uuid) REFERENCES users(user_uuid)
);
ALTER TABLE sessions OWNER TO #!variable!session!#;
CREATE TABLE history.sessions (
history_id bigserial,
session_uuid uuid,
session_host_uuid uuid,
session_user_uuid uuid,
session_session_salt text,
session_user_agent text,
modified_date timestamp with time zone not null
);
ALTER TABLE history.sessions OWNER TO #!variable!session!#;
CREATE FUNCTION history_sessions() RETURNS trigger
AS $$
DECLARE
history_sessions RECORD;
BEGIN
SELECT INTO history_sessions * FROM sessions WHERE session_uuid = new.session_uuid;
INSERT INTO history.sessions
(session_uuid,
session_host_uuid,
session_user_uuid,
session_session_salt,
session_user_agent,
modified_date)
VALUES
(history_sessions.session_uuid,
history_sessions.session_host_uuid,
history_sessions.session_user_uuid,
history_sessions.session_session_salt,
history_sessions.session_user_agent,
history_sessions.modified_date);
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
ALTER FUNCTION history_sessions() OWNER TO #!variable!session!#;
CREATE TRIGGER trigger_sessions
AFTER INSERT OR UPDATE ON sessions
FOR EACH ROW EXECUTE PROCEDURE history_sessions();
-- This stores information about the host machine. This is the master table that everything will be linked
-- to.

Loading…
Cancel
Save