diff --git a/CHANGELOG.md b/CHANGELOG.md index 1857179..cc037b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ v2.0 - Fix FLEXIAPI-321 Disable the account creation button when the Space is full for admins - Fix FLEXIAPI-322 Api Keys documentation - Fix FLEXIAPI-328 Set realm on Space creation, limit the update if some accounts are present +- Fix FLEXIAPI-325 Add endpoints to send the password reset and provisioning emails v1.6 ---- diff --git a/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php b/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php index 65afd37..f2b6482 100644 --- a/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php +++ b/flexiapi/app/Http/Controllers/Api/Admin/AccountController.php @@ -21,14 +21,19 @@ namespace App\Http\Controllers\Api\Admin; use App\Http\Controllers\Controller; use Illuminate\Http\Request; +use Illuminate\Support\Str; use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Mail; use App\Account; use App\AccountTombstone; use App\AccountType; use App\ContactsList; +use App\ResetPasswordEmailToken; use App\Http\Requests\Account\Create\Api\AsAdminRequest; use App\Http\Requests\Account\Update\Api\AsAdminRequest as ApiAsAdminRequest; +use App\Mail\Provisioning; +use App\Mail\ResetPassword; use App\Services\AccountService; use App\Space; @@ -198,4 +203,36 @@ class AccountController extends Controller return Account::findOrFail($accountId)->contactsLists()->detach($contactsListId); } + + /** + * Emails + */ + + public function sendProvisioningEmail(int $accountId) + { + $account = Account::findOrFail($accountId); + + if (!$account->email) abort(403, 'No email configured'); + + $account->provision(); + + Mail::to($account)->send(new Provisioning($account)); + + Log::channel('events')->info('API: Sending provisioning email', ['id' => $account->identifier]); + } + + public function sendResetPasswordEmail(int $accountId) + { + $account = Account::findOrFail($accountId); + + if (!$account->email) abort(403, 'No email configured'); + + $resetPasswordEmail = new ResetPasswordEmailToken; + $resetPasswordEmail->account_id = $account->id; + $resetPasswordEmail->token = Str::random(16); + $resetPasswordEmail->email = $account->email; + $resetPasswordEmail->save(); + + Mail::to($account)->send(new ResetPassword($account)); + } } diff --git a/flexiapi/resources/views/api/documentation_markdown.blade.php b/flexiapi/resources/views/api/documentation_markdown.blade.php index 0e777bf..f7d5403 100644 --- a/flexiapi/resources/views/api/documentation_markdown.blade.php +++ b/flexiapi/resources/views/api/documentation_markdown.blade.php @@ -501,6 +501,16 @@ Unblock an account. Provision an account by generating a fresh `provisioning_token`. +### `POST /accounts/{id}/send_provisioning_email` +Admin + +Send a provisioning email to the account. + +### `POST /accounts/{id}/send_reset_password_email` +Admin + +Send a password reset email to the account. + ## Accounts email ### `POST /accounts/me/email/request` diff --git a/flexiapi/routes/api.php b/flexiapi/routes/api.php index 3981c4f..ec4b468 100644 --- a/flexiapi/routes/api.php +++ b/flexiapi/routes/api.php @@ -118,6 +118,8 @@ Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blo Route::post('{account_id}/block', 'block'); Route::post('{account_id}/unblock', 'unblock'); Route::get('{account_id}/provision', 'provision'); + Route::post('{account_id}/send_provisioning_email', 'sendProvisioningEmail'); + Route::post('{account_id}/send_reset_password_email', 'sendResetPasswordEmail'); Route::post('/', 'store'); Route::put('{account_id}', 'update'); diff --git a/flexiapi/tests/Feature/ApiAccountTest.php b/flexiapi/tests/Feature/ApiAccountTest.php index cbb5e94..bd8a3d5 100644 --- a/flexiapi/tests/Feature/ApiAccountTest.php +++ b/flexiapi/tests/Feature/ApiAccountTest.php @@ -669,6 +669,49 @@ class ApiAccountTest extends TestCase ->json('GET', '/api/accounts/me'); } + public function testSendProvisioningEmail() + { + $password = Password::factory()->create(); + $account = $password->account; + + $admin = Account::factory()->admin()->create(); + $admin->generateUserApiKey(); + $admin->save(); + + $this->keyAuthenticated($admin) + ->json('POST', $this->route . '/' . $account->id . '/send_provisioning_email') + ->assertStatus(403); + + $account->email = 'test@email.com'; + $account->save(); + + $this->keyAuthenticated($admin) + ->json('POST', $this->route . '/' . $account->id . '/send_provisioning_email') + ->assertStatus(200); + } + + public function testSendResetPasswordEmail() + { + $password = Password::factory()->create(); + $account = $password->account; + + $admin = Account::factory()->admin()->create(); + $admin->generateUserApiKey(); + $admin->save(); + + $this->keyAuthenticated($admin) + ->json('POST', $this->route . '/' . $account->id . '/send_reset_password_email') + ->assertStatus(403); + + $account->email = 'test@email.com'; + $account->save(); + + $this->keyAuthenticated($admin) + ->json('POST', $this->route . '/' . $account->id . '/send_reset_password_email') + ->assertStatus(200); + } + + public function testEditAdmin() { $password = Password::factory()->create();