diff --git a/.editorconfig b/.editorconfig index 6537ca467..78326873f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,9 +3,9 @@ root = true [*] charset = utf-8 end_of_line = lf -insert_final_newline = true +indent_size = 2 indent_style = space -indent_size = 4 +insert_final_newline = true trim_trailing_whitespace = true [*.md] @@ -13,3 +13,24 @@ trim_trailing_whitespace = false [*.{yml,yaml}] indent_size = 2 + +[docker-compose.yml] +indent_size = 2 + +[*.php] +indent_size = 4 + +[*.blade.php] +indent_size = 2 + +[*.js] +indent_size = 4 + +[*.jsx] +indent_size = 2 + +[*.tsx] +indent_size = 2 + +[*.json] +indent_size = 4 diff --git a/.env.example b/.env.example index ee25724ca..bf995c5bc 100644 --- a/.env.example +++ b/.env.example @@ -1,28 +1,54 @@ +# ⚠️ CAUTION: Advanced Configuration ⚠️ +# +# This file (.env) stores sensitive environment variables. +# Modifying these values can significantly impact your application's behavior. +# +# Proceed with caution: +# - Only edit if you have a clear understanding of the specific variable and its purpose. +# - Use the control panel or installer for most configuration changes whenever possible. +# - Keep a backup of this file before making any modifications. +# +# Need Help? Consult the documentation or contact support before making changes. + ### --- App Settings --- ### -APP_NAME=Ctrlpanel.gg +APP_NAME=CtrlPanel.gg APP_ENV=production APP_KEY= APP_DEBUG=false APP_URL=http://localhost -# List with timezones https://www.php.net/manual/en/timezones.php APP_TIMEZONE=UTC ### --- App Settings End --- ### -### --- DB Settings (required) --- ### +### --- Database Settings (required) --- ### +# SQL DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=dashboard DB_USERNAME=dashboarduser DB_PASSWORD= -### --- DB Settings End --- ### +### --- Discord Settings (required for Discord OAuth) --- ### +DISCORD_CLIENT_ID= +DISCORD_CLIENT_SECRET= + +### --- Discord Settings End --- ### -# Google Recaptcha API Credentials - https://www.google.com/recaptcha/admin - reCaptcha V2 (not v3) +### --- Google Recaptcha Settings --- ### RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI RECAPTCHA_SECRET_KEY=6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe +### --- Google Recaptcha Settings End --- ### + +# No-SQL +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 +### --- Database Settings End --- ### -# Mail Server Settings - (HOST -> SMTP Server) + +### --- Mail Server Settings --- ### MAIL_MAILER=smtp MAIL_HOST=mailhog MAIL_PORT=1025 @@ -31,25 +57,22 @@ MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_FROM_ADDRESS=null MAIL_FROM_NAME="${APP_NAME}" +### --- Mail Server Settings End --- ### - -# Laravel Logging Settings - https://laravel.com/docs/5.7/logging - Not needed to be changed +### --- Logging Settings --- ### LOG_CHANNEL=stack LOG_LEVEL=debug +### --- Logging Settings End --- ### -# Do not change anything below this line -BROADCAST_DRIVER=log +### --- Cache and Queue Settings --- ### CACHE_DRIVER=file QUEUE_CONNECTION=database SESSION_DRIVER=file SESSION_LIFETIME=120 +SETTINGS_CACHE_ENABLED=true +### --- Cache and Queue Settings End --- ### -MEMCACHED_HOST=127.0.0.1 - -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - +### --- External Services Credentials --- ### AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 @@ -62,3 +85,7 @@ PUSHER_APP_CLUSTER=mt1 MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" + +RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI +RECAPTCHA_SECRET_KEY=6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe +### --- External Services Credentials End --- ### diff --git a/.gitattributes b/.gitattributes index 967315dd3..2f74b7dd8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,10 @@ +# Automatically detect text files * text=auto + +# Vendored files for specific languages *.css linguist-vendored *.scss linguist-vendored *.js linguist-vendored + +# Ignore CHANGELOG.md when exporting CHANGELOG.md export-ignore diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..6b807f423 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,22 @@ +## Code of Conduct + +### 🤝 Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +### 🌟 Our Standards +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000..93b4ee75c --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,37 @@ +# Contributing Guidelines + +Thank you for considering contributing to this repository! Before making a contribution, please take a moment to review the following guidelines. + +## 🕵️‍♂️ Finding Tasks + +Check the open issues to see if there's something you can contribute to. If you have an idea or encounter a bug that's not already listed, feel free to create a new issue and wait for feedback from the development team. + +## 🤝 Code of Conduct & Contributor License + +Please adhere to our [Code of Conduct](https://github.com/Ctrlpanel-gg/panel/blob/main/.github/CODE_OF_CONDUCT.md) and our [Contributor License](https://github.com/Ctrlpanel-gg/panel/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md) in all your interactions with the project. + +## 🌍 Localization + +Please read our [Localization Guide](https://github.com/Ctrlpanel-gg/panel/blob/main/lang/README.md) on how to manage and add localization to the project. + +## 🚀 Pull Request Process + +1. Provide a clear and descriptive title for your pull request (PR) summarizing the changes in this format : 'commit-norms-action: what-you-are-doing'. +2. If your PR is not yet finished, correctly mark it as a draft and mention any errors it's correcting. +3. The development team will review your code and offer feedback or approve/merge it as necessary. +4. Ensure that your PR adheres to our Code of Conduct and coding style guidelines. +5. Test your changes thoroughly to ensure they function as expected. +6. Include relevant documentation updates if applicable. +7. Address any review comments promptly to expedite the review process. + +### 💻 Coding Style + +We adhere to the PSR12 code standard for PHP. + +- Follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) commit norms. +- Name your PR branch as [commit-norms-action]/what-you-are-doing. +- Make clear commits, one per action, and include comments. + +⚠️ **Important Note:** The owner of the project has the final decision, and the development team of CtrlPanel reserves the right to close incorrect PRs. PRs that remain inactive or invalid for an extended period may also be subject to closure. + +Thank you for your contributions! 🎉 diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 077ef34d4..53671ccd3 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,6 +1,5 @@ name: "\U0001F41B Bug report" description: Create a report to help us improve -title: "[Bug]: " labels: ["bug"] body: - type: textarea @@ -33,8 +32,8 @@ body: - type: textarea id: ctrlpanel-logs attributes: - label: Ctrlpanel Logs - description: Please copy and paste your laravel-log output. You may also provide a link to it using the following command `tail -n 100 /var/www/controlpanel/storage/logs/laravel.log | nc pteropaste.com 99` + label: CtrlPanel Logs + description: Please copy and paste your laravel-log output. You may also provide a link to it using the following command `tail -n 100 /var/www/ctrlpanel/storage/logs/laravel.log | nc pteropaste.com 99` render: Shell - type: textarea id: additional-info diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 7b1652eaa..34e1506be 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -5,4 +5,4 @@ contact_links: about: Please visit our Discord for help with your installation. - name: ❓ General Question url: https://discord.gg/4Y6HjD2uyU - about: Please visit our Discord for general questions about the ControlPanel. + about: Please visit our Discord for general questions about the CtrlPanel. diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 6d628f97c..e61d14909 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,6 +1,5 @@ name: "\U0001F680 Feature request" description: Suggest a feature or idea for this project -title: "[Feature] " labels: ["feature"] body: - type: textarea diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..7da279d75 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,37 @@ +✨ Thank you for your contribution to our project! Before you submit your pull request, please take a moment to review and complete the following + +⚠️ Please modify this template below and if not already done, read our contributing rules in .github folder, Thanks! + +Ensure that your pull request meets the following criteria: + +- The code follows the style guidelines of this project +- You have performed a self-review of your own code and tested it +- You have commented your code, particularly in hard-to-understand areas +- Your changes generate no new warnings + +Delete the above text and the following sections before submitting your pull request. + +--- + +💡 **Description** + +Briefly describe the purpose of your pull request, including any relevant issue numbers it addresses. + +--- + +🛠️ **Type of Change** + +Please select the appropriate type of change: + +- Bug fix (non-breaking change which fixes an issue) +- User interface (UI) improvement +- New feature (non-breaking change which adds functionality) +- Breaking change (a fix or feature that would cause existing functionality to not work as expected) +- Other +- This change requires a documentation update + +--- + +🖼️ **Screenshots (if applicable)** + +If your pull request includes any visual changes, please provide screenshots here, do not use any external link. diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 000000000..ef6b07aa9 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Reporting a Vulnerability + +🛡️ If you discover a security vulnerability, please report it to us via GitHub Advisories. + +⚠️ Please refrain from using the public issue tracker or discussing the vulnerability in public channels, as it may exacerbate the issue. + +## Acceptance of Bug Bounty Platforms + +At this time, we only accept vulnerability reports through GitHub Advisories. We kindly ask that you do not submit reports via other third-party bug bounty platforms, as they will be disregarded. + +## Supported Versions +- Latests + +### CtrlPanel Versions +We strongly recommend using or upgrading to the latest version of CtrlPanel to ensure you have access to the latest security fixes and enhancements. diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 000000000..54016c792 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,43 @@ +name: Build and Push Docker Image + +on: + push: + tags: + - '*' + +jobs: + build-and-push-docker-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + file: docker/standalone/Dockerfile + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore index 58212a1db..e27770f13 100644 --- a/.gitignore +++ b/.gitignore @@ -1,28 +1,38 @@ +# Ignore dependencies and cache +/.idea /node_modules +/vendor +/storage/*.key + +# Ignore public assets /public/hot /public/storage -/storage/*.key -/vendor -/storage/credit_deduction_log -storage/debugbar +/storage/app/public/logo.png + +# Ignore environment files and configuration .env .env.testing .env.backup -.idea +.env.dev + +# Ignore testing and debug logs .phpunit.result.cache -docker-compose.override.yml -Homestead.json -Homestead.yaml npm-debug.log yarn-error.log yarn.lock + +# Ignore Docker and Homestead configuration +docker-compose.override.yml +Homestead.json +Homestead.yaml + +# Ignore gitignore itself .gitignore -.env.dev -.env.testing -storage/invoices.zip -storage/app/public/logo.png -*vscode - - Kopie.env + +# Ignore installation logs and locks public/install/logs.txt install.lock public/install/logs/installer.log + +/.idea +cpggdatabase.sql diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 74ddb1f9f..000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,43 +0,0 @@ -# Contributing - -When contributing to this repository, please go through the open issues to see if you can contribute to something. If you want to contribute something that is not in the issues you can make an issue and wait for response from the dev team. - -Please note we have a code of conduct, please follow it in all your interactions with the project. - -If you added any Strings which are displayed at the frontend please localize them (e.g. "New String" -> {{ __('New String') }}) and run the localization string generation: - -```cmd -php artisan translatable:export en -``` - -## Pull request process - -1. Give your PR a good descriptive title, so we can view immediately what the PR is about. -2. The dev team will look at your code and approve / merge when possible. -3. Make sure your PR follows our code of conduct and coding style. - -## Code of Conduct - -### Our Pledge -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. - -### Coding Style - -We are following the PSR12 code standard for PHP. - -### Our Standards -Examples of behavior that contributes to creating a positive environment include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a professional setting diff --git a/CONTRIBUTOR_LICENSE_AGREEMENT.md b/CONTRIBUTOR_LICENSE_AGREEMENT.md new file mode 100644 index 000000000..05df29748 --- /dev/null +++ b/CONTRIBUTOR_LICENSE_AGREEMENT.md @@ -0,0 +1,96 @@ +Thank you for your interest in CtrlPanel-gg ("CtrlPanel Developers"). To clarify the intellectual property license +granted with Contributions from any person or entity, the CtrlPanel Developers +must have on file a signed Contributor License Agreement ("CLA") +from each Contributor, indicating agreement with the license +terms below. This agreement is for your protection as a Contributor +as well as the protection of the CtrlPanel Developers and its users. It does not +change your rights to use your own Contributions for any other purpose. + +You accept and agree to the following terms and conditions for Your +Contributions (present and future) that you submit to the CtrlPanel Developers. In +return, the CtrlPanel Developers shall not use Your Contributions in a way that +is contrary to the public benefit or inconsistent with its nonprofit +status and bylaws in effect at the time of the Contribution. Except +for the license granted herein to the CtrlPanel Developers and recipients of +software distributed by the CtrlPanel Developers, You reserve all right, title, +and interest in and to Your Contributions. +1. Definitions. + "You" (or "Your") shall mean the copyright owner or legal entity + authorized by the copyright owner that is making this Agreement + with the CtrlPanel Developers. For legal entities, the entity making a + Contribution and all other entities that control, are controlled + by, or are under common control with that entity are considered to + be a single Contributor. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, that + is intentionally submitted by You to the CtrlPanel Developers for inclusion + in, or documentation of, any of the products owned or managed by + the CtrlPanel Developers (the "Work"). For the purposes of this definition, + "submitted" means any form of electronic, verbal, or written + communication sent to the CtrlPanel Developers or its representatives, + including but not limited to communication on electronic mailing + lists, source code control systems, and issue tracking systems that + are managed by, or on behalf of, the CtrlPanel Developers for the purpose of + discussing and improving the Work, but excluding communication that + is conspicuously marked or otherwise designated in writing by You + as "Not a Contribution." +2. Grant of Copyright License. Subject to the terms and conditions of + this Agreement, You hereby grant to the CtrlPanel Developers and to + recipients of software distributed by the CtrlPanel Developers a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare derivative works of, + publicly display, publicly perform, sublicense, and distribute Your + Contributions and such derivative works. +3. Grant of Patent License. Subject to the terms and conditions of + this Agreement, You hereby grant to the CtrlPanel Developers and to + recipients of software distributed by the CtrlPanel Developers a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have + made, use, offer to sell, sell, import, and otherwise transfer the + Work, where such license applies only to those patent claims + licensable by You that are necessarily infringed by Your + Contribution(s) alone or by combination of Your Contribution(s) + with the Work to which such Contribution(s) was submitted. If any + entity institutes patent litigation against You or any other entity + (including a cross-claim or counterclaim in a lawsuit) alleging + that your Contribution, or the Work to which you have contributed, + constitutes direct or contributory patent infringement, then any + patent licenses granted to that entity under this Agreement for + that Contribution or Work shall terminate as of the date such + litigation is filed. +4. You represent that you are legally entitled to grant the above + license. If your employer(s) has rights to intellectual property + that you create that includes your Contributions, you represent + that you have received permission to make Contributions on behalf + of that employer, that your employer has waived such rights for + your Contributions to the CtrlPanel Developers, or that your employer has + executed a separate Corporate CLA with the CtrlPanel Developers. +5. You represent that each of Your Contributions is Your original + creation (see section 7 for submissions on behalf of others). You + represent that Your Contribution submissions include complete + details of any third-party license or other restriction (including, + but not limited to, related patents and trademarks) of which you + are personally aware and which are associated with any part of Your + Contributions. +6. You are not expected to provide support for Your Contributions, + except to the extent You desire to provide support. You may provide + support for free, for a fee, or not at all. Unless required by + applicable law or agreed to in writing, You provide Your + Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS + OF ANY KIND, either express or implied, including, without + limitation, any warranties or conditions of TITLE, NON- + INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. +7. Should You wish to submit work that is not Your original creation, + You may submit it to the CtrlPanel Developers separately from any + Contribution, identifying the complete details of its source and of + any license or other restriction (including, but not limited to, + related patents, trademarks, and license agreements) of which you + are personally aware, and conspicuously marking the work as + "Submitted on behalf of a third-party: [named here]". +8. You agree to notify the CtrlPanel Developers of any facts or circumstances of + which you become aware that would make these representations + inaccurate in any respect. diff --git a/LICENSE b/LICENSE index 00e2a0b66..29ebfa545 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,661 @@ -MIT License - -Copyright (c) 2021 CtrlPanel.gg - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file diff --git a/README.md b/README.md index 2dee85a12..8bbc922c3 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,87 @@ -### Features - -- PayPal Integration -- Stripe Integration -- Referral System -- Partner System -- Ticket System -- Upgrade/Downgrade Server Resources -- Store (credit system with hourly billing and invoices) -- Email Verification -- Audit Log -- Admin Dashboard -- User/Server Management -- Customisable server plans -- Vouchers -- Alert System -- Theme Support -- and so much more! +
+ +
# CtrlPanel-gg -![ctrlpanel](https://user-images.githubusercontent.com/67899387/214684708-739c1d21-06e8-4dec-a4f1-81533a46cc7e.png) +CtrlPanel offers an easy-to-use and free billing solution for all starting and experienced hosting providers that seamlessly integrates with the Pterodactyl panel. It facilitates account creation, server ordering, and management, while offering addons, multiple payment methods, and customizable themes for a comprehensive solution. +![GitHub tag](https://img.shields.io/github/tag/Ctrlpanel-gg/panel) +![Overall Installations](https://img.shields.io/badge/Overall%20Installations-5000%2B-green) +![GitHub stars](https://img.shields.io/github/stars/Ctrlpanel-gg/panel) +![License](https://img.shields.io/github/license/Ctrlpanel-gg/panel) +![Discord](https://img.shields.io/discord/787829714483019826) -![](https://img.shields.io/endpoint?label=v0.9%20Installations&url=https%3A%2F%2Fmarket.ctrlpanel.gg%2Fcallhome.php%3Fgetinstalls) -![](https://img.shields.io/badge/Overall%20Installations-5000%2B-green) -![](https://img.shields.io/github/stars/CtrlPanel-gg/panel) ![](https://img.shields.io/github/forks/CtrlPanel-gg/panel) ![](https://img.shields.io/github/tag/CtrlPanel-gg/panel) [![Crowdin](https://badges.crowdin.net/controlpanelgg/localized.svg)](https://crowdin.com/project/controlpanelgg) ![](https://img.shields.io/github/issues/CtrlPanel-gg/panel) ![](https://img.shields.io/github/license/CtrlPanel-gg/panel) ![](https://img.shields.io/discord/787829714483019826) -## About +![CtrlPanel](https://user-images.githubusercontent.com/67899387/214684708-739c1d21-06e8-4dec-a4f1-81533a46cc7e.png) -CtrlPanel's Dashboard is a dashboard application designed to offer clients a management tool to manage their pterodactyl servers. This dashboard comes with a credit-based billing solution that credits users hourly for each server they have and suspends them if they run out of credits. +## ⭐ Features -This dashboard offers an easy to use and free billing solution for all starting and experienced hosting providers. This dashboard has many customisation options and added discord Oauth verification to offer a solid link between your discord server and your dashboard. You can check our [Demo here](https://demo.ctrlpanel.gg "Demo"). +- Store (credit system with hourly billing and invoices) +- Many Popular Payment Methods +- Referral +- Partner +- Vouchers +- Ticket +- Account Management +- Admin Dashboard and Tools +- Addon Support +- Multiple Languages Supported +- and More! -### [Installation](https://ctrlpanel.gg/docs/intro "Installation") +## ⛰️ Live Demo -### [Updating](https://ctrlpanel.gg/docs/Installation/updating "Updating") +Try it! -### [Discord](https://discord.gg/4Y6HjD2uyU "Discord") +Demo Server: [demo.CtrlPanel.gg](https://demo.CtrlPanel.gg) -### [Contributing](https://ctrlpanel.gg/docs/Contributing/contributing "Contributing") +*It is a temporary live demo; all data will be deleted.* -### [Donating](https://ctrlpanel.gg/docs/Contributing/donating "Donating") +## 🔧 How to Install +### 🐳 Docker +*Soon...* -# Preview + -### Example server products -![image](https://user-images.githubusercontent.com/67899387/214686950-218e1ede-6a1f-4e53-b3f4-fe1abc371a9c.png) +### 💪🏻 Non-Docker -### Ticket System -![image](https://user-images.githubusercontent.com/67899387/214687123-0a3d0f8f-b53c-4b0d-869a-4d5df45f5184.png) +Requirements: -### Voucher System -![image](https://user-images.githubusercontent.com/67899387/214686578-ec9f0b0f-6047-4665-835f-70594b56dfd5.png) +- Platform + - Major Linux distros such as Debian, Ubuntu, CentOS, Fedora, and ArchLinux etc. -### Partner System -![image](https://user-images.githubusercontent.com/67899387/214686321-36ba97a3-4181-4e60-9ba3-c9b318fe66a8.png) +Follow the [documentation](https://ctrlpanel.gg/docs/intro) to know how to install. +### MarketPlace +If you need more functionality, check out [Marketplace](https://market.ctrlpanel.gg/). +## 🆙 How to Update + +Please read: [Update Instructions](https://ctrlpanel.gg/docs/Installation/updating) + +## 🆕 What's Next? + +Roadmap: [CtrlPanel Roadmap](https://github.com/orgs/Ctrlpanel-gg/projects/1) + +## 🗣️ Discussion / Ask for Help + +For any general or technical questions, join CtrlPanel [Discord](https://discord.gg/4Y6HjD2uyU) for finding answers to your question. If you cannot find the information you need, feel free to ask. + +## 🤝 Contributing + +Please read [CONTRIBUTING.md](https://github.com/Ctrlpanel-gg/panel/blob/main/.github/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. + +Thanks to all contributors and supporters! + +## ♥️ Donations + +If you like what we do, please consider [supporting](https://ctrlpanel.gg/docs/Contributing/donating) us. diff --git a/app/Classes/AbstractExtension.php b/app/Classes/AbstractExtension.php new file mode 100644 index 000000000..7c0683980 --- /dev/null +++ b/app/Classes/AbstractExtension.php @@ -0,0 +1,8 @@ +where([['group', '=', $group], ['name', '=', $name]])->get(['payload'])->first(); + + if (is_null($new_value) || is_null($new_value->payload)) { + return null; + } + + // Some keys returns '""' as a value. + if ($new_value->payload === '""') { + return null; + } + + + // remove the quotes from the string + if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') { + return substr($new_value->payload, 1, -1); + } + + return $new_value->payload; + } + + /** + * Get the old value from the settings_old table. + * @param string $key The key to get the value from table. + * @param int|string|bool|null $default The default value to return if the value is null. If value is not nullable, a default must be provided. + */ + public function getOldValue(string $key, int|string|bool|null $default = null) + { + $old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first(); + + if (is_null($old_value) || is_null($old_value->value)) { + return $default; + } + + switch ($old_value->type) { + case 'string': + case 'text': + // Edgecase: The value is a boolean, but it's stored as a string. + if ($old_value->value === "false" || $old_value->value === "true") { + return filter_var($old_value->value, FILTER_VALIDATE_BOOL); + } + return $old_value->value; + case 'boolean': + return filter_var($old_value->value, FILTER_VALIDATE_BOOL); + case 'integer': + return filter_var($old_value->value, FILTER_VALIDATE_INT); + default: + throw new Exception("Unknown type: {$old_value->type}"); + } + } +} diff --git a/app/Classes/PaymentExtensions.php b/app/Classes/PaymentExtensions.php new file mode 100644 index 000000000..30bb1e19f --- /dev/null +++ b/app/Classes/PaymentExtensions.php @@ -0,0 +1,14 @@ + $egg->docker_image, 'startup' => $egg->startup, 'environment' => $egg->getEnvironmentVariables(), + 'oom_disabled' => !$server->product->oom_killer, 'limits' => [ 'memory' => $server->product->memory, 'swap' => $server->product->swap, @@ -366,6 +367,7 @@ public static function updateServer(Server $server, Product $product) 'io' => $product->io, 'cpu' => $product->cpu, 'threads' => null, + 'oom_disabled' => !$server->product->oom_killer, 'feature_limits' => [ 'databases' => $product->databases, 'backups' => $product->backups, diff --git a/app/Console/Commands/ChargeCreditsCommand.php b/app/Console/Commands/ChargeCreditsCommand.php deleted file mode 100644 index 145943c7e..000000000 --- a/app/Console/Commands/ChargeCreditsCommand.php +++ /dev/null @@ -1,101 +0,0 @@ -chunk(10, function ($servers) { - /** @var Server $server */ - foreach ($servers as $server) { - /** @var Product $product */ - $product = $server->product; - /** @var User $user */ - $user = $server->user; - - //charge credits / suspend server - if ($user->credits >= $product->getHourlyPrice()) { - $this->line("{$user->name} Current credits: {$user->credits} Credits to be removed: {$product->getHourlyPrice()}"); - $user->decrement('credits', $product->getHourlyPrice()); - } else { - try { - //suspend server - $this->line("{$server->name} from user: {$user->name} has been suspended!"); - $server->suspend(); - - //add user to notify list - if (!in_array($user, $this->usersToNotify)) { - array_push($this->usersToNotify, $user); - } - } catch (\Exception $exception) { - $this->error($exception->getMessage()); - } - } - } - }); - - return $this->notifyUsers(); - } - - /** - * @return bool - */ - public function notifyUsers() - { - if (!empty($this->usersToNotify)) { - /** @var User $user */ - foreach ($this->usersToNotify as $user) { - $this->line("Notified user: {$user->name}"); - $user->notify(new ServersSuspendedNotification()); - } - } - - //reset array - $this->usersToNotify = []; - - return true; - } -} diff --git a/app/Console/Commands/ChargeServers.php b/app/Console/Commands/ChargeServers.php new file mode 100644 index 000000000..f623b8ec2 --- /dev/null +++ b/app/Console/Commands/ChargeServers.php @@ -0,0 +1,139 @@ +with('user', 'product')->chunk(10, function ($servers) { + /** @var Server $server */ + foreach ($servers as $server) { + /** @var Product $product */ + $product = $server->product; + /** @var User $user */ + $user = $server->user; + + $billing_period = $product->billing_period; + + + // check if server is due to be charged by comparing its last_billed date with the current date and the billing period + $newBillingDate = null; + switch ($billing_period) { + case 'annually': + $newBillingDate = Carbon::parse($server->last_billed)->addYear(); + break; + case 'half-annually': + $newBillingDate = Carbon::parse($server->last_billed)->addMonths(6); + break; + case 'quarterly': + $newBillingDate = Carbon::parse($server->last_billed)->addMonths(3); + break; + case 'monthly': + $newBillingDate = Carbon::parse($server->last_billed)->addMonth(); + break; + case 'weekly': + $newBillingDate = Carbon::parse($server->last_billed)->addWeek(); + break; + case 'daily': + $newBillingDate = Carbon::parse($server->last_billed)->addDay(); + break; + case 'hourly': + $newBillingDate = Carbon::parse($server->last_billed)->addHour(); + default: + $newBillingDate = Carbon::parse($server->last_billed)->addHour(); + break; + }; + + if (!($newBillingDate->isPast())) { + continue; + } + + // check if the server is canceled or if user has enough credits to charge the server or + if ($server->canceled || ($user->credits <= $product->price && $product->price != 0 )) { + try { + // suspend server + $this->line("{$server->name} from user: {$user->name} has been suspended!"); + $server->suspend(); + + // add user to notify list + if (!in_array($user, $this->usersToNotify)) { + array_push($this->usersToNotify, $user); + } + } catch (\Exception $exception) { + $this->error($exception->getMessage()); + } + return; + } + + // charge credits to user + $this->line("{$user->name} Current credits: {$user->credits} Credits to be removed: {$product->price}"); + $user->decrement('credits', $product->price); + + // update server last_billed date in db + DB::table('servers')->where('id', $server->id)->update(['last_billed' => $newBillingDate]); + } + + return $this->notifyUsers(); + }); + } + + /** + * @return bool + */ + public function notifyUsers() + { + if (!empty($this->usersToNotify)) { + /** @var User $user */ + foreach ($this->usersToNotify as $user) { + $this->line("Notified user: {$user->name}"); + $user->notify(new ServersSuspendedNotification()); + } + } + + #reset array + $this->usersToNotify = array(); + return true; + } +} diff --git a/app/Console/Commands/DeleteExpiredCoupons.php b/app/Console/Commands/DeleteExpiredCoupons.php new file mode 100644 index 000000000..9d3ded87a --- /dev/null +++ b/app/Console/Commands/DeleteExpiredCoupons.php @@ -0,0 +1,42 @@ +delete_coupon_on_expires) { + $expired_coupons = Coupon::where('expires_at', '<=', Carbon::now(config('app.timezone')))->get(); + + foreach ($expired_coupons as $expired_coupon) { + $expired_coupon->delete(); + } + } + } +} diff --git a/app/Console/Commands/GetSettingCommand.php b/app/Console/Commands/GetSettingCommand.php new file mode 100644 index 000000000..9be2191ad --- /dev/null +++ b/app/Console/Commands/GetSettingCommand.php @@ -0,0 +1,49 @@ +argument('class'); + $key = $this->argument('key'); + $sameline = $this->option('sameline'); + + try { + $settings_class = "App\\Settings\\$class"; + $settings = new $settings_class(); + + $this->output->write($settings->$key, !$sameline); + + return Command::SUCCESS; + } catch (\Throwable $th) { + $this->error('Error: ' . $th->getMessage()); + return Command::FAILURE; + } + + return Command::SUCCESS; + } +} diff --git a/app/Console/Commands/MakeUserCommand.php b/app/Console/Commands/MakeUserCommand.php index d579a8774..2facbb0de 100644 --- a/app/Console/Commands/MakeUserCommand.php +++ b/app/Console/Commands/MakeUserCommand.php @@ -101,6 +101,8 @@ public function handle() ['Referral code', $user->referral_code], ]); + $user->syncRoles(1); + return 1; } } diff --git a/app/Console/Commands/SetSettingCommand.php b/app/Console/Commands/SetSettingCommand.php new file mode 100644 index 000000000..03481f93e --- /dev/null +++ b/app/Console/Commands/SetSettingCommand.php @@ -0,0 +1,52 @@ +argument('class'); + $key = $this->argument('key'); + $value = $this->argument('value'); + + try { + $settings_class = "App\\Settings\\$class"; + $settings = new $settings_class(); + + $settings->$key = $value; + + $settings->save(); + + $this->info("Successfully updated '$key'."); + } catch (\Throwable $th) { + $this->error('Error: ' . $th->getMessage()); + return Command::FAILURE; + } + + return Command::SUCCESS; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 28d1d36ae..a271e673d 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -8,6 +8,16 @@ class Kernel extends ConsoleKernel { + /** + * The Artisan commands provided by your application. + * + * @var array + */ + protected $commands = [ + Commands\ChargeServers::class, + Commands\DeleteExpiredCoupons::class, + ]; + /** * Define the application's command schedule. * @@ -16,9 +26,10 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - $schedule->command('credits:charge')->hourly(); + $schedule->command('servers:charge')->everyMinute(); $schedule->command('cp:versioncheck:get')->daily(); $schedule->command('payments:open:clear')->daily(); + $schedule->command('coupons:delete')->daily(); //log cronjob activity $schedule->call(function () { diff --git a/app/Enums/PaymentStatus.php b/app/Enums/PaymentStatus.php new file mode 100644 index 000000000..eb01dbddc --- /dev/null +++ b/app/Enums/PaymentStatus.php @@ -0,0 +1,12 @@ +couponCode = $couponCode; + $this->coupon = Coupon::where('code', $couponCode)->first(); + } +} diff --git a/app/Extensions/PaymentGateways/MercadoPago/MercadoPagoExtension.php b/app/Extensions/PaymentGateways/MercadoPago/MercadoPagoExtension.php new file mode 100644 index 000000000..be280ba51 --- /dev/null +++ b/app/Extensions/PaymentGateways/MercadoPago/MercadoPagoExtension.php @@ -0,0 +1,178 @@ + "MercadoPago", + "RoutesIgnoreCsrf" => [ + "payment/MercadoPagoWebhook" + ], + ]; + } + + public static function getRedirectUrl(Payment $payment, ShopProduct $shopProduct, string $totalPriceString): string + { + /** + * For Mercado Pago to work correctly, + * it is necessary to use SSL and the app.url must start with "https://", + * this is necessary so that the webhook receives the information and not an error. + */ + if (!str_contains(config('app.url'), 'https://')) { + throw new Exception(__('It is not possible to purchase via MercadoPago: APP_URL does not have HTTPS, required by Mercado Pago.')); + } + + $user = Auth::user(); + $user = User::findOrFail($user->id); + $url = 'https://api.mercadopago.com/checkout/preferences'; + $settings = new MercadoPagoSettings(); + try { + $response = Http::withHeaders([ + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . $settings->access_token, + ])->post($url, [ + 'back_urls' => [ + 'success' => route('payment.MercadoPagoSuccess'), + 'failure' => route('payment.Cancel'), + 'pending' => route('payment.MercadoPagoSuccess'), + ], + 'notification_url' => route('payment.MercadoPagoWebhook'), + 'payer' => [ + 'email' => $user->email, + ], + 'items' => [ + [ + 'title' => "Order #{$payment->id} - " . $shopProduct->name, + 'quantity' => 1, + 'unit_price' => floatval($totalPriceString), + 'currency_id' => $shopProduct->currency_code, + ], + ], + 'metadata' => [ + 'credit_amount' => $shopProduct->quantity, + 'user_id' => $user->id, + 'crtl_panel_payment_id' => $payment->id, + ], + ]); + + if ($response->successful()) { + return $response->json()['init_point']; + } else { + Log::error('MercadoPago Payment: ' . $response->body()); + throw new Exception('Payment failed'); + } + } catch (Exception $ex) { + Log::error('MercadoPago Payment: ' . $ex->getMessage()); + throw new Exception('Payment failed'); + } + } + + static function Success(Request $request): void + { + $payment = Payment::findOrFail($request->input('payment')); + $payment->status = PaymentStatus::PROCESSING; + $payment->save(); + Redirect::route('home')->with('success', 'Your payment is being processed!')->send(); + return; + } + + static function Webhook(Request $request): JsonResponse + { + $topic = $request->input('topic'); + $action = $request->input('action'); + + /** + * Mercado Pago sends several requests for information in the webhook, + * but most are for other types of API, and that is why it is filtered here. + */ + if ($topic && ($topic === 'merchant_order' || $topic === 'payment')) { + return response()->json(['success' => true]); + } + + try { + if($action) { + $notification = $request['data']['id']; + + // Filter the API for payments + if (!$notification || !$action) return response()->json(['success' => false], 400); + // Mercado pago test api, for testing webhook request + if ($notification == '123456') return response()->json(['success' => true], 200); + + /** + * Check action have payment.*, + * what is expected for this type of api + */ + if (str_contains($action, 'payment')) { + $url = "https://api.mercadopago.com/v1/payments/" . $notification; + $settings = new MercadoPagoSettings(); + $response = Http::withHeaders([ + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . $settings->access_token, + ])->get($url); + if ($response->successful()) { + $mercado = $response->json(); + $status = $mercado['status']; + $payment = Payment::findOrFail($mercado['metadata']['crtl_panel_payment_id']); + $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id); + if ($status == "approved") { + // Avoid double addition of credits, whether due to double requests from the paid market, or a malicious user + if ($payment->status !== PaymentStatus::PAID) { + $user = User::findOrFail($payment->user_id); + $payment->status = PaymentStatus::PAID; + $payment->save(); + $user->notify(new ConfirmPaymentNotification($payment)); + event(new PaymentEvent($user, $payment, $shopProduct)); + event(new UserUpdateCreditsEvent($user)); + } + } else { + if ($status == "cancelled") { + $user = User::findOrFail($payment->user_id); + $payment->status = PaymentStatus::CANCELED; + } else { + $user = User::findOrFail($payment->user_id); + $payment->status = PaymentStatus::PROCESSING; + } + $payment->save(); + event(new PaymentEvent($user, $payment, $shopProduct)); + } + return response()->json(['success' => true]); + } else { + return response()->json(['success' => false]); + } + } else { + return response()->json(['success' => false]); + } + } + } catch (Exception $ex) { + Log::error('MercadoPago Webhook(IPN) Payment: ' . $ex->getMessage()); + return response()->json(['success' => false]); + } + return response()->json(['success' => true]); + } +} diff --git a/app/Extensions/PaymentGateways/MercadoPago/MercadoPagoSettings.php b/app/Extensions/PaymentGateways/MercadoPago/MercadoPagoSettings.php new file mode 100644 index 000000000..f543b6f50 --- /dev/null +++ b/app/Extensions/PaymentGateways/MercadoPago/MercadoPagoSettings.php @@ -0,0 +1,41 @@ + 'fas fa-dollar-sign', + 'access_token' => [ + 'type' => 'string', + 'label' => 'Access Token Key', + 'description' => 'The Access Token of your Mercado Pago App', + ], + 'enabled' => [ + 'type' => 'boolean', + 'label' => 'Enabled', + 'description' => 'Enable or disable this payment gateway', + ], + ]; + } +} diff --git a/app/Extensions/PaymentGateways/MercadoPago/migrations/2024_01_24_120635_create_mercadopago_settings.php b/app/Extensions/PaymentGateways/MercadoPago/migrations/2024_01_24_120635_create_mercadopago_settings.php new file mode 100644 index 000000000..5d4cf411c --- /dev/null +++ b/app/Extensions/PaymentGateways/MercadoPago/migrations/2024_01_24_120635_create_mercadopago_settings.php @@ -0,0 +1,18 @@ +migrator->addEncrypted('mercadopago.access_token', null); + $this->migrator->add('mercadopago.enabled', false); + } + + public function down(): void + { + $this->migrator->delete('mercadopago.access_token'); + $this->migrator->delete('mercadopago.enabled'); + } +} diff --git a/app/Extensions/PaymentGateways/MercadoPago/web_routes.php b/app/Extensions/PaymentGateways/MercadoPago/web_routes.php new file mode 100644 index 000000000..e826d6da5 --- /dev/null +++ b/app/Extensions/PaymentGateways/MercadoPago/web_routes.php @@ -0,0 +1,18 @@ +group(function () { + Route::get( + 'payment/MercadoPagoSuccess', + function () { + MercadoPagoExtension::Success(request()); + } + )->name('payment.MercadoPagoSuccess'); +}); + + +Route::post('payment/MercadoPagoWebhook', function () { + MercadoPagoExtension::Webhook(request()); +})->name('payment.MercadoPagoWebhook'); diff --git a/app/Extensions/PaymentGateways/Mollie/MollieExtension.php b/app/Extensions/PaymentGateways/Mollie/MollieExtension.php new file mode 100644 index 000000000..08d4480d7 --- /dev/null +++ b/app/Extensions/PaymentGateways/Mollie/MollieExtension.php @@ -0,0 +1,119 @@ + "Mollie", + "RoutesIgnoreCsrf" => [ + "payment/MollieWebhook" + ], + ]; + } + + public static function getRedirectUrl(Payment $payment, ShopProduct $shopProduct, string $totalPriceString): string + { + $url = 'https://api.mollie.com/v2/payments'; + $settings = new MollieSettings(); + try { + $response = Http::withHeaders([ + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . $settings->api_key, + ])->post($url, [ + 'amount' => [ + 'currency' => $shopProduct->currency_code, + 'value' => $totalPriceString, + ], + 'description' => "Order #{$payment->id} - " . $shopProduct->name, + 'redirectUrl' => route('payment.MollieSuccess'), + 'cancelUrl' => route('payment.Cancel'), + 'webhookUrl' => url('/extensions/payment/MollieWebhook'), + 'metadata' => [ + 'payment_id' => $payment->id, + ], + ]); + + if ($response->status() != 201) { + Log::error('Mollie Payment: ' . $response->body()); + throw new Exception('Payment failed'); + } + + return $response->json()['_links']['checkout']['href']; + } catch (Exception $ex) { + Log::error('Mollie Payment: ' . $ex->getMessage()); + throw new Exception('Payment failed'); + } + } + + static function success(Request $request): void + { + $payment = Payment::findOrFail($request->input('payment')); + $payment->status = PaymentStatus::PROCESSING; + $payment->save(); + + Redirect::route('home')->with('success', 'Your payment is being processed')->send(); + return; + } + + static function webhook(Request $request): JsonResponse + { + $url = 'https://api.mollie.com/v2/payments/' . $request->id; + $settings = new MollieSettings(); + + try { + $response = Http::withHeaders([ + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer ' . $settings->api_key, + ])->get($url); + if ($response->status() != 200) { + Log::error('Mollie Payment Webhook: ' . $response->json()['title']); + return response()->json(['success' => false]); + } + + + $payment = Payment::findOrFail($response->json()['metadata']['payment_id']); + $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id); + event(new PaymentEvent($payment, $payment, $shopProduct)); + + if ($response->json()['status'] == 'paid') { + $user = User::findOrFail($payment->user_id); + $payment->status = PaymentStatus::PAID; + $payment->save(); + event(new UserUpdateCreditsEvent($user)); + } + } catch (Exception $ex) { + Log::error('Mollie Payment Webhook: ' . $ex->getMessage()); + return response()->json(['success' => false]); + } + + // return a 200 status code + return response()->json(['success' => true]); + } +} diff --git a/app/Extensions/PaymentGateways/Mollie/MollieSettings.php b/app/Extensions/PaymentGateways/Mollie/MollieSettings.php new file mode 100644 index 000000000..a551b4a52 --- /dev/null +++ b/app/Extensions/PaymentGateways/Mollie/MollieSettings.php @@ -0,0 +1,36 @@ + 'fas fa-dollar-sign', + 'api_key' => [ + 'type' => 'string', + 'label' => 'API Key', + 'description' => 'The API Key of your Mollie App', + ], + 'enabled' => [ + 'type' => 'boolean', + 'label' => 'Enabled', + 'description' => 'Enable or disable this payment gateway', + ], + ]; + } +} diff --git a/app/Extensions/PaymentGateways/Mollie/web_routes.php b/app/Extensions/PaymentGateways/Mollie/web_routes.php new file mode 100644 index 000000000..6d07f533d --- /dev/null +++ b/app/Extensions/PaymentGateways/Mollie/web_routes.php @@ -0,0 +1,18 @@ +group(function () { + Route::get( + 'payment/MollieSuccess', + function () { + MollieExtension::success(request()); + } + )->name('payment.MollieSuccess'); +}); + + +Route::post('payment/MollieWebhook', function () { + MollieExtension::webhook(request()); +})->name('payment.MollieWebhook'); diff --git a/app/Extensions/PaymentGateways/PayPal/PayPalExtension.php b/app/Extensions/PaymentGateways/PayPal/PayPalExtension.php new file mode 100644 index 000000000..04eb97ed9 --- /dev/null +++ b/app/Extensions/PaymentGateways/PayPal/PayPalExtension.php @@ -0,0 +1,180 @@ + "PayPal", + "RoutesIgnoreCsrf" => [], + ]; + } + + public static function getRedirectUrl(Payment $payment, ShopProduct $shopProduct, string $totalPriceString): string + { + $request = new OrdersCreateRequest(); + $request->prefer('return=representation'); + $request->body = [ + "intent" => "CAPTURE", + "purchase_units" => [ + [ + "reference_id" => uniqid(), + "description" => $shopProduct->display, + "amount" => [ + "value" => $totalPriceString, + 'currency_code' => strtoupper($shopProduct->currency_code), + 'breakdown' => [ + 'item_total' => [ + 'currency_code' => strtoupper($shopProduct->currency_code), + 'value' => $totalPriceString, + ], + + /* Removed due to errors in the coupon discount calculation. Its not used in other paymentgateways aswell and basically nice to have but unnessecary + + 'tax_total' => [ + 'currency_code' => strtoupper($shopProduct->currency_code), + 'value' => round($shopProduct->getTaxValue(), 2), + ] + */ + ] + ] + ] + ], + "application_context" => [ + "cancel_url" => route('payment.Cancel'), + "return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id]), + 'brand_name' => config('app.name', 'CtrlPanel.GG'), + 'shipping_preference' => 'NO_SHIPPING' + ] + ]; + + + + try { + // Call API with your client and get a response for your call + $response = self::getPayPalClient()->execute($request); + + // check for any errors in the response + if ($response->statusCode != 201) { + throw new \Exception($response->statusCode); + } + + // make sure the link is not empty + if (empty($response->result->links[1]->href)) { + throw new \Exception('No redirect link found'); + } + + return $response->result->links[1]->href; + } catch (HttpException $ex) { + Log::error('PayPal Payment: ' . $ex->getMessage()); + + throw new \Exception('PayPal Payment: ' . $ex->getMessage()); + } + } + + + static function PaypalSuccess(Request $laravelRequest): void + { + $user = Auth::user(); + $user = User::findOrFail($user->id); + + $payment = Payment::findOrFail($laravelRequest->payment); + $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id); + + $request = new OrdersCaptureRequest($laravelRequest->input('token')); + $request->prefer('return=representation'); + + try { + // Call API with your client and get a response for your call + $response = self::getPayPalClient()->execute($request); + if ($response->statusCode == 201 || $response->statusCode == 200) { + //update payment + $payment->update([ + 'status' => PaymentStatus::PAID, + 'payment_id' => $response->result->id, + ]); + + + event(new UserUpdateCreditsEvent($user)); + event(new PaymentEvent($user, $payment, $shopProduct)); + + // redirect to the payment success page with success message + Redirect::route('home')->with('success', 'Payment successful')->send(); + } elseif (env('APP_ENV') == 'local') { + // If call returns body in response, you can get the deserialized version from the result attribute of the response + $payment->delete(); + dd($response); + } else { + $payment->update([ + 'status' => PaymentStatus::CANCELED, + 'payment_id' => $response->result->id, + ]); + abort(500); + } + } catch (HttpException $ex) { + if (env('APP_ENV') == 'local') { + echo $ex->statusCode; + $payment->delete(); + dd($ex->getMessage()); + } else { + $payment->update([ + 'status' => PaymentStatus::CANCELED, + 'payment_id' => $response->result->id, + ]); + abort(422); + } + } + } + + static function getPayPalClient(): PayPalHttpClient + { + + $environment = config('app.env') == 'local' + ? new SandboxEnvironment(self::getPaypalClientId(), self::getPaypalClientSecret()) + : new ProductionEnvironment(self::getPaypalClientId(), self::getPaypalClientSecret()); + return new PayPalHttpClient($environment); + } + /** + * @return string + */ + static function getPaypalClientId(): string + { + $settings = new PayPalSettings(); + return config('app.env') == 'local' ? $settings->sandbox_client_id : $settings->client_id; + } + /** + * @return string + */ + static function getPaypalClientSecret(): string + { + $settings = new PayPalSettings(); + return config('app.env') == 'local' ? $settings->sandbox_client_secret : $settings->client_secret; + } +} diff --git a/app/Extensions/PaymentGateways/PayPal/PayPalSettings.php b/app/Extensions/PaymentGateways/PayPal/PayPalSettings.php new file mode 100644 index 000000000..9d22dec26 --- /dev/null +++ b/app/Extensions/PaymentGateways/PayPal/PayPalSettings.php @@ -0,0 +1,59 @@ +>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-dollar-sign', + 'client_id' => [ + 'type' => 'string', + 'label' => 'Client ID', + 'description' => 'The Client ID of your PayPal App', + ], + 'client_secret' => [ + 'type' => 'string', + 'label' => 'Client Secret', + 'description' => 'The Client Secret of your PayPal App', + ], + 'enabled' => [ + 'type' => 'boolean', + 'label' => 'Enabled', + 'description' => 'Enable this payment gateway', + ], + 'sandbox_client_id' => [ + 'type' => 'string', + 'label' => 'Sandbox Client ID', + 'description' => 'The Sandbox Client ID used when app_env = local', + ], + 'sandbox_client_secret' => [ + 'type' => 'string', + 'label' => 'Sandbox Client Secret', + 'description' => 'The Sandbox Client Secret used when app_env = local', + ], + ]; + } +} diff --git a/app/Extensions/PaymentGateways/PayPal/migrations/2023_03_04_135248_create_pay_pal_settings.php b/app/Extensions/PaymentGateways/PayPal/migrations/2023_03_04_135248_create_pay_pal_settings.php new file mode 100644 index 000000000..db7d0bdd5 --- /dev/null +++ b/app/Extensions/PaymentGateways/PayPal/migrations/2023_03_04_135248_create_pay_pal_settings.php @@ -0,0 +1,104 @@ +exists(); + + + $this->migrator->addEncrypted('paypal.client_id', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') : null); + $this->migrator->addEncrypted('paypal.client_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SECRET') : null); + $this->migrator->addEncrypted('paypal.sandbox_client_id', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') : null); + $this->migrator->addEncrypted('paypal.sandbox_client_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') : null); + $this->migrator->add('paypal.enabled', false); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID', + 'value' => $this->getNewValue('client_id'), + 'type' => 'string', + 'description' => 'The Client ID of your PayPal App' + ], + [ + 'key' => 'SETTINGS::PAYMENTS:PAYPAL:SECRET', + 'value' => $this->getNewValue('client_secret'), + 'type' => 'string', + 'description' => 'The Client Secret of your PayPal App' + ], + [ + 'key' => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID', + 'value' => $this->getNewValue('sandbox_client_id'), + 'type' => 'string', + 'description' => 'The Sandbox Client ID of your PayPal App' + ], + [ + 'key' => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET', + 'value' => $this->getNewValue('sandbox_client_secret'), + 'type' => 'string', + 'description' => 'The Sandbox Client Secret of your PayPal App' + ] + ]); + + + $this->migrator->delete('paypal.client_id'); + $this->migrator->delete('paypal.client_secret'); + $this->migrator->delete('paypal.enabled'); + $this->migrator->delete('paypal.sandbox_client_id'); + $this->migrator->delete('paypal.sandbox_client_secret'); + } + + public function getNewValue(string $name) + { + $new_value = DB::table('settings')->where([['group', '=', 'paypal'], ['name', '=', $name]])->get(['payload'])->first(); + + // Some keys returns '""' as a value. + if ($new_value->payload === '""') { + return null; + } + + // remove the quotes from the string + if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') { + return substr($new_value->payload, 1, -1); + } + + return $new_value->payload; + } + + public function getOldValue(string $key) + { + // Always get the first value of the key. + $old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first(); + + if (is_null($old_value)) { + return null; + } + + // Handle the old values to return without it being a string in all cases. + if ($old_value->type === "string" || $old_value->type === "text") { + if (is_null($old_value->value)) { + return ''; + } + + // Some values have the type string, but their values are boolean. + if ($old_value->value === "false" || $old_value->value === "true") { + return filter_var($old_value->value, FILTER_VALIDATE_BOOL); + } + + return $old_value->value; + } + + if ($old_value->type === "boolean") { + return filter_var($old_value->value, FILTER_VALIDATE_BOOL); + } + + return filter_var($old_value->value, FILTER_VALIDATE_INT); + } +} diff --git a/app/Extensions/PaymentGateways/PayPal/web_routes.php b/app/Extensions/PaymentGateways/PayPal/web_routes.php index 56497768e..75b1da191 100644 --- a/app/Extensions/PaymentGateways/PayPal/web_routes.php +++ b/app/Extensions/PaymentGateways/PayPal/web_routes.php @@ -1,18 +1,13 @@ group(function () { - Route::get('payment/PayPalPay/{shopProduct}', function () { - PaypalPay(request()); - })->name('payment.PayPalPay'); - Route::get( 'payment/PayPalSuccess', function () { - PaypalSuccess(request()); + PayPalExtension::PaypalSuccess(request()); } )->name('payment.PayPalSuccess'); }); diff --git a/app/Extensions/PaymentGateways/Stripe/StripeExtension.php b/app/Extensions/PaymentGateways/Stripe/StripeExtension.php new file mode 100644 index 000000000..12f80844f --- /dev/null +++ b/app/Extensions/PaymentGateways/Stripe/StripeExtension.php @@ -0,0 +1,373 @@ + "Stripe", + "RoutesIgnoreCsrf" => [ + "payment/StripeWebhooks", + ], + ]; + } + + public static function getRedirectUrl(Payment $payment, ShopProduct $shopProduct, string $totalPriceString): string + { + // check if the total price is valid for stripe + $totalPriceNumber = floatval($totalPriceString); + if (!self::checkPriceAmount($totalPriceNumber, strtoupper($shopProduct->currency_code), 'stripe')) { + throw new Exception('Invalid price amount'); + } + + $stripeClient = self::getStripeClient(); + $request = $stripeClient->checkout->sessions->create([ + 'line_items' => [ + [ + 'price_data' => [ + 'currency' => $shopProduct->currency_code, + 'product_data' => [ + 'name' => $shopProduct->display, + 'description' => $shopProduct->description, + ], + 'unit_amount_decimal' => self::priceInCents($totalPriceString), + ], + 'quantity' => 1, + ], + /* Removed due to errors in the coupon discount calculation. Its not used in other paymentgateways aswell and basically nice to have but unnessecary + [ + 'price_data' => [ + 'currency' => $shopProduct->currency_code, + 'product_data' => [ + 'name' => __('Tax'), + 'description' => $shopProduct->getTaxPercent() . '%', + ], + 'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2), + ], + 'quantity' => 1, + ], + */ + ], + + 'mode' => 'payment', + 'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}', + 'cancel_url' => route('payment.Cancel'), + 'payment_intent_data' => [ + 'metadata' => [ + 'payment_id' => $payment->id, + ], + ], + ]); + + return $request->url; + } + + /** + * @param Request $request + */ + public static function StripeSuccess(Request $request) + { + $user = Auth::user(); + $user = User::findOrFail($user->id); + $payment = Payment::findOrFail($request->input('payment')); + $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id); + + Redirect::route('home')->with('success', 'Please wait for success')->send(); + + $stripeClient = self::getStripeClient(); + try { + //get stripe data + $paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id')); + $paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent); + + //get DB entry of this payment ID if existing + $paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count(); + + // check if payment is 100% completed and payment does not exist in db already + if ($paymentSession->status == 'complete' && $paymentIntent->status == 'succeeded' && $paymentDbEntry == 0) { + + //update payment + $payment->update([ + 'payment_id' => $paymentSession->payment_intent, + 'status' => PaymentStatus::PAID, + ]); + + //payment notification + $user->notify(new ConfirmPaymentNotification($payment)); + event(new UserUpdateCreditsEvent($user)); + event(new PaymentEvent($user, $payment, $shopProduct)); + + //redirect back to home + Redirect::route('home')->with('success', 'Payment successful')->send(); + } else { + if ($paymentIntent->status == 'processing') { + + //update payment + $payment->update([ + 'payment_id' => $paymentSession->payment_intent, + 'status' => PaymentStatus::PROCESSING, + ]); + + event(new PaymentEvent($user, $payment, $shopProduct)); + + Redirect::route('home')->with('success', 'Your payment is being processed')->send(); + } + + if ($paymentDbEntry == 0 && $paymentIntent->status != 'processing') { + $stripeClient->paymentIntents->cancel($paymentIntent->id); + + //redirect back to home + Redirect::route('home')->with('info', __('Your payment has been canceled!'))->send(); + } else { + abort(402); + } + } + } catch (Exception $e) { + if (env('APP_ENV') == 'local') { + dd($e->getMessage()); + } else { + abort(422); + } + } + } + + /** + * @param Request $request + */ + public static function handleStripePaymentSuccessHook($paymentIntent) + { + try { + $payment = Payment::where('id', $paymentIntent->metadata->payment_id)->with('user')->first(); + $user = User::where('id', $payment->user_id)->first(); + $shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id); + + if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') { + + //update payment db entry status + $payment->update([ + 'payment_id' => $payment->payment_id ?? $paymentIntent->id, + 'status' => PaymentStatus::PAID, + ]); + + //payment notification + $user->notify(new ConfirmPaymentNotification($payment)); + event(new UserUpdateCreditsEvent($user)); + event(new PaymentEvent($user, $payment, $shopProduct)); + } + + // return 200 + return response()->json(['success' => true], 200); + } catch (Exception $ex) { + abort(422); + } + } + + /** + * @param Request $request + */ + public static function StripeWebhooks(Request $request) + { + Stripe::setApiKey(self::getStripeSecret()); + + try { + $payload = @file_get_contents('php://input'); + $sig_header = $request->header('Stripe-Signature'); + $event = null; + $event = \Stripe\Webhook::constructEvent( + $payload, + $sig_header, + self::getStripeEndpointSecret() + ); + } catch (\UnexpectedValueException $e) { + // Invalid payload + + abort(400); + } catch (SignatureVerificationException $e) { + // Invalid signature + + abort(400); + } + + // Handle the event + switch ($event->type) { + case 'payment_intent.succeeded': + $paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent + self::handleStripePaymentSuccessHook($paymentIntent); + break; + default: + echo 'Received unknown event type ' . $event->type; + } + } + + /** + * @return \Stripe\StripeClient + */ + public static function getStripeClient() + { + return new StripeClient(self::getStripeSecret()); + } + + /** + * @return string + */ + public static function getStripeSecret() + { + $settings = new StripeSettings(); + + return env('APP_ENV') == 'local' + ? $settings->test_secret_key + : $settings->secret_key; + } + + /** + * @return string + */ + public static function getStripeEndpointSecret() + { + $settings = new StripeSettings(); + return env('APP_ENV') == 'local' + ? $settings->test_endpoint_secret + : $settings->endpoint_secret; + } + /** + * @param $amount + * @param $currencyCode + * @param $payment_method + * @return bool + * @description check if the amount is higher than the minimum amount for the stripe gateway + */ + public static function checkPriceAmount(float $amount, string $currencyCode, string $payment_method) + { + $minimums = [ + "USD" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "AED" => [ + "paypal" => 0, + "stripe" => 2 + ], + "AUD" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "BGN" => [ + "paypal" => 0, + "stripe" => 1 + ], + "BRL" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "CAD" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "CHF" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "CZK" => [ + "paypal" => 0, + "stripe" => 15 + ], + "DKK" => [ + "paypal" => 0, + "stripe" => 2.5 + ], + "EUR" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "GBP" => [ + "paypal" => 0, + "stripe" => 0.3 + ], + "HKD" => [ + "paypal" => 0, + "stripe" => 4 + ], + "HRK" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "HUF" => [ + "paypal" => 0, + "stripe" => 175 + ], + "INR" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "JPY" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "MXN" => [ + "paypal" => 0, + "stripe" => 10 + ], + "MYR" => [ + "paypal" => 0, + "stripe" => 2 + ], + "NOK" => [ + "paypal" => 0, + "stripe" => 3 + ], + "NZD" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "PLN" => [ + "paypal" => 0, + "stripe" => 2 + ], + "RON" => [ + "paypal" => 0, + "stripe" => 2 + ], + "SEK" => [ + "paypal" => 0, + "stripe" => 3 + ], + "SGD" => [ + "paypal" => 0, + "stripe" => 0.5 + ], + "THB" => [ + "paypal" => 0, + "stripe" => 10 + ] + ]; + return $amount >= $minimums[$currencyCode][$payment_method]; + } + public static function priceInCents($price){ + $centPrice = str_replace(".", "", $price); + $centPrice = str_replace(",", "", $centPrice); + //$centPrice = str_pad($centPrice, 4, '0', STR_PAD_RIGHT); + return $centPrice; + } + +} diff --git a/app/Extensions/PaymentGateways/Stripe/StripeSettings.php b/app/Extensions/PaymentGateways/Stripe/StripeSettings.php new file mode 100644 index 000000000..7cf6de5f6 --- /dev/null +++ b/app/Extensions/PaymentGateways/Stripe/StripeSettings.php @@ -0,0 +1,55 @@ + 'fas fa-dollar-sign', + 'secret_key' => [ + 'type' => 'string', + 'label' => 'Secret Key', + 'description' => 'The Secret Key of your Stripe App', + ], + 'endpoint_secret' => [ + 'type' => 'string', + 'label' => 'Endpoint Secret', + 'description' => 'The Endpoint Secret of your Stripe App', + ], + 'test_secret_key' => [ + 'type' => 'string', + 'label' => 'Test Secret Key', + 'description' => 'The Test Secret Key used when app_env = local', + ], + 'test_endpoint_secret' => [ + 'type' => 'string', + 'label' => 'Test Endpoint Secret', + 'description' => 'The Test Endpoint Secret used when app_env = local', + ], + 'enabled' => [ + 'type' => 'boolean', + 'label' => 'Enabled', + 'description' => 'Enable this payment gateway', + ] + ]; + } +} diff --git a/app/Extensions/PaymentGateways/Stripe/migrations/2023_03_04_181917_create_stripe_settings.php b/app/Extensions/PaymentGateways/Stripe/migrations/2023_03_04_181917_create_stripe_settings.php new file mode 100644 index 000000000..c320c80db --- /dev/null +++ b/app/Extensions/PaymentGateways/Stripe/migrations/2023_03_04_181917_create_stripe_settings.php @@ -0,0 +1,102 @@ +exists(); + + $this->migrator->addEncrypted('stripe.secret_key', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:SECRET') : null); + $this->migrator->add('stripe.endpoint_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') : null); + $this->migrator->addEncrypted('stripe.test_secret_key', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') : null); + $this->migrator->add('stripe.test_endpoint_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET') : null); + $this->migrator->add('stripe.enabled', false); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::PAYMENTS:STRIPE:SECRET', + 'value' => $this->getNewValue('secret_key'), + 'type' => 'string', + 'description' => 'The Secret Key of your Stripe App' + ], + [ + 'key' => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET', + 'value' => $this->getNewValue('endpoint_secret'), + 'type' => 'string', + 'description' => 'The Endpoint Secret of your Stripe App' + + ], + [ + 'key' => 'SETTINGS::PAYMENTS:STRIPE:TEST_SECRET', + 'value' => $this->getNewValue('test_secret_key'), + 'type' => 'string', + 'description' => 'The Test Secret Key of your Stripe App' + ], + [ + 'key' => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET', + 'value' => $this->getNewValue('test_endpoint_secret'), + 'type' => 'string', + 'description' => 'The Test Endpoint Secret of your Stripe App' + ] + ]); + + $this->migrator->delete('stripe.secret_key'); + $this->migrator->delete('stripe.endpoint_secret'); + $this->migrator->delete('stripe.enabled'); + $this->migrator->delete('stripe.test_secret_key'); + $this->migrator->delete('stripe.test_endpoint_secret'); + } + + public function getNewValue(string $name) + { + $new_value = DB::table('settings')->where([['group', '=', 'stripe'], ['name', '=', $name]])->get(['payload'])->first(); + + // Some keys returns '""' as a value. + if ($new_value->payload === '""') { + return null; + } + + // remove the quotes from the string + if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') { + return substr($new_value->payload, 1, -1); + } + + return $new_value->payload; + } + + public function getOldValue(string $key) + { + // Always get the first value of the key. + $old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first(); + + if (is_null($old_value)) { + return null; + } + + // Handle the old values to return without it being a string in all cases. + if ($old_value->type === "string" || $old_value->type === "text") { + if (is_null($old_value->value)) { + return ''; + } + + // Some values have the type string, but their values are boolean. + if ($old_value->value === "false" || $old_value->value === "true") { + return filter_var($old_value->value, FILTER_VALIDATE_BOOL); + } + + return $old_value->value; + } + + if ($old_value->type === "boolean") { + return filter_var($old_value->value, FILTER_VALIDATE_BOOL); + } + + return filter_var($old_value->value, FILTER_VALIDATE_INT); + } +} diff --git a/app/Extensions/PaymentGateways/Stripe/web_routes.php b/app/Extensions/PaymentGateways/Stripe/web_routes.php index adf481da0..742940d8c 100644 --- a/app/Extensions/PaymentGateways/Stripe/web_routes.php +++ b/app/Extensions/PaymentGateways/Stripe/web_routes.php @@ -1,17 +1,13 @@ group(function () { - Route::get('payment/StripePay/{shopProduct}', function () { - StripePay(request()); - })->name('payment.StripePay'); - Route::get( 'payment/StripeSuccess', function () { - StripeSuccess(request()); + StripeExtension::StripeSuccess(request()); } )->name('payment.StripeSuccess'); }); @@ -19,5 +15,5 @@ function () { // Stripe WebhookRoute -> validation in Route Handler Route::post('payment/StripeWebhooks', function () { - StripeWebhooks(request()); + StripeExtension::StripeWebhooks(request()); })->name('payment.StripeWebhooks'); diff --git a/app/Helpers/ExtensionHelper.php b/app/Helpers/ExtensionHelper.php index 7e1bbda3f..6bf0d3726 100644 --- a/app/Helpers/ExtensionHelper.php +++ b/app/Helpers/ExtensionHelper.php @@ -2,81 +2,231 @@ namespace App\Helpers; +/** + * Summary of ExtensionHelper + */ class ExtensionHelper { /** - * Get a config of an extension by its name - * @param string $extensionName - * @param string $configname + * Get all extensions + * @return array array of all extensions e.g. ["App\Extensions\PayPal", "App\Extensions\Stripe"] */ - public static function getExtensionConfig(string $extensionName, string $configname) + public static function getAllExtensions() + { + $extensionNamespaces = glob(app_path() . '/Extensions/*', GLOB_ONLYDIR); + $extensions = []; + foreach ($extensionNamespaces as $extensionNamespace) { + $extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR)); + } + + // remove base path from every extension but keep app/Extensions/... + $extensions = array_map(fn ($item) => str_replace(app_path() . '/', 'App/', $item), $extensions); + + return $extensions; + } + + /** + * Get all extensions by namespace + * @param string $namespace case sensitive namespace of the extension e.g. PaymentGateways + * @return array array of all extensions e.g. ["App\Extensions\PayPal", "App\Extensions\Stripe"] + */ + public static function getAllExtensionsByNamespace(string $namespace) { - $extensions = ExtensionHelper::getAllExtensions(); + $extensions = glob(app_path() . '/Extensions/' . $namespace . '/*', GLOB_ONLYDIR); + // remove base path from every extension but keep app/Extensions/... + $extensions = array_map(fn ($item) => str_replace(app_path() . '/', 'App/', $item), $extensions); + + return $extensions; + } + + /** + * Get an extension by its name + * @param string $extensionName case sensitive name of the extension e.g. PayPal + * @return string|null the path of the extension e.g. App\Extensions\PayPal + */ + public static function getExtension(string $extensionName) + { + $extensions = self::getAllExtensions(); + // filter the extensions by the extension name + $extensions = array_filter($extensions, fn ($item) => basename($item) == $extensionName); + + // return the only extension + return array_shift($extensions); + } + + /** + * Get all extension classes + * @return array array of all extension classes e.g. ["App\Extensions\PayPal\PayPalExtension", "App\Extensions\Stripe\StripeExtension"] + */ + public static function getAllExtensionClasses() + { + $extensions = self::getAllExtensions(); + + // Replace slashes with backslashes and add the gateway name with "Extension" at the end + $extensions = array_map(function ($item) { + // Convert to backslashes + $item = str_replace('/', '\\', $item); + // Get the last part of the path as the gateway name + $gatewayName = explode('\\', $item); + $gatewayName = array_pop($gatewayName); + + // Construct the full class namespace + return $item . '\\' . $gatewayName . 'Extension'; + }, $extensions); + + // Filter out non-existing extension classes + $extensions = array_filter($extensions, fn ($item) => class_exists($item)); + return $extensions; + } + + /** + * Get all extension classes by namespace + * @param string $namespace case sensitive namespace of the extension e.g. PaymentGateways + * @return array array of all extension classes e.g. ["App\Extensions\PayPal\PayPalExtension", "App\Extensions\Stripe\StripeExtension"] + */ + public static function getAllExtensionClassesByNamespace(string $namespace) + { + $extensions = self::getAllExtensionsByNamespace($namespace); + + // replace all slashes with backslashes + $extensions = array_map(fn ($item) => str_replace('/', '\\', $item), $extensions); + // add the ExtensionClass to the end of the namespace + $extensions = array_map(fn ($item) => $item . '\\' . basename($item) . 'Extension', $extensions); + // filter out non existing extension classes + $extensions = array_filter($extensions, fn ($item) => class_exists($item)); + + return $extensions; + } + + /** + * Get the class of an extension by its name + * @param string $extensionName case sensitive name of the extension e.g. PayPal + * @return string|null the class name of the extension e.g. App\Extensions\PayPal\PayPalExtension + */ + public static function getExtensionClass(string $extensionName) + { + $extensions = self::getAllExtensions(); - // call the getConfig function of the config file of the extension like that - // call_user_func("App\\Extensions\\PaymentGateways\\Stripe" . "\\getConfig"); foreach ($extensions as $extension) { if (!(basename($extension) == $extensionName)) { continue; } + $extension = str_replace('/', '\\', $extension); + $extensionClass = $extension . '\\' . $extensionName . 'Extension'; + return $extensionClass; + } + } - $configFile = $extension . '/config.php'; - if (file_exists($configFile)) { - include_once $configFile; - $config = call_user_func('App\\Extensions\\' . basename(dirname($extension)) . '\\' . basename($extension) . "\\getConfig"); - } - if (isset($config[$configname])) { - return $config[$configname]; - } + + /** + * Get a config of an extension by its name + * @param string $extensionName + * @param string $configname + */ + public static function getExtensionConfig(string $extensionName, string $configname) + { + + $extension = self::getExtensionClass($extensionName); + + $config = $extension::getConfig(); + + + + if (isset($config[$configname])) { + return $config[$configname]; } + return null; } public static function getAllCsrfIgnoredRoutes() { - $extensions = ExtensionHelper::getAllExtensions(); + $extensions = self::getAllExtensionClasses(); $routes = []; + foreach ($extensions as $extension) { - $configFile = $extension . '/config.php'; - if (file_exists($configFile)) { - include_once $configFile; - $config = call_user_func('App\\Extensions\\' . basename(dirname($extension)) . '\\' . basename($extension) . "\\getConfig"); - } + $config = $extension::getConfig(); if (isset($config['RoutesIgnoreCsrf'])) { $routes = array_merge($routes, $config['RoutesIgnoreCsrf']); } - - // map over the routes and add the extension name as prefix - $result = array_map(fn ($item) => "extensions/{$item}", $routes); } + // map over the routes and add the extension name as prefix + $result = array_map(fn ($item) => "extensions/{$item}", $routes); return $result; } /** - * Get all extensions - * @return array + * Summary of getAllExtensionMigrations + * @return array of all migration paths look like: app/Extensions/ExtensionNamespace/ExtensionName/migrations/ */ - public static function getAllExtensions() + public static function getAllExtensionMigrations() { - $extensionNamespaces = glob(app_path() . '/Extensions/*', GLOB_ONLYDIR); - $extensions = []; - foreach ($extensionNamespaces as $extensionNamespace) { - $extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR)); + $extensions = self::getAllExtensions(); + // Transform the extensions to a path + $extensions = array_map(fn ($item) => self::extensionNameToPath($item), $extensions); + + // get all migration directories of the extensions and return them as array + $migrations = []; + foreach ($extensions as $extension) { + $migrationDir = $extension . '/migrations'; + if (file_exists($migrationDir)) { + $migrations[] = $migrationDir; + } } - return $extensions; + return $migrations; } - public static function getAllExtensionsByNamespace(string $namespace) + /** + * Summary of getAllExtensionSettings + * @return array of all setting classes look like: App\Extensions\PaymentGateways\PayPal\PayPalSettings + */ + public static function getAllExtensionSettingsClasses() { - $extensions = glob(app_path() . '/Extensions/' . $namespace . '/*', GLOB_ONLYDIR); + $extensions = self::getAllExtensions(); - return $extensions; + + $settings = []; + foreach ($extensions as $extension) { + $extensionName = basename($extension); + + // replace all slashes with backslashes + $extension = str_replace('/', '\\', $extension); + $settingsClass = $extension . '\\' . $extensionName . 'Settings'; + if (class_exists($settingsClass)) { + $settings[] = $settingsClass; + } + } + + return $settings; + } + + public static function getExtensionSettings(string $extensionName) + { + $extension = self::getExtension($extensionName); + // replace all slashes with backslashes + $extension = str_replace('/', '\\', $extension); + + $settingClass = $extension . '\\' . $extensionName . 'Settings'; + + if (class_exists($settingClass)) { + return new $settingClass(); + } + } + + /** + * Transforms a extension name to a path + * @param string $extensionName e.g. App\Extensions\PaymentGateways\PayPal + * @return string e.g. C:\xampp\htdocs\laravel\app/Extensions/PaymentGateways/PayPal + */ + private static function extensionNameToPath(string $extensionName) + { + return app_path() . '/' . str_replace('App/', '', $extensionName); } } diff --git a/app/Http/Controllers/Admin/ActivityLogController.php b/app/Http/Controllers/Admin/ActivityLogController.php index 2b0610948..25978a378 100644 --- a/app/Http/Controllers/Admin/ActivityLogController.php +++ b/app/Http/Controllers/Admin/ActivityLogController.php @@ -14,6 +14,7 @@ class ActivityLogController extends Controller { + const VIEW_PERMISSION = "admin.logs.read"; /** * Display a listing of the resource. * @@ -21,6 +22,9 @@ class ActivityLogController extends Controller */ public function index(Request $request) { + $this->checkPermission(self::VIEW_PERMISSION); + + $cronLogs = Storage::disk('logs')->exists('cron.log') ? Storage::disk('logs')->get('cron.log') : null; if ($request->input('search')) { diff --git a/app/Http/Controllers/Admin/ApplicationApiController.php b/app/Http/Controllers/Admin/ApplicationApiController.php index b71689392..f53a4fb42 100644 --- a/app/Http/Controllers/Admin/ApplicationApiController.php +++ b/app/Http/Controllers/Admin/ApplicationApiController.php @@ -4,6 +4,7 @@ use App\Http\Controllers\Controller; use App\Models\ApplicationApi; +use App\Settings\LocaleSettings; use Exception; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; @@ -15,14 +16,20 @@ class ApplicationApiController extends Controller { + const READ_PERMISSION = "admin.api.read"; + const WRITE_PERMISSION = "admin.api.write"; /** * Display a listing of the resource. * * @return Application|Factory|View|Response */ - public function index() + public function index(LocaleSettings $locale_settings) { - return view('admin.api.index'); + $this->checkAnyPermission([self::READ_PERMISSION,self::WRITE_PERMISSION]); + + return view('admin.api.index', [ + 'locale_datatables' => $locale_settings->datatables + ]); } /** @@ -32,6 +39,8 @@ public function index() */ public function create() { + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.api.create'); } @@ -73,6 +82,7 @@ public function show(ApplicationApi $applicationApi) */ public function edit(ApplicationApi $applicationApi) { + $this->checkPermission(self::WRITE_PERMISSION); return view('admin.api.edit', [ 'applicationApi' => $applicationApi, ]); @@ -104,6 +114,8 @@ public function update(Request $request, ApplicationApi $applicationApi) */ public function destroy(ApplicationApi $applicationApi) { + $this->checkPermission(self::WRITE_PERMISSION); + $applicationApi->delete(); return redirect()->back()->with('success', __('api key has been removed!')); diff --git a/app/Http/Controllers/Admin/CouponController.php b/app/Http/Controllers/Admin/CouponController.php new file mode 100644 index 000000000..d7d796b20 --- /dev/null +++ b/app/Http/Controllers/Admin/CouponController.php @@ -0,0 +1,242 @@ +checkAnyPermission([self::WRITE_PERMISSION,self::READ_PERMISSION]); + + return view('admin.coupons.index', [ + 'locale_datatables' => $localeSettings->datatables + ]); + } + + /** + * Show the form for creating a new resource. + * + * @return \Illuminate\Http\Response + */ + public function create() + { + $this->checkPermission(self::WRITE_PERMISSION); + + return view('admin.coupons.create'); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + $coupon_code = $request->input('code'); + $random_codes_amount = $request->input('range_codes'); + $rules = $this->requestRules($request); + + // If for some reason you pass both fields at once. + if ($coupon_code && $random_codes_amount) { + return redirect()->back()->with('error', __('Only one of the two code inputs must be provided.'))->withInput($request->all()); + } + + if (!$coupon_code && !$random_codes_amount) { + return redirect()->back()->with('error', __('At least one of the two code inputs must be provided.'))->withInput($request->all()); + } + + $request->validate($rules); + + if (array_key_exists('range_codes', $rules)) { + $data = []; + $coupons = Coupon::generateRandomCoupon($random_codes_amount); + + // Scroll through all the randomly generated coupons. + foreach ($coupons as $coupon) { + $data[] = [ + 'code' => $coupon, + 'type' => $request->input('type'), + 'value' => $request->input('value'), + 'max_uses' => $request->input('max_uses'), + 'expires_at' => $request->input('expires_at'), + 'created_at' => Carbon::now(), // Does not fill in by itself when using the 'insert' method. + 'updated_at' => Carbon::now() + ]; + } + Coupon::insert($data); + } else { + Coupon::create($request->except('_token')); + } + + return redirect()->route('admin.coupons.index')->with('success', __("The coupon's was registered successfully.")); + } + + /** + * Display the specified resource. + * + * @param \App\Models\Coupon $coupon + * @return \Illuminate\Http\Response + */ + public function show(Coupon $coupon) + { + // + } + + /** + * Show the form for editing the specified resource. + * + * @param \App\Models\Coupon $coupon + * @return \Illuminate\Http\Response + */ + public function edit(Coupon $coupon) + { + $this->checkPermission(self::WRITE_PERMISSION); + + return view('admin.coupons.edit', [ + 'coupon' => $coupon, + 'expired_at' => $coupon->expires_at ? Carbon::createFromTimestamp($coupon->expires_at) : null + ]); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param \App\Models\Coupon $coupon + * @return \Illuminate\Http\Response + */ + public function update(Request $request, Coupon $coupon) + { + $coupon_code = $request->input('code'); + $random_codes_amount = $request->input('range_codes'); + $rules = $this->requestRules($request); + + // If for some reason you pass both fields at once. + if ($coupon_code && $random_codes_amount) { + return redirect()->back()->with('error', __('Only one of the two code inputs must be provided.'))->withInput($request->all()); + } + + if (!$coupon_code && !$random_codes_amount) { + return redirect()->back()->with('error', __('At least one of the two code inputs must be provided.'))->withInput($request->all()); + } + + $request->validate($rules); + $coupon->update($request->except('_token')); + + return redirect()->route('admin.coupons.index')->with('success', __('coupon has been updated!')); + } + + /** + * Remove the specified resource from storage. + * + * @param \App\Models\Coupon $coupon + * @return \Illuminate\Http\Response + */ + public function destroy(Coupon $coupon) + { + $this->checkPermission(self::WRITE_PERMISSION); + $coupon->delete(); + + return redirect()->back()->with('success', __('coupon has been removed!')); + } + + private function requestRules(Request $request) + { + $coupon_code = $request->input('code'); + $random_codes_amount = $request->input('range_codes'); + $rules = [ + "type" => "required|string|in:percentage,amount", + "max_uses" => "required|integer|digits_between:1,100", + "value" => "required|numeric|between:0,100", + "expires_at" => "nullable|date|after:" . Carbon::now()->format(Coupon::formatDate()) + ]; + + if ($coupon_code) { + $rules['code'] = "required|string|min:4"; + } elseif ($random_codes_amount) { + $rules['range_codes'] = 'required|integer|digits_between:1,100'; + } + + return $rules; + } + + public function redeem(Request $request) + { + return $this->validateCoupon($request->user(), $request->input('couponCode'), $request->input('productId')); + } + + public function dataTable() + { + $query = Coupon::selectRaw(' + coupons.*, + CASE + WHEN coupons.uses >= coupons.max_uses THEN "USES_LIMIT_REACHED" + WHEN coupons.expires_at IS NOT NULL AND coupons.expires_at < NOW() THEN "EXPIRED" + ELSE "VALID" + END as derived_status + '); + + return datatables($query) + ->addColumn('actions', function(Coupon $coupon) { + return ' + + +
+ '.csrf_field().' + '.method_field('DELETE').' + +
+ '; + }) + ->addColumn('status', function (Coupon $coupon) { + $color = ($coupon->derived_status == 'VALID') ? 'success' : 'danger'; + $status = str_replace('_', ' ', $coupon->derived_status); + + return ''.$status.''; + }) + ->editColumn('uses', function (Coupon $coupon) { + return "{$coupon->uses} / {$coupon->max_uses}"; + }) + ->editColumn('value', function (Coupon $coupon) { + if ($coupon->type === 'percentage') { + return $coupon->value . "%"; + } + + return number_format($coupon->value, 2, '.', ''); + }) + ->editColumn('expires_at', function (Coupon $coupon) { + if (!$coupon->expires_at) { + return __('Never'); + } + + return Carbon::createFromTimestamp($coupon->expires_at); + }) + ->editColumn('created_at', function(Coupon $coupon) { + return Carbon::createFromTimeString($coupon->created_at); + }) + ->editColumn('code', function (Coupon $coupon) { + return "{$coupon->code}"; + }) + ->orderColumn('status', 'derived_status $1') + ->rawColumns(['actions', 'code', 'status']) + ->make(); + } +} diff --git a/app/Http/Controllers/Admin/LegalController.php b/app/Http/Controllers/Admin/LegalController.php index 0eafca573..2f101e356 100644 --- a/app/Http/Controllers/Admin/LegalController.php +++ b/app/Http/Controllers/Admin/LegalController.php @@ -10,6 +10,8 @@ class LegalController extends Controller { + const READ_PERMISSION = "admin.legal.read"; + const WRITE_PERMISSION = "admin.legal.write"; /** * Display * @@ -17,6 +19,8 @@ class LegalController extends Controller */ public function index() { + $this->checkAnyPermission([self::READ_PERMISSION,self::WRITE_PERMISSION]); + $tos = File::get(Theme::path($path = 'views', "default") . '/information/tos-content.blade.php'); $privacy = File::get(Theme::path($path = 'views', "default") . '/information/privacy-content.blade.php'); $imprint = File::get(Theme::path($path = 'views', "default") . '/information/imprint-content.blade.php'); @@ -29,6 +33,8 @@ public function index() } public function update(Request $request){ + $this->checkPermission(self::WRITE_PERMISSION); + $tos = $request->tos; $privacy = $request->privacy; $imprint = $request->imprint; diff --git a/app/Http/Controllers/Admin/OverViewController.php b/app/Http/Controllers/Admin/OverViewController.php index 280b59d4c..6d9ebab80 100644 --- a/app/Http/Controllers/Admin/OverViewController.php +++ b/app/Http/Controllers/Admin/OverViewController.php @@ -2,12 +2,14 @@ namespace App\Http\Controllers\Admin; -use App\Classes\Pterodactyl; +use App\Classes\PterodactylClient; +use App\Settings\PterodactylSettings; +use App\Settings\GeneralSettings; use App\Http\Controllers\Controller; -use App\Models\Egg; -use App\Models\Location; -use App\Models\Nest; -use App\Models\Node; +use App\Models\Pterodactyl\Egg; +use App\Models\Pterodactyl\Location; +use App\Models\Pterodactyl\Nest; +use App\Models\Pterodactyl\Node; use App\Models\Payment; use App\Models\Product; use App\Models\Server; @@ -17,15 +19,28 @@ class OverViewController extends Controller { + const READ_PERMISSION = "admin.overview.read"; + const SYNC_PERMISSION = "admin.overview.sync"; public const TTL = 86400; - public function index() + private $pterodactyl; + + public function __construct(PterodactylSettings $ptero_settings) + { + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + + public function index(GeneralSettings $general_settings) { + $this->checkAnyPermission([self::READ_PERMISSION,self::SYNC_PERMISSION]); + //Get counters $counters = collect(); //Set basic variables in the collection - $counters->put('users', User::query()->count()); - $counters->put('credits', number_format(User::query()->where('role', '!=', 'admin')->sum('credits'), 2, '.', '')); + $counters->put('users', collect()); + $counters['users']->active = User::where("suspended", 0)->count(); + $counters['users']->total = User::query()->count(); + $counters->put('credits', number_format(User::query()->whereHas("roles", function($q){ $q->where("id", "!=", "1"); })->sum('credits'), 2, '.', '')); $counters->put('payments', Payment::query()->count()); $counters->put('eggs', Egg::query()->count()); $counters->put('nests', Nest::query()->count()); @@ -134,7 +149,7 @@ public function index() //Get node information and prepare collection $pteroNodeIds = []; - foreach (Pterodactyl::getNodes() as $pteroNode) { + foreach ($this->pterodactyl->getNodes() as $pteroNode) { array_push($pteroNodeIds, $pteroNode['attributes']['id']); } $nodes = collect(); @@ -145,7 +160,7 @@ public function index() } //Check if node exists on pterodactyl too, if not, skip $nodes->put($nodeId, collect()); $nodes[$nodeId]->name = $DBnode['name']; - $pteroNode = Pterodactyl::getNode($nodeId); + $pteroNode = $this->pterodactyl->getNode($nodeId); $nodes[$nodeId]->usagePercent = round(max($pteroNode['allocated_resources']['memory'] / ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100), $pteroNode['allocated_resources']['disk'] / ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) * 100, 2); $counters['totalUsagePercent'] += $nodes[$nodeId]->usagePercent; @@ -156,11 +171,12 @@ public function index() } $counters['totalUsagePercent'] = ($DBnodes->count()) ? round($counters['totalUsagePercent'] / $DBnodes->count(), 2) : 0; - foreach (Pterodactyl::getServers() as $server) { //gets all servers from Pterodactyl and calculates total of credit usage for each node separately + total + foreach ($this->pterodactyl->getServers() as $server) { //gets all servers from Pterodactyl and calculates total of credit usage for each node separately + total $nodeId = $server['attributes']['node']; if ($CPServer = Server::query()->where('pterodactyl_id', $server['attributes']['id'])->first()) { - $price = Product::query()->where('id', $CPServer->product_id)->first()->price; + $product = Product::query()->where('id', $CPServer->product_id)->first(); + $price = $product->getMonthlyPrice(); if (! $CPServer->suspended) { $counters['earnings']->active += $price; $counters['servers']->active++; @@ -207,6 +223,7 @@ public function index() 'deletedNodesPresent' => ($DBnodes->count() != count($pteroNodeIds)) ? true : false, 'perPageLimit' => ($counters['servers']->total != Server::query()->count()) ? true : false, 'tickets' => $tickets, + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -215,6 +232,8 @@ public function index() */ public function syncPterodactyl() { + $this->checkPermission(self::SYNC_PERMISSION); + Node::syncNodes(); Egg::syncEggs(); diff --git a/app/Http/Controllers/Admin/PartnerController.php b/app/Http/Controllers/Admin/PartnerController.php index c91f592de..3b641c5f2 100644 --- a/app/Http/Controllers/Admin/PartnerController.php +++ b/app/Http/Controllers/Admin/PartnerController.php @@ -5,13 +5,21 @@ use App\Http\Controllers\Controller; use App\Models\PartnerDiscount; use App\Models\User; +use App\Settings\LocaleSettings; +use App\Settings\ReferralSettings; use Illuminate\Http\Request; class PartnerController extends Controller { - public function index() + const READ_PERMISSION = "admin.partners.read"; + const WRITE_PERMISSION = "admin.partners.write"; + public function index(LocaleSettings $locale_settings) { - return view('admin.partners.index'); + $this->checkAnyPermission([self::WRITE_PERMISSION,self::READ_PERMISSION]); + + return view('admin.partners.index', [ + 'locale_datatables' => $locale_settings->datatables + ]); } /** @@ -21,6 +29,8 @@ public function index() */ public function create() { + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.partners.create', [ 'partners' => PartnerDiscount::get(), 'users' => User::orderBy('name')->get(), @@ -58,6 +68,8 @@ public function store(Request $request) */ public function edit(PartnerDiscount $partner) { + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.partners.edit', [ 'partners' => PartnerDiscount::get(), 'partner' => $partner, @@ -94,6 +106,8 @@ public function update(Request $request, PartnerDiscount $partner) */ public function destroy(PartnerDiscount $partner) { + $this->checkPermission(self::WRITE_PERMISSION); + $partner->delete(); return redirect()->back()->with('success', __('partner has been removed!')); @@ -108,29 +122,30 @@ public function dataTable() return datatables($query) ->addColumn('actions', function (PartnerDiscount $partner) { return ' - +
'.csrf_field().' '.method_field('DELETE').' - +
'; }) ->addColumn('user', function (PartnerDiscount $partner) { - return ($user = User::where('id', $partner->user_id)->first()) ? ''.$user->name.'' : __('Unknown user'); + return ($user = User::where('id', $partner->user_id)->first()) ? '' . $user->name . '' : __('Unknown user'); }) ->editColumn('created_at', function (PartnerDiscount $partner) { return $partner->created_at ? $partner->created_at->diffForHumans() : ''; }) ->editColumn('partner_discount', function (PartnerDiscount $partner) { - return $partner->partner_discount ? $partner->partner_discount.'%' : '0%'; + return $partner->partner_discount ? $partner->partner_discount . '%' : '0%'; }) ->editColumn('registered_user_discount', function (PartnerDiscount $partner) { - return $partner->registered_user_discount ? $partner->registered_user_discount.'%' : '0%'; + return $partner->registered_user_discount ? $partner->registered_user_discount . '%' : '0%'; }) - ->editColumn('referral_system_commission', function (PartnerDiscount $partner) { - return $partner->referral_system_commission >= 0 ? $partner->referral_system_commission.'%' : __('Default').' ('.config('SETTINGS::REFERRAL:PERCENTAGE').'%)'; + ->editColumn('referral_system_commission', function (PartnerDiscount $partner, ReferralSettings $referral_settings) { + return $partner->referral_system_commission >= 0 ? $partner->referral_system_commission . '%' : __('Default') . ' ('.$referral_settings->percentage . '%)'; }) + ->orderColumn('user', 'user_id $1') ->rawColumns(['user', 'actions']) ->make(); } diff --git a/app/Http/Controllers/Admin/PaymentController.php b/app/Http/Controllers/Admin/PaymentController.php index 0cf2e3993..3d2da91e7 100644 --- a/app/Http/Controllers/Admin/PaymentController.php +++ b/app/Http/Controllers/Admin/PaymentController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Admin; +use App\Enums\PaymentStatus; +use App\Events\CouponUsedEvent; use App\Events\PaymentEvent; use App\Events\UserUpdateCreditsEvent; use App\Http\Controllers\Controller; @@ -9,6 +11,7 @@ use App\Models\Payment; use App\Models\User; use App\Models\ShopProduct; +use App\Traits\Coupon as CouponTrait; use Exception; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; @@ -18,17 +21,29 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use App\Helpers\ExtensionHelper; - +use App\Settings\CouponSettings; +use App\Settings\GeneralSettings; +use App\Settings\LocaleSettings; +use Illuminate\Support\Facades\Log; class PaymentController extends Controller { + const BUY_PERMISSION = 'user.shop.buy'; + const VIEW_PERMISSION = "admin.payments.read"; + + use CouponTrait; + /** * @return Application|Factory|View */ - public function index() + public function index(LocaleSettings $locale_settings) { + $this->checkPermission(self::VIEW_PERMISSION); + + return view('admin.payments.index')->with([ 'payments' => Payment::paginate(15), + 'locale_datatables' => $locale_settings->datatables ]); } @@ -37,8 +52,10 @@ public function index() * @param ShopProduct $shopProduct * @return Application|Factory|View */ - public function checkOut(ShopProduct $shopProduct) + public function checkOut(ShopProduct $shopProduct, GeneralSettings $general_settings, CouponSettings $coupon_settings) { + $this->checkPermission(self::BUY_PERMISSION); + $discount = PartnerDiscount::getDiscount(); $price = $shopProduct->price - ($shopProduct->price * $discount / 100); @@ -49,7 +66,10 @@ public function checkOut(ShopProduct $shopProduct) // build a paymentgateways array that contains the routes for the payment gateways and the image path for the payment gateway which lays in public/images/Extensions/PaymentGateways with the extensionname in lowercase foreach ($extensions as $extension) { $extensionName = basename($extension); - if (!ExtensionHelper::getExtensionConfig($extensionName, 'enabled')) continue; // skip if not enabled + + $extensionSettings = ExtensionHelper::getExtensionSettings($extensionName); + if ($extensionSettings->enabled == false) continue; + $payment = new \stdClass(); $payment->name = ExtensionHelper::getExtensionConfig($extensionName, 'name'); @@ -58,11 +78,6 @@ public function checkOut(ShopProduct $shopProduct) } } - - - - - return view('store.checkout')->with([ 'product' => $shopProduct, 'discountpercent' => $discount, @@ -73,6 +88,8 @@ public function checkOut(ShopProduct $shopProduct) 'total' => $shopProduct->getTotalPrice(), 'paymentGateways' => $paymentGateways, 'productIsFree' => $price <= 0, + 'credits_display_name' => $general_settings->credits_display_name, + 'isCouponsEnabled' => $coupon_settings->enabled, ]); } @@ -92,7 +109,7 @@ public function handleFreeProduct(ShopProduct $shopProduct) 'payment_id' => uniqid(), 'payment_method' => 'free', 'type' => $shopProduct->type, - 'status' => 'paid', + 'status' => PaymentStatus::PAID, 'amount' => $shopProduct->quantity, 'price' => $shopProduct->price - ($shopProduct->price * PartnerDiscount::getDiscount() / 100), 'tax_value' => $shopProduct->getTaxValue(), @@ -113,16 +130,68 @@ public function handleFreeProduct(ShopProduct $shopProduct) public function pay(Request $request) { - $product = ShopProduct::find($request->product_id); - $paymentGateway = $request->payment_method; + try { + $user = Auth::user(); + $user = User::findOrFail($user->id); + $productId = $request->product_id; + $shopProduct = ShopProduct::findOrFail($productId); + $discount = PartnerDiscount::getDiscount(); + + + $paymentGateway = $request->payment_method; + $couponCode = $request->coupon_code; + + $subtotal = $shopProduct->getTotalPrice(); + + // Apply Coupon + if ($couponCode) { + if ($this->isCouponValid($couponCode, $user, $shopProduct->id)) { + $subtotal = $this->applyCoupon($couponCode, $subtotal); + event(new CouponUsedEvent($couponCode)); - // on free products, we don't need to use a payment gateway - $realPrice = $product->price - ($product->price * PartnerDiscount::getDiscount() / 100); - if ($realPrice <= 0) { - return $this->handleFreeProduct($product); + } + } + + // Apply Partner Discount + $subtotal = $subtotal - ($subtotal * $discount / 100); + if ($subtotal <= 0) { + if ($couponCode) { + event(new CouponUsedEvent($couponCode)); + + } + + return $this->handleFreeProduct($shopProduct); + } + // Format the total price to a readable string + $totalPriceString = number_format($subtotal, 2, '.', ''); + //reset the price after coupon use + $shopProduct->price = $totalPriceString; + + // create a new payment + $payment = Payment::create([ + 'user_id' => $user->id, + 'payment_id' => null, + 'payment_method' => $paymentGateway, + 'type' => $shopProduct->type, + 'status' => 'open', + 'amount' => $shopProduct->quantity, + 'price' => $shopProduct->price, + 'tax_value' => $shopProduct->getTaxValue(), + 'tax_percent' => $shopProduct->getTaxPercent(), + 'total_price' => $totalPriceString, + 'currency_code' => $shopProduct->currency_code, + 'shop_item_product_id' => $shopProduct->id, + ]); + + $paymentGatewayExtension = ExtensionHelper::getExtensionClass($paymentGateway); + $redirectUrl = $paymentGatewayExtension::getRedirectUrl($payment, $shopProduct, $totalPriceString); + + } catch (Exception $e) { + Log::error($e->getMessage()); + return redirect()->route('store.index')->with('error', __('Oops, something went wrong! Please try again later.')); } - return redirect()->route('payment.' . $paymentGateway . 'Pay', ['shopProduct' => $product->id]); + return redirect()->away($redirectUrl); } /** diff --git a/app/Http/Controllers/Admin/ProductController.php b/app/Http/Controllers/Admin/ProductController.php index 5e9157d9f..2778dd6f5 100644 --- a/app/Http/Controllers/Admin/ProductController.php +++ b/app/Http/Controllers/Admin/ProductController.php @@ -3,9 +3,12 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; -use App\Models\Location; -use App\Models\Nest; +use App\Models\Pterodactyl\Location; +use App\Models\Pterodactyl\Nest; use App\Models\Product; +use App\Settings\GeneralSettings; +use App\Settings\LocaleSettings; +use App\Settings\UserSettings; use Exception; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; @@ -16,14 +19,24 @@ class ProductController extends Controller { + const READ_PERMISSION = "admin.products.read"; + + const WRITE_PERMISSION = "admin.products.create"; + const EDIT_PERMISSION = "admin.products.edit"; + const DELETE_PERMISSION = "admin.products.delete"; /** * Display a listing of the resource. * * @return Application|Factory|View */ - public function index() + public function index(LocaleSettings $locale_settings) { - return view('admin.products.index'); + $allConstants = (new \ReflectionClass(__CLASS__))->getConstants(); + $this->checkAnyPermission($allConstants); + + return view('admin.products.index', [ + 'locale_datatables' => $locale_settings->datatables + ]); } /** @@ -31,18 +44,23 @@ public function index() * * @return Application|Factory|View */ - public function create() + public function create(GeneralSettings $general_settings) { + $this->checkPermission(self::WRITE_PERMISSION); return view('admin.products.create', [ 'locations' => Location::with('nodes')->get(), 'nests' => Nest::with('eggs')->get(), + 'credits_display_name' => $general_settings->credits_display_name ]); } - public function clone(Request $request, Product $product) + public function clone(Product $product, GeneralSettings $general_settings) { + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.products.create', [ 'product' => $product, + 'credits_display_name' => $general_settings->credits_display_name, 'locations' => Location::with('nodes')->get(), 'nests' => Nest::with('eggs')->get(), ]); @@ -72,10 +90,14 @@ public function store(Request $request) 'nodes.*' => 'required|exists:nodes,id', 'eggs.*' => 'required|exists:eggs,id', 'disabled' => 'nullable', + 'oom_killer' => 'nullable', + 'billing_period' => 'required|in:hourly,daily,weekly,monthly,quarterly,half-annually,annually', ]); + $disabled = ! is_null($request->input('disabled')); - $product = Product::create(array_merge($request->all(), ['disabled' => $disabled])); + $oomkiller = ! is_null($request->input('oom_killer')); + $product = Product::create(array_merge($request->all(), ['disabled' => $disabled, 'oom_killer' => $oomkiller])); //link nodes and eggs $product->eggs()->attach($request->input('eggs')); @@ -90,11 +112,14 @@ public function store(Request $request) * @param Product $product * @return Application|Factory|View */ - public function show(Product $product) + public function show(Product $product, UserSettings $user_settings, GeneralSettings $general_settings) { + $this->checkAnyPermission([self::READ_PERMISSION,self::WRITE_PERMISSION]); + return view('admin.products.show', [ 'product' => $product, - 'minimum_credits' => config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER'), + 'minimum_credits' => $user_settings->min_credits_to_make_server, + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -104,12 +129,15 @@ public function show(Product $product) * @param Product $product * @return Application|Factory|View */ - public function edit(Product $product) + public function edit(Product $product, GeneralSettings $general_settings) { + $this->checkPermission(self::EDIT_PERMISSION); + return view('admin.products.edit', [ 'product' => $product, 'locations' => Location::with('nodes')->get(), 'nests' => Nest::with('eggs')->get(), + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -138,10 +166,13 @@ public function update(Request $request, Product $product): RedirectResponse 'nodes.*' => 'required|exists:nodes,id', 'eggs.*' => 'required|exists:eggs,id', 'disabled' => 'nullable', + 'oom_killer' => 'nullable', + 'billing_period' => 'required|in:hourly,daily,weekly,monthly,quarterly,half-annually,annually', ]); $disabled = ! is_null($request->input('disabled')); - $product->update(array_merge($request->all(), ['disabled' => $disabled])); + $oomkiller = ! is_null($request->input('oom_killer')); + $product->update(array_merge($request->all(), ['disabled' => $disabled, 'oom_killer' => $oomkiller])); //link nodes and eggs $product->eggs()->detach(); @@ -157,8 +188,10 @@ public function update(Request $request, Product $product): RedirectResponse * @param Product $product * @return RedirectResponse */ - public function disable(Request $request, Product $product) + public function disable(Product $product) { + $this->checkPermission(self::WRITE_PERMISSION); + $product->update(['disabled' => ! $product->disabled]); return redirect()->route('admin.products.index')->with('success', 'Product has been updated!'); @@ -172,6 +205,8 @@ public function disable(Request $request, Product $product) */ public function destroy(Product $product) { + $this->checkPermission(self::DELETE_PERMISSION); + $servers = $product->servers()->count(); if ($servers > 0) { return redirect()->back()->with('error', "Product cannot be removed while it's linked to {$servers} servers"); @@ -194,14 +229,14 @@ public function dataTable() return datatables($query) ->addColumn('actions', function (Product $product) { return ' - - - + + +
'.csrf_field().' '.method_field('DELETE').' - +
'; }) @@ -215,22 +250,25 @@ public function dataTable() ->addColumn('eggs', function (Product $product) { return $product->eggs()->count(); }) - ->addColumn('disabled', function (Product $product) { + ->editColumn('disabled', function (Product $product) { $checked = $product->disabled == false ? 'checked' : ''; return ' -
- '.csrf_field().' - '.method_field('PATCH').' -
- - -
-
+
+ '.csrf_field().' + '.method_field('PATCH').' +
+ + +
+
'; }) - ->editColumn('minimum_credits', function (Product $product) { - return $product->minimum_credits==-1 ? config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') : $product->minimum_credits; + ->editColumn('minimum_credits', function (Product $product, UserSettings $user_settings) { + return $product->minimum_credits==-1 ? $user_settings->min_credits_to_make_server : $product->minimum_credits; + }) + ->editColumn('oom_killer', function (Product $product) { + return $product->oom_killer ? __("enabled") : __("disabled"); }) ->editColumn('created_at', function (Product $product) { return $product->created_at ? $product->created_at->diffForHumans() : ''; diff --git a/app/Http/Controllers/Admin/RoleController.php b/app/Http/Controllers/Admin/RoleController.php new file mode 100644 index 000000000..0d09c5d5f --- /dev/null +++ b/app/Http/Controllers/Admin/RoleController.php @@ -0,0 +1,223 @@ +getConstants(); + $this->checkAnyPermission($allConstants); + + //datatables + if ($request->ajax()) { + return $this->dataTableQuery(); + } + + $html = $this->dataTable(); + return view('admin.roles.index', compact('html')); + } + + /** + * Show the form for creating a new resource. + * + * @return Application|Factory|View + */ + public function create() + { + $this->checkPermission(self::CREATE_PERMISSION); + + $permissions = Permission::all(); + + return view('admin.roles.edit', compact('permissions')); + } + + /** + * Store a newly created resource in storage. + * + * @return RedirectResponse + */ + public function store(Request $request): RedirectResponse + { + $this->checkPermission(self::CREATE_PERMISSION); + + $role = Role::create([ + 'name' => $request->name, + 'color' => $request->color, + 'power' => $request->power + ]); + + if ($request->permissions) { + $collectedPermissions = collect($request->permissions)->map(fn($val)=>(int)$val); + $role->givePermissionTo($collectedPermissions); + } + + return redirect() + ->route('admin.roles.index') + ->with('success', __('Role saved')); + } + + /** + * Display the specified resource. + */ + public function show() + { + abort(404); + } + + /** + * Show the form for editing the specified resource. + * + * @param Role $role + * @return Application|Factory|View + */ + public function edit(Role $role) + { + $this->checkPermission(self::EDIT_PERMISSION); + + if(Auth::user()->roles[0]->power < $role->power){ + return back()->with("error","You dont have enough Power to edit that Role"); + } + + $permissions = Permission::all(); + + return view('admin.roles.edit', compact('role', 'permissions')); + } + + /** + * Update the specified resource in storage. + * + * @param Role $role + * @return RedirectResponse + */ + public function update(Request $request, Role $role) + { + $this->checkPermission(self::EDIT_PERMISSION); + + if(Auth::user()->roles[0]->power < $role->power){ + return back()->with("error","You dont have enough Power to edit that Role"); + } + + if ($request->permissions) { + if($role->id != 1){ //disable admin permissions change + $collectedPermissions = collect($request->permissions)->map(fn($val)=>(int)$val); + $role->syncPermissions($collectedPermissions); + } + } + + //if($role->id == 1 || $role->id == 3 || $role->id == 4){ //dont let the user change the names of these roles + // $role->update([ + // 'color' => $request->color + // ]); + //}else{ + $role->update([ + 'name' => $request->name, + 'color' => $request->color, + 'power' => $request->power + ]); + //} + + //if($role->id == 1){ + // return redirect()->route('admin.roles.index')->with('success', __('Role updated. Name and Permissions of this Role cannot be changed')); + //}elseif($role->id == 4 || $role->id == 3){ + // return redirect()->route('admin.roles.index')->with('success', __('Role updated. Name of this Role cannot be changed')); + // }else{ + return redirect() + ->route('admin.roles.index') + ->with('success', __('Role saved')); + //} + } + + /** + * Remove the specified resource from storage. + * + * @return RedirectResponse + */ + public function destroy(Role $role) + { + $this->checkPermission(self::DELETE_PERMISSION); + + if($role->id == 1 || $role->id == 3 || $role->id == 4){ //cannot delete the hard coded roles + return back()->with("error","You cannot delete that role"); + } + + $users = User::role($role)->get(); + + foreach($users as $user){ + //$user->syncRoles(['Member']); + $user->syncRoles(4); + } + + $role->delete(); + + return redirect() + ->route('admin.roles.index') + ->with('success', __('Role removed')); + } + + /** + * @return mixed + * @throws Exception + */ + public function dataTable() + { + $query = Role::query()->withCount(['users', 'permissions'])->get(); + + return datatables($query) + ->editColumn('id', function (Role $role) { + return $role->id; + }) + ->addColumn('actions', function (Role $role) { + return ' + +
+ ' . csrf_field() . ' + ' . method_field("DELETE") . ' + +
+ '; + }) + + ->editColumn('name', function (Role $role) { + return "$role->name"; + }) + ->editColumn('users_count', function ($query) { + return $query->users_count; + }) + ->editColumn('permissions_count', function ($query){ + return $query->permissions_count; + }) + ->editColumn('power', function (Role $role){ + return $role->power; + }) + ->rawColumns(['actions', 'name']) + ->make(true); + } +} diff --git a/app/Http/Controllers/Admin/ServerController.php b/app/Http/Controllers/Admin/ServerController.php index c10634711..4d83d39c8 100644 --- a/app/Http/Controllers/Admin/ServerController.php +++ b/app/Http/Controllers/Admin/ServerController.php @@ -2,10 +2,13 @@ namespace App\Http\Controllers\Admin; -use App\Classes\Pterodactyl; use App\Http\Controllers\Controller; use App\Models\Server; use App\Models\User; +use App\Settings\DiscordSettings; +use App\Settings\LocaleSettings; +use App\Settings\PterodactylSettings; +use App\Classes\PterodactylClient; use Exception; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; @@ -18,14 +21,33 @@ class ServerController extends Controller { + + const READ_PERMISSION = "admin.servers.read"; + const WRITE_PERMISSION = "admin.servers.write"; + const SUSPEND_PERMISSION = "admin.servers.suspend"; + const CHANGEOWNER_PERMISSION = "admin.servers.write.owner"; + const CHANGE_IDENTIFIER_PERMISSION = "admin.servers.write.identifier"; + const DELETE_PERMISSION = "admin.servers.delete"; + private $pterodactyl; + + public function __construct(PterodactylSettings $ptero_settings) + { + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + /** * Display a listing of the resource. * * @return Application|Factory|View|Response */ - public function index() + public function index(LocaleSettings $locale_settings) { - return view('admin.servers.index'); + $allConstants = (new \ReflectionClass(__CLASS__))->getConstants(); + $this->checkAnyPermission($allConstants); + + return view('admin.servers.index', [ + 'locale_datatables' => $locale_settings->datatables + ]); } /** @@ -36,6 +58,10 @@ public function index() */ public function edit(Server $server) { + $allConstants = (new \ReflectionClass(__CLASS__))->getConstants(); + $permissions = array_filter($allConstants, fn($key) => str_starts_with($key, 'admin.servers.write')); + $this->checkAnyPermission($permissions); + // get all users from the database $users = User::all(); @@ -51,7 +77,7 @@ public function edit(Server $server) * @param Request $request * @param Server $server */ - public function update(Request $request, Server $server) + public function update(Request $request, Server $server, DiscordSettings $discord_settings) { $request->validate([ 'identifier' => 'required|string', @@ -59,26 +85,50 @@ public function update(Request $request, Server $server) ]); - if ($request->get('user_id') != $server->user_id) { + if ($request->get('user_id') != $server->user_id && $this->can(self::CHANGEOWNER_PERMISSION)) { // find the user $user = User::findOrFail($request->get('user_id')); // try to update the owner on pterodactyl try { - $response = Pterodactyl::updateServerOwner($server, $user->pterodactyl_id); + $response = $this->pterodactyl->updateServerOwner($server, $user->pterodactyl_id); if ($response->getStatusCode() != 200) { return redirect()->back()->with('error', 'Failed to update server owner on pterodactyl'); } + // Attempt to remove/add roles respectively + try { + if($discord_settings->role_on_purchase) { + // remove the role from the old owner + $oldOwner = User::findOrFail($server->user_id); + $discordUser = $oldOwner->discordUser; + if ($discordUser && $oldOwner->servers->count() <= 1) { + $discordUser->addOrRemoveRole('remove', $discord_settings->role_id_on_purchase); + } + + // add the role to the new owner + $discordUser = $user->discordUser; + if ($discordUser && $user->servers->count() >= 1) { + $discordUser->addOrRemoveRole('add', $discord_settings->role_id_on_purchase); + } + } + } catch (Exception $e) { + log::debug('Failed to update discord roles' . $e->getMessage()); + } + // update the owner on the database $server->user_id = $user->id; + } catch (Exception $e) { return redirect()->back()->with('error', 'Internal Server Error'); } } // update the identifier - $server->identifier = $request->get('identifier'); + if ($this->can(self::CHANGE_IDENTIFIER_PERMISSION)) { + + $server->identifier = $request->get('identifier'); + } $server->save(); return redirect()->route('admin.servers.index')->with('success', 'Server updated!'); @@ -90,9 +140,24 @@ public function update(Request $request, Server $server) * @param Server $server * @return RedirectResponse|Response */ - public function destroy(Server $server) + public function destroy(Server $server, DiscordSettings $discord_settings) { + $this->checkPermission(self::DELETE_PERMISSION); try { + // Remove role from discord + try { + if($discord_settings->role_on_purchase) { + $user = User::findOrFail($server->user_id); + $discordUser = $user->discordUser; + if($discordUser && $user->servers->count() <= 1) { + $discordUser->addOrRemoveRole('remove', $discord_settings->role_id_on_purchase); + } + } + } catch (Exception $e) { + log::debug('Failed to update discord roles' . $e->getMessage()); + } + + // Attempt to remove the server from pterodactyl $server->delete(); return redirect()->route('admin.servers.index')->with('success', __('Server removed')); @@ -102,11 +167,31 @@ public function destroy(Server $server) } /** - * @param Server $server + * Cancel the Server billing cycle. + * + * @param Server $server + * @return RedirectResponse|Response + */ + public function cancel(Server $server) + { + try { + $server->update([ + 'canceled' => now(), + ]); + return redirect()->route('servers.index')->with('success', __('Server canceled')); + } catch (Exception $e) { + return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to cancel the server"') . $e->getMessage() . '"'); + } + } + + /** + * @param Server $server * @return RedirectResponse */ public function toggleSuspended(Server $server) { + $this->checkPermission(self::SUSPEND_PERMISSION); + try { $server->isSuspended() ? $server->unSuspend() : $server->suspend(); } catch (Exception $exception) { @@ -118,7 +203,6 @@ public function toggleSuspended(Server $server) public function syncServers() { - $pteroServers = Pterodactyl::getServers(); $CPServers = Server::get(); $CPIDArray = []; @@ -129,7 +213,7 @@ public function syncServers() } } - foreach ($pteroServers as $server) { //go thru all ptero servers, if server exists, change value to true in array. + foreach ($this->pterodactyl->getServers() as $server) { //go thru all ptero servers, if server exists, change value to true in array. if (isset($CPIDArray[$server['attributes']['id']])) { $CPIDArray[$server['attributes']['id']] = true; @@ -149,7 +233,7 @@ public function syncServers() }, ARRAY_FILTER_USE_BOTH); //Array of servers, that dont exist on ptero (value == false) $deleteCount = 0; foreach ($filteredArray as $key => $CPID) { //delete servers that dont exist on ptero anymore - if (!Pterodactyl::getServerAttributes($key, true)) { + if (!$this->pterodactyl->getServerAttributes($key, true)) { $deleteCount++; } } @@ -183,7 +267,7 @@ public function dataTable(Request $request) return '' . $server->user->name . ''; }) ->addColumn('resources', function (Server $server) { - return $server->product->description; + return $server->product->name; }) ->addColumn('actions', function (Server $server) { $suspendColor = $server->isSuspended() ? 'btn-success' : 'btn-warning'; @@ -216,8 +300,8 @@ public function dataTable(Request $request) ->editColumn('suspended', function (Server $server) { return $server->suspended ? $server->suspended->diffForHumans() : ''; }) - ->editColumn('name', function (Server $server) { - return '' . strip_tags($server->name) . ''; + ->editColumn('name', function (Server $server, PterodactylSettings $ptero_settings) { + return '' . strip_tags($server->name) . ''; }) ->rawColumns(['user', 'actions', 'status', 'name']) ->make(); diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index d0f6d6cd8..3725801ff 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -2,15 +2,23 @@ namespace App\Http\Controllers\Admin; +use App\Helpers\ExtensionHelper; use App\Http\Controllers\Controller; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; use Illuminate\Http\Response; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Redirect; +use Illuminate\Support\Facades\Validator; use Qirolab\Theme\Theme; class SettingsController extends Controller { + const ICON_PERMISSION = "admin.icons.edit"; + + + /** * Display a listing of the resource. * @@ -20,36 +28,139 @@ public function index() { - //Get all tabs as laravel view paths - $tabs = []; - if(file_exists(Theme::getViewPaths()[0] . '/admin/settings/tabs/')){ - $tabspath = glob(Theme::getViewPaths()[0] . '/admin/settings/tabs/*.blade.php'); - }else{ - $tabspath = glob(Theme::path($path = 'views', $themeName = 'default').'/admin/settings/tabs/*.blade.php'); - } + // get all other settings in app/Settings directory + // group items by file name like $categories + $settings = collect(); + $settings_classes = []; - foreach ($tabspath as $filename) { - $tabs[] = 'admin.settings.tabs.'.basename($filename, '.blade.php'); + // get all app settings + $app_settings = scandir(app_path('Settings')); + $app_settings = array_diff($app_settings, ['.', '..']); + // append App\Settings to class name + foreach ($app_settings as $app_setting) { + $settings_classes[] = 'App\\Settings\\' . str_replace('.php', '', $app_setting); } + // get all extension settings + $settings_files = array_merge($settings_classes, ExtensionHelper::getAllExtensionSettingsClasses()); + + + foreach ($settings_files as $file) { + $className = $file; + // instantiate the class and call toArray method to get all options + $options = (new $className())->toArray(); - //Generate a html list item for each tab based on tabs file basename, set first tab as active - $tabListItems = []; - foreach ($tabs as $tab) { - $tabName = str_replace('admin.settings.tabs.', '', $tab); - $tabListItems[] = ''; + // call getOptionInputData method to get all options + if (method_exists($className, 'getOptionInputData')) { + $optionInputData = $className::getOptionInputData(); + } else { + $optionInputData = []; + } + + // collect all option input data + $optionsData = []; + foreach ($options as $key => $value) { + $optionsData[$key] = [ + 'value' => $value, + 'label' => $optionInputData[$key]['label'] ?? ucwords(str_replace('_', ' ', $key)), + 'type' => $optionInputData[$key]['type'] ?? 'string', + 'description' => $optionInputData[$key]['description'] ?? '', + 'options' => $optionInputData[$key]['options'] ?? [], + 'identifier' => $optionInputData[$key]['identifier'] ?? 'option' + ]; + } + + // collect category icon if available + if (isset($optionInputData['category_icon'])) { + $optionsData['category_icon'] = $optionInputData['category_icon']; + } + $optionsData['settings_class'] = $className; + + $settings[str_replace('Settings', '', class_basename($className))] = $optionsData; } + $settings->sort(); + + $themes = array_diff(scandir(base_path('themes')), array('..', '.')); return view('admin.settings.index', [ - 'tabs' => $tabs, - 'tabListItems' => $tabListItems, + 'settings' => $settings->all(), 'themes' => $themes, 'active_theme' => Theme::active(), ]); } + + /** + * Update the specified resource in storage. + * + */ + public function update(Request $request) + { + $category = request()->get('category'); + + $this->checkPermission("settings." . strtolower($category) . ".write"); + + $settings_class = (string) request()->get('settings_class'); + + if (method_exists($settings_class, 'getValidations')) { + $validations = $settings_class::getValidations(); + } else { + $validations = []; + } + + + $validator = Validator::make($request->all(), $validations); + if ($validator->fails()) { + return Redirect::to('admin/settings' . '#' . $category)->withErrors($validator)->withInput(); + } + + $settingsClass = new $settings_class(); + + foreach ($settingsClass->toArray() as $key => $value) { + // Get the type of the settingsclass property + $rp = new \ReflectionProperty($settingsClass, $key); + $rpType = $rp->getType(); + + if ($rpType == 'bool') { + $settingsClass->$key = $request->has($key); + continue; + } + if ($rp->name == 'available') { + $settingsClass->$key = implode(",", $request->$key); + continue; + } + + $nullable = $rpType->allowsNull(); + if ($nullable) $settingsClass->$key = $request->input($key) ?? null; + else $settingsClass->$key = $request->input($key); + } + $settingsClass->save(); + + + return Redirect::to('admin/settings' . '#' . $category)->with('success', 'Settings updated successfully.'); + } + + public function updateIcons(Request $request) + { + $this->checkPermission(self::ICON_PERMISSION); + + $request->validate([ + 'icon' => 'nullable|max:10000|mimes:jpg,png,jpeg', + 'logo' => 'nullable|max:10000|mimes:jpg,png,jpeg', + 'favicon' => 'nullable|max:10000|mimes:ico', + ]); + + if ($request->hasFile('icon')) { + $request->file('icon')->storeAs('public', 'icon.png'); + } + if ($request->hasFile('logo')) { + $request->file('logo')->storeAs('public', 'logo.png'); + } + if ($request->hasFile('favicon')) { + $request->file('favicon')->storeAs('public', 'favicon.ico'); + } + + return Redirect::to('admin/settings')->with('success', 'Icons updated successfully.'); + } } diff --git a/app/Http/Controllers/Admin/ShopProductController.php b/app/Http/Controllers/Admin/ShopProductController.php index 655636f90..4ed07ba3c 100644 --- a/app/Http/Controllers/Admin/ShopProductController.php +++ b/app/Http/Controllers/Admin/ShopProductController.php @@ -2,38 +2,40 @@ namespace App\Http\Controllers\Admin; +use App\Http\Controllers\Controller; use App\Models\ShopProduct; +use App\Settings\GeneralSettings; +use App\Settings\LocaleSettings; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; -use Illuminate\Routing\Controller; use Illuminate\Validation\Rule; class ShopProductController extends Controller { + const READ_PERMISSION = 'admin.store.read'; + const WRITE_PERMISSION = 'admin.store.write'; + const DISABLE_PERMISSION = 'admin.store.disable'; + /** * Display a listing of the resource. * * @return Application|Factory|View|Response */ - public function index(Request $request) + public function index(LocaleSettings $locale_settings, GeneralSettings $general_settings) { - $isPaymentSetup = false; + $this->checkAnyPermission([self::READ_PERMISSION, self::WRITE_PERMISSION]); + + $isStoreEnabled = $general_settings->store_enabled; - if ( - env('APP_ENV') == 'local' || - config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') || - config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:METHODS') - ) { - $isPaymentSetup = true; - } return view('admin.store.index', [ - 'isPaymentSetup' => $isPaymentSetup, + 'isStoreEnabled' => $isStoreEnabled, + 'locale_datatables' => $locale_settings->datatables ]); } @@ -42,10 +44,13 @@ public function index(Request $request) * * @return Application|Factory|View|Response */ - public function create() + public function create(GeneralSettings $general_settings) { + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.store.create', [ 'currencyCodes' => config('currency_codes'), + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -79,11 +84,14 @@ public function store(Request $request) * @param ShopProduct $shopProduct * @return Application|Factory|View|Response */ - public function edit(ShopProduct $shopProduct) + public function edit(ShopProduct $shopProduct, GeneralSettings $general_settings) { + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.store.edit', [ 'currencyCodes' => config('currency_codes'), 'shopProduct' => $shopProduct, + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -117,8 +125,10 @@ public function update(Request $request, ShopProduct $shopProduct) * @param ShopProduct $shopProduct * @return RedirectResponse */ - public function disable(Request $request, ShopProduct $shopProduct) + public function disable(ShopProduct $shopProduct) { + $this->checkPermission(self::DISABLE_PERMISSION); + $shopProduct->update(['disabled' => !$shopProduct->disabled]); return redirect()->route('admin.store.index')->with('success', __('Product has been updated!')); @@ -132,6 +142,7 @@ public function disable(Request $request, ShopProduct $shopProduct) */ public function destroy(ShopProduct $shopProduct) { + $this->checkPermission(self::WRITE_PERMISSION); $shopProduct->delete(); return redirect()->back()->with('success', __('Store item has been removed!')); @@ -145,16 +156,16 @@ public function dataTable(Request $request) return datatables($query) ->addColumn('actions', function (ShopProduct $shopProduct) { return ' - +
' . csrf_field() . ' ' . method_field('DELETE') . ' - +
'; }) - ->addColumn('disabled', function (ShopProduct $shopProduct) { + ->editColumn('disabled', function (ShopProduct $shopProduct) { $checked = $shopProduct->disabled == false ? 'checked' : ''; return ' diff --git a/app/Http/Controllers/Moderation/TicketCategoryController.php b/app/Http/Controllers/Admin/TicketCategoryController.php similarity index 81% rename from app/Http/Controllers/Moderation/TicketCategoryController.php rename to app/Http/Controllers/Admin/TicketCategoryController.php index 729e2f3c2..b0ae8e21b 100644 --- a/app/Http/Controllers/Moderation/TicketCategoryController.php +++ b/app/Http/Controllers/Admin/TicketCategoryController.php @@ -1,6 +1,6 @@ checkAnyPermission([self::READ_PERMISSION, self::WRITE_PERMISSION]); + $categories = TicketCategory::all(); - return view('moderator.ticket.category')->with("categories",$categories); + return view('admin.ticket.category')->with("categories",$categories); } /** @@ -28,6 +33,8 @@ public function index() */ public function store(Request $request) { + $this->checkPermission(self::WRITE_PERMISSION); + $request->validate([ 'name' => 'required|string|max:191', ]); @@ -35,7 +42,7 @@ public function store(Request $request) TicketCategory::create($request->all()); - return redirect(route("moderator.ticket.category.index"))->with("success",__("Category created")); + return redirect(route("admin.ticket.category.index"))->with("success",__("Category created")); } /** @@ -46,6 +53,8 @@ public function store(Request $request) */ public function update(Request $request) { + $this->checkPermission(self::WRITE_PERMISSION); + $request->validate([ 'category' => 'required|int', 'name' => 'required|string|max:191', @@ -68,6 +77,8 @@ public function update(Request $request) */ public function destroy($id) { + $this->checkPermission(self::WRITE_PERMISSION); + $category = TicketCategory::where("id",$id)->firstOrFail(); if($category->id == 5 ){ //cannot delete "other" category @@ -84,7 +95,7 @@ public function destroy($id) $category->delete(); return redirect() - ->route('moderator.ticket.category.index') + ->route('admin.ticket.category.index') ->with('success', __('Category removed')); } @@ -101,7 +112,7 @@ public function datatable() }) ->addColumn('actions', function (TicketCategory $category) { return ' -
+ '.csrf_field().' '.method_field('DELETE').' diff --git a/app/Http/Controllers/Moderation/TicketsController.php b/app/Http/Controllers/Admin/TicketsController.php similarity index 76% rename from app/Http/Controllers/Moderation/TicketsController.php rename to app/Http/Controllers/Admin/TicketsController.php index c927e6858..ec1d6578d 100644 --- a/app/Http/Controllers/Moderation/TicketsController.php +++ b/app/Http/Controllers/Admin/TicketsController.php @@ -1,8 +1,9 @@ paginate(10); - $ticketcategories = TicketCategory::all(); + $this->checkAnyPermission([self::READ_PERMISSION, self::WRITE_PERMISSION]); - return view('moderator.ticket.index', compact('tickets', 'ticketcategories')); + return view('admin.ticket.index', [ + 'tickets' => Ticket::orderBy('id', 'desc')->paginate(10), + 'ticketcategories' => TicketCategory::all(), + 'locale_datatables' => $locale_settings->datatables + ]); } - public function show($ticket_id) + public function show($ticket_id, PterodactylSettings $ptero_settings) { + $this->checkAnyPermission([self::READ_PERMISSION, self::WRITE_PERMISSION]); try { $ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail(); } catch (Exception $e) @@ -34,12 +46,14 @@ public function show($ticket_id) $ticketcomments = $ticket->ticketcomments; $ticketcategory = $ticket->ticketcategory; $server = Server::where('id', $ticket->server)->first(); + $pterodactyl_url = $ptero_settings->panel_url; - return view('moderator.ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server')); + return view('admin.ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server', 'pterodactyl_url')); } public function changeStatus($ticket_id) { + $this->checkPermission(self::WRITE_PERMISSION); try { $ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail(); } catch(Exception $e) @@ -61,6 +75,7 @@ public function changeStatus($ticket_id) public function delete($ticket_id) { + $this->checkPermission(self::WRITE_PERMISSION); try { $ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail(); } catch (Exception $e) @@ -76,6 +91,9 @@ public function delete($ticket_id) public function reply(Request $request) { + $this->checkPermission(self::WRITE_PERMISSION); + + $this->validate($request, ['ticketcomment' => 'required']); try { $ticket = Ticket::where('id', $request->input('ticket_id'))->firstOrFail(); @@ -103,14 +121,15 @@ public function reply(Request $request) public function dataTable() { - $query = Ticket::query(); + $query = Ticket::leftJoin('ticket_categories', 'tickets.ticketcategory_id', '=', 'ticket_categories.id') + ->select(['tickets.*', 'ticket_categories.name as category_name']); return datatables($query) - ->addColumn('category', function (Ticket $tickets) { - return $tickets->ticketcategory->name; + ->addColumn('category', function (Ticket $ticket) { + return $ticket->category_name; }) ->editColumn('title', function (Ticket $tickets) { - return ''.'#'.$tickets->ticket_id.' - '.htmlspecialchars($tickets->title).''; + return ''.'#'.$tickets->ticket_id.' - '.htmlspecialchars($tickets->title).''; }) ->editColumn('user_id', function (Ticket $tickets) { return ''.$tickets->user->name.''; @@ -121,16 +140,16 @@ public function dataTable() $statusButtonText = ($tickets->status == "Closed") ? __('Reopen') : __('Close'); return ' - - + + '.csrf_field().' '.method_field('POST').' - +
-
+ '.csrf_field().' '.method_field('POST').' - +
'; }) @@ -160,17 +179,24 @@ public function dataTable() return ['display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '', 'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : '']; }) - ->rawColumns(['category', 'title', 'user_id', 'status', 'priority', 'updated_at', 'actions']) + ->orderColumn('category', 'category_name $1') + ->rawColumns(['title', 'user_id', 'status', 'priority', 'updated_at', 'actions']) ->make(true); } - public function blacklist() + public function blacklist(LocaleSettings $locale_settings) { - return view('moderator.ticket.blacklist'); + $this->checkAnyPermission([self::BLACKLIST_READ_PERMISSION, self::BLACKLIST_WRITE_PERMISSION]); + + return view('admin.ticket.blacklist', [ + 'locale_datatables' => $locale_settings->datatables + ]); } public function blacklistAdd(Request $request) { + $this->checkPermission(self::BLACKLIST_WRITE_PERMISSION); + try { $user = User::where('id', $request->user_id)->firstOrFail(); $check = TicketBlacklist::where('user_id', $user->id)->first(); @@ -196,6 +222,8 @@ public function blacklistAdd(Request $request) public function blacklistDelete($id) { + $this->checkPermission(self::BLACKLIST_WRITE_PERMISSION); + $blacklist = TicketBlacklist::where('id', $id)->first(); $blacklist->delete(); @@ -204,6 +232,8 @@ public function blacklistDelete($id) public function blacklistChange($id) { + $this->checkPermission(self::BLACKLIST_WRITE_PERMISSION); + try { $blacklist = TicketBlacklist::where('id', $id)->first(); } @@ -248,15 +278,15 @@ public function dataTableBlacklist() }) ->addColumn('actions', function (TicketBlacklist $blacklist) { return ' -
+ '.csrf_field().' '.method_field('POST').' - +
-
+ '.csrf_field().' '.method_field('POST').' - +
'; }) diff --git a/app/Http/Controllers/Admin/UsefulLinkController.php b/app/Http/Controllers/Admin/UsefulLinkController.php index 79e6b4dae..55a62d684 100644 --- a/app/Http/Controllers/Admin/UsefulLinkController.php +++ b/app/Http/Controllers/Admin/UsefulLinkController.php @@ -5,6 +5,7 @@ use App\Enums\UsefulLinkLocation; use App\Http\Controllers\Controller; use App\Models\UsefulLink; +use App\Settings\LocaleSettings; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; @@ -14,14 +15,19 @@ class UsefulLinkController extends Controller { + const READ_PERMISSION = "admin.useful_links.read"; + const WRITE_PERMISSION = "admin.useful_links.write"; /** * Display a listing of the resource. * * @return Application|Factory|View|Response */ - public function index() + public function index(LocaleSettings $locale_settings) { - return view('admin.usefullinks.index'); + $this->checkAnyPermission([self::READ_PERMISSION, self::WRITE_PERMISSION]); + return view('admin.usefullinks.index', [ + 'locale_datatables' => $locale_settings->datatables + ]); } /** @@ -31,6 +37,7 @@ public function index() */ public function create() { + $this->checkPermission(self::WRITE_PERMISSION); $positions = UsefulLinkLocation::cases(); return view('admin.usefullinks.create')->with('positions', $positions); } @@ -81,6 +88,8 @@ public function show(UsefulLink $usefullink) */ public function edit(UsefulLink $usefullink) { + $this->checkPermission(self::WRITE_PERMISSION); + $positions = UsefulLinkLocation::cases(); return view('admin.usefullinks.edit', [ 'link' => $usefullink, @@ -123,6 +132,7 @@ public function update(Request $request, UsefulLink $usefullink) */ public function destroy(UsefulLink $usefullink) { + $this->checkPermission(self::WRITE_PERMISSION); $usefullink->delete(); return redirect()->back()->with('success', __('product has been removed!')); diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index 763490db1..cfa02b256 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -2,11 +2,14 @@ namespace App\Http\Controllers\Admin; -use App\Classes\Pterodactyl; use App\Events\UserUpdateCreditsEvent; use App\Http\Controllers\Controller; use App\Models\User; use App\Notifications\DynamicNotification; +use App\Settings\LocaleSettings; +use App\Settings\PterodactylSettings; +use App\Classes\PterodactylClient; +use App\Settings\GeneralSettings; use Exception; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; @@ -23,15 +26,32 @@ use Illuminate\Validation\Rule; use Illuminate\Validation\ValidationException; use Spatie\QueryBuilder\QueryBuilder; +use App\Models\Role; class UserController extends Controller { - - private Pterodactyl $pterodactyl; - - public function __construct(Pterodactyl $pterodactyl) + const READ_PERMISSION = "admin.users.read"; + const WRITE_PERMISSION = "admin.users.write"; + const SUSPEND_PERMISSION = "admin.users.suspend"; + const CHANGE_EMAIL_PERMISSION = "admin.users.write.email"; + const CHANGE_CREDITS_PERMISSION = "admin.users.write.credits"; + const CHANGE_USERNAME_PERMISSION = "admin.users.write.username"; + const CHANGE_PASSWORD_PERMISSION = "admin.users.write.password"; + const CHANGE_ROLE_PERMISSION ="admin.users.write.role"; + const CHANGE_REFERRAL_PERMISSION ="admin.users.write.referral"; + const CHANGE_PTERO_PERMISSION = "admin.users.write.pterodactyl"; + + const CHANGE_SERVERLIMIT_PERMISSION = "admin.users.write.serverlimit"; + const DELETE_PERMISSION = "admin.users.delete"; + const NOTIFY_PERMISSION = "admin.users.notify"; + const LOGIN_PERMISSION = "admin.users.login_as"; + + + private $pterodactyl; + + public function __construct(PterodactylSettings $ptero_settings) { - $this->pterodactyl = $pterodactyl; + $this->pterodactyl = new PterodactylClient($ptero_settings); } /** @@ -40,9 +60,17 @@ public function __construct(Pterodactyl $pterodactyl) * @param Request $request * @return Application|Factory|View|Response */ - public function index(Request $request) + public function index(LocaleSettings $locale_settings, GeneralSettings $general_settings) { - return view('admin.users.index'); + $allConstants = (new \ReflectionClass(__CLASS__))->getConstants(); + $this->checkAnyPermission($allConstants); + + //$this->checkPermission(self::READ_PERMISSION); + + return view('admin.users.index', [ + 'locale_datatables' => $locale_settings->datatables, + 'credits_display_name' => $general_settings->credits_display_name + ]); } /** @@ -51,8 +79,10 @@ public function index(Request $request) * @param User $user * @return Application|Factory|View|Response */ - public function show(User $user) + public function show(User $user, LocaleSettings $locale_settings, GeneralSettings $general_settings) { + $this->checkPermission(self::READ_PERMISSION); + //QUERY ALL REFERRALS A USER HAS //i am not proud of this at all. $allReferals = []; @@ -65,6 +95,8 @@ public function show(User $user) return view('admin.users.show')->with([ 'user' => $user, 'referrals' => $allReferals, + 'locale_datatables' => $locale_settings->datatables, + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -99,10 +131,17 @@ public function json(Request $request) * @param User $user * @return Application|Factory|View|Response */ - public function edit(User $user) + public function edit(User $user, GeneralSettings $general_settings) { + $allConstants = (new \ReflectionClass(__CLASS__))->getConstants(); + $permissions = array_filter($allConstants, fn($key) => str_starts_with($key, 'admin.users.write')); + $this->checkAnyPermission($permissions); + + $roles = Role::all(); return view('admin.users.edit')->with([ 'user' => $user, + 'credits_display_name' => $general_settings->credits_display_name, + 'roles' => $roles ]); } @@ -117,34 +156,69 @@ public function edit(User $user) */ public function update(Request $request, User $user) { - $request->validate([ + $data = $request->validate([ 'name' => 'required|string|min:4|max:30', 'pterodactyl_id' => "required|numeric|unique:users,pterodactyl_id,{$user->id}", 'email' => 'required|string|email', 'credits' => 'required|numeric|min:0|max:99999999', 'server_limit' => 'required|numeric|min:0|max:1000000', - 'role' => Rule::in(['admin', 'moderator', 'client', 'member']), 'referral_code' => "required|string|min:2|max:32|unique:users,referral_code,{$user->id}", ]); + //update roles + if ($request->roles && $this->can(self::CHANGE_ROLE_PERMISSION)) { + $collectedRoles = collect($request->roles)->map(fn($val)=>(int)$val); + $user->syncRoles($collectedRoles); + } + if (isset($this->pterodactyl->getUser($request->input('pterodactyl_id'))['errors'])) { throw ValidationException::withMessages([ 'pterodactyl_id' => [__("User does not exists on pterodactyl's panel")], ]); } - if (!is_null($request->input('new_password'))) { + $dataArray = []; + + if ($this->canAny([self::CHANGE_USERNAME_PERMISSION, self::WRITE_PERMISSION]) && $request->filled('name')) { + $dataArray['name'] = $request->input('name'); + } + + if ($this->canAny([self::CHANGE_CREDITS_PERMISSION, self::WRITE_PERMISSION]) && $request->filled('credits')) { + $dataArray['credits'] = $request->input('credits'); + } + + if ($this->canAny([self::CHANGE_PTERO_PERMISSION, self::WRITE_PERMISSION]) && $request->filled('pterodactyl_id')) { + $dataArray['pterodactyl_id'] = $request->input('pterodactyl_id'); + } + + if ($this->canAny([self::CHANGE_REFERRAL_PERMISSION, self::WRITE_PERMISSION]) && $request->filled('referral_code')) { + $dataArray['referral_code'] = $request->input('referral_code'); + } + + if ($this->canAny([self::CHANGE_EMAIL_PERMISSION, self::WRITE_PERMISSION]) && $request->filled('email')) { + $dataArray['email'] = $request->input('email'); + } + + if ($this->canAny([self::CHANGE_SERVERLIMIT_PERMISSION, self::WRITE_PERMISSION]) && $request->filled('server_limit')) { + $dataArray['server_limit'] = $request->input('server_limit'); + } + + +// Update password separately with validation, if permission is granted + if (!is_null($request->input('new_password')) && $this->canAny([self::CHANGE_PASSWORD_PERMISSION, self::WRITE_PERMISSION])) { $request->validate([ 'new_password' => 'required|string|min:8', 'new_password_confirmation' => 'required|same:new_password', ]); - $user->update([ - 'password' => Hash::make($request->input('new_password')), - ]); + $dataArray['password'] = Hash::make($request->input('new_password')); + } + +// Only update with the collected data + if (!empty($dataArray)) { + $user->update($dataArray); } - $user->update($request->all()); event(new UserUpdateCreditsEvent($user)); return redirect()->route('admin.users.index')->with('success', 'User updated!'); @@ -158,6 +232,12 @@ public function update(Request $request, User $user) */ public function destroy(User $user) { + $this->checkPermission(self::DELETE_PERMISSION); + + if ($user->hasRole(1) && User::role(1)->count() === 1) { + return redirect()->back()->with('error', __('You can not delete the last admin!')); + } + $user->delete(); return redirect()->back()->with('success', __('user has been removed!')); @@ -169,7 +249,7 @@ public function destroy(User $user) * @param User $user * @return RedirectResponse */ - public function verifyEmail(Request $request, User $user) + public function verifyEmail(User $user) { $user->verifyEmail(); @@ -183,6 +263,8 @@ public function verifyEmail(Request $request, User $user) */ public function loginAs(Request $request, User $user) { + $this->checkPermission(self::LOGIN_PERMISSION); + $request->session()->put('previousUser', Auth::user()->id); Auth::login($user); @@ -195,6 +277,7 @@ public function loginAs(Request $request, User $user) */ public function logBackIn(Request $request) { + Auth::loginUsingId($request->session()->get('previousUser'), true); $request->session()->remove('previousUser'); @@ -207,9 +290,13 @@ public function logBackIn(Request $request) * @param User $user * @return Application|Factory|View|Response */ - public function notifications(User $user) + public function notifications() { - return view('admin.users.notifications'); + $this->checkPermission(self::NOTIFY_PERMISSION); + + $roles = Role::all(); + + return view('admin.users.notifications')->with(["roles" => $roles]); } /** @@ -223,12 +310,16 @@ public function notifications(User $user) */ public function notify(Request $request) { + $this->checkPermission(self::NOTIFY_PERMISSION); + +//TODO: reimplement the required validation on all,users and roles . didnt work -- required_without:users,roles $data = $request->validate([ 'via' => 'required|min:1|array', 'via.*' => 'required|string|in:mail,database', - 'all' => 'required_without:users|boolean', - 'users' => 'required_without:all|min:1|array', - 'users.*' => 'exists:users,id', + 'all' => 'boolean', + 'users' => 'min:1|array', + 'roles' => 'min:1|array', + 'roles.*' => 'required_without:all,users|exists:roles,id', 'title' => 'required|string|min:1', 'content' => 'required|string|min:1', ]); @@ -247,8 +338,19 @@ public function notify(Request $request) ->line(new HtmlString($data['content'])); } $all = $data['all'] ?? false; - $users = $all ? User::all() : User::whereIn('id', $data['users'])->get(); - Notification::send($users, new DynamicNotification($data['via'], $database, $mail)); + $roles = $data['roles'] ?? false; + if(!$roles){ + $users = $all ? User::all() : User::whereIn('id', $data['users'])->get(); + } else{ + $users = User::role($data["roles"])->get(); + } + + + try { + Notification::send($users, new DynamicNotification($data['via'], $database, $mail)); + } catch (Exception $e) { + return redirect()->route('admin.users.notifications')->with('error', __('The attempt to send the email failed with the error: ' . $e->getMessage())); + } return redirect()->route('admin.users.notifications')->with('success', __('Notification sent!')); } @@ -259,6 +361,12 @@ public function notify(Request $request) */ public function toggleSuspended(User $user) { + $this->checkPermission(self::SUSPEND_PERMISSION); + + if (Auth::user()->id === $user->id) { + return redirect()->back()->with('error', __('You can not suspend yourself!')); + } + try { !$user->isSuspended() ? $user->suspend() : $user->unSuspend(); } catch (Exception $exception) { @@ -273,34 +381,39 @@ public function toggleSuspended(User $user) */ public function dataTable(Request $request) { - $query = User::with('discordUser')->withCount('servers'); - // manually count referrals in user_referrals table - $query->selectRaw('users.*, (SELECT COUNT(*) FROM user_referrals WHERE user_referrals.referral_id = users.id) as referrals_count'); - + $query = User::query() + ->withCount('servers') + ->leftJoin('model_has_roles', 'users.id', '=', 'model_has_roles.model_id') + ->leftJoin('roles', 'model_has_roles.role_id', '=', 'roles.id') + ->selectRaw('users.*, roles.name as role_name, (SELECT COUNT(*) FROM user_referrals WHERE user_referrals.referral_id = users.id) as referrals_count') + ->where('model_has_roles.model_type', User::class); return datatables($query) ->addColumn('avatar', function (User $user) { - return ''; + return ''; }) ->addColumn('credits', function (User $user) { - return ' ' . $user->credits(); + return ' ' . $user->credits(); }) ->addColumn('verified', function (User $user) { return $user->getVerifiedStatus(); }) + /* This broke the ability to search the table. Have to revisit later + ->addColumn('discordId', function (User $user) { return $user->discordUser ? $user->discordUser->id : ''; }) + */ ->addColumn('actions', function (User $user) { $suspendColor = $user->isSuspended() ? 'btn-success' : 'btn-warning'; $suspendIcon = $user->isSuspended() ? 'fa-play-circle' : 'fa-pause-circle'; $suspendText = $user->isSuspended() ? __('Unsuspend') : __('Suspend'); return ' - - - - + + + +
' . csrf_field() . ' @@ -308,34 +421,26 @@ public function dataTable(Request $request) ' . csrf_field() . ' ' . method_field('DELETE') . ' - +
'; }) ->editColumn('role', function (User $user) { - switch ($user->role) { - case 'admin': - $badgeColor = 'badge-danger'; - break; - case 'moderator': - $badgeColor = 'badge-info'; - break; - case 'client': - $badgeColor = 'badge-success'; - break; - default: - $badgeColor = 'badge-secondary'; - break; + $html = ''; + + foreach ($user->roles as $role) { + $html .= "$role->name"; } - return '' . $user->role . ''; + return $html; }) ->editColumn('last_seen', function (User $user) { return $user->last_seen ? $user->last_seen->diffForHumans() : __('Never'); }) - ->editColumn('name', function (User $user) { - return '' . strip_tags($user->name) . ''; + ->editColumn('name', function (User $user, PterodactylSettings $ptero_settings) { + return '' . strip_tags($user->name) . ''; }) + ->orderColumn('role', 'role_name $1') ->rawColumns(['avatar', 'name', 'credits', 'role', 'usage', 'actions']) ->make(); } diff --git a/app/Http/Controllers/Admin/VoucherController.php b/app/Http/Controllers/Admin/VoucherController.php index ce8bcf5db..4e65e7d54 100644 --- a/app/Http/Controllers/Admin/VoucherController.php +++ b/app/Http/Controllers/Admin/VoucherController.php @@ -6,6 +6,8 @@ use App\Http\Controllers\Controller; use App\Models\User; use App\Models\Voucher; +use App\Settings\GeneralSettings; +use App\Settings\LocaleSettings; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; @@ -17,14 +19,21 @@ class VoucherController extends Controller { + const READ_PERMISSION = "admin.voucher.read"; + const WRITE_PERMISSION = "admin.voucher.write"; /** * Display a listing of the resource. * * @return Application|Factory|View */ - public function index() + public function index(LocaleSettings $locale_settings, GeneralSettings $general_settings) { - return view('admin.vouchers.index'); + $this->checkAnyPermission([self::READ_PERMISSION, self::WRITE_PERMISSION]); + + return view('admin.vouchers.index', [ + 'locale_datatables' => $locale_settings->datatables, + 'credits_display_name' => $general_settings->credits_display_name + ]); } /** @@ -32,9 +41,12 @@ public function index() * * @return Application|Factory|View */ - public function create() + public function create(GeneralSettings $general_settings) { - return view('admin.vouchers.create'); + $this->checkPermission(self::WRITE_PERMISSION); + return view('admin.vouchers.create', [ + 'credits_display_name' => $general_settings->credits_display_name + ]); } /** @@ -75,10 +87,12 @@ public function show(Voucher $voucher) * @param Voucher $voucher * @return Application|Factory|View */ - public function edit(Voucher $voucher) + public function edit(Voucher $voucher, GeneralSettings $general_settings) { + $this->checkPermission(self::WRITE_PERMISSION); return view('admin.vouchers.edit', [ 'voucher' => $voucher, + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -112,15 +126,20 @@ public function update(Request $request, Voucher $voucher) */ public function destroy(Voucher $voucher) { + $this->checkPermission(self::WRITE_PERMISSION); $voucher->delete(); return redirect()->back()->with('success', __('voucher has been removed!')); } - public function users(Voucher $voucher) + public function users(Voucher $voucher, LocaleSettings $locale_settings, GeneralSettings $general_settings) { + $this->checkPermission(self::READ_PERMISSION); + return view('admin.vouchers.users', [ 'voucher' => $voucher, + 'locale_datatables' => $locale_settings->datatables, + 'credits_display_name' => $general_settings->credits_display_name ]); } @@ -130,7 +149,7 @@ public function users(Voucher $voucher) * * @throws ValidationException */ - public function redeem(Request $request) + public function redeem(Request $request, GeneralSettings $general_settings) { //general validations $request->validate([ @@ -161,7 +180,7 @@ public function redeem(Request $request) if ($request->user()->credits + $voucher->credits >= 99999999) { throw ValidationException::withMessages([ - 'code' => "You can't redeem this voucher because you would exceed the limit of ".CREDITS_DISPLAY_NAME, + 'code' => "You can't redeem this voucher because you would exceed the limit of " . $general_settings->credits_display_name, ]); } @@ -171,7 +190,7 @@ public function redeem(Request $request) event(new UserUpdateCreditsEvent($request->user())); return response()->json([ - 'success' => "{$voucher->credits} ".CREDITS_DISPLAY_NAME.' '.__('have been added to your balance!'), + 'success' => "{$voucher->credits} ". $general_settings->credits_display_name .' '.__('have been added to your balance!'), ]); } @@ -184,7 +203,7 @@ public function usersDataTable(Voucher $voucher) return ''.$user->name.''; }) ->addColumn('credits', function (User $user) { - return ' '.$user->credits(); + return ' '.$user->credits(); }) ->addColumn('last_seen', function (User $user) { return $user->last_seen ? $user->last_seen->diffForHumans() : ''; @@ -195,28 +214,33 @@ public function usersDataTable(Voucher $voucher) public function dataTable() { - $query = Voucher::query(); + $query = Voucher::selectRaw(' + vouchers.*, + CASE + WHEN (SELECT COUNT(*) FROM user_voucher WHERE user_voucher.voucher_id = vouchers.id) >= vouchers.uses THEN "USES_LIMIT_REACHED" + WHEN vouchers.expires_at IS NOT NULL AND vouchers.expires_at < NOW() THEN "EXPIRED" + ELSE "VALID" + END as derived_status + '); return datatables($query) ->addColumn('actions', function (Voucher $voucher) { return ' - - + +
'.csrf_field().' '.method_field('DELETE').' - +
'; }) ->addColumn('status', function (Voucher $voucher) { - $color = 'success'; - if ($voucher->getStatus() != __('VALID')) { - $color = 'danger'; - } + $color = ($voucher->derived_status == 'VALID') ? 'success' : 'danger'; + $status = str_replace('_', ' ', $voucher->derived_status); - return ''.$voucher->getStatus().''; + return ''.$status.''; }) ->editColumn('uses', function (Voucher $voucher) { return "{$voucher->used} / {$voucher->uses}"; @@ -226,14 +250,15 @@ public function dataTable() }) ->editColumn('expires_at', function (Voucher $voucher) { if (! $voucher->expires_at) { - return ''; + return __("Never"); } - return $voucher->expires_at ? $voucher->expires_at->diffForHumans() : ''; + return $voucher->expires_at ? $voucher->expires_at->diffForHumans() : __("Never"); }) ->editColumn('code', function (Voucher $voucher) { return "{$voucher->code}"; }) + ->orderColumn('status', 'derived_status $1') ->rawColumns(['actions', 'code', 'status']) ->make(); } diff --git a/app/Http/Controllers/Api/RoleController.php b/app/Http/Controllers/Api/RoleController.php new file mode 100644 index 000000000..1deca23fe --- /dev/null +++ b/app/Http/Controllers/Api/RoleController.php @@ -0,0 +1,162 @@ +allowedIncludes(self::ALLOWED_INCLUDES) + ->allowedFilters(self::ALLOWED_FILTERS); + + return $query->paginate($request->input('per_page') ?? 50); + } + + /** + * Show the form for creating a new resource. + * + * @return Response + */ + public function create() + { + // + } + + /** + * Store a newly created resource in storage. + * + * @param Request $request + * @return Response + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string|max:191', + 'color' => [ + 'required', + 'regex:/^#([a-f0-9]{6}|[a-f0-9]{3})$/i' + ], + 'power' => 'required', + ]); + + $role = Role::create([ + 'name' => $request->name, + 'color' => $request->color, + 'power' => $request->power, + ]); + + if ($request->permissions) { + $permissions = explode(",",$request->permissions); + $collectedPermissions = collect($permissions)->map(fn($val)=>(int)$val); + foreach($collectedPermissions as $permission){ + $role->givePermissionTo($permission); + } + } + + return $role; + } + + /** + * Display the specified resource. + * + * @param int $id + * @return Role|Collection|Model + */ + public function show(int $id) + { + $query = QueryBuilder::for(Role::class) + ->where('id', '=', $id) + ->allowedIncludes(self::ALLOWED_INCLUDES); + + return $query->firstOrFail(); + } + + /** + * Show the form for editing the specified resource. + * + * @param int $id + * @return Response + */ + public function edit($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param Request $request + * @param int $id + * @return Response + */ + public function update(Request $request, int $id) + { + $role = Role::findOrFail($id); + + $request->validate([ + 'name' => 'sometimes|string|max:191', + 'color' => [ + 'sometimes', + 'regex:/^#([a-f0-9]{6}|[a-f0-9]{3})$/i' + ], + 'power' => 'sometimes', + ]); + + if ($request->permissions) { + $permissions = explode(",",$request->permissions); + $collectedPermissions = collect($permissions)->map(fn($val)=>(int)$val); + $role->syncPermissions($collectedPermissions); + } + + + $role->update($request->except('permissions')); + + return $role; + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return Response + */ + public function destroy(int $id) + { + $role = Role::findOrFail($id); + + if($role->id == 1 || $role->id == 3|| $role->id == 4){ //cannot delete admin and User role + return response()->json([ + 'error' => 'Not allowed to delete Admin, Client or Member'], 400); + } + + $users = User::role($role)->get(); + + foreach($users as $user){ + $user->syncRoles([4]); + } + $role->delete(); + + return $role; + } +} diff --git a/app/Http/Controllers/Api/UserController.php b/app/Http/Controllers/Api/UserController.php index 68b0f948d..3f2a281f7 100644 --- a/app/Http/Controllers/Api/UserController.php +++ b/app/Http/Controllers/Api/UserController.php @@ -8,7 +8,7 @@ use App\Models\DiscordUser; use App\Models\User; use App\Notifications\ReferralNotification; -use App\Traits\Referral; +use App\Settings\UserSettings; use Carbon\Carbon; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Pagination\LengthAwarePaginator; @@ -28,11 +28,9 @@ class UserController extends Controller { - use Referral; + const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'roles', 'discordUser']; - const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser']; - - const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended']; + const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'suspended']; /** * Display a listing of the resource. @@ -88,14 +86,13 @@ public function update(Request $request, int $id) 'email' => 'sometimes|string|email', 'credits' => 'sometimes|numeric|min:0|max:1000000', 'server_limit' => 'sometimes|numeric|min:0|max:1000000', - 'role' => ['sometimes', Rule::in(['admin', 'moderator', 'client', 'member'])], ]); event(new UserUpdateCreditsEvent($user)); //Update Users Password on Pterodactyl //Username,Mail,First and Lastname are required aswell - $response = Pterodactyl::client()->patch('/application/users/' . $user->pterodactyl_id, [ + $response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [ 'username' => $request->name, 'first_name' => $request->name, 'last_name' => $request->name, @@ -108,7 +105,11 @@ public function update(Request $request, int $id) 'pterodactyl_error_status' => $response->toException()->getCode(), ]); } - $user->update($request->all()); + if($request->has("role")){ + $collectedRoles = collect($request->role)->map(fn($val)=>(int)$val); + $user->syncRoles($collectedRoles); + } + $user->update($request->except('role')); return $user; } @@ -232,7 +233,7 @@ public function unsuspend(Request $request, int $id) $discordUser = DiscordUser::find($id); $user = $discordUser ? $discordUser->user : User::findOrFail($id); - if (!$user->isSuspended()) { + if (! $user->isSuspended()) { throw ValidationException::withMessages([ 'error' => 'You cannot unsuspend an User who is not suspended.', ]); @@ -243,10 +244,25 @@ public function unsuspend(Request $request, int $id) return $user; } + /** + * Create a unique Referral Code for User + * + * @return string + */ + protected function createReferralCode() + { + $referralcode = STR::random(8); + if (User::where('referral_code', '=', $referralcode)->exists()) { + $this->createReferralCode(); + } + + return $referralcode; + } + /** * @throws ValidationException */ - public function store(Request $request) + public function store(Request $request, UserSettings $userSettings) { $request->validate([ 'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'], @@ -255,7 +271,7 @@ public function store(Request $request) ]); // Prevent the creation of new users via API if this is enabled. - if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_USERS', 'true')) { + if (! $userSettings->creation_enabled) { throw ValidationException::withMessages([ 'error' => 'The creation of new users has been blocked by the system administrator.', ]); @@ -293,7 +309,7 @@ public function store(Request $request) 'pterodactyl_id' => $response->json()['attributes']['id'], ]); //INCREMENT REFERRAL-USER CREDITS - if (!empty($request->input('referral_code'))) { + if (! empty($request->input('referral_code'))) { $ref_code = $request->input('referral_code'); $new_user = $user->id; if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) { diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index bd9df2d89..6c3f34aef 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\Settings\GeneralSettings; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Http\Request; @@ -37,7 +38,9 @@ protected function validateEmail(Request $request) 'email' => ['required', 'string', 'email', 'max:255'], ]); - if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') { + $recaptcha_enabled = app(GeneralSettings::class)->recaptcha_enabled; + + if ($recaptcha_enabled) { $this->validate($request, [ 'g-recaptcha-response' => 'required|recaptcha', ]); diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index ec678ace8..b315f8d77 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -2,13 +2,18 @@ namespace App\Http\Controllers\Auth; -use App\Classes\Pterodactyl; use App\Http\Controllers\Controller; use App\Models\User; use App\Notifications\ReferralNotification; use App\Providers\RouteServiceProvider; use App\Traits\Referral; use Carbon\Carbon; +use App\Settings\PterodactylSettings; +use App\Classes\PterodactylClient; +use App\Settings\GeneralSettings; +use App\Settings\ReferralSettings; +use App\Settings\UserSettings; +use App\Settings\WebsiteSettings; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\DB; @@ -17,9 +22,28 @@ use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; use Illuminate\Validation\ValidationException; +use Spatie\Permission\Models\Role; class RegisterController extends Controller { + private $pterodactyl; + + private $credits_display_name; + + private $recaptcha_enabled; + + private $website_show_tos; + + private $register_ip_check; + + private $initial_credits; + + private $initial_server_limit; + + private $referral_mode; + + private $referral_reward; + /* |-------------------------------------------------------------------------- | Register Controller @@ -45,9 +69,18 @@ class RegisterController extends Controller * * @return void */ - public function __construct() + public function __construct(PterodactylSettings $ptero_settings, GeneralSettings $general_settings, WebsiteSettings $website_settings, UserSettings $user_settings, ReferralSettings $referral_settings) { $this->middleware('guest'); + $this->pterodactyl = new PterodactylClient($ptero_settings); + $this->credits_display_name = $general_settings->credits_display_name; + $this->recaptcha_enabled = $general_settings->recaptcha_enabled; + $this->website_show_tos = $website_settings->show_tos; + $this->register_ip_check = $user_settings->register_ip_check; + $this->initial_credits = $user_settings->initial_credits; + $this->initial_server_limit = $user_settings->initial_server_limit; + $this->referral_mode = $referral_settings->mode; + $this->referral_reward = $referral_settings->reward; } /** @@ -63,14 +96,14 @@ protected function validator(array $data) 'email' => ['required', 'string', 'email', 'max:64', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]; - if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') { + if ($this->recaptcha_enabled) { $validationRules['g-recaptcha-response'] = ['required', 'recaptcha']; } - if (config('SETTINGS::SYSTEM:SHOW_TOS') == 'true') { + if ($this->website_show_tos) { $validationRules['terms'] = ['required']; } - if (config('SETTINGS::SYSTEM:REGISTER_IP_CHECK', 'true') == 'true') { + if ($this->register_ip_check) { //check if ip has already made an account $data['ip'] = session()->get('ip') ?? request()->ip(); @@ -99,15 +132,18 @@ protected function create(array $data) $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], - 'credits' => config('SETTINGS::USER:INITIAL_CREDITS', 150), - 'server_limit' => config('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1), + 'credits' => $this->initial_credits, + 'server_limit' => $this->initial_server_limit, 'password' => Hash::make($data['password']), 'referral_code' => $this->createReferralCode(), + 'pterodactyl_id' => Str::uuid(), ]); - $response = Pterodactyl::client()->post('/application/users', [ - 'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id, + $user->syncRoles(Role::findByName('User')); + + $response = $this->pterodactyl->application->post('/application/users', [ + 'external_id' => null, 'username' => $user->name, 'email' => $user->email, 'first_name' => $user->name, @@ -117,6 +153,10 @@ protected function create(array $data) 'language' => 'en', ]); + $user->update([ + 'pterodactyl_id' => $response->json()['attributes']['id'], + ]); + if ($response->failed()) { $user->delete(); Log::error('Pterodactyl Registration Error: ' . $response->json()['errors'][0]['detail']); @@ -125,24 +165,23 @@ protected function create(array $data) ]); } - $user->update([ - 'pterodactyl_id' => $response->json()['attributes']['id'], - ]); + // delete activity log for user creation where description = 'created' or 'deleted' and subject_id = user_id + DB::table('activity_log')->where('description', 'created')->orWhere('description', 'deleted')->where('subject_id', $user->id)->delete(); //INCREMENT REFERRAL-USER CREDITS if (!empty($data['referral_code'])) { $ref_code = $data['referral_code']; $new_user = $user->id; if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) { - if (config('SETTINGS::REFERRAL:MODE') == 'sign-up' || config('SETTINGS::REFERRAL:MODE') == 'both') { - $ref_user->increment('credits', config('SETTINGS::REFERRAL::REWARD')); + if ($this->referral_mode === 'sign-up' || $this->referral_mode === 'both') { + $ref_user->increment('credits', $this->referral_reward); $ref_user->notify(new ReferralNotification($ref_user->id, $new_user)); //LOGS REFERRALS IN THE ACTIVITY LOG activity() ->performedOn($user) ->causedBy($ref_user) - ->log('gained ' . config('SETTINGS::REFERRAL::REWARD') . ' ' . config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME') . ' for sign-up-referral of ' . $user->name . ' (ID:' . $user->id . ')'); + ->log('gained ' . $this->referral_reward . ' ' . $this->credits_display_name . ' for sign-up-referral of ' . $user->name . ' (ID:' . $user->id . ')'); } //INSERT INTO USER_REFERRALS TABLE DB::table('user_referrals')->insert([ diff --git a/app/Http/Controllers/Auth/SocialiteController.php b/app/Http/Controllers/Auth/SocialiteController.php index 101a367a2..66cc001b7 100644 --- a/app/Http/Controllers/Auth/SocialiteController.php +++ b/app/Http/Controllers/Auth/SocialiteController.php @@ -15,9 +15,9 @@ public function redirect() { $scopes = ! empty(config('SETTINGS::DISCORD:BOT_TOKEN')) && ! empty(config('SETTINGS::DISCORD:GUILD_ID')) ? ['guilds.join'] : []; - return Socialite::driver('discord') + return ( Socialite::driver('discord') ->scopes($scopes) - ->redirect(); + ->redirect()); } public function callback() @@ -68,18 +68,11 @@ public function callback() "https://discord.com/api/guilds/{$guildId}/members/{$discord->id}", ['access_token' => $discord->token] ); - + $discordUser = $user->discordUser; //give user a role in the discord server if (! empty($roleId)) { - $response = Http::withHeaders( - [ - 'Authorization' => 'Bot '.$botToken, - 'Content-Type' => 'application/json', - ] - )->put( - "https://discord.com/api/guilds/{$guildId}/members/{$discord->id}/roles/{$roleId}", - ['access_token' => $discord->token] - ); + // Function addOrRemoveRole is defined in app/Models/DiscordUser.php + $discordUser->addOrRemoveRole('add', $roleId); } } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index a0a2a8a34..b6060d827 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,12 +2,61 @@ namespace App\Http\Controllers; +use App\Models\User; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; +use Illuminate\Support\Facades\Auth; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + /** + * Check if user has permissions + * Abort 403 if the user doesn't have the required permission + * + * @param string $permission + * @return void + */ + public function checkPermission(string $permission) + { + /** @var User $user */ + $user = Auth::user(); + + if (!$user->can($permission)) { + abort(403, __('User does not have the right permissions.')); + } + } + + public function checkAnyPermission(iterable $permission) + { + /** @var User $user */ + $user = Auth::user(); + + if (!$user->canAny($permission)) { + abort(403, __('User does not have the right permissions.')); + } + } + + /** + * Check if user has permissions + * + * @param string $permission + * @return bool + */ + public function can(string $permission): bool + { + /** @var User $user */ + $user = Auth::user(); + + return $user->can($permission); + } + public function canAny(iterable $permission): bool + { + /** @var User $user */ + $user = Auth::user(); + + return $user->canAny($permission); + } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 9dbe62be9..9b53dd000 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -4,7 +4,9 @@ use App\Models\PartnerDiscount; use App\Models\UsefulLink; -use Illuminate\Http\Request; +use App\Settings\GeneralSettings; +use App\Settings\WebsiteSettings; +use App\Settings\ReferralSettings; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Hash; @@ -32,7 +34,7 @@ public function callHome() if (Storage::exists('callHome')) { return; } - Http::asForm()->post('https://market.ctrlpanel.gg/callhome.php', [ + Http::asForm()->post('https://market.CtrlPanel.gg/callhome.php', [ 'id' => Hash::make(URL::current()), ]); Storage::put('callHome', 'This is only used to count the installations of cpgg.'); @@ -89,7 +91,7 @@ public function getTimeLeftBoxText(float $daysLeft, float $hoursLeft) } /** Show the application dashboard. */ - public function index(Request $request) + public function index(GeneralSettings $general_settings, WebsiteSettings $website_settings, ReferralSettings $referral_settings) { $usage = Auth::user()->creditUsage(); $credits = Auth::user()->Credits(); @@ -99,7 +101,7 @@ public function index(Request $request) /** Build our Time-Left-Box */ if ($credits > 0.01 and $usage > 0) { - $daysLeft = number_format(($credits * 30) / $usage, 2, '.', ''); + $daysLeft = number_format($credits / ($usage / 30), 2, '.', ''); $hoursLeft = number_format($credits / ($usage / 30 / 24), 2, '.', ''); $bg = $this->getTimeLeftBoxBackground($daysLeft); @@ -120,6 +122,9 @@ public function index(Request $request) 'numberOfReferrals' => DB::table('user_referrals')->where('referral_id', '=', Auth::user()->id)->count(), 'partnerDiscount' => PartnerDiscount::where('user_id', Auth::user()->id)->first(), 'myDiscount' => PartnerDiscount::getDiscount(), + 'general_settings' => $general_settings, + 'website_settings' => $website_settings, + 'referral_settings' => $referral_settings ]); } } diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 117ac33e1..4e7e09e56 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -2,18 +2,31 @@ namespace App\Http\Controllers; -use App\Classes\Pterodactyl; -use App\Models\Egg; -use App\Models\Location; -use App\Models\Node; +use App\Classes\PterodactylClient; +use App\Models\Pterodactyl\Egg; +use App\Models\Pterodactyl\Location; +use App\Models\Pterodactyl\Node; use App\Models\Product; +use App\Models\User; +use App\Notifications\DynamicNotification; +use App\Settings\PterodactylSettings; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Notification; +use Illuminate\Support\Facades\RateLimiter; class ProductController extends Controller { + private $pterodactyl; + + public function __construct(PterodactylSettings $ptero_settings) + { + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + /** * @description get product locations based on selected egg * @@ -60,7 +73,7 @@ public function getLocationsBasedOnEgg(Request $request, Egg $egg) { $nodes = $this->getNodesBasedOnEgg($request, $egg); foreach ($nodes as $key => $node) { - $pteroNode = Pterodactyl::getNode($node->id); + $pteroNode = $this->pterodactyl->getNode($node->id); if ($pteroNode['allocated_resources']['memory'] >= ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) || $pteroNode['allocated_resources']['disk'] >= ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) { $nodes->forget($key); } @@ -85,34 +98,60 @@ public function getLocationsBasedOnEgg(Request $request, Egg $egg) } }); + if($locations->isEmpty()){ + // Rate limit the node full notification to 1 attempt per 30 minutes + RateLimiter::attempt( + key: 'nodes-full-warning', + maxAttempts: 1, + callback: function() { + // get admin role and check users + $users = User::query()->where('role', '=', '1')->get(); + Notification::send($users,new DynamicNotification(['mail'],[], + mail: (new MailMessage)->subject('Attention! All of the nodes are full!')->greeting('Attention!')->line('All nodes are full, please add more nodes'))); + }, + decaySeconds: 5 + ); + } + return $locations; } /** - * @param Node $node + * @param Int $location * @param Egg $egg * @return Collection|JsonResponse */ - public function getProductsBasedOnNode(Egg $egg, Node $node) + public function getProductsBasedOnLocation(Egg $egg, Int $location) { - if (is_null($egg->id) || is_null($node->id)) { - return response()->json('node and egg id is required', '400'); + if (is_null($egg->id) || is_null($location)) { + return response()->json('location and egg id is required', '400'); } + // Get all nodes in this location + $nodes = Node::query() + ->where('location_id', '=', $location) + ->get(); + $products = Product::query() ->where('disabled', '=', false) - ->whereHas('nodes', function (Builder $builder) use ($node) { - $builder->where('id', '=', $node->id); + ->whereHas('nodes', function (Builder $builder) use ($nodes) { + $builder->whereIn('id', $nodes->map(function ($node) { + return $node->id; + })); }) ->whereHas('eggs', function (Builder $builder) use ($egg) { $builder->where('id', '=', $egg->id); }) ->get(); - $pteroNode = Pterodactyl::getNode($node->id); + // Instead of the old node check, we will check if the product fits in any given node in the location foreach ($products as $key => $product) { - if ($product->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) { - $product->doesNotFit = true; + $product->doesNotFit = false; + foreach ($nodes as $node) { + $pteroNode = $this->pterodactyl->getNode($node->id); + if ($product->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) { + $product->doesNotFit = true; + } } } diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index bffbc9638..52cb0bffe 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -2,8 +2,12 @@ namespace App\Http\Controllers; -use App\Classes\Pterodactyl; use App\Models\User; +use App\Settings\UserSettings; +use App\Settings\PterodactylSettings; +use App\Classes\PterodactylClient; +use App\Settings\DiscordSettings; +use App\Settings\ReferralSettings; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -12,37 +16,32 @@ class ProfileController extends Controller { + private $pterodactyl; + + public function __construct(PterodactylSettings $ptero_settings) + { + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + /** Display a listing of the resource. */ - public function index() + public function index(UserSettings $user_settings, DiscordSettings $discord_settings, ReferralSettings $referral_settings) { - switch (Auth::user()->role) { - case 'admin': - $badgeColor = 'badge-danger'; - break; - case 'mod': - $badgeColor = 'badge-info'; - break; - case 'client': - $badgeColor = 'badge-success'; - break; - default: - $badgeColor = 'badge-secondary'; - break; - } return view('profile.index')->with([ 'user' => Auth::user(), - 'credits_reward_after_verify_discord' => config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'), - 'force_email_verification' => config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION'), - 'force_discord_verification' => config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION'), - 'badgeColor' => $badgeColor, + 'credits_reward_after_verify_discord' => $user_settings->credits_reward_after_verify_discord, + 'force_email_verification' => $user_settings->force_email_verification, + 'force_discord_verification' => $user_settings->force_discord_verification, + 'discord_client_id' => $discord_settings->client_id, + 'discord_client_secret' => $discord_settings->client_secret, + 'referral_enabled' => $referral_settings->enabled ]); } public function selfDestroyUser() { $user = Auth::user(); - if ($user->role == "admin") return back()->with("error", "You cannot delete yourself as an admin!"); + if ($user->hasRole("Admin")) return back()->with("error", "You cannot delete yourself as an admin!"); $user->delete(); @@ -63,15 +62,15 @@ public function update(Request $request, int $id) $user = User::findOrFail($id); //update password if necessary - if (! is_null($request->input('new_password'))) { + if (!is_null($request->input('new_password'))) { //validate password request $request->validate([ 'current_password' => [ 'required', function ($attribute, $value, $fail) use ($user) { - if (! Hash::check($value, $user->password)) { - $fail('The '.$attribute.' is invalid.'); + if (!Hash::check($value, $user->password)) { + $fail('The ' . $attribute . ' is invalid.'); } }, ], @@ -81,7 +80,7 @@ function ($attribute, $value, $fail) use ($user) { //Update Users Password on Pterodactyl //Username,Mail,First and Lastname are required aswell - $response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [ + $response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ 'password' => $request->input('new_password'), 'username' => $request->input('name'), 'first_name' => $request->input('name'), @@ -103,13 +102,13 @@ function ($attribute, $value, $fail) use ($user) { //validate request $request->validate([ - 'name' => 'required|min:4|max:30|alpha_num|unique:users,name,'.$id.',id', - 'email' => 'required|email|max:64|unique:users,email,'.$id.',id', + 'name' => 'required|min:4|max:30|alpha_num|unique:users,name,' . $id . ',id', + 'email' => 'required|email|max:64|unique:users,email,' . $id . ',id', 'avatar' => 'nullable', ]); //update avatar - if (! is_null($request->input('avatar'))) { + if (!is_null($request->input('avatar'))) { $avatar = json_decode($request->input('avatar')); if ($avatar->input->size > 3000000) { abort(500); @@ -125,7 +124,7 @@ function ($attribute, $value, $fail) use ($user) { } //update name and email on Pterodactyl - $response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [ + $response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ 'username' => $request->input('name'), 'first_name' => $request->input('name'), 'last_name' => $request->input('name'), diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php index 656064c39..d7b1c833c 100644 --- a/app/Http/Controllers/ServerController.php +++ b/app/Http/Controllers/ServerController.php @@ -2,26 +2,44 @@ namespace App\Http\Controllers; -use App\Classes\Pterodactyl; -use App\Models\Egg; -use App\Models\Location; -use App\Models\Nest; -use App\Models\Node; +use App\Models\Pterodactyl\Egg; +use App\Models\Pterodactyl\Location; +use App\Models\Pterodactyl\Nest; +use App\Models\Pterodactyl\Node; use App\Models\Product; use App\Models\Server; +use App\Models\User; use App\Notifications\ServerCreationError; +use App\Settings\DiscordSettings; +use Carbon\Carbon; +use App\Settings\UserSettings; +use App\Settings\ServerSettings; +use App\Settings\PterodactylSettings; +use App\Classes\PterodactylClient; +use App\Settings\GeneralSettings; use Exception; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Client\Response; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request as FacadesRequest; class ServerController extends Controller { + const CREATE_PERMISSION = 'user.server.create'; + const UPGRADE_PERMISSION = 'user.server.upgrade'; + + private $pterodactyl; + + public function __construct(PterodactylSettings $ptero_settings) + { + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + /** Display a listing of the resource. */ - public function index() + public function index(GeneralSettings $general_settings, PterodactylSettings $ptero_settings) { $servers = Auth::user()->servers; @@ -29,8 +47,8 @@ public function index() foreach ($servers as $server) { //Get server infos from ptero - $serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id, true); - if (! $serverAttributes) { + $serverAttributes = $this->pterodactyl->getServerAttributes($server->pterodactyl_id); + if (!$serverAttributes) { continue; } $serverRelationships = $serverAttributes['relationships']; @@ -61,14 +79,21 @@ public function index() return view('servers.index')->with([ 'servers' => $servers, + 'credits_display_name' => $general_settings->credits_display_name, + 'pterodactyl_url' => $ptero_settings->panel_url, + 'phpmyadmin_url' => $general_settings->phpmyadmin_url ]); } /** Show the form for creating a new resource. */ - public function create() + public function create(UserSettings $user_settings, ServerSettings $server_settings, GeneralSettings $general_settings) { - if (! is_null($this->validateConfigurationRules())) { - return $this->validateConfigurationRules(); + $this->checkPermission(self::CREATE_PERMISSION); + + $validate_configuration = $this->validateConfigurationRules($user_settings, $server_settings, $general_settings); + + if (!is_null($validate_configuration)) { + return $validate_configuration; } $productCount = Product::query()->where('disabled', '=', false)->count(); @@ -98,13 +123,18 @@ public function create() 'locations' => $locations, 'eggs' => $eggs, 'user' => Auth::user(), + 'server_creation_enabled' => $server_settings->creation_enabled, + 'min_credits_to_make_server' => $user_settings->min_credits_to_make_server, + 'credits_display_name' => $general_settings->credits_display_name, + 'location_description_enabled' => $server_settings->location_description_enabled, + 'store_enabled' => $general_settings->store_enabled ]); } /** * @return null|RedirectResponse */ - private function validateConfigurationRules() + private function validateConfigurationRules(UserSettings $user_settings, ServerSettings $server_settings, GeneralSettings $generalSettings) { //limit validation if (Auth::user()->servers()->count() >= Auth::user()->server_limit) { @@ -116,39 +146,32 @@ private function validateConfigurationRules() $product = Product::findOrFail(FacadesRequest::input('product')); // Get node resource allocation info - $node = $product->nodes()->findOrFail(FacadesRequest::input('node')); - $nodeName = $node->name; - - // Check if node has enough memory and disk space - $checkResponse = Pterodactyl::checkNodeResources($node, $product->memory, $product->disk); - if ($checkResponse == false) { - return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to allocate this product.")); + $location = FacadesRequest::input('location'); + $availableNode = $this->getAvailableNode($location, $product); + if (!$availableNode) { + return redirect()->route('servers.index')->with('error', __("The chosen location doesn't have the required memory or disk left to allocate this product.")); } // Min. Credits - if ( - Auth::user()->credits < - ($product->minimum_credits == -1 - ? config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50) - : $product->minimum_credits) - ) { - return redirect()->route('servers.index')->with('error', 'You do not have the required amount of '.CREDITS_DISPLAY_NAME.' to use this product!'); + if (Auth::user()->credits < ($product->minimum_credits == -1 + ? $user_settings->min_credits_to_make_server + : $product->minimum_credits)) { + return redirect()->route('servers.index')->with('error', 'You do not have the required amount of ' . $generalSettings->credits_display_name . ' to use this product!'); } } //Required Verification for creating an server - if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && ! Auth::user()->hasVerifiedEmail()) { + if ($user_settings->force_email_verification && !Auth::user()->hasVerifiedEmail()) { return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can create a server.')); } //Required Verification for creating an server - - if (! config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', 'true') && Auth::user()->role != 'admin') { + if (!$server_settings->creation_enabled && Auth::user()->cannot("admin.servers.bypass_creation_enabled")) { return redirect()->route('servers.index')->with('error', __('The system administrator has blocked the creation of new servers.')); } //Required Verification for creating an server - if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && ! Auth::user()->discordUser) { + if ($user_settings->force_discord_verification && !Auth::user()->discordUser) { return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can create a server.')); } @@ -156,40 +179,51 @@ private function validateConfigurationRules() } /** Store a newly created resource in storage. */ - public function store(Request $request) + public function store(Request $request, UserSettings $user_settings, ServerSettings $server_settings, GeneralSettings $generalSettings, DiscordSettings $discord_settings) { - /** @var Node $node */ + /** @var Location $location */ /** @var Egg $egg */ /** @var Product $product */ - if (! is_null($this->validateConfigurationRules())) { - return $this->validateConfigurationRules(); + $validate_configuration = $this->validateConfigurationRules($user_settings, $server_settings, $generalSettings); + + if (!is_null($validate_configuration)) { + return $validate_configuration; } $request->validate([ 'name' => 'required|max:191', - 'node' => 'required|exists:nodes,id', + 'location' => 'required|exists:locations,id', 'egg' => 'required|exists:eggs,id', 'product' => 'required|exists:products,id', ]); - //get required resources + // Get the product and egg $product = Product::query()->findOrFail($request->input('product')); $egg = $product->eggs()->findOrFail($request->input('egg')); - $node = $product->nodes()->findOrFail($request->input('node')); + + // Get an available node + $location = $request->input('location'); + $availableNode = $this->getAvailableNode($location, $product); + $node = Node::query()->find($availableNode); + + if(!$node) { + return redirect()->route('servers.index')->with('error', __("No nodes satisfying the requirements for automatic deployment on this location were found.")); + } $server = $request->user()->servers()->create([ 'name' => $request->input('name'), 'product_id' => $request->input('product'), + 'last_billed' => Carbon::now()->toDateTimeString(), ]); //get free allocation ID - $allocationId = Pterodactyl::getFreeAllocationId($node); - if (! $allocationId) { + $allocationId = $this->pterodactyl->getFreeAllocationId($node); + if (!$allocationId) { return $this->noAllocationsError($server); } //create server on pterodactyl - $response = Pterodactyl::createServer($server, $egg, $allocationId); + $response = $this->pterodactyl->createServer($server, $egg, $allocationId); if ($response->failed()) { return $this->serverCreationFailed($response, $server); } @@ -201,12 +235,23 @@ public function store(Request $request) 'identifier' => $serverAttributes['identifier'], ]); - if (config('SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') { - if ($request->user()->credits >= $server->product->getHourlyPrice()) { - $request->user()->decrement('credits', $server->product->getHourlyPrice()); + // Charge first billing cycle + $request->user()->decrement('credits', $server->product->price); + + // Add role from discord + try { + if($discord_settings->role_on_purchase) { + $user = $request->user(); + $discordUser = $user->discordUser; + if($discordUser && $user->servers->count() >= 1) { + $discordUser->addOrRemoveRole('add', $discord_settings->role_id_on_purchase); + } } + } catch (Exception $e) { + log::debug('Failed to update discord roles' . $e->getMessage()); } + return redirect()->route('servers.index')->with('success', __('Server created')); } @@ -234,30 +279,60 @@ private function noAllocationsError(Server $server) */ private function serverCreationFailed(Response $response, Server $server) { - $server->delete(); - return redirect()->route('servers.index')->with('error', json_encode($response->json())); } /** Remove the specified resource from storage. */ - public function destroy(Server $server) + public function destroy(Server $server, DiscordSettings $discord_settings) { + if ($server->user_id != Auth::user()->id) { + return back()->with('error', __('This is not your Server!')); + } try { + // Remove role from discord + try { + if($discord_settings->role_on_purchase) { + $user = User::findOrFail($server->user_id); + $discordUser = $user->discordUser; + if($discordUser && $user->servers->count() <= 1) { + $discordUser->addOrRemoveRole('remove', $discord_settings->role_id_on_purchase); + } + } + } catch (Exception $e) { + log::debug('Failed to update discord roles' . $e->getMessage()); + } + $server->delete(); return redirect()->route('servers.index')->with('success', __('Server removed')); } catch (Exception $e) { - return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to remove a resource "').$e->getMessage().'"'); + return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to remove a resource"') . $e->getMessage() . '"'); + } + } + + /** Cancel Server */ + public function cancel(Server $server) + { + if ($server->user_id != Auth::user()->id) { + return back()->with('error', __('This is not your Server!')); + } + try { + $server->update([ + 'canceled' => now(), + ]); + return redirect()->route('servers.index')->with('success', __('Server canceled')); + } catch (Exception $e) { + return redirect()->route('servers.index')->with('error', __('An exception has occurred while trying to cancel the server"') . $e->getMessage() . '"'); } } /** Show Server Settings */ - public function show(Server $server) + public function show(Server $server, ServerSettings $server_settings, GeneralSettings $general_settings) { if ($server->user_id != Auth::user()->id) { - return back()->with('error', __('´This is not your Server!')); + return back()->with('error', __('This is not your Server!')); } - $serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id); + $serverAttributes = $this->pterodactyl->getServerAttributes($server->pterodactyl_id); $serverRelationships = $serverAttributes['relationships']; $serverLocationAttributes = $serverRelationships['location']['attributes']; @@ -273,15 +348,15 @@ public function show(Server $server) $server->name = $serverAttributes['name']; $server->egg = $serverRelationships['egg']['attributes']['name']; - $pteroNode = Pterodactyl::getNode($serverRelationships['node']['attributes']['id']); + $pteroNode = $this->pterodactyl->getNode($serverRelationships['node']['attributes']['id']); $products = Product::orderBy('created_at') - ->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node - $builder->where('id', '=', $serverRelationships['node']['attributes']['id']); - }) - ->get(); + ->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node + $builder->where('id', '=', $serverRelationships['node']['attributes']['id']); + }) + ->get(); - // Set the each product eggs array to just contain the eggs name + // Set each product eggs array to just contain the eggs name foreach ($products as $product) { $product->eggs = $product->eggs->pluck('name')->toArray(); if ($product->memory - $currentProduct->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk - $currentProduct->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) { @@ -292,21 +367,26 @@ public function show(Server $server) return view('servers.settings')->with([ 'server' => $server, 'products' => $products, + 'server_enable_upgrade' => $server_settings->enable_upgrade, + 'credits_display_name' => $general_settings->credits_display_name, + 'location_description_enabled' => $server_settings->location_description_enabled, ]); } public function upgrade(Server $server, Request $request) { + $this->checkPermission(self::UPGRADE_PERMISSION); + if ($server->user_id != Auth::user()->id) { return redirect()->route('servers.index'); } - if (! isset($request->product_upgrade)) { + if (!isset($request->product_upgrade)) { return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('this product is the only one')); } $user = Auth::user(); $oldProduct = Product::where('id', $server->product->id)->first(); $newProduct = Product::where('id', $request->product_upgrade)->first(); - $serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id); + $serverAttributes = $this->pterodactyl->getServerAttributes($server->pterodactyl_id); $serverRelationships = $serverAttributes['relationships']; // Get node resource allocation info @@ -317,35 +397,86 @@ public function upgrade(Server $server, Request $request) // Check if node has enough memory and disk space $requireMemory = $newProduct->memory - $oldProduct->memory; $requiredisk = $newProduct->disk - $oldProduct->disk; - $checkResponse = Pterodactyl::checkNodeResources($node, $requireMemory, $requiredisk); - if ($checkResponse == false) { - return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to upgrade the server.")); + $nodeFree = $this->pterodactyl->checkNodeResources($node, $requireMemory, $requiredisk); + if (!$nodeFree) { + return redirect()->route('servers.index')->with('error', __("The node '" . $nodeName . "' doesn't have the required memory or disk left to upgrade the server.")); } - $priceupgrade = $newProduct->getHourlyPrice(); - - if ($priceupgrade < $oldProduct->getHourlyPrice()) { - $priceupgrade = 0; - } - if ($user->credits >= $priceupgrade && $user->credits >= $newProduct->minimum_credits) { - $server->product_id = $request->product_upgrade; - $server->update(); + // calculate the amount of credits that the user overpayed for the old product when canceling the server right now + // billing periods are hourly, daily, weekly, monthly, quarterly, half-annually, annually + $billingPeriod = $oldProduct->billing_period; + // seconds + $billingPeriods = [ + 'hourly' => 3600, + 'daily' => 86400, + 'weekly' => 604800, + 'monthly' => 2592000, + 'quarterly' => 7776000, + 'half-annually' => 15552000, + 'annually' => 31104000 + ]; + // Get the amount of hours the user has been using the server + $billingPeriodMultiplier = $billingPeriods[$billingPeriod]; + $timeDifference = now()->diffInSeconds($server->last_billed); + + // Calculate the price for the time the user has been using the server + $overpayedCredits = $oldProduct->price - $oldProduct->price * ($timeDifference / $billingPeriodMultiplier); + + + if ($user->credits >= $newProduct->price && $user->credits >= $newProduct->minimum_credits) { $server->allocation = $serverAttributes['allocation']; - $response = Pterodactyl::updateServer($server, $newProduct); - if ($response->failed()) { - return $this->serverCreationFailed($response, $server); - } - //update user balance - $user->decrement('credits', $priceupgrade); + $response = $this->pterodactyl->updateServer($server, $newProduct); + if ($response->failed()) return redirect()->route('servers.index')->with('error', __("The system was unable to update your server product. Please try again later or contact support.")); //restart the server - $response = Pterodactyl::powerAction($server, 'restart'); - if ($response->failed()) { - return redirect()->route('servers.index')->with('error', $response->json()['errors'][0]['detail']); - } + $response = $this->pterodactyl->powerAction($server, 'restart'); + if ($response->failed()) return redirect()->route('servers.index')->with('error', 'Upgrade Failed! Could not restart the server: ' . $response->json()['errors'][0]['detail']); + + + // Remove the allocation property from the server object as it is not a column in the database + unset($server->allocation); + // Update the server on CtrlPanel + $server->update([ + 'product_id' => $newProduct->id, + 'updated_at' => now(), + 'last_billed' => now(), + 'canceled' => null, + ]); + + // Refund the user the overpayed credits + if ($overpayedCredits > 0) $user->increment('credits', $overpayedCredits); + + // Withdraw the credits for the new product + $user->decrement('credits', $newProduct->price); return redirect()->route('servers.show', ['server' => $server->id])->with('success', __('Server Successfully Upgraded')); } else { return redirect()->route('servers.show', ['server' => $server->id])->with('error', __('Not Enough Balance for Upgrade')); } } + + /** + * @param string $location + * @param Product $product + * @return int | null Node ID + */ + private function getAvailableNode(string $location, Product $product) + { + $collection = Node::query()->where('location_id', $location)->get(); + + // loop through nodes and check if the node has enough resources + foreach ($collection as $node) { + // Check if the node has enough memory and disk space + $freeNode = $this->pterodactyl->checkNodeResources($node, $product->memory, $product->disk); + // Remove the node from the collection if it doesn't have enough resources + if (!$freeNode) { + $collection->forget($node['id']); + } + } + + if($collection->isEmpty()) { + return null; + } + + return $collection->first()['id']; + } } diff --git a/app/Http/Controllers/TicketsController.php b/app/Http/Controllers/TicketsController.php index 3b2571c02..447e0cc8d 100644 --- a/app/Http/Controllers/TicketsController.php +++ b/app/Http/Controllers/TicketsController.php @@ -11,30 +11,53 @@ use App\Notifications\Ticket\Admin\AdminCreateNotification; use App\Notifications\Ticket\Admin\AdminReplyNotification; use App\Notifications\Ticket\User\CreateNotification; +use App\Settings\GeneralSettings; +use App\Settings\LocaleSettings; +use App\Settings\PterodactylSettings; +use App\Settings\TicketSettings; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Notification; +use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Str; + class TicketsController extends Controller { - public function index() + const READ_PERMISSION = 'user.ticket.read'; + const WRITE_PERMISSION = 'user.ticket.write'; + public function index(LocaleSettings $locale_settings, TicketSettings $ticketSettings) { - $tickets = Ticket::where('user_id', Auth::user()->id)->paginate(10); - $ticketcategories = TicketCategory::all(); - - return view('ticket.index', compact('tickets', 'ticketcategories')); + return view('ticket.index', [ + 'ticketsettings' => $ticketSettings, + 'tickets' => Ticket::where('user_id', Auth::user()->id)->paginate(10), + 'ticketcategories' => TicketCategory::all(), + 'locale_datatables' => $locale_settings->datatables + ]); } - public function store(Request $request) + + public function store(Request $request, GeneralSettings $generalSettings) { - $this->validate($request, [ - 'title' => 'required', - 'ticketcategory' => 'required', - 'priority' => 'required', - 'message' => 'required',] - ); - $ticket = new Ticket([ + if (RateLimiter::tooManyAttempts('ticket-send:'.Auth::user()->id, $perMinute = 1)) { + return redirect()->back()->with('error', __('Please wait before creating a new Ticket')); + } + + $validateData = [ + 'title' => 'required|string|max:255', + 'ticketcategory' => 'required|numeric', + 'priority' => ['required', 'in:Low,Medium,High'], + 'message' => 'required|string|min:10|max:2000', + ]; + + if ($generalSettings->recaptcha_enabled) { + $validateData['g-recaptcha-response'] = ['required', 'recaptcha']; + } + + $this->validate($request, $validateData); + + $ticket = new Ticket( + [ 'title' => $request->input('title'), 'user_id' => Auth::user()->id, 'ticket_id' => strtoupper(Str::random(8)), @@ -42,29 +65,27 @@ public function store(Request $request) 'priority' => $request->input('priority'), 'message' => $request->input('message'), 'status' => 'Open', - 'server' => $request->input('server'),] + 'server' => $request->input('server'), + ] ); $ticket->save(); $user = Auth::user(); - if (config('SETTINGS::TICKET:NOTIFY') == "all") { - $admin = User::where('role', 'admin')->orWhere('role', 'mod')->get(); - } - if (config('SETTINGS::TICKET:NOTIFY') == "admin") { - $admin = User::where('role', 'admin')->get(); - } - if (config('SETTINGS::TICKET:NOTIFY') == "moderator") { - $admin = User::where('role', 'mod')->get(); + + $staffNotify = User::permission('admin.tickets.get_notification')->get(); + foreach($staffNotify as $staff){ + Notification::send($staff, new AdminCreateNotification($ticket, $user)); } + + $user->notify(new CreateNotification($ticket)); - if (config('SETTINGS::TICKET:NOTIFY') != "none") { - Notification::send($admin, new AdminCreateNotification($ticket, $user)); - } + RateLimiter::hit('ticket-send:'.Auth::user()->id); return redirect()->route('ticket.index')->with('success', __('A ticket has been opened, ID: #') . $ticket->ticket_id); } - public function show($ticket_id) + public function show($ticket_id, PterodactylSettings $ptero_settings) { + $this->checkPermission(self::READ_PERMISSION); try { $ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail(); } catch (Exception $e) { @@ -73,12 +94,16 @@ public function show($ticket_id) $ticketcomments = $ticket->ticketcomments; $ticketcategory = $ticket->ticketcategory; $server = Server::where('id', $ticket->server)->first(); + $pterodactyl_url = $ptero_settings->panel_url; - return view('ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server')); + return view('ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server', 'pterodactyl_url')); } public function reply(Request $request) { + if (RateLimiter::tooManyAttempts('ticket-reply:'.Auth::user()->id, $perMinute = 1)) { + return redirect()->back()->with('error', __('Please wait before answering a Ticket')); + } //check in blacklist $check = TicketBlacklist::where('user_id', Auth::user()->id)->first(); if ($check && $check->status == 'True') { @@ -91,6 +116,7 @@ public function reply(Request $request) return redirect()->back()->with('warning', __('Ticket not found on the server. It potentially got deleted earlier')); } $ticket->status = 'Client Reply'; + $ticket->updated_at = now(); $ticket->update(); $ticketcomment = TicketComment::create([ 'ticket_id' => $request->input('ticket_id'), @@ -99,15 +125,19 @@ public function reply(Request $request) 'message' => $request->input('message'), ]); $user = Auth::user(); - $admin = User::where('role', 'admin')->orWhere('role', 'mod')->get(); $newmessage = $request->input('ticketcomment'); - Notification::send($admin, new AdminReplyNotification($ticket, $user, $newmessage)); + $staffNotify = User::permission('admin.tickets.get_notification')->get(); + foreach($staffNotify as $staff){ + Notification::send($staff, new AdminReplyNotification($ticket, $user, $newmessage)); + } + RateLimiter::hit('ticket-reply:'.Auth::user()->id); return redirect()->back()->with('success', __('Your comment has been submitted')); } public function create() { + $this->checkPermission(self::WRITE_PERMISSION); //check in blacklist $check = TicketBlacklist::where('user_id', Auth::user()->id)->first(); if ($check && $check->status == 'True') { @@ -170,8 +200,10 @@ public function dataTable() return __($tickets->priority); }) ->editColumn('updated_at', function (Ticket $tickets) { - return ['display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '', - 'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : '']; + return [ + 'display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '', + 'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : '' + ]; }) ->addColumn('actions', function (Ticket $tickets) { $statusButtonColor = ($tickets->status == "Closed") ? 'btn-success' : 'btn-warning'; diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 3e372e091..c334a067b 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -4,9 +4,7 @@ use App\Http\Middleware\ApiAuthToken; use App\Http\Middleware\CheckSuspended; -use App\Http\Middleware\GlobalNames; -use App\Http\Middleware\isAdmin; -use App\Http\Middleware\isMod; +use App\Http\Middleware\InstallerLock; use App\Http\Middleware\LastSeen; use Illuminate\Foundation\Http\Kernel as HttpKernel; @@ -27,6 +25,7 @@ class Kernel extends HttpKernel \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, + ]; /** @@ -36,6 +35,7 @@ class Kernel extends HttpKernel */ protected $middlewareGroups = [ 'web' => [ + InstallerLock::class, \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, @@ -43,14 +43,12 @@ class Kernel extends HttpKernel \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, LastSeen::class, - GlobalNames::class, \App\Http\Middleware\SetLocale::class, ], 'api' => [ 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, - GlobalNames::class, ], ]; @@ -72,9 +70,11 @@ class Kernel extends HttpKernel 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, - 'admin' => isAdmin::class, - 'moderator' => isMod::class, 'api.token' => ApiAuthToken::class, 'checkSuspended' => CheckSuspended::class, + 'role' => \Spatie\Permission\Middleware\RoleMiddleware::class, + 'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class, + 'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class, ]; + } diff --git a/app/Http/Middleware/GlobalNames.php b/app/Http/Middleware/GlobalNames.php deleted file mode 100644 index 4874a2f61..000000000 --- a/app/Http/Middleware/GlobalNames.php +++ /dev/null @@ -1,27 +0,0 @@ -role == 'admin') { - return $next($request); - } - - return redirect(RouteServiceProvider::HOME); - } -} diff --git a/app/Http/Middleware/isMod.php b/app/Http/Middleware/isMod.php deleted file mode 100644 index c9120719c..000000000 --- a/app/Http/Middleware/isMod.php +++ /dev/null @@ -1,27 +0,0 @@ -role == 'moderator' || Auth::user() && Auth::user()->role == 'admin') { - return $next($request); - } - - return redirect(RouteServiceProvider::HOME); - } -} diff --git a/app/Listeners/CouponUsed.php b/app/Listeners/CouponUsed.php new file mode 100644 index 000000000..c9abb42bc --- /dev/null +++ b/app/Listeners/CouponUsed.php @@ -0,0 +1,61 @@ +delete_coupon_on_expires = $couponSettings->delete_coupon_on_expires; + $this->delete_coupon_on_uses_reached = $couponSettings->delete_coupon_on_uses_reached; + } + + /** + * Handle the event. + * + * @param \App\Events\CouponUsedEvent $event + * @return void + */ + public function handle(CouponUsedEvent $event) + { + // Automatically increments the coupon usage. + $this->incrementUses($event); + + if ($this->delete_coupon_on_expires) { + if (!is_null($event->coupon->expired_at)) { + if ($event->coupon->expires_at <= Carbon::now()->timestamp) { + $event->coupon->delete(); + } + } + } + + if ($this->delete_coupon_on_uses_reached) { + if ($event->coupon->uses >= $event->coupon->max_uses) { + $event->coupon->delete(); + } + } + } + + /** + * Increments the use of a coupon. + * + * @param \App\Events\CouponUsedEvent $event + */ + private function incrementUses(CouponUsedEvent $event) + { + $event->coupon->increment('uses'); + $event->coupon->save(); + } +} diff --git a/app/Listeners/UserPayment.php b/app/Listeners/UserPayment.php index be9470874..cb75f589f 100644 --- a/app/Listeners/UserPayment.php +++ b/app/Listeners/UserPayment.php @@ -2,15 +2,52 @@ namespace App\Listeners; +use App\Enums\PaymentStatus; use App\Events\PaymentEvent; use App\Models\User; +use App\Settings\DiscordSettings; use Illuminate\Support\Facades\DB; use App\Models\PartnerDiscount; -use Illuminate\Contracts\Queue\ShouldQueue; -use Illuminate\Queue\InteractsWithQueue; +use App\Settings\GeneralSettings; +use App\Settings\ReferralSettings; +use App\Settings\UserSettings; class UserPayment { + private $server_limit_after_irl_purchase; + + private $referral_mode; + + private $referral_percentage; + + private $referral_always_give_commission; + + private $credits_display_name; + + private $role_id_on_purchase; + + private $role_on_purchase; + + private $bot_token; + + /** + * Create the event listener. + * + * @return void + */ + public function __construct(UserSettings $user_settings, ReferralSettings $referral_settings, GeneralSettings $general_settings, DiscordSettings $discord_settings) + { + $this->server_limit_after_irl_purchase = $user_settings->server_limit_after_irl_purchase; + $this->referral_mode = $referral_settings->mode; + $this->referral_percentage = $referral_settings->percentage; + $this->referral_always_give_commission = $referral_settings->always_give_commission; + $this->credits_display_name = $general_settings->credits_display_name; + $this->role_id_on_purchase = $discord_settings->role_id_on_purchase; + $this->role_on_purchase = $discord_settings->role_on_purchase; + $this->bot_token = $discord_settings->bot_token; + + } + /** * Handle the event. * @@ -23,15 +60,16 @@ public function handle(PaymentEvent $event) $shopProduct = $event->shopProduct; // only update user if payment is paid - if ($event->payment->status != "paid") { + if ($event->payment->status != PaymentStatus::PAID) { return; } //update server limit - if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0 && $user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) { - $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]); + if ($this->server_limit_after_irl_purchase !== 0 && $user->server_limit < $this->server_limit_after_irl_purchase) { + $user->update(['server_limit' => $this->server_limit_after_irl_purchase]); } + //update User with bought item if ($shopProduct->type == "Credits") { $user->increment('credits', $shopProduct->quantity); @@ -40,39 +78,51 @@ public function handle(PaymentEvent $event) } //give referral commission always - if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "true") { + if (($this->referral_mode === "commission" || $this->referral_mode === "both") && $shopProduct->type == "Credits" && $this->referral_always_give_commission) { if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) { $ref_user = User::findOrFail($ref_user->referral_id); - $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", ""); + $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id, $this->referral_percentage)) / 100, 0, "", ""); $ref_user->increment('credits', $increment); //LOGS REFERRALS IN THE ACTIVITY LOG activity() ->performedOn($user) ->causedBy($ref_user) - ->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')'); + ->log('gained ' . $increment . ' ' . $this->credits_display_name . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')'); } } //update role give Referral-reward - if ($user->role == 'member') { - $user->update(['role' => 'client']); + if ($user->hasRole(4)) { + $user->syncRoles(3); //give referral commission only on first purchase - if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "false") { + if (($this->referral_mode === "commission" || $this->referral_mode === "both") && $shopProduct->type == "Credits" && !$this->referral_always_give_commission) { if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) { $ref_user = User::findOrFail($ref_user->referral_id); - $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", ""); + $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id, $this->referral_percentage)) / 100, 0, "", ""); $ref_user->increment('credits', $increment); //LOGS REFERRALS IN THE ACTIVITY LOG activity() ->performedOn($user) ->causedBy($ref_user) - ->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')'); + ->log('gained ' . $increment . ' ' . $this->credits_display_name . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')'); } } } + //set discord role + if(!empty($this->bot_token) && $this->role_on_purchase && !empty($this->role_id_on_purchase)) { + $discordUser = $user->discordUser; + $discordUser->addOrRemoveRole('add', $this->role_id_on_purchase); + + activity() + ->performedOn($user) + ->causedBy($user) + ->log('was added to role ' . $this->role_id_on_purchase . " on Discord"); + } + + // LOGS PAYMENT IN THE ACTIVITY LOG activity() ->performedOn($user) diff --git a/app/Listeners/Verified.php b/app/Listeners/Verified.php index d0afa9b94..c6e759127 100644 --- a/app/Listeners/Verified.php +++ b/app/Listeners/Verified.php @@ -2,16 +2,22 @@ namespace App\Listeners; +use App\Settings\UserSettings; + class Verified { + private $server_limit_after_verify_email; + private $credits_reward_after_verify_email; + /** * Create the event listener. * * @return void */ - public function __construct() + public function __construct(UserSettings $user_settings) { - // + $this->server_limit_after_verify_email = $user_settings->server_limit_after_verify_email; + $this->credits_reward_after_verify_email = $user_settings->credits_reward_after_verify_email; } /** @@ -23,8 +29,8 @@ public function __construct() public function handle($event) { if (!$event->user->email_verified_reward) { - $event->user->increment('server_limit', config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL')); - $event->user->increment('credits', config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL')); + $event->user->increment('server_limit', $this->server_limit_after_verify_email); + $event->user->increment('credits', $this->credits_reward_after_verify_email); $event->user->update(['email_verified_reward' => true]); } } diff --git a/app/Models/Coupon.php b/app/Models/Coupon.php new file mode 100644 index 000000000..8cd02621c --- /dev/null +++ b/app/Models/Coupon.php @@ -0,0 +1,119 @@ +logOnlyDirty() + ->logOnly(['*']) + ->dontSubmitEmptyLogs(); + } + + /** + * @var string[] + */ + protected $fillable = [ + 'code', + 'type', + 'value', + 'uses', + 'max_uses', + 'expires_at' + ]; + + /** + * @var string[] + */ + protected $casts = [ + 'value' => 'float', + 'uses' => 'integer', + 'max_uses' => 'integer', + 'expires_at' => 'timestamp' + ]; + + /** + * Returns the date format used by the coupons. + * + * @return string + */ + public static function formatDate(): string + { + return 'Y-MM-DD HH:mm:ss'; + } + + /** + * Returns the current state of the coupon. + * + * @return string + */ + public function getStatus() + { + if ($this->uses >= $this->max_uses) { + return 'USES_LIMIT_REACHED'; + } + + if (!is_null($this->expires_at)) { + if ($this->expires_at <= Carbon::now(config('app.timezone'))->timestamp) { + return __('EXPIRED'); + } + } + + return __('VALID'); + } + + /** + * Check if a user has already exceeded the uses of a coupon. + * + * @param User $user The request being made. + * + * @return bool + */ + public function isMaxUsesReached($user): bool + { + $coupon_settings = new CouponSettings; + $coupon_uses = $user->coupons()->where('id', $this->id)->count(); + + return $coupon_uses >= $coupon_settings->max_uses_per_user; + } + + /** + * Generate a specified quantity of coupon codes. + * + * @param int $amount Amount of coupons to be generated. + * + * @return array + */ + public static function generateRandomCoupon(int $amount = 10): array + { + $coupons = []; + + for ($i = 0; $i < $amount; $i++) { + $random_coupon = strtoupper(bin2hex(random_bytes(3))); + + $coupons[] = $random_coupon; + } + + return $coupons; + } + + /** + * @return BelongsToMany + */ + public function users() + { + return $this->belongsToMany(User::class, 'user_coupons'); + } +} diff --git a/app/Models/DiscordUser.php b/app/Models/DiscordUser.php index 03051ea32..fd2940c1d 100644 --- a/app/Models/DiscordUser.php +++ b/app/Models/DiscordUser.php @@ -2,9 +2,11 @@ namespace App\Models; +use App\Settings\DiscordSettings; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Support\Facades\Http; class DiscordUser extends Model { @@ -42,4 +44,39 @@ public function getAvatar() { return 'https://cdn.discordapp.com/avatars/'.$this->id.'/'.$this->avatar.'.png'; } + + + /** + * Add or remove role on discord server + * @param string $action The action to perform (add or remove) + * @param string $role_id The Role ID to add or remove + * @return mixed + */ + public function addOrRemoveRole(string $action, string $role_id): mixed + { + $discordSettings = app(DiscordSettings::class); + return match ($action) { + 'add' => Http::withHeaders( + [ + 'Authorization' => 'Bot ' . $discordSettings->bot_token, + 'Content-Type' => 'application/json', + 'X-Audit-Log-Reason' => 'Role added by panel' + ] + )->put( + "https://discord.com/api/guilds/{$discordSettings->guild_id}/members/{$this->id}/roles/{$discordSettings->role_id}", + ['access_token' => $discordSettings->bot_token] + ), + 'remove' => Http::withHeaders( + [ + 'Authorization' => 'Bot ' . $discordSettings->bot_token, + 'Content-Type' => 'application/json', + 'X-Audit-Log-Reason' => 'Role removed by panel' + ] + )->remove( + "https://discord.com/api/guilds/{$discordSettings->guild_id}/members/{$this->id}/roles/{$discordSettings->role_id}", + ['access_token' => $discordSettings->bot_token] + ), + default => null, + }; + } } diff --git a/app/Models/Location.php b/app/Models/Location.php index a020c73f5..1447c6b20 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -52,7 +52,7 @@ public static function syncLocations() ], [ 'name' => $location['name'], - 'description' => $location['name'], + 'description' => $location['description'], ] ); } diff --git a/app/Models/Permission.php b/app/Models/Permission.php new file mode 100644 index 000000000..38ed7d427 --- /dev/null +++ b/app/Models/Permission.php @@ -0,0 +1,22 @@ + + */ + protected $fillable = [ + 'name', + 'guard_name', + 'readable_name' + ]; +} diff --git a/app/Models/Product.php b/app/Models/Product.php index a31ebf50a..195eccaa0 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -43,12 +43,46 @@ public static function boot() public function getHourlyPrice() { - return ($this->price / 30) / 24; + // calculate the hourly price with the billing period + switch($this->billing_period) { + case 'daily': + return $this->price / 24; + case 'weekly': + return $this->price / 24 / 7; + case 'monthly': + return $this->price / 24 / 30; + case 'quarterly': + return $this->price / 24 / 30 / 3; + case 'half-annually': + return $this->price / 24 / 30 / 6; + case 'annually': + return $this->price / 24 / 365; + default: + return $this->price; + } } - public function getDailyPrice() + public function getMonthlyPrice() { - return $this->price / 30; + // calculate the hourly price with the billing period + switch($this->billing_period) { + case 'hourly': + return $this->price * 24 * 30; + case 'daily': + return $this->price * 30; + case 'weekly': + return $this->price * 4; + case 'monthly': + return $this->price; + case 'quarterly': + return $this->price / 3; + case 'half-annually': + return $this->price / 6; + case 'annually': + return $this->price / 12; + default: + return $this->price; + } } public function getWeeklyPrice() diff --git a/app/Models/Role.php b/app/Models/Role.php new file mode 100644 index 000000000..a3b7e6e10 --- /dev/null +++ b/app/Models/Role.php @@ -0,0 +1,23 @@ + + */ + protected $fillable = [ + 'name', + 'guard_name', + 'power', + 'color' + ]; +} diff --git a/app/Models/Server.php b/app/Models/Server.php index 94365dd47..bd70c5367 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -2,7 +2,9 @@ namespace App\Models; -use App\Classes\Pterodactyl; +use Carbon\Carbon; +use App\Classes\PterodactylClient; +use App\Settings\PterodactylSettings; use Exception; use GuzzleHttp\Promise\PromiseInterface; use Hidehalo\Nanoid\Client; @@ -21,13 +23,17 @@ class Server extends Model { use HasFactory; use LogsActivity; + + private PterodactylClient $pterodactyl; + public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() - -> logOnlyDirty() - -> logOnly(['*']) - -> dontSubmitEmptyLogs(); + ->logOnlyDirty() + ->logOnly(['*']) + ->dontSubmitEmptyLogs(); } + /** * @var bool */ @@ -47,12 +53,14 @@ public function getActivitylogOptions(): LogOptions * @var string[] */ protected $fillable = [ - 'name', - 'description', - 'suspended', - 'identifier', - 'product_id', - 'pterodactyl_id', + "name", + "description", + "suspended", + "identifier", + "product_id", + "pterodactyl_id", + "last_billed", + "canceled" ]; /** @@ -62,6 +70,14 @@ public function getActivitylogOptions(): LogOptions 'suspended' => 'datetime', ]; + public function __construct() + { + parent::__construct(); + + $ptero_settings = new PterodactylSettings(); + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + public static function boot() { parent::boot(); @@ -73,8 +89,8 @@ public static function boot() }); static::deleting(function (Server $server) { - $response = Pterodactyl::client()->delete("/application/servers/{$server->pterodactyl_id}"); - if ($response->failed() && ! is_null($server->pterodactyl_id)) { + $response = $server->pterodactyl->application->delete("/application/servers/{$server->pterodactyl_id}"); + if ($response->failed() && !is_null($server->pterodactyl_id)) { //only return error when it's not a 404 error if ($response['errors'][0]['status'] != '404') { throw new Exception($response['errors'][0]['code']); @@ -88,7 +104,7 @@ public static function boot() */ public function isSuspended() { - return ! is_null($this->suspended); + return !is_null($this->suspended); } /** @@ -96,7 +112,7 @@ public function isSuspended() */ public function getPterodactylServer() { - return Pterodactyl::client()->get("/application/servers/{$this->pterodactyl_id}"); + return $this->pterodactyl->application->get("/application/servers/{$this->pterodactyl_id}"); } /** @@ -104,7 +120,7 @@ public function getPterodactylServer() */ public function suspend() { - $response = Pterodactyl::suspendServer($this); + $response = $this->pterodactyl->suspendServer($this); if ($response->successful()) { $this->update([ @@ -120,14 +136,16 @@ public function suspend() */ public function unSuspend() { - $response = Pterodactyl::unSuspendServer($this); + $response = $this->pterodactyl->unSuspendServer($this); if ($response->successful()) { $this->update([ 'suspended' => null, + 'last_billed' => Carbon::now()->toDateTimeString(), ]); } + return $this; } diff --git a/app/Models/ShopProduct.php b/app/Models/ShopProduct.php index cfe3f7838..278183dc8 100644 --- a/app/Models/ShopProduct.php +++ b/app/Models/ShopProduct.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Settings\GeneralSettings; use Hidehalo\Nanoid\Client; use Illuminate\Database\Eloquent\Model; use NumberFormatter; @@ -36,6 +37,13 @@ public function getActivitylogOptions(): LogOptions 'disabled', ]; + /** + * @var string[] + */ + protected $casts = [ + 'price' => 'float' + ]; + public static function boot() { parent::boot(); @@ -66,14 +74,17 @@ public function formatToCurrency($value, $locale = 'en_US') */ public function getTaxPercent() { - $tax = config('SETTINGS::PAYMENTS:SALES_TAX'); + $generalSettings = new GeneralSettings(); + $tax = intval($generalSettings->sales_tax); return $tax < 0 ? 0 : $tax; } public function getPriceAfterDiscount() { - return number_format($this->price - ($this->price * PartnerDiscount::getDiscount() / 100), 2); + $discountRate = PartnerDiscount::getDiscount() / 100; + $discountedPrice = $this->price * (1 - $discountRate); + return round($discountedPrice, 2); } /** @@ -83,7 +94,8 @@ public function getPriceAfterDiscount() */ public function getTaxValue() { - return number_format($this->getPriceAfterDiscount() * $this->getTaxPercent() / 100, 2); + $taxValue = $this->getPriceAfterDiscount() * $this->getTaxPercent() / 100; + return round($taxValue, 2); } /** @@ -93,6 +105,7 @@ public function getTaxValue() */ public function getTotalPrice() { - return number_format($this->getPriceAfterDiscount() + $this->getTaxValue(), 2); + $total = $this->getPriceAfterDiscount() + $this->getTaxValue(); + return round($total, 2); } } diff --git a/app/Models/User.php b/app/Models/User.php index c20c50baa..350e73bd0 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,9 +2,10 @@ namespace App\Models; -use App\Classes\Pterodactyl; use App\Notifications\Auth\QueuedVerifyEmail; use App\Notifications\WelcomeMessage; +use App\Classes\PterodactylClient; +use App\Settings\PterodactylSettings; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -12,16 +13,22 @@ use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\RateLimiter; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\CausesActivity; use Spatie\Activitylog\Traits\LogsActivity; +use Spatie\Permission\Traits\HasRoles; /** * Class User */ class User extends Authenticatable implements MustVerifyEmail { - use HasFactory, Notifiable, LogsActivity, CausesActivity; + use HasFactory, Notifiable, LogsActivity, CausesActivity, HasRoles; + + private PterodactylClient $pterodactyl; /** * @var string[] @@ -61,7 +68,7 @@ class User extends Authenticatable implements MustVerifyEmail 'avatar', 'suspended', 'referral_code', - 'email_verified_reward' + 'email_verified_reward', ]; /** @@ -87,6 +94,14 @@ class User extends Authenticatable implements MustVerifyEmail 'email_verified_reward' => 'boolean' ]; + public function __construct() + { + parent::__construct(); + + $ptero_settings = new PterodactylSettings(); + $this->pterodactyl = new PterodactylClient($ptero_settings); + } + public static function boot() { parent::boot(); @@ -113,7 +128,7 @@ public static function boot() $user->discordUser()->delete(); - Pterodactyl::client()->delete("/application/users/{$user->pterodactyl_id}"); + $user->pterodactyl->application->delete("/application/users/{$user->pterodactyl_id}"); }); } @@ -157,6 +172,14 @@ public function vouchers() return $this->belongsToMany(Voucher::class); } + /** + * @return BelongsToMany + */ + public function coupons() + { + return $this->belongsToMany(Coupon::class, 'user_coupons'); + } + /** * @return HasOne */ @@ -167,7 +190,24 @@ public function discordUser() public function sendEmailVerificationNotification() { - $this->notify(new QueuedVerifyEmail); + try { + // Rate limit the email verification notification to 5 attempt per 30 minutes + $executed = RateLimiter::attempt( + key: 'verify-mail' . $this->id, + maxAttempts: 5, + callback: function () { + $this->notify(new QueuedVerifyEmail); + }, + decaySeconds: 1800 + ); + + if (!$executed) { + return redirect()->back()->with('error', 'Too many requests. Try again in ' . RateLimiter::availableIn('verify-mail:' . $this->id) . ' seconds.'); + } + }catch (\Exception $exception){ + Log::error($exception->getMessage()); + return redirect()->back()->with('error', __("Something went wrong. Please try again later!")); + } } /** @@ -186,9 +226,6 @@ public function isSuspended() return $this->suspended; } - /** - * @throws Exception - */ public function suspend() { foreach ($this->servers as $server) { @@ -202,9 +239,6 @@ public function suspend() return $this; } - /** - * @throws Exception - */ public function unSuspend() { foreach ($this->getServersWithProduct() as $server) { @@ -220,45 +254,34 @@ public function unSuspend() return $this; } - private function getServersWithProduct() - { - return $this->servers() - ->with('product') - ->get(); - } /** * @return string */ public function getAvatar() { - //TODO loading the images to confirm they exist is causing to much load time. alternative has to be found :) maybe onerror tag on the - // if ($this->discordUser()->exists()) { - // if(@getimagesize($this->discordUser->getAvatar())) { - // $avatar = $this->discordUser->getAvatar(); - // } else { - // $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email))); - // } - // } else { - // $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email))); - // } - return 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($this->email))); } - /** - * @return string - */ public function creditUsage() { $usage = 0; foreach ($this->getServersWithProduct() as $server) { - $usage += $server->product->price; + $usage += $server->product->getHourlyPrice() * 24 * 30; } return number_format($usage, 2, '.', ''); } + private function getServersWithProduct() + { + return $this->servers() + ->whereNull('suspended') + ->whereNull('canceled') + ->with('product') + ->get(); + } + /** * @return array|string|string[] */ @@ -279,7 +302,7 @@ public function getVerifiedStatus() public function verifyEmail() { $this->forceFill([ - 'email_verified_at' => now(), + 'email_verified_at' => now() ])->save(); } @@ -290,6 +313,17 @@ public function reVerifyEmail() ])->save(); } + public function referredBy() + { + $referee = DB::table('user_referrals')->where("registered_user_id", $this->id)->first(); + + if ($referee) { + $referee = User::where("id", $referee->referral_id)->firstOrFail(); + return $referee; + } + return Null; + } + public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() diff --git a/app/Notifications/ReferralNotification.php b/app/Notifications/ReferralNotification.php index dec1ea0e7..f8acbcf52 100644 --- a/app/Notifications/ReferralNotification.php +++ b/app/Notifications/ReferralNotification.php @@ -3,6 +3,8 @@ namespace App\Notifications; use App\Models\User; +use App\Settings\GeneralSettings; +use App\Settings\ReferralSettings; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; @@ -15,6 +17,12 @@ class ReferralNotification extends Notification */ private $user; + private $ref_user; + + private $reward; + + private $credits_display_name; + /** * Create a new notification instance. * @@ -22,6 +30,11 @@ class ReferralNotification extends Notification */ public function __construct(int $user, int $ref_user) { + $general_settings= new GeneralSettings(); + $referral_settings = new ReferralSettings(); + + $this->credits_display_name = $general_settings->credits_display_name; + $this->reward = $referral_settings->reward; $this->user = User::findOrFail($user); $this->ref_user = User::findOrFail($ref_user); } @@ -48,8 +61,8 @@ public function toArray($notifiable) return [ 'title' => __('Someone registered using your Code!'), 'content' => ' -

You received '.config('SETTINGS::REFERRAL::REWARD').' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').'

-

because '.$this->ref_user->name.' registered with your Referral-Code!

+

You received '. $this->reward . ' ' . $this->credits_display_name . '

+

because ' . $this->ref_user->name . ' registered with your Referral-Code!

Thank you very much for supporting us!.

'.config('app.name', 'Laravel').'

', diff --git a/app/Notifications/WelcomeMessage.php b/app/Notifications/WelcomeMessage.php index d6aa073b6..83ab1317a 100644 --- a/app/Notifications/WelcomeMessage.php +++ b/app/Notifications/WelcomeMessage.php @@ -23,6 +23,9 @@ class WelcomeMessage extends Notification implements ShouldQueue */ public function __construct(User $user) { + $general_settings= new GeneralSettings(); + $user_settings = new UserSettings(); + $this->user = $user; } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 6299bf4f3..cfef99b9d 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,17 +2,21 @@ namespace App\Providers; -use App\Models\Settings; use App\Models\UsefulLink; +use App\Settings\DiscordSettings; +use App\Settings\GeneralSettings; +use App\Settings\MailSettings; use Exception; use Illuminate\Pagination\Paginator; -use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; +use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\Validator; use Illuminate\Support\ServiceProvider; use Qirolab\Theme\Theme; + class AppServiceProvider extends ServiceProvider { /** @@ -35,6 +39,10 @@ public function boot() Paginator::useBootstrap(); Schema::defaultStringLength(191); + Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) { + $event->extendSocialite('discord', \SocialiteProviders\Discord\Provider::class); + }); + Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) { $ok = true; $result = []; @@ -54,6 +62,29 @@ public function boot() return $ok; }); + // Force HTTPS if APP_URL is set to https + if (config('app.url') && parse_url(config('app.url'), PHP_URL_SCHEME) === 'https') { + URL::forceScheme('https'); + } + + //get the Github Branch the panel is running on + try { + $stringfromfile = file(base_path() . '/.git/HEAD'); + + $firstLine = $stringfromfile[0]; //get the string from the array + + $explodedstring = explode('/', $firstLine, 3); //seperate out by the "/" in the string + + $branchname = $explodedstring[2]; //get the one that is always the branch name + } catch (Exception $e) { + $branchname = 'unknown'; + Log::notice($e); + } + config(['BRANCHNAME' => $branchname]); + + // Do not run this code if no APP_KEY is set + if (config('app.key') == null) return; + try { if (Schema::hasColumn('useful_links', 'position')) { $useful_links = UsefulLink::where("position", "like", "%topbar%")->get()->sortby("id"); @@ -63,92 +94,24 @@ public function boot() Log::error("Couldnt find useful_links. Probably the installation is not completet. " . $e); } - //only run if the installer has been executed - try { - $settings = Settings::all(); - // Set all configs from database - foreach ($settings as $setting) { - config([$setting->key => $setting->value]); - } - if (!file_exists(base_path('themes') . "/" . config("SETTINGS::SYSTEM:THEME"))) { - config(['SETTINGS::SYSTEM:THEME' => "default"]); + try { + $generalSettings = $this->app->make(GeneralSettings::class); + if (!file_exists(base_path('themes') . "/" . $generalSettings->theme)) { + $generalSettings->theme = "default"; } - if (config('SETTINGS::SYSTEM:THEME') && config('SETTINGS::SYSTEM:THEME') !== config('theme.active')) { - Theme::set(config("SETTINGS::SYSTEM:THEME", "default"), "default"); + if ($generalSettings->theme && $generalSettings->theme !== config('theme.active')) { + Theme::set($generalSettings->theme, "default"); } else { Theme::set("default", "default"); } - // Set Mail Config - //only update config if mail settings have changed in DB - if ( - config('mail.default') != config('SETTINGS:MAIL:MAILER') || - config('mail.mailers.smtp.host') != config('SETTINGS:MAIL:HOST') || - config('mail.mailers.smtp.port') != config('SETTINGS:MAIL:PORT') || - config('mail.mailers.smtp.username') != config('SETTINGS:MAIL:USERNAME') || - config('mail.mailers.smtp.password') != config('SETTINGS:MAIL:PASSWORD') || - config('mail.mailers.smtp.encryption') != config('SETTINGS:MAIL:ENCRYPTION') || - config('mail.from.address') != config('SETTINGS:MAIL:FROM_ADDRESS') || - config('mail.from.name') != config('SETTINGS:MAIL:FROM_NAME') - ) { - config(['mail.default' => config('SETTINGS::MAIL:MAILER')]); - config(['mail.mailers.smtp' => [ - 'transport' => 'smtp', - 'host' => config('SETTINGS::MAIL:HOST'), - 'port' => config('SETTINGS::MAIL:PORT'), - 'encryption' => config('SETTINGS::MAIL:ENCRYPTION'), - 'username' => config('SETTINGS::MAIL:USERNAME'), - 'password' => config('SETTINGS::MAIL:PASSWORD'), - 'timeout' => null, - 'auth_mode' => null, - ]]); - config(['mail.from' => ['address' => config('SETTINGS::MAIL:FROM_ADDRESS'), 'name' => config('SETTINGS::MAIL:FROM_NAME')]]); - - Artisan::call('queue:restart'); - } - - // Set Recaptcha API Config - // Load recaptcha package if recaptcha is enabled - if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') { - $this->app->register(\Biscolab\ReCaptcha\ReCaptchaServiceProvider::class); - } - - //only update config if recaptcha settings have changed in DB - if ( - config('recaptcha.api_site_key') != config('SETTINGS::RECAPTCHA:SITE_KEY') || - config('recaptcha.api_secret_key') != config('SETTINGS::RECAPTCHA:SECRET_KEY') - ) { - config(['recaptcha.api_site_key' => config('SETTINGS::RECAPTCHA:SITE_KEY')]); - config(['recaptcha.api_secret_key' => config('SETTINGS::RECAPTCHA:SECRET_KEY')]); - - Artisan::call('config:clear'); - Artisan::call('cache:clear'); - } - - try { - $stringfromfile = file(base_path() . '/.git/HEAD'); - - $firstLine = $stringfromfile[0]; //get the string from the array - - $explodedstring = explode('/', $firstLine, 3); //seperate out by the "/" in the string - - $branchname = $explodedstring[2]; //get the one that is always the branch name - } catch (Exception $e) { - $branchname = 'unknown'; - Log::notice($e); - } - config(['BRANCHNAME' => $branchname]); + $settings = $this->app->make(MailSettings::class); + $settings->setConfig(); - // Set Discord-API Config - config(['services.discord.client_id' => config('SETTINGS::DISCORD:CLIENT_ID')]); - config(['services.discord.client_secret' => config('SETTINGS::DISCORD:CLIENT_SECRET')]); } catch (Exception $e) { - error_log('Settings Error: Could not load settings from database. The Installation probably is not done yet.'); - error_log($e); - Log::error('Settings Error: Could not load settings from database. The Installation probably is not done yet.'); - Log::error($e); + Log::error("Couldnt load Settings. Probably the installation is not completet. " . $e); } } } diff --git a/app/Providers/DiscordServiceProvider.php b/app/Providers/DiscordServiceProvider.php new file mode 100644 index 000000000..4d0e7b514 --- /dev/null +++ b/app/Providers/DiscordServiceProvider.php @@ -0,0 +1,41 @@ +app->make(DiscordSettings::class); + // Retrieve Discord settings from the Spatie settings class + + // Inject the settings into the config + Config::set('services.discord.client_id', $discordSettings->client_id ?: ""); + Config::set('services.discord.client_secret', $discordSettings->client_secret ?: ""); + Config::set('services.discord.redirect', env('APP_URL', 'http://localhost') . '/auth/callback'); + + // optional + Config::set('services.discord.allow_gif_avatars', (bool)env('DISCORD_AVATAR_GIF', true)); + Config::set('services.discord.avatar_default_extension', env('DISCORD_EXTENSION_DEFAULT', 'jpg')); + + } catch (Exception $e) { + Log::error("Couldnt find settings. Probably the installation is not completet. " . $e); + } + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 52af48ffe..cc535566a 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -4,15 +4,17 @@ use App\Events\PaymentEvent; use App\Events\UserUpdateCreditsEvent; +use App\Events\CouponUsedEvent; +use App\Listeners\CouponUsed; use App\Listeners\CreateInvoice; use App\Listeners\UnsuspendServers; use App\Listeners\UserPayment; -use App\Listeners\Verified as VerifiedListener; +use App\Listeners\Verified as ListenerVerified; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; +use Illuminate\Auth\Events\Verified; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use SocialiteProviders\Manager\SocialiteWasCalled; -use Illuminate\Auth\Events\Verified; class EventServiceProvider extends ServiceProvider { @@ -32,12 +34,15 @@ class EventServiceProvider extends ServiceProvider CreateInvoice::class, UserPayment::class, ], + CouponUsedEvent::class => [ + CouponUsed::class + ], SocialiteWasCalled::class => [ // ... other providers 'SocialiteProviders\\Discord\\DiscordExtendSocialite@handle', ], Verified::class => [ - VerifiedListener::class, + ListenerVerified::class, ], ]; diff --git a/app/Settings/CouponSettings.php b/app/Settings/CouponSettings.php new file mode 100644 index 000000000..7669b06a3 --- /dev/null +++ b/app/Settings/CouponSettings.php @@ -0,0 +1,64 @@ + + */ + public static function getValidations() + { + return [ + 'enabled' => "nullable|boolean", + 'delete_coupon_on_expires' => 'nullable|boolean', + 'delete_coupon_on_uses_reached' => 'nullable|boolean', + 'max_uses_per_user' => 'nullable|integer', + ]; + } + + /** + * Summary of optionInputData array + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + "category_icon" => "fas fa-ticket-alt", + 'enabled' => [ + 'label' => 'Enable Coupons', + 'type' => 'boolean', + 'description' => 'Enables coupons to be used in the store.' + ], + 'delete_coupon_on_expires' => [ + 'label' => 'Auto Delete Expired Coupons', + 'type' => 'boolean', + 'description' => 'Automatically deletes the coupon if it expires.' + ], + 'delete_coupon_on_uses_reached' => [ + 'label' => 'Delete Coupon When Max Uses Reached', + 'type' => 'boolean', + 'description' => 'Delete a coupon as soon as its maximum usage is reached.' + ], + 'max_uses_per_user' => [ + 'label' => 'Max Uses Per User', + 'type' => 'number', + 'description' => 'Maximum number of uses that a user can make of the same coupon.' + ], + ]; + } +} diff --git a/app/Settings/DiscordSettings.php b/app/Settings/DiscordSettings.php new file mode 100644 index 000000000..c2ad55395 --- /dev/null +++ b/app/Settings/DiscordSettings.php @@ -0,0 +1,97 @@ + + */ + public static function getValidations() + { + return [ + 'bot_token' => 'nullable|string', + 'client_id' => 'nullable|string', + 'client_secret' => 'nullable|string', + 'guild_id' => 'nullable|string', + 'invite_url' => 'nullable|string|url', + 'role_id' => 'nullable|string', + 'role_on_purchase' => 'nullable|string', + 'role_id_on_purchase' => 'nullable|string', + ]; + } + + /** + * Summary of optionInputData array + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-user-friends', + 'bot_token' => [ + 'label' => 'Bot Token', + 'type' => 'string', + 'description' => 'The bot token for your Discord bot.', + ], + 'client_id' => [ + 'label' => 'Client ID', + 'type' => 'string', + 'description' => 'The client ID for your Discord bot.', + ], + 'client_secret' => [ + 'label' => 'Client Secret', + 'type' => 'string', + 'description' => 'The client secret for your Discord bot.', + ], + 'guild_id' => [ + 'label' => 'Guild ID', + 'type' => 'string', + 'description' => 'The guild ID for your Discord server.', + ], + 'invite_url' => [ + 'label' => 'Invite URL', + 'type' => 'string', + 'description' => 'The invite URL for your Discord server.', + ], + 'role_id' => [ + 'label' => 'Role ID', + 'type' => 'string', + 'description' => 'Role to give users when linking their discord Account.', + ], + + 'role_on_purchase' => [ + 'label' => 'Role on Purchase', + 'type' => 'select', + 'options' => [ + '0' => 'Disabled', + '1' => 'Enabled' + ], + 'description' => 'Give the user a role on purchase of Credits/Servers (removes when user has no active servers)', + ], + 'role_id_on_purchase' => [ + 'label' => 'Role ID on Purchase', + 'type' => 'string', + 'description' => 'The role ID for your Discord server on purchase.', + ], + ]; + } +} diff --git a/app/Settings/GeneralSettings.php b/app/Settings/GeneralSettings.php new file mode 100644 index 000000000..1b8e26944 --- /dev/null +++ b/app/Settings/GeneralSettings.php @@ -0,0 +1,129 @@ + + */ + public static function getValidations() + { + return [ + 'store_enabled' => 'nullable|string', + 'sales_tax' => 'nullable|numeric', + 'credits_display_name' => 'required|string', + 'recaptcha_enabled' => 'nullable|string', + 'recaptcha_site_key' => 'nullable|string', + 'recaptcha_secret_key' => 'nullable|string', + 'phpmyadmin_url' => 'nullable|string', + 'alert_enabled' => 'nullable|string', + 'alert_type' => 'required|in:primary,secondary,success,danger,warning,info', + 'alert_message' => 'nullable|string', + 'theme' => 'required|in:default,BlueInfinity' // TODO: themes should be made/loaded dynamically + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => "fas fa-cog", + 'store_enabled' => [ + 'type' => 'boolean', + 'label' => 'Enable Store', + 'description' => 'Enable the store for users to purchase credits.' + ], + 'sales_tax' => [ + 'type' => 'number', + 'label' => 'Sales Tax in %', + 'description' => 'Your countrys sales tax in %' + ], + 'credits_display_name' => [ + 'type' => 'string', + 'label' => 'Credits Display Name', + 'description' => 'The name of the currency used.' + ], + 'recaptcha_enabled' => [ + 'type' => 'boolean', + 'label' => 'Enable reCAPTCHA', + 'description' => 'Enable reCAPTCHA on the login page.' + ], + 'recaptcha_site_key' => [ + 'type' => 'string', + 'label' => 'reCAPTCHA Site Key', + 'description' => 'The site key for reCAPTCHA.' + ], + 'recaptcha_secret_key' => [ + 'type' => 'string', + 'label' => 'reCAPTCHA Secret Key', + 'description' => 'The secret key for reCAPTCHA.' + ], + 'phpmyadmin_url' => [ + 'type' => 'string', + 'label' => 'phpMyAdmin URL', + 'description' => 'The URL of your phpMyAdmin installation.' + ], + 'alert_enabled' => [ + 'type' => 'boolean', + 'label' => 'Enable Alert', + 'description' => 'Enable an alert to be displayed on the home page.' + ], + 'alert_type' => [ + 'type' => 'select', + 'label' => 'Alert Type', + 'options' => [ + 'primary' => 'Blue', + 'secondary' => 'Grey', + 'success' => 'Green', + 'danger' => 'Red', + 'warning' => 'Orange', + 'info' => 'Cyan', + ], + 'description' => 'The type of alert to display.' + ], + 'alert_message' => [ + 'type' => 'textarea', + 'label' => 'Alert Message', + 'description' => 'The message to display in the alert.' + ], + 'theme' => [ + 'type' => 'select', + 'label' => 'Theme', + 'options' => [ + 'default' => 'Default', + 'BlueInfinity' => 'Blue Infinity', + ], // TODO: themes should be made/loaded dynamically + 'description' => 'The theme to use for the site.' + ], + ]; + } +} diff --git a/app/Settings/InvoiceSettings.php b/app/Settings/InvoiceSettings.php new file mode 100644 index 000000000..62ba6f1e3 --- /dev/null +++ b/app/Settings/InvoiceSettings.php @@ -0,0 +1,92 @@ + + */ + public static function getValidations() + { + return [ + 'company_address' => 'nullable|string', + 'company_mail' => 'nullable|string', + 'company_name' => 'nullable|string', + 'company_phone' => 'nullable|string', + 'company_vat' => 'nullable|string', + 'company_website' => 'nullable|string', + 'enabled' => 'nullable|string', + 'prefix' => 'nullable|string', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-file-invoice-dollar', + 'company_address' => [ + 'label' => 'Company Address', + 'type' => 'string', + 'description' => 'The address of your company.', + ], + 'company_mail' => [ + 'label' => 'Company Mail', + 'type' => 'string', + 'description' => 'The mail of your company.', + ], + 'company_name' => [ + 'label' => 'Company Name', + 'type' => 'string', + 'description' => 'The name of your company.', + ], + 'company_phone' => [ + 'label' => 'Company Phone', + 'type' => 'string', + 'description' => 'The phone of your company.', + ], + 'company_vat' => [ + 'label' => 'Company VAT ID', + 'type' => 'string', + 'description' => 'The VAT ID of your company.', + ], + 'company_website' => [ + 'label' => 'Company Website', + 'type' => 'string', + 'description' => 'The website of your company.', + ], + 'enabled' => [ + 'label' => 'Enabled', + 'type' => 'boolean', + 'description' => 'Enable or disable invoices.', + ], + 'prefix' => [ + 'label' => 'Prefix', + 'type' => 'string', + 'description' => 'The prefix of your invoices.', + ], + ]; + } +} diff --git a/app/Settings/LocaleSettings.php b/app/Settings/LocaleSettings.php new file mode 100644 index 000000000..32006f572 --- /dev/null +++ b/app/Settings/LocaleSettings.php @@ -0,0 +1,74 @@ + + */ + public static function getValidations() + { + return [ + 'available' => 'array|required', + 'clients_can_change' => 'nullable|string', + 'datatables' => 'nullable|string', + 'default' => 'required|in:' . implode(',', config('app.available_locales')), + 'dynamic' => 'nullable|string', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-globe', + 'available' => [ + 'label' => 'Available Locales', + 'type' => 'multiselect', + 'description' => 'The locales that are available for the user to choose from.', + 'options' => config('app.available_locales'), + ], + 'clients_can_change' => [ + 'label' => 'Clients Can Change', + 'type' => 'boolean', + 'description' => 'Whether clients can change their locale.', + ], + 'datatables' => [ + 'label' => 'Datatables Locale', + 'type' => 'string', + 'description' => 'The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: https://datatables.net/plug-ins/i18n/', + ], + 'default' => [ + 'label' => 'Default Locale', + 'type' => 'select', + 'description' => 'The default locale to use.', + 'options' => config('app.available_locales'), + 'identifier' => 'display' + ], + 'dynamic' => [ + 'label' => 'Dynamic Locale', + 'type' => 'boolean', + 'description' => 'Whether to choose the language automatically based on the Geolocation of the client.', + ], + ]; + } +} diff --git a/app/Settings/MailSettings.php b/app/Settings/MailSettings.php new file mode 100644 index 000000000..75bc106ff --- /dev/null +++ b/app/Settings/MailSettings.php @@ -0,0 +1,119 @@ +set('mail.mailers.smtp.host', $this->mail_host); + config()->set('mail.mailers.smtp.port', $this->mail_port); + config()->set('mail.mailers.smtp.encryption', $this->mail_encryption); + config()->set('mail.mailers.smtp.username', $this->mail_username); + config()->set('mail.mailers.smtp.password', $this->mail_password); + config()->set('mail.from.address', $this->mail_from_address); + config()->set('mail.from.name', $this->mail_from_name); + } catch (\Exception) { + } + } + + /** + * Summary of validations array + * @return array + */ + public static function getValidations() + { + return [ + 'mail_host' => 'nullable|string', + 'mail_port' => 'nullable|int', + 'mail_username' => 'nullable|string', + 'mail_password' => 'nullable|string', + 'mail_encryption' => 'nullable|string', + 'mail_from_address' => 'nullable|string', + 'mail_from_name' => 'nullable|string', + 'mail_mailer' => 'nullable|string', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-envelope', + 'mail_host' => [ + 'label' => 'Mail Host', + 'type' => 'string', + 'description' => 'The host of your mail server.', + ], + 'mail_port' => [ + 'label' => 'Mail Port', + 'type' => 'number', + 'description' => 'The port of your mail server.', + ], + 'mail_username' => [ + 'label' => 'Mail Username', + 'type' => 'string', + 'description' => 'The username of your mail server.', + ], + 'mail_password' => [ + 'label' => 'Mail Password', + 'type' => 'password', + 'description' => 'The password of your mail server.', + ], + 'mail_encryption' => [ + 'label' => 'Mail Encryption', + 'type' => 'select', + 'options' => [ + 'null' => 'None', + 'tls' => 'TLS', + 'ssl' => 'SSL' + ], + 'description' => 'The encryption of your mail server.', + ], + 'mail_from_address' => [ + 'label' => 'Mail From Address', + 'type' => 'string', + 'description' => 'The from address of your mail server.', + ], + 'mail_from_name' => [ + 'label' => 'Mail From Name', + 'type' => 'string', + 'description' => 'The from name of your mail server.', + ], + 'mail_mailer' => [ + 'label' => 'Mail Mailer', + 'type' => 'string', + 'description' => 'The mailer of your mail server.', + ], + ]; + } +} diff --git a/app/Settings/PterodactylSettings.php b/app/Settings/PterodactylSettings.php new file mode 100644 index 000000000..6ece4a975 --- /dev/null +++ b/app/Settings/PterodactylSettings.php @@ -0,0 +1,82 @@ +panel_url, '/') ? $this->panel_url : $this->panel_url . '/'; + } + + /** + * Summary of validations array + * @return array + */ + public static function getValidations() + { + return [ + 'panel_url' => 'required|string|url', + 'admin_token' => 'required|string', + 'user_token' => 'required|string', + 'per_page_limit' => 'required|integer|min:1|max:10000', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-server', + 'panel_url' => [ + 'label' => 'Panel URL', + 'type' => 'string', + 'description' => 'The URL to your Pterodactyl panel.', + ], + 'admin_token' => [ + 'label' => 'Admin Token', + 'type' => 'string', + 'description' => 'The admin user token for your Pterodactyl panel.', + ], + 'user_token' => [ + 'label' => 'User Token', + 'type' => 'string', + 'description' => 'The user token for your Pterodactyl panel.', + ], + 'per_page_limit' => [ + 'label' => 'Per Page Limit', + 'type' => 'number', + 'description' => 'The number of servers to show per page for the API call. Only change this when needed.', + ], + ]; + } +} diff --git a/app/Settings/ReferralSettings.php b/app/Settings/ReferralSettings.php new file mode 100644 index 000000000..de16ff89d --- /dev/null +++ b/app/Settings/ReferralSettings.php @@ -0,0 +1,76 @@ + + */ + public static function getValidations() + { + return [ + 'always_give_commission' => 'nullable|string', + 'enabled' => 'nullable|string', + 'reward' => 'nullable|numeric', + 'mode' => 'required|in:commission,sign-up,both', + 'percentage' => 'nullable|numeric', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-user-friends', + 'always_give_commission' => [ + 'label' => 'Always Give Commission', + 'type' => 'boolean', + 'description' => 'Always give commission to the referrer or only on the first Purchase.', + ], + 'enabled' => [ + 'label' => 'Enabled', + 'type' => 'boolean', + 'description' => 'Enable referral system.', + ], + 'reward' => [ + 'label' => 'Reward', + 'type' => 'number', + 'description' => 'Reward in credits for the referrer.', + ], + 'mode' => [ + 'label' => 'Mode', + 'type' => 'select', + 'description' => 'Referral mode.', + 'options' => [ + 'commission' => 'Commission', + 'sign-up' => 'Sign-Up', + 'both' => 'Both', + ], + ], + 'percentage' => [ + 'label' => 'Percentage', + 'type' => 'number', + 'description' => 'If a referred user buys credits, the referral-user will get x% of the Credits the referred user bought.', + ], + ]; + } +} diff --git a/app/Settings/ServerSettings.php b/app/Settings/ServerSettings.php new file mode 100644 index 000000000..8ed4547d1 --- /dev/null +++ b/app/Settings/ServerSettings.php @@ -0,0 +1,64 @@ + + */ + public static function getValidations() + { + return [ + 'allocation_limit' => 'required|integer|min:0', + 'creation_enabled' => 'nullable|string', + 'enable_upgrade' => 'nullable|string', + 'location_description_enabled' => 'nullable|string', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-server', + 'allocation_limit' => [ + 'label' => 'Allocation Limit', + 'type' => 'number', + 'description' => 'The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created.', + ], + 'creation_enabled' => [ + 'label' => 'Creation Enabled', + 'type' => 'boolean', + 'description' => 'Enable the user server creation.', + ], + 'enable_upgrade' => [ + 'label' => 'Server Upgrade Enabled', + 'type' => 'boolean', + 'description' => 'Enable the server upgrade feature.', + ], + 'location_description_enabled' => [ + 'label' => 'Enable Location Description', + 'type' => 'boolean', + 'description' => 'Enable the location description field on the server creation page.', + ], + ]; + } +} diff --git a/app/Settings/TicketSettings.php b/app/Settings/TicketSettings.php new file mode 100644 index 000000000..89eec7270 --- /dev/null +++ b/app/Settings/TicketSettings.php @@ -0,0 +1,50 @@ + + */ + public static function getValidations() + { + return [ + 'enabled' => 'nullable|string', + 'information' => 'nullable|string', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-ticket-alt', + 'enabled' => [ + 'label' => 'Enabled', + 'type' => 'boolean', + 'description' => 'Enable or disable the ticket system.', + ], + 'information' => [ + 'label' => 'Ticket Information', + 'type' => 'textarea', + 'description' => 'Message shown on the right side when users create a new ticket.', + ], + ]; + } +} diff --git a/app/Settings/UserSettings.php b/app/Settings/UserSettings.php new file mode 100644 index 000000000..adc849af3 --- /dev/null +++ b/app/Settings/UserSettings.php @@ -0,0 +1,120 @@ + + */ + public static function getValidations() + { + return [ + 'credits_reward_after_verify_discord' => 'required|numeric', + 'credits_reward_after_verify_email' => 'required|numeric', + 'force_discord_verification' => 'nullable|string', + 'force_email_verification' => 'nullable|string', + 'initial_credits' => 'required|numeric', + 'initial_server_limit' => 'required|numeric', + 'min_credits_to_make_server' => 'required|numeric', + 'server_limit_after_irl_purchase' => 'required|numeric', + 'server_limit_after_verify_discord' => 'required|numeric', + 'server_limit_after_verify_email' => 'required|numeric', + 'register_ip_check' => 'nullable|string', + 'creation_enabled' => 'nullable|string', + ]; + } + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-user', + 'credits_reward_after_verify_discord' => [ + 'label' => 'Credits Reward After Verify Discord', + 'type' => 'number', + 'description' => 'The amount of credits a user gets after verifying their discord account.', + ], + 'credits_reward_after_verify_email' => [ + 'label' => 'Credits Reward After Verify Email', + 'type' => 'number', + 'description' => 'The amount of credits a user gets after verifying their email.', + ], + 'force_discord_verification' => [ + 'label' => 'Force Discord Verification', + 'type' => 'boolean', + 'description' => 'Force users to verify their discord account.', + ], + 'force_email_verification' => [ + 'label' => 'Force Email Verification', + 'type' => 'boolean', + 'description' => 'Force users to verify their email.', + ], + 'initial_credits' => [ + 'label' => 'Initial Credits', + 'type' => 'number', + 'description' => 'The amount of credits a user gets when they register.', + ], + 'initial_server_limit' => [ + 'label' => 'Initial Server Limit', + 'type' => 'number', + 'description' => 'The amount of servers a user can create when they register.', + ], + 'min_credits_to_make_server' => [ + 'label' => 'Min Credits To Make Server', + 'type' => 'number', + 'description' => 'The minimum amount of credits a user needs to create a server.', + ], + 'server_limit_after_irl_purchase' => [ + 'label' => 'Server Limit After first purchase', + 'type' => 'number', + 'description' => 'The amount of servers a user can create after they make their first purchase.', + ], + 'server_limit_after_verify_discord' => [ + 'label' => 'Server Limit After Verify Discord', + 'type' => 'number', + 'description' => 'The amount of servers a user can create after they verify their discord account.', + ], + 'server_limit_after_verify_email' => [ + 'label' => 'Server Limit After Verify Email', + 'type' => 'number', + 'description' => 'The amount of servers a user can create after they verify their email.', + ], + 'register_ip_check' => [ + 'label' => 'Register IP Check Enabled', + 'type' => 'boolean', + 'description' => 'Check if the IP a user is registering from is already in use.', + ], + 'creation_enabled' => [ + 'label' => 'Creation Enabled', + 'type' => 'boolean', + 'description' => 'Enable the user registration.', + ], + ]; + } +} diff --git a/app/Settings/WebsiteSettings.php b/app/Settings/WebsiteSettings.php new file mode 100644 index 000000000..f768b0212 --- /dev/null +++ b/app/Settings/WebsiteSettings.php @@ -0,0 +1,103 @@ + + */ + public static function getValidations() + { + return [ + 'motd_enabled' => 'nullable|string', + 'motd_message' => 'nullable|string', + 'show_imprint' => 'nullable|string', + 'show_privacy' => 'nullable|string', + 'show_tos' => 'nullable|string', + 'useful_links_enabled' => 'nullable|string', + 'enable_login_logo' => 'nullable|string', + 'seo_title' => 'nullable|string', + 'seo_description' => 'nullable|string', + ]; + } + + + /** + * Summary of optionTypes + * Only used for the settings page + * @return array>> + */ + public static function getOptionInputData() + { + return [ + 'category_icon' => 'fas fa-globe', + 'motd_enabled' => [ + 'label' => 'Enable MOTD', + 'type' => 'boolean', + 'description' => 'Enable the MOTD (Message of the day) on the dashboard.', + ], + 'motd_message' => [ + 'label' => 'MOTD Message', + 'type' => 'textarea', + 'description' => 'The message of the day.', + ], + 'show_imprint' => [ + 'label' => 'Show Imprint', + 'type' => 'boolean', + 'description' => 'Show the imprint on the website.', + ], + 'show_privacy' => [ + 'label' => 'Show Privacy', + 'type' => 'boolean', + 'description' => 'Show the privacy on the website.', + ], + 'show_tos' => [ + 'label' => 'Show TOS', + 'type' => 'boolean', + 'description' => 'Show the TOS on the website.', + ], + 'useful_links_enabled' => [ + 'label' => 'Enable Useful Links', + 'type' => 'boolean', + 'description' => 'Enable the useful links on the dashboard.', + ], + 'seo_title' => [ + 'label' => 'SEO Title', + 'type' => 'string', + 'description' => 'The title of the website.', + ], + 'seo_description' => [ + 'label' => 'SEO Description', + 'type' => 'string', + 'description' => 'The description of the website shown in the Meta tag (for example when sending the URL in discord).', + ], + 'enable_login_logo' => [ + 'label' => 'Enable Login Logo', + 'type' => 'boolean', + 'description' => 'Enable the logo on the login page.', + ], + ]; + } +} diff --git a/app/Traits/Coupon.php b/app/Traits/Coupon.php new file mode 100644 index 000000000..7c01efae7 --- /dev/null +++ b/app/Traits/Coupon.php @@ -0,0 +1,115 @@ +first(); + $shopProduct = ShopProduct::findOrFail($productId); + $coupon_settings = new CouponSettings; + $response = response()->json([ + 'isValid' => false, + 'error' => __('This coupon does not exist.') + ], 404); + + if (!is_null($coupon)) { + if ($coupon->getStatus() == 'USES_LIMIT_REACHED') { + $response = response()->json([ + 'isValid' => false, + 'error' => __('This coupon has reached the maximum amount of uses.') + ], 422); + + return $response; + } + + if ($coupon->getStatus() == 'EXPIRED') { + $response = response()->json([ + 'isValid' => false, + 'error' => __('This coupon has expired.') + ], 422); + + return $response; + } + + if ($coupon->isMaxUsesReached($requestUser, $coupon_settings)) { + $response = response()->json([ + 'isValid' => false, + 'error' => __('You have reached the maximum uses of this coupon.') + ], 422); + + return $response; + } + + if ($coupon->type === 'amount' && $coupon->value >= $shopProduct->price) { + $response = response()->json([ + 'isValid' => false, + 'error' => __('The coupon you are trying to use would give you 100% off, so it cannot be used for this product, sorry.') + ], 422); + + return $response; + } + + $response = response()->json([ + 'isValid' => true, + 'couponCode' => $coupon->code, + 'couponType' => $coupon->type, + 'couponValue' => $coupon->value + ]); + } + + return $response; + } + + public function isCouponValid(string $couponCode, User $user, string $productId): bool + { + if (is_null($couponCode)) return false; + + $coupon = CouponModel::where('code', $couponCode)->firstOrFail(); + $shopProduct = ShopProduct::findOrFail($productId); + + if ($coupon->getStatus() == 'USES_LIMIT_REACHED') { + return false; + } + + if ($coupon->getStatus() == 'EXPIRED') { + return false; + } + + if ($coupon->isMaxUsesReached($user)) { + return false; + } + + if ($coupon->type === 'amount' && $coupon->value >= $shopProduct->price) { + return false; + } + + return true; + } + + public function applyCoupon(string $couponCode, float $price) + { + $coupon = CouponModel::where('code', $couponCode)->first(); + + if ($coupon->type === 'percentage') { + return $price - ($price * $coupon->value / 100); + } + + if ($coupon->type === 'amount') { + // There is no discount if the value of the coupon is greater than or equal to the value of the product. + if ($coupon->value >= $price) { + return $price; + } + } + + return $price - $coupon->value; + } +} diff --git a/app/Traits/Invoiceable.php b/app/Traits/Invoiceable.php index 932fa89de..3ee77c90e 100644 --- a/app/Traits/Invoiceable.php +++ b/app/Traits/Invoiceable.php @@ -5,32 +5,34 @@ use App\Models\PartnerDiscount; use App\Models\Payment; use App\Models\ShopProduct; +use App\Models\Invoice; use App\Notifications\InvoiceNotification; +use App\Settings\InvoiceSettings; use Illuminate\Support\Facades\Storage; use LaravelDaily\Invoices\Classes\Buyer; use LaravelDaily\Invoices\Classes\InvoiceItem; use LaravelDaily\Invoices\Classes\Party; -use LaravelDaily\Invoices\Invoice; +use LaravelDaily\Invoices\Invoice as DailyInvoice; use Symfony\Component\Intl\Currencies; trait Invoiceable { - public function createInvoice(Payment $payment, ShopProduct $shopProduct) + public function createInvoice(Payment $payment, ShopProduct $shopProduct, InvoiceSettings $invoice_settings) { $user = $payment->user; //create invoice - $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id"); + $lastInvoiceID = Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id"); $newInvoiceID = $lastInvoiceID + 1; $logoPath = storage_path('app/public/logo.png'); $seller = new Party([ - 'name' => config("SETTINGS::INVOICE:COMPANY_NAME"), - 'phone' => config("SETTINGS::INVOICE:COMPANY_PHONE"), - 'address' => config("SETTINGS::INVOICE:COMPANY_ADDRESS"), - 'vat' => config("SETTINGS::INVOICE:COMPANY_VAT"), + 'name' => $invoice_settings->company_name, + 'phone' => $invoice_settings->company_phone, + 'address' => $invoice_settings->company_address, + 'vat' => $invoice_settings->company_vat, 'custom_fields' => [ - 'E-Mail' => config("SETTINGS::INVOICE:COMPANY_MAIL"), - "Web" => config("SETTINGS::INVOICE:COMPANY_WEBSITE") + 'E-Mail' => $invoice_settings->company_mail, + "Web" => $invoice_settings->company_website ], ]); @@ -51,8 +53,8 @@ public function createInvoice(Payment $payment, ShopProduct $shopProduct) $notes = implode("
", $notes); - $invoice = Invoice::make() - ->template('controlpanel') + $invoice = DailyInvoice::make() + ->template('ctrlpanel') ->name(__("Invoice")) ->buyer($customer) ->seller($seller) @@ -64,7 +66,7 @@ public function createInvoice(Payment $payment, ShopProduct $shopProduct) ->series(now()->format('mY')) ->delimiter("-") ->sequence($newInvoiceID) - ->serialNumberFormat(config("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}') + ->serialNumberFormat($invoice_settings->prefix . '{DELIMITER}{SERIES}{SEQUENCE}') ->currencyCode(strtoupper($payment->currency_code)) ->currencySymbol(Currencies::getSymbol(strtoupper($payment->currency_code))) ->notes($notes); @@ -78,7 +80,7 @@ public function createInvoice(Payment $payment, ShopProduct $shopProduct) $invoice->render(); Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output); - \App\Models\Invoice::create([ + Invoice::create([ 'invoice_user' => $user->id, 'invoice_name' => $invoice->getSerialNumber(), 'payment_id' => $payment->payment_id, diff --git a/bin/rebuild.sh b/bin/rebuild.sh deleted file mode 100644 index 7aba0c5cc..000000000 --- a/bin/rebuild.sh +++ /dev/null @@ -1,2 +0,0 @@ -docker-compose -f docker/docker-compose.yml down -docker-compose -f docker/docker-compose.yml build --no-cache diff --git a/bin/startdocker.sh b/bin/startdocker.sh deleted file mode 100644 index 57a6c5154..000000000 --- a/bin/startdocker.sh +++ /dev/null @@ -1,2 +0,0 @@ -docker-compose -f docker/docker-compose.yml down -docker-compose -f docker/docker-compose.yml up -d --force-recreate --remove-orphans diff --git a/bin/stopdocker.sh b/bin/stopdocker.sh deleted file mode 100644 index f0bed643b..000000000 --- a/bin/stopdocker.sh +++ /dev/null @@ -1 +0,0 @@ -docker-compose -f docker/docker-compose.yml down diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore old mode 100644 new mode 100755 diff --git a/composer.json b/composer.json index 6dfc73bbe..231988a4e 100644 --- a/composer.json +++ b/composer.json @@ -8,46 +8,50 @@ ], "license": "MIT", "require": { - "php": "^8.1", + "php": "^8.2", "ext-intl": "*", - "biscolab/laravel-recaptcha": "^5.4", - "doctrine/dbal": "^3.1", - "guzzlehttp/guzzle": "^7.2", - "hidehalo/nanoid-php": "^1.1", - "kkomelin/laravel-translatable-string-exporter": "^1.18", - "laravel/framework": "^9.46", - "laravel/tinker": "^2.7", - "laravel/ui": "^3.3", - "laraveldaily/laravel-invoices": "^3.0", - "league/flysystem-aws-s3-v3": "^3.0", - "paypal/paypal-checkout-sdk": "^1.0", - "paypal/rest-api-sdk-php": "^1.14", - "qirolab/laravel-themer": "^2.0", - "socialiteproviders/discord": "^4.1", - "spatie/laravel-activitylog": "^4.4", - "spatie/laravel-query-builder": "^5.0", - "spatie/laravel-validation-rules": "^3.2", - "stripe/stripe-php": "^7.107", - "symfony/http-client": "^6.2", - "symfony/intl": "^6.0", - "symfony/mailgun-mailer": "^6.2", - "yajra/laravel-datatables-oracle": "^9.19" + "ext-mysqli": "*", + "ext-curl": "*", + "biscolab/laravel-recaptcha": "^6.1", + "doctrine/dbal": "^4.0.4", + "guzzlehttp/guzzle": "^7.5", + "hidehalo/nanoid-php": "^1.1.12", + "kkomelin/laravel-translatable-string-exporter": "^1.22", + "laravel/framework": "^11.17", + "laravel/tinker": "^2.9", + "laravel/ui": "^4.5.2", + "laraveldaily/laravel-invoices": "^4.0.0", + "league/flysystem-aws-s3-v3": "^3.28.0", + "paypal/paypal-checkout-sdk": "^1.0.2", + "predis/predis": "*", + "qirolab/laravel-themer": "^2.3.3", + "socialiteproviders/discord": "^4.1.2", + "spatie/laravel-activitylog": "^4.8.0", + "spatie/laravel-permission": "^6.9", + "spatie/laravel-query-builder": "^6.0.1", + "spatie/laravel-settings": "^3.3", + "spatie/laravel-validation-rules": "^3.4.0", + "stripe/stripe-php": "^7.128", + "symfony/http-client": "^7.1.2", + "symfony/intl": "^7.1.1", + "symfony/mailgun-mailer": "^7.1.2", + "yajra/laravel-datatables-oracle": "^11.1.3" }, "require-dev": { - "barryvdh/laravel-debugbar": "^3.6", - "fakerphp/faker": "^1.9.1", - "laravel/sail": "^1.15", - "mockery/mockery": "^1.4.4", - "nunomaduro/collision": "^6.3", - "phpunit/phpunit": "^9.5.10", - "spatie/laravel-ignition": "^1.4" + "barryvdh/laravel-debugbar": "^3.13", + "fakerphp/faker": "^1.21", + "laravel/sail": "^1.31", + "mockery/mockery": "^1.5.1", + "nunomaduro/collision": "^8.3", + "phpunit/phpunit": "^11.2", + "spatie/laravel-ignition": "^2.8" }, "config": { "optimize-autoloader": true, "preferred-install": "dist", "sort-packages": true, "platform": { - "php": "8.1" + "php": "8.2" } }, "extra": { diff --git a/composer.lock b/composer.lock index 587a39b8e..c8907a7ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,31 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d98e4be75e05c71049fe452b69b54901", + "content-hash": "6284e796f9bb6fd440148a123c7a77e3", "packages": [ { "name": "aws/aws-crt-php", - "version": "v1.0.2", + "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/awslabs/aws-crt-php.git", - "reference": "3942776a8c99209908ee0b287746263725685732" + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/3942776a8c99209908ee0b287746263725685732", - "reference": "3942776a8c99209908ee0b287746263725685732", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", "shasum": "" }, "require": { "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "^4.8.35|^5.4.3" + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." }, "type": "library", "autoload": { @@ -43,7 +47,7 @@ } ], "description": "AWS Common Runtime for PHP", - "homepage": "http://aws.amazon.com/sdkforphp", + "homepage": "https://github.com/awslabs/aws-crt-php", "keywords": [ "amazon", "aws", @@ -52,34 +56,35 @@ ], "support": { "issues": "https://github.com/awslabs/aws-crt-php/issues", - "source": "https://github.com/awslabs/aws-crt-php/tree/v1.0.2" + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" }, - "time": "2021-09-03T22:57:30+00:00" + "time": "2024-10-18T22:15:13+00:00" }, { "name": "aws/aws-sdk-php", - "version": "3.257.5", + "version": "3.328.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "c600a07da531d6c29af791b9d2e8b6df796aa14b" + "reference": "a99b58e166ae367f2b067937afb04e843e900745" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c600a07da531d6c29af791b9d2e8b6df796aa14b", - "reference": "c600a07da531d6c29af791b9d2e8b6df796aa14b", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/a99b58e166ae367f2b067937afb04e843e900745", + "reference": "a99b58e166ae367f2b067937afb04e843e900745", "shasum": "" }, "require": { - "aws/aws-crt-php": "^1.0.2", + "aws/aws-crt-php": "^1.2.3", "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", - "guzzlehttp/promises": "^1.4.0", - "guzzlehttp/psr7": "^1.8.5 || ^2.3", + "guzzlehttp/promises": "^1.4.0 || ^2.0", + "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", "mtdowling/jmespath.php": "^2.6", - "php": ">=5.5" + "php": ">=7.2.5", + "psr/http-message": "^1.0 || ^2.0" }, "require-dev": { "andrewsville/php-token-reflection": "^1.4", @@ -94,7 +99,7 @@ "ext-sockets": "*", "nette/neon": "^2.3", "paragonie/random_compat": ">= 2", - "phpunit/phpunit": "^4.8.35 || ^5.6.3 || ^9.5", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", "psr/cache": "^1.0", "psr/simple-cache": "^1.0", "sebastian/comparator": "^1.2.3 || ^4.0", @@ -119,7 +124,10 @@ ], "psr-4": { "Aws\\": "src/" - } + }, + "exclude-from-classmap": [ + "src/data/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -146,33 +154,33 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.257.5" + "source": "https://github.com/aws/aws-sdk-php/tree/3.328.0" }, - "time": "2023-01-20T19:34:14+00:00" + "time": "2024-11-15T19:06:57+00:00" }, { "name": "barryvdh/laravel-dompdf", - "version": "v2.0.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "1d47648c6cef37f715ecb8bcc5f5a656ad372e27" + "reference": "c96f90c97666cebec154ca1ffb67afed372114d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/1d47648c6cef37f715ecb8bcc5f5a656ad372e27", - "reference": "1d47648c6cef37f715ecb8bcc5f5a656ad372e27", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/c96f90c97666cebec154ca1ffb67afed372114d8", + "reference": "c96f90c97666cebec154ca1ffb67afed372114d8", "shasum": "" }, "require": { - "dompdf/dompdf": "^2", - "illuminate/support": "^6|^7|^8|^9", + "dompdf/dompdf": "^2.0.7", + "illuminate/support": "^6|^7|^8|^9|^10|^11", "php": "^7.2 || ^8.0" }, "require-dev": { - "nunomaduro/larastan": "^1|^2", - "orchestra/testbench": "^4|^5|^6|^7", - "phpro/grumphp": "^1", + "larastan/larastan": "^1.0|^2.7.0", + "orchestra/testbench": "^4|^5|^6|^7|^8|^9", + "phpro/grumphp": "^1 || ^2.5", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", @@ -213,7 +221,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.0.0" + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.2.0" }, "funding": [ { @@ -225,30 +233,30 @@ "type": "github" } ], - "time": "2022-07-06T11:12:10+00:00" + "time": "2024-04-25T13:16:04+00:00" }, { "name": "biscolab/laravel-recaptcha", - "version": "v5.4.0", + "version": "v6.1.0", "source": { "type": "git", "url": "https://github.com/biscolab/laravel-recaptcha.git", - "reference": "1bab726402d5376553a439b88a0faa07e84488fd" + "reference": "440fc617cba9f39aab7fda5d7697b76a55286e31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/biscolab/laravel-recaptcha/zipball/1bab726402d5376553a439b88a0faa07e84488fd", - "reference": "1bab726402d5376553a439b88a0faa07e84488fd", + "url": "https://api.github.com/repos/biscolab/laravel-recaptcha/zipball/440fc617cba9f39aab7fda5d7697b76a55286e31", + "reference": "440fc617cba9f39aab7fda5d7697b76a55286e31", "shasum": "" }, "require": { - "illuminate/routing": "^7.0|^8.0|^9.0", - "illuminate/support": "^7.0|^8.0|^9.0", + "illuminate/routing": "^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "^7.0|^8.0|^9.0|^10.0|^11.0", "php": "^7.3|^8.0" }, "require-dev": { - "orchestra/testbench": "5.*|6.*|^7.0", - "phpunit/phpunit": "^9.1" + "orchestra/testbench": "5.*|6.*|^7.0|^8.0|^9.0", + "phpunit/phpunit": "^9.1|^10.5" }, "suggest": { "biscolab/laravel-authlog": "It allows to handle logged-in users and force log-out if needed" @@ -294,32 +302,32 @@ ], "support": { "issues": "https://github.com/biscolab/laravel-recaptcha/issues", - "source": "https://github.com/biscolab/laravel-recaptcha/tree/v5.4.0" + "source": "https://github.com/biscolab/laravel-recaptcha/tree/v6.1.0" }, - "time": "2022-05-07T12:52:46+00:00" + "abandoned": true, + "time": "2024-03-27T11:06:21+00:00" }, { "name": "brick/math", - "version": "0.10.2", + "version": "0.12.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "459f2781e1a08d52ee56b0b1444086e038561e3f" + "reference": "f510c0a40911935b77b86859eb5223d58d660df1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/459f2781e1a08d52ee56b0b1444086e038561e3f", - "reference": "459f2781e1a08d52ee56b0b1444086e038561e3f", + "url": "https://api.github.com/repos/brick/math/zipball/f510c0a40911935b77b86859eb5223d58d660df1", + "reference": "f510c0a40911935b77b86859eb5223d58d660df1", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^7.4 || ^8.0" + "php": "^8.1" }, "require-dev": { "php-coveralls/php-coveralls": "^2.2", - "phpunit/phpunit": "^9.0", - "vimeo/psalm": "4.25.0" + "phpunit/phpunit": "^10.1", + "vimeo/psalm": "5.16.0" }, "type": "library", "autoload": { @@ -339,12 +347,17 @@ "arithmetic", "bigdecimal", "bignum", + "bignumber", "brick", - "math" + "decimal", + "integer", + "math", + "mathematics", + "rational" ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.10.2" + "source": "https://github.com/brick/math/tree/0.12.1" }, "funding": [ { @@ -352,20 +365,89 @@ "type": "github" } ], - "time": "2022-08-10T22:54:19+00:00" + "time": "2023-11-29T23:19:16+00:00" + }, + { + "name": "carbonphp/carbon-doctrine-types", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "conflict": { + "doctrine/dbal": "<4.0.0 || >=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" }, { "name": "dflydev/dot-access-data", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/dflydev/dflydev-dot-access-data.git", - "reference": "f41715465d65213d644d3141a6a93081be5d3549" + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", - "reference": "f41715465d65213d644d3141a6a93081be5d3549", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", "shasum": "" }, "require": { @@ -425,144 +507,48 @@ ], "support": { "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", - "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" - }, - "time": "2022-10-27T11:44:00+00:00" - }, - { - "name": "doctrine/cache", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb", - "reference": "1ca8f21980e770095a31456042471a57bc4c68fb", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/2.2.0" + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "time": "2022-05-20T20:07:39+00:00" + "time": "2024-07-08T12:26:09+00:00" }, { "name": "doctrine/dbal", - "version": "3.5.3", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "88fa7e5189fd5ec6682477044264dc0ed4e3aa1e" + "reference": "dadd35300837a3a2184bd47d403333b15d0a9bd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/88fa7e5189fd5ec6682477044264dc0ed4e3aa1e", - "reference": "88fa7e5189fd5ec6682477044264dc0ed4e3aa1e", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/dadd35300837a3a2184bd47d403333b15d0a9bd0", + "reference": "dadd35300837a3a2184bd47d403333b15d0a9bd0", "shasum": "" }, "require": { - "composer-runtime-api": "^2", - "doctrine/cache": "^1.11|^2.0", "doctrine/deprecations": "^0.5.3|^1", - "doctrine/event-manager": "^1|^2", - "php": "^7.4 || ^8.0", + "php": "^8.1", "psr/cache": "^1|^2|^3", "psr/log": "^1|^2|^3" }, "require-dev": { - "doctrine/coding-standard": "11.0.0", - "jetbrains/phpstorm-stubs": "2022.3", - "phpstan/phpstan": "1.9.4", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "9.5.27", - "psalm/plugin-phpunit": "0.18.4", - "squizlabs/php_codesniffer": "3.7.1", - "symfony/cache": "^5.4|^6.0", - "symfony/console": "^4.4|^5.4|^6.0", - "vimeo/psalm": "4.30.0" + "doctrine/coding-standard": "12.0.0", + "fig/log-test": "^1", + "jetbrains/phpstorm-stubs": "2023.2", + "phpstan/phpstan": "1.12.6", + "phpstan/phpstan-phpunit": "1.4.0", + "phpstan/phpstan-strict-rules": "^1.6", + "phpunit/phpunit": "10.5.30", + "psalm/plugin-phpunit": "0.19.0", + "slevomat/coding-standard": "8.13.1", + "squizlabs/php_codesniffer": "3.10.2", + "symfony/cache": "^6.3.8|^7.0", + "symfony/console": "^5.4|^6.3|^7.0", + "vimeo/psalm": "5.25.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." }, - "bin": [ - "bin/doctrine-dbal" - ], "type": "library", "autoload": { "psr-4": { @@ -615,7 +601,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.5.3" + "source": "https://github.com/doctrine/dbal/tree/4.2.1" }, "funding": [ { @@ -631,29 +617,33 @@ "type": "tidelift" } ], - "time": "2023-01-12T10:21:44+00:00" + "time": "2024-10-10T18:01:27+00:00" }, { "name": "doctrine/deprecations", - "version": "v1.0.0", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", - "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^9", - "phpunit/phpunit": "^7.5|^8.5|^9.5", - "psr/log": "^1|^2|^3" + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -672,125 +662,34 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" - }, - "time": "2022-05-02T15:47:09+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", - "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" - }, - "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^4.28" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ], - "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.0" + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", - "type": "tidelift" - } - ], - "time": "2022-10-12T20:59:15+00:00" + "time": "2024-01-30T19:34:25+00:00" }, { "name": "doctrine/inflector", - "version": "2.0.6", + "version": "2.0.10", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024" + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^10", + "doctrine/coding-standard": "^11.0", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.3", "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25" + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", "autoload": { @@ -840,7 +739,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.6" + "source": "https://github.com/doctrine/inflector/tree/2.0.10" }, "funding": [ { @@ -856,31 +755,31 @@ "type": "tidelift" } ], - "time": "2022-10-20T09:10:12+00:00" + "time": "2024-02-18T20:23:39+00:00" }, { "name": "doctrine/lexer", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "84a527db05647743d50373e0ec53a152f2cde568" + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", - "reference": "84a527db05647743d50373e0ec53a152f2cde568", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.5", + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.0" + "vimeo/psalm": "^5.21" }, "type": "library", "autoload": { @@ -917,7 +816,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.0" + "source": "https://github.com/doctrine/lexer/tree/3.0.1" }, "funding": [ { @@ -933,20 +832,20 @@ "type": "tidelift" } ], - "time": "2022-12-15T16:57:16+00:00" + "time": "2024-02-05T11:56:58+00:00" }, { "name": "dompdf/dompdf", - "version": "v2.0.1", + "version": "v2.0.8", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "c5310df0e22c758c85ea5288175fc6cd777bc085" + "reference": "c20247574601700e1f7c8dab39310fca1964dc52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/c5310df0e22c758c85ea5288175fc6cd777bc085", - "reference": "c5310df0e22c758c85ea5288175fc6cd777bc085", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/c20247574601700e1f7c8dab39310fca1964dc52", + "reference": "c20247574601700e1f7c8dab39310fca1964dc52", "shasum": "" }, "require": { @@ -954,7 +853,7 @@ "ext-mbstring": "*", "masterminds/html5": "^2.0", "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0", + "phenx/php-svg-lib": ">=0.5.2 <1.0.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -993,22 +892,22 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.1" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.8" }, - "time": "2022-09-22T13:43:41+00:00" + "time": "2024-04-29T13:06:17+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.2", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { @@ -1021,10 +920,14 @@ "require-dev": { "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", - "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -1048,7 +951,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, "funding": [ { @@ -1056,20 +959,20 @@ "type": "github" } ], - "time": "2022-09-10T18:51:20+00:00" + "time": "2024-10-09T13:47:03+00:00" }, { "name": "egulias/email-validator", - "version": "4.0.1", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff" + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/3a85486b709bc384dae8eb78fb2eec649bdb64ff", - "reference": "3a85486b709bc384dae8eb78fb2eec649bdb64ff", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", + "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", "shasum": "" }, "require": { @@ -1078,8 +981,8 @@ "symfony/polyfill-intl-idn": "^1.26" }, "require-dev": { - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^4.30" + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" }, "suggest": { "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" @@ -1115,7 +1018,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.1" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" }, "funding": [ { @@ -1123,7 +1026,7 @@ "type": "github" } ], - "time": "2023-01-14T14:17:03+00:00" + "time": "2023-10-06T06:47:41+00:00" }, { "name": "facade/ignition-contracts", @@ -1179,66 +1082,129 @@ "time": "2020-10-16T08:27:54+00:00" }, { - "name": "fruitcake/php-cors", - "version": "v1.2.0", + "name": "firebase/php-jwt", + "version": "v6.10.1", "source": { "type": "git", - "url": "https://github.com/fruitcake/php-cors.git", - "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e" + "url": "https://github.com/firebase/php-jwt.git", + "reference": "500501c2ce893c824c801da135d02661199f60c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/58571acbaa5f9f462c9c77e911700ac66f446d4e", - "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", + "reference": "500501c2ce893c824c801da135d02661199f60c5", "shasum": "" }, "require": { - "php": "^7.4|^8.0", - "symfony/http-foundation": "^4.4|^5.4|^6" + "php": "^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^9", - "squizlabs/php_codesniffer": "^3.5" + "guzzlehttp/guzzle": "^7.4", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.1-dev" - } + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" }, + "type": "library", "autoload": { "psr-4": { - "Fruitcake\\Cors\\": "src/" + "Firebase\\JWT\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fruitcake", - "homepage": "https://fruitcake.nl" + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" }, { - "name": "Barryvdh", - "email": "barryvdh@gmail.com" + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" } ], - "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", - "homepage": "https://github.com/fruitcake/php-cors", + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", "keywords": [ - "cors", - "laravel", - "symfony" + "jwt", + "php" ], "support": { - "issues": "https://github.com/fruitcake/php-cors/issues", - "source": "https://github.com/fruitcake/php-cors/tree/v1.2.0" + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" }, - "funding": [ - { + "time": "2024-05-18T18:05:11+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { "url": "https://fruitcake.nl", "type": "custom" }, @@ -1247,28 +1213,28 @@ "type": "github" } ], - "time": "2022-02-20T15:07:15+00:00" + "time": "2023-10-12T05:21:21+00:00" }, { "name": "graham-campbell/result-type", - "version": "v1.1.0", + "version": "v1.1.3", "source": { "type": "git", "url": "https://github.com/GrahamCampbell/Result-Type.git", - "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8" + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/a878d45c1914464426dc94da61c9e1d36ae262a8", - "reference": "a878d45c1914464426dc94da61c9e1d36ae262a8", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", - "phpoption/phpoption": "^1.9" + "phpoption/phpoption": "^1.9.3" }, "require-dev": { - "phpunit/phpunit": "^8.5.28 || ^9.5.21" + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "autoload": { @@ -1297,7 +1263,7 @@ ], "support": { "issues": "https://github.com/GrahamCampbell/Result-Type/issues", - "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.0" + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" }, "funding": [ { @@ -1309,26 +1275,26 @@ "type": "tidelift" } ], - "time": "2022-07-30T15:56:11+00:00" + "time": "2024-07-20T21:45:45+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.5.0", + "version": "7.9.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba" + "reference": "d281ed313b989f213357e3be1a179f02196ac99b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b50a2a1251152e43f6a37f0fa053e730a67d25ba", - "reference": "b50a2a1251152e43f6a37f0fa053e730a67d25ba", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", + "reference": "d281ed313b989f213357e3be1a179f02196ac99b", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5", - "guzzlehttp/psr7": "^1.9 || ^2.4", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1337,10 +1303,11 @@ "psr/http-client-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "php-http/client-integration-tests": "^3.0", - "phpunit/phpunit": "^8.5.29 || ^9.5.23", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -1353,9 +1320,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "7.5-dev" } }, "autoload": { @@ -1421,7 +1385,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.5.0" + "source": "https://github.com/guzzle/guzzle/tree/7.9.2" }, "funding": [ { @@ -1437,38 +1401,37 @@ "type": "tidelift" } ], - "time": "2022-08-28T15:39:27+00:00" + "time": "2024-07-24T11:22:20+00:00" }, { "name": "guzzlehttp/promises", - "version": "1.5.2", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "b94b2807d85443f9719887892882d0329d1e2598" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/b94b2807d85443f9719887892882d0329d1e2598", - "reference": "b94b2807d85443f9719887892882d0329d1e2598", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { - "php": ">=5.5" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "symfony/phpunit-bridge": "^4.4 || ^5.1" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.5-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { - "files": [ - "src/functions_include.php" - ], "psr-4": { "GuzzleHttp\\Promise\\": "src/" } @@ -1505,7 +1468,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.5.2" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -1521,26 +1484,26 @@ "type": "tidelift" } ], - "time": "2022-08-28T14:55:35+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.4.3", + "version": "2.7.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "67c26b443f348a51926030c83481b85718457d3d" + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d", - "reference": "67c26b443f348a51926030c83481b85718457d3d", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", - "psr/http-message": "^1.0", + "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0" }, "provide": { @@ -1548,9 +1511,9 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.1", - "http-interop/http-factory-tests": "^0.9", - "phpunit/phpunit": "^8.5.29 || ^9.5.23" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1560,9 +1523,6 @@ "bamarni-bin": { "bin-links": true, "forward-command": false - }, - "branch-alias": { - "dev-master": "2.4-dev" } }, "autoload": { @@ -1624,7 +1584,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.4.3" + "source": "https://github.com/guzzle/psr7/tree/2.7.0" }, "funding": [ { @@ -1640,20 +1600,106 @@ "type": "tidelift" } ], - "time": "2022-10-26T14:07:24+00:00" + "time": "2024-07-18T11:15:46+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", + "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2023-12-03T19:50:20+00:00" }, { "name": "hidehalo/nanoid-php", - "version": "1.1.12", + "version": "1.1.13", "source": { "type": "git", "url": "https://github.com/hidehalo/nanoid-php.git", - "reference": "3229400d7e69b127a9e4f8fdad2e498e64cdaae4" + "reference": "3fc7c949f4e655939cc30e7110d658af3dbb0e30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hidehalo/nanoid-php/zipball/3229400d7e69b127a9e4f8fdad2e498e64cdaae4", - "reference": "3229400d7e69b127a9e4f8fdad2e498e64cdaae4", + "url": "https://api.github.com/repos/hidehalo/nanoid-php/zipball/3fc7c949f4e655939cc30e7110d658af3dbb0e30", + "reference": "3fc7c949f4e655939cc30e7110d658af3dbb0e30", "shasum": "" }, "require": { @@ -1695,35 +1741,35 @@ ], "support": { "issues": "https://github.com/hidehalo/nanoid-php/issues", - "source": "https://github.com/hidehalo/nanoid-php/tree/1.1.12" + "source": "https://github.com/hidehalo/nanoid-php/tree/1.1.13" }, - "time": "2021-12-30T07:27:43+00:00" + "time": "2022-08-04T12:07:12+00:00" }, { "name": "kkomelin/laravel-translatable-string-exporter", - "version": "1.18.0", + "version": "1.22.0", "source": { "type": "git", "url": "https://github.com/kkomelin/laravel-translatable-string-exporter.git", - "reference": "c8b3364816d9f0ad2865c7538d8eb29ed8319136" + "reference": "0c6dbec4694a7e702830ecfc005d131cd5ffe402" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kkomelin/laravel-translatable-string-exporter/zipball/c8b3364816d9f0ad2865c7538d8eb29ed8319136", - "reference": "c8b3364816d9f0ad2865c7538d8eb29ed8319136", + "url": "https://api.github.com/repos/kkomelin/laravel-translatable-string-exporter/zipball/0c6dbec4694a7e702830ecfc005d131cd5ffe402", + "reference": "0c6dbec4694a7e702830ecfc005d131cd5ffe402", "shasum": "" }, "require": { "ext-json": "*", - "illuminate/support": "^8|^9", - "illuminate/translation": "^8|^9", + "illuminate/support": "^8|^9|^10.0|^11.0", + "illuminate/translation": "^8|^9|^10.0|^11.0", "php": "^8.0", - "symfony/finder": "^5|^6" + "symfony/finder": "^5|^6|^7.0" }, "require-dev": { "nunomaduro/larastan": "^1.0|^2.0", - "orchestra/testbench": "^6.0|^7.0", - "phpunit/phpunit": "^9.0" + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0", + "phpunit/phpunit": "^9.0|^10.5" }, "type": "library", "extra": { @@ -1760,63 +1806,75 @@ ], "support": { "issues": "https://github.com/kkomelin/laravel-translatable-string-exporter/issues", - "source": "https://github.com/kkomelin/laravel-translatable-string-exporter/tree/1.18.0" + "source": "https://github.com/kkomelin/laravel-translatable-string-exporter/tree/1.22.0" }, - "time": "2023-01-12T15:11:42+00:00" + "time": "2024-03-13T13:44:41+00:00" }, { "name": "laravel/framework", - "version": "v9.48.0", + "version": "v11.32.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "c78ae7aeb0cbcb1a205050d3592247ba07f5b711" + "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/c78ae7aeb0cbcb1a205050d3592247ba07f5b711", - "reference": "c78ae7aeb0cbcb1a205050d3592247ba07f5b711", + "url": "https://api.github.com/repos/laravel/framework/zipball/bc2aad63f83ee5089be7b21cf29d645ccf31e927", + "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927", "shasum": "" }, "require": { - "brick/math": "^0.10.2", - "doctrine/inflector": "^2.0", + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.3.2", "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", "ext-mbstring": "*", "ext-openssl": "*", - "fruitcake/php-cors": "^1.2", - "laravel/serializable-closure": "^1.2.2", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "laravel/serializable-closure": "^1.3", "league/commonmark": "^2.2.1", "league/flysystem": "^3.8.0", - "monolog/monolog": "^2.0", - "nesbot/carbon": "^2.62.1", - "nunomaduro/termwind": "^1.13", - "php": "^8.0.2", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.72.2|^3.0", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^6.0.9", - "symfony/error-handler": "^6.0", - "symfony/finder": "^6.0", - "symfony/http-foundation": "^6.0", - "symfony/http-kernel": "^6.0", - "symfony/mailer": "^6.0", - "symfony/mime": "^6.0", - "symfony/process": "^6.0", - "symfony/routing": "^6.0", - "symfony/uid": "^6.0", - "symfony/var-dumper": "^6.0", + "symfony/console": "^7.0", + "symfony/error-handler": "^7.0", + "symfony/finder": "^7.0", + "symfony/http-foundation": "^7.0", + "symfony/http-kernel": "^7.0", + "symfony/mailer": "^7.0", + "symfony/mime": "^7.0", + "symfony/polyfill-php83": "^1.28", + "symfony/process": "^7.0", + "symfony/routing": "^7.0", + "symfony/uid": "^7.0", + "symfony/var-dumper": "^7.0", "tijsverkoyen/css-to-inline-styles": "^2.2.5", "vlucas/phpdotenv": "^5.4.1", "voku/portable-ascii": "^2.0" }, "conflict": { + "mockery/mockery": "1.6.8", "tightenco/collect": "<5.5.33" }, "provide": { "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", "psr/simple-cache-implementation": "1.0|2.0|3.0" }, "replace": { @@ -1825,6 +1883,7 @@ "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", "illuminate/conditionable": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", @@ -1843,6 +1902,7 @@ "illuminate/notifications": "self.version", "illuminate/pagination": "self.version", "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", "illuminate/queue": "self.version", "illuminate/redis": "self.version", "illuminate/routing": "self.version", @@ -1851,75 +1911,81 @@ "illuminate/testing": "self.version", "illuminate/translation": "self.version", "illuminate/validation": "self.version", - "illuminate/view": "self.version" + "illuminate/view": "self.version", + "spatie/once": "*" }, "require-dev": { "ably/ably-php": "^1.0", "aws/aws-sdk-php": "^3.235.5", - "doctrine/dbal": "^2.13.3|^3.1.4", - "fakerphp/faker": "^1.21", - "guzzlehttp/guzzle": "^7.5", + "ext-gmp": "*", + "fakerphp/faker": "^1.23", "league/flysystem-aws-s3-v3": "^3.0", "league/flysystem-ftp": "^3.0", "league/flysystem-path-prefixing": "^3.3", "league/flysystem-read-only": "^3.3", "league/flysystem-sftp-v3": "^3.0", - "mockery/mockery": "^1.5.1", - "orchestra/testbench-core": "^7.16", - "pda/pheanstalk": "^4.0", - "phpstan/phpdoc-parser": "^1.15", - "phpstan/phpstan": "^1.4.7", - "phpunit/phpunit": "^9.5.8", - "predis/predis": "^1.1.9|^2.0.2", - "symfony/cache": "^6.0", - "symfony/http-client": "^6.0" + "mockery/mockery": "^1.6", + "nyholm/psr7": "^1.2", + "orchestra/testbench-core": "^9.5", + "pda/pheanstalk": "^5.0", + "phpstan/phpstan": "^1.11.5", + "phpunit/phpunit": "^10.5|^11.0", + "predis/predis": "^2.0.2", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.0", + "symfony/http-client": "^7.0", + "symfony/psr-http-message-bridge": "^7.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", - "brianium/paratest": "Required to run tests in parallel (^6.0).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.13.3|^3.1.4).", - "ext-bcmath": "Required to use the multiple_of validation rule.", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", "ext-memcached": "Required to use the memcache cache driver.", - "ext-pcntl": "Required to use all features of the queue worker.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", "ext-posix": "Required to use all features of the queue worker.", - "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", - "guzzlehttp/guzzle": "Required to use the HTTP Client and the ping methods on schedules (^7.5).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", "league/flysystem-read-only": "Required to use read-only disks (^3.3)", "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", - "mockery/mockery": "Required to use mocking (^1.5.1).", + "mockery/mockery": "Required to use mocking (^1.6).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", - "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", - "phpunit/phpunit": "Required to use assertions and run tests (^9.5.8).", - "predis/predis": "Required to use the predis connector (^1.1.9|^2.0.2).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).", + "predis/predis": "Required to use the predis connector (^2.0.2).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^6.0).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^6.0).", - "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.0).", - "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.0).", - "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.0).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.0).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.0).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "9.x-dev" + "dev-master": "11.x-dev" } }, "autoload": { "files": [ "src/Illuminate/Collections/helpers.php", "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", "src/Illuminate/Support/helpers.php" ], "psr-4": { @@ -1951,30 +2017,90 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-01-17T15:06:19+00:00" + "time": "2024-11-15T17:04:33+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/0e0535747c6b8d6d10adca8b68293cf4517abb0f", + "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.2" + }, + "time": "2024-11-12T14:59:47+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.2.2", + "version": "v1.3.6", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae" + "reference": "f865a58ea3a0107c336b7045104c75243fa59d96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/47afb7fae28ed29057fdca37e16a84f90cc62fae", - "reference": "47afb7fae28ed29057fdca37e16a84f90cc62fae", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/f865a58ea3a0107c336b7045104c75243fa59d96", + "reference": "f865a58ea3a0107c336b7045104c75243fa59d96", "shasum": "" }, "require": { "php": "^7.3|^8.0" }, "require-dev": { - "nesbot/carbon": "^2.61", + "illuminate/support": "^8.0|^9.0|^10.0|^11.0", + "nesbot/carbon": "^2.61|^3.0", "pestphp/pest": "^1.21.3", "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11" + "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" }, "type": "library", "extra": { @@ -2011,35 +2137,38 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2022-09-08T13:45:54+00:00" + "time": "2024-11-11T17:06:04+00:00" }, { "name": "laravel/socialite", - "version": "v5.6.1", + "version": "v5.16.0", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "a14a177f2cc71d8add71e2b19e00800e83bdda09" + "reference": "40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/a14a177f2cc71d8add71e2b19e00800e83bdda09", - "reference": "a14a177f2cc71d8add71e2b19e00800e83bdda09", + "url": "https://api.github.com/repos/laravel/socialite/zipball/40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf", + "reference": "40a2dc98c53d9dc6d55eadb0d490d3d72b73f1bf", "shasum": "" }, "require": { "ext-json": "*", + "firebase/php-jwt": "^6.4", "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "league/oauth1-client": "^1.10.1", - "php": "^7.2|^8.0" + "php": "^7.2|^8.0", + "phpseclib/phpseclib": "^3.0" }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0", - "phpunit/phpunit": "^8.0|^9.3" + "orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.0|^9.3|^10.4" }, "type": "library", "extra": { @@ -2080,42 +2209,40 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2023-01-20T15:42:35+00:00" + "time": "2024-09-03T09:46:57+00:00" }, { "name": "laravel/tinker", - "version": "v2.8.0", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/laravel/tinker.git", - "reference": "74d0b287cc4ae65d15c368dd697aae71d62a73ad" + "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/tinker/zipball/74d0b287cc4ae65d15c368dd697aae71d62a73ad", - "reference": "74d0b287cc4ae65d15c368dd697aae71d62a73ad", + "url": "https://api.github.com/repos/laravel/tinker/zipball/ba4d51eb56de7711b3a37d63aa0643e99a339ae5", + "reference": "ba4d51eb56de7711b3a37d63aa0643e99a339ae5", "shasum": "" }, "require": { - "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0", - "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0", + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0", "php": "^7.2.5|^8.0", - "psy/psysh": "^0.10.4|^0.11.1", - "symfony/var-dumper": "^4.3.4|^5.0|^6.0" + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" }, "require-dev": { "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", "phpunit/phpunit": "^8.5.8|^9.3.3" }, "suggest": { - "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0)." + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0)." }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - }, "laravel": { "providers": [ "Laravel\\Tinker\\TinkerServiceProvider" @@ -2146,38 +2273,40 @@ ], "support": { "issues": "https://github.com/laravel/tinker/issues", - "source": "https://github.com/laravel/tinker/tree/v2.8.0" + "source": "https://github.com/laravel/tinker/tree/v2.10.0" }, - "time": "2023-01-10T18:03:30+00:00" + "time": "2024-09-23T13:32:56+00:00" }, { "name": "laravel/ui", - "version": "v3.4.6", + "version": "v4.5.2", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c" + "reference": "c75396f63268c95b053c8e4814eb70e0875e9628" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/65ec5c03f7fee2c8ecae785795b829a15be48c2c", - "reference": "65ec5c03f7fee2c8ecae785795b829a15be48c2c", + "url": "https://api.github.com/repos/laravel/ui/zipball/c75396f63268c95b053c8e4814eb70e0875e9628", + "reference": "c75396f63268c95b053c8e4814eb70e0875e9628", "shasum": "" }, "require": { - "illuminate/console": "^8.42|^9.0", - "illuminate/filesystem": "^8.42|^9.0", - "illuminate/support": "^8.82|^9.0", - "illuminate/validation": "^8.42|^9.0", - "php": "^7.3|^8.0" + "illuminate/console": "^9.21|^10.0|^11.0", + "illuminate/filesystem": "^9.21|^10.0|^11.0", + "illuminate/support": "^9.21|^10.0|^11.0", + "illuminate/validation": "^9.21|^10.0|^11.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0" }, "require-dev": { - "orchestra/testbench": "^6.23|^7.0" + "orchestra/testbench": "^7.35|^8.15|^9.0", + "phpunit/phpunit": "^9.3|^10.4|^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-master": "4.x-dev" }, "laravel": { "providers": [ @@ -2207,33 +2336,33 @@ "ui" ], "support": { - "source": "https://github.com/laravel/ui/tree/v3.4.6" + "source": "https://github.com/laravel/ui/tree/v4.5.2" }, - "time": "2022-05-20T13:38:08+00:00" + "time": "2024-05-08T18:07:10+00:00" }, { "name": "laraveldaily/laravel-invoices", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/LaravelDaily/laravel-invoices.git", - "reference": "6dabfd95ef9819b80182ebea8267b64f77c89326" + "reference": "d9fa7eca22a7836fb9b09ee7fc2a97b4dfd7b228" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LaravelDaily/laravel-invoices/zipball/6dabfd95ef9819b80182ebea8267b64f77c89326", - "reference": "6dabfd95ef9819b80182ebea8267b64f77c89326", + "url": "https://api.github.com/repos/LaravelDaily/laravel-invoices/zipball/d9fa7eca22a7836fb9b09ee7fc2a97b4dfd7b228", + "reference": "d9fa7eca22a7836fb9b09ee7fc2a97b4dfd7b228", "shasum": "" }, "require": { "barryvdh/laravel-dompdf": "^v2.0", - "illuminate/http": "^5.5|^6|^7|^8|^9", - "illuminate/support": "^5.5|^6|^7|^8|^9", - "php": "^7.3|^8.0" + "illuminate/http": "^10|^11", + "illuminate/support": "^10|^11", + "php": ">=8.2", + "symfony/http-foundation": "^6|^7" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/var-dumper": "^5.0" + "phpunit/phpunit": "^10.1" }, "type": "library", "extra": { @@ -2259,7 +2388,7 @@ { "name": "David Lun", "email": "mysticcode@gmail.com", - "homepage": "https://lun.lt", + "homepage": "https://davidlun.com", "role": "Developer" } ], @@ -2273,22 +2402,22 @@ ], "support": { "issues": "https://github.com/LaravelDaily/laravel-invoices/issues", - "source": "https://github.com/LaravelDaily/laravel-invoices/tree/3.0.2" + "source": "https://github.com/LaravelDaily/laravel-invoices/tree/4.0.0" }, - "time": "2022-08-05T06:57:45+00:00" + "time": "2024-03-14T08:31:01+00:00" }, { "name": "league/commonmark", - "version": "2.3.8", + "version": "2.5.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "c493585c130544c4e91d2e0e131e6d35cb0cbc47" + "reference": "b650144166dfa7703e62a22e493b853b58d874b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c493585c130544c4e91d2e0e131e6d35cb0cbc47", - "reference": "c493585c130544c4e91d2e0e131e6d35cb0cbc47", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0", + "reference": "b650144166dfa7703e62a22e493b853b58d874b0", "shasum": "" }, "require": { @@ -2301,8 +2430,8 @@ }, "require-dev": { "cebe/markdown": "^1.0", - "commonmark/cmark": "0.30.0", - "commonmark/commonmark.js": "0.30.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", "composer/package-versions-deprecated": "^1.8", "embed/embed": "^4.4", "erusev/parsedown": "^1.0", @@ -2311,10 +2440,10 @@ "michelf/php-markdown": "^1.4 || ^2.0", "nyholm/psr7": "^1.5", "phpstan/phpstan": "^1.8.2", - "phpunit/phpunit": "^9.5.21", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0", + "symfony/finder": "^5.3 | ^6.0 || ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0" }, @@ -2324,7 +2453,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.4-dev" + "dev-main": "2.6-dev" } }, "autoload": { @@ -2381,7 +2510,7 @@ "type": "tidelift" } ], - "time": "2022-12-10T16:02:17+00:00" + "time": "2024-08-16T11:46:16+00:00" }, { "name": "league/config", @@ -2467,23 +2596,26 @@ }, { "name": "league/flysystem", - "version": "3.12.2", + "version": "3.29.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "f6377c709d2275ed6feaf63e44be7a7162b0e77f" + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f6377c709d2275ed6feaf63e44be7a7162b0e77f", - "reference": "f6377c709d2275ed6feaf63e44be7a7162b0e77f", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", "shasum": "" }, "require": { + "league/flysystem-local": "^3.0.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" }, "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", "aws/aws-sdk-php": "3.209.31 || 3.210.0", "guzzlehttp/guzzle": "<7.0", "guzzlehttp/ringphp": "<1.1.1", @@ -2491,20 +2623,23 @@ "symfony/http-client": "<5.2" }, "require-dev": { - "async-aws/s3": "^1.5", - "async-aws/simple-s3": "^1.1", - "aws/aws-sdk-php": "^3.220.0", + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", "composer/semver": "^3.0", "ext-fileinfo": "*", "ext-ftp": "*", + "ext-mongodb": "^1.3", "ext-zip": "*", "friendsofphp/php-cs-fixer": "^3.5", "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", "microsoft/azure-storage-blob": "^1.1", - "phpseclib/phpseclib": "^3.0.14", - "phpstan/phpstan": "^0.12.26", - "phpunit/phpunit": "^9.5.11", - "sabre/dav": "^4.3.1" + "mongodb/mongodb": "^1.2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" }, "type": "library", "autoload": { @@ -2538,40 +2673,26 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.12.2" + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" }, - "funding": [ - { - "url": "https://ecologi.com/frankdejonge", - "type": "custom" - }, - { - "url": "https://github.com/frankdejonge", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/league/flysystem", - "type": "tidelift" - } - ], - "time": "2023-01-19T12:02:19+00:00" + "time": "2024-10-08T08:58:34+00:00" }, { "name": "league/flysystem-aws-s3-v3", - "version": "3.12.2", + "version": "3.29.0", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "645e14e4a80bd2da8b01e57388e7296a695a80c2" + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/645e14e4a80bd2da8b01e57388e7296a695a80c2", - "reference": "645e14e4a80bd2da8b01e57388e7296a695a80c2", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9", "shasum": "" }, "require": { - "aws/aws-sdk-php": "^3.220.0", + "aws/aws-sdk-php": "^3.295.10", "league/flysystem": "^3.10.0", "league/mime-type-detection": "^1.0.0", "php": "^8.0.2" @@ -2607,47 +2728,81 @@ "storage" ], "support": { - "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.12.2" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0" }, - "funding": [ - { - "url": "https://ecologi.com/frankdejonge", - "type": "custom" - }, - { - "url": "https://github.com/frankdejonge", - "type": "github" - }, + "time": "2024-08-17T13:10:48+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ { - "url": "https://tidelift.com/funding/github/packagist/league/flysystem", - "type": "tidelift" + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" } ], - "time": "2023-01-17T14:15:08+00:00" + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + }, + "time": "2024-08-09T21:24:39+00:00" }, { "name": "league/mime-type-detection", - "version": "1.11.0", + "version": "1.16.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd" + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd", - "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", "shasum": "" }, "require": { "ext-fileinfo": "*", - "php": "^7.2 || ^8.0" + "php": "^7.4 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.2", "phpstan/phpstan": "^0.12.68", - "phpunit/phpunit": "^8.5.8 || ^9.3" + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" }, "type": "library", "autoload": { @@ -2668,7 +2823,7 @@ "description": "Mime-type detection for Flysystem", "support": { "issues": "https://github.com/thephpleague/mime-type-detection/issues", - "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0" + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" }, "funding": [ { @@ -2680,7 +2835,7 @@ "type": "tidelift" } ], - "time": "2022-04-17T13:12:02+00:00" + "time": "2024-09-21T08:32:55+00:00" }, { "name": "league/oauth1-client", @@ -2760,26 +2915,24 @@ }, { "name": "masterminds/html5", - "version": "2.7.6", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "897eb517a343a2281f11bc5556d6548db7d93947" + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/897eb517a343a2281f11bc5556d6548db7d93947", - "reference": "897eb517a343a2281f11bc5556d6548db7d93947", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-dom": "*", - "ext-libxml": "*", "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, "type": "library", "extra": { @@ -2823,48 +2976,49 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.7.6" + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" }, - "time": "2022-08-18T16:18:26+00:00" + "time": "2024-03-31T07:05:07+00:00" }, { "name": "monolog/monolog", - "version": "2.8.0", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "720488632c590286b88b80e62aa3d3d551ad4a50" + "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/720488632c590286b88b80e62aa3d3d551ad4a50", - "reference": "720488632c590286b88b80e62aa3d3d551ad4a50", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/32e515fdc02cdafbe4593e30a9350d486b125b67", + "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67", "shasum": "" }, "require": { - "php": ">=7.2", - "psr/log": "^1.0.1 || ^2.0 || ^3.0" + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" }, "provide": { - "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0" + "psr/log-implementation": "3.0.0" }, "require-dev": { - "aws/aws-sdk-php": "^2.4.9 || ^3.0", + "aws/aws-sdk-php": "^3.0", "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2", - "guzzlehttp/guzzle": "^7.4", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpspec/prophecy": "^1.15", - "phpstan/phpstan": "^0.12.91", - "phpunit/phpunit": "^8.5.14", - "predis/predis": "^1.1 || ^2.0", - "rollbar/rollbar": "^1.3 || ^2 || ^3", - "ruflin/elastica": "^7", - "swiftmailer/swiftmailer": "^5.3|^6.0", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -2887,7 +3041,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { @@ -2915,7 +3069,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.8.0" + "source": "https://github.com/Seldaek/monolog/tree/3.8.0" }, "funding": [ { @@ -2927,29 +3081,29 @@ "type": "tidelift" } ], - "time": "2022-07-24T11:55:47+00:00" + "time": "2024-11-12T13:57:08+00:00" }, { "name": "mtdowling/jmespath.php", - "version": "2.6.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/jmespath/jmespath.php.git", - "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb" + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb", - "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", "shasum": "" }, "require": { - "php": "^5.4 || ^7.0 || ^8.0", + "php": "^7.2.5 || ^8.0", "symfony/polyfill-mbstring": "^1.17" }, "require-dev": { - "composer/xdebug-handler": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^7.5.15" + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" }, "bin": [ "bin/jp.php" @@ -2957,7 +3111,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -2973,6 +3127,11 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", @@ -2986,43 +3145,47 @@ ], "support": { "issues": "https://github.com/jmespath/jmespath.php/issues", - "source": "https://github.com/jmespath/jmespath.php/tree/2.6.1" + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" }, - "time": "2021-06-14T00:11:39+00:00" + "time": "2024-09-04T18:46:31+00:00" }, { "name": "nesbot/carbon", - "version": "2.65.0", + "version": "3.8.2", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "09acf64155c16dc6f580f36569ae89344e9734a3" + "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/09acf64155c16dc6f580f36569ae89344e9734a3", - "reference": "09acf64155c16dc6f580f36569ae89344e9734a3", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e1268cdbc486d97ce23fef2c666dc3c6b6de9947", + "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947", "shasum": "" }, "require": { + "carbonphp/carbon-doctrine-types": "<100.0", "ext-json": "*", - "php": "^7.1.8 || ^8.0", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3 || ^7.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" }, "require-dev": { - "doctrine/dbal": "^2.0 || ^3.1.4", - "doctrine/orm": "^2.7", - "friendsofphp/php-cs-fixer": "^3.0", - "kylekatarnls/multi-tester": "^2.0", - "ondrejmirtes/better-reflection": "*", - "phpmd/phpmd": "^2.9", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.99 || ^1.7.14", - "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", - "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", - "squizlabs/php_codesniffer": "^3.4" + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.57.2", + "kylekatarnls/multi-tester": "^2.5.3", + "ondrejmirtes/better-reflection": "^6.25.0.4", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.11.2", + "phpunit/phpunit": "^10.5.20", + "squizlabs/php_codesniffer": "^3.9.0" }, "bin": [ "bin/carbon" @@ -3030,8 +3193,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-3.x": "3.x-dev", - "dev-master": "2.x-dev" + "dev-master": "3.x-dev", + "dev-2.x": "2.x-dev" }, "laravel": { "providers": [ @@ -3090,35 +3253,35 @@ "type": "tidelift" } ], - "time": "2023-01-06T15:55:01+00:00" + "time": "2024-11-07T17:46:48+00:00" }, { "name": "nette/schema", - "version": "v1.2.3", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f" + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", - "reference": "abbdbb70e0245d5f3bf77874cea1dfb0c930d06f", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", "shasum": "" }, "require": { - "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", - "php": ">=7.1 <8.3" + "nette/utils": "^4.0", + "php": "8.1 - 8.4" }, "require-dev": { - "nette/tester": "^2.3 || ^2.4", + "nette/tester": "^2.5.2", "phpstan/phpstan-nette": "^1.0", - "tracy/tracy": "^2.7" + "tracy/tracy": "^2.8" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -3150,35 +3313,36 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.2.3" + "source": "https://github.com/nette/schema/tree/v1.3.2" }, - "time": "2022-10-13T01:24:26+00:00" + "time": "2024-10-06T23:10:23+00:00" }, { "name": "nette/utils", - "version": "v3.2.9", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "c91bac3470c34b2ecd5400f6e6fdf0b64a836a5c" + "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/c91bac3470c34b2ecd5400f6e6fdf0b64a836a5c", - "reference": "c91bac3470c34b2ecd5400f6e6fdf0b64a836a5c", + "url": "https://api.github.com/repos/nette/utils/zipball/736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", + "reference": "736c567e257dbe0fcf6ce81b4d6dbe05c6899f96", "shasum": "" }, "require": { - "php": ">=7.2 <8.3" + "php": "8.0 - 8.4" }, "conflict": { - "nette/di": "<3.0.6" + "nette/finder": "<3", + "nette/schema": "<1.2.2" }, "require-dev": { "jetbrains/phpstorm-attributes": "dev-master", - "nette/tester": "~2.0", + "nette/tester": "^2.5", "phpstan/phpstan": "^1.0", - "tracy/tracy": "^2.3" + "tracy/tracy": "^2.9" }, "suggest": { "ext-gd": "to use Image", @@ -3186,13 +3350,12 @@ "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", "ext-json": "to use Nette\\Utils\\Json", "ext-mbstring": "to use Strings::lower() etc...", - "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", - "ext-xml": "to use Strings::length() etc. when mbstring is not available" + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3236,31 +3399,33 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v3.2.9" + "source": "https://github.com/nette/utils/tree/v4.0.5" }, - "time": "2023-01-18T03:26:20+00:00" + "time": "2024-08-07T15:39:19+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.3", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", - "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.0" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -3268,7 +3433,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3292,39 +3457,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2023-01-16T22:05:37+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "nunomaduro/termwind", - "version": "v1.15.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "594ab862396c16ead000de0c3c38f4a5cbe1938d" + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/594ab862396c16ead000de0c3c38f4a5cbe1938d", - "reference": "594ab862396c16ead000de0c3c38f4a5cbe1938d", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/42c84e4e8090766bbd6445d06cd6e57650626ea3", + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": "^8.0", - "symfony/console": "^5.3.0|^6.0.0" + "php": "^8.2", + "symfony/console": "^7.1.5" }, "require-dev": { - "ergebnis/phpstan-rules": "^1.0.", - "illuminate/console": "^8.0|^9.0", - "illuminate/support": "^8.0|^9.0", - "laravel/pint": "^1.0.0", - "pestphp/pest": "^1.21.0", - "pestphp/pest-plugin-mock": "^1.0", - "phpstan/phpstan": "^1.4.6", - "phpstan/phpstan-strict-rules": "^1.1.0", - "symfony/var-dumper": "^5.2.7|^6.0.0", + "illuminate/console": "^11.28.0", + "laravel/pint": "^1.18.1", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -3333,6 +3496,9 @@ "providers": [ "Termwind\\Laravel\\TermwindServiceProvider" ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -3364,7 +3530,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v1.15.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.2.0" }, "funding": [ { @@ -3380,7 +3546,74 @@ "type": "github" } ], - "time": "2022-12-20T19:00:15+00:00" + "time": "2024-10-15T16:15:16+00:00" + }, + { + "name": "paragonie/constant_time_encoding", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/constant_time_encoding.git", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/df1e7fde177501eee2037dd159cf04f5f301a512", + "reference": "df1e7fde177501eee2037dd159cf04f5f301a512", + "shasum": "" + }, + "require": { + "php": "^8" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "vimeo/psalm": "^4|^5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ParagonIE\\ConstantTime\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com", + "role": "Maintainer" + }, + { + "name": "Steve 'Sc00bz' Thomas", + "email": "steve@tobtu.com", + "homepage": "https://www.tobtu.com", + "role": "Original Developer" + } + ], + "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)", + "keywords": [ + "base16", + "base32", + "base32_decode", + "base32_encode", + "base64", + "base64_decode", + "base64_encode", + "bin2hex", + "encoding", + "hex", + "hex2bin", + "rfc4648" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/constant_time_encoding/issues", + "source": "https://github.com/paragonie/constant_time_encoding" + }, + "time": "2024-05-08T12:36:18+00:00" }, { "name": "paragonie/random_compat", @@ -3482,7 +3715,7 @@ "support": { "source": "https://github.com/paypal/Checkout-PHP-SDK/tree/1.0.2" }, - "abandoned": true, + "abandoned": "paypal/paypal-server-sdk", "time": "2021-09-21T20:57:38+00:00" }, { @@ -3529,88 +3762,80 @@ "time": "2021-09-14T21:35:26+00:00" }, { - "name": "paypal/rest-api-sdk-php", - "version": "1.14.0", + "name": "phenx/php-font-lib", + "version": "0.5.6", "source": { "type": "git", - "url": "https://github.com/paypal/PayPal-PHP-SDK.git", - "reference": "72e2f2466975bf128a31e02b15110180f059fc04" + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "a1681e9793040740a405ac5b189275059e2a9863" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paypal/PayPal-PHP-SDK/zipball/72e2f2466975bf128a31e02b15110180f059fc04", - "reference": "72e2f2466975bf128a31e02b15110180f059fc04", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863", + "reference": "a1681e9793040740a405ac5b189275059e2a9863", "shasum": "" }, "require": { - "ext-curl": "*", - "ext-json": "*", - "php": ">=5.3.0", - "psr/log": "^1.0.0" + "ext-mbstring": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.35" + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" }, "type": "library", "autoload": { - "psr-0": { - "PayPal": "lib/" + "psr-4": { + "FontLib\\": "src/FontLib" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "LGPL-2.1-or-later" ], "authors": [ { - "name": "PayPal", - "homepage": "https://github.com/paypal/rest-api-sdk-php/contributors" + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" } ], - "description": "PayPal's PHP SDK for REST APIs", - "homepage": "http://paypal.github.io/PayPal-PHP-SDK/", - "keywords": [ - "payments", - "paypal", - "rest", - "sdk" - ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/PhenX/php-font-lib", "support": { - "issues": "https://github.com/paypal/PayPal-PHP-SDK/issues", - "source": "https://github.com/paypal/PayPal-PHP-SDK/tree/master" + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/0.5.6" }, - "abandoned": true, - "time": "2019-01-04T20:04:25+00:00" + "time": "2024-01-29T14:45:26+00:00" }, { - "name": "phenx/php-font-lib", + "name": "phenx/php-svg-lib", "version": "0.5.4", "source": { "type": "git", - "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691", + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691", "shasum": "" }, "require": { - "ext-mbstring": "*" + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" }, "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5" + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" }, "type": "library", "autoload": { "psr-4": { - "FontLib\\": "src/FontLib" + "Svg\\": "src/Svg" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-3.0-or-later" ], "authors": [ { @@ -3618,86 +3843,151 @@ "email": "fabien.menager@gmail.com" } ], - "description": "A library to read, parse, export and make subsets of different types of font files.", - "homepage": "https://github.com/PhenX/php-font-lib", + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/PhenX/php-svg-lib", "support": { - "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4" }, - "time": "2021-12-17T19:44:54+00:00" + "time": "2024-04-08T12:52:34+00:00" }, { - "name": "phenx/php-svg-lib", - "version": "0.5.0", + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "76876c6cf3080bcb6f249d7d59705108166a6685" + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/76876c6cf3080bcb6f249d7d59705108166a6685", - "reference": "76876c6cf3080bcb6f249d7d59705108166a6685", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": "^7.1 || ^8.0", - "sabberworm/php-css-parser": "^8.4" + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18|^2.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" }, "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, "autoload": { "psr-4": { - "Svg\\": "src/Svg" + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "MIT" ], "authors": [ { - "name": "Fabien Ménager", - "email": "fabien.menager@gmail.com" + "name": "Mike van Riel", + "email": "me@mikevanriel.com" } ], - "description": "A library to read, parse and export to PDF SVG files.", - "homepage": "https://github.com/PhenX/php-svg-lib", + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { - "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.0" + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.10.0" }, - "time": "2022-09-06T12:16:56+00:00" + "time": "2024-11-09T15:12:26+00:00" }, { "name": "phpoption/phpoption", - "version": "1.9.0", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/schmittjoh/php-option.git", - "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab" + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/dc5ff11e274a90cc1c743f66c9ad700ce50db9ab", - "reference": "dc5ff11e274a90cc1c743f66c9ad700ce50db9ab", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", "shasum": "" }, "require": { "php": "^7.2.5 || ^8.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.8", - "phpunit/phpunit": "^8.5.28 || ^9.5.21" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" }, "type": "library", "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { "dev-master": "1.9-dev" @@ -3732,20 +4022,238 @@ "type" ], "support": { - "issues": "https://github.com/schmittjoh/php-option/issues", - "source": "https://github.com/schmittjoh/php-option/tree/1.9.0" + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:41:07+00:00" + }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.42", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "reference": "db92f1b1987b12b13f248fe76c3a52cadb67bb98", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1|^2|^3", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.42" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2024-09-16T03:06:04+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/c00d78fb6b29658347f9d37ebe104bffadf36299", + "reference": "c00d78fb6b29658347f9d37ebe104bffadf36299", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^5.3.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^9.6", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.0.0" + }, + "time": "2024-10-13T11:29:49+00:00" + }, + { + "name": "predis/predis", + "version": "v2.2.2", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1", + "reference": "b1d3255ed9ad4d7254f9f9bba386c99f4bb983d1", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.3", + "phpstan/phpstan": "^1.9", + "phpunit/phpunit": "^8.0 || ~9.4.4" + }, + "suggest": { + "ext-relay": "Faster connection with in-memory caching (>=0.6.2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "A flexible and feature-complete Redis client for PHP.", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v2.2.2" }, "funding": [ { - "url": "https://github.com/GrahamCampbell", + "url": "https://github.com/sponsors/tillkruss", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", - "type": "tidelift" } ], - "time": "2022-07-30T15:51:26+00:00" + "time": "2023-09-13T16:42:03+00:00" }, { "name": "psr/cache", @@ -3796,6 +4304,54 @@ }, "time": "2021-02-03T23:26:27+00:00" }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, { "name": "psr/container", "version": "2.0.2", @@ -3901,21 +4457,21 @@ }, { "name": "psr/http-client", - "version": "1.0.1", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { "php": "^7.0 || ^8.0", - "psr/http-message": "^1.0" + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -3935,7 +4491,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP clients", @@ -3947,27 +4503,27 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "source": "https://github.com/php-fig/http-client" }, - "time": "2020-06-29T06:28:15+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", - "version": "1.0.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-factory.git", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", - "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", "shasum": "" }, "require": { - "php": ">=7.0.0", - "psr/http-message": "^1.0" + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" }, "type": "library", "extra": { @@ -3987,10 +4543,10 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Common interfaces for PSR-7 HTTP message factories", + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", "keywords": [ "factory", "http", @@ -4002,31 +4558,31 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-factory/tree/master" + "source": "https://github.com/php-fig/http-factory" }, - "time": "2019-04-30T12:38:16+00:00" + "time": "2024-04-15T12:06:14+00:00" }, { "name": "psr/http-message", - "version": "1.0.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4041,7 +4597,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -4055,36 +4611,36 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/log", - "version": "1.1.4", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", - "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Log\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4105,9 +4661,9 @@ "psr-3" ], "support": { - "source": "https://github.com/php-fig/log/tree/1.1.4" + "source": "https://github.com/php-fig/log/tree/3.0.2" }, - "time": "2021-05-03T11:20:27+00:00" + "time": "2024-09-11T13:17:53+00:00" }, { "name": "psr/simple-cache", @@ -4162,25 +4718,25 @@ }, { "name": "psy/psysh", - "version": "v0.11.10", + "version": "v0.12.4", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "e9eadffbed9c9deb5426fd107faae0452bf20a36" + "reference": "2fd717afa05341b4f8152547f142cd2f130f6818" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e9eadffbed9c9deb5426fd107faae0452bf20a36", - "reference": "e9eadffbed9c9deb5426fd107faae0452bf20a36", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/2fd717afa05341b4f8152547f142cd2f130f6818", + "reference": "2fd717afa05341b4f8152547f142cd2f130f6818", "shasum": "" }, "require": { "ext-json": "*", "ext-tokenizer": "*", - "nikic/php-parser": "^4.0 || ^3.1", - "php": "^8.0 || ^7.0.8", - "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", - "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" @@ -4191,8 +4747,7 @@ "suggest": { "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", "ext-pdo-sqlite": "The doc command requires SQLite to work.", - "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", - "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." }, "bin": [ "bin/psysh" @@ -4200,7 +4755,11 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "0.11.x-dev" + "dev-main": "0.12.x-dev" + }, + "bamarni-bin": { + "bin-links": false, + "forward-command": false } }, "autoload": { @@ -4232,33 +4791,33 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.10" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.4" }, - "time": "2022-12-23T17:47:18+00:00" + "time": "2024-06-10T01:18:23+00:00" }, { "name": "qirolab/laravel-themer", - "version": "2.0.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/qirolab/laravel-themer.git", - "reference": "9c4e17fe7334c921bf5c57395d926154cc25a1e8" + "reference": "d1ad2eae0068c026fcb5ebfe5391c280f5ace361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/qirolab/laravel-themer/zipball/9c4e17fe7334c921bf5c57395d926154cc25a1e8", - "reference": "9c4e17fe7334c921bf5c57395d926154cc25a1e8", + "url": "https://api.github.com/repos/qirolab/laravel-themer/zipball/d1ad2eae0068c026fcb5ebfe5391c280f5ace361", + "reference": "d1ad2eae0068c026fcb5ebfe5391c280f5ace361", "shasum": "" }, "require": { "facade/ignition-contracts": "^1.0", - "illuminate/support": "^9.19", + "illuminate/support": "^9.19|^10.0|^11.0", "php": ">=7.1.0" }, "require-dev": { - "orchestra/testbench": "^7.0", - "phpunit/phpunit": "^8.3|^9.0", - "vimeo/psalm": "^4.0" + "orchestra/testbench": "^7.0|^8.0|^9.0", + "phpunit/phpunit": "^8.3|^9.0|^10.5", + "vimeo/psalm": "^4.0|^5.22" }, "type": "library", "extra": { @@ -4296,7 +4855,7 @@ ], "support": { "issues": "https://github.com/qirolab/laravel-themer/issues", - "source": "https://github.com/qirolab/laravel-themer/tree/2.0.2" + "source": "https://github.com/qirolab/laravel-themer/tree/2.3.3" }, "funding": [ { @@ -4304,7 +4863,7 @@ "type": "other" } ], - "time": "2022-09-03T21:30:32+00:00" + "time": "2024-05-15T15:29:58+00:00" }, { "name": "ralouphie/getallheaders", @@ -4441,20 +5000,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.3", + "version": "4.7.6", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "433b2014e3979047db08a17a205f410ba3869cf2" + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/433b2014e3979047db08a17a205f410ba3869cf2", - "reference": "433b2014e3979047db08a17a205f410ba3869cf2", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -4517,7 +5076,7 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.3" + "source": "https://github.com/ramsey/uuid/tree/4.7.6" }, "funding": [ { @@ -4529,34 +5088,38 @@ "type": "tidelift" } ], - "time": "2023-01-12T18:13:24+00:00" + "time": "2024-04-27T21:32:50+00:00" }, { "name": "sabberworm/php-css-parser", - "version": "8.4.0", + "version": "v8.7.0", "source": { "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "f414ff953002a9b18e3a116f5e462c56f21237cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/f414ff953002a9b18e3a116f5e462c56f21237cf", + "reference": "f414ff953002a9b18e3a116f5e462c56f21237cf", "shasum": "" }, "require": { "ext-iconv": "*", - "php": ">=5.6.20" + "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" + "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.40" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, "autoload": { "psr-4": { "Sabberworm\\CSS\\": "src/" @@ -4569,6 +5132,14 @@ "authors": [ { "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" } ], "description": "Parser for CSS Files written in PHP", @@ -4579,28 +5150,28 @@ "stylesheet" ], "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.7.0" }, - "time": "2021-12-11T13:40:54+00:00" + "time": "2024-10-27T17:38:32+00:00" }, { "name": "socialiteproviders/discord", - "version": "4.1.1", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Discord.git", - "reference": "c6eddeb07ace7473e82d02d4db852dfacf5ef574" + "reference": "c71c379acfdca5ba4aa65a3db5ae5222852a919c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Discord/zipball/c6eddeb07ace7473e82d02d4db852dfacf5ef574", - "reference": "c6eddeb07ace7473e82d02d4db852dfacf5ef574", + "url": "https://api.github.com/repos/SocialiteProviders/Discord/zipball/c71c379acfdca5ba4aa65a3db5ae5222852a919c", + "reference": "c71c379acfdca5ba4aa65a3db5ae5222852a919c", "shasum": "" }, "require": { "ext-json": "*", - "php": "^7.2 || ^8.0", + "php": "^7.4 || ^8.0", "socialiteproviders/manager": "~4.0" }, "type": "library", @@ -4620,33 +5191,42 @@ } ], "description": "Discord OAuth2 Provider for Laravel Socialite", + "keywords": [ + "discord", + "laravel", + "oauth", + "provider", + "socialite" + ], "support": { - "source": "https://github.com/SocialiteProviders/Discord/tree/4.1.1" + "docs": "https://socialiteproviders.com/discord", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" }, - "time": "2021-01-05T22:03:58+00:00" + "time": "2023-07-24T23:28:47+00:00" }, { "name": "socialiteproviders/manager", - "version": "v4.2.0", + "version": "v4.7.0", "source": { "type": "git", "url": "https://github.com/SocialiteProviders/Manager.git", - "reference": "738276dfbc2b68a9145db7b3df1588d53db528a1" + "reference": "ab0691b82cec77efd90154c78f1854903455c82f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/738276dfbc2b68a9145db7b3df1588d53db528a1", - "reference": "738276dfbc2b68a9145db7b3df1588d53db528a1", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/ab0691b82cec77efd90154c78f1854903455c82f", + "reference": "ab0691b82cec77efd90154c78f1854903455c82f", "shasum": "" }, "require": { - "illuminate/support": "^6.0 || ^7.0 || ^8.0 || ^9.0", - "laravel/socialite": "~5.0", - "php": "^7.4 || ^8.0" + "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "laravel/socialite": "^5.5", + "php": "^8.0" }, "require-dev": { "mockery/mockery": "^1.2", - "phpunit/phpunit": "^6.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { @@ -4697,33 +5277,33 @@ "issues": "https://github.com/socialiteproviders/manager/issues", "source": "https://github.com/socialiteproviders/manager" }, - "time": "2022-09-02T10:20:10+00:00" + "time": "2024-11-10T01:56:18+00:00" }, { "name": "spatie/laravel-activitylog", - "version": "4.7.2", + "version": "4.9.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-activitylog.git", - "reference": "eee61436e2984119fd71fc338a45ec7d68e3b548" + "reference": "e0fc28178515a5396f48e107ed697719189bbe02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/eee61436e2984119fd71fc338a45ec7d68e3b548", - "reference": "eee61436e2984119fd71fc338a45ec7d68e3b548", + "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/e0fc28178515a5396f48e107ed697719189bbe02", + "reference": "e0fc28178515a5396f48e107ed697719189bbe02", "shasum": "" }, "require": { - "illuminate/config": "^8.0 || ^9.0", - "illuminate/database": "^8.69 || ^9.27", - "illuminate/support": "^8.0 || ^9.0", - "php": "^8.0", + "illuminate/config": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "illuminate/database": "^8.69 || ^9.27 || ^10.0 || ^11.0", + "illuminate/support": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "php": "^8.1", "spatie/laravel-package-tools": "^1.6.3" }, "require-dev": { "ext-json": "*", - "orchestra/testbench": "^6.23 || ^7.0", - "pestphp/pest": "^1.20" + "orchestra/testbench": "^6.23 || ^7.0 || ^8.0 || ^9.0", + "pestphp/pest": "^1.20 || ^2.0" }, "type": "library", "extra": { @@ -4776,7 +5356,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-activitylog/issues", - "source": "https://github.com/spatie/laravel-activitylog/tree/4.7.2" + "source": "https://github.com/spatie/laravel-activitylog/tree/4.9.0" }, "funding": [ { @@ -4788,24 +5368,24 @@ "type": "github" } ], - "time": "2022-11-14T12:16:46+00:00" + "time": "2024-10-18T13:38:47+00:00" }, { "name": "spatie/laravel-package-tools", - "version": "1.14.0", + "version": "1.16.5", "source": { "type": "git", "url": "https://github.com/spatie/laravel-package-tools.git", - "reference": "9964e65c318c30577ca1b91469f739d2b381359b" + "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/9964e65c318c30577ca1b91469f739d2b381359b", - "reference": "9964e65c318c30577ca1b91469f739d2b381359b", + "url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/c7413972cf22ffdff97b68499c22baa04eddb6a2", + "reference": "c7413972cf22ffdff97b68499c22baa04eddb6a2", "shasum": "" }, "require": { - "illuminate/contracts": "^9.28|^10.0", + "illuminate/contracts": "^9.28|^10.0|^11.0", "php": "^8.0" }, "require-dev": { @@ -4840,7 +5420,90 @@ ], "support": { "issues": "https://github.com/spatie/laravel-package-tools/issues", - "source": "https://github.com/spatie/laravel-package-tools/tree/1.14.0" + "source": "https://github.com/spatie/laravel-package-tools/tree/1.16.5" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-08-27T18:56:10+00:00" + }, + { + "name": "spatie/laravel-permission", + "version": "6.10.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-permission.git", + "reference": "8bb69d6d67387f7a00d93a2f5fab98860f06e704" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/8bb69d6d67387f7a00d93a2f5fab98860f06e704", + "reference": "8bb69d6d67387f7a00d93a2f5fab98860f06e704", + "shasum": "" + }, + "require": { + "illuminate/auth": "^8.12|^9.0|^10.0|^11.0", + "illuminate/container": "^8.12|^9.0|^10.0|^11.0", + "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0", + "illuminate/database": "^8.12|^9.0|^10.0|^11.0", + "php": "^8.0" + }, + "require-dev": { + "larastan/larastan": "^1.0|^2.0", + "laravel/passport": "^11.0|^12.0", + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0", + "phpunit/phpunit": "^9.4|^10.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.x-dev", + "dev-master": "6.x-dev" + }, + "laravel": { + "providers": [ + "Spatie\\Permission\\PermissionServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\Permission\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Permission handling for Laravel 8.0 and up", + "homepage": "https://github.com/spatie/laravel-permission", + "keywords": [ + "acl", + "laravel", + "permission", + "permissions", + "rbac", + "roles", + "security", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-permission/issues", + "source": "https://github.com/spatie/laravel-permission/tree/6.10.1" }, "funding": [ { @@ -4848,35 +5511,37 @@ "type": "github" } ], - "time": "2023-01-10T14:09:55+00:00" + "time": "2024-11-08T18:45:41+00:00" }, { "name": "spatie/laravel-query-builder", - "version": "5.1.1", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-query-builder.git", - "reference": "14a6802cd513cfd2abf68044cca5fd7391eb543d" + "reference": "64f0453f4dea6a6fabf1ce4ddbb553e14da67bb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/14a6802cd513cfd2abf68044cca5fd7391eb543d", - "reference": "14a6802cd513cfd2abf68044cca5fd7391eb543d", + "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/64f0453f4dea6a6fabf1ce4ddbb553e14da67bb6", + "reference": "64f0453f4dea6a6fabf1ce4ddbb553e14da67bb6", "shasum": "" }, "require": { - "illuminate/database": "^9.0", - "illuminate/http": "^9.0", - "illuminate/support": "^9.0", - "php": "^8.0", + "illuminate/database": "^10.0|^11.0", + "illuminate/http": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "php": "^8.2", "spatie/laravel-package-tools": "^1.11" }, "require-dev": { "ext-json": "*", "mockery/mockery": "^1.4", - "orchestra/testbench": "^7.0", - "pestphp/pest": "^1.20", - "spatie/laravel-ray": "^1.28" + "nunomaduro/larastan": "^2.0", + "orchestra/testbench": "^7.0|^8.0", + "pestphp/pest": "^2.0", + "phpunit/phpunit": "^10.0", + "spatie/invade": "^2.0" }, "type": "library", "extra": { @@ -4907,61 +5572,205 @@ "description": "Easily build Eloquent queries from API requests", "homepage": "https://github.com/spatie/laravel-query-builder", "keywords": [ - "laravel-query-builder", + "laravel-query-builder", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-query-builder/issues", + "source": "https://github.com/spatie/laravel-query-builder" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + } + ], + "time": "2024-10-03T11:10:10+00:00" + }, + { + "name": "spatie/laravel-settings", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-settings.git", + "reference": "2da8cb5b051678725476b299ef8e13b2e5015260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-settings/zipball/2da8cb5b051678725476b299ef8e13b2e5015260", + "reference": "2da8cb5b051678725476b299ef8e13b2e5015260", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/database": "^8.73|^9.0|^10.0|^11.0", + "php": "^7.4|^8.0", + "phpdocumentor/type-resolver": "^1.5", + "spatie/temporary-directory": "^1.3|^2.0" + }, + "require-dev": { + "ext-redis": "*", + "larastan/larastan": "^2.0", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0", + "pestphp/pest": "^1.21|^2.0", + "pestphp/pest-plugin-laravel": "^1.2|^2.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5|^10.0", + "spatie/laravel-data": "^1.0.0|^2.0.0|^4.0.0", + "spatie/pest-plugin-snapshots": "^1.1|^2.0", + "spatie/phpunit-snapshot-assertions": "^4.2|^5.0", + "spatie/ray": "^1.36" + }, + "suggest": { + "spatie/data-transfer-object": "Allows for DTO casting to settings. (deprecated)" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\LaravelSettings\\LaravelSettingsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\LaravelSettings\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Store your application settings", + "homepage": "https://github.com/spatie/laravel-settings", + "keywords": [ + "laravel-settings", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-settings/issues", + "source": "https://github.com/spatie/laravel-settings/tree/3.4.0" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2024-09-20T13:48:17+00:00" + }, + { + "name": "spatie/laravel-validation-rules", + "version": "3.4.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-validation-rules.git", + "reference": "b629b0a1049ddfe18e5534717b1627bacfaef208" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-validation-rules/zipball/b629b0a1049ddfe18e5534717b1627bacfaef208", + "reference": "b629b0a1049ddfe18e5534717b1627bacfaef208", + "shasum": "" + }, + "require": { + "illuminate/support": "^8.0|^9.0|^10.0|^11.0", + "php": "^8.0" + }, + "require-dev": { + "laravel/pint": "^1.3", + "league/iso3166": "^3.0|^4.3", + "myclabs/php-enum": "^1.6", + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0", + "pestphp/pest": "^1.23|^2.6", + "spatie/enum": "^2.2|^3.0" + }, + "suggest": { + "league/iso3166": "Needed for the CountryCode rule and Currency rule" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\ValidationRules\\ValidationRulesServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\ValidationRules\\": "src", + "Spatie\\ValidationRules\\Database\\Factories\\": "database/factories" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "A set of useful Laravel validation rules", + "homepage": "https://github.com/spatie/laravel-validation-rules", + "keywords": [ + "laravel-validation-rules", "spatie" ], "support": { - "issues": "https://github.com/spatie/laravel-query-builder/issues", - "source": "https://github.com/spatie/laravel-query-builder" + "issues": "https://github.com/spatie/laravel-validation-rules/issues", + "source": "https://github.com/spatie/laravel-validation-rules/tree/3.4.0" }, "funding": [ { - "url": "https://spatie.be/open-source/support-us", - "type": "custom" + "url": "https://github.com/spatie", + "type": "github" } ], - "time": "2022-12-02T21:28:40+00:00" + "time": "2024-03-02T05:57:47+00:00" }, { - "name": "spatie/laravel-validation-rules", - "version": "3.2.1", + "name": "spatie/temporary-directory", + "version": "2.2.1", "source": { "type": "git", - "url": "https://github.com/spatie/laravel-validation-rules.git", - "reference": "47a63a724e10d72432d0dcdf438d1fecbc963bae" + "url": "https://github.com/spatie/temporary-directory.git", + "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-validation-rules/zipball/47a63a724e10d72432d0dcdf438d1fecbc963bae", - "reference": "47a63a724e10d72432d0dcdf438d1fecbc963bae", + "url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", + "reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a", "shasum": "" }, "require": { - "illuminate/support": "^8.0|^9.0", - "php": "^7.4|^8.0" + "php": "^8.0" }, "require-dev": { - "league/iso3166": "^3.0", - "myclabs/php-enum": "^1.6", - "orchestra/testbench": "^6.23|^7.0", - "phpunit/phpunit": "^9.4", - "spatie/enum": "^2.2|^3.0" - }, - "suggest": { - "league/iso3166": "Needed for the CountryCode rule and Currency rule" + "phpunit/phpunit": "^9.5" }, "type": "library", - "extra": { - "laravel": { - "providers": [ - "Spatie\\ValidationRules\\ValidationRulesServiceProvider" - ] - } - }, "autoload": { "psr-4": { - "Spatie\\ValidationRules\\": "src", - "Spatie\\ValidationRules\\Database\\Factories\\": "database/factories" + "Spatie\\TemporaryDirectory\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -4970,29 +5779,34 @@ ], "authors": [ { - "name": "Freek Van der Herten", - "email": "freek@spatie.be", + "name": "Alex Vanderbist", + "email": "alex@spatie.be", "homepage": "https://spatie.be", "role": "Developer" } ], - "description": "A set of useful Laravel validation rules", - "homepage": "https://github.com/spatie/laravel-validation-rules", + "description": "Easily create, use and destroy temporary directories", + "homepage": "https://github.com/spatie/temporary-directory", "keywords": [ - "laravel-validation-rules", - "spatie" + "php", + "spatie", + "temporary-directory" ], "support": { - "issues": "https://github.com/spatie/laravel-validation-rules/issues", - "source": "https://github.com/spatie/laravel-validation-rules/tree/3.2.1" + "issues": "https://github.com/spatie/temporary-directory/issues", + "source": "https://github.com/spatie/temporary-directory/tree/2.2.1" }, "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, { "url": "https://github.com/spatie", "type": "github" } ], - "time": "2022-08-01T11:52:01+00:00" + "time": "2023-12-25T11:46:58+00:00" }, { "name": "stripe/stripe-php", @@ -5054,51 +5868,122 @@ }, "time": "2022-05-05T17:18:02+00:00" }, + { + "name": "symfony/clock", + "version": "v7.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "97bebc53548684c17ed696bc8af016880f0f098d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/97bebc53548684c17ed696bc8af016880f0f098d", + "reference": "97bebc53548684c17ed696bc8af016880f0f098d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, { "name": "symfony/console", - "version": "v6.2.3", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0f579613e771dba2dbb8211c382342a641f5da06" + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0f579613e771dba2dbb8211c382342a641f5da06", - "reference": "0f579613e771dba2dbb8211c382342a641f5da06", + "url": "https://api.github.com/repos/symfony/console/zipball/ff04e5b5ba043d2badfb308197b9e6b42883fcd5", + "reference": "ff04e5b5ba043d2badfb308197b9e6b42883fcd5", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5127,12 +6012,12 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.2.3" + "source": "https://github.com/symfony/console/tree/v7.1.8" }, "funding": [ { @@ -5148,24 +6033,24 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:26:22+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/css-selector", - "version": "v6.2.3", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ab1df4ba3ded7b724766ba3a6e0eca0418e74f80" + "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab1df4ba3ded7b724766ba3a6e0eca0418e74f80", - "reference": "ab1df4ba3ded7b724766ba3a6e0eca0418e74f80", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", + "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -5197,7 +6082,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.2.3" + "source": "https://github.com/symfony/css-selector/tree/v7.1.6" }, "funding": [ { @@ -5213,20 +6098,20 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:26:22+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.2.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3", - "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", "shasum": "" }, "require": { @@ -5235,7 +6120,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5264,7 +6149,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" }, "funding": [ { @@ -5280,31 +6165,35 @@ "type": "tidelift" } ], - "time": "2022-11-25T10:21:52+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/error-handler", - "version": "v6.2.3", + "version": "v7.1.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "0926124c95d220499e2baf0fb465772af3a4eddb" + "reference": "010e44661f4c6babaf8c4862fe68c24a53903342" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/0926124c95d220499e2baf0fb465772af3a4eddb", - "reference": "0926124c95d220499e2baf0fb465772af3a4eddb", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/010e44661f4c6babaf8c4862fe68c24a53903342", + "reference": "010e44661f4c6babaf8c4862fe68c24a53903342", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" }, "require-dev": { - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -5335,7 +6224,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.2.3" + "source": "https://github.com/symfony/error-handler/tree/v7.1.7" }, "funding": [ { @@ -5351,28 +6240,29 @@ "type": "tidelift" } ], - "time": "2022-12-19T14:33:49+00:00" + "time": "2024-11-05T15:34:55+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.2.2", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1" + "reference": "87254c78dd50721cfd015b62277a8281c5589702" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ffeb31139b49bf6ef0bc09d1db95eac053388d1", - "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87254c78dd50721cfd015b62277a8281c5589702", + "reference": "87254c78dd50721cfd015b62277a8281c5589702", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/event-dispatcher-contracts": "^2|^3" + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" }, "provide": { "psr/event-dispatcher-implementation": "1.0", @@ -5380,17 +6270,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/stopwatch": "^5.4|^6.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5418,7 +6304,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.6" }, "funding": [ { @@ -5434,33 +6320,30 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:11:27+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.2.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "0782b0b52a737a05b4383d0df35a474303cabdae" + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0782b0b52a737a05b4383d0df35a474303cabdae", - "reference": "0782b0b52a737a05b4383d0df35a474303cabdae", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", + "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "suggest": { - "symfony/event-dispatcher-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5497,7 +6380,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" }, "funding": [ { @@ -5513,27 +6396,27 @@ "type": "tidelift" } ], - "time": "2022-11-25T10:21:52+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/finder", - "version": "v6.2.3", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e" + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/81eefbddfde282ee33b437ba5e13d7753211ae8e", - "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e", + "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5561,7 +6444,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.2.3" + "source": "https://github.com/symfony/finder/tree/v7.1.6" }, "funding": [ { @@ -5577,28 +6460,32 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:55:15+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/http-client", - "version": "v6.2.2", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "7054ad466f836309aef511789b9c697bc986d8ce" + "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/7054ad466f836309aef511789b9c697bc986d8ce", - "reference": "7054ad466f836309aef511789b9c697bc986d8ce", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", + "reference": "c30d91a1deac0dc3ed5e604683cf2e1dfc635b8a", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/http-client-contracts": "^3", - "symfony/service-contracts": "^1.0|^2|^3" + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" }, "provide": { "php-http/async-client-implementation": "*", @@ -5611,14 +6498,16 @@ "amphp/http-client": "^4.2.1", "amphp/http-tunnel": "^1.0", "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4", + "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5645,8 +6534,11 @@ ], "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", + "keywords": [ + "http" + ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.2.2" + "source": "https://github.com/symfony/http-client/tree/v7.1.8" }, "funding": [ { @@ -5662,32 +6554,29 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:11:27+00:00" + "time": "2024-11-13T13:40:27+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.2.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "c5f587eb445224ddfeb05b5ee703476742d730bf" + "reference": "20414d96f391677bf80078aa55baece78b82647d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c5f587eb445224ddfeb05b5ee703476742d730bf", - "reference": "c5f587eb445224ddfeb05b5ee703476742d730bf", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", "shasum": "" }, "require": { "php": ">=8.1" }, - "suggest": { - "symfony/http-client-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -5727,7 +6616,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.2.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" }, "funding": [ { @@ -5743,41 +6632,40 @@ "type": "tidelift" } ], - "time": "2022-11-25T10:21:52+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.2.2", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "ddf4dd35de1623e7c02013523e6c2137b67b636f" + "reference": "f4419ec69ccfc3f725a4de7c20e4e57626d10112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ddf4dd35de1623e7c02013523e6c2137b67b636f", - "reference": "ddf4dd35de1623e7c02013523e6c2137b67b636f", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f4419ec69ccfc3f725a4de7c20e4e57626d10112", + "reference": "f4419ec69ccfc3f725a4de7c20e4e57626d10112", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/polyfill-mbstring": "~1.1" + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.2" + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { - "predis/predis": "~1.0", - "symfony/cache": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^5.4|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" - }, - "suggest": { - "symfony/mime": "To use the file extension guesser" + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5805,7 +6693,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.2.2" + "source": "https://github.com/symfony/http-foundation/tree/v7.1.8" }, "funding": [ { @@ -5821,74 +6709,77 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:11:27+00:00" + "time": "2024-11-09T09:16:45+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.2.4", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "74f2e638ec3fa0315443bd85fab7fc8066b77f83" + "reference": "33fef24e3dc79d6d30bf4936531f2f4bd2ca189e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74f2e638ec3fa0315443bd85fab7fc8066b77f83", - "reference": "74f2e638ec3fa0315443bd85fab7fc8066b77f83", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/33fef24e3dc79d6d30bf4936531f2f4bd2ca189e", + "reference": "33fef24e3dc79d6d30bf4936531f2f4bd2ca189e", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.1|^3", - "symfony/error-handler": "^6.1", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/browser-kit": "<5.4", - "symfony/cache": "<5.4", - "symfony/config": "<6.1", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.2", - "symfony/doctrine-bridge": "<5.4", - "symfony/form": "<5.4", - "symfony/http-client": "<5.4", - "symfony/mailer": "<5.4", - "symfony/messenger": "<5.4", - "symfony/translation": "<5.4", - "symfony/twig-bridge": "<5.4", - "symfony/validator": "<5.4", - "twig/twig": "<2.13" + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.0.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^6.1", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.2", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/process": "^5.4|^6.0", - "symfony/routing": "^5.4|^6.0", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", - "symfony/translation-contracts": "^1.1|^2|^3", - "symfony/uid": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "suggest": { - "symfony/browser-kit": "", - "symfony/config": "", - "symfony/console": "", - "symfony/dependency-injection": "" + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.0.4" }, "type": "library", "autoload": { @@ -5916,7 +6807,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.2.4" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.8" }, "funding": [ { @@ -5932,28 +6823,32 @@ "type": "tidelift" } ], - "time": "2022-12-29T19:05:08+00:00" + "time": "2024-11-13T14:25:32+00:00" }, { "name": "symfony/intl", - "version": "v6.2.0", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "04726ae6cec43582f7dfbfc67a313d1ecdd81c0f" + "reference": "e56b243fc0afa5a12bd11dace4002ada5a7d99f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/04726ae6cec43582f7dfbfc67a313d1ecdd81c0f", - "reference": "04726ae6cec43582f7dfbfc67a313d1ecdd81c0f", + "url": "https://api.github.com/repos/symfony/intl/zipball/e56b243fc0afa5a12bd11dace4002ada5a7d99f8", + "reference": "e56b243fc0afa5a12bd11dace4002ada5a7d99f8", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/string": "<7.1" }, "require-dev": { - "symfony/filesystem": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0" + "symfony/filesystem": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -5961,7 +6856,8 @@ "Symfony\\Component\\Intl\\": "" }, "exclude-from-classmap": [ - "/Tests/" + "/Tests/", + "/Resources/data/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -5986,7 +6882,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a PHP replacement layer for the C intl extension that includes additional data from the ICU library", + "description": "Provides access to the localization data of the ICU library", "homepage": "https://symfony.com", "keywords": [ "i18n", @@ -5997,7 +6893,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.2.0" + "source": "https://github.com/symfony/intl/tree/v7.1.8" }, "funding": [ { @@ -6013,43 +6909,43 @@ "type": "tidelift" } ], - "time": "2022-11-02T09:08:04+00:00" + "time": "2024-11-08T15:46:42+00:00" }, { "name": "symfony/mailer", - "version": "6.3.x-dev", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "de3acc2fbc81d26957b551aabeea8b6cb0dc1f72" + "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/de3acc2fbc81d26957b551aabeea8b6cb0dc1f72", - "reference": "de3acc2fbc81d26957b551aabeea8b6cb0dc1f72", + "url": "https://api.github.com/repos/symfony/mailer/zipball/69c9948451fb3a6a4d47dc8261d1794734e76cdd", + "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3|^4", - "php": ">=8.1", + "php": ">=8.2", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^6.2", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", "symfony/service-contracts": "^2.5|^3" }, "conflict": { "symfony/http-client-contracts": "<2.5", - "symfony/http-kernel": "<5.4", - "symfony/messenger": "<6.2", - "symfony/mime": "<6.2", - "symfony/twig-bridge": "<6.2.1" + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0", - "symfony/http-client-contracts": "^2.5|^3", - "symfony/messenger": "^6.2", - "symfony/twig-bridge": "^6.2" + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -6077,7 +6973,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/6.3" + "source": "https://github.com/symfony/mailer/tree/v7.1.6" }, "funding": [ { @@ -6093,28 +6989,32 @@ "type": "tidelift" } ], - "time": "2023-01-23T14:48:49+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/mailgun-mailer", - "version": "v6.2.0", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "c5364fbcf5581ba9eae569db12b380b9255ce238" + "reference": "b0117bf42b6dd8dfcfcab2a7e18508b594520b5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/c5364fbcf5581ba9eae569db12b380b9255ce238", - "reference": "c5364fbcf5581ba9eae569db12b380b9255ce238", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/b0117bf42b6dd8dfcfcab2a7e18508b594520b5a", + "reference": "b0117bf42b6dd8dfcfcab2a7e18508b594520b5a", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/mailer": "^5.4|^6.0" + "php": ">=8.2", + "symfony/mailer": "^6.4|^7.0" + }, + "conflict": { + "symfony/http-foundation": "<6.4" }, "require-dev": { - "symfony/http-client": "^5.4|^6.0" + "symfony/http-client": "^6.4|^7.0", + "symfony/webhook": "^6.4|^7.0" }, "type": "symfony-mailer-bridge", "autoload": { @@ -6142,7 +7042,7 @@ "description": "Symfony Mailgun Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v6.2.0" + "source": "https://github.com/symfony/mailgun-mailer/tree/v7.1.6" }, "funding": [ { @@ -6158,24 +7058,24 @@ "type": "tidelift" } ], - "time": "2022-10-09T08:55:40+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/mime", - "version": "v6.2.2", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "8c98bf40406e791043890a163f6f6599b9cfa1ed" + "reference": "caa1e521edb2650b8470918dfe51708c237f0598" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/8c98bf40406e791043890a163f6f6599b9cfa1ed", - "reference": "8c98bf40406e791043890a163f6f6599b9cfa1ed", + "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", + "reference": "caa1e521edb2650b8470918dfe51708c237f0598", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -6183,17 +7083,18 @@ "egulias/email-validator": "~3.0.0", "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", - "symfony/mailer": "<5.4", - "symfony/serializer": "<6.2" + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" }, "require-dev": { - "egulias/email-validator": "^2.1.10|^3.1", + "egulias/email-validator": "^2.1.10|^3.1|^4", "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/property-access": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^6.2" + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" }, "type": "library", "autoload": { @@ -6225,7 +7126,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.2.2" + "source": "https://github.com/symfony/mime/tree/v7.1.6" }, "funding": [ { @@ -6241,24 +7142,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:38:10+00:00" + "time": "2024-10-25T15:11:02+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -6268,9 +7169,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6307,7 +7205,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" }, "funding": [ { @@ -6323,33 +7221,30 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6388,7 +7283,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" }, "funding": [ { @@ -6404,35 +7299,31 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6475,7 +7366,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" }, "funding": [ { @@ -6491,33 +7382,30 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6559,7 +7447,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" }, "funding": [ { @@ -6575,24 +7463,24 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -6602,9 +7490,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6642,7 +7527,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" }, "funding": [ { @@ -6658,30 +7543,27 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php72", - "version": "v1.27.0", + "name": "symfony/polyfill-php80", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6692,14 +7574,21 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -6709,7 +7598,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -6718,7 +7607,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" }, "funding": [ { @@ -6734,30 +7623,27 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "name": "symfony/polyfill-php83", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6768,7 +7654,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php83\\": "" }, "classmap": [ "Resources/stubs" @@ -6779,10 +7665,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -6792,7 +7674,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -6801,7 +7683,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -6817,24 +7699,24 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.27.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166" + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166", - "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-uuid": "*" @@ -6844,9 +7726,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" @@ -6883,7 +7762,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" }, "funding": [ { @@ -6899,24 +7778,24 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", - "version": "v6.2.0", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877" + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/ba6e55359f8f755fe996c58a81e00eaa67a35877", - "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877", + "url": "https://api.github.com/repos/symfony/process/zipball/42783370fda6e538771f7c7a36e9fa2ee3a84892", + "reference": "42783370fda6e538771f7c7a36e9fa2ee3a84892", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -6944,7 +7823,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.2.0" + "source": "https://github.com/symfony/process/tree/v7.1.8" }, "funding": [ { @@ -6960,45 +7839,38 @@ "type": "tidelift" } ], - "time": "2022-11-02T09:08:04+00:00" + "time": "2024-11-06T14:23:19+00:00" }, { "name": "symfony/routing", - "version": "v6.2.3", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "35fec764f3e2c8c08fb340d275c84bc78ca7e0c9" + "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/35fec764f3e2c8c08fb340d275c84bc78ca7e0c9", - "reference": "35fec764f3e2c8c08fb340d275c84bc78ca7e0c9", + "url": "https://api.github.com/repos/symfony/routing/zipball/66a2c469f6c22d08603235c46a20007c0701ea0a", + "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { - "doctrine/annotations": "<1.12", - "symfony/config": "<6.2", - "symfony/dependency-injection": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" }, "require-dev": { - "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "symfony/config": "For using the all-in-one router or any loader", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7032,7 +7904,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.2.3" + "source": "https://github.com/symfony/routing/tree/v7.1.6" }, "funding": [ { @@ -7048,36 +7920,34 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:41:15+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.2.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75" + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75", - "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -7117,7 +7987,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.2.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" }, "funding": [ { @@ -7133,38 +8003,39 @@ "type": "tidelift" } ], - "time": "2022-11-25T10:21:52+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/string", - "version": "v6.2.2", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "863219fd713fa41cbcd285a79723f94672faff4d" + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/863219fd713fa41cbcd285a79723f94672faff4d", - "reference": "863219fd713fa41cbcd285a79723f94672faff4d", + "url": "https://api.github.com/repos/symfony/string/zipball/591ebd41565f356fcd8b090fe64dbb5878f50281", + "reference": "591ebd41565f356fcd8b090fe64dbb5878f50281", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7203,7 +8074,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.2.2" + "source": "https://github.com/symfony/string/tree/v7.1.8" }, "funding": [ { @@ -7219,58 +8090,54 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:11:27+00:00" + "time": "2024-11-13T13:31:21+00:00" }, { "name": "symfony/translation", - "version": "v6.2.3", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "a2a15404ef4c15d92c205718eb828b225a144379" + "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/a2a15404ef4c15d92c205718eb828b225a144379", - "reference": "a2a15404ef4c15d92c205718eb828b225a144379", + "url": "https://api.github.com/repos/symfony/translation/zipball/b9f72ab14efdb6b772f85041fa12f820dee8d55f", + "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation-contracts": "^2.3|^3.0" + "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { - "symfony/config": "<5.4", - "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", - "symfony/http-kernel": "<5.4", - "symfony/twig-bundle": "<5.4", - "symfony/yaml": "<5.4" + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" }, "provide": { "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.13", + "nikic/php-parser": "^4.18|^5.0", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/console": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-client-contracts": "^1.1|^2.0|^3.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/intl": "^5.4|^6.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/polyfill-intl-icu": "^1.21", - "symfony/routing": "^5.4|^6.0", - "symfony/service-contracts": "^1.1.2|^2|^3", - "symfony/yaml": "^5.4|^6.0" - }, - "suggest": { - "nikic/php-parser": "To use PhpAstExtractor", - "psr/log-implementation": "To use logging capability in translator", - "symfony/config": "", - "symfony/yaml": "" + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7301,7 +8168,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.2.3" + "source": "https://github.com/symfony/translation/tree/v7.1.6" }, "funding": [ { @@ -7317,32 +8184,29 @@ "type": "tidelift" } ], - "time": "2022-12-23T14:11:11+00:00" + "time": "2024-09-28T12:35:13+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.2.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "68cce71402305a015f8c1589bfada1280dc64fe7" + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/68cce71402305a015f8c1589bfada1280dc64fe7", - "reference": "68cce71402305a015f8c1589bfada1280dc64fe7", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", "shasum": "" }, "require": { "php": ">=8.1" }, - "suggest": { - "symfony/translation-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.3-dev" + "dev-main": "3.5-dev" }, "thanks": { "name": "symfony/contracts", @@ -7382,7 +8246,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.2.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" }, "funding": [ { @@ -7398,28 +8262,28 @@ "type": "tidelift" } ], - "time": "2022-11-25T10:21:52+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/uid", - "version": "v6.2.0", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "4f9f537e57261519808a7ce1d941490736522bbc" + "reference": "65befb3bb2d503bbffbd08c815aa38b472999917" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/4f9f537e57261519808a7ce1d941490736522bbc", - "reference": "4f9f537e57261519808a7ce1d941490736522bbc", + "url": "https://api.github.com/repos/symfony/uid/zipball/65befb3bb2d503bbffbd08c815aa38b472999917", + "reference": "65befb3bb2d503bbffbd08c815aa38b472999917", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -7456,7 +8320,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.2.0" + "source": "https://github.com/symfony/uid/tree/v7.1.6" }, "funding": [ { @@ -7472,41 +8336,36 @@ "type": "tidelift" } ], - "time": "2022-10-09T08:55:40+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.2.3", + "version": "v7.1.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0" + "reference": "7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0", - "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8", + "reference": "7bb01a47b1b00428d32b5e7b4d3b2d1aa58d3db8", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "phpunit/phpunit": "<5.4.3", - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "twig/twig": "^2.13|^3.0.4" - }, - "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-intl": "To show region name in time zone dump", - "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.0.4" }, "bin": [ "Resources/bin/var-dump-server" @@ -7544,7 +8403,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.2.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.8" }, "funding": [ { @@ -7560,27 +8419,27 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:55:15+00:00" + "time": "2024-11-08T15:46:42+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "2.2.6", + "version": "v2.2.7", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c" + "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/c42125b83a4fa63b187fdf29f9c93cb7733da30c", - "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb", + "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "php": "^5.5 || ^7.0 || ^8.0", - "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0" + "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" @@ -7611,37 +8470,37 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.6" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.2.7" }, - "time": "2023-01-03T09:29:04+00:00" + "time": "2023-12-08T13:03:43+00:00" }, { "name": "vlucas/phpdotenv", - "version": "v5.5.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7" + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", - "reference": "1a7ea2afc49c3ee6d87061f5a233e3a035d0eae7", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/a59a13791077fe3d44f90e7133eb68e7d22eaff2", + "reference": "a59a13791077fe3d44f90e7133eb68e7d22eaff2", "shasum": "" }, "require": { "ext-pcre": "*", - "graham-campbell/result-type": "^1.0.2", - "php": "^7.1.3 || ^8.0", - "phpoption/phpoption": "^1.8", - "symfony/polyfill-ctype": "^1.23", - "symfony/polyfill-mbstring": "^1.23.1", - "symfony/polyfill-php80": "^1.23.1" + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4.1", + "bamarni/composer-bin-plugin": "^1.8.2", "ext-filter": "*", - "phpunit/phpunit": "^7.5.20 || ^8.5.30 || ^9.5.25" + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" }, "suggest": { "ext-filter": "Required to use the boolean validator." @@ -7650,10 +8509,10 @@ "extra": { "bamarni-bin": { "bin-links": true, - "forward-command": true + "forward-command": false }, "branch-alias": { - "dev-master": "5.5-dev" + "dev-master": "5.6-dev" } }, "autoload": { @@ -7685,7 +8544,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v5.5.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.1" }, "funding": [ { @@ -7697,7 +8556,7 @@ "type": "tidelift" } ], - "time": "2022-10-16T01:01:54+00:00" + "time": "2024-07-20T21:52:34+00:00" }, { "name": "voku/portable-ascii", @@ -7833,39 +8692,46 @@ }, { "name": "yajra/laravel-datatables-oracle", - "version": "v9.21.2", + "version": "v11.1.5", "source": { "type": "git", "url": "https://github.com/yajra/laravel-datatables.git", - "reference": "a7fd01f06282923e9c63fa27fe6b391e21dc321a" + "reference": "158f2e9cf76d500c707a0ebd6cd2079cd87b8d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/yajra/laravel-datatables/zipball/a7fd01f06282923e9c63fa27fe6b391e21dc321a", - "reference": "a7fd01f06282923e9c63fa27fe6b391e21dc321a", + "url": "https://api.github.com/repos/yajra/laravel-datatables/zipball/158f2e9cf76d500c707a0ebd6cd2079cd87b8d4a", + "reference": "158f2e9cf76d500c707a0ebd6cd2079cd87b8d4a", "shasum": "" }, "require": { - "illuminate/database": "5.8.*|^6|^7|^8|^9", - "illuminate/filesystem": "5.8.*|^6|^7|^8|^9", - "illuminate/http": "5.8.*|^6|^7|^8|^9", - "illuminate/support": "5.8.*|^6|^7|^8|^9", - "illuminate/view": "5.8.*|^6|^7|^8|^9", - "php": "^7.1.3|^8" + "illuminate/database": "^11", + "illuminate/filesystem": "^11", + "illuminate/http": "^11", + "illuminate/support": "^11", + "illuminate/view": "^11", + "php": "^8.2" }, "require-dev": { - "orchestra/testbench": "^3.8|^4.0|^5.0|^6.0|^7.0" + "algolia/algoliasearch-client-php": "^3.4.1", + "larastan/larastan": "^2.9.1", + "laravel/pint": "^1.14", + "laravel/scout": "^10.8.3", + "meilisearch/meilisearch-php": "^1.6.1", + "orchestra/testbench": "^9", + "rector/rector": "^1.0" }, "suggest": { "yajra/laravel-datatables-buttons": "Plugin for server-side exporting of dataTables.", "yajra/laravel-datatables-editor": "Plugin to use DataTables Editor (requires a license).", + "yajra/laravel-datatables-export": "Plugin for server-side exporting using livewire and queue worker.", "yajra/laravel-datatables-fractal": "Plugin for server-side response using Fractal.", "yajra/laravel-datatables-html": "Plugin for server-side HTML builder of dataTables." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "9.0-dev" + "dev-master": "11.x-dev" }, "laravel": { "providers": [ @@ -7894,62 +8760,59 @@ "email": "aqangeles@gmail.com" } ], - "description": "jQuery DataTables API for Laravel 5|6|7|8|9", + "description": "jQuery DataTables API for Laravel", "keywords": [ "datatables", "jquery", - "laravel" + "laravel", + "yajra" ], "support": { "issues": "https://github.com/yajra/laravel-datatables/issues", - "source": "https://github.com/yajra/laravel-datatables/tree/v9.21.2" + "source": "https://github.com/yajra/laravel-datatables/tree/v11.1.5" }, "funding": [ { - "url": "https://www.paypal.me/yajra", - "type": "custom" - }, - { - "url": "https://www.patreon.com/yajra", - "type": "patreon" + "url": "https://github.com/sponsors/yajra", + "type": "github" } ], - "time": "2022-07-12T04:48:03+00:00" + "time": "2024-08-26T01:43:52+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.7.0", + "version": "v3.14.7", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "3372ed65e6d2039d663ed19aa699956f9d346271" + "reference": "f484b8c9124de0b163da39958331098ffcd4a65e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/3372ed65e6d2039d663ed19aa699956f9d346271", - "reference": "3372ed65e6d2039d663ed19aa699956f9d346271", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/f484b8c9124de0b163da39958331098ffcd4a65e", + "reference": "f484b8c9124de0b163da39958331098ffcd4a65e", "shasum": "" }, "require": { - "illuminate/routing": "^7|^8|^9", - "illuminate/session": "^7|^8|^9", - "illuminate/support": "^7|^8|^9", - "maximebf/debugbar": "^1.17.2", - "php": ">=7.2.5", - "symfony/finder": "^5|^6" + "illuminate/routing": "^9|^10|^11", + "illuminate/session": "^9|^10|^11", + "illuminate/support": "^9|^10|^11", + "maximebf/debugbar": "~1.23.0", + "php": "^8.0", + "symfony/finder": "^6|^7" }, "require-dev": { "mockery/mockery": "^1.3.3", - "orchestra/testbench-dusk": "^5|^6|^7", - "phpunit/phpunit": "^8.5|^9.0", + "orchestra/testbench-dusk": "^5|^6|^7|^8|^9", + "phpunit/phpunit": "^9.6|^10.5", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.6-dev" + "dev-master": "3.14-dev" }, "laravel": { "providers": [ @@ -7987,103 +8850,33 @@ "webprofiler" ], "support": { - "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.7.0" - }, - "funding": [ - { - "url": "https://fruitcake.nl", - "type": "custom" - }, - { - "url": "https://github.com/barryvdh", - "type": "github" - } - ], - "time": "2022-07-11T09:26:42+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "2.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^11", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-phpunit": "^1.3", - "phpunit/phpunit": "^9.5.27", - "vimeo/psalm": "^5.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/2.0.0" + "issues": "https://github.com/barryvdh/laravel-debugbar/issues", + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.7" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", + "url": "https://fruitcake.nl", "type": "custom" }, { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" + "url": "https://github.com/barryvdh", + "type": "github" } ], - "time": "2022-12-30T00:23:10+00:00" + "time": "2024-11-14T09:12:35+00:00" }, { "name": "fakerphp/faker", - "version": "v1.21.0", + "version": "v1.24.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d" + "reference": "a136842a532bac9ecd8a1c723852b09915d7db50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/92efad6a967f0b79c499705c69b662f738cc9e4d", - "reference": "92efad6a967f0b79c499705c69b662f738cc9e4d", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/a136842a532bac9ecd8a1c723852b09915d7db50", + "reference": "a136842a532bac9ecd8a1c723852b09915d7db50", "shasum": "" }, "require": { @@ -8109,11 +8902,6 @@ "ext-mbstring": "Required for multibyte Unicode string functionality." }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "v1.21-dev" - } - }, "autoload": { "psr-4": { "Faker\\": "src/Faker/" @@ -8136,32 +8924,32 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.21.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.0" }, - "time": "2022-12-13T13:54:32+00:00" + "time": "2024-11-07T15:11:20+00:00" }, { "name": "filp/whoops", - "version": "2.14.6", + "version": "2.16.0", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "f7948baaa0330277c729714910336383286305da" + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/f7948baaa0330277c729714910336383286305da", - "reference": "f7948baaa0330277c729714910336383286305da", + "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", + "php": "^7.1 || ^8.0", "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { - "mockery/mockery": "^0.9 || ^1.0", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.3", - "symfony/var-dumper": "^2.6 || ^3.0 || ^4.0 || ^5.0" + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" }, "suggest": { "symfony/var-dumper": "Pretty print complex values better with var-dumper available", @@ -8201,7 +8989,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.14.6" + "source": "https://github.com/filp/whoops/tree/2.16.0" }, "funding": [ { @@ -8209,7 +8997,7 @@ "type": "github" } ], - "time": "2022-11-02T16:23:29+00:00" + "time": "2024-09-25T12:00:00+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -8264,32 +9052,35 @@ }, { "name": "laravel/sail", - "version": "v1.18.1", + "version": "v1.38.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "a64f78a4ab86c04a4c5de39bea20a8d36ad48a22" + "reference": "d17abae06661dd6c46d13627b1683a2924259145" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/a64f78a4ab86c04a4c5de39bea20a8d36ad48a22", - "reference": "a64f78a4ab86c04a4c5de39bea20a8d36ad48a22", + "url": "https://api.github.com/repos/laravel/sail/zipball/d17abae06661dd6c46d13627b1683a2924259145", + "reference": "d17abae06661dd6c46d13627b1683a2924259145", "shasum": "" }, "require": { - "illuminate/console": "^8.0|^9.0|^10.0", - "illuminate/contracts": "^8.0|^9.0|^10.0", - "illuminate/support": "^8.0|^9.0|^10.0", - "php": "^7.3|^8.0" + "illuminate/console": "^9.52.16|^10.0|^11.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0", + "illuminate/support": "^9.52.16|^10.0|^11.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0", + "phpstan/phpstan": "^1.10" }, "bin": [ "bin/sail" ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - }, "laravel": { "providers": [ "Laravel\\Sail\\SailServiceProvider" @@ -8320,29 +9111,31 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2023-01-11T14:35:04+00:00" + "time": "2024-11-11T20:16:51+00:00" }, { "name": "maximebf/debugbar", - "version": "v1.18.1", + "version": "v1.23.3", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "ba0af68dd4316834701ecb30a00ce9604ced3ee9" + "reference": "687400043d77943ef95e8417cb44e1673ee57844" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/ba0af68dd4316834701ecb30a00ce9604ced3ee9", - "reference": "ba0af68dd4316834701ecb30a00ce9604ced3ee9", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/687400043d77943ef95e8417cb44e1673ee57844", + "reference": "687400043d77943ef95e8417cb44e1673ee57844", "shasum": "" }, "require": { - "php": "^7.1|^8", + "php": "^7.2|^8", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^2.6|^3|^4|^5|^6" + "symfony/var-dumper": "^4|^5|^6|^7" }, "require-dev": { - "phpunit/phpunit": "^7.5.20 || ^9.4.2", + "dbrekelmans/bdi": "^1", + "phpunit/phpunit": "^8|^9", + "symfony/panther": "^1|^2.1", "twig/twig": "^1.38|^2.7|^3.0" }, "suggest": { @@ -8353,7 +9146,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.18-dev" + "dev-master": "1.23-dev" } }, "autoload": { @@ -8384,44 +9177,44 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.18.1" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.23.3" }, - "time": "2022-03-31T14:55:54+00:00" + "time": "2024-10-29T12:24:25+00:00" }, { "name": "mockery/mockery", - "version": "1.5.1", + "version": "1.6.12", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e" + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/e92dcc83d5a51851baf5f5591d32cb2b16e3684e", - "reference": "e92dcc83d5a51851baf5f5591d32cb2b16e3684e", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "^2.0.1", "lib-pcre": ">=7.0", - "php": "^7.3 || ^8.0" + "php": ">=7.3" }, "conflict": { "phpunit/phpunit": "<8.0" }, "require-dev": { - "phpunit/phpunit": "^8.5 || ^9.3" + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, "autoload": { - "psr-0": { - "Mockery": "library/" + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" } }, "notification-url": "https://packagist.org/downloads/", @@ -8432,12 +9225,20 @@ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", - "homepage": "http://blog.astrumfutura.com" + "homepage": "https://github.com/padraic", + "role": "Author" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", - "homepage": "http://davedevelopment.co.uk" + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" } ], "description": "Mockery is a simple yet flexible PHP mock object framework", @@ -8455,23 +9256,26 @@ "testing" ], "support": { + "docs": "https://docs.mockery.io/", "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.5.1" + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" }, - "time": "2022-09-07T15:32:08+00:00" + "time": "2024-05-16T03:13:13+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -8479,11 +9283,12 @@ }, "conflict": { "doctrine/collections": "<1.6.8", - "doctrine/common": "<2.13.3 || >=3,<3.2.2" + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { "doctrine/collections": "^1.6.8", "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", @@ -8509,7 +9314,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -8517,49 +9322,58 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nunomaduro/collision", - "version": "v6.4.0", + "version": "v8.5.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "f05978827b9343cba381ca05b8c7deee346b6015" + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f05978827b9343cba381ca05b8c7deee346b6015", - "reference": "f05978827b9343cba381ca05b8c7deee346b6015", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", "shasum": "" }, "require": { - "filp/whoops": "^2.14.5", - "php": "^8.0.0", - "symfony/console": "^6.0.2" + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", + "php": "^8.2.0", + "symfony/console": "^7.1.5" + }, + "conflict": { + "laravel/framework": "<11.0.0 || >=12.0.0", + "phpunit/phpunit": "<10.5.1 || >=12.0.0" }, "require-dev": { - "brianium/paratest": "^6.4.1", - "laravel/framework": "^9.26.1", - "laravel/pint": "^1.1.1", - "nunomaduro/larastan": "^1.0.3", - "nunomaduro/mock-final-classes": "^1.1.0", - "orchestra/testbench": "^7.7", - "phpunit/phpunit": "^9.5.23", - "spatie/ignition": "^1.4.1" + "larastan/larastan": "^2.9.8", + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", "extra": { - "branch-alias": { - "dev-develop": "6.x-dev" - }, "laravel": { "providers": [ "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" } }, "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], "psr-4": { "NunoMaduro\\Collision\\": "src/" } @@ -8605,24 +9419,25 @@ "type": "patreon" } ], - "time": "2023-01-03T12:54:54+00:00" + "time": "2024-10-15T16:06:32+00:00" }, { "name": "phar-io/manifest", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", - "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-phar": "*", "ext-xmlwriter": "*", "phar-io/version": "^3.0.1", @@ -8663,9 +9478,15 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/2.0.3" + "source": "https://github.com/phar-io/manifest/tree/2.0.4" }, - "time": "2021-07-20T11:28:43+00:00" + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" }, { "name": "phar-io/version", @@ -8720,44 +9541,44 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.23", + "version": "11.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c" + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", - "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.3", - "phpunit/php-text-template": "^2.0.2", - "sebastian/code-unit-reverse-lookup": "^2.0.2", - "sebastian/complexity": "^2.0", - "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0.3", - "sebastian/version": "^3.0.1", - "theseer/tokenizer": "^1.2.0" + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.4.1" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "9.2-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { @@ -8785,7 +9606,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" }, "funding": [ { @@ -8793,32 +9615,32 @@ "type": "github" } ], - "time": "2022-12-28T12:41:10+00:00" + "time": "2024-10-09T06:21:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -8845,7 +9667,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -8853,28 +9676,28 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-pcntl": "*" @@ -8882,7 +9705,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -8908,7 +9731,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -8916,32 +9740,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -8967,7 +9791,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -8975,32 +9800,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "7.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -9026,7 +9851,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -9034,54 +9860,51 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { "name": "phpunit/phpunit", - "version": "9.5.28", + "version": "11.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "954ca3113a03bf780d22f07bf055d883ee04b65e" + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/954ca3113a03bf780d22f07bf055d883ee04b65e", - "reference": "954ca3113a03bf780d22f07bf055d883ee04b65e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.3.1 || ^2", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.3", - "phar-io/version": "^3.0.2", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", - "phpunit/php-file-iterator": "^3.0.5", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.3", - "phpunit/php-timer": "^5.0.2", - "sebastian/cli-parser": "^1.0.1", - "sebastian/code-unit": "^1.0.6", - "sebastian/comparator": "^4.0.8", - "sebastian/diff": "^4.0.3", - "sebastian/environment": "^5.1.3", - "sebastian/exporter": "^4.0.5", - "sebastian/global-state": "^5.0.1", - "sebastian/object-enumerator": "^4.0.3", - "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^3.2", - "sebastian/version": "^3.0.2" + "myclabs/deep-copy": "^1.12.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.1", + "sebastian/comparator": "^6.1.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.1.3", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -9089,7 +9912,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-main": "11.4-dev" } }, "autoload": { @@ -9120,7 +9943,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.28" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" }, "funding": [ { @@ -9136,32 +9960,32 @@ "type": "tidelift" } ], - "time": "2023-01-14T12:32:24+00:00" + "time": "2024-10-28T13:07:50+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", - "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -9184,7 +10008,8 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -9192,32 +10017,32 @@ "type": "github" } ], - "time": "2020-09-28T06:08:49+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -9240,7 +10065,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" }, "funding": [ { @@ -9248,32 +10074,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2024-07-03T04:44:28+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -9295,7 +10121,8 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -9303,34 +10130,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.2-dev" } }, "autoload": { @@ -9369,7 +10198,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" }, "funding": [ { @@ -9377,33 +10207,33 @@ "type": "github" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2024-10-31T05:30:08+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", - "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { - "nikic/php-parser": "^4.7", - "php": ">=7.3" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -9426,7 +10256,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -9434,33 +10265,33 @@ "type": "github" } ], - "time": "2020-10-26T15:52:27+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3", + "phpunit/phpunit": "^11.0", "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -9492,7 +10323,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -9500,27 +10332,27 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "suggest": { "ext-posix": "*" @@ -9528,7 +10360,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -9547,7 +10379,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -9555,7 +10387,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { @@ -9563,34 +10396,34 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2024-07-03T04:54:44+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.5", + "version": "6.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", - "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -9632,7 +10465,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" }, "funding": [ { @@ -9640,38 +10474,35 @@ "type": "github" } ], - "time": "2022-09-14T06:03:37+00:00" + "time": "2024-07-03T04:56:19+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "7.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -9690,13 +10521,14 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -9704,33 +10536,33 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.3", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", - "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { - "nikic/php-parser": "^4.6", - "php": ">=7.3" + "nikic/php-parser": "^5.0", + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -9753,7 +10585,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -9761,34 +10594,34 @@ "type": "github" } ], - "time": "2020-11-28T06:42:11+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -9810,7 +10643,8 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { @@ -9818,32 +10652,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -9865,7 +10699,8 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { @@ -9873,32 +10708,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -9925,65 +10760,11 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-10-26T13:17:30+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "issues": "https://github.com/sebastianbergmann/resource-operations/issues", - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { @@ -9991,32 +10772,32 @@ "type": "github" } ], - "time": "2020-09-28T06:45:17+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -10039,7 +10820,8 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" }, "funding": [ { @@ -10047,29 +10829,29 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2024-09-17T13:12:04+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -10092,7 +10874,8 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -10100,20 +10883,20 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "spatie/backtrace", - "version": "1.2.1", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "4ee7d41aa5268107906ea8a4d9ceccde136dbd5b" + "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/4ee7d41aa5268107906ea8a4d9ceccde136dbd5b", - "reference": "4ee7d41aa5268107906ea8a4d9ceccde136dbd5b", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/1a9a145b044677ae3424693f7b06479fc8c137a9", + "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9", "shasum": "" }, "require": { @@ -10121,7 +10904,9 @@ }, "require-dev": { "ext-json": "*", + "laravel/serializable-closure": "^1.3", "phpunit/phpunit": "^9.3", + "spatie/phpunit-snapshot-assertions": "^4.2", "symfony/var-dumper": "^5.1" }, "type": "library", @@ -10149,8 +10934,7 @@ "spatie" ], "support": { - "issues": "https://github.com/spatie/backtrace/issues", - "source": "https://github.com/spatie/backtrace/tree/1.2.1" + "source": "https://github.com/spatie/backtrace/tree/1.6.2" }, "funding": [ { @@ -10162,43 +10946,117 @@ "type": "other" } ], - "time": "2021-11-09T10:57:15+00:00" + "time": "2024-07-22T08:21:24+00:00" + }, + { + "name": "spatie/error-solutions", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/error-solutions.git", + "reference": "ae7393122eda72eed7cc4f176d1e96ea444f2d67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/ae7393122eda72eed7cc4f176d1e96ea444f2d67", + "reference": "ae7393122eda72eed7cc4f176d1e96ea444f2d67", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "illuminate/broadcasting": "^10.0|^11.0", + "illuminate/cache": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "livewire/livewire": "^2.11|^3.3.5", + "openai-php/client": "^0.10.1", + "orchestra/testbench": "^7.0|8.22.3|^9.0", + "pestphp/pest": "^2.20", + "phpstan/phpstan": "^1.11", + "psr/simple-cache": "^3.0", + "psr/simple-cache-implementation": "^3.0", + "spatie/ray": "^1.28", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "simple-cache-implementation": "To cache solutions from OpenAI" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Ignition\\": "legacy/ignition", + "Spatie\\ErrorSolutions\\": "src", + "Spatie\\LaravelIgnition\\": "legacy/laravel-ignition" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ruben Van Assche", + "email": "ruben@spatie.be", + "role": "Developer" + } + ], + "description": "This is my package error-solutions", + "homepage": "https://github.com/spatie/error-solutions", + "keywords": [ + "error-solutions", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/error-solutions/issues", + "source": "https://github.com/spatie/error-solutions/tree/1.1.1" + }, + "funding": [ + { + "url": "https://github.com/Spatie", + "type": "github" + } + ], + "time": "2024-07-25T11:06:04+00:00" }, { "name": "spatie/flare-client-php", - "version": "1.3.3", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/spatie/flare-client-php.git", - "reference": "f5aea0629d1fff794b2aabbcd483bd83824b112f" + "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/f5aea0629d1fff794b2aabbcd483bd83824b112f", - "reference": "f5aea0629d1fff794b2aabbcd483bd83824b112f", + "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122", + "reference": "180f8ca4c0d0d6fc51477bd8c53ce37ab5a96122", "shasum": "" }, "require": { - "illuminate/pipeline": "^8.0|^9.0", + "illuminate/pipeline": "^8.0|^9.0|^10.0|^11.0", "php": "^8.0", - "spatie/backtrace": "^1.2", - "symfony/http-foundation": "^5.0|^6.0", - "symfony/mime": "^5.2|^6.0", - "symfony/process": "^5.2|^6.0", - "symfony/var-dumper": "^5.2|^6.0" + "spatie/backtrace": "^1.6.1", + "symfony/http-foundation": "^5.2|^6.0|^7.0", + "symfony/mime": "^5.2|^6.0|^7.0", + "symfony/process": "^5.2|^6.0|^7.0", + "symfony/var-dumper": "^5.2|^6.0|^7.0" }, "require-dev": { - "dms/phpunit-arraysubset-asserts": "^0.3.0", - "pestphp/pest": "^1.20", + "dms/phpunit-arraysubset-asserts": "^0.5.0", + "pestphp/pest": "^1.20|^2.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "spatie/phpunit-snapshot-assertions": "^4.0" + "spatie/pest-plugin-snapshots": "^1.0|^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.1.x-dev" + "dev-main": "1.3.x-dev" } }, "autoload": { @@ -10223,7 +11081,7 @@ ], "support": { "issues": "https://github.com/spatie/flare-client-php/issues", - "source": "https://github.com/spatie/flare-client-php/tree/1.3.3" + "source": "https://github.com/spatie/flare-client-php/tree/1.8.0" }, "funding": [ { @@ -10231,43 +11089,51 @@ "type": "github" } ], - "time": "2022-12-26T14:37:55+00:00" + "time": "2024-08-01T08:27:26+00:00" }, { "name": "spatie/ignition", - "version": "1.4.2", + "version": "1.15.0", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "79a2eedbfa88955bb41411e61f7db9134c9a6a82" + "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/79a2eedbfa88955bb41411e61f7db9134c9a6a82", - "reference": "79a2eedbfa88955bb41411e61f7db9134c9a6a82", + "url": "https://api.github.com/repos/spatie/ignition/zipball/e3a68e137371e1eb9edc7f78ffa733f3b98991d2", + "reference": "e3a68e137371e1eb9edc7f78ffa733f3b98991d2", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", - "monolog/monolog": "^2.0", "php": "^8.0", - "spatie/flare-client-php": "^1.1", - "symfony/console": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "spatie/error-solutions": "^1.0", + "spatie/flare-client-php": "^1.7", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "require-dev": { + "illuminate/cache": "^9.52|^10.0|^11.0", "mockery/mockery": "^1.4", - "pestphp/pest": "^1.20", + "pestphp/pest": "^1.20|^2.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-phpunit": "^1.0", - "symfony/process": "^5.4|^6.0" + "psr/simple-cache-implementation": "*", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "simple-cache-implementation": "To cache solutions from OpenAI" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.2.x-dev" + "dev-main": "1.5.x-dev" } }, "autoload": { @@ -10306,45 +11172,46 @@ "type": "github" } ], - "time": "2023-01-23T15:14:00+00:00" + "time": "2024-06-12T14:55:22+00:00" }, { "name": "spatie/laravel-ignition", - "version": "1.6.4", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "1a2b4bd3d48c72526c0ba417687e5c56b5cf49bc" + "reference": "3c067b75bfb50574db8f7e2c3978c65eed71126c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1a2b4bd3d48c72526c0ba417687e5c56b5cf49bc", - "reference": "1a2b4bd3d48c72526c0ba417687e5c56b5cf49bc", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/3c067b75bfb50574db8f7e2c3978c65eed71126c", + "reference": "3c067b75bfb50574db8f7e2c3978c65eed71126c", "shasum": "" }, "require": { "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", - "illuminate/support": "^8.77|^9.27", - "monolog/monolog": "^2.3", - "php": "^8.0", - "spatie/flare-client-php": "^1.0.1", - "spatie/ignition": "^1.4.1", - "symfony/console": "^5.0|^6.0", - "symfony/var-dumper": "^5.0|^6.0" + "illuminate/support": "^10.0|^11.0", + "php": "^8.1", + "spatie/ignition": "^1.15", + "symfony/console": "^6.2.3|^7.0", + "symfony/var-dumper": "^6.2.3|^7.0" }, "require-dev": { - "filp/whoops": "^2.14", - "livewire/livewire": "^2.8|dev-develop", - "mockery/mockery": "^1.4", - "nunomaduro/larastan": "^1.0", - "orchestra/testbench": "^6.23|^7.0", - "pestphp/pest": "^1.20", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0", - "spatie/laravel-ray": "^1.27" + "livewire/livewire": "^2.11|^3.3.5", + "mockery/mockery": "^1.5.1", + "openai-php/client": "^0.8.1", + "orchestra/testbench": "8.22.3|^9.0", + "pestphp/pest": "^2.34", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.16", + "vlucas/phpdotenv": "^5.5" + }, + "suggest": { + "openai-php/client": "Require get solutions from OpenAI", + "psr/simple-cache-implementation": "Needed to cache solutions from OpenAI" }, "type": "library", "extra": { @@ -10396,20 +11263,91 @@ "type": "github" } ], - "time": "2023-01-03T19:28:04+00:00" + "time": "2024-06-12T15:01:18+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", + "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.1", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", - "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", "shasum": "" }, "require": { @@ -10438,7 +11376,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" }, "funding": [ { @@ -10446,7 +11384,7 @@ "type": "github" } ], - "time": "2021-07-28T10:34:58+00:00" + "time": "2024-03-03T12:36:25+00:00" } ], "aliases": [], @@ -10455,12 +11393,14 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.1", - "ext-intl": "*" + "php": "^8.2", + "ext-intl": "*", + "ext-mysqli": "*", + "ext-curl": "*" }, "platform-dev": [], "platform-overrides": { - "php": "8.1" + "php": "8.2" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.3.0" } diff --git a/config/app.php b/config/app.php index c5956ed69..7c7b09a3d 100644 --- a/config/app.php +++ b/config/app.php @@ -4,7 +4,7 @@ return [ - 'version' => '0.9.8', + 'version' => '1.0.0', /* |-------------------------------------------------------------------------- @@ -17,7 +17,7 @@ | */ - 'name' => env('APP_NAME', 'Ctrlpanel.gg'), + 'name' => env('APP_NAME', 'CtrlPanel.gg'), /* |-------------------------------------------------------------------------- @@ -210,9 +210,9 @@ App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, Yajra\DataTables\DataTablesServiceProvider::class, - KKomelin\TranslatableStringExporter\Providers\ExporterServiceProvider::class, - + Biscolab\ReCaptcha\ReCaptchaServiceProvider::class, + App\Providers\DiscordServiceProvider::class, ], /* diff --git a/config/logging.php b/config/logging.php index 5aa1dbb78..5d4134ffa 100644 --- a/config/logging.php +++ b/config/logging.php @@ -61,6 +61,7 @@ 'driver' => 'single', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), + 'permission' => 0664, ], 'daily' => [ @@ -68,6 +69,7 @@ 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'days' => 14, + 'permission' => 0664, ], 'slack' => [ @@ -116,6 +118,7 @@ 'emergency' => [ 'path' => storage_path('logs/laravel.log'), + 'permission' => 0664, ], ], diff --git a/config/mail.php b/config/mail.php index 534395a36..867155b50 100644 --- a/config/mail.php +++ b/config/mail.php @@ -93,7 +93,7 @@ 'from' => [ 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), - 'name' => env('MAIL_FROM_NAME', 'Example'), + 'name' => env('MAIL_FROM_NAME', 'CtrlPanel'), ], /* diff --git a/config/permission.php b/config/permission.php new file mode 100644 index 000000000..f06debdc4 --- /dev/null +++ b/config/permission.php @@ -0,0 +1,161 @@ + [ + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * Eloquent model should be used to retrieve your permissions. Of course, it + * is often just the "Permission" model but you may use whatever you like. + * + * The model you want to use as a Permission model needs to implement the + * `Spatie\Permission\Contracts\Permission` contract. + */ + + 'permission' => App\Models\Permission::class, + + /* + * When using the "HasRoles" trait from this package, we need to know which + * Eloquent model should be used to retrieve your roles. Of course, it + * is often just the "Role" model but you may use whatever you like. + * + * The model you want to use as a Role model needs to implement the + * `Spatie\Permission\Contracts\Role` contract. + */ + + 'role' => App\Models\Role::class, + + ], + + 'table_names' => [ + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your roles. We have chosen a basic + * default value but you may easily change it to any table you like. + */ + + 'roles' => 'roles', + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * table should be used to retrieve your permissions. We have chosen a basic + * default value but you may easily change it to any table you like. + */ + + 'permissions' => 'permissions', + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * table should be used to retrieve your models permissions. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'model_has_permissions' => 'model_has_permissions', + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your models roles. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'model_has_roles' => 'model_has_roles', + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your roles permissions. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'role_has_permissions' => 'role_has_permissions', + ], + + 'column_names' => [ + /* + * Change this if you want to name the related pivots other than defaults + */ + 'role_pivot_key' => null, //default 'role_id', + 'permission_pivot_key' => null, //default 'permission_id', + + /* + * Change this if you want to name the related model primary key other than + * `model_id`. + * + * For example, this would be nice if your primary keys are all UUIDs. In + * that case, name this `model_uuid`. + */ + + 'model_morph_key' => 'model_id', + + /* + * Change this if you want to use the teams feature and your related model's + * foreign key is other than `team_id`. + */ + + 'team_foreign_key' => 'team_id', + ], + + /* + * When set to true, the method for checking permissions will be registered on the gate. + * Set this to false, if you want to implement custom logic for checking permissions. + */ + + 'register_permission_check_method' => true, + + /* + * When set to true the package implements teams using the 'team_foreign_key'. If you want + * the migrations to register the 'team_foreign_key', you must set this to true + * before doing the migration. If you already did the migration then you must make a new + * migration to also add 'team_foreign_key' to 'roles', 'model_has_roles', and + * 'model_has_permissions'(view the latest version of package's migration file) + */ + + 'teams' => false, + + /* + * When set to true, the required permission names are added to the exception + * message. This could be considered an information leak in some contexts, so + * the default setting is false here for optimum safety. + */ + + 'display_permission_in_exception' => false, + + /* + * When set to true, the required role names are added to the exception + * message. This could be considered an information leak in some contexts, so + * the default setting is false here for optimum safety. + */ + + 'display_role_in_exception' => false, + + /* + * By default wildcard permission lookups are disabled. + */ + + 'enable_wildcard_permission' => true, + + 'cache' => [ + + /* + * By default all permissions are cached for 24 hours to speed up performance. + * When permissions or roles are updated the cache is flushed automatically. + */ + + 'expiration_time' => \DateInterval::createFromDateString('24 hours'), + + /* + * The cache key used to store all permissions. + */ + + 'key' => 'spatie.permission.cache', + + /* + * You may optionally indicate a specific cache driver to use for permission and + * role caching using any of the `store` drivers listed in the cache.php config + * file. Using 'default' here means to use the `default` set in cache.php. + */ + + 'store' => 'default', + ], +]; diff --git a/config/permissions_web.php b/config/permissions_web.php new file mode 100644 index 000000000..38033129d --- /dev/null +++ b/config/permissions_web.php @@ -0,0 +1,143 @@ + '*', + + 'View Roles Backend' => 'admin.roles.read', + 'Create Role' => 'admin.roles.create', + 'Edit Role' => 'admin.roles.edit', + 'Delete Role' => 'admin.roles.delete', + + + 'View Tickets Backend' => 'admin.tickets.read', + 'Manage Ticket Backend' => 'admin.tickets.write', + 'Receive new Ticket Notifications' => 'admin.tickets.get_notification', + + 'Create Ticket Category' => 'admin.tickets.category.read', + 'Manage Ticket Category Backend' => 'admin.tickets.category.write', + + 'View Ticket-Blacklist' => 'admin.ticket_blacklist.read', + 'Manage Ticket-Blacklist' => 'admin.ticket_blacklist.write', + + 'View Overview' => 'admin.overview.read', + 'Overview Sync' => 'admin.overview.sync', + + 'View Api Keys' => 'admin.api.read', + 'Manage Api Keys' => 'admin.api.write', + + 'View User List' => 'admin.users.read', + 'Edit anything on User' => 'admin.users.write', + 'Suspend Users' => 'admin.users.suspend', + 'Edit User Credits' => 'admin.users.write.credits', + 'Edit User Name' => 'admin.users.write.username', + 'Edit User Email' => 'admin.users.write.email', + 'Edit User Password' => 'admin.users.write.password', + 'Edit User Role' => 'admin.users.write.role', + 'Edit User Referral' => 'admin.users.write.referral', + 'Edit User Pterodactyl' => 'admin.users.write.pterodactyl', + 'Edit User Serverlimit' => 'admin.users.write.serverlimit', + + "Manage Icons" => "admin.icons.edit", + + 'Notify Users' => 'admin.users.notify', + 'Login As User' => 'admin.users.login_as', + 'Delete User' => 'admin.users.delete', + + 'View Server List' => 'admin.servers.read', + 'Manage all Servers' => 'admin.servers.write', + 'Suspend any Server' => 'admin.servers.suspend', + 'Change any Servers Owner' => 'admin.servers.write.owner', + 'Manage any Servers Identifier' => 'admin.servers.write.identifier', + 'Bypass Server-creation restriction ' => 'admin.servers.bypass_creation_enabled', + 'Delete any Servers' => 'admin.servers.delete', + + 'View Product List' => 'admin.products.read', + 'Create Product' => 'admin.products.create', + 'Edit Product' => 'admin.products.edit', + 'Delete Product' => 'admin.products.delete', + + 'View Store Backend' => 'admin.store.read', + 'Manage Store Backend' => 'admin.store.write', + 'Disable Store' => 'admin.store.disable', + + 'View Vouchers Backend' => 'admin.voucher.read', + 'Manage Voucher Backend' => 'admin.voucher.write', + + 'View Useful Links Backend' => 'admin.useful_links.read', + 'Manage Useful Links Backend' => 'admin.useful_links.write', + + 'View Legal Backend' => 'admin.legal.read', + 'Manage Legal Backend' => 'admin.legal.write', + + 'View Payments Backend' => 'admin.payments.read', + + 'View Partners Backend' => 'admin.partners.read', + 'Manage Partners Backend' => 'admin.partners.write', + + 'View Coupons Backend' => 'admin.coupons.read', + 'Manage Coupons Backend' => 'admin.coupons.write', + + 'View Logs' => 'admin.logs.read', + + /* + * Settings Permissions + */ + 'View Discord Settings' => 'settings.discord.read', + 'Manage Discord Settings' => 'settings.discord.write', + + 'View General Settings' => 'settings.general.read', + 'Manage General Settings' => 'settings.general.write', + + 'View Invoice Settings' => 'settings.invoice.read', + 'Manage Invoice Settings' => 'settings.invoice.write', + + 'View Locale Settings' => 'settings.locale.read', + 'Manage Locale Settings' => 'settings.locale.write', + + 'View Mail Settings' => 'settings.mail.read', + 'Manage Mail Settings' => 'settings.mail.write', + + 'View Pterodactyl Settings' => 'settings.pterodactyl.read', + 'Manage Pterodactyl Settings' => 'settings.pterodactyl.write', + + 'View Referral Settings' => 'settings.referral.read', + 'Manage Referral Settings' => 'settings.referral.write', + + 'View Server Settings' => 'settings.server.read', + 'Manage Server Settings' => 'settings.server.write', + + 'View Ticket Settings' => 'settings.ticket.read', + 'Manage Ticket Settings' => 'settings.ticket.write', + + 'View User Settings' => 'settings.user.read', + 'Manage User Settings' => 'settings.user.write', + + 'View Website Settings' => 'settings.website.read', + 'Manage Website Settings' => 'settings.website.write', + + 'View Paypal Settings' => 'settings.paypal.read', + 'Manage Paypal Settings' => 'settings.paypal.write', + + 'View Mercado Pago Settings' => 'settings.mercadopago.read', + 'Manage Mercado Pago Settings' => 'settings.mercadopago.write', + + 'View Stripe Settings' => 'settings.stripe.read', + 'Manage Stripe Settings' => 'settings.stripe.write', + + 'View Mollie Settings' => 'settings.mollie.read', + 'Manage Mollie Settings' => 'settings.mollie.write', + + /* + * Permissions for users + */ + 'Customer Create Server' => 'user.server.create', + 'Customer Upgrade Server' => 'user.server.upgrade', + 'Customer Shop Buy' => 'user.shop.buy', + 'Customer View Supportticket' => 'user.ticket.read', + 'Customer Write Supportticket' => 'user.ticket.write', + 'Customer View Referral' => 'user.referral', +]; diff --git a/config/services.php b/config/services.php index aedb7007c..4ca9034f5 100644 --- a/config/services.php +++ b/config/services.php @@ -1,5 +1,6 @@ env('AWS_DEFAULT_REGION', 'us-east-1'), ], - 'discord' => [ - 'client_id' => env('DISCORD_CLIENT_ID'), - 'client_secret' => env('DISCORD_CLIENT_SECRET'), - 'redirect' => env('APP_URL', 'http://localhost').'/auth/callback', - - // optional - 'allow_gif_avatars' => (bool) env('DISCORD_AVATAR_GIF', true), - 'avatar_default_extension' => env('DISCORD_EXTENSION_DEFAULT', 'jpg'), // only pick from jpg, png, webp - ], ]; diff --git a/config/settings.php b/config/settings.php new file mode 100644 index 000000000..e9a3a4b10 --- /dev/null +++ b/config/settings.php @@ -0,0 +1,113 @@ + [ + GeneralSettings::class, + DiscordSettings::class, + InvoiceSettings::class, + LocaleSettings::class, + MailSettings::class, + PterodactylSettings::class, + ReferralSettings::class, + ServerSettings::class, + UserSettings::class, + WebsiteSettings::class, + TicketSettings::class, + CouponSettings::class, + ], + + /* + * The path where the settings classes will be created. + */ + 'setting_class_path' => app_path('Settings'), + + /* + * In these directories settings migrations will be stored and ran when migrating. A settings + * migration created via the make:settings-migration command will be stored in the first path or + * a custom defined path when running the command. + */ + 'migrations_paths' => [ + database_path('settings'), + ...ExtensionHelper::getAllExtensionMigrations() + + ], + + /* + * When no repository was set for a settings class the following repository + * will be used for loading and saving settings. + */ + 'default_repository' => 'database', + + /* + * Settings will be stored and loaded from these repositories. + */ + 'repositories' => [ + 'database' => [ + 'type' => Spatie\LaravelSettings\SettingsRepositories\DatabaseSettingsRepository::class, + 'model' => null, + 'table' => null, + 'connection' => null, + ], + 'redis' => [ + 'type' => Spatie\LaravelSettings\SettingsRepositories\RedisSettingsRepository::class, + 'connection' => null, + 'prefix' => null, + ], + ], + + /* + * The contents of settings classes can be cached through your application, + * settings will be stored within a provided Laravel store and can have an + * additional prefix. + */ + 'cache' => [ + 'enabled' => env('SETTINGS_CACHE_ENABLED', true), + 'store' => 'redis', + 'prefix' => 'setting', + 'ttl' => null, + ], + + /* + * These global casts will be automatically used whenever a property within + * your settings class isn't a default PHP type. + */ + 'global_casts' => [ + DateTimeInterface::class => Spatie\LaravelSettings\SettingsCasts\DateTimeInterfaceCast::class, + DateTimeZone::class => Spatie\LaravelSettings\SettingsCasts\DateTimeZoneCast::class, + // Spatie\DataTransferObject\DataTransferObject::class => Spatie\LaravelSettings\SettingsCasts\DtoCast::class, + Spatie\LaravelData\Data::class => Spatie\LaravelSettings\SettingsCasts\DataCast::class, + ], + + /* + * The package will look for settings in these paths and automatically + * register them. + */ + 'auto_discover_settings' => [ + app()->path(), + ], + + /* + * Automatically discovered settings classes can be cached so they don't + * need to be searched each time the application boots up. + */ + 'discovered_settings_cache_path' => storage_path('app/laravel-settings'), +]; diff --git a/config/trustedproxy.php b/config/trustedproxy.php index dc46c31ba..f3b88cd52 100644 --- a/config/trustedproxy.php +++ b/config/trustedproxy.php @@ -26,7 +26,7 @@ * subsequently passed through. */ 'proxies' => in_array(env('TRUSTED_PROXIES', []), ['*', '**']) ? - env('TRUSTED_PROXIES') : explode(',', env('TRUSTED_PROXIES', null)), + env('TRUSTED_PROXIES') : explode(',', env('TRUSTED_PROXIES', '')), /* * Or, to trust all proxies that connect diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index c28f40d8e..b619113e6 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -19,7 +19,7 @@ public function up() $table->id(); $table->string('name'); $table->string('role')->default('member'); - $table->unsignedFloat('credits')->default(250); + $table->float('credits')->default(250)->unsigned(); $table->unsignedInteger('server_limit')->default(1); $table->unsignedInteger('pterodactyl_id')->nullable(); $table->longText('avatar')->nullable(); diff --git a/database/migrations/2021_07_09_190453_create_vouchers_table.php b/database/migrations/2021_07_09_190453_create_vouchers_table.php index 481674b38..5be8937e4 100644 --- a/database/migrations/2021_07_09_190453_create_vouchers_table.php +++ b/database/migrations/2021_07_09_190453_create_vouchers_table.php @@ -17,7 +17,7 @@ public function up() $table->id(); $table->string('code', 36)->unique(); $table->string('memo')->nullable(); - $table->unsignedFloat('credits', 10); + $table->float('credits', 10)->unsigned(); $table->unsignedInteger('uses')->default(1); $table->timestamp('expires_at')->nullable(); $table->timestamps(); diff --git a/database/migrations/2021_07_10_062140_update_credits_to_users_table.php b/database/migrations/2021_07_10_062140_update_credits_to_users_table.php index ef4e069d7..bf106b371 100644 --- a/database/migrations/2021_07_10_062140_update_credits_to_users_table.php +++ b/database/migrations/2021_07_10_062140_update_credits_to_users_table.php @@ -14,7 +14,7 @@ public function up() { Schema::table('users', function (Blueprint $table) { - $table->unsignedFloat('credits', 10)->change(); + $table->float('credits', 10)->change()->unsigned(); }); } @@ -26,7 +26,7 @@ public function up() public function down() { Schema::table('users', function (Blueprint $table) { - $table->unsignedFloat('credits')->change(); + $table->float('credits')->change()->unsigned(); }); } }; diff --git a/database/migrations/2022_01_05_144858_rename_configurations_table.php b/database/migrations/2022_01_05_144858_rename_configurations_table.php index 4785ed01e..1090a0223 100644 --- a/database/migrations/2022_01_05_144858_rename_configurations_table.php +++ b/database/migrations/2022_01_05_144858_rename_configurations_table.php @@ -28,7 +28,6 @@ public function up() DB::table('settings')->where('key', 'REGISTER_IP_CHECK')->update(['key' => 'SETTINGS::SYSTEM:REGISTER_IP_CHECK']); DB::table('settings')->where('key', 'CREDITS_DISPLAY_NAME')->update(['key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME']); DB::table('settings')->where('key', 'ALLOCATION_LIMIT')->update(['key' => 'SETTINGS::SERVER:ALLOCATION_LIMIT']); - DB::table('settings')->where('key', 'SERVER_CREATE_CHARGE_FIRST_HOUR')->update(['key' => 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR']); DB::table('settings')->where('key', 'SALES_TAX')->update(['key' => 'SETTINGS::PAYMENTS:SALES_TAX']); } @@ -52,7 +51,6 @@ public function down() DB::table('configurations')->where('key', 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION')->update(['key' => 'FORCE_EMAIL_VERIFICATION']); DB::table('configurations')->where('key', 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION')->update(['key' => 'FORCE_DISCORD_VERIFICATION']); DB::table('configurations')->where('key', 'SETTINGS::SYSTEM:REGISTER_IP_CHECK')->update(['key' => 'REGISTER_IP_CHECK']); - DB::table('configurations')->where('key', 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR')->update(['key' => 'SERVER_CREATE_CHARGE_FIRST_HOUR']); DB::table('configurations')->where('key', 'SETTINGS::SERVER:ALLOCATION_LIMIT')->update(['key' => 'ALLOCATION_LIMIT']); DB::table('configurations')->where('key', 'SETTINGS::SERVER:CREDITS_DISPLAY_NAME')->update(['key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME']); DB::table('configurations')->where('key', 'SETTINGS::PAYMENTS:SALES_TAX')->update(['key' => 'SALES_TAX']); diff --git a/database/migrations/2022_07_12_051152_decimals-in-price.php b/database/migrations/2022_07_12_051152_decimals-in-price.php index cf1a35b4c..da5c6582d 100644 --- a/database/migrations/2022_07_12_051152_decimals-in-price.php +++ b/database/migrations/2022_07_12_051152_decimals-in-price.php @@ -14,7 +14,7 @@ public function up() { Schema::table('products', function (Blueprint $table) { - $table->decimal('price', ['11', '2'])->change(); + $table->decimal('price', 11, 2)->change(); }); } diff --git a/database/migrations/2023_04_03_231829_update_users_table.php b/database/migrations/2023_04_03_231829_update_users_table.php new file mode 100644 index 000000000..df2497417 --- /dev/null +++ b/database/migrations/2023_04_03_231829_update_users_table.php @@ -0,0 +1,32 @@ +string('pterodactyl_id')->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->integer('pterodactyl_id')->nullable()->change(); + }); + } +}; diff --git a/database/migrations/2023_04_29_232942_create_permission_tables.php b/database/migrations/2023_04_29_232942_create_permission_tables.php new file mode 100644 index 000000000..ef728fec0 --- /dev/null +++ b/database/migrations/2023_04_29_232942_create_permission_tables.php @@ -0,0 +1,142 @@ +bigIncrements('id'); // permission id + $table->string('name'); // For MySQL 8.0 use string('name', 125); + $table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125); + $table->timestamps(); + + $table->unique(['name', 'guard_name']); + }); + + Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) { + $table->bigIncrements('id'); // role id + if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing + $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable(); + $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index'); + } + $table->string('name'); // For MySQL 8.0 use string('name', 125); + $table->string('color')->nullable()->default('#485460'); // For MySQL 8.0 use string('name', 125); + $table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125); + $table->timestamps(); + if ($teams || config('permission.testing')) { + $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']); + } else { + $table->unique(['name', 'guard_name']); + } + }); + + Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) { + $table->unsignedBigInteger(app(PermissionRegistrar::class)->pivotPermission); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); + + $table->foreign(app(PermissionRegistrar::class)->pivotPermission) + ->references('id') // permission id + ->on($tableNames['permissions']) + ->onDelete('cascade'); + if ($teams) { + $table->unsignedBigInteger($columnNames['team_foreign_key']); + $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index'); + + $table->primary([$columnNames['team_foreign_key'], app(PermissionRegistrar::class)->pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + } else { + $table->primary([app(PermissionRegistrar::class)->pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + } + + }); + + Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) { + $table->unsignedBigInteger(app(PermissionRegistrar::class)->pivotRole); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); + + $table->foreign(app(PermissionRegistrar::class)->pivotRole) + ->references('id') // role id + ->on($tableNames['roles']) + ->onDelete('cascade'); + if ($teams) { + $table->unsignedBigInteger($columnNames['team_foreign_key']); + $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index'); + + $table->primary([$columnNames['team_foreign_key'], app(PermissionRegistrar::class)->pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + } else { + $table->primary([app(PermissionRegistrar::class)->pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + } + }); + + Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) { + $table->unsignedBigInteger(app(PermissionRegistrar::class)->pivotPermission); + $table->unsignedBigInteger(app(PermissionRegistrar::class)->pivotRole); + + $table->foreign(app(PermissionRegistrar::class)->pivotPermission) + ->references('id') // permission id + ->on($tableNames['permissions']) + ->onDelete('cascade'); + + $table->foreign(app(PermissionRegistrar::class)->pivotRole) + ->references('id') // role id + ->on($tableNames['roles']) + ->onDelete('cascade'); + + $table->primary([app(PermissionRegistrar::class)->pivotPermission, app(PermissionRegistrar::class)->pivotRole], 'role_has_permissions_permission_id_role_id_primary'); + }); + + app('cache') + ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null) + ->forget(config('permission.cache.key')); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $tableNames = config('permission.table_names'); + + if (empty($tableNames)) { + throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.'); + } + + Schema::drop($tableNames['role_has_permissions']); + Schema::drop($tableNames['model_has_roles']); + Schema::drop($tableNames['model_has_permissions']); + Schema::drop($tableNames['roles']); + Schema::drop($tableNames['permissions']); + } +} diff --git a/database/migrations/2023_05_05_090127_role_power.php b/database/migrations/2023_05_05_090127_role_power.php new file mode 100644 index 000000000..9c8da51d0 --- /dev/null +++ b/database/migrations/2023_05_05_090127_role_power.php @@ -0,0 +1,32 @@ +integer('power')->after("color")->default(50); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('roles', function (Blueprint $table) { + $table->dropColumn('power'); + }); + } +}; diff --git a/database/migrations/2023_05_05_103834_oom_killer.php b/database/migrations/2023_05_05_103834_oom_killer.php new file mode 100644 index 000000000..3fecb34ef --- /dev/null +++ b/database/migrations/2023_05_05_103834_oom_killer.php @@ -0,0 +1,32 @@ +boolean('oom_killer')->after("allocations")->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('products', function (Blueprint $table) { + $table->dropColumn('oom_killer'); + }); + } +}; diff --git a/database/migrations/2023_05_08_092704_add_billing_period_to_products.php b/database/migrations/2023_05_08_092704_add_billing_period_to_products.php new file mode 100644 index 000000000..7936e7fda --- /dev/null +++ b/database/migrations/2023_05_08_092704_add_billing_period_to_products.php @@ -0,0 +1,52 @@ +string('billing_period')->default("hourly"); + $table->decimal('price', 15, 4)->change(); + $table->decimal('minimum_credits', 15, 4)->default(-1)->change(); + }); + + DB::statement('UPDATE products SET billing_period="hourly"'); + + $products = DB::table('products')->get(); + foreach ($products as $product) { + $price = $product->price; + $price = $price / 30 / 24; + DB::table('products')->where('id', $product->id)->update(['price' => $price]); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('products', function (Blueprint $table) { + $table->dropColumn('billing_period'); + $table->decimal('price', 10, 0)->change(); + $table->float('minimum_credits')->change(); + }); + } +} diff --git a/database/migrations/2023_05_08_094402_update_user_credits_datatype.php b/database/migrations/2023_05_08_094402_update_user_credits_datatype.php new file mode 100644 index 000000000..57a350377 --- /dev/null +++ b/database/migrations/2023_05_08_094402_update_user_credits_datatype.php @@ -0,0 +1,32 @@ +decimal('credits', 15, 4)->default(0)->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->decimal('credits', 11, 2)->change(); + }); + } +} diff --git a/database/migrations/2023_05_08_095818_add_last_billed_field_to_servers.php b/database/migrations/2023_05_08_095818_add_last_billed_field_to_servers.php new file mode 100644 index 000000000..9d43ae96d --- /dev/null +++ b/database/migrations/2023_05_08_095818_add_last_billed_field_to_servers.php @@ -0,0 +1,38 @@ +dateTime('last_billed')->default(DB::raw('CURRENT_TIMESTAMP'))->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('servers', function (Blueprint $table) { + $table->dropColumn('last_billed'); + }); + } +} diff --git a/database/migrations/2023_05_08_234527_add_cancelation_to_servers_table.php b/database/migrations/2023_05_08_234527_add_cancelation_to_servers_table.php new file mode 100644 index 000000000..94efae378 --- /dev/null +++ b/database/migrations/2023_05_08_234527_add_cancelation_to_servers_table.php @@ -0,0 +1,40 @@ +renameColumn('cancelled', 'canceled'); + }); + return; + } + + Schema::table('servers', function (Blueprint $table) { + $table->dateTime('canceled')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('servers', function (Blueprint $table) { + $table->dropColumn('canceled'); + }); + } +} diff --git a/database/migrations/2023_05_11_153719_create_coupons_table.php b/database/migrations/2023_05_11_153719_create_coupons_table.php new file mode 100644 index 000000000..db26a65b5 --- /dev/null +++ b/database/migrations/2023_05_11_153719_create_coupons_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('code')->unique(); + $table->enum('type', ['percentage', 'amount']); + $table->decimal('value', 10); + $table->integer('uses')->default(0); + $table->integer('max_uses'); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('coupons'); + } +}; diff --git a/database/migrations/2023_05_14_152604_create_user_coupons_table.php b/database/migrations/2023_05_14_152604_create_user_coupons_table.php new file mode 100644 index 000000000..10f584aec --- /dev/null +++ b/database/migrations/2023_05_14_152604_create_user_coupons_table.php @@ -0,0 +1,32 @@ +foreignId('user_id')->constrained(); + $table->foreignId('coupon_id')->constrained(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('user_coupons'); + } +}; diff --git a/database/migrations/2023_09_15_142409_add_readable_name_to_permissions_table.php b/database/migrations/2023_09_15_142409_add_readable_name_to_permissions_table.php new file mode 100644 index 000000000..473db247e --- /dev/null +++ b/database/migrations/2023_09_15_142409_add_readable_name_to_permissions_table.php @@ -0,0 +1,32 @@ +string('readable_name')->after('name'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('permissions', function (Blueprint $table) { + $table->removeColumn('readable_name'); + }); + } +}; diff --git a/database/migrations/2024_05_22_141233_update_description_servers_table.php b/database/migrations/2024_05_22_141233_update_description_servers_table.php new file mode 100644 index 000000000..e0964c529 --- /dev/null +++ b/database/migrations/2024_05_22_141233_update_description_servers_table.php @@ -0,0 +1,32 @@ +text('description')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('servers', function (Blueprint $table) { + $table->string('description')->nullable()->change(); + }); + } +}; diff --git a/database/migrations/2024_05_22_143551_update_description_locations_table.php b/database/migrations/2024_05_22_143551_update_description_locations_table.php new file mode 100644 index 000000000..e2b70688b --- /dev/null +++ b/database/migrations/2024_05_22_143551_update_description_locations_table.php @@ -0,0 +1,32 @@ +text('description')->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('locations', function (Blueprint $table) { + $table->string('description')->change(); + }); + } +}; diff --git a/database/migrations/2024_07_24_175733_add_required_nullable_and_text_columns.php b/database/migrations/2024_07_24_175733_add_required_nullable_and_text_columns.php new file mode 100644 index 000000000..a28f51083 --- /dev/null +++ b/database/migrations/2024_07_24_175733_add_required_nullable_and_text_columns.php @@ -0,0 +1,32 @@ +text('description')->nullable()->change(); + }); + Schema::table('nodes', function (Blueprint $table) { + $table->text('description')->nullable()->change(); + }); + Schema::table('nests', function (Blueprint $table) { + $table->text('description')->nullable()->change(); + }); + Schema::table('eggs', function (Blueprint $table) { + $table->text('description')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void {} +}; diff --git a/database/migrations/2024_07_25_083712_update_settings_default_and_unique.php b/database/migrations/2024_07_25_083712_update_settings_default_and_unique.php new file mode 100644 index 000000000..ad81ce1ee --- /dev/null +++ b/database/migrations/2024_07_25_083712_update_settings_default_and_unique.php @@ -0,0 +1,32 @@ +boolean('locked')->default(false)->change(); + $table->unique(['group', 'name']); + $table->dropIndex(['group']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('settings', function (Blueprint $table) { + $table->boolean('locked')->default(null)->change(); + $table->dropUnique(['group', 'name']); + $table->index('group'); + }); + } +}; diff --git a/database/seeders/PermissionsSeeder.php b/database/seeders/PermissionsSeeder.php new file mode 100644 index 000000000..5ddef8f4d --- /dev/null +++ b/database/seeders/PermissionsSeeder.php @@ -0,0 +1,77 @@ +forgetCachedPermissions(); + + $this->createPermissions(); + $this->createRoles(); + + + $users = User::all(); + foreach($users as $user){ + $user->assignRole(Role::findByName('user')); + } + + $admins = User::where("role","admin")->get(); + foreach($admins as $admin) { + $admin->syncRoles(Role::findByName('Admin')); + } + + $mods = User::where("role","moderator")->get(); + foreach($mods as $mod) { + $mod->syncRoles(Role::findByName('Support-Team')); + } + + $clients = User::where("role","client")->get(); + foreach($clients as $client) { + $client->syncRoles(Role::findByName('Client')); + } + } + + public function createPermissions() + { + foreach(config('permissions_web') as $permission_name => $permission_value) { + Permission::create(['name' => $permission_value, 'readable_name' => $permission_name]); + } + } + + //TODO run only once + public function createRoles() + { + $userPermissions=[ + 'user.server.create', + 'user.server.upgrade', + 'user.shop.buy', + 'user.ticket.read', + 'user.ticket.write', + 'user.referral', + ]; + /** @var Role $adminRole */ + $adminRole = Role::create(["name"=>"Admin","color"=>"#fa0000", "power"=>100]); + $supportRole = Role::create(["name"=>"Support-Team","color"=>"#00b0b3","power"=>50]); + $clientRole = Role::create(["name"=>"Client","color"=>"#008009","power"=>10]); + $userRole = Role::create(["name"=>"User","color"=>"#0052a3","power"=>10]); + + $adminRole->givePermissionTo(Permission::findByName('*')); + + $userRole->syncPermissions($userPermissions); + $clientRole->syncPermissions($userPermissions); + } +} diff --git a/database/seeders/Seeds/ProductSeeder.php b/database/seeders/Seeds/ProductSeeder.php index 4f5e43754..a6035c009 100644 --- a/database/seeders/Seeds/ProductSeeder.php +++ b/database/seeders/Seeds/ProductSeeder.php @@ -16,29 +16,32 @@ public function run() { Product::create([ 'name' => 'Starter', - 'description' => '64MB Ram, 1GB Disk, 1 Database, 140 credits monthly', + 'description' => '64MB Ram, 1GB Disk, 1 Database, 140 credits hourly', 'price' => 140, 'memory' => 64, 'disk' => 1000, 'databases' => 1, + 'billing_period' => 'hourly' ]); Product::create([ 'name' => 'Standard', - 'description' => '128MB Ram, 2GB Disk, 2 Database, 210 credits monthly', + 'description' => '128MB Ram, 2GB Disk, 2 Database, 210 credits hourly', 'price' => 210, 'memory' => 128, 'disk' => 2000, 'databases' => 2, + 'billing_period' => 'hourly' ]); Product::create([ 'name' => 'Advanced', - 'description' => '256MB Ram, 5GB Disk, 5 Database, 280 credits monthly', + 'description' => '256MB Ram, 5GB Disk, 5 Database, 280 credits hourly', 'price' => 280, 'memory' => 256, 'disk' => 5000, 'databases' => 5, + 'billing_period' => 'hourly' ]); } } diff --git a/database/seeders/Seeds/UsefulLinksSeeder.php b/database/seeders/Seeds/UsefulLinksSeeder.php index 03a8ce9dd..0d5f2b188 100644 --- a/database/seeders/Seeds/UsefulLinksSeeder.php +++ b/database/seeders/Seeds/UsefulLinksSeeder.php @@ -28,12 +28,5 @@ public function run() 'description' => 'View your database online using phpMyAdmin', 'position' => 'dashboard,topbar', ]); - UsefulLink::create([ - 'icon' => 'fab fa-discord', - 'title' => 'Discord', - 'link' => env('DISCORD_INVITE_URL', 'https://discord.gg/4Y6HjD2uyU'), - 'description' => 'Need a helping hand? Want to chat? Got any questions? Join our discord!', - 'position' => 'dashboard', - ]); } } diff --git a/database/settings/2023_02_01_164731_create_general_settings.php b/database/settings/2023_02_01_164731_create_general_settings.php new file mode 100644 index 000000000..e799e4406 --- /dev/null +++ b/database/settings/2023_02_01_164731_create_general_settings.php @@ -0,0 +1,107 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('general.store_enabled', true); + $this->migrator->add('general.sales_tax', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:SALES_TAX', '0') : '0'); + $this->migrator->add('general.credits_display_name', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME', 'Credits') : 'Credits'); + $this->migrator->add('general.recaptcha_site_key', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:SITE_KEY") : env('RECAPTCHA_SITE_KEY', '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI')); + $this->migrator->add('general.recaptcha_secret_key', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:SECRET_KEY") : env('RECAPTCHA_SECRET_KEY', '6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe')); + $this->migrator->add('general.recaptcha_enabled', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:ENABLED", false) : false); + $this->migrator->add('general.phpmyadmin_url', $table_exists ? $this->getOldValue("SETTINGS::MISC:PHPMYADMIN:URL") : env('PHPMYADMIN_URL')); + $this->migrator->add('general.alert_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:ALERT_ENABLED", false) : false); + $this->migrator->add('general.alert_type', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:ALERT_TYPE", 'dark') : 'dark'); + $this->migrator->add('general.alert_message', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:ALERT_MESSAGE") : null); + $this->migrator->add('general.theme', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:THEME", 'default') : 'default'); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME', + 'value' => $this->getNewValue('credits_display_name', 'general'), + 'type' => 'string', + 'description' => 'The name of the credits on the panel.' + ], + [ + 'key' => 'SETTINGS::PAYMENTS:SALES_TAX', + 'value' => $this->getNewValue('sales_tax', 'general'), + 'type' => 'string', + 'description' => 'Sales tax in %.' + ], + [ + 'key' => 'SETTINGS::SYSTEM:ALERT_ENABLED', + 'value' => $this->getNewValue('alert_enabled', 'general'), + 'type' => 'boolean', + 'description' => 'Enable the alert at the top of the panel.' + ], + [ + 'key' => 'SETTINGS::SYSTEM:ALERT_TYPE', + 'value' => $this->getNewValue('alert_type', 'general'), + 'type' => 'string', + 'description' => 'The type of alert to display.' + ], + [ + 'key' => 'SETTINGS::SYSTEM:ALERT_MESSAGE', + 'value' => $this->getNewValue('alert_message', 'general'), + 'type' => 'text', + 'description' => 'The message to display in the alert.' + ], + [ + 'key' => 'SETTINGS::SYSTEM:THEME', + 'value' => $this->getNewValue('theme', 'general'), + 'type' => 'string', + 'description' => 'The theme to use for the panel.' + + ], + [ + 'key' => 'SETTINGS::RECAPTCHA:SITE_KEY', + 'value' => $this->getNewValue('recaptcha_site_key', 'general'), + 'type' => 'string', + 'description' => 'The site key for reCAPTCHA.' + ], + [ + 'key' => 'SETTINGS::RECAPTCHA:SECRET_KEY', + 'value' => $this->getNewValue('recaptcha_secret_key', 'general'), + 'type' => 'string', + 'description' => 'The secret key for reCAPTCHA.' + ], + [ + 'key' => 'SETTINGS::RECAPTCHA:ENABLED', + 'value' => $this->getNewValue('recaptcha_enabled', 'general'), + 'type' => 'boolean', + 'description' => 'Enable reCAPTCHA on the panel.' + ], + [ + 'key' => 'SETTINGS::MISC:PHPMYADMIN:URL', + 'value' => $this->getNewValue('phpmyadmin_url', 'general'), + 'type' => 'string', + 'description' => 'The URL to your phpMyAdmin installation.' + ], + ]); + try { + $this->migrator->delete('general.store_enabled'); + $this->migrator->delete('general.sales_tax'); + $this->migrator->delete('general.credits_display_name'); + $this->migrator->delete('general.recaptcha_site_key'); + $this->migrator->delete('general.recaptcha_secret_key'); + $this->migrator->delete('general.recaptcha_enabled'); + $this->migrator->delete('general.phpmyadmin_url'); + $this->migrator->delete('general.alert_enabled'); + $this->migrator->delete('general.alert_type'); + $this->migrator->delete('general.alert_message'); + $this->migrator->delete('general.theme'); + } catch (Exception $e) { + // Do nothing + } + } +} diff --git a/database/settings/2023_02_01_181334_create_pterodactyl_settings.php b/database/settings/2023_02_01_181334_create_pterodactyl_settings.php new file mode 100644 index 000000000..f2ed645a5 --- /dev/null +++ b/database/settings/2023_02_01_181334_create_pterodactyl_settings.php @@ -0,0 +1,58 @@ +exists(); + + $this->migrator->add('pterodactyl.admin_token', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:TOKEN', '') : env('PTERODACTYL_TOKEN', '')); + $this->migrator->add('pterodactyl.user_token', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN', '') : ''); + $this->migrator->add('pterodactyl.panel_url', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:URL', '') : env('PTERODACTYL_URL', '')); + $this->migrator->add('pterodactyl.per_page_limit', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT', 200) : 200); + } + + public function down(): void + { + + + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::SYSTEM:PTERODACTYL:TOKEN', + 'value' => $this->getNewValue('admin_token', 'pterodactyl'), + 'type' => 'string', + 'description' => 'The admin token for the Pterodactyl panel.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN', + 'value' => $this->getNewValue('user_token', 'pterodactyl'), + 'type' => 'string', + 'description' => 'The user token for the Pterodactyl panel.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:PTERODACTYL:URL', + 'value' => $this->getNewValue('panel_url', 'pterodactyl'), + 'type' => 'string', + 'description' => 'The URL for the Pterodactyl panel.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT', + 'value' => $this->getNewValue('per_page_limit', 'pterodactyl'), + 'type' => 'integer', + 'description' => 'The number of servers to show per page.', + ], + ]); + + try { + $this->migrator->delete('pterodactyl.admin_token'); + $this->migrator->delete('pterodactyl.user_token'); + $this->migrator->delete('pterodactyl.panel_url'); + $this->migrator->delete('pterodactyl.per_page_limit'); + } catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + } + } +} diff --git a/database/settings/2023_02_01_181453_create_mail_settings.php b/database/settings/2023_02_01_181453_create_mail_settings.php new file mode 100644 index 000000000..5dd15cab4 --- /dev/null +++ b/database/settings/2023_02_01_181453_create_mail_settings.php @@ -0,0 +1,90 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('mail.mail_host', $table_exists ? $this->getOldValue('SETTINGS::MAIL:HOST') : env('MAIL_HOST', 'localhost')); + $this->migrator->add('mail.mail_port', $table_exists ? $this->getOldValue('SETTINGS::MAIL:PORT') : env('MAIL_PORT', 25)); + $this->migrator->add('mail.mail_username', $table_exists ? $this->getOldValue('SETTINGS::MAIL:USERNAME') : env('MAIL_USERNAME', '')); + $this->migrator->add('mail.mail_password', $table_exists ? $this->getOldValue('SETTINGS::MAIL:PASSWORD') : env('MAIL_PASSWORD', '')); + $this->migrator->add('mail.mail_encryption', $table_exists ? $this->getOldValue('SETTINGS::MAIL:ENCRYPTION') : env('MAIL_ENCRYPTION', 'tls')); + $this->migrator->add('mail.mail_from_address', $table_exists ? $this->getOldValue('SETTINGS::MAIL:FROM_ADDRESS') : env('MAIL_FROM_ADDRESS', 'example@example.com')); + $this->migrator->add('mail.mail_from_name', $table_exists ? $this->getOldValue('SETTINGS::MAIL:FROM_NAME') : env('APP_NAME', 'CtrlPanel.gg')); + $this->migrator->add('mail.mail_mailer', $table_exists ? $this->getOldValue('SETTINGS::MAIL:MAILER') : env('MAIL_MAILER', 'smtp')); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::MAIL:HOST', + 'value' => $this->getNewValue('mail_host', 'mail'), + 'type' => 'string', + 'description' => 'The host of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:PORT', + 'value' => $this->getNewValue('mail_port', 'mail'), + 'type' => 'integer', + 'description' => 'The port of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:USERNAME', + 'value' => $this->getNewValue('mail_username', 'mail'), + 'type' => 'string', + 'description' => 'The username of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:PASSWORD', + 'value' => $this->getNewValue('mail_password', 'mail'), + 'type' => 'string', + 'description' => 'The password of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:ENCRYPTION', + 'value' => $this->getNewValue('mail_encryption', 'mail'), + 'type' => 'string', + 'description' => 'The encryption of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:FROM_ADDRESS', + 'value' => $this->getNewValue('mail_from_address', 'mail'), + 'type' => 'string', + 'description' => 'The from address of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:FROM_NAME', + 'value' => $this->getNewValue('mail_from_name', 'mail'), + 'type' => 'string', + 'description' => 'The from name of the mail server.', + ], + [ + 'key' => 'SETTINGS::MAIL:MAILER', + 'value' => $this->getNewValue('mail_mailer', 'mail'), + 'type' => 'string', + 'description' => 'The mailer of the mail server.', + ], + + ]); + + try { + $this->migrator->delete('mail.mail_host'); + $this->migrator->delete('mail.mail_port'); + $this->migrator->delete('mail.mail_username'); + $this->migrator->delete('mail.mail_password'); + $this->migrator->delete('mail.mail_encryption'); + $this->migrator->delete('mail.mail_from_address'); + $this->migrator->delete('mail.mail_from_name'); + $this->migrator->delete('mail.mail_mailer'); + } catch (Exception $e) { + // + } + } +} diff --git a/database/settings/2023_02_01_181925_create_user_settings.php b/database/settings/2023_02_01_181925_create_user_settings.php new file mode 100644 index 000000000..683c998b0 --- /dev/null +++ b/database/settings/2023_02_01_181925_create_user_settings.php @@ -0,0 +1,124 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('user.credits_reward_after_verify_discord', $table_exists ? $this->getOldValue('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD', 250) : 250); + $this->migrator->add('user.credits_reward_after_verify_email', $table_exists ? $this->getOldValue('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL', 250) : 250); + $this->migrator->add('user.force_discord_verification', $table_exists ? $this->getOldValue('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', false) : false); + $this->migrator->add('user.force_email_verification', $table_exists ? $this->getOldValue('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', false) : false); + $this->migrator->add('user.initial_credits', $table_exists ? $this->getOldValue('SETTINGS::USER:INITIAL_CREDITS', 250) : 250); + $this->migrator->add('user.initial_server_limit', $table_exists ? $this->getOldValue('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1) : 1); + $this->migrator->add('user.min_credits_to_make_server', $table_exists ? $this->getOldValue('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50) : 50); + $this->migrator->add('user.server_limit_after_irl_purchase', $table_exists ? $this->getOldValue('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE', 10) : 10); + $this->migrator->add('user.server_limit_after_verify_discord', $table_exists ? $this->getOldValue('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD', 2) : 2); + $this->migrator->add('user.server_limit_after_verify_email', $table_exists ? $this->getOldValue('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL', 2) : 2); + $this->migrator->add('user.register_ip_check', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:REGISTER_IP_CHECK", true) : true); + $this->migrator->add('user.creation_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:CREATION_OF_NEW_USERS", true) : true); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD', + 'value' => $this->getNewValue('credits_reward_after_verify_discord', 'user'), + 'type' => 'integer', + 'description' => 'The amount of credits that the user will receive after verifying their Discord account.', + ], + [ + 'key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL', + 'value' => $this->getNewValue('credits_reward_after_verify_email', 'user'), + 'type' => 'integer', + 'description' => 'The amount of credits that the user will receive after verifying their email.', + + ], + [ + 'key' => 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION', + 'value' => $this->getNewValue('force_discord_verification', 'user'), + 'type' => 'boolean', + 'description' => 'If the user must verify their Discord account to use the panel.', + ], + [ + 'key' => 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION', + 'value' => $this->getNewValue('force_email_verification', 'user'), + 'type' => 'boolean', + 'description' => 'If the user must verify their email to use the panel.', + + ], + [ + 'key' => 'SETTINGS::USER:INITIAL_CREDITS', + 'value' => $this->getNewValue('initial_credits', 'user'), + 'type' => 'integer', + 'description' => 'The amount of credits that the user will receive when they register.', + ], + [ + 'key' => 'SETTINGS::USER:INITIAL_SERVER_LIMIT', + 'value' => $this->getNewValue('initial_server_limit', 'user'), + 'type' => 'integer', + 'description' => 'The amount of servers that the user will be able to create when they register.', + ], + [ + 'key' => 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', + 'value' => $this->getNewValue('min_credits_to_make_server', 'user'), + 'type' => 'integer', + 'description' => 'The minimum amount of credits that the user must have to create a server.', + ], + [ + 'key' => 'SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE', + 'value' => $this->getNewValue('server_limit_after_irl_purchase', 'user'), + 'type' => 'integer', + 'description' => 'The amount of servers that the user will be able to create after making a real purchase.', + ], + [ + 'key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD', + 'value' => $this->getNewValue('server_limit_after_verify_discord', 'user'), + 'type' => 'integer', + 'description' => 'The amount of servers that the user will be able to create after verifying their Discord account.', + + ], + [ + 'key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL', + 'value' => $this->getNewValue('server_limit_after_verify_email', 'user'), + 'type' => 'integer', + 'description' => 'The amount of servers that the user will be able to create after verifying their email.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:REGISTER_IP_CHECK', + 'value' => $this->getNewValue('register_ip_check', 'user'), + 'type' => 'boolean', + 'description' => 'If the user must verify their IP address to register.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:CREATION_OF_NEW_USERS', + 'value' => $this->getNewValue('creation_enabled', 'user'), + 'type' => 'boolean', + 'description' => 'If the user can register.', + ], + ]); + + try { + $this->migrator->delete('user.credits_reward_after_verify_discord'); + $this->migrator->delete('user.credits_reward_after_verify_email'); + $this->migrator->delete('user.force_discord_verification'); + $this->migrator->delete('user.force_email_verification'); + $this->migrator->delete('user.initial_credits'); + $this->migrator->delete('user.initial_server_limit'); + $this->migrator->delete('user.min_credits_to_make_server'); + $this->migrator->delete('user.server_limit_after_irl_purchase'); + $this->migrator->delete('user.server_limit_after_verify_discord'); + $this->migrator->delete('user.server_limit_after_verify_email'); + $this->migrator->delete('user.register_ip_check'); + $this->migrator->delete('user.creation_enabled'); + } catch (Exception $e) { + // Do nothing + } + } +} diff --git a/database/settings/2023_02_01_181950_create_server_settings.php b/database/settings/2023_02_01_181950_create_server_settings.php new file mode 100644 index 000000000..bd63d8e71 --- /dev/null +++ b/database/settings/2023_02_01_181950_create_server_settings.php @@ -0,0 +1,49 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('server.allocation_limit', $table_exists ? $this->getOldValue('SETTINGS::SERVER:ALLOCATION_LIMIT', 200) : 200); + $this->migrator->add('server.creation_enabled', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', true) : true); + $this->migrator->add('server.enable_upgrade', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:ENABLE_UPGRADE', false) : false); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::SERVER:ALLOCATION_LIMIT', + 'value' => $this->getNewValue('allocation_limit', 'server'), + 'type' => 'integer', + 'description' => 'The number of servers to show per page.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', + 'value' => $this->getNewValue('creation_enabled', 'server'), + 'type' => 'boolean', + 'description' => 'Whether or not users can create new servers.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:ENABLE_UPGRADE', + 'value' => $this->getNewValue('enable_upgrade', 'server'), + 'type' => 'boolean', + 'description' => 'Whether or not users can upgrade their servers.', + ], + ]); + + try { + $this->migrator->delete('server.allocation_limit'); + $this->migrator->delete('server.creation_enabled'); + $this->migrator->delete('server.enable_upgrade'); + } catch (Exception $e) { + // Do nothing + } + } +} diff --git a/database/settings/2023_02_01_182021_create_invoice_settings.php b/database/settings/2023_02_01_182021_create_invoice_settings.php new file mode 100644 index 000000000..d3ac8f637 --- /dev/null +++ b/database/settings/2023_02_01_182021_create_invoice_settings.php @@ -0,0 +1,89 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('invoice.company_address', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_ADDRESS') : null); + $this->migrator->add('invoice.company_mail', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_MAIL') : null); + $this->migrator->add('invoice.company_name', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_NAME') : null); + $this->migrator->add('invoice.company_phone', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_PHONE') : null); + $this->migrator->add('invoice.company_vat', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_VAT') : null); + $this->migrator->add('invoice.company_website', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_WEBSITE') : null); + $this->migrator->add('invoice.enabled', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:ENABLED', false) : false); + $this->migrator->add('invoice.prefix', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:PREFIX') : null); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::INVOICE:COMPANY_ADDRESS', + 'value' => $this->getNewValue('company_address', 'invoice'), + 'type' => 'string', + 'description' => 'The address of the company.', + ], + [ + 'key' => 'SETTINGS::INVOICE:COMPANY_MAIL', + 'value' => $this->getNewValue('company_mail', 'invoice'), + 'type' => 'string', + 'description' => 'The email address of the company.', + ], + [ + 'key' => 'SETTINGS::INVOICE:COMPANY_NAME', + 'value' => $this->getNewValue('company_name', 'invoice'), + 'type' => 'string', + 'description' => 'The name of the company.', + ], + [ + 'key' => 'SETTINGS::INVOICE:COMPANY_PHONE', + 'value' => $this->getNewValue('company_phone', 'invoice'), + 'type' => 'string', + 'description' => 'The phone number of the company.', + ], + [ + 'key' => 'SETTINGS::INVOICE:COMPANY_VAT', + 'value' => $this->getNewValue('company_vat', 'invoice'), + 'type' => 'string', + 'description' => 'The VAT number of the company.', + ], + [ + 'key' => 'SETTINGS::INVOICE:COMPANY_WEBSITE', + 'value' => $this->getNewValue('company_website', 'invoice'), + 'type' => 'string', + 'description' => 'The website of the company.', + ], + [ + 'key' => 'SETTINGS::INVOICE:ENABLED', + 'value' => $this->getNewValue('enabled', 'invoice'), + 'type' => 'boolean', + 'description' => 'Enable or disable the invoice system.', + ], + [ + 'key' => 'SETTINGS::INVOICE:PREFIX', + 'value' => $this->getNewValue('prefix', 'invoice'), + 'type' => 'string', + 'description' => 'The prefix of the invoice.', + ], + ]); + + try { + $this->migrator->delete('invoice.company_address'); + $this->migrator->delete('invoice.company_mail'); + $this->migrator->delete('invoice.company_name'); + $this->migrator->delete('invoice.company_phone'); + $this->migrator->delete('invoice.company_vat'); + $this->migrator->delete('invoice.company_website'); + $this->migrator->delete('invoice.enabled'); + $this->migrator->delete('invoice.prefix'); + } catch (Exception $e) { + // Do nothing + } + } +} diff --git a/database/settings/2023_02_01_182043_create_discord_settings.php b/database/settings/2023_02_01_182043_create_discord_settings.php new file mode 100644 index 000000000..c8216c495 --- /dev/null +++ b/database/settings/2023_02_01_182043_create_discord_settings.php @@ -0,0 +1,74 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('discord.bot_token', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:BOT_TOKEN') : null); + $this->migrator->add('discord.client_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:CLIENT_ID') : null); + $this->migrator->add('discord.client_secret', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:CLIENT_SECRET') : null); + $this->migrator->add('discord.guild_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:GUILD_ID') : null); + $this->migrator->add('discord.invite_url', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:INVITE_URL') : null); + $this->migrator->add('discord.role_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:ROLE_ID') : null); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::DISCORD:BOT_TOKEN', + 'value' => $this->getNewValue('bot_token', 'discord'), + 'type' => 'string', + 'description' => 'The bot token for the Discord bot.', + ], + [ + 'key' => 'SETTINGS::DISCORD:CLIENT_ID', + 'value' => $this->getNewValue('client_id', 'discord'), + 'type' => 'string', + 'description' => 'The client ID for the Discord bot.', + + ], + [ + 'key' => 'SETTINGS::DISCORD:CLIENT_SECRET', + 'value' => $this->getNewValue('client_secret', 'discord'), + 'type' => 'string', + 'description' => 'The client secret for the Discord bot.', + ], + [ + 'key' => 'SETTINGS::DISCORD:GUILD_ID', + 'value' => $this->getNewValue('guild_id', 'discord'), + 'type' => 'string', + 'description' => 'The guild ID for the Discord bot.', + ], + [ + 'key' => 'SETTINGS::DISCORD:INVITE_URL', + 'value' => $this->getNewValue('invite_url', 'discord'), + 'type' => 'string', + 'description' => 'The invite URL for the Discord bot.', + ], + [ + 'key' => 'SETTINGS::DISCORD:ROLE_ID', + 'value' => $this->getNewValue('role_id', 'discord'), + 'type' => 'string', + 'description' => 'The role ID for the Discord bot.', + ] + ]); + + try { + $this->migrator->delete('discord.bot_token'); + $this->migrator->delete('discord.client_id'); + $this->migrator->delete('discord.client_secret'); + $this->migrator->delete('discord.guild_id'); + $this->migrator->delete('discord.invite_url'); + $this->migrator->delete('discord.role_id'); + } catch (Exception $e) { + // Do nothing. + } + } +} diff --git a/database/settings/2023_02_01_182108_create_locale_settings.php b/database/settings/2023_02_01_182108_create_locale_settings.php new file mode 100644 index 000000000..86f3d6e42 --- /dev/null +++ b/database/settings/2023_02_01_182108_create_locale_settings.php @@ -0,0 +1,65 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('locale.available', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:AVAILABLE') : ''); + $this->migrator->add('locale.clients_can_change', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:CLIENTS_CAN_CHANGE', true) : true); + $this->migrator->add('locale.datatables', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:DATATABLES') : 'en-gb'); + $this->migrator->add('locale.default', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:DEFAULT', 'en') : 'en'); + $this->migrator->add('locale.dynamic', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:DYNAMIC', false) : false); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::LOCALE:AVAILABLE', + 'value' => $this->getNewValue('available', 'locale'), + 'type' => 'string', + 'description' => 'The available locales.', + ], + [ + 'key' => 'SETTINGS::LOCALE:CLIENTS_CAN_CHANGE', + 'value' => $this->getNewValue('clients_can_change', 'locale'), + 'type' => 'boolean', + 'description' => 'If clients can change their locale.', + ], + [ + 'key' => 'SETTINGS::LOCALE:DATATABLES', + 'value' => $this->getNewValue('datatables', 'locale'), + 'type' => 'string', + 'description' => 'The locale for datatables.', + ], + [ + 'key' => 'SETTINGS::LOCALE:DEFAULT', + 'value' => $this->getNewValue('default', 'locale'), + 'type' => 'string', + 'description' => 'The default locale.', + ], + [ + 'key' => 'SETTINGS::LOCALE:DYNAMIC', + 'value' => $this->getNewValue('dynamic', 'locale'), + 'type' => 'boolean', + 'description' => 'If the locale should be dynamic.', + ], + ]); + + try { + $this->migrator->delete('locale.available'); + $this->migrator->delete('locale.clients_can_change'); + $this->migrator->delete('locale.datatables'); + $this->migrator->delete('locale.default'); + $this->migrator->delete('locale.dynamic'); + } catch (Exception $e) { + // Do nothing + } + } +} diff --git a/database/settings/2023_02_01_182135_create_referral_settings.php b/database/settings/2023_02_01_182135_create_referral_settings.php new file mode 100644 index 000000000..ed7ff3fd4 --- /dev/null +++ b/database/settings/2023_02_01_182135_create_referral_settings.php @@ -0,0 +1,72 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('referral.always_give_commission', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION', false) : false); + $this->migrator->add('referral.enabled', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::ENABLED', false) : false); + $this->migrator->add('referral.reward', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::REWARD') : 100); + $this->migrator->add('referral.mode', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL:MODE', 'sign-up') : 'sign-up'); + $this->migrator->add('referral.percentage', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL:PERCENTAGE', 100) : 100); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::REFERRAL::ALLOWED', + 'value' => $this->getNewValue('allowed', 'referral'), + 'type' => 'string', + 'description' => 'The allowed referral types.', + ], + [ + 'key' => 'SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION', + 'value' => $this->getNewValue('always_give_commission', 'referral'), + 'type' => 'boolean', + 'description' => 'Whether to always give commission to the referrer.', + ], + [ + 'key' => 'SETTINGS::REFERRAL::ENABLED', + 'value' => $this->getNewValue('enabled', 'referral'), + 'type' => 'boolean', + 'description' => 'Whether to enable the referral system.', + ], + [ + 'key' => 'SETTINGS::REFERRAL::REWARD', + 'value' => $this->getNewValue('reward', 'referral'), + 'type' => 'integer', + 'description' => 'The reward for the referral.', + ], + [ + 'key' => 'SETTINGS::REFERRAL:MODE', + 'value' => $this->getNewValue('mode', 'referral'), + 'type' => 'string', + 'description' => 'The referral mode.', + ], + [ + 'key' => 'SETTINGS::REFERRAL:PERCENTAGE', + 'value' => $this->getNewValue('percentage', 'referral'), + 'type' => 'integer', + 'description' => 'The referral percentage.', + ], + ]); + + try { + $this->migrator->delete('referral.allowed'); + $this->migrator->delete('referral.always_give_commission'); + $this->migrator->delete('referral.enabled'); + $this->migrator->delete('referral.reward'); + $this->migrator->delete('referral.mode'); + $this->migrator->delete('referral.percentage'); + } catch (Exception $e) { + // + } + } +} diff --git a/database/settings/2023_02_01_182158_create_website_settings.php b/database/settings/2023_02_01_182158_create_website_settings.php new file mode 100644 index 000000000..eb8f3295d --- /dev/null +++ b/database/settings/2023_02_01_182158_create_website_settings.php @@ -0,0 +1,104 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('website.motd_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:MOTD_ENABLED", true) : true); + $this->migrator->add( + 'website.motd_message', + $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:MOTD_MESSAGE") : + "

 width=CtrlPanel.gg

+

Thank you for using our Software

+

If you have any questions, make sure to join our Discord

+

(you can change this message in the Settings )

" + ); + $this->migrator->add('website.show_imprint', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SHOW_IMPRINT", false) : false); + $this->migrator->add('website.show_privacy', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SHOW_PRIVACY", false) : false); + $this->migrator->add('website.show_tos', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SHOW_TOS", false) : false); + $this->migrator->add('website.useful_links_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:USEFULLINKS_ENABLED", true) : true); + $this->migrator->add('website.seo_title', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SEO_TITLE") : 'CtrlPanel.gg'); + $this->migrator->add('website.seo_description', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SEO_DESCRIPTION") : 'Billing software for Pterodactyl Panel.'); + $this->migrator->add('website.enable_login_logo', true); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::SYSTEM:MOTD_ENABLED', + 'value' => $this->getNewValue('motd_enabled', 'website'), + 'type' => 'boolean', + 'description' => 'Enable or disable the MOTD.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:MOTD_MESSAGE', + 'value' => $this->getNewValue('motd_message', 'website'), + 'type' => 'text', + 'description' => 'The message that will be displayed in the MOTD.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:SHOW_IMPRINT', + 'value' => $this->getNewValue('show_imprint', 'website'), + 'type' => 'boolean', + 'description' => 'Enable or disable the imprint.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:SHOW_PRIVACY', + 'value' => $this->getNewValue('show_privacy', 'website'), + 'type' => 'boolean', + 'description' => 'Enable or disable the privacy policy.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:SHOW_TOS', + 'value' => $this->getNewValue('show_tos', 'website'), + 'type' => 'boolean', + 'description' => 'Enable or disable the terms of service.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:USEFULLINKS_ENABLED', + 'value' => $this->getNewValue('useful_links_enabled', 'website'), + 'type' => 'boolean', + 'description' => 'Enable or disable the useful links.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:SEO_TITLE', + 'value' => $this->getNewValue('seo_title', 'website'), + 'type' => 'string', + 'description' => 'The title of the website.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:SEO_DESCRIPTION', + 'value' => $this->getNewValue('seo_description', 'website'), + 'type' => 'string', + 'description' => 'The description of the website.', + ], + [ + 'key' => 'SETTINGS::SYSTEM:ENABLE_LOGIN_LOGO', + 'value' => $this->getNewValue('enable_login_logo', 'website'), + 'type' => 'boolean', + 'description' => 'Enable or disable the login logo.', + ] + ]); + + try { + $this->migrator->delete('website.motd_enabled'); + $this->migrator->delete('website.motd_message'); + $this->migrator->delete('website.show_imprint'); + $this->migrator->delete('website.show_privacy'); + $this->migrator->delete('website.show_tos'); + $this->migrator->delete('website.useful_links_enabled'); + $this->migrator->delete('website.seo_title'); + $this->migrator->delete('website.seo_description'); + $this->migrator->delete('website.enable_login_logo'); + } catch (Exception $e) { + // Do nothing + } + } +} diff --git a/database/settings/2023_02_04_181156_create_ticket_settings.php b/database/settings/2023_02_04_181156_create_ticket_settings.php new file mode 100644 index 000000000..f893d2270 --- /dev/null +++ b/database/settings/2023_02_04_181156_create_ticket_settings.php @@ -0,0 +1,41 @@ +exists(); + + // Get the user-set configuration values from the old table. + $this->migrator->add('ticket.enabled', 'true'); + $this->migrator->add('ticket.notify', 'all'); + } + + public function down(): void + { + DB::table('settings_old')->insert([ + [ + 'key' => 'SETTINGS::TICKET:NOTIFY', + 'value' => $this->getNewValue('notify', 'ticket'), + 'type' => 'string', + 'description' => 'The notification type for tickets.', + ], + [ + 'key' => 'SETTINGS::TICKET:ENABLED', + 'value' => $this->getNewValue('enabled', 'ticket'), + 'type' => 'boolean', + 'description' => 'Enable or disable the ticket system.', + ] + ]); + + try { + $this->migrator->delete('ticket.enabled'); + $this->migrator->delete('ticket.notify'); + } catch (Exception $e) { + // Do nothing. + } + } +} diff --git a/database/settings/2023_05_07_195343_delete_notify_add_ticket_information.php b/database/settings/2023_05_07_195343_delete_notify_add_ticket_information.php new file mode 100644 index 000000000..68ec45556 --- /dev/null +++ b/database/settings/2023_05_07_195343_delete_notify_add_ticket_information.php @@ -0,0 +1,18 @@ +migrator->delete('ticket.notify'); + $this->migrator->add('ticket.information', "Can't start your server? Need an additional port? Do you have any other questions? Let us know by opening a ticket."); + } + + public function down(): void + { + $this->migrator->add('ticket.notify', 'all'); + $this->migrator->delete('ticket.information'); + } +}; diff --git a/database/settings/2023_05_12_170041_create_coupon_settings.php b/database/settings/2023_05_12_170041_create_coupon_settings.php new file mode 100644 index 000000000..8e912bef3 --- /dev/null +++ b/database/settings/2023_05_12_170041_create_coupon_settings.php @@ -0,0 +1,22 @@ +migrator->add('coupon.enabled', true); + $this->migrator->add('coupon.max_uses_per_user', 1); + $this->migrator->add('coupon.delete_coupon_on_expires', false); + $this->migrator->add('coupon.delete_coupon_on_uses_reached', false); + } + + public function down(): void + { + $this->migrator->delete('coupon.enabled'); + $this->migrator->delete('coupon.max_uses_per_user'); + $this->migrator->delete('coupon.delete_coupon_on_expires'); + $this->migrator->delete('coupon.delete_coupon_on_uses_reached'); + } +}; diff --git a/database/settings/2024_05_22_152306_add_location_settings_table.php b/database/settings/2024_05_22_152306_add_location_settings_table.php new file mode 100644 index 000000000..aaa01e040 --- /dev/null +++ b/database/settings/2024_05_22_152306_add_location_settings_table.php @@ -0,0 +1,16 @@ +migrator->add('server.location_description_enabled',false); + } + + public function down(): void + { + $this->migrator->delete('server.location_description_enabled'); + } +}; diff --git a/database/settings/2024_06_25_133205_add_discord_settings.php b/database/settings/2024_06_25_133205_add_discord_settings.php new file mode 100644 index 000000000..1ed0ae241 --- /dev/null +++ b/database/settings/2024_06_25_133205_add_discord_settings.php @@ -0,0 +1,18 @@ +migrator->add('discord.role_on_purchase', false); + $this->migrator->add('discord.role_id_on_purchase', ""); + } + + public function down(): void + { + $this->migrator->delete('discord.role_on_purchase'); + $this->migrator->delete('discord.role_id_on_purchase'); + } +} diff --git a/BUILDING.md b/docker/README.md similarity index 84% rename from BUILDING.md rename to docker/README.md index 1581bd17a..d76483b7c 100644 --- a/BUILDING.md +++ b/docker/README.md @@ -3,9 +3,9 @@ cd into the project directory and run the following command: `sh bin/startdocker.sh` This should start building the images and start the containers. -After that you need to go into the controlpanel_php container and run some commands: +After that you need to go into the ctrlpanel_php container and run some commands: -Type `docker exec -it controlpanel_php ash` to go into the container and run the following commands: +Type `docker exec -it ctrlpanel_php ash` to go into the container and run the following commands: ```shell composer install @@ -17,7 +17,7 @@ php artisan migrate --seed --force ## Setting up testing environment -Create the .env.testing file to your needs. Then once done you need to go into your phpmyadmin to create a new database named __controlpanel_test__. +Create the .env.testing file to your needs. Then once done you need to go into your phpmyadmin to create a new database named __ctrlpanel_test__. Visit http://127.0.0.1:8080/ and create your database. Now you're ready to run the following commands which switches to the testing config, migrates the test database and seeds it. diff --git a/docker/development/.gitignore b/docker/development/.gitignore new file mode 100755 index 000000000..aaec72ce4 --- /dev/null +++ b/docker/development/.gitignore @@ -0,0 +1,3 @@ +!.gitignore +mysql +nginx_config diff --git a/docker/development/README.md b/docker/development/README.md new file mode 100644 index 000000000..46f3f9c95 --- /dev/null +++ b/docker/development/README.md @@ -0,0 +1,23 @@ +# 🐳 Docker Development Environment + +This development environment utilizes standalone Docker with necessary tools pre-configured. + +## Included Services +- Redis +- MySQL +- Tools like phpMyAdmin + +## Not Included Services (for the moment) +- Pterodactyl +- Wings + +Feel free to modify the Docker Compose file to remove any services you already have. + +## Setting Up the Testing Environment + +1. **Manual Setup:** As mentioned in the standalone Docker guide, you will need to manually set up some components. +2. **Custom Configuration:** Modify the CtrlPanel Docker Compose configuration to use your current project as a base. If you point it to an empty folder, it will clone the repository, and you won't see your changes immediately. + +For detailed setup instructions, refer to the standalone Docker documentation. + +⚠ Caution: These instructions have not been finished. Therefore, there may be inaccuracies, instability, or non-functional aspects. Proceed with care. diff --git a/docker/development/compose.yaml b/docker/development/compose.yaml new file mode 100644 index 000000000..1e8571a05 --- /dev/null +++ b/docker/development/compose.yaml @@ -0,0 +1,60 @@ +services: + # TODO: add wings and pterodactyl + ctrlpanel_development: + build: + context: ../../ + dockerfile: ./docker/standalone/Dockerfile + container_name: ctrlpanel_development + restart: unless-stopped + ports: + - "80:80" + - "443:443" + volumes: + - '../..:/var/www/html:rw' + - './nginx_config:/etc/nginx/conf.d/:rw' + networks: + - ctrlpanel + + mysql: + image: mysql + container_name: ctrlpanel_mysql + restart: unless-stopped + tty: true + ports: + - "3306:3306" + environment: + MYSQL_DATABASE: ctrlpanel + MYSQL_USER: ctrlpaneluser + MYSQL_PASSWORD: root + MYSQL_ROOT_PASSWORD: root + volumes: + - "./mysql:/var/lib/mysql:delegated" + networks: + - ctrlpanel + + phpmyadmin: + image: phpmyadmin/phpmyadmin + container_name: ctrlpanel_phpmyadmin + depends_on: + - mysql + ports: + - '8080:80' + environment: + - PMA_HOST=ctrlpanel_mysql + - PMA_USER=root + - PMA_PASSWORD=root + - PMA_ARBITRARY=1 + networks: + - ctrlpanel + + redis: + image: redis + container_name: ctrlpanel_redis + restart: unless-stopped + ports: + - "6379:6379" + networks: + - ctrlpanel + +networks: + ctrlpanel: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index 52aee969a..000000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,65 +0,0 @@ -version: '3' - -networks: - laravel: - -services: - nginx: - build: - context: ../ - dockerfile: docker/nginx/Dockerfile - container_name: controlpanel_nginx - ports: - - 80:80 - volumes: - - "../:/var/www/html" - depends_on: - - php - - mysql - networks: - - laravel - - mysql: - image: mysql - container_name: controlpanel_mysql - restart: unless-stopped - tty: true - ports: - - "3306:3306" - environment: - MYSQL_DATABASE: controlpanel - MYSQL_USER: controlpanel - MYSQL_PASSWORD: root - MYSQL_ROOT_PASSWORD: root - volumes: - - "mysql:/var/lib/mysql:delegated" - networks: - - laravel - - php: - build: - context: ../ - dockerfile: docker/php/Dockerfile - container_name: controlpanel_php - volumes: - - "../:/var/www/html" - networks: - - laravel - - phpmyadmin: - image: phpmyadmin/phpmyadmin - container_name: controlpanel_phpmyadmin - depends_on: - - mysql - ports: - - '8080:80' - environment: - - PMA_HOST=controlpanel_mysql - - PMA_USER=root - - PMA_PASSWORD=root - - PMA_ARBITRARY=1 - networks: - - laravel - -volumes: - mysql: diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile deleted file mode 100644 index 51bf97ea1..000000000 --- a/docker/nginx/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM nginx:stable-alpine - -RUN addgroup -g 1000 laravel && adduser -G laravel -g laravel -s /bin/sh -D laravel - -ADD ./docker/nginx/nginx.conf /etc/nginx/ -ADD ./docker/nginx/default.conf /etc/nginx/conf.d/ - -RUN mkdir -p /var/www/html - -RUN chown laravel:laravel /var/www/html diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile deleted file mode 100644 index c372e4f80..000000000 --- a/docker/php/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM php:8.1-fpm-buster -RUN apt-get update \ - && apt-get install -y build-essential zlib1g-dev default-mysql-client curl gnupg procps vim git unzip libzip-dev libpq-dev libicu-dev libonig-dev libpng-dev libjpeg-dev libfreetype6-dev - -RUN docker-php-ext-install mysqli pdo pdo_mysql intl zip gd bcmath - -ADD ./docker/php/www.conf /usr/local/etc/php-fpm.d/ - -RUN mkdir -p /var/www/html - -RUN addgroup --gid 1000 laravel && adduser --ingroup laravel --uid 1000 --shell /bin/sh --disabled-password --gecos "" laravel -RUN chown laravel:laravel /var/www/html - -WORKDIR /var/www/html - -USER laravel - -COPY --from=composer:latest /usr/bin/composer /usr/bin/composer - diff --git a/docker/standalone/Dockerfile b/docker/standalone/Dockerfile new file mode 100644 index 000000000..a16bed8cb --- /dev/null +++ b/docker/standalone/Dockerfile @@ -0,0 +1,62 @@ +FROM php:8.1-fpm + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + nginx \ + nano \ + curl \ + git \ + libcurl4-openssl-dev \ + libicu-dev \ + libzip-dev \ + libpng-dev \ + && rm -rf /var/lib/apt/lists/* + +# Install PHP extensions +RUN pecl install redis \ + && docker-php-ext-enable redis \ + && docker-php-ext-install -j$(nproc) \ + mysqli \ + pdo \ + pdo_mysql \ + intl \ + zip \ + gd \ + bcmath \ + && rm -rf /tmp/* /var/cache/* + +# Install Composer +COPY --from=composer:latest /usr/bin/composer /usr/bin/composer + +# Create directory for application +RUN mkdir -p /var/default /var/www/html + +# Create user and group for Laravel +RUN groupadd -g 1000 laravel \ + && useradd -u 1000 -g laravel -ms /bin/bash laravel \ + && chown -R laravel:laravel /var/default /var/www/html + +# Copy application files +COPY --chown=laravel:laravel . /var/default + +# Copy PHP-FPM configuration +COPY --chown=laravel:laravel ./docker/standalone/php/www.conf /usr/local/etc/php-fpm.d/ + +# Copy Nginx configuration +COPY --chown=laravel:laravel ./docker/standalone/nginx/nginx.conf /etc/nginx/nginx.conf +# Create directory for Nginx logs +RUN mkdir -p /var/log/nginx && chown -R laravel:laravel /var/log/nginx + +# Expose ports +EXPOSE 80 443 + +# Copy startup script +COPY --chown=laravel:laravel ./docker/standalone/scripts/startup.sh /usr/local/bin/startup-script.sh +# Make startup script executable +RUN chmod +x /usr/local/bin/startup-script.sh + +# Set the working directory +WORKDIR /var/www/html + +# Start the startup script +CMD ["/usr/local/bin/startup-script.sh"] diff --git a/docker/standalone/README.md b/docker/standalone/README.md new file mode 100644 index 000000000..2efaf6bfd --- /dev/null +++ b/docker/standalone/README.md @@ -0,0 +1,34 @@ +# 🐳 Standalone Docker + +The CtrlPanel standalone Docker enables users to run CtrlPanel easily with just a few clicks. + +To run CtrlPanel standalone Docker, you need to have Docker installed on your machine. Some server operating systems like Unraid, TrueNAS, etc.. already have Docker installed, making it even easier to run CtrlPanel. +If you're using a different operating system, you can follow the official Docker installation guide [here](https://docs.docker.com/get-docker/). + +Once you have Docker installed, you can run CtrlPanel standalone Docker by executing the following command: + +Running as commandline command: + +```bash +docker run -p 80:80 -p 443:443 -v /path/to/website_files:/var/www/html ghcr.io/ctrlpanel-gg/panel:latest +``` + +This command will run the latest CtrlPanel Docker image from GitHub Container Registry and run it. + +Recommended way via Docker Compose: + +1. Copy and configure your docker compose file to your needs `curl -L -o compose.yaml https://raw.githubusercontent.com/Ctrlpanel-gg/panel/blob/main/docker/standalone/compose.yaml`. +2. Create the env file in the same directory as the compose file `touch env_file`. +3. When installing you need to update the `env_file` file. Change those two variables to: `MEMCACHED_HOST=redis` and `REDIS_HOST=redis`, to use the Redis server which comes with the docker compose installation. + +The control panel will be available at http://localhost/install and will be a completely fresh installation. + +Note that while the container contains the full CtrlPanel installation, you will still need to perform the basic setup. You can find instructions for this [here](https://ctrlpanel.gg/docs/Installation/getting-started#basic-setup). + +## 🏗️ Migrating from a previous bare metal installation + +If you are migrating, from a previous bare metal installation, you can follow the instructions [here]() (Soon on documentation). + +## 🧰 Creating your own Docker image + +If you want to create your own Docker image, you can follow the instructions [here]() (Soon on documentation). diff --git a/docker/standalone/compose.yaml b/docker/standalone/compose.yaml new file mode 100644 index 000000000..b2d3ce2f4 --- /dev/null +++ b/docker/standalone/compose.yaml @@ -0,0 +1,62 @@ +services: + ctrlpanel_standalone: + image: ghcr.io/ctrlpanel-gg/panel:latest + container_name: ctrlpanel_standalone + restart: unless-stopped + depends_on: + - redis + ports: + - "80:80" + - "443:443" + volumes: + - './logs:/var/www/html/storage/logs:w' + - './env_file:/var/www/html/.env' + - './website_files:/var/www/html:rw' # optionally remove this bind mount, it's not needed unless you want access to all project files, to modify the project with addons/plugins. + - './nginx_config:/etc/nginx/conf.d/:rw' # optionally remove this bind mount, it's not needed unless you want to modify the project with addons/plugins. (dangerous to edit) + networks: + - ctrlpanel + + mysql: + image: mysql + container_name: ctrlpanel_mysql + restart: unless-stopped + tty: true + ports: + - "3306:3306" + environment: + MYSQL_DATABASE: ctrlpanel + MYSQL_USER: ctrlpaneluser + MYSQL_PASSWORD: root # change it + MYSQL_ROOT_PASSWORD: root # change it + volumes: + - "./mysql:/var/lib/mysql:delegated" + networks: + - ctrlpanel + + phpmyadmin: + image: phpmyadmin/phpmyadmin + container_name: ctrlpanel_phpmyadmin + restart: unless-stopped + depends_on: + - mysql + ports: + - '8080:80' + environment: + - PMA_HOST=ctrlpanel_mysql + - PMA_USER=root # change it + - PMA_PASSWORD=root # change it + - PMA_ARBITRARY=1 + networks: + - ctrlpanel + + redis: + image: redis + container_name: ctrlpanel_redis + restart: unless-stopped + ports: + - "6379:6379" + networks: + - ctrlpanel + +networks: + ctrlpanel: diff --git a/docker/nginx/default.conf b/docker/standalone/nginx/default.conf similarity index 56% rename from docker/nginx/default.conf rename to docker/standalone/nginx/default.conf index 282633d76..2fe700465 100644 --- a/docker/nginx/default.conf +++ b/docker/standalone/nginx/default.conf @@ -1,20 +1,21 @@ server { listen 80; - index index.php index.html; server_name _; root /var/www/html/public; + index index.php index.html index.htm index.nginx-debian.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { - try_files $uri =404; - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass php:9000; - fastcgi_index index.php; + include snippets/fastcgi-php.conf; + fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param PATH_INFO $fastcgi_path_info; + } + + location ~ /\.ht { + deny all; } } diff --git a/docker/nginx/nginx.conf b/docker/standalone/nginx/nginx.conf similarity index 100% rename from docker/nginx/nginx.conf rename to docker/standalone/nginx/nginx.conf diff --git a/docker/php/www.conf b/docker/standalone/php/www.conf similarity index 100% rename from docker/php/www.conf rename to docker/standalone/php/www.conf diff --git a/docker/standalone/scripts/startup.sh b/docker/standalone/scripts/startup.sh new file mode 100644 index 000000000..bf11b5bff --- /dev/null +++ b/docker/standalone/scripts/startup.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +# Log directory +LOG_DIR="/var/www/html/storage/logs" + +echo "Starting script..." + +echo "Clearing log file..." +# clean all logs in log directory +if [ -n "$LOG_DIR" ]; then + rm -f "$LOG_DIR/startup-script.log" +fi + +# Check if log directory exists +if [ ! -d "$LOG_DIR" ]; then + echo "Warning: Log directory does not exist (maybe first install ?). Logging disabled until restart." + LOG_DIR="" +fi + +# Function to log messages +log_message() { + if [ -n "$LOG_DIR" ]; then + echo "$1" >> "$LOG_DIR/startup-script.log" + fi + echo "$1" +} + +# Check if public folder is exists. If not, copy project. +if [ ! -d "/var/www/html/public" ]; then + log_message "Warning: project folder is empty. Copying default files..." + # Copy everything from /var/default to /var/www/html + cp -nr /var/default/. /var/www/html # Use -n to avoid overwriting existing files + chown -R laravel:laravel /var/www/html/ + chmod -R 755 /var/www/html/ +fi + +# Copy .env file for it to be available when starting the Docker container (to be able to bind-mount it to the host, instead of the entire project folder). +cp -n /var/default/.env.example /var/www/html/.env # Use -n to avoid overwriting existing files + +# Check and copy default Nginx configuration if not exists +if [ ! -f "/etc/nginx/conf.d/default.conf" ]; then + log_message "Warning: Nginx configuration not found. Copying default configuration..." + cp -n /var/default/docker/standalone/nginx/default.conf /etc/nginx/conf.d/default.conf +fi + +# Check and execute composer install if composer.json is present and there's no vendor directory +if [ -f "/var/www/html/composer.json" ] && [ ! -d "/var/www/html/vendor" ]; then + log_message "Warning: Composer dependencies not found. Running composer install..." + cd /var/www/html || exit + composer install --no-dev --optimize-autoloader + cd - || exit +fi + +# Start the queue worker service +log_message "Starting the queue worker service..." +runuser -u laravel -- php /var/www/html/artisan queue:work --sleep=3 --tries=3 & + +# Start Nginx +log_message "Starting Nginx..." +service nginx start + +# Start PHP-FPM +log_message "Starting PHP-FPM..." +php-fpm -F diff --git a/lang/README.md b/lang/README.md new file mode 100644 index 000000000..89edaeb97 --- /dev/null +++ b/lang/README.md @@ -0,0 +1,10 @@ +# 🌍 Localization + +If you add any strings that are displayed on the frontend, please localize them using the following format: +``` +"New String" -> {{ __('New String') }} +``` +After adding localized strings, run the following command to generate localization files: +```cmd +php artisan translatable:export en +``` diff --git a/lang/bg.json b/lang/bg.json index dbd6881a4..1618b1ccd 100644 --- a/lang/bg.json +++ b/lang/bg.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Грешка при създаване на сървър", "Your servers have been suspended!": "Сървърите ви са спрени!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "За да активирате автоматично вашия сървър\/и, трябва да закупите повече кредити.", + "To automatically re-enable your server/s, you need to purchase more credits.": "За да активирате автоматично вашия сървър/и, трябва да закупите повече кредити.", "Purchase credits": "Купете кредити", "If you have any questions please let us know.": "При допълнителни въпроси, моля свържете се с нас.", "Regards": "Поздрави", @@ -93,7 +93,7 @@ "Getting started!": "Приготвяме се да започнем!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Сървър за поддръжка", "Documentation": "Документация", "Github": "GitHub", - "Support ControlPanel": "Подкрепете Control Panel", + "Support CtrlPanel": "Подкрепете CtrlPanel", "Servers": "Сървъри", "Total": "Общо", "Payments": "Плащания", @@ -187,7 +187,7 @@ "Default language": "Език по подразбиране", "The fallback Language, if something goes wrong": "Резервният език, ако нещо се обърка", "Datable language": "Език с данни", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Езиков код на таблиците с данни.
Пример:<\/strong> en-gb, fr_fr, de_de
Повече информация: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Езиков код на таблиците с данни.
Пример: en-gb, fr_fr, de_de
Повече информация: ", "Auto-translate": "Автоматичен превод", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Ако това е отметнато, таблото за управление ще се преведе на езика на клиентите, ако е наличен", "Client Language-Switch": "Превключване на клиентски език", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Таксува кредити за първия час при създаване на сървър.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Въведете URL адреса на вашата инсталация на PHPMyAdmin. Без крайна наклонена черта!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Въведете URL адреса на вашата инсталация на PHPMyAdmin. Без крайна наклонена черта!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Въведете URL адреса на вашата инсталация на Pterodactyl.Без крайна наклонена черта!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Въведете URL адреса на вашата инсталация на Pterodactyl.Без крайна наклонена черта!", "Pterodactyl API Key": "Pterodactyl API Kлюч", "Enter the API Key to your Pterodactyl installation.": "Въведете API ключа към вашата инсталация на Pterodactyl.", "Force Discord verification": "Принудително потвърждаване на Discord", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Ваучер може да се използва само веднъж на потребител. Uses определя броя на различните потребители, които могат да използват този ваучер.", "Max": "Макс", "Expires at": "Изтича на", - "Used \/ Uses": "Използван \/ Използвания", + "Used / Uses": "Използван / Използвания", "Expires": "Изтича", "Sign in to start your session": "Влезте, за да започнете сесията си", "Password": "Парола", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Няма свързани Node-ове!", "No nests available!": "Няма налични Nest-ове!", "No eggs have been linked!": "Няма свързани Egg-ове!", - "Software \/ Games": "Софтуер \/ Игри", + "Software / Games": "Софтуер / Игри", "Please select software ...": "Моля, изберете софтуер...", "---": "---", "Specification ": "Спецификация ", @@ -447,18 +447,25 @@ "Notes": "Бележки", "Amount in words": "Сума с думи", "Please pay until": "Моля, платете до", - "cs": "Чешки", - "de": "Немски", - "en": "Английски", - "es": "Испански", - "fr": "Френски", - "hi": "Хинди", - "it": "Италиански", - "nl": "Холандски", - "pl": "Полски", - "zh": "Китайски", - "tr": "Турски", - "ru": "Руски", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Актуализирането / надграждането на сървъра ви ще нулира вашата билнгова цикъл до сега. Вашите превишени кредити ще бъдат възстановени. Цената за новия билнгов цикъл ще бъде извлечена", + "Caution": "Внимание", + "You can not see your Referral Code": "Не можете да видите вашия код за препращане", + "SERVER NAME": "ИМЕ НА СЪРВЪР", + "STORAGE": "Съхранение", + "Cancel": "Отказ" } diff --git a/lang/bs.json b/lang/bs.json index 8a84b67a3..79615b407 100644 --- a/lang/bs.json +++ b/lang/bs.json @@ -80,7 +80,7 @@ "User ID": "User ID", "Server Creation Error": "Server Creation Error", "Your servers have been suspended!": "Your servers have been suspended!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "To automatically re-enable your server\/s, you need to purchase more credits.", + "To automatically re-enable your server/s, you need to purchase more credits.": "To automatically re-enable your server/s, you need to purchase more credits.", "Purchase credits": "Purchase credits", "If you have any questions please let us know.": "If you have any questions please let us know.", "Regards": "Regards", @@ -112,7 +112,7 @@ "Support server": "Support server", "Documentation": "Documentation", "Github": "Github", - "Support ControlPanel": "Support ControlPanel", + "Support CtrlPanel": "Support CtrlPanel", "Servers": "Servers", "Total": "Total", "Payments": "Payments", @@ -173,7 +173,7 @@ "Default language": "Default language", "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Auto-translate", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -214,9 +214,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -284,7 +284,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Max", "Expires at": "Expires at", - "Used \/ Uses": "Used \/ Uses", + "Used / Uses": "Used / Uses", "Expires": "Expires", "Sign in to start your session": "Sign in to start your session", "Password": "Password", @@ -354,7 +354,7 @@ "No nodes have been linked!": "No nodes have been linked!", "No nests available!": "No nests available!", "No eggs have been linked!": "No eggs have been linked!", - "Software \/ Games": "Software \/ Games", + "Software / Games": "Software / Games", "Please select software ...": "Please select software ...", "---": "---", "Specification ": "Specification ", @@ -417,7 +417,6 @@ "Value": "Value", "Edit Configuration": "Edit Configuration", "Text Field": "Text Field", - "Cancel": "Cancel", "Save": "Save", "Images and Icons may be cached, reload without cache to see your changes appear": "Images and Icons may be cached, reload without cache to see your changes appear", "Enter your companys name": "Enter your companys name", @@ -441,5 +440,14 @@ "pl": "Polish", "zh": "Chinese", "tr": "Turkish", - "ru": "Russian" + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed", + "Caution": "Caution", + "You can not see your Referral Code": "You can not see your Referral Code", + "SERVER NAME": "SERVER NAME", + "STORAGE": "STORAGE", + "Cancel": "Cancel" } diff --git a/lang/cs.json b/lang/cs.json index 7f7235420..146670294 100644 --- a/lang/cs.json +++ b/lang/cs.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Někdo se zaregistroval pomocí vašeho kódu!", "Server Creation Error": "Chyba při vytváření serveru", "Your servers have been suspended!": "Vaše servery byly pozastaveny!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Pro opětovné spuštění vašich serverů dobijte prosím kredity.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Pro opětovné spuštění vašich serverů dobijte prosím kredity.", "Purchase credits": "Zakoupit kredity", "If you have any questions please let us know.": "Máte-li jakékoli dotazy, dejte nám vědět.", "Regards": "S pozdravem", @@ -93,7 +93,7 @@ "Getting started!": "Začínáme!", "Welcome to our dashboard": "Vítejte v našem ovládacím panelu", "Verification": "Ověření", - "You can verify your e-mail address and link\/verify your Discord account.": "Můžete ověřit svojí e-mail adresu a přiojit váš Discord účet.", + "You can verify your e-mail address and link/verify your Discord account.": "Můžete ověřit svojí e-mail adresu a přiojit váš Discord účet.", "Information": "Informace", "This dashboard can be used to create and delete servers": "Tento panel může použít pro vytvoření a mazání serverů", "These servers can be used and managed on our pterodactyl panel": "Tyto servery můžete používat a spravovat v našem pterodactyl panelu", @@ -114,7 +114,7 @@ "Token": "Token", "Last used": "Naposledy použito", "Are you sure you wish to delete?": "Opravdu si přejete odstranit?", - "Nests": "Software\/hra", + "Nests": "Software/hra", "Sync": "Synchronizovat", "Active": "Aktivní", "ID": "ID", @@ -126,7 +126,7 @@ "Support server": "Server podpory", "Documentation": "Dokumentace", "Github": "GitHub", - "Support ControlPanel": "Podpořit ControlPanel", + "Support CtrlPanel": "Podpořit CtrlPanel", "Servers": "Servery", "Total": "Celkem", "Payments": "Platby", @@ -174,10 +174,10 @@ "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!": "prosím vytvoř soubor který bude pojmenován install.lock v Kontrolním panelu (hlavní složka)\nPokud tak neuděláš, žádné změny nebudou načteny!", "or click here": "nebo klikněte sem", "Company Name": "Název společnosti", - "Company Address": "Adresa Firmy", + "Company Adress": "Adresa Firmy", "Company Phonenumber": "Telefon společnosti", "VAT ID": "DIČ", - "Company E-Mail Address": "E-mailová adresa společnosti", + "Company E-Mail Adress": "E-mailová adresa společnosti", "Company Website": "Web společnosti", "Invoice Prefix": "Prefix pro faktury", "Enable Invoices": "Povolit faktury", @@ -187,7 +187,7 @@ "Default language": "Výchozí jazyk", "The fallback Language, if something goes wrong": "Záložní jazyk, kdyby se něco pokazilo", "Datable language": "Jazyk tabulek", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Kód jazyka datových tabulek.
Příklad:<\/strong> en-gb, fr_fr, de_de
Více informací: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Kód jazyka datových tabulek.
Příklad: en-gb, fr_fr, de_de
Více informací: ", "Auto-translate": "Automatický překlad", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Pokud je tohle zaškrtlé, Panel bude přeložen do Jazyka klienta (pokud to je možné)", "Client Language-Switch": "Povolit uživatelům změnu jazyka", @@ -199,7 +199,7 @@ "Mail Username": "Uživatelské jméno pro e-mail", "Mail Password": "E-mailové heslo", "Mail Encryption": "Šifrování e-mailu", - "Mail From Address": "E-mail odesílatele", + "Mail From Adress": "E-mail odesílatele", "Mail From Name": "Název odešílatele", "Discord Client-ID": "Discord Client-ID", "Discord Client-Secret": "Discord Client-Secret", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Po vytvoření služby náčtuje ihned první hodinu.", "Credits Display Name": "Název kreditů", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Vložte URL vaší instalace PHPmyAdmin. Bez koncového lomítka!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Vložte URL vaší instalace PHPmyAdmin. Bez koncového lomítka!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Vložte URL vaší instalace Pterodactyl. Bez koncového lomítka!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Vložte URL vaší instalace Pterodactyl. Bez koncového lomítka!", "Pterodactyl API Key": "Pterodactyl API klíč", "Enter the API Key to your Pterodactyl installation.": "Zadejte API klíč Vaší Pterodactyl instalace.", "Force Discord verification": "Vynutit ověření skrz Discord", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Poukaz může být použit pouze jednou na uživatele. Počet použití upravuje počet různých uživatelů, kteří můžou poukaz použít.", "Max": "Maximum", "Expires at": "Vyprší", - "Used \/ Uses": "Použito", + "Used / Uses": "Použito", "Expires": "Vyprší", "Sign in to start your session": "Pro pokračování se prosím přihlašte", "Password": "Heslo", @@ -386,9 +386,9 @@ "Sync now": "Synchronizovat nyní", "No products available!": "Žádné dostupné balíčky!", "No nodes have been linked!": "Nebyly propojeny žádné uzly!", - "No nests available!": "Žádný dostupný software\/hry!", + "No nests available!": "Žádný dostupný software/hry!", "No eggs have been linked!": "Nebyly nastaveny žádné distribuce!", - "Software \/ Games": "Software\/hry", + "Software / Games": "Software/hry", "Please select software ...": "Prosím zvolte software ...", "---": "----", "Specification ": "Specifikace ", @@ -447,18 +447,26 @@ "Notes": "Poznámky", "Amount in words": "Celkem slovy", "Please pay until": "Splatné do", - "cs": "Čeština", - "de": "Němčina", - "en": "Angličtina", - "es": "Španělština", - "fr": "Francouzština", - "hi": "Hindština", - "it": "Italština", - "nl": "Holandština", - "pl": "Polština", - "zh": "Čínština", - "tr": "Turečtina", - "ru": "Ruština", - "sv": "Švédština", - "sk": "Slovensky" + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "The system was unable to update your server product. Please try again later or contact support.": "Systém nebyl schopen změnit Váš balíček serveru. Prosím zkuste to znovu nebo kontaktujte podporu.", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Aktualizace/snížení vašeho serveru resetuje váš fakturační cyklus na aktuální. Vaše přeplacené kredity budou vráceny. Cena za nový fakturační cyklus bude odečtena", + "Caution": "Upozornění", + "You can not see your Referral Code": "Nemůžete vidět váš doporučující kód", + "SERVER NAME": "NÁZEV SERVERU", + "STORAGE": "ZAVAZADLO", + "Cancel": "Zrušit" } diff --git a/lang/de.json b/lang/de.json index 9107634ba..2460899a3 100644 --- a/lang/de.json +++ b/lang/de.json @@ -126,7 +126,7 @@ "Support server": "Discord Server", "Documentation": "Dokumentation", "Github": "Github", - "Support ControlPanel": "Unterstütze Controlpanel.gg", + "Support CtrlPanel": "Unterstütze CtrlPanel.gg", "Servers": "Server", "Total": "Gesamt", "Payments": "Zahlungen", @@ -174,10 +174,10 @@ "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!": "Bitte erstellen Sie eine Datei mit dem Namen \"install.lock\" in Ihrem Dashboard-Root-Verzeichnis. Sonst werden keine Einstellungen geladen!", "or click here": "oder klicke hier", "Company Name": "Firmenname", - "Company Address": "Firmenadresse", + "Company Adress": "Firmenadresse", "Company Phonenumber": "Firmen Telefonnummer", "VAT ID": "Umsatzsteuer-ID", - "Company E-Mail Address": "Firmen E-Mail Adresse", + "Company E-Mail Adress": "Firmen E-Mail Adresse", "Company Website": "Firmenwebseite", "Invoice Prefix": "Rechnungspräfix", "Enable Invoices": "Rechnungen aktivieren", @@ -199,7 +199,7 @@ "Mail Username": "E-Mail Nutzername", "Mail Password": "E-Mail Passwort", "Mail Encryption": "E-Mail Verschlüsselungsart", - "Mail From Address": "Absender E-Mailadresse", + "Mail From Adress": "Absender E-Mailadresse", "Mail From Name": "Absender E-Mailname", "Discord Client-ID": "Discord Client-ID", "Discord Client-Secret": "DIscord Client-Secret", @@ -447,21 +447,48 @@ "Notes": "Notizen", "Amount in words": "Betrag in Worten", "Please pay until": "Zahlbar bis", - "cs": "Tschechisch", - "de": "Deutsch", - "en": "Englisch", - "es": "Spanisch", - "fr": "Französisch", - "hi": "Indisch", - "it": "Italienisch", - "nl": "Niederländisch", - "pl": "Polnisch", - "zh": "Chinesisch", - "tr": "Türkisch", - "ru": "Russisch", - "sv": "Schwedisch", - "sk": "Slowakisch", - "Imprint": "Impressum", - "Privacy": "Datenschutz", - "Privacy Policy": "Datenschutzerklärung" + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "hourly": "Stündlich", + "monthly": "Monatlich", + "yearly": "Jährlich", + "daily": "Täglich", + "weekly": "Wöchentlich", + "quarterly": "Vierteljährlich", + "half-annually": "Halbjährlich", + "annually": "Jährlich", + "Suspended": "Gesperrt", + "Cancelled": "Gekündigt", + "An exception has occurred while trying to cancel the server": "Ein Fehler ist aufgetreten beim Versuch, den Server zu kündigen", + "This will cancel your current server to the next billing period. It will get suspended when the current period runs out.": "Dies wird Ihren aktuellen Server zur nächsten Abrechnungsperiode kündigen. Er wird beim Ablauf der aktuellen Periode gesperrt.", + "This is an irreversible action, all files of this server will be removed. No funds will get refunded. We recommend deleting the server when server is suspended.": "Dies ist eine irreversiblen Aktion, alle Dateien dieses Servers werden gelöscht. Keine Rückerstattung!. Wir empfehlen, den Server zu löschen, wenn er gesperrt ist.", + "Cancel Server?": "Server kündigen?", + "Delete Server?": "Server löschen?", + "Billing Period": "Abrechnungsperiode", + "Next Billing Cycle": "Nächste Abrechnungsperiode", + "Manage Server": "Server verwalten", + "Delete Server": "Server löschen", + "Cancel Server": "Server kündigen", + "Yes, cancel it!": "Ja, löschen!", + "No, abort!": "Abbrechen", + "Billing period": "Abrechnungsperiode", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Das Upgrade/Downgrade Ihres Servers wird Ihre Abrechnungsperiode auf \"jetzt\" zurücksetzen. Ihre überzahlten Credits werden erstattet. Der Preis für die neue Abrechnungsperiode wird abgebucht.", + "Caution": "Achtung", + "You can not see your Referral Code": "Sie können Ihren Empfehlungscode nicht sehen", + "SERVER NAME": "SERVERNAMEN", + "STORAGE": "STORAGE", + "Cancel": "Stornieren" } diff --git a/lang/en.json b/lang/en.json index bbdabf014..b468f14f7 100644 --- a/lang/en.json +++ b/lang/en.json @@ -10,10 +10,6 @@ "Everything is good!": "Everything is good!", "System settings have not been updated!": "System settings have not been updated!", "System settings updated!": "System settings updated!", - "Discount": "Discount", - "The product you chose can't be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.": "The product you chose can't be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.", - "Tax": "Tax", - "Your payment has been canceled!": "Your payment has been canceled!", "api key created!": "api key created!", "api key updated!": "api key updated!", "api key has been removed!": "api key has been removed!", @@ -24,9 +20,11 @@ "Invoice does not exist on filesystem!": "Invoice does not exist on filesystem!", "unknown": "unknown", "Pterodactyl synced": "Pterodactyl synced", - "An error ocured. Please try again.": "An error ocured. Please try again.", "Your credit balance has been increased!": "Your credit balance has been increased!", - "Unknown user": "Unknown user", + "Your payment is being processed!": "Your payment is being processed!", + "Your payment has been canceled!": "Your payment has been canceled!", + "Payment method": "Payment method", + "Invoice": "Invoice", "Download": "Download", "Product has been created!": "Product has been created!", "Product has been updated!": "Product has been updated!", @@ -36,10 +34,6 @@ "Server removed": "Server removed", "An exception has occurred while trying to remove a resource \"": "An exception has occurred while trying to remove a resource \"", "Server has been updated!": "Server has been updated!", - "renamed": "renamed", - "servers": "servers", - "deleted": "deleted", - "old servers": "old servers", "Unsuspend": "Unsuspend", "Suspend": "Suspend", "Store item has been created!": "Store item has been created!", @@ -75,15 +69,10 @@ "Close": "Close", "Target User already in blacklist. Reason updated": "Target User already in blacklist. Reason updated", "Change Status": "Change Status", - "partner has been created!": "partner has been created!", - "partner has been updated!": "partner has been updated!", - "partner has been removed!": "partner has been removed!", - "Default": "Default", - "Account permanently deleted!": "Account permanently deleted!", "Profile updated": "Profile updated", "Server limit reached!": "Server limit reached!", + "The chosen location doesn't have the required memory or disk left to allocate this product.": "The chosen location doesn't have the required memory or disk left to allocate this product.", "You are required to verify your email address before you can create a server.": "You are required to verify your email address before you can create a server.", - "The system administrator has blocked the creation of new servers.": "The system administrator has blocked the creation of new servers.", "You are required to link your discord account before you can create a server.": "You are required to link your discord account before you can create a server.", "Server created": "Server created", "No allocations satisfying the requirements for automatic deployment on this node were found.": "No allocations satisfying the requirements for automatic deployment on this node were found.", @@ -93,7 +82,9 @@ "Not Enough Balance for Upgrade": "Not Enough Balance for Upgrade", "You are required to verify your email address before you can purchase credits.": "You are required to verify your email address before you can purchase credits.", "You are required to link your discord account before you can purchase Credits": "You are required to link your discord account before you can purchase Credits", + "You can't make a ticket because you're on the blacklist for a reason: '\" . $check->reason . \"": "You can't make a ticket because you're on the blacklist for a reason: '\" . $check->reason . \"", "A ticket has been opened, ID: #": "A ticket has been opened, ID: #", + "You can't reply a ticket because you're on the blacklist for a reason: '\" . $check->reason . \"": "You can't reply a ticket because you're on the blacklist for a reason: '\" . $check->reason . \"", "EXPIRED": "EXPIRED", "Payment Confirmation": "Payment Confirmation", "Payment Confirmed!": "Payment Confirmed!", @@ -109,7 +100,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Server Creation Error", "Your servers have been suspended!": "Your servers have been suspended!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "To automatically re-enable your server\/s, you need to purchase more credits.", + "To automatically re-enable your server/s, you need to purchase more credits.": "To automatically re-enable your server/s, you need to purchase more credits.", "Purchase credits": "Purchase credits", "If you have any questions please let us know.": "If you have any questions please let us know.", "Regards": "Regards", @@ -121,14 +112,12 @@ "Getting started!": "Getting started!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", "If you have any questions, please join our Discord server and #create-a-ticket": "If you have any questions, please join our Discord server and #create-a-ticket", "We hope you can enjoy this hosting experience and if you have any suggestions please let us know": "We hope you can enjoy this hosting experience and if you have any suggestions please let us know", - "Payment method": "Payment method", - "Invoice": "Invoice", "Activity Logs": "Activity Logs", "Dashboard": "Dashboard", "No recent activity from cronjobs": "No recent activity from cronjobs", @@ -153,10 +142,6 @@ "Nodes": "Nodes", "Location": "Location", "Admin Overview": "Admin Overview", - "Version Outdated:": "Version Outdated:", - "You are running on": "You are running on", - "The latest Version is": "The latest Version is", - "Consider updating now": "Consider updating now", "Support server": "Support server", "Documentation": "Documentation", "Github": "Github", @@ -165,8 +150,6 @@ "Total": "Total", "Payments": "Payments", "Pterodactyl": "Pterodactyl", - "Warning!": "Warning!", - "Some nodes got deleted on pterodactyl only. Please click the sync button above.": "Some nodes got deleted on pterodactyl only. Please click the sync button above.", "Resources": "Resources", "Count": "Count", "Locations": "Locations", @@ -177,7 +160,7 @@ "Title": "Title", "User": "User", "Last updated": "Last updated", - "Ctrlpanel.gg": "Ctrlpanel.gg", + "CtrlPanel.gg": "CtrlPanel.gg", "Version": "Version", "Individual nodes": "Individual nodes", "You reached the Pterodactyl perPage limit. Please make sure to set it higher than your server count.": "You reached the Pterodactyl perPage limit. Please make sure to set it higher than your server count.", @@ -245,9 +228,6 @@ "Link your products to nodes and eggs to create dynamic pricing for each option": "Link your products to nodes and eggs to create dynamic pricing for each option", "This product will only be available for these nodes": "This product will only be available for these nodes", "This product will only be available for these eggs": "This product will only be available for these eggs", - "No Eggs or Nodes shown?": "No Eggs or Nodes shown?", - "Sync now": "Sync now", - "Min Credits": "Min Credits", "Product": "Product", "CPU": "CPU", "Updated at": "Updated at", @@ -256,9 +236,6 @@ "You usually do not need to change anything here": "You usually do not need to change anything here", "Edit Server": "Edit Server", "Server identifier": "Server identifier", - "Change the server identifier on ctrlpanel to match a pterodactyl server.": "Change the server identifier on ctrlpanel to match a pterodactyl server.", - "Server owner": "Server owner", - "Change the current server owner on ctrlpanel and pterodactyl.": "Change the current server owner on ctrlpanel and pterodactyl.", "Server id": "Server id", "Config": "Config", "Suspended at": "Suspended at", @@ -267,10 +244,10 @@ "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!": "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!", "or click here": "or click here", "Company Name": "Company Name", - "Company Address": "Company Address", + "Company Adress": "Company Adress", "Company Phonenumber": "Company Phonenumber", "VAT ID": "VAT ID", - "Company E-Mail Address": "Company E-Mail Address", + "Company E-Mail Adress": "Company E-Mail Adress", "Company Website": "Company Website", "Invoice Prefix": "Invoice Prefix", "Enable Invoices": "Enable Invoices", @@ -280,7 +257,7 @@ "Default language": "Default language", "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Auto-translate", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -292,7 +269,7 @@ "Mail Username": "Mail Username", "Mail Password": "Mail Password", "Mail Encryption": "Mail Encryption", - "Mail From Address": "Mail From Address", + "Mail From Adress": "Mail From Adress", "Mail From Name": "Mail From Name", "Discord Client-ID": "Discord Client-ID", "Discord Client-Secret": "Discord Client-Secret", @@ -303,11 +280,7 @@ "Enable ReCaptcha": "Enable ReCaptcha", "ReCaptcha Site-Key": "ReCaptcha Site-Key", "ReCaptcha Secret-Key": "ReCaptcha Secret-Key", - "Your Recaptcha": "Your Recaptcha", - "Referral System": "Referral System", "Enable Referral": "Enable Referral", - "Always give commission": "Always give commission", - "Should users recieve the commission only for the first payment, or for every payment?": "Should users recieve the commission only for the first payment, or for every payment?", "Mode": "Mode", "Should a reward be given if a new User registers or if a new user buys credits": "Should a reward be given if a new User registers or if a new user buys credits", "Commission": "Commission", @@ -323,10 +296,7 @@ "Everyone": "Everyone", "Clients": "Clients", "Enable Ticketsystem": "Enable Ticketsystem", - "Notify on Ticket creation": "Notify on Ticket creation", - "Who will receive an E-Mail when a new Ticket is created": "Who will receive an E-Mail when a new Ticket is created", - "Admins": "Admins", - "Moderators": "Moderators", + "It is not possible to purchase via MercadoPago: APP_URL does not have HTTPS, required by Mercado Pago":"It is not possible to purchase via MercadoPago: APP_URL does not have HTTPS, required by Mercado Pago", "PayPal Client-ID": "PayPal Client-ID", "PayPal Secret-Key": "PayPal Secret-Key", "PayPal Sandbox Client-ID": "PayPal Sandbox Client-ID", @@ -339,20 +309,15 @@ "Payment Methods": "Payment Methods", "Tax Value in %": "Tax Value in %", "System": "System", - "Show Terms of Service": "Show Terms of Service", - "Show Imprint": "Show Imprint", - "Show Privacy Policy": "Show Privacy Policy", "Register IP Check": "Register IP Check", "Prevent users from making multiple accounts using the same IP address.": "Prevent users from making multiple accounts using the same IP address.", "Charge first hour at creation": "Charge first hour at creation", "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", - "Pterodactyl API perPage limit": "Pterodactyl API perPage limit", - "The Pterodactyl API perPage limit. It is necessary to set it higher than your server count.": "The Pterodactyl API perPage limit. It is necessary to set it higher than your server count.", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Pterodactyl Admin-Account API Key": "Pterodactyl Admin-Account API Key", @@ -360,8 +325,6 @@ "Test API": "Test API", "Force Discord verification": "Force Discord verification", "Force E-Mail verification": "Force E-Mail verification", - "Creation of new users": "Creation of new users", - "If unchecked, it will disable the registration of new users in the system, and this will also apply to the API.": "If unchecked, it will disable the registration of new users in the system, and this will also apply to the API.", "Initial Credits": "Initial Credits", "Initial Server Limit": "Initial Server Limit", "Credits Reward Amount - Discord": "Credits Reward Amount - Discord", @@ -370,38 +333,13 @@ "Server Limit Increase - E-Mail": "Server Limit Increase - E-Mail", "Server Limit after Credits Purchase": "Server Limit after Credits Purchase", "Server": "Server", - "Enable upgrade\/downgrade of servers": "Enable upgrade\/downgrade of servers", - "Allow upgrade\/downgrade to a new product for the given server": "Allow upgrade\/downgrade to a new product for the given server", - "Creation of new servers": "Creation of new servers", - "If unchecked, it will disable the creation of new servers for regular users and system moderators, this has no effect for administrators.": "If unchecked, it will disable the creation of new servers for regular users and system moderators, this has no effect for administrators.", "Server Allocation Limit": "Server Allocation Limit", "The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created!": "The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created!", - "Minimum credits": "Minimum credits", - "The minimum amount of credits user has to have to create a server. Can be overridden by package limits.": "The minimum amount of credits user has to have to create a server. Can be overridden by package limits.", - "SEO": "SEO", - "SEO Title": "SEO Title", - "An SEO title tag must contain your target keyword. This tells both Google and searchers that your web page is relevant to this search query!": "An SEO title tag must contain your target keyword. This tells both Google and searchers that your web page is relevant to this search query!", - "SEO Description": "SEO Description", - "The SEO site description represents your homepage. Search engines show this description in search results for your homepage if they dont find content more relevant to a visitors search terms.": "The SEO site description represents your homepage. Search engines show this description in search results for your homepage if they dont find content more relevant to a visitors search terms.", "Design": "Design", - "Theme": "Theme", "Enable Logo on Loginpage": "Enable Logo on Loginpage", "Select panel icon": "Select panel icon", "Select Login-page Logo": "Select Login-page Logo", "Select panel favicon": "Select panel favicon", - "Enable the Alert Message on Homepage": "Enable the Alert Message on Homepage", - "Alert Color": "Alert Color", - "Blue": "Blue", - "Grey": "Grey", - "Green": "Green", - "Red": "Red", - "Orange": "Orange", - "Cyan": "Cyan", - "Alert Message (HTML might be used)": "Alert Message (HTML might be used)", - "Message of the day": "Message of the day", - "Enable the MOTD on the Homepage": "Enable the MOTD on the Homepage", - "Enable the Useful-Links section": "Enable the Useful-Links section", - "MOTD-Text": "MOTD-Text", "Store": "Store", "Server Slots": "Server Slots", "Currency code": "Currency code", @@ -457,18 +395,14 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Max", "Expires at": "Expires at", - "Used \/ Uses": "Used \/ Uses", + "Used / Uses": "Used / Uses", "Expires": "Expires", "Sign in to start your session": "Sign in to start your session", - "Email or Username": "Email or Username", "Password": "Password", "Remember Me": "Remember Me", "Sign In": "Sign In", "Forgot Your Password?": "Forgot Your Password?", "Register a new membership": "Register a new membership", - "Imprint": "Imprint", - "Privacy": "Privacy", - "Terms of Service": "Terms of Service", "Please confirm your password before continuing.": "Please confirm your password before continuing.", "You forgot your password? Here you can easily retrieve a new password.": "You forgot your password? Here you can easily retrieve a new password.", "Request new password": "Request new password", @@ -476,10 +410,7 @@ "You are only one step a way from your new password, recover your password now.": "You are only one step a way from your new password, recover your password now.", "Retype password": "Retype password", "Change password": "Change password", - "The system administrator has blocked the registration of new users": "The system administrator has blocked the registration of new users", - "Back": "Back", "Referral code": "Referral code", - "I agree to the": "I agree to the", "Register": "Register", "I already have a membership": "I already have a membership", "Verify Your Email Address": "Verify Your Email Address", @@ -489,17 +420,6 @@ "click here to request another": "click here to request another", "per month": "per month", "Out of Credits in": "Out of Credits in", - "Partner program": "Partner program", - "Your referral URL": "Your referral URL", - "Click to copy": "Click to copy", - "Number of referred users:": "Number of referred users:", - "Your discount": "Your discount", - "Discount for your new users": "Discount for your new users", - "Reward per registered user": "Reward per registered user", - "New user payment commision": "New user payment commision", - "Make a purchase to reveal your referral-URL": "Make a purchase to reveal your referral-URL", - "URL copied to clipboard": "URL copied to clipboard", - "Privacy Policy": "Privacy Policy", "Home": "Home", "Language": "Language", "See all Notifications": "See all Notifications", @@ -517,6 +437,7 @@ "Management": "Management", "Other": "Other", "Logs": "Logs", + "Warning!": "Warning!", "You have not yet verified your email address": "You have not yet verified your email address", "Click here to resend verification email": "Click here to resend verification email", "Please contact support If you didnt receive your verification email.": "Please contact support If you didnt receive your verification email.", @@ -530,10 +451,9 @@ "Created At": "Created At", "Add To Blacklist": "Add To Blacklist", "please make the best of it": "please make the best of it", - "Please note, the blacklist will make the user unable to make a ticket\/reply again": "Please note, the blacklist will make the user unable to make a ticket\/reply again", + "Please note, the blacklist will make the user unable to make a ticket/reply again": "Please note, the blacklist will make the user unable to make a ticket/reply again", "Ticket": "Ticket", "Category": "Category", - "Priority": "Priority", "Last Updated": "Last Updated", "Comment": "Comment", "All notifications": "All notifications", @@ -544,7 +464,6 @@ "Please contact support If you face any issues.": "Please contact support If you face any issues.", "Due to system settings you are required to verify your discord account!": "Due to system settings you are required to verify your discord account!", "It looks like this hasnt been set-up correctly! Please contact support.": "It looks like this hasnt been set-up correctly! Please contact support.", - "Permanently delete my account": "Permanently delete my account", "Change Password": "Change Password", "Current Password": "Current Password", "Link your discord account!": "Link your discord account!", @@ -553,19 +472,16 @@ "You are verified!": "You are verified!", "Re-Sync Discord": "Re-Sync Discord", "Save Changes": "Save Changes", - "Are you sure you want to permanently delete your account and all of your servers?": "Are you sure you want to permanently delete your account and all of your servers?", - "Delete my account": "Delete my account", - "Account has been destroyed": "Account has been destroyed", - "Account was NOT deleted.": "Account was NOT deleted.", + "URL copied to clipboard": "URL copied to clipboard", "Server configuration": "Server configuration", - "here": "here", "Make sure to link your products to nodes and eggs.": "Make sure to link your products to nodes and eggs.", "There has to be at least 1 valid product for server creation": "There has to be at least 1 valid product for server creation", + "Sync now": "Sync now", "No products available!": "No products available!", "No nodes have been linked!": "No nodes have been linked!", "No nests available!": "No nests available!", "No eggs have been linked!": "No eggs have been linked!", - "Software \/ Games": "Software \/ Games", + "Software / Games": "Software / Games", "Please select software ...": "Please select software ...", "---": "---", "Specification ": "Specification ", @@ -574,9 +490,6 @@ "MB": "MB", "MySQL": "MySQL", "ports": "ports", - "Required": "Required", - "to create this server": "to create this server", - "Server cant fit on this Node": "Server cant fit on this Node", "Not enough": "Not enough", "Create server": "Create server", "Please select a node ...": "Please select a node ...", @@ -600,20 +513,20 @@ "Hourly Price": "Hourly Price", "Monthly Price": "Monthly Price", "MySQL Database": "MySQL Database", - "Upgrade \/ Downgrade": "Upgrade \/ Downgrade", - "Upgrade\/Downgrade Server": "Upgrade\/Downgrade Server", + "To enable the upgrade/downgrade system, please set your Ptero Admin-User API Key in the Settings!": "To enable the upgrade/downgrade system, please set your Ptero Admin-User API Key in the Settings!", + "Upgrade / Downgrade": "Upgrade / Downgrade", + "Upgrade/Downgrade Server": "Upgrade/Downgrade Server", "FOR DOWNGRADE PLEASE CHOOSE A PLAN BELOW YOUR PLAN": "FOR DOWNGRADE PLEASE CHOOSE A PLAN BELOW YOUR PLAN", "YOUR PRODUCT": "YOUR PRODUCT", "Select the product": "Select the product", - "Server can´t fit on this node": "Server can´t fit on this node", "Once the Upgrade button is pressed, we will automatically deduct the amount for the first hour according to the new product from your credits": "Once the Upgrade button is pressed, we will automatically deduct the amount for the first hour according to the new product from your credits", - "Server will be automatically restarted once upgraded": "Server will be automatically restarted once upgraded", "Change Product": "Change Product", "Delete Server": "Delete Server", "This is an irreversible action, all files of this server will be removed!": "This is an irreversible action, all files of this server will be removed!", "Date": "Date", "Subtotal": "Subtotal", "Amount Due": "Amount Due", + "Tax": "Tax", "Submit Payment": "Submit Payment", "Purchase": "Purchase", "There are no store products!": "There are no store products!", @@ -632,6 +545,7 @@ "VAT Code": "VAT Code", "Phone": "Phone", "Units": "Units", + "Discount": "Discount", "Total discount": "Total discount", "Taxable amount": "Taxable amount", "Tax rate": "Tax rate", @@ -653,5 +567,95 @@ "ru": "Russian", "sv": "Swedish", "sk": "Slovakish", - "hu": "Hungarian" -} \ No newline at end of file + "hu": "Hungarian", + "hourly": "Hourly", + "monthly": "Monthly", + "yearly": "Yearly", + "daily": "Daily", + "weekly": "Weekly", + "quarterly": "Quarterly", + "half-annually": "Half-annually", + "annually": "Annually", + "Suspended": "Suspended", + "Cancelled": "Cancelled", + "An exception has occurred while trying to cancel the server": "An exception has occurred while trying to cancel the server", + "This will cancel your current server to the next billing period. It will get suspended when the current period runs out.": "This will cancel your current server to the next billing period. It will get suspended when the current period runs out.", + "Cancel Server?": "Cancel Server?", + "Delete Server?": "Delete Server?", + "This is an irreversible action, all files of this server will be removed. No funds will get refunded. We recommend deleting the server when server is suspended.": "This is an irreversible action, all files of this server will be removed. No funds will get refunded. We recommend deleting the server when server is suspended.", + "Billing Period": "Billing Period", + "Next Billing Cycle": "Next Billing Cycle", + "Manage Server": "Manage Server", + "Cancel Server": "Cancel Server", + "Yes, cancel it!": "Yes, cancel it!", + "No, abort!": "No, abort!", + "Billing period": "Billing period", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed", + "Caution": "Caution", + "Only one of the two code inputs must be provided.": "Only one of the two code inputs must be provided.", + "At least one of the two code inputs must be provided.": "At least one of the two code inputs must be provided.", + "The coupon's was registered successfully.": "The coupon's was registered successfully.", + "coupon has been updated!": "coupon has been updated!", + "coupon has been removed!": "coupon has been removed!", + "Never": "Never", + "Legal pages updated": "Legal pages updated", + "Partner already exists": "Partner already exists", + "partner has been created!": "partner has been created!", + "partner has been updated!": "partner has been updated!", + "partner has been removed!": "partner has been removed!", + "Unknown user": "Unknown user", + "Default": "Default", + "Oops, something went wrong! Please try again later.": "Oops, something went wrong! Please try again later.", + "enabled": "enabled", + "disabled": "disabled", + "Role saved": "Role saved", + "Role updated. Name and Permissions of this Role cannot be changed": "Role updated. Name and Permissions of this Role cannot be changed", + "Role updated. Name of this Role cannot be changed": "Role updated. Name of this Role cannot be changed", + "Role removed": "Role removed", + "Server cancelled": "Server cancelled", + "An exception has occurred while trying to cancel the server\"": "An exception has occurred while trying to cancel the server\"", + "renamed": "renamed", + "servers": "servers", + "deleted": "deleted", + "old servers": "old servers", + "Category created": "Category created", + "Category name updated": "Category name updated", + "Category removed": "Category removed", + "Ticket not found on the server. It potentially got deleted earlier": "Ticket not found on the server. It potentially got deleted earlier", + "A ticket has been reopened, ID: #": "A ticket has been reopened, ID: #", + "User not found on the server. Check on the admin database or try again later.": "User not found on the server. Check on the admin database or try again later.", + "Reopen": "Reopen", + "User not found on the server. Check the admin database or try again later.": "User not found on the server. Check the admin database or try again later.", + "You can not delete the last admin!": "You can not delete the last admin!", + "User does not have the right permissions.": "User does not have the right permissions.", + "Account permanently deleted!": "Account permanently deleted!", + "The system administrator has blocked the creation of new servers.": "The system administrator has blocked the creation of new servers.", + "An exception has occurred while trying to remove a resource\"": "An exception has occurred while trying to remove a resource\"", + "This is not your Server!": "This is not your Server!", + "The system was unable to update your server product. Please try again later or contact support.": "The system was unable to update your server product. Please try again later or contact support.", + "This coupon does not exist.": "This coupon does not exist.", + "This coupon has reached the maximum amount of uses.": "This coupon has reached the maximum amount of uses.", + "This coupon has expired.": "This coupon has expired.", + "You have reached the maximum uses of this coupon.": "You have reached the maximum uses of this coupon.", + "The coupon you are trying to use would give you 100% off, so it cannot be used for this product, sorry.": "The coupon you are trying to use would give you 100% off, so it cannot be used for this product, sorry.", + "Select": "Select", + "Selected": "Selected", + "Pricing": "Pricing", + "Product details": "Product details", + "Total Amount": "Total Amount", + "Partner Discount": "Partner Discount", + "Coupon Discount": "Coupon Discount", + "Enter your coupon here...": "Enter your coupon here...", + "Coupon": "Coupon", + "Checkout details": "Checkout details", + "per 6 Months": "per 6 Months", + "per 3 Months": "per 3 Months", + "per Year": "per Year", + "per Week": "per Week", + "per Day": "per Day", + "You can not see your Referral Code": "You can not see your Referral Code", + "SERVER NAME": "SERVER NAME", + "STORAGE": "STORAGE", + "Cancel": "Cancel", + "Buy more": "Buy more" +} diff --git a/lang/es.json b/lang/es.json index 400a46f49..f4c3121a0 100644 --- a/lang/es.json +++ b/lang/es.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Error de creación del servidor", "Your servers have been suspended!": "¡Sus servidores han sido suspendidos!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Para volver a habilitar automáticamente sus servidores, debe comprar más créditos.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Para volver a habilitar automáticamente sus servidores, debe comprar más créditos.", "Purchase credits": "Comprar Créditos", "If you have any questions please let us know.": "Si tienes más preguntas, por favor háznoslas saber.", "Regards": "Atentamente", @@ -93,7 +93,7 @@ "Getting started!": "¡Empezando!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Servidor de Ayuda", "Documentation": "Documentación", "Github": "GitHub", - "Support ControlPanel": "Apoya ControlPanel", + "Support CtrlPanel": "Apoya CtrlPanel", "Servers": "Servidores", "Total": "Total", "Payments": "Pagos", @@ -174,10 +174,10 @@ "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!": "cree un archivo llamado \"install.lock\" en el directorio Raíz de su tablero. ¡De lo contrario, no se cargará ninguna configuración!", "or click here": "o haga clic aquí", "Company Name": "Nombre Empresa", - "Company Address": "Dirección de la Empresa", + "Company Adress": "Dirección de la Empresa", "Company Phonenumber": "Número de teléfono de la empresa", "VAT ID": "ID de IVA", - "Company E-Mail Address": "Dirección de correo electrónico de la empresa", + "Company E-Mail Adress": "Dirección de correo electrónico de la empresa", "Company Website": "Página Web de la empresa", "Invoice Prefix": "Prefijo de factura", "Enable Invoices": "Habilitar facturas", @@ -187,7 +187,7 @@ "Default language": "Idioma predeterminado", "The fallback Language, if something goes wrong": "El lenguaje alternativo, si algo sale mal", "Datable language": "Lenguaje de tabla de datos", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "El código de idioma de las tablas de datos.
Ejemplo:<\/strong> en-gb, fr_fr, de_de
Más información: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "El código de idioma de las tablas de datos.
Ejemplo: en-gb, fr_fr, de_de
Más información: ", "Auto-translate": "Traducir automáticamente", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Si está marcado, el Tablero se traducirá solo al idioma del Cliente, si está disponible", "Client Language-Switch": "Cambio de idioma del cliente", @@ -199,7 +199,7 @@ "Mail Username": "Nombre de usuario del correo", "Mail Password": "Contraseña de correo", "Mail Encryption": "Cifrado de correo", - "Mail From Address": "Dirección del correo", + "Mail From Adress": "Dirección del correo", "Mail From Name": "Nombre del correo", "Discord Client-ID": "Discord ID-Cliente", "Discord Client-Secret": "Discord Secreto-Cliente", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Carga la primera hora de créditos al crear un servidor.", "Credits Display Name": "Nombre de los Créditos para mostrar", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Ingrese la URL de su instalación de PHPMyAdmin. ¡Sin una barra diagonal final!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Ingrese la URL de su instalación de PHPMyAdmin. ¡Sin una barra diagonal final!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Introduzca la URL de su instalación de Pterodactyl. ¡Sin una barra diagonal final!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Introduzca la URL de su instalación de Pterodactyl. ¡Sin una barra diagonal final!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Ingrese la API Key para su instalación de Pterodactyl.", "Force Discord verification": "Forzar verificación de Discord", @@ -263,7 +263,7 @@ "Select panel favicon": "Seleccionar favicon del panel", "Store": "Tienda", "Server Slots": "Server Slots", - "Currency code": "Código de divisa\/moneda", + "Currency code": "Código de divisa/moneda", "Checkout the paypal docs to select the appropriate code": "Consulte los documentos de PayPal para seleccionar el código apropiado", "Quantity": "Cantidad", "Amount given to the user after purchasing": "Importe dado al usuario después de la compra", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "El descuento solo se puede utilizar una vez por usuario. Los usos especifica el número de usuarios diferentes que pueden utilizar este cupón.", "Max": "Máx", "Expires at": "Expira el", - "Used \/ Uses": "Uso \/ Usos", + "Used / Uses": "Uso / Usos", "Expires": "Expira", "Sign in to start your session": "Iniciar sesión para comenzar", "Password": "Contraseña", @@ -388,7 +388,7 @@ "No nodes have been linked!": "¡No se han vinculado nodos!", "No nests available!": "¡No hay nidos disponibles!", "No eggs have been linked!": "¡No se han vinculado huevos!", - "Software \/ Games": "Software \/ Juegos", + "Software / Games": "Software / Juegos", "Please select software ...": "Seleccione el software...", "---": "---", "Specification ": "Especificación ", @@ -447,18 +447,25 @@ "Notes": "Notas", "Amount in words": "Cantidad en palabras", "Please pay until": "Por favor pague hasta", - "cs": "Checo", - "de": "Alemán", - "en": "Inglés", - "es": "Español", - "fr": "Francés", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", "hi": "Hindi", - "it": "Italiano", - "nl": "Holandés", - "pl": "Polaco", - "zh": "Chino", - "tr": "Turco", - "ru": "Ruso", - "sv": "Sueco", - "sk": "Eslovaco" + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Actualizar/Reducir el servidor restablecerá su ciclo de facturación a ahora. Se reembolsarán los créditos sobrepagados. El precio del nuevo ciclo de facturación se retirará", + "Caution": "Cuidado", + "You can not see your Referral Code": "Не puedes ver tu Código de Referencia", + "SERVER NAME": "NOMBRE DEL SERVIDOR", + "STORAGE": "ALMACENAMIENTO", + "Cancel": "Cancelar" } diff --git a/lang/fr.json b/lang/fr.json index f415e5c62..8811187d7 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Erreur lors de la création de votre serveur", "Your servers have been suspended!": "Votre serveur à été suspendu !", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Pour réactiver automatiquement votre ou vos serveurs, vous devez racheter des crédits.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Pour réactiver automatiquement votre ou vos serveurs, vous devez racheter des crédits.", "Purchase credits": "Acheter des crédits", "If you have any questions please let us know.": "N'hésitez pas à nous contacter si vous avez des questions.", "Regards": "Cordialement", @@ -93,7 +93,7 @@ "Getting started!": "Commencer !", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Serveur de support", "Documentation": "Documentation", "Github": "Github", - "Support ControlPanel": "ControlPanel Support", + "Support CtrlPanel": "CtrlPanel Support", "Servers": "Serveurs", "Total": "Total", "Payments": "Paiments", @@ -187,7 +187,7 @@ "Default language": "Langue par défaut", "The fallback Language, if something goes wrong": "La langue de repli, si quelque chose ne va pas", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Auto-translate", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Le code ne peut être utilisé qu'une seule fois. L'utilisation spécifie le nombre d'utilisateurs différents qui peuvent utiliser ce code.", "Max": "Max", "Expires at": "Expire à", - "Used \/ Uses": "Utilisé \/ Utilisations", + "Used / Uses": "Utilisé / Utilisations", "Expires": "Expire", "Sign in to start your session": "Identifiez-vous pour commencer votre session", "Password": "Mot de passe", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Aucune node n'a été lié !", "No nests available!": "Aucun nests disponible !", "No eggs have been linked!": "Aucun eggs n'a été lié !", - "Software \/ Games": "Logiciels \/ Jeux", + "Software / Games": "Logiciels / Jeux", "Please select software ...": "Veuillez sélectionner...", "---": "---", "Specification ": "Spécification ", @@ -447,6 +447,8 @@ "Notes": "Notes", "Amount in words": "Montant en toutes lettres", "Please pay until": "Veuillez payer avant", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Mettre à niveau / Réduire votre serveur réinitialisera votre cycle de facturation à maintenant. Vos crédits surpayés seront remboursés. Le prix du nouveau cycle de facturation sera débité", + "Caution": "Attention", "cs": "Czech", "de": "German", "en": "English", @@ -460,5 +462,10 @@ "tr": "Turkish", "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Vous ne pouvez pas voir votre Code de parrainage", + "SERVER NAME": "NOM DU SERVEUR", + "STORAGE": "STOCKAGE", + "Cancel": "Annuler" } diff --git a/lang/he.json b/lang/he.json index a1524d6fb..04af79956 100644 --- a/lang/he.json +++ b/lang/he.json @@ -60,8 +60,8 @@ "You ran out of Credits": "נגמר לך המטבעות", "Profile updated": "הפרופיל עודכן", "Server limit reached!": "הגעת להגבלת השרתים!", - "You are required to verify your email address before you can create a server.": "אתה מדרש לאמת את כתובת המייל שלך לפני שתוכל\/י ליצור שרת", - "You are required to link your discord account before you can create a server.": "אתה חייב לקשר את החשבון דיסקורד שלך לפני שתוכל\/י ליצור שרת", + "You are required to verify your email address before you can create a server.": "אתה מדרש לאמת את כתובת המייל שלך לפני שתוכל/י ליצור שרת", + "You are required to link your discord account before you can create a server.": "אתה חייב לקשר את החשבון דיסקורד שלך לפני שתוכל/י ליצור שרת", "Server created": "השרת נוצר", "No allocations satisfying the requirements for automatic deployment on this node were found.": "לא נמצאו הקצאות העומדות בדרישות לפריסה אוטומטית בשרת זה.", "You are required to verify your email address before you can purchase credits.": "אתה נדרש לאמת את כתובת המייל שלך לפני רכישת מטבעות", @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "שגיאה ביצירת שרת", "Your servers have been suspended!": "השרת שלך מושעה!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "כדי להפעיל מחדש את השרתים שלך באופן אוטומטי, עליך לרכוש מטבעות נוספות.", + "To automatically re-enable your server/s, you need to purchase more credits.": "כדי להפעיל מחדש את השרתים שלך באופן אוטומטי, עליך לרכוש מטבעות נוספות.", "Purchase credits": "לרכישת מטבעות", "If you have any questions please let us know.": "אם יש לכם כל שאלה תיידעו אותנו", "Regards": "בברכה", @@ -93,7 +93,7 @@ "Getting started!": "מתחילים!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -125,8 +125,8 @@ "Admin Overview": "סקירת מנהל", "Support server": "שרת תמיכה", "Documentation": "מדריך", - "Github": "Github\/גיטאהב", - "Support ControlPanel": "תמיכת ControlPanel", + "Github": "Github/גיטאהב", + "Support CtrlPanel": "תמיכת CtrlPanel", "Servers": "שרתים", "Total": "בסך הכל", "Payments": "תשלומים", @@ -156,7 +156,7 @@ "Minimum": "מינימום", "Setting to -1 will use the value from configuration.": "הגדרות ל -1 ישתמש בערך מ configuration.", "IO": "IO", - "Databases": "Databases\/ממסד נתונים", + "Databases": "Databases/ממסד נתונים", "Backups": "גיבויים", "Allocations": "הקצאות", "Product Linking": "מוצרים מקושרים", @@ -174,10 +174,10 @@ "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!": "אנא צור קובץ בשם \"install.lock\" בספריית השורש של dashboard שלך. אחרת לא ייטענו הגדרות!", "or click here": "או לחץ כאן", "Company Name": "שם החברה", - "Company Address": "כתובת החברה", + "Company Adress": "כתובת החברה", "Company Phonenumber": "מספר טלפון של החברה", "VAT ID": "מזהה מעמ", - "Company E-Mail Address": "כתובת מייל של החברה", + "Company E-Mail Adress": "כתובת מייל של החברה", "Company Website": "אתר החברה", "Invoice Prefix": "קידומת החשבונים", "Enable Invoices": "אפשר חשבוניות", @@ -187,7 +187,7 @@ "Default language": "שפת ברירת מחדל", "The fallback Language, if something goes wrong": "אם משהו משתבש", "Datable language": "שפה ניתנת לנתונים", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "טבלת הנתונים של השפות.
לדוגמא:<\/strong> en-gb, fr_fr, de_de
למידע נוסף: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "טבלת הנתונים של השפות.
לדוגמא: en-gb, fr_fr, de_de
למידע נוסף: ", "Auto-translate": "תרגום אוטומטי", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "אם זה מסומן, Dashboard יתרגם את עצמו לשפת הלקוח, אם זמין", "Client Language-Switch": "החלפת שפת לקוח", @@ -199,7 +199,7 @@ "Mail Username": "שם המייל", "Mail Password": "סיסמת המייל", "Mail Encryption": "הצפנת המייל", - "Mail From Address": "מייל מכתובת", + "Mail From Adress": "מייל מכתובת", "Mail From Name": "מייל משם", "Discord Client-ID": "מזהה של בוט דיסקורד", "Discord Client-Secret": "מזהה סודי של בוט דיסקורד", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Cגובה מטבעות בשווי השעה הראשונה בעת יצירת שרת.", "Credits Display Name": "שם המטבעות", "PHPMyAdmin URL": "קישור PHPMyAdmin", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "הכנס את הקישור to פיחפי. בלי צלייה נגררת!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "הכנס את הקישור to פיחפי. בלי צלייה נגררת!", "Pterodactyl URL": "קישור Pterodactyl", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API מפתח", "Enter the API Key to your Pterodactyl installation.": "הכנס את מפתח ה API Pterodactyl installation.", "Force Discord verification": "אימות דיסקורד חובה", @@ -300,12 +300,12 @@ "Notifications": "התראות", "All": "הכל", "Send via": "שליחה באמצאות", - "Database": "Database\/מאגר נתונים", + "Database": "Database/מאגר נתונים", "Content": "קשר", "Server limit": "הגבלת שרת", - "Discord": "Discord\/דיסקורד", + "Discord": "Discord/דיסקורד", "Usage": "נוהג", - "IP": "IP\/אייפי", + "IP": "IP/אייפי", "Referals": "Referals", "Vouchers": "קופונים", "Voucher details": "פרטי קופון", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "ניתן להשתמש בשובר פעם אחת בלבד לכל משתמש. שימושים מציינים את מספר המשתמשים השונים שיכולים להשתמש בשובר זה.", "Max": "מקסימום", "Expires at": "יפוג ב", - "Used \/ Uses": "משומש \/ שימושים", + "Used / Uses": "משומש / שימושים", "Expires": "פגי תוקף", "Sign in to start your session": "התחבר על מנת להתחיל", "Password": "סיסמה", @@ -339,7 +339,7 @@ "Before proceeding, please check your email for a verification link.": "לפני שתמשיך, אנא בדוק באימייל שלך קישור לאימות.", "If you did not receive the email": "אם לא קיבלת את המייל", "click here to request another": "לחץ כאן כדי לבקש אחר", - "per month": "\/חודש", + "per month": "/חודש", "Out of Credits in": "נגמרו המטבעות ב", "Home": "בית", "Language": "שפה", @@ -388,7 +388,7 @@ "No nodes have been linked!": "שרתים לא מקושרים!", "No nests available!": "No nests available!", "No eggs have been linked!": "אין eggs מקושרים", - "Software \/ Games": "תוכנה \/ משחקים", + "Software / Games": "תוכנה / משחקים", "Please select software ...": "בבקשה תחבר תוכנה ...", "---": "---", "Specification ": "ציין ", @@ -411,9 +411,9 @@ "Specification": "לציין", "Resource plan": "תוכנית משאבים", "RAM": "RAM", - "MySQL Databases": "בסיס הנתונים MySQL<\/bdi>", - "per Hour": "\/שעה", - "per Month": "\/חודש", + "MySQL Databases": "בסיס הנתונים MySQL", + "per Hour": "/שעה", + "per Month": "/חודש", "Manage": "לנהל", "Are you sure?": "האם אתה בטוח?", "This is an irreversible action, all files of this server will be removed.": "זוהי פעולה בלתי הפיכה, כל הקבצים של שרת זה יוסרו.", @@ -447,18 +447,25 @@ "Notes": "הערות", "Amount in words": "כמות במילים", "Please pay until": "בבקשה שלם עד", - "cs": "צכית", - "de": "גרמנית", - "en": "אנגלית", - "es": "ספרדית", - "fr": "צרפתית", - "hi": "הודית", - "it": "אטלקית", - "nl": "הולנדית", - "pl": "פולנית", - "zh": "סִינִית", - "tr": "טורקית", - "ru": "רוסית", - "sv": "שוודית", - "sk": "סלובקית" + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "שדרוג / הורדת שרת יאפס את מחזור החיוב שלך לעכשיו. הקרדיטים ששילמת יוחזרו. המחיר למחזור החיוב החדש יוחסם", + "Caution": "אזהרה", + "You can not see your Referral Code": "You can not see your Referral Code", + "SERVER NAME": "SERVER NAME", + "STORAGE": "STORAGE", + "Cancel": "Cancel" } diff --git a/lang/hi.json b/lang/hi.json index e7b950b14..5b310de06 100644 --- a/lang/hi.json +++ b/lang/hi.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "सर्वर निर्माण त्रुटि", "Your servers have been suspended!": "आपके सर्वर निलंबित कर दिए गए हैं!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "अपने सर्वर\/सर्वर को स्वचालित रूप से पुन: सक्षम करने के लिए, आपको अधिक क्रेडिट खरीदने की आवश्यकता है।", + "To automatically re-enable your server/s, you need to purchase more credits.": "अपने सर्वर/सर्वर को स्वचालित रूप से पुन: सक्षम करने के लिए, आपको अधिक क्रेडिट खरीदने की आवश्यकता है।", "Purchase credits": "क्रेडिट खरीदें", "If you have any questions please let us know.": "यदि आपके पास कोई प्रश्न है, तो हमें बताएं।", "Regards": "सादर", @@ -93,7 +93,7 @@ "Getting started!": "शुरू करना!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "समर्थन सर्वर", "Documentation": "प्रलेखन", "Github": "गिटहब", - "Support ControlPanel": "समर्थन नियंत्रण पैनल", + "Support CtrlPanel": "CtrlPanel का समर्थन करें", "Servers": "सर्वरस", "Total": "कुल", "Payments": "भुगतान", @@ -187,7 +187,7 @@ "Default language": "डिफ़ॉल्ट भाषा", "The fallback Language, if something goes wrong": "फ़ॉलबैक भाषा, अगर कुछ गलत हो जाता है", "Datable language": "डेटा योग्य भाषा", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "डेटाटेबल्स लैंग-कोड।
उदाहरण:<\/strong> en-gb, fr_fr, de_de
अधिक जानकारी: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "डेटाटेबल्स लैंग-कोड।
उदाहरण: en-gb, fr_fr, de_de
अधिक जानकारी: ", "Auto-translate": "ऑटो का अनुवाद", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "यदि यह चेक किया जाता है, तो डैशबोर्ड स्वयं को क्लाइंट भाषा में अनुवाद करेगा, यदि उपलब्ध हो", "Client Language-Switch": "क्लाइंट भाषा-स्विच", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "सर्वर बनाने पर पहले घंटे के क्रेडिट का शुल्क लेता है।", "Credits Display Name": "क्रेडिट प्रदर्शन नाम", "PHPMyAdmin URL": "PhpMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "अपने PHPMyAdmin इंस्टॉलेशन का URL दर्ज करें। पिछली स्लैश के बिना!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "अपने PHPMyAdmin इंस्टॉलेशन का URL दर्ज करें। पिछली स्लैश के बिना!", "Pterodactyl URL": "पटरोडैक्टाइल यूआरएल", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "अपने Pterodactyl संस्थापन का URL दर्ज करें। पिछली स्लैश के बिना!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "अपने Pterodactyl संस्थापन का URL दर्ज करें। पिछली स्लैश के बिना!", "Pterodactyl API Key": "पटरोडैक्टाइल एपीआई कुंजी", "Enter the API Key to your Pterodactyl installation.": "अपने Pterodactyl स्थापना के लिए API कुंजी दर्ज करें।", "Force Discord verification": "बल विवाद सत्यापन", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "वाउचर प्रति उपयोगकर्ता केवल एक बार उपयोग किया जा सकता है। उपयोग इस वाउचर का उपयोग करने वाले विभिन्न उपयोगकर्ताओं की संख्या को निर्दिष्ट करता है।", "Max": "मैक्स", "Expires at": "पर समाप्त हो रहा है", - "Used \/ Uses": "प्रयुक्त \/ उपयोग", + "Used / Uses": "प्रयुक्त / उपयोग", "Expires": "समय-सीमा समाप्त", "Sign in to start your session": "अपना सत्र शुरू करने के लिए साइन इन करें", "Password": "पासवर्ड", @@ -388,7 +388,7 @@ "No nodes have been linked!": "कोई नोड लिंक नहीं किया गया है!", "No nests available!": "कोई घोंसला उपलब्ध नहीं है!", "No eggs have been linked!": "कोई अंडे नहीं जोड़े गए हैं!", - "Software \/ Games": "सॉफ्टवेयर \/ खेल", + "Software / Games": "सॉफ्टवेयर / खेल", "Please select software ...": "कृपया सॉफ्टवेयर चुनें...", "---": "---", "Specification ": "विनिर्देश", @@ -447,18 +447,25 @@ "Notes": "टिप्पणियाँ", "Amount in words": "राशि शब्दों में", "Please pay until": "कृपया भुगतान करें", - "cs": "चेक", - "de": "जर्मन", - "en": "अंग्रेज़ी", - "es": "स्पेनिश", - "fr": "फ्रांसीसी", - "hi": "हिंदी", - "it": "इटॅलियन", - "nl": "डच", - "pl": "पोलिश", - "zh": "चीनी", - "tr": "तुर्क", - "ru": "रूसी", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "अपने सर्वर को अपग्रेड / डाउनग्रेड करने से आपका बिलिंग साइकिल अब तक रीसेट हो जाएगा। आपके ओवरपेड क्रेडिट वापस किया जाएगा। नए बिलिंग साइकिल के लिए की गई मूल्य निकाला जाएगा", + "Caution": "सावधान", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "आप अपना रेफरल कोड नहीं देख सकते", + "SERVER NAME": "सर्वर का नाम", + "STORAGE": "स्टोरेज", + "Cancel": "रद्द करें" } diff --git a/lang/hu.json b/lang/hu.json index 744fcf0c3..2479fdb5b 100644 --- a/lang/hu.json +++ b/lang/hu.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Valaki regisztrált a te Kódoddal!", "Server Creation Error": "Hiba a szerver készítése közben", "Your servers have been suspended!": "A szervered fel lett függesztve!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "A szervered\/szervereid autómatikus újraengedélyezéséhez Kreditet kell vásárolnod.", + "To automatically re-enable your server/s, you need to purchase more credits.": "A szervered/szervereid autómatikus újraengedélyezéséhez Kreditet kell vásárolnod.", "Purchase credits": "Kreditek vásárlása", "If you have any questions please let us know.": "Ha kérdésed van, kérjük fordulj hozzánk.", "Regards": "Üdvözlettel", @@ -93,7 +93,7 @@ "Getting started!": "Kezdhetjük!", "Welcome to our dashboard": "Üdvözlünk az Irányítópultban", "Verification": "Hitelesítés", - "You can verify your e-mail address and link\/verify your Discord account.": "Hitelesíteni tudod az email címedet és a Discord fiókodat.", + "You can verify your e-mail address and link/verify your Discord account.": "Hitelesíteni tudod az email címedet és a Discord fiókodat.", "Information": "Információk", "This dashboard can be used to create and delete servers": "Ebben az Irányítópultban szervereket tudsz létrehozni és törölni", "These servers can be used and managed on our pterodactyl panel": "Ezeket a szervereket a Pterodactyl panelben tudod kezelni", @@ -126,7 +126,7 @@ "Support server": "Szerver támogatása", "Documentation": "Dokumentáció", "Github": "Github", - "Support ControlPanel": "ControlPanel támogatása", + "Support CtrlPanel": "CtrlPanel támogatása", "Servers": "Szerverek", "Total": "Összesen", "Payments": "Fizetések", @@ -187,7 +187,7 @@ "Default language": "Alapértelmezett nyelv", "The fallback Language, if something goes wrong": "A tartalék nyelv, ha bármi rosszul működne", "Datable language": "Keltezhető nyelv", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Az adattáblák kódnyelve.
Például:<\/strong> en-gb, fr_fr, de_de
Több információ: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Az adattáblák kódnyelve.
Például: en-gb, fr_fr, de_de
Több információ: ", "Auto-translate": "Autómatikus fordítás", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Ha be van kapcsolva, akkor az Irányítópult autómatikusan le lesz fordítva a Kliens által használt nyelvre, ha az elérhető", "Client Language-Switch": "Kliens nyelv váltás", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Első óra kifizetése szerver létrehozásnál.", "Credits Display Name": "Kredit megnevezése", "PHPMyAdmin URL": "PHPMyAdmin Hivatkozás", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Írd be a hivatkozást a PHPMyAdmin telepítéséhez. A zárjó perjel nélkül!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Írd be a hivatkozást a PHPMyAdmin telepítéséhez. A zárjó perjel nélkül!", "Pterodactyl URL": "Pterodactyl Hivatkozás", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Írd be a hivatkozást a Pterodactyl telepítéséhez. A zárjó perjel nélkül!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Írd be a hivatkozást a Pterodactyl telepítéséhez. A zárjó perjel nélkül!", "Pterodactyl API Key": "Pterodactyl API Kulcs", "Enter the API Key to your Pterodactyl installation.": "Írd be az API Kulcsot a Pterodactyl telepítéséhez.", "Force Discord verification": "Discord hitelesítés kötelezése", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Az utalványt egy felhasználó csak egyszer használhatja fel. Ezzel meg tudod adni, hogy hány felhasználó tudja felhasználni az utalványt.", "Max": "Max", "Expires at": "Lejárás ideje", - "Used \/ Uses": "Felhasználva \/ Felhasználások száma", + "Used / Uses": "Felhasználva / Felhasználások száma", "Expires": "Lejár", "Sign in to start your session": "Jelentkezz be a munkamenet elindításához", "Password": "Jelszó", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Nem lett csomópont hozzácsatolva!", "No nests available!": "Nincs elérhető fészek!", "No eggs have been linked!": "Nem lett tojás hozzácsatolva!", - "Software \/ Games": "Szoftver \/ Játékok", + "Software / Games": "Szoftver / Játékok", "Please select software ...": "Szoftver kiválasztása ...", "---": "---", "Specification ": "Specifikációk ", @@ -447,18 +447,25 @@ "Notes": "Jegyzetek", "Amount in words": "Mennyiség szavakban", "Please pay until": "Fizetési határidő", - "cs": "Cseh", - "de": "Német", - "en": "Angol", - "es": "Spanyol", - "fr": "Francia", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "A szerver frissítése / lefrissítése visszaállítja a számlázási ciklust az aktuálisra. A túlfizetett Kreditet visszatérítjük. A számlázási ciklus új ára lesz kivonva", + "Caution": "Figyelem", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", "hi": "Hindi", - "it": "Olasz", - "nl": "Holland", - "pl": "Lengyel", - "zh": "Kínai", - "tr": "Török", - "ru": "Orosz", - "sv": "Svéd", - "sk": "Szlovák" + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Nem látod a hivatkozási kódodat", + "SERVER NAME": "SZERVERNEVE", + "STORAGE": "TÁROLÁS", + "Cancel": "Mégse" } diff --git a/lang/it.json b/lang/it.json index 5bc51c875..12f1c29f1 100644 --- a/lang/it.json +++ b/lang/it.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Errore di creazione del server", "Your servers have been suspended!": "I tuoi server sono stati sospesi!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Per ri-abilitare i tuoi server automaticamente, devi acquistare più crediti.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Per ri-abilitare i tuoi server automaticamente, devi acquistare più crediti.", "Purchase credits": "Acquista crediti", "If you have any questions please let us know.": "Se hai una domanda faccelo sapere.", "Regards": "Cordialmente", @@ -93,7 +93,7 @@ "Getting started!": "Come iniziare!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Server di supporto", "Documentation": "Documentazione", "Github": "GitHub", - "Support ControlPanel": "Supporta ControlPanel", + "Support CtrlPanel": "Supporta CtrlPanel", "Servers": "Servers", "Total": "Totale", "Payments": "Pagamenti", @@ -187,7 +187,7 @@ "Default language": "Lingua predefinita", "The fallback Language, if something goes wrong": "La lingua secondaria, se qualcosa va storto", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Il lang-code dei datatables.
Esempio:<\/strong> en-gb, fr_fr, de_de
Piu informazioni: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Il lang-code dei datatables.
Esempio: en-gb, fr_fr, de_de
Piu informazioni: ", "Auto-translate": "Traduzione-automatica", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Se questo è abilitato la dashboard si traducerà automaticamente alla lingua dei clienti, se disponibile", "Client Language-Switch": "Switch delle lingue dei clienti", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Addebita la prima ora in crediti alla creazione di un server.", "Credits Display Name": "Nome di Visualizzazione dei Crediti", "PHPMyAdmin URL": "URL PHPMyAdmin", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Inserisci l'URL alla tua installazione di PHPMyAdmin. Senza lo slash finale!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Inserisci l'URL alla tua installazione di PHPMyAdmin. Senza lo slash finale!", "Pterodactyl URL": "URL di Pterodactyl", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Inserisci l'URL alla tua installazione di Pterodactyl. Senza un trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Inserisci l'URL alla tua installazione di Pterodactyl. Senza un trailing slash!", "Pterodactyl API Key": "Chiave API di Pterodactyl", "Enter the API Key to your Pterodactyl installation.": "Inserisci la Chiave API alla tua installazione di Pterodactyl.", "Force Discord verification": "Forza la verifica di Discord", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Un voucher può essere utilizzato solo una volta per utente. Il numero di usi specifica il numero di utenti diversi che possono utilizzare questo voucher.", "Max": "Massimo", "Expires at": "Scade il", - "Used \/ Uses": "Usato \/ Utilizzi", + "Used / Uses": "Usato / Utilizzi", "Expires": "Scade", "Sign in to start your session": "Accedi per iniziare la sessione", "Password": "Password", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Nessun nodo è stato connesso!", "No nests available!": "Nessun nido (nest) disponibile!", "No eggs have been linked!": "Nessun uovo (egg) è stato connesso!", - "Software \/ Games": "Software \/ Giochi", + "Software / Games": "Software / Giochi", "Please select software ...": "Per favore selezione il software...", "---": "---", "Specification ": "Specifiche ", @@ -447,18 +447,25 @@ "Notes": "Note", "Amount in words": "Numero in parole", "Please pay until": "Per favore paga fino", - "cs": "Ceco", - "de": "Tedesco", - "en": "Inglese", - "es": "Spagnolo", - "fr": "Francese", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "L’aggiornamento / riduzione del tuo server reimposterà il tuo ciclo di fatturazione a ora. I tuoi crediti in eccesso saranno rimborsati. Il prezzo per il nuovo ciclo di fatturazione sarà prelevato", + "Caution": "Attenzione", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", "hi": "Hindi", - "it": "Italiano", - "nl": "Olandese", - "pl": "Polacco", - "zh": "Cinese", - "tr": "Turco", - "ru": "Russo", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Non puoi vedere il tuo Codice di Riferimento", + "SERVER NAME": "NOME DEL SERVER", + "STORAGE": "ARCHIVIAZIONE", + "Cancel": "Annulla" } diff --git a/lang/nl.json b/lang/nl.json index 5e72fc395..8b1add000 100644 --- a/lang/nl.json +++ b/lang/nl.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Fout bij het maken van de server", "Your servers have been suspended!": "Uw servers zijn opgeschort!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Om uw server(s) automatisch opnieuw in te schakelen, moet u meer credits kopen.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Om uw server(s) automatisch opnieuw in te schakelen, moet u meer credits kopen.", "Purchase credits": "Credits kopen", "If you have any questions please let us know.": "Als u vragen heeft, laat het ons dan weten.", "Regards": "Met vriendelijke groet", @@ -93,7 +93,7 @@ "Getting started!": "Aan de slag!", "Welcome to our dashboard": "Welkom bij ons dashboard", "Verification": "Verificatie", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Informatie", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Ondersteuningsserver", "Documentation": "Documentatie", "Github": "Github", - "Support ControlPanel": "Ondersteuning ControlPanel", + "Support CtrlPanel": "Ondersteuning CtrlPanel", "Servers": "Servers", "Total": "Totaal", "Payments": "Betalingen", @@ -187,7 +187,7 @@ "Default language": "Standaard taal", "The fallback Language, if something goes wrong": "De terugval-taal, als er iets misgaat", "Datable language": "Dateerbare taal", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "De datatabellen lang-code.
Voorbeeld:<\/strong> nl-gb, fr_fr, de_de
Meer informatie: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "De datatabellen lang-code.
Voorbeeld: nl-gb, fr_fr, de_de
Meer informatie: ", "Auto-translate": "Automatisch vertalen", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Als dit is aangevinkt, zal het dashboard zichzelf vertalen naar de taal van de klant, indien beschikbaar", "Client Language-Switch": "Klant Taal-Switch", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Brengt het eerste uur aan credits in rekening bij het maken van een server.", "Credits Display Name": "Weergavenaam tegoed", "PHPMyAdmin URL": "PHPMyAdmin-URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Voer de URL naar uw PHPMyAdmin-installatie in. Zonder een slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Voer de URL naar uw PHPMyAdmin-installatie in. Zonder een slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Voer de URL naar uw Pterodactyl-installatie in. Zonder een slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Voer de URL naar uw Pterodactyl-installatie in. Zonder een slash!", "Pterodactyl API Key": "Pterodactyl API sleutel", "Enter the API Key to your Pterodactyl installation.": "Voer de API-sleutel in voor uw Pterodactyl-installatie.", "Force Discord verification": "Forceer Discord Verificatie", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Een voucher kan slechts één keer per gebruiker worden gebruikt. Gebruik geeft het aantal verschillende gebruikers aan dat deze voucher kan gebruiken.", "Max": "Maximum", "Expires at": "Verloopt om", - "Used \/ Uses": "Gebruikt \/ Toepassingen", + "Used / Uses": "Gebruikt / Toepassingen", "Expires": "Verloopt", "Sign in to start your session": "Login om te beginnen", "Password": "Wachtwoord", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Er zijn geen nodes gekoppeld!", "No nests available!": "Er zijn geen nesten beschikbaar!", "No eggs have been linked!": "Geen eieren gekoppeld!", - "Software \/ Games": "Software \/ Spellen", + "Software / Games": "Software / Spellen", "Please select software ...": "Selecteer software...", "---": "---", "Specification ": "Specificatie ", @@ -447,18 +447,25 @@ "Notes": "Notities", "Amount in words": "Hoeveelheid in eenheden", "Please pay until": "Gelieve te betalen tot", - "cs": "Tsjechisch", - "de": "Duits", - "en": "Engels", - "es": "Spaans", - "fr": "Frans", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgraden/downgraden van uw server zal uw facturatiecyclus resetten naar nu. Uw overbetalen krediet zal worden terugbetaald. De prijs voor de nieuwe facturatiecyclus zal worden afgeschreven", + "Caution": "Let op", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", "hi": "Hindi", - "it": "Italiaans", - "nl": "Nederlands", - "pl": "Pools", - "zh": "Chinees", - "tr": "Turks", - "ru": "Russisch", - "sv": "Zweeds", - "sk": "Slovakish" + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Je kunt je Verwijzingscode niet zien", + "SERVER NAME": "SERVERNAAM", + "STORAGE": "OPSLAG", + "Cancel": "Annuleren" } diff --git a/lang/pl.json b/lang/pl.json index 14bfaee38..05e68bac1 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Błąd podczas tworzenia serwera", "Your servers have been suspended!": "Serwery zostały zawieszone!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Aby reaktywować swoje serwery, musisz kupić więcej kredytów.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Aby reaktywować swoje serwery, musisz kupić więcej kredytów.", "Purchase credits": "Zakup kredyty", "If you have any questions please let us know.": "W razie jakichkolwiek pytań prosimy o kontakt.", "Regards": "Z poważaniem", @@ -93,7 +93,7 @@ "Getting started!": "Zaczynajmy!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Serwer pomocy", "Documentation": "Dokumentacja", "Github": "Github", - "Support ControlPanel": "Wesprzyj ControlPanel", + "Support CtrlPanel": "Wesprzyj CtrlPanel", "Servers": "Serwery", "Total": "Razem", "Payments": "Płatności", @@ -187,7 +187,7 @@ "Default language": "Domyślny język", "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong", "Datable language": "Domyślny język", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Automatyczne tłumaczenie", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Nazwa Waluty", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "URL Pterodactyl Panelu", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Klucz API Pterodactyl panelu", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Kupon może zostać zrealizowany tylko raz przez użytkownika. „Użycie” określa liczbę użytkowników, którzy mogą zrealizować ten kupon.", "Max": "Max", "Expires at": "Wygasa", - "Used \/ Uses": "Użyto \/ Użyć", + "Used / Uses": "Użyto / Użyć", "Expires": "Wygasa", "Sign in to start your session": "Zaloguj się, aby rozpocząć sesję", "Password": "Hasło", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Żaden węzeł nie został połączony!", "No nests available!": "Brak dostępnych gniazd!", "No eggs have been linked!": "Jajka nie zostały połaczone!", - "Software \/ Games": "Oprogramowanie \/ gry", + "Software / Games": "Oprogramowanie / gry", "Please select software ...": "Proszę wybrać oprogramowanie...", "---": "---", "Specification ": "Specyfikacja ", @@ -447,18 +447,25 @@ "Notes": "Uwagi", "Amount in words": "Wszystkie słowa", "Please pay until": "Zapłać w ciągu:", - "cs": "Czeski", - "de": "Niemiecki", - "en": "Angielski", - "es": "Hiszpański", - "fr": "Francuski", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Aktualizacja / degradacja twojego serwera spowoduje zresetowanie cyklu rozliczeniowego do teraz. Twoje nadpłacone kredyty zostaną zwrócone. Cena za nowy cykl rozliczeniowy zostanie pobrana", + "Caution": "Uwaga", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", "hi": "Hindi", - "it": "Włoski", + "it": "Italian", "nl": "Dutch", - "pl": "Polski", - "zh": "Chiński", - "tr": "Turecki", - "ru": "Rosyjski", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Nie możesz zobaczyć swojego kodu polecającego", + "SERVER NAME": "NAZWA SERWERA", + "STORAGE": "PAMIĘĆ", + "Cancel": "Anuluj" } diff --git a/lang/pt.json b/lang/pt.json index 1ce81866a..e07ec430b 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Alguém se registrou usando seu código!", "Server Creation Error": "Erro de criação do servidor", "Your servers have been suspended!": "Os seus servidores foram suspensos!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Para reativar automaticamente o seu(s) servidor(es), é preciso comprar mais créditos.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Para reativar automaticamente o seu(s) servidor(es), é preciso comprar mais créditos.", "Purchase credits": "Compra de créditos", "If you have any questions please let us know.": "Se tiver alguma dúvida, por favor, nos avise.", "Regards": "Cumprimentos,", @@ -93,7 +93,7 @@ "Getting started!": "Começar", "Welcome to our dashboard": "Bem-vindo ao nosso painel", "Verification": "Verificação", - "You can verify your e-mail address and link\/verify your Discord account.": "Você pode verificar o seu endereço de e-mail e link", + "You can verify your e-mail address and link/verify your Discord account.": "Você pode verificar o seu endereço de e-mail e link", "Information": "Informações", "This dashboard can be used to create and delete servers": "Este painel pode ser usado para criar e excluir servidores", "These servers can be used and managed on our pterodactyl panel": "Esses servidores podem ser usados e gerenciados no nosso painel pterodactyl ", @@ -126,7 +126,7 @@ "Support server": "Servidor de suporte", "Documentation": "Documentação", "Github": "Github", - "Support ControlPanel": "Suporte para ControlPanel", + "Support CtrlPanel": "Suporte para CtrlPanel", "Servers": "Servidores", "Total": "Total", "Payments": "Pagamentos", @@ -187,7 +187,7 @@ "Default language": "Idioma padrão", "The fallback Language, if something goes wrong": "Um idioma padrão, se algo der errado", "Datable language": "Idioma de dados", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Os lang-codes disponíveis.
Exemplo:<\/strong> en-gb, fr_fr, de_de
Mais informações:", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Os lang-codes disponíveis.
Exemplo: en-gb, fr_fr, de_de
Mais informações:", "Auto-translate": "Traduzir Automaticamente", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Se isto for ativado, o Painel se traduzirá para o idioma do cliente, se disponível.", "Client Language-Switch": "Trocar Idioma do cliente", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Cobra a primeira hora de créditos ao criar um servidor.", "Credits Display Name": "Nome de exibição dos créditos", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Insira o URL do seu PHPMyAdmin. Sem barra de arrasto!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Insira o URL do seu PHPMyAdmin. Sem barra de arrasto!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Insira o URL do seu pterodactyl. Sem barra de arrasto!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Insira o URL do seu pterodactyl. Sem barra de arrasto!", "Pterodactyl API Key": "Chave API pterodactyl", "Enter the API Key to your Pterodactyl installation.": "Insira a chave API do seu painel pterodactyl.", "Force Discord verification": "Forçar verificação do Discord", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Um vale só pode ser usado uma vez por utilizador. Os usos especificam o número de diferentes utilizadores que podem usar este comprovante.", "Max": "Máximo", "Expires at": "Expira em", - "Used \/ Uses": "Usados \/ Usos", + "Used / Uses": "Usados / Usos", "Expires": "Expira", "Sign in to start your session": "Entre para iniciar a sua sessão", "Password": "Senha", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Nenhum nó foi ligado!", "No nests available!": "Não há ninhos disponíveis!", "No eggs have been linked!": "Nenhum ovo foi ligado!", - "Software \/ Games": "“Software” \/ Jogos", + "Software / Games": "“Software” / Jogos", "Please select software ...": "Por favor, selecione o “software”...", "---": "—", "Specification ": "Especificação", @@ -447,18 +447,25 @@ "Notes": "Notas", "Amount in words": "Quantia em palavras", "Please pay until": "Favor pagar até", - "cs": "Tcheco", - "de": "Alemão", - "en": "Inglês", - "es": "Espanhol", - "fr": "Francês", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Atualizar / Reduzir o seu servidor irá redefinir o seu ciclo de faturação para agora. Os seus créditos pagos a mais serão reembolsados. O preço para o novo ciclo de faturação será debitado", + "Caution": "Cuidado", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", "hi": "Hindi", - "it": "Italiano", - "nl": "Holandês", - "pl": "Polonês", - "zh": "Chinês", - "tr": "Turco", - "ru": "Russo", - "sv": "Sueco", - "sk": "Eslovaco" + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Você não pode ver o seu Código de Referência", + "SERVER NAME": "NOME DO SERVIDOR", + "STORAGE": "ARMAZENAMENTO", + "Cancel": "Cancelar" } diff --git a/lang/ro.json b/lang/ro.json index f4c9004c1..9aeb0f05b 100644 --- a/lang/ro.json +++ b/lang/ro.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Server Creation Error", "Your servers have been suspended!": "Your servers have been suspended!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "To automatically re-enable your server\/s, you need to purchase more credits.", + "To automatically re-enable your server/s, you need to purchase more credits.": "To automatically re-enable your server/s, you need to purchase more credits.", "Purchase credits": "Purchase credits", "If you have any questions please let us know.": "If you have any questions please let us know.", "Regards": "Regards", @@ -93,7 +93,7 @@ "Getting started!": "Getting started!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Support server", "Documentation": "Documentation", "Github": "Github", - "Support ControlPanel": "Support ControlPanel", + "Support CtrlPanel": "Support CtrlPanel", "Servers": "Servers", "Total": "Total", "Payments": "Payments", @@ -187,7 +187,7 @@ "Default language": "Default language", "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Auto-translate", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Max", "Expires at": "Expires at", - "Used \/ Uses": "Used \/ Uses", + "Used / Uses": "Used / Uses", "Expires": "Expires", "Sign in to start your session": "Sign in to start your session", "Password": "Password", @@ -388,7 +388,7 @@ "No nodes have been linked!": "No nodes have been linked!", "No nests available!": "No nests available!", "No eggs have been linked!": "No eggs have been linked!", - "Software \/ Games": "Software \/ Games", + "Software / Games": "Software / Games", "Please select software ...": "Please select software ...", "---": "---", "Specification ": "Specification ", @@ -447,6 +447,8 @@ "Notes": "Notes", "Amount in words": "Amount in words", "Please pay until": "Please pay until", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed", + "Caution": "Caution", "cs": "Czech", "de": "German", "en": "English", @@ -460,5 +462,10 @@ "tr": "Turkish", "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Nu poți vedea codul tău de recomandare", + "SERVER NAME": "NUMELE SERVERULUI", + "STORAGE": "STOCARE", + "Cancel": "Anulare" } diff --git a/lang/ru.json b/lang/ru.json index 68755fabd..a9bfeb9f5 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -39,7 +39,7 @@ "Store item has been removed!": "Товар в магазине был удален!", "link has been created!": "Ссылка была создана!", "link has been updated!": "Ссылка была обновлена!", - "product has been removed!": "Продукт\/Товар был удалён!", + "product has been removed!": "Продукт/Товар был удалён!", "User does not exists on pterodactyl's panel": "Пользователь не был найден в панеле птеродактиль", "user has been removed!": "Пользователь был удален!", "Notification sent!": "Оповещение отправлено!", @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Ошибка создание сервера", "Your servers have been suspended!": "Ваши сервера были заблокированы!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Чтобы автоматически повторно включить ваш сервер \/ серверы, вам необходимо приобрести больше кредитов.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Чтобы автоматически повторно включить ваш сервер / серверы, вам необходимо приобрести больше кредитов.", "Purchase credits": "Приобрести кредиты", "If you have any questions please let us know.": "Пожалуйста, сообщите нам, если у Вас есть какие-либо вопросы.", "Regards": "С уважением,", @@ -93,7 +93,7 @@ "Getting started!": "Начало работы!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Сервер поддержки", "Documentation": "Документация", "Github": "GitHub", - "Support ControlPanel": "Поддержка панели управления", + "Support CtrlPanel": "Поддержка CtrlPanel", "Servers": "Серверы", "Total": "Всего", "Payments": "Оплаты", @@ -149,7 +149,6 @@ "Will hide this option from being selected": "Скрывает эту опцию от выбора", "Price in": "Цена в", "Memory": "Оперативная память", - "Cpu": "Процессор", "Swap": "Файл подкачки", "This is what the users sees": "Вот что видят пользователи", "Disk": "Диск", @@ -164,7 +163,6 @@ "This product will only be available for these nodes": "Данный продукт будет доступен только для этих узлов", "This product will only be available for these eggs": "Этот продукт будет доступен только для этих яиц", "Product": "Продукт", - "CPU": "Процессор", "Updated at": "Обновлено", "User": "Пользователь", "Config": "Конфигурация", @@ -187,7 +185,7 @@ "Default language": "Язык по умолчанию", "The fallback Language, if something goes wrong": "Резервный язык, если что-то пойдет не так", "Datable language": "Датадатируемый язык", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Языковой код таблицы данных.
Пример:<\/strong> en-gb, fr_fr, de_de
Дополнительная информация:", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Языковой код таблицы данных.
Пример: en-gb, fr_fr, de_de
Дополнительная информация:", "Auto-translate": "Автоперевод", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Если этот флажок установлен, информационная панель будет переводиться на язык клиентов, если он доступен", "Client Language-Switch": "Переключение языка клиента", @@ -243,9 +241,9 @@ "Charges the first hour worth of credits upon creating a server.": "Взимает кредиты за первый час при создании сервера.", "Credits Display Name": "Отображаемое имя кредитов", "PHPMyAdmin URL": "URL-адрес PHPMyAdmin", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Введите URL-адрес вашей установки PHPMyAdmin. Без косой черты в конце!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Введите URL-адрес вашей установки PHPMyAdmin. Без косой черты в конце!", "Pterodactyl URL": "URL-адрес птеродактиля", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Введите URL-адрес вашей установки Pterodactyl. Без косой черты в конце!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Введите URL-адрес вашей установки Pterodactyl. Без косой черты в конце!", "Pterodactyl API Key": "API-ключ птеродактиля", "Enter the API Key to your Pterodactyl installation.": "Введите ключ API для установки Pterodactyl.", "Force Discord verification": "Требуется верификация в Discord", @@ -316,7 +314,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Промокод можно использовать только один раз для каждого пользователя. Пользователь указывает количество различных пользователей, которые могут использовать этот промокод.", "Max": "Макс.", "Expires at": "Срок действия до", - "Used \/ Uses": "Используется \/ Использует", + "Used / Uses": "Используется / Использует", "Expires": "Истекает", "Sign in to start your session": "Войдите, чтобы начать сессию", "Password": "Пароль", @@ -388,7 +386,7 @@ "No nodes have been linked!": "Ни один узел не был связан!", "No nests available!": "Гнезда в наличии нет!", "No eggs have been linked!": "Группы были связаны!", - "Software \/ Games": "Программное обеспечение \/ Игры", + "Software / Games": "Программное обеспечение / Игры", "Please select software ...": "Пожалуйста, выберите программное обеспечение...", "---": "---", "Specification ": "Характеристики ", @@ -447,6 +445,8 @@ "Notes": "Примечания", "Amount in words": "Сумма прописью", "Please pay until": "Пожалуйста, платите до", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Обновление/Уменьшение вашего сервера сбросит ваш цикл оплаты на текущий. Ваши переплаты будут возвращены. Цена за новый цикл оплаты будет списана", + "Caution": "Внимание", "cs": "Czech", "de": "German", "en": "English", @@ -458,7 +458,14 @@ "pl": "Polish", "zh": "Chinese", "tr": "Turkish", - "ru": "Русский", + "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Вы не можете видеть свой реферельный код", + "SERVER NAME": "НАЗВАНИЕ СЕРВЕРА", + "CPU": "ЦПУ", + "MEMORY": "ОЗУ", + "STORAGE": "ХРАНИЛИЩЕ", + "Cancel": "Отменить" } diff --git a/lang/sh.json b/lang/sh.json index 2755ad282..1809b0c01 100644 --- a/lang/sh.json +++ b/lang/sh.json @@ -80,7 +80,7 @@ "User ID": "User ID", "Server Creation Error": "Server Creation Error", "Your servers have been suspended!": "Your servers have been suspended!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "To automatically re-enable your server\/s, you need to purchase more credits.", + "To automatically re-enable your server/s, you need to purchase more credits.": "To automatically re-enable your server/s, you need to purchase more credits.", "Purchase credits": "Purchase credits", "If you have any questions please let us know.": "If you have any questions please let us know.", "Regards": "Regards", @@ -112,7 +112,7 @@ "Support server": "Support server", "Documentation": "Documentation", "Github": "Github", - "Support ControlPanel": "Support ControlPanel", + "Support CtrlPanel": "Support CtrlPanel", "Servers": "Servers", "Total": "Total", "Payments": "Payments", @@ -160,10 +160,10 @@ "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!": "please create a file called \"install.lock\" in your dashboard Root directory. Otherwise no settings will be loaded!", "or click here": "or click here", "Company Name": "Company Name", - "Company Address": "Company Address", + "Company Adress": "Company Adress", "Company Phonenumber": "Company Phonenumber", "VAT ID": "VAT ID", - "Company E-Mail Address": "Company E-Mail Address", + "Company E-Mail Adress": "Company E-Mail Adress", "Company Website": "Company Website", "Invoice Prefix": "Invoice Prefix", "Enable Invoices": "Enable Invoices", @@ -173,7 +173,7 @@ "Default language": "Default language", "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Auto-translate", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -185,7 +185,7 @@ "Mail Username": "Mail Username", "Mail Password": "Mail Password", "Mail Encryption": "Mail Encryption", - "Mail From Address": "Mail From Address", + "Mail From Adress": "Mail From Adress", "Mail From Name": "Mail From Name", "Discord Client-ID": "Discord Client-ID", "Discord Client-Secret": "Discord Client-Secret", @@ -214,9 +214,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -284,7 +284,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Max", "Expires at": "Expires at", - "Used \/ Uses": "Used \/ Uses", + "Used / Uses": "Used / Uses", "Expires": "Expires", "Sign in to start your session": "Sign in to start your session", "Password": "Password", @@ -354,7 +354,7 @@ "No nodes have been linked!": "No nodes have been linked!", "No nests available!": "No nests available!", "No eggs have been linked!": "No eggs have been linked!", - "Software \/ Games": "Software \/ Games", + "Software / Games": "Software / Games", "Please select software ...": "Please select software ...", "---": "---", "Specification ": "Specification ", @@ -417,7 +417,6 @@ "Value": "Value", "Edit Configuration": "Edit Configuration", "Text Field": "Text Field", - "Cancel": "Cancel", "Save": "Save", "Images and Icons may be cached, reload without cache to see your changes appear": "Images and Icons may be cached, reload without cache to see your changes appear", "Enter your companys name": "Enter your companys name", @@ -430,6 +429,8 @@ "The Language of the Datatables. Grab the Language-Codes from here": "The Language of the Datatables. Grab the Language-Codes from here", "Let the Client change the Language": "Let the Client change the Language", "Icons updated!": "Icons updated!", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed", + "Caution": "Caution", "cs": "Czech", "de": "German", "en": "English", @@ -441,5 +442,12 @@ "pl": "Polish", "zh": "Chinese", "tr": "Turkish", - "ru": "Russian" + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "You can not see your Referral Code", + "SERVER NAME": "SERVER NAME", + "STORAGE": "STORAGE", + "Cancel": "Cancel" } diff --git a/lang/sk.json b/lang/sk.json index 136d498de..99fa908e3 100644 --- a/lang/sk.json +++ b/lang/sk.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Server Creation Error", "Your servers have been suspended!": "Your servers have been suspended!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "To automatically re-enable your server\/s, you need to purchase more credits.", + "To automatically re-enable your server/s, you need to purchase more credits.": "To automatically re-enable your server/s, you need to purchase more credits.", "Purchase credits": "Purchase credits", "If you have any questions please let us know.": "If you have any questions please let us know.", "Regards": "Regards", @@ -93,7 +93,7 @@ "Getting started!": "Getting started!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Server podpory", "Documentation": "Dokumentácia", "Github": "Github", - "Support ControlPanel": "Podporiť ControlPanel", + "Support CtrlPanel": "Podporiť CtrlPanel", "Servers": "Servery", "Total": "Celkom", "Payments": "Platby", @@ -187,7 +187,7 @@ "Default language": "Default language", "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Auto-translate", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Max", "Expires at": "Expires at", - "Used \/ Uses": "Used \/ Uses", + "Used / Uses": "Used / Uses", "Expires": "Expires", "Sign in to start your session": "Sign in to start your session", "Password": "Password", @@ -388,7 +388,7 @@ "No nodes have been linked!": "No nodes have been linked!", "No nests available!": "No nests available!", "No eggs have been linked!": "No eggs have been linked!", - "Software \/ Games": "Software \/ Games", + "Software / Games": "Software / Games", "Please select software ...": "Please select software ...", "---": "---", "Specification ": "Specification ", @@ -447,6 +447,8 @@ "Notes": "Notes", "Amount in words": "Amount in words", "Please pay until": "Please pay until", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Aktualizácia alebo deaktualizácia servera resetuje Vašu fakturačnú dobu na aktuálny čas. Vaše nadbytočné kredity budú vrátené. Cena za novú fakturačnú dobu bude odobraná.", + "Caution": "Upozornenie", "cs": "Czech", "de": "German", "en": "English", @@ -460,5 +462,10 @@ "tr": "Turkish", "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Nemôžete vidieť váš Referral Code", + "SERVER NAME": "MENO SERVERA", + "STORAGE": "ÚLOŽISKO", + "Cancel": "Zrušiť" } diff --git a/lang/sr.json b/lang/sr.json index 6e23c5260..65ecd37cc 100644 --- a/lang/sr.json +++ b/lang/sr.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Greška pri kreiranju servera", "Your servers have been suspended!": "Vaši serveri su suspendovani!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Da biste automatski ponovo omogućili svoje servere, potrebno je da kupite još kredita.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Da biste automatski ponovo omogućili svoje servere, potrebno je da kupite još kredita.", "Purchase credits": "Kupite kredite", "If you have any questions please let us know.": "Ako imate bilo kakvih pitanja, molimo vas da nas obavestite.", "Regards": "Pozdravi", @@ -93,7 +93,7 @@ "Getting started!": "Početak!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Server za podršku", "Documentation": "Dokumentacija", "Github": "GitHub", - "Support ControlPanel": "Podrži ControlPanel", + "Support CtrlPanel": "Podrži CtrlPanel", "Servers": "Serveri", "Total": "Ukupno", "Payments": "Plaćanja", @@ -187,7 +187,7 @@ "Default language": "Podrazumevani jezik", "The fallback Language, if something goes wrong": "Sekundarni jezik, u slučaju da bude problema", "Datable language": "Datable language", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ", "Auto-translate": "Automatski prevod", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Korisnički izbor za jezik", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Naplaćuje kredite u vrednosti od prvog sata prilikom kreiranja servera.", "Credits Display Name": "Ime prikaza kredita", "PHPMyAdmin URL": "PHPMyAdmin Link", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Unesite URL adresu instalacije PHPMyAdmin. Bez kose crte!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Unesite URL adresu instalacije PHPMyAdmin. Bez kose crte!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Maksimalno", "Expires at": "Ističe", - "Used \/ Uses": "Upotrebljeno \/ Upotrebe", + "Used / Uses": "Upotrebljeno / Upotrebe", "Expires": "Ističe", "Sign in to start your session": "Prijavite se da biste započeli sesiju", "Password": "Lozinka", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Node-ovi nisu povezani!", "No nests available!": "Nema dostupnih gnezda!", "No eggs have been linked!": "Jaja nisu povezana!", - "Software \/ Games": "Softver \/ Igrice", + "Software / Games": "Softver / Igrice", "Please select software ...": "Molimo izaberite softver ...", "---": "---", "Specification ": "Specification ", @@ -447,6 +447,8 @@ "Notes": "Napomena", "Amount in words": "Iznos u rečima", "Please pay until": "Molimo platite do", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed", + "Caution": "Caution", "cs": "Czech", "de": "German", "en": "English", @@ -460,5 +462,10 @@ "tr": "Turkish", "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Не можете видети свој код за препоруку", + "SERVER NAME": "ИМЕ СЕРВЕРА", + "STORAGE": "СКЛАДИШТЕ", + "Cancel": "Откажи" } diff --git a/lang/sv.json b/lang/sv.json index 805887ef8..d26a47107 100644 --- a/lang/sv.json +++ b/lang/sv.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Someone registered using your Code!", "Server Creation Error": "Serverskapande fel", "Your servers have been suspended!": "Ditt konto har blivit avstängt!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "För att automatiskt återaktivera din server\/s, så måste du köpa mer krediter.", + "To automatically re-enable your server/s, you need to purchase more credits.": "För att automatiskt återaktivera din server/s, så måste du köpa mer krediter.", "Purchase credits": "Köp krediter", "If you have any questions please let us know.": "Kontakta oss gärna om du har några eventuella frågor.", "Regards": "Hälsningar", @@ -93,7 +93,7 @@ "Getting started!": "Kom igång!", "Welcome to our dashboard": "Welcome to our dashboard", "Verification": "Verification", - "You can verify your e-mail address and link\/verify your Discord account.": "You can verify your e-mail address and link\/verify your Discord account.", + "You can verify your e-mail address and link/verify your Discord account.": "You can verify your e-mail address and link/verify your Discord account.", "Information": "Information", "This dashboard can be used to create and delete servers": "This dashboard can be used to create and delete servers", "These servers can be used and managed on our pterodactyl panel": "These servers can be used and managed on our pterodactyl panel", @@ -126,7 +126,7 @@ "Support server": "Stödservern", "Documentation": "Dokumentation", "Github": "Github", - "Support ControlPanel": "Support ControlPanel", + "Support CtrlPanel": "Support CtrlPanel", "Servers": "Servers", "Total": "Total", "Payments": "Payments", @@ -187,7 +187,7 @@ "Default language": "Förvalt språk", "The fallback Language, if something goes wrong": "Reservspråket, om något går fel", "Datable language": "Daterbart språk", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Datatabellernas språkkod.
Exempel:<\/strong> en-gb, fr_fr, de_de
Mer information: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Datatabellernas språkkod.
Exempel: en-gb, fr_fr, de_de
Mer information: ", "Auto-translate": "Auto-översätt", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available", "Client Language-Switch": "Client Language-Switch", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Charges the first hour worth of credits upon creating a server.", "Credits Display Name": "Credits Display Name", "PHPMyAdmin URL": "PHPMyAdmin URL", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!", "Pterodactyl URL": "Pterodactyl URL", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Enter the URL to your Pterodactyl installation. Without a trailing slash!", "Pterodactyl API Key": "Pterodactyl API Key", "Enter the API Key to your Pterodactyl installation.": "Enter the API Key to your Pterodactyl installation.", "Force Discord verification": "Force Discord verification", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.", "Max": "Max", "Expires at": "Expires at", - "Used \/ Uses": "Used \/ Uses", + "Used / Uses": "Used / Uses", "Expires": "Expires", "Sign in to start your session": "Sign in to start your session", "Password": "Password", @@ -388,7 +388,7 @@ "No nodes have been linked!": "No nodes have been linked!", "No nests available!": "No nests available!", "No eggs have been linked!": "No eggs have been linked!", - "Software \/ Games": "Software \/ Games", + "Software / Games": "Software / Games", "Please select software ...": "Please select software ...", "---": "---", "Specification ": "Specification ", @@ -447,6 +447,8 @@ "Notes": "Notes", "Amount in words": "Amount in words", "Please pay until": "Please pay until", + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed", + "Caution": "Caution", "cs": "Czech", "de": "German", "en": "English", @@ -460,5 +462,10 @@ "tr": "Turkish", "ru": "Russian", "sv": "Swedish", - "sk": "Slovakish" + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Du kan inte se din hänvisningskod", + "SERVER NAME": "SERVERNAMN", + "STORAGE": "LAGRING", + "Cancel": "Avbryt" } diff --git a/lang/tr.json b/lang/tr.json index f712fd680..1a31d925a 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "Birileri senin kodunu kullanarak kayıt oldu!", "Server Creation Error": "Sunucu Oluşturma Hatası", "Your servers have been suspended!": "Sunucularınız askıya alındı!", - "To automatically re-enable your server\/s, you need to purchase more credits.": "Sunucularınızı\/sunucularınızı otomatik olarak yeniden etkinleştirmek için daha fazla kredi satın almanız gerekir.", + "To automatically re-enable your server/s, you need to purchase more credits.": "Sunucularınızı/sunucularınızı otomatik olarak yeniden etkinleştirmek için daha fazla kredi satın almanız gerekir.", "Purchase credits": "Satın alma kredisi", "If you have any questions please let us know.": "Herhangi bir sorunuz varsa lütfen bize bildirin.", "Regards": "Saygılarımızla", @@ -93,7 +93,7 @@ "Getting started!": "Başlarken!", "Welcome to our dashboard": "Kontrol panelimize hoş geldiniz", "Verification": "Doğrulama", - "You can verify your e-mail address and link\/verify your Discord account.": "E-posta adresinizi doğrulayabilir ve Discord hesabınızı bağlayabilir\/doğrulayabilirsiniz.", + "You can verify your e-mail address and link/verify your Discord account.": "E-posta adresinizi doğrulayabilir ve Discord hesabınızı bağlayabilir/doğrulayabilirsiniz.", "Information": "Bilgi", "This dashboard can be used to create and delete servers": "Bu gösterge panosu, sunucular oluşturmak ve silmek için kullanılabilir", "These servers can be used and managed on our pterodactyl panel": "Bu sunucular pterodactyl panelimizde kullanılabilir ve yönetilebilir", @@ -126,7 +126,7 @@ "Support server": "Destek sunucusu", "Documentation": "Dökümantasyon", "Github": "GitHub", - "Support ControlPanel": "ContrılPanel'i destekle", + "Support CtrlPanel": "CtrlPanel'i destekle", "Servers": "Sunucular", "Total": "Toplam", "Payments": "Ödemeler", @@ -187,7 +187,7 @@ "Default language": "Varsayılan Dil", "The fallback Language, if something goes wrong": "Yedek dil, eğer bir şeyler yanlış giderse", "Datable language": "Tarih Dili", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "Tarihlerde kullanılacak dil kodu.
Örnek:<\/strong> en-gb, fr_fr, de_de
Daha fazla bilgi: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "Tarihlerde kullanılacak dil kodu.
Örnek: en-gb, fr_fr, de_de
Daha fazla bilgi: ", "Auto-translate": "Otomatik çeviri", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "Eğer bu seçili ise Yönetim paneli kendisini kullanıcının diline çevirecek, eğer kullanılabiliyorsa", "Client Language-Switch": "Müşteri Dil Değiştiricisi", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "Kullanıcı sunucu oluşturduğumda ilk saatin ödemesini direkt olarak alır.", "Credits Display Name": "Kredi ismi", "PHPMyAdmin URL": "PHPMyAdmin linki", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "PHPMyAdmin kurulumunuzun linkini girin Sonda eğik çizgi olmadan<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "PHPMyAdmin kurulumunuzun linkini girin Sonda eğik çizgi olmadan", "Pterodactyl URL": "Pterodactyl Linki", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "Pterodactyl kurulumunuzun linkini girin Sonda eğik çizgi olmadan!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "Pterodactyl kurulumunuzun linkini girin Sonda eğik çizgi olmadan!", "Pterodactyl API Key": "Pterodactyl API Anahtarı", "Enter the API Key to your Pterodactyl installation.": "Pterodactyl kurulumunuzun API anahtarını girin.", "Force Discord verification": "Discord Doğrulamasını zorunlu yap", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Bir kupon, kullanıcı başına yalnızca bir kez kullanılabilir. Kullanımlar, bu kuponu kullanabilecek farklı kullanıcıların sayısını belirtir.", "Max": "Maks", "Expires at": "Sona eriyor", - "Used \/ Uses": "Kullanılmış \/ Kullanım Alanları", + "Used / Uses": "Kullanılmış / Kullanım Alanları", "Expires": "Sona eriyor", "Sign in to start your session": "Oturumunuzu başlatmak için oturum açın", "Password": "Parola", @@ -388,7 +388,7 @@ "No nodes have been linked!": "Hiçbir makine bağlanmamış!", "No nests available!": "Hiçbir nest bulunamadı!", "No eggs have been linked!": "Hiçbir egg bağlanmamış!", - "Software \/ Games": "Yazılımlar \/ Oyunlar", + "Software / Games": "Yazılımlar / Oyunlar", "Please select software ...": "Lütfen bir yazılım seçin ...", "---": "---", "Specification ": "Özellikler ", @@ -447,18 +447,25 @@ "Notes": "Notlar", "Amount in words": "Yazı ile Tutar", "Please pay until": "Lütfen şu tarihe kadar ödeyin", - "cs": "Çekçe", - "de": "Almanca", - "en": "İngilizce", - "es": "İspanyolca", - "fr": "Fransızca", - "hi": "Hintçe", - "it": "İtalyanca", - "nl": "Flemenkçe", - "pl": "Polonya", - "zh": "Çince", - "tr": "Türkçe", - "ru": "Rusça", - "sv": "İsveççe", - "sk": "Slovakça" + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "Sunucunuzu yükseltmek / düşürmek faturalandırma döngünüzü şimdiye sıfırlayacaktır. Aşırı ödenen kredileriniz iade edilecektir. Yeni faturalandırma döngüsü için ödenen tutar çekilecektir", + "Caution": "Dikkat", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "Yönlendirme Kodunuzu göremezsiniz", + "SERVER NAME": "SUNUCU ADI", + "STORAGE": "DEPOLAMA", + "Cancel": "Iptal" } diff --git a/lang/zh.json b/lang/zh.json index 0e665123e..c18dad757 100644 --- a/lang/zh.json +++ b/lang/zh.json @@ -81,7 +81,7 @@ "Someone registered using your Code!": "已经有人使用您的代码注册了", "Server Creation Error": "服务器创建错误", "Your servers have been suspended!": "您的服务器已被暂停", - "To automatically re-enable your server\/s, you need to purchase more credits.": "如需重新启用你的服务器,您需要购买更多的余额", + "To automatically re-enable your server/s, you need to purchase more credits.": "如需重新启用你的服务器,您需要购买更多的余额", "Purchase credits": "购买余额", "If you have any questions please let us know.": "如果您有其他任何问题,欢迎联系我们。", "Regards": "此致", @@ -93,7 +93,7 @@ "Getting started!": "开始吧!", "Welcome to our dashboard": "欢迎访问 dashboard", "Verification": "验证", - "You can verify your e-mail address and link\/verify your Discord account.": "你可以验证你的邮箱地址或者连接到你的Discord账户", + "You can verify your e-mail address and link/verify your Discord account.": "你可以验证你的邮箱地址或者连接到你的Discord账户", "Information": "相关信息", "This dashboard can be used to create and delete servers": "此仪表板可用于创建和删除服务器", "These servers can be used and managed on our pterodactyl panel": "这些服务器可以在我们的pterodactyl面板上使用和管理", @@ -126,7 +126,7 @@ "Support server": "支持服务器", "Documentation": "文档", "Github": "Github", - "Support ControlPanel": "支持我们", + "Support CtrlPanel": "支持我们", "Servers": "服务器", "Total": "总数", "Payments": "支付费用", @@ -187,7 +187,7 @@ "Default language": "默认语言", "The fallback Language, if something goes wrong": "备用语言", "Datable language": "可用语言", - "The datatables lang-code.
Example:<\/strong> en-gb, fr_fr, de_de
More Information: ": "数据表语言代码
示例:<\/strong> en-gb、fr_fr、de_de
更多信息: ", + "The datatables lang-code.
Example: en-gb, fr_fr, de_de
More Information: ": "数据表语言代码
示例: en-gb、fr_fr、de_de
更多信息: ", "Auto-translate": "自动翻译", "If this is checked, the Dashboard will translate itself to the Clients language, if available": "如果勾选此项,系统将把自己翻译成客户语言(如果有)", "Client Language-Switch": "客户语言切换", @@ -243,9 +243,9 @@ "Charges the first hour worth of credits upon creating a server.": "在创建服务器时收取第一个小时的费用", "Credits Display Name": "积分显示名称", "PHPMyAdmin URL": "PHPMyAdmin地址", - "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!<\/strong>": "输入你PHPMyAdmin的URL。不要有尾部斜线!<\/strong>", + "Enter the URL to your PHPMyAdmin installation. Without a trailing slash!": "输入你PHPMyAdmin的URL。不要有尾部斜线!", "Pterodactyl URL": "Pterodactyl地址", - "Enter the URL to your Pterodactyl installation. Without a trailing slash!<\/strong>": "输入你Pterodactyl的URL。不要有尾部斜线!<\/strong>", + "Enter the URL to your Pterodactyl installation. Without a trailing slash!": "输入你Pterodactyl的URL。不要有尾部斜线!", "Pterodactyl API Key": "Pterodactyl API密钥", "Enter the API Key to your Pterodactyl installation.": "输入Pterodactyl API密钥", "Force Discord verification": "强制Discord验证", @@ -316,7 +316,7 @@ "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "每个用户只能使用一次代金券。使用次数指定了可以使用此代金券的不同用户的数量。", "Max": "最大", "Expires at": "过期时间", - "Used \/ Uses": "已使用\/使用情况", + "Used / Uses": "已使用/使用情况", "Expires": "过期", "Sign in to start your session": "登录以开始您的会议", "Password": "密码", @@ -388,7 +388,7 @@ "No nodes have been linked!": "没有节点被链接!", "No nests available!": "没有可用的巢穴!", "No eggs have been linked!": "没有蛋被链接!", - "Software \/ Games": "软件\/游戏", + "Software / Games": "软件/游戏", "Please select software ...": "请选择软件...", "---": "---", "Specification ": "规格 ", @@ -447,18 +447,25 @@ "Notes": "笔记", "Amount in words": "税额的字数", "Please pay until": "请支付至", - "cs": "捷克语", - "de": "德语", - "en": "英语", - "es": "西班牙语", - "fr": "法语", - "hi": "印度语", - "it": "意大利语", - "nl": "荷兰语", - "pl": "波兰语", - "zh": "中文(简体)", - "tr": "土耳其语", - "ru": "俄语", - "sv": "乌克兰语", - "sk": "斯洛伐克语" + "Upgrading/Downgrading your server will reset your billing cycle to now. Your overpayed Credits will be refunded. The price for the new billing cycle will be withdrawed": "升级/降级你的服务器将重置你的账单周期。你的多余的点数将被退还。新的账单周期的价格将被扣除", + "Caution": "警告", + "cs": "Czech", + "de": "German", + "en": "English", + "es": "Spanish", + "fr": "French", + "hi": "Hindi", + "it": "Italian", + "nl": "Dutch", + "pl": "Polish", + "zh": "Chinese", + "tr": "Turkish", + "ru": "Russian", + "sv": "Swedish", + "sk": "Slovakish", + "hu": "Hungarian", + "You can not see your Referral Code": "您无法查看您的推荐码", + "SERVER NAME": "服务器名称", + "STORAGE": "存储", + "Cancel": "取消" } diff --git a/package-lock.json b/package-lock.json index 98052340c..95a8ff2b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "dashboard", + "name": "CtrlPanel", "lockfileVersion": 2, "requires": true, "packages": { @@ -416,9 +416,9 @@ } }, "node_modules/@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", + "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", "dev": true, "peer": true, "dependencies": { @@ -822,9 +822,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { @@ -838,10 +838,10 @@ ], "peer": true, "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -867,9 +867,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001449", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz", - "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", + "version": "1.0.30001450", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", + "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", "dev": true, "funding": [ { @@ -1027,9 +1027,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.285", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.285.tgz", + "integrity": "sha512-47o4PPgxfU1KMNejz+Dgaodf7YTcg48uOfV1oM6cs3adrl2+7R+dHkt3Jpxqo0LRCbGJEzTKMUt0RdvByb/leg==", "dev": true, "peer": true }, @@ -1336,9 +1336,9 @@ } }, "node_modules/immutable": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", - "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.3.tgz", + "integrity": "sha512-IHpmvaOIX4VLJwPOuQr1NpeBr2ZG6vpIj3blsLVxXRWJscLioaJRStqC+NcBsLeCDsnGlPpXd5/WZmnE7MbsKA==", "devOptional": true }, "node_modules/inherits": { @@ -1575,9 +1575,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", + "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==", "dev": true, "peer": true }, @@ -1788,9 +1788,9 @@ "dev": true }, "node_modules/rollup": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.12.0.tgz", - "integrity": "sha512-4MZ8kA2HNYahIjz63rzrMMRvDqQDeS9LoriJvMuV0V6zIGysP36e9t4yObUfwdT9h/szXoHQideICftcdZklWg==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.13.0.tgz", + "integrity": "sha512-HJwQtrXAc0AmyDohTJ/2c+Bx/sWPScJLlAUJ1kuD7rAkCro8Cr2SnVB2gVYBiSLxpgD2kZ24jbyXtG++GumrYQ==", "bin": { "rollup": "dist/bin/rollup" }, @@ -1809,9 +1809,9 @@ "dev": true }, "node_modules/sass": { - "version": "1.57.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", - "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", + "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", "devOptional": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -2018,9 +2018,9 @@ } }, "node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", "devOptional": true, "peer": true, "dependencies": { @@ -2138,14 +2138,14 @@ "dev": true }, "node_modules/vite": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz", - "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.1.tgz", + "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==", "dependencies": { - "esbuild": "^0.16.3", - "postcss": "^8.4.20", + "esbuild": "^0.16.14", + "postcss": "^8.4.21", "resolve": "^1.22.1", - "rollup": "^3.7.0" + "rollup": "^3.10.0" }, "bin": { "vite": "bin/vite.js" @@ -2465,9 +2465,9 @@ } }, "@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", + "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", "dev": true, "peer": true, "requires": { @@ -2813,16 +2813,16 @@ } }, "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "peer": true, "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" } }, "buffer-from": { @@ -2839,9 +2839,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001449", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz", - "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==", + "version": "1.0.30001450", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", + "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", "dev": true, "peer": true }, @@ -2965,9 +2965,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.285", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.285.tgz", + "integrity": "sha512-47o4PPgxfU1KMNejz+Dgaodf7YTcg48uOfV1oM6cs3adrl2+7R+dHkt3Jpxqo0LRCbGJEzTKMUt0RdvByb/leg==", "dev": true, "peer": true }, @@ -3207,9 +3207,9 @@ "peer": true }, "immutable": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.2.tgz", - "integrity": "sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.3.tgz", + "integrity": "sha512-IHpmvaOIX4VLJwPOuQr1NpeBr2ZG6vpIj3blsLVxXRWJscLioaJRStqC+NcBsLeCDsnGlPpXd5/WZmnE7MbsKA==", "devOptional": true }, "inherits": { @@ -3392,9 +3392,9 @@ "dev": true }, "node-releases": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", - "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.9.tgz", + "integrity": "sha512-2xfmOrRkGogbTK9R6Leda0DGiXeY3p2NJpy4+gNCffdUvV6mdEJnaDEic1i3Ec2djAo8jWYoJMR5PB0MSMpxUA==", "dev": true, "peer": true }, @@ -3553,9 +3553,9 @@ "dev": true }, "rollup": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.12.0.tgz", - "integrity": "sha512-4MZ8kA2HNYahIjz63rzrMMRvDqQDeS9LoriJvMuV0V6zIGysP36e9t4yObUfwdT9h/szXoHQideICftcdZklWg==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.13.0.tgz", + "integrity": "sha512-HJwQtrXAc0AmyDohTJ/2c+Bx/sWPScJLlAUJ1kuD7rAkCro8Cr2SnVB2gVYBiSLxpgD2kZ24jbyXtG++GumrYQ==", "requires": { "fsevents": "~2.3.2" } @@ -3567,9 +3567,9 @@ "dev": true }, "sass": { - "version": "1.57.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.57.1.tgz", - "integrity": "sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==", + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", + "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", "devOptional": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", @@ -3703,9 +3703,9 @@ "peer": true }, "terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", "devOptional": true, "peer": true, "requires": { @@ -3776,15 +3776,15 @@ "dev": true }, "vite": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz", - "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.1.tgz", + "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==", "requires": { - "esbuild": "^0.16.3", + "esbuild": "^0.16.14", "fsevents": "~2.3.2", - "postcss": "^8.4.20", + "postcss": "^8.4.21", "resolve": "^1.22.1", - "rollup": "^3.7.0" + "rollup": "^3.10.0" } }, "vite-plugin-full-reload": { diff --git a/phpunit.xml b/phpunit.xml index fc15f97bc..1c2c01844 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,7 +22,7 @@ - + diff --git a/public/images/Extensions/PaymentGateways/mercadopago_logo.png b/public/images/Extensions/PaymentGateways/mercadopago_logo.png new file mode 100644 index 000000000..9c896983a Binary files /dev/null and b/public/images/Extensions/PaymentGateways/mercadopago_logo.png differ diff --git a/public/images/controlpanel.png b/public/images/controlpanel.png deleted file mode 100644 index 63a4d3bf2..000000000 Binary files a/public/images/controlpanel.png and /dev/null differ diff --git a/public/images/controlpanel_logo.png b/public/images/ctrlpanel_logo.png similarity index 100% rename from public/images/controlpanel_logo.png rename to public/images/ctrlpanel_logo.png diff --git a/public/install/forms.php b/public/install/forms.php deleted file mode 100644 index 980ee3ceb..000000000 --- a/public/install/forms.php +++ /dev/null @@ -1,278 +0,0 @@ -load(); - -include 'functions.php'; - -if (isset($_POST['checkDB'])) { - $values = [ - //SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form) - 'DB_HOST' => 'databasehost', - 'DB_DATABASE' => 'database', - 'DB_USERNAME' => 'databaseuser', - 'DB_PASSWORD' => 'databaseuserpass', - 'DB_PORT' => 'databaseport', - 'DB_CONNECTION' => 'databasedriver', - ]; - - $db = new mysqli($_POST['databasehost'], $_POST['databaseuser'], $_POST['databaseuserpass'], $_POST['database'], $_POST['databaseport']); - if ($db->connect_error) { - wh_log($db->connect_error); - header('LOCATION: index.php?step=2&message=Could not connect to the Database'); - exit(); - } - - foreach ($values as $key => $value) { - $param = $_POST[$value]; - // if ($key == "DB_PASSWORD") { - // $param = '"' . $_POST[$value] . '"'; - // } - setEnvironmentValue($key, $param); - } - - header('LOCATION: index.php?step=2.5'); -} - -if (isset($_POST['checkGeneral'])) { - $appname = '"'.$_POST['name'].'"'; - $appurl = $_POST['url']; - - if (substr($appurl, -1) === '/') { - $appurl = substr_replace($appurl, '', -1); - } - - setEnvironmentValue('APP_NAME', $appname); - setEnvironmentValue('APP_URL', $appurl); - - header('LOCATION: index.php?step=4'); -} - -if (isset($_POST['feedDB'])) { - $logs = ''; - - //$logs .= run_console(putenv('COMPOSER_HOME=' . dirname(__FILE__, 3) . '/vendor/bin/composer')); - //$logs .= run_console('composer install --no-dev --optimize-autoloader'); - $logs .= run_console('php artisan migrate --seed --force'); - $logs .= run_console('php artisan db:seed --class=ExampleItemsSeeder --force'); - if (strpos(getEnvironmentValue('APP_KEY'), 'base64') === false) { - $logs .= run_console('php artisan key:generate --force'); - } else { - $logs .= "Key already exists. Skipping\n"; - } - $logs .= run_console('php artisan storage:link'); - - wh_log($logs); - - if (strpos(getEnvironmentValue('APP_KEY'), 'base64') !== false) { - header('LOCATION: index.php?step=3'); - } else { - header('LOCATION: index.php?step=2.5&message=There was an error. Please check the .txt file in /var/www/controlpanel/public/install/logs !'); - } -} - -if (isset($_POST['checkSMTP'])) { - try { - $mail = new PHPMailer(true); - - //Server settings - $mail->isSMTP(); // Send using SMTP - $mail->Host = $_POST['host']; // Set the SMTP server to send through - $mail->SMTPAuth = true; // Enable SMTP authentication - $mail->Username = $_POST['user']; // SMTP username - $mail->Password = $_POST['pass']; // SMTP password - $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged - $mail->Port = $_POST['port']; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` - - //Recipients - $mail->setFrom($_POST['user'], $_POST['user']); - $mail->addAddress($_POST['user'], $_POST['user']); // Add a recipient - - // Content - $mail->isHTML(true); // Set email format to HTML - $mail->Subject = 'It Worked!'; - $mail->Body = 'Your E-Mail Settings are correct!'; - - $mail->send(); - } catch (Exception $e) { - header('LOCATION: index.php?step=4&message=Something wasnt right when sending the E-Mail!'); - exit(); - } - - $db = new mysqli(getEnvironmentValue('DB_HOST'), getEnvironmentValue('DB_USERNAME'), getEnvironmentValue('DB_PASSWORD'), getEnvironmentValue('DB_DATABASE'), getEnvironmentValue('DB_PORT')); - if ($db->connect_error) { - wh_log($db->connect_error); - header('LOCATION: index.php?step=4&message=Could not connect to the Database: '); - exit(); - } - $values = [ - 'SETTINGS::MAIL:MAILER' => $_POST['method'], - 'SETTINGS::MAIL:HOST' => $_POST['host'], - 'SETTINGS::MAIL:PORT' => $_POST['port'], - 'SETTINGS::MAIL:USERNAME' => $_POST['user'], - 'SETTINGS::MAIL:PASSWORD' => $_POST['pass'], - 'SETTINGS::MAIL:ENCRYPTION' => $_POST['encryption'], - 'SETTINGS::MAIL:FROM_ADDRESS' => $_POST['user'], - ]; - - foreach ($values as $key => $value) { - $query = 'UPDATE `'.getEnvironmentValue('DB_DATABASE')."`.`settings` SET `value` = '$value' WHERE (`key` = '$key')"; - $db->query($query); - } - - header('LOCATION: index.php?step=5'); -} - -if (isset($_POST['checkPtero'])) { - $url = $_POST['url']; - $key = $_POST['key']; - $clientkey = $_POST['clientkey']; - - if (substr($url, -1) === '/') { - $url = substr_replace($url, '', -1); - } - - $callpteroURL = $url.'/api/client/account'; - $call = curl_init(); - - curl_setopt($call, CURLOPT_URL, $callpteroURL); - curl_setopt($call, CURLOPT_RETURNTRANSFER, true); - curl_setopt($call, CURLOPT_HTTPHEADER, [ - 'Accept: application/json', - 'Content-Type: application/json', - 'Authorization: Bearer '.$clientkey, - ]); - $callresponse = curl_exec($call); - $callresult = json_decode($callresponse, true); - curl_close($call); // Close the connection - - $pteroURL = $url.'/api/application/users'; - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $pteroURL); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Accept: application/json', - 'Content-Type: application/json', - 'Authorization: Bearer '.$key, - ]); - $response = curl_exec($ch); - $result = json_decode($response, true); - curl_close($ch); // Close the connection - - if (! is_array($result) or in_array($result['errors'][0]['code'], $result)) { - header('LOCATION: index.php?step=5&message=Couldnt connect to Pterodactyl. Make sure your API key has all read and write permissions!'); - wh_log('API CALL ERROR: '.$result['errors'][0]['code']); - exit(); - } elseif (! is_array($callresult) or in_array($result['errors'][0]['code'], $result) or $callresult['attributes']['admin'] == false) { - header('LOCATION: index.php?step=5&message=Your ClientAPI Key is wrong or the account is not an admin!'); - wh_log('API CALL ERROR: '.$result['errors'][0]['code']); - exit(); - } else { - $query1 = 'UPDATE `'.getEnvironmentValue('DB_DATABASE')."`.`settings` SET `value` = '$url' WHERE (`key` = 'SETTINGS::SYSTEM:PTERODACTYL:URL')"; - $query2 = 'UPDATE `'.getEnvironmentValue('DB_DATABASE')."`.`settings` SET `value` = '$key' WHERE (`key` = 'SETTINGS::SYSTEM:PTERODACTYL:TOKEN')"; - $query3 = 'UPDATE `'.getEnvironmentValue('DB_DATABASE')."`.`settings` SET `value` = '$clientkey' WHERE (`key` = 'SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN')"; - - $db = new mysqli(getEnvironmentValue('DB_HOST'), getEnvironmentValue('DB_USERNAME'), getEnvironmentValue('DB_PASSWORD'), getEnvironmentValue('DB_DATABASE'), getEnvironmentValue('DB_PORT')); - if ($db->connect_error) { - wh_log($db->connect_error); - header('LOCATION: index.php?step=5&message=Could not connect to the Database'); - exit(); - } - - if ($db->query($query1) && $db->query($query2) && $db->query($query3)) { - header('LOCATION: index.php?step=6'); - } else { - wh_log($db->error); - header('LOCATION: index.php?step=5&message=Something went wrong when communicating with the Database!'); - } - } -} - -if (isset($_POST['createUser'])) { - $db = new mysqli(getEnvironmentValue('DB_HOST'), getEnvironmentValue('DB_USERNAME'), getEnvironmentValue('DB_PASSWORD'), getEnvironmentValue('DB_DATABASE'), getEnvironmentValue('DB_PORT')); - if ($db->connect_error) { - wh_log($db->connect_error); - header('LOCATION: index.php?step=6&message=Could not connect to the Database'); - exit(); - } - - $pteroID = $_POST['pteroID']; - $pass = $_POST['pass']; - $repass = $_POST['repass']; - - $key = $db->query('SELECT `value` FROM `'.getEnvironmentValue('DB_DATABASE')."`.`settings` WHERE `key` = 'SETTINGS::SYSTEM:PTERODACTYL:TOKEN'")->fetch_assoc(); - $pterobaseurl = $db->query('SELECT `value` FROM `'.getEnvironmentValue('DB_DATABASE')."`.`settings` WHERE `key` = 'SETTINGS::SYSTEM:PTERODACTYL:URL'")->fetch_assoc(); - - $pteroURL = $pterobaseurl['value'].'/api/application/users/'.$pteroID; - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $pteroURL); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Accept: application/json', - 'Content-Type: application/json', - 'Authorization: Bearer '.$key['value'], - ]); - $response = curl_exec($ch); - $result = json_decode($response, true); - curl_close($ch); // Close the connection - - if (! $result['attributes']['email']) { - header('LOCATION: index.php?step=6&message=Could not find the user with pterodactyl ID '.$pteroID); - exit(); - } - if ($pass !== $repass) { - header('LOCATION: index.php?step=6&message=The Passwords did not match!'); - exit(); - } - - $mail = $result['attributes']['email']; - $name = $result['attributes']['username']; - $pass = password_hash($pass, PASSWORD_DEFAULT); - - $pteroURL = $pterobaseurl['value'].'/api/application/users/'.$pteroID; - $ch = curl_init(); - - curl_setopt($ch, CURLOPT_URL, $pteroURL); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_HTTPHEADER, [ - 'Accept: application/json', - 'Content-Type: application/json', - 'Authorization: Bearer '.$key['value'], - ]); - curl_setopt($ch, CURLOPT_POSTFIELDS, [ - 'email' => $mail, - 'username' => $name, - 'first_name' => $name, - 'last_name' => $name, - 'password' => $pass, - ]); - $response = curl_exec($ch); - $result = json_decode($response, true); - curl_close($ch); // Close the connection - - if (! is_array($result) or in_array($result['errors'][0]['code'], $result)) { - header('LOCATION: index.php?step=5&message=Couldnt connect to Pterodactyl. Make sure your API key has all read and write permissions!'); - exit(); - } - - $random = generateRandomString(); - $query1 = 'INSERT INTO `'.getEnvironmentValue('DB_DATABASE')."`.`users` (`name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `email`, `password`, `created_at`, `referral_code`) VALUES ('$name', 'admin', '250', '1', '$pteroID', '$mail', '$pass', CURRENT_TIMESTAMP, '$random')"; - - if ($db->query($query1)) { - wh_log('[USER MAKER] Created user with Email '.$mail.' and pterodactyl ID '.$pteroID); - header('LOCATION: index.php?step=7'); - } else { - wh_log($db->error); - header('LOCATION: index.php?step=6&message=Something went wrong when communicating with the Database'); - } -} diff --git a/public/install/functions.php b/public/install/functions.php deleted file mode 100644 index ed983c57c..000000000 --- a/public/install/functions.php +++ /dev/null @@ -1,149 +0,0 @@ - '8.1', - 'maxPhp' => '8.2', // This version is not supported - 'mysql' => '5.7.22', -]; - -function checkPhpVersion() -{ - global $requirements; - if (version_compare(phpversion(), $requirements['minPhp'], '>=') && version_compare(phpversion(), $requirements['maxPhp'], '<=')) { - return 'OK'; - } - - return 'not OK'; -} -function checkWriteable() -{ - return is_writable('../../.env'); -} -function checkHTTPS() -{ - return (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') - || $_SERVER['SERVER_PORT'] == 443; -} - -function getMySQLVersion() -{ - global $requirements; - - $output = shell_exec('mysql -V'); - preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); - - $versionoutput = $version[0] ?? '0'; - - return intval($versionoutput) > intval($requirements['mysql']) ? 'OK' : $versionoutput; -} - -function getZipVersion() -{ - $output = shell_exec('zip -v'); - preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); - - $versionoutput = $version[0] ?? 0; - - return $versionoutput != 0 ? 'OK' : 'not OK'; -} - -function getGitVersion() -{ - $output = shell_exec('git --version'); - preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); - - $versionoutput = $version[0] ?? 0; - - return $versionoutput != 0 ? 'OK' : 'not OK'; -} - -function getTarVersion() -{ - $output = shell_exec('tar --version'); - preg_match('@[0-9]+\.[0-9]+@', $output, $version); - - $versionoutput = $version[0] ?? 0; - - return $versionoutput != 0 ? 'OK' : 'not OK'; -} - -function checkExtensions() -{ - global $required_extentions; - - $not_ok = []; - $extentions = get_loaded_extensions(); - - foreach ($required_extentions as $ext) { - if (! preg_grep('/^(?=.*'.$ext.').*$/', $extentions)) { - array_push($not_ok, $ext); - } - } - - return $not_ok; -} - -function setEnvironmentValue($envKey, $envValue) -{ - $envFile = dirname(__FILE__, 3).'/.env'; - $str = file_get_contents($envFile); - - $str .= "\n"; // In case the searched variable is in the last line without \n - $keyPosition = strpos($str, "{$envKey}="); - $endOfLinePosition = strpos($str, PHP_EOL, $keyPosition); - $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition); - $str = str_replace($oldLine, "{$envKey}={$envValue}", $str); - $str = substr($str, 0, -1); - - $fp = fopen($envFile, 'w'); - fwrite($fp, $str); - fclose($fp); -} - -function getEnvironmentValue($envKey) -{ - $envFile = dirname(__FILE__, 3).'/.env'; - $str = file_get_contents($envFile); - - $str .= "\n"; // In case the searched variable is in the last line without \n - $keyPosition = strpos($str, "{$envKey}="); - $endOfLinePosition = strpos($str, PHP_EOL, $keyPosition); - $oldLine = substr($str, $keyPosition, $endOfLinePosition - $keyPosition); - $value = substr($oldLine, strpos($oldLine, '=') + 1); - - return $value; -} - -function run_console($command) -{ - $path = dirname(__FILE__, 3); - $cmd = "cd '$path' && bash -c 'exec -a ServerCPP $command' 2>&1"; - - return shell_exec($cmd); -} - -function wh_log($log_msg) -{ - $log_filename = 'logs'; - if (! file_exists($log_filename)) { - // create directory/folder uploads. - mkdir($log_filename, 0777, true); - } - $log_file_data = $log_filename.'/installer.log'; - // if you don't add `FILE_APPEND`, the file will be erased each time you add a log - file_put_contents($log_file_data, '['.date('h:i:s').'] '.$log_msg."\n", FILE_APPEND); -} - -function generateRandomString($length = 8) -{ - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[rand(0, $charactersLength - 1)]; - } - - return $randomString; -} diff --git a/public/install/index.php b/public/install/index.php deleted file mode 100644 index cb4ef943d..000000000 --- a/public/install/index.php +++ /dev/null @@ -1,455 +0,0 @@ - - - - - Ctrlpanel.gg installer Script - - - - - - -
- Ctrlpanel.GG -
-
'; - -if (! isset($_GET['step'])) { - if (! file_exists('../../.env')) { - echo run_console('cp .env.example .env'); - } - echo $cardheader; ?> - -

HTTPS is required

- -

Write-permissions on .env-file

- -

php - version: (minimum required )

- -

mysql - version: (minimum required )

- -

Missing - php-extentions:

- - - - -

Git - version:

- -

Tar - version:

- - - - - -
- - - - -".$_GET['message'].'

'; - } ?> - -
- -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
- -
-
- - -
-
- -
- - -
-
- - - - - - - -

This process might take a while. Please do not refresh or close this page!

- ".$_GET['message'].'

'; - } ?> - -
- - - - - - - - - - - - - ".$_GET['message'].'

'; - } ?> - - - - -
-
-
-
- - -
-
-
-
- - -
-
- -
- - -
-
- - - - - - - - - - ".$_GET['message'].'

'; - } ?> - -
- - -
-
-
-
- - - -
-
-
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- - -
-
- - -
-
- -
-
- - -
-
- -
- - - - -
- - - - - - - - - - - - ".$_GET['message'].'

'; - } ?> - -
- - -
-
-
-
- - - -
-
-
-
- - -
-
-
-
- - -
-
- - -
- - -
-
- - - - - - - - - ".$_GET['message'].'

'; - } ?> - -
- -
-
- - -
-
- -
-
- - -
-
-
-
- - -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - diff --git a/public/install/dotenv.php b/public/installer/dotenv.php similarity index 100% rename from public/install/dotenv.php rename to public/installer/dotenv.php diff --git a/public/installer/index.php b/public/installer/index.php new file mode 100644 index 000000000..600a3297e --- /dev/null +++ b/public/installer/index.php @@ -0,0 +1,103 @@ +load(); + +$stepConfig = [ + 1 => ['view' => 'mandatory-checks', 'is_revertable' => false], + 2 => ['view' => 'timezone-configuration', 'is_revertable' => true], + 3 => ['view' => 'database-configuration', 'is_revertable' => true], + 4 => ['view' => 'database-migration', 'is_revertable' => false], + 5 => ['view' => 'redis-configuration', 'is_revertable' => true], + 6 => ['view' => 'dashboard-configuration', 'is_revertable' => true], + 7 => ['view' => 'email-configuration', 'is_revertable' => true], + 8 => ['view' => 'pterodactyl-configuration', 'is_revertable' => false], + 9 => ['view' => 'admin-creation', 'is_revertable' => false], + 10 => ['view' => 'installation-complete', 'is_revertable' => false], +]; + +$_SESSION['last_installation_step'] = count($stepConfig); + +// Initialize or get the current step: +if (!isset($_SESSION['current_installation_step'])) { + // Session variable is not set, initialize it in the SESSION + $_SESSION['current_installation_step'] = 1; +} + +if (isset($_GET['step'])) { + $stepValue = $_GET['step']; + $currentStep = $_SESSION['current_installation_step']; + + if (strtolower($stepValue) === 'next' && $currentStep < $_SESSION['last_installation_step']) { + $_SESSION['current_installation_step']++; + // Redirect to clean URL after processing + header('Location: index.php'); + exit; + } + elseif (strtolower($stepValue) === 'previous' && $currentStep > 1) { + if ($stepConfig[$currentStep - 1]['is_revertable']) { + $_SESSION['current_installation_step']--; + header('Location: index.php'); + exit; + } + } + elseif (is_numeric($stepValue)) { + // Only allow accessing previous or current steps + if ($stepValue <= $currentStep && $stepValue >= 1 && $stepValue <= $_SESSION['last_installation_step']) { + $_SESSION['current_installation_step'] = $stepValue; + } + header('Location: index.php'); + exit; + } +} + +$viewName = $stepConfig[$_SESSION['current_installation_step']]['view']; + +// Set previous button availability based on step reversibility +$_SESSION['is_previous_button_available'] = $_SESSION['current_installation_step'] > 1 && $stepConfig[$_SESSION['current_installation_step'] - 1]['is_revertable']; + +// Load the layout and the specific view file +include './views/layout-top.php'; +include "./views/{$viewName}.php"; +include './views/layout-bottom.php'; + +// setting / reseting the error message +$_SESSION['error-message'] = null; + +?> \ No newline at end of file diff --git a/public/installer/src/forms/admin.php b/public/installer/src/forms/admin.php new file mode 100644 index 000000000..5626e5dc3 --- /dev/null +++ b/public/installer/src/forms/admin.php @@ -0,0 +1,101 @@ +load(); + +if (isset($_POST['createUser'])) { + wh_log('Getting Pterodactyl User', 'debug'); + + try { + $db = new mysqli(getenv('DB_HOST'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'), getenv('DB_PORT')); + } catch (Throwable $th) { + wh_log($th->getMessage(), 'error'); + send_error_message("Could not connect to the Database"); + exit(); + } + + $pteroID = $_POST['pteroID']; + $pass = $_POST['pass']; + $repass = $_POST['repass']; + + try { + $panelUrl = run_console("php artisan settings:get 'PterodactylSettings' 'panel_url' --sameline"); + $adminToken = run_console("php artisan settings:get 'PterodactylSettings' 'admin_token' --sameline"); + } catch (Throwable $th) { + wh_log("Getting Pterodactyl information failed.", 'error'); + send_error_message($th->getMessage() . "
Please check the installer.log file in /var/www/controlpanel/storage/logs!"); + exit(); + } + + $panelApiUrl = $panelUrl . '/api/application/users/' . $pteroID; + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $panelApiUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Accept: application/json', + 'Content-Type: application/json', + 'Authorization: Bearer ' . $adminToken, + ]); + $response = curl_exec($ch); + $result = json_decode($response, true); + curl_close($ch); + + if ($pass !== $repass) { + send_error_message("The Passwords did not match!"); + exit(); + } + + if (array_key_exists('errors', $result)) { + send_error_message("Could not find the user with pterodactyl ID" . $pteroID); + exit(); + } + + $mail = $result['attributes']['email']; + $name = $result['attributes']['username']; + $pass = password_hash($pass, PASSWORD_DEFAULT); + + $ch = curl_init(); + + curl_setopt($ch, CURLOPT_URL, $panelApiUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Accept: application/json', + 'Content-Type: application/json', + 'Authorization: Bearer ' . $adminToken, + ]); + curl_setopt($ch, CURLOPT_POSTFIELDS, [ + 'email' => $mail, + 'username' => $name, + 'first_name' => $name, + 'last_name' => $name, + 'password' => $pass, + ]); + $response = curl_exec($ch); + $result = json_decode($response, true); + curl_close($ch); + + $random = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 8); // random referal + + $query1 = 'INSERT INTO `' . getenv('DB_DATABASE') . "`.`users` (`name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `email`, `password`, `created_at`, `referral_code`) VALUES ('$name', 'admin', '250', '1', '$pteroID', '$mail', '$pass', CURRENT_TIMESTAMP, '$random')"; + $query2 = "INSERT INTO `" . getenv('DB_DATABASE') . "`.`model_has_roles` (`role_id`, `model_type`, `model_id`) VALUES ('1', 'App\\\Models\\\User', '1')"; + try { + $db->query($query1); + $db->query($query2); + + wh_log('Created user with Email ' . $mail . ' and pterodactyl ID ' . $pteroID); + next_step(); + } catch (Throwable $th) { + wh_log($th->getMessage(), 'error'); + if (str_contains($th->getMessage(), 'Duplicate entry')) { + send_error_message("User already exists in CtrlPanel\'s Database"); + } else { + send_error_message("Something went wrong when communicating with the Database."); + } + exit(); + } +} + +?> diff --git a/public/installer/src/forms/dashboard.php b/public/installer/src/forms/dashboard.php new file mode 100644 index 000000000..79804edd6 --- /dev/null +++ b/public/installer/src/forms/dashboard.php @@ -0,0 +1,29 @@ + diff --git a/public/installer/src/forms/database.php b/public/installer/src/forms/database.php new file mode 100644 index 000000000..cace72f5a --- /dev/null +++ b/public/installer/src/forms/database.php @@ -0,0 +1,76 @@ +load(); + +mysqli_report(MYSQLI_REPORT_STRICT | MYSQLI_REPORT_ALL); + +if (isset($_POST['checkDB'])) { + $values = [ + //SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form) + 'DB_HOST' => 'databasehost', + 'DB_DATABASE' => 'database', + 'DB_USERNAME' => 'databaseuser', + 'DB_PASSWORD' => 'databaseuserpass', + 'DB_PORT' => 'databaseport', + 'DB_CONNECTION' => 'databasedriver', + ]; + + wh_log('Trying to connect to the Database', 'debug'); + + try { + $db = new mysqli($_POST['databasehost'], $_POST['databaseuser'], $_POST['databaseuserpass'], $_POST['database'], $_POST['databaseport']); + } catch (mysqli_sql_exception $e) { + wh_log($e->getMessage(), 'error'); + send_error_message($e->getMessage()); + exit(); + } + + foreach ($values as $key => $value) { + $param = $_POST[$value]; + setenv($key, $param); + } + + wh_log('Start APP_KEY generation', 'debug'); + + try { + if (!str_contains(getenv('APP_KEY'), 'base64')) { + $logs = run_console('php artisan key:generate --force'); + wh_log($logs, 'debug'); + + wh_log('Created APP_KEY successful', 'debug'); + } else { + wh_log('Key already exists. Skipping', 'debug'); + } + } catch (Throwable $th) { + wh_log('Creating APP_KEY failed', 'error'); + header("LOCATION: index.php?step=3&message=" . $th->getMessage() . "
Please check the installer.log file in /var/www/controlpanel/storage/logs !"); + exit(); + } + + wh_log('Database connection successful', 'debug'); + next_step(); +} + +if (isset($_POST['feedDB'])) { + wh_log('Feeding the Database', 'debug'); + $logs = ''; + + try { + $logs .= run_console('php artisan storage:link'); + $logs .= run_console('php artisan migrate --seed --force'); + $logs .= run_console('php artisan db:seed --class=ExampleItemsSeeder --force'); + $logs .= run_console('php artisan db:seed --class=PermissionsSeeder --force'); + + wh_log($logs, 'debug'); + + wh_log('Feeding the Database successful', 'debug'); + next_step(); + } catch (Throwable $th) { + wh_log('Feeding the Database failed', 'error'); + send_error_message("Feeding the Database failed"); + } +} + +?> diff --git a/public/installer/src/forms/pterodactyl.php b/public/installer/src/forms/pterodactyl.php new file mode 100644 index 000000000..d4c24dd94 --- /dev/null +++ b/public/installer/src/forms/pterodactyl.php @@ -0,0 +1,80 @@ +getMessage() . "
Please check the installer.log file in /var/www/controlpanel/storage/logs!"); + exit(); + } +} +?> \ No newline at end of file diff --git a/public/installer/src/forms/redis.php b/public/installer/src/forms/redis.php new file mode 100644 index 000000000..882c8ff05 --- /dev/null +++ b/public/installer/src/forms/redis.php @@ -0,0 +1,34 @@ + $redisHost, + 'port' => $redisPort, + 'password' => $redisPassword, + 'timeout' => 1.0, + ]); + + try { + $redisClient->ping(); + + setenv('MEMCACHED_HOST', $redisHost); + setenv('REDIS_HOST', $redisHost); + setenv('REDIS_PORT', $redisPort); + setenv('REDIS_PASSWORD', ($redisPassword === '' ? 'null' : $redisPassword)); + + wh_log('Redis connection successful. Settings updated.', 'debug'); + next_step(); + } catch (Throwable $th) { + wh_log('Redis connection failed. Settings updated.', 'debug'); + send_error_message("Please check your credentials!
" . $th->getMessage()); + } +} + +?> diff --git a/public/installer/src/forms/smtp.php b/public/installer/src/forms/smtp.php new file mode 100644 index 000000000..28c6b500f --- /dev/null +++ b/public/installer/src/forms/smtp.php @@ -0,0 +1,73 @@ +load(); + +require './src/phpmailer/Exception.php'; +require './src/phpmailer/PHPMailer.php'; +require './src/phpmailer/SMTP.php'; + + +if (isset($_POST['checkSMTP'])) { + wh_log('Checking SMTP Settings', 'debug'); + try { + $mail = new PHPMailer(true); + + //Server settings + // Send using SMTP + $mail->isSMTP(); + $mail->Host = $_POST['host']; + // Enable SMTP authentication + $mail->SMTPAuth = true; + $mail->Username = $_POST['user']; + $mail->Password = $_POST['pass']; + $mail->SMTPSecure = $_POST['encryption']; + $mail->Port = (int) $_POST['port']; + + // Test E-mail metadata + $mail->setFrom($_POST['user'], $_POST['user']); + $mail->addAddress($_POST['user'], $_POST['user']); + + // Content + // Set email format to HTML + $mail->isHTML(true); + $mail->Subject = 'It Worked! - Test E-Mail from Ctrlpanel.gg'; + $mail->Body = 'Your E-Mail Settings are correct!'; + + $mail->send(); + } catch (Exception $e) { + wh_log($mail->ErrorInfo, 'error'); + send_error_message("Something went wrong while sending test E-Mail!
" . $mail->ErrorInfo); + exit(); + } + + wh_log('SMTP Settings are correct', 'debug'); + wh_log('Updating Database', 'debug'); + $db = new mysqli(getenv('DB_HOST'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'), getenv('DB_PORT')); + if ($db->connect_error) { + wh_log($db->connect_error, 'error'); + send_error_message("Could not connect to the Database"); + exit(); + } + $values = [ + 'mail_mailer' => $_POST['method'], + 'mail_host' => $_POST['host'], + 'mail_port' => $_POST['port'], + 'mail_username' => $_POST['user'], + 'mail_password' => $_POST['pass'], + 'mail_encryption' => $_POST['encryption'], + 'mail_from_address' => $_POST['user'], + ]; + + foreach ($values as $key => $value) { + run_console("php artisan settings:set 'MailSettings' '$key' '$value'"); + } + + wh_log('Database updated', 'debug'); + next_step(); +} + +?> \ No newline at end of file diff --git a/public/installer/src/forms/timezone.php b/public/installer/src/forms/timezone.php new file mode 100644 index 000000000..b3ff5fa2c --- /dev/null +++ b/public/installer/src/forms/timezone.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/public/installer/src/functions/environment.php b/public/installer/src/functions/environment.php new file mode 100644 index 000000000..456680673 --- /dev/null +++ b/public/installer/src/functions/environment.php @@ -0,0 +1,133 @@ + '8.2', + 'maxPhp' => '8.4', // This version is not supported + 'mysql' => '5.7.22', +]; + +/** + * Check if the minimum PHP version is present + * @return string 'OK' on success and 'not OK' on failure. + */ +function checkPhpVersion(): string +{ + global $requirements; + + wh_log('php version: ' . phpversion(), 'debug'); + if (version_compare(phpversion(), $requirements['minPhp'], '>=') && version_compare(phpversion(), $requirements['maxPhp'], '<=')) { + return 'OK'; + } + + return 'not OK'; +} + +/** + * Check if zip is installed using a shell command + * @return string 'OK' on success and 'not OK' on failure. + */ +function getZipVersion(): string +{ + wh_log('attempting to get zip version', 'debug'); + $output = shell_exec('zip -v') ?? ''; + preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); + + $versionoutput = $version[0] ?? 0; + wh_log('zip version: ' . $versionoutput, 'debug'); + + return $versionoutput != 0 ? 'OK' : 'not OK'; +} + +/** + * Check if git is installed using a shell command + * @return string 'OK' on success and 'not OK' on failure. + */ +function getGitVersion(): string +{ + wh_log('attempting to get git version', 'debug'); + $output = shell_exec('git --version') ?? ''; + preg_match('@[0-9]+\.[0-9]+\.[0-9]+@', $output, $version); + + $versionoutput = $version[0] ?? 0; + wh_log('git version: ' . $versionoutput, 'debug'); + + return $versionoutput != 0 ? 'OK' : 'not OK'; +} + +/** + * Check if tar is installed using a shell command + * @return string 'OK' on success and 'not OK' on failure. + */ +function getTarVersion(): string +{ + wh_log('attempting to get tar version', 'debug'); + $output = shell_exec('tar --version') ?? ''; + preg_match('@[0-9]+\.[0-9]+@', $output, $version); + + $versionoutput = $version[0] ?? 0; + wh_log('tar version: ' . $versionoutput, 'debug'); + + return $versionoutput != 0 ? 'OK' : 'not OK'; +} + +/** + * Check if the environment file is writable + * @return bool Returns true on writable and false on not writable. + */ +function checkWriteable(): bool +{ + return is_writable('../../.env'); +} + +?> diff --git a/public/installer/src/functions/installer.php b/public/installer/src/functions/installer.php new file mode 100644 index 000000000..b9732eff0 --- /dev/null +++ b/public/installer/src/functions/installer.php @@ -0,0 +1,17 @@ + diff --git a/public/installer/src/functions/logging.php b/public/installer/src/functions/logging.php new file mode 100644 index 000000000..70324ccd9 --- /dev/null +++ b/public/installer/src/functions/logging.php @@ -0,0 +1,48 @@ +load(); + +/** + * Log to the default laravel.log file + * @param string $message The message to log + * @param string $level The log level to use (debug, info, warning, error, critical) + * @param array $context [optional] The context to log extra information + * @return void + */ +function wh_log(string $message, string $level = 'info', array $context = []): void +{ + $formatter = new LineFormatter(null, null, true, true); + $stream = new StreamHandler(dirname(__DIR__, 4) . '/storage/logs/installer.log', Logger::DEBUG); + $stream->setFormatter($formatter); + + $log = new Logger('CtrlPanel'); + $log->pushHandler($stream); + + switch (strtolower($level)) { + case 'debug': // Only log debug messages if APP_DEBUG is true + if (getenv('APP_DEBUG') === false) return; + $log->debug($message, $context); + break; + case 'info': + $log->info($message, $context); + break; + case 'warning': + $log->warning($message, $context); + break; + case 'error': + $log->error($message, $context); + break; + case 'critical': + $log->critical($message, $context); + break; + } + // Prevent memory leaks by resetting the logger + $log->reset(); +} + +?> diff --git a/public/installer/src/functions/shell.php b/public/installer/src/functions/shell.php new file mode 100644 index 000000000..7a72fcedf --- /dev/null +++ b/public/installer/src/functions/shell.php @@ -0,0 +1,41 @@ + + * An indexed array where the key represents the descriptor number and the value represents how PHP will pass that descriptor to the child process. 0 is stdin, 1 is stdout, while 2 is stderr. + * Default descriptors when null are 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w'] + *

+ * @param string|null $cwd [optional]

+ * The initial working dir for the command. This must be an + * absolute directory path, or null + * if you want to use the default value (the working dir of the current + * PHP process) + *

+ * @param array|null $options [optional]

+ * Allows you to specify additional options. + * @link https://www.php.net/manual/en/function.proc-open.php proc_open + *

+ * @return false|string|null Returns the result from the command. + */ +function run_console(string $command, array $descriptors = null, string $cwd = null, array $options = null) +{ + wh_log('running command: ' . $command, 'debug'); + + $path = dirname(__DIR__, 4); + $descriptors = $descriptors ?? [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']]; + $handle = proc_open("cd '$path' && bash -c 'exec -a ServerCPP $command'", $descriptors, $pipes, $cwd, null, $options); + $output = stream_get_contents($pipes[1]); + $exit_code = proc_close($handle); + + if ($exit_code > 0) { + wh_log('command result: ' . $output, 'error'); + throw new Exception("There was an error after running command `$command`", $exit_code); + return $output; + } else { + return $output; + } +} + +?> diff --git a/public/installer/src/functions/utils.php b/public/installer/src/functions/utils.php new file mode 100644 index 000000000..5c13ec524 --- /dev/null +++ b/public/installer/src/functions/utils.php @@ -0,0 +1,46 @@ +load(); + +/** + * Encrypt the given value + * @param mixed $value The variable to be encrypted + * @param bool $serialize If the encryption should be serialized + * @return string Returns the encrypted variable. + */ +function encryptSettingsValue(mixed $value, $serialize = true): string +{ + $appKey = getenv('APP_KEY'); + $appKey = base64_decode(Str::after($appKey, 'base64:')); + $encrypter = new Encrypter($appKey, 'AES-256-CBC'); + $encryptedKey = $encrypter->encrypt($value, $serialize); + + return $encryptedKey; +} + +/** + * Decrypt the given value + * @param mixed $payload The payload to be decrypted + * @param bool $unserialize If the encryption should be unserialized + * @return mixed Returns the decrypted variable on success, throws otherwise. + */ + +function decryptSettingsValue(mixed $payload, $unserialize = true) +{ + $appKey = getenv('APP_KEY'); + $appKey = base64_decode(Str::after($appKey, 'base64:')); + $encrypter = new Encrypter($appKey, 'AES-256-CBC'); + $decryptedKey = $encrypter->decrypt($payload, $unserialize); + + return $decryptedKey; +} + +function determineIfRunningInDocker(): bool +{ + return file_exists('/.dockerenv'); +} + +?> diff --git a/public/install/phpmailer/Exception.php b/public/installer/src/phpmailer/Exception.php similarity index 100% rename from public/install/phpmailer/Exception.php rename to public/installer/src/phpmailer/Exception.php diff --git a/public/install/phpmailer/PHPMailer.php b/public/installer/src/phpmailer/PHPMailer.php similarity index 100% rename from public/install/phpmailer/PHPMailer.php rename to public/installer/src/phpmailer/PHPMailer.php diff --git a/public/install/phpmailer/SMTP.php b/public/installer/src/phpmailer/SMTP.php similarity index 100% rename from public/install/phpmailer/SMTP.php rename to public/installer/src/phpmailer/SMTP.php diff --git a/public/installer/styles.css b/public/installer/styles.css new file mode 100644 index 000000000..c9ed45534 --- /dev/null +++ b/public/installer/styles.css @@ -0,0 +1,983 @@ +/* + * You need to have `tailwindcss` packages installed for these commands to work. + * + * Build: `tailwindcss -i tailwind_styles.css -o styles.css -m` + * Dev: `tailwindcss -i tailwind_styles.css -o styles.css --watch` + */ + +/* + ! tailwindcss v3.4.4 | MIT License | https://tailwindcss.com + */ + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +*/ + +*, +::before, +::after { + box-sizing: border-box; + /* 1 */ + border-width: 0; + /* 2 */ + border-style: solid; + /* 2 */ + border-color: #e2e8f0; + /* 2 */ +} + +::before, +::after { + --tw-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS +*/ + +html, +:host { + line-height: 1.5; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ + -moz-tab-size: 4; + /* 3 */ + -o-tab-size: 4; + tab-size: 4; + /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + /* 4 */ + font-feature-settings: normal; + /* 5 */ + font-variation-settings: normal; + /* 6 */ + -webkit-tap-highlight-color: transparent; + /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; + /* 1 */ + line-height: inherit; + /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; + /* 1 */ + color: inherit; + /* 2 */ + border-top-width: 1px; + /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + /* 1 */ + font-feature-settings: normal; + /* 2 */ + font-variation-settings: normal; + /* 3 */ + font-size: 1em; + /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; + /* 1 */ + border-color: inherit; + /* 2 */ + border-collapse: collapse; + /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-feature-settings: inherit; + /* 1 */ + font-variation-settings: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + font-weight: inherit; + /* 1 */ + line-height: inherit; + /* 1 */ + letter-spacing: inherit; + /* 1 */ + color: inherit; + /* 1 */ + margin: 0; + /* 2 */ + padding: 0; + /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +input:where([type='button']), +input:where([type='reset']), +input:where([type='submit']) { + -webkit-appearance: button; + /* 1 */ + background-color: transparent; + /* 2 */ + background-image: none; + /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing and border for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +/* +Reset default styling for dialogs. +*/ + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::-moz-placeholder, textarea::-moz-placeholder { + opacity: 1; + /* 1 */ + color: #94a3b8; + /* 2 */ +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + /* 1 */ + color: #94a3b8; + /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; + /* 1 */ + vertical-align: middle; + /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* Make elements with the HTML hidden attribute stay hidden by default */ + +[hidden] { + display: none; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; + --tw-contain-size: ; + --tw-contain-layout: ; + --tw-contain-paint: ; + --tw-contain-style: ; +} + +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.bottom-0 { + bottom: 0px; +} + +.m-0 { + margin: 0px; +} + +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +.my-6 { + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-3 { + margin-bottom: 0.75rem; +} + +.mt-2 { + margin-top: 0.5rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.mr-1 { + margin-right: 0.25rem; +} + +.ml-1 { + margin-left: 0.25rem; +} + +.box-border { + box-sizing: border-box; +} + +.block { + display: block; +} + +.inline { + display: inline; +} + +.flex { + display: flex; +} + +.hidden { + display: none; +} + +.w-full { + width: 100%; +} + +.cursor-not-allowed { + cursor: not-allowed; +} + +.list-none { + list-style-type: none; +} + +.flex-col { + flex-direction: column; +} + +.items-center { + align-items: center; +} + +.justify-center { + justify-content: center; +} + +.justify-between { + justify-content: space-between; +} + +.gap-4 { + gap: 1rem; +} + +.rounded-2xl { + border-radius: 1rem; +} + +.rounded-full { + border-radius: 9999px; +} + +.rounded-md { + border-radius: 0.375rem; +} + +.border { + border-width: 1px; +} + +.border-2 { + border-width: 2px; +} + +.border-4 { + border-width: 4px; +} + +.border-\[\#2E373B\] { + --tw-border-opacity: 1; + border-color: rgb(46 55 59 / var(--tw-border-opacity)); +} + +.border-transparent { + border-color: transparent; +} + +.bg-\[\#1D2125\] { + --tw-bg-opacity: 1; + background-color: rgb(29 33 37 / var(--tw-bg-opacity)); +} + +.bg-\[\#242A2E\] { + --tw-bg-opacity: 1; + background-color: rgb(36 42 46 / var(--tw-bg-opacity)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(226 232 240 / var(--tw-bg-opacity)); +} + +.bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(30 41 59 / var(--tw-bg-opacity)); +} + +.bg-green-500\/90 { + background-color: rgb(34 197 94 / 0.9); +} + +.bg-red-500 { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity)); +} + +.bg-sky-500 { + --tw-bg-opacity: 1; + background-color: rgb(14 165 233 / var(--tw-bg-opacity)); +} + +.bg-sky-600 { + --tw-bg-opacity: 1; + background-color: rgb(2 132 199 / var(--tw-bg-opacity)); +} + +.bg-yellow-500\/90 { + background-color: rgb(234 179 8 / 0.9); +} + +.bg-opacity-20 { + --tw-bg-opacity: 0.2; +} + +.p-0 { + padding: 0px; +} + +.p-0\.5 { + padding: 0.125rem; +} + +.p-6 { + padding: 1.5rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.px-4 { + padding-left: 1rem; + padding-right: 1rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.py-2 { + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.pt-3 { + padding-top: 0.75rem; +} + +.text-center { + text-align: center; +} + +.text-3xl { + font-size: 1.875rem; + line-height: 2.25rem; +} + +.text-xl { + font-size: 1.25rem; + line-height: 1.75rem; +} + +.text-xs { + font-size: 0.75rem; + line-height: 1rem; +} + +.font-bold { + font-weight: 700; +} + +.font-medium { + font-weight: 500; +} + +.leading-none { + line-height: 1; +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(100 116 139 / var(--tw-text-opacity)); +} + +.text-neutral-400 { + --tw-text-opacity: 1; + color: rgb(163 163 163 / var(--tw-text-opacity)); +} + +.text-sky-100 { + --tw-text-opacity: 1; + color: rgb(224 242 254 / var(--tw-text-opacity)); +} + +.text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.shadow-inner { + --tw-shadow: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); + --tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-green-400 { + --tw-shadow-color: #4ade80; + --tw-shadow: var(--tw-shadow-colored); +} + +.shadow-red-200 { + --tw-shadow-color: #fecaca; + --tw-shadow: var(--tw-shadow-colored); +} + +.shadow-sky-400 { + --tw-shadow-color: #38bdf8; + --tw-shadow: var(--tw-shadow-colored); +} + +.shadow-yellow-400 { + --tw-shadow-color: #facc15; + --tw-shadow: var(--tw-shadow-colored); +} + +.outline-none { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.\[hostname\:port\] { + hostname: port; +} + +.hover\:bg-green-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(22 163 74 / var(--tw-bg-opacity)); +} + +.hover\:bg-red-400:hover { + --tw-bg-opacity: 1; + background-color: rgb(248 113 113 / var(--tw-bg-opacity)); +} + +.hover\:bg-sky-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(2 132 199 / var(--tw-bg-opacity)); +} + +.hover\:bg-yellow-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(202 138 4 / var(--tw-bg-opacity)); +} + +.focus\:border-sky-500:focus { + --tw-border-opacity: 1; + border-color: rgb(14 165 233 / var(--tw-border-opacity)); +} + +.focus\:outline:focus { + outline-style: solid; +} + +.focus\:outline-2:focus { + outline-width: 2px; +} + +.focus\:outline-offset-2:focus { + outline-offset: 2px; +} + +.focus\:outline-green-500:focus { + outline-color: #22c55e; +} + +.focus\:outline-red-500:focus { + outline-color: #ef4444; +} + +.focus\:outline-sky-500:focus { + outline-color: #0ea5e9; +} + +.focus\:outline-yellow-600:focus { + outline-color: #ca8a04; +} + +.left-0 { + left: 0px; +} + +.right-0 { + right: 0px; +} + +@media (min-width: 640px) { + .sm\:w-auto { + width: auto; + } + + .sm\:min-w-\[550px\] { + min-width: 550px; + } +} \ No newline at end of file diff --git a/public/installer/tailwind.config.js b/public/installer/tailwind.config.js new file mode 100644 index 000000000..5fc499bb2 --- /dev/null +++ b/public/installer/tailwind.config.js @@ -0,0 +1,24 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./**/*.{html,php}"], + theme: { + extend: { + colors: { + gray: { + '50': "#f8fafc", + '100': "#f1f5f9", + '200': "#e2e8f0", + '300': "#cbd5e1", + '400': "#94a3b8", + '500': "#64748b", + '600': "#475569", + '700': "#334155", + '800': "#1e293b", + '900': "#0f172a", + '950': "#020617", + } + } + }, + }, + plugins: [], +} \ No newline at end of file diff --git a/public/installer/tailwind_styles.css b/public/installer/tailwind_styles.css new file mode 100644 index 000000000..13de0f344 --- /dev/null +++ b/public/installer/tailwind_styles.css @@ -0,0 +1,10 @@ +/* + * You need to have `tailwindcss` packages installed for these commands to work. + * + * Build: `tailwindcss -i tailwind_styles.css -o styles.css -m` + * Dev: `tailwindcss -i tailwind_styles.css -o styles.css --watch` + */ + +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/public/installer/views/admin-creation.php b/public/installer/views/admin-creation.php new file mode 100644 index 000000000..96705f831 --- /dev/null +++ b/public/installer/views/admin-creation.php @@ -0,0 +1,70 @@ + + + + + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+ + + Found in the users-list on your pterodactyl dashboard +
+
+ +
+
+ + + This will be your new pterodactyl password aswell! +
+
+
+
+ + +
+
+ +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/installer/views/dashboard-configuration.php b/public/installer/views/dashboard-configuration.php new file mode 100644 index 000000000..f6368e63d --- /dev/null +++ b/public/installer/views/dashboard-configuration.php @@ -0,0 +1,64 @@ + + + + + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/installer/views/database-configuration.php b/public/installer/views/database-configuration.php new file mode 100644 index 000000000..b0ba51ad7 --- /dev/null +++ b/public/installer/views/database-configuration.php @@ -0,0 +1,97 @@ + + + + + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/installer/views/database-migration.php b/public/installer/views/database-migration.php new file mode 100644 index 000000000..adaf381d6 --- /dev/null +++ b/public/installer/views/database-migration.php @@ -0,0 +1,45 @@ + + + + This process might take a while. Please do not refresh or close this page!" +); ?> + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/installer/views/email-configuration.php b/public/installer/views/email-configuration.php new file mode 100644 index 000000000..7afab1bad --- /dev/null +++ b/public/installer/views/email-configuration.php @@ -0,0 +1,102 @@ + + + +Please do not refresh or close this page!" +); ?> + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+ +
+
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + + + + + +
+
+ + diff --git a/public/installer/views/installation-complete.php b/public/installer/views/installation-complete.php new file mode 100644 index 000000000..56b77fe4b --- /dev/null +++ b/public/installer/views/installation-complete.php @@ -0,0 +1,25 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/public/installer/views/layout-bottom.php b/public/installer/views/layout-bottom.php new file mode 100644 index 000000000..60e1efca0 --- /dev/null +++ b/public/installer/views/layout-bottom.php @@ -0,0 +1,12 @@ + + + + + + +
+ © CtrlPanel | installer v2.0.0 +
+ + + diff --git a/public/installer/views/layout-top.php b/public/installer/views/layout-top.php new file mode 100644 index 000000000..60c084b89 --- /dev/null +++ b/public/installer/views/layout-top.php @@ -0,0 +1,72 @@ + + + CtrlPanel.gg installer Script + + + + + + + +

CtrlPanel.gg Installation

+
+
Step {$currentStep}
+
+
+

$title

" + . (isset($subtitle) ? "

$subtitle

" : ""); +} +?> + + + diff --git a/public/installer/views/mandatory-checks.php b/public/installer/views/mandatory-checks.php new file mode 100644 index 000000000..24c0aa6a7 --- /dev/null +++ b/public/installer/views/mandatory-checks.php @@ -0,0 +1,77 @@ + + + + + +
    + +
  • Write-permissions on .env-file
  • + +
  • + php version: (minimum required ) +
  • + +
  • + Missing php-extentions: + +
  • + +
  • + Git version: + +
  • + +
  • + Tar version: + +
  • + +
  • +

    +
    + Important: + CtrlPanel.gg requires a MySQL-Database, Redis-Server, and Pterodactyl-Panel to work.
    + Please make sure you have these installed and running before you continue. +

    +
  • + +
+ +
+ +
+ + + + + + + + + + +
+ + diff --git a/public/installer/views/pterodactyl-configuration.php b/public/installer/views/pterodactyl-configuration.php new file mode 100644 index 000000000..cacce33f7 --- /dev/null +++ b/public/installer/views/pterodactyl-configuration.php @@ -0,0 +1,74 @@ + + + + + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+
+
+ + +
+
+
+
+ + + + [Found at: ptero.example.com/admin/api]
+ The key needs all Read & Write permissions!
+
+
+
+
+ + + + [Found at: ptero.example.com/account/api]
+ Your Account needs to be an Admin!
+
+
+
+
+ +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/installer/views/redis-configuration.php b/public/installer/views/redis-configuration.php new file mode 100644 index 000000000..54bc220fc --- /dev/null +++ b/public/installer/views/redis-configuration.php @@ -0,0 +1,73 @@ + + + + + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/installer/views/timezone-configuration.php b/public/installer/views/timezone-configuration.php new file mode 100644 index 000000000..9aaaf595d --- /dev/null +++ b/public/installer/views/timezone-configuration.php @@ -0,0 +1,64 @@ + + + + +
+ + " . $_SESSION['error-message'] . '

'; + } ?> + +
+
+
+
+ + +
+
+
+
+ +
+ +
+ + + + + + + + + +
+
+ + diff --git a/public/plugins/alpinejs/3.12.0_cdn.min.js b/public/plugins/alpinejs/3.12.0_cdn.min.js new file mode 100644 index 000000000..d806d3234 --- /dev/null +++ b/public/plugins/alpinejs/3.12.0_cdn.min.js @@ -0,0 +1,5 @@ +(()=>{var Ye=!1,Ze=!1,V=[],Qe=-1;function Bt(e){hn(e)}function hn(e){V.includes(e)||V.push(e),_n()}function ye(e){let t=V.indexOf(e);t!==-1&&t>Qe&&V.splice(t,1)}function _n(){!Ze&&!Ye&&(Ye=!0,queueMicrotask(gn))}function gn(){Ye=!1,Ze=!0;for(let e=0;ee.effect(t,{scheduler:r=>{Xe?Bt(r):r()}}),et=e.raw}function tt(e){P=e}function Vt(e){let t=()=>{};return[n=>{let i=P(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),L(i))},i},()=>{t()}]}var Ht=[],qt=[],Ut=[];function Wt(e){Ut.push(e)}function we(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,qt.push(t))}function Gt(e){Ht.push(e)}function Jt(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function nt(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}var it=new MutationObserver(ct),ot=!1;function se(){it.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ot=!0}function st(){xn(),it.disconnect(),ot=!1}var oe=[],rt=!1;function xn(){oe=oe.concat(it.takeRecords()),oe.length&&!rt&&(rt=!0,queueMicrotask(()=>{yn(),rt=!1}))}function yn(){ct(oe),oe.length=0}function h(e){if(!ot)return e();st();let t=e();return se(),t}var at=!1,be=[];function Yt(){at=!0}function Zt(){at=!1,ct(be),be=[]}function ct(e){if(at){be=be.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;os.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{nt(s,o)}),n.forEach((o,s)=>{Ht.forEach(a=>a(s,o))});for(let o of r)if(!t.includes(o)&&(qt.forEach(s=>s(o)),o._x_cleanups))for(;o._x_cleanups.length;)o._x_cleanups.pop()();t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.includes(o)||o.isConnected&&(delete o._x_ignoreSelf,delete o._x_ignore,Ut.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function Ee(e){return j($(e))}function R(e,t,r){return e._x_dataStack=[t,...$(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function lt(e,t){let r=e._x_dataStack[0];Object.entries(t).forEach(([n,i])=>{r[n]=i})}function $(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?$(e.host):e.parentNode?$(e.parentNode):[]}function j(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function ve(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Se(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>bn(n,i),s=>ut(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function bn(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function ut(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),ut(e[t[0]],t.slice(1),r)}}var Qt={};function y(e,t){Qt[e]=t}function ae(e,t){return Object.entries(Qt).forEach(([r,n])=>{Object.defineProperty(e,`$${r}`,{get(){let[i,o]=ft(t);return i={interceptor:Se,...i},we(t,o),n(t,i)},enumerable:!1})}),e}function Xt(e,t,r,...n){try{return r(...n)}catch(i){Z(i,e,t)}}function Z(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message} + +${r?'Expression: "'+r+`" + +`:""}`,t),setTimeout(()=>{throw e},0)}var Ae=!0;function er(e){let t=Ae;Ae=!1,e(),Ae=t}function I(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return tr(...e)}var tr=pt;function rr(e){tr=e}function pt(e,t){let r={};ae(r,e);let n=[r,...$(e)],i=typeof t=="function"?wn(n,t):vn(n,t,e);return Xt.bind(null,e,t,i)}function wn(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(j([n,...e]),i);Oe(r,o)}}var dt={};function En(e,t){if(dt[e])return dt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(async()=>{ ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return Z(s,t,e),Promise.resolve()}})();return dt[e]=o,o}function vn(e,t,r){let n=En(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=j([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>Z(l,r,t));n.finished?(Oe(i,n.result,a,s,r),n.result=void 0):c.then(l=>{Oe(i,l,a,s,r)}).catch(l=>Z(l,r,t)).finally(()=>n.result=void 0)}}}function Oe(e,t,r,n,i){if(Ae&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Oe(e,s,r,n)).catch(s=>Z(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var gt="x-";function S(e=""){return gt+e}function nr(e){gt=e}var mt={};function p(e,t){return mt[e]=t,{before(r){if(!mt[r]){console.warn("Cannot find directive `${directive}`. `${name}` will use the default order of execution");return}let n=H.indexOf(r);H.splice(n>=0?n:H.indexOf("DEFAULT"),0,e)}}}function le(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=xt(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(sr((o,s)=>n[o]=s)).filter(cr).map(An(n,r)).sort(On).map(o=>Sn(e,o))}function xt(e){return Array.from(e).map(sr()).filter(t=>!cr(t))}var ht=!1,ce=new Map,ir=Symbol();function or(e){ht=!0;let t=Symbol();ir=t,ce.set(t,[]);let r=()=>{for(;ce.get(t).length;)ce.get(t).shift()();ce.delete(t)},n=()=>{ht=!1,r()};e(r),n()}function ft(e){let t=[],r=a=>t.push(a),[n,i]=Vt(e);return t.push(i),[{Alpine:F,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:I.bind(I,e)},()=>t.forEach(a=>a())]}function Sn(e,t){let r=()=>{},n=mt[t.type]||r,[i,o]=ft(e);Jt(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),ht?ce.get(ir).push(n):n())};return s.runCleanups=o,s}var Ce=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Te=e=>e;function sr(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=ar.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var ar=[];function Q(e){ar.push(e)}function cr({name:e}){return lr().test(e)}var lr=()=>new RegExp(`^${gt}([^:^.]+)\\b`);function An(e,t){return({name:r,value:n})=>{let i=r.match(lr()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var _t="DEFAULT",H=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",_t,"teleport"];function On(e,t){let r=H.indexOf(e.type)===-1?_t:e.type,n=H.indexOf(t.type)===-1?_t:t.type;return H.indexOf(r)-H.indexOf(n)}function q(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function A(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>A(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)A(n,t,!1),n=n.nextElementSibling}function T(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}function ur(){document.body||T("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's ` + {{-- --}} - + {{-- summernote --}} @@ -36,7 +40,7 @@ - + @@ -52,49 +56,51 @@ class="fas fa-bars"> - @if (config('SETTINGS::DISCORD:INVITE_URL')) + @if (!empty($discord_settings->invite_url)) @endif - @if (config('SETTINGS::LOCALE:CLIENTS_CAN_CHANGE') == 'true') + @php($locale_settings = app(App\Settings\LocaleSettings::class)) + @if ($locale_settings->clients_can_change) @endif - @foreach($useful_links as $link) + @foreach ($useful_links as $link) @endforeach -
+ + diff --git a/themes/default/views/admin/api/create.blade.php b/themes/default/views/admin/api/create.blade.php index e0025e859..24fba4459 100644 --- a/themes/default/views/admin/api/create.blade.php +++ b/themes/default/views/admin/api/create.blade.php @@ -50,6 +50,8 @@ class="form-control @error('memo') is-invalid @enderror"> {{__('Submit')}} + + diff --git a/themes/default/views/admin/api/edit.blade.php b/themes/default/views/admin/api/edit.blade.php index f99e0b278..e9ebdc669 100644 --- a/themes/default/views/admin/api/edit.blade.php +++ b/themes/default/views/admin/api/edit.blade.php @@ -51,6 +51,8 @@ class="form-control @error('memo') is-invalid @enderror"> {{__('Submit')}} + + diff --git a/themes/default/views/admin/coupons/create.blade.php b/themes/default/views/admin/coupons/create.blade.php new file mode 100644 index 000000000..765a4b4f4 --- /dev/null +++ b/themes/default/views/admin/coupons/create.blade.php @@ -0,0 +1,291 @@ +@extends('layouts.main') + +@section('content') + +
+
+
+
+

{{__('Coupon')}}

+
+ +
+
+
+ + + +
+
+
+
+
+
+
+ + {{__('Coupon Details')}} +
+
+
+
+ @csrf + +
+
+ + +
+
+ +
+ + + @error('code') +
+ {{ $message }} +
+ @enderror +
+
+
+ + + @error('type') +
+ {{ $message }} +
+ @enderror +
+
+
+
+ +
+ + % +
+ @error('value') +
+ {{ $message }} +
+ @enderror +
+
+
+ + + @error('max_uses') +
+ {{ $message }} +
+ @enderror +
+
+ +
+ +
+
+ +
+
+
+ @error('expires_at') +
+ {{ $message }} +
+ @enderror +
+
+ +
+ + +
+
+
+
+
+
+
+ + + +@endsection diff --git a/themes/default/views/admin/coupons/edit.blade.php b/themes/default/views/admin/coupons/edit.blade.php new file mode 100644 index 000000000..e527e9d62 --- /dev/null +++ b/themes/default/views/admin/coupons/edit.blade.php @@ -0,0 +1,293 @@ +@extends('layouts.main') + +@section('content') + +
+
+
+
+

{{__('Coupon')}}

+
+ +
+
+
+ + + +
+
+ +
+
+
+
+
+ {{__('Coupon details')}} +
+
+
+
+ @csrf + @method('PATCH') + +
+
+ + +
+
+ +
+ + + @error('code') +
+ {{ $message }} +
+ @enderror +
+
+
+ + + @error('type') +
+ {{ $message }} +
+ @enderror +
+
+
+
+ +
+ + % +
+ @error('value') +
+ {{ $message }} +
+ @enderror +
+
+
+ + + @error('max_uses') +
+ {{ $message }} +
+ @enderror +
+
+ +
+ +
+
+ +
+
+
+ @error('expires_at') +
+ {{ $message }} +
+ @enderror +
+
+ +
+ + +
+
+
+
+
+ +
+
+ + + +@endsection diff --git a/themes/default/views/admin/coupons/index.blade.php b/themes/default/views/admin/coupons/index.blade.php new file mode 100644 index 000000000..cad2aa4e4 --- /dev/null +++ b/themes/default/views/admin/coupons/index.blade.php @@ -0,0 +1,96 @@ +@extends('layouts.main') + +@section('content') + +
+
+
+
+

{{__('Coupons')}}

+
+ +
+
+
+ + + +
+
+
+
+
+
+ + {{__('Coupons')}} +
+ + + {{__('Create new')}} + +
+
+ +
+ + + + + + + + + + + + + + + +
{{__('Status')}}{{__('Code')}}{{__('Value')}}{{__('Used / Max Uses')}}{{__('Expires')}}{{__('Created At')}}{{__('Actions')}}
+ +
+
+ + +
+ + +
+ + +@endsection diff --git a/themes/default/views/admin/legal/index.blade.php b/themes/default/views/admin/legal/index.blade.php index 5fb6025f9..d6120eeb7 100644 --- a/themes/default/views/admin/legal/index.blade.php +++ b/themes/default/views/admin/legal/index.blade.php @@ -96,6 +96,8 @@ class="form-control @error('imprint') is-invalid @enderror">
+ + diff --git a/themes/default/views/admin/nests/index.blade.php b/themes/default/views/admin/nests/index.blade.php deleted file mode 100644 index 152773e48..000000000 --- a/themes/default/views/admin/nests/index.blade.php +++ /dev/null @@ -1,100 +0,0 @@ - - - -@extends('layouts.main') - -@section('content') - -
-
-
-
-

{{__('Nests')}}

-
- -
-
-
- - - -
-
- -
- -
-
-
{{__('Nests')}}
- {{__('Sync')}} -
-
- -
- - - - - - - - - - - - - - - -
{{__('Active')}}{{__('ID')}}{{__('eggs')}}{{__('Name')}}{{__('Description')}}{{__('Created at')}}
- -
-
- - -
- - -
- - - - - - -@endsection diff --git a/themes/default/views/admin/nodes/index.blade.php b/themes/default/views/admin/nodes/index.blade.php deleted file mode 100644 index bb57e0cee..000000000 --- a/themes/default/views/admin/nodes/index.blade.php +++ /dev/null @@ -1,100 +0,0 @@ - - - -@extends('layouts.main') - -@section('content') - -
-
-
-
-

{{__('Nodes')}}

-
- -
-
-
- - - -
-
- -
- -
-
-
{{__('Nodes')}}
- {{__('Sync')}} -
-
- -
- - - - - - - - - - - - - - - -
{{__('Active')}}{{__('ID')}}{{__('Location')}}{{__('Name')}}{{__('Description')}}{{__('Created at')}}
- -
-
- - -
- - -
- - - - - - -@endsection diff --git a/themes/default/views/admin/overview/index.blade.php b/themes/default/views/admin/overview/index.blade.php index 7b0980b22..ab053f6bf 100644 --- a/themes/default/views/admin/overview/index.blade.php +++ b/themes/default/views/admin/overview/index.blade.php @@ -4,7 +4,7 @@
-
+

{{__('Admin Overview')}}

@@ -23,7 +23,7 @@ {{__("Version Outdated:")}}
{{__("You are running on")}} v{{config("app.version")}}-{{config("BRANCHNAME")}}. {{__("The latest Version is")}} v{{Storage::get('latestVersion')}}
- {{__("Consider updating now")}} + {{__("Consider updating now")}}
@endif
@@ -33,22 +33,18 @@
-
+ @@ -58,7 +54,12 @@ class="fas fa-money-bill mr-2"> {{__('Support CtrlPanel')}}
- {{__('Servers')}} + {{__('Servers')}} + + {{$counters['servers']->active}}/{{$counters['servers']->total}}
@@ -71,8 +72,13 @@ class="fas fa-money-bill mr-2"> {{__('Support CtrlPanel')}}
- {{__('Users')}} - {{$counters['users']}} + {{__('Users')}} + + + {{$counters['users']->active}}/{{$counters['users']->total}}
@@ -82,10 +88,10 @@ class="fas fa-money-bill mr-2"> {{__('Support CtrlPanel')}}
+ class="text-white fas fa-coins">
- {{__('Total')}} {{CREDITS_DISPLAY_NAME}} + {{__('Total')}} {{ $credits_display_name }} {{$counters['credits']}}
@@ -113,15 +119,15 @@ class="fas fa-coins text-white">
- {{__('Pterodactyl')}} + {{__('Pterodactyl')}}
{{__('Sync')}} + class="mr-2 fas fa-sync">{{__('Sync')}}
-
+
@if ($deletedNodesPresent) -
+
{{ __('Warning!') }}

{{ __('Some nodes got deleted on pterodactyl only. Please click the sync button above.') }} @@ -156,42 +162,44 @@ class="fas fa-sync mr-2">{{__('Sync')}}

- {{__('Latest tickets')}} + {{__('Latest tickets')}}
-
+
@if(!$tickets->count()){{__('There are no tickets')}}. @else - - - - - - - - - - +
+
{{__('Title')}}{{__('User')}}{{__('Status')}}{{__('Last updated')}}
+ + + + + + + + + - @foreach($tickets as $ticket_id => $ticket) - - - - - - - @endforeach + @foreach($tickets as $ticket_id => $ticket) + + + + + + + @endforeach - -
{{__('Title')}}{{__('User')}}{{__('Status')}}{{__('Last updated')}}
#{{$ticket_id}} - {{$ticket->title}}{{$ticket->user}}{{$ticket->status}}{{$ticket->last_updated}}
#{{$ticket_id}} - {{$ticket->title}}{{$ticket->user}}{{$ticket->status}}{{$ticket->last_updated}}
+ + +
@endif
@@ -199,14 +207,14 @@ class="fas fa-sync mr-2">{{__('Sync')}}
- {{__('Ctrlpanel.gg')}} + {{__('CtrlPanel.gg')}}
-
+
@@ -216,13 +224,13 @@ class="fas fa-sync mr-2">{{__('Sync')}}
- {{__('Individual nodes')}} + {{__('Individual nodes')}}
-
+
@if ($perPageLimit) -
+
{{ __('Error!') }}

{{ __('You reached the Pterodactyl perPage limit. Please make sure to set it higher than your server count.') }}
@@ -230,39 +238,41 @@ class="fas fa-sync mr-2">{{__('Sync')}} {{ __('Note') }}: {{ __('If this error persists even after changing the limit, it might mean a server was deleted on Pterodactyl, but not on CtrlPanel. Try clicking the button below.') }}

{{__('Sync servers')}} + class="mr-2 fas fa-sync">{{__('Sync servers')}}
@endif - - - - - - - - - - - - @foreach($nodes as $nodeID => $node) +
+
{{__('ID')}}{{__('Node')}}{{__('Server count')}}{{__('Resource usage')}}{{CREDITS_DISPLAY_NAME . ' ' . __('Usage')}}
+ + + + + + + + + + + @foreach($nodes as $nodeID => $node) + + + + + + + + @endforeach + + - - - - - + + + + - @endforeach - - - - - - - - - -
{{__('ID')}}{{__('Node')}}{{__('Server count')}}{{__('Resource usage')}}{{ $credits_display_name . ' ' . __('Usage') ." (".__('per month').")"}}
{{$nodeID}}{{$node->name}}{{$node->activeServers}}/{{$node->totalServers}}{{$node->usagePercent}}%{{$node->activeEarnings}}/{{$node->totalEarnings}}
{{$nodeID}}{{$node->name}}{{$node->activeServers}}/{{$node->totalServers}}{{$node->usagePercent}}%{{$node->activeEarnings}}/{{$node->totalEarnings}}{{__('Total')}} ({{__('active')}}/{{__('total')}}):{{$counters['servers']->active}}/{{$counters['servers']->total}}{{$counters['totalUsagePercent']}}%{{$counters['earnings']->active}}/{{$counters['earnings']->total}}
{{__('Total')}} ({{__('active')}}/{{__('total')}}):{{$counters['servers']->active}}/{{$counters['servers']->total}}{{$counters['totalUsagePercent']}}%{{$counters['earnings']->active}}/{{$counters['earnings']->total}}
+ + +

@@ -270,11 +280,11 @@ class="fas fa-sync mr-2">{{__('Sync servers')}}
- {{__('Latest payments')}} + {{__('Latest payments')}}
-
+
@if($counters['payments']['lastMonth']->count())
@@ -283,16 +293,46 @@ class="fas fa-sync mr-2">{{__('Sync servers')}} data-content="{{ __('Payments in this time window') }}:
{{$counters['payments']['lastMonth']->timeStart}} - {{$counters['payments']['lastMonth']->timeEnd}}" class="fas fa-info-circle"> +
+ + + + + + + + + + @foreach($counters['payments']['lastMonth'] as $currency => $income) + + + + + + @endforeach + +
{{__('Currency')}}{{__('Number of payments')}}{{__('Total amount')}}
{{$currency}}{{$income->count}}{{$income->total}}
+
+
+ @endif + @if($counters['payments']['lastMonth']->count())
+ @else
@endif + {{__('This month')}}: + + +
- + - @foreach($counters['payments']['lastMonth'] as $currency => $income) + @foreach($counters['payments']['thisMonth'] as $currency => $income) @@ -301,35 +341,7 @@ class="fas fa-info-circle"> @endforeach
{{__('Currency')}} {{__('Number of payments')}} {{__('Total amount')}}
{{$currency}} {{$income->count}}
-
- @endif - @if($counters['payments']['lastMonth']->count())
- @else
@endif - {{__('This month')}}: - - - - - - - - - - - - @foreach($counters['payments']['thisMonth'] as $currency => $income) - - - - - - @endforeach - -
{{__('Currency')}}{{__('Number of payments')}}{{__('Total amount')}}
{{$currency}}{{$income->count}}{{$income->total}}
-
@@ -339,20 +351,52 @@ class="fas fa-info-circle">
- {{__('Tax overview')}} + {{__('Tax overview')}}
-
+
@if($counters['taxPayments']['lastYear']->count()) {{__('Last year')}}: +
+ + + + + + + + + + + + @foreach($counters['taxPayments']['lastYear'] as $currency => $income) + + + + + + + + @endforeach + +
{{__('Currency')}}{{__('Number of payments')}}{{__('Base amount')}}{{__('Total taxes')}}{{__('Total amount')}}
{{$currency}}{{$income->count}}{{$income->price}}{{$income->taxes}}{{$income->total}}
+
+
+ @endif + {{__('This year')}}: + + +
- + @@ -361,7 +405,7 @@ class="fas fa-info-circle"> - @foreach($counters['taxPayments']['lastYear'] as $currency => $income) + @foreach($counters['taxPayments']['thisYear'] as $currency => $income) @@ -372,35 +416,7 @@ class="fas fa-info-circle"> @endforeach
{{__('Currency')}} {{__('Number of payments')}} {{__('Base amount')}}
{{$currency}} {{$income->count}}
-
- @endif - {{__('This year')}}: - - - - - - - - - - - - - - @foreach($counters['taxPayments']['thisYear'] as $currency => $income) - - - - - - - - @endforeach - -
{{__('Currency')}}{{__('Number of payments')}}{{__('Base amount')}}{{__('Total taxes')}}{{__('Total amount')}}
{{$currency}}{{$income->count}}{{$income->price}}{{$income->taxes}}{{$income->total}}
+

diff --git a/themes/default/views/admin/partners/create.blade.php b/themes/default/views/admin/partners/create.blade.php index 03f8cab31..6d3aad1e9 100644 --- a/themes/default/views/admin/partners/create.blade.php +++ b/themes/default/views/admin/partners/create.blade.php @@ -106,6 +106,8 @@ class="form-control @error('referral_system_commission') is-invalid @enderror"> {{__('Submit')}}
+ +
diff --git a/themes/default/views/admin/partners/edit.blade.php b/themes/default/views/admin/partners/edit.blade.php index 289edf5ba..3c87549c2 100644 --- a/themes/default/views/admin/partners/edit.blade.php +++ b/themes/default/views/admin/partners/edit.blade.php @@ -113,6 +113,8 @@ class="form-control @error('referral_system_commission') is-invalid @enderror"> {{__('Submit')}}
+ +
diff --git a/themes/default/views/admin/payments/index.blade.php b/themes/default/views/admin/payments/index.blade.php index 5e1096ae6..c0d9c4bbb 100644 --- a/themes/default/views/admin/payments/index.blade.php +++ b/themes/default/views/admin/payments/index.blade.php @@ -47,6 +47,7 @@ class="btn btn-info">{{ __('Download all Invoices') }} {{ __('Total Price') }} {{ __('Payment ID') }} {{ __('Payment Method') }} + {{ __('Status') }} {{ __('Created at') }} @@ -85,6 +86,7 @@ class="btn btn-info">{{ __('Download all Invoices') }} {data: 'total_price'}, {data: 'payment_id'}, {data: 'payment_method'}, + {data: 'status'}, {data: 'created_at', type: 'num', render: {_: 'display', sort: 'raw'}}, {data: 'actions' , sortable : false}, ], diff --git a/themes/default/views/admin/products/create.blade.php b/themes/default/views/admin/products/create.blade.php index c6d72f68b..b074fdd3c 100644 --- a/themes/default/views/admin/products/create.blade.php +++ b/themes/default/views/admin/products/create.blade.php @@ -6,15 +6,15 @@
-

{{__('Products')}}

+

{{ __('Products') }}

@@ -26,23 +26,23 @@
-
+ @csrf
-
{{__('Product Details')}}
+
{{ __('Product Details') }}
-
@@ -50,172 +50,209 @@ class="fas fa-info-circle">
- - + + @error('name') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('price') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('memory') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('cpu') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('swap') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + + @error('allocations') +
+ {{ $message }} +
+ @enderror +
+ +
+ + @error('description') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
+
+ + +
- - + + @error('disk') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- + + + @error('billing_period') +
+ {{ $message }} +
+ @enderror +
+ +
+ @error('minimum_credits') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('io') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('databases') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('backups') -
- {{ $message }} -
- @enderror -
-
- - - @error('allocations') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
@@ -223,7 +260,7 @@ class="form-control @error('allocations') is-invalid @enderror"
@@ -234,72 +271,83 @@ class="form-control @error('allocations') is-invalid @enderror"
-
{{__('Product Linking')}} -
+
{{ __('Product Linking') }} + +
- + @error('nodes') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- {{__('This product will only be available for these nodes')}} + {{ __('This product will only be available for these nodes') }}
- +
+ +
+ + +
+
@error('eggs') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- {{__('This product will only be available for these eggs')}} + {{ __('This product will only be available for these eggs') }}
- {{__('No Eggs or Nodes shown?')}} {{__("Sync now")}} + {{ __('No Eggs or Nodes shown?') }} {{ __('Sync now') }}
+ +
@@ -307,9 +355,19 @@ class="custom-select @error('eggs') is-invalid @enderror" @endsection diff --git a/themes/default/views/admin/products/edit.blade.php b/themes/default/views/admin/products/edit.blade.php index 61357c716..cc3bba664 100644 --- a/themes/default/views/admin/products/edit.blade.php +++ b/themes/default/views/admin/products/edit.blade.php @@ -6,15 +6,15 @@
-

{{__('Products')}}

+

{{ __('Products') }}

@@ -26,35 +26,39 @@
-
+ @csrf @method('PATCH')
- @if($product->servers()->count() > 0) + @if ($product->servers()->count() > 0)
-

{{__('Editing the resource options will not automatically update the servers on - pterodactyls side!')}}'

-

{{__('Automatically updating resource options on pterodactyl side is on - my todo list :)')}}

+

{{ __('Editing the resource options will not automatically update the servers on + pterodactyls side!') }}' +

+

+ {{ __('Automatically updating resource options on pterodactyl side is on + my todo list :)') }} +

@endif
-
{{__('Product Details')}}
+
{{ __('Product Details') }}
- disabled) checked @endif name="disabled" - class="custom-control-input custom-control-input-danger" id="switch1"> -
@@ -63,155 +67,203 @@ class="fas fa-info-circle">
- - + + @error('name') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('price') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- + + type="number" class="form-control @error('memory') is-invalid @enderror" + required="required"> @error('memory') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- + + class="form-control @error('cpu') is-invalid @enderror" required="required"> @error('cpu') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('swap') -
- {{ $message }} -
+
+ {{ $message }} +
+ @enderror +
+
+ + + @error('allocations') +
+ {{ $message }} +
@enderror
-
- - + + @error('description') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
+
+ oom_killer) checked @endif + value="1" id="oom" name="oom_killer" class=""> + + +
+
- - + + @error('disk') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
+
- + + + @error('billing_period') +
+ {{ $message }} +
+ @enderror +
+ +
+ + name="minimum_credits" type="number" + class="form-control @error('minimum_credits') is-invalid @enderror" + required="required"> @error('minimum_credits') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- - + + @error('io') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- + + type="number" + class="form-control @error('databases') is-invalid @enderror" + required="required"> @error('databases') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
- + + type="number" + class="form-control @error('backups') is-invalid @enderror" + required="required"> @error('backups') -
- {{ $message }} -
- @enderror -
-
- - - @error('allocations') -
- {{ $message }} -
+
+ {{ $message }} +
@enderror
@@ -219,7 +271,7 @@ class="form-control @error('allocations') is-invalid @enderror"
@@ -230,59 +282,65 @@ class="form-control @error('allocations') is-invalid @enderror"
-
{{__('Product Linking')}} -
+
{{ __('Product Linking') }} + +
- + @error('nodes') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- {{__('This product will only be available for these nodes')}} + {{ __('This product will only be available for these nodes') }}
- +
+ +
+ + +
+
@error('eggs') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- {{__('This product will only be available for these eggs')}} + {{ __('This product will only be available for these eggs') }}
@@ -291,6 +349,8 @@ class="custom-select @error('eggs') is-invalid @enderror" name="eggs[]"
+ +
@@ -299,12 +359,21 @@ class="custom-select @error('eggs') is-invalid @enderror" name="eggs[]" - @endsection diff --git a/themes/default/views/admin/products/index.blade.php b/themes/default/views/admin/products/index.blade.php index bc15a70b4..f6a13dec0 100644 --- a/themes/default/views/admin/products/index.blade.php +++ b/themes/default/views/admin/products/index.blade.php @@ -4,7 +4,7 @@
-
+

{{__('Products')}}

@@ -30,9 +30,9 @@
-
{{__('Products')}}
+
{{__('Products')}}
{{__('Create new')}} + class="mr-1 fas fa-plus">
{{__('Create new')}}
@@ -44,12 +44,14 @@ class="fas fa-plus mr-1">
{{__('Create new')}} {{__('Active')}} {{__('Name')}} {{__('Price')}} + {{__('Billing period')}} {{__('Memory')}} {{__('Cpu')}} {{__('Swap')}} {{__('Disk')}} {{__('Databases')}} {{__('Backups')}} + {{__('OOM Killer')}} {{__('Nodes')}} {{__('Eggs')}} {{__('Min Credits')}} @@ -92,12 +94,14 @@ function submitResult() { {data: "disabled"}, {data: "name"}, {data: "price"}, + {data: "billing_period"}, {data: "memory"}, {data: "cpu"}, {data: "swap"}, {data: "disk"}, {data: "databases"}, {data: "backups"}, + {data: "oom_killer"}, {data: "nodes", sortable: false}, {data: "eggs", sortable: false}, {data: "minimum_credits"}, diff --git a/themes/default/views/admin/products/show.blade.php b/themes/default/views/admin/products/show.blade.php index daf9a6ab9..c8c504738 100644 --- a/themes/default/views/admin/products/show.blade.php +++ b/themes/default/views/admin/products/show.blade.php @@ -4,7 +4,7 @@
-
+

{{__('Products')}}

@@ -28,17 +28,17 @@
-
{{__('Product')}}
+
{{__('Product')}}
{{ csrf_field() }} {{ method_field('DELETE') }} + class="mr-1 btn btn-sm btn-danger">
@@ -78,7 +78,7 @@ class="btn btn-sm btn-danger mr-1">
- {{ $product->price }} + {{ $product->price }}
@@ -92,9 +92,9 @@ class="btn btn-sm btn-danger mr-1">
@if ($product->minimum_credits == -1) - {{ $minimum_credits }} + {{ $minimum_credits }} @else - {{ $product->minimum_credits }} + {{ $product->minimum_credits }} @endif
@@ -213,7 +213,7 @@ class="btn btn-sm btn-danger mr-1">
- + {{ $product->description }}
@@ -240,7 +240,7 @@ class="btn btn-sm btn-danger mr-1">
-
{{__('Servers')}}
+
{{__('Servers')}}
diff --git a/themes/default/views/admin/roles/edit.blade.php b/themes/default/views/admin/roles/edit.blade.php new file mode 100644 index 000000000..4db1f15c3 --- /dev/null +++ b/themes/default/views/admin/roles/edit.blade.php @@ -0,0 +1,97 @@ +@extends('layouts.main') + +@section('content') +
+
+
+
+

{{ isset($role) ? __('Edit role') : __('Create role') }}

+
+ +
+
+
+ +
+
+
+
+
+
{{ isset($role) ? __('Edit role') : __('Create role') }}
+
+
+
+
+
+ @csrf + @isset($role) + @method('PATCH') + @endisset + +
+
+ + + + + + + +
+ +
+ + + @foreach($permissions as $permission) + + @endforeach + + +
+
+ +
+ +
+ + +
+
+
+
+
+
+
+ + +@endsection diff --git a/themes/default/views/admin/roles/index.blade.php b/themes/default/views/admin/roles/index.blade.php new file mode 100644 index 000000000..0486f6279 --- /dev/null +++ b/themes/default/views/admin/roles/index.blade.php @@ -0,0 +1,98 @@ +@extends('layouts.main') + +@section('content') + +
+
+
+
+

{{__('Create role')}}

+
+ +
+
+
+ +
+
+ +
+ +
+
+
{{__('Roles List')}}
+ @can('admin.roles.write') + {{__('Create role')}} + @endcan +
+
+ +
+ + + + + + + + + + + + + + +
{{__("ID")}}{{__("Name")}}{{__("User count")}}{{__("Permissions count")}}{{__("Power")}}{{__("Actions")}}
+ +
+
+ + +
+ +
+ + +@endsection diff --git a/themes/default/views/admin/servers/edit.blade.php b/themes/default/views/admin/servers/edit.blade.php index cece37b96..db3dc8925 100644 --- a/themes/default/views/admin/servers/edit.blade.php +++ b/themes/default/views/admin/servers/edit.blade.php @@ -43,7 +43,7 @@
+
diff --git a/themes/default/views/admin/servers/index.blade.php b/themes/default/views/admin/servers/index.blade.php index 916eedd35..2a0f8791e 100644 --- a/themes/default/views/admin/servers/index.blade.php +++ b/themes/default/views/admin/servers/index.blade.php @@ -4,14 +4,15 @@
-
+
-

{{__('Servers')}}

+

{{ __('Servers') }}

@@ -27,27 +28,86 @@
- {{__('Servers')}} + {{ __('Servers') }}
- {{__('Sync')}} + {{ __('Sync') }}
- - @include('admin.servers.table') - -{{--
--}} -{{-- {!! $servers->links() !!}--}} -{{--
--}} - + + + + + + + + + + + + + + + +
{{ __('Status') }}{{ __('Name') }}{{ __('User') }}{{ __('Server id') }}{{ __('Product') }}{{ __('Suspended at') }}{{ __('Created at') }}{{ __('Actions') }}
- -
@endsection + + diff --git a/themes/default/views/admin/settings/index.blade.php b/themes/default/views/admin/settings/index.blade.php index 624f80b9e..fee27197e 100644 --- a/themes/default/views/admin/settings/index.blade.php +++ b/themes/default/views/admin/settings/index.blade.php @@ -4,26 +4,30 @@
-
+

{{ __('Settings') }}

- @if(!file_exists(base_path()."/install.lock")) + @if (!file_exists(base_path() . '/install.lock'))

{{ __('The installer is not locked!') }}

-

{{ __('please create a file called "install.lock" in your dashboard Root directory. Otherwise no settings will be loaded!') }}

- +

{{ __('please create a file called "install.lock" in your dashboard Root directory. Otherwise no settings will be loaded!') }} +

+ + +
@endif @@ -31,37 +35,294 @@
-
-
{{ __('Settings') }}
+
{{ __('Settings') }}
+
+ +
+
+ +
+ + +
+
+
- @foreach ($tabs as $tab) - @include($tab) - @endforeach -
+
+ @csrf + @method('POST') +
+
+ {{ __('FavIcon') }} + ... +
+ +
+ +
+ +
+ {{ __('Icon') }} + ... +
+ +
+ +
+ +
+ {{ __('Login-page Logo') }} + ... +
+ +
+ +
+
+
+ +
+ + +
+
+ @foreach ($settings as $category => $options) + @canany(['settings.' . strtolower($category) . '.read', 'settings.' . + strtolower($category) . '.write']) +
+ +
+ @csrf + @method('POST') + + + + @foreach ($options as $key => $value) + @if ($key == 'category_icon' || $key == 'settings_class') + @continue + @endif +
+
+ +
+ +
+
+ @if ($value['description']) + + @else + + @endif + +
+ @switch($value) + @case($value['type'] == 'string') + + @break + + @case($value['type'] == 'password') + + @break + + @case($value['type'] == 'boolean') + + @break + + @case($value['type'] == 'number') + + @break + + @case($value['type'] == 'select') + + @break + + @case($value['type'] == 'multiselect') + + @break + + @case($value['type'] == 'textarea') + + @break + @default + @endswitch + @error($key) +
+ {{ $message }} +
+ @enderror +
- +
+ +
+
+ @endforeach + + + + +
+
+ + +
+
+ + + +
+ @endcanany + @endforeach + +
+
+
-
@@ -72,27 +333,31 @@ + document.addEventListener('DOMContentLoaded', (event) => { + $('.custom-select').select2(); + }) + tinymce.init({ + selector: 'textarea', + promotion: false, + skin: "oxide-dark", + content_css: "dark", + branding: false, + height: 500, + width: '100%', + plugins: ['image', 'link'], + }); + @endsection diff --git a/themes/default/views/admin/store/create.blade.php b/themes/default/views/admin/store/create.blade.php index c7c17ed7c..e0556d7e7 100644 --- a/themes/default/views/admin/store/create.blade.php +++ b/themes/default/views/admin/store/create.blade.php @@ -152,6 +152,8 @@ class="form-control @error('description') is-invalid @enderror" {{__('Submit')}}
+ +
diff --git a/themes/default/views/admin/store/edit.blade.php b/themes/default/views/admin/store/edit.blade.php index 90590c45a..7fcaa524c 100644 --- a/themes/default/views/admin/store/edit.blade.php +++ b/themes/default/views/admin/store/edit.blade.php @@ -142,6 +142,8 @@ class="form-control @error('description') is-invalid @enderror" required="requir {{ __('Submit') }}
+ +
diff --git a/themes/default/views/moderator/ticket/blacklist.blade.php b/themes/default/views/admin/ticket/blacklist.blade.php similarity index 92% rename from themes/default/views/moderator/ticket/blacklist.blade.php rename to themes/default/views/admin/ticket/blacklist.blade.php index 403a5b903..2f2987d06 100644 --- a/themes/default/views/moderator/ticket/blacklist.blade.php +++ b/themes/default/views/admin/ticket/blacklist.blade.php @@ -4,7 +4,7 @@
-
+

{{ __('Ticket Blacklist') }}

@@ -12,7 +12,7 @@
@@ -29,7 +29,7 @@
-
{{__('Blacklist List')}}
+
{{__('Blacklist List')}}
@@ -60,9 +60,9 @@ class="fas fa-info-circle">
-
- @csrf -
+ + @csrf +
@@ -95,12 +97,12 @@ class="fas fa-info-circle"> processing: true, serverSide: true, stateSave: true, - ajax: "{{route('moderator.ticket.blacklist.datatable')}}", + ajax: "{{route('admin.ticket.blacklist.datatable')}}", columns: [ {data: 'user' , name : 'user.name'}, {data: 'status'}, {data: 'reason'}, - {data: 'created_at', sortable: false}, + {data: 'created_at'}, {data: 'actions', sortable: false}, ], fnDrawCallback: function( oSettings ) { @@ -179,4 +181,3 @@ function escapeHtml(str) { }); @endsection - diff --git a/themes/default/views/moderator/ticket/category.blade.php b/themes/default/views/admin/ticket/category.blade.php similarity index 89% rename from themes/default/views/moderator/ticket/category.blade.php rename to themes/default/views/admin/ticket/category.blade.php index 28f723589..04414502e 100644 --- a/themes/default/views/moderator/ticket/category.blade.php +++ b/themes/default/views/admin/ticket/category.blade.php @@ -12,7 +12,7 @@
@@ -56,8 +56,8 @@
{{__('Add Category')}}
-
- @csrf + + @csrf
@@ -65,6 +65,8 @@ + +
@@ -73,7 +75,7 @@
{{__('Edit Category')}}
-
+ @csrf @method('PATCH')
@@ -109,7 +113,7 @@ processing: true, serverSide: true, stateSave: true, - ajax: "{{route('moderator.ticket.category.datatable')}}", + ajax: "{{route('admin.ticket.category.datatable')}}", columns: [ {data: 'id'}, {data: 'name'}, @@ -129,4 +133,3 @@ @endsection - diff --git a/themes/default/views/moderator/ticket/index.blade.php b/themes/default/views/admin/ticket/index.blade.php similarity index 86% rename from themes/default/views/moderator/ticket/index.blade.php rename to themes/default/views/admin/ticket/index.blade.php index d71b4a759..489c33074 100644 --- a/themes/default/views/moderator/ticket/index.blade.php +++ b/themes/default/views/admin/ticket/index.blade.php @@ -4,7 +4,7 @@
-
+

{{__('Ticket')}}

@@ -12,7 +12,7 @@
@@ -28,9 +28,9 @@
-
{{__('Ticket List')}}
+
{{__('Ticket List')}}
- +
@@ -72,7 +72,7 @@ processing: true, serverSide: true, stateSave: true, - ajax: "{{route('moderator.ticket.datatable')}}", + ajax: "{{route('admin.ticket.datatable')}}", order: [[ 4, "desc" ]], columns: [ {data: 'category'}, diff --git a/themes/default/views/moderator/ticket/show.blade.php b/themes/default/views/admin/ticket/show.blade.php similarity index 82% rename from themes/default/views/moderator/ticket/show.blade.php rename to themes/default/views/admin/ticket/show.blade.php index dda8c1f92..ab2fdb4e7 100644 --- a/themes/default/views/moderator/ticket/show.blade.php +++ b/themes/default/views/admin/ticket/show.blade.php @@ -12,7 +12,7 @@
@@ -74,7 +74,7 @@

{{__("Created on")}}: {{ $ticket->created_at->diffForHumans() }}

@if($ticket->status=='Closed')
+ action="{{route('admin.ticket.changeStatus', ['ticket_id' => $ticket->ticket_id ])}}"> {{csrf_field()}} {{method_field("POST") }}
@else
+ action="{{route('admin.ticket.changeStatus', ['ticket_id' => $ticket->ticket_id ])}}"> {{csrf_field()}} {{method_field("POST") }} src="https://www.gravatar.com/avatar/{{ md5(strtolower($ticket->user->email)) }}?s=25" class="user-image" alt="User Image"> {{ $ticket->user->name }} - @if($ticket->user->role === "member") - Member - @elseif ($ticket->user->role === "client") - Client - @elseif ($ticket->user->role === "moderator") - Moderator - @elseif ($ticket->user->role === "admin") - Admin - @endif + @foreach ($ticket->user->roles as $role) + {{$role->name}} + @endforeach {{ $ticket->created_at->diffForHumans() }}
@@ -135,15 +129,9 @@ class="user-image" alt="User Image"> src="https://www.gravatar.com/avatar/{{ md5(strtolower($ticketcomment->user->email)) }}?s=25" class="user-image" alt="User Image"> {{ $ticketcomment->user->name }} - @if($ticketcomment->user->role === "member") - Member - @elseif ($ticketcomment->user->role === "client") - Client - @elseif ($ticketcomment->user->role === "moderator") - Moderator - @elseif ($ticketcomment->user->role === "admin") - Admin - @endif + @foreach ($ticketcomment->user->roles as $role) + {{$role->name}} + @endforeach {{ $ticketcomment->created_at->diffForHumans() }}
@@ -152,7 +140,7 @@ class="user-image" alt="User Image">
@endforeach
- + {!! csrf_field() !!}
diff --git a/themes/default/views/admin/usefullinks/create.blade.php b/themes/default/views/admin/usefullinks/create.blade.php index 2c09571a1..3eb63dc4b 100644 --- a/themes/default/views/admin/usefullinks/create.blade.php +++ b/themes/default/views/admin/usefullinks/create.blade.php @@ -34,7 +34,6 @@ @csrf -
{{__('Submit')}}
+ +
diff --git a/themes/default/views/admin/usefullinks/edit.blade.php b/themes/default/views/admin/usefullinks/edit.blade.php index 72d8c9a69..acbfee4e3 100644 --- a/themes/default/views/admin/usefullinks/edit.blade.php +++ b/themes/default/views/admin/usefullinks/edit.blade.php @@ -118,6 +118,8 @@ class="form-control @error('description') is-invalid @enderror"> {{__('Submit')}}
+ + diff --git a/themes/default/views/admin/users/edit.blade.php b/themes/default/views/admin/users/edit.blade.php index ad938f679..d6a339b79 100644 --- a/themes/default/views/admin/users/edit.blade.php +++ b/themes/default/views/admin/users/edit.blade.php @@ -97,26 +97,16 @@ class="form-control @error('server_limit') is-invalid @enderror"
- -
+ @foreach($roles as $role) + + @endforeach + +
@@ -128,15 +118,18 @@ class="form-control @error('referral_code') is-invalid @enderror" required="requ
@enderror - @error('role') -
- {{$message}} -
- @enderror + @error('role') +
+ {{$message}} +
+ @enderror
+ + + diff --git a/themes/default/views/admin/users/index.blade.php b/themes/default/views/admin/users/index.blade.php index e2ac9828b..be3cdfa30 100644 --- a/themes/default/views/admin/users/index.blade.php +++ b/themes/default/views/admin/users/index.blade.php @@ -84,11 +84,15 @@ function submitResult() { order: [ [11, "desc"] ], - columns: [{ + columns: [ + /* This broke the ability to search the table. Have to revisit later + { data: 'discordId', visible: false, name: 'discordUser.id' }, + */ + { data: 'pterodactyl_id', visible: false diff --git a/themes/default/views/admin/users/notifications.blade.php b/themes/default/views/admin/users/notifications.blade.php index 53a87f19a..13290c6f4 100644 --- a/themes/default/views/admin/users/notifications.blade.php +++ b/themes/default/views/admin/users/notifications.blade.php @@ -33,13 +33,20 @@ @method('POST')
-
- +
+
+ +
+
@error('all')
@@ -97,6 +104,8 @@ class="form-control @error('content') is-invalid @enderror">
+ +
@@ -126,6 +135,7 @@ class="form-control @error('content') is-invalid @enderror"> }) function initUserSelect(data) { + $('#roles').select2(); $('#users').select2({ ajax: { url: '/admin/users.json', diff --git a/themes/default/views/admin/users/show.blade.php b/themes/default/views/admin/users/show.blade.php index c9cf9b7cd..6bdc21921 100644 --- a/themes/default/views/admin/users/show.blade.php +++ b/themes/default/views/admin/users/show.blade.php @@ -6,14 +6,14 @@
-

{{__('Users')}}

+

{{ __('Users') }}

@@ -26,18 +26,18 @@
- @if($user->discordUser) + @if ($user->discordUser)
-

{{$user->discordUser->username}} {{$user->discordUser->locale}}

-

{{$user->discordUser->id}} +

{{ $user->discordUser->username }} {{ $user->discordUser->locale }}

+

{{ $user->discordUser->id }}

avatar
+ src="{{ $user->discordUser->getAvatar() }}" alt="avatar">
- @endsection + + diff --git a/themes/default/views/admin/vouchers/create.blade.php b/themes/default/views/admin/vouchers/create.blade.php index 4f28e1912..e539ed702 100644 --- a/themes/default/views/admin/vouchers/create.blade.php +++ b/themes/default/views/admin/vouchers/create.blade.php @@ -133,6 +133,8 @@ class="form-control @error('expires_at') is-invalid @enderror datetimepicker-inp {{__('Submit')}}
+ +
diff --git a/themes/default/views/admin/vouchers/edit.blade.php b/themes/default/views/admin/vouchers/edit.blade.php index 11c7c5e35..6f04a782e 100644 --- a/themes/default/views/admin/vouchers/edit.blade.php +++ b/themes/default/views/admin/vouchers/edit.blade.php @@ -136,6 +136,8 @@ class="form-control @error('expires_at') is-invalid @enderror datetimepicker-inp {{__('Submit')}} + + diff --git a/themes/default/views/admin/vouchers/index.blade.php b/themes/default/views/admin/vouchers/index.blade.php index 1f60e9aad..8746e9b81 100644 --- a/themes/default/views/admin/vouchers/index.blade.php +++ b/themes/default/views/admin/vouchers/index.blade.php @@ -4,7 +4,7 @@
-
+

{{__('Vouchers')}}

@@ -28,9 +28,9 @@
-
{{__('Vouchers')}}
+
{{__('Vouchers')}}
{{__('Create new')}} + class="mr-1 fas fa-plus">{{__('Create new')}}
@@ -81,7 +81,7 @@ function submitResult() { {data: 'code'}, {data: 'memo'}, {data: 'credits'}, - {data: 'uses'}, + {data: 'uses', sortable: false}, {data: 'expires_at'}, {data: 'actions', sortable: false}, ], diff --git a/themes/default/views/auth/login.blade.php b/themes/default/views/auth/login.blade.php index ba6d84e37..11dd5d3cb 100644 --- a/themes/default/views/auth/login.blade.php +++ b/themes/default/views/auth/login.blade.php @@ -1,20 +1,20 @@ @extends('layouts.app') @section('content') - + @php($website_settings = app(App\Settings\WebsiteSettings::class)) +

{{ __('Login') }} diff --git a/themes/default/views/auth/passwords/reset.blade.php b/themes/default/views/auth/passwords/reset.blade.php index 1e56b8453..ea38f1d59 100644 --- a/themes/default/views/auth/passwords/reset.blade.php +++ b/themes/default/views/auth/passwords/reset.blade.php @@ -67,6 +67,8 @@ class="btn btn-primary btn-block">{{ __('Change password') }}

+ +

diff --git a/themes/default/views/auth/register.blade.php b/themes/default/views/auth/register.blade.php index 783508c88..02acc2470 100644 --- a/themes/default/views/auth/register.blade.php +++ b/themes/default/views/auth/register.blade.php @@ -10,7 +10,7 @@ class="mr-1">{{ config('app.name', 'Laravel') }}

- @if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_USERS')) + @if (!app(App\Settings\UserSettings::class)->creation_enabled)
{{ __('Warning!') }}
{{ __('The system administrator has blocked the registration of new users') }} @@ -108,7 +108,7 @@ class="form-control @error('email') is-invalid @enderror"
- @if (config('SETTINGS::REFERRAL::ENABLED') == 'true') + @if (app(App\Settings\ReferralSettings::class)->enabled)
@endif - @if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') + @if (app(App\Settings\GeneralSettings::class)->recaptcha_enabled)
{!! htmlFormSnippet() !!} @error('g-recaptcha-response') @@ -133,8 +133,8 @@ class="form-control @error('email') is-invalid @enderror"
- @if (config('SETTINGS::SYSTEM:SHOW_TOS')) - + @php($website_settings = app(App\Settings\WebsiteSettings::class)) + @if ($website_settings->show_tos)
@@ -155,20 +154,10 @@ class="form-control @error('email') is-invalid @enderror"
-
- - - {{-- --}} + + + {{ __('I already have a membership') }} @@ -179,15 +168,15 @@ class="form-control @error('email') is-invalid @enderror" {{-- imprint and privacy policy --}}
- @if (config('SETTINGS::SYSTEM:SHOW_IMPRINT') == "true") - {{ __('Imprint') }} | - @endif - @if (config('SETTINGS::SYSTEM:SHOW_PRIVACY') == "true") - {{ __('Privacy') }} - @endif - @if (config('SETTINGS::SYSTEM:SHOW_TOS') == "true") - | {{ __('Terms of Service') }} - @endif + @if ($website_settings->show_imprint) + {{ __('Imprint') }} | + @endif + @if ($website_settings->show_privacy) + {{ __('Privacy') }} + @endif + @if ($website_settings->show_tos) + | {{ __('Terms of Service') }} + @endif
diff --git a/themes/default/views/auth/verify.blade.php b/themes/default/views/auth/verify.blade.php index 9f8c1bc0f..521400148 100644 --- a/themes/default/views/auth/verify.blade.php +++ b/themes/default/views/auth/verify.blade.php @@ -19,6 +19,8 @@
@csrf . + +
diff --git a/themes/default/views/home.blade.php b/themes/default/views/home.blade.php index 720e39aa1..f6bd50047 100644 --- a/themes/default/views/home.blade.php +++ b/themes/default/views/home.blade.php @@ -18,18 +18,19 @@
- @if(!file_exists(base_path()."/install.lock") && Auth::User()->role == "admin") + @if (!file_exists(base_path() . '/install.lock') && Auth::User()->hasRole("Admin"))

{{ __('The installer is not locked!') }}

-

{{ __('please create a file called "install.lock" in your dashboard Root directory. Otherwise no settings will be loaded!') }}

- +

{{ __('please create a file called "install.lock" in your dashboard Root directory. Otherwise no settings will be loaded!') }} +

+
@endif - @if(config("SETTINGS::SYSTEM:ALERT_ENABLED") && !empty(config("SETTINGS::SYSTEM:ALERT_MESSAGE"))) - - @if ($credits > 0.01 and $usage > 0) + @if ($credits > 0.01 && $usage > 0)
{{ __('Out of Credits in', ['credits' => CREDITS_DISPLAY_NAME]) }} + class="info-box-text">{{ __('Out of Credits in', ['credits' => $general_settings->credits_display_name]) }} {{ $boxText }}{{ $unit }}
@@ -106,7 +108,7 @@ class="info-box-text">{{ __('Out of Credits in', ['credits' => CREDITS_DISPLAY_N
- @if(config("SETTINGS::SYSTEM:MOTD_ENABLED") == "true") + @if ($website_settings->motd_enabled)

@@ -116,43 +118,40 @@ class="info-box-text">{{ __('Out of Credits in', ['credits' => CREDITS_DISPLAY_N

- {!! config('SETTINGS::SYSTEM:MOTD_MESSAGE', '') !!} + {!! $website_settings->motd_message !!}
@endif - @if(config("SETTINGS::SYSTEM:USEFULLINKS_ENABLED") == "true") -
-
-

- - {{ __('Useful Links') }} -

-
- -
- @foreach ($useful_links_dashboard as $useful_link) -
- -
- - {{ $useful_link->title }} - -
- {!! $useful_link->description !!} -
- @endforeach + @if ($website_settings->useful_links_enabled) +
+
+

+ + {{ __('Useful Links') }} +

+
+ +
+ @foreach ($useful_links_dashboard as $useful_link) +
+ +
+ + {{ $useful_link->title }} + +
+ {!! $useful_link->description !!} +
+ @endforeach +
+
- -
@endif -
-
@@ -168,15 +167,15 @@ class="info-box-text">{{ __('Out of Credits in', ['credits' => CREDITS_DISPLAY_N @foreach (Auth::user()->actions()->take(8)->orderBy('created_at', 'desc')->get() as $log)
  • - @if(str_starts_with($log->description,"created")) + @if (str_starts_with($log->description, 'created')) - @elseif(str_starts_with($log->description,"redeemed")) + @elseif(str_starts_with($log->description, 'redeemed')) - @elseif(str_starts_with($log->description,"deleted")) + @elseif(str_starts_with($log->description, 'deleted')) - @elseif(str_starts_with($log->description,"gained")) + @elseif(str_starts_with($log->description, 'gained')) - @elseif(str_starts_with($log->description,"updated")) + @elseif(str_starts_with($log->description, 'updated')) @endif {{ explode('\\', $log->subject_type)[2] }} @@ -192,7 +191,8 @@ class="info-box-text">{{ __('Out of Credits in', ['credits' => CREDITS_DISPLAY_N
  • - @if((config('SETTINGS::REFERRAL::ENABLED') ==true)) + @if ($referral_settings->enabled) +

    @@ -202,64 +202,72 @@ class="info-box-text">{{ __('Out of Credits in', ['credits' => CREDITS_DISPLAY_N

    - @if((config('SETTINGS::REFERRAL::ALLOWED') == "client" && Auth::user()->role != "member") || config('SETTINGS::REFERRAL::ALLOWED') == "everyone") + @if (Auth::user()->can("user.referral"))
    - {{__("Your referral URL")}}: - - {{__('Click to copy')}} + {{ __('Your referral URL') }}: + + {{ __('Click to copy') }}
    - {{__("Number of referred users:")}} {{$numberOfReferrals}} + {{ __('Number of referred users:') }} + {{ $numberOfReferrals }}
    - @if($partnerDiscount) -
    + @if ($partnerDiscount) +
    - - - - - - + + + + + + - - - - + + + +
    {{__('Your discount')}}{{__('Discount for your new users')}}{{__('Reward per registered user')}}{{__('New user payment commision')}}
    {{ __('Your discount') }}{{ __('Discount for your new users') }}{{ __('Reward per registered user') }}{{ __('New user payment commision') }}
    {{$partnerDiscount->partner_discount}}%{{$partnerDiscount->registered_user_discount}}%{{config('SETTINGS::REFERRAL::REWARD')}} {{config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME')}}{{($partnerDiscount->referral_system_commission==-1)?config('SETTINGS::REFERRAL:PERCENTAGE'):($partnerDiscount->referral_system_commission)}}%{{ $partnerDiscount->partner_discount }}%{{ $partnerDiscount->registered_user_discount }}%{{ $referral_settings->reward }} + {{ $general_settings->credits_display_name }}{{ $partnerDiscount->referral_system_commission == -1 ? $referral_settings->percentage : $partnerDiscount->referral_system_commission }}% +
    -
    +
    @else -
    +
    - - - - - + + + @if(in_array($referral_settings->mode, ["sign-up","both"])) @endif + @if(in_array($referral_settings->mode, ["commission","both"])) @endif + - - + @if(in_array($referral_settings->mode, ["sign-up","both"])) @endif + @if(in_array($referral_settings->mode, ["commission","both"])) @endif
    {{__('Reward per registered user')}}{{__('New user payment commision')}}
    {{ __('Reward per registered user') }}{{ __('New user payment commision') }}
    {{config('SETTINGS::REFERRAL::REWARD')}} {{config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME')}}{{config('SETTINGS::REFERRAL:PERCENTAGE')}}%{{ $referral_settings->reward }} {{ $general_settings->credits_display_name }}{{ $referral_settings->percentage }}%
    -
    +
    @endif @else - - {{__("Make a purchase to reveal your referral-URL")}} + + {{ __('Make a purchase to reveal your referral-URL') }} @endif
    @@ -267,33 +275,32 @@ class="fa fa-user-check mr-2"> @endif
    - - -
    -
    @@ -27,7 +28,7 @@ - @if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') + @if (app(App\Settings\GeneralSettings::class)->recaptcha_enabled) {!! htmlScriptTagJsApi() !!} @endif @vite('themes/default/sass/app.scss') diff --git a/themes/default/views/layouts/main.blade.php b/themes/default/views/layouts/main.blade.php index 6ab40a02b..509dc11af 100644 --- a/themes/default/views/layouts/main.blade.php +++ b/themes/default/views/layouts/main.blade.php @@ -2,22 +2,26 @@ + @php($website_settings = app(App\Settings\WebsiteSettings::class)) + @php($general_settings = app(App\Settings\GeneralSettings::class)) - - - exists('logo.png') ? asset('storage/logo.png') : asset('images/controlpanel_logo.png') }}' property="og:image"> + + + exists('logo.png') ? asset('storage/logo.png') : asset('images/ctrlpanel_logo.png') }}' + property="og:image"> {{ config('app.name', 'Laravel') }} - + {{-- --}} - + {{-- summernote --}} @@ -36,7 +40,7 @@ - + @vite('themes/default/sass/app.scss') @@ -52,49 +56,51 @@ class="fas fa-bars"> - @if (config('SETTINGS::DISCORD:INVITE_URL')) + @if (!empty($discord_settings->invite_url)) @endif - @if (config('SETTINGS::LOCALE:CLIENTS_CAN_CHANGE') == 'true') + @php($locale_settings = app(App\Settings\LocaleSettings::class)) + @if ($locale_settings->clients_can_change) @endif - @foreach($useful_links as $link) - + @foreach ($useful_links as $link) + @endforeach - -
    +
    @@ -187,7 +189,7 @@ class="form-control @error('email') is-invalid @enderror"
    -
    +
    {{ __('Change Password') }}
    @@ -239,8 +241,8 @@ class="form-control @error('new_password_confirmation') is-invalid @enderror"
    - @if (!empty(config('SETTINGS::DISCORD:CLIENT_ID')) && !empty(config('SETTINGS::DISCORD:CLIENT_SECRET'))) -
    + @if (!empty($discord_client_id) && !empty($discord_client_secret)) +
    @if (is_null(Auth::user()->discordUser)) {{ __('Link your discord account!') }}
    @@ -253,7 +255,7 @@ class="form-control @error('new_password_confirmation') is-invalid @enderror"
    - {{ __('Login with Discord') }} + {{ __('Login with Discord') }} @else
    @@ -261,7 +263,7 @@ class="form-control @error('new_password_confirmation') is-invalid @enderror"

    {{ __('You are verified!') }}

    -
    +
    @@ -302,8 +304,9 @@ class="fab fa-discord mr-1">{{ __('Re-Sync Discord') }}
    - + +
    @@ -365,4 +368,3 @@ function onClickCopy() { } @endsection - diff --git a/themes/default/views/servers/create.blade.php b/themes/default/views/servers/create.blade.php index a613c29f4..d1da2f8b0 100644 --- a/themes/default/views/servers/create.blade.php +++ b/themes/default/views/servers/create.blade.php @@ -35,17 +35,17 @@ class="row justify-content-center">
    {{ __('Server configuration') }}
    - @if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS')) + @if (!$server_creation_enabled)
    - The creation of new servers has been disabled for regular users, enable it again - {{ __('here') }}. + {{ __('The creation of new servers has been disabled for regular users, enable it again') }} + {{ __('here') }}.
    @endif @if ($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0)
    {{ __('Error!') }}

    - @if (Auth::user()->role == 'admin') + @if (Auth::user()->hasRole("Admin")) {{ __('Make sure to link your products to nodes and eggs.') }}
    {{ __('There has to be at least 1 valid product for server creation') }} {{ __('Sync now') }} @@ -133,32 +133,32 @@ class="custom-select">

    -
    - - + + -
    +
    +
    + {{ __('There seem to be no nodes available for this specification. Admins have been notified. Please try again later of contact us.') }} +
    -
    +
    -
    -
    - - + + + @@ -271,13 +288,14 @@ function serverApp() { name: null, selectedNest: null, selectedEgg: null, - selectedNode: null, + selectedLocation: null, selectedProduct: null, + locationDescription: null, //selected objects based on input selectedNestObject: {}, selectedEggObject: {}, - selectedNodeObject: {}, + selectedLocationObject: {}, selectedProductObject: {}, //values @@ -302,8 +320,9 @@ function serverApp() { this.locations = []; this.products = []; this.selectedEgg = 'null'; - this.selectedNode = 'null'; + this.selectedLocation = 'null'; this.selectedProduct = 'null'; + this.locationDescription = 'null'; this.eggs = this.eggsSave.filter(egg => egg.nest_id == this.selectedNest) @@ -336,8 +355,9 @@ function serverApp() { this.fetchedProducts = false; this.locations = []; this.products = []; - this.selectedNode = 'null'; + this.selectedLocation = 'null'; this.selectedProduct = 'null'; + this.locationDescription = null; let response = await axios.get(`{{ route('products.locations.egg') }}/${this.selectedEgg}`) .catch(console.error) @@ -347,7 +367,8 @@ function serverApp() { //automatically select the first entry if there is only 1 if (this.locations.length === 1 && this.locations[0]?.nodes?.length === 1) { - this.selectedNode = this.locations[0]?.nodes[0]?.id; + this.selectedLocation = this.locations[0]?.id; + await this.fetchProducts(); return; } @@ -359,19 +380,20 @@ function serverApp() { /** * @description fetch all available products based on the selected node * @note called whenever a node is selected - * @see selectedNode + * @see selectedLocation */ async fetchProducts() { this.loading = true; this.fetchedProducts = false; this.products = []; - this.selectedProduct = 'null'; + this.selectedProduct = null; let response = await axios.get( - `{{ route('products.products.node') }}/${this.selectedEgg}/${this.selectedNode}`) + `{{ route('products.products.location') }}/${this.selectedEgg}/${this.selectedLocation}`) .catch(console.error) this.fetchedProducts = true; + // TODO: Sortable by user chosen property (cpu, ram, disk...) this.products = response.data.sort((p1, p2) => parseInt(p1.price, 10) > parseInt(p2.price, 10) && 1 || -1) @@ -381,11 +403,19 @@ function serverApp() { product.cpu = product.cpu / 100; }) + //format price to have no decimals if it is a whole number + this.products.forEach(product => { + if (product.price % 1 === 0) { + product.price = Math.round(product.price); + } + }) + this.locationDescription = this.locations.find(location => location.id == this.selectedLocation).description ?? null; this.loading = false; this.updateSelectedObjects() }, + /** * @description map selected id's to selected objects * @note being used in the server info box @@ -394,10 +424,10 @@ function serverApp() { this.selectedNestObject = this.nests.find(nest => nest.id == this.selectedNest) ?? {} this.selectedEggObject = this.eggs.find(egg => egg.id == this.selectedEgg) ?? {} - this.selectedNodeObject = {}; + this.selectedLocationObject = {}; this.locations.forEach(location => { - if (!this.selectedNodeObject?.id) { - this.selectedNodeObject = location.nodes.find(node => node.id == this.selectedNode) ?? + if (!this.selectedLocationObject?.id) { + this.selectedLocationObject = location.nodes.find(node => node.id == this.selectedLocation) ?? {}; } }) @@ -413,17 +443,17 @@ function serverApp() { isFormValid() { if (Object.keys(this.selectedNestObject).length === 0) return false; if (Object.keys(this.selectedEggObject).length === 0) return false; - if (Object.keys(this.selectedNodeObject).length === 0) return false; + if (Object.keys(this.selectedLocationObject).length === 0) return false; if (Object.keys(this.selectedProductObject).length === 0) return false; return !!this.name; }, - getNodeInputText() { + getLocationInputText() { if (this.fetchedLocations) { if (this.locations.length > 0) { - return '{{ __('Please select a node ...') }}'; + return '{{ __('Please select a location ...') }}'; } - return '{{ __('No nodes found matching current configuration') }}' + return '{{ __('No location found matching current configuration') }}' } return '{{ __('---') }}'; }, diff --git a/themes/default/views/servers/index.blade.php b/themes/default/views/servers/index.blade.php index ef856b6a0..93f0baeba 100644 --- a/themes/default/views/servers/index.blade.php +++ b/themes/default/views/servers/index.blade.php @@ -27,18 +27,18 @@
    - Servers->count() >= Auth::user()->server_limit) - disabled="disabled" title="Server limit reached!" - @endif href="{{ route('servers.create') }}" - class="btn - @if (Auth::user()->Servers->count() >= Auth::user()->server_limit) disabled - @endif btn-primary"> + Servers->count() >= Auth::user()->server_limit) disabled="disabled" title="Server limit reached!" @endif + @cannot("user.server.create") disabled="disabled" title="No Permission!" @endcannot + href="{{ route('servers.create') }}" class="btn + @if (Auth::user()->Servers->count() >= Auth::user()->server_limit) disabled @endif + @cannot("user.server.create") disabled @endcannot + btn-primary"> + {{ __('Create Server') }} - @if (Auth::user()->Servers->count() > 0&&!empty(config('SETTINGS::MISC:PHPMYADMIN:URL'))) - Servers->count() > 0 && !empty($phpmyadmin_url)) + {{ __('Database') }} @@ -47,113 +47,253 @@ class="fas fa-database mr-2">{{ __('Database') }}
    @foreach ($servers as $server) - @if($server->location&&$server->node&&$server->nest&&$server->egg) -
    -
    -
    -
    {{ $server->name }} -
    -
    + @if($server->location && $server->node && $server->nest && $server->egg) +
    +
    +
    +
    {{ $server->name }}
    -
    -
    -
    -
    {{ __('Status') }}:
    -
    - - {{ $server->isSuspended() ? 'Suspended' : 'Active' }} -
    +
    +
    +
    +
    +
    {{ __('Status') }}:
    +
    + @if($server->suspended) + {{ __('Suspended') }} + @elseif($server->canceled) + {{ __('Canceled') }} + @else + {{ __('Active') }} + @endif +
    +
    +
    +
    + {{ __('Location') }}: +
    +
    + {{ $server->location }} +
    -
    -
    - {{ __('Location') }}: -
    -
    - {{ $server->location }} - -
    +
    +
    +
    + {{ __('Software') }}: +
    +
    + {{ $server->nest }}
    -
    -
    - {{ __('Software') }}: -
    -
    - {{ $server->nest }} -
    +
    +
    +
    + {{ __('Specification') }}: +
    +
    + {{ $server->egg }}
    -
    -
    - {{ __('Specification') }}: -
    -
    - {{ $server->egg }} -
    +
    +
    +
    + {{ __('Resource plan') }}: +
    +
    + {{ $server->product->name }} + + {{ __('Billing Period') }}: {{$server->product->billing_period}}" + class="fas fa-info-circle">
    -
    -
    - {{ __('Resource plan') }}: -
    -
    - {{ $server->product->name }} - - -
    +
    +
    +
    + {{ __('Next Billing Cycle') }}:
    -
    -
    - {{ __('Price') }}: - - ({{ CREDITS_DISPLAY_NAME }}) - -
    -
    -
    -
    -
    {{ __('per Hour') }}
    - - {{ number_format($server->product->getHourlyPrice(), 2, '.', '') }} - -
    -
    -
    {{ __('per Month') }} -
    - - {{ $server->product->getHourlyPrice() * 24 * 30 }} - -
    +
    + + @if ($server->suspended) + - + @else + @switch($server->product->billing_period) + @case('monthly') + {{ \Carbon\Carbon::parse($server->last_billed)->addMonth()->toDayDateTimeString(); }} + @break + @case('weekly') + {{ \Carbon\Carbon::parse($server->last_billed)->addWeek()->toDayDateTimeString(); }} + @break + @case('daily') + {{ \Carbon\Carbon::parse($server->last_billed)->addDay()->toDayDateTimeString(); }} + @break + @case('hourly') + {{ \Carbon\Carbon::parse($server->last_billed)->addHour()->toDayDateTimeString(); }} + @break + @case('quarterly') + {{ \Carbon\Carbon::parse($server->last_billed)->addMonths(3)->toDayDateTimeString(); }} + @break + @case('half-annually') + {{ \Carbon\Carbon::parse($server->last_billed)->addMonths(6)->toDayDateTimeString(); }} + @break + @case('annually') + {{ \Carbon\Carbon::parse($server->last_billed)->addYear()->toDayDateTimeString(); }} + @break + @default + {{ __('Unknown') }} + @endswitch + @endif + +
    +
    + +
    +
    + {{ __('Price') }}: + + ({{ $credits_display_name }}) + +
    +
    +
    + @if($server->product->billing_period == 'monthly') + {{ __('per Month') }} + @elseif($server->product->billing_period == 'half-annually') + {{ __('per 6 Months') }} + @elseif($server->product->billing_period == 'quarterly') + {{ __('per 3 Months') }} + @elseif($server->product->billing_period == 'annually') + {{ __('per Year') }} + @elseif($server->product->billing_period == 'weekly') + {{ __('per Week') }} + @elseif($server->product->billing_period == 'daily') + {{ __('per Day') }} + @elseif($server->product->billing_period == 'hourly') + {{ __('per Hour') }} + @endif + product->billing_period . ". " . __("This however calculates to ") . number_format($server->product->getMonthlyPrice(),2,",",".") . " ". $credits_display_name . " ". __('per Month')}}" + class="fas fa-info-circle">
    -
    + + {{ $server->product->price == round($server->product->price) ? round($server->product->price) : $server->product->price }} +
    +
    - + - @endif +
    + @endif @endforeach
    + + @endsection diff --git a/themes/default/views/servers/settings.blade.php b/themes/default/views/servers/settings.blade.php index 9fead6814..ae659be2b 100644 --- a/themes/default/views/servers/settings.blade.php +++ b/themes/default/views/servers/settings.blade.php @@ -33,7 +33,7 @@
    -

    SERVER NAME

    +

    {{ __('SERVER NAME') }}

    {{ $server->name }}
    @@ -54,9 +54,9 @@
    -

    CPU

    +

    {{ __('CPU') }}

    - @if($server->product->cpu == 0)Unlimited @else {{$server->product->cpu}} % @endif + @if($server->product->cpu == 0){{ __('Unlimited') }} @else {{$server->product->cpu}} % @endif
    @@ -75,9 +75,9 @@
    -

    Memory

    +

    {{ __('MEMORY') }}

    - @if($server->product->memory == 0)Unlimited @else {{$server->product->memory}}MB @endif + @if($server->product->memory == 0){{ __('Unlimited') }} @else {{$server->product->memory}}MB @endif
    @@ -96,9 +96,9 @@
    -

    STORAGE

    +

    {{ __('STORAGE') }}

    - @if($server->product->disk == 0)Unlimited @else {{$server->product->disk}}MB @endif + @if($server->product->disk == 0){{ __('Unlimited') }} @else {{$server->product->disk}}MB @endif
    @@ -204,6 +204,18 @@
    +
    +
    +
    + +
    +
    + + {{ $server->product->oom_killer ? __("enabled") : __("disabled") }} + +
    +
    +
    @@ -222,16 +234,12 @@ @@ -292,11 +299,12 @@ class="btn btn-danger btn-md"> {{__("This is an irreversible action, all files of this server will be removed!")}}
    diff --git a/themes/default/views/store/checkout.blade.php b/themes/default/views/store/checkout.blade.php index de61135de..66ac8c962 100644 --- a/themes/default/views/store/checkout.blade.php +++ b/themes/default/views/store/checkout.blade.php @@ -22,135 +22,311 @@ -
    +
    +
    + @csrf + @method('post') +
    + @if (!$productIsFree) +
    +
    -
    -
    - - - @csrf - @method('post') - -
    - -
    -
    -

    - {{ config('app.name', 'Laravel') }} - {{ __('Date') }}: - {{ Carbon\Carbon::now()->isoFormat('LL') }} -

    -
    - -
    +
    +
      +
    • +
      + + +
      + {{ __('Payment Methods') }} +
      + @foreach ($paymentGateways as $gateway) +
      +
      + + + + +
      +
      + @endforeach +
      +
      +
      +
    • + +
    • +
      +
      + @if ($isCouponsEnabled) + {{ __('Coupon') }} + +
      + + - -
      -
      - - - - - - - - - - - - - - - - - -
      {{ __('Quantity') }}{{ __('Product') }}{{ __('Description') }}{{ __('Subtotal') }}
      1{{ $product->quantity }} - {{ strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type }} - {{ $product->description }}{{ $product->formatToCurrency($product->price) }}
      - +
      + @error('coupon_code') +
      + {{ $message }} +
      + @enderror + @endif +
      +
      +
    • +
    -
    - - -
    - -
    - @if (!$productIsFree) -

    {{ __('Payment Methods') }}:

    - -
    - - @foreach ($paymentGateways as $gateway) -
    - -
    - @endforeach +
    + @endif +
    +
    +
    +

    + + Checkout details +

    +
    + +
    +
      +
    • +
      +
      {{ __('Product details') }}
      - @endif +
        +
      • + {{ __('Type') }} + {{ strtolower($product->type) == 'credits' ? $credits_display_name : $product->type }} +
      • +
      • + {{ __('Amount') }} + {{ $product->quantity }} +
      • +
      • + {{ __('Total Amount') }} + {{ $product->quantity }} +
      • +
      -
    - -
    -

    {{ __('Amount Due') }} - {{ Carbon\Carbon::now()->isoFormat('LL') }}

    + + + + +
  • +
    +
    {{ __('Description') }}
    + + {{ $product->description }} + +
    +
  • +
  • +
    +
    {{ __('Pricing') }}
    +
    + +
      +
    • + {{ __('Subtotal') }} + + {{ $product->formatToCurrency($product->price) }} +
    • +
      + {{ __('Tax') }} + @if ($taxpercent > 0) + ({{ $taxpercent }}%): + @endif + + + + {{ $product->formatToCurrency($taxvalue) }} +
      +
      + + {{ __('Coupon Discount') }} + + -
      - + + @if ($discountpercent && $discountvalue) - - - - +
      + {{ __('Partner Discount') }} + ({{ $discountpercent }}%) + + - {{ $product->formatToCurrency($discountvalue) }} + +
      @endif - - - - - - - - - - - - -
      {{ __('Discount') }} ({{ $discountpercent }}%):{{ $product->formatToCurrency($discountvalue) }}
      {{ __('Subtotal') }}:{{ $product->formatToCurrency($discountedprice) }}
      {{ __('Tax') }} ({{ $taxpercent }}%):{{ $product->formatToCurrency($taxvalue) }}
      {{ __('Total') }}:{{ $product->formatToCurrency($total) }}
      -
      -
      - -
  • - - - -
    -
    - -
    +
    +
    + {{ __('Total') }} + + + +
    + + + + + + +
    - - -
    -
    +
    +
    + + +
    +
    + + @endsection diff --git a/themes/default/views/store/index.blade.php b/themes/default/views/store/index.blade.php index 7d105867c..8fd58f5fd 100644 --- a/themes/default/views/store/index.blade.php +++ b/themes/default/views/store/index.blade.php @@ -1,5 +1,4 @@ @extends('layouts.main') - @section('content') @@ -11,10 +10,9 @@
    @@ -32,55 +30,56 @@
    - @if ($isPaymentSetup && $products->count() > 0) - + @if ($isStoreEnabled && $products->count() > 0)
    -
    {{ CREDITS_DISPLAY_NAME }}
    +
    {{ $credits_display_name }}
    - - - - - - + + + + + + - - @foreach ($products as $product) - - - - + + + - - - @endforeach + {{ $product->display }} + + + + @endforeach
    {{ __('Price') }}{{ __('Type') }}{{ __('Description') }}
    {{ __('Price') }}{{ __('Type') }}{{ __('Description') }}
    {{ $product->formatToCurrency($product->price) }}{{ strtolower($product->type) == 'credits' ? CREDITS_DISPLAY_NAME : $product->type }} - - @if(strtolower($product->type) == 'credits') - - @elseif (strtolower($product->type) == 'server slots') - - @endif + @foreach ($products as $product) +
    {{ $product->formatToCurrency($product->price) }}{{ strtolower($product->type) == 'credits' ? $credits_display_name : $product->type }} + + @if (strtolower($product->type) == 'credits') + + @elseif (strtolower($product->type) == 'server slots') + + @endif - {{ $product->display }}{{ __('Purchase') }} -
    {{ __('Purchase') }} +
    - @else
    -

    @if ($products->count() == 0) {{ __('There are no store products!') }} @else {{ __('The store is not correctly configured!') }} @endif +

    + @if ($products->count() == 0) + {{ __('There are no store products!') }} + @else + {{ __('The store is not correctly configured!') }} + @endif

    - @endif diff --git a/themes/default/views/ticket/create.blade.php b/themes/default/views/ticket/create.blade.php index 7da409cfa..a8e1b1a20 100644 --- a/themes/default/views/ticket/create.blade.php +++ b/themes/default/views/ticket/create.blade.php @@ -44,14 +44,16 @@ @endif
    - @if ($servers->count() >= 1) +
    @if ($errors->has('category')) @@ -60,7 +62,7 @@ @endif
    - @endif +
    @@ -132,4 +147,3 @@ @endsection - diff --git a/themes/default/views/ticket/index.blade.php b/themes/default/views/ticket/index.blade.php index b23048e8b..d32fe26e0 100644 --- a/themes/default/views/ticket/index.blade.php +++ b/themes/default/views/ticket/index.blade.php @@ -30,8 +30,8 @@
    @@ -66,8 +66,7 @@ class="fas fa-info-circle">
    -

    {{__("Can't start your server? Need an additional port? Do you have any other questions? Let us know by - opening a ticket.")}}

    +

    {!! $ticketsettings->information !!}

    diff --git a/themes/default/views/ticket/show.blade.php b/themes/default/views/ticket/show.blade.php index 7401038fd..2be80d06f 100644 --- a/themes/default/views/ticket/show.blade.php +++ b/themes/default/views/ticket/show.blade.php @@ -114,15 +114,9 @@ class="fas fa-times">{{__("Close")}} src="https://www.gravatar.com/avatar/{{ md5(strtolower($ticket->user->email)) }}?s=25" class="user-image" alt="User Image"> {{ $ticket->user->name }} - @if($ticket->user->role === "member") - Member - @elseif ($ticket->user->role === "client") - Client - @elseif ($ticket->user->role === "moderator") - Moderator - @elseif ($ticket->user->role === "admin") - Admin - @endif + @foreach ($ticket->user->roles as $role) + {{$role->name}} + @endforeach {{ $ticket->created_at->diffForHumans() }} @@ -138,15 +132,9 @@ class="badge badge-primary">{{ $ticket->created_at->diffForHumans() }} src="https://www.gravatar.com/avatar/{{ md5(strtolower($ticketcomment->user->email)) }}?s=25" class="user-image" alt="User Image"> {{ $ticketcomment->user->name }} - @if($ticketcomment->user->role === "member") - Member - @elseif ($ticketcomment->user->role === "client") - Client - @elseif ($ticketcomment->user->role === "moderator") - Moderator - @elseif ($ticketcomment->user->role === "admin") - Admin - @endif + @foreach ($ticketcomment->user->roles as $role) + {{$role->name}} + @endforeach {{ $ticketcomment->created_at->diffForHumans() }} diff --git a/themes/default/views/vendor/invoices/templates/controlpanel.blade.php b/themes/default/views/vendor/invoices/templates/ctrlpanel.blade.php similarity index 100% rename from themes/default/views/vendor/invoices/templates/controlpanel.blade.php rename to themes/default/views/vendor/invoices/templates/ctrlpanel.blade.php diff --git a/transferusers.php b/transferusers.php new file mode 100644 index 000000000..89496b3d3 --- /dev/null +++ b/transferusers.php @@ -0,0 +1,95 @@ +fetch_assoc()) { + $id = $pterouser["id"]; + $username = $pterouser["username"]; + $email = $pterouser['email']; + $password = $pterouser['password']; + $now = date("Y-m-d H:i:s"); + $role = "member"; + $referral_code = generateRandomString(); + try { + if ($pterouser["root_admin"]) { + $role = "admin"; + } + $checkusersql = mysqli_query($cpggdb, "SELECT * FROM `users` WHERE `email` = '$email'"); + if (mysqli_num_rows($checkusersql) > 0) { + echo "User ".$email." exists. Skipping! \n"; + } else { + + + $sql = "INSERT INTO `users` (`id`, `name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `avatar`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`, `ip`, `last_seen`, `discord_verified_at`, `suspended`, `referral_code`) VALUES (NULL, '$username', '$role', '$init_credits', '$serverlimit', '$id', NULL, '$email', NULL, '$password', NULL, '$now', NULL, NULL, NULL, NULL, '0', '$referral_code')"; + $res = mysqli_query($cpggdb, $sql); + echo "User ".$email." created \n"; + } + + } catch (Exception $e) { + echo "Fail: " . $e; + } +} + + +?> \ No newline at end of file