refactor: replace custom CRM with Monica fork
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s
This commit is contained in:
54
app/Models/User/Changelog.php
Normal file
54
app/Models/User/Changelog.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\User;
|
||||
|
||||
use Parsedown;
|
||||
use App\Helpers\DateHelper;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Changelog extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $dates = [
|
||||
'created_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the user records associated with the tag.
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany(User::class)->withPivot('read', 'upvote')->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the markdown parsed description.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescriptionAttribute($value)
|
||||
{
|
||||
return (new Parsedown())->text($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the created_at date in a friendly format.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatedAtAttribute($value)
|
||||
{
|
||||
return DateHelper::getShortDate($value);
|
||||
}
|
||||
}
|
||||
52
app/Models/User/Module.php
Normal file
52
app/Models/User/Module.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\User;
|
||||
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
/**
|
||||
* A module is a section of information that appears in the Contact sheet, like
|
||||
* 'Activities' or 'Notes'.
|
||||
*/
|
||||
class Module extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'active' => 'boolean',
|
||||
'delible' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the module.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope a query to only include modules that are active.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('active', true);
|
||||
}
|
||||
}
|
||||
33
app/Models/User/RecoveryCode.php
Normal file
33
app/Models/User/RecoveryCode.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\User;
|
||||
|
||||
use App\Models\ModelBinding as Model;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class RecoveryCode extends Model
|
||||
{
|
||||
protected $table = 'recovery_codes';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'account_id',
|
||||
'user_id',
|
||||
'recovery',
|
||||
];
|
||||
|
||||
/**
|
||||
* Scope a query to only include unused code.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeUnused($query)
|
||||
{
|
||||
return $query->where('used', 0);
|
||||
}
|
||||
}
|
||||
29
app/Models/User/SyncToken.php
Normal file
29
app/Models/User/SyncToken.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\User;
|
||||
|
||||
use App\Models\ModelBinding as Model;
|
||||
|
||||
class SyncToken extends Model
|
||||
{
|
||||
protected $table = 'synctoken';
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'account_id',
|
||||
'user_id',
|
||||
'name',
|
||||
'timestamp',
|
||||
];
|
||||
}
|
||||
308
app/Models/User/User.php
Normal file
308
app/Models/User/User.php
Normal file
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\User;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Traits\HasUuid;
|
||||
use App\Helpers\FormHelper;
|
||||
use App\Jobs\SendVerifyEmail;
|
||||
use App\Models\Settings\Term;
|
||||
use App\Models\Account\Account;
|
||||
use App\Models\Contact\Contact;
|
||||
use App\Helpers\ComplianceHelper;
|
||||
use App\Models\Settings\Currency;
|
||||
use Laravel\Passport\HasApiTokens;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Contracts\Translation\HasLocalePreference;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
|
||||
class User extends Authenticatable implements MustVerifyEmail, HasLocalePreference
|
||||
{
|
||||
use Notifiable, HasApiTokens, HasUuid;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array<string>|bool
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'password',
|
||||
'timezone',
|
||||
'locale',
|
||||
'currency_id',
|
||||
'fluid_container',
|
||||
'temperature_scale',
|
||||
'name_order',
|
||||
'google2fa_secret',
|
||||
];
|
||||
|
||||
/**
|
||||
* Eager load account with every user.
|
||||
*/
|
||||
protected $with = ['account'];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for arrays.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password', 'remember_token', 'google2fa_secret',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'profile_new_life_event_badge_seen' => 'boolean',
|
||||
'admin' => 'boolean',
|
||||
'fluid_container' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Available names order.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public const NAMES_ORDER = [
|
||||
'firstname_lastname',
|
||||
'lastname_firstname',
|
||||
'firstname_lastname_nickname',
|
||||
'firstname_nickname_lastname',
|
||||
'lastname_firstname_nickname',
|
||||
'lastname_nickname_firstname',
|
||||
'nickname_firstname_lastname',
|
||||
'nickname_lastname_firstname',
|
||||
'nickname_bracketed_firstname_lastname',
|
||||
'nickname',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the account record associated with the user.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the contact record associated with the 'me' contact.
|
||||
*
|
||||
* @return HasOne
|
||||
*/
|
||||
public function me()
|
||||
{
|
||||
return $this->hasOne(Contact::class, 'id', 'me_contact_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the term records associated with the user.
|
||||
*
|
||||
* @return BelongsToMany
|
||||
*/
|
||||
public function terms()
|
||||
{
|
||||
return $this->belongsToMany(Term::class)->withPivot('ip_address')->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the recovery codes associated with the user.
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function recoveryCodes()
|
||||
{
|
||||
return $this->hasMany(RecoveryCode::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currency for this user.
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function currency()
|
||||
{
|
||||
return $this->belongsTo(Currency::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a default value just in case the sort order is empty.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function getContactsSortOrderAttribute($value): string
|
||||
{
|
||||
return ! empty($value) ? $value : 'firstnameAZ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the layout is fluid or not for the UI.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFluidLayout(): string
|
||||
{
|
||||
if ($this->fluid_container) {
|
||||
return 'container-fluid';
|
||||
} else {
|
||||
return 'container';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get users's full name. The name is formatted according to the user's
|
||||
* preference, either "Firstname Lastname", or "Lastname Firstname".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameAttribute(): string
|
||||
{
|
||||
$completeName = '';
|
||||
|
||||
if (FormHelper::getNameOrderForForms($this) === 'firstname') {
|
||||
$completeName = $this->first_name;
|
||||
|
||||
if ($this->last_name !== '') {
|
||||
$completeName = $completeName.' '.$this->last_name;
|
||||
}
|
||||
} else {
|
||||
if ($this->last_name !== '') {
|
||||
$completeName = $this->last_name;
|
||||
}
|
||||
|
||||
$completeName = $completeName.' '.$this->first_name;
|
||||
}
|
||||
|
||||
return $completeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ecrypt the user's google_2fa secret.
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function setGoogle2faSecretAttribute($value): void
|
||||
{
|
||||
$this->attributes['google2fa_secret'] = encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the user's google_2fa secret.
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return string|null
|
||||
*/
|
||||
public function getGoogle2faSecretAttribute($value): ?string
|
||||
{
|
||||
return is_null($value) ? null : decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate if the user has accepted the most current terms and privacy.
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return bool
|
||||
*/
|
||||
public function getPolicyCompliantAttribute($value): bool
|
||||
{
|
||||
return ComplianceHelper::isCompliantWithCurrentTerm($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether the user should be reminded at this time.
|
||||
* This is affected by the user settings regarding the hour of the day he
|
||||
* wants to be reminded.
|
||||
*
|
||||
* @param Carbon|null $date
|
||||
* @return bool
|
||||
*/
|
||||
public function isTheRightTimeToBeReminded($date)
|
||||
{
|
||||
if (is_null($date)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$now = now($this->timezone);
|
||||
$isTheRightTime = true;
|
||||
|
||||
// compare date with current date for the user
|
||||
if (! $date->isSameDay($now)) {
|
||||
$isTheRightTime = false;
|
||||
}
|
||||
|
||||
// compare current hour for the user with the hour they want to be
|
||||
// reminded as per the hour set on the profile
|
||||
if (! $now->isSameHour($this->account->default_time_reminder_is_sent)) {
|
||||
$isTheRightTime = false;
|
||||
}
|
||||
|
||||
return $isTheRightTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the email verification notification.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendEmailVerificationNotification(): void
|
||||
{
|
||||
/** @var int $count */
|
||||
$count = Account::count();
|
||||
if (config('monica.signup_double_optin') && $count > 1) {
|
||||
SendVerifyEmail::dispatch($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the preferred locale of the entity.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function preferredLocale()
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try using a recovery code.
|
||||
*
|
||||
* @param string $recovery
|
||||
* @return bool
|
||||
*/
|
||||
public function recoveryChallenge(string $recovery): bool
|
||||
{
|
||||
$recoveryCodes = $this->recoveryCodes()->unused()->get();
|
||||
|
||||
foreach ($recoveryCodes as $recoveryCode) {
|
||||
if ($recoveryCode->recovery === $recovery) {
|
||||
$recoveryCode->used = true;
|
||||
$recoveryCode->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user