opnform-host-nginx/api/app/Models/User.php

272 lines
6.4 KiB
PHP
Raw Normal View History

2022-09-20 21:59:52 +02:00
<?php
namespace App\Models;
use App\Models\Forms\Form;
use App\Notifications\ResetPassword;
use App\Notifications\VerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Cashier\Billable;
use Laravel\Sanctum\HasApiTokens;
2022-09-20 21:59:52 +02:00
use Tymon\JWTAuth\Contracts\JWTSubject;
2023-10-12 12:06:03 +02:00
class User extends Authenticatable implements JWTSubject
2022-09-20 21:59:52 +02:00
{
2024-02-23 11:54:12 +01:00
use Billable;
use HasFactory;
use Notifiable;
use HasApiTokens;
2022-09-20 21:59:52 +02:00
public const ROLE_ADMIN = 'admin';
public const ROLE_USER = 'user';
Readonly User (#637) * Readonly User * Refactor FormPolicy and TemplatePolicy to centralize write operation logic - Introduced a private method `canPerformWriteOperation` in both FormPolicy and TemplatePolicy to encapsulate the logic for determining if a user can perform write operations on the respective models. - Updated the `update`, `delete`, `restore`, and `forceDelete` methods in FormPolicy to use the new method for improved readability and maintainability. - Simplified the `update` and `delete` methods in TemplatePolicy to leverage the centralized write operation logic. This refactoring enhances code clarity and reduces duplication across policy classes. * Refactor user and workspace permissions handling - Updated FormController to authorize form creation based on workspace context. - Removed the `is_readonly` attribute from UserResource and integrated it into WorkspaceResource for better encapsulation. - Refactored User model to eliminate the `getIsReadonlyAttribute` method, shifting readonly logic to the Workspace model. - Adjusted FormPolicy and TemplatePolicy to utilize workspace readonly checks for user permissions. - Updated various frontend components to reference workspace readonly status instead of user readonly status, enhancing clarity and consistency in permission handling. These changes improve the management of user permissions in relation to workspaces, ensuring a more robust and maintainable authorization system. * Fix isReadonlyUser * fix pint --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-30 14:35:23 +01:00
public const ROLE_READONLY = 'readonly';
public const ROLES = [
self::ROLE_ADMIN,
self::ROLE_USER,
self::ROLE_READONLY,
];
2022-09-20 21:59:52 +02:00
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'email',
'password',
2024-02-23 11:54:12 +01:00
'hear_about_us',
'utm_data',
Email spam security (#641) * Add hCaptcha on register page * register page captcha test cases * Refactor integration validation rules to include form context - Updated the `getValidationRules` method in various integration handlers (Discord, Email, Google Sheets, Slack, Webhook, Zapier) to accept an optional `Form` parameter, allowing for context-aware validation. - Enhanced the `EmailIntegration` handler to enforce restrictions based on user plans, ensuring free users can only create one email integration per form and can only send to a single email address. - Added a new test suite for `EmailIntegration` to validate the new restrictions and ensure proper functionality for both free and pro users. - Introduced loading state management in the `IntegrationModal` component to improve user experience during save operations. These changes improve the flexibility and user experience of form integrations, particularly for email handling. * for self-hosted ignore emil validation for spam * fix pint * ignore register throttle for testing env * support new migration for mysql also * Register page captcha enable if captcha key set * fix test case * fix test case * fix test case * fix pint * Refactor RegisterController middleware and update TestCase setup - Removed environment check for throttling middleware in RegisterController, ensuring consistent rate limiting for the registration endpoint. - Updated TestCase to disable throttle middleware during tests, allowing for more flexible testing scenarios without rate limiting interference. * Enhance hCaptcha integration in tests and configuration - Added hCaptcha site and secret keys to phpunit.xml for testing purposes. - Updated RegisterTest to configure hCaptcha secret key dynamically, ensuring proper token validation in production environment. These changes improve the testing setup for hCaptcha, facilitating more accurate simulation of production conditions. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 13:16:27 +01:00
'meta'
2022-09-20 21:59:52 +02:00
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
'remember_token',
2024-02-23 11:54:12 +01:00
'hear_about_us',
Email spam security (#641) * Add hCaptcha on register page * register page captcha test cases * Refactor integration validation rules to include form context - Updated the `getValidationRules` method in various integration handlers (Discord, Email, Google Sheets, Slack, Webhook, Zapier) to accept an optional `Form` parameter, allowing for context-aware validation. - Enhanced the `EmailIntegration` handler to enforce restrictions based on user plans, ensuring free users can only create one email integration per form and can only send to a single email address. - Added a new test suite for `EmailIntegration` to validate the new restrictions and ensure proper functionality for both free and pro users. - Introduced loading state management in the `IntegrationModal` component to improve user experience during save operations. These changes improve the flexibility and user experience of form integrations, particularly for email handling. * for self-hosted ignore emil validation for spam * fix pint * ignore register throttle for testing env * support new migration for mysql also * Register page captcha enable if captcha key set * fix test case * fix test case * fix test case * fix pint * Refactor RegisterController middleware and update TestCase setup - Removed environment check for throttling middleware in RegisterController, ensuring consistent rate limiting for the registration endpoint. - Updated TestCase to disable throttle middleware during tests, allowing for more flexible testing scenarios without rate limiting interference. * Enhance hCaptcha integration in tests and configuration - Added hCaptcha site and secret keys to phpunit.xml for testing purposes. - Updated RegisterTest to configure hCaptcha secret key dynamically, ensuring proper token validation in production environment. These changes improve the testing setup for hCaptcha, facilitating more accurate simulation of production conditions. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 13:16:27 +01:00
'meta'
2022-09-20 21:59:52 +02:00
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected function casts()
{
return [
'email_verified_at' => 'datetime',
'utm_data' => 'array',
Email spam security (#641) * Add hCaptcha on register page * register page captcha test cases * Refactor integration validation rules to include form context - Updated the `getValidationRules` method in various integration handlers (Discord, Email, Google Sheets, Slack, Webhook, Zapier) to accept an optional `Form` parameter, allowing for context-aware validation. - Enhanced the `EmailIntegration` handler to enforce restrictions based on user plans, ensuring free users can only create one email integration per form and can only send to a single email address. - Added a new test suite for `EmailIntegration` to validate the new restrictions and ensure proper functionality for both free and pro users. - Introduced loading state management in the `IntegrationModal` component to improve user experience during save operations. These changes improve the flexibility and user experience of form integrations, particularly for email handling. * for self-hosted ignore emil validation for spam * fix pint * ignore register throttle for testing env * support new migration for mysql also * Register page captcha enable if captcha key set * fix test case * fix test case * fix test case * fix pint * Refactor RegisterController middleware and update TestCase setup - Removed environment check for throttling middleware in RegisterController, ensuring consistent rate limiting for the registration endpoint. - Updated TestCase to disable throttle middleware during tests, allowing for more flexible testing scenarios without rate limiting interference. * Enhance hCaptcha integration in tests and configuration - Added hCaptcha site and secret keys to phpunit.xml for testing purposes. - Updated RegisterTest to configure hCaptcha secret key dynamically, ensuring proper token validation in production environment. These changes improve the testing setup for hCaptcha, facilitating more accurate simulation of production conditions. --------- Co-authored-by: Julien Nahum <julien@nahum.net>
2024-12-18 13:16:27 +01:00
'meta' => 'array',
];
}
2022-09-20 21:59:52 +02:00
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'photo_url',
];
public function ownsForm(Form $form)
{
2024-02-23 11:54:12 +01:00
return $this->workspaces()->where('workspaces.id', $form->workspace_id)->exists();
2023-12-03 15:02:48 +01:00
}
public function ownsWorkspace(Workspace $workspace)
{
2024-02-23 11:54:12 +01:00
return $this->workspaces()->where('workspaces.id', $workspace->id)->exists();
}
2022-09-20 21:59:52 +02:00
/**
* Get the profile photo URL attribute.
*
* @return string
*/
public function getPhotoUrlAttribute()
{
return vsprintf('https://www.gravatar.com/avatar/%s.jpg?s=200&d=%s', [
md5(strtolower($this->email)),
$this->name ? urlencode("https://ui-avatars.com/api/$this->name.jpg") : 'mp',
2022-09-20 21:59:52 +02:00
]);
}
public function getHasFormsAttribute()
{
return $this->workspaces()->whereHas('forms')->exists();
}
public function getIsSubscribedAttribute()
{
return $this->subscribed()
|| in_array($this->email, config('opnform.extra_pro_users_emails'))
|| !is_null($this->activeLicense());
2022-09-20 21:59:52 +02:00
}
public function getHasCustomerIdAttribute()
{
return !is_null($this->stripe_id);
2022-09-20 21:59:52 +02:00
}
public function getAdminAttribute()
{
2023-10-12 12:06:03 +02:00
return in_array($this->email, config('opnform.admin_emails'));
2022-09-20 21:59:52 +02:00
}
2024-01-19 14:27:04 +01:00
public function getModeratorAttribute()
{
return in_array($this->email, config('opnform.moderator_emails')) || $this->admin;
}
2022-11-16 13:12:48 +01:00
public function getTemplateEditorAttribute()
{
2023-10-12 12:06:03 +02:00
return $this->admin || in_array($this->email, config('opnform.template_editor_emails'));
2022-11-16 13:12:48 +01:00
}
2022-09-20 21:59:52 +02:00
/**
* =================================
* Helper Related
* =================================
*/
/**
* Send the password reset notification.
*
2024-02-23 11:54:12 +01:00
* @param string $token
2022-09-20 21:59:52 +02:00
* @return void
*/
public function sendPasswordResetNotification($token)
{
$this->notify(new ResetPassword($token));
}
/**
* Send the email verification notification.
*
* @return void
*/
public function sendEmailVerificationNotification()
{
2024-02-23 11:54:12 +01:00
$this->notify(new VerifyEmail());
2022-09-20 21:59:52 +02:00
}
/**
* =================================
* Relationship
* =================================
*/
public function workspaces()
{
return $this->belongsToMany(Workspace::class);
}
public function forms()
{
return $this->hasMany(Form::class, 'creator_id');
2022-09-20 21:59:52 +02:00
}
public function formTemplates()
{
return $this->hasMany(Template::class, 'creator_id');
}
public function licenses()
{
return $this->hasMany(License::class);
}
2023-11-01 18:14:01 +01:00
public function activeLicense(): ?License
{
return $this->licenses()->active()->first();
}
2022-09-20 21:59:52 +02:00
/**
* =================================
* Oauth Related
* =================================
*/
/**
* Get the oauth providers.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function oauthProviders()
{
return $this->hasMany(OAuthProvider::class);
}
/**
* @return int
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* @return array
*/
public function getJWTCustomClaims()
{
2024-01-09 10:43:07 +01:00
return [
'ip' => \Hash::make(request()->ip()),
'ua' => \Hash::make(request()->userAgent()),
];
2022-09-20 21:59:52 +02:00
}
public function getIsRiskyAttribute()
{
return $this->created_at->isAfter(now()->subDays(3)) || // created in last 3 days
$this->subscriptions()->where(function ($q) {
$q->where('stripe_status', 'trialing')
->orWhere('stripe_status', 'active');
})->first()?->onTrial();
}
2023-12-03 15:02:48 +01:00
public function flushCache()
{
$this->workspaces()->with('forms')->get()->each(function (Workspace $workspace) {
$workspace->flush();
$workspace->forms->each(function (Form $form) {
$form->flush();
});
});
}
public static function boot()
2022-09-20 21:59:52 +02:00
{
parent::boot();
static::deleting(function (User $user) {
2022-09-20 21:59:52 +02:00
// Remove user's workspace if he's the only one with this workspace
foreach ($user->workspaces as $workspace) {
if ($workspace->users()->count() == 1) {
$workspace->delete();
} else {
$workspace->users()->detach($user->id);
2022-09-20 21:59:52 +02:00
}
}
});
2022-09-20 21:59:52 +02:00
}
public function scopeWithActiveSubscription($query)
{
return $query->whereHas('subscriptions', function ($query) {
$query->where(function ($q) {
$q->where('stripe_status', 'trialing')
->orWhere('stripe_status', 'active');
});
2022-09-20 21:59:52 +02:00
});
}
}