-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make iThenticate reports work with new TCA integration #172
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
; Used by CopyPatrolBot, which populates the database that gets feed into the frontend. | ||
; For more information, see https://github.com/JJMC89/copypatrol-backend#configuration | ||
[copypatrol] | ||
version = 2023.08.10 | ||
url-ignore-list-title = example-url-title | ||
user-ignore-list-title = example-user-title | ||
|
||
[copypatrol:en.wikipedia.org] | ||
enabled = true | ||
namespaces = 0,2,118 | ||
pagetriage-namespaces = 0,118 | ||
|
||
[copypatrol:es.wikipedia.org] | ||
enabled = true | ||
namespaces = 0,2 | ||
|
||
[copypatrol:fr.wikipedia.org] | ||
enabled = false | ||
|
||
[client] | ||
drivername = mysql+pymysql | ||
username = example-db-user | ||
password = example-db-password | ||
database = example-db-name | ||
host = localhost | ||
port = 3306 | ||
|
||
[tca] | ||
domain = example-tca-domain.com | ||
key = example-tca-key |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
.idea/ | ||
.copypatrol.ini | ||
|
||
###> symfony/framework-bundle ### | ||
/.env.local | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
use DateTime; | ||
use Doctrine\DBAL\Exception\DriverException; | ||
use Exception; | ||
use Krinkle\Intuition\Intuition; | ||
use PhpXmlRpc\Client; | ||
use PhpXmlRpc\Value; | ||
use stdClass; | ||
|
@@ -18,8 +19,10 @@ | |
use Symfony\Component\HttpFoundation\RequestStack; | ||
use Symfony\Component\HttpFoundation\Response; | ||
use Symfony\Component\HttpFoundation\Session\SessionInterface; | ||
use Symfony\Component\HttpKernel\Exception\HttpException; | ||
// phpcs:ignore MediaWiki.Classes.UnusedUseStatement.UnusedUse | ||
use Symfony\Component\Routing\Annotation\Route; | ||
use Symfony\Contracts\HttpClient\HttpClientInterface; | ||
|
||
class AppController extends AbstractController { | ||
|
||
|
@@ -278,26 +281,39 @@ public function undoReviewAction( | |
} | ||
|
||
/** | ||
* @Route("/ithenticate/{id}", name="ithenticate", requirements={"id"="\d+|[a-z\d+\-]"}) | ||
* @Route("/ithenticate/{id}", name="ithenticate", requirements={"id"="\d+|[a-z\d+\-]+"}) | ||
* @param HttpClientInterface $httpClient | ||
* @param RequestStack $requestStack | ||
* @param CopyPatrolRepository $copyPatrolRepo | ||
* @param Intuition $intuition | ||
* @param string $iThenticateUser | ||
* @param string $iThenticatePassword | ||
* @param int $id | ||
* @param string $id | ||
* @return RedirectResponse | ||
* @throws Exception | ||
*/ | ||
public function iThenticateAction( | ||
HttpClientInterface $httpClient, | ||
RequestStack $requestStack, | ||
CopyPatrolRepository $copyPatrolRepo, | ||
Intuition $intuition, | ||
string $iThenticateUser, | ||
string $iThenticatePassword, | ||
int $id | ||
string $id | ||
): RedirectResponse { | ||
$record = $copyPatrolRepo->getRecordById( $id ); | ||
$v2DateTime = new DateTime( self::ITHENTICATE_V2_TIMESTAMP ); | ||
if ( new DateTime( $record['rev_timestamp'] ) > $v2DateTime ) { | ||
// New system | ||
// TODO: make this work | ||
return new RedirectResponse( '' ); | ||
// New system. | ||
$loggedInUser = $requestStack->getSession()->get( 'logged_in_user' )->username; | ||
if ( $loggedInUser === null ) { | ||
return $this->redirectToRoute( 'toolforge_login', [ | ||
'callback' => $this->generateUrl( 'toolforge_oauth_callback', [ | ||
'redirect' => $requestStack->getCurrentRequest()->getUri(), | ||
] ) | ||
] ); | ||
} | ||
return $this->redirectToTcaViewer( $httpClient, $loggedInUser, $intuition->getLang(), $id ); | ||
} | ||
|
||
$client = new Client( 'https://api.ithenticate.com/rpc' ); | ||
|
@@ -315,6 +331,63 @@ public function iThenticateAction( | |
return $this->redirect( $response['view_only_url']->scalarval() ); | ||
} | ||
|
||
/** | ||
* @param HttpClientInterface $client | ||
* @param string $loggedInUser | ||
* @param string $locale | ||
* @param string $id | ||
* @param int $retries | ||
* @return RedirectResponse | ||
*/ | ||
private function redirectToTcaViewer( | ||
HttpClientInterface $client, | ||
string $loggedInUser, | ||
string $locale, | ||
string $id, | ||
int $retries = 0 | ||
): RedirectResponse { | ||
// Load config settings. This lives in .copypatrol.ini and is shared with the bot. | ||
$projectDir = $this->getParameter( 'kernel.project_dir' ); | ||
$config = parse_ini_file( "$projectDir/.copypatrol.ini" ); | ||
// Request the viewer URL from Turnitin. | ||
$response = $client->request( | ||
'POST', | ||
"https://{$config['domain']}/api/v1/submissions/$id/viewer-url", | ||
[ | ||
'json' => [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider whether any There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added |
||
'viewer_user_id' => $loggedInUser, | ||
'locale' => $locale, | ||
'viewer_permissions' => [ | ||
'may_view_submission_full_source' => true, | ||
'may_view_match_submission_info' => true, | ||
'may_view_document_details_panel' => true, | ||
'may_view_sections_exclusion_panel' => true, | ||
], | ||
], | ||
'headers' => [ | ||
'Authorization' => "Bearer {$config['key']}", | ||
'From' => '[email protected]', | ||
'User-Agent' => "copypatrol/{$config['version']}", | ||
MusikAnimal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'X-Turnitin-Integration-Name' => 'CopyPatrol', | ||
'X-Turnitin-Integration-Version' => $config['version'], | ||
], | ||
] | ||
); | ||
|
||
if ( $response->getStatusCode() !== Response::HTTP_OK ) { | ||
if ( $retries > 5 ) { | ||
throw new HttpException( | ||
Response::HTTP_BAD_GATEWAY, | ||
'Failed to fetch URL from the Turnitin Core API' | ||
); | ||
} | ||
sleep( $retries + 1 ); | ||
return $this->redirectToTcaViewer( $client, $loggedInUser, $locale, $id, $retries + 1 ); | ||
} | ||
|
||
return $this->redirect( json_decode( $response->getContent() )->viewer_url ); | ||
} | ||
|
||
/** | ||
* ToolforgeBundle's logout apparently doesn't work :( | ||
* | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TCA can be down (e.g., maintenance). Does this need any special handling for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added automatic retries up to 5 times. I'm only checking if the response from Turnitin is not 200, so it's possible we'll needlessly retry when it's something on our end (i.e. bad credentials), but regardless we'll get an email (once I set that up) so we'll be able to diagnose and fix accordingly.