Unverified Commit d4a64701 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

Users: support notifications about pending follow requests

parent b2feb1b6
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -1518,7 +1518,36 @@ my @migrations = (
			}
		);
	},

	# v35 -> v36
	sub {
		my ($db) = @_;
		$db->query(
			qq{
				alter table relations
					add column ts timestamptz not null;
				alter table users
					add column accept_follows smallint default 1;
				update schema_version set version = 36;
			}
		);
	},

	# v36 -> v37
	sub {
		my ($db) = @_;
		$db->query(
			qq{
				alter table users
					add column notifications smallint default 0,
					add column profile jsonb;
				update schema_version set version = 37;
			}
		);
	},
);

# TODO add 'hafas' column to in_transit (and maybe journeys? undo/redo needs something to work with...)

sub sync_stations {
	my ( $db, $iris_version ) = @_;
+131 −14
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ sub verify_registration_token {
	my $db    = $opt{db} // $self->{pg}->db;

	my $tx;

	if ( not $opt{in_transaction} ) {
		$tx = $db->begin;
	}
@@ -120,7 +119,7 @@ sub verify_registration_token {
	if ( $res->hash->{count} ) {
		$db->update( 'users', { status => 1 }, { id => $uid } );
		$db->delete( 'pending_registrations', { user_id => $uid } );
		if ( not $opt{in_transaction} ) {
		if ($tx) {
			$tx->commit;
		}
		return 1;
@@ -179,8 +178,11 @@ sub get_privacy_by {
		$where{id} = $opt{uid};
	}

	my $res = $db->select( 'users', [ 'id', 'public_level' ],
		{ %where, status => 1 } );
	my $res = $db->select(
		'users',
		[ 'id', 'public_level', 'accept_follows' ],
		{ %where, status => 1 }
	);

	if ( my $user = $res->hash ) {
		return {
@@ -193,6 +195,8 @@ sub get_privacy_by {
			past_visible           => ( $user->{public_level} & 0x300 ) >> 8,
			past_all               => $user->{public_level} & 0x400 ? 1 : 0,
			past_status            => $user->{public_level} & 0x800 ? 1 : 0,
			accept_follows         => $user->{accept_follows} == 2  ? 1 : 0,
			accept_follow_requests => $user->{accept_follows} == 1  ? 1 : 0,
		};
	}
	return;
@@ -215,6 +219,27 @@ sub set_privacy {
	$db->update( 'users', { public_level => $public_level }, { id => $uid } );
}

sub set_social {
	my ( $self, %opt ) = @_;
	my $db  = $opt{db} // $self->{pg}->db;
	my $uid = $opt{uid};

	my $accept_follows = 0;

	if ( $opt{accept_follows} ) {
		$accept_follows = 2;
	}
	elsif ( $opt{accept_follow_requests} ) {
		$accept_follows = 1;
	}

	$db->update(
		'users',
		{ accept_follows => $accept_follows },
		{ id             => $uid }
	);
}

sub mark_for_password_reset {
	my ( $self, %opt ) = @_;
	my $db    = $opt{db} // $self->{pg}->db;
@@ -373,7 +398,8 @@ sub get {

	my $user = $db->select(
		'users',
		'id, name, status, public_level, email, external_services, '
		'id, name, status, public_level, email, '
		  . 'external_services, accept_follows, notifications, '
		  . 'extract(epoch from registered_at) as registered_at_ts, '
		  . 'extract(epoch from last_seen) as last_seen_ts, '
		  . 'extract(epoch from deletion_requested) as deletion_requested_ts',
@@ -384,6 +410,9 @@ sub get {
			id                     => $user->{id},
			name                   => $user->{name},
			status                 => $user->{status},
			notifications          => $user->{notifications},
			accept_follows         => $user->{accept_follows} == 2 ? 1 : 0,
			accept_follow_requests => $user->{accept_follows} == 1 ? 1 : 0,
			is_public              => $user->{public_level},
			default_visibility     => $user->{public_level} & 0x7f,
			default_visibility_str =>
@@ -512,7 +541,6 @@ sub delete {
	my $db  = $opt{db} // $self->{pg}->db;
	my $uid = $opt{uid};
	my $tx;

	if ( not $opt{in_transaction} ) {
		$tx = $db->begin;
	}
@@ -537,7 +565,7 @@ sub delete {
		die("Deleted $res{users} rows from users, expected 1. Rolling back.\n");
	}

	if ( not $opt{in_transaction} ) {
	if ($tx) {
		$tx->commit;
	}

@@ -722,8 +750,6 @@ sub update_webhook_status {
	);
}

# TODO irgendwo muss auch noch ne einstellung rein, um follows / follow requests global zu deaktivieren

sub get_relation {
	my ( $self, %opt ) = @_;

@@ -749,6 +775,31 @@ sub get_relation {
   #	{ subject_id => [$uid, $target], object_id => [$target, $target] } )->hash;
}

sub update_notifications {
	my ( $self, %opt ) = @_;

	# must be called inside a transaction, so $opt{db} is mandatory.
	my $db  = $opt{db};
	my $uid = $opt{uid};

	my $has_follow_requests = $opt{has_follow_requests}
	  // $self->has_follow_requests(
		db  => $db,
		uid => $uid
	  );

	my $notifications
	  = $db->select( 'users', ['notifications'], { id => $uid } )
	  ->hash->{notifications};
	if ($has_follow_requests) {
		$notifications |= 0x01;
	}
	else {
		$notifications &= ~0x01;
	}
	$db->update( 'users', { notifications => $notifications }, { id => $uid } );
}

sub request_follow {
	my ( $self, %opt ) = @_;

@@ -756,14 +807,29 @@ sub request_follow {
	my $uid    = $opt{uid};
	my $target = $opt{target};

	my $tx;
	if ( not $opt{in_transaction} ) {
		$tx = $db->begin;
	}

	$db->insert(
		'relations',
		{
			subject_id => $uid,
			predicate  => $predicate_atoi{requests_follow},
			object_id  => $target,
			ts         => DateTime->now( time_zone => 'Europe/Berlin' ),
		}
	);
	$self->update_notifications(
		db                  => $db,
		uid                 => $target,
		has_follow_requests => 1,
	);

	if ($tx) {
		$tx->commit;
	}
}

sub accept_follow_request {
@@ -773,10 +839,16 @@ sub accept_follow_request {
	my $uid       = $opt{uid};
	my $applicant = $opt{applicant};

	my $tx;
	if ( not $opt{in_transaction} ) {
		$tx = $db->begin;
	}

	$db->update(
		'relations',
		{
			predicate => $predicate_atoi{follows},
			ts        => DateTime->now( time_zone => 'Europe/Berlin' ),
		},
		{
			subject_id => $applicant,
@@ -784,6 +856,14 @@ sub accept_follow_request {
			object_id  => $uid
		}
	);
	$self->update_notifications(
		db  => $db,
		uid => $uid
	);

	if ($tx) {
		$tx->commit;
	}
}

sub reject_follow_request {
@@ -793,6 +873,11 @@ sub reject_follow_request {
	my $uid       = $opt{uid};
	my $applicant = $opt{applicant};

	my $tx;
	if ( not $opt{in_transaction} ) {
		$tx = $db->begin;
	}

	$db->delete(
		'relations',
		{
@@ -801,6 +886,14 @@ sub reject_follow_request {
			object_id  => $uid
		}
	);
	$self->update_notifications(
		db  => $db,
		uid => $uid
	);

	if ($tx) {
		$tx->commit;
	}
}

sub unfollow {
@@ -837,18 +930,32 @@ sub block {
	my $uid    = $opt{uid};
	my $target = $opt{target};

	my $tx;
	if ( not $opt{in_transaction} ) {
		$tx = $db->begin;
	}

	$db->insert(
		'relations',
		{
			subject_id => $target,
			predicate  => $predicate_atoi{is_blocked_by},
			object_id  => $uid
			object_id  => $uid,
			ts         => DateTime->now( time_zone => 'Europe/Berlin' ),
		},
		{
			on_conflict => \
'(subject_id, object_id) do update set predicate = EXCLUDED.predicate'
		},
	);
	$self->update_notifications(
		db  => $db,
		uid => $uid
	);

	if ($tx) {
		$tx->commit;
	}
}

sub unblock {
@@ -891,6 +998,16 @@ sub get_follow_requests {
	return $res->hashes->each;
}

sub has_follow_requests {
	my ( $self, %opt ) = @_;

	my $db  = $opt{db} // $self->{pg}->db;
	my $uid = $opt{uid};

	return $db->select( 'follow_requests', 'count(*) as count',
		{ self_id => $uid } )->hash->{count};
}

sub get_followees {
	my ( $self, %opt ) = @_;

+46 −0
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );

$u->request_follow(
	uid    => $uid1,
@@ -110,6 +114,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 1 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        1 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       1 );
is_deeply(
	[ $u->get_follow_requests( uid => $uid2 ) ],
	[ { id => $uid1, name => 'test1' } ]
@@ -142,6 +150,8 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );

$u->request_follow(
	uid    => $uid1,
@@ -170,6 +180,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 1 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        1 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       1 );
is_deeply(
	[ $u->get_follow_requests( uid => $uid2 ) ],
	[ { id => $uid1, name => 'test1' } ]
@@ -202,6 +216,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );
is_deeply(
	[ $u->get_followers( uid => $uid2 ) ],
	[ { id => $uid1, name => 'test1' } ]
@@ -238,6 +256,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );

$u->request_follow(
	uid    => $uid1,
@@ -286,6 +308,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   1 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );
is_deeply(
	[ $u->get_blocked_users( uid => $uid2 ) ],
	[ { id => $uid1, name => 'test1' } ]
@@ -318,6 +344,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );

$u->block(
	uid    => $uid2,
@@ -346,6 +376,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   1 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );
is_deeply(
	[ $u->get_blocked_users( uid => $uid2 ) ],
	[ { id => $uid1, name => 'test1' } ]
@@ -378,6 +412,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );

$u->request_follow(
	uid    => $uid1,
@@ -410,6 +448,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );
is_deeply(
	[ $u->get_followers( uid => $uid2 ) ],
	[ { id => $uid1, name => 'test1' } ]
@@ -446,6 +488,10 @@ is( scalar $u->get_follow_requests( uid => $uid1 ), 0 );
is( scalar $u->get_follow_requests( uid => $uid2 ), 0 );
is( scalar $u->get_blocked_users( uid => $uid1 ),   0 );
is( scalar $u->get_blocked_users( uid => $uid2 ),   0 );
is( $u->has_follow_requests( uid => $uid1 ),        0 );
is( $u->has_follow_requests( uid => $uid2 ),        0 );
is( $u->get( uid => $uid1 )->{notifications},       0 );
is( $u->get( uid => $uid2 )->{notifications},       0 );

$t->app->pg->db->query('drop schema travelynx_test_21 cascade');
done_testing();