From 913dcbb8556ef6e09535d1972f144e0ddb46695b Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 11:27:00 -0500
Subject: [PATCH 01/13] prettier
---
.gitignore | 2 ++
.pre-commit-config.yaml | 28 ++++++++++++++++++++++++++++
CONTRIBUTING.md | 2 ++
prettierrc.yml | 4 ++++
4 files changed, 36 insertions(+)
create mode 100644 prettierrc.yml
diff --git a/.gitignore b/.gitignore
index 94aa9f54..d08024d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,5 @@ deployment/**/*
!deployment/**/README.md
.phpunit.result.cache
+
+node_modules
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 97d65767..41455ad0 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,6 +26,34 @@ repos:
workers/.*|
)$
+ - repo: https://github.com/rbubley/mirrors-prettier
+ rev: v3.4.2
+ hooks:
+ - id: prettier
+ exclude: |
+ (?x)^(
+ composer\.json|
+ composer\.lock|
+ )$
+
+ - repo: local
+ hooks:
+ - id: prettier (php)
+ name: prettier (php)
+ entry: npx
+ args: [prettier, --plugin=@prettier/plugin-php, --write]
+ language: system
+ files: \.php$
+ # prettier doesn't do well with the html files with
Date: Fri, 7 Nov 2025 11:41:43 -0500
Subject: [PATCH 02/13] no more psr12
---
.phpcs-ruleset.xml | 11 -----------
.pre-commit-config.yaml | 29 +++--------------------------
CONTRIBUTING.md | 5 ++---
3 files changed, 5 insertions(+), 40 deletions(-)
delete mode 100644 .phpcs-ruleset.xml
diff --git a/.phpcs-ruleset.xml b/.phpcs-ruleset.xml
deleted file mode 100644
index 13faff04..00000000
--- a/.phpcs-ruleset.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
- PSR12, with max line length = 100 characters
-
-
-
-
-
-
-
-
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 41455ad0..61ff708f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -10,21 +10,9 @@ repos:
rev: v5.0.0
hooks:
- id: trailing-whitespace
- - id: end-of-file-fixer
-
- - repo: local
- hooks:
- - id: phpcbf
- name: PHP Code Beautifier and Fixer
- entry: phpcbf
- language: system
- files: \.php$
- args: [--standard=./.phpcs-ruleset.xml, --colors]
- exclude: |
- (?x)^(
- test/.*|
- workers/.*|
- )$
+ # prettier should take care of this, but it has this one problem with shebang files
+ # https://github.com/prettier/plugin-php/issues/2430
+ # - id: end-of-file-fixer
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.4.2
@@ -71,17 +59,6 @@ repos:
- repo: local
hooks:
- - id: phpcs
- name: PHP CodeSniffer
- entry: phpcs
- language: system
- files: \.php$
- args: [--standard=./.phpcs-ruleset.xml, --colors]
- exclude: |
- (?x)^(
- test/.*|
- workers/.*|
- )$
- id: php-l
name: php -l
entry: php
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 59b83eb9..4bc035a3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -3,9 +3,8 @@
## Conventions
* PHP version 8.3.
-* All files are required to be linted with PSR-12 standard.
-* All files are required to be formatted with Prettier and then PHPCBF.
-* The maximum line length for any PHP file is 100 characters, instead of PSR-12's 120 characters.
+* All files are required to be formatted with Prettier.
+* The maximum line length for any PHP file is 100 characters.
* Comments should be used sparingly.
* Empty lines should be used sparingly.
* No code should fail quietly, instead exceptions should be thrown.
From ea174a92d3a4a3c2741c4bdf7e191bbbf79731e1 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 11:52:48 -0500
Subject: [PATCH 03/13] format everything with prettier
---
.github/workflows/phpunit.yml | 32 +-
.github/workflows/pre-commit.yml | 20 +-
CONTRIBUTING.md | 43 +-
README.md | 181 ++++----
coverage.php | 6 +-
resources/config.php | 8 +-
resources/init.php | 30 +-
resources/lib/UnityConfig.php | 16 +-
resources/lib/UnityGithub.php | 10 +-
resources/lib/UnityGroup.php | 214 +++++-----
resources/lib/UnityHTTPD.php | 62 ++-
resources/lib/UnityLDAP.php | 170 +++++---
resources/lib/UnityMailer.php | 44 +-
resources/lib/UnityOrg.php | 4 +-
resources/lib/UnityPerms.php | 54 ++-
resources/lib/UnityRedis.php | 6 +-
resources/lib/UnitySQL.php | 112 +++--
resources/lib/UnitySSO.php | 41 +-
resources/lib/UnityUser.php | 128 +++---
resources/lib/UnityWebhook.php | 22 +-
.../lib/exceptions/ArrayKeyException.php | 4 +-
.../EncodingConversionException.php | 4 +-
.../exceptions/EncodingUnknownException.php | 4 +-
resources/lib/exceptions/EnsureException.php | 4 +-
resources/lib/exceptions/NoDieException.php | 4 +-
resources/lib/exceptions/SSOException.php | 4 +-
resources/lib/utils.php | 15 +-
.../mail/account_deletion_request_admin.php | 3 +-
resources/mail/group_created.php | 3 +-
resources/mail/group_denied.php | 3 +-
resources/mail/group_disband.php | 7 +-
.../mail/group_join_request_cancelled.php | 8 +-
resources/mail/group_request.php | 3 +-
resources/mail/group_request_admin.php | 3 +-
resources/mail/group_request_cancelled.php | 7 +-
resources/mail/group_user_added.php | 3 +-
resources/mail/group_user_added_owner.php | 5 +-
resources/mail/group_user_denied.php | 7 +-
resources/mail/group_user_denied_owner.php | 7 +-
resources/mail/group_user_removed.php | 3 +-
resources/mail/group_user_removed_owner.php | 5 +-
resources/mail/group_user_request.php | 3 +-
resources/mail/group_user_request_owner.php | 5 +-
resources/mail/user_created.php | 3 +-
resources/mail/user_loginshell.php | 7 +-
resources/mail/user_sshkey.php | 9 +-
.../functional/AccountDeletionRequestTest.php | 27 +-
test/functional/InvalidEPPNTest.php | 7 +-
test/functional/LoginShellSetTest.php | 21 +-
test/functional/NewUserTest.php | 155 ++++---
test/functional/PIMemberRequestTest.php | 25 +-
test/functional/PageLoadTest.php | 5 +-
test/functional/PiBecomeRequestTest.php | 47 +-
test/functional/PiMemberApproveTest.php | 47 +-
test/functional/PiMemberDenyTest.php | 33 +-
test/functional/PiRemoveUserTest.php | 22 +-
test/functional/SSHKeyAddTest.php | 79 ++--
test/functional/SSHKeyDeleteTest.php | 21 +-
test/functional/ViewAsUserTest.php | 29 +-
test/phpunit-bootstrap.php | 113 +++--
test/unit/AjaxSshValidateTest.php | 5 +-
test/unit/UnityGithubTest.php | 7 +-
test/unit/UnitySSOTest.php | 12 +-
test/unit/UtilsTest.php | 20 +-
tools/docker-dev/docker-compose.yml | 18 +-
.../identity/phpldapadmin-config.php | 25 +-
tools/docker-dev/sql/phpmyadmin-config.php | 16 +-
webroot/css/filters.css | 16 +-
webroot/css/global.css | 400 +++++++++---------
webroot/css/modal.css | 75 ++--
webroot/css/navbar.css | 162 +++----
webroot/css/tables.css | 124 +++---
webroot/js/filter.js | 146 ++++---
webroot/js/global.js | 38 +-
webroot/js/modal.js | 23 +-
webroot/js/sort.js | 138 +++---
webroot/js/tables.js | 91 ++--
workers/clear-audit-log.php | 10 +-
workers/group_user_request_owner_reminder.php | 20 +-
workers/remove-users-from-group.php | 13 +-
workers/update-ldap-cache.php | 55 ++-
81 files changed, 1893 insertions(+), 1488 deletions(-)
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index 84702a15..79c16afa 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -9,19 +9,19 @@ jobs:
docker-compose-phpunit:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- with:
- submodules: true
- - name: setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: "8.3"
- tools: composer
- - name: install composer dependencies
- run: composer update
- - name: Run docker compose
- uses: hoverkraft-tech/compose-action@v2.0.1
- with:
- compose-file: "./tools/docker-dev/docker-compose.yml"
- - name: Execute tests in the running services
- run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover="$(mktemp --suffix=.xml)" -d --min-coverage=./coverage.php'
+ - uses: actions/checkout@v3
+ with:
+ submodules: true
+ - name: setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.3"
+ tools: composer
+ - name: install composer dependencies
+ run: composer update
+ - name: Run docker compose
+ uses: hoverkraft-tech/compose-action@v2.0.1
+ with:
+ compose-file: "./tools/docker-dev/docker-compose.yml"
+ - name: Execute tests in the running services
+ run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover="$(mktemp --suffix=.xml)" -d --min-coverage=./coverage.php'
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index 929a14b2..3a35b365 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -9,13 +9,13 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- with:
- submodules: true
- - uses: actions/setup-python@v3
- - name: setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: "8.3"
- tools: composer, phpcs, phpcbf
- - uses: pre-commit/action@v3.0.1
+ - uses: actions/checkout@v3
+ with:
+ submodules: true
+ - uses: actions/setup-python@v3
+ - name: setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: "8.3"
+ tools: composer, phpcs, phpcbf
+ - uses: pre-commit/action@v3.0.1
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4bc035a3..eb6f717e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,24 +2,24 @@
## Conventions
-* PHP version 8.3.
-* All files are required to be formatted with Prettier.
-* The maximum line length for any PHP file is 100 characters.
-* Comments should be used sparingly.
-* Empty lines should be used sparingly.
-* No code should fail quietly, instead exceptions should be thrown.
+- PHP version 8.3.
+- All files are required to be formatted with Prettier.
+- The maximum line length for any PHP file is 100 characters.
+- Comments should be used sparingly.
+- Empty lines should be used sparingly.
+- No code should fail quietly, instead exceptions should be thrown.
PHP builtin functions that fail quietly (ex: `json_encode`) should be replaced with a wrapper in `resources/utils.php`.
-* No code should call `die()` or `exit()`, instead `UnityHTTPD::die()`.
+- No code should call `die()` or `exit()`, instead `UnityHTTPD::die()`.
This will avoid the premature death of our automated testing processes.
-* No code should call `assert()`, instead `\ensure()`.
+- No code should call `assert()`, instead `\ensure()`.
This will enforce conditions even in production.
-* No code should call `json_encode()`, instead `\jsonEncode()`.
+- No code should call `json_encode()`, instead `\jsonEncode()`.
This will throw errors and escape slashes by default.
-* No code should call `mb_convert_encoding()`, instead `\mbConvertEncoding()`.
+- No code should call `mb_convert_encoding()`, instead `\mbConvertEncoding()`.
This will throw an exception rather than returning `false`.
-* No code should call `mb_detect_encoding()`, instead `\mbDetectEncoding()`.
+- No code should call `mb_detect_encoding()`, instead `\mbDetectEncoding()`.
This will enable strict mode and throw an exception rather than returning `false`.
-* `UnityHTTPD`'s user-facing error functionality (ex: `badRequest`) should only be called from `webroot/**/*.php`.
+- `UnityHTTPD`'s user-facing error functionality (ex: `badRequest`) should only be called from `webroot/**/*.php`.
`resources/**/*.php` should throw exceptions instead.
This repository will automatically check PRs for linting compliance.
@@ -44,10 +44,10 @@ This repository will automatically check PRs for linting compliance.
While the environment is running, the following is accessible:
-* http://127.0.0.1:8000 - Web Portal
-* http://127.0.0.1:8010 - PHPLDAPAdmin Portal
-* http://127.0.0.1:8020 - PHPMyAdmin Portal
-* http://127.0.0.1:8030 - Mailcatcher Portal
+- http://127.0.0.1:8000 - Web Portal
+- http://127.0.0.1:8010 - PHPLDAPAdmin Portal
+- http://127.0.0.1:8020 - PHPMyAdmin Portal
+- http://127.0.0.1:8030 - Mailcatcher Portal
### Test Users
@@ -56,9 +56,10 @@ When accessing locked down portions of the portal, you will be asked for a usern
The password is always `password`. `tools/docker-dev/web/htpasswd` contains all valid usernames.
Notable users:
-* `user1@org1.test` - admin, PI
-* `user2@org1.test` - not admin, not PI
-* `user2000@org2.test` - does not yet have an account
+
+- `user1@org1.test` - admin, PI
+- `user2@org1.test` - not admin, not PI
+- `user2000@org2.test` - does not yet have an account
### Changes to Dev Environment
@@ -87,6 +88,7 @@ Once a user action has been taken, internal interfaces are used to verify the re
To run `phpunit`, spawn 2 shells in differnt tabs:
tab 1:
+
```shell
cd ./tools/docker-dev
./build.sh
@@ -94,6 +96,7 @@ cd ./tools/docker-dev
```
tab 2:
+
```
$ container="$(docker container ls | grep web | awk '{print $1}')"
$ docker exec -it "$container" bash
@@ -139,6 +142,7 @@ When writing a test, it may be tempting to use the PHP API directly, but the HTT
Example:
using the PHP API:
+
```php
private function requestGroupCreation()
{
@@ -147,6 +151,7 @@ private function requestGroupCreation()
```
using the HTTP API:
+
```php
private function requestGroupCreation()
{
diff --git a/README.md b/README.md
index d3f1b054..ab20b422 100644
--- a/README.md
+++ b/README.md
@@ -1,77 +1,84 @@

# Unity Web Portal
+
Unity Web Portal is a PHP application built in top of MariaDB and LDAP which acts as a central user portal for high-performance-computing clusters.
Basic Features:
- * User signs up
- * PIs require admin approval, users require PI approval
- * User manages SSH public keys
- * no passwords
- * Github import, upload file, paste, generate and download private key
- * User changes login shell
- * User requests their own PI group
- * PI approves/denies requests to join their PI group
- * PI removes members from their group
+
+- User signs up
+ - PIs require admin approval, users require PI approval
+- User manages SSH public keys
+ - no passwords
+ - Github import, upload file, paste, generate and download private key
+- User changes login shell
+- User requests their own PI group
+- PI approves/denies requests to join their PI group
+- PI removes members from their group
Admin features:
- * Automatic updating of LDAP to reflect current state of users, groups, organizations, PI groups
- * Cluster notices
- * Added to front page, mailed, and exposed via REST API
- * WYSIWYG HTML editor for webpage contents, cluster notices
- * Branding customization for multiple domains simultaneously
- * Custom UIDNumber / GIDNumber mappings for specific users
- * Login as another user
- * Mailing
+
+- Automatic updating of LDAP to reflect current state of users, groups, organizations, PI groups
+- Cluster notices
+ - Added to front page, mailed, and exposed via REST API
+- WYSIWYG HTML editor for webpage contents, cluster notices
+- Branding customization for multiple domains simultaneously
+- Custom UIDNumber / GIDNumber mappings for specific users
+- Login as another user
+- Mailing
## Installation/Deployment
See the Docker Compose environment (`tools/docker-dev/`) for an (unsafe for production) example.
1. OpenLDAP server
- * Structure should be similar to `tools/docker-dev/identity/bootstrap.ldif`
- * Also see `tools/docker-dev/identity/{config,ssh}.ldif`
- * recommended openldap modules/overlays:
- * `unique`: prevent UIDNumber, GIDNumber conflicts
- * `pw-sha2`: allow the use of sha2 password hashing algorithms for bind
+ - Structure should be similar to `tools/docker-dev/identity/bootstrap.ldif`
+ - Also see `tools/docker-dev/identity/{config,ssh}.ldif`
+ - recommended openldap modules/overlays:
+ - `unique`: prevent UIDNumber, GIDNumber conflicts
+ - `pw-sha2`: allow the use of sha2 password hashing algorithms for bind
1. MySQL / MariaDB server
- * Structure should be similar to `tools/docker-dev/sql/bootstrap.sql`
+ - Structure should be similar to `tools/docker-dev/sql/bootstrap.sql`
1. SMTP server
1. Web server
- * This repository cloned
- * `deployment/config/config.ini` should be owned by the apache user (`www-data` on Ubuntu), with mode `0600`
- * Submodules checked out (`git submodule update --checkout --init`)
- * Composer (`apt install composer` on Ubuntu)
- * Dependencies:
- * PHP extensions
- * curl, intl, ldap, mbstring, mysql, pdo, redis, xml (`apt install php-` on Ubuntu)
- * Libraries
- * `COMPOSER_ALLOW_SUPERUSER=1 composer --no-dev --no-scripts --no-plugins install`
- * `httpd` `DocumentRoot` set to `webroot/`
- * `httpd` Authentication
- * Any authentication will do as long as it defines `REMOTE_USER`, `givenName`, `sn`, and `mail`
- * `REMOTE_USER` must also be unique, non-reassignable, and persistent
- * Unity uses Shibboleth SP and the Apache Shibboleth module (`apt install shibboleth-sp-utils libapache2-mod-shib` on Ubuntu)
- * `httpd` Authorization
- * Global access to `webroot/panel/`
- * Restricted access to `webroot/admin/`
- * No access anywhere else
+ - This repository cloned
+ - `deployment/config/config.ini` should be owned by the apache user (`www-data` on Ubuntu), with mode `0600`
+ - Submodules checked out (`git submodule update --checkout --init`)
+ - Composer (`apt install composer` on Ubuntu)
+ - Dependencies:
+ - PHP extensions
+ - curl, intl, ldap, mbstring, mysql, pdo, redis, xml (`apt install php-` on Ubuntu)
+ - Libraries
+ - `COMPOSER_ALLOW_SUPERUSER=1 composer --no-dev --no-scripts --no-plugins install`
+ - `httpd` `DocumentRoot` set to `webroot/`
+ - `httpd` Authentication
+ - Any authentication will do as long as it defines `REMOTE_USER`, `givenName`, `sn`, and `mail`
+ - `REMOTE_USER` must also be unique, non-reassignable, and persistent
+ - Unity uses Shibboleth SP and the Apache Shibboleth module (`apt install shibboleth-sp-utils libapache2-mod-shib` on Ubuntu)
+ - `httpd` Authorization
+ - Global access to `webroot/panel/`
+ - Restricted access to `webroot/admin/`
+ - No access anywhere else
## Configuration
+
1. Create `deployment/config/config.ini` using `/deployment/defaults/config.ini` as a reference
- * Make sure this file is not world readable!
+ - Make sure this file is not world readable!
1. If using mulitple domains, create `deployment/overrides//config/config.ini`
1. If using custom UIDNumber/GIDNumber mappings, create `deployment/custom_user_mappings/*.csv`
- * The 1st column is UID, the 2nd column is both UIDNumber and GIDNumber
+ - The 1st column is UID, the 2nd column is both UIDNumber and GIDNumber
1. Add logos to `webroot/assets/footer_logos/`
## Integration
+
The scope of this project ends at being responsible for the LDAP user database. We recommend production deployments to set up scripts which detect changes in LDAP and then perform further actions. For example, Unity uses such scripts to create home directories and add records to the Slurm account database.
## Updating
+
We recommend a deployment where each version of the portal is its own clone, then just change a symlink to point to the new version. This way a rollback is much easier.
Example folder structure, where `->` indicates a symlink:
+
```
/srv/www/
unity-web-portal -> unity-web-portal-1.1.0
@@ -107,51 +114,55 @@ rm "$prod" && ln -s "$old" "$prod"
### Version-specific update instructions:
### 1.2 -> 1.3
-* SQL:
- * remove the `sitevars` table
-* `defaults/config.ini.default` has some new fields that need to be overriden:
- * `offset_UIDGID`
- * `offset_PIGID`
- * `offset_ORGGID`
-* `custom_user_mappings` can no longer match with just the 1st segment of the logged in user's UID, an exact match is required
-* LDAP:
- * create the `gecos` attribute for all users by concatenating `givenName` and `sn`
+
+- SQL:
+ - remove the `sitevars` table
+- `defaults/config.ini.default` has some new fields that need to be overriden:
+ - `offset_UIDGID`
+ - `offset_PIGID`
+ - `offset_ORGGID`
+- `custom_user_mappings` can no longer match with just the 1st segment of the logged in user's UID, an exact match is required
+- LDAP:
+ - create the `gecos` attribute for all users by concatenating `givenName` and `sn`
### 1.2.0 -> 1.2.1
-* SQL:
- * Add new columns to the `requests` table:
- ```sql
- ALTER TABLE `requests`
- ADD `firstname` VARCHAR(768) NOT NULL AFTER `timestamp`,
- ADD `lastname` VARCHAR(768) NOT NULL AFTER `firstname`,
- ADD `email` VARCHAR(768) NOT NULL AFTER `lastname`,
- ADD `org` VARCHAR(768) NOT NULL AFTER `email`;
- ```
+
+- SQL:
+ - Add new columns to the `requests` table:
+ ```sql
+ ALTER TABLE `requests`
+ ADD `firstname` VARCHAR(768) NOT NULL AFTER `timestamp`,
+ ADD `lastname` VARCHAR(768) NOT NULL AFTER `firstname`,
+ ADD `email` VARCHAR(768) NOT NULL AFTER `lastname`,
+ ADD `org` VARCHAR(768) NOT NULL AFTER `email`;
+ ```
### 1.1 -> 1.2
-* SQL:
- * Create the `sitevars` table (see `bootstrap.sql` for details)
- * Create the `audit_log` table (see `bootstrap.sql` for details)
- * Create the `account_deletion_requests` table (see `bootstrap.sql` for details)
- * Create the `user_last_logins` table (see `bootstrap.sql` for details)
- * Drop the `sso_log` table
- * Drop the `events` table
- * Reduce the size of all `varchar(1000)` columns to `varchar(768)`
- * Delete the `priv` row in the `pages` table (if moving site policy to external site)
- * Add the `account_policy` row in the `pages` table (if NOT moving site policy to external site)
-* `defaults/config.ini.default` has some new fields that may need to be overriden:
- * `ldap.user_group`
- * `site.terms_of_service_url`
- * example, created account policy page: `https://unity.rc.umass.edu/panel/account_policy.php`
- * `site.account_policy_url`
- * example, using old site policy page: `https://unity.rc.umass.edu/panel/priv.php`
-* LDAP:
- * Create a new group defined by `ldap.user_group` in the config
+
+- SQL:
+ - Create the `sitevars` table (see `bootstrap.sql` for details)
+ - Create the `audit_log` table (see `bootstrap.sql` for details)
+ - Create the `account_deletion_requests` table (see `bootstrap.sql` for details)
+ - Create the `user_last_logins` table (see `bootstrap.sql` for details)
+ - Drop the `sso_log` table
+ - Drop the `events` table
+ - Reduce the size of all `varchar(1000)` columns to `varchar(768)`
+ - Delete the `priv` row in the `pages` table (if moving site policy to external site)
+ - Add the `account_policy` row in the `pages` table (if NOT moving site policy to external site)
+- `defaults/config.ini.default` has some new fields that may need to be overriden:
+ - `ldap.user_group`
+ - `site.terms_of_service_url`
+ - example, created account policy page: `https://unity.rc.umass.edu/panel/account_policy.php`
+ - `site.account_policy_url`
+ - example, using old site policy page: `https://unity.rc.umass.edu/panel/priv.php`
+- LDAP:
+ - Create a new group defined by `ldap.user_group` in the config
### 1.0 -> 1.1
-* SQL:
- * Add the `home` content management row
-* `config/branding/config.ini.default` has some new fields that may need to be overriden:
- * `mail.pi_approve*`
- * `page.home`
- * The entire `loginshell` section
+
+- SQL:
+ - Add the `home` content management row
+- `config/branding/config.ini.default` has some new fields that may need to be overriden:
+ - `mail.pi_approve*`
+ - `page.home`
+ - The entire `loginshell` section
diff --git a/coverage.php b/coverage.php
index f2a48ae7..44119cb9 100644
--- a/coverage.php
+++ b/coverage.php
@@ -3,9 +3,5 @@
use RobinIngelbrecht\PHPUnitCoverageTools\MinCoverage\MinCoverageRule;
return [
- new MinCoverageRule(
- pattern: '*',
- minCoverage: 62,
- exitOnLowCoverage: true
- ),
+ new MinCoverageRule(pattern: "*", minCoverage: 62, exitOnLowCoverage: true),
];
diff --git a/resources/config.php b/resources/config.php
index ac43e9ed..92014ab1 100644
--- a/resources/config.php
+++ b/resources/config.php
@@ -2,4 +2,10 @@
use UnityWebPortal\lib\UnityConfig;
-define("CONFIG", UnityConfig::getConfig(__DIR__ . "/../defaults", __DIR__ . "/../deployment"));
+define(
+ "CONFIG",
+ UnityConfig::getConfig(
+ __DIR__ . "/../defaults",
+ __DIR__ . "/../deployment",
+ ),
+);
diff --git a/resources/init.php b/resources/init.php
index 770e4e72..d1e08d3d 100644
--- a/resources/init.php
+++ b/resources/init.php
@@ -15,7 +15,10 @@
use UnityWebPortal\lib\UnityHTTPD;
if (CONFIG["site"]["enable_exception_handler"]) {
- set_exception_handler(["UnityWebPortal\lib\UnityHTTPD", "exceptionHandler"]);
+ set_exception_handler([
+ "UnityWebPortal\lib\UnityHTTPD",
+ "exceptionHandler",
+ ]);
}
session_start();
@@ -32,15 +35,30 @@
$WEBHOOK = new UnityWebhook();
$GITHUB = new UnityGithub();
-if (isset($_SERVER["REMOTE_USER"])) { // Check if SSO is enabled on this page
+if (isset($_SERVER["REMOTE_USER"])) {
+ // Check if SSO is enabled on this page
$SSO = UnitySSO::getSSO();
$_SESSION["SSO"] = $SSO;
- $OPERATOR = new UnityUser($SSO["user"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $OPERATOR = new UnityUser(
+ $SSO["user"],
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
$_SESSION["is_admin"] = $OPERATOR->isAdmin();
if (isset($_SESSION["viewUser"]) && $_SESSION["is_admin"]) {
- $USER = new UnityUser($_SESSION["viewUser"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $USER = new UnityUser(
+ $_SESSION["viewUser"],
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
} else {
$USER = $OPERATOR;
}
@@ -51,9 +69,9 @@
$SQL->addLog(
$OPERATOR->uid,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"user_login",
- $OPERATOR->uid
+ $OPERATOR->uid,
);
if (!$_SESSION["user_exists"]) {
diff --git a/resources/lib/UnityConfig.php b/resources/lib/UnityConfig.php
index c638df8e..ce8f05b5 100644
--- a/resources/lib/UnityConfig.php
+++ b/resources/lib/UnityConfig.php
@@ -6,10 +6,14 @@ class UnityConfig
{
public static function getConfig($def_config_loc, $deploy_loc)
{
- $CONFIG = parse_ini_file($def_config_loc . "/config.ini.default", true, INI_SCANNER_TYPED);
+ $CONFIG = parse_ini_file(
+ $def_config_loc . "/config.ini.default",
+ true,
+ INI_SCANNER_TYPED,
+ );
$CONFIG = self::pullConfig($CONFIG, $deploy_loc);
if (array_key_exists("HTTP_HOST", $_SERVER)) {
- $cur_url = $_SERVER['HTTP_HOST'];
+ $cur_url = $_SERVER["HTTP_HOST"];
$url_override_path = $deploy_loc . "/overrides/" . $cur_url;
if (is_dir($url_override_path)) {
$CONFIG = self::pullConfig($CONFIG, $url_override_path);
@@ -21,8 +25,12 @@ public static function getConfig($def_config_loc, $deploy_loc)
private static function pullConfig($CONFIG, $loc)
{
$file_loc = $loc . "/config/config.ini";
- if (file_exists(($file_loc))) {
- $CONFIG_override = parse_ini_file($file_loc, true, INI_SCANNER_TYPED);
+ if (file_exists($file_loc)) {
+ $CONFIG_override = parse_ini_file(
+ $file_loc,
+ true,
+ INI_SCANNER_TYPED,
+ );
return array_replace_recursive($CONFIG, $CONFIG_override);
} else {
return $CONFIG;
diff --git a/resources/lib/UnityGithub.php b/resources/lib/UnityGithub.php
index e9898cee..33417f77 100644
--- a/resources/lib/UnityGithub.php
+++ b/resources/lib/UnityGithub.php
@@ -7,9 +7,7 @@ class UnityGithub
public function getSshPublicKeys($username)
{
$url = "https://api.github.com/users/$username/keys";
- $headers = array(
- "User-Agent: Unity Cluster User Portal"
- );
+ $headers = ["User-Agent: Unity Cluster User Portal"];
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
@@ -21,11 +19,13 @@ public function getSshPublicKeys($username)
// normally returns array of objects each with a ->key attribute
// if bad URL or no such user, returns status=404 object
// if no keys, returns []
- if ((!is_array($keys)) || (count($keys) == 0)) {
+ if (!is_array($keys) || count($keys) == 0) {
return [];
}
// phpcs:disable
- return array_map(function($x){return $x->key;}, $keys);
+ return array_map(function ($x) {
+ return $x->key;
+ }, $keys);
// phpcs:enable
}
}
diff --git a/resources/lib/UnityGroup.php b/resources/lib/UnityGroup.php
index 34e6ef02..54f98d72 100644
--- a/resources/lib/UnityGroup.php
+++ b/resources/lib/UnityGroup.php
@@ -44,7 +44,9 @@ public function equals($other_group)
{
if (!is_a($other_group, self::class)) {
throw new Exception(
- "Unable to check equality because the parameter is not a " . self::class . " object"
+ "Unable to check equality because the parameter is not a " .
+ self::class .
+ " object",
);
}
@@ -72,7 +74,7 @@ public function requestGroup(
$email,
$org,
$send_mail_to_admins,
- $send_mail = true
+ $send_mail = true,
) {
if ($this->exists()) {
return;
@@ -80,43 +82,35 @@ public function requestGroup(
if ($this->SQL->accDeletionRequestExists($this->getOwner()->uid)) {
return;
}
- $this->SQL->addRequest($this->getOwner()->uid, $firstname, $lastname, $email, $org);
+ $this->SQL->addRequest(
+ $this->getOwner()->uid,
+ $firstname,
+ $lastname,
+ $email,
+ $org,
+ );
if ($send_mail) {
- $this->MAILER->sendMail(
- $email,
- "group_request"
- );
- $this->WEBHOOK->sendWebhook(
- "group_request_admin",
- array(
- "user" => $this->getOwner()->uid,
- "org" => $org,
- "name" => "$firstname $lastname",
- "email" => $email
- )
- );
+ $this->MAILER->sendMail($email, "group_request");
+ $this->WEBHOOK->sendWebhook("group_request_admin", [
+ "user" => $this->getOwner()->uid,
+ "org" => $org,
+ "name" => "$firstname $lastname",
+ "email" => $email,
+ ]);
if ($send_mail_to_admins) {
- $this->MAILER->sendMail(
- "admin",
- "group_request_admin",
- array(
- "user" => $this->getOwner()->uid,
- "org" => $org,
- "name" => "$firstname $lastname",
- "email" => $email
- )
- );
- }
- $this->MAILER->sendMail(
- "pi_approve",
- "group_request_admin",
- array(
+ $this->MAILER->sendMail("admin", "group_request_admin", [
"user" => $this->getOwner()->uid,
"org" => $org,
"name" => "$firstname $lastname",
- "email" => $email
- )
- );
+ "email" => $email,
+ ]);
+ }
+ $this->MAILER->sendMail("pi_approve", "group_request_admin", [
+ "user" => $this->getOwner()->uid,
+ "org" => $org,
+ "name" => "$firstname $lastname",
+ "email" => $email,
+ ]);
}
}
@@ -136,23 +130,22 @@ public function approveGroup($operator = null, $send_mail = true)
$request["lastname"],
$request["email"],
$request["org"],
- $send_mail
+ $send_mail,
);
}
$this->init();
$this->SQL->removeRequest($this->getOwner()->uid);
- $operator = is_null($operator) ? $this->getOwner()->uid : $operator->uid;
+ $operator = is_null($operator)
+ ? $this->getOwner()->uid
+ : $operator->uid;
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"approved_group",
- $this->getOwner()->uid
+ $this->getOwner()->uid,
);
if ($send_mail) {
- $this->MAILER->sendMail(
- $request["email"],
- "group_created"
- );
+ $this->MAILER->sendMail($request["email"], "group_created");
}
}
@@ -161,23 +154,25 @@ public function approveGroup($operator = null, $send_mail = true)
*/
public function denyGroup($operator = null, $send_mail = true)
{
- $request = $this->SQL->getRequest($this->getOwner()->uid, UnitySQL::REQUEST_BECOME_PI);
+ $request = $this->SQL->getRequest(
+ $this->getOwner()->uid,
+ UnitySQL::REQUEST_BECOME_PI,
+ );
$this->SQL->removeRequest($this->getOwner()->uid);
if ($this->exists()) {
return;
}
- $operator = is_null($operator) ? $this->getOwner()->uid : $operator->uid;
+ $operator = is_null($operator)
+ ? $this->getOwner()->uid
+ : $operator->uid;
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"denied_group",
- $this->getOwner()->uid
+ $this->getOwner()->uid,
);
if ($send_mail) {
- $this->MAILER->sendMail(
- $request["email"],
- "group_denied"
- );
+ $this->MAILER->sendMail($request["email"], "group_denied");
}
}
@@ -188,11 +183,9 @@ public function cancelGroupRequest($send_mail = true)
}
$this->SQL->removeRequest($this->getOwner()->uid);
if ($send_mail) {
- $this->MAILER->sendMail(
- "admin",
- "group_request_cancelled",
- ["uid" => $this->getOwner()->uid],
- );
+ $this->MAILER->sendMail("admin", "group_request_cancelled", [
+ "uid" => $this->getOwner()->uid,
+ ]);
}
}
@@ -206,7 +199,7 @@ public function cancelGroupJoinRequest($user, $send_mail = true)
$this->MAILER->sendMail(
$this->getOwner()->getMail(),
"group_join_request_cancelled",
- ["uid" => $user->uid]
+ ["uid" => $user->uid],
);
}
}
@@ -266,21 +259,20 @@ public function approveUser($new_user, $send_mail = true)
$this->addUserToGroup($new_user);
$this->SQL->removeRequest($new_user->uid, $this->gid);
if ($send_mail) {
- $this->MAILER->sendMail(
- $new_user->getMail(),
- "group_user_added",
- array("group" => $this->gid)
- );
+ $this->MAILER->sendMail($new_user->getMail(), "group_user_added", [
+ "group" => $this->gid,
+ ]);
$this->MAILER->sendMail(
$this->getOwner()->getMail(),
"group_user_added_owner",
- array(
+ [
"group" => $this->gid,
"user" => $new_user->uid,
- "name" => $request["firstname"] . " " . $request["lastname"],
+ "name" =>
+ $request["firstname"] . " " . $request["lastname"],
"email" => $request["email"],
"org" => $request["org"],
- )
+ ],
);
}
}
@@ -291,21 +283,19 @@ public function denyUser($new_user, $send_mail = true)
// remove request, this will fail silently if the request doesn't exist
$this->SQL->removeRequest($new_user->uid, $this->gid);
if ($send_mail) {
- $this->MAILER->sendMail(
- $request["email"],
- "group_user_denied",
- array("group" => $this->gid)
- );
+ $this->MAILER->sendMail($request["email"], "group_user_denied", [
+ "group" => $this->gid,
+ ]);
$this->MAILER->sendMail(
$this->getOwner()->getMail(),
"group_user_denied_owner",
- array(
+ [
"group" => $this->gid,
"user" => $new_user->uid,
"name" => $new_user->getFullName(),
"email" => $new_user->getMail(),
- "org" => $new_user->getOrg()
- )
+ "org" => $new_user->getOrg(),
+ ],
);
}
}
@@ -316,7 +306,9 @@ public function removeUser($new_user, $send_mail = true)
return;
}
if ($new_user->uid == $this->getOwner()->uid) {
- throw new Exception("Cannot delete group owner from group. Disband group instead");
+ throw new Exception(
+ "Cannot delete group owner from group. Disband group instead",
+ );
}
// remove request, this will fail silently if the request doesn't exist
$this->removeUserFromGroup($new_user);
@@ -324,18 +316,18 @@ public function removeUser($new_user, $send_mail = true)
$this->MAILER->sendMail(
$new_user->getMail(),
"group_user_removed",
- array("group" => $this->gid)
+ ["group" => $this->gid],
);
$this->MAILER->sendMail(
$this->getOwner()->getMail(),
"group_user_removed_owner",
- array(
+ [
"group" => $this->gid,
"user" => $new_user->uid,
"name" => $new_user->getFullName(),
"email" => $new_user->getMail(),
- "org" => $new_user->getOrg()
- )
+ "org" => $new_user->getOrg(),
+ ],
);
}
}
@@ -346,14 +338,20 @@ public function newUserRequest(
$lastname,
$email,
$org,
- $send_mail = true
+ $send_mail = true,
) {
if ($this->memberExists($new_user)) {
- UnityHTTPD::errorLog("warning", "user '$new_user' already in group");
+ UnityHTTPD::errorLog(
+ "warning",
+ "user '$new_user' already in group",
+ );
return;
}
if ($this->requestExists($new_user)) {
- UnityHTTPD::errorLog("warning", "user '$new_user' already requested group membership");
+ UnityHTTPD::errorLog(
+ "warning",
+ "user '$new_user' already requested group membership",
+ );
return;
}
if ($this->SQL->accDeletionRequestExists($new_user->uid)) {
@@ -362,21 +360,19 @@ public function newUserRequest(
}
$this->addRequest($new_user->uid, $firstname, $lastname, $email, $org);
if ($send_mail) {
- $this->MAILER->sendMail(
- $email,
- "group_user_request",
- array("group" => $this->gid)
- );
+ $this->MAILER->sendMail($email, "group_user_request", [
+ "group" => $this->gid,
+ ]);
$this->MAILER->sendMail(
$this->getOwner()->getMail(),
"group_user_request_owner",
- array(
+ [
"group" => $this->gid,
"user" => $new_user->uid,
"name" => "$firstname $lastname",
"email" => $email,
"org" => $org,
- )
+ ],
);
}
}
@@ -384,7 +380,7 @@ public function newUserRequest(
public function getRequests()
{
$requests = $this->SQL->getRequests($this->gid);
- $out = array();
+ $out = [];
foreach ($requests as $request) {
$user = new UnityUser(
$request["uid"],
@@ -392,19 +388,16 @@ public function getRequests()
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
- );
- array_push(
- $out,
- [
- $user,
- $request["timestamp"],
- $request["firstname"],
- $request["lastname"],
- $request["email"],
- $request["org"],
- ]
+ $this->WEBHOOK,
);
+ array_push($out, [
+ $user,
+ $request["timestamp"],
+ $request["firstname"],
+ $request["lastname"],
+ $request["email"],
+ $request["org"],
+ ]);
}
return $out;
}
@@ -412,7 +405,7 @@ public function getRequests()
public function getGroupMembers($ignorecache = false)
{
$members = $this->getGroupMemberUIDs($ignorecache);
- $out = array();
+ $out = [];
foreach ($members as $member) {
$user_obj = new UnityUser(
$member,
@@ -420,7 +413,7 @@ public function getGroupMembers($ignorecache = false)
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
+ $this->WEBHOOK,
);
array_push($out, $user_obj);
}
@@ -467,7 +460,7 @@ private function init()
$nextGID = $this->LDAP->getNextPIGIDNumber();
$this->entry->setAttribute("objectclass", UnityLDAP::POSIX_GROUP_CLASS);
$this->entry->setAttribute("gidnumber", strval($nextGID));
- $this->entry->setAttribute("memberuid", array($owner->uid));
+ $this->entry->setAttribute("memberuid", [$owner->uid]);
$this->entry->write();
$this->REDIS->appendCacheArray("sorted_groups", "", $this->gid);
// TODO if we ever make this project based,
@@ -497,7 +490,14 @@ public function memberExists($user)
private function addRequest($uid, $firstname, $lastname, $email, $org)
{
- $this->SQL->addRequest($uid, $firstname, $lastname, $email, $org, $this->gid);
+ $this->SQL->addRequest(
+ $uid,
+ $firstname,
+ $lastname,
+ $email,
+ $org,
+ $this->gid,
+ );
}
public function getOwner()
@@ -508,7 +508,7 @@ public function getOwner()
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
+ $this->WEBHOOK,
);
}
@@ -520,7 +520,9 @@ public static function ownerUID2GID($uid)
public static function GID2OwnerUID($gid)
{
if (substr($gid, 0, strlen(self::PI_PREFIX)) != self::PI_PREFIX) {
- throw new Exception("PI group GID doesn't have the correct prefix.");
+ throw new Exception(
+ "PI group GID doesn't have the correct prefix.",
+ );
}
return substr($gid, strlen(self::PI_PREFIX));
}
diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php
index 61585a7c..688f42bc 100644
--- a/resources/lib/UnityHTTPD.php
+++ b/resources/lib/UnityHTTPD.php
@@ -27,7 +27,10 @@ public static function die($x = null, $show_user = false)
public static function redirect($dest)
{
header("Location: $dest");
- self::errorToUser("Redirect failed, click here to continue.", 302);
+ self::errorToUser(
+ "Redirect failed, click here to continue.",
+ 302,
+ );
self::die();
}
@@ -49,7 +52,8 @@ public static function errorLog(
\jsonEncode($data);
$output["data"] = $data;
} catch (\JsonException $e) {
- $output["data"] = "data could not be JSON encoded: " . $e->getMessage();
+ $output["data"] =
+ "data could not be JSON encoded: " . $e->getMessage();
}
}
$output["REMOTE_USER"] = $_SERVER["REMOTE_USER"] ?? null;
@@ -61,7 +65,10 @@ public static function errorLog(
$output["error"] = self::throwableToArray($error);
} else {
// newlines are bad for error log, but getTrace() is too verbose
- $output["trace"] = explode("\n", (new \Exception())->getTraceAsString());
+ $output["trace"] = explode(
+ "\n",
+ new \Exception()->getTraceAsString(),
+ );
}
error_log("$title: " . \jsonEncode($output));
}
@@ -85,12 +92,13 @@ private static function throwableToArray(\Throwable $t): array
private static function errorToUser(
string $msg,
int $http_response_code,
- ?string $errorid = null
+ ?string $errorid = null,
) {
if (!CONFIG["site"]["enable_error_to_user"]) {
return;
}
- $notes = "Please notify a Unity admin at " . CONFIG["mail"]["support"] . ".";
+ $notes =
+ "Please notify a Unity admin at " . CONFIG["mail"]["support"] . ".";
if (!is_null($errorid)) {
$notes = $notes . " Error ID: $errorid.";
}
@@ -105,7 +113,11 @@ private static function errorToUser(
public static function badRequest($message, $error = null, $data = null)
{
$errorid = uniqid();
- self::errorToUser("Invalid requested action or submitted data.", 400, $errorid);
+ self::errorToUser(
+ "Invalid requested action or submitted data.",
+ 400,
+ $errorid,
+ );
self::errorLog("bad request", $message, $errorid, $error, $data);
self::die($message);
}
@@ -118,11 +130,24 @@ public static function forbidden($message, $error = null, $data = null)
self::die($message);
}
- public static function internalServerError($message, $error = null, $data = null)
- {
+ public static function internalServerError(
+ $message,
+ $error = null,
+ $data = null,
+ ) {
$errorid = uniqid();
- self::errorToUser("An internal server error has occurred.", 500, $errorid);
- self::errorLog("internal server error", $message, $errorid, $error, $data);
+ self::errorToUser(
+ "An internal server error has occurred.",
+ 500,
+ $errorid,
+ );
+ self::errorLog(
+ "internal server error",
+ $message,
+ $errorid,
+ $error,
+ $data,
+ );
self::die($message);
}
@@ -130,7 +155,10 @@ public static function internalServerError($message, $error = null, $data = null
public static function exceptionHandler($e)
{
ini_set("log_errors", true); // in case something goes wrong and error is not logged
- self::internalServerError("An internal server error has occurred.", error: $e);
+ self::internalServerError(
+ "An internal server error has occurred.",
+ error: $e,
+ );
ini_set("log_errors", false); // error logged successfully
}
@@ -139,7 +167,9 @@ public static function getPostData(...$keys)
try {
return \arrayGet($_POST, ...$keys);
} catch (ArrayKeyException $e) {
- self::badRequest('failed to get $_POST data', $e, ['$_POST' => $_POST]);
+ self::badRequest('failed to get $_POST data', $e, [
+ '$_POST' => $_POST,
+ ]);
}
}
@@ -151,7 +181,9 @@ public static function getUploadedFileContents(
try {
$tmpfile_path = \arrayGet($_FILES, $filename, "tmp_name");
} catch (ArrayKeyException $e) {
- self::badRequest('no such uploaded file', $e, ['$_FILES' => $_FILES]);
+ self::badRequest("no such uploaded file", $e, [
+ '$_FILES' => $_FILES,
+ ]);
}
$contents = file_get_contents($tmpfile_path);
if ($contents === false) {
@@ -169,6 +201,8 @@ public static function getUploadedFileContents(
public static function alert(string $message)
{
// jsonEncode escapes quotes
- echo "";
+ echo "";
}
}
diff --git a/resources/lib/UnityLDAP.php b/resources/lib/UnityLDAP.php
index 74e30c08..940f75a5 100644
--- a/resources/lib/UnityLDAP.php
+++ b/resources/lib/UnityLDAP.php
@@ -10,25 +10,19 @@
*/
class UnityLDAP extends ldapConn
{
- private const RDN = "cn"; // The defauls RDN for LDAP entries is set to "common name"
-
- public const POSIX_ACCOUNT_CLASS = array(
- "inetorgperson",
- "posixAccount",
- "top",
- "ldapPublicKey"
- );
-
- public const POSIX_GROUP_CLASS = array(
- "posixGroup",
- "top"
- );
-
- private $custom_mappings_path = (
- __DIR__
- . "/../../"
- . CONFIG["ldap"]["custom_user_mappings_dir"]
- );
+ private const RDN = "cn"; // The defauls RDN for LDAP entries is set to "common name"
+
+ public const POSIX_ACCOUNT_CLASS = [
+ "inetorgperson",
+ "posixAccount",
+ "top",
+ "ldapPublicKey",
+ ];
+
+ public const POSIX_GROUP_CLASS = ["posixGroup", "top"];
+
+ private $custom_mappings_path =
+ __DIR__ . "/../../" . CONFIG["ldap"]["custom_user_mappings_dir"];
private $def_user_shell = CONFIG["ldap"]["def_user_shell"];
private $offset_UIDGID = CONFIG["ldap"]["offset_UIDGID"];
private $offset_PIGID = CONFIG["ldap"]["offset_PIGID"];
@@ -45,7 +39,11 @@ class UnityLDAP extends ldapConn
public function __construct()
{
- parent::__construct(CONFIG["ldap"]["uri"], CONFIG["ldap"]["user"], CONFIG["ldap"]["pass"]);
+ parent::__construct(
+ CONFIG["ldap"]["uri"],
+ CONFIG["ldap"]["user"],
+ CONFIG["ldap"]["pass"],
+ );
$this->baseOU = $this->getEntry(CONFIG["ldap"]["basedn"]);
$this->userOU = $this->getEntry(CONFIG["ldap"]["user_ou"]);
$this->groupOU = $this->getEntry(CONFIG["ldap"]["group_ou"]);
@@ -92,13 +90,22 @@ public function getDefUserShell()
public function getNextUIDGIDNumber($uid)
{
- $IDNumsInUse = array_merge($this->getAllUIDNumbersInUse(), $this->getAllGIDNumbersInUse());
+ $IDNumsInUse = array_merge(
+ $this->getAllUIDNumbersInUse(),
+ $this->getAllGIDNumbersInUse(),
+ );
$customIDMappings = $this->getCustomIDMappings();
$customMappedID = $customIDMappings[$uid] ?? null;
- if (!is_null($customMappedID) && !in_array($customMappedID, $IDNumsInUse)) {
+ if (
+ !is_null($customMappedID) &&
+ !in_array($customMappedID, $IDNumsInUse)
+ ) {
return $customMappedID;
}
- if (!is_null($customMappedID) && in_array($customMappedID, $IDNumsInUse)) {
+ if (
+ !is_null($customMappedID) &&
+ in_array($customMappedID, $IDNumsInUse)
+ ) {
UnityHTTPD::errorLog(
"warning",
"user '$uid' has a custom mapped IDNumber $customMappedID but it's already in use!",
@@ -106,7 +113,10 @@ public function getNextUIDGIDNumber($uid)
}
return $this->getNextIDNumber(
$this->offset_UIDGID,
- array_merge($IDNumsInUse, array_values($this->getCustomIDMappings()))
+ array_merge(
+ $IDNumsInUse,
+ array_values($this->getCustomIDMappings()),
+ ),
);
}
@@ -114,7 +124,10 @@ public function getNextPIGIDNumber()
{
return $this->getNextIDNumber(
$this->offset_PIGID,
- array_merge($this->getAllGIDNumbersInUse(), array_values($this->getCustomIDMappings()))
+ array_merge(
+ $this->getAllGIDNumbersInUse(),
+ array_values($this->getCustomIDMappings()),
+ ),
);
}
@@ -122,7 +135,10 @@ public function getNextOrgGIDNumber()
{
return $this->getNextIDNumber(
$this->offset_ORGGID,
- array_merge($this->getAllGIDNumbersInUse(), array_values($this->getCustomIDMappings()))
+ array_merge(
+ $this->getAllGIDNumbersInUse(),
+ array_values($this->getCustomIDMappings()),
+ ),
);
}
@@ -130,13 +146,16 @@ private function isIDNumberForbidden($id)
{
// 0-99 are probably going to be used for local system accounts instead of LDAP accounts
// 100-999, 60000-64999 are reserved for debian packages
- return (($id <= 999) || ($id >= 60000 && $id <= 64999));
+ return $id <= 999 || ($id >= 60000 && $id <= 64999);
}
private function getNextIDNumber($start, $IDsToSkip)
{
$new_id = $start;
- while ($this->isIDNumberForbidden($new_id) || in_array($new_id, $IDsToSkip)) {
+ while (
+ $this->isIDNumberForbidden($new_id) ||
+ in_array($new_id, $IDsToSkip)
+ ) {
$new_id++;
}
return $new_id;
@@ -148,7 +167,7 @@ private function getCustomIDMappings()
$dir = new \DirectoryIterator($this->custom_mappings_path);
foreach ($dir as $fileinfo) {
$filename = $fileinfo->getFilename();
- if ($fileinfo->isDot() || ($filename == "README.md")) {
+ if ($fileinfo->isDot() || $filename == "README.md") {
continue;
}
if ($fileinfo->getExtension() == "csv") {
@@ -175,7 +194,11 @@ private function getAllUIDNumbersInUse()
// use baseOU for awareness of externally managed entries
return array_map(
fn($x) => $x["uidnumber"][0],
- $this->baseOU->getChildrenArray(["uidNumber"], true, "(objectClass=posixAccount)"),
+ $this->baseOU->getChildrenArray(
+ ["uidNumber"],
+ true,
+ "(objectClass=posixAccount)",
+ ),
);
}
@@ -184,7 +207,11 @@ private function getAllGIDNumbersInUse()
// use baseOU for awareness of externally managed entries
return array_map(
fn($x) => $x["gidnumber"][0],
- $this->baseOU->getChildrenArray(["gidNumber"], true, "(objectClass=posixGroup)"),
+ $this->baseOU->getChildrenArray(
+ ["gidNumber"],
+ true,
+ "(objectClass=posixGroup)",
+ ),
);
}
@@ -200,9 +227,9 @@ public function getAllUsers(
$UnityMailer,
$UnityRedis,
$UnityWebhook,
- $ignorecache = false
+ $ignorecache = false,
) {
- $out = array();
+ $out = [];
if (!$ignorecache) {
$users = $UnityRedis->getCache("sorted_users", "");
@@ -216,8 +243,8 @@ public function getAllUsers(
$UnitySQL,
$UnityMailer,
$UnityRedis,
- $UnityWebhook
- )
+ $UnityWebhook,
+ ),
);
}
return $out;
@@ -227,7 +254,14 @@ public function getAllUsers(
$users = $this->getAllUsersUIDs();
sort($users);
foreach ($users as $user) {
- $params = array($user, $this, $UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook);
+ $params = [
+ $user,
+ $this,
+ $UnitySQL,
+ $UnityMailer,
+ $UnityRedis,
+ $UnityWebhook,
+ ];
array_push($out, new UnityUser(...$params));
}
return $out;
@@ -239,7 +273,7 @@ public function getAllUsersAttributes($attributes)
$user_attributes = $this->baseOU->getChildrenArray(
$attributes,
true, // recursive
- "(objectClass=posixAccount)"
+ "(objectClass=posixAccount)",
);
foreach ($user_attributes as $i => $attributes) {
if (!in_array($attributes["uid"][0], $include_uids)) {
@@ -254,17 +288,22 @@ public function getAllPIGroups(
$UnityMailer,
$UnityRedis,
$UnityWebhook,
- $ignorecache = false
+ $ignorecache = false,
) {
- $out = array();
+ $out = [];
if (!$ignorecache) {
$groups = $UnityRedis->getCache("sorted_groups", "");
if (!is_null($groups)) {
foreach ($groups as $group) {
- $params = array(
- $group, $this, $UnitySQL, $UnityMailer, $UnityRedis, $UnityWebhook
- );
+ $params = [
+ $group,
+ $this,
+ $UnitySQL,
+ $UnityMailer,
+ $UnityRedis,
+ $UnityWebhook,
+ ];
array_push($out, new UnityGroup(...$params));
}
@@ -283,8 +322,8 @@ public function getAllPIGroups(
$UnitySQL,
$UnityMailer,
$UnityRedis,
- $UnityWebhook
- )
+ $UnityWebhook,
+ ),
);
}
@@ -304,7 +343,7 @@ public function getPIGroupGIDsWithMemberUID($uid)
["cn"],
false,
"(memberuid=" . ldap_escape($uid, LDAP_ESCAPE_FILTER) . ")",
- )
+ ),
);
}
@@ -327,12 +366,14 @@ public function getAllPIGroupOwnerAttributes($attributes)
$owner_attributes = array_values($owner_attributes); // reindex
$owners_not_found = array_diff(
$owner_uids,
- array_map(fn($x) => $x["uid"][0], $owner_attributes)
+ array_map(fn($x) => $x["uid"][0], $owner_attributes),
);
if (count($owners_not_found) > 0) {
UnityHTTPD::errorLog(
"warning",
- "PI group owners not found: " . \jsonEncode($owners_not_found) . "\n"
+ "PI group owners not found: " .
+ \jsonEncode($owners_not_found) .
+ "\n",
);
}
return $owner_attributes;
@@ -347,7 +388,10 @@ public function getAllUID2PIGIDs()
$uids = $this->getAllUsersUIDs();
$uid2pigids = array_combine($uids, array_fill(0, count($uids), []));
// for each PI group, append that GID to the member list for each of its member UIDs
- foreach ($this->getAllPIGroupsAttributes(["cn", "memberuid"]) as $array) {
+ foreach (
+ $this->getAllPIGroupsAttributes(["cn", "memberuid"])
+ as $array
+ ) {
$gid = $array["cn"][0];
foreach ($array["memberuid"] as $uid) {
if (array_key_exists($uid, $uid2pigids)) {
@@ -355,7 +399,7 @@ public function getAllUID2PIGIDs()
} else {
UnityHTTPD::errorLog(
"warning",
- "user '$uid' is a member of a PI group but is not a Unity user!"
+ "user '$uid' is a member of a PI group but is not a Unity user!",
);
}
}
@@ -368,9 +412,9 @@ public function getAllOrgGroups(
$UnityMailer,
$UnityRedis,
$UnityWebhook,
- $ignorecache = false
+ $ignorecache = false,
) {
- $out = array();
+ $out = [];
if (!$ignorecache) {
$orgs = $UnityRedis->getCache("sorted_orgs", "");
@@ -384,8 +428,8 @@ public function getAllOrgGroups(
$UnitySQL,
$UnityMailer,
$UnityRedis,
- $UnityWebhook
- )
+ $UnityWebhook,
+ ),
);
}
return $out;
@@ -403,8 +447,8 @@ public function getAllOrgGroups(
$UnitySQL,
$UnityMailer,
$UnityRedis,
- $UnityWebhook
- )
+ $UnityWebhook,
+ ),
);
}
@@ -419,24 +463,32 @@ public function getAllOrgGroupsAttributes($attributes)
public function getUserEntry($uid)
{
$uid = ldap_escape($uid, "", LDAP_ESCAPE_DN);
- return $this->getEntry(unityLDAP::RDN . "=$uid," . CONFIG["ldap"]["user_ou"]);
+ return $this->getEntry(
+ unityLDAP::RDN . "=$uid," . CONFIG["ldap"]["user_ou"],
+ );
}
public function getGroupEntry($gid)
{
$gid = ldap_escape($gid, "", LDAP_ESCAPE_DN);
- return $this->getEntry(unityLDAP::RDN . "=$gid," . CONFIG["ldap"]["group_ou"]);
+ return $this->getEntry(
+ unityLDAP::RDN . "=$gid," . CONFIG["ldap"]["group_ou"],
+ );
}
public function getPIGroupEntry($gid)
{
$gid = ldap_escape($gid, "", LDAP_ESCAPE_DN);
- return $this->getEntry(unityLDAP::RDN . "=$gid," . CONFIG["ldap"]["pigroup_ou"]);
+ return $this->getEntry(
+ unityLDAP::RDN . "=$gid," . CONFIG["ldap"]["pigroup_ou"],
+ );
}
public function getOrgGroupEntry($gid)
{
$gid = ldap_escape($gid, "", LDAP_ESCAPE_DN);
- return $this->getEntry(unityLDAP::RDN . "=$gid," . CONFIG["ldap"]["orggroup_ou"]);
+ return $this->getEntry(
+ unityLDAP::RDN . "=$gid," . CONFIG["ldap"]["orggroup_ou"],
+ );
}
}
diff --git a/resources/lib/UnityMailer.php b/resources/lib/UnityMailer.php
index 9a8d4756..910293fd 100644
--- a/resources/lib/UnityMailer.php
+++ b/resources/lib/UnityMailer.php
@@ -11,7 +11,8 @@
class UnityMailer extends PHPMailer
{
private $template_dir = __DIR__ . "/../mail"; // location of all email templates
- private $override_template_dir = __DIR__ . "/../../deployment/mail_overrides";
+ private $override_template_dir =
+ __DIR__ . "/../../deployment/mail_overrides";
private $MSG_LINKREF;
private $MSG_SENDER_EMAIL;
@@ -48,10 +49,11 @@ public function __construct()
$this->Port = CONFIG["smtp"]["port"];
$security = CONFIG["smtp"]["security"];
- $security_conf_valid = empty($security) || $security == "tls" || $security == "ssl";
+ $security_conf_valid =
+ empty($security) || $security == "tls" || $security == "ssl";
if (!$security_conf_valid) {
throw new Exception(
- "SMTP security is not set correctly, leave empty, use 'tls', or 'ssl'"
+ "SMTP security is not set correctly, leave empty, use 'tls', or 'ssl'",
);
}
$this->SMTPSecure = $security;
@@ -68,13 +70,13 @@ public function __construct()
}
if (CONFIG["smtp"]["ssl_verify"] == "false") {
- $this->SMTPOptions = array(
- 'ssl' => array(
- 'verify_peer' => false,
- 'verify_peer_name' => false,
- 'allow_self_signed' => true
- )
- );
+ $this->SMTPOptions = [
+ "ssl" => [
+ "verify_peer" => false,
+ "verify_peer_name" => false,
+ "allow_self_signed" => true,
+ ],
+ ];
}
}
@@ -82,17 +84,26 @@ public function sendMail($recipients, $template = null, $data = null)
{
if (isset($template)) {
$this->setFrom($this->MSG_SENDER_EMAIL, $this->MSG_SENDER_NAME);
- $this->addReplyTo($this->MSG_SUPPORT_EMAIL, $this->MSG_SUPPORT_NAME);
+ $this->addReplyTo(
+ $this->MSG_SUPPORT_EMAIL,
+ $this->MSG_SUPPORT_NAME,
+ );
$template_filename = $template . ".php";
- if (file_exists($this->override_template_dir . "/" . $template_filename)) {
- $template_path = $this->override_template_dir . "/" . $template_filename;
+ if (
+ file_exists(
+ $this->override_template_dir . "/" . $template_filename,
+ )
+ ) {
+ $template_path =
+ $this->override_template_dir . "/" . $template_filename;
} else {
$template_path = $this->template_dir . "/" . $template_filename;
}
if (file_exists($this->override_template_dir . "/footer.php")) {
- $footer_template_path = $this->override_template_dir . "/footer.php";
+ $footer_template_path =
+ $this->override_template_dir . "/footer.php";
} else {
$footer_template_path = $this->template_dir . "/footer.php";
}
@@ -106,7 +117,10 @@ public function sendMail($recipients, $template = null, $data = null)
if ($recipients == "admin") {
$this->addBCC($this->MSG_ADMIN_EMAIL, $this->MSG_ADMIN_NAME);
} elseif ($recipients == "pi_approve") {
- $this->addBCC($this->MSG_PI_APPROVAL_EMAIL, $this->MSG_PI_APPROVAL_NAME);
+ $this->addBCC(
+ $this->MSG_PI_APPROVAL_EMAIL,
+ $this->MSG_PI_APPROVAL_NAME,
+ );
} else {
if (is_array($recipients)) {
foreach ($recipients as $addr) {
diff --git a/resources/lib/UnityOrg.php b/resources/lib/UnityOrg.php
index eef5f76c..5753e73b 100644
--- a/resources/lib/UnityOrg.php
+++ b/resources/lib/UnityOrg.php
@@ -51,7 +51,7 @@ public function inOrg($user, $ignorecache = false)
public function getOrgMembers($ignorecache = false)
{
$members = $this->getGroupMemberUIDs($ignorecache);
- $out = array();
+ $out = [];
foreach ($members as $member) {
$user_obj = new UnityUser(
$member,
@@ -59,7 +59,7 @@ public function getOrgMembers($ignorecache = false)
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
+ $this->WEBHOOK,
);
array_push($out, $user_obj);
}
diff --git a/resources/lib/UnityPerms.php b/resources/lib/UnityPerms.php
index fe5d4981..0c624408 100644
--- a/resources/lib/UnityPerms.php
+++ b/resources/lib/UnityPerms.php
@@ -22,19 +22,22 @@ public function checkApproveUser($uid, $operated_on, $group)
$role = $this->SQL->getRole($uid, $group);
if (
- $this->SQL->hasPerm($role, 'unity.admin')
- || $this->SQL->hasPerm($role, 'unity.admin_no_grant')
+ $this->SQL->hasPerm($role, "unity.admin") ||
+ $this->SQL->hasPerm($role, "unity.admin_no_grant")
) {
return true;
}
- if (!$this->SQL->hasPerm($role, 'unity.approve_user')) {
+ if (!$this->SQL->hasPerm($role, "unity.approve_user")) {
return false;
}
$operated_on_role = $this->SQL->getRole($operated_on, $group);
- if ($this->SQL->getPriority($operated_on_role) >= $this->SQL->getPriority($role)) {
+ if (
+ $this->SQL->getPriority($operated_on_role) >=
+ $this->SQL->getPriority($role)
+ ) {
return false;
}
@@ -50,19 +53,22 @@ public function checkDenyUser($uid, $operated_on, $group)
$role = $this->SQL->getRole($uid, $group);
if (
- $this->SQL->hasPerm($role, 'unity.admin')
- || $this->SQL->hasPerm($role, 'unity.admin_no_grant')
+ $this->SQL->hasPerm($role, "unity.admin") ||
+ $this->SQL->hasPerm($role, "unity.admin_no_grant")
) {
return true;
}
- if (!$this->SQL->hasPerm($role, 'unity.deny_user')) {
+ if (!$this->SQL->hasPerm($role, "unity.deny_user")) {
return false;
}
$operated_on_role = $this->SQL->getRole($operated_on, $group);
- if ($this->SQL->getPriority($operated_on_role) >= $this->SQL->getPriority($role)) {
+ if (
+ $this->SQL->getPriority($operated_on_role) >=
+ $this->SQL->getPriority($role)
+ ) {
return false;
}
@@ -81,24 +87,30 @@ public function checkGrantRole($uid, $group, $role)
$user_role = $this->SQL->getRole($uid, $group);
- if ($this->SQL->hasPerm($user_role, 'unity.admin_no_grant') && $role == 'unity.admin') {
+ if (
+ $this->SQL->hasPerm($user_role, "unity.admin_no_grant") &&
+ $role == "unity.admin"
+ ) {
return false;
}
if (
- $this->SQL->hasPerm($user_role, 'unity.admin')
- || $this->SQL->hasPerm($user_role, 'unity.admin_no_grant')
+ $this->SQL->hasPerm($user_role, "unity.admin") ||
+ $this->SQL->hasPerm($user_role, "unity.admin_no_grant")
) {
return true;
}
- if (!$this->SQL->hasPerm($user_role, 'unity.grant_role')) {
+ if (!$this->SQL->hasPerm($user_role, "unity.grant_role")) {
return false;
}
$role_to_grant = $this->SQL->getRole($role, $group);
- if ($this->SQL->getPriority($role_to_grant) >= $this->SQL->getPriority($user_role)) {
+ if (
+ $this->SQL->getPriority($role_to_grant) >=
+ $this->SQL->getPriority($user_role)
+ ) {
return false;
}
@@ -117,24 +129,30 @@ public function checkRevokeRole($uid, $group, $role)
$user_role = $this->SQL->getRole($uid, $group);
- if ($this->SQL->hasPerm($user_role, 'unity.admin_no_grant') && $role == 'unity.admin') {
+ if (
+ $this->SQL->hasPerm($user_role, "unity.admin_no_grant") &&
+ $role == "unity.admin"
+ ) {
return false;
}
if (
- $this->SQL->hasPerm($user_role, 'unity.admin')
- || $this->SQL->hasPerm($user_role, 'unity.admin_no_grant')
+ $this->SQL->hasPerm($user_role, "unity.admin") ||
+ $this->SQL->hasPerm($user_role, "unity.admin_no_grant")
) {
return true;
}
- if (!$this->SQL->hasPerm($user_role, 'unity.revoke_role')) {
+ if (!$this->SQL->hasPerm($user_role, "unity.revoke_role")) {
return false;
}
$role_to_revoke = $this->SQL->getRole($role, $group);
- if ($this->SQL->getPriority($role_to_revoke) >= $this->SQL->getPriority($user_role)) {
+ if (
+ $this->SQL->getPriority($role_to_revoke) >=
+ $this->SQL->getPriority($user_role)
+ ) {
return false;
}
diff --git a/resources/lib/UnityRedis.php b/resources/lib/UnityRedis.php
index e17e624d..4397d566 100644
--- a/resources/lib/UnityRedis.php
+++ b/resources/lib/UnityRedis.php
@@ -69,7 +69,7 @@ public function appendCacheArray($object, $key, $value)
$cached_val = $this->getCache($object, $key);
if (is_null($cached_val)) {
- $this->setCache($object, $key, array($value));
+ $this->setCache($object, $key, [$value]);
} else {
if (!is_array($cached_val)) {
throw new Exception("This cache value is not an array");
@@ -89,13 +89,13 @@ public function removeCacheArray($object, $key, $value)
$cached_val = $this->getCache($object, $key);
if (is_null($cached_val)) {
- $this->setCache($object, $key, array());
+ $this->setCache($object, $key, []);
} else {
if (!is_array($cached_val)) {
throw new Exception("This cache value is not an array");
}
- $cached_val = array_diff($cached_val, array($value));
+ $cached_val = array_diff($cached_val, [$value]);
$this->setCache($object, $key, $cached_val);
}
}
diff --git a/resources/lib/UnitySQL.php b/resources/lib/UnitySQL.php
index e7291dab..b5a69106 100644
--- a/resources/lib/UnitySQL.php
+++ b/resources/lib/UnitySQL.php
@@ -17,7 +17,6 @@ class UnitySQL
private const TABLE_GROUP_REQUESTS = "groupRequests";
private const TABLE_GROUP_JOIN_REQUESTS = "groupJoinRequests";
-
// FIXME this string should be changed to something more intuitive, requires production change
public const REQUEST_BECOME_PI = "admin";
@@ -26,9 +25,12 @@ class UnitySQL
public function __construct()
{
$this->conn = new PDO(
- "mysql:host=" . CONFIG["sql"]["host"] . ";dbname=" . CONFIG["sql"]["dbname"],
+ "mysql:host=" .
+ CONFIG["sql"]["host"] .
+ ";dbname=" .
+ CONFIG["sql"]["dbname"],
CONFIG["sql"]["user"],
- CONFIG["sql"]["pass"]
+ CONFIG["sql"]["pass"],
);
$this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
@@ -47,16 +49,18 @@ public function addRequest(
$lastname,
$email,
$org,
- $dest = self::REQUEST_BECOME_PI
+ $dest = self::REQUEST_BECOME_PI,
) {
if ($this->requestExists($requestor, $dest)) {
return;
}
$stmt = $this->conn->prepare(
- "INSERT INTO " . self::TABLE_REQS . " " .
- "(uid, firstname, lastname, email, org, request_for) VALUES " .
- "(:uid, :firstname, :lastname, :email, :org, :request_for)"
+ "INSERT INTO " .
+ self::TABLE_REQS .
+ " " .
+ "(uid, firstname, lastname, email, org, request_for) VALUES " .
+ "(:uid, :firstname, :lastname, :email, :org, :request_for)",
);
$stmt->bindParam(":uid", $requestor);
$stmt->bindParam(":request_for", $dest);
@@ -75,7 +79,9 @@ public function removeRequest($requestor, $dest = self::REQUEST_BECOME_PI)
}
$stmt = $this->conn->prepare(
- "DELETE FROM " . self::TABLE_REQS . " WHERE uid=:uid and request_for=:request_for"
+ "DELETE FROM " .
+ self::TABLE_REQS .
+ " WHERE uid=:uid and request_for=:request_for",
);
$stmt->bindParam(":uid", $requestor);
$stmt->bindParam(":request_for", $dest);
@@ -86,7 +92,9 @@ public function removeRequest($requestor, $dest = self::REQUEST_BECOME_PI)
public function removeRequests($dest = self::REQUEST_BECOME_PI)
{
$stmt = $this->conn->prepare(
- "DELETE FROM " . self::TABLE_REQS . " WHERE request_for=:request_for"
+ "DELETE FROM " .
+ self::TABLE_REQS .
+ " WHERE request_for=:request_for",
);
$stmt->bindParam(":request_for", $dest);
@@ -96,17 +104,23 @@ public function removeRequests($dest = self::REQUEST_BECOME_PI)
public function getRequest($user, $dest)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_REQS . " WHERE uid=:uid and request_for=:request_for"
+ "SELECT * FROM " .
+ self::TABLE_REQS .
+ " WHERE uid=:uid and request_for=:request_for",
);
$stmt->bindParam(":uid", $user);
$stmt->bindParam(":request_for", $dest);
$stmt->execute();
$result = $stmt->fetchAll();
if (count($result) == 0) {
- throw new \Exception("no such request: uid='$user' request_for='$dest'");
+ throw new \Exception(
+ "no such request: uid='$user' request_for='$dest'",
+ );
}
if (count($result) > 1) {
- throw new \Exception("multiple requests for uid='$user' request_for='$dest'");
+ throw new \Exception(
+ "multiple requests for uid='$user' request_for='$dest'",
+ );
}
return $result[0];
}
@@ -132,7 +146,9 @@ public function getAllRequests()
public function getRequests($dest = self::REQUEST_BECOME_PI)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_REQS . " WHERE request_for=:request_for"
+ "SELECT * FROM " .
+ self::TABLE_REQS .
+ " WHERE request_for=:request_for",
);
$stmt->bindParam(":request_for", $dest);
@@ -144,7 +160,7 @@ public function getRequests($dest = self::REQUEST_BECOME_PI)
public function getRequestsByUser($user)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_REQS . " WHERE uid=:uid"
+ "SELECT * FROM " . self::TABLE_REQS . " WHERE uid=:uid",
);
$stmt->bindParam(":uid", $user);
@@ -156,7 +172,7 @@ public function getRequestsByUser($user)
public function deleteRequestsByUser($user)
{
$stmt = $this->conn->prepare(
- "DELETE FROM " . self::TABLE_REQS . " WHERE uid=:uid"
+ "DELETE FROM " . self::TABLE_REQS . " WHERE uid=:uid",
);
$stmt->bindParam(":uid", $user);
@@ -167,7 +183,7 @@ public function addNotice($title, $date, $content, $operator)
{
$table = self::TABLE_NOTICES;
$stmt = $this->conn->prepare(
- "INSERT INTO $table (date, title, message) VALUES (:date, :title, :message)"
+ "INSERT INTO $table (date, title, message) VALUES (:date, :title, :message)",
);
$stmt->bindParam(":date", $date);
$stmt->bindParam(":title", $title);
@@ -177,9 +193,9 @@ public function addNotice($title, $date, $content, $operator)
$this->addLog(
$operator->uid,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"added_cluster_notice",
- $operator
+ $operator,
);
}
@@ -187,7 +203,7 @@ public function editNotice($id, $title, $date, $content)
{
$table = self::TABLE_NOTICES;
$stmt = $this->conn->prepare(
- "UPDATE $table SET date=:date, title=:title, message=:message WHERE id=:id"
+ "UPDATE $table SET date=:date, title=:title, message=:message WHERE id=:id",
);
$stmt->bindParam(":date", $date);
$stmt->bindParam(":title", $title);
@@ -200,7 +216,7 @@ public function editNotice($id, $title, $date, $content)
public function deleteNotice($id)
{
$stmt = $this->conn->prepare(
- "DELETE FROM " . self::TABLE_NOTICES . " WHERE id=:id"
+ "DELETE FROM " . self::TABLE_NOTICES . " WHERE id=:id",
);
$stmt->bindParam(":id", $id);
@@ -210,7 +226,7 @@ public function deleteNotice($id)
public function getNotice($id)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_NOTICES . " WHERE id=:id"
+ "SELECT * FROM " . self::TABLE_NOTICES . " WHERE id=:id",
);
$stmt->bindParam(":id", $id);
@@ -222,7 +238,7 @@ public function getNotice($id)
public function getNotices()
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_NOTICES . " ORDER BY date DESC"
+ "SELECT * FROM " . self::TABLE_NOTICES . " ORDER BY date DESC",
);
$stmt->execute();
@@ -231,9 +247,7 @@ public function getNotices()
public function getPages()
{
- $stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_PAGES
- );
+ $stmt = $this->conn->prepare("SELECT * FROM " . self::TABLE_PAGES);
$stmt->execute();
return $stmt->fetchAll();
@@ -242,7 +256,7 @@ public function getPages()
public function getPage($id)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_PAGES . " WHERE page=:id"
+ "SELECT * FROM " . self::TABLE_PAGES . " WHERE page=:id",
);
$stmt->bindParam(":id", $id);
@@ -254,7 +268,9 @@ public function getPage($id)
public function editPage($id, $content, $operator)
{
$stmt = $this->conn->prepare(
- "UPDATE " . self::TABLE_PAGES . " SET content=:content WHERE page=:id"
+ "UPDATE " .
+ self::TABLE_PAGES .
+ " SET content=:content WHERE page=:id",
);
$stmt->bindParam(":id", $id);
$stmt->bindParam(":content", $content);
@@ -263,9 +279,9 @@ public function editPage($id, $content, $operator)
$this->addLog(
$operator->uid,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"edited_page",
- $operator
+ $operator,
);
}
@@ -274,7 +290,7 @@ public function addLog($operator, $operator_ip, $action_type, $recipient)
$table = self::TABLE_AUDIT_LOG;
$stmt = $this->conn->prepare(
"INSERT INTO $table (operator, operator_ip, action_type, recipient)
- VALUE (:operator, :operator_ip, :action_type, :recipient)"
+ VALUE (:operator, :operator_ip, :action_type, :recipient)",
);
$stmt->bindParam(":operator", $operator);
$stmt->bindParam(":operator_ip", $operator_ip);
@@ -287,7 +303,9 @@ public function addLog($operator, $operator_ip, $action_type, $recipient)
public function addAccountDeletionRequest($uid)
{
$stmt = $this->conn->prepare(
- "INSERT INTO " . self::TABLE_ACCOUNT_DELETION_REQUESTS . " (uid) VALUE (:uid)"
+ "INSERT INTO " .
+ self::TABLE_ACCOUNT_DELETION_REQUESTS .
+ " (uid) VALUE (:uid)",
);
$stmt->bindParam(":uid", $uid);
@@ -297,7 +315,9 @@ public function addAccountDeletionRequest($uid)
public function accDeletionRequestExists($uid)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_ACCOUNT_DELETION_REQUESTS . " WHERE uid=:uid"
+ "SELECT * FROM " .
+ self::TABLE_ACCOUNT_DELETION_REQUESTS .
+ " WHERE uid=:uid",
);
$stmt->bindParam(":uid", $uid);
@@ -312,7 +332,9 @@ public function deleteAccountDeletionRequest($uid)
return;
}
$stmt = $this->conn->prepare(
- "DELETE FROM " . self::TABLE_ACCOUNT_DELETION_REQUESTS . " WHERE uid=:uid"
+ "DELETE FROM " .
+ self::TABLE_ACCOUNT_DELETION_REQUESTS .
+ " WHERE uid=:uid",
);
$stmt->bindParam(":uid", $uid);
$stmt->execute();
@@ -321,63 +343,67 @@ public function deleteAccountDeletionRequest($uid)
public function getRole($uid, $group)
{
$table = self::TABLE_GROUP_ROLE_ASSIGNMENTS;
- $stmt = $this->conn->prepare("SELECT * FROM $table WHERE user=:uid AND `group`=:group");
+ $stmt = $this->conn->prepare(
+ "SELECT * FROM $table WHERE user=:uid AND `group`=:group",
+ );
$stmt->bindParam(":uid", $uid);
$stmt->bindParam(":group", $group);
$stmt->execute();
- return $stmt->fetchAll()[0]['role'];
+ return $stmt->fetchAll()[0]["role"];
}
public function hasPerm($role, $perm)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_GROUP_ROLES . " WHERE slug=:role"
+ "SELECT * FROM " . self::TABLE_GROUP_ROLES . " WHERE slug=:role",
);
$stmt->bindParam(":role", $role);
$stmt->execute();
$row = $stmt->fetchAll()[0];
- $perms = explode(",", $row['perms']);
+ $perms = explode(",", $row["perms"]);
return in_array($perm, $perms);
}
public function getPriority($role)
{
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_GROUP_ROLES . " WHERE slug=:role"
+ "SELECT * FROM " . self::TABLE_GROUP_ROLES . " WHERE slug=:role",
);
$stmt->bindParam(":role", $role);
$stmt->execute();
$row = $stmt->fetchAll()[0];
- return $row['priority'];
+ return $row["priority"];
}
public function roleAvailableInGroup($uid, $group, $role)
{
$table = self::TABLE_GROUP_ROLE_ASSIGNMENTS;
- $stmt = $this->conn->prepare("SELECT * FROM $table WHERE user=:uid AND `group`=:group");
+ $stmt = $this->conn->prepare(
+ "SELECT * FROM $table WHERE user=:uid AND `group`=:group",
+ );
$stmt->bindParam(":uid", $uid);
$stmt->bindParam(":group", $group);
$stmt->execute();
$row = $stmt->fetchAll()[0];
- $group_slug = $row['group'];
+ $group_slug = $row["group"];
$stmt = $this->conn->prepare(
- "SELECT * FROM " . self::TABLE_GROUP_TYPES . " WHERE slug=:slug"
+ "SELECT * FROM " . self::TABLE_GROUP_TYPES . " WHERE slug=:slug",
);
$stmt->bindParam(":slug", $group_slug);
$stmt->execute();
$row = $stmt->fetchAll()[0];
- $roles = explode(",", $row['roles']);
+ $roles = explode(",", $row["roles"]);
return in_array($role, $roles);
}
diff --git a/resources/lib/UnitySSO.php b/resources/lib/UnitySSO.php
index 0495a164..6f98881f 100644
--- a/resources/lib/UnitySSO.php
+++ b/resources/lib/UnitySSO.php
@@ -30,26 +30,38 @@ private static function eppnToOrg($eppn)
// shibboleth service provider does not garuntee attributes are set, even REMOTE_USER
// https://shibboleth.atlassian.net/wiki/spaces/SP3/pages/2065335257/AttributeAccess
// I have observed attributes to be set to empty strings while shibd complains of bad config
- private static function getAttributeRaw($attributeName, $fallbackAttributeName = null)
- {
+ private static function getAttributeRaw(
+ $attributeName,
+ $fallbackAttributeName = null,
+ ) {
if (isset($_SERVER[$attributeName]) && $_SERVER[$attributeName] != "") {
return $_SERVER[$attributeName];
}
if (is_null($fallbackAttributeName)) {
- throw new SSOException("\$_SERVER[\"$attributeName\"] is unset or empty!");
+ throw new SSOException(
+ "\$_SERVER[\"$attributeName\"] is unset or empty!",
+ );
}
- if (isset($_SERVER[$fallbackAttributeName]) && $_SERVER[$fallbackAttributeName] != "") {
+ if (
+ isset($_SERVER[$fallbackAttributeName]) &&
+ $_SERVER[$fallbackAttributeName] != ""
+ ) {
return $_SERVER[$fallbackAttributeName];
}
throw new SSOException(
- "\$_SERVER[\"$attributeName\"] and \$_SERVER[\"$fallbackAttributeName\"]"
- . " are both unset or empty!"
+ "\$_SERVER[\"$attributeName\"] and \$_SERVER[\"$fallbackAttributeName\"]" .
+ " are both unset or empty!",
);
}
- private static function getAttribute($attributeName, $fallbackAttributeName = null)
- {
- $attribute_raw = self::getAttributeRaw($attributeName, $fallbackAttributeName);
+ private static function getAttribute(
+ $attributeName,
+ $fallbackAttributeName = null,
+ ) {
+ $attribute_raw = self::getAttributeRaw(
+ $attributeName,
+ $fallbackAttributeName,
+ );
// attributes may have multiple values, by default they are split by ';'
// see SPConfig setting attributeValueDelimiter
return explode(";", $attribute_raw)[0];
@@ -57,13 +69,16 @@ private static function getAttribute($attributeName, $fallbackAttributeName = nu
public static function getSSO()
{
- return array(
+ return [
"user" => self::eppnToUID(self::getAttribute("REMOTE_USER")),
"org" => self::eppnToOrg(self::getAttribute("REMOTE_USER")),
"firstname" => self::getAttribute("givenName"),
"lastname" => self::getAttribute("sn"),
- "name" => self::getAttribute("givenName") . " " . self::getAttribute("sn"),
- "mail" => self::getAttribute("mail", "eppn")
- );
+ "name" =>
+ self::getAttribute("givenName") .
+ " " .
+ self::getAttribute("sn"),
+ "mail" => self::getAttribute("mail", "eppn"),
+ ];
}
}
diff --git a/resources/lib/UnityUser.php b/resources/lib/UnityUser.php
index f13352c6..a9e0693b 100644
--- a/resources/lib/UnityUser.php
+++ b/resources/lib/UnityUser.php
@@ -35,7 +35,9 @@ public function equals($other_user)
{
if (!is_a($other_user, self::class)) {
throw new Exception(
- "Unable to check equality because the parameter is not a " . self::class . " object"
+ "Unable to check equality because the parameter is not a " .
+ self::class .
+ " object",
);
}
@@ -62,23 +64,38 @@ public function init($firstname, $lastname, $email, $org, $send_mail = true)
$ldapGroupEntry = $this->getGroupEntry();
$id = $this->LDAP->getNextUIDGIDNumber($this->uid);
\ensure(!$ldapGroupEntry->exists());
- $ldapGroupEntry->setAttribute("objectclass", UnityLDAP::POSIX_GROUP_CLASS);
+ $ldapGroupEntry->setAttribute(
+ "objectclass",
+ UnityLDAP::POSIX_GROUP_CLASS,
+ );
$ldapGroupEntry->setAttribute("gidnumber", strval($id));
$ldapGroupEntry->write();
\ensure(!$this->entry->exists());
- $this->entry->setAttribute("objectclass", UnityLDAP::POSIX_ACCOUNT_CLASS);
+ $this->entry->setAttribute(
+ "objectclass",
+ UnityLDAP::POSIX_ACCOUNT_CLASS,
+ );
$this->entry->setAttribute("uid", $this->uid);
$this->entry->setAttribute("givenname", $firstname);
$this->entry->setAttribute("sn", $lastname);
$this->entry->setAttribute(
"gecos",
- \transliterator_transliterate("Latin-ASCII", "$firstname $lastname")
+ \transliterator_transliterate(
+ "Latin-ASCII",
+ "$firstname $lastname",
+ ),
);
$this->entry->setAttribute("mail", $email);
$this->entry->setAttribute("o", $org);
- $this->entry->setAttribute("homedirectory", self::HOME_DIR . $this->uid);
- $this->entry->setAttribute("loginshell", $this->LDAP->getDefUserShell());
+ $this->entry->setAttribute(
+ "homedirectory",
+ self::HOME_DIR . $this->uid,
+ );
+ $this->entry->setAttribute(
+ "loginshell",
+ $this->LDAP->getDefUserShell(),
+ );
$this->entry->setAttribute("uidnumber", strval($id));
$this->entry->setAttribute("gidnumber", strval($id));
$this->entry->write();
@@ -87,9 +104,17 @@ public function init($firstname, $lastname, $email, $org, $send_mail = true)
$this->REDIS->setCache($this->uid, "lastname", $lastname);
$this->REDIS->setCache($this->uid, "mail", $email);
$this->REDIS->setCache($this->uid, "org", $org);
- $this->REDIS->setCache($this->uid, "homedir", self::HOME_DIR . $this->uid);
- $this->REDIS->setCache($this->uid, "loginshell", $this->LDAP->getDefUserShell());
- $this->REDIS->setCache($this->uid, "sshkeys", array());
+ $this->REDIS->setCache(
+ $this->uid,
+ "homedir",
+ self::HOME_DIR . $this->uid,
+ );
+ $this->REDIS->setCache(
+ $this->uid,
+ "loginshell",
+ $this->LDAP->getDefUserShell(),
+ );
+ $this->REDIS->setCache($this->uid, "sshkeys", []);
$org = $this->getOrgGroup();
if (!$org->exists()) {
@@ -107,17 +132,16 @@ public function init($firstname, $lastname, $email, $org, $send_mail = true)
$this->SQL->addLog(
$this->uid,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"user_added",
- $this->uid
+ $this->uid,
);
if ($send_mail) {
- $this->MAILER->sendMail(
- $this->getMail(),
- "user_created",
- array("user" => $this->uid, "org" => $this->getOrg())
- );
+ $this->MAILER->sendMail($this->getMail(), "user_created", [
+ "user" => $this->uid,
+ "org" => $this->getOrg(),
+ ]);
}
}
@@ -178,9 +202,9 @@ public function setFirstname($firstname, $operator = null)
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"firstname_changed",
- $this->uid
+ $this->uid,
);
$this->entry->write();
@@ -227,9 +251,9 @@ public function setLastname($lastname, $operator = null)
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"lastname_changed",
- $this->uid
+ $this->uid,
);
$this->entry->write();
@@ -282,9 +306,9 @@ public function setMail($email, $operator = null)
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"email_changed",
- $this->uid
+ $this->uid,
);
$this->entry->write();
@@ -336,17 +360,15 @@ public function setSSHKeys($keys, $operator = null, $send_mail = true)
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"sshkey_modify",
- $this->uid
+ $this->uid,
);
if ($send_mail) {
- $this->MAILER->sendMail(
- $this->getMail(),
- "user_sshkey",
- array("keys" => $this->getSSHKeys())
- );
+ $this->MAILER->sendMail($this->getMail(), "user_sshkey", [
+ "keys" => $this->getSSHKeys(),
+ ]);
}
}
@@ -368,7 +390,7 @@ public function getSSHKeys($ignorecache = false)
if ($this->exists()) {
$result = $this->entry->getAttribute("sshpublickey");
if (is_null($result)) {
- $keys = array();
+ $keys = [];
} else {
$keys = $result;
}
@@ -391,11 +413,15 @@ public function getSSHKeys($ignorecache = false)
public function setLoginShell($shell, $operator = null, $send_mail = true)
{
// ldap schema syntax is "IA5 String (1.3.6.1.4.1.1466.115.121.1.26)"
- if (!mb_check_encoding($shell, 'ASCII')) {
- throw new Exception("non ascii characters are not allowed in a login shell!");
+ if (!mb_check_encoding($shell, "ASCII")) {
+ throw new Exception(
+ "non ascii characters are not allowed in a login shell!",
+ );
}
if ($shell != trim($shell)) {
- throw new Exception("leading/trailing whitespace is not allowed in a login shell!");
+ throw new Exception(
+ "leading/trailing whitespace is not allowed in a login shell!",
+ );
}
if (empty($shell)) {
throw new Exception("login shell must not be empty!");
@@ -408,19 +434,17 @@ public function setLoginShell($shell, $operator = null, $send_mail = true)
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"loginshell_changed",
- $this->uid
+ $this->uid,
);
$this->REDIS->setCache($this->uid, "loginshell", $shell);
if ($send_mail) {
- $this->MAILER->sendMail(
- $this->getMail(),
- "user_loginshell",
- array("new_shell" => $this->getLoginShell())
- );
+ $this->MAILER->sendMail($this->getMail(), "user_loginshell", [
+ "new_shell" => $this->getLoginShell(),
+ ]);
}
}
@@ -461,9 +485,9 @@ public function setHomeDir($home, $operator = null)
$this->SQL->addLog(
$operator,
- $_SERVER['REMOTE_ADDR'],
+ $_SERVER["REMOTE_ADDR"],
"homedir_changed",
- $this->uid
+ $this->uid,
);
$this->REDIS->setCache($this->uid, "homedir", $home);
@@ -526,7 +550,7 @@ public function getPIGroup()
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
+ $this->WEBHOOK,
);
}
@@ -538,7 +562,7 @@ public function getOrgGroup()
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
+ $this->WEBHOOK,
);
}
@@ -569,15 +593,11 @@ public function getPIGroupGIDs($ignorecache = false)
public function requestAccountDeletion()
{
$this->SQL->addAccountDeletionRequest($this->uid);
- $this->MAILER->sendMail(
- "admin",
- "account_deletion_request_admin",
- array(
- "user" => $this->uid,
- "name" => $this->getFullname(),
- "email" => $this->getMail()
- )
- );
+ $this->MAILER->sendMail("admin", "account_deletion_request_admin", [
+ "user" => $this->uid,
+ "name" => $this->getFullname(),
+ "email" => $this->getMail(),
+ ]);
}
/**
@@ -606,7 +626,7 @@ public function isInGroup($uid, $group)
$this->SQL,
$this->MAILER,
$this->REDIS,
- $this->WEBHOOK
+ $this->WEBHOOK,
);
} else {
$group_checked = $group;
diff --git a/resources/lib/UnityWebhook.php b/resources/lib/UnityWebhook.php
index 61c9dd1d..5a49c319 100644
--- a/resources/lib/UnityWebhook.php
+++ b/resources/lib/UnityWebhook.php
@@ -5,7 +5,8 @@
class UnityWebhook
{
private $template_dir = __DIR__ . "/../mail";
- private $override_template_dir = __DIR__ . "/../../deployment/mail_overrides";
+ private $override_template_dir =
+ __DIR__ . "/../../deployment/mail_overrides";
private $url = CONFIG["webhook"]["url"];
private $MSG_LINKREF;
private $Subject; // set by template
@@ -17,9 +18,9 @@ public function __construct()
public function htmlToMarkdown($html)
{
// Define regex patterns for each markdown format
- $bold = '/<(b|strong)\b[^>]*>(.*?)<\/(b|strong)>/s';
- $italic = '/]*>(.*?)<\/i>/s';
- $strikethrough = '/]*>(.*?)<\/del>/s';
+ $bold = "/<(b|strong)\b[^>]*>(.*?)<\/(b|strong)>/s";
+ $italic = "/]*>(.*?)<\/i>/s";
+ $strikethrough = "/]*>(.*?)<\/del>/s";
$link = '/]*href=["\']?([^"\'\s]*)[^>]*>(.*?)<\/a>/s';
// Replace each HTML tag with its corresponding markdown format
@@ -37,8 +38,11 @@ public function htmlToMarkdown($html)
public function sendWebhook($template = null, $data = null)
{
$template_filename = $template . ".php";
- if (file_exists($this->override_template_dir . "/" . $template_filename)) {
- $template_path = $this->override_template_dir . "/" . $template_filename;
+ if (
+ file_exists($this->override_template_dir . "/" . $template_filename)
+ ) {
+ $template_path =
+ $this->override_template_dir . "/" . $template_filename;
} else {
$template_path = $this->template_dir . "/" . $template_filename;
}
@@ -52,9 +56,11 @@ public function sendWebhook($template = null, $data = null)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->url);
curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ "Content-Type: application/json",
+ ]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, \jsonEncode(array('text' => $message)));
+ curl_setopt($ch, CURLOPT_POSTFIELDS, \jsonEncode(["text" => $message]));
$result = curl_exec($ch);
curl_close($ch);
return $result;
diff --git a/resources/lib/exceptions/ArrayKeyException.php b/resources/lib/exceptions/ArrayKeyException.php
index 7b591ac8..722878c2 100644
--- a/resources/lib/exceptions/ArrayKeyException.php
+++ b/resources/lib/exceptions/ArrayKeyException.php
@@ -2,6 +2,4 @@
namespace UnityWebPortal\lib\exceptions;
-class ArrayKeyException extends \Exception
-{
-}
+class ArrayKeyException extends \Exception {}
diff --git a/resources/lib/exceptions/EncodingConversionException.php b/resources/lib/exceptions/EncodingConversionException.php
index ac316d89..aeab6ef5 100644
--- a/resources/lib/exceptions/EncodingConversionException.php
+++ b/resources/lib/exceptions/EncodingConversionException.php
@@ -2,6 +2,4 @@
namespace UnityWebPortal\lib\exceptions;
-class EncodingConversionException extends \Exception
-{
-}
+class EncodingConversionException extends \Exception {}
diff --git a/resources/lib/exceptions/EncodingUnknownException.php b/resources/lib/exceptions/EncodingUnknownException.php
index 63725d01..d3520183 100644
--- a/resources/lib/exceptions/EncodingUnknownException.php
+++ b/resources/lib/exceptions/EncodingUnknownException.php
@@ -2,6 +2,4 @@
namespace UnityWebPortal\lib\exceptions;
-class EncodingUnknownException extends \Exception
-{
-}
+class EncodingUnknownException extends \Exception {}
diff --git a/resources/lib/exceptions/EnsureException.php b/resources/lib/exceptions/EnsureException.php
index f184f903..178142d9 100644
--- a/resources/lib/exceptions/EnsureException.php
+++ b/resources/lib/exceptions/EnsureException.php
@@ -2,6 +2,4 @@
namespace UnityWebPortal\lib\exceptions;
-class EnsureException extends \Exception
-{
-}
+class EnsureException extends \Exception {}
diff --git a/resources/lib/exceptions/NoDieException.php b/resources/lib/exceptions/NoDieException.php
index 49d8b2d8..9a069dca 100644
--- a/resources/lib/exceptions/NoDieException.php
+++ b/resources/lib/exceptions/NoDieException.php
@@ -2,6 +2,4 @@
namespace UnityWebPortal\lib\exceptions;
-class NoDieException extends \Exception
-{
-}
+class NoDieException extends \Exception {}
diff --git a/resources/lib/exceptions/SSOException.php b/resources/lib/exceptions/SSOException.php
index 2551180e..ce631639 100644
--- a/resources/lib/exceptions/SSOException.php
+++ b/resources/lib/exceptions/SSOException.php
@@ -2,6 +2,4 @@
namespace UnityWebPortal\lib\exceptions;
-class SSOException extends \Exception
-{
-}
+class SSOException extends \Exception {}
diff --git a/resources/lib/utils.php b/resources/lib/utils.php
index c0ae48ab..42acfed9 100644
--- a/resources/lib/utils.php
+++ b/resources/lib/utils.php
@@ -15,8 +15,11 @@ function arrayGet($array, ...$keys)
if (!isset($cursor[$key])) {
throw new ArrayKeyException(
"key not found: \$array" .
- // [1, 2, "foo"] => [1][2]["foo"]
- implode("", array_map(fn($x) => jsonEncode([$x]), $keysTraversed))
+ // [1, 2, "foo"] => [1][2]["foo"]
+ implode(
+ "",
+ array_map(fn($x) => jsonEncode([$x]), $keysTraversed),
+ ),
);
}
$cursor = $cursor[$key];
@@ -67,9 +70,11 @@ function mbConvertEncoding($string, $to_encoding, $from_encoding = null)
$output = mb_convert_encoding($string, $to_encoding, $from_encoding);
if ($output === false) {
throw new EncodingConversionException(
- jsonEncode(
- ["to" => $to_encoding, "from" => $from_encoding, "base64" => base64_encode($string)]
- )
+ jsonEncode([
+ "to" => $to_encoding,
+ "from" => $from_encoding,
+ "base64" => base64_encode($string),
+ ]),
);
}
return $output;
diff --git a/resources/mail/account_deletion_request_admin.php b/resources/mail/account_deletion_request_admin.php
index c9170d93..6d8fde1a 100644
--- a/resources/mail/account_deletion_request_admin.php
+++ b/resources/mail/account_deletion_request_admin.php
@@ -1,8 +1,7 @@
Subject = "Account Deletion Request";
-?>
+$this->Subject = "Account Deletion Request"; ?>
Hello,
diff --git a/resources/mail/group_created.php b/resources/mail/group_created.php
index 504be1f5..618ef57f 100644
--- a/resources/mail/group_created.php
+++ b/resources/mail/group_created.php
@@ -1,8 +1,7 @@
Subject = "PI Account Approved";
-?>
+$this->Subject = "PI Account Approved"; ?>
Hello,
diff --git a/resources/mail/group_denied.php b/resources/mail/group_denied.php
index 857e58f4..7d633e7e 100644
--- a/resources/mail/group_denied.php
+++ b/resources/mail/group_denied.php
@@ -1,8 +1,7 @@
Subject = "PI Account Denied";
-?>
+$this->Subject = "PI Account Denied"; ?>
Hello,
diff --git a/resources/mail/group_disband.php b/resources/mail/group_disband.php
index defa3b93..c26b3eb1 100644
--- a/resources/mail/group_disband.php
+++ b/resources/mail/group_disband.php
@@ -1,12 +1,13 @@
Subject = "PI Group Disbanded";
-?>
+$this->Subject = "PI Group Disbanded"; ?>
Hello,
-Your PI group, , has been disbanded on the Unity
+
Your PI group, , has been disbanded on the Unity
cluster. Any jobs associated with this PI account have been killed.
If you believe this to be a mistake, please reply to this email
diff --git a/resources/mail/group_join_request_cancelled.php b/resources/mail/group_join_request_cancelled.php
index 3421f198..331350ca 100644
--- a/resources/mail/group_join_request_cancelled.php
+++ b/resources/mail/group_join_request_cancelled.php
@@ -1,5 +1,7 @@
Subject = "Unity PI Membership Request Cancelled: '" . $data["uid"] . "'";
-?>
+$this->Subject =
+ "Unity PI Membership Request Cancelled: '" . $data["uid"] . "'"; ?>
Hello,
-The user '' has cancelled their request to join your PI group.
+The user '' has cancelled their request to join your PI group.
diff --git a/resources/mail/group_request.php b/resources/mail/group_request.php
index 5828bcfd..74f6895f 100644
--- a/resources/mail/group_request.php
+++ b/resources/mail/group_request.php
@@ -1,8 +1,7 @@
Subject = "PI Account Requested";
-?>
+$this->Subject = "PI Account Requested"; ?>
Hello,
diff --git a/resources/mail/group_request_admin.php b/resources/mail/group_request_admin.php
index 2a7b7e05..8fe51027 100644
--- a/resources/mail/group_request_admin.php
+++ b/resources/mail/group_request_admin.php
@@ -1,8 +1,7 @@
Subject = "PI Group Request";
-?>
+$this->Subject = "PI Group Request"; ?>
Hello,
diff --git a/resources/mail/group_request_cancelled.php b/resources/mail/group_request_cancelled.php
index 73995b56..31012c59 100644
--- a/resources/mail/group_request_cancelled.php
+++ b/resources/mail/group_request_cancelled.php
@@ -1,5 +1,6 @@
Subject = "PI Request Cancelled: '" . $data["uid"] . "'";
-?>
+$this->Subject = "PI Request Cancelled: '" . $data["uid"] . "'"; ?>
Hello,
-The user '' has cancelled their request to become a PI.
+The user '' has cancelled their request to become a PI.
diff --git a/resources/mail/group_user_added.php b/resources/mail/group_user_added.php
index be11dde3..9c42b8cc 100644
--- a/resources/mail/group_user_added.php
+++ b/resources/mail/group_user_added.php
@@ -1,8 +1,7 @@
Subject = "Group Request Approved";
-?>
+$this->Subject = "Group Request Approved"; ?>
Hello,
diff --git a/resources/mail/group_user_added_owner.php b/resources/mail/group_user_added_owner.php
index 33cd7e77..a082f30e 100644
--- a/resources/mail/group_user_added_owner.php
+++ b/resources/mail/group_user_added_owner.php
@@ -1,14 +1,13 @@
Subject = "Group Member Approved";
-?>
+$this->Subject = "Group Member Approved"; ?>
Hello,
A new user has been added to your PI group,
-''.
+''.
The details of the new user are below:
diff --git a/resources/mail/group_user_denied.php b/resources/mail/group_user_denied.php
index 7c5a864e..36dfc962 100644
--- a/resources/mail/group_user_denied.php
+++ b/resources/mail/group_user_denied.php
@@ -1,11 +1,12 @@
Subject = "Group Request Denied";
-?>
+$this->Subject = "Group Request Denied"; ?>
Hello,
-You have been denied from joining the PI group .
+You have been denied from joining the PI group .
If you believe this to be a mistake, please reply to this email as soon as possible.
diff --git a/resources/mail/group_user_denied_owner.php b/resources/mail/group_user_denied_owner.php
index e2cffbb9..00c2560e 100644
--- a/resources/mail/group_user_denied_owner.php
+++ b/resources/mail/group_user_denied_owner.php
@@ -1,12 +1,13 @@
Subject = "Group Member Denied";
-?>
+$this->Subject = "Group Member Denied"; ?>
Hello,
-A user has been denied from joining your PI group, .
+
A user has been denied from joining your PI group, .
The details of the denied user are below:
diff --git a/resources/mail/group_user_removed.php b/resources/mail/group_user_removed.php
index bfde1f18..83a1786e 100644
--- a/resources/mail/group_user_removed.php
+++ b/resources/mail/group_user_removed.php
@@ -1,8 +1,7 @@
Subject = "Removed from Group";
-?>
+$this->Subject = "Removed from Group"; ?>
Hello,
diff --git a/resources/mail/group_user_removed_owner.php b/resources/mail/group_user_removed_owner.php
index a97d38cf..2cff0e54 100644
--- a/resources/mail/group_user_removed_owner.php
+++ b/resources/mail/group_user_removed_owner.php
@@ -1,14 +1,13 @@
Subject = "Group Member Removed";
-?>
+$this->Subject = "Group Member Removed"; ?>
Hello,
A user has been removed from your PI group,
-''.
+''.
The details of the removed user are below:
diff --git a/resources/mail/group_user_request.php b/resources/mail/group_user_request.php
index ea88e1e1..ad40d215 100644
--- a/resources/mail/group_user_request.php
+++ b/resources/mail/group_user_request.php
@@ -1,8 +1,7 @@
Subject = "Request Submitted";
-?>
+$this->Subject = "Request Submitted"; ?>
Hello,
diff --git a/resources/mail/group_user_request_owner.php b/resources/mail/group_user_request_owner.php
index 1eac99b9..9ad4db55 100644
--- a/resources/mail/group_user_request_owner.php
+++ b/resources/mail/group_user_request_owner.php
@@ -1,14 +1,13 @@
Subject = "Group Member Request";
-?>
+$this->Subject = "Group Member Request"; ?>
Hello,
A user has requested to join your PI group,
-''.
+''.
The details of the user are below:
diff --git a/resources/mail/user_created.php b/resources/mail/user_created.php
index 172a048c..4298e777 100644
--- a/resources/mail/user_created.php
+++ b/resources/mail/user_created.php
@@ -1,8 +1,7 @@
Subject = "User Created";
-?>
+$this->Subject = "User Created"; ?>
Hello,
diff --git a/resources/mail/user_loginshell.php b/resources/mail/user_loginshell.php
index f70eba2e..f78bf54f 100644
--- a/resources/mail/user_loginshell.php
+++ b/resources/mail/user_loginshell.php
@@ -1,12 +1,13 @@
Subject = "Login Shell Updated";
-?>
+$this->Subject = "Login Shell Updated"; ?>
Hello,
-You have updated your login shell on the Unity cluster to .
+
You have updated your login shell on the Unity cluster to .
You can view the login shell settings on the
account settings page
diff --git a/resources/mail/user_sshkey.php b/resources/mail/user_sshkey.php
index d5ff241b..5a4a8076 100644
--- a/resources/mail/user_sshkey.php
+++ b/resources/mail/user_sshkey.php
@@ -1,8 +1,7 @@
Subject = "SSH Key Modified";
-?>
+$this->Subject = "SSH Key Modified"; ?>
Hello,
@@ -10,11 +9,9 @@
You have modified the SSH keys on your Unity account. These public keys are currently available:
-$key";
-}
-?>
+} ?>
You can view the SSH public keys attached to your account on the
diff --git a/test/functional/AccountDeletionRequestTest.php b/test/functional/AccountDeletionRequestTest.php
index e3530642..d8c4bb04 100644
--- a/test/functional/AccountDeletionRequestTest.php
+++ b/test/functional/AccountDeletionRequestTest.php
@@ -22,9 +22,9 @@ private function assertNumberAccountDeletionRequests(int $x)
private function getNumberAccountDeletionRequests()
{
global $USER, $SQL;
- $stmt = $SQL->getConn()->prepare(
- "SELECT * FROM account_deletion_requests WHERE uid=:uid"
- );
+ $stmt = $SQL
+ ->getConn()
+ ->prepare("SELECT * FROM account_deletion_requests WHERE uid=:uid");
$uid = $USER->uid;
$stmt->bindParam(":uid", $uid);
$stmt->execute();
@@ -38,15 +38,13 @@ public function testRequestAccountDeletionUserHasNoGroups()
$this->assertEmpty($USER->getPIGroupGIDs());
$this->assertNumberAccountDeletionRequests(0);
try {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "account_deletion_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "account_deletion_request",
+ ]);
$this->assertNumberAccountDeletionRequests(1);
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "account_deletion_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "account_deletion_request",
+ ]);
$this->assertNumberAccountDeletionRequests(1);
} finally {
$SQL->deleteAccountDeletionRequest($USER->uid);
@@ -62,10 +60,9 @@ public function testRequestAccountDeletionUserHasGroup()
$this->assertNotEmpty($USER->getPIGroupGIDs());
$this->assertNumberAccountDeletionRequests(0);
try {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "account_deletion_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "account_deletion_request",
+ ]);
$this->assertNumberAccountDeletionRequests(0);
} finally {
$SQL->deleteAccountDeletionRequest($USER->uid);
diff --git a/test/functional/InvalidEPPNTest.php b/test/functional/InvalidEPPNTest.php
index 239d9d91..40cc454d 100644
--- a/test/functional/InvalidEPPNTest.php
+++ b/test/functional/InvalidEPPNTest.php
@@ -8,12 +8,7 @@ class InvalidEPPNTest extends TestCase
{
public static function provider()
{
- return [
- ["", false],
- ["a", false],
- ["a@b", true],
- ["a@b@c", false],
- ];
+ return [["", false], ["a", false], ["a@b", true], ["a@b@c", false]];
}
#[DataProvider("provider")]
diff --git a/test/functional/LoginShellSetTest.php b/test/functional/LoginShellSetTest.php
index 90233248..a03cebfa 100644
--- a/test/functional/LoginShellSetTest.php
+++ b/test/functional/LoginShellSetTest.php
@@ -23,16 +23,17 @@ public function tearDown(): void
public static function getShells()
{
global $HTTP_HEADER_TEST_INPUTS;
- return [["/bin/bash"]] + array_map(function($x){return [$x];}, $HTTP_HEADER_TEST_INPUTS);
+ return [["/bin/bash"]] +
+ array_map(function ($x) {
+ return [$x];
+ }, $HTTP_HEADER_TEST_INPUTS);
}
private function isShellValid(string $shell)
{
- return (
- (mb_check_encoding($shell, 'ASCII')) &&
- ($shell == trim($shell)) &&
- (!empty($shell))
- );
+ return mb_check_encoding($shell, "ASCII") &&
+ $shell == trim($shell) &&
+ !empty($shell);
}
#[DataProvider("getShells")]
@@ -42,10 +43,10 @@ public function testSetLoginShell(string $shell): void
if (!$this->isShellValid($shell)) {
$this->expectException("Exception");
}
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "loginshell", "shellSelect" => $shell]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "loginshell",
+ "shellSelect" => $shell,
+ ]);
$this->assertEquals($shell, $USER->getLoginShell());
}
}
diff --git a/test/functional/NewUserTest.php b/test/functional/NewUserTest.php
index e9254ec1..dc6d8f7b 100644
--- a/test/functional/NewUserTest.php
+++ b/test/functional/NewUserTest.php
@@ -8,7 +8,8 @@
class NewUserTest extends TestCase
{
- public static function provider() {
+ public static function provider()
+ {
return [
getNonExistentUserAndExpectedUIDGIDNoCustomMapping(),
getNonExistentUserAndExpectedUIDGIDWithCustomMapping(),
@@ -20,78 +21,68 @@ private function assertRequestedPIGroup(bool $expected)
global $USER, $SQL;
$this->assertEquals(
$expected,
- $SQL->requestExists($USER->uid, UnitySQL::REQUEST_BECOME_PI)
+ $SQL->requestExists($USER->uid, UnitySQL::REQUEST_BECOME_PI),
);
}
private function assertRequestedMembership(bool $expected, string $gid)
{
global $USER, $SQL;
- $this->assertEquals(
- $expected,
- $SQL->requestExists($USER->uid, $gid)
- );
+ $this->assertEquals($expected, $SQL->requestExists($USER->uid, $gid));
}
private function requestGroupCreation()
{
- http_post(
- __DIR__ . "/../../webroot/panel/new_account.php",
- ["new_user_sel" => "pi", "eula" => "agree", "confirm_pi" => "agree"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/new_account.php", [
+ "new_user_sel" => "pi",
+ "eula" => "agree",
+ "confirm_pi" => "agree",
+ ]);
}
private function requestGroupMembership(string $gid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/new_account.php",
- ["new_user_sel" => "not_pi", "eula" => "agree", "pi" => $gid]
- );
+ http_post(__DIR__ . "/../../webroot/panel/new_account.php", [
+ "new_user_sel" => "not_pi",
+ "eula" => "agree",
+ "pi" => $gid,
+ ]);
}
private function cancelAllRequests()
{
http_post(
__DIR__ . "/../../webroot/panel/new_account.php",
- ["cancel" => "true"] // value of cancel is arbitrary
+ ["cancel" => "true"], // value of cancel is arbitrary
);
}
private function approveUserByAdmin($gid, $uid)
{
- http_post(
- __DIR__ . "/../../webroot/admin/pi-mgmt.php",
- [
- "form_type" => "reqChild",
- "action" => "Approve",
- "pi" => $gid,
- "uid" => $uid,
- ]
- );
+ http_post(__DIR__ . "/../../webroot/admin/pi-mgmt.php", [
+ "form_type" => "reqChild",
+ "action" => "Approve",
+ "pi" => $gid,
+ "uid" => $uid,
+ ]);
}
private function approveUserByPI($uid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/pi.php",
- [
- "form_type" => "userReq",
- "action" => "Approve",
- "uid" => $uid,
- ]
- );
+ http_post(__DIR__ . "/../../webroot/panel/pi.php", [
+ "form_type" => "userReq",
+ "action" => "Approve",
+ "uid" => $uid,
+ ]);
}
private function approveGroup($uid)
{
- http_post(
- __DIR__ . "/../../webroot/admin/pi-mgmt.php",
- [
- "form_type" => "req",
- "action" => "Approve",
- "uid" => $uid,
- ]
- );
+ http_post(__DIR__ . "/../../webroot/admin/pi-mgmt.php", [
+ "form_type" => "req",
+ "action" => "Approve",
+ "uid" => $uid,
+ ]);
}
// delete requests made by that user
@@ -124,10 +115,15 @@ private function ensureUserDoesNotExist()
"memberuid",
// array_diff will break the contiguity of the array indexes
// ldap_mod_replace requires contiguity, array_values restores contiguity
- array_values(array_diff($all_member_uids, [$USER->uid]))
+ array_values(array_diff($all_member_uids, [$USER->uid])),
);
$all_users_group->write();
- ensure(!in_array($USER->uid, $all_users_group->getAttribute("memberuid")));
+ ensure(
+ !in_array(
+ $USER->uid,
+ $all_users_group->getAttribute("memberuid"),
+ ),
+ );
}
$REDIS->removeCacheArray("sorted_users", "", $USER->uid);
}
@@ -165,8 +161,10 @@ private function ensurePIGroupDoesNotExist()
}
#[DataProvider("provider")]
- public function testCreateUserByJoinGoupByPI($user_to_create_args, $expected_uid_gid)
- {
+ public function testCreateUserByJoinGoupByPI(
+ $user_to_create_args,
+ $expected_uid_gid,
+ ) {
global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK;
$pi_user_args = getUserIsPIHasNoMembersNoMemberRequests();
switchUser(...$pi_user_args);
@@ -174,7 +172,14 @@ public function testCreateUserByJoinGoupByPI($user_to_create_args, $expected_uid
$gid = $pi_group->gid;
switchUser(...$user_to_create_args);
$this->assertTrue(!$USER->exists());
- $newOrg = new UnityOrg($SSO["org"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $newOrg = new UnityOrg(
+ $SSO["org"],
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
$this->assertTrue(!$newOrg->exists());
$this->assertTrue($pi_group->exists());
$this->assertTrue(!$pi_group->memberExists($USER));
@@ -214,8 +219,14 @@ public function testCreateUserByJoinGoupByPI($user_to_create_args, $expected_uid
$user_entry = $LDAP->getUserEntry($approve_uid);
$user_group_entry = $LDAP->getGroupEntry($approve_uid);
- $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]);
- $this->assertEquals($expected_uid_gid, $user_group_entry->getAttribute("gidnumber")[0]);
+ $this->assertEquals(
+ $expected_uid_gid,
+ $user_entry->getAttribute("uidnumber")[0],
+ );
+ $this->assertEquals(
+ $expected_uid_gid,
+ $user_group_entry->getAttribute("gidnumber")[0],
+ );
// $third_request_failed = false;
// try {
@@ -271,15 +282,24 @@ public function testCreateMultipleUsersByJoinGoupByPI()
}
#[DataProvider("provider")]
- public function testCreateUserByJoinGoupByAdmin($user_to_create_args, $expected_uid_gid)
- {
+ public function testCreateUserByJoinGoupByAdmin(
+ $user_to_create_args,
+ $expected_uid_gid,
+ ) {
global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK;
switchUser(...getUserIsPIHasNoMembersNoMemberRequests());
$pi_group = $USER->getPIGroup();
$gid = $pi_group->gid;
switchUser(...$user_to_create_args);
$this->assertTrue(!$USER->exists());
- $newOrg = new UnityOrg($SSO["org"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $newOrg = new UnityOrg(
+ $SSO["org"],
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
$this->assertTrue(!$newOrg->exists());
$this->assertTrue($pi_group->exists());
$this->assertTrue(!$pi_group->memberExists($USER));
@@ -319,8 +339,14 @@ public function testCreateUserByJoinGoupByAdmin($user_to_create_args, $expected_
$user_entry = $LDAP->getUserEntry($approve_uid);
$user_group_entry = $LDAP->getGroupEntry($approve_uid);
- $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]);
- $this->assertEquals($expected_uid_gid, $user_group_entry->getAttribute("gidnumber")[0]);
+ $this->assertEquals(
+ $expected_uid_gid,
+ $user_entry->getAttribute("uidnumber")[0],
+ );
+ $this->assertEquals(
+ $expected_uid_gid,
+ $user_group_entry->getAttribute("gidnumber")[0],
+ );
// $third_request_failed = false;
// try {
@@ -340,14 +366,23 @@ public function testCreateUserByJoinGoupByAdmin($user_to_create_args, $expected_
}
#[DataProvider("provider")]
- public function testCreateUserByCreateGroup($user_to_create_args, $expected_uid_gid)
- {
+ public function testCreateUserByCreateGroup(
+ $user_to_create_args,
+ $expected_uid_gid,
+ ) {
global $USER, $SSO, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK;
switchuser(...$user_to_create_args);
$pi_group = $USER->getPIGroup();
$this->assertTrue(!$USER->exists());
$this->assertTrue(!$pi_group->exists());
- $newOrg = new UnityOrg($SSO["org"], $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $newOrg = new UnityOrg(
+ $SSO["org"],
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
$this->assertTrue(!$newOrg->exists());
try {
$this->requestGroupCreation();
@@ -382,8 +417,14 @@ public function testCreateUserByCreateGroup($user_to_create_args, $expected_uid_
$user_entry = $LDAP->getUserEntry($approve_uid);
$user_group_entry = $LDAP->getGroupEntry($approve_uid);
- $this->assertEquals($expected_uid_gid, $user_entry->getAttribute("uidnumber")[0]);
- $this->assertEquals($expected_uid_gid, $user_group_entry->getAttribute("gidnumber")[0]);
+ $this->assertEquals(
+ $expected_uid_gid,
+ $user_entry->getAttribute("uidnumber")[0],
+ );
+ $this->assertEquals(
+ $expected_uid_gid,
+ $user_group_entry->getAttribute("gidnumber")[0],
+ );
// $third_request_failed = false;
// try {
diff --git a/test/functional/PIMemberRequestTest.php b/test/functional/PIMemberRequestTest.php
index 7b31e01b..c1a7dec0 100644
--- a/test/functional/PIMemberRequestTest.php
+++ b/test/functional/PIMemberRequestTest.php
@@ -5,21 +5,20 @@
class PiMemberRequestTest extends TestCase
{
-
private function requestMembership(string $gid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/groups.php",
- ["form_type" => "addPIform", "pi" => $gid],
- );
+ http_post(__DIR__ . "/../../webroot/panel/groups.php", [
+ "form_type" => "addPIform",
+ "pi" => $gid,
+ ]);
}
private function cancelRequest(string $gid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/groups.php",
- ["form_type" => "cancelPIForm", "pi" => $gid],
- );
+ http_post(__DIR__ . "/../../webroot/panel/groups.php", [
+ "form_type" => "cancelPIForm",
+ "pi" => $gid,
+ ]);
}
public function testRequestMembership()
@@ -31,12 +30,16 @@ public function testRequestMembership()
$gid = $pi_group->gid;
$this->assertTrue($USER->isPI());
$this->assertTrue($pi_group->exists());
- $this->assertTrue(arraysAreEqualUnOrdered([$pi], $pi_group->getGroupMembers()));
+ $this->assertTrue(
+ arraysAreEqualUnOrdered([$pi], $pi_group->getGroupMembers()),
+ );
$this->assertEquals([], $SQL->getRequests($gid));
switchUser(...getUserNotPiNotRequestedBecomePi());
$uid = $USER->uid;
$this->assertFalse($USER->isPI());
- $this->assertFalse($SQL->requestExists($uid, UnitySQL::REQUEST_BECOME_PI));
+ $this->assertFalse(
+ $SQL->requestExists($uid, UnitySQL::REQUEST_BECOME_PI),
+ );
$this->assertFalse($pi_group->memberExists($USER));
try {
$this->requestMembership($gid);
diff --git a/test/functional/PageLoadTest.php b/test/functional/PageLoadTest.php
index 71d531dd..1d812b08 100644
--- a/test/functional/PageLoadTest.php
+++ b/test/functional/PageLoadTest.php
@@ -16,7 +16,10 @@ public static function provider()
[$admin, __DIR__ . "/../../webroot/admin/user-mgmt.php"],
[$admin, __DIR__ . "/../../webroot/admin/content.php"],
[$admin, __DIR__ . "/../../webroot/admin/notices.php"],
- [$nonexistent_user, __DIR__ . "/../../webroot/panel/new_account.php"],
+ [
+ $nonexistent_user,
+ __DIR__ . "/../../webroot/panel/new_account.php",
+ ],
[$normal_user, __DIR__ . "/../../webroot/panel/account.php"],
[$normal_user, __DIR__ . "/../../webroot/panel/groups.php"],
[$normal_user, __DIR__ . "/../../webroot/panel/support.php"],
diff --git a/test/functional/PiBecomeRequestTest.php b/test/functional/PiBecomeRequestTest.php
index abd446a1..6a549a5b 100644
--- a/test/functional/PiBecomeRequestTest.php
+++ b/test/functional/PiBecomeRequestTest.php
@@ -23,9 +23,11 @@ private function getNumberPiBecomeRequests()
global $USER, $SQL;
// FIXME table name, "admin" are private constants in UnitySQL
// FIXME "admin" should be something else
- $stmt = $SQL->getConn()->prepare(
- "SELECT * FROM requests WHERE uid=:uid and request_for='admin'"
- );
+ $stmt = $SQL
+ ->getConn()
+ ->prepare(
+ "SELECT * FROM requests WHERE uid=:uid and request_for='admin'",
+ );
$uid = $USER->uid;
$stmt->bindParam(":uid", $uid);
$stmt->execute();
@@ -39,25 +41,21 @@ public function testRequestBecomePi()
$this->assertFalse($USER->isPI());
$this->assertNumberPiBecomeRequests(0);
try {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "pi_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "pi_request",
+ ]);
$this->assertNumberPiBecomeRequests(1);
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "cancel_pi_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "cancel_pi_request",
+ ]);
$this->assertNumberPiBecomeRequests(0);
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "pi_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "pi_request",
+ ]);
$this->assertNumberPiBecomeRequests(1);
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "pi_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "pi_request",
+ ]);
$this->assertNumberPiBecomeRequests(1);
} finally {
if ($SQL->requestExists($USER, UnitySQL::REQUEST_BECOME_PI)) {
@@ -69,15 +67,16 @@ public function testRequestBecomePi()
public function testRequestBecomePiUserRequestedAccountDeletion()
{
global $USER, $SQL;
- switchUser(...getUserNotPiNotRequestedBecomePiRequestedAccountDeletion());
+ switchUser(
+ ...getUserNotPiNotRequestedBecomePiRequestedAccountDeletion(),
+ );
$this->assertFalse($USER->isPI());
$this->assertNumberPiBecomeRequests(0);
$this->assertTrue($SQL->accDeletionRequestExists($USER->uid));
try {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "pi_request"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "pi_request",
+ ]);
$this->assertNumberPiBecomeRequests(0);
} finally {
if ($SQL->requestExists($USER, UnitySQL::REQUEST_BECOME_PI)) {
diff --git a/test/functional/PiMemberApproveTest.php b/test/functional/PiMemberApproveTest.php
index 020675ef..f8b3d700 100644
--- a/test/functional/PiMemberApproveTest.php
+++ b/test/functional/PiMemberApproveTest.php
@@ -6,42 +6,41 @@
use UnityWebPortal\lib\UnityGroup;
use UnityWebPortal\lib\UnitySSO;
-class PiMemberApproveTest extends TestCase {
- static $userWithRequestSwitchArgs;
- static $userWithoutRequestSwitchArgs;
- static $piSwitchArgs;
- static $pi;
- static $userWithRequestUID;
- static $userWithoutRequestUID;
- static $piUID;
- static $userWithRequest;
- static $userWithoutRequest;
- static $piGroup;
- static $piGroupGID;
+class PiMemberApproveTest extends TestCase
+{
+ static $userWithRequestSwitchArgs;
+ static $userWithoutRequestSwitchArgs;
+ static $piSwitchArgs;
+ static $pi;
+ static $userWithRequestUID;
+ static $userWithoutRequestUID;
+ static $piUID;
+ static $userWithRequest;
+ static $userWithoutRequest;
+ static $piGroup;
+ static $piGroupGID;
private function approveUser(string $uid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/pi.php",
- ["form_type" => "userReq", "action" => "Approve", "uid" => $uid]
- );
+ http_post(__DIR__ . "/../../webroot/panel/pi.php", [
+ "form_type" => "userReq",
+ "action" => "Approve",
+ "uid" => $uid,
+ ]);
}
private function requestJoinPI(string $gid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/groups.php",
- ["form_type" => "addPIform", "pi" => $gid]
- );
+ http_post(__DIR__ . "/../../webroot/panel/groups.php", [
+ "form_type" => "addPIform",
+ "pi" => $gid,
+ ]);
}
private function assertGroupMembers(UnityGroup $group, array $members)
{
$this->assertTrue(
- arraysAreEqualUnOrdered(
- $members,
- $group->getGroupMemberUIDs()
- )
+ arraysAreEqualUnOrdered($members, $group->getGroupMemberUIDs()),
);
}
diff --git a/test/functional/PiMemberDenyTest.php b/test/functional/PiMemberDenyTest.php
index 08b944d3..373bab5b 100644
--- a/test/functional/PiMemberDenyTest.php
+++ b/test/functional/PiMemberDenyTest.php
@@ -4,10 +4,12 @@
use PHPUnit\Framework\Attributes\DataProvider;
use UnityWebPortal\lib\UnityUser;
-class PiMemberDenyTest extends TestCase {
+class PiMemberDenyTest extends TestCase
+{
static $requestUid;
- public static function setUpBeforeClass(): void{
+ public static function setUpBeforeClass(): void
+ {
global $USER;
switchUser(...getNormalUser());
self::$requestUid = $USER->uid;
@@ -15,10 +17,11 @@ public static function setUpBeforeClass(): void{
private function denyUser(string $uid)
{
- post(
- __DIR__ . "/../../webroot/panel/pi.php",
- ["form_type" => "userReq", "action" => "approve", "uid" => $uid]
- );
+ post(__DIR__ . "/../../webroot/panel/pi.php", [
+ "form_type" => "userReq",
+ "action" => "approve",
+ "uid" => $uid,
+ ]);
}
public function testDenyRequest()
@@ -29,13 +32,17 @@ public function testDenyRequest()
$piGroup = $USER->getPIGroup();
$this->assertTrue($piGroup->exists());
$this->assertTrue(
- arraysAreEqualUnOrdered(
- [$pi->uid],
- $piGroup->getGroupMemberUIDs()
- )
+ arraysAreEqualUnOrdered([$pi->uid], $piGroup->getGroupMemberUIDs()),
);
$this->assertEmpty($piGroup->getRequests());
- $requestedUser = new UnityUser(self::$requestUid, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $requestedUser = new UnityUser(
+ self::$requestUid,
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
try {
$piGroup->newUserRequest(
$requestedUser,
@@ -51,8 +58,8 @@ public function testDenyRequest()
$this->assertTrue(
arraysAreEqualUnOrdered(
[$pi->uid],
- $piGroup->getGroupMemberUIDs()
- )
+ $piGroup->getGroupMemberUIDs(),
+ ),
);
$this->assertFalse($piGroup->memberExists($requestedUser));
} finally {
diff --git a/test/functional/PiRemoveUserTest.php b/test/functional/PiRemoveUserTest.php
index dc4e7773..e6858bd5 100644
--- a/test/functional/PiRemoveUserTest.php
+++ b/test/functional/PiRemoveUserTest.php
@@ -4,13 +4,14 @@
use PHPUnit\Framework\Attributes\DataProvider;
use UnityWebPortal\lib\UnityUser;
-class PiRemoveUserTest extends TestCase {
+class PiRemoveUserTest extends TestCase
+{
private function removeUser(string $uid)
{
- http_post(
- __DIR__ . "/../../webroot/panel/pi.php",
- ["form_type" => "remUser", "uid" => $uid]
- );
+ http_post(__DIR__ . "/../../webroot/panel/pi.php", [
+ "form_type" => "remUser",
+ "uid" => $uid,
+ ]);
}
public function testRemoveUser()
@@ -29,7 +30,14 @@ public function testRemoveUser()
$memberToDelete = null;
foreach ($memberUIDs as $uid) {
if ($uid != $piUid) {
- $memberToDelete = new UnityUser($uid, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
+ $memberToDelete = new UnityUser(
+ $uid,
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $REDIS,
+ $WEBHOOK,
+ );
if ($memberToDelete->hasRequestedAccountDeletion()) {
continue;
}
@@ -78,6 +86,6 @@ public function testRemovePIFromTheirOwnGroup()
);
$piGroup->approveUser($pi);
}
- }
+ }
}
}
diff --git a/test/functional/SSHKeyAddTest.php b/test/functional/SSHKeyAddTest.php
index bd4abebb..c330ae58 100644
--- a/test/functional/SSHKeyAddTest.php
+++ b/test/functional/SSHKeyAddTest.php
@@ -7,30 +7,29 @@
class SSHKeyAddTest extends TestCase
{
- private function addSshKeysPaste(array $keys): void {
+ private function addSshKeysPaste(array $keys): void
+ {
foreach ($keys as $key) {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- [
- "form_type" => "addKey",
- "add_type" => "paste",
- "key" => $key
- ]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "addKey",
+ "add_type" => "paste",
+ "key" => $key,
+ ]);
}
}
- private function addSshKeysImport(array $keys): void {
+ private function addSshKeysImport(array $keys): void
+ {
foreach ($keys as $key) {
$tmp = tmpfile();
$tmp_path = stream_get_meta_data($tmp)["uri"];
fwrite($tmp, $key);
$_FILES["keyfile"] = ["tmp_name" => $tmp_path];
try {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "addKey", "add_type" => "import"]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "addKey",
+ "add_type" => "import",
+ ]);
$this->assertFalse(file_exists($tmp_path));
} finally {
unset($_FILES["keyfile"]);
@@ -38,46 +37,44 @@ private function addSshKeysImport(array $keys): void {
}
}
- private function addSshKeysGenerate(array $keys): void {
+ private function addSshKeysGenerate(array $keys): void
+ {
foreach ($keys as $key) {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- [
- "form_type" => "addKey",
- "add_type" => "generate",
- "gen_key" => $key
- ]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "addKey",
+ "add_type" => "generate",
+ "gen_key" => $key,
+ ]);
}
}
- private function addSshKeysGithub(array $keys): void {
+ private function addSshKeysGithub(array $keys): void
+ {
global $GITHUB;
$oldGithub = $GITHUB;
$GITHUB = $this->createMock(UnityGithub::class);
$GITHUB->method("getSshPublicKeys")->willReturn($keys);
try {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- [
- "form_type" => "addKey",
- "add_type" => "github",
- "gh_user" => "foobar"
- ]
- );
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "addKey",
+ "add_type" => "github",
+ "gh_user" => "foobar",
+ ]);
} finally {
$GITHUB = $oldGithub;
}
}
- public static function provider() {
- $validKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+XqO25MUB9x/pS04I3JQ7rMGboWyGXh0GUzkOrTi7a foobar";
+ public static function provider()
+ {
+ $validKey =
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+XqO25MUB9x/pS04I3JQ7rMGboWyGXh0GUzkOrTi7a foobar";
$invalidKey = "foobar";
$methods = [
"addSshKeysPaste",
"addSshKeysImport",
"addSshKeysGenerate",
- "addSshKeysGithub"
+ "addSshKeysGithub",
];
$output = [];
foreach ($methods as $method) {
@@ -99,8 +96,11 @@ public function getKeyCount()
}
#[DataProvider("provider")]
- public function testAddSshKeys(string $methodName, int $expectedKeysAdded, array $keys)
- {
+ public function testAddSshKeys(
+ string $methodName,
+ int $expectedKeysAdded,
+ array $keys,
+ ) {
global $USER;
switchUser(...getUserHasNoSshKeys());
$numKeysBefore = $this->getKeyCount($USER);
@@ -109,7 +109,10 @@ public function testAddSshKeys(string $methodName, int $expectedKeysAdded, array
call_user_func([SSHKeyAddTest::class, $methodName], $keys);
// $method($keys);
$numKeysAfter = $this->getKeyCount($USER);
- $this->assertEquals($expectedKeysAdded, ($numKeysAfter - $numKeysBefore));
+ $this->assertEquals(
+ $expectedKeysAdded,
+ $numKeysAfter - $numKeysBefore,
+ );
} finally {
$USER->setSSHKeys([]);
}
diff --git a/test/functional/SSHKeyDeleteTest.php b/test/functional/SSHKeyDeleteTest.php
index d924acd3..c4a3aaab 100644
--- a/test/functional/SSHKeyDeleteTest.php
+++ b/test/functional/SSHKeyDeleteTest.php
@@ -3,26 +3,31 @@
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\DataProvider;
-class SSHKeyDeleteTest extends TestCase {
+class SSHKeyDeleteTest extends TestCase
+{
static $initialKeys;
- public static function setUpBeforeClass(): void{
+ public static function setUpBeforeClass(): void
+ {
global $USER;
switchUser(...getUserWithOneKey());
self::$initialKeys = $USER->getSSHKeys(true);
}
- private function deleteKey(string $index): void {
- http_post(
- __DIR__ . "/../../webroot/panel/account.php",
- ["form_type" => "delKey", "delIndex" => $index]
- );
+ private function deleteKey(string $index): void
+ {
+ http_post(__DIR__ . "/../../webroot/panel/account.php", [
+ "form_type" => "delKey",
+ "delIndex" => $index,
+ ]);
}
public static function getGarbageIndexArgs()
{
global $HTTP_HEADER_TEST_INPUTS;
- return array_map(function($x){return [$x];}, $HTTP_HEADER_TEST_INPUTS);
+ return array_map(function ($x) {
+ return [$x];
+ }, $HTTP_HEADER_TEST_INPUTS);
}
#[DataProvider("getGarbageIndexArgs")]
diff --git a/test/functional/ViewAsUserTest.php b/test/functional/ViewAsUserTest.php
index 12d6e70a..a4195e0d 100644
--- a/test/functional/ViewAsUserTest.php
+++ b/test/functional/ViewAsUserTest.php
@@ -14,13 +14,10 @@ public function _testViewAsUser(array $beforeUser, array $afterUser)
// $this->assertTrue($USER->isAdmin());
$beforeUid = $USER->uid;
// $this->assertNotEquals($afterUid, $beforeUid);
- http_post(
- __DIR__ . "/../../webroot/admin/user-mgmt.php",
- [
- "form_type" => "viewAsUser",
- "uid" => $afterUid,
- ],
- );
+ http_post(__DIR__ . "/../../webroot/admin/user-mgmt.php", [
+ "form_type" => "viewAsUser",
+ "uid" => $afterUid,
+ ]);
$this->assertArrayHasKey("viewUser", $_SESSION);
// redirect means that php process dies and user's browser will initiate a new one
// this makes `require_once autoload.php` run again and init.php changes $USER
@@ -29,10 +26,9 @@ public function _testViewAsUser(array $beforeUser, array $afterUser)
// now we should be new user
$this->assertEquals($afterUid, $USER->uid);
// $this->assertTrue($_SESSION["user_exists"]);
- http_post(
- __DIR__ . "/../../resources/templates/header.php",
- ["form_type" => "clearView"],
- );
+ http_post(__DIR__ . "/../../resources/templates/header.php", [
+ "form_type" => "clearView",
+ ]);
$this->assertArrayNotHasKey("viewUser", $_SESSION);
// redirect means that php process dies and user's browser will initiate a new one
// this makes `require_once autoload.php` run again and init.php changes $USER
@@ -64,13 +60,10 @@ public function testNonAdminViewAsAdmin()
$adminUid = $USER->uid;
$this->assertTrue($USER->isAdmin());
switchUser(...getNormalUser());
- http_post(
- __DIR__ . "/../../webroot/admin/user-mgmt.php",
- [
- "form_type" => "viewAsUser",
- "uid" => $adminUid,
- ],
- );
+ http_post(__DIR__ . "/../../webroot/admin/user-mgmt.php", [
+ "form_type" => "viewAsUser",
+ "uid" => $adminUid,
+ ]);
$this->assertArrayNotHasKey("viewUser", $_SESSION);
}
}
diff --git a/test/phpunit-bootstrap.php b/test/phpunit-bootstrap.php
index 34b370d9..34f81f53 100644
--- a/test/phpunit-bootstrap.php
+++ b/test/phpunit-bootstrap.php
@@ -1,7 +1,9 @@
This is a paragraph
',
+ "",
+ "a",
+ "Hello, World!",
+ " Some text ",
+ " ",
+ "12345",
+ "abc123",
+ "Hello@World!",
+ str_repeat("a", 8190), // https://httpd.apache.org/docs/2.2/mod/core.html#limitrequestfieldsize
+ "This is a paragraph
",
"'; DROP TABLE users; --",
"",
- 'こんにちは世界',
+ "こんにちは世界",
"Hello 👋 World 🌍",
"Line 1\nLine 2",
"Column1\tColumn2",
- 'MiXeD cAsE',
- 'https://www.example.com',
- 'user@example.com',
+ "MiXeD cAsE",
+ "https://www.example.com",
+ "user@example.com",
'{"key": "value"}',
- 'SGVsbG8sIFdvcmxkIQ==',
+ "SGVsbG8sIFdvcmxkIQ==",
"Hello\x00World",
- mbConvertEncoding("Hello, World!", "UTF-16")
+ mbConvertEncoding("Hello, World!", "UTF-16"),
];
function arraysAreEqualUnOrdered(array $a, array $b): bool
{
- return (array_diff($a, $b) == [] && array_diff($b, $a) == []);
+ return array_diff($a, $b) == [] && array_diff($b, $a) == [];
}
-
function switchUser(
string $eppn,
string $given_name,
string $sn,
string $mail,
- ?string $session_id = null
+ ?string $session_id = null,
): void {
- global $REDIS, $LDAP, $SQL, $MAILER, $WEBHOOK, $GITHUB, $SITE, $SSO, $OPERATOR, $USER, $SEND_PIMESG_TO_ADMINS, $LOC_HEADER, $LOC_FOOTER;
+ global $REDIS,
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $WEBHOOK,
+ $GITHUB,
+ $SITE,
+ $SSO,
+ $OPERATOR,
+ $USER,
+ $SEND_PIMESG_TO_ADMINS,
+ $LOC_HEADER,
+ $LOC_FOOTER;
session_write_close();
if (is_null($session_id)) {
session_id(str_replace(["_", "@", "."], "-", uniqid($eppn . "_")));
@@ -80,17 +95,29 @@ function switchUser(
$_SERVER["eppn"] = $eppn;
$_SERVER["givenName"] = $given_name;
$_SERVER["sn"] = $sn;
- include __DIR__ . "/../resources/autoload.php";
+ include __DIR__ . "/../resources/autoload.php";
ensure(!is_null($USER));
}
function http_post(string $phpfile, array $post_data): void
{
- global $REDIS, $LDAP, $SQL, $MAILER, $WEBHOOK, $GITHUB, $SITE, $SSO, $OPERATOR, $USER, $SEND_PIMESG_TO_ADMINS, $LOC_HEADER, $LOC_FOOTER;
+ global $REDIS,
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $WEBHOOK,
+ $GITHUB,
+ $SITE,
+ $SSO,
+ $OPERATOR,
+ $USER,
+ $SEND_PIMESG_TO_ADMINS,
+ $LOC_HEADER,
+ $LOC_FOOTER;
$_PREVIOUS_SERVER = $_SERVER;
$_SERVER["REQUEST_METHOD"] = "POST";
$_SERVER["PHP_SELF"] = preg_replace("/.*webroot\//", "/", $phpfile);
- $_SERVER["REQUEST_URI"] = preg_replace("/.*webroot\//", "/", $phpfile); // Slightly imprecise because it doesn't include get parameters
+ $_SERVER["REQUEST_URI"] = preg_replace("/.*webroot\//", "/", $phpfile); // Slightly imprecise because it doesn't include get parameters
$_POST = $post_data;
ob_start();
$post_did_redirect_or_die = false;
@@ -107,13 +134,25 @@ function http_post(string $phpfile, array $post_data): void
ensure($post_did_redirect_or_die, "post did not redirect or die!");
}
-function http_get(string $phpfile, array $get_data = array()): void
+function http_get(string $phpfile, array $get_data = []): void
{
- global $REDIS, $LDAP, $SQL, $MAILER, $WEBHOOK, $GITHUB, $SITE, $SSO, $OPERATOR, $USER, $SEND_PIMESG_TO_ADMINS, $LOC_HEADER, $LOC_FOOTER;
+ global $REDIS,
+ $LDAP,
+ $SQL,
+ $MAILER,
+ $WEBHOOK,
+ $GITHUB,
+ $SITE,
+ $SSO,
+ $OPERATOR,
+ $USER,
+ $SEND_PIMESG_TO_ADMINS,
+ $LOC_HEADER,
+ $LOC_FOOTER;
$_PREVIOUS_SERVER = $_SERVER;
$_SERVER["REQUEST_METHOD"] = "GET";
$_SERVER["PHP_SELF"] = preg_replace("/.*webroot\//", "/", $phpfile);
- $_SERVER["REQUEST_URI"] = preg_replace("/.*webroot\//", "/", $phpfile); // Slightly imprecise because it doesn't include get parameters
+ $_SERVER["REQUEST_URI"] = preg_replace("/.*webroot\//", "/", $phpfile); // Slightly imprecise because it doesn't include get parameters
$_GET = $get_data;
ob_start();
try {
@@ -192,13 +231,19 @@ function getNonExistentUserAndExpectedUIDGIDNoCustomMapping()
{
// defaults/config.ini.default: ldap.offset_UIDGID=1000000
// test/custom_user_mappings/test.csv has reservations for 1000000-1000004
- return [["user2002@org998.test", "foo", "bar", "user2002@org998.test"], 1000005];
+ return [
+ ["user2002@org998.test", "foo", "bar", "user2002@org998.test"],
+ 1000005,
+ ];
}
function getNonExistentUserAndExpectedUIDGIDWithCustomMapping()
{
// test/custom_user_mappings/test.csv: {user2001: 555}
- return [["user2001@org998.test", "foo", "bar", "user2001@org998.test"], 555];
+ return [
+ ["user2001@org998.test", "foo", "bar", "user2001@org998.test"],
+ 555,
+ ];
}
function getMultipleValueAttributesAndExpectedSSO()
@@ -214,7 +259,7 @@ function getMultipleValueAttributesAndExpectedSSO()
"firstname" => "foo",
"lastname" => "bar",
"mail" => "user2003@org998.test",
- ]
+ ],
];
}
diff --git a/test/unit/AjaxSshValidateTest.php b/test/unit/AjaxSshValidateTest.php
index 43a3e685..e22cb0b2 100644
--- a/test/unit/AjaxSshValidateTest.php
+++ b/test/unit/AjaxSshValidateTest.php
@@ -12,7 +12,10 @@ public static function providerTestSshValidate()
// sanity check only, see UnityHTTPDTest for more comprehensive test cases
return [
[false, "foobar"],
- [true, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+XqO25MUB9x/pS04I3JQ7rMGboWyGXh0GUzkOrTi7a"],
+ [
+ true,
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+XqO25MUB9x/pS04I3JQ7rMGboWyGXh0GUzkOrTi7a",
+ ],
];
}
diff --git a/test/unit/UnityGithubTest.php b/test/unit/UnityGithubTest.php
index cd62d4c8..57cd5f8f 100644
--- a/test/unit/UnityGithubTest.php
+++ b/test/unit/UnityGithubTest.php
@@ -17,7 +17,12 @@ public static function providerTestGetGithubKeys()
# user with no keys
["sheldor1510", []],
# user with 1 key
- ["simonLeary42", ["ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLeHpW10CCamJtXNXJui49WM07wRnQbQTbQ2MSvF4j8vBpBuAbjiEp14qERLDs3FoWdpbiUwL9mZq6PmUSxaTnk="]]
+ [
+ "simonLeary42",
+ [
+ "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLeHpW10CCamJtXNXJui49WM07wRnQbQTbQ2MSvF4j8vBpBuAbjiEp14qERLDs3FoWdpbiUwL9mZq6PmUSxaTnk=",
+ ],
+ ],
];
}
diff --git a/test/unit/UnitySSOTest.php b/test/unit/UnitySSOTest.php
index 12469626..bb4ae3aa 100644
--- a/test/unit/UnitySSOTest.php
+++ b/test/unit/UnitySSOTest.php
@@ -65,10 +65,9 @@ public function testFallbackAttribute()
$this->assertEquals("foobar@baz", $sso["mail"]);
}
- public static function validEppnProvider() {
- return [
- ["foo@bar.edu", "foo_bar_edu", "bar_edu"],
- ];
+ public static function validEppnProvider()
+ {
+ return [["foo@bar.edu", "foo_bar_edu", "bar_edu"]];
}
#[DataProvider("validEppnProvider")]
@@ -103,11 +102,12 @@ public function testEppnToOrg(string $eppn, string $_, string $expectedOrg)
}
}
- public static function invalidEppnProvider() {
+ public static function invalidEppnProvider()
+ {
return [
["foo"], // missing @
["foo@bar@baz"], // too many @
- [""]
+ [""],
];
}
diff --git a/test/unit/UtilsTest.php b/test/unit/UtilsTest.php
index 6f16a651..f024e0ef 100644
--- a/test/unit/UtilsTest.php
+++ b/test/unit/UtilsTest.php
@@ -11,9 +11,9 @@ public function testArrayGetReturnsValueWhenKeyExists()
$array = [
"a" => [
"b" => [
- "c" => 123
- ]
- ]
+ "c" => 123,
+ ],
+ ],
];
$result = \arrayGet($array, "a", "b", "c");
$this->assertSame(123, $result);
@@ -23,8 +23,8 @@ public function testArrayGetReturnsArrayWhenTraversingPartially()
{
$array = [
"foo" => [
- "bar" => "baz"
- ]
+ "bar" => "baz",
+ ],
];
$result = \arrayGet($array, "foo");
$this->assertSame(["bar" => "baz"], $result);
@@ -120,10 +120,14 @@ public static function SSHKeyProvider()
"gG7Fy2a+VWwcB6w0nzyxbqg16AP+luuqHxfVsvP6Uyde4C7LPeB3r3GhAfuU",
"Nxnpz/bXGxbJu3+aCnbtaZMzGJ6UFBeJp8MtlmVajDnjx3oEuOGGmobTlaop",
"HYVsQ3ySfQ==",
- ])
+ ]),
];
- $validKeysArgs = array_map(function($x){return [true, $x];}, $validKeys);
- $invalidKeysArgs = array_map(function($x){return [false, $x];}, $HTTP_HEADER_TEST_INPUTS);
+ $validKeysArgs = array_map(function ($x) {
+ return [true, $x];
+ }, $validKeys);
+ $invalidKeysArgs = array_map(function ($x) {
+ return [false, $x];
+ }, $HTTP_HEADER_TEST_INPUTS);
return $validKeysArgs + $invalidKeysArgs;
}
diff --git a/tools/docker-dev/docker-compose.yml b/tools/docker-dev/docker-compose.yml
index 7d0d426e..3a712dc6 100644
--- a/tools/docker-dev/docker-compose.yml
+++ b/tools/docker-dev/docker-compose.yml
@@ -9,7 +9,11 @@ services:
- "8010:80"
- "389:389"
healthcheck:
- test: ["CMD-SHELL", "if [ -f /tmp/up ]; then (nc -z localhost 389 && touch /tmp/up); else true; fi"]
+ test:
+ [
+ "CMD-SHELL",
+ "if [ -f /tmp/up ]; then (nc -z localhost 389 && touch /tmp/up); else true; fi",
+ ]
interval: 1s
sql:
hostname: sql
@@ -18,7 +22,11 @@ services:
- "8020:80"
- "3306:3306"
healthcheck:
- test: ["CMD-SHELL", "if [ -f /tmp/up ]; then (nc -z localhost 3306 && touch /tmp/up); else true; fi"]
+ test:
+ [
+ "CMD-SHELL",
+ "if [ -f /tmp/up ]; then (nc -z localhost 3306 && touch /tmp/up); else true; fi",
+ ]
interval: 1s
smtp:
hostname: smtp
@@ -31,7 +39,11 @@ services:
ports:
- "6379:6379"
healthcheck:
- test: ["CMD-SHELL", "if [ -f /tmp/up ]; then (nc -z localhost 6379 && touch /tmp/up); else true; fi"]
+ test:
+ [
+ "CMD-SHELL",
+ "if [ -f /tmp/up ]; then (nc -z localhost 6379 && touch /tmp/up); else true; fi",
+ ]
interval: 1s
web:
hostname: web
diff --git a/tools/docker-dev/identity/phpldapadmin-config.php b/tools/docker-dev/identity/phpldapadmin-config.php
index 3bd9ef93..b4253ae0 100644
--- a/tools/docker-dev/identity/phpldapadmin-config.php
+++ b/tools/docker-dev/identity/phpldapadmin-config.php
@@ -1,15 +1,18 @@
custom->appearance['timezone'] = 'America/New_York';
-$config->custom->appearance['hide_template_warning'] = true;
-$config->custom->appearance['friendly_attrs'] = array();
+$config->custom->appearance["timezone"] = "America/New_York";
+$config->custom->appearance["hide_template_warning"] = true;
+$config->custom->appearance["friendly_attrs"] = [];
$servers = new Datastore();
-$servers->newServer('ldap_pla');
-$servers->setValue('server', 'name', 'unity-web-portal-dev');
-$servers->setValue('server', 'host', 'identity');
-$servers->setValue('login', 'auth_type', 'config');
-$servers->setValue('login', 'bind_id', 'cn=admin,dc=unityhpc,dc=test');
-$servers->setValue('login', 'bind_pass', 'password');
-$servers->setValue('server', 'base', array('dc=unityhpc,dc=test'));
-$servers->setValue('auto_number', 'min', array('uidNumber' => 30000,'gidNumber' => 30000));
+$servers->newServer("ldap_pla");
+$servers->setValue("server", "name", "unity-web-portal-dev");
+$servers->setValue("server", "host", "identity");
+$servers->setValue("login", "auth_type", "config");
+$servers->setValue("login", "bind_id", "cn=admin,dc=unityhpc,dc=test");
+$servers->setValue("login", "bind_pass", "password");
+$servers->setValue("server", "base", ["dc=unityhpc,dc=test"]);
+$servers->setValue("auto_number", "min", [
+ "uidNumber" => 30000,
+ "gidNumber" => 30000,
+]);
diff --git a/tools/docker-dev/sql/phpmyadmin-config.php b/tools/docker-dev/sql/phpmyadmin-config.php
index 24716bf1..7814b5f8 100644
--- a/tools/docker-dev/sql/phpmyadmin-config.php
+++ b/tools/docker-dev/sql/phpmyadmin-config.php
@@ -1,15 +1,15 @@
* {
- display: block;
+form > * {
+ display: block;
}
-form>*:not(:first-child) {
- margin-top: 5px;
+form > *:not(:first-child) {
+ margin-top: 5px;
}
input:focus,
textarea:focus,
select:focus {
- outline: var(--accent) solid 2px;
+ outline: var(--accent) solid 2px;
}
button:focus,
-input[type=submit]:focus {
- outline: none;
+input[type="submit"]:focus {
+ outline: none;
}
-input[type=text],
-input[type=password],
-input[type=date] {
- margin: 10px 0 10px 0;
- border: 1px solid var(--light_borders);
- padding: 5px;
- width: calc(100% - 12px);
- /* Factors in extra border and padding */
- max-width: 300px;
- border-radius: 5px;
+input[type="text"],
+input[type="password"],
+input[type="date"] {
+ margin: 10px 0 10px 0;
+ border: 1px solid var(--light_borders);
+ padding: 5px;
+ width: calc(100% - 12px);
+ /* Factors in extra border and padding */
+ max-width: 300px;
+ border-radius: 5px;
}
-input[type=submit],
+input[type="submit"],
button {
- background: var(--accent);
- color: var(--accent_foreground);
- cursor: pointer;
- border: 0;
- padding: 8px 12px 8px 12px;
- border-radius: 5px;
- transition: background 0.1s;
- display: inline-block;
+ background: var(--accent);
+ color: var(--accent_foreground);
+ cursor: pointer;
+ border: 0;
+ padding: 8px 12px 8px 12px;
+ border-radius: 5px;
+ transition: background 0.1s;
+ display: inline-block;
}
-input[type=submit]:hover,
+input[type="submit"]:hover,
button:hover {
- background: var(--accent_2);
+ background: var(--accent_2);
}
-input[type=submit]:disabled,
+input[type="submit"]:disabled,
button:disabled {
- background: var(--accent_disabled);
- cursor: default;
+ background: var(--accent_disabled);
+ cursor: default;
}
-input[type=checkbox],
-input[type=radio] {
- display: inline-block;
+input[type="checkbox"],
+input[type="radio"] {
+ display: inline-block;
}
label {
- display: inline;
- user-select: none;
- font-size: 10pt;
- color: var(--color-background-text-inactive);
- overflow: hidden;
+ display: inline;
+ user-select: none;
+ font-size: 10pt;
+ color: var(--color-background-text-inactive);
+ overflow: hidden;
}
-input[type=radio] {
- margin-bottom: 0;
+input[type="radio"] {
+ margin-bottom: 0;
}
select {
- border: 1px solid var(--light_borders);
- background: white;
- padding: 5px 10px 5px 20px;
- max-width: 300px;
- border-radius: 5px;
+ border: 1px solid var(--light_borders);
+ background: white;
+ padding: 5px 10px 5px 20px;
+ max-width: 300px;
+ border-radius: 5px;
}
textarea {
- border: 1px solid var(--light_borders);
- width: calc(100% - 12px);
- min-height: 150px;
- display: block;
- margin: 10px 0 10px 0;
- resize: vertical;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 10pt;
- border-radius: 5px;
- padding: 5px;
+ border: 1px solid var(--light_borders);
+ width: calc(100% - 12px);
+ min-height: 150px;
+ display: block;
+ margin: 10px 0 10px 0;
+ resize: vertical;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 10pt;
+ border-radius: 5px;
+ padding: 5px;
}
div.inline * {
- display: inline;
- margin-right: 10px;
+ display: inline;
+ margin-right: 10px;
}
/*
@@ -224,122 +224,122 @@ div.inline * {
/* WRAPPERS */
main {
- flex: 1 0 auto;
- padding: 15px 20px 20px 20px;
- max-width: 1000px;
- line-height: 24px;
+ flex: 1 0 auto;
+ padding: 15px 20px 20px 20px;
+ max-width: 1000px;
+ line-height: 24px;
}
/* FOOTER */
footer {
- background: var(--light_footer_background);
- flex-shrink: 0;
- text-align: center;
- font-size: 8pt;
- color: var(--light_footer_foreground);
- padding-bottom: 10px;
+ background: var(--light_footer_background);
+ flex-shrink: 0;
+ text-align: center;
+ font-size: 8pt;
+ color: var(--light_footer_foreground);
+ padding-bottom: 10px;
}
-footer>* {
- display: table;
- margin: 10px auto 0 auto;
+footer > * {
+ display: table;
+ margin: 10px auto 0 auto;
}
footer #footerLogos img {
- padding: 0 10px 0 10px;
- max-width: 120px;
- max-height: 90px;
- margin-bottom: 10px;
- vertical-align: middle;
+ padding: 0 10px 0 10px;
+ max-width: 120px;
+ max-height: 90px;
+ margin-bottom: 10px;
+ vertical-align: middle;
}
@media only screen and (min-width: 501px) {
- footer #footerLogos>* {
- display: inline-block;
- }
+ footer #footerLogos > * {
+ display: inline-block;
+ }
}
@media only screen and (max-width: 500px) {
- footer #footerLogos>* {
- display: block;
- }
+ footer #footerLogos > * {
+ display: block;
+ }
}
/* notices */
div.notice {
- background: var(--light_panel_background);
- border-radius: 10px;
- margin: 20px 0 20px 0;
- padding-bottom: 5px;
+ background: var(--light_panel_background);
+ border-radius: 10px;
+ margin: 20px 0 20px 0;
+ padding-bottom: 5px;
}
-div.notice>span.noticeTitle {
- display: block;
- background: var(--accent);
- color: var(--accent_foreground);
- border-radius: 8px 8px 0 0;
- padding: 10px 10px 0 10px;
- font-size: 14pt;
- font-weight: bold;
+div.notice > span.noticeTitle {
+ display: block;
+ background: var(--accent);
+ color: var(--accent_foreground);
+ border-radius: 8px 8px 0 0;
+ padding: 10px 10px 0 10px;
+ font-size: 14pt;
+ font-weight: bold;
}
-div.notice>span.noticeDate {
- display: block;
- background: var(--accent);
- color: var(--accent_foreground);
- padding: 0 10px 10px 10px;
+div.notice > span.noticeDate {
+ display: block;
+ background: var(--accent);
+ color: var(--accent_foreground);
+ padding: 0 10px 10px 10px;
}
-div.notice>p {
- margin: 10px 15px 10px 15px;
- padding: 0;
+div.notice > p {
+ margin: 10px 15px 10px 15px;
+ padding: 0;
}
-div.notice>div.noticeText {
- padding: 0 10px 0 10px;
+div.notice > div.noticeText {
+ padding: 0 10px 0 10px;
}
-div.notice>button {
- margin: 0 0 5px 10px;
+div.notice > button {
+ margin: 0 0 5px 10px;
}
#viewAsBar {
- background: orange;
- padding: 10px;
- border-radius: 10px;
- margin-bottom: 20px;
+ background: orange;
+ padding: 10px;
+ border-radius: 10px;
+ margin-bottom: 20px;
}
-#viewAsBar>* {
- display: inline-block;
+#viewAsBar > * {
+ display: inline-block;
}
-#viewAsBar input[type=submit] {
- margin: 0 0 0 20px;
+#viewAsBar input[type="submit"] {
+ margin: 0 0 0 20px;
}
/* Search Box CSS */
div.searchWrapper {
- background: var(--light_background);
- position: absolute;
- top: 50px;
- z-index: 200;
- overflow: hidden;
- font-size: 11pt;
- user-select: none;
- width: 100%;
- margin-left: -2px;
- border: 1px solid var(--light_borders);
- border-radius: 5px;
-}
-
-div.searchWrapper>* {
- display: block;
- cursor: pointer;
- padding: 4px 10px 4px 10px;
-}
-
-div.searchWrapper>*:hover {
- background: var(--light_panel_background);
+ background: var(--light_background);
+ position: absolute;
+ top: 50px;
+ z-index: 200;
+ overflow: hidden;
+ font-size: 11pt;
+ user-select: none;
+ width: 100%;
+ margin-left: -2px;
+ border: 1px solid var(--light_borders);
+ border-radius: 5px;
+}
+
+div.searchWrapper > * {
+ display: block;
+ cursor: pointer;
+ padding: 4px 10px 4px 10px;
+}
+
+div.searchWrapper > *:hover {
+ background: var(--light_panel_background);
}
diff --git a/webroot/css/modal.css b/webroot/css/modal.css
index 7252e62b..af0aa313 100644
--- a/webroot/css/modal.css
+++ b/webroot/css/modal.css
@@ -1,67 +1,66 @@
div.modalWrapper {
- position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- background: rgba(0, 0, 0, 0.6);
- z-index: 100;
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: rgba(0, 0, 0, 0.6);
+ z-index: 100;
}
div.modalContent {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background: var(--light_background);
- padding: 15px;
- width: calc(100% - 30px);
- box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.4);
- border-radius: 5px;
- max-width: 600px;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ background: var(--light_background);
+ padding: 15px;
+ width: calc(100% - 30px);
+ box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.4);
+ border-radius: 5px;
+ max-width: 600px;
}
div.modalTitleWrapper {
- overflow: hidden;
- display: inline-block;
+ overflow: hidden;
+ display: inline-block;
}
span.modalTitle {
- font-size: 13pt;
+ font-size: 13pt;
}
div.modalMessages {
- color: var(--color-text-failure);
- font-size: 11pt;
+ color: var(--color-text-failure);
+ font-size: 11pt;
}
-div.modalMessages>* {
- margin-top: 7px;
- display: block;
+div.modalMessages > * {
+ margin-top: 7px;
+ display: block;
}
-div.modalBody>* {
- margin: 0;
+div.modalBody > * {
+ margin: 0;
}
.btnClose {
- width: 30px;
- height: 30px;
- padding: 0;
- text-align: center;
- font-size: 20pt;
+ width: 30px;
+ height: 30px;
+ padding: 0;
+ text-align: center;
+ font-size: 20pt;
}
-
.btnClose::before {
- content: "\00d7";
+ content: "\00d7";
}
.buttonList {
- margin-top: 10px;
+ margin-top: 10px;
}
-.buttonList>* {
- display: inline-block;
- margin-right: 10px;
+.buttonList > * {
+ display: inline-block;
+ margin-right: 10px;
}
diff --git a/webroot/css/navbar.css b/webroot/css/navbar.css
index 5f3e919a..42b73456 100644
--- a/webroot/css/navbar.css
+++ b/webroot/css/navbar.css
@@ -1,120 +1,120 @@
/* Navbar */
hr.navHR {
- margin-left: 10px;
- margin-right: 10px;
+ margin-left: 10px;
+ margin-right: 10px;
}
nav.mainNav {
- background: var(--accent);
- position: fixed;
- left: 0;
- top: 45px;
- font-size: 11pt;
- overflow: hidden;
- white-space: nowrap;
- z-index: 100;
+ background: var(--accent);
+ position: fixed;
+ left: 0;
+ top: 45px;
+ font-size: 11pt;
+ overflow: hidden;
+ white-space: nowrap;
+ z-index: 100;
}
nav.mainNav a {
- color: var(--accent_foreground);
- background: var(--accent_1);
- border-radius: 10px;
- display: block;
- margin: 10px 8px 10px 8px;
- padding: 8px;
- text-decoration: none;
- cursor: pointer;
- transition: background 0.1s;
+ color: var(--accent_foreground);
+ background: var(--accent_1);
+ border-radius: 10px;
+ display: block;
+ margin: 10px 8px 10px 8px;
+ padding: 8px;
+ text-decoration: none;
+ cursor: pointer;
+ transition: background 0.1s;
}
nav.mainNav a:hover {
- text-decoration: none;
- background: var(--accent_2);
+ text-decoration: none;
+ background: var(--accent_2);
}
nav.mainNav a.active {
- background: var(--accent_2);
+ background: var(--accent_2);
}
header {
- background: var(--accent);
- height: 50px;
- width: 250px;
- position: fixed;
- top: 0;
- left: 0;
+ background: var(--accent);
+ height: 50px;
+ width: 250px;
+ position: fixed;
+ top: 0;
+ left: 0;
}
-header>#imgLogo {
- height: 65%;
- margin-left: 10px;
- margin-top: 8px;
+header > #imgLogo {
+ height: 65%;
+ margin-left: 10px;
+ margin-top: 8px;
}
-header>a.unity-state {
- background: var(--accent_foreground);
- color: var(--accent);
- display: block;
- position: absolute;
- top: 8px;
- left: 140px;
- padding: 1px 5px 1px 5px;
- font-weight: bold;
- font-size: 10pt;
- border-radius: 5px;
+header > a.unity-state {
+ background: var(--accent_foreground);
+ color: var(--accent);
+ display: block;
+ position: absolute;
+ top: 8px;
+ left: 140px;
+ padding: 1px 5px 1px 5px;
+ font-weight: bold;
+ font-size: 10pt;
+ border-radius: 5px;
}
-header>a.unity-state:hover {
- text-decoration: none;
+header > a.unity-state:hover {
+ text-decoration: none;
}
-header>button.hamburger {
- background: var(--accent);
- padding: 0;
- right: 23px;
- height: 60%;
+header > button.hamburger {
+ background: var(--accent);
+ padding: 0;
+ right: 23px;
+ height: 60%;
}
-header>button.hamburger>img {
- position: relative;
- height: 100%;
+header > button.hamburger > img {
+ position: relative;
+ height: 100%;
}
/* MOBILE VIEW */
@media only screen and (max-width: 1000px) {
- nav.mainNav {
- right: 0;
- }
-
- header {
- width: 100%;
- }
-
- main {
- /* Header element height + 2*element padding */
- margin-top: 45px;
- }
+ nav.mainNav {
+ right: 0;
+ }
+
+ header {
+ width: 100%;
+ }
+
+ main {
+ /* Header element height + 2*element padding */
+ margin-top: 45px;
+ }
}
/* DESKTOP VIEW */
@media only screen and (min-width: 1001px) {
- nav.mainNav {
- bottom: 0;
- width: 250px;
- }
-
- header>button.hamburger {
- display: none;
- }
-
- main {
- margin-left: 250px;
- }
-
- footer {
- margin-left: 250px;
- }
+ nav.mainNav {
+ bottom: 0;
+ width: 250px;
+ }
+
+ header > button.hamburger {
+ display: none;
+ }
+
+ main {
+ margin-left: 250px;
+ }
+
+ footer {
+ margin-left: 250px;
+ }
}
diff --git a/webroot/css/tables.css b/webroot/css/tables.css
index 132c1f5e..d867ae48 100644
--- a/webroot/css/tables.css
+++ b/webroot/css/tables.css
@@ -1,142 +1,142 @@
table {
- border-collapse: collapse;
- margin-bottom: 10px;
- table-layout: fixed;
- word-wrap: break-word;
- max-width: 100%;
+ border-collapse: collapse;
+ margin-bottom: 10px;
+ table-layout: fixed;
+ word-wrap: break-word;
+ max-width: 100%;
}
table.longTable {
- width: 100%;
+ width: 100%;
}
table.longTable tr:not(:last-child) {
- border-bottom: 1px solid var(--light_borders);
+ border-bottom: 1px solid var(--light_borders);
}
table tr,
table td {
- padding: 0 20px 0 4px;
- overflow: hidden;
- white-space: nowrap;
+ padding: 0 20px 0 4px;
+ overflow: hidden;
+ white-space: nowrap;
}
table button,
-table input[type=submit] {
- padding: 5px 10px 5px 10px;
+table input[type="submit"] {
+ padding: 5px 10px 5px 10px;
}
table form {
- display: inline-block;
+ display: inline-block;
}
table form:not(:first-child) {
- margin-left: 10px;
+ margin-left: 10px;
}
-table form>* {
- margin: 0;
+table form > * {
+ margin: 0;
}
tr.expanded {
- border: 0;
+ border: 0;
}
-tr.expanded>td {
- background: var(--light_panel_background);
+tr.expanded > td {
+ background: var(--light_panel_background);
}
tr.expandable {
- cursor: pointer;
+ cursor: pointer;
}
tr.expandable:hover {
- background: var(--light_footer_background);
+ background: var(--light_footer_background);
}
-tr.expandable:hover>td:first-child {
- border-top-left-radius: 10px;
- border-bottom-left-radius: 10px;
+tr.expandable:hover > td:first-child {
+ border-top-left-radius: 10px;
+ border-bottom-left-radius: 10px;
}
-tr.expandable:hover>td:last-child {
- border-top-right-radius: 10px;
- border-bottom-right-radius: 10px;
+tr.expandable:hover > td:last-child {
+ border-top-right-radius: 10px;
+ border-bottom-right-radius: 10px;
}
-tr.expandable.first>td:first-child {
- border-bottom-left-radius: 0;
+tr.expandable.first > td:first-child {
+ border-bottom-left-radius: 0;
}
-tr.expandable.first>td:last-child {
- border-bottom-right-radius: 0;
+tr.expandable.first > td:last-child {
+ border-bottom-right-radius: 0;
}
tr.expanded.first {
- border-bottom: 2px solid var(--light_borders);
+ border-bottom: 2px solid var(--light_borders);
}
-tr.expanded.first>td:first-child {
- border-top-left-radius: 10px;
+tr.expanded.first > td:first-child {
+ border-top-left-radius: 10px;
}
-tr.expanded.first>td:last-child {
- border-top-right-radius: 10px;
+tr.expanded.first > td:last-child {
+ border-top-right-radius: 10px;
}
-tr.expanded.last>td:first-child {
- border-bottom-left-radius: 10px;
+tr.expanded.last > td:first-child {
+ border-bottom-left-radius: 10px;
}
-tr.expanded.last>td:last-child {
- border-bottom-right-radius: 10px;
+tr.expanded.last > td:last-child {
+ border-bottom-right-radius: 10px;
}
tr.expanded:not(.expandable) {
- padding-top: 0;
- padding-bottom: 0;
+ padding-top: 0;
+ padding-bottom: 0;
}
-tr.expanded:not(.expandable)>td:first-child {
- padding-left: 30px;
+tr.expanded:not(.expandable) > td:first-child {
+ padding-left: 30px;
}
button.btnExpanded {
- transform: rotate(90deg);
+ transform: rotate(90deg);
}
/* Buttons */
button.btnExpand {
- margin: 0 10px 0 0;
- padding: 0;
- background: transparent;
- color: var(--accent);
+ margin: 0 10px 0 0;
+ padding: 0;
+ background: transparent;
+ color: var(--accent);
}
button.btnExpand:hover {
- background: transparent;
+ background: transparent;
}
button.btnExpanded {
- transform: rotate(90deg);
+ transform: rotate(90deg);
}
-td:last-child>button {
- float: right;
+td:last-child > button {
+ float: right;
}
tr.key {
- background: var(--light_panel_background);
- text-align: center;
- font-weight: bold;
+ background: var(--light_panel_background);
+ text-align: center;
+ font-weight: bold;
}
-tr.key>td:first-child {
- border-top-left-radius: 10px;
- border-bottom-left-radius: 10px;
+tr.key > td:first-child {
+ border-top-left-radius: 10px;
+ border-bottom-left-radius: 10px;
}
-tr.key>td:last-child {
- border-top-right-radius: 10px;
- border-bottom-right-radius: 10px;
+tr.key > td:last-child {
+ border-top-right-radius: 10px;
+ border-bottom-right-radius: 10px;
}
diff --git a/webroot/js/filter.js b/webroot/js/filter.js
index af8d85a7..7e2bfa14 100644
--- a/webroot/js/filter.js
+++ b/webroot/js/filter.js
@@ -1,90 +1,102 @@
function getQueryVariable(variable) {
- var query = window.location.search.substring(1);
- var vars = query.split("&");
- for (var i = 0; i < vars.length; i++) {
- var pair = vars[i].split("=");
+ var query = window.location.search.substring(1);
+ var vars = query.split("&");
+ for (var i = 0; i < vars.length; i++) {
+ var pair = vars[i].split("=");
- if (pair[0] == variable) {
- return pair[1];
- }
+ if (pair[0] == variable) {
+ return pair[1];
}
- return false;
+ }
+ return false;
}
function updateQueryStringParameter(uri, key, value) {
- let currentURL = new URL(window.location.href);
- let params = currentURL.searchParams;
- if (params.has(key)) {
- params.delete(key);
- }
- params.append(key, value);
- window.history.pushState("object or string", "Title", currentURL.href);
+ let currentURL = new URL(window.location.href);
+ let params = currentURL.searchParams;
+ if (params.has(key)) {
+ params.delete(key);
+ }
+ params.append(key, value);
+ window.history.pushState("object or string", "Title", currentURL.href);
}
function updateFilterInput() {
- const commonFilterInputBox = document.querySelector(".filterSearch");
- commonFilterInputBox.style.display = "none";
- commonFilterInputBox.style.visibility = "hidden";
- commonFilterInputBox.value = "";
-
- var filter = getQueryVariable("filter");
- if (filter) {
- commonFilterInputBox.style.display = "inline-block";
- commonFilterInputBox.style.visibility = "visible";
+ const commonFilterInputBox = document.querySelector(".filterSearch");
+ commonFilterInputBox.style.display = "none";
+ commonFilterInputBox.style.visibility = "hidden";
+ commonFilterInputBox.value = "";
- if (filter == "uid") {
- commonFilterInputBox.placeholder = "Filter by " + filter.toUpperCase() + '...';
- } else {
- commonFilterInputBox.placeholder = "Filter by " + filter.charAt(0).toUpperCase() + filter.slice(1) + '...';
- }
+ var filter = getQueryVariable("filter");
+ if (filter) {
+ commonFilterInputBox.style.display = "inline-block";
+ commonFilterInputBox.style.visibility = "visible";
- if (getQueryVariable("value") != false) {
- commonFilterInputBox.value = getQueryVariable("value");
- filterRows();
- }
+ if (filter == "uid") {
+ commonFilterInputBox.placeholder =
+ "Filter by " + filter.toUpperCase() + "...";
+ } else {
+ commonFilterInputBox.placeholder =
+ "Filter by " + filter.charAt(0).toUpperCase() + filter.slice(1) + "...";
+ }
- commonFilterInputBox.addEventListener("keyup", function(e) {
- updateQueryStringParameter(window.location.href, "value", e.target.value);
- filterRows();
- });
+ if (getQueryVariable("value") != false) {
+ commonFilterInputBox.value = getQueryVariable("value");
+ filterRows();
}
+
+ commonFilterInputBox.addEventListener("keyup", function (e) {
+ updateQueryStringParameter(window.location.href, "value", e.target.value);
+ filterRows();
+ });
+ }
}
updateFilterInput();
var filters = document.querySelectorAll("span.filter");
-filters.forEach(function(filter) {
- filter.addEventListener("click", function(e) {
- e.preventDefault();
- e.stopPropagation();
- if (e.target.parentElement.id != getQueryVariable("filter")) {
- updateQueryStringParameter(window.location.href, "filter", e.target.parentElement.id);
- updateQueryStringParameter(window.location.href, "value", "");
- filterRows();
- } else {
- updateQueryStringParameter(window.location.href, "filter", "");
- updateQueryStringParameter(window.location.href, "value", "");
- filterRows();
- }
- updateFilterInput();
- });
+filters.forEach(function (filter) {
+ filter.addEventListener("click", function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ if (e.target.parentElement.id != getQueryVariable("filter")) {
+ updateQueryStringParameter(
+ window.location.href,
+ "filter",
+ e.target.parentElement.id,
+ );
+ updateQueryStringParameter(window.location.href, "value", "");
+ filterRows();
+ } else {
+ updateQueryStringParameter(window.location.href, "filter", "");
+ updateQueryStringParameter(window.location.href, "value", "");
+ filterRows();
+ }
+ updateFilterInput();
+ });
});
function filterRows() {
- var filter = getQueryVariable("filter");
- var filterValue = getQueryVariable("value");
+ var filter = getQueryVariable("filter");
+ var filterValue = getQueryVariable("value");
- if (filter) {
- var table = document.querySelector("table.filterable");
- var rows = Array.from(table.querySelectorAll("tr:nth-child(n+2)"));
- var column = table.querySelector("tr.key").querySelector("td#" + filter).cellIndex;
- rows.forEach(function(row) {
- if (row.cells[column].textContent.trim().toLowerCase().indexOf(filterValue.toLowerCase()) == -1) {
- row.style.display = "none";
- } else {
- row.style.display = "";
- }
- }
- );
- }
+ if (filter) {
+ var table = document.querySelector("table.filterable");
+ var rows = Array.from(table.querySelectorAll("tr:nth-child(n+2)"));
+ var column = table
+ .querySelector("tr.key")
+ .querySelector("td#" + filter).cellIndex;
+ rows.forEach(function (row) {
+ if (
+ row.cells[column].textContent
+ .trim()
+ .toLowerCase()
+ .indexOf(filterValue.toLowerCase()) == -1
+ ) {
+ row.style.display = "none";
+ } else {
+ row.style.display = "";
+ }
+ });
+ }
}
diff --git a/webroot/js/global.js b/webroot/js/global.js
index cfaade95..933bd194 100644
--- a/webroot/js/global.js
+++ b/webroot/js/global.js
@@ -3,9 +3,9 @@ $(window).resize(setNav);
function setNav() {
if ($("button.hamburger").is(":visible")) {
- $("nav.mainNav").hide(); // Mobile View
+ $("nav.mainNav").hide(); // Mobile View
} else {
- $("nav.mainNav").show(); // Desktop View
+ $("nav.mainNav").show(); // Desktop View
}
}
@@ -19,36 +19,39 @@ $("button.hamburger").on("click", function () {
});
$(window).click(function (e) {
- if (!$(e.target).parent().hasClass("hamburger") && $("button.hamburger").is(":visible")) {
+ if (
+ !$(e.target).parent().hasClass("hamburger") &&
+ $("button.hamburger").is(":visible")
+ ) {
$("nav.mainNav").fadeOut(100);
}
});
// Functions to set nav links as active. Sub links can activate parents by naming files with same prefix, for example: documentation.php and documentation_view.php activate the same link
var url = location.pathname;
-if (url.lastIndexOf('.') >= 0) {
- url = url.substring(0, url.lastIndexOf('.'));
+if (url.lastIndexOf(".") >= 0) {
+ url = url.substring(0, url.lastIndexOf("."));
}
-if (url.lastIndexOf('/') >= 0) {
- url = url.substring(url.lastIndexOf('/') + 1);
+if (url.lastIndexOf("/") >= 0) {
+ url = url.substring(url.lastIndexOf("/") + 1);
}
-$('nav.mainNav a').each(function () {
+$("nav.mainNav a").each(function () {
var href = $(this).attr("href");
- if (href.lastIndexOf('.') >= 0) {
- href = href.substring(0, href.lastIndexOf('.'));
+ if (href.lastIndexOf(".") >= 0) {
+ href = href.substring(0, href.lastIndexOf("."));
}
- if (href.lastIndexOf('/') >= 0) {
- href = href.substring(href.lastIndexOf('/') + 1);
+ if (href.lastIndexOf("/") >= 0) {
+ href = href.substring(href.lastIndexOf("/") + 1);
}
if (url.indexOf(href) == 0) {
$(this).addClass("active");
}
-})
+});
/**
* btnDropdown Click Events
@@ -64,9 +67,12 @@ $(window).click(function (e) {
});
function downloadFile(text, filename) {
- var element = document.createElement('a');
- element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
- element.setAttribute('download', filename);
+ var element = document.createElement("a");
+ element.setAttribute(
+ "href",
+ "data:text/plain;charset=utf-8," + encodeURIComponent(text),
+ );
+ element.setAttribute("download", filename);
element.style.display = "none";
$("body").append(element);
diff --git a/webroot/js/modal.js b/webroot/js/modal.js
index 8cd681ff..d7c28b3d 100644
--- a/webroot/js/modal.js
+++ b/webroot/js/modal.js
@@ -1,17 +1,18 @@
function openModal(title, link, message = "") {
- $("span.modalTitle").html(title);
- $("div.modalMessages").html(message);
- $.ajax({
- url: link, success: function (result) {
- $("div.modalBody").html(result);
- }
- });
+ $("span.modalTitle").html(title);
+ $("div.modalMessages").html(message);
+ $.ajax({
+ url: link,
+ success: function (result) {
+ $("div.modalBody").html(result);
+ },
+ });
- $("div.modalWrapper").fadeIn(100); // With Animation
- //$("div.modalWrapper").show();
+ $("div.modalWrapper").fadeIn(100); // With Animation
+ //$("div.modalWrapper").show();
}
$("button.btnClose").click(function () {
- //$("div.modalWrapper").fadeOut(50); // With Animation
- $("div.modalWrapper").hide();
+ //$("div.modalWrapper").fadeOut(50); // With Animation
+ $("div.modalWrapper").hide();
});
diff --git a/webroot/js/sort.js b/webroot/js/sort.js
index 3ab04f28..5f8b7e1e 100644
--- a/webroot/js/sort.js
+++ b/webroot/js/sort.js
@@ -1,73 +1,89 @@
var table = document.querySelector("table.sortable");
-table.querySelectorAll("td").forEach(function(td) {
- td.addEventListener("click", function(e) {
- if (td.parentElement.classList.contains("key") && td.innerHTML != "Actions") {
- if (e.target.classList.contains("filter")) {
- updateQueryStringParameter(window.location.href, "filter", e.target.parentElement.id);
- updateFilterInput();
- } else {
- var column = td.cellIndex;
- var rows = Array.from(table.querySelectorAll("tr:nth-child(n+2)"));
- var order = td.classList.toggle("asc") ? 1 : -1;
- rows.sort(function(a, b) {
- return order * (a.cells[column].textContent.trim().localeCompare(b.cells[column].textContent.trim(), undefined, {
- numeric: true
- }));
- });
- rows.forEach(function(row) {
- table.appendChild(row);
- });
- var keys = document.querySelectorAll("tr.key");
- keys.forEach(function(key) {
- key.querySelectorAll("td").forEach(function(td) {
- td.innerHTML = td.innerHTML.replace(/ ▲| ▼/, "");
- });
- });
- var orderSymbol = order == 1 ? "▲" : "▼";
- td.innerHTML = td.innerHTML + " " + orderSymbol;
- updateQueryStringParameter(window.location.href, "sort", td.id);
- updateQueryStringParameter(window.location.href, "order", order == 1 ? "asc" : "desc");
- }
- }
- });
+table.querySelectorAll("td").forEach(function (td) {
+ td.addEventListener("click", function (e) {
+ if (
+ td.parentElement.classList.contains("key") &&
+ td.innerHTML != "Actions"
+ ) {
+ if (e.target.classList.contains("filter")) {
+ updateQueryStringParameter(
+ window.location.href,
+ "filter",
+ e.target.parentElement.id,
+ );
+ updateFilterInput();
+ } else {
+ var column = td.cellIndex;
+ var rows = Array.from(table.querySelectorAll("tr:nth-child(n+2)"));
+ var order = td.classList.toggle("asc") ? 1 : -1;
+ rows.sort(function (a, b) {
+ return (
+ order *
+ a.cells[column].textContent
+ .trim()
+ .localeCompare(b.cells[column].textContent.trim(), undefined, {
+ numeric: true,
+ })
+ );
+ });
+ rows.forEach(function (row) {
+ table.appendChild(row);
+ });
+ var keys = document.querySelectorAll("tr.key");
+ keys.forEach(function (key) {
+ key.querySelectorAll("td").forEach(function (td) {
+ td.innerHTML = td.innerHTML.replace(/ ▲| ▼/, "");
+ });
+ });
+ var orderSymbol = order == 1 ? "▲" : "▼";
+ td.innerHTML = td.innerHTML + " " + orderSymbol;
+ updateQueryStringParameter(window.location.href, "sort", td.id);
+ updateQueryStringParameter(
+ window.location.href,
+ "order",
+ order == 1 ? "asc" : "desc",
+ );
+ }
+ }
+ });
});
function getQueryVariable(variable) {
- var query = window.location.search.substring(1);
- var vars = query.split("&");
- for (var i = 0; i < vars.length; i++) {
- var pair = vars[i].split("=");
+ var query = window.location.search.substring(1);
+ var vars = query.split("&");
+ for (var i = 0; i < vars.length; i++) {
+ var pair = vars[i].split("=");
- if (pair[0] == variable) {
- return pair[1];
- }
+ if (pair[0] == variable) {
+ return pair[1];
}
- return false;
+ }
+ return false;
}
function updateQueryStringParameter(uri, key, value) {
- let currentURL = new URL(window.location.href);
- let params = currentURL.searchParams;
- if (params.has(key)) {
- params.delete(key);
- }
- params.append(key, value);
- window.history.pushState("object or string", "Title", currentURL.href);
+ let currentURL = new URL(window.location.href);
+ let params = currentURL.searchParams;
+ if (params.has(key)) {
+ params.delete(key);
+ }
+ params.append(key, value);
+ window.history.pushState("object or string", "Title", currentURL.href);
}
-window.onload = function() {
- var sort = getQueryVariable("sort");
- var order = getQueryVariable("order");
- if (sort) {
- var sortElement = document.getElementById(sort);
- if (sortElement) {
- if (order == "asc") {
- sortElement.click();
- } else if (order == "desc") {
- sortElement.click();
- sortElement.click();
- }
- }
+window.onload = function () {
+ var sort = getQueryVariable("sort");
+ var order = getQueryVariable("order");
+ if (sort) {
+ var sortElement = document.getElementById(sort);
+ if (sortElement) {
+ if (order == "asc") {
+ sortElement.click();
+ } else if (order == "desc") {
+ sortElement.click();
+ sortElement.click();
+ }
}
- filterRows();
-}
+ }
+ filterRows();
+};
diff --git a/webroot/js/tables.js b/webroot/js/tables.js
index a749b43e..aea1739e 100644
--- a/webroot/js/tables.js
+++ b/webroot/js/tables.js
@@ -1,54 +1,53 @@
+$("tr.expandable").on("click", function (e) {
+ var target = $(e.target);
+ if (target.is("button") || target.is("a") || target.is("input")) {
+ return;
+ }
+
+ var button = $(this).find("button.btnExpand");
+ button.trigger("click");
+});
-$("tr.expandable").on('click', function(e) {
- var target = $(e.target);
- if (target.is("button") || target.is("a") || target.is("input")) {
- return;
- }
+$("button.btnExpand").click(function () {
+ var pi_wrapper = $(this).parent(); // parent column (td)
+ var piRow = pi_wrapper.parent(); // parent row (tr)
+ var piTree = piRow.parent(); // parent table (table)
+ var gid = pi_wrapper.next().html();
- var button = $(this).find("button.btnExpand");
- button.trigger("click");
-});
+ if ($(this).hasClass("btnExpanded")) {
+ // already expanded
+ var currentNode = piRow.nextAll().first();
-$("button.btnExpand").click(function() {
- var pi_wrapper = $(this).parent(); // parent column (td)
- var piRow = pi_wrapper.parent(); // parent row (tr)
- var piTree = piRow.parent(); // parent table (table)
- var gid = pi_wrapper.next().html();
-
- if ($(this).hasClass("btnExpanded")) {
- // already expanded
- var currentNode = piRow.nextAll().first();
-
- while (!currentNode.hasClass("expandable") && currentNode.length != 0) {
- var nextNode = currentNode.nextAll().first();
- currentNode.remove();
- currentNode = nextNode;
- }
-
- $(this).removeClass("btnExpanded");
- piRow.removeClass("expanded");
- piRow.removeClass("first");
- } else {
- $("button.btnExpanded").trigger("click");
- // not expanded
- $.ajax({
- url: ajax_url + gid,
- success: function(result) {
- console.log(result);
- piRow.after(result);
- }
- });
-
- $(this).addClass("btnExpanded");
- piRow.addClass("expanded");
- piRow.addClass("first");
+ while (!currentNode.hasClass("expandable") && currentNode.length != 0) {
+ var nextNode = currentNode.nextAll().first();
+ currentNode.remove();
+ currentNode = nextNode;
}
+
+ $(this).removeClass("btnExpanded");
+ piRow.removeClass("expanded");
+ piRow.removeClass("first");
+ } else {
+ $("button.btnExpanded").trigger("click");
+ // not expanded
+ $.ajax({
+ url: ajax_url + gid,
+ success: function (result) {
+ console.log(result);
+ piRow.after(result);
+ },
+ });
+
+ $(this).addClass("btnExpanded");
+ piRow.addClass("expanded");
+ piRow.addClass("first");
+ }
});
-$('#tableSearch').keyup(function() {
- var value = $(this).val().toLowerCase();
+$("#tableSearch").keyup(function () {
+ var value = $(this).val().toLowerCase();
- $("table.searchable tr:not(:first-child)").filter(function() {
- $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
- });
+ $("table.searchable tr:not(:first-child)").filter(function () {
+ $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
+ });
});
diff --git a/workers/clear-audit-log.php b/workers/clear-audit-log.php
index 6a28dcd4..63cfee69 100755
--- a/workers/clear-audit-log.php
+++ b/workers/clear-audit-log.php
@@ -1,6 +1,5 @@
#!/usr/bin/env php
getConn()
+ ->prepare("DELETE FROM audit_log WHERE timestamp < :daysAgo")
+ ->execute(["daysAgo" => $daysAgo]);
-$SQL->getConn()->prepare(
- "DELETE FROM audit_log WHERE timestamp < :daysAgo"
-)->execute(['daysAgo' => $daysAgo]);
diff --git a/workers/group_user_request_owner_reminder.php b/workers/group_user_request_owner_reminder.php
index 4f463262..9464712c 100755
--- a/workers/group_user_request_owner_reminder.php
+++ b/workers/group_user_request_owner_reminder.php
@@ -1,6 +1,5 @@
#!/usr/bin/env php
1 && $daysDifference % 7 == 0) {
$new_user = $request[0];
// send email to PI
- $MAILER->sendMail(
- $pi_user->getMail(),
- "group_user_request_owner",
- array(
- "group" => $pi_group->gid,
- "user" => $new_user->uid,
- "name" => $new_user->getFullName(),
- "email" => $new_user->getMail(),
- "org" => $new_user->getOrg()
- )
- );
+ $MAILER->sendMail($pi_user->getMail(), "group_user_request_owner", [
+ "group" => $pi_group->gid,
+ "user" => $new_user->uid,
+ "name" => $new_user->getFullName(),
+ "email" => $new_user->getMail(),
+ "org" => $new_user->getOrg(),
+ ]);
}
}
}
+
diff --git a/workers/remove-users-from-group.php b/workers/remove-users-from-group.php
index b293b841..01fe8c99 100755
--- a/workers/remove-users-from-group.php
+++ b/workers/remove-users-from-group.php
@@ -1,6 +1,5 @@
#!/usr/bin/env php
exists()) {
_die("No such group '$gid'\n");
}
-$handle = fopen($filename, "r") or _die("Can't open '$filename'\n");
+($handle = fopen($filename, "r")) or _die("Can't open '$filename'\n");
while (($line = fgets($handle)) !== false) {
$uid = trim($line);
$user = new UnityUser($uid, $LDAP, $SQL, $MAILER, $REDIS, $WEBHOOK);
if (!$group->memberExists($user)) {
- print("Skipping '$uid' who doesn't appear to be in '$gid'\n");
+ print "Skipping '$uid' who doesn't appear to be in '$gid'\n";
continue;
}
$group->removeUser($user);
}
fclose($handle);
+
diff --git a/workers/update-ldap-cache.php b/workers/update-ldap-cache.php
index 96bd02f0..0afc0153 100755
--- a/workers/update-ldap-cache.php
+++ b/workers/update-ldap-cache.php
@@ -1,6 +1,5 @@
#!/usr/bin/env php
flushAll();
}
-if ((!is_null($REDIS->getCache("initialized", "")) and (!array_key_exists("u", $options)))) {
+if (
+ !is_null($REDIS->getCache("initialized", "")) and
+ !array_key_exists("u", $options)
+) {
echo "cache is already initialized, nothing doing.";
echo " use -f argument to flush cache, or -u argument to update without flush.\n";
} else {
@@ -37,7 +39,11 @@
// search entire tree, some users created for admin purposes might not be in the normal OU
echo "waiting for LDAP search (users)...\n";
- $users = $LDAP->search("objectClass=posixAccount", CONFIG["ldap"]["basedn"], []);
+ $users = $LDAP->search(
+ "objectClass=posixAccount",
+ CONFIG["ldap"]["basedn"],
+ [],
+ );
echo "response received.\n";
$user_CNs = $LDAP->getUserGroup()->getAttribute("memberuid");
sort($user_CNs);
@@ -47,35 +53,57 @@
if (!in_array($uid, $user_CNs)) {
continue;
}
- $REDIS->setCache($uid, "firstname", $user->getAttribute("givenname")[0]);
+ $REDIS->setCache(
+ $uid,
+ "firstname",
+ $user->getAttribute("givenname")[0],
+ );
$REDIS->setCache($uid, "lastname", $user->getAttribute("sn")[0]);
$REDIS->setCache($uid, "org", $user->getAttribute("o")[0]);
$REDIS->setCache($uid, "mail", $user->getAttribute("mail")[0]);
$REDIS->setCache($uid, "sshkeys", $user->getAttribute("sshpublickey"));
- $REDIS->setCache($uid, "loginshell", $user->getAttribute("loginshell")[0]);
- $REDIS->setCache($uid, "homedir", $user->getAttribute("homedirectory")[0]);
+ $REDIS->setCache(
+ $uid,
+ "loginshell",
+ $user->getAttribute("loginshell")[0],
+ );
+ $REDIS->setCache(
+ $uid,
+ "homedir",
+ $user->getAttribute("homedirectory")[0],
+ );
}
- $org_group_ou = new LDAPEntry($LDAP->getConn(), CONFIG["ldap"]["orggroup_ou"]);
+ $org_group_ou = new LDAPEntry(
+ $LDAP->getConn(),
+ CONFIG["ldap"]["orggroup_ou"],
+ );
echo "waiting for LDAP search (org groups)...\n";
$org_groups = $org_group_ou->getChildrenArray(["cn", "memberuid"], true);
echo "response received.\n";
// phpcs:disable
- $org_group_CNs = array_map(function($x){return $x["cn"][0];}, $org_groups);
+ $org_group_CNs = array_map(function ($x) {
+ return $x["cn"][0];
+ }, $org_groups);
// phpcs:enable
sort($org_group_CNs);
$REDIS->setCache("sorted_orgs", "", $org_group_CNs);
foreach ($org_groups as $org_group) {
$gid = $org_group["cn"][0];
- $REDIS->setCache($gid, "members", ($org_group["memberuid"] ?? []));
+ $REDIS->setCache($gid, "members", $org_group["memberuid"] ?? []);
}
- $pi_group_ou = new LDAPEntry($LDAP->getConn(), CONFIG["ldap"]["pigroup_ou"]);
+ $pi_group_ou = new LDAPEntry(
+ $LDAP->getConn(),
+ CONFIG["ldap"]["pigroup_ou"],
+ );
echo "waiting for LDAP search (pi groups)...\n";
$pi_groups = $pi_group_ou->getChildrenArray(["cn", "memberuid"], true);
echo "response received.\n";
// phpcs:disable
- $pi_group_CNs = array_map(function($x){return $x["cn"][0];}, $pi_groups);
+ $pi_group_CNs = array_map(function ($x) {
+ return $x["cn"][0];
+ }, $pi_groups);
// phpcs:enable
sort($pi_group_CNs);
// FIXME should be sorted_pi_groups
@@ -87,7 +115,7 @@
}
foreach ($pi_groups as $pi_group) {
$gid = $pi_group["cn"][0];
- $members = ($pi_group["memberuid"] ?? []);
+ $members = $pi_group["memberuid"] ?? [];
foreach ($members as $uid) {
if (in_array($uid, $user_CNs)) {
array_push($user_pi_group_member_of[$uid], $gid);
@@ -95,7 +123,7 @@
echo "warning: group '$gid' has member '$uid' who is not in the users group!\n";
}
}
- $REDIS->setCache($gid, "members", ($pi_group["memberuid"] ?? []));
+ $REDIS->setCache($gid, "members", $pi_group["memberuid"] ?? []);
}
foreach ($user_pi_group_member_of as $uid => $pi_groups) {
// FIXME should be pi_groups
@@ -105,3 +133,4 @@
$REDIS->setCache("initialized", "", true);
echo "done!\n";
}
+
From 0bef3de9f90f9dc52d0839a26e97286890441443 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 12:30:06 -0500
Subject: [PATCH 04/13] fix php version
---
CONTRIBUTING.md | 1 +
composer.json | 5 +++++
composer.lock | 33 ++++++++++++++++++++-------------
3 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index eb6f717e..4d04e91c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -29,6 +29,7 @@ This repository will automatically check PRs for linting compliance.
### Setting up your Environment
1. Clone this repo (including submodules): `git clone --recurse-submodules`
+1. Install php v8.3
1. install [composer](https://getcomposer.org/)
1. install PHP dependencies: `composer update`
1. If you're on Windows, use [WSL](https://learn.microsoft.com/en-us/windows/wsl/)
diff --git a/composer.json b/composer.json
index e0e04619..a3edd9a0 100644
--- a/composer.json
+++ b/composer.json
@@ -7,5 +7,10 @@
"require-dev": {
"phpunit/phpunit": ">=12",
"robiningelbrecht/phpunit-coverage-tools": "<2"
+ },
+ "config": {
+ "platform": {
+ "php": "8.3.6"
+ }
}
}
diff --git a/composer.lock b/composer.lock
index bd70b728..5d3ad790 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "3cc718e763cf89866d307423ef19105d",
+ "content-hash": "ca6d4e77c5ab7ba1fbe152a409d86cf9",
"packages": [
{
"name": "paragonie/constant_time_encoding",
@@ -2103,16 +2103,16 @@
},
{
"name": "symfony/console",
- "version": "v7.3.5",
+ "version": "v7.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7"
+ "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
- "reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
+ "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
+ "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
"shasum": ""
},
"require": {
@@ -2177,7 +2177,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v7.3.5"
+ "source": "https://github.com/symfony/console/tree/v7.3.6"
},
"funding": [
{
@@ -2197,7 +2197,7 @@
"type": "tidelift"
}
],
- "time": "2025-10-14T15:46:26+00:00"
+ "time": "2025-11-04T01:21:42+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -2603,16 +2603,16 @@
},
{
"name": "symfony/service-contracts",
- "version": "v3.6.0",
+ "version": "v3.6.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
- "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
"shasum": ""
},
"require": {
@@ -2666,7 +2666,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
},
"funding": [
{
@@ -2677,12 +2677,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-04-25T09:37:31+00:00"
+ "time": "2025-07-15T11:30:57+00:00"
},
{
"name": "symfony/string",
@@ -2832,5 +2836,8 @@
"prefer-lowest": false,
"platform": {},
"platform-dev": {},
+ "platform-overrides": {
+ "php": "8.3.6"
+ },
"plugin-api-version": "2.6.0"
}
From 284055aeb16bbf3b9455b88c7e1e0700769faf68 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 12:40:56 -0500
Subject: [PATCH 05/13] specify php version
---
.pre-commit-config.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 61ff708f..de9876a8 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -29,7 +29,8 @@ repos:
- id: prettier (php)
name: prettier (php)
entry: npx
- args: [prettier, --plugin=@prettier/plugin-php, --write]
+ args:
+ [prettier, --plugin=@prettier/plugin-php, --php-version=8.3, --write]
language: system
files: \.php$
# prettier doesn't do well with the html files with
Date: Fri, 7 Nov 2025 12:41:16 -0500
Subject: [PATCH 06/13] fix formatting for php8.3
---
resources/lib/UnityHTTPD.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/resources/lib/UnityHTTPD.php b/resources/lib/UnityHTTPD.php
index 688f42bc..bdadb22b 100644
--- a/resources/lib/UnityHTTPD.php
+++ b/resources/lib/UnityHTTPD.php
@@ -67,7 +67,7 @@ public static function errorLog(
// newlines are bad for error log, but getTrace() is too verbose
$output["trace"] = explode(
"\n",
- new \Exception()->getTraceAsString(),
+ (new \Exception())->getTraceAsString(),
);
}
error_log("$title: " . \jsonEncode($output));
From e4970d8f3227b99c05f62558b17911676733ac2b Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 12:42:21 -0500
Subject: [PATCH 07/13] gitignore
---
.gitignore | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.gitignore b/.gitignore
index d08024d2..c776c0fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,4 +21,6 @@ deployment/**/*
.phpunit.result.cache
+package.json
+package-lock.json
node_modules
From 31b89bd14074f2ecd0f643db0cca41c01fa7fd30 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 12:48:55 -0500
Subject: [PATCH 08/13] bring back psr12 for impure PHP files
---
.phpcs-ruleset.xml | 11 ++++++
.pre-commit-config.yaml | 36 +++++++++++++++++-
CONTRIBUTING.md | 3 +-
composer.json | 3 +-
composer.lock | 81 ++++++++++++++++++++++++++++++++++++++++-
5 files changed, 130 insertions(+), 4 deletions(-)
create mode 100644 .phpcs-ruleset.xml
diff --git a/.phpcs-ruleset.xml b/.phpcs-ruleset.xml
new file mode 100644
index 00000000..13faff04
--- /dev/null
+++ b/.phpcs-ruleset.xml
@@ -0,0 +1,11 @@
+
+
+ PSR12, with max line length = 100 characters
+
+
+
+
+
+
+
+
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index de9876a8..77c7bb88 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -24,6 +24,24 @@ repos:
composer\.lock|
)$
+ - repo: local
+ hooks:
+ - id: phpcbf
+ name: PHP Code Beautifier and Fixer
+ entry: ./vendor/bin/phpcbf
+ args: [--standard=./.phpcs-ruleset.xml, --colors]
+ language: system
+ files: \.php$
+ # exclude pure PHP files
+ exclude: |
+ (?x)^(
+ node_modules/.*|
+ resources/lib/phpopenldaper/.*|
+ vendor/.*|
+ resources/lib/.*|
+ workers/.*|
+ )$
+
- repo: local
hooks:
- id: prettier (php)
@@ -33,7 +51,7 @@ repos:
[prettier, --plugin=@prettier/plugin-php, --php-version=8.3, --write]
language: system
files: \.php$
- # prettier doesn't do well with the html files with =12",
- "robiningelbrecht/phpunit-coverage-tools": "<2"
+ "robiningelbrecht/phpunit-coverage-tools": "<2",
+ "squizlabs/php_codesniffer": "*"
},
"config": {
"platform": {
diff --git a/composer.lock b/composer.lock
index 5d3ad790..74733f60 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "ca6d4e77c5ab7ba1fbe152a409d86cf9",
+ "content-hash": "fa7299619e6198f9ef10dca9d729d04e",
"packages": [
{
"name": "paragonie/constant_time_encoding",
@@ -2049,6 +2049,85 @@
],
"time": "2025-02-07T05:00:38+00:00"
},
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "06113cfdaf117fc2165f9cd040bd0f17fcd5242d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/06113cfdaf117fc2165f9cd040bd0f17fcd5242d",
+ "reference": "06113cfdaf117fc2165f9cd040bd0f17fcd5242d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=7.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31"
+ },
+ "bin": [
+ "bin/phpcbf",
+ "bin/phpcs"
+ ],
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "keywords": [
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-09-15T11:28:58+00:00"
+ },
{
"name": "staabm/side-effects-detector",
"version": "1.0.5",
From 65c441e860f3f56c4f2886e77f6cee27124f8b91 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 12:52:22 -0500
Subject: [PATCH 09/13] check end of file but ignore workers
---
.pre-commit-config.yaml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 77c7bb88..1d4a5933 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -10,9 +10,9 @@ repos:
rev: v5.0.0
hooks:
- id: trailing-whitespace
- # prettier should take care of this, but it has this one problem with shebang files
- # https://github.com/prettier/plugin-php/issues/2430
- # - id: end-of-file-fixer
+ - id: end-of-file-fixer
+ # https://github.com/prettier/plugin-php/issues/2430
+ exclude: workers/.*
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.4.2
From 6c503a3cd3fc2385dc209ee8ee73d48b69a63203 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 12:54:10 -0500
Subject: [PATCH 10/13] dont check test
---
.pre-commit-config.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 1d4a5933..88cdcbcc 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -35,11 +35,12 @@ repos:
# exclude pure PHP files
exclude: |
(?x)^(
+ test/.*|
+ workers/.*|
node_modules/.*|
resources/lib/phpopenldaper/.*|
vendor/.*|
resources/lib/.*|
- workers/.*|
)$
- repo: local
From 00b1c63a4f170dad132f118e876f72b0b4a5514f Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 13:07:56 -0500
Subject: [PATCH 11/13] fix CI
---
.github/workflows/phpunit.yml | 2 +-
.github/workflows/pre-commit.yml | 4 +++-
.pre-commit-config.yaml | 11 ++++++++++-
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index 79c16afa..2ccdda08 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -18,7 +18,7 @@ jobs:
php-version: "8.3"
tools: composer
- name: install composer dependencies
- run: composer update
+ run: composer install --dev
- name: Run docker compose
uses: hoverkraft-tech/compose-action@v2.0.1
with:
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index 3a35b365..1618f33c 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -17,5 +17,7 @@ jobs:
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
- tools: composer, phpcs, phpcbf
+ tools: composer
+ - name: install composer dependencies
+ run: composer install --dev
- uses: pre-commit/action@v3.0.1
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 88cdcbcc..bc28907b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -49,7 +49,16 @@ repos:
name: prettier (php)
entry: npx
args:
- [prettier, --plugin=@prettier/plugin-php, --php-version=8.3, --write]
+ [
+ -p,
+ prettier,
+ -p,
+ "@prettier/plugin-php",
+ prettier,
+ --plugin=@prettier/plugin-php,
+ --php-version=8.3,
+ --write,
+ ]
language: system
files: \.php$
# exclude impure PHP files
From 9fdcf91da3399280bf709c171b18ed6caaecc48f Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 13:13:26 -0500
Subject: [PATCH 12/13] save node tools in package.json, package.lock
---
.github/workflows/phpunit.yml | 12 +++----
.github/workflows/pre-commit.yml | 7 ++--
.gitignore | 2 --
CONTRIBUTING.md | 3 +-
package-lock.json | 57 ++++++++++++++++++++++++++++++++
package.json | 6 ++++
6 files changed, 72 insertions(+), 15 deletions(-)
create mode 100644 package-lock.json
create mode 100644 package.json
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index 2ccdda08..92fa84bb 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -12,16 +12,12 @@ jobs:
- uses: actions/checkout@v3
with:
submodules: true
- - name: setup PHP
- uses: shivammathur/setup-php@v2
+ - uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
tools: composer
- - name: install composer dependencies
- run: composer install --dev
- - name: Run docker compose
- uses: hoverkraft-tech/compose-action@v2.0.1
+ - run: composer install --dev
+ - uses: hoverkraft-tech/compose-action@v2.0.1
with:
compose-file: "./tools/docker-dev/docker-compose.yml"
- - name: Execute tests in the running services
- run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover="$(mktemp --suffix=.xml)" -d --min-coverage=./coverage.php'
+ - run: docker compose -f ./tools/docker-dev/docker-compose.yml exec -w '/var/www/unity-web-portal' web bash -c 'XDEBUG_MODE=coverage ./vendor/bin/phpunit --coverage-clover="$(mktemp --suffix=.xml)" -d --min-coverage=./coverage.php'
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index 1618f33c..aa806672 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -13,11 +13,10 @@ jobs:
with:
submodules: true
- uses: actions/setup-python@v3
- - name: setup PHP
- uses: shivammathur/setup-php@v2
+ - uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
tools: composer
- - name: install composer dependencies
- run: composer install --dev
+ - run: composer install --dev
+ - uses: actions/setup-node@v6.0.0
- uses: pre-commit/action@v3.0.1
diff --git a/.gitignore b/.gitignore
index c776c0fc..d08024d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,4 @@ deployment/**/*
.phpunit.result.cache
-package.json
-package-lock.json
node_modules
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c6c055e9..d4c3e197 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -40,7 +40,8 @@ This repository will automatically check PRs for linting compliance.
1. Install [pre-commit](https://pre-commit.com/)
1. setup pre-commit hooks: `pre-commit install`
1. Install modern implementation of grep (not macOS builtin grep): `brew install grep`
-1. Install `prettier`, `prettier-plugin-php`: `npm install --dev prettier '@prettier/plugin-php'`
+1. Install `npm`
+1. Install nodeJS tools: `npm install`
### Environment Usage
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..5e051dcb
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,57 @@
+{
+ "name": "unity-web-portal",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "devDependencies": {
+ "@prettier/plugin-php": "^0.24.0",
+ "prettier": "^3.6.2"
+ }
+ },
+ "node_modules/@prettier/plugin-php": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/@prettier/plugin-php/-/plugin-php-0.24.0.tgz",
+ "integrity": "sha512-x9l65fCE/pgoET6RQowgdgG8Xmzs44z6j6Hhg3coINCyCw9JBGJ5ZzMR2XHAM2jmAdbJAIgqB6cUn4/3W3XLTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "linguist-languages": "^8.0.0",
+ "php-parser": "^3.2.5"
+ },
+ "peerDependencies": {
+ "prettier": "^3.0.0"
+ }
+ },
+ "node_modules/linguist-languages": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/linguist-languages/-/linguist-languages-8.2.0.tgz",
+ "integrity": "sha512-KCUUH9x97QWYU0SXOCGxUrZR6cSfuQrMhABB7L/0I8N0LXOeaKe7+RZs7FAwvWCV2qKfZ4Wv1luLq4OfMezSJg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/php-parser": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/php-parser/-/php-parser-3.2.5.tgz",
+ "integrity": "sha512-M1ZYlALFFnESbSdmRtTQrBFUHSriHgPhgqtTF/LCbZM4h7swR5PHtUceB2Kzby5CfqcsYwBn7OXTJ0+8Sajwkw==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/prettier": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
+ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..84c53231
--- /dev/null
+++ b/package.json
@@ -0,0 +1,6 @@
+{
+ "devDependencies": {
+ "@prettier/plugin-php": "^0.24.0",
+ "prettier": "^3.6.2"
+ }
+}
From dbebc8a85b61d82ea46057da5753595fa7d21ba7 Mon Sep 17 00:00:00 2001
From: Simon Leary
Date: Fri, 7 Nov 2025 13:15:46 -0500
Subject: [PATCH 13/13] npm install
---
.github/workflows/pre-commit.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
index aa806672..fca4d814 100644
--- a/.github/workflows/pre-commit.yml
+++ b/.github/workflows/pre-commit.yml
@@ -19,4 +19,5 @@ jobs:
tools: composer
- run: composer install --dev
- uses: actions/setup-node@v6.0.0
+ - run: npm install --dev
- uses: pre-commit/action@v3.0.1