mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-18 10:28:07 +00:00
Compare commits
58 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c9f7ab53f | ||
|
|
b168bb47f4 | ||
|
|
2dc2200171 | ||
|
|
747dec721f | ||
|
|
f3e06bb125 | ||
|
|
f035b720cd | ||
|
|
da63835902 | ||
|
|
80d10bed7a | ||
|
|
992761c1d0 | ||
|
|
5082654d01 | ||
|
|
92978bf256 | ||
|
|
84fdb380d7 | ||
|
|
d9b0f83e5d | ||
|
|
7ae237eb7c | ||
|
|
e888d53d31 | ||
|
|
18cdf04026 | ||
|
|
3b0dd419bb | ||
|
|
ef110eb4ce | ||
|
|
2006fa0929 | ||
|
|
7e9d34cf0b | ||
|
|
740f603bbe | ||
|
|
6af68374d6 | ||
|
|
fe89060698 | ||
|
|
80246a232e | ||
|
|
0578125f70 | ||
|
|
8882cdab18 | ||
|
|
058d253dbc | ||
|
|
2d611a1e33 | ||
|
|
695d36e279 | ||
|
|
f5d6abc836 | ||
|
|
f37bc45194 | ||
|
|
40c8209cdc | ||
|
|
d55cc59e19 | ||
|
|
5771e39a9e | ||
|
|
dcd1719a61 | ||
|
|
aa2051d281 | ||
|
|
80f32a9887 | ||
|
|
336c037590 | ||
|
|
d2cac6d60f | ||
|
|
c8e587db01 | ||
|
|
f712755b79 | ||
|
|
2e11db0c83 | ||
|
|
bd4dbfeb7a | ||
|
|
37baeb2fc2 | ||
|
|
3a7f4486bb | ||
|
|
f561a55221 | ||
|
|
73c0132051 | ||
|
|
4f3e9c57c9 | ||
|
|
f20056ec73 | ||
|
|
6b589d1d0f | ||
|
|
0348eecf4c | ||
|
|
52eadf91ce | ||
|
|
39992c0bd5 | ||
|
|
6b22d2ec86 | ||
|
|
fae800343f | ||
|
|
92825b0211 | ||
|
|
d4a757a892 | ||
|
|
f1c0247960 |
203 changed files with 2950 additions and 5353 deletions
|
|
@ -14,14 +14,6 @@ rocky9-deploy:
|
|||
- rocky9-package
|
||||
- rocky9-test
|
||||
|
||||
rocky10-deploy:
|
||||
extends: .deploy
|
||||
script:
|
||||
- ./deploy_packages.sh rockylinux 10
|
||||
needs:
|
||||
- rocky10-package
|
||||
- rocky10-test
|
||||
|
||||
debian12-deploy:
|
||||
extends: .deploy
|
||||
script:
|
||||
|
|
@ -30,24 +22,26 @@ debian12-deploy:
|
|||
- debian12-package
|
||||
- debian12-test
|
||||
|
||||
debian13-deploy:
|
||||
extends: .deploy
|
||||
script:
|
||||
- ./deploy_packages.sh debian trixie
|
||||
needs:
|
||||
- debian13-package
|
||||
- debian13-test
|
||||
|
||||
remi-rocky8-deploy:
|
||||
extends: .deploy
|
||||
#rules:
|
||||
#- changes:
|
||||
# - .gitlab-ci.yml
|
||||
rules:
|
||||
- changes:
|
||||
- .gitlab-ci.yml
|
||||
script:
|
||||
- ./deploy_packages.sh rockylinux 8
|
||||
needs:
|
||||
- remi-rocky8-package
|
||||
|
||||
remi-rocky9-deploy:
|
||||
extends: .deploy
|
||||
rules:
|
||||
- changes:
|
||||
- .gitlab-ci.yml
|
||||
script:
|
||||
- ./deploy_packages.sh rockylinux 9
|
||||
needs:
|
||||
- remi-rocky9-package
|
||||
|
||||
.deploy:
|
||||
stage: deploy
|
||||
tags: ["docker"]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,12 @@ rocky8-package:
|
|||
extends: .package
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/rocky8-php:$ROCKY_8_IMAGE_VERSION
|
||||
script:
|
||||
# We install this dependency only for the pipeline
|
||||
- dnf -y install https://rpms.remirepo.net/enterprise/remi-release-8.rpm
|
||||
- dnf -y module reset php
|
||||
- dnf -y module enable php:remi-8.2
|
||||
- dnf -y update php\*
|
||||
- dnf -y install php-sodium
|
||||
- make package-el8
|
||||
|
||||
rocky9-package:
|
||||
|
|
@ -12,28 +18,20 @@ rocky9-package:
|
|||
extends: .package
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/rocky9-php:$ROCKY_9_IMAGE_VERSION
|
||||
script:
|
||||
# We install this dependency only for the pipeline
|
||||
- dnf -y install https://rpms.remirepo.net/enterprise/remi-release-9.rpm
|
||||
- dnf -y module reset php
|
||||
- dnf -y module enable php:remi-8.2
|
||||
- dnf -y update php\*
|
||||
- dnf -y install php-sodium
|
||||
- make package-el9
|
||||
|
||||
rocky10-package:
|
||||
needs:
|
||||
- prepare-package
|
||||
extends: .package
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/rocky10-php:$ROCKY_10_IMAGE_VERSION
|
||||
script:
|
||||
- make package-el10
|
||||
|
||||
debian12-package:
|
||||
needs:
|
||||
- prepare-package
|
||||
extends: .debian_package
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/debian12-php:$DEBIAN_12_IMAGE_VERSION
|
||||
|
||||
debian13-package:
|
||||
needs:
|
||||
- prepare-package
|
||||
extends: .debian_package
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/debian13-php:$DEBIAN_13_IMAGE_VERSION
|
||||
|
||||
.debian_package:
|
||||
extends: .package
|
||||
script:
|
||||
|
|
@ -48,12 +46,21 @@ remi-rocky8-package:
|
|||
- dnf -y module reset redis
|
||||
- dnf -y install @redis:6
|
||||
|
||||
remi-rocky9-package:
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/rocky9-php:$ROCKY_9_IMAGE_VERSION
|
||||
extends: .remi-rocky-package
|
||||
variables:
|
||||
ROCKY_RELEASE: 9
|
||||
before_script:
|
||||
- dnf -y module reset redis
|
||||
- dnf -y install @redis:7
|
||||
|
||||
.remi-rocky-package:
|
||||
extends: .package
|
||||
rules:
|
||||
- if: $CI_COMMIT_REF_NAME =~ /^release/ || $CI_COMMIT_REF_NAME == "master"
|
||||
#- changes:
|
||||
# - .gitlab-ci.yml
|
||||
- changes:
|
||||
- .gitlab-ci.yml
|
||||
script:
|
||||
# Remi
|
||||
- mkdir -p $CI_PROJECT_DIR/build
|
||||
|
|
|
|||
|
|
@ -10,18 +10,12 @@ rocky9-test:
|
|||
needs:
|
||||
- rocky9-package
|
||||
|
||||
rocky10-test:
|
||||
extends: .rocky-test
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/rocky10-php:$ROCKY_10_IMAGE_VERSION
|
||||
needs:
|
||||
- rocky10-package
|
||||
|
||||
.rocky-test:
|
||||
extends: .test
|
||||
script:
|
||||
- yum -y localinstall build/*.rpm
|
||||
- cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi
|
||||
- composer install --ignore-platform-req=ext-sodium # Rocky 8 and 9 use the external library
|
||||
- composer install --ignore-platform-req=ext-sodium # Rocky 8 use the external library
|
||||
- vendor/bin/phpcs
|
||||
- vendor/bin/phpmd . ansi phpmd.xml
|
||||
- php artisan key:generate
|
||||
|
|
@ -33,16 +27,10 @@ debian12-test:
|
|||
needs:
|
||||
- debian12-package
|
||||
|
||||
debian13-test:
|
||||
extends: .debian-test
|
||||
image: gitlab.linphone.org:4567/bc/public/docker/debian13-php:$DEBIAN_13_IMAGE_VERSION
|
||||
needs:
|
||||
- debian13-package
|
||||
|
||||
.debian-test:
|
||||
extends: .test
|
||||
script:
|
||||
#- apt update
|
||||
- apt update
|
||||
- apt install -y ./build/*.deb
|
||||
- cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi
|
||||
- composer install
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
variables:
|
||||
ROCKY_8_IMAGE_VERSION: 20250702_171834_update_rocky8_dockerhub
|
||||
ROCKY_9_IMAGE_VERSION: 20250702_171314_update_rocky9_dockerhub
|
||||
ROCKY_10_IMAGE_VERSION: 20250908_164454_rocky10_first
|
||||
DEBIAN_12_IMAGE_VERSION: 20250908_154742_refresh_dependencies
|
||||
DEBIAN_13_IMAGE_VERSION: 20251204_115628_update_packages
|
||||
DEBIAN_12_IMAGE_VERSION: 20241204_162237_update_download_linphone_org
|
||||
PHP_REDIS_REMI_VERSION: php-pecl-redis6-6.1.0-1
|
||||
PHP_IGBINARY_REMI_VERSION: php-pecl-igbinary-3.2.16-2
|
||||
PHP_MSGPACK_REMI_VERSION: php-pecl-msgpack-2.2.0-3
|
||||
|
|
|
|||
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -4,21 +4,6 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
||||
|
||||
## [2.1]
|
||||
|
||||
### Added
|
||||
|
||||
- **Add CardDav servers** They can be configured in the administration panels and the API.
|
||||
- **Rockylinux 10 support** Packages are now available in the official repository
|
||||
- **Artisan cleanup script for statistics** Add an artisan console script to clear statistics after n days `app:clear-statistics {days} {--apply}`
|
||||
- **Add Voicemail features and related API endpoints** to integrate with `flexisip-voicemail`
|
||||
|
||||
### Changed
|
||||
|
||||
- **Contacts Lists** The Contacts Lists are now handled per Space. During the migration, if there is only one Space present, existing Contacts Lists are automatically attached to it, otherwise the first Super Space available is used. If they are then attached to the wrong Space you'll have to change directly their `space_id` value in the `contacts_lists` database table.
|
||||
- **PHP 8.2 minimum** Laravel and its dependencies were upgraded to version 11 as well.
|
||||
- **Logout the user when the password is correctly changed**
|
||||
|
||||
## [2.0]
|
||||
|
||||
### Added
|
||||
|
|
|
|||
10
INSTALL.md
10
INSTALL.md
|
|
@ -24,14 +24,6 @@ FlexiAPI is packaged for Debian and RedHat, you can setup those repositories usi
|
|||
|
||||
The `artisan` script is in the root directory of where the application is setup, with packages its often `/opt/belledonne-communications/share/flexisip-account-manager/flexiapi/`.
|
||||
|
||||
⚠️ If you want to enable JWT authentication the php-sodium dependency is required, on Rockylinux it is only available in the Remi repository in some cases. You can install it with the following steps:
|
||||
|
||||
dnf -y install https://rpms.remirepo.net/enterprise/remi-release-{rockylinux-release}.rpm
|
||||
dnf -y module reset php
|
||||
dnf -y module enable php:remi-{php-version}
|
||||
dnf -y update php\*
|
||||
dnf -y install php-sodium
|
||||
|
||||
# 2. Web server configuration
|
||||
|
||||
The package will deploy a `flexisip-account-manager.conf` file in the apache2 configuration directory.
|
||||
|
|
@ -39,8 +31,6 @@ This file can be loaded and configured in your specific VirtualHost configuratio
|
|||
|
||||
To know more about the web server configuration part, you can directly [visit the official Laravel installation documentation](https://laravel.com/docs/).
|
||||
|
||||
⚠️ The Account Manager is handling files upload, please ensure that you raised `upload_max_filesize` and `post_max_size` to a reasonable number in your `php.ini` file to prevent file upload errors.
|
||||
|
||||
# 3. .env file configuration
|
||||
|
||||
Complete all the variables in the `.env` file (from the `.env.example` one if you setup the instance manually) or by overwriting them in your Docker or web-server configuration.
|
||||
|
|
|
|||
21
Makefile
21
Makefile
|
|
@ -50,7 +50,7 @@ package-common:
|
|||
cp -R cron/ $(OUTPUT_DIR)/flexisip-account-manager/
|
||||
cp flexisip-account-manager.spec.run $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
|
||||
tar cf flexisip-account-manager.tar.gz -C $(OUTPUT_DIR) flexisip-account-manager
|
||||
tar cvf flexisip-account-manager.tar.gz -C $(OUTPUT_DIR) flexisip-account-manager
|
||||
mv flexisip-account-manager.tar.gz $(OUTPUT_DIR)/rpmbuild/SOURCES/flexisip-account-manager.tar.gz
|
||||
|
||||
package-end-common:
|
||||
|
|
@ -59,20 +59,15 @@ package-end-common:
|
|||
|
||||
rpm-el8-only:
|
||||
mkdir -p build
|
||||
sed -i 's/Requires:.*/Requires: php >= 8.2, php-gd, php-pdo, php-redis, php-mysqlnd, php-mbstring/g' $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
rpmbuild --quiet -bb --define 'dist .el8' --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
sed -i 's/Requires:.*/Requires: php >= 8.1, php-gd, php-pdo, php-redis, php-mysqlnd, php-mbstring/g' $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
rpmbuild -v -bb --define 'dist .el8' --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
@echo "📦✅ RPM el8 Package Created"
|
||||
|
||||
rpm-el9-only:
|
||||
mkdir -p build
|
||||
rpmbuild --quiet -bb --define 'dist .el9' --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
rpmbuild -v -bb --define 'dist .el9' --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
@echo "📦✅ RPM el9 Package Created"
|
||||
|
||||
rpm-el10-only:
|
||||
mkdir -p build
|
||||
rpmbuild --quiet -bb --define 'dist .el10' --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
@echo "📦✅ RPM el10 Package Created"
|
||||
|
||||
rpm-cleanup:
|
||||
@echo "🧹 Cleanup"
|
||||
mv rpmbuild/*/*.rpm build/.
|
||||
|
|
@ -81,11 +76,11 @@ rpm-cleanup:
|
|||
deb-only:
|
||||
mkdir -p build
|
||||
sed -i 's/posttrans/post/g' $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
rpmbuild --quiet -bb --with deb --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmfilename tmp.rpm" --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
rpmbuild -v -bb --with deb --define '_topdir $(OUTPUT_DIR)/rpmbuild' --define "_rpmfilename tmp.rpm" --define "_rpmdir $(OUTPUT_DIR)/rpmbuild" $(OUTPUT_DIR)/rpmbuild/SPECS/flexisip-account-manager.spec
|
||||
fakeroot alien -g -k --scripts $(OUTPUT_DIR)/rpmbuild/tmp.rpm
|
||||
rm -r $(OUTPUT_DIR)/rpmbuild
|
||||
rm -rf $(OUTPUT_DIR)/*.orig
|
||||
sed -i 's/Depends:.*/Depends: $${shlibs:Depends}, php (>= 8.2), php-xml, php-pdo, php-gd, php-redis, php-mysql, php-mbstring, php-sqlite3/g' $(OUTPUT_DIR)/bc-flexisip-account-manager*/debian/control
|
||||
sed -i 's/Depends:.*/Depends: $${shlibs:Depends}, php (>= 8.1), php-xml, php-pdo, php-gd, php-redis, php-mysql, php-mbstring, php-sqlite3/g' $(OUTPUT_DIR)/bc-flexisip-account-manager*/debian/control
|
||||
|
||||
cd `ls -rt $(OUTPUT_DIR) | tail -1` && dpkg-buildpackage --no-sign
|
||||
@echo "📦✅ DEB Package Created"
|
||||
|
|
@ -106,10 +101,6 @@ package-el9: rpm-el9-only rpm-cleanup cleanup-package-semvers package-end-common
|
|||
rpm-el9: prepare-common package-el9
|
||||
rpm-el9-dev: prepare-dev package-semvers package-common package-el9
|
||||
|
||||
package-el10: rpm-el10-only rpm-cleanup cleanup-package-semvers package-end-common
|
||||
rpm-el10: prepare-common package-el10
|
||||
rpm-el10-dev: prepare-dev package-semvers package-common package-el10
|
||||
|
||||
package-deb: deb-only cleanup-package-semvers package-end-common
|
||||
deb: prepare-common package-deb
|
||||
deb-dev: prepare-dev package-semvers package-common package-deb
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
* * * * * apache /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/artisan schedule:run >> /dev/null 2>&1
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/
|
||||
sudo -su www-data && php artisan accounts:clear-accounts-tombstones 7 --apply
|
||||
sudo -su www-data && php artisan accounts:clear-api-keys 60
|
||||
sudo -su www-data && php artisan accounts:clear-files 30 --apply
|
||||
sudo -su www-data && php artisan accounts:clear-unconfirmed 30 --apply
|
||||
sudo -su www-data && php artisan app:clear-statistics 30 --apply
|
||||
sudo -su www-data && php artisan digest:clear-nonces 60
|
||||
sudo -su www-data && php artisan accounts:clear-api-keys 60
|
||||
sudo -su www-data && php artisan accounts:clear-accounts-tombstones 7 --apply
|
||||
sudo -su www-data && php artisan accounts:clear-unconfirmed 30 --apply
|
||||
sudo -su www-data && php artisan spaces:expiration-emails
|
||||
sudo -su www-data && php artisan app:clear-statistics 30 --apply
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/
|
||||
php artisan accounts:clear-accounts-tombstones 7 --apply
|
||||
php artisan accounts:clear-api-keys 60
|
||||
php artisan accounts:clear-files 30 --apply
|
||||
php artisan accounts:clear-unconfirmed 30 --apply
|
||||
php artisan app:clear-statistics 30 --apply
|
||||
php artisan digest:clear-nonces 60
|
||||
php artisan accounts:clear-api-keys 60
|
||||
php artisan accounts:clear-accounts-tombstones 7 --apply
|
||||
php artisan accounts:clear-unconfirmed 30 --apply
|
||||
php artisan spaces:expiration-emails
|
||||
php artisan app:clear-statistics 30 --apply
|
||||
|
|
@ -23,8 +23,8 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Carbon\Carbon;
|
||||
|
||||
use Awobaz\Compoships\Compoships;
|
||||
|
|
@ -36,7 +36,7 @@ class Account extends Authenticatable
|
|||
use HasFactory;
|
||||
use Compoships;
|
||||
|
||||
protected $with = ['passwords', 'emailChangeCode', 'types', 'actions', 'dictionaryEntries', 'carddavServers'];
|
||||
protected $with = ['passwords', 'emailChangeCode', 'types', 'actions', 'dictionaryEntries'];
|
||||
protected $hidden = ['expire_time', 'pivot', 'currentProvisioningToken', 'currentRecoveryCode', 'dictionaryEntries'];
|
||||
protected $appends = ['realm', 'provisioning_token', 'provisioning_token_expire_at', 'dictionary'];
|
||||
protected $casts = [
|
||||
|
|
@ -73,9 +73,6 @@ class Account extends Authenticatable
|
|||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* config('app.sip_domain') is required for the Tests suit
|
||||
*/
|
||||
$builder->where('domain', config('app.sip_domain') ?? space()->domain);
|
||||
});
|
||||
}
|
||||
|
|
@ -134,23 +131,6 @@ class Account extends Authenticatable
|
|||
return $this->belongsToMany(Account::class, 'contacts', 'account_id', 'contact_id');
|
||||
}
|
||||
|
||||
public function files()
|
||||
{
|
||||
return $this->hasMany(AccountFile::class)->latest();
|
||||
}
|
||||
|
||||
public function voicemails()
|
||||
{
|
||||
return $this->hasMany(AccountFile::class)
|
||||
->whereIn('content_type', AccountFile::VOICEMAIL_CONTENTTYPES)
|
||||
->latest();
|
||||
}
|
||||
|
||||
public function uploadedVoicemails()
|
||||
{
|
||||
return $this->voicemails()->whereNotNull('name');
|
||||
}
|
||||
|
||||
public function vcardsStorage()
|
||||
{
|
||||
return $this->hasMany(VcardStorage::class);
|
||||
|
|
@ -166,12 +146,6 @@ class Account extends Authenticatable
|
|||
return $this->hasMany(AccountDictionaryEntry::class);
|
||||
}
|
||||
|
||||
public function carddavServers()
|
||||
{
|
||||
return $this->belongsToMany(SpaceCardDavServer::class, 'account_carddav_credentials', 'account_id', 'space_carddav_server_id')
|
||||
->withPivot('username', 'realm', 'algorithm', 'password');
|
||||
}
|
||||
|
||||
public function getDictionaryAttribute()
|
||||
{
|
||||
if ($this->dictionaryEntries->isEmpty()) return new stdClass;
|
||||
|
|
@ -344,15 +318,6 @@ class Account extends Authenticatable
|
|||
return null;
|
||||
}
|
||||
|
||||
public function getRemainingCardDavCredentialsCreatableAttribute(): Collection
|
||||
{
|
||||
return $this->space->carddavServers()->whereNotIn('id', function ($query) {
|
||||
$query->select('space_carddav_server_id')
|
||||
->from('account_carddav_credentials')
|
||||
->where('account_id', $this->id);
|
||||
})->get();
|
||||
}
|
||||
|
||||
public function getIdentifierAttribute(): string
|
||||
{
|
||||
return $this->attributes['username'] . '@' . $this->attributes['domain'];
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountCardDavCredentials extends Model
|
||||
{
|
||||
protected $table = 'account_carddav_credentials';
|
||||
|
||||
public function cardDavServer()
|
||||
{
|
||||
return $this->hasOne(SpaceCardDavServer::class, 'id', 'space_carddav_server_id');
|
||||
}
|
||||
|
||||
public function getIdentifierAttribute()
|
||||
{
|
||||
return $this->username . '@' . $this->domain;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class AccountFile extends Model
|
||||
{
|
||||
use HasUuids;
|
||||
|
||||
public const VOICEMAIL_CONTENTTYPES = ['audio/opus', 'audio/wav'];
|
||||
public const FILES_PATH = 'files';
|
||||
protected $hidden = ['account_id', 'updated_at', 'sending_by_mail_at', 'sent_by_mail_at', 'sending_by_mail_tryouts'];
|
||||
protected $appends = ['download_url'];
|
||||
protected $casts = [
|
||||
'uploaded_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::deleting(function (AccountFile $accountFile) {
|
||||
Storage::delete($accountFile->getPathAttribute());
|
||||
});
|
||||
}
|
||||
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class)->withoutGlobalScopes();
|
||||
}
|
||||
|
||||
public function getMaxUploadSizeAttribute(): ?int
|
||||
{
|
||||
return maxUploadSize();
|
||||
}
|
||||
|
||||
public function getUploadUrlAttribute(): ?string
|
||||
{
|
||||
return route('file.upload', $this->attributes['id']);
|
||||
}
|
||||
|
||||
public function getPathAttribute(): string
|
||||
{
|
||||
return self::FILES_PATH . '/' . $this->attributes['name'];
|
||||
}
|
||||
|
||||
public function getUrlAttribute(): ?string
|
||||
{
|
||||
return !empty($this->attributes['name'])
|
||||
&& !empty($this->attributes['id'])
|
||||
? replaceHost(
|
||||
route('file.show', ['uuid' => $this->attributes['id'], 'name' => $this->attributes['name']]),
|
||||
$this->account->space->host
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function getDownloadUrlAttribute(): ?string
|
||||
{
|
||||
return !empty($this->attributes['name'])
|
||||
&& !empty($this->attributes['id'])
|
||||
? replaceHost(route(
|
||||
'file.download',
|
||||
['uuid' => $this->attributes['id'], 'name' => $this->attributes['name']]
|
||||
), $this->account->space->host)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function isVoicemailAudio(): bool
|
||||
{
|
||||
return in_array($this->attributes['content_type'], self::VOICEMAIL_CONTENTTYPES);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,11 @@ class ClearAccountsTombstones extends Command
|
|||
protected $signature = 'accounts:clear-accounts-tombstones {days} {--apply}';
|
||||
protected $description = 'Clear deleted accounts tombstones after n days';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$tombstones = AccountTombstone::where(
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands\Accounts;
|
||||
|
||||
use App\AccountFile;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ClearFiles extends Command
|
||||
{
|
||||
protected $signature = 'accounts:clear-files {days} {--apply}';
|
||||
protected $description = 'Remove the uploaded files after n days';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$files = AccountFile::where(
|
||||
'created_at',
|
||||
'<',
|
||||
Carbon::now()->subDays($this->argument('days'))->toDateTimeString()
|
||||
);
|
||||
|
||||
$count = $files->count();
|
||||
|
||||
if ($this->option('apply')) {
|
||||
$this->info($count . ' files in deletion…');
|
||||
$files->delete();
|
||||
$this->info($count . ' files deleted');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
$this->info($count . ' files to delete');
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,11 @@ class ClearUnconfirmed extends Command
|
|||
protected $signature = 'accounts:clear-unconfirmed {days} {--apply} {--and-confirmed}';
|
||||
protected $description = 'Clear unconfirmed accounts after n days';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$accounts = Account::where(
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@ class CreateAdminTest extends Command
|
|||
protected $signature = 'accounts:create-admin-test';
|
||||
protected $description = 'Create a test admin account, only for tests purpose';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$username = 'admin_test';
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ class Seed extends Command
|
|||
protected $signature = 'accounts:seed {json-file-path}';
|
||||
protected $description = 'Seed some accounts from a JSON file';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$file = $this->argument('json-file-path');
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands\Accounts;
|
||||
|
||||
use App\AccountFile;
|
||||
use App\Mail\Voicemail;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class SendVoicemailsEmails extends Command
|
||||
{
|
||||
protected $signature = 'accounts:send-voicemails-emails {--tryout}';
|
||||
protected $description = 'Send the voicemail emails';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$voicemails = AccountFile::whereNotNull('uploaded_at')
|
||||
->whereNull('sent_by_mail_at')
|
||||
->where('sending_by_mail_tryouts', '<', is_int($this->option('tryout'))
|
||||
? $this->option('tryout')
|
||||
: 3)
|
||||
->get();
|
||||
|
||||
foreach ($voicemails as $voicemail) {
|
||||
$voicemail->sending_by_mail_at = Carbon::now();
|
||||
$voicemail->save();
|
||||
|
||||
if (Mail::to(users: $voicemail->account)->send(new Voicemail($voicemail))) {
|
||||
$voicemail->sent_by_mail_at = Carbon::now();
|
||||
$this->info('Voicemail sent to ' . $voicemail->account->identifier);
|
||||
} else {
|
||||
$voicemail->sending_by_mail_tryouts++;
|
||||
$this->info('Error sending voicemail to ' . $voicemail->account->identifier);
|
||||
}
|
||||
|
||||
$voicemail->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,11 @@ class SetAdmin extends Command
|
|||
protected $signature = 'accounts:set-admin {id}';
|
||||
protected $description = 'Give the admin role to an account';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$account = Account::withoutGlobalScopes()->where('id', $this->argument('id'))->first();
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\PhoneCountry;
|
||||
use Illuminate\Console\Command;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
|
||||
class UpdatePhoneCountries extends Command
|
||||
{
|
||||
protected $signature = 'app:update-phone-countries';
|
||||
protected $description = 'Update the phone_countries table from the getCountryCodes() function';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$phoneNumberUtils = PhoneNumberUtil::getInstance();
|
||||
$countryCodes = getCountryCodes();
|
||||
|
||||
foreach (array_diff(
|
||||
array_keys($countryCodes),
|
||||
PhoneCountry::pluck('code')->toArray()
|
||||
) as $code) {
|
||||
if ($resolvedMetadata = $phoneNumberUtils->getMetadataForRegion($code)) {
|
||||
$phoneCountry = new PhoneCountry();
|
||||
$phoneCountry->code = $code;
|
||||
$phoneCountry->country_code = $resolvedMetadata->getCountryCode();
|
||||
$phoneCountry->save();
|
||||
|
||||
$this->info($code . ' - ' . $countryCodes[$code] . ' inserted');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,9 +15,4 @@ class ContactsList extends Model
|
|||
{
|
||||
return $this->belongsToMany(Account::class, 'contacts_list_contact', 'contacts_list_id', 'contact_id');
|
||||
}
|
||||
|
||||
public function space()
|
||||
{
|
||||
return $this->belongsTo(Space::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use App\Account;
|
||||
|
|
@ -29,15 +28,24 @@ use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
|
|||
use League\CommonMark\Extension\TableOfContents\TableOfContentsExtension;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
function space(): ?Space
|
||||
$hostSpace = null;
|
||||
|
||||
function space($reload = false): ?Space
|
||||
{
|
||||
return is_object(request()->space) ? request()->space : null;
|
||||
global $hostSpace;
|
||||
|
||||
if ($hostSpace != null && $reload == false) {
|
||||
return $hostSpace;
|
||||
}
|
||||
|
||||
$hostSpace = Space::where('host', request()->host())->first();
|
||||
return $hostSpace;
|
||||
}
|
||||
|
||||
function passwordAlgorithms(): array
|
||||
{
|
||||
return [
|
||||
'MD5' => 'md5',
|
||||
'MD5' => 'md5',
|
||||
'SHA-256' => 'sha256',
|
||||
];
|
||||
}
|
||||
|
|
@ -101,7 +109,7 @@ function markdownDocumentationView(string $view): string
|
|||
$converter->getEnvironment()->addExtension(new TableOfContentsExtension());
|
||||
|
||||
return (string) $converter->convert(
|
||||
(string) view($view, [
|
||||
(string)view($view, [
|
||||
'app_name' => space()->name
|
||||
])->render()
|
||||
);
|
||||
|
|
@ -159,15 +167,7 @@ function resolveDomain(Request $request): string
|
|||
&& $request->user()
|
||||
&& $request->user()->superAdmin
|
||||
? $request->get('domain')
|
||||
: $request->space->domain;
|
||||
}
|
||||
|
||||
function maxUploadSize(): int
|
||||
{
|
||||
return min(
|
||||
ini_parse_quantity(ini_get('upload_max_filesize')),
|
||||
ini_parse_quantity(ini_get('post_max_size'))
|
||||
);
|
||||
: config('app.sip_domain');
|
||||
}
|
||||
|
||||
function captchaConfigured(): bool
|
||||
|
|
@ -214,7 +214,7 @@ function validateIsoDate($attribute, $value, $parameters, $validator): bool
|
|||
// Regex from https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/
|
||||
: '/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/';
|
||||
|
||||
return (bool) preg_match($regex, $value);
|
||||
return (bool)preg_match($regex, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -226,253 +226,236 @@ function validateIsoDate($attribute, $value, $parameters, $validator): bool
|
|||
function getCountryCodes()
|
||||
{
|
||||
return [
|
||||
'AD' => 'Andorra',
|
||||
'AE' => 'United Arab Emirates',
|
||||
'AF' => 'Afghanistan',
|
||||
'AG' => 'Antigua & Barbuda',
|
||||
'AI' => 'Anguilla',
|
||||
'AL' => 'Albania',
|
||||
'AM' => 'Armenia',
|
||||
'AO' => 'Angola',
|
||||
'AQ' => 'Antarctica',
|
||||
'AR' => 'Argentina',
|
||||
'AS' => 'American Samoa',
|
||||
'AT' => 'Austria',
|
||||
'AU' => 'Australia',
|
||||
'AW' => 'Aruba',
|
||||
'AX' => 'Åland Islands',
|
||||
'AL' => 'Albania',
|
||||
'DZ' => 'Algeria',
|
||||
'AS' => 'American Samoa',
|
||||
'AD' => 'Andorra',
|
||||
'AO' => 'Angola',
|
||||
'AI' => 'Anguilla',
|
||||
'AG' => 'Antigua & Barbuda',
|
||||
'AR' => 'Argentina',
|
||||
'AU' => 'Australia',
|
||||
'AT' => 'Austria',
|
||||
'AZ' => 'Azerbaijan',
|
||||
'BA' => 'Bosnia & Herzegovina',
|
||||
'BB' => 'Barbados',
|
||||
'BD' => 'Bangladesh',
|
||||
'BE' => 'Belgium',
|
||||
'BF' => 'Burkina Faso',
|
||||
'BG' => 'Bulgaria',
|
||||
'BH' => 'Bahrain',
|
||||
'BI' => 'Burundi',
|
||||
'BJ' => 'Benin',
|
||||
'BL' => 'St. Barthélemy',
|
||||
'BM' => 'Bermuda',
|
||||
'BN' => 'Brunei',
|
||||
'BO' => 'Bolivia',
|
||||
'BQ' => 'Bonaire, Sint Eustatius & Saba',
|
||||
'BR' => 'Brazil',
|
||||
'BS' => 'Bahamas',
|
||||
'BT' => 'Bhutan',
|
||||
'BV' => 'Bouvet Island',
|
||||
'BW' => 'Botswana',
|
||||
'BH' => 'Bahrain',
|
||||
'BD' => 'Bangladesh',
|
||||
'BB' => 'Barbados',
|
||||
'BY' => 'Belarus',
|
||||
'BE' => 'Belgium',
|
||||
'BZ' => 'Belize',
|
||||
'CA' => 'Canada',
|
||||
'CC' => 'Cocos (Keeling) Islands',
|
||||
'CD' => 'Congo - Kinshasa',
|
||||
'CF' => 'Central African Republic',
|
||||
'CG' => 'Congo - Brazzaville',
|
||||
'CH' => 'Switzerland',
|
||||
'CI' => "Côte d'Ivoire",
|
||||
'CK' => 'Cook Islands',
|
||||
'CL' => 'Chile',
|
||||
'BJ' => 'Benin',
|
||||
'BM' => 'Bermuda',
|
||||
'BT' => 'Bhutan',
|
||||
'BO' => 'Bolivia',
|
||||
'BA' => 'Bosnia & Herzegovina',
|
||||
'BW' => 'Botswana',
|
||||
'BR' => 'Brazil',
|
||||
'IO' => 'British Indian Ocean Territory',
|
||||
'BN' => 'Brunei',
|
||||
'BG' => 'Bulgaria',
|
||||
'BF' => 'Burkina Faso',
|
||||
'BI' => 'Burundi',
|
||||
'KH' => 'Cambodia',
|
||||
'CM' => 'Cameroon',
|
||||
'CA' => 'Canada',
|
||||
'CV' => 'Cape Verde',
|
||||
'KY' => 'Cayman Islands',
|
||||
'CF' => 'Central African Republic',
|
||||
'TD' => 'Chad',
|
||||
'CL' => 'Chile',
|
||||
'CN' => 'China',
|
||||
'CO' => 'Colombia',
|
||||
'CR' => 'Costa Rica',
|
||||
'CU' => 'Cuba',
|
||||
'CV' => 'Cabo Verde',
|
||||
'CW' => 'Curaçao',
|
||||
'CX' => 'Christmas Island',
|
||||
'CC' => 'Cocos (Keeling) Islands',
|
||||
'CO' => 'Colombia',
|
||||
'KM' => 'Comoros',
|
||||
'CG' => 'Congo - Brazzaville',
|
||||
'CD' => 'Congo - Kinshasa',
|
||||
'CK' => 'Cook Islands',
|
||||
'CR' => 'Costa Rica',
|
||||
'CI' => 'Côte d’Ivoire',
|
||||
'HR' => 'Croatia',
|
||||
'CU' => 'Cuba',
|
||||
'CY' => 'Cyprus',
|
||||
'CZ' => 'Czechia',
|
||||
'DE' => 'Germany',
|
||||
'DJ' => 'Djibouti',
|
||||
'DK' => 'Denmark',
|
||||
'DJ' => 'Djibouti',
|
||||
'DM' => 'Dominica',
|
||||
'DO' => 'Dominican Republic',
|
||||
'DZ' => 'Algeria',
|
||||
'EC' => 'Ecuador',
|
||||
'EE' => 'Estonia',
|
||||
'EG' => 'Egypt',
|
||||
'EH' => 'Western Sahara',
|
||||
'SV' => 'El Salvador',
|
||||
'GQ' => 'Equatorial Guinea',
|
||||
'ER' => 'Eritrea',
|
||||
'ES' => 'Spain',
|
||||
'EE' => 'Estonia',
|
||||
'ET' => 'Ethiopia',
|
||||
'FI' => 'Finland',
|
||||
'FJ' => 'Fiji',
|
||||
'FK' => 'Falkland Islands',
|
||||
'FM' => 'Micronesia',
|
||||
'FO' => 'Faroe Islands',
|
||||
'FJ' => 'Fiji',
|
||||
'FI' => 'Finland',
|
||||
'FR' => 'France',
|
||||
'GA' => 'Gabon',
|
||||
'GB' => 'United Kingdom',
|
||||
'GD' => 'Grenada',
|
||||
'GE' => 'Georgia',
|
||||
'GF' => 'French Guiana',
|
||||
'GG' => 'Guernsey',
|
||||
'PF' => 'French Polynesia',
|
||||
'GA' => 'Gabon',
|
||||
'GM' => 'Gambia',
|
||||
'GE' => 'Georgia',
|
||||
'DE' => 'Germany',
|
||||
'GH' => 'Ghana',
|
||||
'GI' => 'Gibraltar',
|
||||
'GL' => 'Greenland',
|
||||
'GM' => 'Gambia',
|
||||
'GN' => 'Guinea',
|
||||
'GP' => 'Guadeloupe',
|
||||
'GQ' => 'Equatorial Guinea',
|
||||
'GR' => 'Greece',
|
||||
'GS' => 'South Georgia & South Sandwich Islands',
|
||||
'GT' => 'Guatemala',
|
||||
'GL' => 'Greenland',
|
||||
'GD' => 'Grenada',
|
||||
'GP' => 'Guadeloupe',
|
||||
'GU' => 'Guam',
|
||||
'GT' => 'Guatemala',
|
||||
'GG' => 'Guernsey',
|
||||
'GN' => 'Guinea',
|
||||
'GW' => 'Guinea-Bissau',
|
||||
'GY' => 'Guyana',
|
||||
'HK' => 'Hong Kong',
|
||||
'HM' => 'Heard & McDonald Islands',
|
||||
'HN' => 'Honduras',
|
||||
'HR' => 'Croatia',
|
||||
'HT' => 'Haiti',
|
||||
'HN' => 'Honduras',
|
||||
'HK' => 'Hong Kong SAR China',
|
||||
'HU' => 'Hungary',
|
||||
'ID' => 'Indonesia',
|
||||
'IE' => 'Ireland',
|
||||
'IL' => 'Israel',
|
||||
'IM' => 'Isle of Man',
|
||||
'IN' => 'India',
|
||||
'IO' => 'British Indian Ocean Territory',
|
||||
'IQ' => 'Iraq',
|
||||
'IR' => 'Iran',
|
||||
'IS' => 'Iceland',
|
||||
'IN' => 'India',
|
||||
'ID' => 'Indonesia',
|
||||
'IR' => 'Iran',
|
||||
'IQ' => 'Iraq',
|
||||
'IE' => 'Ireland',
|
||||
'IM' => 'Isle of Man',
|
||||
'IL' => 'Israel',
|
||||
'IT' => 'Italy',
|
||||
'JE' => 'Jersey',
|
||||
'JM' => 'Jamaica',
|
||||
'JO' => 'Jordan',
|
||||
'JP' => 'Japan',
|
||||
'JE' => 'Jersey',
|
||||
'JO' => 'Jordan',
|
||||
'KZ' => 'Kazakhstan',
|
||||
'KE' => 'Kenya',
|
||||
'KG' => 'Kyrgyzstan',
|
||||
'KH' => 'Cambodia',
|
||||
'KI' => 'Kiribati',
|
||||
'KM' => 'Comoros',
|
||||
'KN' => 'St. Kitts & Nevis',
|
||||
'KP' => 'North Korea',
|
||||
'KR' => 'South Korea',
|
||||
'KW' => 'Kuwait',
|
||||
'KY' => 'Cayman Islands',
|
||||
'KZ' => 'Kazakhstan',
|
||||
'KG' => 'Kyrgyzstan',
|
||||
'LA' => 'Laos',
|
||||
'LV' => 'Latvia',
|
||||
'LB' => 'Lebanon',
|
||||
'LC' => 'St. Lucia',
|
||||
'LI' => 'Liechtenstein',
|
||||
'LK' => 'Sri Lanka',
|
||||
'LR' => 'Liberia',
|
||||
'LS' => 'Lesotho',
|
||||
'LR' => 'Liberia',
|
||||
'LY' => 'Libya',
|
||||
'LI' => 'Liechtenstein',
|
||||
'LT' => 'Lithuania',
|
||||
'LU' => 'Luxembourg',
|
||||
'LV' => 'Latvia',
|
||||
'LY' => 'Libya',
|
||||
'MA' => 'Morocco',
|
||||
'MC' => 'Monaco',
|
||||
'MD' => 'Moldova',
|
||||
'ME' => 'Montenegro',
|
||||
'MF' => 'St. Martin',
|
||||
'MG' => 'Madagascar',
|
||||
'MH' => 'Marshall Islands',
|
||||
'MO' => 'Macao SAR China',
|
||||
'MK' => 'North Macedonia',
|
||||
'MG' => 'Madagascar',
|
||||
'MW' => 'Malawi',
|
||||
'MY' => 'Malaysia',
|
||||
'MV' => 'Maldives',
|
||||
'ML' => 'Mali',
|
||||
'MM' => 'Myanmar',
|
||||
'MN' => 'Mongolia',
|
||||
'MO' => 'Macao',
|
||||
'MP' => 'Northern Mariana Islands',
|
||||
'MT' => 'Malta',
|
||||
'MH' => 'Marshall Islands',
|
||||
'MQ' => 'Martinique',
|
||||
'MR' => 'Mauritania',
|
||||
'MS' => 'Montserrat',
|
||||
'MT' => 'Malta',
|
||||
'MU' => 'Mauritius',
|
||||
'MV' => 'Maldives',
|
||||
'MW' => 'Malawi',
|
||||
'YT' => 'Mayotte',
|
||||
'MX' => 'Mexico',
|
||||
'MY' => 'Malaysia',
|
||||
'FM' => 'Micronesia',
|
||||
'MD' => 'Moldova',
|
||||
'MC' => 'Monaco',
|
||||
'MN' => 'Mongolia',
|
||||
'ME' => 'Montenegro',
|
||||
'MS' => 'Montserrat',
|
||||
'MA' => 'Morocco',
|
||||
'MZ' => 'Mozambique',
|
||||
'MM' => 'Myanmar (Burma)',
|
||||
'NA' => 'Namibia',
|
||||
'NC' => 'New Caledonia',
|
||||
'NE' => 'Niger',
|
||||
'NF' => 'Norfolk Island',
|
||||
'NG' => 'Nigeria',
|
||||
'NI' => 'Nicaragua',
|
||||
'NL' => 'Netherlands',
|
||||
'NO' => 'Norway',
|
||||
'NP' => 'Nepal',
|
||||
'NR' => 'Nauru',
|
||||
'NU' => 'Niue',
|
||||
'NP' => 'Nepal',
|
||||
'NL' => 'Netherlands',
|
||||
'NC' => 'New Caledonia',
|
||||
'NZ' => 'New Zealand',
|
||||
'NI' => 'Nicaragua',
|
||||
'NE' => 'Niger',
|
||||
'NG' => 'Nigeria',
|
||||
'NU' => 'Niue',
|
||||
'NF' => 'Norfolk Island',
|
||||
'MP' => 'Northern Mariana Islands',
|
||||
'NO' => 'Norway',
|
||||
'OM' => 'Oman',
|
||||
'PA' => 'Panama',
|
||||
'PE' => 'Peru',
|
||||
'PF' => 'French Polynesia',
|
||||
'PG' => 'Papua New Guinea',
|
||||
'PH' => 'Philippines',
|
||||
'PK' => 'Pakistan',
|
||||
'PL' => 'Poland',
|
||||
'PM' => 'St. Pierre & Miquelon',
|
||||
'PN' => 'Pitcairn Islands',
|
||||
'PR' => 'Puerto Rico',
|
||||
'PS' => 'Palestine',
|
||||
'PT' => 'Portugal',
|
||||
'PW' => 'Palau',
|
||||
'PS' => 'Palestinian Territories',
|
||||
'PA' => 'Panama',
|
||||
'PG' => 'Papua New Guinea',
|
||||
'PY' => 'Paraguay',
|
||||
'PE' => 'Peru',
|
||||
'PH' => 'Philippines',
|
||||
'PL' => 'Poland',
|
||||
'PT' => 'Portugal',
|
||||
'PR' => 'Puerto Rico',
|
||||
'QA' => 'Qatar',
|
||||
'RE' => 'Réunion',
|
||||
'RO' => 'Romania',
|
||||
'RS' => 'Serbia',
|
||||
'RU' => 'Russia',
|
||||
'RW' => 'Rwanda',
|
||||
'SA' => 'Saudi Arabia',
|
||||
'SB' => 'Solomon Islands',
|
||||
'SC' => 'Seychelles',
|
||||
'SD' => 'Sudan',
|
||||
'SE' => 'Sweden',
|
||||
'SG' => 'Singapore',
|
||||
'SH' => 'St. Helena',
|
||||
'SI' => 'Slovenia',
|
||||
'SJ' => 'Svalbard & Jan Mayen',
|
||||
'SK' => 'Slovakia',
|
||||
'SL' => 'Sierra Leone',
|
||||
'KN' => 'St. Kitts & Nevis',
|
||||
'LC' => 'St. Lucia',
|
||||
'PM' => 'St. Pierre & Miquelon',
|
||||
'VC' => 'St. Vincent & Grenadines',
|
||||
'WS' => 'Samoa',
|
||||
'SM' => 'San Marino',
|
||||
'SN' => 'Senegal',
|
||||
'SO' => 'Somalia',
|
||||
'SR' => 'Suriname',
|
||||
'SS' => 'South Sudan',
|
||||
'ST' => 'São Tomé & Príncipe',
|
||||
'SV' => 'El Salvador',
|
||||
'SX' => 'Sint Maarten',
|
||||
'SY' => 'Syria',
|
||||
'SA' => 'Saudi Arabia',
|
||||
'SN' => 'Senegal',
|
||||
'RS' => 'Serbia',
|
||||
'SC' => 'Seychelles',
|
||||
'SL' => 'Sierra Leone',
|
||||
'SG' => 'Singapore',
|
||||
'SK' => 'Slovakia',
|
||||
'SI' => 'Slovenia',
|
||||
'SB' => 'Solomon Islands',
|
||||
'SO' => 'Somalia',
|
||||
'ZA' => 'South Africa',
|
||||
'ES' => 'Spain',
|
||||
'LK' => 'Sri Lanka',
|
||||
'SD' => 'Sudan',
|
||||
'SR' => 'Suriname',
|
||||
'SJ' => 'Svalbard & Jan Mayen',
|
||||
'SZ' => 'Eswatini',
|
||||
'TC' => 'Turks & Caicos Islands',
|
||||
'TD' => 'Chad',
|
||||
'TF' => 'French Southern Territories',
|
||||
'TG' => 'Togo',
|
||||
'TH' => 'Thailand',
|
||||
'TJ' => 'Tajikistan',
|
||||
'TK' => 'Tokelau',
|
||||
'TL' => 'Timor-Leste',
|
||||
'TM' => 'Turkmenistan',
|
||||
'TN' => 'Tunisia',
|
||||
'TO' => 'Tonga',
|
||||
'TR' => 'Türkiye',
|
||||
'TT' => 'Trinidad & Tobago',
|
||||
'TV' => 'Tuvalu',
|
||||
'SE' => 'Sweden',
|
||||
'CH' => 'Switzerland',
|
||||
'SY' => 'Syria',
|
||||
'TW' => 'Taiwan',
|
||||
'TJ' => 'Tajikistan',
|
||||
'TZ' => 'Tanzania',
|
||||
'UA' => 'Ukraine',
|
||||
'TH' => 'Thailand',
|
||||
'TL' => 'Timor-Leste',
|
||||
'TG' => 'Togo',
|
||||
'TK' => 'Tokelau',
|
||||
'TO' => 'Tonga',
|
||||
'TT' => 'Trinidad & Tobago',
|
||||
'TN' => 'Tunisia',
|
||||
'TM' => 'Turkmenistan',
|
||||
'TC' => 'Turks & Caicos Islands',
|
||||
'TV' => 'Tuvalu',
|
||||
'UG' => 'Uganda',
|
||||
'UM' => 'U.S. Minor Outlying Islands',
|
||||
'UA' => 'Ukraine',
|
||||
'AE' => 'United Arab Emirates',
|
||||
'GB' => 'United Kingdom',
|
||||
'US' => 'United States',
|
||||
'UY' => 'Uruguay',
|
||||
'UZ' => 'Uzbekistan',
|
||||
'VA' => 'Holy See (Vatican City)',
|
||||
'VC' => 'St. Vincent & Grenadines',
|
||||
'VU' => 'Vanuatu',
|
||||
'VE' => 'Venezuela',
|
||||
'VN' => 'Vietnam',
|
||||
'VG' => 'British Virgin Islands',
|
||||
'VI' => 'U.S. Virgin Islands',
|
||||
'VN' => 'Vietnam',
|
||||
'VU' => 'Vanuatu',
|
||||
'WF' => 'Wallis & Futuna',
|
||||
'WS' => 'Samoa',
|
||||
'EH' => 'Western Sahara',
|
||||
'YE' => 'Yemen',
|
||||
'YT' => 'Mayotte',
|
||||
'ZA' => 'South Africa',
|
||||
'ZM' => 'Zambia',
|
||||
'ZW' => 'Zimbabwe',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Account;
|
||||
|
||||
use App\AccountFile;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function show(string $uuid, string $name)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
||||
if ($file->name != $name) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::get($file->path);
|
||||
}
|
||||
|
||||
public function download(string $uuid, string $name)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
||||
if ($file->name != $name) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::download($file->path);
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@ namespace App\Http\Controllers\Account;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PasswordController extends Controller
|
||||
|
|
@ -47,10 +46,12 @@ class PasswordController extends Controller
|
|||
|
||||
if ($account->passwords()->count() > 0) {
|
||||
Log::channel('events')->info('Web: Password changed', ['id' => $account->identifier]);
|
||||
return redirect()->route('account.logout');
|
||||
|
||||
return redirect()->route('account.dashboard');
|
||||
}
|
||||
|
||||
Log::channel('events')->info('Web: Password set for the first time', ['id' => $account->identifier]);
|
||||
return redirect()->route('account.logout');
|
||||
|
||||
return redirect()->route('account.dashboard');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ class ProvisioningController extends Controller
|
|||
private function checkProvisioningHeader(Request $request)
|
||||
{
|
||||
if (!$request->hasHeader('x-linphone-provisioning')
|
||||
&& $request->space->provisioning_use_linphone_provisioning_header) {
|
||||
&& space()?->provisioning_use_linphone_provisioning_header) {
|
||||
abort(400, 'x-linphone-provisioning header is missing');
|
||||
}
|
||||
}
|
||||
|
|
@ -172,8 +172,8 @@ class ProvisioningController extends Controller
|
|||
|
||||
$dom->appendChild($config);
|
||||
|
||||
if ($request->space?->custom_provisioning_entries) {
|
||||
$rc = parse_ini_string($request->space->custom_provisioning_entries, true);
|
||||
if (space()?->custom_provisioning_entries) {
|
||||
$rc = parse_ini_string(space()->custom_provisioning_entries, true);
|
||||
|
||||
foreach ($rc as $sectionName => $values) {
|
||||
$section = $dom->createElement('section');
|
||||
|
|
@ -189,44 +189,6 @@ class ProvisioningController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
$remoteContactDirectoryCounter = 0;
|
||||
$authInfoIndex = 0;
|
||||
|
||||
// CardDav servers
|
||||
|
||||
if ($request->space?->carddavServers) {
|
||||
foreach ($request->space->carddavServers as $carddavServer) {
|
||||
$carddavServer->getProvisioningSection($config, $remoteContactDirectoryCounter);
|
||||
$remoteContactDirectoryCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($account) {
|
||||
foreach ($account->carddavServers as $carddavServer) {
|
||||
$section = $dom->createElement('section');
|
||||
$section->setAttribute('name', 'auth_info_' . $authInfoIndex);
|
||||
$config->appendChild($section);
|
||||
|
||||
$entry = $dom->createElement('entry', $carddavServer->pivot->username);
|
||||
$entry->setAttribute('name', 'username');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $carddavServer->pivot->realm);
|
||||
$entry->setAttribute('name', 'realm');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $carddavServer->pivot->password);
|
||||
$entry->setAttribute('name', 'ha1');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $carddavServer->pivot->algorithm);
|
||||
$entry->setAttribute('name', 'algorithm');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$authInfoIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Password reset
|
||||
if ($account && $request->has('reset_password')) {
|
||||
$account->updatePassword(Str::random(10));
|
||||
|
|
@ -289,6 +251,7 @@ class ProvisioningController extends Controller
|
|||
}
|
||||
|
||||
$passwords = $account->passwords()->get();
|
||||
$authInfoIndex = 0;
|
||||
|
||||
foreach ($passwords as $password) {
|
||||
$section = $xpath->query("//section[@name='auth_info_" . $authInfoIndex . "']")->item(0);
|
||||
|
|
@ -334,7 +297,7 @@ class ProvisioningController extends Controller
|
|||
}
|
||||
|
||||
// Overwrite all the entries
|
||||
if ($request->space?->custom_provisioning_overwrite_all) {
|
||||
if (space()?->custom_provisioning_overwrite_all) {
|
||||
$xpath = new \DOMXpath($dom);
|
||||
$entries = $xpath->query("//section/entry");
|
||||
if (!is_null($entries)) {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Account;
|
|||
use App\ResetPasswordEmailToken;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class ResetPasswordEmailController extends Controller
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2023 Belledonne Communications SARL, All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountCardDavCredentials;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use App\Http\Requests\Account\CardDavCredentials;
|
||||
|
||||
class CardDavCredentialsController extends Controller
|
||||
{
|
||||
public function create(int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$this->checkFeatureEnabled($account);
|
||||
|
||||
return view('admin.account.carddav.create', [
|
||||
'account' => $account,
|
||||
'carddavServers' => $account->remainingCardDavCredentialsCreatable
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(CardDavCredentials $request, int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$this->checkFeatureEnabled($account);
|
||||
|
||||
$request->validate([
|
||||
'carddav_id' => ['required', Rule::exists('space_carddav_servers', 'id')->where(function (Builder $query) use ($account) {
|
||||
return $query->where('space_id', $account->space->id);
|
||||
})]
|
||||
]);
|
||||
|
||||
$accountCarddavCredentials = new AccountCardDavCredentials;
|
||||
$accountCarddavCredentials->space_carddav_server_id = $request->get('carddav_id');
|
||||
$accountCarddavCredentials->account_id = $account->id;
|
||||
$accountCarddavCredentials->username = $request->get('username');
|
||||
$accountCarddavCredentials->realm = $request->get('realm');
|
||||
$accountCarddavCredentials->password = bchash(
|
||||
$request->get('username'),
|
||||
$request->get('realm'),
|
||||
$request->get('password'),
|
||||
$request->get('algorithm')
|
||||
);
|
||||
$accountCarddavCredentials->algorithm = $request->get('algorithm');
|
||||
$accountCarddavCredentials->save();
|
||||
|
||||
return redirect()->route('admin.account.show', $account);
|
||||
}
|
||||
|
||||
public function delete(int $accountId, int $cardDavId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$this->checkFeatureEnabled($account);
|
||||
|
||||
$accountCarddavCredentials = AccountCardDavCredentials::where('space_carddav_server_id', $cardDavId)
|
||||
->where('account_id', $account->id)
|
||||
->firstOrFail();
|
||||
|
||||
return view('admin.account.carddav.delete', [
|
||||
'account' => $account,
|
||||
'carddavCredentials' => $accountCarddavCredentials,
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$this->checkFeatureEnabled($account);
|
||||
|
||||
$accountCarddavCredentials = AccountCardDavCredentials::where('space_carddav_server_id', $request->carddav_id)
|
||||
->where('account_id', $account->id)
|
||||
->delete();
|
||||
|
||||
return redirect()->route('admin.account.show', $account);
|
||||
}
|
||||
|
||||
private function checkFeatureEnabled(Account $account)
|
||||
{
|
||||
if (!$account->space->carddav_user_credentials) {
|
||||
abort(403, 'CardDav Credentials features disabled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
|
||||
use App\Account;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function delete(int $accountId, string $fileId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$file = $account->files()->where('id', $fileId)->firstOrFail();
|
||||
|
||||
return view('admin.account.file.delete', [
|
||||
'account' => $account,
|
||||
'file' => $file
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, string $fileId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$accountFile = $account->files()
|
||||
->where('id', $fileId)
|
||||
->firstOrFail();
|
||||
$accountFile->delete();
|
||||
|
||||
return redirect()->route('admin.account.show', $account)->withFragment('#files');
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -26,7 +26,7 @@ use Illuminate\Support\Facades\Log;
|
|||
use App\Account;
|
||||
use App\AccountType;
|
||||
|
||||
class AccountTypeController extends Controller
|
||||
class AccountAccountTypeController extends Controller
|
||||
{
|
||||
public function create(int $id)
|
||||
{
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -27,7 +27,7 @@ use App\Account;
|
|||
use App\AccountAction;
|
||||
use App\Rules\NoUppercase;
|
||||
|
||||
class ActionController extends Controller
|
||||
class AccountActionController extends Controller
|
||||
{
|
||||
public function create(int $accountId)
|
||||
{
|
||||
|
|
@ -17,13 +17,13 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
use App\Account;
|
||||
|
||||
class ActivityController extends Controller
|
||||
class AccountActivityController extends Controller
|
||||
{
|
||||
public function index(int $accountId)
|
||||
{
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -26,7 +26,7 @@ use Illuminate\Support\Facades\Log;
|
|||
use App\Account;
|
||||
use App\ContactsList;
|
||||
|
||||
class ContactController extends Controller
|
||||
class AccountContactController extends Controller
|
||||
{
|
||||
public function index(int $accountId)
|
||||
{
|
||||
|
|
@ -17,14 +17,14 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Libraries\FlexisipRedisConnector;
|
||||
|
||||
class DeviceController extends Controller
|
||||
class AccountDeviceController extends Controller
|
||||
{
|
||||
public function index(int $accountId)
|
||||
{
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -25,7 +25,7 @@ use Illuminate\Http\Request;
|
|||
use App\Account;
|
||||
use App\AccountDictionaryEntry;
|
||||
|
||||
class DictionaryController extends Controller
|
||||
class AccountDictionaryController extends Controller
|
||||
{
|
||||
public function create(int $accountId)
|
||||
{
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\ExternalAccount;
|
||||
|
|
@ -32,7 +32,7 @@ use Illuminate\Support\Facades\Storage;
|
|||
use Illuminate\Validation\Rules\File;
|
||||
use Propaganistas\LaravelPhone\PhoneNumber;
|
||||
|
||||
class ImportController extends Controller
|
||||
class AccountImportController extends Controller
|
||||
{
|
||||
private Collection $errors;
|
||||
private string $importDirectory = 'imported_csv';
|
||||
|
|
@ -307,7 +307,7 @@ class ImportController extends Controller
|
|||
'account_id' => $passwordAccount->id,
|
||||
'password' => bchash(
|
||||
$passwordAccount->username,
|
||||
$request->space?->account_realm ?? $domain,
|
||||
space()?->account_realm ?? $domain,
|
||||
$passwords[$passwordAccount->username],
|
||||
$algorithm
|
||||
),
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
|
@ -26,7 +26,7 @@ use App\StatisticsCall;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class StatisticsController extends Controller
|
||||
class AccountStatisticsController extends Controller
|
||||
{
|
||||
public function edit(Request $request, int $accountId)
|
||||
{
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -27,7 +27,7 @@ use Illuminate\Validation\Rule;
|
|||
use App\AccountType;
|
||||
use App\Rules\NoUppercase;
|
||||
|
||||
class TypeController extends Controller
|
||||
class AccountTypeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
|
|
@ -17,19 +17,18 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Space;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\ContactsList;
|
||||
use App\Space;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContactsListContactController extends Controller
|
||||
{
|
||||
public function add(Request $request, Space $space, int $contactsListId)
|
||||
public function add(Request $request, int $contactsListId)
|
||||
{
|
||||
$accounts = $space->accounts()->orderBy('updated_at', $request->get('updated_at_order', 'desc'));
|
||||
$accounts = Account::orderBy('updated_at', $request->get('updated_at_order', 'desc'));
|
||||
|
||||
if ($request->has('search')) {
|
||||
$accounts = $accounts->where('username', 'like', '%' . $request->get('search') . '%');
|
||||
|
|
@ -39,9 +38,9 @@ class ContactsListContactController extends Controller
|
|||
$accounts = $accounts->where('domain', $request->get('domain'));
|
||||
}
|
||||
|
||||
return view('admin.space.contacts_list.contacts.add', [
|
||||
'space' => $space,
|
||||
'contacts_list' => $space->contactsLists()->findOrFail($contactsListId),
|
||||
return view('admin.contacts_list.contacts.add', [
|
||||
'domains' => Account::groupBy('domain')->pluck('domain'),
|
||||
'contacts_list' => ContactsList::findOrFail($contactsListId),
|
||||
'params' => [
|
||||
'contacts_list_id' => $contactsListId
|
||||
],
|
||||
|
|
@ -53,33 +52,33 @@ class ContactsListContactController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function search(Request $request, Space $space, int $contactsListId)
|
||||
public function search(Request $request, int $contactsListId)
|
||||
{
|
||||
return redirect()->route('admin.spaces.contacts_lists.contacts.add', ['contacts_list_id' => $contactsListId] + $request->except('_token'));
|
||||
return redirect()->route('admin.contacts_lists.contacts.add', ['contacts_list_id' => $contactsListId] + $request->except('_token'));
|
||||
}
|
||||
|
||||
public function store(Request $request, Space $space, int $contactsListId)
|
||||
public function store(Request $request, int $contactsListId)
|
||||
{
|
||||
$request->validate([
|
||||
'contacts_ids' => 'required|exists:accounts,id'
|
||||
]);
|
||||
|
||||
$contactsList = $space->contactsLists()->findOrFail($contactsListId);
|
||||
$contactsList = ContactsList::findOrFail($contactsListId);
|
||||
$contactsList->contacts()->detach($request->get('contacts_ids')); // Just in case
|
||||
$contactsList->contacts()->attach($request->get('contacts_ids'));
|
||||
|
||||
return redirect()->route('admin.spaces.contacts_lists.edit', [$space, $contactsList->id]);
|
||||
return redirect()->route('admin.contacts_lists.edit', $contactsList->id);
|
||||
}
|
||||
|
||||
public function destroy(Request $request, Space $space, int $contactsListId)
|
||||
public function destroy(Request $request, int $contactsListId)
|
||||
{
|
||||
$request->validate([
|
||||
'contacts_ids' => 'required|exists:accounts,id'
|
||||
]);
|
||||
|
||||
$contactsList = $space->contactsLists()->findOrFail($contactsListId);
|
||||
$contactsList = ContactsList::findOrFail($contactsListId);
|
||||
$contactsList->contacts()->detach($request->get('contacts_ids'));
|
||||
|
||||
return redirect()->route('admin.spaces.contacts_lists.edit', [$space, $contactsList->id]);
|
||||
return redirect()->route('admin.contacts_lists.edit', $contactsList->id);
|
||||
}
|
||||
}
|
||||
|
|
@ -17,67 +17,61 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin\Space;
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\ContactsList;
|
||||
use App\Space;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContactsListController extends Controller
|
||||
{
|
||||
public function index(Request $request, Space $space)
|
||||
public function index(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'order_by' => 'in:title,updated_at,contacts_count',
|
||||
'order_sort' => 'in:asc,desc',
|
||||
]);
|
||||
|
||||
$contactsLists = $space->contactsLists()->orderBy($request->get('order_by', 'updated_at'), $request->get('order_sort', 'desc'));
|
||||
$contactsLists = ContactsList::orderBy($request->get('order_by', 'updated_at'), $request->get('order_sort', 'desc'));
|
||||
|
||||
return view('admin.space.contacts_list.index', [
|
||||
'space' => $space,
|
||||
return view('admin.contacts_list.index', [
|
||||
'contacts_lists' => $contactsLists
|
||||
->paginate(20)
|
||||
->appends($request->query()),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(Request $request, Space $space)
|
||||
public function create(Request $request)
|
||||
{
|
||||
return view('admin.space.contacts_list.create_edit', [
|
||||
'space' => $space,
|
||||
return view('admin.contacts_list.create_edit', [
|
||||
'contacts_list' => new ContactsList,
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request, Space $space)
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required|unique:contacts_lists'
|
||||
]);
|
||||
|
||||
$contactsList = new ContactsList;
|
||||
$contactsList->space_id = $space->id;
|
||||
$contactsList->title = $request->get('title');
|
||||
$contactsList->description = $request->get('description');
|
||||
$contactsList->save();
|
||||
|
||||
return redirect()->route('admin.spaces.contacts_lists.edit', [$space, $contactsList->id]);
|
||||
return redirect()->route('admin.contacts_lists.edit', $contactsList->id);
|
||||
}
|
||||
|
||||
public function search(Request $request, Space $space, int $contactsListId)
|
||||
public function search(Request $request, int $contactsListId)
|
||||
{
|
||||
return redirect()->route('admin.spaces.contacts_lists.edit', [
|
||||
'space' => $space,
|
||||
'contacts_list_id' => $contactsListId] + $request->except('_token'));
|
||||
return redirect()->route('admin.contacts_lists.edit', ['contacts_list_id' => $contactsListId] + $request->except('_token'));
|
||||
}
|
||||
|
||||
public function edit(Request $request, Space $space, int $id)
|
||||
public function edit(Request $request, int $id)
|
||||
{
|
||||
$contacts = $space->contactsLists()->findOrFail($id)->contacts();
|
||||
$contacts = ContactsList::findOrFail($id)->contacts();
|
||||
|
||||
if ($request->has('search')) {
|
||||
$contacts = $contacts->where('username', 'like', '%' . $request->get('search') . '%');
|
||||
|
|
@ -89,15 +83,14 @@ class ContactsListController extends Controller
|
|||
|
||||
$contacts = $contacts->get();
|
||||
|
||||
return view('admin.space.contacts_list.create_edit', [
|
||||
'space' => $space,
|
||||
return view('admin.contacts_list.create_edit', [
|
||||
'domains' => Account::groupBy('domain')->pluck('domain'),
|
||||
'contacts_list' => $space->contactsLists()->findOrFail($id),
|
||||
'contacts_list' => ContactsList::findOrFail($id),
|
||||
'contacts' => $contacts
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, Space $space, int $id)
|
||||
public function update(Request $request, int $id)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => [
|
||||
|
|
@ -106,27 +99,26 @@ class ContactsListController extends Controller
|
|||
],
|
||||
]);
|
||||
|
||||
$contactsList = $space->contactsLists()->findOrFail($id);
|
||||
$contactsList = ContactsList::findOrFail($id);
|
||||
$contactsList->title = $request->get('title');
|
||||
$contactsList->description = $request->get('description');
|
||||
$contactsList->save();
|
||||
|
||||
return redirect()->route('admin.spaces.contacts_lists.index', $space);
|
||||
return redirect()->route('admin.contacts_lists.index');
|
||||
}
|
||||
|
||||
public function delete(Space $space, int $id)
|
||||
public function delete(int $id)
|
||||
{
|
||||
return view('admin.space.contacts_list.delete', [
|
||||
'space' => $space,
|
||||
'contacts_list' => $space->contactsLists()->findOrFail($id),
|
||||
return view('admin.contacts_list.delete', [
|
||||
'contacts_list' => ContactsList::findOrFail($id),
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Request $request, Space $space)
|
||||
public function destroy(Request $request)
|
||||
{
|
||||
$contactsList = $space->contactsLists()->findOrFail($request->get('contacts_lists_id'));
|
||||
$contactsList = ContactsList::findOrFail($request->get('contacts_lists_id'));
|
||||
$contactsList->delete();
|
||||
|
||||
return redirect()->route('admin.spaces.contacts_lists.index', $space);
|
||||
return redirect()->route('admin.contacts_lists.index');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Space;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Space\CardDavServer;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Space;
|
||||
use App\SpaceCardDavServer;
|
||||
|
||||
class CardDavServerController extends Controller
|
||||
{
|
||||
public function create(Space $space)
|
||||
{
|
||||
return view('admin.space.carddav_server.create_edit', [
|
||||
'space' => $space,
|
||||
'carddavServer' => new SpaceCardDavServer
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(CardDavServer $request, Space $space)
|
||||
{
|
||||
$carddavServer = new SpaceCardDavServer;
|
||||
$carddavServer->space_id = $space->id;
|
||||
$carddavServer->fill($request->validated());
|
||||
$carddavServer->enabled = getRequestBoolean($request, 'enabled');
|
||||
$carddavServer->use_exact_match_policy = getRequestBoolean($request, 'use_exact_match_policy');
|
||||
$carddavServer->save();
|
||||
|
||||
return redirect()->route('admin.spaces.integration', $space);
|
||||
}
|
||||
|
||||
public function edit(Space $space, int $carddavServerId)
|
||||
{
|
||||
return view('admin.space.carddav_server.create_edit', [
|
||||
'space' => $space,
|
||||
'carddavServer' => $space->carddavServers()->findOrFail($carddavServerId)
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(CardDavServer $request, Space $space, int $carddavServerId)
|
||||
{
|
||||
$carddavServer = $space->carddavServers()->findOrFail($carddavServerId);
|
||||
$carddavServer->fill($request->validated());
|
||||
$carddavServer->enabled = getRequestBoolean($request, 'enabled');
|
||||
$carddavServer->use_exact_match_policy = getRequestBoolean($request, 'use_exact_match_policy');
|
||||
$carddavServer->save();
|
||||
|
||||
return redirect()->route('admin.spaces.integration', $space);
|
||||
}
|
||||
|
||||
public function delete(Space $space, int $carddavServerId)
|
||||
{
|
||||
return view('admin.space.carddav_server.delete', [
|
||||
'space' => $space,
|
||||
'carddavServer' => $space->carddavServers()->findOrFail($carddavServerId)
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Space $space, int $carddavServerId)
|
||||
{
|
||||
$carddavServer = $space->carddavServers()->findOrFail($carddavServerId);
|
||||
$carddavServer->delete();
|
||||
|
||||
return redirect()->route('admin.spaces.integration', $space->id);
|
||||
}
|
||||
}
|
||||
|
|
@ -146,7 +146,6 @@ class SpaceController extends Controller
|
|||
$space->expire_at = $request->get('expire_at');
|
||||
$space->custom_theme = getRequestBoolean($request, 'custom_theme');
|
||||
$space->web_panel = getRequestBoolean($request, 'web_panel');
|
||||
$space->carddav_user_credentials = getRequestBoolean($request, 'carddav_user_credentials');
|
||||
$space->save();
|
||||
|
||||
return redirect()->route('admin.spaces.show', $space);
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class StatisticsController extends Controller
|
|||
|
||||
$domain = $request->user()->superAdmin
|
||||
? $request->get('domain')
|
||||
: $request->space->domain;
|
||||
: $request->user()->domain;
|
||||
|
||||
if ($domain) {
|
||||
$fromQuery->where('to_domain', $domain);
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Account;
|
||||
|
||||
use App\AccountFile;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\AudioMime;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function upload(Request $request, string $uuid)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
||||
if (!empty($file->name)) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$request->validate(['file' => 'required|file']);
|
||||
|
||||
if ($file->isVoicemailAudio()) {
|
||||
$request->validate(['file' => [new AudioMime($file)]]);
|
||||
}
|
||||
|
||||
$uploadedFile = $request->file('file');
|
||||
$name = Str::random(8) . '_' . $uploadedFile->getClientOriginalName();
|
||||
|
||||
if ($uploadedFile->storeAs(AccountFile::FILES_PATH, $name)) {
|
||||
$file->name = $name;
|
||||
$file->size = $uploadedFile->getSize();
|
||||
$file->uploaded_at = Carbon::now();
|
||||
$file->save();
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
abort(503);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,12 +10,12 @@ class VcardsStorageController extends Controller
|
|||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return (new AdminVcardsStorageController)->index($request, $request->user()->id);
|
||||
return (new AdminVcardsStorageController)->index($request->user()->id);
|
||||
}
|
||||
|
||||
public function show(Request $request, string $uuid)
|
||||
{
|
||||
return (new AdminVcardsStorageController)->show($request, $request->user()->id, $uuid);
|
||||
return (new AdminVcardsStorageController)->show($request->user()->id, $uuid);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Account;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Controllers\Api\Admin\Account\VoicemailController as AdminVoicemailController;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class VoicemailController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return (new AdminVoicemailController)->index($request, $request->user()->id);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
return (new AdminVoicemailController)->store($request, $request->user()->id);
|
||||
}
|
||||
|
||||
public function show(Request $request, string $uuid)
|
||||
{
|
||||
return (new AdminVoicemailController)->show($request, $request->user()->id, $uuid);
|
||||
}
|
||||
|
||||
public function destroy(Request $request, string $uuid)
|
||||
{
|
||||
return (new AdminVoicemailController)->destroy($request, $request->user()->id, $uuid);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Account;
|
||||
use App\Space;
|
||||
use App\AccountCardDavCredentials;
|
||||
use App\SpaceCardDavServer;
|
||||
use App\Http\Requests\Account\CardDavCredentials;
|
||||
|
||||
class CardDavCredentialsController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$cardDavServers = $account->carddavServers;
|
||||
|
||||
if ($cardDavServers->isEmpty()) return new \stdClass;
|
||||
|
||||
return $cardDavServers->map(function ($cardDavServer) {
|
||||
return $this->extractCardDavServer($cardDavServer);
|
||||
})->keyBy('carddav_id');
|
||||
}
|
||||
|
||||
public function show(Request $request, int $accountId, int $cardDavServerId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$cardDavServer = $account->cardDavServers()->findOrFail($cardDavServerId);
|
||||
|
||||
return $this->extractCardDavServer($cardDavServer);
|
||||
}
|
||||
|
||||
public function update(CardDavCredentials $request, int $accountId, int $cardDavServerId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$cardDavServer = $request->space->cardDavServers()->findOrFail($cardDavServerId);
|
||||
|
||||
$accountCarddavCredentials = AccountCardDavCredentials::where('account_id', $account->id)
|
||||
->where('space_carddav_server_id', $cardDavServer->id)
|
||||
->delete();
|
||||
|
||||
$accountCarddavCredentials = new AccountCardDavCredentials;
|
||||
$accountCarddavCredentials->space_carddav_server_id = $cardDavServer->id;
|
||||
$accountCarddavCredentials->account_id = $account->id;
|
||||
$accountCarddavCredentials->username = $request->get('username');
|
||||
$accountCarddavCredentials->realm = $request->get('realm');
|
||||
$accountCarddavCredentials->password = bchash(
|
||||
$request->get('username'),
|
||||
$request->get('realm'),
|
||||
$request->get('password'),
|
||||
$request->get('algorithm')
|
||||
);
|
||||
$accountCarddavCredentials->algorithm = $request->get('algorithm');
|
||||
return $accountCarddavCredentials->save();
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, int $cardDavServerId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$cardDavServer = $account->cardDavServers()->findOrFail($cardDavServerId);
|
||||
|
||||
return $cardDavServer->delete();
|
||||
}
|
||||
|
||||
private function extractCardDavServer(SpaceCardDavServer $cardDavServer)
|
||||
{
|
||||
return [
|
||||
'carddav_id' => $cardDavServer->id,
|
||||
'username' => $cardDavServer->pivot->username,
|
||||
'realm' => $cardDavServer->pivot->realm,
|
||||
'algorithm' => $cardDavServer->pivot->algorithm,
|
||||
'password' => $cardDavServer->pivot->password,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountFile;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class VoicemailController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
{
|
||||
return Account::findOrFail($accountId)->voicemails;
|
||||
}
|
||||
|
||||
public function store(Request $request, int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$request->validate([
|
||||
'sip_from' => 'nullable|starts_with:sip',
|
||||
'content_type' => [
|
||||
'required',
|
||||
Rule::in(AccountFile::VOICEMAIL_CONTENTTYPES),
|
||||
]
|
||||
]);
|
||||
|
||||
$voicemail = new AccountFile;
|
||||
$voicemail->account_id = $account->id;
|
||||
$voicemail->sip_from = $request->get('sip_from');
|
||||
$voicemail->content_type = $request->get('content_type');
|
||||
$voicemail->save();
|
||||
|
||||
$voicemail->append(['upload_url', 'max_upload_size']);
|
||||
|
||||
return $voicemail;
|
||||
}
|
||||
|
||||
public function show(Request $request, int $accountId, string $uuid)
|
||||
{
|
||||
return Account::findOrFail($accountId)->voicemails()->where('id', $uuid)->firstOrFail();
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, string $uuid)
|
||||
{
|
||||
return Account::findOrFail($accountId)->voicemails()->where('id', $uuid)->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -17,32 +17,33 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountAction;
|
||||
use App\Rules\NoUppercase;
|
||||
|
||||
class ActionController extends Controller
|
||||
class AccountActionController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
public function index(int $id)
|
||||
{
|
||||
return $this->resolveAccount($request, $accountId)->actions;
|
||||
return $this->resolveAccount($id)->actions;
|
||||
}
|
||||
|
||||
public function get(Request $request, int $accountId, int $actionId)
|
||||
public function get(int $id, int $actionId)
|
||||
{
|
||||
return $this->resolveAccount($request, $accountId)
|
||||
return $this->resolveAccount($id)
|
||||
->actions()
|
||||
->where('id', $actionId)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
public function store(Request $request, int $accountId)
|
||||
public function store(Request $request, int $id)
|
||||
{
|
||||
$account = $this->resolveAccount($request, $accountId);
|
||||
$account = $this->resolveAccount($id);
|
||||
|
||||
$request->validate([
|
||||
'key' => ['required', 'alpha_dash', new NoUppercase],
|
||||
|
|
@ -58,9 +59,9 @@ class ActionController extends Controller
|
|||
return $accountAction;
|
||||
}
|
||||
|
||||
public function update(Request $request, int $accountId, int $actionId)
|
||||
public function update(Request $request, int $id, int $actionId)
|
||||
{
|
||||
$account = $this->resolveAccount($request, $accountId);
|
||||
$account = $this->resolveAccount($id);
|
||||
|
||||
$request->validate([
|
||||
'key' => ['alpha_dash', new NoUppercase],
|
||||
|
|
@ -78,17 +79,17 @@ class ActionController extends Controller
|
|||
return $accountAction;
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, int $actionId)
|
||||
public function destroy(int $id, int $actionId)
|
||||
{
|
||||
return $this->resolveAccount($request, $accountId)
|
||||
return $this->resolveAccount($id)
|
||||
->actions()
|
||||
->where('id', $actionId)
|
||||
->delete();
|
||||
}
|
||||
|
||||
private function resolveAccount(Request $request, int $accountId)
|
||||
private function resolveAccount(int $id)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($id);
|
||||
if ($account->dtmf_protocol == null) abort(403, 'DTMF Protocol must be configured');
|
||||
|
||||
return $account;
|
||||
|
|
@ -17,39 +17,40 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ContactController extends Controller
|
||||
use App\Account;
|
||||
|
||||
class AccountContactController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
public function index(int $id)
|
||||
{
|
||||
return $request->space->accounts()->findOrFail($accountId)->contacts;
|
||||
return Account::findOrFail($id)->contacts;
|
||||
}
|
||||
|
||||
public function show(Request $request, int $accountId, int $contactId)
|
||||
public function show(int $id, int $contactId)
|
||||
{
|
||||
return $request->space->accounts()->findOrFail($accountId)
|
||||
return Account::findOrFail($id)
|
||||
->contacts()
|
||||
->where('id', $contactId)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
public function add(Request $request, int $accountId, int $contactId)
|
||||
public function add(int $id, int $contactId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($id);
|
||||
$account->contacts()->detach($contactId);
|
||||
|
||||
if ($request->space->accounts()->findOrFail($contactId)) {
|
||||
if (Account::findOrFail($contactId)) {
|
||||
return $account->contacts()->attach($contactId);
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(Request $request, int $accountId, int $contactId)
|
||||
public function remove(int $id, int $contactId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($id);
|
||||
|
||||
if (!$account->contacts()->pluck('id')->contains($contactId)) {
|
||||
abort(404);
|
||||
|
|
@ -25,6 +25,7 @@ use Illuminate\Support\Str;
|
|||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountTombstone;
|
||||
use App\AccountType;
|
||||
use App\ContactsList;
|
||||
|
|
@ -34,23 +35,18 @@ use App\Http\Requests\Account\Update\Api\AsAdminRequest as ApiAsAdminRequest;
|
|||
use App\Mail\Provisioning;
|
||||
use App\Mail\ResetPassword;
|
||||
use App\Services\AccountService;
|
||||
use App\Space;
|
||||
|
||||
class AccountController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return $request->space->accounts()
|
||||
->without(['passwords', 'admin'])
|
||||
->with(['phoneChangeCode', 'emailChangeCode'])
|
||||
->paginate(20);
|
||||
return Account::without(['passwords', 'admin'])->with(['phoneChangeCode', 'emailChangeCode'])->paginate(20);
|
||||
}
|
||||
|
||||
public function show(Request $request, $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()
|
||||
->without(['passwords', 'admin'])
|
||||
->with(['phoneChangeCode', 'emailChangeCode'])
|
||||
->findOrFail($accountId);
|
||||
$account = Account::without(['passwords', 'admin'])->with(['phoneChangeCode', 'emailChangeCode'])->findOrFail($accountId);
|
||||
|
||||
if ($request->user()->admin) {
|
||||
if ($account->phoneChangeCode) {
|
||||
|
|
@ -65,29 +61,27 @@ class AccountController extends Controller
|
|||
return $account;
|
||||
}
|
||||
|
||||
public function search(Request $request, string $sip)
|
||||
public function search(string $sip)
|
||||
{
|
||||
$account = $request->space->accounts()->sip($sip)->first();
|
||||
$account = Account::sip($sip)->first();
|
||||
|
||||
if (!$account)
|
||||
abort(404, 'SIP address not found');
|
||||
if (!$account) abort(404, 'SIP address not found');
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
public function searchByEmail(Request $request, string $email)
|
||||
public function searchByEmail(string $email)
|
||||
{
|
||||
$account = $request->space->accounts()->where('email', $email)->first();
|
||||
$account = Account::where('email', $email)->first();
|
||||
|
||||
if (!$account)
|
||||
abort(404, 'Email address not found');
|
||||
if (!$account) abort(404, 'Email address not found');
|
||||
|
||||
return $account;
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
if (!$account->hasTombstone()) {
|
||||
$tombstone = new AccountTombstone();
|
||||
|
|
@ -101,9 +95,9 @@ class AccountController extends Controller
|
|||
Log::channel('events')->info('API Admin: Account destroyed', ['id' => $account->identifier]);
|
||||
}
|
||||
|
||||
public function activate(Request $request, int $accountId)
|
||||
public function activate(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->activated = true;
|
||||
$account->save();
|
||||
|
||||
|
|
@ -112,9 +106,9 @@ class AccountController extends Controller
|
|||
return $account;
|
||||
}
|
||||
|
||||
public function deactivate(Request $request, int $accountId)
|
||||
public function deactivate(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->activated = false;
|
||||
$account->save();
|
||||
|
||||
|
|
@ -123,9 +117,9 @@ class AccountController extends Controller
|
|||
return $account;
|
||||
}
|
||||
|
||||
public function block(Request $request, int $accountId)
|
||||
public function block(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->blocked = true;
|
||||
$account->save();
|
||||
|
||||
|
|
@ -134,9 +128,9 @@ class AccountController extends Controller
|
|||
return $account;
|
||||
}
|
||||
|
||||
public function unblock(Request $request, int $accountId)
|
||||
public function unblock(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->blocked = false;
|
||||
$account->save();
|
||||
|
||||
|
|
@ -145,9 +139,9 @@ class AccountController extends Controller
|
|||
return $account;
|
||||
}
|
||||
|
||||
public function provision(Request $request, int $accountId)
|
||||
public function provision(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
$account->provision();
|
||||
$account->save();
|
||||
|
||||
|
|
@ -170,56 +164,55 @@ class AccountController extends Controller
|
|||
return $account->makeVisible(['provisioning_token']);
|
||||
}
|
||||
|
||||
public function typeAdd(Request $request, int $accountId, int $typeId)
|
||||
public function typeAdd(int $accountId, int $typeId)
|
||||
{
|
||||
if ($request->space->accounts()->findOrFail($accountId)->types()->pluck('id')->contains($typeId)) {
|
||||
if (Account::findOrFail($accountId)->types()->pluck('id')->contains($typeId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (AccountType::findOrFail($typeId)) {
|
||||
return $request->space->accounts()->findOrFail($accountId)->types()->attach($typeId);
|
||||
return Account::findOrFail($accountId)->types()->attach($typeId);
|
||||
}
|
||||
}
|
||||
|
||||
public function typeRemove(Request $request, int $accountId, int $typeId)
|
||||
public function typeRemove(int $accountId, int $typeId)
|
||||
{
|
||||
if (!$request->space->accounts()->findOrFail($accountId)->types()->pluck('id')->contains($typeId)) {
|
||||
if (!Account::findOrFail($accountId)->types()->pluck('id')->contains($typeId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return $request->space->accounts()->findOrFail($accountId)->types()->detach($typeId);
|
||||
return Account::findOrFail($accountId)->types()->detach($typeId);
|
||||
}
|
||||
|
||||
public function contactsListAdd(Request $request, int $accountId, int $contactsListId)
|
||||
public function contactsListAdd(int $accountId, int $contactsListId)
|
||||
{
|
||||
if ($request->space->accounts()->findOrFail($accountId)->contactsLists()->pluck('id')->contains($contactsListId)) {
|
||||
if (Account::findOrFail($accountId)->contactsLists()->pluck('id')->contains($contactsListId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (ContactsList::findOrFail($contactsListId)) {
|
||||
return $request->space->accounts()->findOrFail($accountId)->contactsLists()->attach($contactsListId);
|
||||
return Account::findOrFail($accountId)->contactsLists()->attach($contactsListId);
|
||||
}
|
||||
}
|
||||
|
||||
public function contactsListRemove(Request $request, int $accountId, int $contactsListId)
|
||||
public function contactsListRemove(int $accountId, int $contactsListId)
|
||||
{
|
||||
if (!$request->space->accounts()->findOrFail($accountId)->contactsLists()->pluck('id')->contains($contactsListId)) {
|
||||
if (!Account::findOrFail($accountId)->contactsLists()->pluck('id')->contains($contactsListId)) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
return $request->space->accounts()->findOrFail($accountId)->contactsLists()->detach($contactsListId);
|
||||
return Account::findOrFail($accountId)->contactsLists()->detach($contactsListId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emails
|
||||
*/
|
||||
|
||||
public function sendProvisioningEmail(Request $request, int $accountId)
|
||||
public function sendProvisioningEmail(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
if (!$account->email)
|
||||
abort(403, 'No email configured');
|
||||
if (!$account->email) abort(403, 'No email configured');
|
||||
|
||||
$account->provision();
|
||||
|
||||
|
|
@ -228,12 +221,11 @@ class AccountController extends Controller
|
|||
Log::channel('events')->info('API: Sending provisioning email', ['id' => $account->identifier]);
|
||||
}
|
||||
|
||||
public function sendResetPasswordEmail(Request $request, int $accountId)
|
||||
public function sendResetPasswordEmail(int $accountId)
|
||||
{
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
if (!$account->email)
|
||||
abort(403, 'No email configured');
|
||||
if (!$account->email) abort(403, 'No email configured');
|
||||
|
||||
$resetPasswordEmail = new ResetPasswordEmailToken;
|
||||
$resetPasswordEmail->account_id = $account->id;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -26,7 +26,7 @@ use Illuminate\Support\Str;
|
|||
use App\AccountCreationToken;
|
||||
use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController;
|
||||
|
||||
class CreationTokenController extends Controller
|
||||
class AccountCreationTokenController extends Controller
|
||||
{
|
||||
public function create(Request $request)
|
||||
{
|
||||
|
|
@ -17,23 +17,23 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Account;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DictionaryController extends Controller
|
||||
class AccountDictionaryController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
public function index(int $accountId)
|
||||
{
|
||||
return $request->space->accounts()->findOrFail($accountId)->dictionary;
|
||||
return Account::findOrFail($accountId)->dictionary;
|
||||
}
|
||||
|
||||
public function show(Request $request, int $accountId, string $key)
|
||||
public function show(int $accountId, string $key)
|
||||
{
|
||||
return $request->space->accounts()
|
||||
->findOrFail($accountId)->dictionaryEntries()->where('key', $key)->first();
|
||||
return Account::findOrFail($accountId)->dictionaryEntries()->where('key', $key)->first();
|
||||
}
|
||||
|
||||
public function set(Request $request, int $accountId, string $key)
|
||||
|
|
@ -42,7 +42,7 @@ class DictionaryController extends Controller
|
|||
'value' => 'required'
|
||||
]);
|
||||
|
||||
$account = $request->space->accounts()->findOrFail($accountId);
|
||||
$account = Account::findOrFail($accountId);
|
||||
$result = $account->setDictionaryEntry($key, $request->get('value'));
|
||||
|
||||
if (function_exists('accountServiceAccountEditedHook')) {
|
||||
|
|
@ -53,15 +53,8 @@ class DictionaryController extends Controller
|
|||
return $result;
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, string $key)
|
||||
public function destroy(int $accountId, string $key)
|
||||
{
|
||||
return $request->space->accounts()
|
||||
->findOrFail($accountId)->dictionaryEntries()->where('key', $key)->delete();
|
||||
}
|
||||
|
||||
public function clear(Request $request, int $accountId)
|
||||
{
|
||||
return $request->space->accounts()
|
||||
->findOrFail($accountId)->dictionaryEntries()->delete();
|
||||
return Account::findOrFail($accountId)->dictionaryEntries()->where('key', $key)->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Account;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\NoUppercase;
|
||||
|
|
@ -25,7 +25,7 @@ use Illuminate\Http\Request;
|
|||
|
||||
use App\AccountType;
|
||||
|
||||
class TypeController extends Controller
|
||||
class AccountTypeController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
|
|
@ -17,8 +17,9 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Space;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\ContactsList;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -27,12 +28,12 @@ class ContactsListController extends Controller
|
|||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
return $request->space->contactsLists;
|
||||
return ContactsList::all();
|
||||
}
|
||||
|
||||
public function get(Request $request, int $contactsListId)
|
||||
public function get(int $contactsListId)
|
||||
{
|
||||
return $request->space->contactsLists()->findOrFail($contactsListId);
|
||||
return ContactsList::findOrFail($contactsListId);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
|
|
@ -43,7 +44,6 @@ class ContactsListController extends Controller
|
|||
]);
|
||||
|
||||
$contactsList = new ContactsList;
|
||||
$contactsList->space_id = $request->space->id;
|
||||
$contactsList->title = $request->get('title');
|
||||
$contactsList->description = $request->get('description');
|
||||
$contactsList->save();
|
||||
|
|
@ -59,7 +59,6 @@ class ContactsListController extends Controller
|
|||
]);
|
||||
|
||||
$contactsList = ContactsList::findOrFail($contactsListId);
|
||||
$contactsList->space_id = $request->space->id;
|
||||
$contactsList->title = $request->get('title');
|
||||
$contactsList->description = $request->get('description');
|
||||
$contactsList->save();
|
||||
|
|
@ -67,25 +66,25 @@ class ContactsListController extends Controller
|
|||
return $contactsList;
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $contactsListId)
|
||||
public function destroy(int $contactsListId)
|
||||
{
|
||||
return $request->space->contactsLists()->where('id', $contactsListId)
|
||||
return ContactsList::where('id', $contactsListId)
|
||||
->delete();
|
||||
}
|
||||
|
||||
public function contactAdd(Request $request, int $id, int $contactId)
|
||||
public function contactAdd(int $id, int $contactId)
|
||||
{
|
||||
$contactsList = $request->space->contactsLists()->findOrFail($id);
|
||||
$contactsList = ContactsList::findOrFail($id);
|
||||
$contactsList->contacts()->detach($contactId);
|
||||
|
||||
if ($request->space->accounts()->findOrFail($contactId)) {
|
||||
if (Account::findOrFail($contactId)) {
|
||||
return $contactsList->contacts()->attach($contactId);
|
||||
}
|
||||
}
|
||||
|
||||
public function contactRemove(Request $request, int $id, int $contactId)
|
||||
public function contactRemove(int $id, int $contactId)
|
||||
{
|
||||
$contactsList = $request->space->contactsLists()->findOrFail($id);
|
||||
$contactsList = ContactsList::findOrFail($id);
|
||||
|
||||
if (!$contactsList->contacts()->pluck('id')->contains($contactId)) {
|
||||
abort(404);
|
||||
|
|
@ -22,27 +22,21 @@ namespace App\Http\Controllers\Api\Admin;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Libraries\FlexisipRedisConnector;
|
||||
use App\Account;
|
||||
use Illuminate\Http\Request;
|
||||
use stdClass;
|
||||
|
||||
class DeviceController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
public function index(int $accountId)
|
||||
{
|
||||
$devices = (new FlexisipRedisConnector)->getDevices(
|
||||
$request->space->accounts()->findOrFail($accountId)->identifier
|
||||
);
|
||||
$devices = (new FlexisipRedisConnector)->getDevices(Account::findOrFail($accountId)->identifier);
|
||||
|
||||
return ($devices->isEmpty()) ? new stdClass : $devices;
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, string $uuid)
|
||||
public function destroy(int $accountId, string $uuid)
|
||||
{
|
||||
$connector = new FlexisipRedisConnector;
|
||||
|
||||
return $connector->deleteDevice(
|
||||
$request->space->accounts()->findOrFail($accountId)->identifier,
|
||||
$uuid
|
||||
);
|
||||
return $connector->deleteDevice(Account::findOrFail($accountId)->identifier, $uuid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Space;
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\EmailServer\CreateUpdate;
|
||||
|
|
@ -23,12 +23,16 @@ use App\Http\Controllers\Controller;
|
|||
use App\Http\Requests\ExternalAccount\CreateUpdate;
|
||||
use App\Services\AccountService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\ExternalAccount;
|
||||
use App\Account;
|
||||
|
||||
class ExternalAccountController extends Controller
|
||||
{
|
||||
public function show(Request $request, int $accountId)
|
||||
public function show(int $accountId)
|
||||
{
|
||||
return $request->space->accounts()->findOrFail($accountId)->external()->firstOrFail();
|
||||
return Account::findOrFail($accountId)->external()->firstOrFail();
|
||||
}
|
||||
|
||||
public function store(CreateUpdate $request, int $accountId)
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\PhoneCountry;
|
||||
|
||||
class PhoneCountryController extends Controller
|
||||
{
|
||||
public function activate(string $code)
|
||||
{
|
||||
$phoneCountry = PhoneCountry::where('code', $code)->firstOrFail();
|
||||
return PhoneCountry::where('country_code', $phoneCountry->country_code)->update(['activated' => true]);
|
||||
}
|
||||
|
||||
public function deactivate(string $code)
|
||||
{
|
||||
$phoneCountry = PhoneCountry::where('code', $code)->firstOrFail();
|
||||
return PhoneCountry::where('country_code', $phoneCountry->country_code)->update(['activated' => false]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin\Space;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Space\CardDavServer;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Space;
|
||||
use App\SpaceCardDavServer;
|
||||
|
||||
class CardDavServerController extends Controller
|
||||
{
|
||||
public function index(string $domain)
|
||||
{
|
||||
return Space::where('domain', $domain)->firstOrFail()->carddavServers;
|
||||
}
|
||||
|
||||
public function show(string $domain, int $carddavServerId)
|
||||
{
|
||||
return Space::where('domain', $domain)->firstOrFail()->carddavServers()->findOrFail($carddavServerId);
|
||||
}
|
||||
|
||||
public function store(CardDavServer $request, string $domain)
|
||||
{
|
||||
$space = Space::where('domain', $domain)->firstOrFail();
|
||||
|
||||
$carddavServer = new SpaceCardDavServer;
|
||||
$carddavServer->space_id = $space->id;
|
||||
$carddavServer->fill($request->validated());
|
||||
$carddavServer->enabled = $request->has('enabled') && (bool)$request->get('enabled');
|
||||
$carddavServer->use_exact_match_policy = $request->has('use_exact_match_policy') && (bool)$request->get('use_exact_match_policy');
|
||||
|
||||
return $carddavServer->save();
|
||||
}
|
||||
|
||||
public function update(CardDavServer $request, string $domain, int $carddavServerId)
|
||||
{
|
||||
$space = Space::where('domain', $domain)->firstOrFail();
|
||||
|
||||
$carddavServer = $space->carddavServers()->findOrFail($carddavServerId);
|
||||
$carddavServer->fill($request->validated());
|
||||
$carddavServer->enabled = $request->has('enabled') && (bool)$request->get('enabled');
|
||||
$carddavServer->use_exact_match_policy = $request->has('use_exact_match_policy') && (bool)$request->get('use_exact_match_policy');
|
||||
|
||||
return $carddavServer->save();
|
||||
}
|
||||
|
||||
public function destroy(string $domain, int $carddavServerId)
|
||||
{
|
||||
$space = Space::where('domain', $domain)->firstOrFail();
|
||||
|
||||
$carddavServer = $space->carddavServers()->findOrFail($carddavServerId);
|
||||
return $carddavServer->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -45,37 +45,38 @@ class SpaceController extends Controller
|
|||
]);
|
||||
|
||||
$space = new Space;
|
||||
$space->account_proxy_registrar_address = $request->get('account_proxy_registrar_address');
|
||||
$space->account_realm = $request->get('account_realm');
|
||||
$space->copyright_text = $request->get('copyright_text');
|
||||
$space->custom_provisioning_entries = $request->get('custom_provisioning_entries');
|
||||
$space->domain = $request->get('domain');
|
||||
$space->expire_at = $request->get('expire_at');
|
||||
$space->host = $request->get('host');
|
||||
$space->intro_registration_text = $request->get('intro_registration_text');
|
||||
$space->max_account = $request->get('max_account', 0);
|
||||
$space->max_accounts = $request->get('max_accounts', 0);
|
||||
$space->name = $request->get('name');
|
||||
$space->newsletter_registration_address = $request->get('newsletter_registration_address');
|
||||
$this->setRequestBoolean($request, $space, 'assistant_disable_qr_code');
|
||||
$this->setRequestBoolean($request, $space, 'assistant_hide_create_account');
|
||||
$this->setRequestBoolean($request, $space, 'assistant_hide_third_party_account');
|
||||
$this->setRequestBoolean($request, $space, 'carddav_user_credentials');
|
||||
$this->setRequestBoolean($request, $space, 'custom_provisioning_overwrite_all');
|
||||
$this->setRequestBoolean($request, $space, 'custom_theme');
|
||||
$this->setRequestBoolean($request, $space, 'disable_broadcast_feature');
|
||||
$this->setRequestBoolean($request, $space, 'disable_call_recordings_feature');
|
||||
$space->domain = $request->get('domain');
|
||||
$space->host = $request->get('host');
|
||||
$this->setRequestBoolean($request, $space, 'super');
|
||||
$this->setRequestBoolean($request, $space, 'disable_chat_feature');
|
||||
$this->setRequestBoolean($request, $space, 'disable_meetings_feature');
|
||||
$this->setRequestBoolean($request, $space, 'hide_account_settings');
|
||||
$this->setRequestBoolean($request, $space, 'disable_broadcast_feature');
|
||||
$this->setRequestBoolean($request, $space, 'hide_settings');
|
||||
$this->setRequestBoolean($request, $space, 'intercom_features');
|
||||
$this->setRequestBoolean($request, $space, 'hide_account_settings');
|
||||
$this->setRequestBoolean($request, $space, 'disable_call_recordings_feature');
|
||||
$this->setRequestBoolean($request, $space, 'only_display_sip_uri_username');
|
||||
$this->setRequestBoolean($request, $space, 'phone_registration');
|
||||
$this->setRequestBoolean($request, $space, 'assistant_hide_create_account');
|
||||
$this->setRequestBoolean($request, $space, 'assistant_disable_qr_code');
|
||||
$this->setRequestBoolean($request, $space, 'assistant_hide_third_party_account');
|
||||
$space->max_account = $request->get('max_account', 0);
|
||||
$space->max_accounts = $request->get('max_accounts', 0);
|
||||
$space->expire_at = $request->get('expire_at');
|
||||
|
||||
$space->copyright_text = $request->get('copyright_text');
|
||||
$space->intro_registration_text = $request->get('intro_registration_text');
|
||||
$space->newsletter_registration_address = $request->get('newsletter_registration_address');
|
||||
$space->account_proxy_registrar_address = $request->get('account_proxy_registrar_address');
|
||||
$space->account_realm = $request->get('account_realm');
|
||||
$space->custom_provisioning_entries = $request->get('custom_provisioning_entries');
|
||||
$this->setRequestBoolean($request, $space, 'custom_provisioning_overwrite_all');
|
||||
$this->setRequestBoolean($request, $space, 'provisioning_use_linphone_provisioning_header');
|
||||
$this->setRequestBoolean($request, $space, 'public_registration');
|
||||
$this->setRequestBoolean($request, $space, 'super');
|
||||
$this->setRequestBoolean($request, $space, 'custom_theme');
|
||||
$this->setRequestBoolean($request, $space, 'web_panel');
|
||||
$this->setRequestBoolean($request, $space, 'public_registration');
|
||||
$this->setRequestBoolean($request, $space, 'phone_registration');
|
||||
$this->setRequestBoolean($request, $space, 'intercom_features');
|
||||
|
||||
$space->save();
|
||||
|
||||
return $space->refresh();
|
||||
|
|
@ -89,30 +90,30 @@ class SpaceController extends Controller
|
|||
public function update(Request $request, string $domain)
|
||||
{
|
||||
$request->validate([
|
||||
'account_realm' => ['nullable', new Domain()],
|
||||
'assistant_disable_qr_code' => 'required|boolean',
|
||||
'assistant_hide_create_account' => 'required|boolean',
|
||||
'assistant_hide_third_party_account' => 'required|boolean',
|
||||
'carddav_user_credentials' => 'required|boolean',
|
||||
'custom_provisioning_entries' => ['nullable', new Ini(Space::FORBIDDEN_KEYS)],
|
||||
'custom_provisioning_overwrite_all' => 'required|boolean',
|
||||
'custom_theme' => 'required|boolean',
|
||||
'disable_broadcast_feature' => 'required|boolean',
|
||||
'disable_call_recordings_feature' => 'required|boolean',
|
||||
'super' => 'required|boolean',
|
||||
'disable_chat_feature' => 'required|boolean',
|
||||
'disable_meetings_feature' => 'required|boolean',
|
||||
'expire_at' => 'nullable|date|after_or_equal:today',
|
||||
'hide_account_settings' => 'required|boolean',
|
||||
'disable_broadcast_feature' => 'required|boolean',
|
||||
'hide_settings' => 'required|boolean',
|
||||
'intercom_features' => 'required|boolean',
|
||||
'hide_account_settings' => 'required|boolean',
|
||||
'disable_call_recordings_feature' => 'required|boolean',
|
||||
'only_display_sip_uri_username' => 'required|boolean',
|
||||
'assistant_hide_create_account' => 'required|boolean',
|
||||
'assistant_disable_qr_code' => 'required|boolean',
|
||||
'assistant_hide_third_party_account' => 'required|boolean',
|
||||
'max_account' => 'required|integer',
|
||||
'max_accounts' => 'required|integer',
|
||||
'only_display_sip_uri_username' => 'required|boolean',
|
||||
'phone_registration' => 'required|boolean',
|
||||
'expire_at' => 'nullable|date|after_or_equal:today',
|
||||
'account_realm' => ['nullable', new Domain()],
|
||||
|
||||
'custom_provisioning_entries' => ['nullable', new Ini(Space::FORBIDDEN_KEYS)],
|
||||
'custom_provisioning_overwrite_all' => 'required|boolean',
|
||||
'provisioning_use_linphone_provisioning_header' => 'required|boolean',
|
||||
'public_registration' => 'required|boolean',
|
||||
'super' => 'required|boolean',
|
||||
'custom_theme' => 'required|boolean',
|
||||
'web_panel' => 'required|boolean',
|
||||
'public_registration' => 'required|boolean',
|
||||
'phone_registration' => 'required|boolean',
|
||||
'intercom_features' => 'required|boolean',
|
||||
]);
|
||||
|
||||
$space = Space::where('domain', $domain)->firstOrFail();
|
||||
|
|
@ -131,33 +132,33 @@ class SpaceController extends Controller
|
|||
$space->name = $request->get('name');
|
||||
$space->host = $request->get('host');
|
||||
$space->super = $request->get('super');
|
||||
$space->account_proxy_registrar_address = $request->get('account_proxy_registrar_address');
|
||||
$space->account_realm = $request->get('account_realm');
|
||||
$space->assistant_disable_qr_code = $request->get('assistant_disable_qr_code');
|
||||
$space->assistant_hide_create_account = $request->get('assistant_hide_create_account');
|
||||
$space->assistant_hide_third_party_account = $request->get('assistant_hide_third_party_account');
|
||||
$space->copyright_text = $request->get('copyright_text');
|
||||
$space->carddav_user_credentials = $request->get('carddav_user_credentials');
|
||||
$space->custom_provisioning_entries = $request->get('custom_provisioning_entries');
|
||||
$space->custom_provisioning_overwrite_all = $request->get('custom_provisioning_overwrite_all');
|
||||
$space->custom_theme = $request->get('custom_theme');
|
||||
$space->disable_broadcast_feature = $request->get('disable_broadcast_feature');
|
||||
$space->disable_call_recordings_feature = $request->get('disable_call_recordings_feature');
|
||||
$space->disable_chat_feature = $request->get('disable_chat_feature');
|
||||
$space->disable_meetings_feature = $request->get('disable_meetings_feature');
|
||||
$space->expire_at = $request->get('expire_at');
|
||||
$space->hide_account_settings = $request->get('hide_account_settings');
|
||||
$space->disable_broadcast_feature = $request->get('disable_broadcast_feature');
|
||||
$space->hide_settings = $request->get('hide_settings');
|
||||
$space->intercom_features = $request->get('intercom_features');
|
||||
$space->intro_registration_text = $request->get('intro_registration_text');
|
||||
$space->hide_account_settings = $request->get('hide_account_settings');
|
||||
$space->disable_call_recordings_feature = $request->get('disable_call_recordings_feature');
|
||||
$space->only_display_sip_uri_username = $request->get('only_display_sip_uri_username');
|
||||
$space->assistant_hide_create_account = $request->get('assistant_hide_create_account');
|
||||
$space->assistant_disable_qr_code = $request->get('assistant_disable_qr_code');
|
||||
$space->assistant_hide_third_party_account = $request->get('assistant_hide_third_party_account');
|
||||
$space->max_account = $request->get('max_account', 0);
|
||||
$space->max_accounts = $request->get('max_accounts', 0);
|
||||
$space->expire_at = $request->get('expire_at');
|
||||
|
||||
$space->copyright_text = $request->get('copyright_text');
|
||||
$space->intro_registration_text = $request->get('intro_registration_text');
|
||||
$space->newsletter_registration_address = $request->get('newsletter_registration_address');
|
||||
$space->only_display_sip_uri_username = $request->get('only_display_sip_uri_username');
|
||||
$space->phone_registration = $request->get('phone_registration');
|
||||
$space->account_proxy_registrar_address = $request->get('account_proxy_registrar_address');
|
||||
$space->account_realm = $request->get('account_realm');
|
||||
$space->custom_provisioning_entries = $request->get('custom_provisioning_entries');
|
||||
$space->custom_provisioning_overwrite_all = $request->get('custom_provisioning_overwrite_all');
|
||||
$space->provisioning_use_linphone_provisioning_header = $request->get('provisioning_use_linphone_provisioning_header');
|
||||
$space->public_registration = $request->get('public_registration');
|
||||
$space->custom_theme = $request->get('custom_theme');
|
||||
$space->web_panel = $request->get('web_panel');
|
||||
$space->public_registration = $request->get('public_registration');
|
||||
$space->phone_registration = $request->get('phone_registration');
|
||||
$space->intercom_features = $request->get('intercom_features');
|
||||
|
||||
$space->save();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Account;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\Vcard;
|
||||
use App\VcardStorage;
|
||||
|
|
@ -29,15 +30,15 @@ use stdClass;
|
|||
|
||||
class VcardsStorageController extends Controller
|
||||
{
|
||||
public function index(Request $request, int $accountId)
|
||||
public function index(int $accountId)
|
||||
{
|
||||
$list = $request->space->accounts()->findOrFail($accountId)->vcardsStorage()->get()->keyBy('uuid');
|
||||
$list = Account::findOrFail($accountId)->vcardsStorage()->get()->keyBy('uuid');
|
||||
return $list->isEmpty() ? new stdClass : $list;
|
||||
}
|
||||
|
||||
public function show(Request $request, int $accountId, string $uuid)
|
||||
public function show(int $accountId, string $uuid)
|
||||
{
|
||||
return $request->space->accounts()->findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
|
||||
return Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
|
||||
}
|
||||
|
||||
public function store(Request $request, int $accountId)
|
||||
|
|
@ -47,14 +48,18 @@ class VcardsStorageController extends Controller
|
|||
]);
|
||||
|
||||
$vcardo = VObject\Reader::read($request->get('vcard'));
|
||||
$vcardoUID = substr($vcardo->UID, 9);
|
||||
|
||||
if ($request->space->accounts()->findOrFail($accountId)->vcardsStorage()->where('uuid', $vcardo->UID)->first()) {
|
||||
$request->merge(['uuid' => $vcardoUID]);
|
||||
$request->validate(['uuid' => 'uuid']);
|
||||
|
||||
if (Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $vcardoUID)->first()) {
|
||||
abort(409, 'Vcard already exists');
|
||||
}
|
||||
|
||||
$vcard = new VcardStorage();
|
||||
$vcard->account_id = $accountId;
|
||||
$vcard->uuid = $vcardo->UID;
|
||||
$vcard->uuid = $vcardoUID;
|
||||
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
|
||||
$vcard->save();
|
||||
|
||||
|
|
@ -63,17 +68,24 @@ class VcardsStorageController extends Controller
|
|||
|
||||
public function update(Request $request, int $accountId, string $uuid)
|
||||
{
|
||||
$request->merge(['uuid' => $uuid]);
|
||||
|
||||
$request->validate([
|
||||
'uuid' => 'uuid',
|
||||
'vcard' => ['required', new Vcard()]
|
||||
]);
|
||||
|
||||
$vcardo = VObject\Reader::read($request->get('vcard'));
|
||||
$vcardoUID = substr($vcardo->UID, 9);
|
||||
|
||||
if ($vcardo->UID != $uuid) {
|
||||
$request->merge(['vuuid' => $vcardoUID]);
|
||||
$request->validate(['vuuid' => 'uuid']);
|
||||
|
||||
if ($vcardoUID != $uuid) {
|
||||
abort(422, 'UUID should be the same');
|
||||
}
|
||||
|
||||
$vcard = $request->space->accounts()->findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
|
||||
$vcard = Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
|
||||
$vcard->vcard = preg_replace('/\r\n?/', "\n", $vcardo->serialize());
|
||||
$vcard->save();
|
||||
|
||||
|
|
@ -82,7 +94,10 @@ class VcardsStorageController extends Controller
|
|||
|
||||
public function destroy(Request $request, int $accountId, string $uuid)
|
||||
{
|
||||
$vcard = $request->space->accounts()->findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
|
||||
$request->merge(['uuid' => $uuid]);
|
||||
$request->validate(['uuid' => 'uuid']);
|
||||
|
||||
$vcard = Account::findOrFail($accountId)->vcardsStorage()->where('uuid', $uuid)->firstOrFail();
|
||||
|
||||
return $vcard->delete();
|
||||
}
|
||||
|
|
|
|||
116
flexiapi/app/Http/Kernel.php
Normal file
116
flexiapi/app/Http/Kernel.php
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 Belledonne Communications SARL, All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http;
|
||||
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
/**
|
||||
* The application's global HTTP middleware stack.
|
||||
*
|
||||
* These middleware are run during every request to your application.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\App\Http\Middleware\CheckForMaintenanceMode::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware groups.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\App\Http\Middleware\Localization::class,
|
||||
'space.check',
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'throttle:600,1', // move to 600 instead of 60
|
||||
'bindings',
|
||||
'validate_json',
|
||||
'localization',
|
||||
'space.check',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
*
|
||||
* These middleware may be assigned to groups or used individually.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewareAliases = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.admin' => \App\Http\Middleware\AuthenticateAdmin::class,
|
||||
'auth.super_admin' => \App\Http\Middleware\AuthenticateSuperAdmin::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'auth.digest_or_key' => \App\Http\Middleware\AuthenticateDigestOrKey::class,
|
||||
'auth.jwt' => \App\Http\Middleware\AuthenticateJWT::class,
|
||||
'auth.check_blocked' => \App\Http\Middleware\CheckBlocked::class,
|
||||
'validate_json' => \App\Http\Middleware\ValidateJSON::class,
|
||||
'web_panel_enabled' => \App\Http\Middleware\IsWebPanelEnabled::class,
|
||||
'public_registration' => \App\Http\Middleware\IsPublicRegistration::class,
|
||||
'phone_registration' => \App\Http\Middleware\IsPhoneRegistration::class,
|
||||
'intercom_features' => \App\Http\Middleware\IsIntercomFeatures::class,
|
||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'cookie' => \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
'cookie.encrypt' => \App\Http\Middleware\EncryptCookies::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'space.check' => \App\Http\Middleware\SpaceCheck::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'localization' => \App\Http\Middleware\Localization::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* The priority-sorted list of middleware.
|
||||
*
|
||||
* This forces non-global middleware to always be in the given order.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $middlewarePriority = [
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
\Illuminate\Auth\Middleware\Authorize::class,
|
||||
];
|
||||
}
|
||||
|
|
@ -29,9 +29,7 @@ class AuthenticateAdmin
|
|||
return redirect()->route('account.login');
|
||||
}
|
||||
|
||||
if (!$request->user()->admin
|
||||
|| (!$request->user()->superAdmin && $request->user()->domain != $request->space->domain)
|
||||
) {
|
||||
if (!$request->user()->admin) {
|
||||
return abort(403, 'Unauthorized area');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,20 +76,18 @@ class AuthenticateJWT
|
|||
}
|
||||
|
||||
$account = null;
|
||||
$identifierKey = config('services.jwt.sip_identifier');
|
||||
if ($identifierKey == '') $identifierKey = 'sip_identity';
|
||||
|
||||
if ($token->claims()->has($identifierKey)) {
|
||||
list($username, $domain) = parseSIP($token->claims()->get($identifierKey));
|
||||
if ($token->claims()->has(config('services.jwt.sip_identifier'))) {
|
||||
list($username, $domain) = parseSIP($token->claims()->get(config('services.jwt.sip_identifier')));
|
||||
|
||||
$account = Account::withoutGlobalScopes()
|
||||
->where('username', $username)
|
||||
->where('domain', $domain)
|
||||
->first();
|
||||
->where('username', $username)
|
||||
->where('domain', $domain)
|
||||
->first();
|
||||
} elseif ($token->claims()->has('email')) {
|
||||
$account = Account::withoutGlobalScopes()
|
||||
->where('email', $token->claims()->get('email'))
|
||||
->first();
|
||||
->where('email', $token->claims()->get('email'))
|
||||
->first();
|
||||
}
|
||||
|
||||
if (!$account) {
|
||||
|
|
@ -101,7 +99,8 @@ class AuthenticateJWT
|
|||
return $next($request);
|
||||
}
|
||||
|
||||
if (!empty(config('app.account_authentication_bearer'))
|
||||
if (
|
||||
!empty(config('app.account_authentication_bearer'))
|
||||
// Bypass the JWT auth if we have an API Key
|
||||
&& !$request->header('x-api-key')
|
||||
&& !$request->cookie('x-api-key')
|
||||
|
|
@ -131,7 +130,7 @@ class AuthenticateJWT
|
|||
$response = new Response();
|
||||
$response->header(
|
||||
'WWW-Authenticate',
|
||||
$bearer . 'error="' . $error . '", error_description="' . $description . '"'
|
||||
$bearer . 'error="' . $error . '", error_description="'. $description . '"'
|
||||
);
|
||||
$response->setStatusCode(401);
|
||||
|
||||
|
|
|
|||
17
flexiapi/app/Http/Middleware/CheckForMaintenanceMode.php
Normal file
17
flexiapi/app/Http/Middleware/CheckForMaintenanceMode.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
|
||||
|
||||
class CheckForMaintenanceMode extends Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be reachable while maintenance mode is enabled.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
}
|
||||
17
flexiapi/app/Http/Middleware/EncryptCookies.php
Normal file
17
flexiapi/app/Http/Middleware/EncryptCookies.php
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
|
||||
|
||||
class EncryptCookies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the cookies that should not be encrypted.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class IsCardDavCredentialsEnabled
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if ($request->space->carddav_user_credentials) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
abort(403, 'CardDav Credentials features disabled');
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ class IsIntercomFeatures
|
|||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if ($request->space->intercom_features) {
|
||||
if (space()?->intercom_features) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class IsPhoneRegistration
|
|||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if ($request->space->phone_registration) {
|
||||
if (space()?->phone_registration) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ class IsPublicRegistration
|
|||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if ($request->space?->public_registration) {
|
||||
if (space()?->public_registration) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
abort(404, 'Public registration disabled');
|
||||
return abort(404, 'Public registration disabled');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class IsWebPanelEnabled
|
|||
{
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if (!$request->expectsJson() && $request->space->web_panel) {
|
||||
if (!$request->expectsJson() && space()?->web_panel) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use App\Space;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
|
@ -16,16 +15,15 @@ class SpaceCheck
|
|||
abort(503, 'APP_ROOT_HOST is not configured');
|
||||
}
|
||||
|
||||
$space = Space::where('host', config('app.sip_domain') ?? request()->host())->first();
|
||||
$space = space(reload: true);
|
||||
|
||||
if ($space != null) {
|
||||
if (!str_ends_with($space->host, config('app.root_host'))) {
|
||||
abort(503, 'The APP_ROOT_HOST configured does not match with the current root domain');
|
||||
}
|
||||
|
||||
$request->merge(['space' => $space]);
|
||||
|
||||
Config::set('app.url', '://' . $space->host);
|
||||
Config::set('app.sip_domain', $space->domain);
|
||||
|
||||
if ($space->isExpired()) {
|
||||
abort($request->expectsJson() ? 403 : 490, 'The related Space has expired');
|
||||
|
|
|
|||
18
flexiapi/app/Http/Middleware/TrimStrings.php
Normal file
18
flexiapi/app/Http/Middleware/TrimStrings.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
|
||||
|
||||
class TrimStrings extends Middleware
|
||||
{
|
||||
/**
|
||||
* The names of the attributes that should not be trimmed.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
'password',
|
||||
'password_confirmation',
|
||||
];
|
||||
}
|
||||
28
flexiapi/app/Http/Middleware/TrustProxies.php
Normal file
28
flexiapi/app/Http/Middleware/TrustProxies.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Middleware\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
{
|
||||
/**
|
||||
* The trusted proxies for this application.
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
protected $proxies;
|
||||
|
||||
/**
|
||||
* The headers that should be used to detect proxies.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
||||
24
flexiapi/app/Http/Middleware/VerifyCsrfToken.php
Normal file
24
flexiapi/app/Http/Middleware/VerifyCsrfToken.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||
|
||||
class VerifyCsrfToken extends Middleware
|
||||
{
|
||||
/**
|
||||
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $addHttpCookie = true;
|
||||
|
||||
/**
|
||||
* The URIs that should be excluded from CSRF verification.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $except = [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2023 Belledonne Communications SARL, All rights reserved.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Space;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\EmailServer;
|
||||
use App\Rules\CommaList;
|
||||
|
||||
class CardDavServer extends FormRequest
|
||||
{
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'uri' => 'required|url',
|
||||
'min_characters' => 'integer|min:1',
|
||||
'results_limit' => 'integer|min:0',
|
||||
'timeout' => 'integer|min:1',
|
||||
'delay' => 'integer|min:100',
|
||||
'fields_for_user_input' => [new CommaList],
|
||||
'fields_for_domain' => [new CommaList],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ class StatisticsGraphFactory
|
|||
$toQuery = StatisticsMessage::query();
|
||||
|
||||
if (!Auth::user()?->superAdmin) {
|
||||
$fromQuery->where('from_domain', $this->request->space->domain);
|
||||
$fromQuery->where('from_domain', space()->domain);
|
||||
$toQuery->toDomain(space()->domain);
|
||||
} elseif ($this->domain) {
|
||||
$fromQuery->where('from_domain', $this->domain);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace App\Mail;
|
|||
use App\Space;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace App\Mail;
|
|||
use App\Account;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace App\Mail;
|
|||
use App\Account;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace App\Mail;
|
|||
use App\Account;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@
|
|||
namespace App\Mail;
|
||||
|
||||
use App\Account;
|
||||
use App\ResetPasswordEmailToken;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\AccountFile;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
|
||||
class Voicemail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public function __construct(public AccountFile $accountFile)
|
||||
{
|
||||
}
|
||||
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: $this->accountFile->account->space->name .
|
||||
': ' .
|
||||
__('New voice message from :sipfrom', ['sipfrom' => $this->accountFile->sip_from]),
|
||||
);
|
||||
}
|
||||
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'mails.voicemail',
|
||||
);
|
||||
}
|
||||
|
||||
public function attachments(): array
|
||||
{
|
||||
return [
|
||||
Attachment::fromStorage($this->accountFile->path)
|
||||
->withMime($this->accountFile->content_type)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use App\AccountFile;
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class AudioMime implements Rule
|
||||
{
|
||||
public function __construct(private AccountFile $accountFile)
|
||||
{
|
||||
}
|
||||
|
||||
public function passes($attribute, $file): bool
|
||||
{
|
||||
$mimeType = null;
|
||||
switch ($file->getMimeType()) {
|
||||
case 'audio/opus':
|
||||
$mimeType = 'audio/opus';
|
||||
break;
|
||||
|
||||
case 'audio/vnd.wave':
|
||||
case 'audio/wav':
|
||||
case 'audio/wave':
|
||||
case 'audio/x-wav':
|
||||
case 'audio/x-pn-wav':
|
||||
$mimeType = 'audio/wav';
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->accountFile->content_type == $mimeType;
|
||||
}
|
||||
|
||||
public function message()
|
||||
{
|
||||
return __('The file should have the declared mime-type');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use Respect\Validation\Validator;
|
||||
|
||||
class CommaList implements Rule
|
||||
{
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
preg_match_all('/[^, ]+/', $value, $matches);
|
||||
|
||||
return $value == null || (!empty($matches) && (implode(',', $matches[0]) == $value));
|
||||
}
|
||||
|
||||
public function message()
|
||||
{
|
||||
return 'The :attribute should be null or contain a list of words separated by commas without spaces';
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use Respect\Validation\Validator;
|
||||
use Propaganistas\LaravelPhone\PhoneNumber;
|
||||
|
||||
class IsNotPhoneNumber implements Rule
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ use Illuminate\Contracts\Validation\Rule;
|
|||
|
||||
class WithoutSpaces implements Rule
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
return preg_match('/^\S*$/u', $value);
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ class AccountService
|
|||
$account = new Account();
|
||||
$account->username = $request->get('username');
|
||||
$account->activated = false;
|
||||
$account->domain = $request->space->domain;
|
||||
$account->domain = space()->domain;
|
||||
$account->ip_address = $request->ip();
|
||||
$account->created_at = Carbon::now();
|
||||
$account->user_agent = $request->space->name;
|
||||
$account->user_agent = space()->name;
|
||||
$account->dtmf_protocol = $request->get('dtmf_protocol');
|
||||
|
||||
if ($request->asAdmin) {
|
||||
|
|
@ -73,7 +73,7 @@ class AccountService
|
|||
$account->display_name = $request->get('display_name');
|
||||
$account->activated = $request->has('activated') ? (bool)$request->get('activated') : false;
|
||||
$account->domain = resolveDomain($request);
|
||||
$account->user_agent = $request->header('User-Agent') ?? $request->space->name;
|
||||
$account->user_agent = $request->header('User-Agent') ?? space()->name;
|
||||
$account->admin = $request->has('admin') && (bool)$request->get('admin');
|
||||
|
||||
if (!$request->api && $request->has('role')) {
|
||||
|
|
@ -113,8 +113,8 @@ class AccountService
|
|||
);
|
||||
|
||||
if (!$request->api) {
|
||||
if (!empty($request->space?->newsletter_registration_address) && $request->has('newsletter')) {
|
||||
Mail::to($request->space->newsletter_registration_address)->send(new NewsletterRegistration($account));
|
||||
if (!empty(space()?->newsletter_registration_address) && $request->has('newsletter')) {
|
||||
Mail::to(space()->newsletter_registration_address)->send(new NewsletterRegistration($account));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,67 +21,52 @@ namespace App;
|
|||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class Space extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $with = ['emailServer', 'carddavServers'];
|
||||
protected $with = ['emailServer'];
|
||||
|
||||
public const FORBIDDEN_KEYS = [
|
||||
'account_proxy_registrar_address',
|
||||
'account_realm',
|
||||
'assistant_disable_qr_code',
|
||||
'assistant_hide_create_account',
|
||||
'assistant_hide_third_party_account',
|
||||
'copyright_text',
|
||||
'disable_broadcast_feature',
|
||||
'disable_call_recordings_feature',
|
||||
'disable_chat_feature',
|
||||
'disable_meetings_feature',
|
||||
'hide_account_settings',
|
||||
'hide_settings',
|
||||
'intro_registration_text',
|
||||
'disable_broadcast_feature',
|
||||
'max_account',
|
||||
'newsletter_registration_address',
|
||||
'hide_settings',
|
||||
'hide_account_settings',
|
||||
'disable_call_recordings_feature',
|
||||
'only_display_sip_uri_username',
|
||||
'assistant_hide_create_account',
|
||||
'assistant_disable_qr_code',
|
||||
'assistant_hide_third_party_account',
|
||||
'copyright_text',
|
||||
'intro_registration_text',
|
||||
'newsletter_registration_address',
|
||||
'account_proxy_registrar_address',
|
||||
'account_realm'
|
||||
];
|
||||
|
||||
protected $hidden = ['id'];
|
||||
protected $casts = [
|
||||
'assistant_disable_qr_code' => 'boolean',
|
||||
'assistant_hide_create_account' => 'boolean',
|
||||
'assistant_hide_third_party_account' => 'boolean',
|
||||
'carddav_user_credentials' => 'boolean',
|
||||
'disable_broadcast_feature' => 'boolean',
|
||||
'disable_call_recordings_feature' => 'boolean',
|
||||
'super' => 'boolean',
|
||||
'disable_chat_feature' => 'boolean',
|
||||
'disable_meetings_feature' => 'boolean',
|
||||
'expire_at' => 'date',
|
||||
'hide_account_settings' => 'boolean',
|
||||
'disable_broadcast_feature' => 'boolean',
|
||||
'hide_settings' => 'boolean',
|
||||
'hide_account_settings' => 'boolean',
|
||||
'disable_call_recordings_feature' => 'boolean',
|
||||
'only_display_sip_uri_username' => 'boolean',
|
||||
'super' => 'boolean',
|
||||
'assistant_hide_create_account' => 'boolean',
|
||||
'assistant_disable_qr_code' => 'boolean',
|
||||
'assistant_hide_third_party_account' => 'boolean',
|
||||
'expire_at' => 'date',
|
||||
];
|
||||
|
||||
public const HOST_REGEX = '[\w\-]+';
|
||||
public const DOMAIN_REGEX = '(?=^.{4,253}$)(^((?!-)[a-z0-9-]{1,63}(?<!-)\.)+[a-z]{2,63}$)';
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::addGlobalScope('domain', function (Builder $builder) {
|
||||
if (!Auth::hasUser()) return;
|
||||
|
||||
if (Auth::hasUser() || Auth::user()->superAdmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
$builder->where('domain', Auth::user()->domain);
|
||||
});
|
||||
}
|
||||
|
||||
public function accounts()
|
||||
{
|
||||
return $this->hasMany(Account::class, 'domain', 'domain');
|
||||
|
|
@ -97,16 +82,6 @@ class Space extends Model
|
|||
return $this->hasOne(SpaceEmailServer::class);
|
||||
}
|
||||
|
||||
public function carddavServers()
|
||||
{
|
||||
return $this->hasMany(SpaceCardDavServer::class);
|
||||
}
|
||||
|
||||
public function contactsLists()
|
||||
{
|
||||
return $this->hasMany(ContactsList::class);
|
||||
}
|
||||
|
||||
public function scopeNotFull(Builder $query)
|
||||
{
|
||||
return $query->where('max_accounts', 0)
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SpaceCardDavServer extends Model
|
||||
{
|
||||
protected $hidden = ['space_id'];
|
||||
protected $table = 'space_carddav_servers';
|
||||
protected $fillable = ['uri', 'enabled', 'min_characters', 'results_limist', 'use_exact_match_policy', 'timeout', 'delay', 'fields_for_user_input', 'fields_for_domain'];
|
||||
|
||||
protected $casts = [
|
||||
'enabled' => 'boolean',
|
||||
'use_exact_match_policy' => 'boolean',
|
||||
];
|
||||
|
||||
public function space()
|
||||
{
|
||||
return $this->belongsTo(Space::class);
|
||||
}
|
||||
|
||||
public function accounts()
|
||||
{
|
||||
return $this->belongsToMany(Account::class, 'account_carddav_credentials', 'space_carddav_server_id', 'account_id');
|
||||
}
|
||||
|
||||
public function getNameAttribute()
|
||||
{
|
||||
return __('CardDav Server') . ' ' . $this->id;
|
||||
}
|
||||
|
||||
public function getProvisioningSection($config, int $remoteContactDirectoryCounter)
|
||||
{
|
||||
$dom = $config->ownerDocument;
|
||||
|
||||
$section = $dom->createElement('section');
|
||||
$section->setAttribute('name', 'remote_contact_directory_' . $remoteContactDirectoryCounter);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->enabled ? '1': '0');
|
||||
$entry->setAttribute('name', 'enabled');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', 'carddav');
|
||||
$entry->setAttribute('name', 'type');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->uri);
|
||||
$entry->setAttribute('name', 'uri');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->min_characters);
|
||||
$entry->setAttribute('name', 'min_characters');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->results_limit);
|
||||
$entry->setAttribute('name', 'results_limit');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->timeout);
|
||||
$entry->setAttribute('name', 'timeout');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->delay);
|
||||
$entry->setAttribute('name', 'delay');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->fields_for_user_input);
|
||||
$entry->setAttribute('name', 'carddav_fields_for_user_input');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->fields_for_domain);
|
||||
$entry->setAttribute('name', 'carddav_fields_for_domain');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$entry = $dom->createElement('entry', $this->use_exact_match_policy ? '1': '0');
|
||||
$entry->setAttribute('name', 'carddav_use_exact_match_policy');
|
||||
$section->appendChild($entry);
|
||||
|
||||
$config->appendChild($section);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,53 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
// Register the Composer autoloader...
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register The Auto Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Composer provides a convenient, automatically generated class loader
|
||||
| for our application. We just need to utilize it! We'll require it
|
||||
| into the script here so that we do not have to worry about the
|
||||
| loading of any our classes "manually". Feels great to relax.
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
// Bootstrap Laravel and handle the command...
|
||||
/** @var Application $app */
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
$status = $app->handleCommand(new ArgvInput);
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Run The Artisan Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When we run the console application, the current CLI command will be
|
||||
| executed in this console and the response sent back to a terminal
|
||||
| or another output device for the developers. Here goes nothing!
|
||||
|
|
||||
*/
|
||||
|
||||
exit($status);
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
|
||||
$status = $kernel->handle(
|
||||
$input = new Symfony\Component\Console\Input\ArgvInput,
|
||||
new Symfony\Component\Console\Output\ConsoleOutput
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Shutdown The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Once Artisan has finished running, we will fire off the shutdown events
|
||||
| so that any final work may be done by the application before we shut
|
||||
| down the process. This is the last thing to happen to the request.
|
||||
|
|
||||
*/
|
||||
|
||||
$kernel->terminate($input, $status);
|
||||
|
||||
exit($status);
|
||||
|
|
|
|||
|
|
@ -1,50 +1,55 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Middleware\Authenticate;
|
||||
use App\Http\Middleware\AuthenticateAdmin;
|
||||
use App\Http\Middleware\AuthenticateDigestOrKey;
|
||||
use App\Http\Middleware\AuthenticateJWT;
|
||||
use App\Http\Middleware\AuthenticateSuperAdmin;
|
||||
use App\Http\Middleware\CheckBlocked;
|
||||
use App\Http\Middleware\IsCardDavCredentialsEnabled;
|
||||
use App\Http\Middleware\IsIntercomFeatures;
|
||||
use App\Http\Middleware\IsPhoneRegistration;
|
||||
use App\Http\Middleware\IsPublicRegistration;
|
||||
use App\Http\Middleware\IsWebPanelEnabled;
|
||||
use App\Http\Middleware\Localization;
|
||||
use App\Http\Middleware\SpaceCheck;
|
||||
use App\Http\Middleware\ValidateJSON;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Create The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The first thing we will do is create a new Laravel application instance
|
||||
| which serves as the "glue" for all the components of Laravel, and is
|
||||
| the IoC container for the system binding all of the various parts.
|
||||
|
|
||||
*/
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web: __DIR__ . '/../routes/web.php',
|
||||
commands: __DIR__ . '/../routes/console.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
$middleware->append(SpaceCheck::class);
|
||||
$middleware->append(Localization::class);
|
||||
$middleware->api(append: [ValidateJSON::class]);
|
||||
$app = new Illuminate\Foundation\Application(
|
||||
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
|
||||
);
|
||||
|
||||
$middleware->alias([
|
||||
'auth.admin' => AuthenticateAdmin::class,
|
||||
'auth.check_blocked' => CheckBlocked::class,
|
||||
'auth.digest_or_key' => AuthenticateDigestOrKey::class,
|
||||
'auth.jwt' => AuthenticateJWT::class,
|
||||
'auth.super_admin' => AuthenticateSuperAdmin::class,
|
||||
'auth' => Authenticate::class,
|
||||
'feature.carddav_user_credentials' => IsCardDavCredentialsEnabled::class,
|
||||
'feature.intercom' => IsIntercomFeatures::class,
|
||||
'feature.phone_registration' => IsPhoneRegistration::class,
|
||||
'feature.public_registration' => IsPublicRegistration::class,
|
||||
'feature.web_panel_enabled' => IsWebPanelEnabled::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions) {
|
||||
//
|
||||
})->create();
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bind Important Interfaces
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, we need to bind some important interfaces into the container so
|
||||
| we will be able to resolve them when needed. The kernels serve the
|
||||
| incoming requests to this application from both the web and CLI.
|
||||
|
|
||||
*/
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Http\Kernel::class,
|
||||
App\Http\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Console\Kernel::class,
|
||||
App\Console\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Debug\ExceptionHandler::class,
|
||||
App\Exceptions\Handler::class
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Return The Application
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This script returns the application instance. The instance is given to
|
||||
| the calling script so we can separate the building of the instances
|
||||
| from the actual running of the application and sending responses.
|
||||
|
|
||||
*/
|
||||
|
||||
return $app;
|
||||
|
|
|
|||
|
|
@ -8,33 +8,33 @@
|
|||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"laravel/framework": "^11.45.1",
|
||||
"awobaz/compoships": "^2.4.1",
|
||||
"doctrine/dbal": "^3.10.1",
|
||||
"endroid/qr-code": "^5.1",
|
||||
"fakerphp/faker": "^1.24.1",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"php": ">=8.1",
|
||||
"awobaz/compoships": "^2.3",
|
||||
"doctrine/dbal": "^3.0",
|
||||
"endroid/qr-code": "^5.0",
|
||||
"fakerphp/faker": "^1.23",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/tinker": "^2.9",
|
||||
"lcobucci/jwt": "^4.3",
|
||||
"namoshek/laravel-redis-sentinel": "^0.5",
|
||||
"ovh/ovh": "^3.5",
|
||||
"parsedown/laravel": "^1.2.1",
|
||||
"phpunit/phpunit": "^10.5.50",
|
||||
"propaganistas/laravel-phone": "^5.3.6",
|
||||
"ovh/ovh": "^3.3",
|
||||
"parsedown/laravel": "^1.2",
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"propaganistas/laravel-phone": "^5.3",
|
||||
"react/socket": "^1.16",
|
||||
"respect/validation": "^2.4.4",
|
||||
"respect/validation": "^2.3",
|
||||
"rvxlab/hcaptcha": "^5.2",
|
||||
"sabre/vobject": "^4.5.7"
|
||||
"sabre/vobject": "^4.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"nunomaduro/collision": "^8.5",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^7.0",
|
||||
"phpmd/phpmd": "^2.15",
|
||||
"squizlabs/php_codesniffer": "^3.13.2"
|
||||
"squizlabs/php_codesniffer": "^3.7"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.2"
|
||||
"php": "8.1"
|
||||
},
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
|
|
|
|||
1445
flexiapi/composer.lock
generated
1445
flexiapi/composer.lock
generated
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -19,11 +19,13 @@
|
|||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Awobaz\Compoships\Database\Eloquent\Factories\ComposhipsFactory;
|
||||
|
||||
use App\Account;
|
||||
use App\AccountCreationToken;
|
||||
use App\Http\Controllers\Account\AuthenticateController as WebAuthenticateController;
|
||||
use App\Space;
|
||||
|
||||
class AccountFactory extends Factory
|
||||
|
|
@ -52,14 +54,14 @@ class AccountFactory extends Factory
|
|||
|
||||
public function fromSpace(Space $space)
|
||||
{
|
||||
return $this->state(fn(array $attributes) => [
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'domain' => $space->domain
|
||||
]);
|
||||
}
|
||||
|
||||
public function admin()
|
||||
{
|
||||
return $this->state(fn(array $attributes) => [
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'admin' => true,
|
||||
]);
|
||||
}
|
||||
|
|
@ -79,21 +81,21 @@ class AccountFactory extends Factory
|
|||
|
||||
public function deactivated()
|
||||
{
|
||||
return $this->state(fn(array $attributes) => [
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'activated' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function withEmail()
|
||||
{
|
||||
return $this->state(fn(array $attributes) => [
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'email' => $this->faker->email,
|
||||
]);
|
||||
}
|
||||
|
||||
public function withConsumedAccountCreationToken()
|
||||
{
|
||||
return $this->state(fn(array $attributes) => [])->afterCreating(function (Account $account) {
|
||||
return $this->state(fn (array $attributes) => [])->afterCreating(function (Account $account) {
|
||||
$accountCreationToken = new AccountCreationToken;
|
||||
$accountCreationToken->token = 'test_token';
|
||||
$accountCreationToken->account_id = $account->id;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ class PasswordFactory extends Factory
|
|||
|
||||
return [
|
||||
'account_id' => $account->id,
|
||||
'password' => hash('md5', $account->username . ':' . $account->resolvedRealm . ':testtest'),
|
||||
'algorithm' => 'MD5',
|
||||
'password' => hash('md5', $account->username.':'.$account->resolvedRealm.':testtest'),
|
||||
'algorithm' => 'MD5',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -55,18 +55,18 @@ class PasswordFactory extends Factory
|
|||
$account = Account::find($attributes['account_id']);
|
||||
|
||||
return [
|
||||
'password' => hash('sha256', $account->username . ':' . $account->resolvedRealm . ':testtest'),
|
||||
'password' => hash('sha256', $account->username.':'.$account->resolvedRealm.':testtest'),
|
||||
'account_id' => $account->id,
|
||||
'algorithm' => 'SHA-256',
|
||||
'algorithm' => 'SHA-256',
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function clrtxt()
|
||||
{
|
||||
return $this->state(fn(array $attributes) => [
|
||||
'password' => 'testtest',
|
||||
'algorithm' => 'CLRTXT',
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'password' => 'testtest',
|
||||
'algorithm' => 'CLRTXT',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ class SpaceFactory extends Factory
|
|||
];
|
||||
}
|
||||
|
||||
public function local()
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'host' => 'localhost',
|
||||
]);
|
||||
}
|
||||
|
||||
public function withoutProvisioningHeader()
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
|
|
@ -43,14 +50,6 @@ class SpaceFactory extends Factory
|
|||
]);
|
||||
}
|
||||
|
||||
public function domain(string $domain)
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'domain' => $domain,
|
||||
'host' => $domain,
|
||||
]);
|
||||
}
|
||||
|
||||
public function secondDomain()
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use Illuminate\Support\Facades\Schema;
|
|||
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
|
||||
return new class extends Migration {
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('phone_countries', function (Blueprint $table) {
|
||||
|
|
@ -19,12 +20,10 @@ return new class extends Migration {
|
|||
|
||||
$phoneNumberUtils = PhoneNumberUtil::getInstance();
|
||||
foreach (getCountryCodes() as $code => $name) {
|
||||
if ($resolvedMetadata = $phoneNumberUtils->getMetadataForRegion($code)) {
|
||||
$phoneCountry = new PhoneCountry();
|
||||
$phoneCountry->code = $code;
|
||||
$phoneCountry->country_code = $resolvedMetadata->getCountryCode();
|
||||
$phoneCountry->save();
|
||||
}
|
||||
$phoneCountry = new PhoneCountry();
|
||||
$phoneCountry->code = $code;
|
||||
$phoneCountry->country_code = $phoneNumberUtils->getMetadataForRegion($code)->getCountryCode();
|
||||
$phoneCountry->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue