Add all files
This commit is contained in:
104
database/seeders/CustomPropertySeeder.php
Normal file
104
database/seeders/CustomPropertySeeder.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CustomPropertySeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// Seed custom user properties
|
||||
// for phone, company_name, country, address, address2, city, state, zip
|
||||
DB::table('custom_properties')->insertOrIgnore([
|
||||
[
|
||||
'key' => 'phone',
|
||||
'name' => 'Phone',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 1,
|
||||
'show_on_invoice' => 0,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
[
|
||||
'key' => 'company_name',
|
||||
'name' => 'Company Name',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 0,
|
||||
'show_on_invoice' => 1,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
[
|
||||
'key' => 'address',
|
||||
'name' => 'Address',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 1,
|
||||
'show_on_invoice' => 1,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
[
|
||||
'key' => 'address2',
|
||||
'name' => 'Address 2',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 0,
|
||||
'show_on_invoice' => 0,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
[
|
||||
'key' => 'city',
|
||||
'name' => 'City',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 1,
|
||||
'show_on_invoice' => 1,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
[
|
||||
'key' => 'state',
|
||||
'name' => 'State',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 1,
|
||||
'show_on_invoice' => 1,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
[
|
||||
'key' => 'zip',
|
||||
'name' => 'ZIP',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'string',
|
||||
'non_editable' => 0,
|
||||
'required' => 1,
|
||||
'show_on_invoice' => 1,
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
]);
|
||||
|
||||
DB::table('custom_properties')->insertOrIgnore([
|
||||
[
|
||||
'key' => 'country',
|
||||
'name' => 'Country',
|
||||
'model' => 'App\Models\User',
|
||||
'type' => 'select',
|
||||
'non_editable' => 0,
|
||||
'required' => 1,
|
||||
'show_on_invoice' => 1,
|
||||
'allowed_values' => json_encode(array_values(array_slice(config('app.countries', []), 1))),
|
||||
'validation' => 'string|max:255',
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
54
database/seeders/DatabaseSeeder.php
Normal file
54
database/seeders/DatabaseSeeder.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Role;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// User::factory(10)->create();
|
||||
Role::updateOrCreate(['name' => 'admin'], ['permissions' => ['*']]);
|
||||
|
||||
foreach (\App\Classes\Settings::settings() as $settings) {
|
||||
foreach ($settings as $setting) {
|
||||
if (!isset($setting['default'])) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($setting['name'], ['mail_header', 'mail_footer', 'mail_css'])) {
|
||||
// Read from file in ./data/<name>
|
||||
$setting['default'] = file_get_contents(__DIR__ . '/data/' . $setting['name']);
|
||||
}
|
||||
Setting::firstOrCreate([
|
||||
'key' => $setting['name'],
|
||||
], [
|
||||
'value' => $setting['default'],
|
||||
'type' => $setting['database_type'] ?? 'string',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Seed default currency (USD)
|
||||
if (\App\Models\Currency::count() === 0) {
|
||||
\App\Models\Currency::create([
|
||||
'code' => 'USD',
|
||||
'prefix' => '$',
|
||||
'suffix' => '',
|
||||
'format' => '1.000,00',
|
||||
]);
|
||||
}
|
||||
|
||||
\App\Providers\SettingsProvider::flushCache();
|
||||
|
||||
$this->call([
|
||||
CustomPropertySeeder::class,
|
||||
EmailTemplateSeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
214
database/seeders/EmailTemplateSeeder.php
Normal file
214
database/seeders/EmailTemplateSeeder.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class EmailTemplateSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('email_templates')->insertOrIgnore([
|
||||
[
|
||||
'key' => 'new_login_detected',
|
||||
'subject' => 'New login detected',
|
||||
'body' => <<<'HTML'
|
||||
# New login detected
|
||||
|
||||
A new login was detected on your account.
|
||||
|
||||
- IP: {{ $ip }}
|
||||
- Device: {{ $device }}
|
||||
- Time: {{ $time }}
|
||||
|
||||
**If this was you**
|
||||
You can ignore this message, there is no need to take any action.
|
||||
|
||||
**If this wasn't you**
|
||||
Please reset your password [here]({{ route('password.request') }}).
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'new_invoice_created',
|
||||
'subject' => 'New invoice created',
|
||||
'body' => <<<'HTML'
|
||||
# New invoice created
|
||||
|
||||
A new invoice was created on your account.
|
||||
|
||||
Total amount: **{{ $total }}**
|
||||
|
||||
|
||||
<div class="table">
|
||||
|
||||
| Item | Quantity | Price |
|
||||
| :------: | :------: | :------: |
|
||||
@foreach ($items as $item)
|
||||
| {{ $item->description }} | {{ $item->quantity }} | {{ $item->price }} |
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="action">
|
||||
<a class="button button-blue" href="{{ route('invoices.show', $invoice) }}">
|
||||
Go to invoice
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@if($has_subscription)
|
||||
You have a active subscription, the invoice will be automatically paid.
|
||||
@endif
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'new_order_created',
|
||||
'subject' => 'New order created',
|
||||
'body' => <<<'HTML'
|
||||
# New order created
|
||||
|
||||
A new order was created on your account.
|
||||
|
||||
**Order details**
|
||||
<div class="table">
|
||||
|
||||
| Item | Quantity | Price |
|
||||
| :------: | :------: | :------: |
|
||||
@foreach ($items as $item)
|
||||
| {{ $item->product->name }} | {{ $item->quantity }} | {{ $item->formattedPrice }} |
|
||||
@endforeach
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'new_server_created',
|
||||
'subject' => 'Server activated',
|
||||
'body' => <<<'HTML'
|
||||
# Server activated
|
||||
|
||||
Your server has been activated.
|
||||
|
||||
**Server details**
|
||||
- Name: {{ $service->product->name }}
|
||||
|
||||
@isset($service->product->email_template)
|
||||
**Server information**
|
||||
{!! Str::markdown(Illuminate\View\Compilers\BladeCompiler::render($service->product->email_template, get_defined_vars()['__data'])) !!}
|
||||
@endisset
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'server_suspended',
|
||||
'subject' => 'Server suspended',
|
||||
'body' => <<<'HTML'
|
||||
# Server suspended
|
||||
|
||||
Your server has been suspended due to a payment failure.
|
||||
|
||||
**Server details**
|
||||
- Name: {{ $service->product->name }}
|
||||
|
||||
Please pay the invoice to reactivate the server.
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'server_terminated',
|
||||
'subject' => 'Server terminated',
|
||||
'body' => <<<'HTML'
|
||||
# Server terminated
|
||||
|
||||
Your server has been terminated.
|
||||
|
||||
**Server details**
|
||||
- Name: {{ $service->product->name }}
|
||||
|
||||
Do you consider it a mistake?
|
||||
<div class="action">
|
||||
<a class="button button-blue" href="{{ route('tickets.create') }}">
|
||||
Contact us
|
||||
</a>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'new_ticket_message',
|
||||
'subject' => 'New ticket reply',
|
||||
'body' => <<<'HTML'
|
||||
# New ticket reply
|
||||
|
||||
{{ $ticketMessage->user->name }} replied to your ticket.
|
||||
|
||||
**Message**
|
||||
{!! Str::markdown($ticketMessage->message, [
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]) !!}
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'email_verification',
|
||||
'subject' => 'Email verification',
|
||||
'body' => <<<'HTML'
|
||||
# Email verification
|
||||
|
||||
Please verify your email address by clicking the link below.
|
||||
<div class="action">
|
||||
<a class="button button-blue" href="{{ $url }}">
|
||||
Verify email
|
||||
</a>
|
||||
</div>
|
||||
|
||||
This link will expire in 60 minutes.
|
||||
|
||||
If you did not create an account, you can ignore this email.
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'password_reset',
|
||||
'subject' => 'Password reset',
|
||||
'body' => <<<'HTML'
|
||||
# Password reset
|
||||
|
||||
You are receiving this email because we received a password reset request for your account.
|
||||
|
||||
**Reset password**
|
||||
<div class="action">
|
||||
<a class="button button-blue" href="{{ $url }}">
|
||||
Reset password
|
||||
</a>
|
||||
</div>
|
||||
|
||||
This password reset link will expire in 60 minutes.
|
||||
|
||||
If you did not request a password reset, no further action is required.
|
||||
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'key' => 'service_cancellation_received',
|
||||
'subject' => 'Service cancellation received',
|
||||
'body' => <<<'HTML'
|
||||
# Server Cancellation Received
|
||||
|
||||
We're sorry to see you go! Your server cancellation has been successfully received.
|
||||
|
||||
**Cancellation Details**
|
||||
- Server: {{ $service->product->name }}
|
||||
@if($cancellation->reason)
|
||||
- Reason: {{ $cancellation->reason }}
|
||||
@endif
|
||||
- Requested at: {{ $cancellation->created_at->format('F j, Y, g:i A') }}
|
||||
|
||||
@if($cancellation->type === 'end_of_period')
|
||||
Your server will remain active until {{ $service->expires_at->format('F j, Y') }} (end of your current billing period).
|
||||
@else
|
||||
Your server has been terminated immediately.
|
||||
@endif
|
||||
|
||||
HTML,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
290
database/seeders/data/mail_css
Normal file
290
database/seeders/data/mail_css
Normal file
@@ -0,0 +1,290 @@
|
||||
/* Base */
|
||||
|
||||
body,
|
||||
body *:not(html):not(style):not(br):not(tr):not(code) {
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif,
|
||||
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
position: relative;
|
||||
}
|
||||
|
||||
body {
|
||||
-webkit-text-size-adjust: none;
|
||||
background-color: #ffffff;
|
||||
color: #718096;
|
||||
height: 100%;
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
blockquote {
|
||||
line-height: 1.4;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #3869d4;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
|
||||
h1 {
|
||||
color: #3d4852;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 16px;
|
||||
line-height: 1.5em;
|
||||
margin-top: 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
p.sub {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
|
||||
.wrapper {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
background-color: #edf2f7;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
||||
.header {
|
||||
padding: 25px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header a {
|
||||
color: #3d4852;
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
|
||||
.logo {
|
||||
height: 75px;
|
||||
max-height: 75px;
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
/* Body */
|
||||
|
||||
.body {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
background-color: #edf2f7;
|
||||
border-bottom: 1px solid #edf2f7;
|
||||
border-top: 1px solid #edf2f7;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.inner-body {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 570px;
|
||||
background-color: #ffffff;
|
||||
border-color: #e8e5ef;
|
||||
border-radius: 2px;
|
||||
border-width: 1px;
|
||||
box-shadow: 0 2px 0 rgba(0, 0, 150, 0.025), 2px 4px 0 rgba(0, 0, 150, 0.015);
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
width: 570px;
|
||||
}
|
||||
|
||||
/* Subcopy */
|
||||
|
||||
.subcopy {
|
||||
border-top: 1px solid #e8e5ef;
|
||||
margin-top: 25px;
|
||||
padding-top: 25px;
|
||||
}
|
||||
|
||||
.subcopy p {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
.footer {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 570px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 570px;
|
||||
}
|
||||
|
||||
.footer p {
|
||||
color: #b0adc5;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #b0adc5;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
|
||||
.table table {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
margin: 30px auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.table th {
|
||||
border-bottom: 1px solid #edeff2;
|
||||
margin: 0;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
color: #74787e;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
margin: 0;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.content-cell {
|
||||
max-width: 100vw;
|
||||
padding: 32px;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
.action {
|
||||
-premailer-cellpadding: 0;
|
||||
-premailer-cellspacing: 0;
|
||||
-premailer-width: 100%;
|
||||
margin: 30px auto;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button {
|
||||
-webkit-text-size-adjust: none;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.button-blue,
|
||||
.button-primary {
|
||||
background-color: #2d3748;
|
||||
border-bottom: 8px solid #2d3748;
|
||||
border-left: 18px solid #2d3748;
|
||||
border-right: 18px solid #2d3748;
|
||||
border-top: 8px solid #2d3748;
|
||||
}
|
||||
|
||||
.button-green,
|
||||
.button-success {
|
||||
background-color: #48bb78;
|
||||
border-bottom: 8px solid #48bb78;
|
||||
border-left: 18px solid #48bb78;
|
||||
border-right: 18px solid #48bb78;
|
||||
border-top: 8px solid #48bb78;
|
||||
}
|
||||
|
||||
.button-red,
|
||||
.button-error {
|
||||
background-color: #e53e3e;
|
||||
border-bottom: 8px solid #e53e3e;
|
||||
border-left: 18px solid #e53e3e;
|
||||
border-right: 18px solid #e53e3e;
|
||||
border-top: 8px solid #e53e3e;
|
||||
}
|
||||
|
||||
/* Panels */
|
||||
|
||||
.panel {
|
||||
border-left: #2d3748 solid 4px;
|
||||
margin: 21px 0;
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
background-color: #edf2f7;
|
||||
color: #718096;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.panel-content p {
|
||||
color: #718096;
|
||||
}
|
||||
|
||||
.panel-item {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.panel-item p:last-of-type {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
|
||||
.break-all {
|
||||
word-break: break-all;
|
||||
}
|
||||
11
database/seeders/data/mail_footer
Normal file
11
database/seeders/data/mail_footer
Normal file
@@ -0,0 +1,11 @@
|
||||
<tr>
|
||||
<td>
|
||||
<table class="footer" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td class="content-cell" align="center">
|
||||
© {{ date('Y') }} {{ config('app.name') }}. {{ __('All rights reserved.') }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
51
database/seeders/data/mail_header
Normal file
51
database/seeders/data/mail_header
Normal file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>{{ config('app.name') }}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="color-scheme" content="light">
|
||||
<meta name="supported-color-schemes" content="light">
|
||||
<style>
|
||||
@media only screen and (max-width: 600px) {
|
||||
.inner-body {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
.button {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
{!! config('settings.mail_css') !!}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<table class="content" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
@if(config('settings.logo'))
|
||||
<tr>
|
||||
<td class="header">
|
||||
<a href="{{ url('/') }}" style="display: inline-block;">
|
||||
<img src="{{ url(Storage::url(config('settings.logo'))) }}" class="logo" alt="{{ config('app.name') }}">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
|
||||
|
||||
<!-- Email Body -->
|
||||
<tr>
|
||||
<td class="body" width="100%" cellpadding="0" cellspacing="0" style="border: hidden !important;">
|
||||
<table class="inner-body" align="center" width="570" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<!-- Body content -->
|
||||
<tr>
|
||||
<td class="content-cell">
|
||||
Reference in New Issue
Block a user