Skip to content

Commit

Permalink
Bump 20240820 (#723)
Browse files Browse the repository at this point in the history
* chore: update pnpm dependencies

* feat: dfo domain restriction

* refactor: updates to registration and invitation - add domain validation

* chore: update php dependencies

* refactor: imporve cypress tests env, handle allowed domain
  • Loading branch information
vincentauger authored Aug 21, 2024
1 parent f3144a0 commit 83e8dcf
Show file tree
Hide file tree
Showing 24 changed files with 933 additions and 761 deletions.
4 changes: 4 additions & 0 deletions .env.ci
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ APP_DEBUG=true
APP_URL=http://127.0.0.1:8000/
FRONTEND_URL=http://127.0.0.1:8000/

ALLOWED_REGISTRATION_EMAIL_DOMAINS="example.com"

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
TELESCOPE_ENABLED=false

DB_CONNECTION=sqlite

MAIL_MAILER=log

BROADCAST_DRIVER=log
CACHE_DRIVER=array
FILESYSTEM_DISK=local
Expand Down
67 changes: 0 additions & 67 deletions .env.cypress

This file was deleted.

2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ APP_DEBUG=true
APP_URL=http://localhost
FRONTEND_URL=http://localhost/

ALLOWED_REGISTRATION_EMAIL_DOMAINS=example.com

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
Expand Down
62 changes: 59 additions & 3 deletions _ide_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

/**
* A helper file for Laravel, to provide autocomplete information to your IDE
* Generated for Laravel 11.20.0.
* Generated for Laravel 11.21.0.
*
* This file should not be included in your code, only analyzed by your IDE!
*
Expand Down Expand Up @@ -1362,6 +1362,17 @@
{ //Method inherited from \Illuminate\Container\Container
/** @var \Illuminate\Foundation\Application $instance */
return $instance->build($concrete);
}
/**
* Resolve a dependency based on an attribute.
*
* @param \ReflectionAttribute $attribute
* @return mixed
* @static
*/ public static function resolveFromAttribute($attribute)
{ //Method inherited from \Illuminate\Container\Container
/** @var \Illuminate\Foundation\Application $instance */
return $instance->resolveFromAttribute($attribute);
}
/**
* Register a new before resolving callback for all types.
Expand Down Expand Up @@ -1410,6 +1421,18 @@
{ //Method inherited from \Illuminate\Container\Container
/** @var \Illuminate\Foundation\Application $instance */
$instance->afterResolvingAttribute($attribute, $callback);
}
/**
* Fire all of the after resolving attribute callbacks.
*
* @param \ReflectionAttribute[] $abstract
* @param mixed $object
* @return void
* @static
*/ public static function fireAfterResolvingAttributeCallbacks($attributes, $object)
{ //Method inherited from \Illuminate\Container\Container
/** @var \Illuminate\Foundation\Application $instance */
$instance->fireAfterResolvingAttributeCallbacks($attributes, $object);
}
/**
* Get the container's bindings.
Expand Down Expand Up @@ -6529,8 +6552,8 @@
/**
* Register an event listener with the dispatcher.
*
* @param \Closure|string|array $events
* @param \Closure|string|array|null $listener
* @param \Illuminate\Events\Queued\Closure|\Closure|string|array $events
* @param \Illuminate\Events\Queued\Closure|\Closure|string|array|null $listener
* @return void
* @static
*/ public static function listen($events, $listener = null)
Expand Down Expand Up @@ -18012,6 +18035,39 @@
{
/** @var \Illuminate\Foundation\Vite $instance */
return $instance->usePreloadTagAttributes($attributes);
}
/**
* Use the "waterfall" prefetching strategy.
*
* @param int|null $concurrency
* @return \Illuminate\Foundation\Vite
* @static
*/ public static function useWaterfallPrefetching($concurrency = null)
{
/** @var \Illuminate\Foundation\Vite $instance */
return $instance->useWaterfallPrefetching($concurrency);
}
/**
* Use the "aggressive" prefetching strategy.
*
* @return \Illuminate\Foundation\Vite
* @static
*/ public static function useAggressivePrefetching()
{
/** @var \Illuminate\Foundation\Vite $instance */
return $instance->useAggressivePrefetching();
}
/**
* Set the prefetching strategy.
*
* @param \Illuminate\Foundation\'waterfall'|\Illuminate\Foundation\'aggressive'|null $strategy
* @param array $config
* @return \Illuminate\Foundation\Vite
* @static
*/ public static function usePrefetchStrategy($strategy, $config = [])
{
/** @var \Illuminate\Foundation\Vite $instance */
return $instance->usePrefetchStrategy($strategy, $config);
}
/**
* Generate React refresh runtime script.
Expand Down
19 changes: 18 additions & 1 deletion app/Http/Controllers/Auth/InvitedUserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,44 @@
namespace App\Http\Controllers\Auth;

use App\Events\Auth\Invited;
use App\Http\Controllers\Auth\Traits\AuthorizedDomainTrait;
use App\Http\Controllers\Controller;
use App\Http\Resources\UserResource;
use App\Models\Invitation;
use App\Models\User;
use Hash;
use Illuminate\Auth\Events\Verified;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
use Str;

class InvitedUserController extends Controller
{

use AuthorizedDomainTrait;

public function invite(Request $request): UserResource
{

// validate the request
$validated = $request->validate([
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => 'bail|required|email|unique:users,email',
'email' => 'bail|required|email',
'locale' => 'string|in:en,fr',
]);

$validated['email'] = strtolower($validated['email']);

$this->validateEmailDomain($validated['email']);

// does the user already exist?
if (User::where('email', $validated['email'])->exists()) {
throw ValidationException::withMessages([
'email' => __('The account already exists'),
]);
}

// generate random 20 char password string
$password = Str::password(20);

Expand Down
20 changes: 13 additions & 7 deletions app/Http/Controllers/Auth/RegisteredUserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Auth\Traits\AuthorizedDomainTrait;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Traits\LocaleTrait;
Expand All @@ -10,10 +11,12 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;

class RegisteredUserController extends Controller
{
use LocaleTrait;
use AuthorizedDomainTrait;

/**
* Handle an incoming registration request.
Expand All @@ -24,9 +27,6 @@ public function store(Request $request): JsonResponse
{
$this->setLocaleFromRequest($request);

// request email to lowercase - ensure no duplicate emails
$request->merge(['email' => strtolower($request->email)]);

$validated = $request->validate([
'first_name' => ['required', 'string', 'max:255'],
'last_name' => ['required', 'string', 'max:255'],
Expand All @@ -35,24 +35,31 @@ public function store(Request $request): JsonResponse
'locale' => ['string', 'max:2', 'in:en,fr'],
]);

// request email to lowercase - ensure no duplicate emails
$validated['email'] = strtolower($validated['email']);

// check if the email domain is part of the allowed domains
$this->validateEmailDomain($validated['email']);

// check if the user already exists
$user = User::where('email', $validated['email'])->first();
if ($user) {
// User exits and does not have an invitation or is active (has registered)
if ($user->active) {
$request->validate([
'email' => ['unique:users'],
throw ValidationException::withMessages(
['account' => __('Problem with registration, please contact support')
]);
throw new \Exception('User already exists');
}

// User exists but is not active (has not registered), so update the user
// with the new password.
$user->password = Hash::make($validated['password']);
$user->active = true;
$user->save();

} else {
$user = User::create([

'first_name' => $validated['first_name'],
'last_name' => $validated['last_name'],
'email' => $validated['email'],
Expand All @@ -63,7 +70,6 @@ public function store(Request $request): JsonResponse

$user->email_verification_token = User::generateEmailVerificationToken();
$user->save();
//$user->refresh();
$user->associateAuthor();

// give the user the author role - this is the default role
Expand Down
41 changes: 41 additions & 0 deletions app/Http/Controllers/Auth/Traits/AuthorizedDomainTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace App\Http\Controllers\Auth\Traits;

use Illuminate\Validation\ValidationException;

trait AuthorizedDomainTrait
{
/**
* Check if the email domain is part of the allowed domains
*
* @param string $email
* @return bool
*/
public function isEmailDomainAllowed(string $email): bool
{
$allowedDomains = config('osp.allowed_registration_email_domains');

if ($allowedDomains) {
$emailDomain = explode('@', $email)[1];
if (! in_array($emailDomain, $allowedDomains)) {
return false;
}
}

return true;
}

/**
* Validate the email domain and throw validation
* exception if not allowed
*/
public function validateEmailDomain(string $email): void
{
if (! $this->isEmailDomainAllowed($email)) {
throw ValidationException::withMessages([
'email' => __('Email domain not allowed')
]);
}
}
}
2 changes: 0 additions & 2 deletions app/Http/Controllers/Orcid/FullFlowController.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ public function callback(Request $request): RedirectResponse
$scope = $response->json('scope');
$orcid = $response->json('orcid');

// we shoudl be able to use the access token to get the user's ORCID iD
//$orcid = $this->getOrcidId($accessToken);

CauserResolver::setCauser($user);

Expand Down
Loading

0 comments on commit 83e8dcf

Please sign in to comment.