diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php
index 082d13b5d5..8cf4a02824 100644
--- a/app/Http/Controllers/Admin/UserController.php
+++ b/app/Http/Controllers/Admin/UserController.php
@@ -28,10 +28,12 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Http\Requests\InviteUserFormRequest;
use FireflyIII\Http\Requests\UserFormRequest;
+use FireflyIII\Models\InvitedUser;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
+use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
@@ -87,6 +89,24 @@ class UserController extends Controller
return view('admin.users.delete', compact('user', 'subTitle'));
}
+ /**
+ * @param InvitedUser $invitedUser
+ * @return RedirectResponse
+ */
+ public function deleteInvite(InvitedUser $invitedUser): JsonResponse
+ {
+ Log::debug('Will now delete invitation');
+ if ($invitedUser->redeemed) {
+ Log::debug('Is already redeemed.');
+ session()->flash('error', trans('firefly.invite_is_already_redeemed', ['address' => $invitedUser->email]));
+ return response()->json(['success' => false]);
+ }
+ Log::debug('Delete!');
+ session()->flash('success', trans('firefly.invite_is_deleted', ['address' => $invitedUser->email]));
+ $this->repository->deleteInvite($invitedUser);
+ return response()->json(['success' => true]);
+ }
+
/**
* Destroy a user.
*
diff --git a/app/Models/Account.php b/app/Models/Account.php
index ca00205b86..608dcdfbc6 100644
--- a/app/Models/Account.php
+++ b/app/Models/Account.php
@@ -90,7 +90,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static EloquentBuilder|Account whereVirtualBalance($value)
* @method static Builder|Account withTrashed()
* @method static Builder|Account withoutTrashed()
- * @mixin Eloquent
* @property Carbon $lastActivityDate
* @property string $startBalance
* @property string $endBalance
@@ -103,6 +102,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property string $current_debt
* @property int|null $user_group_id
* @method static EloquentBuilder|Account whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Account extends Model
{
diff --git a/app/Models/Attachment.php b/app/Models/Attachment.php
index fb1b835677..67c5a9d55b 100644
--- a/app/Models/Attachment.php
+++ b/app/Models/Attachment.php
@@ -78,9 +78,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Attachment whereUserId($value)
* @method static Builder|Attachment withTrashed()
* @method static Builder|Attachment withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Attachment whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Attachment extends Model
{
diff --git a/app/Models/AuditLogEntry.php b/app/Models/AuditLogEntry.php
index 5509e5431f..adbada0ab5 100644
--- a/app/Models/AuditLogEntry.php
+++ b/app/Models/AuditLogEntry.php
@@ -42,7 +42,6 @@ use Illuminate\Support\Carbon;
* @method static Builder|AuditLogEntry query()
* @method static \Illuminate\Database\Query\Builder|AuditLogEntry withTrashed()
* @method static \Illuminate\Database\Query\Builder|AuditLogEntry withoutTrashed()
- * @mixin Eloquent
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
@@ -65,6 +64,7 @@ use Illuminate\Support\Carbon;
* @method static Builder|AuditLogEntry whereDeletedAt($value)
* @method static Builder|AuditLogEntry whereId($value)
* @method static Builder|AuditLogEntry whereUpdatedAt($value)
+ * @mixin Eloquent
*/
class AuditLogEntry extends Model
{
diff --git a/app/Models/AvailableBudget.php b/app/Models/AvailableBudget.php
index 7b14ebf2f3..6e1fd36526 100644
--- a/app/Models/AvailableBudget.php
+++ b/app/Models/AvailableBudget.php
@@ -62,9 +62,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget whereUserId($value)
* @method static Builder|AvailableBudget withTrashed()
* @method static Builder|AvailableBudget withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget whereUserGroupId($value)
+ * @mixin Eloquent
*/
class AvailableBudget extends Model
{
diff --git a/app/Models/Bill.php b/app/Models/Bill.php
index 06533eda3b..4458013bc6 100644
--- a/app/Models/Bill.php
+++ b/app/Models/Bill.php
@@ -95,9 +95,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Bill whereUserId($value)
* @method static Builder|Bill withTrashed()
* @method static Builder|Bill withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Bill whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Bill extends Model
{
diff --git a/app/Models/Budget.php b/app/Models/Budget.php
index 91e50d746a..ff2379c88e 100644
--- a/app/Models/Budget.php
+++ b/app/Models/Budget.php
@@ -74,12 +74,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Budget whereUserId($value)
* @method static Builder|Budget withTrashed()
* @method static Builder|Budget withoutTrashed()
- * @mixin Eloquent
* @property string $email
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Budget whereUserGroupId($value)
* @property-read Collection|Note[] $notes
* @property-read int|null $notes_count
+ * @mixin Eloquent
*/
class Budget extends Model
{
diff --git a/app/Models/Category.php b/app/Models/Category.php
index 5b46982225..db4b47f7c3 100644
--- a/app/Models/Category.php
+++ b/app/Models/Category.php
@@ -68,9 +68,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Category whereUserId($value)
* @method static Builder|Category withTrashed()
* @method static Builder|Category withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Category whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Category extends Model
{
diff --git a/app/Models/CurrencyExchangeRate.php b/app/Models/CurrencyExchangeRate.php
index 446a60ab99..8197d802a1 100644
--- a/app/Models/CurrencyExchangeRate.php
+++ b/app/Models/CurrencyExchangeRate.php
@@ -60,9 +60,9 @@ use Illuminate\Support\Carbon;
* @method static Builder|CurrencyExchangeRate whereUpdatedAt($value)
* @method static Builder|CurrencyExchangeRate whereUserId($value)
* @method static Builder|CurrencyExchangeRate whereUserRate($value)
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static Builder|CurrencyExchangeRate whereUserGroupId($value)
+ * @mixin Eloquent
*/
class CurrencyExchangeRate extends Model
{
diff --git a/app/Models/InvitedUser.php b/app/Models/InvitedUser.php
index 0fac9d22c9..ec15b70ae3 100644
--- a/app/Models/InvitedUser.php
+++ b/app/Models/InvitedUser.php
@@ -30,6 +30,7 @@ use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class InvitedUser
@@ -38,7 +39,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @method static Builder|InvitedUser newModelQuery()
* @method static Builder|InvitedUser newQuery()
* @method static Builder|InvitedUser query()
- * @mixin Eloquent
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
@@ -55,6 +55,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @method static Builder|InvitedUser whereRedeemed($value)
* @method static Builder|InvitedUser whereUpdatedAt($value)
* @method static Builder|InvitedUser whereUserId($value)
+ * @mixin Eloquent
*/
class InvitedUser extends Model
{
@@ -72,4 +73,25 @@ class InvitedUser extends Model
{
return $this->belongsTo(User::class);
}
+
+ /**
+ * Route binder. Converts the key in the URL to the specified object (or throw 404).
+ *
+ * @param string $value
+ *
+ * @return WebhookAttempt
+ * @throws NotFoundHttpException
+ */
+ public static function routeBinder(string $value): InvitedUser
+ {
+ if (auth()->check()) {
+ $attemptId = (int)$value;
+ /** @var InvitedUser $attempt */
+ $attempt = self::find($attemptId);
+ if (null !== $attempt) {
+ return $attempt;
+ }
+ }
+ throw new NotFoundHttpException();
+ }
}
diff --git a/app/Models/Recurrence.php b/app/Models/Recurrence.php
index 97fb0958c5..43740a8b54 100644
--- a/app/Models/Recurrence.php
+++ b/app/Models/Recurrence.php
@@ -85,9 +85,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Recurrence whereUserId($value)
* @method static Builder|Recurrence withTrashed()
* @method static Builder|Recurrence withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Recurrence whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Recurrence extends Model
{
diff --git a/app/Models/RecurrenceTransaction.php b/app/Models/RecurrenceTransaction.php
index 8eef7928de..9969113ab2 100644
--- a/app/Models/RecurrenceTransaction.php
+++ b/app/Models/RecurrenceTransaction.php
@@ -73,10 +73,10 @@ use Illuminate\Support\Carbon;
* @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction whereUpdatedAt($value)
* @method static Builder|RecurrenceTransaction withTrashed()
* @method static Builder|RecurrenceTransaction withoutTrashed()
- * @mixin Eloquent
* @property int|null $transaction_type_id
* @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction whereTransactionTypeId($value)
* @property-read TransactionType|null $transactionType
+ * @mixin Eloquent
*/
class RecurrenceTransaction extends Model
{
diff --git a/app/Models/Rule.php b/app/Models/Rule.php
index a341663a62..e3c8d4534a 100644
--- a/app/Models/Rule.php
+++ b/app/Models/Rule.php
@@ -74,9 +74,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Rule whereUserId($value)
* @method static Builder|Rule withTrashed()
* @method static Builder|Rule withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Rule whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Rule extends Model
{
diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php
index 824104a160..df2f95dce2 100644
--- a/app/Models/RuleGroup.php
+++ b/app/Models/RuleGroup.php
@@ -66,9 +66,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|RuleGroup whereUserId($value)
* @method static Builder|RuleGroup withTrashed()
* @method static Builder|RuleGroup withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|RuleGroup whereUserGroupId($value)
+ * @mixin Eloquent
*/
class RuleGroup extends Model
{
diff --git a/app/Models/Tag.php b/app/Models/Tag.php
index 124c231e52..2f985f0928 100644
--- a/app/Models/Tag.php
+++ b/app/Models/Tag.php
@@ -75,9 +75,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|Tag whereZoomLevel($value)
* @method static Builder|Tag withTrashed()
* @method static Builder|Tag withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|Tag whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Tag extends Model
{
diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php
index 7a6af8e9c7..ede4e29e4c 100644
--- a/app/Models/Transaction.php
+++ b/app/Models/Transaction.php
@@ -84,8 +84,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static Builder|Transaction whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|Transaction withTrashed()
* @method static \Illuminate\Database\Query\Builder|Transaction withoutTrashed()
- * @mixin Eloquent
* @property int $the_count
+ * @mixin Eloquent
*/
class Transaction extends Model
{
diff --git a/app/Models/TransactionGroup.php b/app/Models/TransactionGroup.php
index 55ffe8b5a4..69506c05b3 100644
--- a/app/Models/TransactionGroup.php
+++ b/app/Models/TransactionGroup.php
@@ -59,9 +59,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|TransactionGroup whereUserId($value)
* @method static Builder|TransactionGroup withTrashed()
* @method static Builder|TransactionGroup withoutTrashed()
- * @mixin Eloquent
* @property int|null $user_group_id
* @method static \Illuminate\Database\Eloquent\Builder|TransactionGroup whereUserGroupId($value)
+ * @mixin Eloquent
*/
class TransactionGroup extends Model
{
diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php
index 3777407c15..8e2e87570c 100644
--- a/app/Models/TransactionJournal.php
+++ b/app/Models/TransactionJournal.php
@@ -112,12 +112,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static EloquentBuilder|TransactionJournal whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withTrashed()
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withoutTrashed()
- * @mixin Eloquent
* @property-read Collection|Location[] $locations
* @property-read int|null $locations_count
* @property int $the_count
* @property int|null $user_group_id
* @method static EloquentBuilder|TransactionJournal whereUserGroupId($value)
+ * @mixin Eloquent
*/
class TransactionJournal extends Model
{
diff --git a/app/Models/Webhook.php b/app/Models/Webhook.php
index cc41df4b18..2fd92377cd 100644
--- a/app/Models/Webhook.php
+++ b/app/Models/Webhook.php
@@ -69,13 +69,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|Webhook whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|Webhook withTrashed()
* @method static \Illuminate\Database\Query\Builder|Webhook withoutTrashed()
- * @mixin Eloquent
* @property string $title
* @property string $secret
* @method static Builder|Webhook whereSecret($value)
* @method static Builder|Webhook whereTitle($value)
* @property int|null $user_group_id
* @method static Builder|Webhook whereUserGroupId($value)
+ * @mixin Eloquent
*/
class Webhook extends Model
{
diff --git a/app/Models/WebhookAttempt.php b/app/Models/WebhookAttempt.php
index 85d617ac33..0f9a04588e 100644
--- a/app/Models/WebhookAttempt.php
+++ b/app/Models/WebhookAttempt.php
@@ -55,10 +55,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|WebhookAttempt whereStatusCode($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebhookAttempt whereUpdatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|WebhookAttempt whereWebhookMessageId($value)
- * @mixin Eloquent
* @method static Builder|WebhookAttempt onlyTrashed()
* @method static Builder|WebhookAttempt withTrashed()
* @method static Builder|WebhookAttempt withoutTrashed()
+ * @mixin Eloquent
*/
class WebhookAttempt extends Model
{
diff --git a/app/Models/WebhookMessage.php b/app/Models/WebhookMessage.php
index 46740053a7..b13333ddec 100644
--- a/app/Models/WebhookMessage.php
+++ b/app/Models/WebhookMessage.php
@@ -63,9 +63,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|WebhookMessage whereUpdatedAt($value)
* @method static Builder|WebhookMessage whereUuid($value)
* @method static Builder|WebhookMessage whereWebhookId($value)
- * @mixin Eloquent
* @property-read Collection|WebhookAttempt[] $webhookAttempts
* @property-read int|null $webhook_attempts_count
+ * @mixin Eloquent
*/
class WebhookMessage extends Model
{
diff --git a/app/Repositories/User/UserRepository.php b/app/Repositories/User/UserRepository.php
index b488822acb..570cf7c105 100644
--- a/app/Repositories/User/UserRepository.php
+++ b/app/Repositories/User/UserRepository.php
@@ -119,6 +119,15 @@ class UserRepository implements UserRepositoryInterface
return Role::create(['name' => $name, 'display_name' => $displayName, 'description' => $description]);
}
+ /**
+ * @inheritDoc
+ */
+ public function deleteInvite(InvitedUser $invite): void
+ {
+ Log::debug(sprintf('Deleting invite #%d', $invite->id));
+ $invite->delete();
+ }
+
/**
* @param User $user
*
@@ -286,24 +295,24 @@ class UserRepository implements UserRepositoryInterface
*
* @return bool
*/
- public function hasRole(User|Authenticatable|null $user, string $role): bool
- {
- if (null === $user) {
- return false;
- }
- /** @var Role $userRole */
- foreach ($user->roles as $userRole) {
- if ($userRole->name === $role) {
- return true;
- }
- }
-
+ public function hasRole(User|Authenticatable|null $user, string $role): bool
+ {
+ if (null === $user) {
return false;
}
+ /** @var Role $userRole */
+ foreach ($user->roles as $userRole) {
+ if ($userRole->name === $role) {
+ return true;
+ }
+ }
+
+ return false;
+ }
/**
- * @inheritDoc
- */
+ * @inheritDoc
+ */
public function inviteUser(User|Authenticatable|null $user, string $email): InvitedUser
{
$now = today(config('app.timezone'));
diff --git a/app/Repositories/User/UserRepositoryInterface.php b/app/Repositories/User/UserRepositoryInterface.php
index 52e804bb93..7e5269cf41 100644
--- a/app/Repositories/User/UserRepositoryInterface.php
+++ b/app/Repositories/User/UserRepositoryInterface.php
@@ -102,6 +102,12 @@ interface UserRepositoryInterface
*/
public function deleteEmptyGroups(): void;
+ /**
+ * @param InvitedUser $invite
+ * @return void
+ */
+ public function deleteInvite(InvitedUser $invite): void;
+
/**
* @param User $user
*
diff --git a/app/User.php b/app/User.php
index 7ffde05b89..e6dc89bb15 100644
--- a/app/User.php
+++ b/app/User.php
@@ -122,7 +122,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|User whereRememberToken($value)
* @method static Builder|User whereReset($value)
* @method static Builder|User whereUpdatedAt($value)
- * @mixin Eloquent
* @property string|null $objectguid
* @property-read int|null $accounts_count
* @property-read int|null $attachments_count
@@ -165,6 +164,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $group_memberships_count
* @property-read UserGroup|null $userGroup
* @method static Builder|User whereUserGroupId($value)
+ * @mixin Eloquent
*/
class User extends Authenticatable
{
diff --git a/app/Validation/CurrencyValidation.php b/app/Validation/CurrencyValidation.php
index a867a7946a..f52d5d714f 100644
--- a/app/Validation/CurrencyValidation.php
+++ b/app/Validation/CurrencyValidation.php
@@ -43,7 +43,7 @@ trait CurrencyValidation
*/
protected function validateForeignCurrencyInformation(Validator $validator): void
{
- if($validator->errors()->count() > 0) {
+ if ($validator->errors()->count() > 0) {
return;
}
Log::debug('Now in validateForeignCurrencyInformation()');
diff --git a/app/Validation/GroupValidation.php b/app/Validation/GroupValidation.php
index 25ed4c50a1..bf00a593ac 100644
--- a/app/Validation/GroupValidation.php
+++ b/app/Validation/GroupValidation.php
@@ -90,7 +90,7 @@ trait GroupValidation
*/
protected function validateDescriptions(Validator $validator): void
{
- if($validator->errors()->count() > 0) {
+ if ($validator->errors()->count() > 0) {
return;
}
Log::debug('Now in GroupValidation::validateDescriptions()');
@@ -116,7 +116,7 @@ trait GroupValidation
*/
protected function validateGroupDescription(Validator $validator): void
{
- if($validator->errors()->count() > 0) {
+ if ($validator->errors()->count() > 0) {
return;
}
Log::debug('Now in validateGroupDescription()');
diff --git a/config/firefly.php b/config/firefly.php
index 6b332e46dc..bf006d7737 100644
--- a/config/firefly.php
+++ b/config/firefly.php
@@ -31,6 +31,7 @@ use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\Category;
+use FireflyIII\Models\InvitedUser;
use FireflyIII\Models\LinkType;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Models\PiggyBank;
@@ -445,6 +446,7 @@ return [
'webhook' => Webhook::class,
'webhookMessage' => WebhookMessage::class,
'webhookAttempt' => WebhookAttempt::class,
+ 'invitedUser' => InvitedUser::class,
// strings
'currency_code' => CurrencyCode::class,
@@ -470,6 +472,7 @@ return [
'dynamicConfigKey' => DynamicConfigKey::class,
'eitherConfigKey' => EitherConfigKey::class,
+
],
'rule-actions' => [
'set_category' => SetCategory::class,
diff --git a/public/v1/js/ff/admin/users.js b/public/v1/js/ff/admin/users.js
new file mode 100644
index 0000000000..f5d4701d6c
--- /dev/null
+++ b/public/v1/js/ff/admin/users.js
@@ -0,0 +1,33 @@
+/*
+ * users.js
+ * Copyright (c) 2023 james@firefly-iii.org
+ *
+ * This file is part of Firefly III (https://github.com/firefly-iii).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see