diff --git a/Tweetodon/User.pm b/Tweetodon/User.pm index 00ee5bc..d596810 100644 --- a/Tweetodon/User.pm +++ b/Tweetodon/User.pm @@ -8,15 +8,20 @@ use JSON; use Tweetodon::Token; use Data::Dumper; -sub dbTable :lvalue { "invalid"; } -sub orderBy :lvalue { "invalid"; } +sub dbTable :lvalue { "users"; } +sub orderBy :lvalue { "username"; } # Class functions sub authenticate { my $class = shift; - my $instance = $main::FORM{instance}; - my $token = $main::FORM{token}; + my $session_id = $main::FORM{session_id}; + return 0 unless defined($session_id); + my $user = $class->get_by("session_id", $session_id); + return 0 unless $user; + + my $instance = $user->{data}->{instance}; + my $token = $user->{data}->{access_token}; if ($token){ open(DATA, "./verify_credentials.bash '$token' '$instance'|"); my $reply; @@ -27,11 +32,12 @@ sub authenticate { close DATA; $reply = decode_json($reply); #{"error":"The access token is invalid"} - if (defined($$reply{error})){ + if (!defined($$reply{username})){ return 0; } + $reply->{token} = $token; + $reply->{instance} = $instance; return $class->new($reply); - #{"id":8225,"username":"b_playsgames","acct":"b_playsgames","display_name":"Ben Plays Games","locked":false,"created_at":"2017-04-18T18:10:51.707Z","followers_count":8,"following_count":0,"statuses_count":13,"note":"Playing games for fun and reduced backlog! Join me at https://yt.benplaysgames.com/","url":"https://toot.berlin/@b_playsgames","avatar":"https://toot.berlin/system/accounts/avatars/000/008/225/original/12899445370222cb.jpg?1492540236","avatar_static":"https://toot.berlin/system/accounts/avatars/000/008/225/original/12899445370222cb.jpg?1492540236","header":"https://toot.berlin/system/accounts/headers/000/008/225/original/0e643b731c89e5a2.jpg?1492540236","header_static":"https://toot.berlin/system/accounts/headers/000/008/225/original/0e643b731c89e5a2.jpg?1492540236"} } return 0; } diff --git a/Tweetodon/Website/Callback.pm b/Tweetodon/Website/Callback.pm index cd33360..2ddb3e8 100644 --- a/Tweetodon/Website/Callback.pm +++ b/Tweetodon/Website/Callback.pm @@ -5,12 +5,14 @@ use HTML::Template; use Tweetodon::Website; use Tweetodon::App; use Tweetodon::Token; -use Tweetodon::DB; package Tweetodon::Website::Callback; @Tweetodon::Website::Callback::ISA = qw(Tweetodon::Website); use Data::Dumper; +use UUID::Tiny; +use Digest::SHA qw(sha256_base64); use JSON; +use Tweetodon::DB; sub requires_authentication { return 0; @@ -27,7 +29,6 @@ sub prerender { $self->{"params"}->{"currentmode"} = "Callback"; my $instance = $main::FORM{instance}; - my $app = Tweetodon::App->get_or_create_by_instance($instance); open(DATA, "./process_code.bash '$app->{data}->{instance_client_id}' '$app->{data}->{instance_client_secret}' '$main::FORM{code}' '$main::config->{app}->{redirect_uris}' '$instance'|"); @@ -38,10 +39,29 @@ sub prerender { } close DATA; $reply = decode_json($reply); + if (!defined($$reply{access_token})){ + main::Error("Login error", "There was an error logging you in!"); + return 0; + } - $self->{"set_cookie"} = ("token=".$reply->{access_token}); - # Tweetodon::DB->doINSERT("INSERT INTO tokens (access_token, token_type, scope, created_at, username) VALUES (?, ?, ?, ?, ?)", $reply->{access_token}, $reply->{token_type}, $reply->{scope}, $reply->{created_at}, $main::FORM{Username}); - #{"access_token":"9615e561d0cf3cb54799ecc381f10b059e781dac2b180e708dcd66683c1cdb81","token_type":"bearer","scope":"read write","created_at":1492718172} + my $token = $$reply{access_token}; + open(DATA, "./verify_credentials.bash '$token' '$instance'|"); + { + $/ = undef; + $reply = + } + close DATA; + $reply = decode_json($reply); + if (!defined($$reply{acct})){ + main::Error("Login error", "There was an error logging you in!"); + return 0; + } + + my $session_id = UUID::Tiny::create_UUID_as_string(UUID_V5, time().$$reply{acct}); + + Tweetodon::DB->doINSERT("INSERT INTO users (username, username_sha256, instance, instance_sha256, access_token, session_id) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE access_token=?, session_id=?", $$reply{acct}, sha256_base64($$reply{acct}), $instance, sha256_base64($instance), $token, $session_id, $token, $session_id); + + $self->{"set_cookie"} = ("session_id=".$session_id); } 1; diff --git a/Tweetodon/Website/Logout.pm b/Tweetodon/Website/Logout.pm new file mode 100644 index 0000000..8f543a7 --- /dev/null +++ b/Tweetodon/Website/Logout.pm @@ -0,0 +1,27 @@ +#!/usr/bin/perl -w + +use strict; +use HTML::Template; +use Tweetodon::Website; + +package Tweetodon::Website::Logout; +@Tweetodon::Website::Logout::ISA = qw(Tweetodon::Website); + +sub requires_authentication { + return 0; +} + +sub fill_content { + return 1; +} + +sub prerender { + my $self = shift; + $self->{"template"} = "Login"; + $self->{"content_type"} = "html"; + $self->{"params"}->{"currentmode"} = "Login"; + + $self->{"set_cookie"} = ("session_id="); +} + +1; diff --git a/Tweetodon/Website/OAuthLogin.pm b/Tweetodon/Website/OAuthLogin.pm index 8b0fd75..0a0b32a 100644 --- a/Tweetodon/Website/OAuthLogin.pm +++ b/Tweetodon/Website/OAuthLogin.pm @@ -36,18 +36,9 @@ sub prerender { $self->{params}->{instance} = $instance; $self->{params}->{token_is_valid} = "false"; - my $token = $main::FORM{token}; - - if (defined($token)){ - #open(DATA, "./verify_credentials.bash '$token' '$instance'|"); - #my $reply; - #{ - #$/ = undef; - #$reply = ; - #} - #close DATA; - #$reply = decode_json($reply); - if (Tweetodon::User->authenticate()){ + if (defined($main::FORM{session_id})){ + my $user = Tweetodon::User->authenticate(); + if ($user){ $self->{params}->{token_is_valid} = "true"; } # {"error":"The access token is invalid"} diff --git a/index.pl b/index.pl index 53450eb..7c222a2 100755 --- a/index.pl +++ b/index.pl @@ -120,7 +120,7 @@ my $object; # TODO: This is a very bad solution but not as bad as an uncontrolled eval... # The @main::modules array holds a list of all permissible values of the $main::FORM{"mode"} variable. # If the value is not in this array, the request is not processed and an error is displayed. -my @modules = ("Login", "OAuthLogin", "Dashboard", "Callback", "JSON", "EditFeed"); +my @modules = ("Login", "Logout", "OAuthLogin", "Dashboard", "Callback", "JSON", "EditFeed"); if (! grep {$_ eq $FORM{mode}} @modules) { Error("Validation Error", "$FORM{mode} is not a valid module");