Skip to content

Commit

Permalink
Feat: confidentiality labels (#727)
Browse files Browse the repository at this point in the history
* refactor: add sensitivity label to User and Media models
* chore: pint format
* feat: add sensitivity label to profile and manuscript
  • Loading branch information
vincentauger authored Aug 22, 2024
1 parent 83e8dcf commit 408f51e
Show file tree
Hide file tree
Showing 68 changed files with 337 additions and 216 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,30 @@ The commit message should be structured as follows:
'test'
]
```

## Running Tests Locally

### Backend Tests

```sh
php artisan test
```

### Frontend Tests

We use Cypress for the front-end E2E tests. It must run with the
`env.ci` environment.

Before starting the test, start the dev server. For the frontend,
you can either use `pnpnm dev` or `pnmp build`. In most cases, `dev`
is better as changes to the code can instantently be tested again.

```sh
pnpm dev
php artisan server --env=ci
```

Once the local server is up and running, you can launch Cypress
with `pnpm cy:open` or just run the tests with `pnpm cy:run`

If using WSL, you will need to follow this [guide](https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps) first.
32 changes: 32 additions & 0 deletions app/Enums/SensitivityLabel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Enums;

use Illuminate\Support\Facades\App;

enum SensitivityLabel: string
{
case Unclassified = 'Unclassified';
case ProtectedA = 'Protected A';

public function translate(?string $locale = null): string
{

collect(['en', 'fr'])->contains($locale) ?: $locale = null;
if ($locale == null) {
$locale = App::getLocale();
}

return match ($locale) {
'en' => match ($this->value) {
'Unclassified' => 'Unclassified',
'Protected A' => 'Protected A',
},
'fr' => match ($this->value) {
'Unclassified' => 'Non classifié',
'Protected A' => 'Protégé A',
},
default => $this->value,
};
}
}
4 changes: 1 addition & 3 deletions app/Events/ItemShared.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ class ItemShared
/**
* Create a new event instance.
*/
public function __construct(public Shareable $shareableItem)
{
}
public function __construct(public Shareable $shareableItem) {}

/**
* Get the channels the event should broadcast on.
Expand Down
4 changes: 1 addition & 3 deletions app/Events/ManagementReviewStepCreated.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class ManagementReviewStepCreated
*
* @return void
*/
public function __construct(public ManagementReviewStep $managementReviewStep)
{
}
public function __construct(public ManagementReviewStep $managementReviewStep) {}

/**
* Get the channels the event should broadcast on.
Expand Down
4 changes: 1 addition & 3 deletions app/Events/ManuscriptManagementReviewComplete.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class ManuscriptManagementReviewComplete
*
* @return void
*/
public function __construct(public ManuscriptRecord $manuscriptRecord)
{
}
public function __construct(public ManuscriptRecord $manuscriptRecord) {}

/**
* Get the channels the event should broadcast on.
Expand Down
4 changes: 1 addition & 3 deletions app/Events/ManuscriptRecordToReviewEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ class ManuscriptRecordToReviewEvent
*
* @return void
*/
public function __construct(public ManuscriptRecord $manuscriptRecord, public User $divisionManagerUser)
{
}
public function __construct(public ManuscriptRecord $manuscriptRecord, public User $divisionManagerUser) {}

/**
* Get the channels the event should broadcast on.
Expand Down
4 changes: 1 addition & 3 deletions app/Events/ManuscriptRecordWithdrawnByAuthor.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class ManuscriptRecordWithdrawnByAuthor
*
* @return void
*/
public function __construct(public ManuscriptRecord $manuscriptRecord)
{
}
public function __construct(public ManuscriptRecord $manuscriptRecord) {}

/**
* Get the channels the event should broadcast on.
Expand Down
4 changes: 1 addition & 3 deletions app/Events/ManuscriptRecordWithheldByManagement.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class ManuscriptRecordWithheldByManagement
*
* @return void
*/
public function __construct(public ManuscriptRecord $manuscriptRecord)
{
}
public function __construct(public ManuscriptRecord $manuscriptRecord) {}

/**
* Get the channels the event should broadcast on.
Expand Down
1 change: 0 additions & 1 deletion app/Http/Controllers/Auth/InvitedUserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

class InvitedUserController extends Controller
{

use AuthorizedDomainTrait;

public function invite(Request $request): UserResource
Expand Down
6 changes: 3 additions & 3 deletions app/Http/Controllers/Auth/RegisteredUserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

class RegisteredUserController extends Controller
{
use LocaleTrait;
use AuthorizedDomainTrait;
use LocaleTrait;

/**
* Handle an incoming registration request.
Expand Down Expand Up @@ -47,8 +47,8 @@ public function store(Request $request): JsonResponse
// User exits and does not have an invitation or is active (has registered)
if ($user->active) {
throw ValidationException::withMessages(
['account' => __('Problem with registration, please contact support')
]);
['account' => __('Problem with registration, please contact support'),
]);
}

// User exists but is not active (has not registered), so update the user
Expand Down
11 changes: 4 additions & 7 deletions app/Http/Controllers/Auth/Traits/AuthorizedDomainTrait.php
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
<?php

namespace App\Http\Controllers\Auth\Traits;
namespace App\Http\Controllers\Auth\Traits;

use Illuminate\Validation\ValidationException;

trait AuthorizedDomainTrait
trait AuthorizedDomainTrait
{
/**
* Check if the email domain is part of the allowed domains
*
* @param string $email
* @return bool
*/
public function isEmailDomainAllowed(string $email): bool
{
Expand All @@ -34,8 +31,8 @@ public function validateEmailDomain(string $email): void
{
if (! $this->isEmailDomainAllowed($email)) {
throw ValidationException::withMessages([
'email' => __('Email domain not allowed')
'email' => __('Email domain not allowed'),
]);
}
}
}
}
10 changes: 5 additions & 5 deletions app/Http/Controllers/ManagementReviewStepController.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function approve(Request $request, ManuscriptRecord $manuscriptRecord, Ma
'comments' => 'required|string',
])->validate();

$nextReviewStep = new ManagementReviewStep();
$nextReviewStep = new ManagementReviewStep;
$nextReviewStep->user_id = $validated['next_user_id'];
$nextReviewStep->status = ManagementReviewStepStatus::PENDING;
$nextReviewStep->decision = ManagementReviewStepDecision::NONE;
Expand Down Expand Up @@ -124,7 +124,7 @@ public function withhold(Request $request, ManuscriptRecord $manuscriptRecord, M

// if the next user is not set, then the review is complete and the manuscript review is complete.
if (isset($validated['next_user_id'])) {
$nextReviewStep = new ManagementReviewStep();
$nextReviewStep = new ManagementReviewStep;
$nextReviewStep->user_id = $validated['next_user_id'];
$nextReviewStep->status = ManagementReviewStepStatus::PENDING;
$nextReviewStep->decision = ManagementReviewStepDecision::NONE;
Expand Down Expand Up @@ -172,7 +172,7 @@ public function reassign(Request $request, ManuscriptRecord $manuscriptRecord, M
'comments' => 'required|string',
])->validate();

$nextReviewStep = new ManagementReviewStep();
$nextReviewStep = new ManagementReviewStep;
$nextReviewStep->user_id = $validated['next_user_id'];
$nextReviewStep->status = ManagementReviewStepStatus::PENDING;
$nextReviewStep->decision = ManagementReviewStepDecision::NONE;
Expand Down Expand Up @@ -207,7 +207,7 @@ public function flag(Request $request, ManuscriptRecord $manuscriptRecord, Manag
'comments' => 'required|string',
])->validate();

$nextReviewStep = new ManagementReviewStep();
$nextReviewStep = new ManagementReviewStep;
$nextReviewStep->user_id = $manuscriptRecord->user_id;
$nextReviewStep->status = ManagementReviewStepStatus::ON_HOLD;
$nextReviewStep->decision = ManagementReviewStepDecision::NONE;
Expand Down Expand Up @@ -244,7 +244,7 @@ public function flaggedResponse(Request $request, ManuscriptRecord $manuscriptRe
'comments' => 'required|string',
])->validate();

$nextReviewStep = new ManagementReviewStep();
$nextReviewStep = new ManagementReviewStep;
$nextReviewStep->user_id = $previousStep->user_id;
$nextReviewStep->status = ManagementReviewStepStatus::PENDING;
$nextReviewStep->decision = ManagementReviewStepDecision::NONE;
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/ManuscriptAuthorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function store(Request $request, ManuscriptRecord $manuscriptRecord): Jso

$author = Author::find($validated['author_id']);

$manuscriptAuthor = new ManuscriptAuthor();
$manuscriptAuthor = new ManuscriptAuthor;
$manuscriptAuthor->manuscript_record_id = $manuscriptRecord->id;
$manuscriptAuthor->author_id = $validated['author_id'];
$manuscriptAuthor->is_corresponding_author = $validated['is_corresponding_author'] ?? false;
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/ManuscriptRecordController.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public function submitForReview(Request $request, ManuscriptRecord $manuscriptRe
$reviewUser = User::findOrFail($validated['reviewer_user_id']);

// create the first management review step for this record
$reviewStep = new ManagementReviewStep();
$reviewStep = new ManagementReviewStep;
$reviewStep->manuscript_record_id = $manuscriptRecord->id;
$reviewStep->decision_expected_by = now()->addBusinessDays(config('osp.management_review.decision_expected_business_days'));
$reviewStep->user_id = $reviewUser->id;
Expand Down
19 changes: 11 additions & 8 deletions app/Http/Controllers/Orcid/FullFlowController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class FullFlowController

public function callback(Request $request): RedirectResponse
{
Log::debug("Callback from ORCID");
Log::debug('Callback from ORCID');
Log::debug($request->all());

$frontendUrl = config('app.frontend_url');
Expand All @@ -37,7 +37,8 @@ public function callback(Request $request): RedirectResponse

if (! Cache::has($validated['key'])) {
Log::error('Invalid key for ORCID callback');
$url = $frontendUrl . '#/auth/orcid-callback?status=invalid-key';
$url = $frontendUrl.'#/auth/orcid-callback?status=invalid-key';

return redirect($url);
}

Expand All @@ -47,7 +48,8 @@ public function callback(Request $request): RedirectResponse

if (! $user) {
Log::error('Invalid user for ORCID callback');
$url = $frontendUrl . '#/auth/orcid-callback?status=invalid-user';
$url = $frontendUrl.'#/auth/orcid-callback?status=invalid-user';

return redirect($url);
}

Expand All @@ -70,7 +72,8 @@ public function callback(Request $request): RedirectResponse
if ($response->failed()) {
Log::error('Failed to get access token from ORCID');
Log::debug($response->body());
return redirect($frontendUrl . '#/auth/orcid-callback?status=failed');

return redirect($frontendUrl.'#/auth/orcid-callback?status=failed');
}

Log::info('Access token received from ORCID');
Expand All @@ -80,20 +83,19 @@ public function callback(Request $request): RedirectResponse
$scope = $response->json('scope');
$orcid = $response->json('orcid');


CauserResolver::setCauser($user);

$author = $user->author;

$author->orcid = 'https://' . $baseUrl . '/' . $orcid;
$author->orcid = 'https://'.$baseUrl.'/'.$orcid;
$author->orcid_access_token = $accessToken;
$author->orcid_token_scope = $scope;
$author->orcid_refresh_token = $refreshToken;
$author->orcid_verified = true;
$author->orcid_expires_at = now()->addSeconds($expiresIn);
$author->save();

return redirect($frontendUrl . '#/auth/orcid-callback?status=success');
return redirect($frontendUrl.'#/auth/orcid-callback?status=success');
}

/**
Expand All @@ -118,7 +120,7 @@ public function redirect(Request $request): RedirectResponse
Cache::add($key, Auth::id(), now()->addMinutes(15));

// add key to redirect URI
$redirectURI .= '?key=' . $key;
$redirectURI .= '?key='.$key;

// encode URI - if it's not encoded, ORCID will returns to base URL
$encoded = urlencode($redirectURI);
Expand All @@ -131,6 +133,7 @@ public function redirect(Request $request): RedirectResponse

Log::info('Redirecting to ORCID for authorization');
Log::debug($link);

// redirect to ORCID
return redirect($link);
}
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/PublicationAuthorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function store(Request $request, Publication $publication): JsonResource

$author = Author::find($validated['author_id']);

$publicationAuthor = new PublicationAuthor();
$publicationAuthor = new PublicationAuthor;
$publicationAuthor->publication_id = $publication->id;
$publicationAuthor->author_id = $validated['author_id'];
$publicationAuthor->is_corresponding_author = $validated['is_corresponding_author'] ?? false;
Expand Down
3 changes: 1 addition & 2 deletions app/Http/Integrations/Orcid/OrcidMemberAPIConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ class OrcidMemberAPIConnector extends Connector
public function __construct(
protected readonly string $bearerToken,
protected readonly string $orcid
) {
}
) {}

/**
* The Base URL of the Member API this will use the sandbox if
Expand Down
3 changes: 1 addition & 2 deletions app/Http/Integrations/Orcid/Requests/GetPersonalInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ class GetPersonalInfo extends Request

public function __construct(
protected PersonalInfoEndpoints $endpoint
) {
}
) {}

/**
* The endpoint for the request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ class GetPersonalInfoRequest extends Request
*/
public function __construct(
protected PersonalInfoEndpoints $endpoint = PersonalInfoEndpoints::PERSON
) {
}
) {}

/**
* The endpoint for the request
Expand Down
Loading

0 comments on commit 408f51e

Please sign in to comment.