Loading lib/Travelynx.pm +2 −0 Original line number Diff line number Diff line Loading @@ -2213,6 +2213,7 @@ sub startup { $authed_r->get('/account')->to('account#account'); $authed_r->get('/account/privacy')->to('account#privacy'); $authed_r->get('/account/profile')->to('account#profile'); $authed_r->get('/account/hooks')->to('account#webhook'); $authed_r->get('/account/traewelling')->to('traewelling#settings'); $authed_r->get('/account/insight')->to('account#insight'); Loading @@ -2239,6 +2240,7 @@ sub startup { $authed_r->get('/s/*station')->to('traveling#station'); $authed_r->get('/confirm_mail/:token')->to('account#confirm_mail'); $authed_r->post('/account/privacy')->to('account#privacy'); $authed_r->post('/account/profile')->to('account#profile'); $authed_r->post('/account/hooks')->to('account#webhook'); $authed_r->post('/account/traewelling')->to('traewelling#settings'); $authed_r->post('/account/insight')->to('account#insight'); Loading lib/Travelynx/Controller/Account.pm +68 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ use Mojo::Base 'Mojolicious::Controller'; use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); use JSON; use Mojo::Util qw(xml_escape); use Text::Markdown; use UUID::Tiny qw(:std); my %visibility_itoa = ( Loading Loading @@ -499,6 +501,72 @@ sub privacy { } } sub profile { my ($self) = @_; my $user = $self->current_user; if ( $self->param('action') and $self->param('action') eq 'save' ) { if ( $self->validation->csrf_protect->has_error('csrf_token') ) { $self->render( 'edit_profile', invalid => 'csrf', ); return; } my $md = Text::Markdown->new; my $bio = $self->param('bio'); if ( length($bio) > 2000 ) { $bio = substr( $bio, 0, 2000 ) . '…'; } my $profile = { bio => { markdown => $bio, html => $md->markdown( xml_escape($bio) ), }, metadata => [], }; for my $i ( 0 .. 20 ) { my $key = $self->param("key_$i"); my $value = $self->param("value_$i"); if ($key) { if ( length($value) > 500 ) { $value = substr( $value, 0, 500 ) . '…'; } my $html_value = ( $value =~ s{ \[ ([^]]+) \]\( ([^)]+) \) }{'<a href="' . xml_escape($2) . '">' . xml_escape($1) .'</a>' }egrx ); $profile->{metadata}[$i] = { key => $key, value => { markdown => $value, html => $html_value, }, }; } else { last; } } $self->users->set_profile( uid => $user->{id}, profile => $profile ); $self->redirect_to( '/p/' . $user->{name} ); } my $profile = $self->users->get_profile( uid => $user->{id} ); $self->param( bio => $profile->{bio}{markdown} ); for my $i ( 0 .. $#{ $profile->{metadata} } ) { $self->param( "key_$i" => $profile->{metadata}[$i]{key} ); $self->param( "value_$i" => $profile->{metadata}[$i]{value}{markdown} ); } $self->render( 'edit_profile', name => $user->{name} ); } sub insight { my ($self) = @_; Loading lib/Travelynx/Controller/Profile.pm +48 −8 Original line number Diff line number Diff line Loading @@ -70,6 +70,30 @@ sub profile { return; } my $profile = $self->users->get_profile( uid => $user->{id} ); my $my_user; my $relation; my $inverse_relation; my $is_self; if ( $self->is_user_authenticated ) { $my_user = $self->current_user; if ( $my_user->{id} == $user->{id} ) { $is_self = 1; $my_user = undef; } else { $relation = $self->users->get_relation( subject => $my_user->{id}, object => $user->{id} ); $inverse_relation = $self->users->get_relation( subject => $user->{id}, object => $my_user->{id} ); } } my $status = $self->get_user_status( $user->{id} ); my $visibility; if ( $status->{checked_in} or $status->{arr_name} ) { Loading @@ -84,7 +108,12 @@ sub profile { and $self->status_token_ok($status) ) or ( $visibility eq 'travelynx' and ( $self->is_user_authenticated and ( $my_user or $self->status_token_ok($status) ) ) or ( $visibility eq 'followers' and ( ( $relation and $relation eq 'follows' ) or $self->status_token_ok($status) ) ) ) Loading @@ -104,7 +133,7 @@ sub profile { my @journeys; if ( $user->{past_visible} == 2 or ( $user->{past_visible} == 1 and $self->is_user_authenticated ) ) or ( $user->{past_visible} == 1 and $my_user ) ) { my %opt = ( Loading @@ -122,7 +151,10 @@ sub profile { if ( $user->{default_visibility_str} eq 'public' or ( $user->{default_visibility_str} eq 'travelynx' and $self->is_user_authenticated ) and $my_user ) or ( $user->{default_visibility_str} eq 'followers' and $relation and $relation eq 'follows' ) ) { $opt{with_default_visibility} = 1; Loading @@ -131,9 +163,14 @@ sub profile { $opt{with_default_visibility} = 0; } if ( $self->is_user_authenticated ) { if ($my_user) { if ( $relation and $relation eq 'follows' ) { $opt{min_visibility} = 'followers'; } else { $opt{min_visibility} = 'travelynx'; } } else { $opt{min_visibility} = 'public'; } Loading @@ -145,7 +182,10 @@ sub profile { 'profile', name => $name, uid => $user->{id}, bio => $profile->{bio}{html}, metadata => $profile->{metadata}, public_level => $user->{public_level}, is_self => $is_self, journey => $status, journey_visibility => $visibility, journeys => [@journeys], Loading lib/Travelynx/Model/Users.pm +24 −0 Original line number Diff line number Diff line Loading @@ -750,6 +750,30 @@ sub update_webhook_status { ); } sub set_profile { my ( $self, %opt ) = @_; my $db = $opt{db} // $self->{pg}->db; my $uid = $opt{uid}; my $profile = $opt{profile}; $db->update( 'users', { profile => JSON->new->encode($profile) }, { id => $uid } ); } sub get_profile { my ( $self, %opt ) = @_; my $db = $opt{db} // $self->{pg}->db; my $uid = $opt{uid}; return $db->select( 'users', ['profile'], { id => $uid } ) ->expand->hash->{profile}; } sub get_relation { my ( $self, %opt ) = @_; Loading templates/account.html.ep +2 −1 Original line number Diff line number Diff line Loading @@ -73,7 +73,8 @@ <th scope="row">Sichtbarkeit</th> <td> <a href="/account/privacy"><i class="material-icons">edit</i></a> <span><i class="material-icons"><%= visibility_icon($acc->{default_visibility_str}) %></i></span> <i class="material-icons"><%= visibility_icon($acc->{default_visibility_str}) %></i> • <a href="/p/<%= $acc->{name} %>">Öffentliches Profil</a> </td> </tr> <tr> Loading Loading
lib/Travelynx.pm +2 −0 Original line number Diff line number Diff line Loading @@ -2213,6 +2213,7 @@ sub startup { $authed_r->get('/account')->to('account#account'); $authed_r->get('/account/privacy')->to('account#privacy'); $authed_r->get('/account/profile')->to('account#profile'); $authed_r->get('/account/hooks')->to('account#webhook'); $authed_r->get('/account/traewelling')->to('traewelling#settings'); $authed_r->get('/account/insight')->to('account#insight'); Loading @@ -2239,6 +2240,7 @@ sub startup { $authed_r->get('/s/*station')->to('traveling#station'); $authed_r->get('/confirm_mail/:token')->to('account#confirm_mail'); $authed_r->post('/account/privacy')->to('account#privacy'); $authed_r->post('/account/profile')->to('account#profile'); $authed_r->post('/account/hooks')->to('account#webhook'); $authed_r->post('/account/traewelling')->to('traewelling#settings'); $authed_r->post('/account/insight')->to('account#insight'); Loading
lib/Travelynx/Controller/Account.pm +68 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ use Mojo::Base 'Mojolicious::Controller'; use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64); use JSON; use Mojo::Util qw(xml_escape); use Text::Markdown; use UUID::Tiny qw(:std); my %visibility_itoa = ( Loading Loading @@ -499,6 +501,72 @@ sub privacy { } } sub profile { my ($self) = @_; my $user = $self->current_user; if ( $self->param('action') and $self->param('action') eq 'save' ) { if ( $self->validation->csrf_protect->has_error('csrf_token') ) { $self->render( 'edit_profile', invalid => 'csrf', ); return; } my $md = Text::Markdown->new; my $bio = $self->param('bio'); if ( length($bio) > 2000 ) { $bio = substr( $bio, 0, 2000 ) . '…'; } my $profile = { bio => { markdown => $bio, html => $md->markdown( xml_escape($bio) ), }, metadata => [], }; for my $i ( 0 .. 20 ) { my $key = $self->param("key_$i"); my $value = $self->param("value_$i"); if ($key) { if ( length($value) > 500 ) { $value = substr( $value, 0, 500 ) . '…'; } my $html_value = ( $value =~ s{ \[ ([^]]+) \]\( ([^)]+) \) }{'<a href="' . xml_escape($2) . '">' . xml_escape($1) .'</a>' }egrx ); $profile->{metadata}[$i] = { key => $key, value => { markdown => $value, html => $html_value, }, }; } else { last; } } $self->users->set_profile( uid => $user->{id}, profile => $profile ); $self->redirect_to( '/p/' . $user->{name} ); } my $profile = $self->users->get_profile( uid => $user->{id} ); $self->param( bio => $profile->{bio}{markdown} ); for my $i ( 0 .. $#{ $profile->{metadata} } ) { $self->param( "key_$i" => $profile->{metadata}[$i]{key} ); $self->param( "value_$i" => $profile->{metadata}[$i]{value}{markdown} ); } $self->render( 'edit_profile', name => $user->{name} ); } sub insight { my ($self) = @_; Loading
lib/Travelynx/Controller/Profile.pm +48 −8 Original line number Diff line number Diff line Loading @@ -70,6 +70,30 @@ sub profile { return; } my $profile = $self->users->get_profile( uid => $user->{id} ); my $my_user; my $relation; my $inverse_relation; my $is_self; if ( $self->is_user_authenticated ) { $my_user = $self->current_user; if ( $my_user->{id} == $user->{id} ) { $is_self = 1; $my_user = undef; } else { $relation = $self->users->get_relation( subject => $my_user->{id}, object => $user->{id} ); $inverse_relation = $self->users->get_relation( subject => $user->{id}, object => $my_user->{id} ); } } my $status = $self->get_user_status( $user->{id} ); my $visibility; if ( $status->{checked_in} or $status->{arr_name} ) { Loading @@ -84,7 +108,12 @@ sub profile { and $self->status_token_ok($status) ) or ( $visibility eq 'travelynx' and ( $self->is_user_authenticated and ( $my_user or $self->status_token_ok($status) ) ) or ( $visibility eq 'followers' and ( ( $relation and $relation eq 'follows' ) or $self->status_token_ok($status) ) ) ) Loading @@ -104,7 +133,7 @@ sub profile { my @journeys; if ( $user->{past_visible} == 2 or ( $user->{past_visible} == 1 and $self->is_user_authenticated ) ) or ( $user->{past_visible} == 1 and $my_user ) ) { my %opt = ( Loading @@ -122,7 +151,10 @@ sub profile { if ( $user->{default_visibility_str} eq 'public' or ( $user->{default_visibility_str} eq 'travelynx' and $self->is_user_authenticated ) and $my_user ) or ( $user->{default_visibility_str} eq 'followers' and $relation and $relation eq 'follows' ) ) { $opt{with_default_visibility} = 1; Loading @@ -131,9 +163,14 @@ sub profile { $opt{with_default_visibility} = 0; } if ( $self->is_user_authenticated ) { if ($my_user) { if ( $relation and $relation eq 'follows' ) { $opt{min_visibility} = 'followers'; } else { $opt{min_visibility} = 'travelynx'; } } else { $opt{min_visibility} = 'public'; } Loading @@ -145,7 +182,10 @@ sub profile { 'profile', name => $name, uid => $user->{id}, bio => $profile->{bio}{html}, metadata => $profile->{metadata}, public_level => $user->{public_level}, is_self => $is_self, journey => $status, journey_visibility => $visibility, journeys => [@journeys], Loading
lib/Travelynx/Model/Users.pm +24 −0 Original line number Diff line number Diff line Loading @@ -750,6 +750,30 @@ sub update_webhook_status { ); } sub set_profile { my ( $self, %opt ) = @_; my $db = $opt{db} // $self->{pg}->db; my $uid = $opt{uid}; my $profile = $opt{profile}; $db->update( 'users', { profile => JSON->new->encode($profile) }, { id => $uid } ); } sub get_profile { my ( $self, %opt ) = @_; my $db = $opt{db} // $self->{pg}->db; my $uid = $opt{uid}; return $db->select( 'users', ['profile'], { id => $uid } ) ->expand->hash->{profile}; } sub get_relation { my ( $self, %opt ) = @_; Loading
templates/account.html.ep +2 −1 Original line number Diff line number Diff line Loading @@ -73,7 +73,8 @@ <th scope="row">Sichtbarkeit</th> <td> <a href="/account/privacy"><i class="material-icons">edit</i></a> <span><i class="material-icons"><%= visibility_icon($acc->{default_visibility_str}) %></i></span> <i class="material-icons"><%= visibility_icon($acc->{default_visibility_str}) %></i> • <a href="/p/<%= $acc->{name} %>">Öffentliches Profil</a> </td> </tr> <tr> Loading