Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
93.33% |
56 / 60 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
LogHandler | |
93.33% |
56 / 60 |
|
66.67% |
2 / 3 |
12.04 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
factory | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
getInfo | |
90.00% |
36 / 40 |
|
0.00% |
0 / 1 |
10.10 |
1 | <?php |
2 | |
3 | namespace MediaWiki\IPInfo\Rest\Handler; |
4 | |
5 | use DatabaseLogEntry; |
6 | use JobQueueGroup; |
7 | use LogEventsList; |
8 | use LogPage; |
9 | use MediaWiki\IPInfo\InfoManager; |
10 | use MediaWiki\IPInfo\Rest\Presenter\DefaultPresenter; |
11 | use MediaWiki\Languages\LanguageFallback; |
12 | use MediaWiki\Permissions\PermissionManager; |
13 | use MediaWiki\Rest\LocalizedHttpException; |
14 | use MediaWiki\User\Options\UserOptionsLookup; |
15 | use MediaWiki\User\UserFactory; |
16 | use Wikimedia\IPUtils; |
17 | use Wikimedia\Message\MessageValue; |
18 | use Wikimedia\Rdbms\IConnectionProvider; |
19 | |
20 | class LogHandler extends IPInfoHandler { |
21 | |
22 | private IConnectionProvider $dbProvider; |
23 | |
24 | public function __construct( |
25 | InfoManager $infoManager, |
26 | IConnectionProvider $dbProvider, |
27 | PermissionManager $permissionManager, |
28 | UserOptionsLookup $userOptionsLookup, |
29 | UserFactory $userFactory, |
30 | DefaultPresenter $presenter, |
31 | JobQueueGroup $jobQueueGroup, |
32 | LanguageFallback $languageFallback |
33 | ) { |
34 | parent::__construct( |
35 | $infoManager, |
36 | $permissionManager, |
37 | $userOptionsLookup, |
38 | $userFactory, |
39 | $presenter, |
40 | $jobQueueGroup, |
41 | $languageFallback, |
42 | ); |
43 | $this->dbProvider = $dbProvider; |
44 | } |
45 | |
46 | /** |
47 | * @param InfoManager $infoManager |
48 | * @param IConnectionProvider $dbProvider |
49 | * @param PermissionManager $permissionManager |
50 | * @param UserOptionsLookup $userOptionsLookup |
51 | * @param UserFactory $userFactory |
52 | * @param JobQueueGroup $jobQueueGroup |
53 | * @param LanguageFallback $languageFallback |
54 | * @return self |
55 | */ |
56 | public static function factory( |
57 | InfoManager $infoManager, |
58 | IConnectionProvider $dbProvider, |
59 | PermissionManager $permissionManager, |
60 | UserOptionsLookup $userOptionsLookup, |
61 | UserFactory $userFactory, |
62 | JobQueueGroup $jobQueueGroup, |
63 | LanguageFallback $languageFallback |
64 | ) { |
65 | return new self( |
66 | $infoManager, |
67 | $dbProvider, |
68 | $permissionManager, |
69 | $userOptionsLookup, |
70 | $userFactory, |
71 | new DefaultPresenter( $permissionManager ), |
72 | $jobQueueGroup, |
73 | $languageFallback |
74 | ); |
75 | } |
76 | |
77 | /** @inheritDoc */ |
78 | protected function getInfo( int $id ): array { |
79 | $dbr = $this->dbProvider->getReplicaDatabase(); |
80 | $entry = DatabaseLogEntry::newFromId( $id, $dbr ); |
81 | |
82 | if ( !$entry ) { |
83 | throw new LocalizedHttpException( |
84 | new MessageValue( 'ipinfo-rest-log-nonexistent' ), |
85 | 404 |
86 | ); |
87 | } |
88 | |
89 | if ( !LogEventsList::userCanViewLogType( $entry->getType(), $this->getAuthority() ) ) { |
90 | throw new LocalizedHttpException( |
91 | new MessageValue( 'ipinfo-rest-log-denied' ), |
92 | 403 |
93 | ); |
94 | } |
95 | |
96 | // A log entry logs an action performed by a performer, on a target. Either the |
97 | // performer, or the target may be an IP address. This returns info about whichever is an |
98 | // IP address, or both, if both are IP addresses. |
99 | $canAccessPerformer = LogEventsList::userCanBitfield( $entry->getDeleted(), LogPage::DELETED_USER, |
100 | $this->getAuthority() ); |
101 | $canAccessTarget = LogEventsList::userCanBitfield( $entry->getDeleted(), LogPage::DELETED_ACTION, |
102 | $this->getAuthority() ); |
103 | |
104 | // If the user cannot access the performer, nor the target, throw an error since there won't |
105 | // be anything to respond with. |
106 | if ( !$canAccessPerformer && !$canAccessTarget ) { |
107 | throw new LocalizedHttpException( |
108 | new MessageValue( 'ipinfo-rest-log-denied' ), |
109 | 403 |
110 | ); |
111 | } |
112 | |
113 | $performer = $entry->getPerformerIdentity()->getName(); |
114 | |
115 | // The target of a log entry may be an IP address. Targets are stored as titles. |
116 | $target = $entry->getTarget()->getText(); |
117 | |
118 | $info = []; |
119 | $showPerformer = IPUtils::isValid( $performer ) && $canAccessPerformer; |
120 | $showTarget = IPUtils::isValid( $target ) && $canAccessTarget; |
121 | if ( $showPerformer ) { |
122 | $info[] = $this->presenter->present( |
123 | $this->infoManager->retrieveFromIP( $performer ), |
124 | $this->getAuthority()->getUser() |
125 | ); |
126 | } |
127 | if ( $showTarget ) { |
128 | $info[] = $this->presenter->present( $this->infoManager->retrieveFromIP( $target ), |
129 | $this->getAuthority()->getUser() ); |
130 | } |
131 | |
132 | if ( count( $info ) === 0 ) { |
133 | // Since the IP address only exists in CheckUser, there is no way to access it. |
134 | // @TODO Allow extensions (like CheckUser) to either pass without a value |
135 | // (which would result in a 404) or throw a fatal (which could result in a 403). |
136 | throw new LocalizedHttpException( |
137 | new MessageValue( 'ipinfo-rest-log-registered' ), |
138 | 404 |
139 | ); |
140 | } |
141 | |
142 | return $info; |
143 | } |
144 | } |