diff --git a/README.md b/README.md
index 3cd593f4..8137ea3b 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,16 @@ curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/loca
# Load php_gmp extension
echo "extension=php_gmp.so" | sudo tee /etc/php/7.4/mods-available/ext_gmp.ini
sudo ln -s /etc/php/7.4/mods-available/ext_gmp.ini /etc/php/7.4/cli/conf.d/20-ext_gmp.ini
+
+# Configure Horizon
+php artisan queue:table
+php artisan migrate
+## Install Redis. Link: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-20-04
+composer require predis/predis
+composer require laravel/horizon
+php artisan horizon:install
+php artisan horizon:publish
+## Configure Supervisor. Link: https://laravel.com/docs/9.x/horizon#installing-supervisor ( Only 'Installing Supervisor', 'Supervisor Configuration', 'Starting Supervisor' Sections )
```
Setup the repo according to our VHOST path. Note, the actual VHOST path in this case should be set to **/var/www/CasperAssociationPortalBackend/public**
diff --git a/ansible/roles/casper-association-portal-backend/defaults/main/main.yml b/ansible/roles/casper-association-portal-backend/defaults/main/main.yml
index 70b31f0a..51304451 100644
--- a/ansible/roles/casper-association-portal-backend/defaults/main/main.yml
+++ b/ansible/roles/casper-association-portal-backend/defaults/main/main.yml
@@ -16,6 +16,8 @@ packages:
- php7.4-curl
- php7.4-xml
- php7.4-gmp
+ - redis-server
+ - supervisor
php:
diff --git a/ansible/roles/casper-association-portal-backend/tasks/main.yml b/ansible/roles/casper-association-portal-backend/tasks/main.yml
index d15a5cc6..4945cae7 100644
--- a/ansible/roles/casper-association-portal-backend/tasks/main.yml
+++ b/ansible/roles/casper-association-portal-backend/tasks/main.yml
@@ -232,7 +232,7 @@
cron:
name: "{{ app.name }}"
user: "{{ security.app_user }}"
- job: "cd /var/www/server && php artisan schedule:run 2>&1"
+ job: "cd /var/www/server && sudo php artisan schedule:run 2>&1"
minute: "*"
hour: "*"
day: "*"
@@ -266,3 +266,13 @@
- config
- first_setup
when: clone_repo.changed
+
+- name: Horizon
+ shell: sudo supervisorctl reread && sudo supervisorctl update && sudo service supervisor restart
+ args:
+ chdir: "{{ app.home }}"
+ tags:
+ - php
+ - update
+ - horizon
+ when: clone_repo.changed
diff --git a/ansible/roles/casper-association-portal-backend/templates/.env.j2 b/ansible/roles/casper-association-portal-backend/templates/.env.j2
index 2164dc7c..a60e1254 100644
--- a/ansible/roles/casper-association-portal-backend/templates/.env.j2
+++ b/ansible/roles/casper-association-portal-backend/templates/.env.j2
@@ -17,12 +17,13 @@ DB_PASSWORD={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_DB_PASSWORD') }}
BROADCAST_DRIVER={{ broadcast.driver }}
CACHE_DRIVER={{ cache.driver }}
FILESYSTEM_DRIVER={{ filesystem.driver }}
-QUEUE_CONNECTION={{ queue.connection }}
+QUEUE_CONNECTION=redis
SESSION_DRIVER={{ session.driver }}
SESSION_LIFETIME={{ session.lifetime }}
MEMCACHED_HOST={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MEMCACHED_HOST') }}
+REDIS_CLIENT=predis
REDIS_HOST={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_REDIS_HOST') }}
REDIS_PASSWORD={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_REDIS_PASSWORD') }}
REDIS_PORT={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_REDIS_PORT') }}
@@ -34,7 +35,7 @@ MAIL_USERNAME={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_USERNAME'
MAIL_PASSWORD={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_PASSWORD') }}
MAIL_ENCRYPTION={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_ENCRYPTION') }}
MAIL_FROM_ADDRESS={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_FROM_ADDRESS') }}
-MAIL_FROM_NAME="{{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_MAIL_FROM_NAME') }}"
+MAIL_FROM_NAME="{{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_APP_NAME') }}"
AWS_ACCESS_KEY_ID={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_AWS_KEY') }}
AWS_SECRET_ACCESS_KEY={{ lookup('ansible.builtin.env', 'CA_MEMBER_PORT_BE_AWS_SECRET') }}
diff --git a/app/Console/Commands/CheckBallot.php b/app/Console/Commands/CheckBallot.php
index 639b1008..a1ed145d 100644
--- a/app/Console/Commands/CheckBallot.php
+++ b/app/Console/Commands/CheckBallot.php
@@ -2,6 +2,7 @@
namespace App\Console\Commands;
+use App\Console\Helper;
use App\Models\Ballot;
use Carbon\Carbon;
use Illuminate\Console\Command;
@@ -39,10 +40,11 @@ public function __construct()
*/
public function handle()
{
- $settings = getSettings();
+ $settings = Helper::getSettings();
$quorumRate = $settings['quorum_rate_ballot'] ?? 50;
- $now = Carbon::now('UTC');
- $ballots = Ballot::with(['vote'])->where('status', 'active')->where('time_end', '<=', $now)->get();
+ $ballots = Ballot::with(['vote'])->where('status', 'active')
+ ->where('time_end', '<=', Carbon::now('UTC'))
+ ->get();
foreach ($ballots as $ballot) {
$vote = $ballot->vote;
if ($vote->result_count == 0) {
diff --git a/app/Console/Commands/CheckBallot2.php b/app/Console/Commands/CheckBallot2.php
new file mode 100644
index 00000000..94d207e6
--- /dev/null
+++ b/app/Console/Commands/CheckBallot2.php
@@ -0,0 +1,37 @@
+where('status', 'active')
+ ->where('time_end', '<=', Carbon::now('UTC')->addHours(24))
+ ->where('time_end', '>', Carbon::now('UTC'))
+ ->where('reminder_24_sent', false)
+ ->orderBy('time_end', 'asc')
+ ->get();
+
+ if ($ballots && count($ballots) > 0) {
+ foreach ($ballots as $ballot) {
+ BallotReminder24::dispatch($ballot)->onQueue('default_long');
+ }
+ }
+
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/app/Console/Commands/CheckNodeStatus.php b/app/Console/Commands/CheckNodeStatus.php
index 44a3e4a7..02ff95c5 100644
--- a/app/Console/Commands/CheckNodeStatus.php
+++ b/app/Console/Commands/CheckNodeStatus.php
@@ -2,275 +2,216 @@
namespace App\Console\Commands;
+use App\Console\Helper;
+
use App\Models\MonitoringCriteria;
use App\Models\User;
use App\Models\UserAddress;
use App\Models\NodeInfo;
+use App\Models\AllNodeData2;
+use App\Jobs\EmailerUserJob;
use Carbon\Carbon;
+use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class CheckNodeStatus extends Command
{
- /**
- * The name and signature of the console command.
- *
- * @var string
- */
protected $signature = 'node-status:check';
- /**
- * The console command description.
- *
- * @var string
- */
protected $description = 'Check node status';
- /**
- * Create a new command instance.
- *
- * @return void
- */
- public function __construct()
- {
+ public function __construct() {
parent::__construct();
}
- /**
- * Execute the console command.
- *
- * @return int
- */
- public function handle()
- {
- $uptime = MonitoringCriteria::where('type', 'uptime')->first();
- $uptimeProbationStart = $uptime->probation_start;
- if ($uptime->given_to_correct_unit == 'Weeks') {
- $uptimeTime = (float) $uptime->given_to_correct_value * 7 * 24;
- } else if ($uptime->given_to_correct_unit == 'Days') {
- $uptimeTime = (float) $uptime->given_to_correct_value * 24;
- } else {
- $uptimeTime = (float) $uptime->given_to_correct_value;
- }
+ public function handle() {
+ $settings = Helper::getSettings();
- $blockHeight = MonitoringCriteria::where('type', 'block-height')->first();
- $blockHeightProbationStart = (float) $blockHeight->probation_start;
- if ($blockHeight->given_to_correct_unit == 'Weeks') {
- $blockHeightTime = (float) $blockHeight->given_to_correct_value * 7 * 24;
- } else if ($blockHeight->given_to_correct_unit == 'Days') {
- $blockHeightTime = (float) $blockHeight->given_to_correct_value * 24;
- } else {
- $blockHeightTime = (float) $blockHeight->given_to_correct_value;
- }
-
- $updateResponsiveness = MonitoringCriteria::where('type', 'update-responsiveness')->first();
- $updateResponsivenessProbationStart = (float) $updateResponsiveness->probation_start;
- if ($updateResponsiveness->given_to_correct_unit == 'Weeks') {
- $updateResponsivenessTime = (float) $updateResponsiveness->given_to_correct_value * 7 * 24;
- } else if ($updateResponsiveness->given_to_correct_unit == 'Days') {
- $updateResponsivenessTime = (float) $updateResponsiveness->given_to_correct_value * 24;
- } else {
- $updateResponsivenessTime = (float) $updateResponsiveness->given_to_correct_value;
- }
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+ $redmarks_revoke = (int) ($settings['redmarks_revoke'] ?? 0);
+ $uptime_probation = (float) ($settings['uptime_probation'] ?? 0);
- $now = Carbon::now('UTC');
- $users = User::with(['addresses', 'metric', 'nodeInfo', 'profile'])
+ $users = User::with(['addresses', 'profile'])
->where('role', 'member')
->where('banned', 0)
->get();
- foreach ($users as $user) {
- $user->node_status = 'Online';
- $user->save();
+ $uptimeHours = 0;
+ if (isset($settings['uptime_correction_unit']) && isset($settings['uptime_correction_value'])) {
+ $unit = $settings['uptime_correction_unit'];
+ $value = (float) $settings['uptime_correction_value'];
+
+ if ($unit == 'Weeks') $uptimeHours = $value * 7 * 24;
+ else if ($unit == 'Days') $uptimeHours = $value * 24;
+ else $uptimeHours = $value;
+ }
+ foreach ($users as $user) {
$addresses = $user->addresses ?? [];
- $nodeInfo = $user->nodeInfo ? $user->nodeInfo : $user->metric;
if (
- !$nodeInfo ||
- !$addresses ||
- count($addresses) == 0 ||
- !$user->node_verified_at ||
- !$user->letter_verified_at ||
- !$user->signature_request_id
+ $addresses &&
+ count($addresses) > 0 &&
+ $user->node_verified_at &&
+ $user->letter_verified_at &&
+ $user->signature_request_id &&
+ isset($user->profile) &&
+ $user->profile &&
+ $user->profile->status == 'approved'
) {
- $user->node_status = null;
- $user->save();
- } else {
- $hasNotFailNode = false;
- foreach ($addresses as $address) {
- $public_address_node = strtolower($address->public_address_node);
- $nodeInfoAddress = NodeInfo::where('node_address', $public_address_node)->first();
- if (!$nodeInfoAddress) {
- $address->node_status = null;
- $address->save();
- }
- if ($address->is_fail_node != 1) {
- $hasNotFailNode = true;
+ // Verified Users
+ if ($user->profile->extra_status == 'Suspended') {
+ // Suspended
+ if (!$user->profile->revoke_at) {
+ $user->profile->revoke_at = Carbon::now('UTC');
+ $user->profile->save();
}
- }
-
- if (!$hasNotFailNode) {
- $user->node_status = 'Offline';
- $user->save();
} else {
- // Begin For Each
- foreach ($addresses as $userAddress) {
- $public_address_node = strtolower($userAddress->public_address_node);
- $nodeInfoAddress = NodeInfo::where('node_address', $public_address_node)->first();
-
- if ($nodeInfoAddress) {
- $nodeInfoAddress->uptime = $nodeInfoAddress->uptime ? $nodeInfoAddress->uptime : 0;
- $nodeInfoAddress->block_height_average = $nodeInfoAddress->block_height_average ? $nodeInfoAddress->block_height_average : 0;
- $nodeInfoAddress->update_responsiveness = $nodeInfoAddress->update_responsiveness ? $nodeInfoAddress->update_responsiveness : 100;
- if (
- $nodeInfoAddress->uptime >= $uptimeProbationStart &&
- $nodeInfoAddress->block_height_average >= $blockHeightProbationStart &&
- $nodeInfoAddress->update_responsiveness >= $updateResponsivenessProbationStart
- ) {
- $userAddress->node_status = 'Online';
- $userAddress->save();
-
- $nodeInfoAddress->uptime_time_start = null;
- $nodeInfoAddress->uptime_time_end = null;
-
- $nodeInfoAddress->block_height_average_time_start = null;
- $nodeInfoAddress->block_height_average_time_end = null;
-
- $nodeInfoAddress->update_responsiveness_time_start = null;
- $nodeInfoAddress->update_responsiveness_time_end = null;
-
- $nodeInfoAddress->save();
- }
- }
-
- if (
- isset($user->profile) &&
- $user->profile &&
- isset($user->profile->status) &&
- $user->profile->status == 'approved' &&
- $nodeInfoAddress
- ) {
- $userAddress->extra_status = null;
- $userAddress->save();
-
- if ($nodeInfoAddress->uptime < $uptimeProbationStart) {
- $userAddress->extra_status = 'On Probation';
-
- if(!$nodeInfoAddress->uptime_time_start) {
- $nodeInfoAddress->uptime_time_start = now();
- }
-
- if(!$nodeInfoAddress->uptime_time_end) {
- $nodeInfoAddress->uptime_time_end = Carbon::now('UTC')->addHours($uptimeTime);
- }
- }
-
- if ($nodeInfoAddress->block_height_average < $blockHeightProbationStart) {
- $userAddress->extra_status = 'On Probation';
-
- if(!$nodeInfoAddress->block_height_average_time_start) {
- $nodeInfoAddress->block_height_average_time_start = now();
- }
-
- if(!$nodeInfoAddress->block_height_average_time_end) {
- $nodeInfoAddress->block_height_average_time_end = Carbon::now('UTC')->addHours($blockHeightTime);
+ // Not Suspended
+
+ $hasOnline = $hasOnProbation = $hasSuspended = false;
+ $revokeReason = [];
+
+ foreach ($addresses as $address) {
+ $public_address_node = strtolower($address->public_address_node);
+
+ $temp = AllNodeData2::select(['id', 'uptime'])
+ ->where('public_key', $public_address_node)
+ ->where('era_id', $current_era_id)
+ ->where('bid_inactive', 0)
+ ->where('in_auction', 1)
+ ->where('in_current_era', 1)
+ ->first();
+ if ($temp) {
+ // All Node Data2 Record Exists!
+
+ $hasOnline = true;
+ $address->node_status = 'Online';
+ $address->extra_status = null;
+ $address->save();
+
+ // Check Redmarks
+ if ($redmarks_revoke > 0) {
+ $bad_marks = Helper::calculateBadMarksRevoke($temp, $public_address_node, $settings);
+
+ if ($bad_marks > $redmarks_revoke) {
+ $address->extra_status = 'Suspended';
+ $address->probation_start = null;
+ $address->probation_end = null;
+ $address->save();
+ if (!in_array('Too many redmarks', $revokeReason)) {
+ $revokeReason[] = 'Too many redmarks';
+ }
}
}
- if ($nodeInfoAddress->update_responsiveness < $updateResponsivenessProbationStart) {
- $userAddress->extra_status = 'On Probation';
-
- if(!$nodeInfoAddress->update_responsiveness_time_start) {
- $nodeInfoAddress->update_responsiveness_time_start = now();
- }
-
- if(!$nodeInfoAddress->update_responsiveness_time_end) {
- $nodeInfoAddress->update_responsiveness_time_end = Carbon::now('UTC')->addHours($updateResponsivenessTime);
+ // Check Historical Performance
+ if (!$address->extra_status && $uptime_probation > 0) {
+ $uptime = Helper::calculateUptime($temp, $public_address_node, $settings);
+
+ if ($uptime < $uptime_probation) {
+ $address->extra_status = 'On Probation';
+ if (!$address->probation_start || !$address->probation_end) {
+ $address->probation_start = Carbon::now('UTC');
+ $address->probation_end = Carbon::now('UTC')->addHours($uptimeHours);
+ }
+ $address->save();
+
+ if ($address->probation_end <= Carbon::now('UTC')) {
+ $address->extra_status = 'Suspended';
+ $address->probation_start = null;
+ $address->probation_end = null;
+ $address->save();
+ if (!in_array('Poor uptime', $revokeReason)) {
+ $revokeReason[] = 'Poor uptime';
+ }
+ } else {
+ $hasOnProbation = true;
+ }
+ } else {
+ $address->probation_start = null;
+ $address->probation_end = null;
+ $address->save();
}
}
- $userAddress->save();
- $nodeInfoAddress->save();
-
- if ($userAddress->extra_status == 'On Probation') {
- if ($nodeInfoAddress->uptime_time_end <= $now && $nodeInfoAddress->uptime < $uptimeProbationStart) {
- $userAddress->extra_status = 'Suspended';
- }
- if ($nodeInfoAddress->block_height_average_time_end <= $now && $nodeInfoAddress->block_height_average < $blockHeightProbationStart) {
- $userAddress->extra_status = 'Suspended';
- }
- if ($nodeInfoAddress->update_responsiveness_time_end <= $now && $nodeInfoAddress->update_responsiveness < $updateResponsivenessProbationStart) {
- $userAddress->extra_status = 'Suspended';
- }
- $userAddress->save();
+ if ($address->extra_status == 'Suspended') {
+ $hasSuspended = true;
}
- }
-
- $inactive = (bool)($nodeInfoAddress->inactive ?? false);
-
- if($inactive) {
- $userAddress->node_status = 'Offline';
- $userAddress->extra_status = 'Suspended';
- $userAddress->save();
- }
- }
- // End For Each
-
- // Begin For Each
- $hasNotOfflineStatus = $hasNotSuspendedStatus = false;
- foreach ($addresses as $userAddress) {
- if ($userAddress->node_status != 'Offline') {
- $hasNotOfflineStatus = true;
- break;
- }
- }
- foreach ($addresses as $userAddress) {
- if ($userAddress->extra_status != 'Suspended') {
- $hasNotSuspendedStatus = true;
- break;
+ } else {
+ // All Node Data2 Record Doesn't Exist!
+
+ $address->node_status = 'Offline';
+ $address->extra_status = null;
+ $address->probation_start = null;
+ $address->probation_end = null;
+ $address->save();
}
}
- if (!$hasNotOfflineStatus) {
+ if ($hasOnline) {
+ $user->node_status = 'Online';
+ $user->save();
+ } else {
$user->node_status = 'Offline';
$user->save();
+ }
+
+ if ($hasOnProbation) {
+ $orgStatus = $user->profile->extra_status;
+
+ $user->profile->extra_status = 'On Probation';
+ $user->profile->save();
+
+ if ($orgStatus && $orgStatus == 'On Probation') {
+ //
+ } else {
+ EmailerUserJob::dispatch($user, 'User goes on probation');
+ }
} else {
- foreach ($addresses as $userAddress) {
- if ($userAddress->node_status == 'Online') {
- $user->node_status = 'Online';
- $user->save();
- break;
- }
- }
- if ($user->node_status != 'Online') {
- $user->node_status = null;
- $user->save();
- }
+ $user->profile->extra_status = null;
+ $user->profile->save();
}
- if (
- !$hasNotSuspendedStatus &&
- isset($user->profile) &&
- $user->profile
- ) {
+ if ($hasOnline && $hasSuspended) {
+ $orgStatus = $user->profile->extra_status;
+
$user->profile->extra_status = 'Suspended';
- $user->profile->save();
- } else if (isset($user->profile) && $user->profile) {
- foreach ($addresses as $userAddress) {
- if ($userAddress->extra_status == 'On Probation') {
- $user->profile->extra_status = 'On Probation';
- $user->save();
- break;
- }
- }
- if ($user->profile->extra_status != 'On Probation') {
- $user->profile->extra_status = null;
- $user->profile->save();
+ $user->profile->revoke_at = Carbon::now('UTC');
+ if (count($revokeReason) > 0) {
+ $user->profile->revoke_reason = implode(', ', $revokeReason);
}
+ $user->profile->save();
+
+ if ($orgStatus && $orgStatus == 'Suspended') {
+ //
+ } else {
+ EmailerUserJob::dispatch($user, 'User membership is revoked');
+ }
+ }
+ }
+ } else {
+ // Non-Verified Users
+
+ $user->node_status = null;
+ $user->save();
+
+ if ($user->profile) {
+ $user->profile->extra_status = null;
+ $user->profile->revoke_reason = null;
+ $user->profile->save();
+ }
+
+ if ($addresses && count($addresses) > 0) {
+ foreach ($addresses as $address) {
+ $address->node_status = null;
+ $address->extra_status = null;
+ $address->probation_start = null;
+ $address->probation_end = null;
+ $address->save();
}
- // End For Each
}
}
}
diff --git a/app/Console/Commands/CheckUpgrade.php b/app/Console/Commands/CheckUpgrade.php
new file mode 100644
index 00000000..35ca4931
--- /dev/null
+++ b/app/Console/Commands/CheckUpgrade.php
@@ -0,0 +1,30 @@
+limit(1)->first();
+ if (
+ !$lastUpgrade->reminder_24_sent &&
+ $lastUpgrade->activation_datetime > Carbon::now('UTC') &&
+ $lastUpgrade->activation_datetime <= Carbon::now('UTC')->addHours(24)
+ ) {
+ UpgradeReminder24::dispatch($lastUpgrade)->onQueue('default_long');
+ }
+ return 0;
+ }
+}
diff --git a/app/Console/Commands/HistoricalData.php b/app/Console/Commands/HistoricalData.php
new file mode 100644
index 00000000..e1d88d32
--- /dev/null
+++ b/app/Console/Commands/HistoricalData.php
@@ -0,0 +1,386 @@
+result->block->header->era_id ?? 0);
+
+ $historic_era = DB::select("
+ SELECT era_id
+ FROM all_node_data2
+ ORDER BY era_id DESC
+ LIMIT 1
+ ");
+
+ $historic_era = (int)($historic_era[0]->era_id ?? 6000);
+ $historic_block = 1;
+ $test_era = 0;
+ $timestamp = '1';
+
+ // reductive binary search algorithm
+ // $m = 1073741824;
+ $m = 1;
+
+ // find max in range first
+ while ($timestamp != '') {
+ $m *= 2;
+ $json = shell_exec($get_block.$node_arg.'-b '.$m);
+ $json = json_decode($json);
+ $test_era = (int)($json->result->block->header->era_id ?? 0);
+ info('finding max block ... '.$m);
+ $timestamp = $json->result->block->header->timestamp ?? '';
+ }
+
+ // run search algo
+ $historic_block = $m;
+
+ while ($test_era != $historic_era) {
+ $json = shell_exec($get_block.$node_arg.'-b '.$historic_block);
+ $json = json_decode($json);
+ $test_era = (int)($json->result->block->header->era_id ?? 0);
+ info('trying historic_block '.$historic_block.' ... got era: '.$test_era);
+ $timestamp = $json->result->block->header->timestamp ?? '';
+
+ if (
+ !$timestamp || $timestamp == '' ||
+ $test_era > $historic_era
+ ) {
+ info('historic_block too high');
+ $historic_block -= $m;
+ if ($historic_block < 1) $historic_block = 1;
+ $m = (int)($m / 2);
+ continue;
+ }
+
+ if ($test_era < $historic_era) {
+ info('historic_block too low');
+ $historic_block += $m;
+ $m = (int)($m / 2);
+ continue;
+ }
+ }
+
+ while ($current_era >= $historic_era) {
+ // first see if we have this era's auction info
+ $node_data = DB::select("
+ SELECT era_id
+ FROM all_node_data2
+ WHERE era_id = $historic_era
+ ");
+ $node_data = (int) ($node_data[0]->era_id ?? 0);
+
+ if ($node_data > 0) {
+ // era's auction info exists. do not need to fetch.
+ info('Already have era ' . $historic_era . ' data. skipping');
+ $historic_era += 1;
+ } else {
+ // decrease block height and check for new switch block
+ $command = $get_block . $node_arg . '-b ' . $historic_block;
+ $switch_block = shell_exec($command);
+ $json = json_decode($switch_block);
+ $era_id = (int)($json->result->block->header->era_id ?? 0);
+ info('Checking block '.$historic_block.' for era '.$historic_era.'. Found era '.$era_id);
+ $block_hash = $json->result->block->hash ?? '';
+ $timestamp = $json->result->block->header->timestamp ?? '';
+ $timestamp = Carbon::parse($timestamp)->format('Y-m-d H:i:s');
+
+ if ($era_id == 0) {
+ break;
+ }
+
+ if ($era_id == $historic_era) {
+ // start timer
+ $start_time = (int) time();
+
+ // get auction info for this new detected era switch
+ info($era_id . ' ' . $block_hash);
+ $historic_era += 1;
+ $command = $get_auction . $node_arg . '-b ' . $block_hash;
+ $auction_info = shell_exec($command);
+
+ // very large object. aprx 10MB
+ $decoded_response = json_decode($auction_info);
+ $auction_state = $decoded_response->result->auction_state ?? [];
+ $bids = $auction_state->bids ?? [];
+
+ // get era ID
+ $era_validators = $auction_state->era_validators ?? [];
+ $current_era_validators = $era_validators[0] ?? [];
+ $next_era_validators = $era_validators[1] ?? [];
+ $current_era_id = (int)($current_era_validators->era_id ?? 0);
+ $next_era_id = (int)($next_era_validators->era_id ?? 0);
+
+ info('Data aquired for era: ' . $current_era_id);
+
+ // set MBS array. minimum bid slot amount
+ $MBS_arr = [];
+
+ // get global uptimes from MAKE
+ $global_uptime = $nodeHelper->retrieveGlobalUptime($current_era_id);
+
+ // Set validator key object
+ $data = [
+ 'era_id' => $era_id,
+ 'validators' => []
+ ];
+
+ // loop auction era
+ info('Looping auction era - Appending uptime, bid, and daily earnings data');
+ foreach ($bids as $b) {
+ $public_key = strtolower($b->public_key ?? 'nill');
+ $bid = $b->bid ?? [];
+
+ // get self
+ $self_staked_amount = (int) ($bid->staked_amount ?? 0);
+ $delegation_rate = (int) ($bid->delegation_rate ?? 0);
+ $bid_inactive = (int) ($bid->inactive ?? false);
+
+ // calculate total stake, delegators + self stake
+ $delegators = (array) ($bid->delegators ?? []);
+ $delegators_count = count($delegators);
+ $delegators_staked_amount = 0;
+
+ foreach ($delegators as $delegator) {
+ $delegators_staked_amount += (int) ($delegator->staked_amount ?? 0);
+ }
+
+ // convert and calculate stake amounts
+ $delegators_staked_amount = (int) ($delegators_staked_amount / 1000000000);
+ $self_staked_amount = (int) ($self_staked_amount / 1000000000);
+ $total_staked_amount = $delegators_staked_amount + $self_staked_amount;
+
+ // append to MBS array and pluck 100th place later
+ $MBS_arr[$public_key] = $total_staked_amount;
+
+ // get node uptime from MAKE object
+ $uptime = 0;
+
+ foreach ($global_uptime as $uptime_array) {
+ $fvid = strtolower($uptime_array->public_key ?? '');
+ if ($fvid == $public_key) {
+ $uptime = (float)($uptime_array->average_score ?? 0);
+ break;
+ }
+ }
+
+ // define DB insert object for all public keys in this era
+ $data['validators'][$public_key] = [
+ 'public_key' => $public_key,
+ 'uptime' => $uptime,
+ 'current_era_weight' => 0,
+ 'next_era_weight' => 0,
+ 'in_current_era' => 0,
+ 'in_next_era' => 0,
+ 'in_auction' => 1,
+ 'bid_delegators_count' => $delegators_count,
+ 'bid_delegation_rate' => $delegation_rate,
+ 'bid_inactive' => $bid_inactive,
+ 'bid_self_staked_amount' => $self_staked_amount,
+ 'bid_delegators_staked_amount' => $delegators_staked_amount,
+ 'bid_total_staked_amount' => $total_staked_amount,
+ 'port8888_peers' => 0,
+ 'port8888_build_version' => '',
+ 'port8888_next_upgrade' => ''
+ ];
+
+ // look for existing peer by public key for port 8888 data
+ foreach ($port8888_responses as $port8888data) {
+ $our_public_signing_key = strtolower($port8888data['our_public_signing_key'] ?? '');
+
+ if ($our_public_signing_key == $public_key) {
+ // found in peers
+ $peer_count = (int) ($port8888data['peer_count'] ?? 0);
+ $era_id = (int) ($port8888data['last_added_block_info']['era_id'] ?? 0);
+ $block_height = (int) ($port8888data['last_added_block_info']['height'] ?? 0);
+ $build_version = $port8888data['build_version'] ?? '1.0.0';
+ $build_version = explode('-', $build_version)[0];
+ $chainspec_name = $port8888data['chainspec_name'] ?? 'casper';
+ $next_upgrade = $port8888data['next_upgrade']['protocol_version'] ?? '';
+ break;
+ }
+ }
+ }
+
+ // loop current era
+ $current_validator_weights = $current_era_validators->validator_weights ?? [];
+ info('Appending current era validator weights');
+
+ foreach ($current_validator_weights as $v) {
+ $public_key = strtolower($v->public_key ?? '');
+ $weight = (int) ($v->weight / 1000000000 ?? 0);
+
+ if (isset($data["validators"][$public_key])) {
+ $data['validators'][$public_key]['current_era_weight'] = $weight;
+ $data['validators'][$public_key]['in_current_era'] = 1;
+ } else {
+ $data['validators'][$public_key] = [
+ 'public_key' => $public_key,
+ 'uptime' => 0,
+ 'current_era_weight' => $weight,
+ 'next_era_weight' => 0,
+ 'in_current_era' => 1,
+ 'in_next_era' => 0,
+ 'in_auction' => 0,
+ 'bid_delegators_count' => 0,
+ 'bid_delegation_rate' => 0,
+ 'bid_inactive' => 1,
+ 'bid_self_staked_amount' => 0,
+ 'bid_delegators_staked_amount' => 0,
+ 'bid_total_staked_amount' => 0,
+ 'port8888_peers' => 0,
+ 'port8888_build_version' => '',
+ 'port8888_next_upgrade' => ''
+ ];
+ }
+ }
+
+ // loop next era
+ $next_validator_weights = $next_era_validators->validator_weights ?? [];
+ info('Appending next era validator weights');
+
+ foreach ($next_validator_weights as $v) {
+ $public_key = $v->public_key ?? '';
+ $weight = (int) ($v->weight / 1000000000 ?? 0);
+
+ if (isset($data["validators"][$public_key])) {
+ $data['validators'][$public_key]['next_era_weight'] = $weight;
+ $data['validators'][$public_key]['in_next_era'] = 1;
+ } else {
+ $data['validators'][$public_key] = [
+ 'public_key' => $public_key,
+ 'uptime' => 0,
+ 'current_era_weight' => $weight,
+ 'next_era_weight' => 0,
+ 'in_current_era' => 1,
+ 'in_next_era' => 0,
+ 'in_auction' => 0,
+ 'bid_delegators_count' => 0,
+ 'bid_delegation_rate' => 0,
+ 'bid_inactive' => 1,
+ 'bid_self_staked_amount' => 0,
+ 'bid_delegators_staked_amount' => 0,
+ 'bid_total_staked_amount' => 0,
+ 'port8888_peers' => 0,
+ 'port8888_build_version' => '',
+ 'port8888_next_upgrade' => ''
+ ];
+ }
+ }
+
+ // Primary DB insertion (time consuming)
+ info('Saving validator objects to DB...');
+
+ foreach ($data["validators"] as $v) {
+ DB::table('all_node_data2')->insert(
+ [
+ 'public_key' => $v['public_key'],
+ 'era_id' => $data['era_id'],
+ 'uptime' => $v['uptime'],
+ 'current_era_weight' => $v['current_era_weight'],
+ 'next_era_weight' => $v['next_era_weight'],
+ 'in_current_era' => $v['in_current_era'],
+ 'in_next_era' => $v['in_next_era'],
+ 'in_auction' => $v['in_auction'],
+ 'bid_delegators_count' => $v['bid_delegators_count'],
+ 'bid_delegation_rate' => $v['bid_delegation_rate'],
+ 'bid_inactive' => $v['bid_inactive'],
+ 'bid_self_staked_amount' => $v['bid_self_staked_amount'],
+ 'bid_delegators_staked_amount' => $v['bid_delegators_staked_amount'],
+ 'bid_total_staked_amount' => $v['bid_total_staked_amount'],
+ 'port8888_peers' => $v['port8888_peers'],
+ 'port8888_build_version' => $v['port8888_build_version'],
+ 'port8888_next_upgrade' => $v['port8888_next_upgrade'],
+ 'created_at' => $timestamp
+ ]
+ );
+
+ info($v["public_key"] . ' - done');
+ }
+
+ // find MBS
+ info('Finding MBS for this era');
+ rsort($MBS_arr);
+ $MBS = 0;
+ if (count($MBS_arr) > 0) {
+ $MBS = (float) ($MBS_arr[99] ?? $MBS_arr[count($MBS_arr) - 1]);
+ }
+
+ // save MBS in new table by current_era
+ $check = DB::select("
+ SELECT mbs
+ FROM mbs
+ WHERE era_id = $current_era_id
+ ");
+ $check = $check[0] ?? null;
+
+ if (!$check) {
+ DB::table('mbs')->insert([
+ 'era_id' => $current_era_id,
+ 'mbs' => $MBS,
+ 'created_at' => $timestamp
+ ]);
+ } else {
+ DB::table('mbs')
+ ->where('era_id', $current_era_id)
+ ->update([
+ 'mbs' => $MBS,
+ 'updated_at' => $timestamp
+ ]);
+ }
+
+ // end timer
+ $end_time = (int) time();
+
+ info("Time spent on era: " . ($end_time - $start_time));
+ }
+ $historic_block += 5;
+ }
+ }
+ info('done');
+ }
+}
\ No newline at end of file
diff --git a/app/Console/Commands/KycReport.php b/app/Console/Commands/KycReport.php
index fca59009..3b17b0ae 100644
--- a/app/Console/Commands/KycReport.php
+++ b/app/Console/Commands/KycReport.php
@@ -45,26 +45,26 @@ public function __construct()
public function handle()
{
// first do shufti temp records
- $now = Carbon::now();
- $yesterday = Carbon::now()->subHours(12);
+ $now = Carbon::now('UTC');
+ $yesterday = Carbon::now('UTC')->subHours(12);
$records_temp = ShuftiproTemp::where('status', 'pending')
->where('created_at', '<=', $yesterday)
->limit(10)
->get();
- $persons_stuck_in_pending = array();
- $known_reference_ids = array();
+ $persons_stuck_in_pending = [];
+ $known_reference_ids = [];
if($records_temp) {
foreach($records_temp as $record) {
$user_id = $record->user_id ?? 0;
$person = User::where('id', $user_id)->first();
- $persons_stuck_in_pending[] = array(
- "name" => $person->first_name.' '.$person->last_name,
- "email" => $person->email,
- "shufti_reference_id" => $record->reference_id,
- "shufti_timestamp" => $record->created_at
- );
+ $persons_stuck_in_pending[] = [
+ 'name' => $person->first_name.' '.$person->last_name,
+ 'email' => $person->email,
+ 'shufti_reference_id' => $record->reference_id,
+ 'shufti_timestamp' => $record->created_at
+ ];
$known_reference_ids[] = $record->reference_id;
}
@@ -76,33 +76,33 @@ public function handle()
->limit(10)
->get();
- $persons_stuck_denied = array();
+ $persons_stuck_denied = [];
if($records_pro) {
foreach($records_pro as $record) {
if(!in_array($record->reference_id, $known_reference_ids)) {
$user_id = $record->user_id ?? 0;
$person = User::where('id', $user_id)->first();
- $persons_stuck_denied[] = array(
- "name" => $person->first_name.' '.$person->last_name,
- "email" => $person->email,
- "shufti_reference_id" => $record->reference_id,
- "shufti_timestamp" => $record->created_at
- );
+ $persons_stuck_denied[] = [
+ 'name' => $person->first_name.' '.$person->last_name,
+ 'email' => $person->email,
+ 'shufti_reference_id' => $record->reference_id,
+ 'shufti_timestamp' => $record->created_at
+ ];
}
}
}
// now make a text list from the matching records
- $body = "";
+ $body = '';
$index = 1;
if($persons_stuck_in_pending) {
$body .= "Members pending for over 24 hours:
";
foreach($persons_stuck_in_pending as $p) {
- $body .= ''.(string)$index.'. ';
- $body .= $p['name'].', '.$p['email'].'
';
+ $body .= '' . (string) $index . '. ';
+ $body .= $p['name'] . ', ' . $p['email'] . '
';
$index += 1;
}
}
@@ -117,8 +117,8 @@ public function handle()
$body .= "Members denied by Shufti. Not reviewed yet:
";
foreach($persons_stuck_denied as $p) {
- $body .= ''.(string)$index.'. ';
- $body .= $p['name'].', '.$p['email'].'
';
+ $body .= '' . (string)$index . '. ';
+ $body .= $p['name'] . ', ' . $p['email'] . '
';
$index += 1;
}
}
@@ -126,7 +126,7 @@ public function handle()
// compose email to admins
if($persons_stuck_in_pending || $persons_stuck_denied) {
$emailerData = EmailerHelper::getEmailerData();
- $admins = $emailerData['admins'] ?? array();
+ $admins = $emailerData['admins'] ?? [];
if($admins) {
Mail::to($admins)->send(new AdminAlert('Casper Association portal KYC issues require attention', $body));
diff --git a/app/Console/Commands/MoveAddresses.php b/app/Console/Commands/MoveAddresses.php
deleted file mode 100644
index 934cf0d4..00000000
--- a/app/Console/Commands/MoveAddresses.php
+++ /dev/null
@@ -1,73 +0,0 @@
-whereNotNull('public_address_node')->get();
- if ($users && count($users) > 0) {
- foreach ($users as $user) {
- $address = $user->public_address_node;
- $userAddress = UserAddress::where('public_address_node', $address)->first();
- if (!$userAddress) {
- $userAddress = new UserAddress;
- $userAddress->user_id = $user->id;
- $userAddress->public_address_node = $address;
- $userAddress->node_verified_at = $user->node_verified_at;
- $userAddress->signed_file = $user->signed_file;
- $userAddress->is_fail_node = $user->is_fail_node;
- $userAddress->rank = $user->rank;
- $userAddress->pending_node = $user->pending_node;
- $userAddress->validator_fee = $user->validator_fee;
- $userAddress->node_status = $user->node_status;
- if ($user->profile && $user->profile->extra_status) {
- $userAddress->extra_status = $user->profile->extra_status;
- }
- $userAddress->save();
- }
- $user->has_address = 1;
- if ($user->node_verified_at) {
- $user->has_verified_address = 1;
- }
- $user->save();
- }
- }
- return 0;
- }
-}
diff --git a/app/Console/Commands/NodeInfo.php b/app/Console/Commands/NodeInfo.php
deleted file mode 100644
index 1801a076..00000000
--- a/app/Console/Commands/NodeInfo.php
+++ /dev/null
@@ -1,226 +0,0 @@
-updateStats();
- $this->updateNode();
- // $this->updateUptime();
- $this->updateRank();
- }
-
- public function updateNode()
- {
- $nodes = Node::whereNotNull('protocol_version')->get();
- $max_hight_block = $nodes->max('block_height');
- $base_block = 10;
- $versions = $nodes->pluck('protocol_version');
- $versions = $versions->toArray();
- usort($versions, 'version_compare');
- $highestVersion = (end($versions));
- $grouped = $nodes->groupBy('node_address');
- foreach ($grouped as $key => $values) {
- $key = strtolower($key);
-
- $versionsNodes = $values->pluck('protocol_version');
- $versionsNodes = $versionsNodes->toArray();
-
- usort($versionsNodes, 'version_compare');
-
- $highestVersionNode = (end($versionsNodes));
- if (version_compare($highestVersion, $highestVersionNode, '<')) {
- $userAddress = UserAddress::where('public_address_node', $key)->first();
- if ($userAddress) {
- $userAddress->is_fail_node = 1;
- $userAddress->node_status = 'Offline';
- $userAddress->save();
- }
- }
-
- $totalResponsiveness = $totalBlockHeight = 0;
-
- $nodeInfo = ModelsNodeInfo::where('node_address', $key)->first();
- if ($nodeInfo) {
- $groupedVersion = $values->groupBy('protocol_version');
- $countVersion = count($groupedVersion);
- $totalArray = [];
-
- foreach ($groupedVersion as $ver => $items) {
- $countItem = count($items);
- $totalVerResponsiveness = 0;
- $totalVerBlockHeight = 0;
- $totalVerPeer = 0;
-
- foreach ($items as $item) {
- $totalVerResponsiveness += $item->update_responsiveness;
- $totalVerBlockHeight += $item->block_height;
- $totalVerPeer += $item->peers;
- }
-
- $totalArray[$ver] = [
- 'totalVerResponsiveness' => round($totalVerResponsiveness / $countItem),
- 'totalVerBlockHeight' => round($totalVerBlockHeight / $countItem),
- 'totalVerPeer' => round($totalVerPeer / $countItem),
- ];
- }
- foreach ($totalArray as $total) {
- $totalResponsiveness += $total['totalVerResponsiveness'];
- $totalBlockHeight += $total['totalVerBlockHeight'];
- }
- $block_height = round($totalBlockHeight / $countVersion);
- $block_height_average = ($base_block - ($max_hight_block - $block_height)) * 10;
- if ($block_height_average <= 0) {
- $block_height_average = 0;
- }
- $nodeInfo->block_height_average = $block_height_average;
- $nodeInfo->save();
- }
- }
-
- $users = User::with(['addresses'])
- ->where('role', 'member')
- ->where('banned', 0)
- ->get();
- if ($users && count($users) > 0) {
- foreach ($users as $user) {
- $addresses = $user->addresses ?? null;
- if (!$addresses) {
- $user->is_fail_node = 1;
- $user->node_status = 'Offline';
- $user->save();
- } else if (count($addresses) > 0) {
- $hasNotFailNode = $hasNotOfflineStatus = false;
- foreach ($addresses as $address) {
- if ($address->is_fail_node != 1) {
- $hasNotFailNode = true;
- }
- if ($address->node_status != 'Offline') {
- $hasNotOfflineStatus = true;
- }
- }
- if (!$hasNotFailNode) {
- $user->is_fail_node = 1;
- $user->node_status = 'Offline';
- $user->save();
- } else if (!$hasNotOfflineStatus) {
- $user->node_status = 'Offline';
- $user->save();
- }
- }
- }
- }
- }
-
- public function updateUptime()
- {
- $nodes = ModelsNodeInfo::get();
- $now = Carbon::now('UTC');
- $time = $now->subDays(14);
- foreach ($nodes as $node) {
- $avg_uptime = Node::where('node_address', strtolower($node->node_address))
- ->whereNotNull('uptime')
- ->where('created_at', '>=', $time)
- ->avg('uptime');
- $node->uptime = $avg_uptime * 100;
- $node->save();
- }
- }
-
- public function updateRank()
- {
- $slide_value_uptime = $slide_value_update_responsiveness = $slide_value_delegotors = $slide_value_stake_amount = $slide_delegation_rate = 20;
-
- $max_uptime = Node::max('uptime');
- $max_uptime = $max_uptime * 100;
- $max_delegators = ModelsNodeInfo::max('delegators_count');
- $max_stake_amount = ModelsNodeInfo::max('total_staked_amount');
-
- DB::table('user_addresses')->update(['rank' => null]);
- $userAddresses = UserAddress::with(['user', 'user.metric', 'user.nodeInfo'])
- ->leftJoin('node_info', 'user_addresses.public_address_node', '=', 'node_info.node_address')
- ->select([
- 'user_addresses.*',
- 'node_info.delegation_rate',
- 'node_info.delegators_count',
- 'node_info.total_staked_amount',
- ])
- ->whereHas('user')
- ->get();
-
- foreach ($userAddresses as $userAddress) {
- $latest = Node::where('node_address', strtolower($userAddress->public_address_node))->whereNotnull('protocol_version')->orderBy('created_at', 'desc')->first();
- if (!$latest) $latest = new Node();
- $delegation_rate = $userAddress->delegation_rate ? $userAddress->delegation_rate / 100 : 1;
- if (!$userAddress->user->metric && !$userAddress->user->nodeInfo) {
- $userAddress->totalScore = null;
- continue;
- }
- $latest_uptime_node = isset($latest->uptime) ? $latest->uptime * 100 : null;
- $latest_update_responsiveness_node = $latest->update_responsiveness ?? null;
- $metric = $userAddress->user->metric;
- if (!$metric) $metric = new Metric();
-
- $latest_uptime_metric = $metric->uptime ? $metric->uptime : null;
- $latest_update_responsiveness_metric = $metric->update_responsiveness ? $metric->update_responsiveness : null;
-
- $latest_uptime = $latest_uptime_node ?? $latest_uptime_metric ?? 1;
- $latest_update_responsiveness = $latest_update_responsiveness_node ?? $latest_update_responsiveness_metric ?? 1;
-
- $delegators_count = $userAddress->delegators_count ? $userAddress->user->nodeInfo->delegators_count : 0;
- $total_staked_amount = $userAddress->total_staked_amount ? $userAddress->user->nodeInfo->total_staked_amount : 0;
-
- $uptime_score = ($slide_value_uptime * $latest_uptime) / 100;
- $update_responsiveness_score = ($slide_value_update_responsiveness * $latest_update_responsiveness) / 100;
- $dellegator_score = ($delegators_count / $max_delegators) * $slide_value_delegotors;
- $stake_amount_score = ($total_staked_amount / $max_stake_amount) * $slide_value_stake_amount;
- $delegation_rate_score = ($slide_delegation_rate * (1 - $delegation_rate)) / 100;
- $totalScore = $uptime_score + $update_responsiveness_score + $dellegator_score + $stake_amount_score + $delegation_rate_score;
-
- $userAddress->totalScore = $totalScore;
- }
- $userAddresses = $userAddresses->sortByDesc('totalScore')->values();
- foreach ($userAddresses as $key => $userAddress) {
- UserAddress::where('id', $userAddress->id)->update(['rank' => $key + 1]);
- $user = User::where('public_address_node', $userAddress->public_address_node)->first();
- if ($user) {
- $user->rank = $key + 1;
- $user->save();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/Console/Commands/NotifCheck.php b/app/Console/Commands/NotifCheck.php
index 4fe87980..f1eb5062 100644
--- a/app/Console/Commands/NotifCheck.php
+++ b/app/Console/Commands/NotifCheck.php
@@ -39,9 +39,13 @@ public function __construct()
*/
public function handle()
{
- $now = Carbon::now()->format('Y-m-d');
+ $now = Carbon::now('UTC')->format('Y-m-d');
// check notification waiting
- $waitingNotification = Notification::where('status', 'waiting')->where('setting', 1)->where('start_date', '<=', $now)->where('end_date', '>=', $now)->get();
+ $waitingNotification = Notification::where('status', 'waiting')
+ ->where('setting', 1)
+ ->where('start_date', '<=', $now)
+ ->where('end_date', '>=', $now)
+ ->get();
foreach ($waitingNotification as $data) {
$data->status = 'active';
$data->visibility = 'visible';
@@ -49,7 +53,9 @@ public function handle()
}
// check notification expired
- $expiredNotification = Notification::where('end_date', '<', $now)->where('setting', 1)->get();
+ $expiredNotification = Notification::where('end_date', '<', $now)
+ ->where('setting', 1)
+ ->get();
foreach ($expiredNotification as $data) {
$data->status = 'expired';
$data->visibility = 'hidden';
diff --git a/app/Console/Commands/PerkCheck.php b/app/Console/Commands/PerkCheck.php
index 6d4a47eb..62571af5 100644
--- a/app/Console/Commands/PerkCheck.php
+++ b/app/Console/Commands/PerkCheck.php
@@ -3,6 +3,7 @@
namespace App\Console\Commands;
use App\Models\Perk;
+use App\Jobs\PerkNotification;
use Carbon\Carbon;
use Illuminate\Console\Command;
@@ -39,17 +40,27 @@ public function __construct()
*/
public function handle()
{
- $now = Carbon::now()->format('Y-m-d');
+ $now = Carbon::now('UTC');
+
// check perk waiting
- $waitingPerks = Perk::where('status', 'waiting')->where('setting', 1)->where('start_date', '<=', $now)->where('end_date', '>=', $now)->get();
+ $waitingPerks = Perk::where('status', 'waiting')
+ ->where('setting', 1)
+ ->where('time_begin', '<=', $now)
+ ->where('time_end', '>=', $now)
+ ->get();
foreach ($waitingPerks as $perk) {
$perk->status = 'active';
$perk->visibility = 'visible';
$perk->save();
- }
+ PerkNotification::dispatch($perk)->onQueue('default_long');
+ }
+
// check perk expired
- $expiredPerks = Perk::where('end_date', '<', $now)->where('setting', 1)->where('status', '!=', 'expired')->get();
+ $expiredPerks = Perk::where('time_end', '<', $now)
+ ->where('setting', 1)
+ ->where('status', '!=', 'expired')
+ ->get();
foreach ($expiredPerks as $perk) {
$perk->status = 'expired';
$perk->visibility = 'hidden';
diff --git a/app/Console/Commands/RefreshAddress.php b/app/Console/Commands/RefreshAddress.php
deleted file mode 100644
index 54b32cc5..00000000
--- a/app/Console/Commands/RefreshAddress.php
+++ /dev/null
@@ -1,98 +0,0 @@
-where('refreshed', 0)
- ->orderBy('created_at', 'asc')
- ->offset(0)
- ->limit(50)
- ->get();
- if ($nodes) {
- foreach ($nodes as $node) {
- $address = strtolower($node->node_address);
- // $newAddress = (new ChecksumValidator())->do($address);
- $node->node_address = $address;
- $node->refreshed = 1;
- $node->save();
- }
- }
-
- $nodeInfos = NodeInfo::whereNotNull('node_address')
- ->where('refreshed', 0)
- ->orderBy('created_at', 'asc')
- ->offset(0)
- ->limit(50)
- ->get();
-
- if ($nodeInfos) {
- foreach ($nodeInfos as $nodeInfo) {
- $address = strtolower($nodeInfo->node_address);
- // $newAddress = (new ChecksumValidator())->do($address);
- $nodeInfo->node_address = $address;
- $nodeInfo->refreshed = 1;
- $nodeInfo->save();
- }
- }
-
- $users = User::whereNotNull('public_address_node')
- ->where('refreshed', 0)
- ->orderBy('created_at', 'asc')
- ->offset(0)
- ->limit(50)
- ->get();
- if ($users) {
- foreach ($users as $user) {
- $address = strtolower($user->public_address_node);
- // $newAddress = (new ChecksumValidator())->do($address);
- $user->public_address_node = $address;
- $user->refreshed = 1;
- $user->save();
- }
- }
-
- return 0;
- }
-}
diff --git a/app/Console/Commands/ShuftiproCheck.php b/app/Console/Commands/ShuftiproCheck.php
deleted file mode 100644
index 45f93e24..00000000
--- a/app/Console/Commands/ShuftiproCheck.php
+++ /dev/null
@@ -1,58 +0,0 @@
-orderBy('id', 'asc')
- ->get();
-
- foreach ($records as $record) {
- try {
- $shuftiproCheck->handle($record);
- } catch (\Exception $th) {
- Log::error($th->getMessage());
- }
- }
- }
-}
diff --git a/app/Console/Helper.php b/app/Console/Helper.php
index 7145edd2..1b7235fd 100644
--- a/app/Console/Helper.php
+++ b/app/Console/Helper.php
@@ -9,6 +9,8 @@
use App\Models\Profile;
use App\Models\Shuftipro;
use App\Models\User;
+use App\Models\Setting;
+use App\Models\AllNodeData2;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
@@ -22,6 +24,291 @@
class Helper
{
+ public static function generateString($strength = 16) {
+ $seed = str_split('ABCDEFGHJKLMNPQRSTUVWXYZ' . '2345678923456789');
+
+ shuffle($seed);
+ $hash = '';
+
+ foreach(array_rand($seed, $strength) as $k) {
+ $hash .= $seed[$k];
+ }
+
+ return $hash;
+ }
+
+ public static function checkAddressValidity($public_address_node) {
+ $current_era_id = self::getCurrentERAId();
+
+ $temp = AllNodeData2::select(['id'])
+ ->where('public_key', $public_address_node)
+ ->where('era_id', $current_era_id)
+ ->first();
+ if ($temp) return true;
+ return false;
+ }
+
+ public static function getSettings() {
+ $items = Setting::get();
+ $settings = [];
+ if ($items) {
+ foreach ($items as $item) {
+ $settings[$item->name] = $item->value;
+ }
+ }
+ if (!isset($settings['peers'])) $settings['peers'] = 0;
+ if (!isset($settings['eras_look_back'])) $settings['eras_look_back'] = 1;
+ if (!isset($settings['eras_to_be_stable'])) $settings['eras_to_be_stable'] = 1;
+ if (!isset($settings['voting_eras_to_vote'])) $settings['voting_eras_to_vote'] = 1;
+ if (!isset($settings['uptime_calc_size'])) $settings['uptime_calc_size'] = 1;
+ if (!isset($settings['voting_eras_since_redmark'])) $settings['voting_eras_since_redmark'] = 1;
+ if (!isset($settings['uptime_warning'])) $settings['uptime_warning'] = 1;
+ if (!isset($settings['uptime_probation'])) $settings['uptime_probation'] = 1;
+ if (!isset($settings['uptime_correction_unit'])) $settings['uptime_correction_unit'] = 'Weeks';
+ if (!isset($settings['uptime_correction_value'])) $settings['uptime_correction_value'] = 1;
+ if (!isset($settings['redmarks_revoke'])) $settings['redmarks_revoke'] = 1;
+ if (!isset($settings['redmarks_revoke_calc_size'])) $settings['redmarks_revoke_calc_size'] = 1;
+ if (!isset($settings['responsiveness_warning'])) $settings['responsiveness_warning'] = 1;
+ if (!isset($settings['responsiveness_probation'])) $settings['responsiveness_probation'] = 1;
+
+ $settings['current_era_id'] = self::getCurrentERAId();
+
+ return $settings;
+ }
+
+ public function getActiveMembers() {
+ $current_era_id = Helper::getCurrentERAId();
+ $temp = DB::select("
+ SELECT
+ a.public_key,
+ b.extra_status,
+ c.id, c.email, c.pseudonym, c.node_status,
+ d.status, d.extra_status as profile_extra_status
+ FROM all_node_data2 AS a
+ JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ JOIN users AS c
+ ON b.user_id = c.id
+ JOIN profile AS d
+ ON c.id = d.user_id
+ WHERE a.era_id = $current_era_id and c.email is not NULL and d.status = 'approved'
+ ");
+ return ($temp ?? []);
+ }
+
+ public static function calculateUptime($baseObject, $public_address_node, $settings = null) {
+ if (!$settings) $settings = self::getSettings();
+
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+ $uptime_calc_size = (int) ($settings['uptime_calc_size'] ?? 1);
+
+ $mbs = 0;
+ if (isset($baseObject->mbs)) {
+ $mbs = (float) ($baseObject->mbs ?? 0);
+ } else {
+ $temp = DB::select("
+ SELECT mbs
+ FROM mbs
+ WHERE era_id = $current_era_id
+ ");
+ $mbs = (float) ($temp[0]->mbs ?? 0);
+ }
+
+ $temp = DB::select("
+ SELECT in_current_era
+ FROM all_node_data2
+ WHERE public_key = '$public_address_node'
+ AND bid_total_staked_amount > $mbs
+ ORDER BY era_id DESC
+ LIMIT $uptime_calc_size
+ ");
+ if (!$temp) $temp = [];
+
+ $window = count($temp);
+ $missed = 0;
+ foreach ($temp as $c) {
+ $in = (bool) ($c->in_current_era ?? 0);
+ if (!$in) {
+ $missed += 1;
+ }
+ }
+
+ $uptime = (float) ($baseObject->uptime ?? 0);
+ if ($window > 0) {
+ $uptime = (float) (($uptime * ($window - $missed)) / $window);
+ }
+
+ return round($uptime, 2);
+ }
+
+ public static function calculateVariables($identifier, $public_address_node, $settings = null) {
+ if (!$settings) $settings = self::getSettings();
+
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+
+ if ($identifier == 'good_standing_eras') {
+ $temp = DB::select("
+ SELECT era_id
+ FROM all_node_data2
+ WHERE public_key = '$public_address_node'
+ AND (
+ in_current_era = 0 OR
+ bid_inactive = 1
+ )
+ ORDER BY era_id DESC
+ LIMIT 1
+ ");
+ $value = $current_era_id - (int) ($temp[0]->era_id ?? 0);
+ if ($value > 0) return $value;
+ return 0;
+ } else if ($identifier == 'total_active_eras') {
+ $temp = DB::select("
+ SELECT count(id) as tCount
+ FROM all_node_data2
+ WHERE public_key = '$public_address_node'
+ AND in_current_era = 1
+ AND bid_inactive = 0
+ ");
+ return (int) ($temp[0]->tCount ?? 0);
+ } else if ($identifier == 'bad_marks_info') {
+ $temp = DB::select("
+ SELECT era_id
+ FROM all_node_data2
+ WHERE public_key = '$public_address_node'
+ AND (
+ in_current_era = 0 OR
+ bid_inactive = 1
+ )
+ ORDER BY era_id DESC
+ ");
+ $total_bad_marks = count($temp ?? []);
+ $eras_since_bad_mark = $current_era_id - (int) ($temp[0]->era_id ?? 0);
+ return [
+ 'total_bad_marks' => $total_bad_marks,
+ 'eras_since_bad_mark' => $eras_since_bad_mark
+ ];
+ } else if ($identifier == 'min_era') {
+ $temp = DB::select("
+ SELECT era_id
+ FROM all_node_data2
+ WHERE public_key = '$public_address_node'
+ ORDER BY era_id ASC
+ LIMIT 1
+ ");
+ return (int) ($temp[0]->era_id ?? 0);
+ }
+ return 0;
+ }
+
+ public static function calculateBadMarksRevoke($baseObject, $public_address_node, $settings = null) {
+ if (!$settings) $settings = self::getSettings();
+
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+ $redmarks_revoke_calc_size = (int) ($settings['redmarks_revoke_calc_size'] ?? 1);
+
+ $window = $current_era_id - $redmarks_revoke_calc_size;
+ if ($window < 0) $window = 0;
+
+ $temp = DB::select("
+ SELECT count(era_id) AS bad_marks
+ FROM all_node_data2
+ WHERE public_key = '$public_address_node'
+ AND era_id > $window
+ AND (
+ in_current_era = 0 OR
+ bid_inactive = 1
+ )
+ ");
+ if (!$temp) $temp = [];
+
+ return (int) ($temp[0]->bad_marks ?? 0);
+ }
+
+ public static function getCurrentERAId() {
+ $record = DB::select("
+ SELECT era_id
+ FROM all_node_data2
+ ORDER BY era_id DESC
+ LIMIT 1
+ ");
+ if ($record && count($record) > 0) {
+ $current_era_id = (int) ($record[0]->era_id ?? 0);
+ return $current_era_id;
+ }
+ return 0;
+ }
+
+ public static function getTotalScore($r, $max_delegators, $max_stake_amount) {
+ $uptime_rate = $fee_rate = $count_rate = $stake_rate = 25;
+ if (isset($r->uptime_rate)) $uptime_rate = (float) $r->uptime_rate;
+ if (isset($r->fee_rate)) $fee_rate = (float) $r->fee_rate;
+ if (isset($r->count_rate)) $count_rate = (float) $r->count_rate;
+ if (isset($r->stake_rate)) $stake_rate = (float) $r->stake_rate;
+
+ $uptime_score = (float) ($uptime_rate * (float) $r->uptime / 100);
+ $uptime_score = $uptime_score < 0 ? 0 : $uptime_score;
+
+ $fee_score = $fee_rate * (1 - (float) ((float) $r->bid_delegation_rate / 100));
+ $fee_score = $fee_score < 0 ? 0 : $fee_score;
+
+ $count_score = (float) ((float) $r->bid_delegators_count / $max_delegators) * $count_rate;
+ $count_score = $count_score < 0 ? 0 : $count_score;
+
+ $stake_score = (float) ((float) $r->bid_total_staked_amount / $max_stake_amount) * $stake_rate;
+ $stake_score = $stake_score < 0 ? 0 : $stake_score;
+
+ return $uptime_score + $fee_score + $count_score + $stake_score;
+ }
+
+ public static function getRanking($current_era_id) {
+ $rankingData = [];
+
+ $ranking = DB::select("
+ SELECT
+ public_key, uptime,
+ bid_delegators_count,
+ bid_delegation_rate,
+ bid_total_staked_amount
+ FROM all_node_data2
+ WHERE era_id = $current_era_id
+ AND in_current_era = 1
+ AND in_next_era = 1
+ AND in_auction = 1
+ ");
+ $max_delegators = $max_stake_amount = 0;
+
+ foreach ($ranking as $r) {
+ if ((int) $r->bid_delegators_count > $max_delegators) {
+ $max_delegators = (int) $r->bid_delegators_count;
+ }
+ if ((int) $r->bid_total_staked_amount > $max_stake_amount) {
+ $max_stake_amount = (int) $r->bid_total_staked_amount;
+ }
+ }
+
+ foreach ($ranking as $r) {
+ $rankingData['ranking'][$r->public_key] = self::getTotalScore($r, $max_delegators, $max_stake_amount);
+ }
+
+ uasort($rankingData['ranking'], function($x, $y) {
+ if ($x == $y) {
+ return 0;
+ }
+ return ($x > $y) ? -1 : 1;
+ });
+
+ $sorted_ranking = [];
+ $i = 1;
+ foreach ($rankingData['ranking'] as $public_key => $score) {
+ $sorted_ranking[$public_key] = $i;
+ $i += 1;
+ }
+ $rankingData['ranking'] = $sorted_ranking;
+ $rankingData['node_rank_total'] = count($sorted_ranking);
+
+ return $rankingData;
+ }
+
public static function isAccessBlocked($user, $page) {
if ($user->role == 'admin') return false;
$flag = false;
@@ -36,11 +323,10 @@ public static function isAccessBlocked($user, $page) {
return $flag;
}
- public static function publicKeyToAccountHash($public_key)
- {
+ public static function publicKeyToAccountHash($public_key) {
$public_key = (string)$public_key;
$first_byte = substr($public_key, 0, 2);
-
+
if($first_byte === '01') {
$algo = unpack('H*', 'ed25519');
} else {
@@ -48,119 +334,136 @@ public static function publicKeyToAccountHash($public_key)
}
$algo = $algo[1] ?? '';
-
+
$blake2b = new Blake2b();
$account_hash = bin2hex($blake2b->hash(hex2bin($algo.'00'.substr($public_key, 2))));
return $account_hash;
}
- public static function getAccountInfoStandard($user)
- {
+ public static function getStateRootHash() {
+ $get_block = 'casper-client get-block ';
+ $node_arg = '--node-address http://' . getenv('NODE_IP') . ':7777/rpc';
+
+ $json = shell_exec($get_block . $node_arg);
+ $json = json_decode($json);
+
+ $state_root_hash = $json->result->block->header->state_root_hash ?? '';
+ return $state_root_hash;
+ }
+
+ public static function getAccountInfoStandard($user) {
$vid = strtolower($user->public_address_node ?? '');
if (!$vid) return;
+
+ try {
+ // convert to account hash
+ $account_hash = self::publicKeyToAccountHash($vid);
+
+ $uid = $user->id ?? 0;
+ $pseudonym = $user->pseudonym ?? null;
+
+ $account_info_urls_uref = getenv('ACCOUNT_INFO_STANDARD_URLS_UREF');
+ $node_ip = 'http://' . getenv('NODE_IP') . ':7777';
+ $casper_client = new RpcClient($node_ip);
+ $latest_block = $casper_client->getLatestBlock();
+ $block_hash = $latest_block->getHash();
+ $state_root_hash = $casper_client->getStateRootHash($block_hash);
+ $curl = curl_init();
+
+ $json_data = [
+ 'id' => (int) time(),
+ 'jsonrpc' => '2.0',
+ 'method' => 'state_get_dictionary_item',
+ 'params' => [
+ 'state_root_hash' => $state_root_hash,
+ 'dictionary_identifier' => [
+ 'URef' => [
+ 'seed_uref' => $account_info_urls_uref,
+ 'dictionary_item_key' => $account_hash,
+ ]
+ ]
+ ]
+ ];
+
+ curl_setopt($curl, CURLOPT_URL, $node_ip . '/rpc');
+ curl_setopt($curl, CURLOPT_POST, true);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data));
+ curl_setopt($curl, CURLOPT_HTTPHEADER, [
+ 'Accept: application/json',
+ 'Content-type: application/json',
+ ]);
- // convert to account hash
- $account_hash = self::publicKeyToAccountHash($vid);
-
- $uid = $user->id ?? 0;
- $pseudonym = $user->pseudonym ?? null;
-
- $account_info_urls_uref = getenv('ACCOUNT_INFO_STANDARD_URLS_UREF');
- $node_ip = 'http://' . getenv('NODE_IP') . ':7777';
- $casper_client = new RpcClient($node_ip);
- $latest_block = $casper_client->getLatestBlock();
- $block_hash = $latest_block->getHash();
- $state_root_hash = $casper_client->getStateRootHash($block_hash);
- $curl = curl_init();
-
- $json_data = array(
- 'id' => (int) time(),
- 'jsonrpc' => '2.0',
- 'method' => 'state_get_dictionary_item',
- 'params' => array(
- 'state_root_hash' => $state_root_hash,
- 'dictionary_identifier' => array(
- 'URef' => array(
- 'seed_uref' => $account_info_urls_uref,
- 'dictionary_item_key' => $account_hash,
- )
- )
- )
- );
-
- curl_setopt($curl, CURLOPT_URL, $node_ip . '/rpc');
- curl_setopt($curl, CURLOPT_POST, true);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($json_data));
- curl_setopt($curl, CURLOPT_HTTPHEADER, array(
- 'Accept: application/json',
- 'Content-type: application/json',
- ));
-
- $response = curl_exec($curl);
- $decodedResponse = [];
- if ($response) $decodedResponse = json_decode($response, true);
- $parsed = $decodedResponse['result']['stored_value']['CLValue']['parsed'] ?? '';
- $json = array();
-
- if($parsed) {
- curl_setopt(
- $curl,
- CURLOPT_URL,
- $parsed.'/.well-known/casper/account-info.casper.json'
- );
- curl_setopt($curl, CURLOPT_POST, false);
$response = curl_exec($curl);
+ $decodedResponse = [];
- try {
- $json = json_decode($response, true);
- } catch (\Exception $e) {
- $json = array();
+ if ($response) {
+ $decodedResponse = json_decode($response, true);
}
- }
- curl_close($curl);
+ $parsed = $decodedResponse['result']['stored_value']['CLValue']['parsed'] ?? '';
+ $json = [];
+
+ if($parsed) {
+ curl_setopt(
+ $curl,
+ CURLOPT_URL,
+ $parsed . '/.well-known/casper/account-info.casper.json'
+ );
+ curl_setopt($curl, CURLOPT_POST, false);
+ $response = curl_exec($curl);
+
+ try {
+ $json = json_decode($response, true);
+ } catch (\Exception $e) {
+ $json = [];
+ }
+ }
- $blockchain_name = $json['owner']['name'] ?? null;
- $blockchain_desc = $json['owner']['description'] ?? null;
- $blockchain_logo = $json['owner']['branding']['logo']['png_256'] ?? null;
- $profile = Profile::where('user_id', $uid)->first();
+ curl_close($curl);
- if ($profile && $json) {
- if ($blockchain_name) {
- $profile->blockchain_name = $blockchain_name;
- }
+ $blockchain_name = $json['owner']['name'] ?? null;
+ $blockchain_desc = $json['owner']['description'] ?? null;
+ $blockchain_logo = $json['owner']['branding']['logo']['png_256'] ?? null;
+ $profile = Profile::where('user_id', $uid)->first();
- if ($blockchain_desc) {
- $profile->blockchain_desc = $blockchain_desc;
- }
+ if ($profile && $json) {
+ if ($blockchain_name) {
+ $profile->blockchain_name = $blockchain_name;
+ }
- if ($blockchain_logo && $user->avatar == null) {
- $user->avatar = $blockchain_logo;
- $user->save();
- }
+ if ($blockchain_desc) {
+ $profile->blockchain_desc = $blockchain_desc;
+ }
+
+ if ($blockchain_logo && $user->avatar == null) {
+ $user->avatar = $blockchain_logo;
+ $user->save();
+ }
- $profile->save();
- $shufti_profile = Shuftipro::where('user_id', $uid)->first();
-
- if (
- $shufti_profile &&
- $shufti_profile->status == 'approved' &&
- $pseudonym
- ) {
- $shuft_status = $shufti_profile->status;
- $reference_id = $shufti_profile->reference_id;
- $hash = md5($pseudonym . $reference_id . $shuft_status);
- $profile->casper_association_kyc_hash = $hash;
$profile->save();
+ $shufti_profile = Shuftipro::where('user_id', $uid)->first();
+
+ if (
+ $shufti_profile &&
+ $shufti_profile->status == 'approved' &&
+ $pseudonym
+ ) {
+ $shuft_status = $shufti_profile->status;
+ $reference_id = $shufti_profile->reference_id;
+ $hash = md5($pseudonym . $reference_id . $shuft_status);
+ $profile->casper_association_kyc_hash = $hash;
+ $profile->save();
+ }
}
+ } catch (\Exception $ex) {
+ //
}
}
// Get Token Price
- public static function getTokenPrice()
- {
+ public static function getTokenPrice() {
$url = 'https://pro-api.coinmarketcap.com/v1/tools/price-conversion';
$apiKey = config('services.token_price.api_key');
@@ -174,107 +477,4 @@ public static function getTokenPrice()
return $response->json();
}
-
- public static function getNodeInfo($user, $public_address_node = null)
- {
- if (!$public_address_node) $public_address_node = $user->public_address_node;
-
- $max_update_responsiveness = DB::select("SELECT max(update_responsiveness) as max_update_responsiveness FROM
- (
- SELECT MAX(update_responsiveness) as update_responsiveness FROM metric
- UNION
- SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info
- ) AS results
- ;");
- $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0;
-
- $max_peers = DB::select("SELECT max(peers) as max_peers FROM
- (
- SELECT MAX(peers) as peers FROM metric
- UNION
- SELECT MAX(peers) as peers FROM node_info
- ) AS results
- ;");
- $max_peers = $max_peers[0]->max_peers ?? 0;
- $max_block_height = Node::max('block_height');
- $max_uptime = DB::select("SELECT max(uptime) as max_uptime FROM
- (
- SELECT MAX(uptime) as uptime FROM metric
- UNION
- SELECT MAX(uptime) as uptime FROM node_info
- ) AS results
- ;");
- $max_uptime = $max_uptime[0]->max_uptime ?? 0;
-
- $latest = Node::where('node_address', strtolower($public_address_node))
- ->whereNotnull('protocol_version')
- ->orderBy('created_at', 'desc')
- ->first();
-
- if (!$latest) {
- $latest = new Node();
- }
-
- $metric = Metric::where('user_id', $user->id)->first();
-
- if (!$metric) {
- $metric = new Metric();
- }
-
- $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null;
-
- $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first();
-
- if (!$nodeInfo) {
- $nodeInfo = new NodeInfo();
- }
-
- $metric->avg_uptime = $nodeInfo->uptime ?? $metric->uptime ?? null;
- $metric->avg_block_height_average = $nodeInfo->block_height ?? $metric_block_height;
- $metric->avg_update_responsiveness = $nodeInfo->update_responsiveness ?? $metric->update_responsiveness ?? null;
- $metric->avg_peers = $nodeInfo->peers ?? $metric->peers ?? null;
-
- $metric->max_peers = $max_peers;
- $metric->max_update_responsiveness = $max_update_responsiveness;
- $metric->max_block_height_average = $max_block_height;
- $metric->max_uptime = $max_uptime;
-
- $metric->peers = $latest->peers ?? $metric->peers ?? null;
- $metric->update_responsiveness = $latest->update_responsiveness ?? $metric->update_responsiveness ?? null;
- $metric->block_height_average = $latest->block_height ?? $metric_block_height;
- $metric->uptime = $nodeInfo->uptime ?? $metric->uptime ?? null;
-
- $monitoringCriteria = MonitoringCriteria::get();
- $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first();
- $rank = $user->rank;
- $delegators = 0;
- $stake_amount = 0;
- $self_staked_amount = 0;
- $is_open_port = 0;
-
- if ($nodeInfo) {
- $delegators = $nodeInfo->delegators_count;
- $stake_amount = $nodeInfo->total_staked_amount;
- $self_staked_amount = $nodeInfo->self_staked_amount;
- $is_open_port = $nodeInfo->is_open_port;
- }
-
- $mbs = NodeInfo::max('mbs');
- $metric->mbs = $mbs;
- $metric->rank = $rank;
- $metric->is_open_port = $is_open_port;
- $metric->delegators = $delegators;
- $metric->stake_amount = $stake_amount;
- $metric->self_staked_amount = $self_staked_amount;
- $metric['node_status'] = $user->node_status;
- $metric['monitoring_criteria'] = $monitoringCriteria;
- return $metric;
- }
-
- public static function paginate($items, $perPage = 5, $page = null, $options = [])
- {
- $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
- $items = $items instanceof Collection ? $items : Collection::make($items);
- return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
- }
}
\ No newline at end of file
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index c6c45b75..b90fd1f6 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -24,38 +24,39 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
- // $schedule->command('inspire')->hourly();
$schedule->command('ballot:check')
- ->everyMinute()
+ ->everyTwoMinutes()
->runInBackground();
- /*
- $schedule->command('shuftipro:check')
- ->everyFiveMinutes()
+
+ $schedule->command('ballot:check2')
+ ->hourly()
+ ->runInBackground();
+
+ $schedule->command('upgrade:check')
+ ->hourly()
->runInBackground();
- // ->withoutOverlapping();
- */
+
$schedule->command('perk:check')
->everyThirtyMinutes()
->runInBackground();
+
$schedule->command('notif:check')
->dailyAt('00:01')
->runInBackground();
+
$schedule->command('node-status:check')
->everyFiveMinutes()
->runInBackground();
+
$schedule->command('token-price:check')
->everyThirtyMinutes()
->runInBackground();
- $schedule->command('node-info')
- ->everyFifteenMinutes()
- ->runInBackground();
- $schedule->command('refresh:address')
+
+ $schedule->command('historical-data')
+ ->withoutOverlapping()
->everyFiveMinutes()
->runInBackground();
-
- /**
- * Added by blockchainthomas. Cron for alerting admins of members stuck at KYC on a daily basis
- */
+
$schedule->command('kyc:report')
->dailyAt('10:02')
->runInBackground();
diff --git a/app/Helpers/helper.php b/app/Helpers/helper.php
deleted file mode 100644
index 62044e23..00000000
--- a/app/Helpers/helper.php
+++ /dev/null
@@ -1,73 +0,0 @@
- $memory,
- 'totalram' => $totalram,
- 'usedmemInGB' => $usedmemInGB,
- 'load' => $load,
- ];
-}
-
-// Get Settings
-function getSettings()
-{
- // Get Settings
- $settings = [];
- $items = Setting::get();
- if ($items) {
- foreach ($items as $item) {
- $settings[$item->name] = $item->value;
- }
- }
- return $settings;
-}
diff --git a/app/Http/Controllers/Api/V1/AdminController.php b/app/Http/Controllers/Api/V1/AdminController.php
index 87c51f53..16a805cc 100644
--- a/app/Http/Controllers/Api/V1/AdminController.php
+++ b/app/Http/Controllers/Api/V1/AdminController.php
@@ -7,6 +7,9 @@
use App\Http\Controllers\Controller;
use App\Http\EmailerHelper;
+use App\Jobs\BallotNotification;
+use App\Jobs\NewUpgradeNotification;
+
use App\Mail\AdminAlert;
use App\Mail\ResetKYC;
use App\Mail\ResetPasswordMail;
@@ -41,6 +44,13 @@
use App\Models\VerifyUser;
use App\Models\Vote;
use App\Models\VoteResult;
+use App\Models\ContactRecipient;
+use App\Models\AllNodeData2;
+use App\Models\ReinstatementHistory;
+use App\Models\Upgrade;
+use App\Models\UpgradeUser;
+
+use App\Services\NodeHelper;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
@@ -59,166 +69,916 @@
class AdminController extends Controller
{
- public function getUsers(Request $request)
+ public function getUpgrades(Request $request) {
+ $upgrades = Upgrade::orderBy('id', 'asc')->get();
+ return $this->successResponse($upgrades);
+ }
+
+ public function getSingleUpgrade($id) {
+ $upgrade = Upgrade::find($id);
+ if ($upgrade) {
+ return $this->successResponse($upgrade);
+ }
+ return $this->errorResponse('The Upgrade does not exist', Response::HTTP_BAD_REQUEST);
+ }
+
+ public function createUpgrade(Request $request) {
+ $validator = Validator::make($request->all(), [
+ 'version' => 'required|string|max:70',
+ 'activation_era' => 'required|integer',
+ 'activation_date' => 'required|date_format:Y-m-d',
+ 'link' => 'required|url|max:255',
+ 'notes' => 'required',
+ ]);
+ if ($validator->fails()) {
+ return $this->validateResponse($validator->errors());
+ }
+
+ $version = $request->version;
+ $link = $request->link;
+ $notes = $request->notes;
+ $activation_era = (int) $request->activation_era;
+ $activation_date = $request->activation_date;
+ $activation_datetime = $activation_date . ' 00:00:00';
+
+ if ($activation_era < 1) {
+ return $this->errorResponse('Activation ERA must be greater than 1', Response::HTTP_BAD_REQUEST);
+ }
+
+ $temp = DB::select("
+ SELECT
+ MAX(activation_era) as era
+ FROM upgrades
+ ");
+ $maxERA = (int) ($temp[0]->era ?? 0);
+
+ if ($activation_era <= $maxERA) {
+ return $this->errorResponse('Activation ERA must be greater than ' . $maxERA, Response::HTTP_BAD_REQUEST);
+ }
+
+ $upgradeRecord = Upgrade::where('version', $version)->first();
+ if ($upgradeRecord) {
+ return $this->errorResponse('The Version No is already used', Response::HTTP_BAD_REQUEST);
+ }
+
+ $upgradeRecord = new Upgrade;
+ $upgradeRecord->version = $version;
+ $upgradeRecord->activation_era = $activation_era;
+ $upgradeRecord->activation_date = $activation_date;
+ $upgradeRecord->activation_datetime = $activation_datetime;
+ $upgradeRecord->link = $link;
+ $upgradeRecord->notes = $notes;
+ $upgradeRecord->save();
+
+ NewUpgradeNotification::dispatch($upgradeRecord)->onQueue('default_long');
+
+ return $this->successResponse($upgradeRecord);
+ }
+
+ public function updateUpgrade($id, Request $request) {
+ $validator = Validator::make($request->all(), [
+ 'version' => 'required|string|max:70',
+ 'activation_era' => 'required|integer',
+ 'activation_date' => 'required|date_format:Y-m-d',
+ 'link' => 'required|url|max:255',
+ 'notes' => 'required',
+ ]);
+ if ($validator->fails()) {
+ return $this->validateResponse($validator->errors());
+ }
+
+ $upgradeRecord = Upgrade::find($id);
+ if (!$upgradeRecord) {
+ return $this->errorResponse('The Upgrade does not exist', Response::HTTP_BAD_REQUEST);
+ }
+
+ $version = $request->version;
+ $link = $request->link;
+ $notes = $request->notes;
+ $activation_era = (int) $request->activation_era;
+ $activation_date = $request->activation_date;
+ $activation_datetime = $activation_date . ' 00:00:00';
+
+ if ($activation_era < 1) {
+ return $this->errorResponse('Activation ERA must be greater than 1', Response::HTTP_BAD_REQUEST);
+ }
+
+ $temp = DB::select("
+ SELECT
+ MAX(activation_era) as era
+ FROM upgrades
+ where id != $id
+ ");
+ $maxERA = (int) ($temp[0]->era ?? 0);
+
+ if ($activation_era <= $maxERA) {
+ return $this->errorResponse('Activation ERA must be greater than ' . $maxERA, Response::HTTP_BAD_REQUEST);
+ }
+
+ $upgradeRecordTemp = Upgrade::where('version', $version)
+ ->where('id', '!=', $id)
+ ->first();
+ if ($upgradeRecordTemp) {
+ return $this->errorResponse('The Version No is already used', Response::HTTP_BAD_REQUEST);
+ }
+
+ $upgradeRecord->version = $version;
+ $upgradeRecord->activation_era = $activation_era;
+ $upgradeRecord->activation_date = $activation_date;
+ $upgradeRecord->activation_datetime = $activation_datetime;
+ $upgradeRecord->link = $link;
+ $upgradeRecord->notes = $notes;
+ $upgradeRecord->save();
+
+ return $this->successResponse($upgradeRecord);
+ }
+
+ public function deleteUpgrade($id) {
+ $user = auth()->user();
+ if (!$user || $user->role != 'admin') {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ UpgradeUser::where('upgrade_id', $id)->delete();
+ Upgrade::where('id', $id)->delete();
+
+ return $this->metaSuccess();
+ }
+
+ public function allErasUser($id) {
+ $user = User::where('id', $id)->first();
+ $user_id = $id;
+
+ if (!$user || $user->role == 'admin') {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ $settings = Helper::getSettings();
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+
+ $return = [
+ 'eras' => [],
+ 'addresses' => []
+ ];
+
+ $uptime_calc_size = isset($settings['uptime_calc_size']) ? (int) $settings['uptime_calc_size'] : 1;
+
+ $era_minus_360 = $current_era_id - $uptime_calc_size;
+ if ($era_minus_360 < 1) {
+ $era_minus_360 = 1;
+ }
+
+ // get addresses data
+ $addresses = DB::select("
+ SELECT
+ a.public_key
+ FROM all_node_data2 AS a
+ JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ WHERE a.era_id = $current_era_id
+ AND b.user_id = $user_id
+ ORDER BY a.era_id DESC
+ ");
+ if (!$addresses) $addresses = [];
+
+ foreach ($addresses as $address) {
+ $return['addresses'][] = $address->public_key;
+ }
+
+ $eras = DB::select("
+ SELECT
+ a.public_key, a.era_id, a.created_at,
+ a.in_current_era, a.in_auction,
+ a.bid_inactive, a.uptime
+ FROM all_node_data2 AS a
+ JOIN user_addresses
+ ON a.public_key = user_addresses.public_address_node
+ JOIN users
+ ON user_addresses.user_id = users.id
+ WHERE users.id = $user_id
+ AND era_id > $era_minus_360
+ ORDER BY a.era_id DESC
+ ");
+ if (!$eras) $eras = [];
+
+ $sorted_eras = [];
+
+ // for each node address's era
+ foreach ($eras as $era) {
+ $era_id = $era->era_id ?? 0;
+ $era_start_time = $era->created_at ?? '';
+ $public_key = $era->public_key;
+
+ if (!isset($sorted_eras[$era_id])) {
+ $sorted_eras[$era_id] = [
+ 'era_start_time' => $era_start_time,
+ 'addresses' => []
+ ];
+ }
+
+ $sorted_eras[$era_id]['addresses'][$public_key] = [
+ 'in_pool' => $era->in_auction,
+ 'rewards' => $era->uptime,
+ ];
+ }
+
+ $return['eras'] = $sorted_eras;
+
+ return $this->successResponse($return);
+ }
+
+ public function allEras() {
+ $settings = Helper::getSettings();
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+
+ // define return object
+ $return = [
+ 'addresses' => [],
+ 'users' => []
+ ];
+
+ // get addresses data
+ $addresses = DB::select("
+ SELECT
+ a.public_key, a.uptime, b.user_id
+ FROM all_node_data2 AS a
+ JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ WHERE a.era_id = $current_era_id
+ ");
+ if (!$addresses) $addresses = [];
+
+ // for each member's node address
+ foreach ($addresses as $address) {
+ $p = $address->public_key ?? '';
+
+ $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings);
+ $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0);
+ $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id);
+
+ $min_era_id = Helper::calculateVariables('min_era', $p, $settings);
+ $eras_active = $current_era_id - $min_era_id;
+
+ $historical_performance = Helper::calculateUptime($address, $p, $settings);
+
+ $return['addresses'][$p] = [
+ 'uptime' => $historical_performance,
+ 'eras_active' => $eras_active,
+ 'eras_since_bad_mark' => $eras_since_bad_mark,
+ 'total_bad_marks' => $total_bad_marks
+ ];
+ }
+
+ $users = DB::select("
+ SELECT
+ a.id, a.first_name, a.last_name, a.pseudonym
+ FROM users AS a
+ WHERE a.role = 'member'
+ AND a.has_address = 1
+ AND a.banned = 0;
+ ");
+ if (!$users) $users = [];
+
+ foreach ($users as $user) {
+ $return['users'][] = [
+ 'user_id' => $user->id,
+ 'name' => $user->first_name . ' ' . $user->last_name,
+ 'pseudonym' => $user->pseudonym,
+ ];
+ }
+
+ return $this->successResponse($return);
+ }
+
+ public function getNodesPage() {
+ $settings = Helper::getSettings();
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+
+ $return = [
+ 'mbs' => 0,
+ 'ranking' => [],
+ 'addresses' => []
+ ];
+
+ $nodeHelper = new NodeHelper();
+
+ $rankingData = Helper::getRanking($current_era_id);
+
+ $return['ranking'] = $rankingData['ranking'];
+
+ // get user addresses
+ $addresses = DB::select("
+ SELECT
+ a.public_key, a.bid_delegators_count,
+ a.bid_total_staked_amount, a.bid_self_staked_amount,
+ a.uptime, a.bid_inactive, a.in_current_era,
+ a.port8888_peers AS peers
+ FROM all_node_data2 AS a
+ JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ JOIN users AS c
+ ON b.user_id = c.id
+ WHERE a.era_id = $current_era_id
+ ");
+ if (!$addresses) $addresses = [];
+
+ // for each member's node address
+ foreach ($addresses as $address) {
+ $a = $address->public_key ?? '';
+
+ $badMarkValues = Helper::calculateVariables('bad_marks_info', $a, $settings);
+ $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0);
+ $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id);
+
+ $min_era_id = Helper::calculateVariables('min_era', $a, $settings);
+ $total_eras = $current_era_id - $min_era_id;
+
+ $historical_performance = Helper::calculateUptime($address, $a, $settings);
+
+ // Calc earning
+ $one_day_ago = Carbon::now('UTC')->subHours(24);
+ $temp = DB::select("
+ SELECT bid_self_staked_amount
+ FROM all_node_data2
+ WHERE public_key = '$a'
+ AND created_at < '$one_day_ago'
+ ORDER BY era_id DESC
+ LIMIT 1
+ ");
+ if (!$temp) $temp = [];
+
+ $daily_earning = (float) ($temp[0]->bid_self_staked_amount ?? 0);
+ $daily_earning = (float) $address->bid_self_staked_amount - $daily_earning;
+ $daily_earning = $daily_earning < 0 ? 0 : $daily_earning;
+
+ $earning_day = $nodeHelper->getValidatorRewards($a, 'day');
+ $earning_week = $nodeHelper->getValidatorRewards($a, 'week');
+ $earning_month = $nodeHelper->getValidatorRewards($a, 'month');
+ $earning_year = $nodeHelper->getValidatorRewards($a, 'year');
+
+ if (
+ $address->in_current_era == 0 ||
+ $address->bid_inactive == 1
+ ) {
+ $failing = 1;
+ } else {
+ $failing = 0;
+ }
+
+ $return['addresses'][$a] = [
+ 'stake_amount' => $address->bid_total_staked_amount,
+ 'delegators' => $address->bid_delegators_count,
+ 'uptime' => $historical_performance,
+ 'update_responsiveness' => 100,
+ 'peers' => $address->peers,
+ 'daily_earning' => $daily_earning,
+ 'total_eras' => $total_eras,
+ 'eras_since_bad_mark' => $eras_since_bad_mark,
+ 'total_bad_marks' => $total_bad_marks,
+ 'failing' => $failing,
+ 'validator_rewards' => [
+ 'day' => $earning_day,
+ 'week' => $earning_week,
+ 'month' => $earning_month,
+ 'year' => $earning_year
+ ]
+ ];
+ }
+
+ // get mbs
+ $temp = DB::select("
+ SELECT mbs
+ FROM mbs
+ ORDER BY era_id DESC
+ LIMIT 1
+ ");
+ $return['mbs'] = (int) ($temp[0]->mbs ?? 0);
+
+ return $this->successResponse($return);
+ }
+
+ public function getActiveReinstatements()
{
- $limit = $request->limit ?? 50;
- $sort_key = $request->sort_key ?? '';
- $sort_direction = $request->sort_direction ?? '';
- if (!$sort_key) $sort_key = 'created_at';
- if (!$sort_direction) $sort_direction = 'desc';
- $users = User::where('role', 'member')
- ->with(['profile'])
- ->leftJoin('node_info', 'users.public_address_node', '=', 'node_info.node_address')
- ->select([
- 'users.*',
- 'node_info.delegation_rate',
- 'node_info.delegators_count',
- 'node_info.self_staked_amount',
- 'node_info.total_staked_amount',
- ])
+ $items = Profile::with('user')
+ ->has('user')
+ ->where('extra_status', 'Suspended')
+ ->where('reactivation_requested', true)
+ ->whereNotNull('reactivation_requested_at')
+ ->orderBy('reactivation_requested_at', 'desc')
->get();
- foreach ($users as $user) {
- $status = 'Not Verified';
- if ($user->profile && $user->profile->status == 'approved') {
- $status = 'Verified';
- if ($user->profile->extra_status)
- $status = $user->profile->extra_status;
+ return $this->successResponse($items);
+ }
+
+ public function getHistoryReinstatements()
+ {
+ $items = ReinstatementHistory::with('user')
+ ->has('user')
+ ->whereNotNull('decision_at')
+ ->orderBy('decision_at', 'desc')
+ ->get();
+ return $this->successResponse($items);
+ }
+
+ public function revokeUser($id)
+ {
+ $user = User::with('profile')
+ ->has('profile')
+ ->where('id', $id)
+ ->where('role', 'member')
+ ->first();
+
+ if ($user && $user->profile->status == 'approved' && $user->profile->extra_status != 'Suspended') {
+ $user->profile->extra_status = 'Suspended';
+ $user->profile->revoke_reason = 'Admin action';
+ $user->profile->revoke_at = Carbon::now('UTC');
+ $user->profile->reactivation_reason = null;
+ $user->profile->reactivation_requested = null;
+ $user->profile->reactivation_requested_at = null;
+ $user->profile->save();
+
+ return $this->metaSuccess();
+ }
+
+ return $this->errorResponse('Fail Revoke User', Response::HTTP_BAD_REQUEST);
+ }
+
+ public function reactivateUser($id)
+ {
+ $user = User::with('profile')
+ ->has('profile')
+ ->where('id', $id)
+ ->where('role', 'member')
+ ->first();
+
+ if (
+ $user &&
+ $user->profile->status == 'approved' &&
+ $user->profile->extra_status == 'Suspended' &&
+ $user->profile->revoke_reason &&
+ $user->profile->revoke_at
+ ) {
+ $user->profile->extra_status = null;
+ $user->profile->revoke_reason = null;
+ $user->profile->revoke_at = null;
+ $user->profile->reactivation_reason = null;
+ $user->profile->reactivation_requested = null;
+ $user->profile->reactivation_requested_at = null;
+ $user->profile->save();
+
+ return $this->metaSuccess();
+ }
+
+ return $this->errorResponse('Fail Reactivate User', Response::HTTP_BAD_REQUEST);
+ }
+
+ public function approveReinstatement(Request $request)
+ {
+ $profileId = (int) ($request->profileId ?? 0);
+ $profile = Profile::find($profileId);
+
+ if (!$profile) {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ if ($profile->extra_status != 'Suspended' || !$profile->reactivation_requested) {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ $userId = (int) $profile->user_id;
+ $revoke_at = $profile->revoke_at;
+ $revoke_reason = $profile->revoke_reason;
+ $reactivation_reason = $profile->reactivation_reason;
+ $reactivation_requested_at = $profile->reactivation_requested_at;
+
+ if (!$revoke_at || !$reactivation_requested_at) {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ $historyRecord = ReinstatementHistory::where('revoke_at', $revoke_at)
+ ->where('reactivation_requested_at', $reactivation_requested_at)
+ ->where('user_id', $userId)
+ ->first();
+ if (!$historyRecord) {
+ $historyRecord = new ReinstatementHistory;
+ $historyRecord->user_id = $userId;
+ $historyRecord->revoke_at = $revoke_at;
+ $historyRecord->revoke_reason = $revoke_reason;
+ $historyRecord->reactivation_reason = $reactivation_reason;
+ $historyRecord->reactivation_requested_at = $reactivation_requested_at;
+ $historyRecord->decision = true;
+ $historyRecord->decision_at = Carbon::now('UTC');
+ $historyRecord->save();
+ }
+
+ $profile->extra_status = null;
+ $profile->revoke_at = null;
+ $profile->revoke_reason = null;
+ $profile->reactivation_reason = null;
+ $profile->reactivation_requested = null;
+ $profile->reactivation_requested_at = null;
+ $profile->save();
+
+ $this->metaSuccess();
+ }
+
+ public function rejectReinstatement(Request $request)
+ {
+ $profileId = (int) ($request->profileId ?? 0);
+ $profile = Profile::find($profileId);
+
+ if (!$profile) {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ if ($profile->extra_status != 'Suspended' || !$profile->reactivation_requested) {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ $userId = (int) $profile->user_id;
+ $revoke_at = $profile->revoke_at;
+ $revoke_reason = $profile->revoke_reason;
+ $reactivation_reason = $profile->reactivation_reason;
+ $reactivation_requested_at = $profile->reactivation_requested_at;
+
+ if (!$revoke_at || !$reactivation_requested_at) {
+ return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
+
+ $historyRecord = ReinstatementHistory::where('revoke_at', $revoke_at)
+ ->where('reactivation_requested_at', $reactivation_requested_at)
+ ->where('user_id', $userId)
+ ->first();
+ if (!$historyRecord) {
+ $historyRecord = new ReinstatementHistory;
+ $historyRecord->user_id = $userId;
+ $historyRecord->revoke_at = $revoke_at;
+ $historyRecord->revoke_reason = $revoke_reason;
+ $historyRecord->reactivation_reason = $reactivation_reason;
+ $historyRecord->reactivation_requested_at = $reactivation_requested_at;
+ $historyRecord->decision = false;
+ $historyRecord->decision_at = Carbon::now('UTC');
+ $historyRecord->save();
+ }
+
+ $profile->reactivation_reason = null;
+ $profile->reactivation_requested = null;
+ $profile->reactivation_requested_at = null;
+ $profile->save();
+
+ $this->metaSuccess();
+ }
+
+ public function getUsers(Request $request)
+ {
+ $current_era_id = Helper::getCurrentERAId();
+
+ $query = "
+ SELECT
+ a.id, a.first_name, a.last_name, a.email,
+ a.pseudonym, a.telegram, a.email_verified_at,
+ a.entity_name, a.last_login_at, a.created_at,
+ a.signature_request_id, a.node_status, a.node_verified_at,
+ a.member_status, a.kyc_verified_at,
+ b.dob, b.country_citizenship, b.country_residence,
+ b.status AS profile_status, b.extra_status, b.revoke_reason,
+ b.type, b.casper_association_kyc_hash,
+ b.blockchain_name, b.blockchain_desc
+ FROM users AS a
+ LEFT JOIN profile AS b
+ ON a.id = b.user_id
+ WHERE a.role = 'member'
+ ";
+
+ $sort_key = $request->get('sort_key');
+ $sort_direction = $request->get('sort_direction');
+
+ if ($sort_key && $sort_direction) {
+ switch ($sort_key) {
+ case 'id':
+ $sort_key = 'a.id';
+ break;
+ case 'membership_status':
+ $sort_key = 'b.status';
+ break;
+ case 'node_status':
+ $sort_key = 'a.node_status';
+ break;
+ case 'email':
+ $sort_key = 'a.email';
+ break;
+ case 'entity_name':
+ $sort_key = 'a.entity_name';
+ break;
+ case 'full_name':
+ $sort_key = 'a.first_name';
+ break;
+ case 'created_at':
+ $sort_key = 'a.created_at';
+ break;
+ default:
+ $sort_key = 'a.id';
+ break;
+ }
+ $query .= " ORDER BY " . $sort_key . " " . $sort_direction;
+ } else {
+ $query .= " ORDER BY a.id desc";
+ }
+
+ $users = DB::select($query);
+
+ if ($users) {
+ foreach ($users as &$user) {
+ $status = 'Not Verified';
+
+ if ($user->profile_status == 'approved') {
+ $status = 'Verified';
+ if ($user->extra_status) {
+ $status = $user->extra_status;
+ if ($user->extra_status == 'Suspended') {
+ $status = 'Revoked';
+ }
+ }
+ }
+
+ $user->membership_status = $status;
+ $userId = (int) $user->id;
+
+ $temp = DB::select("
+ SELECT sum(a.bid_self_staked_amount) as self_staked_amount
+ FROM all_node_data2 as a
+ JOIN user_addresses as b ON b.public_address_node = a.public_key
+ WHERE b.user_id = $userId and a.era_id = $current_era_id
+ ");
+
+ $self_staked_amount = (float) ($temp[0]->self_staked_amount ?? 0);
+ $user->self_staked_amount = round($self_staked_amount, 2);
}
- $user->membership_status = $status;
}
- if ($sort_direction == 'desc') $users = $users->sortByDesc($sort_key)->values();
- else $users = $users->sortBy($sort_key)->values();
- $users = Helper::paginate($users, $limit, $request->page);
- $users = $users->toArray();
- $users['data'] = (collect($users['data'])->values());
+
return $this->successResponse($users);
}
public function getUserDetail($id)
{
$user = User::where('id', $id)->first();
- if (!$user || $user->role == 'admin')
+ if (!$user || $user->role == 'admin') {
return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ }
$user = $user->load(['pagePermissions', 'profile', 'shuftipro', 'shuftiproTemp']);
$status = 'Not Verified';
if ($user->profile && $user->profile->status == 'approved') {
$status = 'Verified';
- if ($user->profile->extra_status)
+ if ($user->profile->extra_status) {
$status = $user->profile->extra_status;
+ if ($user->profile->extra_status == 'Suspended') {
+ $status = 'Revoked';
+ if ($user->profile->revoke_reason) {
+ $status = 'Revoked for ' . $user->profile->revoke_reason;
+ }
+ }
+ }
}
+
$user->membership_status = $status;
- $user->metric = Helper::getNodeInfo($user);
+
+ $addresses = $user->addresses ?? [];
+
+ $settings = Helper::getSettings();
+ $current_era_id = (int) ($settings['current_era_id'] ?? 0);
+
+ foreach ($addresses as &$addressItem) {
+ $temp = AllNodeData2::select([
+ 'uptime',
+ 'bid_delegators_count',
+ 'bid_delegation_rate',
+ 'bid_self_staked_amount',
+ 'bid_total_staked_amount'
+ ])
+ ->where('public_key', $addressItem->public_address_node)
+ ->where('era_id', $current_era_id)
+ ->orderBy('id', 'desc')
+ ->first()
+ ->toArray();
+ if ($temp) {
+ foreach ($temp as $key => $value) {
+ if ($key == 'uptime') $value = round((float) $value, 2);
+ $addressItem->$key = $value;
+ }
+ $addressItem->update_responsiveness = 100;
+ $p = $addressItem->public_address_node;
+
+ $historical_performance = Helper::calculateUptime($addressItem, $p, $settings);
+ $addressItem->uptime = $historical_performance;
+
+ $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings);
+ $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0);
+ $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id);
+
+ $min_era_id = Helper::calculateVariables('min_era', $p, $settings);
+ $eras_active = $current_era_id - $min_era_id;
+
+ $addressItem->eras_since_bad_mark = $eras_since_bad_mark;
+ $addressItem->total_bad_marks = $total_bad_marks;
+ $addressItem->eras_active = $eras_active;
+ }
+ }
+
+ $user->addresses = $addresses;
+
return $this->successResponse($user);
}
public function infoDashboard(Request $request)
{
+ $current_era_id = Helper::getCurrentERAId();
+
+ $return = [
+ 'total_users' => 0,
+ 'total_stake' => 0,
+ 'total_delegators' => 0,
+ 'avg_uptime' => 0,
+ 'avg_responsiveness' => 0,
+ 'new_users_ready' => 0,
+ 'id_to_review' => 0,
+ 'perks_active' => 0,
+ 'perks_views' => 0,
+ 'new_comments' => 0,
+ 'new_threads' => 0
+ ];
+
+ $temp = DB::select("
+ SELECT count(pseudonym) as totalCount
+ FROM users
+ WHERE role = 'member'
+ ");
+ $total_users = (int) ($temp[0]->totalCount ?? 0);
+
+ $temp = DB::select("
+ SELECT
+ SUM(a.bid_total_staked_amount) as totalSum
+ FROM all_node_data2 AS a
+ LEFT JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ WHERE a.era_id = $current_era_id
+ AND b.user_id IS NOT NULL
+ ");
+ $total_stake = (int) ($temp[0]->totalSum ?? 0);
+
+ $temp = DB::select("
+ SELECT
+ SUM(a.bid_delegators_count) as totalSum
+ FROM all_node_data2 AS a
+ LEFT JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ WHERE a.era_id = $current_era_id
+ AND b.user_id IS NOT NULL
+ ");
+ $total_delegators = (int) ($temp[0]->totalSum ?? 0);
+
+ $temp = DB::select("
+ SELECT
+ SUM(a.uptime) AS numerator,
+ COUNT(a.uptime) AS denominator
+ FROM all_node_data2 AS a
+ LEFT JOIN user_addresses AS b
+ ON a.public_key = b.public_address_node
+ WHERE era_id = $current_era_id
+ AND b.user_id IS NOT NULL
+ ");
+ $denominator = (int) ($temp[0]->denominator ?? 1);
+ if (!$denominator) $denominator = 1;
+ $avg_uptime = (float) (($temp[0]->numerator ?? 0) / $denominator);
+ $avg_uptime = round($avg_uptime, 2);
+
+ $avg_responsiveness = 100;
+
+ // get new users ready for admin review
+ $new_users_ready = User::where('banned', 0)
+ ->where('role', 'member')
+ ->where(function ($q) {
+ $q->where('users.node_verified_at', null)
+ ->orWhere('users.letter_verified_at', null)
+ ->orWhere('users.signature_request_id', null);
+ })->count();
+
+ // get new users ready for kyc review
+ $id_to_review = User::where('users.role', 'member')
+ ->where('banned', 0)
+ ->join('profile', function ($query) {
+ $query->on('profile.user_id', '=', 'users.id')
+ ->where('profile.status', 'pending');
+ })
+ ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id')
+ ->count();
+
$timeframe_perk = $request->timeframe_perk ?? 'last_7days';
$timeframe_comments = $request->timeframe_comments ?? 'last_7days';
$timeframe_discussions = $request->timeframe_discussions ?? 'last_7days';
+
// last_24hs, last_7days, last_30days, last_year
- if ($timeframe_perk == 'last_24hs')
- $timeframe_perk = Carbon::now('UTC')->subHours(24);
- else if ($timeframe_perk == 'last_30days')
- $timeframe_perk = Carbon::now('UTC')->subDays(30);
- else if ($timeframe_perk == 'last_year')
- $timeframe_perk = Carbon::now('UTC')->subYear();
- else
- $timeframe_perk = Carbon::now('UTC')->subDays(7);
-
- if ($timeframe_comments == 'last_24hs')
- $timeframe_comments = Carbon::now('UTC')->subHours(24);
- else if ($timeframe_comments == 'last_30days') {
- $timeframe_comments = Carbon::now('UTC')->subDays(30);
+ if ($timeframe_perk == 'last_24hs') {
+ $timeframe_perk = Carbon::now('UTC')->subHours(24);
+ } else if ($timeframe_perk == 'last_30days') {
+ $timeframe_perk = Carbon::now('UTC')->subDays(30);
+ } else if ($timeframe_perk == 'last_year') {
+ $timeframe_perk = Carbon::now('UTC')->subYear();
+ } else {
+ $timeframe_perk = Carbon::now('UTC')->subDays(7);
+ }
+
+ if ($timeframe_comments == 'last_24hs') {
+ $timeframe_comments = Carbon::now('UTC')->subHours(24);
+ } else if ($timeframe_comments == 'last_30days') {
+ $timeframe_comments = Carbon::now('UTC')->subDays(30);
} else if ($timeframe_comments == 'last_year') {
- $timeframe_comments = Carbon::now('UTC')->subYear();
+ $timeframe_comments = Carbon::now('UTC')->subYear();
} else {
- $timeframe_comments = Carbon::now('UTC')->subDays(7);
+ $timeframe_comments = Carbon::now('UTC')->subDays(7);
}
if ($timeframe_discussions == 'last_24hs') {
- $timeframe_discussions = Carbon::now('UTC')->subHours(24);
+ $timeframe_discussions = Carbon::now('UTC')->subHours(24);
} else if ($timeframe_discussions == 'last_30days') {
- $timeframe_discussions = Carbon::now('UTC')->subDays(30);
+ $timeframe_discussions = Carbon::now('UTC')->subDays(30);
} else if ($timeframe_discussions == 'last_year') {
- $timeframe_discussions = Carbon::now('UTC')->subYear();
+ $timeframe_discussions = Carbon::now('UTC')->subYear();
} else {
- $timeframe_discussions = Carbon::now('UTC')->subDays(7);
+ $timeframe_discussions = Carbon::now('UTC')->subDays(7);
}
- $totalUser = User::where('role', 'member')->count();
- $toTalStake = NodeInfo::sum('total_staked_amount');
- $totalDelagateer = NodeInfo::sum('delegators_count');
- $totalNewUserReady = User::where('banned', 0)
- ->where('role', 'member')
- ->where(function ($q) {
- $q->where('users.node_verified_at', null)
- ->orWhere('users.letter_verified_at', null)
- ->orWhere('users.signature_request_id', null);
- })->count();
+ // get active perks
+ $perks_active = Perk::where('status', 'active')
+ ->where('created_at', '>=', $timeframe_perk)
+ ->count();
+
+ // get total perk views
+ $perks_views = Perk::where('status', 'active')
+ ->where('created_at', '>=', $timeframe_perk)
+ ->sum('total_views');
+
+ // get comments
+ $new_comments = DiscussionComment::where('created_at', '>=', $timeframe_comments)->count();
+
+ // get discussions
+ $new_threads = Discussion::where('created_at', '>=', $timeframe_discussions)->count();
+
+ $return['total_users'] = $total_users;
+ $return['total_stake'] = $total_stake;
+ $return['total_delegators'] = $total_delegators;
+ $return['avg_uptime'] = $avg_uptime;
+ $return['avg_responsiveness'] = $avg_responsiveness;
+ $return['new_users_ready'] = $new_users_ready;
+ $return['id_to_review'] = $id_to_review;
+ $return['perks_active'] = $perks_active;
+ $return['perks_views'] = $perks_views;
+ $return['new_comments'] = $new_comments;
+ $return['new_threads'] = $new_threads;
+
+ return $this->successResponse($return);
+ }
+
+ public function bypassApproveKYC($user_id)
+ {
+ $user_id = (int) $user_id;
+ $user = User::find($user_id);
+ $now = Carbon::now('UTC');
+ $admin_user = auth()->user();
+
+ if ($user && $user->role == 'member') {
+ $user->kyc_verified_at = $now;
+ $user->approve_at = $now;
+ $user->kyc_bypass_approval = 1;
+ $user->save();
+
+ $profile = Profile::where('user_id', $user_id)->first();
- $totalUserVerification = User::where('users.role', 'member')
- ->where('banned', 0)
- ->join('profile', function ($query) {
- $query->on('profile.user_id', '=', 'users.id')
- ->where('profile.status', 'pending');
- })
- ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id')
- ->count();
- $totalFailNode = User::where('banned', 0)->whereNotNull('public_address_node')->where('is_fail_node', 1)->count();
-
- $totalPerksActive = Perk::where('status', 'active')->where('created_at', '>=', $timeframe_perk)->count();
- $totalPerksViews = Perk::where('status', 'active')->where('created_at', '>=', $timeframe_perk)->sum('total_views');
-
- $totalNewComments = DiscussionComment::where('created_at', '>=', $timeframe_comments)->count();
- $totalNewDiscussions = Discussion::where('created_at', '>=', $timeframe_discussions)->count();
-
- $uptime_nodes = NodeInfo::whereNotNull('uptime')->pluck('uptime');
- $uptime_metrics = Metric::whereNotNull('uptime')->pluck('uptime');
-
- $blocks_hight_nodes = NodeInfo::whereNotNull('block_height_average')->pluck('block_height_average');
- $blocks_hight_metrics = Metric::whereNotNull('block_height_average')->pluck('block_height_average');
- $total_blocks_hight_metrics = 0;
- $base_block = 10;
- foreach ($blocks_hight_metrics as $value) {
- $avg = ($base_block - $value) * 10;
- if ($avg > 0) {
- $total_blocks_hight_metrics += $avg;
+ if (!$profile) {
+ $profile = new Profile;
+ $profile->user_id = $user_id;
+ $profile->first_name = $user->first_name;
+ $profile->last_name = $user->last_name;
+ $profile->type = $user->type;
}
- }
- $responsiveness_nodes = NodeInfo::whereNotNull('update_responsiveness')->pluck('update_responsiveness');
- $responsiveness_metrics = Metric::whereNotNull('update_responsiveness')->pluck('update_responsiveness');
-
- $countUptime = count($uptime_nodes) + count($uptime_metrics) > 0 ? count($uptime_nodes) + count($uptime_metrics) : 1;
- $count_responsiveness_nodes = count($responsiveness_nodes) + count($responsiveness_metrics);
- $count_responsiveness_nodes = $count_responsiveness_nodes > 0 ? $count_responsiveness_nodes : 1;
- $count_blocks_hight = (count($blocks_hight_nodes) + count($blocks_hight_metrics)) > 0 ? (count($blocks_hight_nodes) + count($blocks_hight_metrics)) : 1;
- $response['totalUser'] = $totalUser;
- $response['totalStake'] = $toTalStake;
- $response['totalDelegators'] = $totalDelagateer;
- $response['totalNewUserReady'] = $totalNewUserReady;
- $response['totalUserVerification'] = $totalUserVerification;
- $response['totalFailNode'] = $totalFailNode;
- $response['totalPerksActive'] = $totalPerksActive;
- $response['totalPerksViews'] = $totalPerksViews;
- $response['totalNewComments'] = $totalNewComments;
- $response['totalNewDiscussions'] = $totalNewDiscussions;
- $response['avgUptime'] = ($uptime_nodes->sum() + $uptime_metrics->sum()) / $countUptime;
- $response['avgBlockHeightAverage'] = ($blocks_hight_nodes->sum() + $total_blocks_hight_metrics) / $count_blocks_hight;
- $response['avgUpdateResponsiveness'] = ($responsiveness_nodes->sum() + $responsiveness_metrics->sum()) / $count_responsiveness_nodes;
- return $this->successResponse($response);
- }
+ $profile->status = 'approved';
+ $profile->save();
+ $shuftipro = Shuftipro::where('user_id', $user_id)->first();
- public function getKYC($id)
- {
- $user = User::with(['shuftipro', 'profile'])->where('id', $id)->first();
- if (!$user || $user->role == 'admin') {
- return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND);
+ if (!$shuftipro) {
+ $shuftipro = new Shuftipro;
+ $shuftipro->user_id = $user_id;
+ $shuftipro->reference_id = 'ByPass#' . time();
+ }
+
+ $shuftipro->is_successful = 1;
+ $shuftipro->status = 'approved';
+ $shuftipro->manual_approved_at = $now;
+ $shuftipro->manual_reviewer = $admin_user->email;
+ $shuftipro->save();
}
- $response = $user->load(['profile', 'shuftipro']);
- return $this->successResponse($response);
+
+ return $this->metaSuccess();
}
// get intake
@@ -227,8 +987,16 @@ public function getIntakes(Request $request)
$limit = $request->limit ?? 50;
$search = $request->search ?? '';
$users = User::select([
- 'id', 'email', 'node_verified_at', 'letter_verified_at', 'signature_request_id', 'created_at',
- 'first_name', 'last_name', 'letter_file', 'letter_rejected_at'
+ 'id',
+ 'email',
+ 'node_verified_at',
+ 'letter_verified_at',
+ 'signature_request_id',
+ 'created_at',
+ 'first_name',
+ 'last_name',
+ 'letter_file',
+ 'letter_rejected_at'
])
->where('banned', 0)
->where('role', 'member')
@@ -238,7 +1006,9 @@ public function getIntakes(Request $request)
->orWhere('users.signature_request_id', null);
})
->where(function ($query) use ($search) {
- if ($search) $query->where('users.email', 'like', '%' . $search . '%');
+ if ($search) {
+ $query->where('users.email', 'like', '%' . $search . '%');
+ }
})
->orderBy('users.id', 'desc')
->paginate($limit);
@@ -253,97 +1023,106 @@ public function submitBallot(Request $request)
$user = auth()->user();
// Validator
$validator = Validator::make($request->all(), [
- 'title' => 'required',
+ 'title' => 'required',
'description' => 'required',
- // 'time' => 'required',
- // 'time_unit' => 'required|in:minutes,hours,days',
- 'files' => 'array',
- 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf',
- 'start_date' => 'required',
- 'start_time' => 'required',
- 'end_date' => 'required',
- 'end_time' => 'required',
+ 'files' => 'array',
+ // 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf',
+ 'files.*' => 'file|max:2048|mimes:pdf,docx,doc,txt,rtf',
+ 'start_date' => 'required',
+ 'start_time' => 'required',
+ 'end_date' => 'required',
+ 'end_time' => 'required',
+ 'timezone' => 'required'
]);
+
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
- $time = $request->time;
- $timeUnit = $request->time_unit;
- $mins = 0;
- if ($timeUnit == 'minutes') {
- $mins = $time;
- } else if ($timeUnit == 'hours') {
- $mins = $time * 60;
- } else if ($timeUnit == 'days') {
- $mins = $time * 60 * 24;
- }
- $start = Carbon::createFromFormat("Y-m-d H:i:s", Carbon::now('UTC'), "UTC");
- $now = Carbon::now('UTC');
- $timeEnd = $start->addMinutes($mins);
+ $timezone = $request->timezone;
+ $startTime = $request->start_date . ' ' . $request->start_time;
+ $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone);
+ $startTimeCarbon->setTimezone('UTC');
+
$endTime = $request->end_date . ' ' . $request->end_time;
- $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, 'EST');
+ $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone);
$endTimeCarbon->setTimezone('UTC');
+ if ($startTimeCarbon->gte($endTimeCarbon)) {
+ return $this->errorResponse('End datetime must greater than start datetime', Response::HTTP_BAD_REQUEST);
+ }
+
$ballot = new Ballot();
- $ballot->user_id = $user->id;
- $ballot->title = $request->title;
+ $ballot->user_id = $user->id;
+ $ballot->title = $request->title;
$ballot->description = $request->description;
- // $ballot->time = $time;
- // $ballot->time_unit = $timeUnit;
- // $ballot->time_end = $timeEnd;
- $ballot->time_end = $endTimeCarbon;
- $ballot->start_date = $request->start_date;
- $ballot->start_time = $request->start_time;
- $ballot->end_date = $request->end_date;
- $ballot->end_time = $request->end_time;
- $ballot->status = 'active';
- $ballot->created_at = $now;
+ $ballot->time_begin = $startTimeCarbon;
+ $ballot->time_end = $endTimeCarbon;
+ $ballot->start_date = $request->start_date;
+ $ballot->start_time = $request->start_time;
+ $ballot->end_date = $request->end_date;
+ $ballot->end_time = $request->end_time;
+ $ballot->status = 'active';
+ $ballot->timezone = $timezone;
$ballot->save();
+
$vote = new Vote();
$vote->ballot_id = $ballot->id;
$vote->save();
+
if ($request->hasFile('files')) {
$files = $request->file('files');
+
foreach ($files as $file) {
- $name = $file->getClientOriginalName();
- $extension = $file->getClientOriginalExtension();
- $filenamehash = md5(Str::random(10) . '_' . (string)time());
+ $name = $file->getClientOriginalName();
+ $extension = $file->getClientOriginalExtension();
+ $filenamehash = md5(Str::random(10) . '_' . (string)time());
$fileNameToStore = $filenamehash . '.' . $extension;
// S3 file upload
$S3 = new S3Client([
- 'version' => 'latest',
- 'region' => getenv('AWS_DEFAULT_REGION'),
+ 'version' => 'latest',
+ 'region' => getenv('AWS_DEFAULT_REGION'),
'credentials' => [
- 'key' => getenv('AWS_ACCESS_KEY_ID'),
- 'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
+ 'key' => getenv('AWS_ACCESS_KEY_ID'),
+ 'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
],
]);
$s3result = $S3->putObject([
- 'Bucket' => getenv('AWS_BUCKET'),
- 'Key' => 'perks/' . $fileNameToStore,
+ 'Bucket' => getenv('AWS_BUCKET'),
+ 'Key' => 'perks/' . $fileNameToStore,
'SourceFile' => $file
]);
- // $ObjectURL = 'https://'.getenv('AWS_BUCKET') . '.s3.amazonaws.com/perks/'.$fileNameToStore;
- $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL') . '/not-found';
- $ballotFile = new BallotFile();
+ $ObjectURL = (
+ $s3result['ObjectURL'] ??
+ getenv('SITE_URL') . '/not-found')
+ ;
+
+ $ballotFile = new BallotFile();
$ballotFile->ballot_id = $ballot->id;
- $ballotFile->name = $name;
- $ballotFile->path = $ObjectURL;
- $ballotFile->url = $ObjectURL;
+ $ballotFile->name = $name;
+ $ballotFile->path = $ObjectURL;
+ $ballotFile->url = $ObjectURL;
$ballotFile->save();
}
}
DB::commit();
+
+ BallotNotification::dispatch($ballot)->onQueue('default_long');
+
return $this->metaSuccess();
} catch (\Exception $ex) {
DB::rollBack();
- return $this->errorResponse('Submit ballot fail', Response::HTTP_BAD_REQUEST, $ex->getMessage());
+
+ return $this->errorResponse(
+ 'Submit ballot fail',
+ Response::HTTP_BAD_REQUEST,
+ $ex->getMessage()
+ );
}
}
@@ -353,171 +1132,181 @@ public function editBallot($id, Request $request)
DB::beginTransaction();
// Validator
$validator = Validator::make($request->all(), [
- 'title' => 'nullable',
- 'description' => 'nullable',
- // 'time' => 'nullable',
- // 'time_unit' => 'nullable|in:minutes,hours,days',
- 'files' => 'array',
- 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf',
+ 'title' => 'nullable',
+ 'description' => 'nullable',
+ 'files' => 'array',
+ // 'files.*' => 'file|max:10240|mimes:pdf,docx,doc,txt,rtf',
+ 'files.*' => 'file|max:2048|mimes:pdf,docx,doc,txt,rtf',
'file_ids_remove' => 'array',
- 'start_date' => 'required',
- 'start_time' => 'required',
- 'end_date' => 'required',
- 'end_time' => 'required',
+ 'start_date' => 'required',
+ 'start_time' => 'required',
+ 'end_date' => 'required',
+ 'end_time' => 'required',
+ 'timezone' => 'required'
]);
+
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
- $time = $request->time;
- $timeUnit = $request->time_unit;
+
$ballot = Ballot::where('id', $id)->first();
if (!$ballot) {
return $this->errorResponse('Not found ballot', Response::HTTP_BAD_REQUEST);
}
- if ($request->title) $ballot->title = $request->title;
- if ($request->description) $ballot->description = $request->description;
- $now = Carbon::now('UTC');
- $ballot->created_at = $now;
- $ballot->time_end = $request->end_date . ' ' . $request->end_time;
- $ballot->start_date = $request->start_date;
- $ballot->start_time = $request->start_time;
- $ballot->end_date = $request->end_date;
- $ballot->end_time = $request->end_time;
+ $timezone = $request->timezone;
+
+ if ($request->title) {
+ $ballot->title = $request->title;
+ }
+
+ if ($request->description) {
+ $ballot->description = $request->description;
+ }
+
+ $startTime = $request->start_date . ' ' . $request->start_time;
+ $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone);
+ $startTimeCarbon->setTimezone('UTC');
+
+ $endTime = $request->end_date . ' ' . $request->end_time;
+ $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone);
+ $endTimeCarbon->setTimezone('UTC');
- /*
- if($time && $timeUnit && ($time != $ballot->time || $timeUnit != $ballot->time_unit)) {
- $mins = 0;
- if ($timeUnit == 'minutes') {
- $mins = $time;
- } else if ($timeUnit == 'hours') {
- $mins = $time * 60;
- } else if ($timeUnit == 'days') {
- $mins = $time * 60 * 24;
- }
- $start = Carbon::createFromFormat("Y-m-d H:i:s", Carbon::now('UTC'), "UTC");
- $now = Carbon::now('UTC');
- $timeEnd = $start->addMinutes($mins);
- $ballot->time = $time;
- $ballot->time_unit = $timeUnit;
- $ballot->created_at = $now;
- $ballot->time_end = $timeEnd;
+ if ($startTimeCarbon->gte($endTimeCarbon)) {
+ return $this->errorResponse('End datetime must greater than start datetime', Response::HTTP_BAD_REQUEST);
}
- */
+ $ballot->time_begin = $startTimeCarbon;
+ $ballot->time_end = $endTimeCarbon;
+ $ballot->start_date = $request->start_date;
+ $ballot->start_time = $request->start_time;
+ $ballot->end_date = $request->end_date;
+ $ballot->end_time = $request->end_time;
+ $ballot->timezone = $request->timezone;
$ballot->save();
+
if ($request->hasFile('files')) {
$files = $request->file('files');
+
foreach ($files as $file) {
- $name = $file->getClientOriginalName();
- $extension = $file->getClientOriginalExtension();
- $filenamehash = md5(Str::random(10) . '_' . (string)time());
+ $name = $file->getClientOriginalName();
+ $extension = $file->getClientOriginalExtension();
+ $filenamehash = md5(Str::random(10) . '_' . (string)time());
$fileNameToStore = $filenamehash . '.' . $extension;
// S3 file upload
$S3 = new S3Client([
- 'version' => 'latest',
- 'region' => getenv('AWS_DEFAULT_REGION'),
+ 'version' => 'latest',
+ 'region' => getenv('AWS_DEFAULT_REGION'),
'credentials' => [
- 'key' => getenv('AWS_ACCESS_KEY_ID'),
- 'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
+ 'key' => getenv('AWS_ACCESS_KEY_ID'),
+ 'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
],
]);
$s3result = $S3->putObject([
- 'Bucket' => getenv('AWS_BUCKET'),
- 'Key' => 'perks/'.$fileNameToStore,
+ 'Bucket' => getenv('AWS_BUCKET'),
+ 'Key' => 'perks/'.$fileNameToStore,
'SourceFile' => $file
]);
- // $ObjectURL = 'https://'.getenv('AWS_BUCKET').'.s3.amazonaws.com/perks/'.$fileNameToStore;
- $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL').'/not-found';
- $ballotFile = new BallotFile();
+ $ObjectURL = (
+ $s3result['ObjectURL'] ??
+ getenv('SITE_URL').'/not-found'
+ );
+
+ $ballotFile = new BallotFile();
$ballotFile->ballot_id = $ballot->id;
- $ballotFile->name = $name;
- $ballotFile->path = $ObjectURL;
- $ballotFile->url = $ObjectURL;
+ $ballotFile->name = $name;
+ $ballotFile->path = $ObjectURL;
+ $ballotFile->url = $ObjectURL;
$ballotFile->save();
}
}
+
if ($request->file_ids_remove) {
foreach($request->file_ids_remove as $file_id) {
- BallotFile::where('id', $file_id)->where('ballot_id', $id)->delete();
+ BallotFile::where('id', $file_id)
+ ->where('ballot_id', $id)
+ ->delete();
}
}
DB::commit();
+
return $this->metaSuccess();
} catch (\Exception $ex) {
DB::rollBack();
- return $this->errorResponse('Submit ballot fail', Response::HTTP_BAD_REQUEST, $ex->getMessage());
+
+ return $this->errorResponse(
+ 'Submit ballot fail',
+ Response::HTTP_BAD_REQUEST,
+ $ex->getMessage()
+ );
}
}
public function getBallots(Request $request)
{
- $limit = $request->limit ?? 50;
- $status = $request->status;
- $sort_key = $request->sort_key ?? '';
- $sort_direction = $request->sort_direction ?? '';
- if (!$sort_key) $sort_key = 'ballot.id';
- if (!$sort_direction) $sort_direction = 'desc';
-
- $now = Carbon::now('EST');
- $startDate = $now->format('Y-m-d');
- $startTime = $now->format('H:i:s');
+ $limit = $request->limit ?? 50;
+ $status = $request->status;
+ $sort_key = $request->sort_key ?? 'ballot.id';
+ $sort_direction = $request->sort_direction ?? 'desc';
+ $now = Carbon::now('UTC');
- if ($status == 'active') {
+ if ($status == 'active') {
$ballots = Ballot::with(['user', 'vote'])
- ->where('ballot.status', 'active')
- ->where(function ($query) use ($startDate, $startTime) {
- $query->where('start_date', '<', $startDate)
- ->orWhere(function ($query) use ($startDate, $startTime) {
- $query->where('start_date', $startDate)
- ->where('start_time', '<=', $startTime);
- });
- })
- ->orderBy($sort_key, $sort_direction)
- ->paginate($limit);
+ ->where('ballot.status', 'active')
+ ->where('ballot.time_begin', '<=', $now)
+ ->orderBy($sort_key, $sort_direction)
+ ->paginate($limit);
} else if ($status && $status == 'scheduled') {
$ballots = Ballot::with(['user', 'vote'])
- ->where('ballot.status', 'active')
- ->where(function ($query) use ($startDate, $startTime) {
- $query->where('start_date', '>', $startDate)
- ->orWhere(function ($query) use ($startDate, $startTime) {
- $query->where('start_date', $startDate)
- ->where('start_time', '>', $startTime);
- });
- })
- ->orderBy($sort_key, $sort_direction)
- ->paginate($limit);
+ ->where('ballot.status', 'active')
+ ->where('ballot.time_begin', '>', $now)
+ ->orderBy($sort_key, $sort_direction)
+ ->paginate($limit);
} else if ($status && $status != 'active' && $status != 'scheduled') {
$ballots = Ballot::with(['user', 'vote'])
- ->where('ballot.status', '!=', 'active')
- ->orderBy($sort_key, $sort_direction)
- ->paginate($limit);
+ ->where('ballot.status', '!=', 'active')
+ ->orderBy($sort_key, $sort_direction)
+ ->paginate($limit);
} else {
- $ballots = Ballot::with(['user', 'vote'])->orderBy($sort_key, $sort_direction)->paginate($limit);
+ $ballots = Ballot::with(['user', 'vote'])
+ ->orderBy($sort_key, $sort_direction)
+ ->paginate($limit);
}
return $this->successResponse($ballots);
}
public function getDetailBallot($id)
{
- $ballot = Ballot::with(['user', 'vote', 'files'])->where('id', $id)->first();
+ $ballot = Ballot::with(['user', 'vote', 'files'])
+ ->where('id', $id)
+ ->first();
+
if (!$ballot) {
- return $this->errorResponse('Not found ballot', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Not found ballot',
+ Response::HTTP_BAD_REQUEST
+ );
}
+
return $this->successResponse($ballot);
}
public function cancelBallot($id)
{
$ballot = Ballot::where('id', $id)->first();
+
if (!$ballot || $ballot->status != 'active') {
- return $this->errorResponse('Cannot cancle ballot', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Cannot cancel ballot',
+ Response::HTTP_BAD_REQUEST
+ );
}
- $ballot->time_end = now();
- $ballot->status = 'cancelled';
+
+ $ballot->time_end = Carbon::now('UTC');
+ $ballot->status = 'cancelled';
$ballot->save();
return $this->metaSuccess();
}
@@ -525,7 +1314,10 @@ public function cancelBallot($id)
public function getBallotVotes($id, Request $request)
{
$limit = $request->limit ?? 50;
- $data = VoteResult::where('ballot_id', '=', $id)->with(['user', 'user.profile'])->orderBy('created_at', 'ASC')->paginate($limit);
+ $data = VoteResult::where('ballot_id', '=', $id)
+ ->with(['user', 'user.profile'])
+ ->orderBy('created_at', 'ASC')
+ ->paginate($limit);
return $this->successResponse($data);
}
@@ -533,45 +1325,76 @@ public function getBallotVotes($id, Request $request)
public function getViewFileBallot(Request $request, $fileId)
{
$limit = $request->limit ?? 50;
- $data = BallotFileView::where('ballot_file_id', '=', $fileId)->with(['user', 'user.profile'])->orderBy('created_at', 'ASC')->paginate($limit);
+ $data = BallotFileView::where('ballot_file_id', '=', $fileId)
+ ->with(['user', 'user.profile'])
+ ->orderBy('created_at', 'ASC')
+ ->paginate($limit);
+
return $this->successResponse($data);
}
// Get Global Settings
public function getGlobalSettings()
{
- $items = Setting::get();
- $settings = [];
- if ($items) {
- foreach ($items as $item) {
- $settings[$item->name] = $item->value;
- }
- }
+ $settings = Helper::getSettings();
+
+ $ruleKycNotVerify = LockRules::where('type', 'kyc_not_verify')
+ ->orderBy('id', 'ASC')
+ ->select(['id', 'screen', 'is_lock'])
+ ->get();
+ $ruleStatusIsPoor = LockRules::where('type', 'status_is_poor')
+ ->orderBy('id', 'ASC')
+ ->select(['id', 'screen', 'is_lock'])
+ ->get();
+
+ $membershipAgreementFile = MembershipAgreementFile::first();
+
+ $contactRecipients = ContactRecipient::orderBy('created_at', 'desc')->get();
- return $this->successResponse($settings);
+ $data = [
+ 'globalSettings' => $settings,
+ 'lockRules' => [
+ 'kyc_not_verify' => $ruleKycNotVerify,
+ 'status_is_poor' => $ruleStatusIsPoor
+ ],
+ 'membershipAgreementFile' => $membershipAgreementFile,
+ 'contactRecipients' => $contactRecipients
+ ];
+
+ return $this->successResponse($data);
}
// Update Global Settings
public function updateGlobalSettings(Request $request)
{
- $validator = Validator::make($request->all(), [
- 'quorum_rate_ballot' => 'required',
- ]);
- if ($validator->fails()) {
- return $this->validateResponse($validator->errors());
- }
$items = [
- 'quorum_rate_ballot' => $request->quorum_rate_ballot,
+ 'quorum_rate_ballot' => ($request->quorum_rate_ballot ?? null),
+ 'uptime_warning' => ($request->uptime_warning ?? null),
+ 'uptime_probation' => ($request->uptime_probation ?? null),
+ 'uptime_correction_unit' => ($request->uptime_correction_unit ?? null),
+ 'uptime_correction_value' => ($request->uptime_correction_value ?? null),
+ 'uptime_calc_size' => ($request->uptime_calc_size ?? null),
+ 'voting_eras_to_vote' => ($request->voting_eras_to_vote ?? null),
+ 'voting_eras_since_redmark' => ($request->voting_eras_since_redmark ?? null),
+ 'redmarks_revoke' => ($request->redmarks_revoke ?? null),
+ 'redmarks_revoke_calc_size' => ($request->redmarks_revoke_calc_size ?? null),
+ 'responsiveness_warning' => ($request->responsiveness_warning ?? null),
+ 'responsiveness_probation' => ($request->responsiveness_probation ?? null)
];
+
foreach ($items as $name => $value) {
- $setting = Setting::where('name', $name)->first();
- if ($setting) {
- $setting->value = $value;
- $setting->save();
- } else {
- $setting = new Setting();
- $setting->value = $value;
- $setting->save();
+ if ($value !== null) {
+ $setting = Setting::where('name', $name)->first();
+
+ if ($setting) {
+ $setting->value = $value;
+ $setting->save();
+ } else {
+ $setting = new Setting();
+ $setting->name = $name;
+ $setting->value = $value;
+ $setting->save();
+ }
}
}
@@ -580,57 +1403,72 @@ public function updateGlobalSettings(Request $request)
public function getSubAdmins(Request $request)
{
- $limit = $request->limit ?? 50;
- $admins = User::with(['permissions'])->where(['role' => 'sub-admin'])
+ $limit = $request->limit ?? 50;
+ $admins = User::with(['permissions'])
+ ->where(['role' => 'sub-admin'])
->orderBy('created_at', 'DESC')
->paginate($limit);
return $this->successResponse($admins);
}
-
+
public function inviteSubAdmin(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => 'required|email',
]);
+
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
$isExist = User::where(['email' => $request->email])->count() > 0;
+
if ($isExist) {
- return $this->errorResponse('This email has already been used to invite another admin.', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'This email has already been used to invite another admin.',
+ Response::HTTP_BAD_REQUEST
+ );
}
- $code = Str::random(6);
- // $url = $request->header('origin') ?? $request->root();
- $url = getenv('SITE_URL');
- $inviteUrl = $url . '/register-sub-admin?code=' . $code . '&email=' . urlencode($request->email);
-
- VerifyUser::where('email', $request->email)->where('type', VerifyUser::TYPE_INVITE_ADMIN)->delete();
-
- $verify = new VerifyUser();
- $verify->email = $request->email;
- $verify->type = VerifyUser::TYPE_INVITE_ADMIN;
- $verify->code = $code;
- $verify->created_at = now();
+ $code = Str::random(6);
+ $url = getenv('SITE_URL');
+
+ $inviteUrl = (
+ $url .
+ '/register-sub-admin?code=' .
+ $code .
+ '&email=' .
+ urlencode($request->email)
+ );
+
+ VerifyUser::where('email', $request->email)
+ ->where('type', VerifyUser::TYPE_INVITE_ADMIN)
+ ->delete();
+
+ $verify = new VerifyUser();
+ $verify->email = $request->email;
+ $verify->type = VerifyUser::TYPE_INVITE_ADMIN;
+ $verify->code = $code;
+ $verify->created_at = Carbon::now('UTC');
$verify->save();
+
$admin = User::create([
- 'first_name' => 'faker',
- 'last_name' => 'faker',
- 'email' => $request->email,
- 'password' => '',
- 'type' => '',
+ 'first_name' => 'faker',
+ 'last_name' => 'faker',
+ 'email' => $request->email,
+ 'password' => '',
+ 'type' => '',
'member_status' => 'invited',
- 'role' => 'sub-admin'
+ 'role' => 'sub-admin'
]);
$data = [
- ['name' => 'intake', 'is_permission' => 0, 'user_id' => $admin->id],
- ['name' => 'users', 'is_permission' => 0, 'user_id' => $admin->id],
+ ['name' => 'intake', 'is_permission' => 0, 'user_id' => $admin->id],
+ ['name' => 'users', 'is_permission' => 0, 'user_id' => $admin->id],
['name' => 'ballots', 'is_permission' => 0, 'user_id' => $admin->id],
- ['name' => 'perks', 'is_permission' => 0, 'user_id' => $admin->id],
- ['name' => 'teams', 'is_permission' => 0, 'user_id' => $admin->id],
+ ['name' => 'perks', 'is_permission' => 0, 'user_id' => $admin->id],
+ ['name' => 'teams', 'is_permission' => 0, 'user_id' => $admin->id],
];
Permission::insert($data);
@@ -641,30 +1479,63 @@ public function inviteSubAdmin(Request $request)
public function changeSubAdminPermissions(Request $request, $id)
{
- $validator = Validator::make($request->all(), [
- 'intake' => 'nullable|in:0,1',
- 'users' => 'nullable|in:0,1',
+ $validator = Validator::make($request->all(), [
+ 'intake' => 'nullable|in:0,1',
+ 'users' => 'nullable|in:0,1',
'ballots' => 'nullable|in:0,1',
- 'perks' => 'nullable|in:0,1',
- 'teams' => 'nullable|in:0,1',
+ 'perks' => 'nullable|in:0,1',
+ 'teams' => 'nullable|in:0,1',
]);
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
+
$admin = User::find($id);
- if ($admin == null || $admin->role != 'sub-admin') {
- return $this->errorResponse('There is no admin user with this email', Response::HTTP_BAD_REQUEST);
+
+ if (
+ $admin == null ||
+ $admin->role != 'sub-admin'
+ ) {
+ return $this->errorResponse(
+ 'There is no admin user with this email',
+ Response::HTTP_BAD_REQUEST
+ );
+ }
+
+ if (isset($request->globalsettings)) {
+ $permisstion = Permission::where('user_id', $id)
+ ->where('name', 'globalsettings')
+ ->first();
+
+ if ($permisstion) {
+ $permisstion->is_permission = $request->globalsettings;
+ $permisstion->save();
+ } else {
+ $permisstion = new Permission();
+ $permisstion->is_permission = $request->globalsettings;
+ $permisstion->user_id = $id;
+ $permisstion->name = 'globalsettings';
+ $permisstion->save();
+ }
}
+
if (isset($request->intake)) {
- $permisstion = Permission::where('user_id', $id)->where('name', 'intake')->first();
+ $permisstion = Permission::where('user_id', $id)
+ ->where('name', 'intake')
+ ->first();
+
if ($permisstion) {
$permisstion->is_permission = $request->intake;
$permisstion->save();
}
}
+
if (isset($request->users)) {
- $permisstion = Permission::where('user_id', $id)->where('name', 'users')->first();
+ $permisstion = Permission::where('user_id', $id)
+ ->where('name', 'users')
+ ->first();
+
if ($permisstion) {
$permisstion->is_permission = $request->users;
$permisstion->save();
@@ -672,7 +1543,10 @@ public function changeSubAdminPermissions(Request $request, $id)
}
if (isset($request->ballots)) {
- $permisstion = Permission::where('user_id', $id)->where('name', 'ballots')->first();
+ $permisstion = Permission::where('user_id', $id)
+ ->where('name', 'ballots')
+ ->first();
+
if ($permisstion) {
$permisstion->is_permission = $request->ballots;
$permisstion->save();
@@ -680,7 +1554,10 @@ public function changeSubAdminPermissions(Request $request, $id)
}
if (isset($request->perks)) {
- $permisstion = Permission::where('user_id', $id)->where('name', 'perks')->first();
+ $permisstion = Permission::where('user_id', $id)
+ ->where('name', 'perks')
+ ->first();
+
if ($permisstion) {
$permisstion->is_permission = $request->perks;
$permisstion->save();
@@ -688,15 +1565,18 @@ public function changeSubAdminPermissions(Request $request, $id)
}
if (isset($request->teams)) {
- $permisstion = Permission::where('user_id', $id)->where('name', 'teams')->first();
+ $permisstion = Permission::where('user_id', $id)
+ ->where('name', 'teams')
+ ->first();
+
if ($permisstion) {
$permisstion->is_permission = $request->teams;
$permisstion->save();
} else {
- $permisstion = new Permission();
+ $permisstion = new Permission();
$permisstion->is_permission = $request->teams;
- $permisstion->user_id = $id;
- $permisstion->name = 'teams';
+ $permisstion->user_id = $id;
+ $permisstion->name = 'teams';
$permisstion->save();
}
}
@@ -707,21 +1587,37 @@ public function changeSubAdminPermissions(Request $request, $id)
public function resendLink(Request $request, $id)
{
$admin = User::find($id);
- if ($admin == null || $admin->role != 'sub-admin')
- return $this->errorResponse('No admin to be send invite link', Response::HTTP_BAD_REQUEST);
- $code = Str::random(6);
- // $url = $request->header('origin') ?? $request->root();
- $url = getenv('SITE_URL');
- $inviteUrl = $url . '/register-sub-admin?code=' . $code . '&email=' . urlencode($admin->email);
-
- VerifyUser::where('email', $admin->email)->where('type', VerifyUser::TYPE_INVITE_ADMIN)->delete();
-
- $verify = new VerifyUser();
- $verify->email = $admin->email;
- $verify->type = VerifyUser::TYPE_INVITE_ADMIN;
- $verify->code = $code;
- $verify->created_at = now();
+ if (
+ $admin == null ||
+ $admin->role != 'sub-admin'
+ ) {
+ return $this->errorResponse(
+ 'No admin to be send invite link',
+ Response::HTTP_BAD_REQUEST
+ );
+ }
+
+ $code = Str::random(6);
+ $url = getenv('SITE_URL');
+
+ $inviteUrl = (
+ $url .
+ '/register-sub-admin?code=' .
+ $code .
+ '&email=' .
+ urlencode($admin->email)
+ );
+
+ VerifyUser::where('email', $admin->email)
+ ->where('type', VerifyUser::TYPE_INVITE_ADMIN)
+ ->delete();
+
+ $verify = new VerifyUser();
+ $verify->email = $admin->email;
+ $verify->type = VerifyUser::TYPE_INVITE_ADMIN;
+ $verify->code = $code;
+ $verify->created_at = Carbon::now('UTC');
$verify->save();
Mail::to($admin->email)->send(new InvitationMail($inviteUrl));
@@ -732,21 +1628,36 @@ public function resendLink(Request $request, $id)
public function resetSubAdminResetPassword(Request $request, $id)
{
$admin = User::find($id);
- if ($admin == null || $admin->role != 'sub-admin')
- return $this->errorResponse('No admin to be revoked', Response::HTTP_BAD_REQUEST);
- $code = Str::random(6);
- // $url = $request->header('origin') ?? $request->root();
- $url = getenv('SITE_URL');
- $resetUrl = $url . '/update-password?code=' . $code . '&email=' . urlencode($admin->email);
-
- VerifyUser::where('email', $admin->email)->where('type', VerifyUser::TYPE_RESET_PASSWORD)->delete();
-
- $verify = new VerifyUser();
- $verify->email = $admin->email;
- $verify->type = VerifyUser::TYPE_RESET_PASSWORD;
- $verify->code = $code;
- $verify->created_at = now();
+ if (
+ $admin == null ||
+ $admin->role != 'sub-admin'
+ ) {
+ return $this->errorResponse(
+ 'No admin to be revoked',
+ Response::HTTP_BAD_REQUEST
+ );
+ }
+
+ $code = Str::random(6);
+ $url = getenv('SITE_URL');
+ $resetUrl = (
+ $url .
+ '/update-password?code=' .
+ $code .
+ '&email=' .
+ urlencode($admin->email)
+ );
+
+ VerifyUser::where('email', $admin->email)
+ ->where('type', VerifyUser::TYPE_RESET_PASSWORD)
+ ->delete();
+
+ $verify = new VerifyUser();
+ $verify->email = $admin->email;
+ $verify->type = VerifyUser::TYPE_RESET_PASSWORD;
+ $verify->code = $code;
+ $verify->created_at = Carbon::now('UTC');
$verify->save();
Mail::to($admin->email)->send(new ResetPasswordMail($resetUrl));
@@ -757,11 +1668,19 @@ public function resetSubAdminResetPassword(Request $request, $id)
public function revokeSubAdmin(Request $request, $id)
{
$admin = User::find($id);
- if ($admin == null || $admin->role != 'sub-admin')
- return $this->errorResponse('No admin to be revoked', Response::HTTP_BAD_REQUEST);
+
+ if (
+ $admin == null ||
+ $admin->role != 'sub-admin'
+ ) {
+ return $this->errorResponse(
+ 'No admin to be revoked',
+ Response::HTTP_BAD_REQUEST
+ );
+ }
$admin->member_status = 'revoked';
- $admin->banned = 1;
+ $admin->banned = 1;
$admin->save();
return $this->metaSuccess();
@@ -770,13 +1689,23 @@ public function revokeSubAdmin(Request $request, $id)
public function undoRevokeSubAdmin(Request $request, $id)
{
$admin = User::find($id);
- if ($admin == null || $admin->role != 'sub-admin')
- return $this->errorResponse('No admin to be revoked', Response::HTTP_BAD_REQUEST);
+
+ if (
+ $admin == null ||
+ $admin->role != 'sub-admin'
+ ) {
+ return $this->errorResponse(
+ 'No admin to be revoked',
+ Response::HTTP_BAD_REQUEST
+ );
+ }
+
if ($admin->password) {
$admin->member_status = 'active';
} else {
$admin->member_status = 'invited';
}
+
$admin->banned = 0;
$admin->save();
@@ -786,72 +1715,126 @@ public function undoRevokeSubAdmin(Request $request, $id)
public function getIpHistories(Request $request, $id)
{
$admin = User::find($id);
- if ($admin == null || $admin->role != 'sub-admin') {
- return $this->errorResponse('Not found admin', Response::HTTP_BAD_REQUEST);
+
+ if (
+ $admin == null ||
+ $admin->role != 'sub-admin'
+ ) {
+ return $this->errorResponse(
+ 'Not found admin',
+ Response::HTTP_BAD_REQUEST
+ );
}
- $limit = $request->limit ?? 50;
+
+ $limit = $request->limit ?? 50;
$ipAddress = IpHistory::where(['user_id' => $admin->id])
->orderBy('created_at', 'DESC')
->paginate($limit);
return $this->successResponse($ipAddress);
}
-
+
public function approveIntakeUser($id)
{
$admin = auth()->user();
+ $user = User::where('id', $id)
+ ->where('banned', 0)
+ ->where('role', 'member')
+ ->first();
- $user = User::where('id', $id)->where('banned', 0)->where('role', 'member')->first();
if ($user && $user->letter_file) {
- $user->letter_verified_at = now();
+ $user->letter_verified_at = Carbon::now('UTC');
$user->save();
$emailerData = EmailerHelper::getEmailerData();
- EmailerHelper::triggerUserEmail($user->email, 'Your letter of motivation is APPROVED', $emailerData, $user);
- if ($user->letter_verified_at && $user->node_verified_at) {
- EmailerHelper::triggerUserEmail($user->email, 'Congratulations', $emailerData, $user);
+
+ EmailerHelper::triggerUserEmail(
+ $user->email,
+ 'Your letter of motivation is APPROVED',
+ $emailerData,
+ $user
+ );
+
+ if (
+ $user->letter_verified_at &&
+ $user->node_verified_at
+ ) {
+ EmailerHelper::triggerUserEmail(
+ $user->email,
+ 'Congratulations',
+ $emailerData,
+ $user
+ );
}
return $this->metaSuccess();
}
- return $this->errorResponse('Fail approved User', Response::HTTP_BAD_REQUEST);
+
+ return $this->errorResponse(
+ 'Fail approved User',
+ Response::HTTP_BAD_REQUEST
+ );
}
public function resetIntakeUser($id, Request $request)
{
$admin = auth()->user();
+ $user = User::where('id', $id)
+ ->where('banned', 0)
+ ->where('role', 'member')
+ ->first();
- $user = User::where('id', $id)->where('banned', 0)->where('role', 'member')->first();
if ($user) {
$user->letter_verified_at = null;
- $user->letter_file = null;
- $user->letter_rejected_at = now();
+ $user->letter_file = null;
+ $user->letter_rejected_at = Carbon::now('UTC');
$user->save();
$message = trim($request->get('message'));
+
if (!$message) {
- return $this->errorResponse('please input message', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'please input message',
+ Response::HTTP_BAD_REQUEST
+ );
}
- Mail::to($user->email)->send(new AdminAlert('You need to submit letter again', $message));
+
+ Mail::to($user->email)->send(new AdminAlert(
+ 'You need to submit letter again',
+ $message
+ ));
+
return $this->metaSuccess();
}
- return $this->errorResponse('Fail reset User', Response::HTTP_BAD_REQUEST);
+
+ return $this->errorResponse(
+ 'Fail reset User',
+ Response::HTTP_BAD_REQUEST
+ );
}
public function banUser($id)
{
$admin = auth()->user();
+ $user = User::where('id', $id)
+ ->where('banned', 0)
+ ->first();
- $user = User::where('id', $id)->where('banned', 0)->first();
if ($user) {
$user->banned = 1;
$user->save();
return $this->metaSuccess();
}
- return $this->errorResponse('Fail Ban User', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Fail Ban User',
+ Response::HTTP_BAD_REQUEST
+ );
}
public function removeUser($id, Request $request)
{
- $user = User::where('id', $id)->where('role', 'member')->first();
+ $user = User::where('id', $id)
+ ->where('role', 'member')
+ ->first();
+
if ($user) {
Shuftipro::where('user_id', $user->id)->delete();
ShuftiproTemp::where('user_id', $user->id)->delete();
@@ -859,27 +1842,29 @@ public function removeUser($id, Request $request)
$user->delete();
return $this->metaSuccess();
}
- return $this->errorResponse('Fail remove User', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Fail remove User',
+ Response::HTTP_BAD_REQUEST
+ );
}
public function getVerificationUsers(Request $request)
{
$limit = $request->limit ?? 50;
- $users = User::where('users.role', 'member')->where('banned', 0)
- ->join('profile', function ($query) {
- $query->on('profile.user_id', '=', 'users.id')
- ->where('profile.status', 'pending');
- })
- ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id')
- ->select([
- 'users.id as user_id',
- 'users.created_at',
- 'users.email',
- 'profile.*',
- 'shuftipro.status as kyc_status',
- 'shuftipro.background_checks_result',
- 'shuftipro.manual_approved_at'
- ])->paginate($limit);
+ $users = User::where('users.role', 'member')
+ ->where('banned', 0)
+ ->join('shuftipro', 'shuftipro.user_id', '=', 'users.id')
+ ->where('shuftipro.status', 'denied')
+ ->orWhere('shuftipro.status', 'pending')
+ ->select([
+ 'users.id as user_id',
+ 'users.created_at',
+ 'users.email',
+ 'shuftipro.status as kyc_status',
+ 'shuftipro.background_checks_result',
+ 'shuftipro.manual_approved_at'
+ ])->paginate($limit);
+
return $this->successResponse($users);
}
@@ -887,17 +1872,23 @@ public function getVerificationUsers(Request $request)
public function resetKYC($id, Request $request)
{
$admin = auth()->user();
-
$message = trim($request->get('message'));
+
if (!$message) {
- return $this->errorResponse('please input message', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'please input message',
+ Response::HTTP_BAD_REQUEST
+ );
}
- $user = User::with(['profile'])->where('id', $id)->first();
+ $user = User::with(['profile'])
+ ->where('id', $id)
+ ->first();
+
if ($user && $user->profile) {
$user->profile->status = null;
$user->profile->save();
-
+
Profile::where('user_id', $user->id)->delete();
Shuftipro::where('user_id', $user->id)->delete();
ShuftiproTemp::where('user_id', $user->id)->delete();
@@ -907,158 +1898,89 @@ public function resetKYC($id, Request $request)
$user->approve_at = null;
$user->reset_kyc = 1;
$user->save();
-
- Mail::to($user->email)->send(new AdminAlert('You need to submit KYC again', $message));
- return $this->metaSuccess();
- }
-
- return $this->errorResponse('Fail Reset KYC', Response::HTTP_BAD_REQUEST);
- }
-
- public function refreshLinks($id)
- {
- $url = 'https://api.shuftipro.com/status';
- $user = User::with('shuftipro')->find($id);
-
- $shuftipro = $user->shuftipro;
- if ($shuftipro) {
- $client_id = config('services.shufti.client_id');
- $secret_key = config('services.shufti.client_secret');
-
- $response = Http::withBasicAuth($client_id, $secret_key)->post($url, [
- 'reference' => $shuftipro->reference_id
- ]);
-
- $data = $response->json();
- if (!$data || !is_array($data)) return;
-
- if (!isset($data['reference']) || !isset($data['event'])) {
- return $this->successResponse([
- 'success' => false,
- ]);
- }
-
- $events = [
- 'verification.accepted',
- 'verification.declined',
- 'request.timeout'
- ];
-
- if (!in_array($data['event'], $events)) {
- return $this->successResponse([
- 'success' => false,
- ]);
- }
-
- $proofs = isset($data['proofs']) ? $data['proofs'] : null;
-
- if ($proofs && isset($proofs['document']) && isset($proofs['document']['proof'])) {
- $shuftipro->document_proof = $proofs['document']['proof'];
- }
-
- // Address Proof
- if ($proofs && isset($proofs['address']) && isset($proofs['address']['proof'])) {
- $shuftipro->address_proof = $proofs['address']['proof'];
- }
-
- $shuftipro->save();
-
- return $this->successResponse([
- 'success' => true,
- ]);
- }
-
- return $this->successResponse([
- 'success' => false,
- ]);
- }
- public function banAndDenyUser($id)
- {
- $user = User::with(['shuftipro', 'profile'])
- ->where('id', $id)
- ->where('users.role', 'member')
- ->where('banned', 0)
- ->first();
+ Mail::to($user->email)->send(new AdminAlert(
+ 'You need to submit KYC again',
+ $message
+ ));
- if ($user && $user->profileT) {
- $user->profile->status = 'denied';
- $user->profile->save();
- $user->banned = 1;
- $user->save();
return $this->metaSuccess();
}
- return $this->errorResponse('Fail deny and ban user', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Fail Reset KYC',
+ Response::HTTP_BAD_REQUEST
+ );
}
public function getVerificationDetail($id)
{
$user = User::with(['shuftipro', 'profile', 'documentFiles'])
- ->leftJoin('shuftipro', 'shuftipro.user_id', '=', 'users.id')
- ->where('users.id', $id)
- ->select([
- 'users.*',
- 'shuftipro.status as kyc_status',
- 'shuftipro.background_checks_result',
- ])
- ->where('users.role', 'member')
- ->where('banned', 0)
- ->first();
+ ->leftJoin('shuftipro', 'shuftipro.user_id', '=', 'users.id')
+ ->where('users.id', $id)
+ ->select([
+ 'users.*',
+ 'shuftipro.status as kyc_status',
+ 'shuftipro.background_checks_result',
+ 'shuftipro.data'
+ ])
+ ->where('users.role', 'member')
+ ->where('banned', 0)
+ ->first();
if ($user) {
- if (isset($user->shuftipro) && isset($user->shuftipro->address_proof) && $user->shuftipro->address_proof) {
+ if (
+ isset($user->shuftipro) &&
+ isset($user->shuftipro->address_proof) &&
+ $user->shuftipro->address_proof
+ ) {
$url = Storage::disk('local')->url($user->shuftipro->address_proof);
$user->shuftipro->address_proof_link = asset($url);
}
- return $this->successResponse($user);
- }
- return $this->errorResponse('Fail get verification user', Response::HTTP_BAD_REQUEST);
- }
+ $declined_reason = '';
- public function approveDocument($id)
- {
- $user = User::with(['profile'])
- ->where('id', $id)
- ->where('users.role', 'member')
- ->where('banned', 0)
- ->first();
+ try {
+ $declined_reason = json_decode(json_decode($user->data))->declined_reason;
+ } catch (\Exception $ex) {}
- if ($user && $user->profile) {
- $user->profile->document_verified_at = now();
- $user->profile->save();
- return $this->metaSuccess();
+ $user->declined_reason = $declined_reason;
+
+ return $this->successResponse($user);
}
- return $this->errorResponse('Fail approve document', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Fail get verification user',
+ Response::HTTP_BAD_REQUEST
+ );
}
- public function activeUser($id)
+ public function approveDocument($id)
{
$user = User::with(['profile'])
- ->where('id', $id)
- ->where('users.role', 'member')
- ->where('banned', 0)
- ->first();
-
+ ->where('id', $id)
+ ->where('users.role', 'member')
+ ->where('banned', 0)
+ ->first();
+
if ($user && $user->profile) {
- $user->profile->status = 'approved';
+ $user->profile->document_verified_at = Carbon::now('UTC');
$user->profile->save();
- $user->approve_at = now();
- $user->save();
return $this->metaSuccess();
}
- return $this->errorResponse('Fail active document', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Fail approve document',
+ Response::HTTP_BAD_REQUEST
+ );
}
// Add Emailer Admin
public function addEmailerAdmin(Request $request)
{
- $user = Auth::user();
-
+ $user = Auth::user();
$email = $request->get('email');
+
if (!$email) {
return [
'success' => false,
@@ -1067,6 +1989,7 @@ public function addEmailerAdmin(Request $request)
}
$record = EmailerAdmin::where('email', $email)->first();
+
if ($record) {
return [
'success' => false,
@@ -1094,27 +2017,34 @@ public function getEmailerData(Request $request)
{
$user = Auth::user();
$data = [];
+ $admins = EmailerAdmin::where('id', '>', 0)
+ ->orderBy('email', 'asc')
+ ->get();
+
+ $triggerAdmin = EmailerTriggerAdmin::where('id', '>', 0)
+ ->orderBy('id', 'asc')
+ ->get();
- $admins = EmailerAdmin::where('id', '>', 0)->orderBy('email', 'asc')->get();
- $triggerAdmin = EmailerTriggerAdmin::where('id', '>', 0)->orderBy('id', 'asc')->get();
- $triggerUser = EmailerTriggerUser::where('id', '>', 0)->orderBy('id', 'asc')->get();
+ $triggerUser = EmailerTriggerUser::where('id', '>', 0)
+ ->orderBy('id', 'asc')
+ ->get();
$data = [
'admins' => $admins,
'triggerAdmin' => $triggerAdmin,
- 'triggerUser' => $triggerUser,
+ 'triggerUser' => $triggerUser,
];
return [
'success' => true,
- 'data' => $data
+ 'data' => $data
];
}
// Update Emailer Trigger Admin
public function updateEmailerTriggerAdmin($recordId, Request $request)
{
- $user = Auth::user();
+ $user = Auth::user();
$record = EmailerTriggerAdmin::find($recordId);
if ($record) {
@@ -1136,51 +2066,12 @@ public function updateEmailerTriggerUser($recordId, Request $request)
if ($record) {
$enabled = (int) $request->get('enabled');
$content = $request->get('content');
-
$record->enabled = $enabled;
- if ($content) $record->content = $content;
-
- $record->save();
-
- return ['success' => true];
- }
-
- return ['success' => false];
- }
-
- public function getMonitoringCriteria(Request $request)
- {
- $data = MonitoringCriteria::get();
- return $this->successResponse($data);
- }
-
- public function updateMonitoringCriteria($type, Request $request)
- {
- $record = MonitoringCriteria::where('type', $type)->first();
-
- if ($record) {
- $validator = Validator::make($request->all(), [
- 'warning_level' => 'required|integer',
- 'probation_start' => 'required',
- // 'frame_calculate_unit' => 'required|in:Weeks,Days,Hours',
- // 'frame_calculate_value' => 'required|integer',
- 'given_to_correct_unit' => 'required|in:Weeks,Days,Hours',
- 'given_to_correct_value' => 'required|integer',
- // 'system_check_unit' => 'required|in:Weeks,Days,Hours',
- // 'system_check_value' => 'required|integer',
- ]);
- if ($validator->fails())
- return $this->validateResponse($validator->errors());
+ if ($content) {
+ $record->content = $content;
+ }
- $record->warning_level = $request->warning_level;
- $record->probation_start = $request->probation_start;
- // $record->frame_calculate_unit = $request->frame_calculate_unit;
- // $record->frame_calculate_value = $request->frame_calculate_value;
- $record->given_to_correct_unit = $request->given_to_correct_unit;
- $record->given_to_correct_value = $request->given_to_correct_value;
- // $record->system_check_unit = $request->system_check_unit;
- // $record->system_check_value = $request->system_check_value;
$record->save();
return ['success' => true];
@@ -1195,64 +2086,32 @@ public function updateLockRules(Request $request, $id)
'is_lock' => 'required|boolean'
]);
- if ($validator->fails()) return $this->validateResponse($validator->errors());
+ if ($validator->fails()) {
+ return $this->validateResponse($validator->errors());
+ }
$rule = LockRules::where('id', $id)->first();
-
$rule->is_lock = $request->is_lock;
$rule->save();
return ['success' => true];
}
- public function getLockRules()
- {
- $ruleKycNotVerify = LockRules::where('type', 'kyc_not_verify')
- ->orderBy('id', 'ASC')->select(['id', 'screen', 'is_lock'])->get();
- $ruleStatusIsPoor = LockRules::where('type', 'status_is_poor')
- ->orderBy('id', 'ASC')->select(['id', 'screen', 'is_lock'])->get();
- $data = [
- 'kyc_not_verify' => $ruleKycNotVerify,
- 'status_is_poor' => $ruleStatusIsPoor,
- ];
- return $this->successResponse($data);
- }
-
- public function getListNodes(Request $request)
- {
- $limit = $request->limit ?? 50;
- $node_failing = $request->node_failing ?? '';
-
- $nodes = UserAddress::select([
- 'user_addresses.user_id as user_id',
- 'user_addresses.public_address_node as public_address_node',
- 'user_addresses.is_fail_node as is_fail_node',
- 'user_addresses.rank as rank',
- ])
- ->join('users', 'users.id', '=', 'user_addresses.user_id')
- ->where('users.banned', 0)
- ->whereNotNull('user_addresses.public_address_node')
- ->where(function ($query) use ($node_failing) {
- if ($node_failing == 1) $query->where('user_addresses.is_fail_node', 1);
- })
- ->orderBy('user_addresses.rank', 'asc')
- ->paginate($limit);
-
- return $this->successResponse($nodes);
- }
-
// Get GraphInfo
public function getGraphInfo(Request $request)
{
$user = Auth::user();
- $graphDataDay = $graphDataWeek = $graphDataMonth = $graphDataYear = [];
+ $graphDataDay = $graphDataWeek = $graphDataMonth = $graphDataYear = [];
$timeDay = Carbon::now('UTC')->subHours(24);
$timeWeek = Carbon::now('UTC')->subDays(7);
$timeMonth = Carbon::now('UTC')->subDays(30);
$timeYear = Carbon::now('UTC')->subYear();
- $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeDay)->get();
+ $items = TokenPrice::orderBy('created_at', 'desc')
+ ->where('created_at', '>=', $timeDay)
+ ->get();
+
if ($items && count($items)) {
foreach ($items as $item) {
$name = strtotime($item->created_at);
@@ -1260,7 +2119,10 @@ public function getGraphInfo(Request $request)
}
}
- $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeWeek)->get();
+ $items = TokenPrice::orderBy('created_at', 'desc')
+ ->where('created_at', '>=', $timeWeek)
+ ->get();
+
if ($items && count($items)) {
foreach ($items as $item) {
$name = strtotime($item->created_at);
@@ -1268,7 +2130,10 @@ public function getGraphInfo(Request $request)
}
}
- $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeMonth)->get();
+ $items = TokenPrice::orderBy('created_at', 'desc')
+ ->where('created_at', '>=', $timeMonth)
+ ->get();
+
if ($items && count($items)) {
foreach ($items as $item) {
$name = strtotime($item->created_at);
@@ -1276,7 +2141,10 @@ public function getGraphInfo(Request $request)
}
}
- $items = TokenPrice::orderBy('created_at', 'desc')->where('created_at', '>=', $timeYear)->get();
+ $items = TokenPrice::orderBy('created_at', 'desc')
+ ->where('created_at', '>=', $timeYear)
+ ->get();
+
if ($items && count($items)) {
foreach ($items as $item) {
$name = strtotime($item->created_at);
@@ -1285,10 +2153,10 @@ public function getGraphInfo(Request $request)
}
return $this->successResponse([
- 'day' => $graphDataDay,
- 'week' => $graphDataWeek,
+ 'day' => $graphDataDay,
+ 'week' => $graphDataWeek,
'month' => $graphDataMonth,
- 'year' => $graphDataYear,
+ 'year' => $graphDataYear,
]);
}
@@ -1297,55 +2165,51 @@ public function uploadMembershipFile(Request $request)
try {
// Validator
$validator = Validator::make($request->all(), [
- 'file' => 'required|mimes:pdf,docx,doc,txt,rtf|max:5000',
+ 'file' => 'required|mimes:pdf,docx,doc,txt,rtf|max:2048',
]);
- if ($validator->fails())
+ if ($validator->fails()) {
return $this->validateResponse($validator->errors());
+ }
$filenameWithExt = $request->file('file')->getClientOriginalName();
- //Get just filename
- $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
- // Get just ext
- $extension = $request->file('file')->getClientOriginalExtension();
- // new filename hash
- $filenamehash = md5(Str::random(10) . '_' . (string)time());
- // Filename to store
+ $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
+ $extension = $request->file('file')->getClientOriginalExtension();
+ $filenamehash = md5(Str::random(10) . '_' . (string)time());
$fileNameToStore = $filenamehash . '.' . $extension;
// S3 File Upload
$S3 = new S3Client([
- 'version' => 'latest',
- 'region' => getenv('AWS_DEFAULT_REGION'),
+ 'version' => 'latest',
+ 'region' => getenv('AWS_DEFAULT_REGION'),
'credentials' => [
- 'key' => getenv('AWS_ACCESS_KEY_ID'),
- 'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
+ 'key' => getenv('AWS_ACCESS_KEY_ID'),
+ 'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
],
]);
$s3result = $S3->putObject([
- 'Bucket' => getenv('AWS_BUCKET'),
- 'Key' => 'client_uploads/' . $fileNameToStore,
+ 'Bucket' => getenv('AWS_BUCKET'),
+ 'Key' => 'client_uploads/' . $fileNameToStore,
'SourceFile' => $request->file('file')
]);
$ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL') . '/not-found';
MembershipAgreementFile::where('id', '>', 0)->delete();
- $membershipAgreementFile = new MembershipAgreementFile();
+ $membershipAgreementFile = new MembershipAgreementFile();
$membershipAgreementFile->name = $filenameWithExt;
$membershipAgreementFile->path = $ObjectURL;
- $membershipAgreementFile->url = $ObjectURL;
+ $membershipAgreementFile->url = $ObjectURL;
$membershipAgreementFile->save();
DB::table('users')->update(['membership_agreement' => 0]);
+
return $this->successResponse($membershipAgreementFile);
} catch (\Exception $ex) {
- return $this->errorResponse(__('Failed upload file'), Response::HTTP_BAD_REQUEST, $ex->getMessage());
+ return $this->errorResponse(
+ __('Failed upload file'),
+ Response::HTTP_BAD_REQUEST,
+ $ex->getMessage()
+ );
}
}
-
- public function getMembershipFile()
- {
- $membershipAgreementFile = MembershipAgreementFile::first();
- return $this->successResponse($membershipAgreementFile);
- }
}
\ No newline at end of file
diff --git a/app/Http/Controllers/Api/V1/AuthController.php b/app/Http/Controllers/Api/V1/AuthController.php
index 0f50f50a..764d2e52 100644
--- a/app/Http/Controllers/Api/V1/AuthController.php
+++ b/app/Http/Controllers/Api/V1/AuthController.php
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Api\V1;
+use Carbon\Carbon;
use App\Console\Helper;
use App\Http\Controllers\Controller;
@@ -20,10 +21,13 @@
use App\Models\User;
use App\Models\UserAddress;
use App\Models\VerifyUser;
+use App\Models\UpgradeList;
use App\Repositories\UserRepository;
use App\Repositories\VerifyUserRepository;
+use App\Jobs\TestJob;
+
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
@@ -57,9 +61,62 @@ public function __construct(
$this->verifyUserRepo = $verifyUserRepo;
}
- public function testHash() {
- exit(Hash::make('ledgerleapllc'));
+ public function testJob() {
+ TestJob::dispatch();
+ return 'Test Job!';
+ }
+
+ public function devUpgradeList() {
+ $items = UpgradeList::orderBy('created_at', 'asc')->get();
+ if ($items && count($items) > 0) {
+ foreach ($items as $item) {
+ echo $item->email . '
';
+ }
+ }
+ }
+
+ public function devVerifyNode($address)
+ {
+ $query = DB::select("
+ SELECT
+ a.user_id, a.node_verified_at, a.signed_file, a.node_status,
+ b.id, b.email, b.node_verified_at, b.signed_file,
+ b.node_status, b.has_verified_address
+ FROM user_addresses AS a
+ JOIN users AS b
+ ON a.user_id = b.id
+ WHERE a.public_address_node = '$address'
+ ");
+
+ $query = $query[0] ?? [];
+ $user_id = $query->user_id ?? 0;
+
+ if ($user_id) {
+ $update = DB::table('user_addresses')
+ ->where('public_address_node', $address)
+ ->update(
+ [
+ 'node_verified_at' => '2022-03-18 19:26:51',
+ 'signed_file' => 'https://casper-assoc-portal-dev.s3.us-east-2.amazonaws.com/signatures/db49744f7535b218c20a48cb833da6a1',
+ 'node_status' => 'Online'
+ ]
+ );
+
+ $update = DB::table('users')
+ ->where('id', $user_id)
+ ->update(
+ [
+ 'node_verified_at' => '2022-03-18 19:26:51',
+ 'signed_file' => 'https://casper-assoc-portal-dev.s3.us-east-2.amazonaws.com/signatures/db49744f7535b218c20a48cb833da6a1',
+ 'node_status' => 'Online',
+ 'has_verified_address' => 1
+ ]
+ );
+ }
+
+ return $this->metaSuccess();
}
+
/**
* Auth user function
@@ -71,35 +128,50 @@ public function testHash() {
public function login(LoginRequest $request)
{
$user = $this->userRepo->first(['email' => $request->email]);
+
if ($user && Hash::check($request->password, $user->password)) {
if ($user->banned == 1) {
- return $this->errorResponse('User banned', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'User banned',
+ Response::HTTP_BAD_REQUEST
+ );
}
+
if ($user->twoFA_login) {
$code = strtoupper(Str::random(6));
$user->twoFA_login_active = 1;
$user->save();
- VerifyUser::where('email', $user->email)->where('type', VerifyUser::TYPE_LOGIN_TWO_FA)->delete();
- $verify = new VerifyUser();
- $verify->email = $user->email;
- $verify->type = VerifyUser::TYPE_LOGIN_TWO_FA;
- $verify->code = $code;
- $verify->created_at = now();
+
+ VerifyUser::where('email', $user->email)
+ ->where('type', VerifyUser::TYPE_LOGIN_TWO_FA)
+ ->delete();
+
+ $verify = new VerifyUser();
+ $verify->email = $user->email;
+ $verify->type = VerifyUser::TYPE_LOGIN_TWO_FA;
+ $verify->code = $code;
+ $verify->created_at = Carbon::now('UTC');
$verify->save();
+
Mail::to($user)->send(new LoginTwoFA($code));
}
- $user->last_login_at = now();
+
+ $user->last_login_at = Carbon::now('UTC');
$user->last_login_ip_address = request()->ip();
$user->save();
- $ipHistory = new IpHistory();
- $ipHistory->user_id = $user->id;
+
+ $ipHistory = new IpHistory();
+ $ipHistory->user_id = $user->id;
$ipHistory->ip_address = request()->ip();
$ipHistory->save();
Helper::getAccountInfoStandard($user);
return $this->createTokenFromUser($user);
}
- return $this->errorResponse(__('api.error.login_not_found'), Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ __('api.error.login_not_found'),
+ Response::HTTP_BAD_REQUEST
+ );
}
/**
@@ -115,32 +187,36 @@ public function registerEntity(RegisterEntityRequest $request)
DB::beginTransaction();
$data = $request->all();
- $data['password'] = bcrypt($request->password);
- $data['last_login_at'] = now();
- $data['type'] = User::TYPE_ENTITY;
+ $data['password'] = bcrypt($request->password);
+ $data['last_login_at'] = Carbon::now('UTC');
+ $data['type'] = User::TYPE_ENTITY;
+
$user = $this->userRepo->create($data);
- $code = generateString(7);
+ $code = Helper::generateString(7);
+
$userVerify = $this->verifyUserRepo->updateOrCreate(
[
'email' => $request->email,
- 'type' => VerifyUser::TYPE_VERIFY_EMAIL,
+ 'type' => VerifyUser::TYPE_VERIFY_EMAIL,
],
[
- 'code' => $code,
- 'created_at' => now()
+ 'code' => $code,
+ 'created_at' => Carbon::now('UTC')
]
);
+
Mail::to($user->email)->send(new UserVerifyMail($code));
DB::commit();
- $user->pending_node = 1;
- $user->last_login_at = now();
+ $user->pending_node = 1;
+ $user->last_login_at = Carbon::now('UTC');
$user->last_login_ip_address = request()->ip();
$user->save();
- $ipHistory = new IpHistory();
- $ipHistory->user_id = $user->id;
+ $ipHistory = new IpHistory();
+ $ipHistory->user_id = $user->id;
$ipHistory->ip_address = request()->ip();
$ipHistory->save();
+
return $this->createTokenFromUser($user);
} catch (\Exception $e) {
DB::rollBack();
@@ -161,32 +237,36 @@ public function registerIndividual(RegisterIndividualRequest $request)
DB::beginTransaction();
$data = $request->all();
- $data['password'] = bcrypt($request->password);
- $data['last_login_at'] = now();
- $data['type'] = User::TYPE_INDIVIDUAL;
+ $data['password'] = bcrypt($request->password);
+ $data['last_login_at'] = Carbon::now('UTC');
+ $data['type'] = User::TYPE_INDIVIDUAL;
+
$user = $this->userRepo->create($data);
- $code = generateString(7);
+ $code = Helper::generateString(7);
+
$userVerify = $this->verifyUserRepo->updateOrCreate(
[
'email' => $request->email,
- 'type' => VerifyUser::TYPE_VERIFY_EMAIL,
+ 'type' => VerifyUser::TYPE_VERIFY_EMAIL,
],
[
- 'code' => $code,
- 'created_at' => now(),
+ 'code' => $code,
+ 'created_at' => Carbon::now('UTC'),
]
);
+
Mail::to($user->email)->send(new UserVerifyMail($code));
DB::commit();
- $user->pending_node = 1;
- $user->last_login_at = now();
+ $user->pending_node = 1;
+ $user->last_login_at = Carbon::now('UTC');
$user->last_login_ip_address = request()->ip();
$user->save();
- $ipHistory = new IpHistory();
- $ipHistory->user_id = $user->id;
- $ipHistory->ip_address = request()->ip();
+ $ipHistory = new IpHistory();
+ $ipHistory->user_id = $user->id;
+ $ipHistory->ip_address = request()->ip();
$ipHistory->save();
+
return $this->createTokenFromUser($user);
} catch (\Exception $e) {
DB::rollBack();
@@ -205,19 +285,35 @@ public function verifyEmail(Request $request)
{
try {
$user = auth()->user();
- $verifyUser = $this->verifyUserRepo->first(
- ['code' => $request->code, 'email' => $user->email]
- );
+ $verifyUser = $this->verifyUserRepo->first([
+ 'code' => $request->code,
+ 'email' => $user->email
+ ]);
+
if ($this->checCode($verifyUser)) {
- $user->update(['email_verified_at' => now()]);
+ $user->update(['email_verified_at' => Carbon::now('UTC')]);
$verifyUser->delete();
$emailerData = EmailerHelper::getEmailerData();
- EmailerHelper::triggerUserEmail($user->email, 'Welcome to the Casper', $emailerData, $user);
+
+ EmailerHelper::triggerUserEmail(
+ $user->email,
+ 'Welcome to the Casper',
+ $emailerData,
+ $user
+ );
+
return $this->metaSuccess();
}
- return $this->errorResponse(__('api.error.code_not_found'), Response::HTTP_BAD_REQUEST);
+
+ return $this->errorResponse(
+ __('api.error.code_not_found'),
+ Response::HTTP_BAD_REQUEST
+ );
} catch (\Exception $ex) {
- return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR);
+ return $this->errorResponse(
+ __('api.error.internal_error'),
+ Response::HTTP_INTERNAL_SERVER_ERROR
+ );
}
}
@@ -236,29 +332,55 @@ public function sendResetLinkEmail(SendResetPasswordMailRequeslRequest $request)
'email' => $request->email,
]
);
+
if (!$user) {
- return $this->errorResponse(__('api.error.email_not_found'), Response::HTTP_BAD_REQUEST);
+ return $this->successResponse([
+ 'success' => false,
+ 'message' => 'We can\'t find an account associated with that email address. Please check the address and try again.'
+ ]);
}
- $code = Str::random(60);
- // $url = $request->header('origin') ?? $request->root();
- $url = getenv('SITE_URL');
- $resetUrl = $url . '/update-password?code=' . $code . '&email=' . urlencode($request->email);
+
+ if (!filter_var($request->email, FILTER_VALIDATE_EMAIL)) {
+ return $this->successResponse([
+ 'success' => false,
+ 'message' => 'Invalid email provided'
+ ]);
+ }
+
+ $code = Str::random(60);
+ $url = getenv('SITE_URL');
+ $resetUrl = (string)(
+ $url .
+ '/update-password?code=' .
+ $code .
+ '&email=' .
+ urlencode($request->email)
+ );
+
$passwordReset = $this->verifyUserRepo->updateOrCreate(
[
'email' => $user->email,
- 'type' => VerifyUser::TYPE_RESET_PASSWORD,
+ 'type' => VerifyUser::TYPE_RESET_PASSWORD,
],
[
- 'code' => $code,
- 'created_at' => now(),
+ 'code' => $code,
+ 'created_at' => Carbon::now('UTC'),
]
);
+
if ($passwordReset) {
Mail::to($request->email)->send(new ResetPasswordMail($resetUrl));
}
- return $this->metaSuccess();
+
+ return $this->successResponse([
+ 'success' => true,
+ 'message' => 'A password reset link has been sent to your email.'
+ ]);
} catch (\Exception $ex) {
- return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR);
+ return $this->errorResponse(
+ __('api.error.internal_error'),
+ Response::HTTP_INTERNAL_SERVER_ERROR
+ );
}
}
@@ -274,23 +396,37 @@ public function resetPassword(ResetPasswordRequest $request)
try {
$passwordReset = $this->verifyUserRepo->first(
[
- 'code' => $request->code,
- 'type' => VerifyUser::TYPE_RESET_PASSWORD,
+ 'code' => $request->code,
+ 'type' => VerifyUser::TYPE_RESET_PASSWORD,
'email' => $request->email
]
);
+
if ($this->checCode($passwordReset)) {
DB::beginTransaction();
- $this->userRepo->updateConditions(['password' => bcrypt($request->password)], ['email' => $passwordReset->email]);
+ $this->userRepo->updateConditions(
+ ['password' => bcrypt($request->password)],
+ ['email' => $passwordReset->email]
+ );
+
$passwordReset->delete();
DB::commit();
return $this->metaSuccess();
}
+
DB::rollBack();
- return $this->errorResponse(__('api.error.code_not_found'), Response::HTTP_BAD_REQUEST);
+
+ return $this->errorResponse(
+ __('api.error.code_not_found'),
+ Response::HTTP_BAD_REQUEST
+ );
} catch (\Exception $ex) {
DB::rollBack();
- return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR);
+
+ return $this->errorResponse(
+ __('api.error.internal_error'),
+ Response::HTTP_INTERNAL_SERVER_ERROR
+ );
}
}
/**
@@ -303,21 +439,23 @@ public function resetPassword(ResetPasswordRequest $request)
public function resendVerifyEmail(Request $request)
{
try {
- $user = auth()->user();
- $code = generateString(7);
+ $user = auth()->user();
+ $code = Helper::generateString(7);
$userVerify = $this->verifyUserRepo->updateOrCreate(
[
'email' => $user->email,
- 'type' => VerifyUser::TYPE_VERIFY_EMAIL,
+ 'type' => VerifyUser::TYPE_VERIFY_EMAIL,
],
[
- 'code' => $code,
- 'created_at' => now()
+ 'code' => $code,
+ 'created_at' => Carbon::now('UTC')
]
);
+
if ($userVerify) {
Mail::to($user->email)->send(new UserVerifyMail($code));
}
+
return $this->metaSuccess();
} catch (\Exception $e) {
throw $e;
@@ -328,35 +466,55 @@ public function registerSubAdmin(Request $request)
{
$validator = Validator::make($request->all(), [
'first_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/',
- 'last_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/',
- 'email' => 'required|email|max:256',
- 'code' => 'required',
- 'password' => 'required|min:8|max:80',
+ 'last_name' => 'required|regex:/^[A-Za-z. ]{1,255}$/',
+ 'email' => 'required|email|max:256',
+ 'code' => 'required',
+ 'password' => 'required|min:8|max:80',
]);
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
- $user = User::where('email', $request->email)->where('member_status', 'invited')->where('role', 'sub-admin')->first();
+
+ $user = User::where('email', $request->email)
+ ->where('member_status', 'invited')
+ ->where('role', 'sub-admin')
+ ->first();
+
if (!$user) {
- return $this->errorResponse('There is no admin user with this email', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'There is no admin user with this email',
+ Response::HTTP_BAD_REQUEST
+ );
}
- $verify = VerifyUser::where('email', $request->email)->where('type', VerifyUser::TYPE_INVITE_ADMIN)->where('code', $request->code)->first();
+
+ $verify = VerifyUser::where('email', $request->email)
+ ->where('type', VerifyUser::TYPE_INVITE_ADMIN)
+ ->where('code', $request->code)
+ ->first();
+
if (!$verify) {
- return $this->errorResponse('Fail register sub-amdin', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'Fail register sub-amdin',
+ Response::HTTP_BAD_REQUEST
+ );
}
- $user->first_name = $request->first_name;
- $user->last_name = $request->last_name;
- $user->password = bcrypt($request->password);
- $user->last_login_at = now();
+
+ $user->first_name = $request->first_name;
+ $user->last_name = $request->last_name;
+ $user->password = bcrypt($request->password);
+ $user->last_login_at = Carbon::now('UTC');
$user->last_login_ip_address = request()->ip();
- $user->member_status = 'active';
+ $user->member_status = 'active';
$user->save();
- $ipHistory = new IpHistory();
- $ipHistory->user_id = $user->id;
+
+ $ipHistory = new IpHistory();
+ $ipHistory->user_id = $user->id;
$ipHistory->ip_address = request()->ip();
$ipHistory->save();
+
$verify->delete();
+
return $this->createTokenFromUser($user);
}
@@ -365,6 +523,7 @@ public function createTokenFromUser($user, $info = [])
Token::where([
'user_id' => $user->id
])->delete();
+
$token = $user->createToken(config('auth.secret_code'));
return $this->responseToken($token, $user->toArray());
}
@@ -378,6 +537,11 @@ public function createTokenFromUser($user, $info = [])
*/
private function checCode($verifyUser)
{
- return ($verifyUser && $verifyUser->created_at >= now()->subMinutes(VerifyUser::TOKEN_LIFETIME));
+ return (
+ $verifyUser &&
+ $verifyUser->created_at >= Carbon::now('UTC')->subMinutes(
+ VerifyUser::TOKEN_LIFETIME
+ )
+ );
}
-}
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/Api/V1/ContactController.php b/app/Http/Controllers/Api/V1/ContactController.php
index 7e9e2187..13137f6f 100644
--- a/app/Http/Controllers/Api/V1/ContactController.php
+++ b/app/Http/Controllers/Api/V1/ContactController.php
@@ -6,6 +6,7 @@
use App\Mail\ContactUsMail;
use App\Models\ContactRecipient;
use App\Models\ContactUs;
+use App\Models\UpgradeList;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
@@ -13,42 +14,67 @@
class ContactController extends Controller
{
+ public function submitUpgradeList(Request $request)
+ {
+ $validator = Validator::make($request->all(), [
+ 'email' => 'required|email'
+ ]);
+
+ if ($validator->fails()) {
+ return $this->validateResponse($validator->errors());
+ }
+
+ $email = $request->email;
+ $record = UpgradeList::where('email', $email)->first();
+
+ if ($record) {
+ return $this->errorResponse(
+ 'This email already exists',
+ Response::HTTP_BAD_REQUEST
+ );
+ }
+
+ $record = new UpgradeList;
+ $record->email = $email;
+ $record->save();
+
+ return $this->metaSuccess();
+ }
+
public function submitContact(Request $request)
{
$user_id = null;
- if(auth()->user()) {
+
+ if (auth()->user()) {
$user_id = auth()->user()->id;
}
+
$validator = Validator::make($request->all(), [
- 'name' => 'required|string|max:255',
- 'email' => 'required|email',
+ 'name' => 'required|string|max:255',
+ 'email' => 'required|email',
'message' => 'required',
]);
+
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
+
$contactUs = new ContactUs();
$contactUs->user_id = $user_id;
- $contactUs->name = $request->name;
- $contactUs->email = $request->email;
+ $contactUs->name = $request->name;
+ $contactUs->email = $request->email;
$contactUs->message = $request->message;
$contactUs->save();
- $contactRecipients = ContactRecipient::get();
+
+ $contactRecipients = ContactRecipient::get();
+
if (count($contactRecipients) > 0) {
foreach ($contactRecipients as $item) {
Mail::to($item->email)->send(new ContactUsMail($contactUs));
}
}
- return $this->metaSuccess();
- }
- public function getContactRecipients(Request $request)
- {
- $limit = $request->limit ?? 50;
- $sort_key = $request->sort_key ?? 'created_at';
- $sort_direction = $request->sort_direction ?? 'desc';
- $contactRecipients = ContactRecipient::orderBy($sort_key, $sort_direction)->paginate($limit);
- return $this->successResponse($contactRecipients);
+ return $this->metaSuccess();
}
public function addContactRecipients(Request $request)
@@ -56,12 +82,18 @@ public function addContactRecipients(Request $request)
$validator = Validator::make($request->all(), [
'email' => 'required|email',
]);
+
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
+
$contactRecipient = ContactRecipient::where('email', $request->email)->first();
+
if ($contactRecipient) {
- return $this->errorResponse('This email has already exist', Response::HTTP_BAD_REQUEST);
+ return $this->errorResponse(
+ 'This email has already exist',
+ Response::HTTP_BAD_REQUEST
+ );
} else {
$contactRecipient = new ContactRecipient();
$contactRecipient->email = $request->email;
diff --git a/app/Http/Controllers/Api/V1/DiscussionController.php b/app/Http/Controllers/Api/V1/DiscussionController.php
index 6302a923..b230d9c8 100644
--- a/app/Http/Controllers/Api/V1/DiscussionController.php
+++ b/app/Http/Controllers/Api/V1/DiscussionController.php
@@ -21,6 +21,7 @@
use App\Models\DiscussionComment;
use App\Models\DiscussionPin;
use App\Models\DiscussionRemoveNew;
+use App\Models\DiscussionVote;
use Carbon\Carbon;
@@ -57,9 +58,15 @@ public function getTrending(Request $request)
if (Helper::isAccessBlocked($user, 'discussions'))
return $this->successResponse(['data' => []]);
- $limit = $request->limit ?? 50;
- $trendings = Discussion::where('likes', '!=', 0)->where('is_draft', 0)->take(9)->orderBy('likes', 'desc')->paginate($limit);
- $count = Discussion::where('likes', '!=', 0)->where('is_draft', 0)->orderBy('likes', 'desc')->count();
+ $trendings = Discussion::where('likes', '!=', 0)
+ ->where('is_draft', 0)
+ ->take(9)
+ ->orderBy('likes', 'desc')
+ ->get();
+ $count = Discussion::where('likes', '!=', 0)
+ ->where('is_draft', 0)
+ ->orderBy('likes', 'desc')
+ ->count();
if ($count >= 9) {
return $this->successResponse($trendings);
} else {
@@ -71,10 +78,8 @@ public function getTrending(Request $request)
->where('is_draft', 0)
->take($remains)->orderBy('id', 'desc')->get();
$trendingArray = $trendings->toArray();
- $trendingArray['data'] = array_merge($trendingArray['data'], $news->toArray());
- return $this->successResponse([
- 'data' => $trendingArray['data']
- ]);
+ $trendingArray = array_merge($trendingArray, $news->toArray());
+ return $this->successResponse($trendingArray);
}
}
@@ -85,7 +90,6 @@ public function getDiscussions(Request $request)
if (Helper::isAccessBlocked($user, 'discussions'))
return $this->successResponse(['data' => []]);
- $data = array();
$limit = $request->limit ?? 50;
$data = Discussion::with(['user', 'user.profile'])->where('discussions.is_draft', 0)
->leftJoin('discussion_pins', function ($query) use ($user) {
@@ -250,7 +254,7 @@ public function createComment(Request $request, $id)
if (Helper::isAccessBlocked($user, 'discussions'))
return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST);
- $data = array();
+ $data = [];
$validator = Validator::make($request->all(), [
'description' => 'required'
]);
@@ -282,7 +286,6 @@ public function updateComment(Request $request, $id)
if (Helper::isAccessBlocked($user, 'discussions'))
return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST);
- $data = array();
$validator = Validator::make($request->all(), [
'description' => 'required',
'comment_id' => 'required'
@@ -290,22 +293,47 @@ public function updateComment(Request $request, $id)
if ($validator->fails()) {
return $this->validateResponse($validator->errors());
}
- $comment = DiscussionComment::where('discussion_id', $request->comment_id)->where('user_id', $user->id)->first();
+ $comment = DiscussionComment::where('id', $request->comment_id)
+ ->where('discussion_id', $id)
+ ->where('user_id', $user->id)->first();
if ($comment) {
$comment->description = $request->description;
+ $comment->edited_at = Carbon::now('UTC');
$comment->save();
return $this->successResponse($comment);
}
return $this->errorResponse('Invalid discussion id', Response::HTTP_BAD_REQUEST);
}
+ public function deleteComment($id, $commentId)
+ {
+ $user = auth()->user()->load(['pagePermissions']);
+ if (Helper::isAccessBlocked($user, 'discussions'))
+ return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST);
+
+ $comment = DiscussionComment::where('id', $commentId)
+ ->where('discussion_id', $id)
+ ->where(function ($query) use ($user) {
+ if ($user->role != 'admin') {
+ $query->where('user_id', $user->id);
+ }
+ })
+ ->first();
+ if ($comment) {
+ $comment->description = '
Comment deleted
'; + $comment->deleted_at = Carbon::now('UTC'); + $comment->save(); + return $this->metaSuccess(); + } + return $this->errorResponse('Invalid discussion id', Response::HTTP_BAD_REQUEST); + } + public function setVote(Request $request, $id) { $user = auth()->user()->load(['pagePermissions']); if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $data = array(); $validator = Validator::make($request->all(), [ 'is_like' => 'required|boolean' ]); @@ -361,7 +389,6 @@ public function setPin(Request $request, $id) if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $data = array(); $pinned = $this->discussionPinRepo->first(['discussion_id' => $id, 'user_id' => $user->id]); if ($pinned == null) { $this->discussionPinRepo->create(['discussion_id' => $id, 'user_id' => $user->id]); @@ -377,7 +404,7 @@ public function removeNewMark(Request $request, $id) if (Helper::isAccessBlocked($user, 'discussions')) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); - $this->discussionRemoveNewRepo->deleteConditions([['created_at', '<=', Carbon::now()->subDays(3)]]); + $this->discussionRemoveNewRepo->deleteConditions([['created_at', '<=', Carbon::now('UTC')->subDays(3)]]); $this->discussionRemoveNewRepo->create(['discussion_id' => $id, 'user_id' => $user->id]); return $this->metaSuccess(); @@ -412,6 +439,32 @@ public function getDraftDiscussions(Request $request) return $this->successResponse($data); } + public function deleteDiscussion($id) + { + $user = auth()->user()->load(['pagePermissions']); + if (Helper::isAccessBlocked($user, 'discussions')) + return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); + + $discussion = Discussion::where('id', $id) + ->where(function ($query) use ($user) { + if ($user->role != 'admin') { + $query->where('user_id', $user->id); + } + }) + ->first(); + if (!$discussion) { + return $this->errorResponse('Can not delete discussion', Response::HTTP_BAD_REQUEST); + } + + DiscussionComment::where('discussion_id', $discussion->id)->delete(); + DiscussionPin::where('discussion_id', $discussion->id)->delete(); + DiscussionRemoveNew::where('discussion_id', $discussion->id)->delete(); + DiscussionVote::where('discussion_id', $discussion->id)->delete(); + $discussion->delete(); + + return $this->metaSuccess(); + } + public function deleteDraftDiscussions($id) { $user = auth()->user()->load(['pagePermissions']); diff --git a/app/Http/Controllers/Api/V1/HelloSignController.php b/app/Http/Controllers/Api/V1/HelloSignController.php index 6d8aba0f..ed388b69 100644 --- a/app/Http/Controllers/Api/V1/HelloSignController.php +++ b/app/Http/Controllers/Api/V1/HelloSignController.php @@ -15,24 +15,31 @@ class HelloSignController extends Controller public function hellosignHook(Request $request) { $payload = $request->get('json'); - if (!$payload) return "error"; + + if (!$payload) { + return "error"; + } $data = json_decode($payload, true); $api_key = env('HELLOSIGN_API_KEY_HOOK'); - if (!is_array($data)) return "error"; + if (!is_array($data)) { + return "error"; + } // hellosign test check $callback_test = $data['event']['event_type'] ?? ''; - if ($callback_test == 'callback_test') { return "Hello API Event Received"; } $md5_header_check = base64_encode(hash_hmac('md5', $payload, $api_key)); $md5_header = $request->header('Content-MD5'); - if ($md5_header != $md5_header_check) + + if ($md5_header != $md5_header_check) { return "error"; + } + // Valid Request if ( isset($data['event']) && @@ -43,15 +50,15 @@ public function hellosignHook(Request $request) $filepath = 'hellosign/hellosign_' . $signature_request_id . '.pdf'; $client = new \HelloSign\Client($api_key); - $client->getFiles($signature_request_id, $filepath, \HelloSign\SignatureRequest::FILE_TYPE_PDF); $user = User::where('signature_request_id', $signature_request_id)->first(); if ($user) { - $user->hellosign_form = $filepath; + $user->hellosign_form = ''; $user->save(); } - return "Hello API Event Received"; } + + return "Hello API Event Received"; } } diff --git a/app/Http/Controllers/Api/V1/MetricController.php b/app/Http/Controllers/Api/V1/MetricController.php deleted file mode 100644 index 586c18bf..00000000 --- a/app/Http/Controllers/Api/V1/MetricController.php +++ /dev/null @@ -1,439 +0,0 @@ -user()->load(['pagePermissions']); - /* - if (Helper::isAccessBlocked($user, 'nodes')) - return $this->successResponse([]); - */ - $public_address_node = $request->get('public_address_node'); - - if (!$public_address_node) { - $public_address_node = $user->public_address_node; - } - - $isTotal = (int) $request->get('isTotal'); - - $max_update_responsiveness = DB::select(" - SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results;" - ); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select(" - SELECT max(peers) as max_peers FROM ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results;" - ); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select(" - SELECT max(uptime) as max_uptime FROM ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results;" - ); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - $latest = Node::where('node_address', strtolower($public_address_node))->whereNotnull('protocol_version')->orderBy('created_at', 'desc')->first(); - - if (!$latest) { - $latest = new Node(); - } - - $latest_block_height = $latest->block_height ?? null; - $latest_update_responsiveness = $latest->update_responsiveness ?? null; - $latest_peers = $latest->peers ?? null; - - $metric = Metric::where('user_id', $user->id)->first(); - - if (!$metric) { - $metric = new Metric(); - } - - $metric_uptime = $metric->uptime ?? null; - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - $metric_update_responsiveness = $metric->update_responsiveness ?? null; - $metric_peers = $metric->peers ?? null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - - if (!$nodeInfo) { - $nodeInfo = new NodeInfo(); - } - - $latest_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_block_height = $nodeInfo->block_height ?? null; - $nodeInfo_update_responsiveness = $nodeInfo->update_responsiveness ?? null; - $nodeInfo_peers = $nodeInfo->peers ?? null; - - $metric->avg_uptime = $nodeInfo_uptime ?? $metric_uptime; - $metric->avg_block_height_average = $nodeInfo_block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo_update_responsiveness ?? $metric_update_responsiveness; - $metric->avg_peers = $nodeInfo_peers ?? $metric_peers; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest_peers ?? $metric_peers; - $metric->update_responsiveness = $latest_update_responsiveness ?? $metric_update_responsiveness; - $metric->block_height_average = $latest_block_height ?? $metric_block_height; - $metric->uptime = $latest_uptime ?? $metric_uptime; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - - $userAddress = UserAddress::where('public_address_node', strtolower($public_address_node)) - ->where('user_id', $user->id) - ->first(); - - $rank = $user->rank; - - if ($userAddress) { - $rank = $userAddress->rank; - } - - $totalCount = UserAddress::select([ - 'users.id as user_id', - 'user_addresses.public_address_node', - 'user_addresses.is_fail_node', - 'user_addresses.rank' - ]) - ->join('users', 'users.id', '=', 'user_addresses.user_id') - ->where('users.banned', 0) - ->whereNotNull('user_addresses.public_address_node') - ->get() - ->count(); - - $delegators = $stake_amount = $self_stake_amount = 0; - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_stake_amount = $nodeInfo->self_staked_amount; - } - - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->totalCount = $totalCount; - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_stake_amount = $self_stake_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - - $setting = Setting::where('name', 'peers')->first(); - - if ($setting) { - $metric['peers_setting'] = (int) $setting->value; - } else { - $metric['peers_setting'] = 0; - } - - $addresses = UserAddress::where('user_id', $user->id)->get(); - $metric['addresses'] = $addresses; - - if ($isTotal) { - $tempRank = $stake_amount = $self_stake_amount = $delegators = 0; - if ($addresses && count($addresses) > 0) { - $tempRank = UserAddress::get()->count(); - foreach ($addresses as $address) { - if ($tempRank > (int) $address->rank) { - $tempRank = (int) $address->rank; - } - } - } - - if ($tempRank > 0) { - $metric->rank = $tempRank; - } - - if ($addresses && count($addresses) > 0) { - foreach ($addresses as $address) { - $nodeInfo = NodeInfo::where('node_address', strtolower($address->public_address_node))->first(); - if ($nodeInfo) { - $stake_amount += $nodeInfo->total_staked_amount; - $delegators += $nodeInfo->delegators_count; - $self_stake_amount += $nodeInfo->self_staked_amount; - } - } - } - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_stake_amount = $self_stake_amount; - } - - return $this->successResponse($metric); - } - - public function updateMetric(Request $request, $id) - { - $validator = Validator::make($request->all(), [ - 'uptime' => 'nullable|numeric|between:0,100', - ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - - $user = User::where('id', $id)->where('role', 'member')->first(); - if (!$user) return $this->errorResponse('User not found', Response::HTTP_BAD_REQUEST); - - $metric = Metric::where('user_id', $id)->first(); - if (!$metric) $metric = new Metric(); - if (isset($request->uptime) && $request->uptime != null) - $metric->uptime = $request->uptime; - if (isset($request->block_height_average) && $request->block_height_average != null) - $metric->block_height_average = $request->block_height_average; - if (isset($request->update_responsiveness) && $request->update_responsiveness != null) - $metric->update_responsiveness = $request->update_responsiveness; - if (isset($request->peers) && $request->peers != null) - $metric->peers = $request->peers; - $metric->user_id = $id; - $metric->save(); - return $this->successResponse($metric); - } - - public function getMetricUser($id) - { - $user = User::find($id); - if (!$user) return $this->successResponse([]); - - $max_update_responsiveness = DB::select("SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results; - "); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select(" - SELECT max(peers) as max_peers FROM - ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results; - "); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select(" - SELECT max(uptime) as max_uptime FROM - ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results; - "); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - $latest = Node::where('node_address', strtolower($user->public_address_node)) - ->whereNotnull('protocol_version') - ->orderBy('created_at', 'desc') - ->first(); - - if (!$latest) $latest = new Node(); - $latest_block_height = $latest->block_height ?? null; - $latest_update_responsiveness = $latest->update_responsiveness ?? null; - $latest_peers = $latest->peers ?? null; - - $metric = Metric::where('user_id', $user->id)->first(); - if (!$metric) $metric = new Metric(); - - $metric_uptime = $metric->uptime ?? null; - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - $metric_update_responsiveness = $metric->update_responsiveness ?? null; - $metric_peers = $metric->peers ?? null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($user->public_address_node))->first(); - if (!$nodeInfo) $nodeInfo = new NodeInfo(); - - $latest_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_block_height = $nodeInfo->block_height ?? null; - $nodeInfo_update_responsiveness = $nodeInfo->update_responsiveness ?? null; - $nodeInfo_peers = $nodeInfo->peers ?? null; - - $metric->avg_uptime = $nodeInfo_uptime ?? $metric_uptime; - $metric->avg_block_height_average = $nodeInfo_block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo_update_responsiveness ?? $metric_update_responsiveness; - $metric->avg_peers = $nodeInfo_peers ?? $metric_peers; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest_peers ?? $metric_peers; - $metric->update_responsiveness = $latest_update_responsiveness ?? $metric_update_responsiveness; - $metric->block_height_average = $latest_block_height ?? $metric_block_height; - $metric->uptime = $latest_uptime ?? $metric_uptime; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($user->public_address_node))->first(); - - $rank = $user->rank; - - $totalCount = User::select([ - 'id as user_id', - 'public_address_node', - 'is_fail_node', - 'rank', - ]) - ->where('banned', 0) - ->whereNotNull('public_address_node') - ->get() - ->count(); - - $delegators = $stake_amount = $self_stake_amount = 0; - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_stake_amount = $nodeInfo->self_staked_amount; - } - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->totalCount = $totalCount; - $metric->delegators = $delegators; - $metric->stake_amount = $stake_amount; - $metric->self_stake_amount = $self_stake_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - - return $this->successResponse($metric); - } - - public function getMetricUserByNodeName($node) - { - $node = strtolower($node); - $userAddress = UserAddress::with('user') - ->has('user') - ->where('public_address_node', $node) - ->first(); - - if ($userAddress && isset($userAddress->user) && $userAddress->user) { - $user = $userAddress->user; - $public_address_node = strtolower($userAddress->public_address_node); - - $max_update_responsiveness = DB::select(" - SELECT max(update_responsiveness) as max_update_responsiveness FROM - ( - SELECT MAX(update_responsiveness) as update_responsiveness FROM metric - UNION - SELECT MAX(update_responsiveness) as update_responsiveness FROM node_info - ) AS results;" - ); - $max_update_responsiveness = $max_update_responsiveness[0]->max_update_responsiveness ?? 0; - - $max_peers = DB::select(" - SELECT max(peers) as max_peers FROM - ( - SELECT MAX(peers) as peers FROM metric - UNION - SELECT MAX(peers) as peers FROM node_info - ) AS results;" - ); - $max_peers = $max_peers[0]->max_peers ?? 0; - $max_block_height = Node::max('block_height'); - $max_uptime = DB::select(" - SELECT max(uptime) as max_uptime FROM - ( - SELECT MAX(uptime) as uptime FROM metric - UNION - SELECT MAX(uptime) as uptime FROM node_info - ) AS results;" - ); - $max_uptime = $max_uptime[0]->max_uptime ?? 0; - - $latest = Node::where('node_address', strtolower($public_address_node))->whereNotnull('protocol_version')->orderBy('created_at', 'desc')->first(); - if (!$latest) $latest = new Node(); - - $latest_block_height = $latest->block_height ?? null; - $latest_update_responsiveness = $latest->update_responsiveness ?? null; - $latest_peers = $latest->peers ?? null; - - $metric = Metric::where('user_id', $user->id)->first(); - if (!$metric) $metric = new Metric(); - $metric_uptime = $metric->uptime ?? null; - $metric_block_height = $metric->block_height_average ? ($max_block_height - $metric->block_height_average) : null; - $metric_update_responsiveness = $metric->update_responsiveness ?? null; - $metric_peers = $metric->peers ?? null; - - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - if (!$nodeInfo) $nodeInfo = new NodeInfo(); - - $latest_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_uptime = $nodeInfo->uptime ?? null; - $nodeInfo_block_height = $nodeInfo->block_height ?? null; - $nodeInfo_peers = $nodeInfo->peers ?? null; - $nodeInfo_update_responsiveness = $nodeInfo->update_responsiveness ?? null; - - $metric->avg_uptime = $nodeInfo_uptime ?? $metric_uptime; - $metric->avg_block_height_average = $nodeInfo_block_height ?? $metric_block_height; - $metric->avg_update_responsiveness = $nodeInfo_update_responsiveness ?? $metric_update_responsiveness; - $metric->avg_peers = $nodeInfo_peers ?? $metric_peers; - - $metric->max_peers = $max_peers; - $metric->max_update_responsiveness = $max_update_responsiveness; - $metric->max_block_height_average = $max_block_height; - $metric->max_uptime = $max_uptime; - - $metric->peers = $latest_peers ?? $metric_peers; - $metric->update_responsiveness = $latest_update_responsiveness ?? $metric_update_responsiveness; - $metric->block_height_average = $latest_block_height ?? $metric_block_height; - $metric->uptime = $latest_uptime ?? $metric_uptime; - - $monitoringCriteria = MonitoringCriteria::get(); - $nodeInfo = NodeInfo::where('node_address', strtolower($public_address_node))->first(); - $rank = $userAddress->rank; - $delegators = $stake_amount = $self_stake_amount = $is_open_port = 0; - if ($nodeInfo) { - $delegators = $nodeInfo->delegators_count; - $stake_amount = $nodeInfo->total_staked_amount; - $self_stake_amount = $nodeInfo->self_staked_amount; - $is_open_port = $nodeInfo->is_open_port; - } - $mbs = NodeInfo::max('mbs'); - $metric->mbs = $mbs; - $metric->rank = $rank; - $metric->is_open_port = $is_open_port; - $metric->delegators = $delegators; - $metric->self_stake_amount = $self_stake_amount; - $metric['node_status'] = $user->node_status; - $metric['monitoring_criteria'] = $monitoringCriteria; - return $this->successResponse($metric); - } - return $this->successResponse([]); - } -} \ No newline at end of file diff --git a/app/Http/Controllers/Api/V1/NotificationController.php b/app/Http/Controllers/Api/V1/NotificationController.php index fd270335..eea65c61 100644 --- a/app/Http/Controllers/Api/V1/NotificationController.php +++ b/app/Http/Controllers/Api/V1/NotificationController.php @@ -62,15 +62,15 @@ public function dismiss($id) $notificationView = new notificationView(); $notificationView->user_id = $user->id; $notificationView->notification_id = $id; - $notificationView->first_view_at = now(); - $notificationView->dismissed_at = now(); + $notificationView->first_view_at = Carbon::now('UTC'); + $notificationView->dismissed_at = Carbon::now('UTC'); $notificationView->save(); $notification->total_views = $notification->total_views + 1; $notification->save(); } else { if (!$notificationView->dismissed_at) { - $notificationView->dismissed_at = now(); + $notificationView->dismissed_at = Carbon::now('UTC'); $notificationView->save(); } } @@ -90,8 +90,8 @@ public function clickCTA($id) $notificationView = new notificationView(); $notificationView->user_id = $user->id; $notificationView->notification_id = $id; - $notificationView->first_view_at = now(); - $notificationView->cta_click_at = now(); + $notificationView->first_view_at = Carbon::now('UTC'); + $notificationView->cta_click_at = Carbon::now('UTC'); $notificationView->cta_click_count = $notificationView->cta_click_count + 1; $notificationView->save(); @@ -99,7 +99,7 @@ public function clickCTA($id) $notification->save(); } else { if (!$notificationView->cta_click_at) { - $notificationView->cta_click_at = now(); + $notificationView->cta_click_at = Carbon::now('UTC'); } $notificationView->cta_click_count = $notificationView->cta_click_count + 1; $notificationView->save(); @@ -120,7 +120,7 @@ public function updateView($id) $notificationView = new notificationView(); $notificationView->user_id = $user->id; $notificationView->notification_id = $id; - $notificationView->first_view_at = now(); + $notificationView->first_view_at = Carbon::now('UTC'); $notificationView->save(); $notification->total_views = $notification->total_views + 1; @@ -203,7 +203,7 @@ public function createNotification(Request $request) return $this->validateResponse($validator->errors()); } - $now = Carbon::now()->format('Y-m-d'); + $now = Carbon::now('UTC')->format('Y-m-d'); $notification = new Notification(); $startDate = $request->start_date; $endDate = $request->end_date; @@ -295,7 +295,7 @@ public function updateNotification(Request $request, $id) return $this->validateResponse($validator->errors()); } - $now = Carbon::now()->format('Y-m-d'); + $now = Carbon::now('UTC')->format('Y-m-d'); $notification = Notification::where('id', $id)->first(); if (!$notification) { return $this->errorResponse('Not found notification', Response::HTTP_BAD_REQUEST); @@ -364,7 +364,6 @@ public function getNotificationDetail($id) if (!$notification) { return $this->errorResponse('Not found notification', Response::HTTP_BAD_REQUEST); } - return $this->successResponse($notification); } } diff --git a/app/Http/Controllers/Api/V1/PerkController.php b/app/Http/Controllers/Api/V1/PerkController.php index e3986122..db4a0f4a 100644 --- a/app/Http/Controllers/Api/V1/PerkController.php +++ b/app/Http/Controllers/Api/V1/PerkController.php @@ -9,6 +9,8 @@ use App\Models\Perk; use App\Models\PerkResult; +use App\Jobs\PerkNotification; + use Carbon\Carbon; use Illuminate\Http\Request; @@ -25,29 +27,37 @@ public function createPerk(Request $request) { 'title' => 'required|string|max:70', 'content' => 'required', 'action_link' => 'required|url', - 'image' => 'required|mimes:jpeg,jpg,png,gif|max:100000', + // 'image' => 'required|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:200000', + 'image' => 'required|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:2048', 'start_date' => 'required|nullable|date_format:Y-m-d', 'end_date' => 'required|nullable|date_format:Y-m-d|after_or_equal:today', 'start_time' => 'required|nullable|date_format:H:i:s', 'end_time' => 'required|nullable|date_format:H:i:s', 'setting' => 'required|in:0,1', + 'timezone' => 'required' ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } $user = auth()->user(); - $now = Carbon::now()->format('Y-m-d'); - $perk = new Perk(); - $startDate = $request->start_date; - $endDate = $request->end_date; + + $timezone = $request->timezone; + + $startTime = $request->start_date . ' ' . $request->start_time; + $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone); + $startTimeCarbon->setTimezone('UTC'); + + $endTime = $request->end_date . ' ' . $request->end_time; + $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone); + $endTimeCarbon->setTimezone('UTC'); + $setting = $request->setting; - $visibility = 'hidden'; - $status = 'inactive'; - if ($startDate && $endDate && $startDate > $endDate) { + if ($startTimeCarbon->gte($endTimeCarbon)) { return $this->errorResponse('End date must greater than start date', Response::HTTP_BAD_REQUEST); } + $perk = new Perk(); $perk->user_id = $user->id; $perk->title = $request->title; $perk->content = $request->content; @@ -56,16 +66,16 @@ public function createPerk(Request $request) { $perk->end_date = $request->end_date; $perk->start_time = $request->start_time; $perk->end_time = $request->end_time; - $perk->setting = $request->setting; + $perk->setting = $setting; + $perk->timezone = $timezone; + $perk->time_begin = $startTimeCarbon; + $perk->time_end = $endTimeCarbon; $filenameWithExt = $request->file('image')->getClientOriginalName(); - //Get just filename $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); - // Get just ext $extension = $request->file('image')->getClientOriginalExtension(); - $filenamehash = md5(Str::random(10) . '_' . (string)time()); - // Filename to store + $filenamehash = md5(Str::random(10) . '_' . (string) time()); $fileNameToStore = $filenamehash . '.' . $extension; // S3 file upload @@ -77,39 +87,30 @@ public function createPerk(Request $request) { 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); - $s3result = $S3->putObject([ 'Bucket' => getenv('AWS_BUCKET'), 'Key' => 'client_uploads/' . $fileNameToStore, 'SourceFile' => $request->file('image') ]); - // $ObjectURL = 'https://'.getenv('AWS_BUCKET').'.s3.amazonaws.com/client_uploads/'.$fileNameToStore; $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL') . '/not-found'; $perk->image = $ObjectURL; // check visibility and status + $now = Carbon::now('UTC'); + $visibility = 'hidden'; + $status = 'inactive'; if ($setting == 1) { - if ($startDate && $endDate && ($now >= $startDate && $now <= $endDate)) { - $visibility = 'visible'; - $status = 'active'; - } - if (!$startDate && !$endDate) { - $visibility = 'visible'; - $status = 'active'; - } - if ($endDate && $endDate >= $now) { - $visibility = 'visible'; - $status = 'active'; - } - if ($startDate && $startDate > $now) { - $visibility = 'hidden'; - $status = 'waiting'; - } - if ($startDate && $startDate <= $now) { - $visibility = 'visible'; - $status = 'active'; - } + if ($now >= $startTimeCarbon && $now <= $endTimeCarbon) { + $visibility = 'visible'; + $status = 'active'; + } else if ($now < $startTimeCarbon) { + $visibility = 'hidden'; + $status = 'waiting'; + } else if ($now > $endTimeCarbon) { + $visibility = 'hidden'; + $status = 'expired'; + } } else { $visibility = 'hidden'; $status = 'inactive'; @@ -117,30 +118,14 @@ public function createPerk(Request $request) { $perk->visibility = $visibility; $perk->status = $status; $perk->save(); - return $this->successResponse($perk); - } - public function getPerksAdmin(Request $request) - { - $limit = $request->limit ?? 50; - $sort_key = $request->sort_key ?? 'end_date'; - $sort_direction = $request->sort_direction ?? 'desc'; - if (isset($request->setting)) { - $perks = Perk::where('setting', $request->setting)->orderBy($sort_key, $sort_direction)->paginate($limit); - } else { - $perks = Perk::orderBy($sort_key, $sort_direction)->paginate($limit); - } - return $this->successResponse($perks); - } + if ($perk->visibility == 'visible' && $perk->status == 'active') { + PerkNotification::dispatch($perk)->onQueue('default_long'); + } - public function getPerkDetailAdmin($id) - { - $perk = Perk::where('id', $id)->first(); - if (!$perk) { - return $this->errorResponse('Not found perk', Response::HTTP_BAD_REQUEST); - } return $this->successResponse($perk); } + public function updatePerk(Request $request, $id) { $data = $request->all(); @@ -148,32 +133,43 @@ public function updatePerk(Request $request, $id) 'title' => 'nullable|string|max:70', 'content' => 'nullable', 'action_link' => 'nullable|url', - 'image' => 'nullable|mimes:jpeg,jpg,png,gif|max:100000', + // 'image' => 'nullable|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:200000', + 'image' => 'nullable|mimes:pdf,jpeg,jpg,png,gif,txt,rtf|max:2048', 'start_date' => 'required|nullable', 'end_date' => 'required|nullable', 'start_time' => 'required|nullable|date_format:H:i:s', 'end_time' => 'required|nullable|date_format:H:i:s', 'setting' => 'nullable|in:0,1', + 'timezone' => 'required' ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } $user = auth()->user(); - $now = Carbon::now()->format('Y-m-d'); + $perk = Perk::where('id', $id)->first(); if (!$perk) { return $this->errorResponse('Not found perk', Response::HTTP_BAD_REQUEST); } - $startDate = array_key_exists('start_date', $data) ? $request->start_date : $perk->start_date; - $endDate = array_key_exists('end_date', $data) ? $request->end_date : $perk->end_date; - $setting = isset($request->setting) ? $request->setting : $perk->setting; - $visibility = 'hidden'; - $status = 'inactive'; - if ($startDate && $endDate && $startDate > $endDate) { + $originalStatus = $perk->status; + $originalVisibility = $perk->visibility; + + $timezone = $request->timezone; + + $startTime = $request->start_date . ' ' . $request->start_time; + $startTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $startTime, $timezone); + $startTimeCarbon->setTimezone('UTC'); + + $endTime = $request->end_date . ' ' . $request->end_time; + $endTimeCarbon = Carbon::createFromFormat('Y-m-d H:i:s', $endTime, $timezone); + $endTimeCarbon->setTimezone('UTC'); + + if ($startTimeCarbon->gte($endTimeCarbon)) { return $this->errorResponse('End date must greater than start date', Response::HTTP_BAD_REQUEST); } + if ($request->title) { $perk->title = $request->title; } @@ -185,10 +181,14 @@ public function updatePerk(Request $request, $id) $perk->end_date = $request->end_date; $perk->start_time = $request->start_time; $perk->end_time = $request->end_time; - + $perk->timezone = $timezone; + $perk->time_begin = $startTimeCarbon; + $perk->time_end = $endTimeCarbon; + if (isset($request->setting)) { $perk->setting = $request->setting; } + if ($request->hasFile('image')) { $extension = $request->file('image')->getClientOriginalExtension(); $filenamehash = md5(Str::random(10) . '_' . (string)time()); @@ -216,31 +216,21 @@ public function updatePerk(Request $request, $id) } // check visibility and status - if ($setting == 1) { - if ($startDate && $endDate && ($now >= $startDate && $now <= $endDate)) { - $visibility = 'visible'; - $status = 'active'; - } - if (!$startDate && !$endDate) { - $visibility = 'visible'; - $status = 'active'; - } - if ($endDate && $endDate >= $now) { - $visibility = 'visible'; - $status = 'active'; - } - if ($endDate && $endDate < $now) { - $visibility = 'hidden'; - $status = 'expired'; - } - if ($startDate && $startDate > $now) { - $visibility = 'hidden'; - $status = 'waiting'; - } - if ($startDate && $startDate <= $now) { - $visibility = 'visible'; - $status = 'active'; - } + $visibility = 'hidden'; + $status = 'inactive'; + $setting = $perk->setting; + $now = Carbon::now('UTC'); + if ($setting == 1) { + if ($now >= $startTimeCarbon && $now <= $endTimeCarbon) { + $visibility = 'visible'; + $status = 'active'; + } else if ($now < $startTimeCarbon) { + $visibility = 'hidden'; + $status = 'waiting'; + } else if ($now > $endTimeCarbon) { + $visibility = 'hidden'; + $status = 'expired'; + } } else { $visibility = 'hidden'; $status = 'inactive'; @@ -248,6 +238,37 @@ public function updatePerk(Request $request, $id) $perk->visibility = $visibility; $perk->status = $status; $perk->save(); + + if ( + $perk->visibility == 'visible' && + $perk->status == 'active' && + ($perk->visibility != $originalVisibility || $perk->status != $originalStatus) + ) { + PerkNotification::dispatch($perk)->onQueue('default_long'); + } + + return $this->successResponse($perk); + } + + public function getPerksAdmin(Request $request) + { + $limit = $request->limit ?? 50; + $sort_key = $request->sort_key ?? 'end_date'; + $sort_direction = $request->sort_direction ?? 'desc'; + if (isset($request->setting)) { + $perks = Perk::where('setting', $request->setting)->orderBy($sort_key, $sort_direction)->paginate($limit); + } else { + $perks = Perk::orderBy($sort_key, $sort_direction)->paginate($limit); + } + return $this->successResponse($perks); + } + + public function getPerkDetailAdmin($id) + { + $perk = Perk::where('id', $id)->first(); + if (!$perk) { + return $this->errorResponse('Not found perk', Response::HTTP_BAD_REQUEST); + } return $this->successResponse($perk); } diff --git a/app/Http/Controllers/Api/V1/UserController.php b/app/Http/Controllers/Api/V1/UserController.php index 75a968ee..af98a02b 100644 --- a/app/Http/Controllers/Api/V1/UserController.php +++ b/app/Http/Controllers/Api/V1/UserController.php @@ -9,7 +9,6 @@ use App\Http\Requests\Api\AddOwnerNodeRequest; use App\Http\Requests\Api\ChangeEmailRequest; -use App\Http\Requests\Api\ChangePasswordRequest; use App\Http\Requests\Api\ResendEmailRequest; use App\Http\Requests\Api\SubmitKYCRequest; use App\Http\Requests\Api\SubmitPublicAddressRequest; @@ -40,6 +39,10 @@ use App\Models\VerifyUser; use App\Models\Vote; use App\Models\VoteResult; +use App\Models\Setting; +use App\Models\AllNodeData2; +use App\Models\Upgrade; +use App\Models\UpgradeUser; use App\Repositories\OwnerNodeRepository; use App\Repositories\ProfileRepository; @@ -77,13 +80,13 @@ class UserController extends Controller private $verifyUserRepo; private $profileRepo; private $ownerNodeRepo; - public $failed_verification_response; + public $failed_verification_response; public function __construct( - UserRepository $userRepo, + UserRepository $userRepo, VerifyUserRepository $verifyUserRepo, - ProfileRepository $profileRepo, - OwnerNodeRepository $ownerNodeRepo + ProfileRepository $profileRepo, + OwnerNodeRepository $ownerNodeRepo ) { $this->userRepo = $userRepo; $this->verifyUserRepo = $verifyUserRepo; @@ -92,39 +95,390 @@ public function __construct( $this->failed_verification_response = 'Failed verification'; } - public function getMemberCountInfo() { - $data = [ - 'total' => 0, - 'verified' => 0, + public function getUserDashboard() { + $user = auth()->user(); + $user_id = $user->id ?? 0; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'node_rank' => 0, + 'node_rank_total' => 0, + 'total_stake' => 0, + 'total_self_stake' => 0, + 'total_delegators' => 0, + 'uptime' => 0, + 'eras_active' => 0, + 'eras_since_bad_mark' => $current_era_id, + 'total_bad_marks' => 0, + 'update_responsiveness' => 100, + 'peers' => 0, + 'total_members' => 0, + 'verified_members' => 0, + 'association_members' => Helper::getActiveMembers(), + 'ranking' => [] ]; - $data['total'] = User::count(); - $data['verified'] = User::join('profile', 'profile.user_id', '=', 'users.id') - ->where('profile.status', 'approved') - ->whereNotNull('users.public_address_node') - ->get() - ->count(); - return $this->successResponse($data); + // get verified members count + $verified_members = DB::select(" + SELECT count(a.id) as totalCount + FROM users AS a + JOIN profile AS b + ON a.id = b.user_id + WHERE b.status = 'approved' + "); + $return['verified_members'] = $verified_members[0]->totalCount ?? 0; + + // get total members count + $total_members = DB::select(" + SELECT count(id) as totalCount + FROM users + WHERE role = 'member' + "); + $return['total_members'] = $total_members[0]->totalCount ?? 0; + + $rankingData = Helper::getRanking($current_era_id); + + $return['ranking'] = $rankingData['ranking']; + $return['node_rank_total'] = $rankingData['node_rank_total']; + + // parse node addresses + $addresses = DB::select(" + SELECT + a.public_key, + a.uptime, + a.bid_delegators_count AS delegators, + a.port8888_peers AS peers, + a.bid_self_staked_amount, a.bid_total_staked_amount + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + // for each address belonging to a user + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + $return['total_bad_marks'] += $total_bad_marks; + if ($eras_since_bad_mark < $return['eras_since_bad_mark']) { + $return['eras_since_bad_mark'] = $eras_since_bad_mark; + } + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + if ($current_era_id - $min_era_id > $return['eras_active']) { + $return['eras_active'] = $current_era_id - $min_era_id; + } + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + if ( + array_key_exists($p, $return['ranking']) && + ($return['node_rank'] == 0 || $return['ranking'][$p] < $return['node_rank']) + ) { + $return['node_rank'] = $return['ranking'][$p]; + } + + $return['total_stake'] += (int) ($address->bid_total_staked_amount ?? 0); + $return['total_self_stake'] += (int) ($address->bid_self_staked_amount ?? 0); + $return['total_delegators'] += (int) ($address->delegators ?? 0); + $return['peers'] += (int) ($address->peers ?? 0); + $return['uptime'] += $historical_performance; + } + + $addresses_count = count($addresses); + if (!$addresses_count) $addresses_count = 1; + + $return['uptime'] = round((float) ($return['uptime'] / $addresses_count), 2); + + unset($return['ranking']); + + return $this->successResponse($return); } - // Get Verified Members - public function getVerifiedMembers(Request $request) { - $data = []; - $limit = $request->limit ?? 50; + public function getMembershipPage() { + $user = auth()->user()->load(['profile']); + $user_id = $user->id ?? 0; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'node_status' => $user->node_status ?? '', + 'kyc_status' => 'Not Verified', + 'uptime' => [], + 'avg_uptime' => 0, + 'total_eras' => 0, + 'eras_since_bad_mark' => $current_era_id, + 'total_bad_marks' => 0, + 'update_responsiveness' => 100, + 'peers' => 0 + ]; + if (isset($user->profile) && $user->profile->status == 'approved') { + $return['kyc_status'] = 'Verified'; + } + + $addresses = DB::select(" + SELECT + a.public_key, a.uptime, + a.port8888_peers AS peers, + a.bid_inactive, a.in_current_era, + c.kyc_verified_at AS kyc_status + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + LEFT JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + $return['total_bad_marks'] += $total_bad_marks; + if ($eras_since_bad_mark < $return['eras_since_bad_mark']) { + $return['eras_since_bad_mark'] = $eras_since_bad_mark; + } + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + if ($current_era_id - $min_era_id > $return['total_eras']) { + $return['total_eras'] = $current_era_id - $min_era_id; + } + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + $return['peers'] += (int) ($address->peers ?? 0); + $return['uptime'][$p] = $historical_performance; + $return['avg_uptime'] += $historical_performance; + } + + $addresses_count = count($addresses); + $addresses_count = $addresses_count ? $addresses_count : 1; + $return['avg_uptime'] = round((float) ($return['avg_uptime'] / $addresses_count), 2); + + return $this->successResponse($return); + } + + public function getNodesPage() { $user = auth()->user(); + $user_id = $user->id ?? 0; - $data = User::select([ - 'users.id', - 'users.pseudonym', - 'users.public_address_node', - 'users.node_status', - 'profile.extra_status', - ]) - ->join('profile', 'profile.user_id', '=', 'users.id') - ->where('profile.status', 'approved') - ->whereNotNull('users.public_address_node') - ->paginate($limit); - return $this->successResponse($data); + $nodeHelper = new NodeHelper(); + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $return = [ + 'mbs' => 0, + 'ranking' => [], + 'addresses' => [] + ]; + + $rankingData = Helper::getRanking($current_era_id); + + $return['ranking'] = $rankingData['ranking']; + + $addresses = DB::select(" + SELECT + a.public_key, a.bid_delegators_count, + a.bid_total_staked_amount, a.bid_self_staked_amount, + a.uptime, a.bid_inactive, a.in_current_era, + a.port8888_peers AS peers + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + // fetch MBS + $mbs = DB::select(" + SELECT mbs + FROM mbs + WHERE era_id = $current_era_id + "); + $mbs = $mbs[0]->mbs ?? 0; + + // for each member's node address + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + $baseObject->mbs = $mbs; + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + $total_eras = $current_era_id - $min_era_id; + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + $one_day_ago = Carbon::now('UTC')->subHours(24); + $temp = DB::select(" + SELECT bid_self_staked_amount + FROM all_node_data2 + WHERE public_key = '$p' + AND created_at < '$one_day_ago' + ORDER BY era_id DESC + LIMIT 1 + "); + if (!$temp) $temp = []; + $daily_earning = (float) $address->bid_self_staked_amount - (float) ($temp[0]->bid_self_staked_amount ?? 0); + $daily_earning = $daily_earning < 0 ? 0 : $daily_earning; + + $earning_day = $nodeHelper->getValidatorRewards($p, 'day'); + $earning_week = $nodeHelper->getValidatorRewards($p, 'week'); + $earning_month = $nodeHelper->getValidatorRewards($p, 'month'); + $earning_year = $nodeHelper->getValidatorRewards($p, 'year'); + + $return['addresses'][$p] = [ + 'stake_amount' => $address->bid_total_staked_amount, + 'delegators' => $address->bid_delegators_count, + 'uptime' => $historical_performance, + 'update_responsiveness' => 100, + 'peers' => (int) ($address->peers ?? 0), + 'daily_earning' => $daily_earning, + 'total_eras' => $total_eras, + 'eras_since_bad_mark' => $eras_since_bad_mark, + 'total_bad_marks' => $total_bad_marks, + 'validator_rewards' => [ + 'day' => $earning_day, + 'week' => $earning_week, + 'month' => $earning_month, + 'year' => $earning_year + ] + ]; + } + + $return['mbs'] = $mbs; + + return $this->successResponse($return); + } + + public function getMyEras() { + $user = auth()->user(); + $user_id = $user->id ?? 0; + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + // define return object + $return = [ + 'addresses' => [], + 'eras' => [] + ]; + + // get addresses data + $addresses = DB::select(" + SELECT + a.public_key, a.uptime + FROM all_node_data2 AS a + JOIN user_addresses AS b + ON a.public_key = b.public_address_node + JOIN users AS c + ON b.user_id = c.id + WHERE a.era_id = $current_era_id + AND b.user_id = $user_id + "); + if (!$addresses) $addresses = []; + + $uptime_calc_size = isset($settings['uptime_calc_size']) ? (int) $settings['uptime_calc_size'] : 1; + + // for each member's node address + foreach ($addresses as $address) { + $p = $address->public_key ?? ''; + + $baseObject = new \stdClass(); + $baseObject->uptime = (float) ($address->uptime ?? 0); + + $badMarkValues = Helper::calculateVariables('bad_marks_info', $p, $settings); + $total_bad_marks = (int) ($badMarkValues['total_bad_marks'] ?? 0); + $eras_since_bad_mark = (int) ($badMarkValues['eras_since_bad_mark'] ?? $current_era_id); + + $min_era_id = Helper::calculateVariables('min_era', $p, $settings); + $eras_active = $current_era_id - $min_era_id; + + $historical_performance = Helper::calculateUptime($baseObject, $p, $settings); + + $return['addresses'][$p] = [ + 'uptime' => $historical_performance, + 'eras_active' => $eras_active, + 'eras_since_bad_mark' => $eras_since_bad_mark, + 'total_bad_marks' => $total_bad_marks + ]; + } + + // get eras table data + $era_minus_360 = $current_era_id - $uptime_calc_size; + if ($era_minus_360 < 1) { + $era_minus_360 = 1; + } + + $eras = DB::select(" + SELECT + a.public_key, a.era_id, a.created_at, + a.in_current_era, a.in_auction, + a.bid_inactive, a.uptime + FROM all_node_data2 AS a + JOIN user_addresses + ON a.public_key = user_addresses.public_address_node + JOIN users + ON user_addresses.user_id = users.id + WHERE users.id = $user_id + AND era_id > $era_minus_360 + ORDER BY a.era_id DESC + "); + if (!$eras) $eras = []; + + $sorted_eras = []; + + // for each node address's era + foreach ($eras as $era) { + $era_id = $era->era_id ?? 0; + $era_start_time = $era->created_at ?? ''; + $public_key = $era->public_key; + + if (!isset($sorted_eras[$era_id])) { + $sorted_eras[$era_id] = [ + 'era_start_time' => $era_start_time, + 'addresses' => [] + ]; + } + + $sorted_eras[$era_id]['addresses'][$public_key] = [ + 'in_pool' => $era->in_auction, + 'rewards' => $era->uptime ?? 0 + ]; + } + + $return['eras'] = $sorted_eras; + + return $this->successResponse($return); } // Shuftipro Webhook @@ -152,12 +506,12 @@ public function updateShuftiproStatus() { if ($user) { $user_id = $user->id; $profile = Profile::where('user_id', $user_id)->first(); - + if ($profile) { $profile->status = null; $profile->save(); } - + Shuftipro::where('user_id', $user->id)->delete(); ShuftiproTemp::where('user_id', $user->id)->delete(); } @@ -167,8 +521,9 @@ public function updateShuftiproStatus() { } else { $events = [ 'verification.accepted', - 'verification.declined', + 'verification.declined' ]; + if (isset($data['event']) && in_array($data['event'], $events)) { $user = User::find($recordTemp->user_id); @@ -194,11 +549,15 @@ public function updateShuftiproStatus() { public function changeEmail(ChangeEmailRequest $request) { + return $this->successResponse( + ['message' => __('Email changes are disabled')] + ); + try { DB::beginTransaction(); $user = auth()->user(); $user->update(['email' => $request->email, 'email_verified_at' => null]); - $code = generateString(7); + $code = Helper::generateString(7); $userVerify = $this->verifyUserRepo->updateOrCreate( [ 'email' => $request->email, @@ -206,9 +565,10 @@ public function changeEmail(ChangeEmailRequest $request) ], [ 'code' => $code, - 'created_at' => now() + 'created_at' => Carbon::now('UTC') ] ); + if ($userVerify) Mail::to($request->email)->send(new UserVerifyMail($code)); DB::commit(); return $this->metaSuccess(); @@ -216,29 +576,68 @@ public function changeEmail(ChangeEmailRequest $request) return $this->errorResponse(__('api.error.internal_error'), Response::HTTP_INTERNAL_SERVER_ERROR); } } - - public function changePassword(ChangePasswordRequest $request) - { - $user = auth()->user(); - if (Hash::check($request->new_password, $user->password)) - return $this->errorResponse(__('api.error.not_same_current_password'), Response::HTTP_BAD_REQUEST); - $newPassword = bcrypt($request->new_password); - $user->update(['password' => $newPassword]); - return $this->metaSuccess(); - } public function getProfile() { $user = auth()->user()->load(['profile', 'pagePermissions', 'permissions', 'shuftipro', 'shuftiproTemp']); Helper::getAccountInfoStandard($user); - $user->metric = Helper::getNodeInfo($user); + $user->globalSettings = Helper::getSettings(); + $lastUpgrade = Upgrade::orderBy('id', 'desc')->limit(1)->first(); + $now = Carbon::now('UTC'); + if ($lastUpgrade) { + $lastUpgrade->time_passed = !!($now >= $lastUpgrade->activation_datetime); + $user->lastUpgrade = $lastUpgrade; + $reply = UpgradeUser::where('upgrade_id', $lastUpgrade->id) + ->where('user_id', $user->id) + ->first(); + if ($reply) { + $user->lastUpgradeReply = $reply; + } + } + $ownReply = UpgradeUser::where('user_id', $user->id) + ->orderBy('created_at', 'desc') + ->orderBy('upgrade_id', 'desc') + ->limit(1) + ->first(); + if ($ownReply) { + $lastOwnUpgrade = Upgrade::find($ownReply->upgrade_id); + if ($lastOwnUpgrade) { + $user->lastOwnUpgrade = $lastOwnUpgrade; + $user->lastOwnUpgradeReply = $ownReply; + } + } return $this->successResponse($user); } - public function logout() - { - auth()->user()->token()->revoke(); - return $this->metaSuccess(); + public function completeUpgrade(Request $request) { + $user_id = auth()->user()->id; + $validator = Validator::make($request->all(), [ + 'upgrade_id' => 'required|integer' + ]); + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + $upgrade_id = (int) $request->upgrade_id; + + $upgrade = Upgrade::find($upgrade_id); + $now = Carbon::now('UTC'); + if (!$upgrade || $upgrade->activation_datetime <= $now) { + return $this->errorResponse(__('The Upgrade is invalid'), Response::HTTP_BAD_REQUEST); + } + + $upgradeReply = UpgradeUser::where('upgrade_id', $upgrade_id) + ->where('user_id', $user_id) + ->first(); + if ($upgradeReply) { + return $this->errorResponse(__('The Upgrade is invalid'), Response::HTTP_BAD_REQUEST); + } + + $upgradeReply = new UpgradeUser; + $upgradeReply->upgrade_id = $upgrade_id; + $upgradeReply->user_id = $user_id; + $upgradeReply->save(); + + return $this->metaSuccess(); } public function uploadLetter(Request $request) @@ -246,7 +645,7 @@ public function uploadLetter(Request $request) try { // Validator $validator = Validator::make($request->all(), [ - 'file' => 'required|mimes:pdf,docx,doc,txt,rtf|max:20000', + 'file' => 'required|mimes:pdf,jpeg,jpg,png,txt,rtf|max:2048' ]); if ($validator->fails()) { @@ -345,41 +744,71 @@ public function submitPublicAddress(SubmitPublicAddressRequest $request) $user = auth()->user(); $address = strtolower($request->public_address); $public_address = strtolower($address); - $public_address_temp = (new ChecksumValidator())->do($address); + if (!$public_address_temp) { return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); } - + $correct_checksum = (int) (new ChecksumValidator($public_address_temp))->do(); + if (!$correct_checksum) { - return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID is invalid'), + Response::HTTP_BAD_REQUEST + ); } - + // User Check $tempUser = User::where('public_address_node', $public_address)->first(); - if ($tempUser && $tempUser->id != $user->id && $tempUser->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + + if ( + $tempUser && + $tempUser->id != $user->id && + $tempUser->node_verified_at + ) { + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // User Address Check $tempUserAddress = UserAddress::where('public_address_node', $public_address)->first(); - if ($tempUserAddress && $tempUserAddress->user_id != $user->id && $tempUserAddress->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + + if ( + $tempUserAddress && + $tempUserAddress->user_id != $user->id && + $tempUserAddress->node_verified_at + ) { + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // Pool Check - $nodeHelper = new NodeHelper(); - $addresses = $nodeHelper->getValidAddresses(); - if (!in_array($public_address, $addresses)) { - return $this->errorResponse(__('The validator ID specified could not be found in the Casper validator pool'), Response::HTTP_BAD_REQUEST); + if (!Helper::checkAddressValidity($public_address)) { + return $this->errorResponse( + __('The validator ID specified could not be found in the Casper validator pool'), + Response::HTTP_BAD_REQUEST + ); } // Remove Other User's Same Address - UserAddress::where('public_address_node', $public_address)->where('user_id', '!=', $user->id)->whereNull('node_verified_at')->delete(); - User::where('public_address_node', $public_address)->where('id', '!=', $user->id)->whereNull('node_verified_at')->update(['public_address_node' => null]); + UserAddress::where('public_address_node', $public_address) + ->where('user_id', '!=', $user->id) + ->whereNull('node_verified_at') + ->delete(); + User::where('public_address_node', $public_address) + ->where('id', '!=', $user->id) + ->whereNull('node_verified_at') + ->update(['public_address_node' => null]); - if (!$tempUserAddress || $tempUserAddress->user_id != $user->id) { + if ( + !$tempUserAddress || + $tempUserAddress->user_id != $user->id + ) { $userAddress = new UserAddress; $userAddress->user_id = $user->id; $userAddress->public_address_node = $public_address; @@ -397,36 +826,47 @@ public function submitPublicAddress(SubmitPublicAddressRequest $request) public function checkValidatorAddress(SubmitPublicAddressRequest $request) { $address = strtolower($request->public_address); - $public_address_temp = (new ChecksumValidator())->do($address); $public_address = strtolower($address); if (!$public_address_temp) { - return $this->successResponse(['message' => __('The validator ID is invalid')]); + return $this->successResponse( + ['message' => __('The validator ID is invalid')] + ); } $correct_checksum = (int) (new ChecksumValidator($public_address_temp))->do(); + if (!$correct_checksum) { - return $this->successResponse(['message' => __('The validator ID is invalid')]); + return $this->successResponse( + ['message' => __('The validator ID is invalid')] + ); } // User Check $tempUser = User::where('public_address_node', $public_address)->first(); + if ($tempUser && $tempUser->node_verified_at) { - return $this->successResponse(['message' => __('The validator ID you specified is already associated with an Association member')]); + return $this->successResponse( + ['message' => __('The validator ID you specified is already associated with an Association member')] + ); } // User Address Check $tempUserAddress = UserAddress::where('public_address_node', $public_address)->first(); + if ($tempUserAddress && $tempUserAddress->node_verified_at) { - return $this->successResponse(['message' => __('The validator ID you specified is already associated with an Association member')]); + return $this->successResponse( + ['message' => __('The validator ID you specified is already associated with an Association member')] + ); } - $nodeHelper = new NodeHelper(); - $addresses = $nodeHelper->getValidAddresses(); - if (!in_array($public_address, $addresses)) { - return $this->successResponse(['message' => __('The validator ID specified could not be found in the Casper validator pool')]); - } + if (!Helper::checkAddressValidity($public_address)) { + return $this->successResponse( + ['message' => __('The validator ID specified could not be found in the Casper validator pool')] + ); + } + return $this->metaSuccess(); } @@ -434,34 +874,50 @@ public function checkPublicAddress(SubmitPublicAddressRequest $request) { $address = strtolower($request->public_address); $public_address = strtolower($address); - $public_address_temp = (new ChecksumValidator())->do($address); + if (!$public_address_temp) { - return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID is invalid'), + Response::HTTP_BAD_REQUEST + ); } $correct_checksum = (int) (new ChecksumValidator($public_address_temp))->do(); + if (!$correct_checksum) { - return $this->errorResponse(__('The validator ID is invalid'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID is invalid'), + Response::HTTP_BAD_REQUEST + ); } // User Check $tempUser = User::where('public_address_node', $public_address)->first(); + if ($tempUser && $tempUser->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // User Address Check $tempUserAddress = UserAddress::where('public_address_node', $public_address)->first(); + if ($tempUserAddress && $tempUserAddress->node_verified_at) { - return $this->errorResponse(__('The validator ID you specified is already associated with an Association member'), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __('The validator ID you specified is already associated with an Association member'), + Response::HTTP_BAD_REQUEST + ); } // Pool Check - $nodeHelper = new NodeHelper(); - $addresses = $nodeHelper->getValidAddresses(); - if (!in_array($public_address, $addresses)) { - return $this->errorResponse(__('The validator ID specified could not be found in the Casper validator pool'), Response::HTTP_BAD_REQUEST); + if (!Helper::checkAddressValidity($public_address)) { + return $this->errorResponse( + __('The validator ID specified could not be found in the Casper validator pool'), + Response::HTTP_BAD_REQUEST + ); } return $this->metaSuccess(); @@ -469,11 +925,12 @@ public function checkPublicAddress(SubmitPublicAddressRequest $request) public function getMessageContent() { - $user = auth()->user(); + $user = auth()->user(); $timestamp = date('d/m/Y'); - $message = "Please use the Casper Signature python tool to sign this message! " . $timestamp; + $message = "Please use the Casper Signature python tool to sign this message! " . $timestamp; $user->update(['message_content' => $message]); - $filename = 'message.txt'; + $filename = 'message.txt'; + return response()->streamDownload(function () use ($message) { echo $message; }, $filename); @@ -482,24 +939,37 @@ public function getMessageContent() public function verifyFileCasperSigner2(VerifyFileCasperSignerRequest $request) { try { - $casperSigVerify = new CasperSigVerify(); - $user = auth()->user(); - $message = $user->message_content; + $casperSigVerify = new CasperSigVerify(); + $user = auth()->user(); + $message = $user->message_content; $public_validator_key = strtolower($request->address); - $userRecord = User::where('public_address_node', $public_validator_key)->first(); - $userAddress = UserAddress::where('public_address_node', $public_validator_key)->first(); + $userRecord = User::where( + 'public_address_node', + $public_validator_key + )->first(); + + $userAddress = UserAddress::where( + 'public_address_node', + $public_validator_key + )->first(); if ($userRecord && $userRecord->node_verified_at) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } if ($userAddress && $userAddress->node_verified_at) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } - $file = $request->file; - $name = $file->getClientOriginalName(); + $file = $request->file; + $name = $file->getClientOriginalName(); $hexstring = $file->get(); if ($hexstring && $name == 'signature') { @@ -513,32 +983,47 @@ public function verifyFileCasperSigner2(VerifyFileCasperSignerRequest $request) $filenamehash = md5(Str::random(10) . '_' . (string)time()); $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'signatures/' . $filenamehash, - 'SourceFile' => $request->file('file') + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'signatures/' . $filenamehash, + 'SourceFile' => $request->file('file') ]); $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL').'/not-found'; // Remove Other User's Same Address - UserAddress::where('public_address_node', $public_validator_key)->where('user_id', '!=', $user->id)->whereNull('node_verified_at')->delete(); - User::where('public_address_node', $public_validator_key)->where('id', '!=', $user->id)->whereNull('node_verified_at')->update(['public_address_node' => null]); - - $userAddress = UserAddress::where('public_address_node', $public_validator_key)->where('user_id', $user->id)->first(); - if (!$userAddress) $userAddress = new UserAddress; - $userAddress->user_id = $user->id; + UserAddress::where('public_address_node', $public_validator_key) + ->where('user_id', '!=', $user->id) + ->whereNull('node_verified_at') + ->delete(); + + User::where('public_address_node', $public_validator_key) + ->where('id', '!=', $user->id) + ->whereNull('node_verified_at') + ->update(['public_address_node' => null]); + + $userAddress = UserAddress::where( + 'public_address_node', + $public_validator_key) + ->where('user_id', $user->id) + ->first(); + + if (!$userAddress) { + $userAddress = new UserAddress; + } + + $userAddress->user_id = $user->id; $userAddress->public_address_node = $public_validator_key; - $userAddress->signed_file = $ObjectURL; - $userAddress->node_verified_at = now(); + $userAddress->signed_file = $ObjectURL; + $userAddress->node_verified_at = Carbon::now('UTC'); $userAddress->save(); $emailerData = EmailerHelper::getEmailerData(); @@ -552,32 +1037,50 @@ public function verifyFileCasperSigner2(VerifyFileCasperSignerRequest $request) ); return $this->metaSuccess(); } else { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } } - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } catch (\Exception $ex) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function verifyFileCasperSigner(VerifyFileCasperSignerRequest $request) { try { - $casperSigVerify = new CasperSigVerify(); - $user = auth()->user(); - $message = $user->message_content; + $casperSigVerify = new CasperSigVerify(); + $user = auth()->user(); + $message = $user->message_content; $public_validator_key = strtolower($request->address); - $userRecord = User::where('id', $user->id)->where('public_address_node', $public_validator_key)->first(); - $userAddress = UserAddress::where('user_id', $user->id)->where('public_address_node', $public_validator_key)->first(); + $userRecord = User::where('id', $user->id) + ->where('public_address_node', $public_validator_key) + ->first(); + + $userAddress = UserAddress::where('user_id', $user->id) + ->where('public_address_node', $public_validator_key) + ->first(); + if (!$userRecord || !$userAddress) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } - $file = $request->file; - - $name = $file->getClientOriginalName(); + $file = $request->file; + $name = $file->getClientOriginalName(); $hexstring = $file->get(); if ($hexstring && $name == 'signature') { @@ -586,130 +1089,119 @@ public function verifyFileCasperSigner(VerifyFileCasperSignerRequest $request) $public_validator_key, $message ); + if ($verified) { $filenamehash = md5(Str::random(10) . '_' . (string)time()); // S3 file upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'signatures/' . $filenamehash, - 'SourceFile' => $request->file('file') + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'signatures/' . $filenamehash, + 'SourceFile' => $request->file('file') ]); $ObjectURL = $s3result['ObjectURL'] ?? getenv('SITE_URL').'/not-found'; - - $user->signed_file = $ObjectURL; - $user->has_verified_address = 1; - $user->node_verified_at = now(); + + $user->signed_file = $ObjectURL; + $user->has_verified_address = 1; + $user->node_verified_at = Carbon::now('UTC'); $user->save(); - $userAddress->signed_file = $ObjectURL; - $userAddress->node_verified_at = now(); + $userAddress->signed_file = $ObjectURL; + $userAddress->node_verified_at = Carbon::now('UTC'); $userAddress->save(); $emailerData = EmailerHelper::getEmailerData(); - EmailerHelper::triggerUserEmail($user->email, 'Your Node is Verified', $emailerData, $user); - if ($user->letter_verified_at && $user->signature_request_id && $user->node_verified_at) - EmailerHelper::triggerUserEmail($user->email, 'Congratulations', $emailerData, $user); + EmailerHelper::triggerUserEmail( + $user->email, + 'Your Node is Verified', + $emailerData, + $user + ); + + if ( + $user->letter_verified_at && + $user->signature_request_id && + $user->node_verified_at + ) { + EmailerHelper::triggerUserEmail( + $user->email, + 'Congratulations', + $emailerData, + $user + ); + } return $this->metaSuccess(); } else { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } } - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST + ); } catch (\Exception $ex) { - return $this->errorResponse(__($this->failed_verification_response), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __($this->failed_verification_response), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function functionSubmitKYC(SubmitKYCRequest $request) { - $user = auth()->user(); - $data = $request->validated(); + $user = auth()->user(); + $data = $request->validated(); $data['dob'] = \Carbon\Carbon::parse($request->dob)->format('Y-m-d'); $user->update(['member_status' => User::STATUS_INCOMPLETE]); + $this->profileRepo->updateOrCreate( [ 'user_id' => $user->id, ], $data ); + $user->reset_kyc = 0; $user->save(); return $this->metaSuccess(); } - public function verifyOwnerNode(Request $request) - { - $user = auth()->user(); - $this->profileRepo->updateConditions( - ['type_owner_node' => $request->type], - ['user_id' => $user->id] - ); - return $this->metaSuccess(); - } - - public function getOwnerNodes() - { - $user = auth()->user(); - $owners = OwnerNode::where('user_id', $user->id)->get(); - foreach ($owners as $owner) { - $email = $owner->email; - $userOwner = User::where('email', $email)->first(); - if ($userOwner) $owner->kyc_verified_at = $userOwner->kyc_verified_at; - else $owner->kyc_verified_at = null; - } - $data = []; - $data['kyc_verified_at'] = $user->kyc_verified_at; - $data['owner_node'] = $owners; - - return $this->successResponse($data); - } - - public function resendEmailOwnerNodes(ResendEmailRequest $request) - { - $user = auth()->user(); - $email = $request->email; - $owners = OwnerNode::where('user_id', $user->id)->where('email', $email)->first(); - if ($owners) { - $userOwner = User::where('email', $email)->first(); - if (!$userOwner) { - $url = $request->header('origin') ?? $request->root(); - $resetUrl = $url . '/register-type'; - Mail::to($email)->send(new AddNodeMail($resetUrl)); - } - } else - return $this->errorResponse('Email does not exist', Response::HTTP_BAD_REQUEST); - return $this->successResponse(null); - } - // Save Shuftipro Temp public function saveShuftiproTemp(Request $request) { $user = auth()->user(); + // Validator $validator = Validator::make($request->all(), [ 'reference_id' => 'required' ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - $user_id = $user->id; - $reference_id = $request->reference_id; + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $user_id = $user->id; + $reference_id = $request->reference_id; ShuftiproTemp::where('user_id', $user_id)->delete(); - $record = new ShuftiproTemp; - $record->user_id = $user_id; + $record = new ShuftiproTemp; + $record->user_id = $user_id; $record->reference_id = $reference_id; $record->save(); @@ -720,15 +1212,20 @@ public function saveShuftiproTemp(Request $request) public function deleteShuftiproTemp(Request $request) { $user = auth()->user(); + // Validator $validator = Validator::make($request->all(), [ 'reference_id' => 'required' ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - $user_id = $user->id; + if ($validator->fails()) { + return $this->validateResponse($validator->errors()); + } + + $user_id = $user->id; $reference_id = $request->reference_id; - $profile = Profile::where('user_id', $user_id)->first(); + $profile = Profile::where('user_id', $user_id)->first(); + if ($profile) { $profile->status = null; $profile->save(); @@ -740,36 +1237,6 @@ public function deleteShuftiproTemp(Request $request) return $this->metaSuccess(); } - // Update Shuftipro Temp Status - public function updateShuftiProTemp(Request $request) - { - $user = auth()->user(); - // Validator - $validator = Validator::make($request->all(), [ - 'reference_id' => 'required' - ]); - if ($validator->fails()) return $this->validateResponse($validator->errors()); - - $user_id = $user->id; - $reference_id = $request->reference_id; - $profile = Profile::where('user_id', $user_id)->first(); - if ($profile) { - $profile->status = 'pending'; - $profile->save(); - } - $record = ShuftiproTemp::where('user_id', $user_id) - ->where('reference_id', $reference_id) - ->first(); - if ($record) { - $record->status = 'booked'; - $record->save(); - $emailerData = EmailerHelper::getEmailerData(); - EmailerHelper::triggerAdminEmail('KYC or AML need review', $emailerData, $user); - return $this->metaSuccess(); - } - return $this->errorResponse('Fail submit AML', Response::HTTP_BAD_REQUEST); - } - // get vote list public function getVotes(Request $request) { @@ -779,40 +1246,39 @@ public function getVotes(Request $request) $status = $request->status ?? 'active'; $limit = $request->limit ?? 50; - $sort_key = $request->sort_key ?? ''; - $sort_direction = $request->sort_direction ?? ''; - if (!$sort_key) $sort_key = 'ballot.id'; - if (!$sort_direction) $sort_direction = 'desc'; + $sort_key = $request->sort_key ?? 'ballot.id'; + $sort_direction = $request->sort_direction ?? 'desc'; + + if ( + $status != 'active' && + $status != 'finish' && + $status != 'scheduled' + ) { + return $this->errorResponse( + 'Paramater invalid (status is active or finish)', + Response::HTTP_BAD_REQUEST + ); + } - if ($status != 'active' && $status != 'finish' && $status != 'scheduled') - return $this->errorResponse('Paramater invalid (status is active or finish)', Response::HTTP_BAD_REQUEST); + $now = Carbon::now('UTC'); - $now = Carbon::now('EST'); $startDate = $now->format('Y-m-d'); $startTime = $now->format('H:i:s'); if ($status == 'active') { $query = Ballot::where('status', 'active') - ->where(function ($query) use ($startDate, $startTime) { - $query->where('start_date', '<', $startDate) - ->orWhere(function ($query) use ($startDate, $startTime) { - $query->where('start_date', $startDate) - ->where('start_time', '<=', $startTime); - }); - }); + ->where('time_begin', '<=', $now); } else if ($status == 'scheduled') { $query = Ballot::where('status', 'active') - ->where(function ($query) use ($startDate, $startTime) { - $query->where('start_date', '>', $startDate) - ->orWhere(function ($query) use ($startDate, $startTime) { - $query->where('start_date', $startDate) - ->where('start_time', '>', $startTime); - }); - }); + ->where('time_begin', '>', $now); + } else { + $query = Ballot::where('status', '<>', 'active'); } - else $query = Ballot::where('status', '<>', 'active'); - $data = $query->with('vote')->orderBy($sort_key, $sort_direction)->paginate($limit); + $data = $query->with('vote')->orderBy( + $sort_key, + $sort_direction + )->paginate($limit); return $this->successResponse($data); } @@ -831,10 +1297,173 @@ public function getVoteDetail($id) $ballotFileView = BallotFileView::where('ballot_file_id', $file->id)->where('user_id', $user->id)->first(); $file->is_viewed = $ballotFileView ? 1 : 0; } - $ballot->user_vote = VoteResult::where('user_id', $user->id)->where('ballot_id', $ballot->id)->first(); + + foreach ($ballot->files as $file) { + $ballotFileView = BallotFileView::where('ballot_file_id', $file->id) + ->where('user_id', $user->id) + ->first(); + + $file->is_viewed = $ballotFileView ? 1 : 0; + } + + $ballot->user_vote = VoteResult::where('user_id', $user->id) + ->where('ballot_id', $ballot->id) + ->first(); + return $this->successResponse($ballot); } + public function requestReactivation(Request $request) + { + $user = auth()->user()->load(['addresses', 'profile']); + $addresses = $user->addresses ?? []; + + $reactivation_reason = $request->reactivationReason ?? ''; + + if ( + $addresses && + count($addresses) > 0 && + $user->node_verified_at && + $user->letter_verified_at && + $user->signature_request_id && + isset($user->profile) && + $user->profile && + $user->profile->status == 'approved' && + $user->profile->extra_status == 'Suspended' && + !$user->profile->reactivation_requested + ) { + $user->profile->reactivation_reason = $reactivation_reason; + $user->profile->reactivation_requested = true; + $user->profile->reactivation_requested_at = Carbon::now('UTC'); + $user->profile->save(); + } + + return $this->metaSuccess(); + } + + public function canRequestReactivation() + { + $user = auth()->user()->load(['addresses', 'profile']); + $user_id = $user->id; + $addresses = $user->addresses ?? []; + + $settings = Helper::getSettings(); + + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $redmarks_revoke = (int) ($settings['redmarks_revoke'] ?? 0); + $uptime_probation = (float) ($settings['uptime_probation'] ?? 0); + + $return = [ + 'canRequest' => false, + 'avg_uptime' => 0, + 'avg_redmarks' => 0 + ]; + + if ( + $addresses && + count($addresses) > 0 && + $user->node_verified_at && + $user->letter_verified_at && + $user->signature_request_id && + isset($user->profile) && + $user->profile && + $user->profile->status == 'approved' && + $user->profile->extra_status == 'Suspended' + ) { + $flag = true; + $count = 0; + foreach ($addresses as $address) { + $public_address_node = strtolower($address->public_address_node); + + if ($address->extra_status == 'Suspended') { + $count++; + + $temp = AllNodeData2::select(['id', 'uptime']) + ->where('public_key', $public_address_node) + ->where('era_id', $current_era_id) + ->where('bid_inactive', 0) + ->where('in_auction', 1) + ->where('in_current_era', 1) + ->first(); + if ($temp) { + // Check Redmarks + if ($redmarks_revoke > 0) { + $bad_marks = Helper::calculateBadMarksRevoke($temp, $public_address_node, $settings); + if ($bad_marks > $redmarks_revoke) { + $flag = false; + } + $return['avg_redmarks'] += $bad_marks; + } + + // Check Historical Performance + if ($uptime_probation > 0) { + $uptime = Helper::calculateUptime($temp, $public_address_node, $settings); + if ($uptime < $uptime_probation) { + $flag = false; + } + $return['avg_uptime'] += $uptime; + } + } + } + } + + $return['canRequest'] = $flag; + if ($count <= 0) $count = 1; + + $return['avg_redmarks'] = (int) ($return['avg_redmarks'] / $count); + $return['avg_uptime'] = (float) ($return['avg_uptime'] / $count); + $return['avg_uptime'] = round($return['avg_uptime'], 2); + } + + return $this->successResponse($return); + } + + public function canVote() + { + $user = auth()->user(); + $user_id = $user->id; + + $return = [ + 'setting_voting_eras' => 0, + 'setting_good_standing_eras' => 0, + 'good_standing_eras' => 0, + 'total_active_eras' => 0, + 'can_vote' => false + ]; + + $settings = Helper::getSettings(); + + $voting_eras_to_vote = isset($settings['voting_eras_to_vote']) ? (int) $settings['voting_eras_to_vote'] : 1; + $voting_eras_since_redmark = isset($settings['voting_eras_since_redmark']) ? (int) $settings['voting_eras_since_redmark'] : 1; + + $return['setting_voting_eras'] = $voting_eras_to_vote; + $return['setting_good_standing_eras'] = $voting_eras_since_redmark; + + $user_addresses = DB::select(" + SELECT public_address_node + FROM user_addresses + WHERE user_id = $user_id + "); + $user_addresses = $user_addresses ?? []; + + foreach ($user_addresses as $a) { + $p = $a->public_address_node ?? ''; + + $return['good_standing_eras'] = Helper::calculateVariables('good_standing_eras', $p, $settings); + $return['total_active_eras'] = Helper::calculateVariables('total_active_eras', $p, $settings); + + if ( + $return['total_active_eras'] >= $voting_eras_to_vote && + $return['good_standing_eras'] >= $voting_eras_since_redmark + ) { + $return['can_vote'] = true; + break; + } + } + + return $this->successResponse($return); + } + // vote the ballot public function vote($id, Request $request) { @@ -843,40 +1472,98 @@ public function vote($id, Request $request) return $this->errorResponse('Your access is blocked', Response::HTTP_BAD_REQUEST); $vote = $request->vote; - if (!$vote || ($vote != 'for' && $vote != 'against')) - return $this->errorResponse('Paramater invalid (vote is for or against)', Response::HTTP_BAD_REQUEST); + + if (!$vote || ($vote != 'for' && $vote != 'against')) { + return $this->errorResponse( + 'Paramater invalid (vote is for or against)', + Response::HTTP_BAD_REQUEST + ); + } + + // New check for stable member validator + $stable = false; + $addresses = UserAddress::where('user_id', $user->id)->get(); + + if (!$addresses) { + $addresses = []; + } + + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + + $voting_eras_to_vote = isset($settings['voting_eras_to_vote']) ? (int) $settings['voting_eras_to_vote'] : 1; + $voting_eras_since_redmark = isset($settings['voting_eras_since_redmark']) ? (int) $settings['voting_eras_since_redmark'] : 1; + + foreach ($addresses as $address) { + $p = $address->public_address_node ?? ''; + + $good_standing_eras = Helper::calculateVariables('good_standing_eras', $p, $settings); + $total_active_eras = Helper::calculateVariables('total_active_eras', $p, $settings); + + if ( + $total_active_eras >= $voting_eras_to_vote && + $good_standing_eras >= $voting_eras_since_redmark + ) { + $stable = true; + break; + } + } + + if (!$stable) { + return $this->errorResponse( + 'Validator is not stable enough to vote', + Response::HTTP_BAD_REQUEST + ); + } + $ballot = Ballot::where('id', $id)->first(); - if (!$ballot) return $this->errorResponse('Not found ballot', Response::HTTP_BAD_REQUEST); - $voteResult = VoteResult::where('user_id', $user->id)->where('ballot_id', $ballot->id)->first(); + + if (!$ballot) { + return $this->errorResponse( + 'Not found ballot', + Response::HTTP_BAD_REQUEST + ); + } + + $voteResult = VoteResult::where('user_id', $user->id) + ->where('ballot_id', $ballot->id) + ->first(); + if ($voteResult) { - if ($vote == $voteResult->type) return $this->metaSuccess(); - else { - $voteResult->type = $vote; - $voteResult->updated_at = now(); + if ($vote == $voteResult->type) { + return $this->metaSuccess(); + } else { + $voteResult->type = $vote; + $voteResult->updated_at = Carbon::now('UTC'); + if ($vote == 'for') { - $ballot->vote->for_value = $ballot->vote->for_value + 1; + $ballot->vote->for_value = $ballot->vote->for_value + 1; $ballot->vote->against_value = $ballot->vote->against_value - 1; } else { - $ballot->vote->for_value = $ballot->vote->for_value - 1; + $ballot->vote->for_value = $ballot->vote->for_value - 1; $ballot->vote->against_value = $ballot->vote->against_value + 1; } - $ballot->vote->updated_at = now(); + + $ballot->vote->updated_at = Carbon::now('UTC'); $ballot->vote->save(); $voteResult->save(); } } else { $voteResult = new VoteResult(); - $voteResult->user_id = $user->id; + $voteResult->user_id = $user->id; $voteResult->ballot_id = $ballot->id; - $voteResult->vote_id = $ballot->vote->id; - $voteResult->type = $vote; + $voteResult->vote_id = $ballot->vote->id; + $voteResult->type = $vote; $voteResult->save(); - if ($vote == 'for') - $ballot->vote->for_value = $ballot->vote->for_value + 1; - else + + if ($vote == 'for') { + $ballot->vote->for_value = $ballot->vote->for_value + 1; + } else { $ballot->vote->against_value = $ballot->vote->against_value + 1; + } + $ballot->vote->result_count = $ballot->vote->result_count + 1; - $ballot->vote->updated_at = now(); + $ballot->vote->updated_at = Carbon::now('UTC'); $ballot->vote->save(); } return $this->metaSuccess(); @@ -884,57 +1571,67 @@ public function vote($id, Request $request) public function submitViewFileBallot(Request $request, $fileId) { - $user = auth()->user(); + $user = auth()->user(); $ballotFile = BallotFile::where('id', $fileId)->first(); - if (!$ballotFile) - return $this->errorResponse('Not found ballot file', Response::HTTP_BAD_REQUEST); - $ballotFileView = BallotFileView::where('ballot_file_id', $ballotFile->id)->where('user_id', $user->id)->first(); - if ($ballotFileView) return $this->metaSuccess(); - $ballotFileView = new BallotFileView(); - $ballotFileView->ballot_file_id = $ballotFile->id; - $ballotFileView->ballot_id = $ballotFile->ballot_id; - $ballotFileView->user_id = $user->id; + + if (!$ballotFile) { + return $this->errorResponse( + 'Not found ballot file', + Response::HTTP_BAD_REQUEST + ); + } + + $ballotFileView = BallotFileView::where('ballot_file_id', $ballotFile->id) + ->where('user_id', $user->id) + ->first(); + + if ($ballotFileView) { + return $this->metaSuccess(); + } + + $ballotFileView = new BallotFileView(); + $ballotFileView->ballot_file_id = $ballotFile->id; + $ballotFileView->ballot_id = $ballotFile->ballot_id; + $ballotFileView->user_id = $user->id; $ballotFileView->save(); return $this->metaSuccess(); } - /** - * verify file casper singer - */ + public function uploadAvatar(Request $request) { try { // Validator $validator = Validator::make($request->all(), [ - 'avatar' => 'sometimes|mimes:jpeg,jpg,png,gif,webp|max:100000', + 'avatar' => 'sometimes|mimes:jpeg,jpg,png,gif,webp|max:2048', ]); if ($validator->fails()) { return $this->validateResponse($validator->errors()); } - $user = auth()->user(); + $user = auth()->user(); $filenameWithExt = $request->file('avatar')->getClientOriginalName(); - $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); - $extension = $request->file('avatar')->getClientOriginalExtension(); + $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME); + $extension = $request->file('avatar')->getClientOriginalExtension(); // new filename hash - $filenamehash = md5(Str::random(10) . '_' . (string)time()); + $filenamehash = md5(Str::random(10) . '_' . (string)time()); // Filename to store $fileNameToStore = $filenamehash . '.' . $extension; // S3 file upload $S3 = new S3Client([ - 'version' => 'latest', - 'region' => getenv('AWS_DEFAULT_REGION'), + 'version' => 'latest', + 'region' => getenv('AWS_DEFAULT_REGION'), 'credentials' => [ - 'key' => getenv('AWS_ACCESS_KEY_ID'), - 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), + 'key' => getenv('AWS_ACCESS_KEY_ID'), + 'secret' => getenv('AWS_SECRET_ACCESS_KEY'), ], ]); $s3result = $S3->putObject([ - 'Bucket' => getenv('AWS_BUCKET'), - 'Key' => 'client_uploads/' . $fileNameToStore, - 'SourceFile' => $request->file('avatar'), + 'Bucket' => getenv('AWS_BUCKET'), + 'Key' => 'client_uploads/' . $fileNameToStore, + 'SourceFile' => $request->file('avatar'), ]); // $ObjectURL = 'https://'.getenv('AWS_BUCKET').'.s3.amazonaws.com/client_uploads/'.$fileNameToStore; @@ -942,106 +1639,173 @@ public function uploadAvatar(Request $request) $user->save(); return $this->metaSuccess(); } catch (\Exception $ex) { - return $this->errorResponse(__('Failed upload avatar'), Response::HTTP_BAD_REQUEST, $ex->getMessage()); + return $this->errorResponse( + __('Failed upload avatar'), + Response::HTTP_BAD_REQUEST, + $ex->getMessage() + ); } } public function getMembers(Request $request) { + $settings = Helper::getSettings(); + $current_era_id = (int) ($settings['current_era_id'] ?? 0); + $search = $request->search; - $limit = $request->limit ?? 50; - - $slide_value_uptime = $request->uptime ?? 0; - $slide_value_update_responsiveness = $request->update_responsiveness ?? 0; - $slide_value_delegotors = $request->delegators ?? 0; - $slide_value_stake_amount = $request->stake_amount ?? 0; - $slide_delegation_rate = $request->delegation_rate ?? 0; - - $max_uptime = Node::max('uptime'); - $max_uptime = $max_uptime * 100; - - $max_delegators = NodeInfo::max('delegators_count'); - if(!$max_delegators || $max_delegators < 1) $max_delegators = 1; - - $max_stake_amount = NodeInfo::max('total_staked_amount'); - if(!$max_stake_amount || $max_stake_amount < 1) $max_stake_amount = 1; $sort_key = $request->sort_key ?? 'created_at'; - - $users = User::with(['metric', 'nodeInfo', 'profile']) - ->whereHas('nodeInfo') - ->where('role', 'member') - ->where(function ($query) use ($search) { - if ($search) { - $query->where('users.first_name', 'like', '%' . $search . '%') - ->orWhere('users.last_name', 'like', '%' . $search . '%'); - } - }) - ->get(); - - foreach ($users as $user) { - $latest = Node::where('node_address', strtolower($user->public_address_node)) - ->whereNotnull('protocol_version') - ->orderBy('created_at', 'desc') - ->first(); - if (!$latest) $latest = new Node(); - - $user->status = isset($user->profile) && isset($user->profile->status) ? $user->profile->status : ''; - - $uptime_nodeInfo = $user->nodeInfo->uptime; - $uptime_node = isset($latest->uptime) && $latest->uptime ? $latest->uptime * 100 : null; - $uptime_metric = isset($user->metric) && isset($user->metric->uptime) ? $user->metric->uptime : null; - - $res_nodeInfo = $user->nodeInfo->update_responsiveness ?? null; - $res_node = $latest->update_responsiveness ?? null; - $res_metric = $user->metric->update_responsiveness ?? null; - - $uptime = $uptime_nodeInfo ? $uptime_nodeInfo : ($uptime_node ? $uptime_node : ($uptime_metric ? $uptime_metric : 1)); - $res = $res_nodeInfo ? $res_nodeInfo : ($res_node ? $res_node : ($res_metric ? $res_metric : 0)); - - $delegation_rate = isset($user->nodeInfo->delegation_rate) && $user->nodeInfo->delegation_rate ? $user->nodeInfo->delegation_rate / 100 : 1; - if ($delegation_rate > 1) $delegation_rate = 1; - $delegators_count = isset($user->nodeInfo->delegators_count) && $user->nodeInfo->delegators_count ? $user->nodeInfo->delegators_count : 0; - $total_staked_amount = isset($user->nodeInfo->total_staked_amount) && $user->nodeInfo->total_staked_amount ? $user->nodeInfo->total_staked_amount : 0; - - $uptime_score = (float) (($slide_value_uptime * $uptime) / 100); - $delegation_rate_score = (float) (($slide_delegation_rate * (1 - $delegation_rate)) / 100); - $delegators_count_score = (float) ($delegators_count / $max_delegators) * $slide_value_delegotors; - $total_staked_amount_score = (float) ($total_staked_amount / $max_stake_amount) * $slide_value_stake_amount; - $res_score = (float) (($slide_value_update_responsiveness * $res) / 100); - - $user->uptime = $uptime; - $user->delegation_rate = $delegation_rate; - $user->delegators_count = $delegators_count; - $user->total_staked_amount = $total_staked_amount; - $user->totalScore = $uptime_score + $delegation_rate_score + $delegators_count_score + $total_staked_amount_score + $res_score; + + $members = DB::table('users') + ->select( + 'users.id', + 'users.pseudonym', + 'users.created_at', + 'users.approve_at', + 'users.kyc_verified_at', + 'user_addresses.node_verified_at', + 'all_node_data2.public_key', + 'all_node_data2.uptime as uptimeBase', + 'all_node_data2.bid_delegators_count', + 'all_node_data2.bid_delegation_rate', + 'all_node_data2.bid_total_staked_amount' + ) + ->join( + 'user_addresses', + 'user_addresses.user_id', + '=', + 'users.id' + ) + ->join( + 'all_node_data2', + 'all_node_data2.public_key', + '=', + 'user_addresses.public_address_node' + ) + ->where([ + 'users.banned' => 0, + 'all_node_data2.era_id' => $current_era_id + ]) + ->where(function ($query) use ($search) { + if ($search) { + $query->where('users.first_name', 'like', '%' . $search . '%') + ->orWhere('users.last_name', 'like', '%' . $search . '%') + ->orWhere('users.pseudonym', 'like', '%' . $search . '%'); + } + }) + ->get(); + + $max_delegators = 0; + $max_stake_amount = 0; + + foreach ($members as $member) { + if ((int)$member->bid_delegators_count > $max_delegators) { + $max_delegators = (int)$member->bid_delegators_count; + } + + if ((int)$member->bid_total_staked_amount > $max_stake_amount) { + $max_stake_amount = (int)$member->bid_total_staked_amount; + } } - $users = $users->sortByDesc($sort_key)->values(); - $users = Helper::paginate($users, $limit, $request->page); - return $this->successResponse($users); + foreach ($members as &$member) { + $baseObject = $member; + $baseObject->uptime = $member->uptimeBase; + $member->uptime = Helper::calculateUptime($member, $member->public_key, $settings); + + $r = $member; + $r->uptime_rate = (float) ($request->uptime ?? 0); + $r->fee_rate = (float) ($request->delegation_rate ?? 0); + $r->count_rate = (float) ($request->delegators ?? 0); + $r->stake_rate = (float) ($request->stake_amount ?? 0); + + $member->totalScore = Helper::getTotalScore($r, $max_delegators, $max_stake_amount); + } + + $members = $members->sortByDesc($sort_key)->values(); + + return $this->successResponse($members); } - public function getMemberDetail($id, Request $request) - { - $public_address_node = $request->get('public_address_node') ?? null; + public function getMemberDetail($id, Request $request) { $user = User::where('id', $id)->first(); + if (!$user || $user->role == 'admin') { + return $this->errorResponse( + __('api.error.not_found'), + Response::HTTP_NOT_FOUND + ); + } Helper::getAccountInfoStandard($user); - if (!$user || $user->role == 'admin') - return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); - $user->metric = Helper::getNodeInfo($user, $public_address_node); - $response = $user->load(['profile', 'addresses']); + $current_era_id = Helper::getCurrentERAId(); + + $response = [ + 'id' => $user->id, + 'full_name' => $user->full_name, + 'avatar_url' => $user->avatar_url, + 'first_name' => $user->first_name, + 'last_name' => $user->last_name, + 'email' => $user->email, + 'pseudonym' => $user->pseudonym, + 'telegram' => $user->telegram, + 'type' => $user->type, + 'entity_name' => $user->entity_name, + 'entity_type' => $user->entity_type, + 'entity_register_number' => $user->entity_register_number, + 'entity_register_country' => $user->entity_register_country, + // 'entity_tax' => $user->entity_tax, + 'public_address_node' => $user->public_address_node, + 'node_verified_at' => $user->node_verified_at, + 'member_status' => $user->member_status, + 'message_content' => $user->message_content, + 'email_verified_at' => $user->email_verified_at, + 'kyc_verified_at' => $user->kyc_verified_at, + 'letter_verified_at' => $user->letter_verified_at, + 'letter_rejected_at' => $user->letter_rejected_at, + 'approve_at' => $user->approve_at, + 'role' => $user->role, + 'node_status' => $user->node_status + ]; - unset($response->last_login_at); - unset($response->last_login_ip_address); + if ($user->profile) { + $response['profile'] = [ + 'id' => $user->profile->id, + 'status' => $user->profile->status, + 'extra_status' => $user->profile->extra_status, + 'casper_association_kyc_hash' => $user->profile->casper_association_kyc_hash, + 'blockchain_name' => $user->profile->blockchain_name, + 'blockchain_desc' => $user->profile->blockchain_desc, + 'type' => $user->profile->type + ]; + } else { + $response['profile'] = [ + 'type' => $user->type + ]; + } - if (isset($response->profile)) { - unset($response->profile->dob); - unset($response->profile->address); - unset($response->profile->city); - unset($response->profile->zip); + $response['addresses'] = $user->addresses ?? []; + + foreach ($response['addresses'] as &$addressItem) { + $temp = AllNodeData2::select([ + 'uptime', + 'bid_delegators_count', + 'bid_delegation_rate', + 'bid_self_staked_amount', + 'bid_total_staked_amount' + ]) + ->where('public_key', $addressItem->public_address_node) + ->where('era_id', $current_era_id) + ->orderBy('id', 'desc') + ->first() + ->toArray(); + if ($temp) { + foreach ($temp as $key => $value) { + if ($key == 'uptime') $value = round((float) $value, 2); + $addressItem->$key = $value; + } + $addressItem->update_responsiveness = 100; + } } return $this->successResponse($response); @@ -1049,21 +1813,27 @@ public function getMemberDetail($id, Request $request) public function getCaKycHash($hash) { - if (!ctype_xdigit($hash)) - return $this->errorResponse(__('api.error.not_found'), Response::HTTP_NOT_FOUND); + if (!ctype_xdigit($hash)) { + return $this->errorResponse( + __('api.error.not_found'), + Response::HTTP_NOT_FOUND + ); + } $selection = DB::select(" - SELECT a.casper_association_kyc_hash as proof_hash, b.reference_id, b.status, c.pseudonym - FROM profile as a + SELECT + a.casper_association_kyc_hash AS proof_hash, + b.reference_id, b.status, + c.pseudonym + FROM profile AS a LEFT JOIN shuftipro AS b ON a.user_id = b.user_id LEFT JOIN users AS c ON b.user_id = c.id WHERE a.casper_association_kyc_hash = '$hash' "); - $selection = $selection[0] ?? array(); - - return $this->successResponse($selection); + + return $this->successResponse($selection[0] ?? []); } public function getMyVotes(Request $request) @@ -1073,8 +1843,8 @@ public function getMyVotes(Request $request) return $this->successResponse(['data' => []]); $limit = $request->limit ?? 50; - $user = auth()->user(); - $data = VoteResult::where('vote_result.user_id', $user->id) + $user = auth()->user(); + $data = VoteResult::where('vote_result.user_id', $user->id) ->join('ballot', function ($query) use ($user) { $query->on('vote_result.ballot_id', '=', 'ballot.id'); }) @@ -1093,79 +1863,141 @@ public function getMyVotes(Request $request) public function checkCurrentPassword(Request $request) { $user = auth()->user(); - if (Hash::check($request->current_password, $user->password)) + + if (Hash::check($request->current_password, $user->password)) { return $this->metaSuccess(); - else - return $this->errorResponse(__('Invalid password'), Response::HTTP_BAD_REQUEST); + } else { + return $this->errorResponse( + __('Invalid password'), + Response::HTTP_BAD_REQUEST + ); + } } public function settingUser(Request $request) { $user = auth()->user(); - if ($request->new_password) $user->password = bcrypt($request->new_password); + + if ($request->new_password) { + $user->password = bcrypt($request->new_password); + } if ($request->username) { $checkUsername = User::where('username', $request->username) - ->where('username', '!=', $user->username) - ->first(); - if ($checkUsername) - return $this->errorResponse(__('this username has already been taken'), Response::HTTP_BAD_REQUEST); + ->where('username', '!=', $user->username) + ->first(); + + if ($checkUsername) { + return $this->errorResponse( + __('this username has already been taken'), + Response::HTTP_BAD_REQUEST + ); + } + $user->username = $request->username; } - if (isset($request->twoFA_login)) $user->twoFA_login = $request->twoFA_login; + if (isset($request->twoFA_login)) { + $user->twoFA_login = $request->twoFA_login; + } if ($request->email && $request->email != $user->email) { $emailParam = $request->email; - $checkEmail = User::where(function ($query) use ($emailParam) { - $query->where('email', $emailParam) - ->orWhere('new_email', $emailParam); - }) - ->where('id', '!=', $user->id) - ->first(); + $checkEmail = User::where( + function ($query) use ($emailParam) { + $query->where('email', $emailParam) + ->orWhere('new_email', $emailParam); + } + ) + ->where('id', '!=', $user->id) + ->first(); $currentEmail = $user->email; - $newEmail = $request->email; - if ($checkEmail) - return $this->errorResponse(__('this email has already been taken'), Response::HTTP_BAD_REQUEST); + $newEmail = $request->email; + + if ($checkEmail) { + return $this->errorResponse( + __('this email has already been taken'), + Response::HTTP_BAD_REQUEST + ); + } + $user->new_email = $newEmail; // Current Email $codeCurrentEmail = Str::random(6); - $url = $request->header('origin') ?? $request->root(); - $urlCurrentEmail = $url . '/change-email/cancel-changes?code=' . $codeCurrentEmail . '&email=' . urlencode($currentEmail); + $url = $request->header('origin') ?? $request->root(); + $urlCurrentEmail = ( + $url . + '/change-email/cancel-changes?code=' . + $codeCurrentEmail . + '&email=' . + urlencode($currentEmail) + ); + $newMemberData = [ - 'title' => 'Are you trying to update your email?', + 'title' => 'Are you trying to update your email?', 'content' => 'You recently requested to update your email address with the Casper Association Portal. If this is correct, click the link sent to your new email address to activate it.-1?Jn(t,e,o):un(e)?hn(o)?t.removeAttribute(e):(o="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,o)):ln(e)?t.setAttribute(e,function(t,e){return hn(e)||"false"===e?"false":"contenteditable"===t&&dn(e)?e:"true"}(e,o)):fn(e)?hn(o)?t.removeAttributeNS(An,qn(e)):t.setAttributeNS(An,e,o):Jn(t,e,o)}function Jn(t,e,o){if(hn(o))t.removeAttribute(e);else{if(Z&&!tt&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==o&&!t.__ieph){var n=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",n)};t.addEventListener("input",n),t.__ieph=!0}t.setAttribute(e,o)}}var Kn={create:Yn,update:Yn};function Qn(t,e){var o=e.elm,n=e.data,p=t.data;if(!(b(n.staticClass)&&b(n.class)&&(b(p)||b(p.staticClass)&&b(p.class)))){var z=Wn(e),r=o._transitionClasses;M(r)&&(z=gn(z,mn(r))),z!==o._prevClass&&(o.setAttribute("class",z),o._prevClass=z)}}var Zn,tp,ep,op,np,pp,bp={create:Qn,update:Qn},Mp=/[\w).+\-_$\]]/;function zp(t){var e,o,n,p,b,M=!1,z=!1,r=!1,c=!1,i=0,a=0,O=0,s=0;for(n=0;n 0&&!isNaN(t)?ce*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){var e,o,n,p,b,M,z,r,c=this,i=0,a=c.chart;if(!t)for(e=0,o=a.data.datasets.length;e -1?t.split("\n"):t}function Xo(t){var e=t._xScale,o=t._yScale||t._scale,n=t._index,p=t._datasetIndex,b=t._chart.getDatasetMeta(p).controller,M=b._getIndexScale(),z=b._getValueScale();return{xLabel:e?e.getLabelForIndex(n,p):"",yLabel:o?o.getLabelForIndex(n,p):"",label:M?""+M.getLabelForIndex(n,p):"",value:z?""+z.getLabelForIndex(n,p):"",index:n,datasetIndex:p,x:t._model.x,y:t._model.y}}function _o(t){var e=Q.global;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,rtl:t.rtl,textDirection:t.textDirection,bodyFontColor:t.bodyFontColor,_bodyFontFamily:mo(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:mo(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:mo(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:mo(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:mo(t.titleFontStyle,e.defaultFontStyle),titleFontSize:mo(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:mo(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:mo(t.footerFontStyle,e.defaultFontStyle),footerFontSize:mo(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function No(t,e){var o=t._chart.ctx,n=2*e.yPadding,p=0,b=e.body,M=b.reduce((function(t,e){return t+e.before.length+e.lines.length+e.after.length}),0);M+=e.beforeBody.length+e.afterBody.length;var z=e.title.length,r=e.footer.length,c=e.titleFontSize,i=e.bodyFontSize,a=e.footerFontSize;n+=z*c,n+=z?(z-1)*e.titleSpacing:0,n+=z?e.titleMarginBottom:0,n+=M*i,n+=M?(M-1)*e.bodySpacing:0,n+=r?e.footerMarginTop:0,n+=r*a,n+=r?(r-1)*e.footerSpacing:0;var O=0,s=function(t){p=Math.max(p,o.measureText(t).width+O)};return o.font=zt.fontString(c,e._titleFontStyle,e._titleFontFamily),zt.each(e.title,s),o.font=zt.fontString(i,e._bodyFontStyle,e._bodyFontFamily),zt.each(e.beforeBody.concat(e.afterBody),s),O=e.displayColors?i+2:0,zt.each(b,(function(t){zt.each(t.before,s),zt.each(t.lines,s),zt.each(t.after,s)})),O=0,o.font=zt.fontString(a,e._footerFontStyle,e._footerFontFamily),zt.each(e.footer,s),{width:p+=2*e.xPadding,height:n}}function wo(t,e){var o,n,p,b,M,z=t._model,r=t._chart,c=t._chart.chartArea,i="center",a="center";z.y c)return b;return Math.max(c,1)}function un(t){var e,o,n=[];for(e=0,o=t.length;e 0,p=t.length>0,b=function(b,M,z,r,i){var a,l,u,A=0,f="0",q=b&&[],h=[],W=c,g=b||p&&n.find.TAG("*",i),m=v+=null==W?1:Math.random()||.1,R=g.length;for(i&&(c=M==s||M||i);f!==R&&null!=(a=g[f]);f++){if(p&&a){for(l=0,M||a.ownerDocument==s||(O(a),z=!d);u=t[l++];)if(u(a,M||s,z)){r.push(a);break}i&&(v=m)}o&&((a=!u&&a)&&A--,b&&q.push(a))}if(A+=f,o&&f!==A){for(l=0;u=e[l++];)u(q,h,M,z);if(b){if(A>0)for(;f--;)q[f]||h[f]||(h[f]=N.call(r));h=vt(h)}x.apply(r,h),i&&!b&&h.length>0&&A+e.length>1&&zt.uniqueSort(r)}return i&&(v=m,c=W),q};return o?ct(b):b}(b,p)),z.selector=t}return z},r=zt.select=function(t,e,o,p){var b,r,c,i,a,O="function"==typeof t&&t,s=!p&&M(t=O.selector||t);if(o=o||[],1===s.length){if((r=s[0]=s[0].slice(0)).length>2&&"ID"===(c=r[0]).type&&9===e.nodeType&&d&&n.relative[r[1].type]){if(!(e=(n.find.ID(c.matches[0].replace(et,ot),e)||[])[0]))return o;O&&(e=e.parentNode),t=t.slice(r.shift().value.length)}for(b=Y.needsContext.test(t)?0:r.length;b--&&(c=r[b],!n.relative[i=c.type]);)if((a=n.find[i])&&(p=a(c.matches[0].replace(et,ot),tt.test(r[0].type)&&At(e.parentNode)||e))){if(r.splice(b,1),!(t=p.length&&qt(r)))return x.apply(o,p),o;break}}return(O||z(t,s))(p,e,!d,o,!e||tt.test(t)&&At(e.parentNode)||e),o},o.sortStable=h.split("").sort(L).join("")===h,o.detectDuplicates=!!a,O(),o.sortDetached=it((function(t){return 1&t.compareDocumentPosition(s.createElement("fieldset"))})),it((function(t){return t.innerHTML="","#"===t.firstChild.getAttribute("href")}))||at("type|href|height|width",(function(t,e,o){if(!o)return t.getAttribute(e,"type"===e.toLowerCase()?1:2)})),o.attributes&&it((function(t){return t.innerHTML="",t.firstChild.setAttribute("value",""),""===t.firstChild.getAttribute("value")}))||at("value",(function(t,e,o){if(!o&&"input"===t.nodeName.toLowerCase())return t.defaultValue})),it((function(t){return null==t.getAttribute("disabled")}))||at(S,(function(t,e,o){var n;if(!o)return!0===t[e]?e.toLowerCase():(n=t.getAttributeNode(e))&&n.specified?n.value:null})),zt}(n);m.find=y,m.expr=y.selectors,m.expr[":"]=m.expr.pseudos,m.uniqueSort=m.unique=y.uniqueSort,m.text=y.getText,m.isXMLDoc=y.isXML,m.contains=y.contains,m.escapeSelector=y.escape;var B=function(t,e,o){for(var n=[],p=void 0!==o;(t=t[e])&&9!==t.nodeType;)if(1===t.nodeType){if(p&&m(t).is(o))break;n.push(t)}return n},L=function(t,e){for(var o=[];t;t=t.nextSibling)1===t.nodeType&&t!==e&&o.push(t);return o},X=m.expr.match.needsContext;function _(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function w(t,e,o){return A(e)?m.grep(t,(function(t,n){return!!e.call(t,n,t)!==o})):e.nodeType?m.grep(t,(function(t){return t===e!==o})):"string"!=typeof e?m.grep(t,(function(t){return i.call(e,t)>-1!==o})):m.filter(e,t,o)}m.filter=function(t,e,o){var n=e[0];return o&&(t=":not("+t+")"),1===e.length&&1===n.nodeType?m.find.matchesSelector(n,t)?[n]:[]:m.find.matches(t,m.grep(e,(function(t){return 1===t.nodeType})))},m.fn.extend({find:function(t){var e,o,n=this.length,p=this;if("string"!=typeof t)return this.pushStack(m(t).filter((function(){for(e=0;e 1)}}),m.Tween=pe,pe.prototype={constructor:pe,init:function(t,e,o,n,p,b){this.elem=t,this.prop=o,this.easing=p||m.easing._default,this.options=e,this.start=this.now=this.cur(),this.end=n,this.unit=b||(m.cssNumber[o]?"":"px")},cur:function(){var t=pe.propHooks[this.prop];return t&&t.get?t.get(this):pe.propHooks._default.get(this)},run:function(t){var e,o=pe.propHooks[this.prop];return this.options.duration?this.pos=e=m.easing[this.easing](t,this.options.duration*t,0,1,this.options.duration):this.pos=e=t,this.now=(this.end-this.start)*e+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),o&&o.set?o.set(this):pe.propHooks._default.set(this),this}},pe.prototype.init.prototype=pe.prototype,pe.propHooks={_default:{get:function(t){var e;return 1!==t.elem.nodeType||null!=t.elem[t.prop]&&null==t.elem.style[t.prop]?t.elem[t.prop]:(e=m.css(t.elem,t.prop,""))&&"auto"!==e?e:0},set:function(t){m.fx.step[t.prop]?m.fx.step[t.prop](t):1!==t.elem.nodeType||!m.cssHooks[t.prop]&&null==t.elem.style[Kt(t.prop)]?t.elem[t.prop]=t.now:m.style(t.elem,t.prop,t.now+t.unit)}}},pe.propHooks.scrollTop=pe.propHooks.scrollLeft={set:function(t){t.elem.nodeType&&t.elem.parentNode&&(t.elem[t.prop]=t.now)}},m.easing={linear:function(t){return t},swing:function(t){return.5-Math.cos(t*Math.PI)/2},_default:"swing"},m.fx=pe.prototype.init,m.fx.step={};var be,Me,ze=/^(?:toggle|show|hide)$/,re=/queueHooks$/;function ce(){Me&&(!1===q.hidden&&n.requestAnimationFrame?n.requestAnimationFrame(ce):n.setTimeout(ce,m.fx.interval),m.fx.tick())}function ie(){return n.setTimeout((function(){be=void 0})),be=Date.now()}function ae(t,e){var o,n=0,p={height:t};for(e=e?1:0;n<4;n+=2-e)p["margin"+(o=bt[n])]=p["padding"+o]=t;return e&&(p.opacity=p.width=t),p}function Oe(t,e,o){for(var n,p=(se.tweeners[e]||[]).concat(se.tweeners["*"]),b=0,M=p.length;bn&&(n=b),n},zt.numberOfLabelLines=function(t){var e=1;return zt.each(t,(function(t){zt.isArray(t)&&t.length>e&&(e=t.length)})),e},zt.color=S?function(t){return t instanceof CanvasGradient&&(t=Q.global.defaultColor),S(t)}:function(t){return t},zt.getHoverColor=function(t){return t instanceof CanvasPattern||t instanceof CanvasGradient?t:zt.color(t).saturate(.5).darken(.1).rgbString()}};function Jo(){throw new Error("This method is not implemented: either no adapter can be found or an incomplete integration was provided.")}function Ko(t){this.options=t||{}}zt.extend(Ko.prototype,{formats:Jo,parse:Jo,format:Jo,add:Jo,diff:Jo,startOf:Jo,endOf:Jo,_create:function(t){return t}}),Ko.override=function(t){zt.extend(Ko.prototype,t)};var Qo={_date:Ko},Zo={formatters:{values:function(t){return zt.isArray(t)?t:""+t},linear:function(t,e,o){var n=o.length>3?o[2]-o[1]:o[1]-o[0];Math.abs(n)>1&&t!==Math.floor(t)&&(n=t-Math.floor(t));var p=zt.log10(Math.abs(n)),b="";if(0!==t)if(Math.max(Math.abs(o[0]),Math.abs(o[o.length-1]))<1e-4){var M=zt.log10(Math.abs(t)),z=Math.floor(M)-Math.floor(p);z=Math.max(Math.min(z,20),0),b=t.toExponential(z)}else{var r=-1*Math.floor(p);r=Math.max(Math.min(r,20),0),b=t.toFixed(r)}else b="0";return b},logarithmic:function(t,e,o){var n=t/Math.pow(10,Math.floor(zt.log10(t)));return 0===t?"0":1===n||2===n||5===n||0===e||e===o.length-1?t.toExponential():""}}},tn=zt.isArray,en=zt.isNullOrUndef,on=zt.valueOrDefault,nn=zt.valueAtIndexOrDefault;function pn(t,e){for(var o=[],n=t.length/e,p=0,b=t.length;pr+c)))return M}function Mn(t,e){zt.each(t,(function(t){var o,n=t.gc,p=n.length/2;if(p>e){for(o=0;o","
"],col:[2,"
"],tr:[2,"","
"],td:[3,"
"],_default:[0,"",""]};function ht(t,e){var o;return o=void 0!==t.getElementsByTagName?t.getElementsByTagName(e||"*"):void 0!==t.querySelectorAll?t.querySelectorAll(e||"*"):[],void 0===e||e&&_(t,e)?m.merge([t],o):o}function Wt(t,e){for(var o=0,n=t.length;o","