├── .git-blame-ignore-revs ├── .github ├── CODEOWNERS ├── contributing.md ├── dependabot.yml ├── issue_template.md ├── issue_template.md.license └── workflows │ ├── appstore-build-publish.yml │ ├── integration.yml │ ├── lint-info-xml.yml │ ├── lint-php-cs.yml │ ├── lint-php.yml │ ├── phpunit-mysql.yml │ ├── phpunit-oci.yml │ ├── phpunit-pgsql.yml │ ├── phpunit-sqlite.yml │ ├── phpunit-summary-when-unrelated.yml │ ├── pr-feedback.yml │ ├── psalm-matrix.yml │ └── reuse.yml ├── .gitignore ├── .patches └── php-saml-600.patch ├── .php-cs-fixer.dist.php ├── .scrutinizer.yml ├── .tx └── config ├── AUTHORS.md ├── CHANGELOG.md ├── LICENSE ├── LICENSES ├── AGPL-3.0-or-later.txt ├── CC0-1.0.txt └── MIT.txt ├── Makefile ├── README.md ├── REUSE.toml ├── appinfo ├── info.xml └── routes.php ├── composer.json ├── composer.lock ├── css ├── admin.css ├── personal.css └── selectUserBackEnd.css ├── img ├── app-dark.svg └── app.svg ├── js ├── admin.js ├── selectUserBackEnd.js ├── timezone.js └── vendor │ └── jstz.min.js ├── l10n ├── .gitkeep ├── af.js ├── af.json ├── ar.js ├── ar.json ├── ast.js ├── ast.json ├── bg.js ├── bg.json ├── ca.js ├── ca.json ├── cs.js ├── cs.json ├── da.js ├── da.json ├── de.js ├── de.json ├── de_DE.js ├── de_DE.json ├── el.js ├── el.json ├── en_GB.js ├── en_GB.json ├── es.js ├── es.json ├── es_419.js ├── es_419.json ├── es_AR.js ├── es_AR.json ├── es_CL.js ├── es_CL.json ├── es_CO.js ├── es_CO.json ├── es_CR.js ├── es_CR.json ├── es_DO.js ├── es_DO.json ├── es_EC.js ├── es_EC.json ├── es_GT.js ├── es_GT.json ├── es_HN.js ├── es_HN.json ├── es_MX.js ├── es_MX.json ├── es_NI.js ├── es_NI.json ├── es_PA.js ├── es_PA.json ├── es_PE.js ├── es_PE.json ├── es_PR.js ├── es_PR.json ├── es_PY.js ├── es_PY.json ├── es_SV.js ├── es_SV.json ├── es_UY.js ├── es_UY.json ├── et_EE.js ├── et_EE.json ├── eu.js ├── eu.json ├── fa.js ├── fa.json ├── fi.js ├── fi.json ├── fr.js ├── fr.json ├── ga.js ├── ga.json ├── gl.js ├── gl.json ├── he.js ├── he.json ├── hr.js ├── hr.json ├── hu.js ├── hu.json ├── ia.js ├── ia.json ├── id.js ├── id.json ├── is.js ├── is.json ├── it.js ├── it.json ├── ja.js ├── ja.json ├── ka.js ├── ka.json ├── ka_GE.js ├── ka_GE.json ├── ko.js ├── ko.json ├── lt_LT.js ├── lt_LT.json ├── lv.js ├── lv.json ├── nb.js ├── nb.json ├── nl.js ├── nl.json ├── oc.js ├── oc.json ├── pl.js ├── pl.json ├── pt_BR.js ├── pt_BR.json ├── pt_PT.js ├── pt_PT.json ├── ro.js ├── ro.json ├── ru.js ├── ru.json ├── sc.js ├── sc.json ├── sk.js ├── sk.json ├── sl.js ├── sl.json ├── sq.js ├── sq.json ├── sr.js ├── sr.json ├── sv.js ├── sv.json ├── th.js ├── th.json ├── tr.js ├── tr.json ├── ug.js ├── ug.json ├── uk.js ├── uk.json ├── vi.js ├── vi.json ├── zh_CN.js ├── zh_CN.json ├── zh_HK.js ├── zh_HK.json ├── zh_TW.js └── zh_TW.json ├── lib ├── AppInfo │ └── Application.php ├── Command │ ├── ConfigCreate.php │ ├── ConfigDelete.php │ ├── ConfigGet.php │ ├── ConfigSet.php │ ├── GetMetadata.php │ └── GroupMigrationCopyIncomplete.php ├── Controller │ ├── SAMLController.php │ ├── SettingsController.php │ └── TimezoneController.php ├── DavPlugin.php ├── Db │ ├── ConfigurationsEntity.php │ └── ConfigurationsMapper.php ├── Exceptions │ ├── GroupNotFoundException.php │ ├── NoUserFoundException.php │ ├── NonMigratableGroupException.php │ └── UserFilterViolationException.php ├── GroupBackend.php ├── GroupManager.php ├── Helper │ └── TXmlHelper.php ├── Jobs │ └── MigrateGroups.php ├── Listener │ ├── LoadAdditionalScriptsListener.php │ └── SabrePluginEventListener.php ├── Middleware │ └── OnlyLoggedInMiddleware.php ├── Migration │ ├── CleanupRemovedConfig.php │ ├── RememberLocalGroupsForPotentialMigrations.php │ ├── TransferGroupMembers.php │ ├── Version3001Date20200630193443.php │ ├── Version5000Date20211025124248.php │ ├── Version6000Date20220912152700.php │ └── Version6001Date20240202183823.php ├── SAMLSettings.php ├── Service │ └── GroupMigration.php ├── Settings │ ├── Admin.php │ └── Section.php ├── UserBackend.php ├── UserData.php └── UserResolver.php ├── psalm.xml ├── rector.php ├── screenshots ├── 1.png └── 2.png ├── templates ├── admin.php ├── error.php ├── login_post.php ├── notPermitted.php ├── notProvisioned.php └── selectUserBackEnd.php ├── tests ├── integration │ ├── composer.json │ ├── composer.lock │ └── features │ │ ├── EnvironmentVariable.feature │ │ ├── Shibboleth.feature │ │ └── bootstrap │ │ └── FeatureContext.php ├── psalm-baseline.xml ├── stub.phpstub └── unit │ ├── AppInfo │ └── ApplicationTest.php │ ├── Command │ └── GetMetadataTest.php │ ├── Controller │ └── SAMLControllerTest.php │ ├── GroupBackendTest.php │ ├── GroupManagerTest.php │ ├── Middleware │ └── OnlyLoggedInMiddlewareTest.php │ ├── Settings │ ├── AdminTest.php │ └── SectionTest.php │ ├── UserBackendTest.php │ ├── UserDataTest.php │ ├── bootstrap.php │ └── phpunit.xml └── vendor-bin ├── cs-fixer ├── composer.json └── composer.lock ├── psalm ├── composer.json └── composer.lock └── rector ├── composer.json └── composer.lock /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # .git-blame-ignore-revs 2 | 3 | # SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 4 | # SPDX-License-Identifier: AGPL-3.0-or-later 5 | 6 | # Update to coding-standard 1.3.1 7 | 21f740715b4acea791cf14958bd1076230990e32 8 | # Update to coding-standard 1.3.2 9 | 5a42da490862ec9f0a7eef5702fc4a669d5c53b1 10 | # Introducing rector 11 | 4f58f1154a933711f823be65bb4d2bd4e92d0794 12 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | /appinfo/info.xml @blizzz @juliushaertl 2 | 3 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | 5 | ## Submitting issues 6 | 7 | If you have questions about how to install or use Nextcloud, please direct these to our [forum][forum]. We are also available on [IRC][irc]. 8 | 9 | ### Short version 10 | 11 | * The [**issue template can be found here**][template]. Please always use the issue template when reporting issues. 12 | 13 | ### Guidelines 14 | * Please search the existing issues first, it's likely that your issue was already reported or even fixed. 15 | - Go to one of the repositories, click "issues" and type any word in the top search/command bar. 16 | - You can also filter by appending e. g. "state:open" to the search string. 17 | - More info on [search syntax within github](https://help.github.com/articles/searching-issues) 18 | * This repository ([User SAML](https://github.com/nextcloud/user_saml/issues)) is *only* for issues within the User SAML code. 19 | * __SECURITY__: Report any potential security bug to us via [our HackerOne page](https://hackerone.com/nextcloud) or security@nextcloud.com following our [security policy](https://nextcloud.com/security/) instead of filing an issue in our bug tracker 20 | * Report the issue using our [template][template], it includes all the information we need to track down the issue. 21 | 22 | Help us to maximize the effort we can spend fixing issues and adding new features, by not reporting duplicate issues. 23 | 24 | [template]: https://raw.github.com/nextcloud/user_saml/master/.github/issue_template.md 25 | [forum]: https://help.nextcloud.com/ 26 | [irc]: https://webchat.freenode.net/?channels=nextcloud 27 | 28 | ### Contribute Code and translations 29 | Please check [server's contribution guidelines](https://github.com/nextcloud/server/blob/master/CONTRIBUTING.md#contributing-to-source-code) for further information about contributing code and translations. 30 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | version: 2 4 | updates: 5 | - package-ecosystem: composer 6 | directories: 7 | - / 8 | - /vendor-bin/cs-fixer 9 | - /vendor-bin/psalm 10 | - /tests/integration 11 | schedule: 12 | interval: daily 13 | time: "03:00" 14 | timezone: Europe/Paris 15 | open-pull-requests-limit: 10 16 | labels: 17 | - 3. to review 18 | - dependencies 19 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 8 | ### Steps to reproduce 9 | 1. 10 | 2. 11 | 3. 12 | 13 | ### Expected behaviour 14 | Tell us what should happen 15 | 16 | ### Actual behaviour 17 | Tell us what happens instead 18 | 19 | ### Server configuration 20 | 23 | 24 | **Operating system**: 25 | 26 | **Web server:** 27 | 28 | **Database:** 29 | 30 | **PHP version:** 31 | 32 | **Nextcloud version:** (see Nextcloud admin page) 33 | 34 | **Where did you install Nextcloud from:** 35 | 36 | 37 | **List of activated apps:** 38 | 39 | ``` 40 | If you have access to your command line run e.g.: 41 | sudo -u www-data php occ app:list 42 | from within your Nextcloud installation folder 43 | ``` 44 | 45 | **Nextcloud configuration:** 46 | 47 | ``` 48 | If you have access to your command line run e.g.: 49 | sudo -u www-data php occ config:list system 50 | from within your Nextcloud installation folder 51 | 52 | or 53 | 54 | Insert your config.php content here 55 | Make sure to remove all sensitive content such as passwords. (e.g. database password, passwordsalt, secret, smtp password, …) 56 | ``` 57 | 58 | ### Client configuration 59 | **Browser:** 60 | 61 | **Operating system:** 62 | 63 | ### Logs 64 | 65 | #### Nextcloud log (data/owncloud.log) 66 | ``` 67 | Insert your Nextcloud log here 68 | ``` 69 | 70 | #### Browser log 71 | ``` 72 | Insert your browser log here, this could for example include: 73 | 74 | a) The javascript console log 75 | b) The network log 76 | c) ... 77 | ``` 78 | -------------------------------------------------------------------------------- /.github/issue_template.md.license: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors 2 | SPDX-License-Identifier: AGPL-3.0-or-later 3 | -------------------------------------------------------------------------------- /.github/workflows/lint-info-xml.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Lint info.xml 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-info-xml-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | xml-linters: 22 | runs-on: ubuntu-latest-low 23 | 24 | name: info.xml lint 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Download schema 32 | run: wget https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd 33 | 34 | - name: Lint info.xml 35 | uses: ChristophWurst/xmllint-action@36f2a302f84f8c83fceea0b9c59e1eb4a616d3c1 # v1.2 36 | with: 37 | xml-file: ./appinfo/info.xml 38 | xml-schema-file: ./info.xsd 39 | -------------------------------------------------------------------------------- /.github/workflows/lint-php-cs.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Lint php-cs 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-php-cs-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | lint: 22 | runs-on: ubuntu-latest 23 | 24 | name: php-cs 25 | 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 29 | with: 30 | persist-credentials: false 31 | 32 | - name: Get php version 33 | id: versions 34 | uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 35 | 36 | - name: Set up php${{ steps.versions.outputs.php-min }} 37 | uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2.33.0 38 | with: 39 | php-version: ${{ steps.versions.outputs.php-min }} 40 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 41 | coverage: none 42 | ini-file: development 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: Install dependencies 47 | run: | 48 | composer remove nextcloud/ocp --dev 49 | composer i 50 | 51 | - name: Lint 52 | run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 ) 53 | -------------------------------------------------------------------------------- /.github/workflows/lint-php.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Lint php 10 | 11 | on: pull_request 12 | 13 | permissions: 14 | contents: read 15 | 16 | concurrency: 17 | group: lint-php-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | matrix: 22 | runs-on: ubuntu-latest-low 23 | outputs: 24 | php-versions: ${{ steps.versions.outputs.php-versions }} 25 | steps: 26 | - name: Checkout app 27 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Get version matrix 32 | id: versions 33 | uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.0.0 34 | 35 | php-lint: 36 | runs-on: ubuntu-latest 37 | needs: matrix 38 | strategy: 39 | matrix: 40 | php-versions: ${{fromJson(needs.matrix.outputs.php-versions)}} 41 | 42 | name: php-lint 43 | 44 | steps: 45 | - name: Checkout 46 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 47 | with: 48 | persist-credentials: false 49 | 50 | - name: Set up php ${{ matrix.php-versions }} 51 | uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2.33.0 52 | with: 53 | php-version: ${{ matrix.php-versions }} 54 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 55 | coverage: none 56 | ini-file: development 57 | env: 58 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 59 | 60 | - name: Lint 61 | run: composer run lint 62 | 63 | summary: 64 | permissions: 65 | contents: none 66 | runs-on: ubuntu-latest-low 67 | needs: php-lint 68 | 69 | if: always() 70 | 71 | name: php-lint-summary 72 | 73 | steps: 74 | - name: Summary status 75 | run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi 76 | -------------------------------------------------------------------------------- /.github/workflows/phpunit-summary-when-unrelated.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | name: PHPUnit summary 9 | 10 | on: 11 | pull_request: 12 | paths-ignore: 13 | - '.github/workflows/**' 14 | - 'appinfo/**' 15 | - 'lib/**' 16 | - 'templates/**' 17 | - 'tests/**' 18 | - 'vendor/**' 19 | - 'vendor-bin/**' 20 | - '.php-cs-fixer.dist.php' 21 | - 'composer.json' 22 | - 'composer.lock' 23 | 24 | permissions: 25 | contents: read 26 | 27 | jobs: 28 | summary-mysql: 29 | permissions: 30 | contents: none 31 | runs-on: ubuntu-latest 32 | 33 | name: phpunit-mysql-summary 34 | 35 | steps: 36 | - name: Summary status 37 | run: 'echo "No PHP files changed, skipped PHPUnit"' 38 | 39 | summary-oci: 40 | permissions: 41 | contents: none 42 | runs-on: ubuntu-latest 43 | 44 | name: phpunit-oci-summary 45 | 46 | steps: 47 | - name: Summary status 48 | run: 'echo "No PHP files changed, skipped PHPUnit"' 49 | 50 | summary-pgsql: 51 | permissions: 52 | contents: none 53 | runs-on: ubuntu-latest 54 | 55 | name: phpunit-pgsql-summary 56 | 57 | steps: 58 | - name: Summary status 59 | run: 'echo "No PHP files changed, skipped PHPUnit"' 60 | 61 | summary-sqlite: 62 | permissions: 63 | contents: none 64 | runs-on: ubuntu-latest 65 | 66 | name: phpunit-sqlite-summary 67 | 68 | steps: 69 | - name: Summary status 70 | run: 'echo "No PHP files changed, skipped PHPUnit"' 71 | -------------------------------------------------------------------------------- /.github/workflows/pr-feedback.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | # SPDX-FileCopyrightText: 2023-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-FileCopyrightText: 2023 Marcel Klehr 8 | # SPDX-FileCopyrightText: 2023 Joas Schilling <213943+nickvergessen@users.noreply.github.com> 9 | # SPDX-FileCopyrightText: 2023 Daniel Kesselberg 10 | # SPDX-FileCopyrightText: 2023 Florian Steffens 11 | # SPDX-License-Identifier: MIT 12 | 13 | name: 'Ask for feedback on PRs' 14 | on: 15 | schedule: 16 | - cron: '30 1 * * *' 17 | 18 | permissions: 19 | contents: read 20 | pull-requests: write 21 | 22 | jobs: 23 | pr-feedback: 24 | if: ${{ github.repository_owner == 'nextcloud' }} 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: The get-github-handles-from-website action 28 | uses: marcelklehr/get-github-handles-from-website-action@06b2239db0a48fe1484ba0bfd966a3ab81a08308 # v1.0.1 29 | id: scrape 30 | with: 31 | website: 'https://nextcloud.com/team/' 32 | 33 | - name: Get blocklist 34 | id: blocklist 35 | run: | 36 | blocklist=$(curl https://raw.githubusercontent.com/nextcloud/.github/master/non-community-usernames.txt | paste -s -d, -) 37 | echo "blocklist=$blocklist" >> "$GITHUB_OUTPUT" 38 | 39 | - uses: nextcloud/pr-feedback-action@1883b38a033fb16f576875e0cf45f98b857655c4 # main 40 | with: 41 | feedback-message: | 42 | Hello there, 43 | Thank you so much for taking the time and effort to create a pull request to our Nextcloud project. 44 | 45 | We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. 46 | 47 | Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 48 | 49 | Thank you for contributing to Nextcloud and we hope to hear from you soon! 50 | 51 | (If you believe you should not receive this message, you can add yourself to the [blocklist](https://github.com/nextcloud/.github/blob/master/non-community-usernames.txt).) 52 | days-before-feedback: 14 53 | start-date: '2024-04-30' 54 | exempt-authors: '${{ steps.blocklist.outputs.blocklist }},${{ steps.scrape.outputs.users }}' 55 | exempt-bots: true 56 | -------------------------------------------------------------------------------- /.github/workflows/psalm-matrix.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | # 6 | # SPDX-FileCopyrightText: 2022-2024 Nextcloud GmbH and Nextcloud contributors 7 | # SPDX-License-Identifier: MIT 8 | 9 | name: Static analysis 10 | 11 | on: pull_request 12 | 13 | concurrency: 14 | group: psalm-${{ github.head_ref || github.run_id }} 15 | cancel-in-progress: true 16 | 17 | permissions: 18 | contents: read 19 | 20 | jobs: 21 | matrix: 22 | runs-on: ubuntu-latest-low 23 | outputs: 24 | ocp-matrix: ${{ steps.versions.outputs.ocp-matrix }} 25 | steps: 26 | - name: Checkout app 27 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Get version matrix 32 | id: versions 33 | uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1 34 | 35 | - name: Check enforcement of minimum PHP version ${{ steps.versions.outputs.php-min }} in psalm.xml 36 | run: grep 'phpVersion="${{ steps.versions.outputs.php-min }}' psalm.xml 37 | 38 | static-analysis: 39 | runs-on: ubuntu-latest 40 | needs: matrix 41 | strategy: 42 | # do not stop on another job's failure 43 | fail-fast: false 44 | matrix: ${{ fromJson(needs.matrix.outputs.ocp-matrix) }} 45 | 46 | name: static-psalm-analysis ${{ matrix.ocp-version }} 47 | steps: 48 | - name: Checkout 49 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 50 | with: 51 | persist-credentials: false 52 | 53 | - name: Set up php${{ matrix.php-min }} 54 | uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2.33.0 55 | with: 56 | php-version: ${{ matrix.php-min }} 57 | extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite 58 | coverage: none 59 | ini-file: development 60 | # Temporary workaround for missing pcntl_* in PHP 8.3 61 | ini-values: disable_functions= 62 | env: 63 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 64 | 65 | - name: Install dependencies 66 | run: | 67 | composer remove nextcloud/ocp --dev 68 | composer i 69 | 70 | 71 | - name: Install dependencies # zizmor: ignore[template-injection] 72 | run: composer require --dev 'nextcloud/ocp:${{ matrix.ocp-version }}' --ignore-platform-reqs --with-dependencies 73 | 74 | - name: Run coding standards check 75 | run: composer run psalm -- --threads=1 --monochrome --no-progress --output-format=github 76 | 77 | summary: 78 | runs-on: ubuntu-latest-low 79 | needs: static-analysis 80 | 81 | if: always() 82 | 83 | name: static-psalm-analysis-summary 84 | 85 | steps: 86 | - name: Summary status 87 | run: if ${{ needs.static-analysis.result != 'success' }}; then exit 1; fi 88 | -------------------------------------------------------------------------------- /.github/workflows/reuse.yml: -------------------------------------------------------------------------------- 1 | # This workflow is provided via the organization template repository 2 | # 3 | # https://github.com/nextcloud/.github 4 | # https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization 5 | 6 | # SPDX-FileCopyrightText: 2022 Free Software Foundation Europe e.V. 7 | # 8 | # SPDX-License-Identifier: CC0-1.0 9 | 10 | name: REUSE Compliance Check 11 | 12 | on: [pull_request] 13 | 14 | permissions: 15 | contents: read 16 | 17 | jobs: 18 | reuse-compliance-check: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 23 | with: 24 | persist-credentials: false 25 | 26 | - name: REUSE Compliance Check 27 | uses: fsfe/reuse-action@bb774aa972c2a89ff34781233d275075cbddf542 # v5.0.0 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | build 4 | vendor/ 5 | .php_cs.cache 6 | .php-cs-fixer.cache 7 | 8 | !/tests/integration/ 9 | 10 | .ackrc 11 | -------------------------------------------------------------------------------- /.patches/php-saml-600.patch: -------------------------------------------------------------------------------- 1 | SPDX-FileCopyrightText: 2024 Nextcloud GmbH 2 | SPDX-License-Identifier: MIT 3 | From 3628572e9916f747a450484c35c51a5164b00c54 Mon Sep 17 00:00:00 2001 4 | From: Arthur Schiwon 5 | Date: Fri, 8 Nov 2024 18:05:46 +0100 6 | Subject: [PATCH] Include PHP 8.4 test coverage 7 | 8 | - also fixes deprecations on implicit null 9 | 10 | Signed-off-by: Arthur Schiwon 11 | --- 12 | .github/workflows/php-package.yml | 6 +++--- 13 | src/Saml2/Auth.php | 2 +- 14 | src/Saml2/Settings.php | 2 +- 15 | src/Saml2/Utils.php | 2 +- 16 | 4 files changed, 6 insertions(+), 6 deletions(-) 17 | 18 | diff --git a/.github/workflows/php-package.yml b/.github/workflows/php-package.yml 19 | index 7840700a..6321b7ef 100644 20 | --- a/.github/workflows/php-package.yml 21 | +++ b/.github/workflows/php-package.yml 22 | @@ -16,7 +16,7 @@ jobs: 23 | fail-fast: false 24 | matrix: 25 | operating-system: ['ubuntu-latest'] 26 | - php-versions: [7.3, 7.4, 8.0, 8.1, 8.2, 8.3] 27 | + php-versions: [7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4] 28 | steps: 29 | - name: Setup PHP, with composer and extensions 30 | uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php 31 | @@ -46,9 +46,9 @@ jobs: 32 | php vendor/bin/phploc src/. 33 | mkdir -p tests/build/dependences 34 | php vendor/bin/pdepend --summary-xml=tests/build/logs/dependence-summary.xml --jdepend-chart=tests/build/dependences/jdepend.svg --overview-pyramid=tests/build/dependences/pyramid.svg src/. 35 | - 36 | + 37 | - name: PHP Code Sniffer 38 | run: php vendor/bin/phpcs --standard=tests/ZendModStandard src/Saml2 demo1 demo2 endpoints tests/src 39 | - 40 | + 41 | - name: Run unit tests 42 | run: vendor/bin/phpunit --verbose --debug 43 | diff --git a/src/Saml2/Auth.php b/src/Saml2/Auth.php 44 | index 35037031..a860b358 100644 45 | --- a/src/Saml2/Auth.php 46 | +++ b/src/Saml2/Auth.php 47 | @@ -171,7 +171,7 @@ class Auth 48 | * @throws Exception 49 | * @throws Error 50 | */ 51 | - public function __construct(array $settings = null, bool $spValidationOnly = false) 52 | + public function __construct(?array $settings = null, bool $spValidationOnly = false) 53 | { 54 | $this->_settings = new Settings($settings, $spValidationOnly); 55 | } 56 | diff --git a/src/Saml2/Settings.php b/src/Saml2/Settings.php 57 | index 0ca095a9..c750608e 100644 58 | --- a/src/Saml2/Settings.php 59 | +++ b/src/Saml2/Settings.php 60 | @@ -120,7 +120,7 @@ class Settings 61 | * @throws Error If any settings parameter is invalid 62 | * @throws Exception If Settings is incorrectly supplied 63 | */ 64 | - public function __construct(array $settings = null,bool $spValidationOnly = false) 65 | + public function __construct(?array $settings = null,bool $spValidationOnly = false) 66 | { 67 | $this->_spValidationOnly = $spValidationOnly; 68 | $this->_loadPaths(); 69 | diff --git a/src/Saml2/Utils.php b/src/Saml2/Utils.php 70 | index eea057ff..5742a063 100644 71 | --- a/src/Saml2/Utils.php 72 | +++ b/src/Saml2/Utils.php 73 | @@ -954,7 +954,7 @@ public static function getExpireTime($cacheDuration = null, $validUntil = null) 74 | * 75 | * @return DOMNodeList The queried nodes 76 | */ 77 | - public static function query(DOMDocument $dom, $query, DOMElement $context = null) 78 | + public static function query(DOMDocument $dom, $query, ?DOMElement $context = null) 79 | { 80 | $xpath = new DOMXPath($dom); 81 | $xpath->registerNamespace('samlp', Constants::NS_SAMLP); 82 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | getFinder() 17 | ->ignoreVCSIgnored(true) 18 | ->notPath('build') 19 | ->notPath('l10n') 20 | ->notPath('src') 21 | ->notPath('vendor') 22 | ->in(__DIR__); 23 | return $config; 24 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | filter: 4 | excluded_paths: 5 | - 'js/jquery*' 6 | - 'l10n/*' 7 | - 'tests/*' 8 | 9 | imports: 10 | - javascript 11 | - php 12 | -------------------------------------------------------------------------------- /.tx/config: -------------------------------------------------------------------------------- 1 | [main] 2 | host = https://www.transifex.com 3 | lang_map = ja_JP: ja, bg_BG: bg, cs_CZ: cs, fi_FI: fi, hu_HU: hu, nb_NO: nb, sk_SK: sk, th_TH: th 4 | 5 | [o:nextcloud:p:nextcloud:r:user_saml] 6 | file_filter = translationfiles//user_saml.po 7 | source_file = translationfiles/templates/user_saml.pot 8 | source_lang = en 9 | type = PO 10 | 11 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | /** 2 | * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: CC0-1.0 4 | */ 5 | # Authors 6 | 7 | - Arthur Schiwon 8 | - Carl Schwan 9 | - Dominik Ach 10 | - Giuliano Mele 11 | - Jean-Baptiste Pin 12 | - Joas Schilling 13 | - Jonathan Treffler 14 | - Julius Härtl 15 | - Lukas Reschke 16 | - Maxime Besson 17 | - Maximilian Ruta 18 | - Robin Appelman 19 | - Roeland Jago Douma 20 | -------------------------------------------------------------------------------- /LICENSES/MIT.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | app_name=user_saml 4 | 5 | project_dir=$(CURDIR)/../$(app_name) 6 | build_dir=$(CURDIR)/build/artifacts 7 | appstore_dir=$(build_dir)/appstore 8 | source_dir=$(build_dir)/source 9 | sign_dir=$(build_dir)/sign 10 | package_name=$(app_name) 11 | cert_dir=$(HOME)/.nextcloud/certificates 12 | version+=4.0.0 13 | 14 | all: appstore 15 | 16 | release: appstore create-tag 17 | 18 | create-tag: 19 | git tag -s -a v$(version) -m "Tagging the $(version) release." 20 | git push origin v$(version) 21 | 22 | clean: 23 | rm -rf $(build_dir) 24 | rm -rf node_modules 25 | 26 | appstore: clean 27 | composer install --no-dev 28 | mkdir -p $(sign_dir) 29 | rsync -a \ 30 | --exclude=.drone.yml \ 31 | --exclude=.git \ 32 | --exclude=.gitattributes \ 33 | --exclude=.github \ 34 | --exclude=.gitignore \ 35 | --exclude=.git-blame-ignore-revs \ 36 | --exclude=.patches \ 37 | --exclude=.php-cs-fixer.dist.php \ 38 | --exclude=.scrutinizer.yml \ 39 | --exclude=.travis.yml \ 40 | --exclude=.tx \ 41 | --exclude=/build \ 42 | --exclude=/CONTRIBUTING.md \ 43 | --exclude=/docs \ 44 | --exclude=/issue_template.md \ 45 | --exclude=/l10n/l10n.pl \ 46 | --exclude=/Makefile \ 47 | --exclude=/psalm.xml \ 48 | --exclude=/README.md \ 49 | --exclude=/rector.php \ 50 | --exclude=/screenshots \ 51 | --exclude=/tests \ 52 | --exclude=/translationfiles \ 53 | --exclude=/vendor/cweagans \ 54 | --exclude=/vendor-bin \ 55 | $(project_dir)/ $(sign_dir)/$(app_name) 56 | tar -czf $(build_dir)/$(app_name).tar.gz \ 57 | -C $(sign_dir) $(app_name) 58 | @if [ -f $(cert_dir)/$(app_name).key ]; then \ 59 | echo "Signing package…"; \ 60 | openssl dgst -sha512 -sign $(cert_dir)/$(app_name).key $(build_dir)/$(app_name).tar.gz | openssl base64; \ 61 | fi 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5 | # Nextcloud SSO & SAML Authentication 6 | 7 | [![REUSE status](https://api.reuse.software/badge/github.com/nextcloud/user_saml)](https://api.reuse.software/info/github.com/nextcloud/user_saml) 8 | 9 | :lock: App for authenticating Nextcloud users using SAML 10 | 11 | Using the SSO & SAML app of your Nextcloud you can make it easily possible to integrate your existing Single-Sign-On solution with Nextcloud. In addition, you can use the Nextcloud LDAP user provider to keep the convenience for users. (e.g. when sharing) 12 | 13 | The following providers are supported and tested at the moment: 14 | 15 | **SAML 2.0** 16 | 17 | - OneLogin 18 | - Shibboleth 19 | - Active Directory Federation Services (ADFS) 20 | 21 | **Authentication via Environment Variable** 22 | - Kerberos (mod_auth_kerb) 23 | - CAS 24 | - Any other provider that authenticates using the environment variable 25 | 26 | While theoretically any other authentication provider implementing either one of those standards is compatible, we like to note that they are **not** part of any internal test matrix. 27 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors 2 | # SPDX-License-Identifier: AGPL-3.0-or-later 3 | version = 1 4 | SPDX-PackageName = "user_saml" 5 | SPDX-PackageSupplier = "Nextcloud " 6 | SPDX-PackageDownloadLocation = "https://github.com/nextcloud/user_saml" 7 | 8 | [[annotations]] 9 | path = [".gitattributes", ".github/issue_template.md", ".github/CODEOWNERS", ".editorconfig", "package-lock.json", "package.json", "composer.json", "composer.lock", "**/composer.json", "**/composer.lock", ".l10nignore", "cypress/tsconfig.json", "vendor-bin/**/composer.json", "vendor-bin/**/composer.lock", ".tx/config", "tsconfig.json", "js/vendor.LICENSE.txt", "krankerl.toml", ".npmignore", ".nextcloudignore", ".eslintrc.json", ".tx/backport"] 10 | precedence = "aggregate" 11 | SPDX-FileCopyrightText = "none" 12 | SPDX-License-Identifier = "CC0-1.0" 13 | 14 | [[annotations]] 15 | path = ["l10n/**.js", "l10n/**.json"] 16 | precedence = "aggregate" 17 | SPDX-FileCopyrightText = "2017 Nextcloud contributors" 18 | SPDX-License-Identifier = "AGPL-3.0-or-later" 19 | 20 | [[annotations]] 21 | path = ["js/**.js.map", "js/**.js", "js/**.mjs", "js/**.mjs.map", "js/templates/**.handlebars", "emptyTemplates/**", "tests/integration/vendor/autoload.php", "tests/integration/vendor/bin/**", "tests/data/**", "img/app.svg", "img/app-dark.svg", "screenshots/1.png", "screenshots/2.png", "tests/integration/features/**.feature"] 22 | precedence = "aggregate" 23 | SPDX-FileCopyrightText = "2016 Nextcloud GmbH and Nextcloud contributors" 24 | SPDX-License-Identifier = "AGPL-3.0-or-later" 25 | 26 | [[annotations]] 27 | path = "tests/integration/vendor/behat/behat/**" 28 | precedence = "aggregate" 29 | SPDX-FileCopyrightText = "2016 Konstantin Kudryashov " 30 | SPDX-License-Identifier = "MIT" 31 | 32 | [[annotations]] 33 | path = "tests/integration/vendor/behat/gherkin/**" 34 | precedence = "aggregate" 35 | SPDX-FileCopyrightText = "2011-2013 Konstantin Kudryashov " 36 | SPDX-License-Identifier = "MIT" 37 | 38 | [[annotations]] 39 | path = "tests/integration/vendor/behat/transliterator/**" 40 | precedence = "aggregate" 41 | SPDX-FileCopyrightText = "behat/transliterator contributors" 42 | SPDX-License-Identifier = "Artistic-1.0" 43 | 44 | [[annotations]] 45 | path = "tests/integration/vendor/composer/**" 46 | precedence = "aggregate" 47 | SPDX-FileCopyrightText = "Nils Adermann, Jordi Boggiano" 48 | SPDX-License-Identifier = "MIT" 49 | 50 | [[annotations]] 51 | path = "tests/integration/vendor/guzzlehttp/guzzle/**" 52 | precedence = "aggregate" 53 | SPDX-FileCopyrightText = "2011 Michael Dowling , 2012 Jeremy Lindblom , 2014 Graham Campbell , 2015 Márk Sági-Kazár , 2015 Tobias Schultze , 2016 Tobias Nyholm , 2016 George Mponos " 54 | SPDX-License-Identifier = "MIT" 55 | 56 | [[annotations]] 57 | path = "tests/integration/vendor/guzzlehttp/promises/**" 58 | precedence = "aggregate" 59 | SPDX-FileCopyrightText = "2015 Michael Dowling , 2015 Graham Campbell , 2017 Tobias Schultze , 2020 Tobias Nyholm " 60 | SPDX-License-Identifier = "MIT" 61 | 62 | [[annotations]] 63 | path = "tests/integration/vendor/guzzlehttp/psr7/**" 64 | precedence = "aggregate" 65 | SPDX-FileCopyrightText = "2015 Michael Dowling , 2015 Márk Sági-Kazár , 2015 Graham Campbell , 2016 Tobias Schultze , 2016 George Mponos , 2018 Tobias Nyholm " 66 | SPDX-License-Identifier = "MIT" 67 | 68 | [[annotations]] 69 | path = "tests/integration/vendor/psr/container/**" 70 | precedence = "aggregate" 71 | SPDX-FileCopyrightText = "2013-2016 container-interop, 2016 PHP Framework Interoperability Group" 72 | SPDX-License-Identifier = "MIT" 73 | 74 | [[annotations]] 75 | path = "tests/integration/vendor/psr/event-dispatcher/**" 76 | precedence = "aggregate" 77 | SPDX-FileCopyrightText = "2018 PHP-FIG" 78 | SPDX-License-Identifier = "MIT" 79 | 80 | [[annotations]] 81 | path = "tests/integration/vendor/psr/http-client/**" 82 | precedence = "aggregate" 83 | SPDX-FileCopyrightText = "2017 PHP Framework Interoperability Group" 84 | SPDX-License-Identifier = "MIT" 85 | 86 | [[annotations]] 87 | path = "tests/integration/vendor/psr/http-factory/**" 88 | precedence = "aggregate" 89 | SPDX-FileCopyrightText = "2018 PHP-FIG" 90 | SPDX-License-Identifier = "MIT" 91 | 92 | [[annotations]] 93 | path = "tests/integration/vendor/psr/http-message/**" 94 | precedence = "aggregate" 95 | SPDX-FileCopyrightText = "2014 PHP Framework Interoperability Group" 96 | SPDX-License-Identifier = "MIT" 97 | 98 | [[annotations]] 99 | path = "tests/integration/vendor/ralouphie/getallheaders/**" 100 | precedence = "aggregate" 101 | SPDX-FileCopyrightText = "2014 Ralph Khattar" 102 | SPDX-License-Identifier = "MIT" 103 | 104 | [[annotations]] 105 | path = "tests/integration/vendor/symfony/**" 106 | precedence = "aggregate" 107 | SPDX-FileCopyrightText = "Fabien Potencier" 108 | SPDX-License-Identifier = "MIT" 109 | -------------------------------------------------------------------------------- /appinfo/info.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | user_saml 8 | SSO & SAML authentication 9 | Authenticate using single sign-on 10 | 23 | 7.0.0 24 | agpl 25 | Lukas Reschke 26 | User_SAML 27 | 28 | 29 | 30 | 31 | https://portal.nextcloud.com/article/configuring-single-sign-on-10.html 32 | 33 | integration 34 | https://github.com/nextcloud/user_saml 35 | https://github.com/nextcloud/user_saml/issues 36 | https://github.com/nextcloud/user_saml.git 37 | https://raw.githubusercontent.com/nextcloud/user_saml/master/screenshots/1.png 38 | https://raw.githubusercontent.com/nextcloud/user_saml/master/screenshots/2.png 39 | 40 | 41 | 42 | 43 | 44 | OCA\User_SAML\Migration\RememberLocalGroupsForPotentialMigrations 45 | 46 | 47 | OCA\User_SAML\Migration\CleanupRemovedConfig 48 | OCA\User_SAML\Migration\TransferGroupMembers 49 | 50 | 51 | 52 | OCA\User_SAML\Command\ConfigCreate 53 | OCA\User_SAML\Command\ConfigDelete 54 | OCA\User_SAML\Command\ConfigGet 55 | OCA\User_SAML\Command\ConfigSet 56 | OCA\User_SAML\Command\GetMetadata 57 | OCA\User_SAML\Command\GroupMigrationCopyIncomplete 58 | 59 | 60 | OCA\User_SAML\Settings\Admin 61 | OCA\User_SAML\Settings\Section 62 | 63 | 64 | -------------------------------------------------------------------------------- /appinfo/routes.php: -------------------------------------------------------------------------------- 1 | [ 12 | [ 13 | 'name' => 'SAML#login', 14 | 'url' => '/saml/login', 15 | 'verb' => 'GET', 16 | ], 17 | [ 18 | 'name' => 'SAML#base', 19 | 'url' => '/saml', 20 | 'verb' => 'GET', 21 | ], 22 | [ 23 | 'name' => 'SAML#getMetadata', 24 | 'url' => '/saml/metadata', 25 | 'verb' => 'GET', 26 | ], 27 | [ 28 | 'name' => 'SAML#assertionConsumerService', 29 | 'url' => '/saml/acs', 30 | 'verb' => 'POST', 31 | ], 32 | [ 33 | 'name' => 'SAML#singleLogoutService', 34 | 'url' => '/saml/sls', 35 | 'verb' => 'GET', 36 | ], 37 | [ 38 | 'name' => 'SAML#singleLogoutService', 39 | 'url' => '/saml/sls', 40 | 'verb' => 'POST', 41 | 'postfix' => 'slspost', 42 | ], 43 | [ 44 | 'name' => 'SAML#notPermitted', 45 | 'url' => '/saml/notPermitted', 46 | 'verb' => 'GET', 47 | ], 48 | [ 49 | 'name' => 'SAML#notProvisioned', 50 | 'url' => '/saml/notProvisioned', 51 | 'verb' => 'GET', 52 | ], 53 | [ 54 | 'name' => 'SAML#genericError', 55 | 'url' => '/saml/error', 56 | 'verb' => 'GET', 57 | ], 58 | [ 59 | 'name' => 'SAML#selectUserBackEnd', 60 | 'url' => '/saml/selectUserBackEnd', 61 | 'verb' => 'GET', 62 | ], 63 | [ 64 | 'name' => 'Settings#getSamlProviderIds', 65 | 'url' => '/settings/providers', 66 | 'verb' => 'GET', 67 | ], 68 | [ 69 | 'name' => 'Settings#getSamlProviderSettings', 70 | 'url' => '/settings/providerSettings/{providerId}', 71 | 'verb' => 'GET', 72 | 'defaults' => [ 73 | 'providerId' => 1 74 | ], 75 | 'requirements' => [ 76 | 'providerId' => '\d+' 77 | ] 78 | ], 79 | [ 80 | 'name' => 'Settings#setProviderSetting', 81 | 'url' => '/settings/providerSettings/{providerId}', 82 | 'verb' => 'PUT', 83 | 'defaults' => [ 84 | 'providerId' => 1 85 | ], 86 | 'requirements' => [ 87 | 'providerId' => '\d+' 88 | ] 89 | ], 90 | [ 91 | 'name' => 'Settings#newSamlProviderSettingsId', 92 | 'url' => '/settings/providerSettings', 93 | 'verb' => 'POST', 94 | ], 95 | [ 96 | 'name' => 'Settings#deleteSamlProviderSettings', 97 | 'url' => '/settings/providerSettings/{providerId}', 98 | 'verb' => 'DELETE', 99 | 'defaults' => [ 100 | 'providerId' => 1 101 | ], 102 | 'requirements' => [ 103 | 'providerId' => '\d+' 104 | ] 105 | ], 106 | [ 107 | 'name' => 'Timezone#setTimezone', 108 | 'url' => '/config/timezone', 109 | 'verb' => 'POST', 110 | ], 111 | ], 112 | ]; 113 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextcloud/user_saml", 3 | "config": { 4 | "optimize-autoloader": true, 5 | "classmap-authoritative": true, 6 | "platform": { 7 | "php": "8.1.32" 8 | }, 9 | "allow-plugins": { 10 | "cweagans/composer-patches": true, 11 | "bamarni/composer-bin-plugin": true 12 | } 13 | }, 14 | "extra": { 15 | "patches": { 16 | "onelogin/php-saml": { 17 | "PHP 8.4 compatibility": ".patches/php-saml-600.patch" 18 | } 19 | }, 20 | "bamarni-bin": { 21 | "bin-links": true, 22 | "forward-command": true 23 | } 24 | }, 25 | "scripts": { 26 | "post-install-cmd": [ 27 | "[ $COMPOSER_DEV_MODE -eq 0 ] || composer bin all install --ansi" 28 | ], 29 | "post-update-cmd": [ 30 | "[ $COMPOSER_DEV_MODE -eq 0 ] || composer bin all update --ansi" 31 | ], 32 | "cs:fix": "php-cs-fixer fix", 33 | "cs:check": "php-cs-fixer fix --dry-run --diff", 34 | "psalm": "psalm", 35 | "psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", 36 | "psalm:update-baseline": "psalm --threads=1 --update-baseline", 37 | "lint": "find . -name \\*.php -not -path '*/vendor/*' -print0 | xargs -0 -n1 php -l", 38 | "rector:check": "rector --dry-run", 39 | "rector:fix": "rector", 40 | "test:unit": "phpunit -c tests/unit/phpunit.xml" 41 | }, 42 | "require-dev": { 43 | "phpunit/phpunit": "^9.6", 44 | "bamarni/composer-bin-plugin": "^1.8" 45 | }, 46 | "require": { 47 | "onelogin/php-saml": "^4.2", 48 | "firebase/php-jwt": "^6.11", 49 | "cweagans/composer-patches": "^1.7" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /css/admin.css: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | #user-saml input[type="text"],textarea { 6 | max-width: 600px; 7 | width: 100%; 8 | } 9 | 10 | #user-saml input[type="checkbox"] { 11 | vertical-align:middle; 12 | cursor: pointer; 13 | } 14 | 15 | .user-saml-standalone-label { 16 | margin-top: 1.5ex; 17 | display: inline-block; 18 | } 19 | 20 | #user-saml h3 { 21 | font-weight: 700; 22 | margin: 20px 0 5px; 23 | } 24 | 25 | #user-saml h3 .icon-delete { 26 | display: inline-block; 27 | padding: 5px; 28 | margin-bottom: -6px; 29 | } 30 | 31 | #user-saml h4 { 32 | font-size: 14px; 33 | font-weight: 300; 34 | margin: 12px 0; 35 | } 36 | 37 | #user-saml .group { 38 | margin-top: 10px; 39 | margin-bottom: 10px; 40 | } 41 | 42 | #user-saml-settings > div { 43 | margin-bottom: 10px; 44 | } 45 | 46 | .indent { 47 | padding-left: 14px; 48 | } 49 | 50 | #user-saml-settings .toggle { 51 | clear: both; 52 | display: block; 53 | padding: 7px 0; 54 | cursor: pointer; 55 | opacity: .5; 56 | } 57 | 58 | #user-saml .account-list { 59 | margin: 10px 0 10px 0; 60 | overflow:hidden; 61 | padding: 10px 0 10px 0; 62 | } 63 | 64 | #user-saml .account-list li { 65 | float: left; 66 | } 67 | 68 | #user-saml .account-list li a:not(.button) { 69 | padding: 7px; 70 | } 71 | 72 | #user-saml .account-list li a.button { 73 | margin-left: 20px; 74 | } 75 | 76 | #user-saml .account-list li.active a { 77 | border-bottom: 1px solid #333; 78 | font-weight: bold; 79 | } 80 | 81 | #user-saml-reset-settings { 82 | float: right; 83 | } 84 | -------------------------------------------------------------------------------- /css/personal.css: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | #user-saml-apppasswords table { 6 | width: 100%; 7 | min-height: 150px; 8 | padding-top: 25px; 9 | } 10 | #user-saml-appasswords table th { 11 | font-weight: 800; 12 | } 13 | #user-saml-apppasswords table th, 14 | #user-saml-apppasswords table td { 15 | padding: 10px; 16 | } 17 | 18 | #user-saml-apppasswords .token-list td { 19 | border-top: 1px solid #DDD; 20 | text-overflow: ellipsis; 21 | max-width: 200px; 22 | white-space: nowrap; 23 | overflow: hidden; 24 | } 25 | #user-saml-apppasswords .token-list td a.icon-delete { 26 | display: block; 27 | opacity: 0.6; 28 | } 29 | 30 | #user-saml-new-app-password { 31 | width: 186px; 32 | font-family: monospace; 33 | background-color: lightyellow; 34 | } 35 | -------------------------------------------------------------------------------- /css/selectUserBackEnd.css: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors 3 | * SPDX-License-Identifier: AGPL-3.0-or-later 4 | */ 5 | #saml-select-user-back-end { 6 | color: var(--color-primary-text); 7 | } 8 | 9 | #saml-select-user-back-end #av_mode { 10 | height: auto; 11 | background-color: var(--color-main-background); 12 | color: var(--color-main-text); 13 | } 14 | 15 | #saml-select-user-back-end h1 { 16 | font-size: 16px; 17 | padding: 20px 0; 18 | } 19 | 20 | .login-option { 21 | border: 1px solid var(--color-primary-text); 22 | font-weight: 600; 23 | height: 40px; 24 | 25 | margin: 15px 0; 26 | min-width: 269px; 27 | border-radius: 3px; 28 | font-size: 20px; 29 | } 30 | 31 | .login-option a { 32 | display:inline-block; 33 | width:100%; 34 | line-height:40px; 35 | color: var(--color-primary-text); 36 | cursor: pointer; 37 | } 38 | 39 | .login-option .icon-confirm-white { 40 | float: right; 41 | line-height: 40px; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /img/app-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /img/app.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /js/selectUserBackEnd.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", (event) => { 2 | document.getElementsByClassName("login-chose-saml-idp")[0].addEventListener('change', function (event) { 3 | var target = this.value; 4 | if (target !== '') { 5 | window.location.href = target; 6 | } 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /js/timezone.js: -------------------------------------------------------------------------------- 1 | /* global $, jstz, OC */ 2 | 3 | /* 4 | * @copyright 2019 Christoph Wurst 5 | * 6 | * @author 2019 Christoph Wurst 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | */ 23 | 24 | console.debug('updating timezone and offset for SAML user') 25 | 26 | $.ajax({ 27 | type: 'POST', 28 | url: OC.generateUrl('/apps/user_saml/config/timezone'), 29 | data: { 30 | timezone: jstz.determine().name(), 31 | timezoneOffset: (-new Date().getTimezoneOffset() / 60) 32 | }, 33 | error: function(e) { 34 | console.error('could not set timezone and offset for SAML user', e) 35 | }, 36 | success: function() { 37 | console.info('timezone and offset udpated for SAML user') 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /l10n/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/user_saml/aad65bd5f0574b6de44f5c549e8552fc2a910604/l10n/.gitkeep -------------------------------------------------------------------------------- /l10n/af.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Bewaar", 5 | "Provider" : "Verskaffer", 6 | "Provider " : "Verskaffer", 7 | "Private key of the Service Provider" : "Privaatsleutel van die Diensverskaffer", 8 | "Email address" : "E-posadres", 9 | "Open documentation" : "Open dokumentasie", 10 | "Remove identity provider" : "Verwyder identiteitsverskaffer", 11 | "Add identity provider" : "Voeg identiteitsverskaffer toe", 12 | "General" : "Algemeen", 13 | "Service Provider Data" : "Diensverskafferdata", 14 | "Identity Provider Data" : "Identiteitsverskafferdata", 15 | "Security settings" : "Sekuriteitsinstellings", 16 | "Signatures and encryption offered" : "Handtekeninge en enkripsie gebied", 17 | "Signatures and encryption required" : "Handtekeninge en enkripsie vereis", 18 | "Download metadata XML" : "Laai metadata XML af", 19 | "Metadata invalid" : "Metadata ongeldig", 20 | "Metadata valid" : "Metadata geldig", 21 | "Error" : "Fout" 22 | }, 23 | "nplurals=2; plural=(n != 1);"); 24 | -------------------------------------------------------------------------------- /l10n/af.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Bewaar", 3 | "Provider" : "Verskaffer", 4 | "Provider " : "Verskaffer", 5 | "Private key of the Service Provider" : "Privaatsleutel van die Diensverskaffer", 6 | "Email address" : "E-posadres", 7 | "Open documentation" : "Open dokumentasie", 8 | "Remove identity provider" : "Verwyder identiteitsverskaffer", 9 | "Add identity provider" : "Voeg identiteitsverskaffer toe", 10 | "General" : "Algemeen", 11 | "Service Provider Data" : "Diensverskafferdata", 12 | "Identity Provider Data" : "Identiteitsverskafferdata", 13 | "Security settings" : "Sekuriteitsinstellings", 14 | "Signatures and encryption offered" : "Handtekeninge en enkripsie gebied", 15 | "Signatures and encryption required" : "Handtekeninge en enkripsie vereis", 16 | "Download metadata XML" : "Laai metadata XML af", 17 | "Metadata invalid" : "Metadata ongeldig", 18 | "Metadata valid" : "Metadata geldig", 19 | "Error" : "Fout" 20 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 21 | } -------------------------------------------------------------------------------- /l10n/ast.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Guardóse", 5 | "Could not save" : "Nun se pudo guardar", 6 | "Provider" : "Fornidor", 7 | "This user account is disabled, please contact your administrator." : "Esta cuenta d'usuariu ta desactivada, ponte en contautu cola alministración", 8 | "Unknown error, please check the log file for more details." : "Hebo un error desconocíu, comprueba'l ficheru de rexistru pa consiguir más detalles.", 9 | "Direct log in" : "Aniciu de la sesión direutu", 10 | "SSO & SAML log in" : "Aniciu de la sesión SAML y SSO", 11 | "This page should not be visited directly." : "Esta páxina nun s'habría visitar direutamente.", 12 | "Provider " : "Fornidor", 13 | "X.509 certificate of the Service Provider" : "Certificáu X.509 del fornidor de servicios", 14 | "Private key of the Service Provider" : "Clave privada del fornidor de servicios", 15 | "Indicates if the SP will validate all received XML." : "Indica si'l fornidor de servicios va validar tolos XML recibíos", 16 | "Group A, Group B, …" : "Grupu A, grupu B…", 17 | "Email address" : "Direición de corréu electrónicu", 18 | "Encrypted" : "Cifróse", 19 | "Entity" : "Entidá", 20 | "Kerberos" : "Kerberos", 21 | "Persistent" : "Persistente", 22 | "Transient" : "Transitoriu", 23 | "Unspecified" : "Ensin especificar", 24 | "Windows domain qualified name" : "Nome cualificáu del dominiu de Windows", 25 | "SSO & SAML authentication" : "Autenticación SAML y SSO", 26 | "Authenticate using single sign-on" : "Autenticar col aniciu de la sesión únicu", 27 | "Open documentation" : "Abrir la documentación", 28 | "Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account will not be possible anymore, unless you enabled \"%s\" or you go directly to the URL %s." : "Asegúrate de configurar un usuariu alministrativu que pueda acceder a esta instancia per SSO. L'aniciu de la sesión cola cuenta «%s» normal yá nun va ser posible, sacante qu'activares «%s» o vaigas direutamente a la URL «%s».", 29 | "Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account will not be possible anymore, unless you go directly to the URL %s." : "Asegúrate de configurar un usuariu alministrativu que pueda acceder a esta instancia per SSO. L'aniciu de la sesión cola cuenta «%s» normal yá nun va ser posible, sacante que vaigas direutamente a la URL «%s».", 30 | "Use built-in SAML authentication" : "Usar l'autenticación SAML integrada", 31 | "Use environment variable" : "Usar la variable d'entornu", 32 | "Global settings" : "Configuración global", 33 | "Remove identity provider" : "Quitar el fornidor d'identidaes", 34 | "Add identity provider" : "Amestar un fornidor d'identidaes", 35 | "General" : "Xeneral", 36 | "Identity Provider Data" : "Datos del fornidor d'identidaes", 37 | "Show optional Identity Provider settings…" : "Amosar la configuración adicional del fornidor d'identidaes…", 38 | "Public X.509 certificate of the IdP" : "Certificáu X.509 públicu del forndior d'identidaes", 39 | "Attribute mapping" : "Mapéu d'atributos", 40 | "Show attribute mapping settings…" : "Amosar la configuración del mapéu d'atributos…", 41 | "Security settings" : "Configuración de seguranza", 42 | "For increased security we recommend enabling the following settings if supported by your environment." : "P'aumentar la seguranza, aconseyámoste activar la configuración siguiente si'l to entornu ye compatible.", 43 | "Show security settings…" : "Amosar la configuración de seguranza…", 44 | "User filtering" : "Peñera d'usuarios", 45 | "Download metadata XML" : "Baxar el XML de los metadatos", 46 | "Reset settings" : "Reafitar la configuración", 47 | "Metadata invalid" : "Los meta datos son inválidos", 48 | "Metadata valid" : "Los metadatos son válidos", 49 | "Error" : "Error", 50 | "Access denied." : "Negóse l'accesu.", 51 | "Login options:" : "Opciones de l'aniciu de la sesión:", 52 | "Choose an authentication provider" : "Escueyi un fornidor d'autenticación" 53 | }, 54 | "nplurals=2; plural=(n != 1);"); 55 | -------------------------------------------------------------------------------- /l10n/ast.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Guardóse", 3 | "Could not save" : "Nun se pudo guardar", 4 | "Provider" : "Fornidor", 5 | "This user account is disabled, please contact your administrator." : "Esta cuenta d'usuariu ta desactivada, ponte en contautu cola alministración", 6 | "Unknown error, please check the log file for more details." : "Hebo un error desconocíu, comprueba'l ficheru de rexistru pa consiguir más detalles.", 7 | "Direct log in" : "Aniciu de la sesión direutu", 8 | "SSO & SAML log in" : "Aniciu de la sesión SAML y SSO", 9 | "This page should not be visited directly." : "Esta páxina nun s'habría visitar direutamente.", 10 | "Provider " : "Fornidor", 11 | "X.509 certificate of the Service Provider" : "Certificáu X.509 del fornidor de servicios", 12 | "Private key of the Service Provider" : "Clave privada del fornidor de servicios", 13 | "Indicates if the SP will validate all received XML." : "Indica si'l fornidor de servicios va validar tolos XML recibíos", 14 | "Group A, Group B, …" : "Grupu A, grupu B…", 15 | "Email address" : "Direición de corréu electrónicu", 16 | "Encrypted" : "Cifróse", 17 | "Entity" : "Entidá", 18 | "Kerberos" : "Kerberos", 19 | "Persistent" : "Persistente", 20 | "Transient" : "Transitoriu", 21 | "Unspecified" : "Ensin especificar", 22 | "Windows domain qualified name" : "Nome cualificáu del dominiu de Windows", 23 | "SSO & SAML authentication" : "Autenticación SAML y SSO", 24 | "Authenticate using single sign-on" : "Autenticar col aniciu de la sesión únicu", 25 | "Open documentation" : "Abrir la documentación", 26 | "Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account will not be possible anymore, unless you enabled \"%s\" or you go directly to the URL %s." : "Asegúrate de configurar un usuariu alministrativu que pueda acceder a esta instancia per SSO. L'aniciu de la sesión cola cuenta «%s» normal yá nun va ser posible, sacante qu'activares «%s» o vaigas direutamente a la URL «%s».", 27 | "Make sure to configure an administrative user that can access the instance via SSO. Logging-in with your regular %s account will not be possible anymore, unless you go directly to the URL %s." : "Asegúrate de configurar un usuariu alministrativu que pueda acceder a esta instancia per SSO. L'aniciu de la sesión cola cuenta «%s» normal yá nun va ser posible, sacante que vaigas direutamente a la URL «%s».", 28 | "Use built-in SAML authentication" : "Usar l'autenticación SAML integrada", 29 | "Use environment variable" : "Usar la variable d'entornu", 30 | "Global settings" : "Configuración global", 31 | "Remove identity provider" : "Quitar el fornidor d'identidaes", 32 | "Add identity provider" : "Amestar un fornidor d'identidaes", 33 | "General" : "Xeneral", 34 | "Identity Provider Data" : "Datos del fornidor d'identidaes", 35 | "Show optional Identity Provider settings…" : "Amosar la configuración adicional del fornidor d'identidaes…", 36 | "Public X.509 certificate of the IdP" : "Certificáu X.509 públicu del forndior d'identidaes", 37 | "Attribute mapping" : "Mapéu d'atributos", 38 | "Show attribute mapping settings…" : "Amosar la configuración del mapéu d'atributos…", 39 | "Security settings" : "Configuración de seguranza", 40 | "For increased security we recommend enabling the following settings if supported by your environment." : "P'aumentar la seguranza, aconseyámoste activar la configuración siguiente si'l to entornu ye compatible.", 41 | "Show security settings…" : "Amosar la configuración de seguranza…", 42 | "User filtering" : "Peñera d'usuarios", 43 | "Download metadata XML" : "Baxar el XML de los metadatos", 44 | "Reset settings" : "Reafitar la configuración", 45 | "Metadata invalid" : "Los meta datos son inválidos", 46 | "Metadata valid" : "Los metadatos son válidos", 47 | "Error" : "Error", 48 | "Access denied." : "Negóse l'accesu.", 49 | "Login options:" : "Opciones de l'aniciu de la sesión:", 50 | "Choose an authentication provider" : "Escueyi un fornidor d'autenticación" 51 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 52 | } -------------------------------------------------------------------------------- /l10n/es_AR.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Guardado", 5 | "X.509 certificate of the Service Provider" : "certificado X.509 del Proveedor de Servicio", 6 | "Private key of the Service Provider" : "Llave privada del Proveedor de Servicio", 7 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Indica que el nameID de enviado por este SP será encriptado. ", 8 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "Indica si los mensajes enviados por este SP serán firmados. [Los metadatos del SP proporcionarán esta información]", 9 | "Indicates whether the messages sent by this SP will be signed." : "Indica si los mensjaes enviados por este SP serán firmados. ", 10 | "Indicates whether the messages sent by this SP will be signed." : "Indica is los mensajes enviados por este SP serán firmados. ", 11 | "Whether the metadata should be signed." : "Si los metadatos deben ser firmados o no. ", 12 | "Indicates a requirement for the , and elements received by this SP to be signed." : "Indica un requerimiento para que los elementos recibidos , y por este SP sean firmados. ", 13 | "Indicates a requirement for the elements received by this SP to be signed. [Metadata of the SP will offer this info]" : "Indica un requerimientos para que los elementos recibidos por este SP para ser firmados. [Los metadatos del SP proporcionarán esta información]", 14 | "Indicates a requirement for the elements received by this SP to be encrypted." : "Indica un requerimiento para que los elelemtnos recibidos de este SP sean encriptados. ", 15 | " Indicates a requirement for the NameID element on the SAMLResponse received by this SP to be present." : "Indica un requerimiento para que el elemento NameID en la SAMLResponse recibida por este SP esté presente. ", 16 | "Indicates a requirement for the NameID received by this SP to be encrypted." : "Indica que un requerimiento para el NameID recibido por este SP está encriptado.", 17 | "ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification." : "ADFS URL-Codifica los datos SAML como minúsculas, y el juego de herramientas usa mayúsculas por defecto. Habilite para tener compatibilidad con ADFS en la verificacón de la firma.", 18 | "Attribute to map the UID to." : "Atributo a mapear al UID.", 19 | "Attribute to map the displayname to." : "Atributo a mapear a displayname. ", 20 | "Attribute to map the email address to." : "Atributo a mapear a email address.", 21 | "SSO & SAML authentication" : "Autenticación SSO & SAML", 22 | "Open documentation" : "Abrir documentación", 23 | "Please choose whether you want to authenticate using the SAML provider built-in in Nextcloud or whether you want to authenticate against an environment variable." : "Favor de seleccionar si usted desdea autenticarse usando el proveedor integrado SAML de Nextcloud o si desdea autenticarse contra una variable de ambiente. ", 24 | "Use built-in SAML authentication" : "Usar autenticación SAML integrada", 25 | "Use environment variable" : "Usar la variable de ambiente", 26 | "Remove identity provider" : "Eliminar proveedor de identidad", 27 | "Add identity provider" : "Añadir proveedor de identidad", 28 | "General" : "General", 29 | "Service Provider Data" : "Datos del Proveedor de Servicio", 30 | "If your Service Provider should use certificates you can optionally specify them here." : "Si su Proveedor de Servicio debe usar certificados, usted puede especificarlos opcionalmente desde aquí.", 31 | "Identity Provider Data" : "Datos del Proveedor de Identidad", 32 | "Identifier of the IdP entity (must be a URI)" : "Identificador de la entidad IdP (debe ser un URI)", 33 | "URL Target of the IdP where the SP will send the Authentication Request Message" : "URL Destino del IdP donde el SP enviará automaticamente el Mensaje de Solicitud de Autenticación", 34 | "URL Location of the IdP where the SP will send the SLO Request" : "Ubicación del URL del IdP donde el SP enviará la Solicitud SLO", 35 | "Public X.509 certificate of the IdP" : "Certificado X.509 público del IdP", 36 | "Attribute mapping" : "Mapeo del atributo", 37 | "Security settings" : "Configuraciones de seguridad", 38 | "For increased security we recommend enabling the following settings if supported by your environment." : "Para mayor seguridad le recomendamos habilitar las siguientes configuraciones si están soportados en su ambiente.", 39 | "Signatures and encryption offered" : "Firmas y encripción disponibles", 40 | "Signatures and encryption required" : "Firmas y encripción requeridos", 41 | "Download metadata XML" : "Descargar metadatos XML", 42 | "Metadata invalid" : "Metadatos inválidos", 43 | "Metadata valid" : "Metadatos válidos", 44 | "Error" : "Error", 45 | "Account not provisioned." : "La cuenta no está aprovisionada. ", 46 | "Your account is not provisioned, access to this service is thus not possible." : "Su cuenta no ha sido aprovisionada, por lo cual el acceso a este servico no es posible. " 47 | }, 48 | "nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 49 | -------------------------------------------------------------------------------- /l10n/es_AR.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Guardado", 3 | "X.509 certificate of the Service Provider" : "certificado X.509 del Proveedor de Servicio", 4 | "Private key of the Service Provider" : "Llave privada del Proveedor de Servicio", 5 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Indica que el nameID de enviado por este SP será encriptado. ", 6 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "Indica si los mensajes enviados por este SP serán firmados. [Los metadatos del SP proporcionarán esta información]", 7 | "Indicates whether the messages sent by this SP will be signed." : "Indica si los mensjaes enviados por este SP serán firmados. ", 8 | "Indicates whether the messages sent by this SP will be signed." : "Indica is los mensajes enviados por este SP serán firmados. ", 9 | "Whether the metadata should be signed." : "Si los metadatos deben ser firmados o no. ", 10 | "Indicates a requirement for the , and elements received by this SP to be signed." : "Indica un requerimiento para que los elementos recibidos , y por este SP sean firmados. ", 11 | "Indicates a requirement for the elements received by this SP to be signed. [Metadata of the SP will offer this info]" : "Indica un requerimientos para que los elementos recibidos por este SP para ser firmados. [Los metadatos del SP proporcionarán esta información]", 12 | "Indicates a requirement for the elements received by this SP to be encrypted." : "Indica un requerimiento para que los elelemtnos recibidos de este SP sean encriptados. ", 13 | " Indicates a requirement for the NameID element on the SAMLResponse received by this SP to be present." : "Indica un requerimiento para que el elemento NameID en la SAMLResponse recibida por este SP esté presente. ", 14 | "Indicates a requirement for the NameID received by this SP to be encrypted." : "Indica que un requerimiento para el NameID recibido por este SP está encriptado.", 15 | "ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification." : "ADFS URL-Codifica los datos SAML como minúsculas, y el juego de herramientas usa mayúsculas por defecto. Habilite para tener compatibilidad con ADFS en la verificacón de la firma.", 16 | "Attribute to map the UID to." : "Atributo a mapear al UID.", 17 | "Attribute to map the displayname to." : "Atributo a mapear a displayname. ", 18 | "Attribute to map the email address to." : "Atributo a mapear a email address.", 19 | "SSO & SAML authentication" : "Autenticación SSO & SAML", 20 | "Open documentation" : "Abrir documentación", 21 | "Please choose whether you want to authenticate using the SAML provider built-in in Nextcloud or whether you want to authenticate against an environment variable." : "Favor de seleccionar si usted desdea autenticarse usando el proveedor integrado SAML de Nextcloud o si desdea autenticarse contra una variable de ambiente. ", 22 | "Use built-in SAML authentication" : "Usar autenticación SAML integrada", 23 | "Use environment variable" : "Usar la variable de ambiente", 24 | "Remove identity provider" : "Eliminar proveedor de identidad", 25 | "Add identity provider" : "Añadir proveedor de identidad", 26 | "General" : "General", 27 | "Service Provider Data" : "Datos del Proveedor de Servicio", 28 | "If your Service Provider should use certificates you can optionally specify them here." : "Si su Proveedor de Servicio debe usar certificados, usted puede especificarlos opcionalmente desde aquí.", 29 | "Identity Provider Data" : "Datos del Proveedor de Identidad", 30 | "Identifier of the IdP entity (must be a URI)" : "Identificador de la entidad IdP (debe ser un URI)", 31 | "URL Target of the IdP where the SP will send the Authentication Request Message" : "URL Destino del IdP donde el SP enviará automaticamente el Mensaje de Solicitud de Autenticación", 32 | "URL Location of the IdP where the SP will send the SLO Request" : "Ubicación del URL del IdP donde el SP enviará la Solicitud SLO", 33 | "Public X.509 certificate of the IdP" : "Certificado X.509 público del IdP", 34 | "Attribute mapping" : "Mapeo del atributo", 35 | "Security settings" : "Configuraciones de seguridad", 36 | "For increased security we recommend enabling the following settings if supported by your environment." : "Para mayor seguridad le recomendamos habilitar las siguientes configuraciones si están soportados en su ambiente.", 37 | "Signatures and encryption offered" : "Firmas y encripción disponibles", 38 | "Signatures and encryption required" : "Firmas y encripción requeridos", 39 | "Download metadata XML" : "Descargar metadatos XML", 40 | "Metadata invalid" : "Metadatos inválidos", 41 | "Metadata valid" : "Metadatos válidos", 42 | "Error" : "Error", 43 | "Account not provisioned." : "La cuenta no está aprovisionada. ", 44 | "Your account is not provisioned, access to this service is thus not possible." : "Su cuenta no ha sido aprovisionada, por lo cual el acceso a este servico no es posible. " 45 | },"pluralForm" :"nplurals=3; plural=n == 1 ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 46 | } -------------------------------------------------------------------------------- /l10n/et_EE.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Salvestatud", 5 | "Could not save" : "Ei õnnestunud salvestada", 6 | "X.509 certificate of the Service Provider" : "Teenusepakkuja X.509 sertifikaat", 7 | "Private key of the Service Provider" : "Teenusepakkuja privaatvõti", 8 | "Email address" : "E-posti aadress", 9 | "Encrypted" : "Krüptitud", 10 | "Use POST method for SAML request (default: GET)" : "Kasuta SAML-i päringute jaoks POST-meetodit (vaikimisi on kasutusel GET-meetod)", 11 | "SSO & SAML authentication" : "SSO & SAML autentimine", 12 | "Open documentation" : "Ava dokumentatsioon", 13 | "Use built-in SAML authentication" : "Kasuta sisse-ehitatud SAML autentimist", 14 | "Use environment variable" : "Kasuta keskonnamuutujat", 15 | "General" : "Üldine", 16 | "Service Provider Data" : "Teenusepakkuja andmed", 17 | "Security settings" : "Turvaseaded", 18 | "Error" : "Viga", 19 | "JavaScript is disabled in your browser. Please enable it to continue." : "JavaScript on sinu veebibrauseris keelatud. Jätkamiseks palun luba JavaScripti kasutamine." 20 | }, 21 | "nplurals=2; plural=(n != 1);"); 22 | -------------------------------------------------------------------------------- /l10n/et_EE.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Salvestatud", 3 | "Could not save" : "Ei õnnestunud salvestada", 4 | "X.509 certificate of the Service Provider" : "Teenusepakkuja X.509 sertifikaat", 5 | "Private key of the Service Provider" : "Teenusepakkuja privaatvõti", 6 | "Email address" : "E-posti aadress", 7 | "Encrypted" : "Krüptitud", 8 | "Use POST method for SAML request (default: GET)" : "Kasuta SAML-i päringute jaoks POST-meetodit (vaikimisi on kasutusel GET-meetod)", 9 | "SSO & SAML authentication" : "SSO & SAML autentimine", 10 | "Open documentation" : "Ava dokumentatsioon", 11 | "Use built-in SAML authentication" : "Kasuta sisse-ehitatud SAML autentimist", 12 | "Use environment variable" : "Kasuta keskonnamuutujat", 13 | "General" : "Üldine", 14 | "Service Provider Data" : "Teenusepakkuja andmed", 15 | "Security settings" : "Turvaseaded", 16 | "Error" : "Viga", 17 | "JavaScript is disabled in your browser. Please enable it to continue." : "JavaScript on sinu veebibrauseris keelatud. Jätkamiseks palun luba JavaScripti kasutamine." 18 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 19 | } -------------------------------------------------------------------------------- /l10n/fi.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Tallennettu", 5 | "Provider" : "Tarjoaja", 6 | "This user account is disabled, please contact your administrator." : "Tämä käyttäjätili ei ole käytössä. Ota yhteys ylläpitoon.", 7 | "Unknown error, please check the log file for more details." : "Tuntematon virhe. Tarkista lisätiedot lokista.", 8 | "Direct log in" : "Suora kirjautuminen", 9 | "SSO & SAML log in" : "SSO- ja SAML-kirjautuminen", 10 | "Provider " : "Tarjoaja", 11 | "X.509 certificate of the Service Provider" : "Palveluntarjoajan X.509-varmenne", 12 | "Private key of the Service Provider" : "Palveluntarjoajan yksityinen avain", 13 | "Email address" : "Sähköpostiosoite", 14 | "Encrypted" : "Salattu", 15 | "Entity" : "Entiteetti", 16 | "Kerberos" : "Kerberos", 17 | "SSO & SAML authentication" : "SSO- ja SAML-tunnistautuminen", 18 | "Authenticate using single sign-on" : "Tunnistaudu käyttäen kertakirjautumista", 19 | "Open documentation" : "Avaa dokumentaatio", 20 | "Use built-in SAML authentication" : "Käytä sisäänrakennettua SAML-tunnistautumista", 21 | "Use environment variable" : "Käytä ympäristömuuttujaa", 22 | "Global settings" : "Yleiset asetukset", 23 | "Remove identity provider" : "Poista identiteetin tarjoaja", 24 | "Add identity provider" : "Lisää identiteetin tarjoaja", 25 | "General" : "Yleiset", 26 | "Show Service Provider settings…" : "Näytä palveluntarjoajan asetukset…", 27 | "Security settings" : "Turvallisuusasetukset", 28 | "Show security settings…" : "Näytä turvallisuusasetukset…", 29 | "Reset settings" : "Nollaa asetukset", 30 | "Error" : "Virhe", 31 | "Login options:" : "Kirjautumisvalinnat:" 32 | }, 33 | "nplurals=2; plural=(n != 1);"); 34 | -------------------------------------------------------------------------------- /l10n/fi.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Tallennettu", 3 | "Provider" : "Tarjoaja", 4 | "This user account is disabled, please contact your administrator." : "Tämä käyttäjätili ei ole käytössä. Ota yhteys ylläpitoon.", 5 | "Unknown error, please check the log file for more details." : "Tuntematon virhe. Tarkista lisätiedot lokista.", 6 | "Direct log in" : "Suora kirjautuminen", 7 | "SSO & SAML log in" : "SSO- ja SAML-kirjautuminen", 8 | "Provider " : "Tarjoaja", 9 | "X.509 certificate of the Service Provider" : "Palveluntarjoajan X.509-varmenne", 10 | "Private key of the Service Provider" : "Palveluntarjoajan yksityinen avain", 11 | "Email address" : "Sähköpostiosoite", 12 | "Encrypted" : "Salattu", 13 | "Entity" : "Entiteetti", 14 | "Kerberos" : "Kerberos", 15 | "SSO & SAML authentication" : "SSO- ja SAML-tunnistautuminen", 16 | "Authenticate using single sign-on" : "Tunnistaudu käyttäen kertakirjautumista", 17 | "Open documentation" : "Avaa dokumentaatio", 18 | "Use built-in SAML authentication" : "Käytä sisäänrakennettua SAML-tunnistautumista", 19 | "Use environment variable" : "Käytä ympäristömuuttujaa", 20 | "Global settings" : "Yleiset asetukset", 21 | "Remove identity provider" : "Poista identiteetin tarjoaja", 22 | "Add identity provider" : "Lisää identiteetin tarjoaja", 23 | "General" : "Yleiset", 24 | "Show Service Provider settings…" : "Näytä palveluntarjoajan asetukset…", 25 | "Security settings" : "Turvallisuusasetukset", 26 | "Show security settings…" : "Näytä turvallisuusasetukset…", 27 | "Reset settings" : "Nollaa asetukset", 28 | "Error" : "Virhe", 29 | "Login options:" : "Kirjautumisvalinnat:" 30 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 31 | } -------------------------------------------------------------------------------- /l10n/he.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "נשמר", 5 | "Provider" : "ספק", 6 | "This user account is disabled, please contact your administrator." : "החשבון הזה מושבת, נא ליצור קשר עם מנהל המערכת.", 7 | "Unknown error, please check the log file for more details." : "שגיאה בלתי ידועה, נא לעיין בקובץ הרישום לפרטים נוספים.", 8 | "Direct log in" : "כניסה ישירה", 9 | "SSO & SAML log in" : "כניסה עם SSO ו־SAML", 10 | "This page should not be visited directly." : "אין סיבה להגיע לעמוד זה ישירות.", 11 | "Provider " : "ספק", 12 | "X.509 certificate of the Service Provider" : "אישור X.509 של ספק השירות", 13 | "Private key of the Service Provider" : "מפתח פרטי של ספק השירות", 14 | "Indicates that the nameID of the sent by this SP will be encrypted." : "מציין שה־nameID של ה־ שנשלח על ידי ספק השירות הזה יהיה מוצפן.", 15 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "מציין האם הודעות מסוג שנשלחות על ידי ספק השירות הזה תהיינה חתומות. [נתוני העל של ספק השירות יציעו את המידע הזה]", 16 | "Indicates whether the messages sent by this SP will be signed." : "מציין האם הודעות מסוג שנשלחות על ידי ספק השירות הזה תהיינה חתומות.", 17 | "Indicates whether the messages sent by this SP will be signed." : "מציין האם הודעות מסוג שנשלחות על ידי ספק השירות הזה תהיינה חתומות.", 18 | "Whether the metadata should be signed." : "האם לחתום על נתוני העל.", 19 | "Indicates a requirement for the , and elements received by this SP to be signed." : "מציין דרישה לחתימה על הרכיבים , ו־ שהתקבלו על ידי ספק השירות הזה.", 20 | "Indicates if the SP will validate all received XML." : "מציין אם ספק השירות יאמת את כל ה־XML שמתקבל", 21 | "Algorithm that the toolkit will use on signing process." : "האלגוריתם בו תשתמש ערכת הכלים בתהליך החתימה.", 22 | "Attribute to map the UID to." : "מאפיין למפות אליו את ה־UID (מזהה המשתמש).", 23 | "Attribute to map the displayname to." : "מאפיין למפות אליו את displayname (שם התצוגה).", 24 | "Attribute to map the email address to." : "מאפיין למפות אליו את email (כתובת הדוא״ל).", 25 | "Attribute to map the quota to." : "מאפיין למפות אליו את quota (מיכסה).", 26 | "Attribute to map the users home to." : "מאפיין למפות אליו את תיקיות הבית של המשתמשים.", 27 | "Attribute to map the users groups to." : "מאפיין למפות אליו את קבוצות המשתמשים.", 28 | "Email address" : "כתובת דוא״ל", 29 | "Encrypted" : "מוצפן", 30 | "Entity" : "יישות", 31 | "Kerberos" : "Kerberos", 32 | "X509 subject name" : "שם נושא X509", 33 | "SSO & SAML authentication" : "אימות גישה אחודה (SSO) ו־SAML", 34 | "Open documentation" : "פתיחת תיעוד", 35 | "Use built-in SAML authentication" : "שימוש באימות SAML מובנה", 36 | "Use environment variable" : "שימוש במשתני סביבה", 37 | "Global settings" : "הגדרות גלובליות", 38 | "Remove identity provider" : "הסרת ספק זהות", 39 | "Add identity provider" : "הוספת ספק זהות", 40 | "General" : "כללי", 41 | "Service Provider Data" : "נתוני ספק שירות", 42 | "If your Service Provider should use certificates you can optionally specify them here." : "אם ספק הזהות שלך אמור להשתמש באישורים ניתן לציין אותם כאן.", 43 | "Show Service Provider settings…" : "הצגת הגדרות ספק שירות…", 44 | "Identity Provider Data" : "נתוני ספק שירות", 45 | "Attribute mapping" : "מיפוי מאפיינים", 46 | "Security settings" : "הגדרות אבטחה", 47 | "Show security settings…" : "הצגת הגדרות אבטחה…", 48 | "Signatures and encryption offered" : "הוצעו חתימות והצפנה", 49 | "Signatures and encryption required" : "נדרשו חתימות והצפנה", 50 | "Download metadata XML" : "הורדת XML של נתוני העל", 51 | "Reset settings" : "איפוס הגדרות", 52 | "Metadata invalid" : "נתוני העל שגויים", 53 | "Metadata valid" : "נתוני העל תקינים", 54 | "Error" : "שגיאה", 55 | "Account not provisioned." : "החשבון לא מנוהל.", 56 | "Your account is not provisioned, access to this service is thus not possible." : "החשבון שלך לא מנוהל, לכן הגישה לשירות הזה אינה אפשרות." 57 | }, 58 | "nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;"); 59 | -------------------------------------------------------------------------------- /l10n/he.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "נשמר", 3 | "Provider" : "ספק", 4 | "This user account is disabled, please contact your administrator." : "החשבון הזה מושבת, נא ליצור קשר עם מנהל המערכת.", 5 | "Unknown error, please check the log file for more details." : "שגיאה בלתי ידועה, נא לעיין בקובץ הרישום לפרטים נוספים.", 6 | "Direct log in" : "כניסה ישירה", 7 | "SSO & SAML log in" : "כניסה עם SSO ו־SAML", 8 | "This page should not be visited directly." : "אין סיבה להגיע לעמוד זה ישירות.", 9 | "Provider " : "ספק", 10 | "X.509 certificate of the Service Provider" : "אישור X.509 של ספק השירות", 11 | "Private key of the Service Provider" : "מפתח פרטי של ספק השירות", 12 | "Indicates that the nameID of the sent by this SP will be encrypted." : "מציין שה־nameID של ה־ שנשלח על ידי ספק השירות הזה יהיה מוצפן.", 13 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "מציין האם הודעות מסוג שנשלחות על ידי ספק השירות הזה תהיינה חתומות. [נתוני העל של ספק השירות יציעו את המידע הזה]", 14 | "Indicates whether the messages sent by this SP will be signed." : "מציין האם הודעות מסוג שנשלחות על ידי ספק השירות הזה תהיינה חתומות.", 15 | "Indicates whether the messages sent by this SP will be signed." : "מציין האם הודעות מסוג שנשלחות על ידי ספק השירות הזה תהיינה חתומות.", 16 | "Whether the metadata should be signed." : "האם לחתום על נתוני העל.", 17 | "Indicates a requirement for the , and elements received by this SP to be signed." : "מציין דרישה לחתימה על הרכיבים , ו־ שהתקבלו על ידי ספק השירות הזה.", 18 | "Indicates if the SP will validate all received XML." : "מציין אם ספק השירות יאמת את כל ה־XML שמתקבל", 19 | "Algorithm that the toolkit will use on signing process." : "האלגוריתם בו תשתמש ערכת הכלים בתהליך החתימה.", 20 | "Attribute to map the UID to." : "מאפיין למפות אליו את ה־UID (מזהה המשתמש).", 21 | "Attribute to map the displayname to." : "מאפיין למפות אליו את displayname (שם התצוגה).", 22 | "Attribute to map the email address to." : "מאפיין למפות אליו את email (כתובת הדוא״ל).", 23 | "Attribute to map the quota to." : "מאפיין למפות אליו את quota (מיכסה).", 24 | "Attribute to map the users home to." : "מאפיין למפות אליו את תיקיות הבית של המשתמשים.", 25 | "Attribute to map the users groups to." : "מאפיין למפות אליו את קבוצות המשתמשים.", 26 | "Email address" : "כתובת דוא״ל", 27 | "Encrypted" : "מוצפן", 28 | "Entity" : "יישות", 29 | "Kerberos" : "Kerberos", 30 | "X509 subject name" : "שם נושא X509", 31 | "SSO & SAML authentication" : "אימות גישה אחודה (SSO) ו־SAML", 32 | "Open documentation" : "פתיחת תיעוד", 33 | "Use built-in SAML authentication" : "שימוש באימות SAML מובנה", 34 | "Use environment variable" : "שימוש במשתני סביבה", 35 | "Global settings" : "הגדרות גלובליות", 36 | "Remove identity provider" : "הסרת ספק זהות", 37 | "Add identity provider" : "הוספת ספק זהות", 38 | "General" : "כללי", 39 | "Service Provider Data" : "נתוני ספק שירות", 40 | "If your Service Provider should use certificates you can optionally specify them here." : "אם ספק הזהות שלך אמור להשתמש באישורים ניתן לציין אותם כאן.", 41 | "Show Service Provider settings…" : "הצגת הגדרות ספק שירות…", 42 | "Identity Provider Data" : "נתוני ספק שירות", 43 | "Attribute mapping" : "מיפוי מאפיינים", 44 | "Security settings" : "הגדרות אבטחה", 45 | "Show security settings…" : "הצגת הגדרות אבטחה…", 46 | "Signatures and encryption offered" : "הוצעו חתימות והצפנה", 47 | "Signatures and encryption required" : "נדרשו חתימות והצפנה", 48 | "Download metadata XML" : "הורדת XML של נתוני העל", 49 | "Reset settings" : "איפוס הגדרות", 50 | "Metadata invalid" : "נתוני העל שגויים", 51 | "Metadata valid" : "נתוני העל תקינים", 52 | "Error" : "שגיאה", 53 | "Account not provisioned." : "החשבון לא מנוהל.", 54 | "Your account is not provisioned, access to this service is thus not possible." : "החשבון שלך לא מנוהל, לכן הגישה לשירות הזה אינה אפשרות." 55 | },"pluralForm" :"nplurals=3; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: 2;" 56 | } -------------------------------------------------------------------------------- /l10n/ia.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Salveguardate", 5 | "Open documentation" : "Aperir documentation", 6 | "General" : "General", 7 | "Security settings" : "Configurationes de securitate", 8 | "Metadata invalid" : "Metadatos non valide", 9 | "Metadata valid" : "Metadatos valide", 10 | "Error" : "Error" 11 | }, 12 | "nplurals=2; plural=(n != 1);"); 13 | -------------------------------------------------------------------------------- /l10n/ia.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Salveguardate", 3 | "Open documentation" : "Aperir documentation", 4 | "General" : "General", 5 | "Security settings" : "Configurationes de securitate", 6 | "Metadata invalid" : "Metadatos non valide", 7 | "Metadata valid" : "Metadatos valide", 8 | "Error" : "Error" 9 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 10 | } -------------------------------------------------------------------------------- /l10n/id.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Tersimpan", 5 | "X.509 certificate of the Service Provider" : "Sertifikat X.509 Penyedia Layanan", 6 | "Private key of the Service Provider" : "Kunci pribadi Penyedia Layanan", 7 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Mengindikasikan bahwa nameID dari dikirimkan oleh SP ini akan dienkripsi", 8 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "Mengindikasikan apabila pesan dikirim dari SP ini akan ditandai. [Metadata SP akan menawarkan informasi ini]", 9 | "Indicates whether the messages sent by this SP will be signed." : "Mengindikasikan apabila pesan dikirim dari SP ini akan ditandai.", 10 | "Indicates whether the messages sent by this SP will be signed." : "Mengindikasikan apabila pesan dikirim dari SP ini akan ditandai.", 11 | "Whether the metadata should be signed." : "Apabila metadatanya harus ditandai.", 12 | "Indicates a requirement for the , and elements received by this SP to be signed." : "Mengindikasikan keharusan untuk elemen , dan diterima oleh SP ini ditandai.", 13 | "Indicates a requirement for the elements received by this SP to be signed. [Metadata of the SP will offer this info]" : "Mengindikasikan keharusan untuk elemen yang diterima SP ini untuk ditandai. [Metadata SP akan menawarkan informasi ini]", 14 | "Indicates a requirement for the elements received by this SP to be encrypted." : "Mengindikasikan keharusan elemen yang diterima SP ini untuk dienkripsi.", 15 | " Indicates a requirement for the NameID element on the SAMLResponse received by this SP to be present." : "Mengindikasikan keharusan untuk elemen NameID di SAMLResponse yang diterima oleh SP ini untuk hadir.", 16 | "Indicates a requirement for the NameID received by this SP to be encrypted." : "Mengindikasikan keharusan untuk elemen NameID yang diterima oleh SP ini untuk dienkripsi.", 17 | "Email address" : "Alamat surel", 18 | "Open documentation" : "Buka dokumentasi", 19 | "General" : "Umum", 20 | "Service Provider Data" : "Data Penyedia Layanan", 21 | "If your Service Provider should use certificates you can optionally specify them here." : "Apabila Penyedia Layanan Anda harus menggunakan sertifikat Anda dapat menentukannya di sini secara opsional.", 22 | "Identity Provider Data" : "Identitas Penyedia Data", 23 | "Identifier of the IdP entity (must be a URI)" : "Pengidentifikasian entitas IdP (harus berupa URI)", 24 | "URL Target of the IdP where the SP will send the Authentication Request Message" : "Target URL IdP dimana SP akan mengirim Pesan Permintaan Otentikasi", 25 | "URL Location of the IdP where the SP will send the SLO Request" : "Lokasi URL IdP dimana SP akan mengirim Permintaan SLO", 26 | "Public X.509 certificate of the IdP" : "Sertifikat publik X.509 IdP", 27 | "Security settings" : "Pengaturan keamanan", 28 | "For increased security we recommend enabling the following settings if supported by your environment." : "Untuk menambah keamanan kami merekomendasikan mengaktifkan pengaturan berikut apabila lingkungan Anda mendukungnya.", 29 | "Signatures and encryption offered" : "Tanda dan enkripsi ditawarkan", 30 | "Signatures and encryption required" : "Tanda dan enkripsi diperlukan", 31 | "Download metadata XML" : "Unduh metadata XML", 32 | "Metadata invalid" : "Metadata tidak sah", 33 | "Metadata valid" : "Metadata sah", 34 | "Error" : "Kesalahan", 35 | "Account not provisioned." : "Akun tidak ditetapkan.", 36 | "Your account is not provisioned, access to this service is thus not possible." : "Akun Anda tidak ditetapkan, akses ke layanan tidak mungkin." 37 | }, 38 | "nplurals=1; plural=0;"); 39 | -------------------------------------------------------------------------------- /l10n/id.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Tersimpan", 3 | "X.509 certificate of the Service Provider" : "Sertifikat X.509 Penyedia Layanan", 4 | "Private key of the Service Provider" : "Kunci pribadi Penyedia Layanan", 5 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Mengindikasikan bahwa nameID dari dikirimkan oleh SP ini akan dienkripsi", 6 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "Mengindikasikan apabila pesan dikirim dari SP ini akan ditandai. [Metadata SP akan menawarkan informasi ini]", 7 | "Indicates whether the messages sent by this SP will be signed." : "Mengindikasikan apabila pesan dikirim dari SP ini akan ditandai.", 8 | "Indicates whether the messages sent by this SP will be signed." : "Mengindikasikan apabila pesan dikirim dari SP ini akan ditandai.", 9 | "Whether the metadata should be signed." : "Apabila metadatanya harus ditandai.", 10 | "Indicates a requirement for the , and elements received by this SP to be signed." : "Mengindikasikan keharusan untuk elemen , dan diterima oleh SP ini ditandai.", 11 | "Indicates a requirement for the elements received by this SP to be signed. [Metadata of the SP will offer this info]" : "Mengindikasikan keharusan untuk elemen yang diterima SP ini untuk ditandai. [Metadata SP akan menawarkan informasi ini]", 12 | "Indicates a requirement for the elements received by this SP to be encrypted." : "Mengindikasikan keharusan elemen yang diterima SP ini untuk dienkripsi.", 13 | " Indicates a requirement for the NameID element on the SAMLResponse received by this SP to be present." : "Mengindikasikan keharusan untuk elemen NameID di SAMLResponse yang diterima oleh SP ini untuk hadir.", 14 | "Indicates a requirement for the NameID received by this SP to be encrypted." : "Mengindikasikan keharusan untuk elemen NameID yang diterima oleh SP ini untuk dienkripsi.", 15 | "Email address" : "Alamat surel", 16 | "Open documentation" : "Buka dokumentasi", 17 | "General" : "Umum", 18 | "Service Provider Data" : "Data Penyedia Layanan", 19 | "If your Service Provider should use certificates you can optionally specify them here." : "Apabila Penyedia Layanan Anda harus menggunakan sertifikat Anda dapat menentukannya di sini secara opsional.", 20 | "Identity Provider Data" : "Identitas Penyedia Data", 21 | "Identifier of the IdP entity (must be a URI)" : "Pengidentifikasian entitas IdP (harus berupa URI)", 22 | "URL Target of the IdP where the SP will send the Authentication Request Message" : "Target URL IdP dimana SP akan mengirim Pesan Permintaan Otentikasi", 23 | "URL Location of the IdP where the SP will send the SLO Request" : "Lokasi URL IdP dimana SP akan mengirim Permintaan SLO", 24 | "Public X.509 certificate of the IdP" : "Sertifikat publik X.509 IdP", 25 | "Security settings" : "Pengaturan keamanan", 26 | "For increased security we recommend enabling the following settings if supported by your environment." : "Untuk menambah keamanan kami merekomendasikan mengaktifkan pengaturan berikut apabila lingkungan Anda mendukungnya.", 27 | "Signatures and encryption offered" : "Tanda dan enkripsi ditawarkan", 28 | "Signatures and encryption required" : "Tanda dan enkripsi diperlukan", 29 | "Download metadata XML" : "Unduh metadata XML", 30 | "Metadata invalid" : "Metadata tidak sah", 31 | "Metadata valid" : "Metadata sah", 32 | "Error" : "Kesalahan", 33 | "Account not provisioned." : "Akun tidak ditetapkan.", 34 | "Your account is not provisioned, access to this service is thus not possible." : "Akun Anda tidak ditetapkan, akses ke layanan tidak mungkin." 35 | },"pluralForm" :"nplurals=1; plural=0;" 36 | } -------------------------------------------------------------------------------- /l10n/is.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Vistað", 5 | "Provider" : "Þjónustuveita", 6 | "This user account is disabled, please contact your administrator." : "Þessi notandaaðgangur er óvirkur; hafðu samband við kerfisstjóra.", 7 | "Unknown error, please check the log file for more details." : "Óþekkt villa, skoðaðu atvikaskráninguna til að sjá nánari upplýsingar.", 8 | "Direct log in" : "Bein innskráning", 9 | "SSO & SAML log in" : "SSO & SAML innskráning", 10 | "This page should not be visited directly." : "Þessa síðu ætti ekki að heimsækja beint.", 11 | "Provider " : "Þjónustuveita ", 12 | "X.509 certificate of the Service Provider" : "X.509 skilríki internetþjónustu", 13 | "Private key of the Service Provider" : "Einkalykill internetþjónustu", 14 | "Whether the metadata should be signed." : "Hvort undirrita eigi lýsigögnin.", 15 | "Email address" : "Tölvupóstfang", 16 | "Encrypted" : "Dulritað", 17 | "Entity" : "Einindi", 18 | "Kerberos" : "Kerberos", 19 | "Persistent" : "Viðvarandi", 20 | "Transient" : "Tímabundið", 21 | "Unspecified" : "Óskilgreint", 22 | "SSO & SAML authentication" : "SSO & SAML auðkenning", 23 | "Open documentation" : "Opna hjálparskjöl", 24 | "Use built-in SAML authentication" : "Nota innbyggða SAML-auðkenningu", 25 | "Use environment variable" : "Nota umhverfisbreytu", 26 | "Global settings" : "Víðværar stillingar", 27 | "Remove identity provider" : "Fjarlægja auðkenningarþjónustu", 28 | "Add identity provider" : "Bæta við auðkenningarþjónustu", 29 | "General" : "Almennt", 30 | "Service Provider Data" : "Gögn um internetþjónustu", 31 | "Show Service Provider settings…" : "Birta stillingar internetþjónustu…", 32 | "Identity Provider Data" : "Gögn um auðkenningarþjónustu", 33 | "Public X.509 certificate of the IdP" : "Opinbert X.509-skilríki fyrir IdP", 34 | "Attribute mapping" : "Vörpun eiginda", 35 | "Security settings" : "Öryggisstillingar", 36 | "Show security settings…" : "Birta öryggisstillingar…", 37 | "Signatures and encryption offered" : "Undirritanir og dulritun í boði", 38 | "Signatures and encryption required" : "Krafist er undirritunar og dulritununar", 39 | "Download metadata XML" : "Sækja XML-lýsigögn", 40 | "Reset settings" : "Frumstilla stillingar", 41 | "Metadata invalid" : "Lýsigögn eru ógild", 42 | "Metadata valid" : "Lýsigögn eru gild", 43 | "Error" : "Villa", 44 | "Account not provisioned." : "Aðgangur ekki tilbúinn." 45 | }, 46 | "nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);"); 47 | -------------------------------------------------------------------------------- /l10n/is.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Vistað", 3 | "Provider" : "Þjónustuveita", 4 | "This user account is disabled, please contact your administrator." : "Þessi notandaaðgangur er óvirkur; hafðu samband við kerfisstjóra.", 5 | "Unknown error, please check the log file for more details." : "Óþekkt villa, skoðaðu atvikaskráninguna til að sjá nánari upplýsingar.", 6 | "Direct log in" : "Bein innskráning", 7 | "SSO & SAML log in" : "SSO & SAML innskráning", 8 | "This page should not be visited directly." : "Þessa síðu ætti ekki að heimsækja beint.", 9 | "Provider " : "Þjónustuveita ", 10 | "X.509 certificate of the Service Provider" : "X.509 skilríki internetþjónustu", 11 | "Private key of the Service Provider" : "Einkalykill internetþjónustu", 12 | "Whether the metadata should be signed." : "Hvort undirrita eigi lýsigögnin.", 13 | "Email address" : "Tölvupóstfang", 14 | "Encrypted" : "Dulritað", 15 | "Entity" : "Einindi", 16 | "Kerberos" : "Kerberos", 17 | "Persistent" : "Viðvarandi", 18 | "Transient" : "Tímabundið", 19 | "Unspecified" : "Óskilgreint", 20 | "SSO & SAML authentication" : "SSO & SAML auðkenning", 21 | "Open documentation" : "Opna hjálparskjöl", 22 | "Use built-in SAML authentication" : "Nota innbyggða SAML-auðkenningu", 23 | "Use environment variable" : "Nota umhverfisbreytu", 24 | "Global settings" : "Víðværar stillingar", 25 | "Remove identity provider" : "Fjarlægja auðkenningarþjónustu", 26 | "Add identity provider" : "Bæta við auðkenningarþjónustu", 27 | "General" : "Almennt", 28 | "Service Provider Data" : "Gögn um internetþjónustu", 29 | "Show Service Provider settings…" : "Birta stillingar internetþjónustu…", 30 | "Identity Provider Data" : "Gögn um auðkenningarþjónustu", 31 | "Public X.509 certificate of the IdP" : "Opinbert X.509-skilríki fyrir IdP", 32 | "Attribute mapping" : "Vörpun eiginda", 33 | "Security settings" : "Öryggisstillingar", 34 | "Show security settings…" : "Birta öryggisstillingar…", 35 | "Signatures and encryption offered" : "Undirritanir og dulritun í boði", 36 | "Signatures and encryption required" : "Krafist er undirritunar og dulritununar", 37 | "Download metadata XML" : "Sækja XML-lýsigögn", 38 | "Reset settings" : "Frumstilla stillingar", 39 | "Metadata invalid" : "Lýsigögn eru ógild", 40 | "Metadata valid" : "Lýsigögn eru gild", 41 | "Error" : "Villa", 42 | "Account not provisioned." : "Aðgangur ekki tilbúinn." 43 | },"pluralForm" :"nplurals=2; plural=(n % 10 != 1 || n % 100 == 11);" 44 | } -------------------------------------------------------------------------------- /l10n/lt_LT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Įrašyta", 5 | "Could not save" : "Nepavyko įrašyti", 6 | "This user account is disabled, please contact your administrator." : "Ši naudotojo paskyra yra išjungta, susisiekite su administratoriumi.", 7 | "Unknown error, please check the log file for more details." : "Nežinoma klaida, išsamesnei informacijai žiūrėkite žurnalo failą.", 8 | "Direct log in" : "Tiesioginis prisijungimas", 9 | "X.509 certificate of the Service Provider" : "Paslaugų teikėjo X.509 liudijimas", 10 | "Private key of the Service Provider" : "Paslaugų teikėjo privatusis raktas", 11 | "Whether the metadata should be signed." : "Ar metaduomenys turėtų būti pasirašyti.", 12 | "Email address" : "El. pašto adresas", 13 | "Entity" : "Esybė", 14 | "SSO & SAML authentication" : "SSO & SAML tapatybės nustatymas", 15 | "Open documentation" : "Atverti dokumentaciją", 16 | "Use built-in SAML authentication" : "Naudoti įtaisytąjį SAML tapatybės nustatymą", 17 | "Use environment variable" : "Naudoti aplinkos kintamąjį", 18 | "Global settings" : "Visuotiniai nustatymai", 19 | "General" : "Bendra", 20 | "Service Provider Data" : "Paslaugų teikėjo duomenys", 21 | "If your Service Provider should use certificates you can optionally specify them here." : "Jeigu jūsų paslaugų teikėjas turėtų naudoti liudijimus, galite čia pasirinktinai juos nurodyti.", 22 | "Show Service Provider settings…" : "Rodyti paslaugų teikėjo nustatymus…", 23 | "Identity Provider Data" : "Tapatybės teikėjo duomenys", 24 | "Identifier of the IdP entity (must be a URI)" : "IdP esybės identifikatorius (privalo būti URI)", 25 | "Security settings" : "Saugumo nustatymai", 26 | "Show security settings…" : "Rodyti saugumo nustatymus…", 27 | "Signatures and encryption offered" : "Siūlomi parašai ir šifravimas", 28 | "Signatures and encryption required" : "Reikalingi parašai ir šifravimas", 29 | "Download metadata XML" : "Atsisiųsti metaduomenų XML", 30 | "Reset settings" : "Atstatyti nustatymus", 31 | "Metadata invalid" : "Metaduomenys neteisingi", 32 | "Metadata valid" : "Metaduomenys teisingi", 33 | "Error" : "Klaida", 34 | "Login options:" : "Prisijungimo parinktys:" 35 | }, 36 | "nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);"); 37 | -------------------------------------------------------------------------------- /l10n/lt_LT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Įrašyta", 3 | "Could not save" : "Nepavyko įrašyti", 4 | "This user account is disabled, please contact your administrator." : "Ši naudotojo paskyra yra išjungta, susisiekite su administratoriumi.", 5 | "Unknown error, please check the log file for more details." : "Nežinoma klaida, išsamesnei informacijai žiūrėkite žurnalo failą.", 6 | "Direct log in" : "Tiesioginis prisijungimas", 7 | "X.509 certificate of the Service Provider" : "Paslaugų teikėjo X.509 liudijimas", 8 | "Private key of the Service Provider" : "Paslaugų teikėjo privatusis raktas", 9 | "Whether the metadata should be signed." : "Ar metaduomenys turėtų būti pasirašyti.", 10 | "Email address" : "El. pašto adresas", 11 | "Entity" : "Esybė", 12 | "SSO & SAML authentication" : "SSO & SAML tapatybės nustatymas", 13 | "Open documentation" : "Atverti dokumentaciją", 14 | "Use built-in SAML authentication" : "Naudoti įtaisytąjį SAML tapatybės nustatymą", 15 | "Use environment variable" : "Naudoti aplinkos kintamąjį", 16 | "Global settings" : "Visuotiniai nustatymai", 17 | "General" : "Bendra", 18 | "Service Provider Data" : "Paslaugų teikėjo duomenys", 19 | "If your Service Provider should use certificates you can optionally specify them here." : "Jeigu jūsų paslaugų teikėjas turėtų naudoti liudijimus, galite čia pasirinktinai juos nurodyti.", 20 | "Show Service Provider settings…" : "Rodyti paslaugų teikėjo nustatymus…", 21 | "Identity Provider Data" : "Tapatybės teikėjo duomenys", 22 | "Identifier of the IdP entity (must be a URI)" : "IdP esybės identifikatorius (privalo būti URI)", 23 | "Security settings" : "Saugumo nustatymai", 24 | "Show security settings…" : "Rodyti saugumo nustatymus…", 25 | "Signatures and encryption offered" : "Siūlomi parašai ir šifravimas", 26 | "Signatures and encryption required" : "Reikalingi parašai ir šifravimas", 27 | "Download metadata XML" : "Atsisiųsti metaduomenų XML", 28 | "Reset settings" : "Atstatyti nustatymus", 29 | "Metadata invalid" : "Metaduomenys neteisingi", 30 | "Metadata valid" : "Metaduomenys teisingi", 31 | "Error" : "Klaida", 32 | "Login options:" : "Prisijungimo parinktys:" 33 | },"pluralForm" :"nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);" 34 | } -------------------------------------------------------------------------------- /l10n/lv.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Saglabāts", 5 | "Unknown error, please check the log file for more details." : "Nezināma kļūda, lūgums pārbaudīt žurnālu, lai iegūtu vairāk informācijas.", 6 | "X.509 certificate of the Service Provider" : "X.509 sertifikātu no pakalpojumu sniedzēja", 7 | "Private key of the Service Provider" : "Privātā atslēga no pakalpojumu sniedzēja", 8 | "Email address" : "E-pasta adrese", 9 | "SSO & SAML authentication" : "SSO & SAML autentifikācija", 10 | "Open documentation" : "Atvērt dokumentāciju", 11 | "Use built-in SAML authentication" : "Izmantot iebūvēto SAML autentifikācija", 12 | "Use environment variable" : "Izmantot vides mainīgo", 13 | "Global settings" : "Globālie iestatījumi", 14 | "General" : "Vispārīgi", 15 | "Service Provider Data" : "Pakalpojumu sniedzēja dati", 16 | "If your Service Provider should use certificates you can optionally specify them here." : "Ja pakalpojumu sniedzējs izmanto sertifikātus, tos vajadzības gadījumā var norādīt šeit.", 17 | "Identity Provider Data" : "Identitātes nodrošinātāja dati", 18 | "Security settings" : "Drošības iestatījumi", 19 | "For increased security we recommend enabling the following settings if supported by your environment." : "Lai paaugstinātu drošību, iesakām iespējot šos iestatījumus, ja to atbalsta jūsu vidē.", 20 | "Show security settings…" : "Rādīt drošības iestatījumus ...", 21 | "Signatures and encryption required" : "Paraksti un šifrēšana ir nepieciešama", 22 | "Download metadata XML" : "Lejupielādēt metadatu XML", 23 | "Reset settings" : "Atiestatīt iestatījumus", 24 | "Metadata invalid" : "Nederīgi metadati", 25 | "Metadata valid" : "Derīgi metadati", 26 | "Error" : "Kļūda", 27 | "Account not provisioned." : "Konts nav nodrošināts.", 28 | "Your account is not provisioned, access to this service is thus not possible." : "Jūsu konts netiek nodrošināts, tādējādi piekļuve šim pakalpojumam nav iespējama." 29 | }, 30 | "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"); 31 | -------------------------------------------------------------------------------- /l10n/lv.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Saglabāts", 3 | "Unknown error, please check the log file for more details." : "Nezināma kļūda, lūgums pārbaudīt žurnālu, lai iegūtu vairāk informācijas.", 4 | "X.509 certificate of the Service Provider" : "X.509 sertifikātu no pakalpojumu sniedzēja", 5 | "Private key of the Service Provider" : "Privātā atslēga no pakalpojumu sniedzēja", 6 | "Email address" : "E-pasta adrese", 7 | "SSO & SAML authentication" : "SSO & SAML autentifikācija", 8 | "Open documentation" : "Atvērt dokumentāciju", 9 | "Use built-in SAML authentication" : "Izmantot iebūvēto SAML autentifikācija", 10 | "Use environment variable" : "Izmantot vides mainīgo", 11 | "Global settings" : "Globālie iestatījumi", 12 | "General" : "Vispārīgi", 13 | "Service Provider Data" : "Pakalpojumu sniedzēja dati", 14 | "If your Service Provider should use certificates you can optionally specify them here." : "Ja pakalpojumu sniedzējs izmanto sertifikātus, tos vajadzības gadījumā var norādīt šeit.", 15 | "Identity Provider Data" : "Identitātes nodrošinātāja dati", 16 | "Security settings" : "Drošības iestatījumi", 17 | "For increased security we recommend enabling the following settings if supported by your environment." : "Lai paaugstinātu drošību, iesakām iespējot šos iestatījumus, ja to atbalsta jūsu vidē.", 18 | "Show security settings…" : "Rādīt drošības iestatījumus ...", 19 | "Signatures and encryption required" : "Paraksti un šifrēšana ir nepieciešama", 20 | "Download metadata XML" : "Lejupielādēt metadatu XML", 21 | "Reset settings" : "Atiestatīt iestatījumus", 22 | "Metadata invalid" : "Nederīgi metadati", 23 | "Metadata valid" : "Derīgi metadati", 24 | "Error" : "Kļūda", 25 | "Account not provisioned." : "Konts nav nodrošināts.", 26 | "Your account is not provisioned, access to this service is thus not possible." : "Jūsu konts netiek nodrošināts, tādējādi piekļuve šim pakalpojumam nav iespējama." 27 | },"pluralForm" :"nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);" 28 | } -------------------------------------------------------------------------------- /l10n/oc.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Enregistrat", 5 | "Email address" : "Adreça mail", 6 | "Encrypted" : "Chifrat", 7 | "Open documentation" : "Dobrir la documentacion", 8 | "Global settings" : "Paramètres globals", 9 | "General" : "Generals", 10 | "Security settings" : "Paramètres de seguretat", 11 | "Error" : "Error" 12 | }, 13 | "nplurals=2; plural=(n > 1);"); 14 | -------------------------------------------------------------------------------- /l10n/oc.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Enregistrat", 3 | "Email address" : "Adreça mail", 4 | "Encrypted" : "Chifrat", 5 | "Open documentation" : "Dobrir la documentacion", 6 | "Global settings" : "Paramètres globals", 7 | "General" : "Generals", 8 | "Security settings" : "Paramètres de seguretat", 9 | "Error" : "Error" 10 | },"pluralForm" :"nplurals=2; plural=(n > 1);" 11 | } -------------------------------------------------------------------------------- /l10n/pt_PT.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Guardado", 5 | "Could not save" : "Não foi possível guardar", 6 | "Provider" : "Fornecedor", 7 | "This user account is disabled, please contact your administrator." : "Esta conta do utilizador está desativada, por favor, contacte o seu administrador.", 8 | "Unknown error, please check the log file for more details." : "Erro desconhecido. Por favor, verifique o ficheiro de logs para obter mais detalhes.", 9 | "Direct log in" : "Início de Sessão direto", 10 | "SSO & SAML log in" : "Início de sessão SSO e SAML", 11 | "This page should not be visited directly." : "Esta página não deve ser visualizada diretamente.", 12 | "Provider " : "Fornecedor", 13 | "X.509 certificate of the Service Provider" : "Certificado X.509 do Fornecedor do Serviço", 14 | "Private key of the Service Provider" : "Chave privada do Fornecedor de Serviço", 15 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Indica que o nameID de enviado pelo Fornecedor do Serviço será encriptado.", 16 | "Whether the metadata should be signed." : "Se os metadados serão assinados.", 17 | "Attribute to map the UID to." : "Atributo para o qual quer mapear o UID.", 18 | "Email address" : "Endereço de email", 19 | "Encrypted" : "Encriptado", 20 | "Entity" : "Entidade", 21 | "Kerberos" : "Kerberos", 22 | "Persistent" : "Persistente", 23 | "Unspecified" : "Não especificado", 24 | "Windows domain qualified name" : "Nome de Domínio do Windows", 25 | "Allow the use of multiple user back-ends (e.g. LDAP)" : "Permitir a utilização de vários métodos de autenticação de utilizadores (ex. LDAP)", 26 | "SSO & SAML authentication" : "Autenticação SSO e SAML", 27 | "Authenticate using single sign-on" : "Autenticar utilizando Inicio de Sessão único", 28 | "Open documentation" : "Abrir documentação", 29 | "Use built-in SAML authentication" : "Utilizar a autenticação SAML incorporada", 30 | "Use environment variable" : "Usar variável de ambiente", 31 | "Global settings" : "Definições globais", 32 | "General" : "Geral", 33 | "Service Provider Data" : "Dados do Provedor de Serviço", 34 | "Attribute mapping" : "Mapeamento de atributos", 35 | "Show attribute mapping settings…" : "Ver definições do mapeamento de atributos", 36 | "Security settings" : "Definições de segurança", 37 | "Show security settings…" : "Mostrar definições de segurança...", 38 | "Signatures and encryption offered" : "Assinaturas e encriptação oferecida", 39 | "Signatures and encryption required" : "Assinaturas e encriptação necessárias", 40 | "User filtering" : "Filtro de utilizador", 41 | "Show user filtering settings …" : "Ver definições do filtro de utilizador ...", 42 | "Download metadata XML" : "Transferir metadados XML", 43 | "Reset settings" : "Reiniciar definições", 44 | "Metadata invalid" : "Metadados inválidos", 45 | "Metadata valid" : "Metadados válidos", 46 | "Error" : "Erro", 47 | "Access denied." : "Acesso negado.", 48 | "Your account is denied, access to this service is thus not possible." : "A sua conta foi negada e, por conseguinte, o acesso ao serviço não é possível.", 49 | "Account not provisioned." : "Conta não aprovisionada.", 50 | "Login options:" : "Opções de Início de Sessão:" 51 | }, 52 | "nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"); 53 | -------------------------------------------------------------------------------- /l10n/pt_PT.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Guardado", 3 | "Could not save" : "Não foi possível guardar", 4 | "Provider" : "Fornecedor", 5 | "This user account is disabled, please contact your administrator." : "Esta conta do utilizador está desativada, por favor, contacte o seu administrador.", 6 | "Unknown error, please check the log file for more details." : "Erro desconhecido. Por favor, verifique o ficheiro de logs para obter mais detalhes.", 7 | "Direct log in" : "Início de Sessão direto", 8 | "SSO & SAML log in" : "Início de sessão SSO e SAML", 9 | "This page should not be visited directly." : "Esta página não deve ser visualizada diretamente.", 10 | "Provider " : "Fornecedor", 11 | "X.509 certificate of the Service Provider" : "Certificado X.509 do Fornecedor do Serviço", 12 | "Private key of the Service Provider" : "Chave privada do Fornecedor de Serviço", 13 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Indica que o nameID de enviado pelo Fornecedor do Serviço será encriptado.", 14 | "Whether the metadata should be signed." : "Se os metadados serão assinados.", 15 | "Attribute to map the UID to." : "Atributo para o qual quer mapear o UID.", 16 | "Email address" : "Endereço de email", 17 | "Encrypted" : "Encriptado", 18 | "Entity" : "Entidade", 19 | "Kerberos" : "Kerberos", 20 | "Persistent" : "Persistente", 21 | "Unspecified" : "Não especificado", 22 | "Windows domain qualified name" : "Nome de Domínio do Windows", 23 | "Allow the use of multiple user back-ends (e.g. LDAP)" : "Permitir a utilização de vários métodos de autenticação de utilizadores (ex. LDAP)", 24 | "SSO & SAML authentication" : "Autenticação SSO e SAML", 25 | "Authenticate using single sign-on" : "Autenticar utilizando Inicio de Sessão único", 26 | "Open documentation" : "Abrir documentação", 27 | "Use built-in SAML authentication" : "Utilizar a autenticação SAML incorporada", 28 | "Use environment variable" : "Usar variável de ambiente", 29 | "Global settings" : "Definições globais", 30 | "General" : "Geral", 31 | "Service Provider Data" : "Dados do Provedor de Serviço", 32 | "Attribute mapping" : "Mapeamento de atributos", 33 | "Show attribute mapping settings…" : "Ver definições do mapeamento de atributos", 34 | "Security settings" : "Definições de segurança", 35 | "Show security settings…" : "Mostrar definições de segurança...", 36 | "Signatures and encryption offered" : "Assinaturas e encriptação oferecida", 37 | "Signatures and encryption required" : "Assinaturas e encriptação necessárias", 38 | "User filtering" : "Filtro de utilizador", 39 | "Show user filtering settings …" : "Ver definições do filtro de utilizador ...", 40 | "Download metadata XML" : "Transferir metadados XML", 41 | "Reset settings" : "Reiniciar definições", 42 | "Metadata invalid" : "Metadados inválidos", 43 | "Metadata valid" : "Metadados válidos", 44 | "Error" : "Erro", 45 | "Access denied." : "Acesso negado.", 46 | "Your account is denied, access to this service is thus not possible." : "A sua conta foi negada e, por conseguinte, o acesso ao serviço não é possível.", 47 | "Account not provisioned." : "Conta não aprovisionada.", 48 | "Login options:" : "Opções de Início de Sessão:" 49 | },"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;" 50 | } -------------------------------------------------------------------------------- /l10n/ro.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Salvat", 5 | "Direct log in" : "Autentificare directă", 6 | "SSO & SAML log in" : "Autentificare SSO & SAML", 7 | "Email address" : "Email", 8 | "Open documentation" : "Deschide documentația", 9 | "General" : "General", 10 | "If you want to optionally restrict user login depending on user data, configure it here." : "Dacă doriți să restricționați opțional autentificarea utilizatorilor în funcție de datele acestora, configurați aceasta aici. ", 11 | "Error" : "Eroare", 12 | "Login options:" : "Opțiuni de autentificare:" 13 | }, 14 | "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"); 15 | -------------------------------------------------------------------------------- /l10n/ro.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Salvat", 3 | "Direct log in" : "Autentificare directă", 4 | "SSO & SAML log in" : "Autentificare SSO & SAML", 5 | "Email address" : "Email", 6 | "Open documentation" : "Deschide documentația", 7 | "General" : "General", 8 | "If you want to optionally restrict user login depending on user data, configure it here." : "Dacă doriți să restricționați opțional autentificarea utilizatorilor în funcție de datele acestora, configurați aceasta aici. ", 9 | "Error" : "Eroare", 10 | "Login options:" : "Opțiuni de autentificare:" 11 | },"pluralForm" :"nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));" 12 | } -------------------------------------------------------------------------------- /l10n/sq.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "U ruajt", 5 | "X.509 certificate of the Service Provider" : "Çertifikata X.509 e ofruesit të shërbimit", 6 | "Private key of the Service Provider" : "Çelësi privat i Ofruesit të Shërbimit", 7 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Tregon se nameID i i dërguar nga kjo SP do të enkriptohet.", 8 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "Tregon nëse mesazhet  të dërguara nga kjo SP do të firmosen. [Metadata të kësaj SP do të ofrojnë këtë informacion]", 9 | "Indicates whether the messages sent by this SP will be signed." : "Tregon nëse mesazhet të dëguara nga ky SP do të nënshkruhen.", 10 | "Indicates whether the messages sent by this SP will be signed." : "Tregon nëse mesazhet   të dërguara nga kjo SP do të firmosen.", 11 | "Whether the metadata should be signed." : "Nëse duhet të nënshkruhet metadata", 12 | "Indicates a requirement for the , and elements received by this SP to be signed." : "Tregon një nevojë për elementët , and të marra nga kjo SP për t'u nënshkruar.", 13 | "Indicates a requirement for the elements received by this SP to be signed. [Metadata of the SP will offer this info]" : "Tregon një nevojë për elementet të marra nga kjo SP për t'u nënshkruar. [Metadata të SP do të ofrojnë këtë informacion]", 14 | "Indicates a requirement for the elements received by this SP to be encrypted." : "Tregon nje kërkesë të elementëve të marrë nga kjo SP për tu enkriptuar.", 15 | " Indicates a requirement for the NameID element on the SAMLResponse received by this SP to be present." : "Tregon një kërkesë për elementin NameID nëSAMLResponse e marrë nga kjo SP për tu prezantuar.", 16 | "Indicates a requirement for the NameID received by this SP to be encrypted." : "Tregon një kërkesë për EmërID të marrë nga ky PS për t'u koduar.", 17 | "Indicates if the SP will validate all received XML." : "Tregon nëse SP do të quaj të vlefshëm të gjitha XML e marra.", 18 | "ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification." : "ADFS URL-Kodon të dhënat SAMP në shkronja të vogla, dhe toolkit sipas parapërzgjedhjes përdor shkronja të vogla. Aktivizo pajtueshmërinë e ADFS në verifikimin e firmës.", 19 | "Attribute to map the UID to." : "Atributi për të identifikuar UID.", 20 | "Attribute to map the displayname to." : "Atributi për të mapuar emrin e shfaqjes në.", 21 | "Attribute to map the email address to." : "Atributi për të hartuar adresën e postës elektronike në.", 22 | "Encrypted" : "E ekriptuar", 23 | "SSO & SAML authentication" : "Identifikim SSO & SAML", 24 | "Open documentation" : "Dokumentacion i hapur", 25 | "Please choose whether you want to authenticate using the SAML provider built-in in Nextcloud or whether you want to authenticate against an environment variable." : "Ju lutem zgjidhni nëse doni të vërtetoni përdorimin e ofruesit SAML të ndërtuar në Nextcloud ose nëse dëshironi të vërtetoni kundër një ndryshoreje mjedisi.", 26 | "Use built-in SAML authentication" : "Përdor identifikimin me SAML", 27 | "Use environment variable" : "Përdor variablin e mjedisit", 28 | "General" : "Të përgjithshme", 29 | "Service Provider Data" : "Të dhënat e ofruesit të shërbimit", 30 | "If your Service Provider should use certificates you can optionally specify them here." : "Nëse Ofruesi i Shërbimit tuaj duhet të përdori çertifikata ju mund ti specifikoni ato këtu.", 31 | "Show Service Provider settings…" : "Trego konfigurimet e Ofruesit të Shërbimit", 32 | "Identity Provider Data" : "Identifiko Ofruesin e të Dhënave", 33 | "Identifier of the IdP entity (must be a URI)" : "Identifikues i ekzistencës së IdP(duhet të jetë një URI)", 34 | "URL Target of the IdP where the SP will send the Authentication Request Message" : "Targeti URL i IdP ku PS do të dërgojë Mesazhin e Kërkesës së Autentifikimit", 35 | "Show optional Identity Provider settings…" : "Trego konfigurimet opsionale të Dhënësit të Identitetit ...", 36 | "URL Location of the IdP where the SP will send the SLO Request" : "Vendndodhja URL e IDP ku PS do të dërgojë Kërkesën SLO", 37 | "Public X.509 certificate of the IdP" : "Çertifikatë publike X.509 e IdP", 38 | "Attribute mapping" : "Përcaktimi i atributeve", 39 | "If you want to optionally map attributes to the user you can configure these here." : "Nëse dëshironi të maponi atributet tek përdoruesi opsionalisht, ju mund t'i konfiguroni ato këtu.", 40 | "Show attribute mapping settings…" : "Trego konfigurimet e përcaktimit të atributeve...", 41 | "Security settings" : "Konfigurimet e sigurisë", 42 | "For increased security we recommend enabling the following settings if supported by your environment." : "Për të rritur nivelin e sigurisë ne ju rekomandojmë të mundësoni konfigurimet në vijim nëse ato suportohen nga mjedisi juaj.", 43 | "Show security settings…" : "Trego konfigurimet e sigurisë...", 44 | "Signatures and encryption offered" : "Firmat dhe enkriptimi janë ofruara", 45 | "Signatures and encryption required" : "Kërkohet firma dhe enkriptimi", 46 | "Download metadata XML" : "Shkarko metadata XML", 47 | "Metadata invalid" : "Metadata jo e vlefshme", 48 | "Metadata valid" : "Metadata e vlefshme", 49 | "Error" : "Error", 50 | "Account not provisioned." : "Llogaria nuk është e provizionuar", 51 | "Your account is not provisioned, access to this service is thus not possible." : "Llogaria juaj nuk është e provizionuar, prandaj aksesi në këtë pajisje nuk është i munduar." 52 | }, 53 | "nplurals=2; plural=(n != 1);"); 54 | -------------------------------------------------------------------------------- /l10n/sq.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "U ruajt", 3 | "X.509 certificate of the Service Provider" : "Çertifikata X.509 e ofruesit të shërbimit", 4 | "Private key of the Service Provider" : "Çelësi privat i Ofruesit të Shërbimit", 5 | "Indicates that the nameID of the sent by this SP will be encrypted." : "Tregon se nameID i i dërguar nga kjo SP do të enkriptohet.", 6 | "Indicates whether the messages sent by this SP will be signed. [Metadata of the SP will offer this info]" : "Tregon nëse mesazhet  të dërguara nga kjo SP do të firmosen. [Metadata të kësaj SP do të ofrojnë këtë informacion]", 7 | "Indicates whether the messages sent by this SP will be signed." : "Tregon nëse mesazhet të dëguara nga ky SP do të nënshkruhen.", 8 | "Indicates whether the messages sent by this SP will be signed." : "Tregon nëse mesazhet   të dërguara nga kjo SP do të firmosen.", 9 | "Whether the metadata should be signed." : "Nëse duhet të nënshkruhet metadata", 10 | "Indicates a requirement for the , and elements received by this SP to be signed." : "Tregon një nevojë për elementët , and të marra nga kjo SP për t'u nënshkruar.", 11 | "Indicates a requirement for the elements received by this SP to be signed. [Metadata of the SP will offer this info]" : "Tregon një nevojë për elementet të marra nga kjo SP për t'u nënshkruar. [Metadata të SP do të ofrojnë këtë informacion]", 12 | "Indicates a requirement for the elements received by this SP to be encrypted." : "Tregon nje kërkesë të elementëve të marrë nga kjo SP për tu enkriptuar.", 13 | " Indicates a requirement for the NameID element on the SAMLResponse received by this SP to be present." : "Tregon një kërkesë për elementin NameID nëSAMLResponse e marrë nga kjo SP për tu prezantuar.", 14 | "Indicates a requirement for the NameID received by this SP to be encrypted." : "Tregon një kërkesë për EmërID të marrë nga ky PS për t'u koduar.", 15 | "Indicates if the SP will validate all received XML." : "Tregon nëse SP do të quaj të vlefshëm të gjitha XML e marra.", 16 | "ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses uppercase. Enable for ADFS compatibility on signature verification." : "ADFS URL-Kodon të dhënat SAMP në shkronja të vogla, dhe toolkit sipas parapërzgjedhjes përdor shkronja të vogla. Aktivizo pajtueshmërinë e ADFS në verifikimin e firmës.", 17 | "Attribute to map the UID to." : "Atributi për të identifikuar UID.", 18 | "Attribute to map the displayname to." : "Atributi për të mapuar emrin e shfaqjes në.", 19 | "Attribute to map the email address to." : "Atributi për të hartuar adresën e postës elektronike në.", 20 | "Encrypted" : "E ekriptuar", 21 | "SSO & SAML authentication" : "Identifikim SSO & SAML", 22 | "Open documentation" : "Dokumentacion i hapur", 23 | "Please choose whether you want to authenticate using the SAML provider built-in in Nextcloud or whether you want to authenticate against an environment variable." : "Ju lutem zgjidhni nëse doni të vërtetoni përdorimin e ofruesit SAML të ndërtuar në Nextcloud ose nëse dëshironi të vërtetoni kundër një ndryshoreje mjedisi.", 24 | "Use built-in SAML authentication" : "Përdor identifikimin me SAML", 25 | "Use environment variable" : "Përdor variablin e mjedisit", 26 | "General" : "Të përgjithshme", 27 | "Service Provider Data" : "Të dhënat e ofruesit të shërbimit", 28 | "If your Service Provider should use certificates you can optionally specify them here." : "Nëse Ofruesi i Shërbimit tuaj duhet të përdori çertifikata ju mund ti specifikoni ato këtu.", 29 | "Show Service Provider settings…" : "Trego konfigurimet e Ofruesit të Shërbimit", 30 | "Identity Provider Data" : "Identifiko Ofruesin e të Dhënave", 31 | "Identifier of the IdP entity (must be a URI)" : "Identifikues i ekzistencës së IdP(duhet të jetë një URI)", 32 | "URL Target of the IdP where the SP will send the Authentication Request Message" : "Targeti URL i IdP ku PS do të dërgojë Mesazhin e Kërkesës së Autentifikimit", 33 | "Show optional Identity Provider settings…" : "Trego konfigurimet opsionale të Dhënësit të Identitetit ...", 34 | "URL Location of the IdP where the SP will send the SLO Request" : "Vendndodhja URL e IDP ku PS do të dërgojë Kërkesën SLO", 35 | "Public X.509 certificate of the IdP" : "Çertifikatë publike X.509 e IdP", 36 | "Attribute mapping" : "Përcaktimi i atributeve", 37 | "If you want to optionally map attributes to the user you can configure these here." : "Nëse dëshironi të maponi atributet tek përdoruesi opsionalisht, ju mund t'i konfiguroni ato këtu.", 38 | "Show attribute mapping settings…" : "Trego konfigurimet e përcaktimit të atributeve...", 39 | "Security settings" : "Konfigurimet e sigurisë", 40 | "For increased security we recommend enabling the following settings if supported by your environment." : "Për të rritur nivelin e sigurisë ne ju rekomandojmë të mundësoni konfigurimet në vijim nëse ato suportohen nga mjedisi juaj.", 41 | "Show security settings…" : "Trego konfigurimet e sigurisë...", 42 | "Signatures and encryption offered" : "Firmat dhe enkriptimi janë ofruara", 43 | "Signatures and encryption required" : "Kërkohet firma dhe enkriptimi", 44 | "Download metadata XML" : "Shkarko metadata XML", 45 | "Metadata invalid" : "Metadata jo e vlefshme", 46 | "Metadata valid" : "Metadata e vlefshme", 47 | "Error" : "Error", 48 | "Account not provisioned." : "Llogaria nuk është e provizionuar", 49 | "Your account is not provisioned, access to this service is thus not possible." : "Llogaria juaj nuk është e provizionuar, prandaj aksesi në këtë pajisje nuk është i munduar." 50 | },"pluralForm" :"nplurals=2; plural=(n != 1);" 51 | } -------------------------------------------------------------------------------- /l10n/th.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "บันทึกแล้ว", 5 | "Provider" : "ผู้ให้บริการ", 6 | "This user account is disabled, please contact your administrator." : "บัญชีผู้ใช้นี้ถูกปิดการใช้งาน กรุณาติดต่อผู้ดูแลระบบ", 7 | "Email address" : "ที่อยู่อีเมล", 8 | "Open documentation" : "เปิดเอกสารประกอบ", 9 | "General" : "ทั่วไป", 10 | "Error" : "ข้อผิดพลาด" 11 | }, 12 | "nplurals=1; plural=0;"); 13 | -------------------------------------------------------------------------------- /l10n/th.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "บันทึกแล้ว", 3 | "Provider" : "ผู้ให้บริการ", 4 | "This user account is disabled, please contact your administrator." : "บัญชีผู้ใช้นี้ถูกปิดการใช้งาน กรุณาติดต่อผู้ดูแลระบบ", 5 | "Email address" : "ที่อยู่อีเมล", 6 | "Open documentation" : "เปิดเอกสารประกอบ", 7 | "General" : "ทั่วไป", 8 | "Error" : "ข้อผิดพลาด" 9 | },"pluralForm" :"nplurals=1; plural=0;" 10 | } -------------------------------------------------------------------------------- /l10n/vi.js: -------------------------------------------------------------------------------- 1 | OC.L10N.register( 2 | "user_saml", 3 | { 4 | "Saved" : "Đã lưu", 5 | "Email address" : "Địa chỉ thư điện tử", 6 | "Encrypted" : "Đã mã hóa", 7 | "Open documentation" : "Mở tài liệu", 8 | "General" : "Tổng hợp", 9 | "Error" : "Lỗi" 10 | }, 11 | "nplurals=1; plural=0;"); 12 | -------------------------------------------------------------------------------- /l10n/vi.json: -------------------------------------------------------------------------------- 1 | { "translations": { 2 | "Saved" : "Đã lưu", 3 | "Email address" : "Địa chỉ thư điện tử", 4 | "Encrypted" : "Đã mã hóa", 5 | "Open documentation" : "Mở tài liệu", 6 | "General" : "Tổng hợp", 7 | "Error" : "Lỗi" 8 | },"pluralForm" :"nplurals=1; plural=0;" 9 | } -------------------------------------------------------------------------------- /lib/Command/ConfigCreate.php: -------------------------------------------------------------------------------- 1 | setName('saml:config:create'); 25 | $this->setDescription('Creates a new config and prints the new provider ID'); 26 | } 27 | 28 | protected function execute(InputInterface $input, OutputInterface $output): int { 29 | $output->writeln((string)$this->samlSettings->getNewProviderId()); 30 | return 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/Command/ConfigDelete.php: -------------------------------------------------------------------------------- 1 | setName('saml:config:delete'); 27 | 28 | $this->addArgument( 29 | 'providerId', 30 | InputArgument::REQUIRED, 31 | 'ProviderID of the SAML config to edit' 32 | ); 33 | } 34 | 35 | protected function execute(InputInterface $input, OutputInterface $output): int { 36 | $pId = (int)$input->getArgument('providerId'); 37 | 38 | if ((string)$pId !== $input->getArgument('providerId')) { 39 | // Make sure we don't delete provider with id 0 by error 40 | $output->writeln('providerId argument needs to be an number. Got: ' . $pId . ''); 41 | return 1; 42 | } 43 | try { 44 | $this->samlSettings->delete($pId); 45 | $output->writeln('Provider deleted.'); 46 | } catch (Exception) { 47 | $output->writeln('Provider with id: ' . $pId . ' does not exist.'); 48 | return 1; 49 | } 50 | return 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/Command/ConfigGet.php: -------------------------------------------------------------------------------- 1 | setName('saml:config:get'); 26 | 27 | $this->addOption( 28 | 'providerId', 29 | 'p', 30 | InputOption::VALUE_REQUIRED, 31 | 'ProviderID of a SAML config to print' 32 | ); 33 | parent::configure(); 34 | } 35 | 36 | protected function execute(InputInterface $input, OutputInterface $output): int { 37 | $providerId = (int)$input->getOption('providerId'); 38 | if (!empty($providerId)) { 39 | $providerIds = [$providerId]; 40 | } else { 41 | $providerIds = array_keys($this->samlSettings->getListOfIdps()); 42 | } 43 | 44 | $settings = []; 45 | foreach ($providerIds as $pid) { 46 | $settings[$pid] = $this->samlSettings->get($pid); 47 | } 48 | 49 | $this->writeArrayInOutputFormat($input, $output, $settings); 50 | 51 | return 0; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/Command/ConfigSet.php: -------------------------------------------------------------------------------- 1 | setName('saml:config:set'); 28 | 29 | $this->addArgument( 30 | 'providerId', 31 | InputArgument::REQUIRED, 32 | 'ProviderID of the SAML config to edit' 33 | ); 34 | 35 | foreach (SAMLSettings::IDP_CONFIG_KEYS as $key) { 36 | $this->addOption( 37 | $key, 38 | null, 39 | InputOption::VALUE_REQUIRED, 40 | ); 41 | } 42 | 43 | parent::configure(); 44 | } 45 | 46 | protected function execute(InputInterface $input, OutputInterface $output): int { 47 | $pId = (int)$input->getArgument('providerId'); 48 | 49 | if ((string)$pId !== $input->getArgument('providerId')) { 50 | // Make sure we don't delete provider with id 0 by error 51 | $output->writeln('providerId argument needs to be an number. Got: ' . $pId . ''); 52 | return 1; 53 | } 54 | try { 55 | $settings = $this->samlSettings->get($pId); 56 | } catch (Exception) { 57 | $output->writeln('Provider with id: ' . $pId . ' does not exist.'); 58 | return 1; 59 | } 60 | 61 | foreach ($input->getOptions() as $key => $value) { 62 | if (!in_array($key, SAMLSettings::IDP_CONFIG_KEYS) || $value === null) { 63 | continue; 64 | } 65 | if ($value === '') { 66 | unset($settings[$key]); 67 | continue; 68 | } 69 | $settings[$key] = $value; 70 | } 71 | $this->samlSettings->set($pId, $settings); 72 | $output->writeln('The provider\'s config was updated.'); 73 | 74 | return 0; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/Command/GetMetadata.php: -------------------------------------------------------------------------------- 1 | setName('saml:metadata') 30 | ->setDescription('Get SAML Metadata') 31 | ->setHelp(<<addArgument( 40 | 'idp', 41 | InputArgument::OPTIONAL, 42 | 'ID of the IDP you want metadata for', 43 | '1' 44 | ) 45 | ; 46 | } 47 | 48 | protected function execute(InputInterface $input, OutputInterface $output): int { 49 | $idp = (int)$input->getArgument('idp'); 50 | $settingsArray = $this->samlSettings->getOneLoginSettingsArray($idp); 51 | $settings = new Settings($settingsArray); 52 | $metadata = $settings->getSPMetadata(); 53 | $errors = $this->callWithXmlEntityLoader(fn () => $settings->validateMetadata($metadata)); 54 | if (empty($errors)) { 55 | $output->writeln($metadata); 56 | } else { 57 | throw new Error( 58 | 'Invalid SP metadata: ' . implode(', ', $errors), 59 | Error::METADATA_SP_INVALID 60 | ); 61 | } 62 | return 0; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/Command/GroupMigrationCopyIncomplete.php: -------------------------------------------------------------------------------- 1 | setName('saml:group-migration:copy-incomplete-members'); 26 | $this->setDescription('Transfers remaining group members from old local to current SAML groups'); 27 | } 28 | 29 | protected function execute(InputInterface $input, OutputInterface $output): int { 30 | $groupsToTreat = $this->groupMigration->findGroupsWithLocalMembers(); 31 | if (empty($groupsToTreat)) { 32 | if ($output->isVerbose()) { 33 | $output->writeln('No pending group member transfer'); 34 | } 35 | return 0; 36 | } 37 | 38 | if (!$this->doMemberTransfer($groupsToTreat, $output)) { 39 | if (!$output->isQuiet()) { 40 | $output->writeln('Not all group members could be transferred completely. Rerun this command or check the Nextcloud log.'); 41 | } 42 | return 1; 43 | } 44 | 45 | if (!$output->isQuiet()) { 46 | $output->writeln('All group members could be transferred completely.'); 47 | } 48 | return 0; 49 | } 50 | 51 | /** 52 | * @param string[]|array $groups 53 | * @param OutputInterface $output 54 | * @return bool 55 | */ 56 | protected function doMemberTransfer(array $groups, OutputInterface $output): bool { 57 | $errorOccurred = false; 58 | for ($i = 0; $i < 2; $i++) { 59 | $retry = []; 60 | foreach ($groups as $gid) { 61 | try { 62 | $isComplete = $this->groupMigration->migrateGroupUsers($gid); 63 | if (!$isComplete) { 64 | $retry[] = $gid; 65 | } else { 66 | $this->groupMigration->cleanUpOldGroupUsers($gid); 67 | if ($output->isVerbose()) { 68 | $output->writeln(sprintf('Members transferred successfully for group %s', $gid)); 69 | } 70 | } 71 | } catch (Throwable $e) { 72 | $errorOccurred = true; 73 | if (!$output->isQuiet()) { 74 | $output->writeln(sprintf('Failed to transfer users from group %s: %s', $gid, $e->getMessage())); 75 | } 76 | $this->logger->warning('Error while transferring group members of {gid}', ['gid' => $gid, 'exception' => $e]); 77 | } 78 | } 79 | if (empty($retry)) { 80 | return true; 81 | } 82 | /** @var string[]|array $groups */ 83 | $groups = $retry; 84 | } 85 | if (!empty($groups) && !$output->isQuiet()) { 86 | $output->writeln(sprintf( 87 | 'Members not or incompletely transferred for groups: %s', 88 | implode(', ', $groups) 89 | )); 90 | } 91 | return empty($groups) && !$errorOccurred; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/Controller/SettingsController.php: -------------------------------------------------------------------------------- 1 | samlSettings->getListOfIdps()); 33 | return new DataResponse([ 'providerIds' => implode(',', $keys)]); 34 | } 35 | 36 | /** 37 | * @return array of categories containing entries for each config parameter with their value 38 | */ 39 | public function getSamlProviderSettings(int $providerId): array { 40 | /** 41 | * This uses the list of available config parameters from the admin section 42 | * and extends it with fields that are not coming from \OCA\User_SAML\Settings\Admin 43 | */ 44 | $params = $this->admin->getForm()->getParams(); 45 | $params['idp'] = [ 46 | 'singleLogoutService.url' => ['required' => false], 47 | 'singleLogoutService.responseUrl' => ['required' => false], 48 | 'singleSignOnService.url' => ['required' => false], 49 | 'entityId' => ['required' => false], 50 | 'x509cert' => ['required' => false], 51 | 'passthroughParameters' => ['required' => false], 52 | ]; 53 | /* Fetch all config values for the given providerId */ 54 | 55 | // initialize settings with default value for option box (others are left empty) 56 | $settings['sp']['name-id-format'] = Constants::NAMEID_UNSPECIFIED; 57 | $storedSettings = $this->samlSettings->get($providerId); 58 | foreach ($params as $category => $content) { 59 | if (empty($content) || $category === 'providers' || $category === 'type') { 60 | continue; 61 | } 62 | foreach ($content as $setting => $details) { 63 | /* use security as category instead of security-* */ 64 | if (str_starts_with($category, 'security-')) { 65 | $category = 'security'; 66 | } 67 | // make sure we properly fetch the attribute mapping 68 | // as this is the only category that has the saml- prefix on config keys 69 | if (str_starts_with($category, 'attribute-mapping')) { 70 | $category = 'attribute-mapping'; 71 | $key = 'saml-attribute-mapping' . '-' . $setting; 72 | } elseif ($category === 'name-id-formats') { 73 | if ($setting === $storedSettings['sp-name-id-format']) { 74 | $settings['sp']['name-id-format'] = $storedSettings['sp-name-id-format']; 75 | //continue 2; 76 | } 77 | continue; 78 | } else { 79 | $key = $category . '-' . $setting; 80 | } 81 | 82 | if (isset($details['global']) && $details['global']) { 83 | // Read legacy data from oc_appconfig 84 | $settings[$category][$setting] = $this->config->getAppValue('user_saml', $key, ''); 85 | } else { 86 | $settings[$category][$setting] = $storedSettings[$key] ?? ''; 87 | } 88 | } 89 | } 90 | return $settings; 91 | } 92 | 93 | public function deleteSamlProviderSettings($providerId): Response { 94 | $this->samlSettings->delete($providerId); 95 | return new Response(); 96 | } 97 | 98 | public function setProviderSetting(int $providerId, string $configKey, string $configValue): Response { 99 | $configuration = $this->samlSettings->get($providerId); 100 | $configuration[$configKey] = $configValue; 101 | $this->samlSettings->set($providerId, $configuration); 102 | return new Response(); 103 | } 104 | 105 | public function newSamlProviderSettingsId(): DataResponse { 106 | return new DataResponse(['id' => $this->samlSettings->getNewProviderId()]); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /lib/Controller/TimezoneController.php: -------------------------------------------------------------------------------- 1 | config->setUserValue($this->userId, 'core', 'timezone', $timezone); 36 | $this->session->set('timezone', $timezoneOffset); 37 | 38 | return new JSONResponse(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/DavPlugin.php: -------------------------------------------------------------------------------- 1 | on('beforeMethod:*', $this->beforeMethod(...), 9); 33 | $this->server = $server; 34 | } 35 | 36 | public function beforeMethod(RequestInterface $request, ResponseInterface $response) { 37 | if ( 38 | $this->config->getAppValue('user_saml', 'type') === 'environment-variable' && 39 | !$this->session->exists('user_saml.samlUserData') 40 | ) { 41 | $uidMapping = $this->samlSettings->get(1)['general-uid_mapping']; 42 | if (isset($this->auth[$uidMapping])) { 43 | $this->session->set(Auth::DAV_AUTHENTICATED, $this->auth[$uidMapping]); 44 | $this->session->set('user_saml.samlUserData', $this->auth); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/Db/ConfigurationsEntity.php: -------------------------------------------------------------------------------- 1 | addType('name', 'string'); 28 | $this->addType('configuration', 'string'); 29 | } 30 | 31 | /** 32 | * sets also the name, because it is a shorthand to 'general-idp0_display_name' 33 | * 34 | * @throws \JsonException 35 | */ 36 | public function importConfiguration(array $configuration): void { 37 | $this->setConfiguration(json_encode($configuration, JSON_THROW_ON_ERROR)); 38 | $this->setName($configuration['general-idp0_display_name'] ?? ''); 39 | } 40 | 41 | public function getConfigurationArray(): array { 42 | return json_decode($this->configuration, true) ?? []; 43 | } 44 | 45 | public function asArray(): array { 46 | return [ 47 | 'id' => $this->getId(), 48 | 'name' => $this->getName(), 49 | 'configuration' => $this->getConfigurationArray() 50 | ]; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/Db/ConfigurationsMapper.php: -------------------------------------------------------------------------------- 1 | setId($id); 23 | $entity->importConfiguration($configuration); 24 | $this->insertOrUpdate($entity); 25 | } 26 | 27 | public function deleteById(int $id): void { 28 | $entity = new ConfigurationsEntity(); 29 | $entity->setId($id); 30 | $this->delete($entity); 31 | } 32 | 33 | public function getAll(): array { 34 | $qb = $this->db->getQueryBuilder(); 35 | $qb->select('id', 'configuration') 36 | ->from('user_saml_configurations') 37 | ->orderBy('id', 'ASC'); 38 | 39 | /** @var ConfigurationsEntity $entity */ 40 | $entities = $this->findEntities($qb); 41 | $result = []; 42 | foreach ($entities as $entity) { 43 | $result[$entity->getId()] = $entity->getConfigurationArray(); 44 | } 45 | return $result; 46 | } 47 | 48 | public function get(int $idp): array { 49 | $qb = $this->db->getQueryBuilder(); 50 | $qb->select('id', 'configuration') 51 | ->from('user_saml_configurations') 52 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($idp, IQueryBuilder::PARAM_INT))); 53 | 54 | /** @var ConfigurationsEntity $entity */ 55 | try { 56 | $entity = $this->findEntity($qb); 57 | } catch (DoesNotExistException) { 58 | return []; 59 | } 60 | return $entity->getConfigurationArray(); 61 | } 62 | 63 | public function reserveId(): int { 64 | $qb = $this->db->getQueryBuilder(); 65 | $qb->select('id') 66 | ->from('user_saml_configurations') 67 | ->orderBy('id', 'DESC') 68 | ->setMaxResults(1); 69 | 70 | try { 71 | $entity = $this->findEntity($qb); 72 | $newId = $entity->getId() + 1; // autoincrement manually 73 | } catch (DoesNotExistException) { 74 | $newId = 1; 75 | } 76 | 77 | $newEntity = new ConfigurationsEntity(); 78 | $newEntity->setId($newId); 79 | $newEntity->importConfiguration([]); 80 | return $this->insert($newEntity)->getId(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/Exceptions/GroupNotFoundException.php: -------------------------------------------------------------------------------- 1 | $system); 17 | $result = $func(); 18 | libxml_set_external_entity_loader(static fn () => null); 19 | return $result; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/Jobs/MigrateGroups.php: -------------------------------------------------------------------------------- 1 | getMigratableGroups(); 51 | $toMigrate = $this->getGroupsToMigrate($argument['gids'], $candidates); 52 | $migrated = $this->migrateGroups($toMigrate); 53 | $this->ownGroupManager->updateCandidatePool($migrated); 54 | } catch (\RuntimeException) { 55 | return; 56 | } 57 | } 58 | 59 | protected function migrateGroups(array $toMigrate): array { 60 | return array_filter($toMigrate, fn ($gid) => $this->migrateGroup($gid)); 61 | } 62 | 63 | protected function migrateGroup(string $gid): bool { 64 | $isMigrated = false; 65 | $allUsersInserted = false; 66 | try { 67 | $allUsersInserted = $this->groupMigration->migrateGroupUsers($gid); 68 | 69 | $this->dbc->beginTransaction(); 70 | 71 | $qb = $this->dbc->getQueryBuilder(); 72 | $affected = $qb->delete('groups') 73 | ->where($qb->expr()->eq('gid', $qb->createNamedParameter($gid))) 74 | ->executeStatement(); 75 | if ($affected === 0) { 76 | throw new \RuntimeException('Could not delete group from local backend'); 77 | } 78 | if (!$this->ownGroupBackend->createGroup($gid)) { 79 | throw new \RuntimeException('Could not create group in SAML backend'); 80 | } 81 | 82 | $this->dbc->commit(); 83 | $isMigrated = true; 84 | } catch (Throwable $e) { 85 | $this->dbc->rollBack(); 86 | $this->logger->warning($e->getMessage(), ['app' => 'user_saml', 'exception' => $e]); 87 | } 88 | 89 | if ($allUsersInserted && $isMigrated) { 90 | try { 91 | $this->groupMigration->cleanUpOldGroupUsers($gid); 92 | } catch (Exception $e) { 93 | $this->logger->warning('Error while cleaning up group members in (oc_)group_user of group (gid) {gid}', [ 94 | 'app' => 'user_saml', 95 | 'gid' => $gid, 96 | 'exception' => $e, 97 | ]); 98 | } 99 | } 100 | 101 | return $isMigrated; 102 | } 103 | 104 | protected function getGroupsToMigrate(array $samlGroups, array $pool): array { 105 | return array_filter($samlGroups, function (string $gid) use ($pool) { 106 | if (!in_array($gid, $pool)) { 107 | return false; 108 | } 109 | 110 | $group = $this->groupManager->get($gid); 111 | if ($group === null) { 112 | $this->logger->debug('Not migrating group "{gid}": not found by the group manager', [ 113 | 'app' => 'user_saml', 114 | 'gid' => $gid, 115 | ]); 116 | return false; 117 | } 118 | 119 | $backendNames = $group->getBackendNames(); 120 | if (!in_array('Database', $backendNames, true)) { 121 | $this->logger->debug('Not migrating group "{gid}": not belonging to local database backend', [ 122 | 'app' => 'user_saml', 123 | 'gid' => $gid, 124 | 'backends' => $backendNames, 125 | ]); 126 | return false; 127 | } 128 | 129 | foreach ($group->getUsers() as $user) { 130 | if ($user->getBackendClassName() !== 'user_saml') { 131 | $this->logger->debug('Not migrating group "{gid}": user "{userId}" from a different backend "{userBackend}"', [ 132 | 'app' => 'user_saml', 133 | 'gid' => $gid, 134 | 'userId' => $user->getUID(), 135 | 'userBackend' => $user->getBackendClassName(), 136 | ]); 137 | return false; 138 | } 139 | } 140 | 141 | return true; 142 | }); 143 | } 144 | 145 | protected function getMigratableGroups(): array { 146 | $candidateInfo = $this->ownGroupManager->getCandidateInfoIfValid(); 147 | if ($candidateInfo === null) { 148 | throw new \RuntimeException('No migration tasks of groups to SAML backend'); 149 | } 150 | 151 | return $candidateInfo['groups']; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /lib/Listener/LoadAdditionalScriptsListener.php: -------------------------------------------------------------------------------- 1 | */ 21 | class LoadAdditionalScriptsListener implements IEventListener { 22 | public function __construct( 23 | private readonly ISession $session, 24 | private readonly IUserSession $userSession, 25 | private readonly IConfig $config, 26 | ) { 27 | } 28 | 29 | public function handle(Event $event): void { 30 | if (!$event instanceof BeforeTemplateRenderedEvent) { 31 | return; 32 | } 33 | 34 | if (!$event->isLoggedIn()) { 35 | return; 36 | } 37 | 38 | $user = $this->userSession->getUser(); 39 | $timezoneDB = $this->config->getUserValue($user->getUID(), 'core', 'timezone', ''); 40 | 41 | if ($timezoneDB === '' || !$this->session->exists('timezone')) { 42 | Util::addScript('user_saml', 'vendor/jstz.min'); 43 | Util::addScript('user_saml', 'timezone'); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/Listener/SabrePluginEventListener.php: -------------------------------------------------------------------------------- 1 | */ 19 | class SabrePluginEventListener implements IEventListener { 20 | public function handle(Event $event): void { 21 | if (!$event instanceof SabrePluginAddEvent) { 22 | return; 23 | } 24 | $event->getServer()->addPlugin(Server::get(DavPlugin::class)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/Middleware/OnlyLoggedInMiddleware.php: -------------------------------------------------------------------------------- 1 | reflector->hasAnnotation('OnlyUnauthenticatedUsers') && $this->userSession->isLoggedIn()) { 38 | throw new \Exception('User is already logged-in'); 39 | } 40 | } 41 | 42 | /** 43 | * @param \OCP\AppFramework\Controller $controller 44 | * @param string $methodName 45 | * @param \Exception $exception 46 | * @return RedirectResponse 47 | * @throws \Exception 48 | */ 49 | public function afterException($controller, $methodName, \Exception $exception) { 50 | if ($exception->getMessage() === 'User is already logged-in') { 51 | return new RedirectResponse($this->urlGenerator->getAbsoluteURL('/')); 52 | } 53 | 54 | throw $exception; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/Migration/CleanupRemovedConfig.php: -------------------------------------------------------------------------------- 1 | config->deleteAppValue('user_saml', 'general-use_saml_auth_for_desktop'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/Migration/RememberLocalGroupsForPotentialMigrations.php: -------------------------------------------------------------------------------- 1 | config->getAppValue('user_saml', GroupManager::LOCAL_GROUPS_CHECK_FOR_MIGRATION, ''); 41 | if ($candidateInfo !== '') { 42 | return; 43 | } 44 | 45 | try { 46 | $backend = $this->findBackend(); 47 | $groupIds = $this->findGroupIds($backend); 48 | } catch (UnexpectedValueException) { 49 | return; 50 | } 51 | 52 | $this->config->setAppValue( 53 | 'user_saml', 54 | GroupManager::LOCAL_GROUPS_CHECK_FOR_MIGRATION, 55 | json_encode([ 56 | 'dropAfter' => time() + 86400 * 60, // 60 days 57 | 'groups' => $groupIds 58 | ]) 59 | ); 60 | } 61 | 62 | protected function findGroupIds(Database $backend): array { 63 | $groupIds = $backend->getGroups(); 64 | $adminGroupIndex = array_search('admin', $groupIds, true); 65 | if ($adminGroupIndex !== false) { 66 | unset($groupIds[$adminGroupIndex]); 67 | } 68 | return $groupIds; 69 | } 70 | 71 | protected function findBackend(): Database { 72 | $groupBackends = $this->groupManager->getBackends(); 73 | foreach ($groupBackends as $backend) { 74 | if ($backend instanceof Database) { 75 | return $backend; 76 | } 77 | } 78 | throw new UnexpectedValueException(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/Migration/TransferGroupMembers.php: -------------------------------------------------------------------------------- 1 | groupMigration->findGroupsWithLocalMembers(); 30 | if (empty($groupsToTreat)) { 31 | return; 32 | } 33 | $hasError = false; 34 | $output->startProgress(count($groupsToTreat)); 35 | foreach ($groupsToTreat as $gid) { 36 | try { 37 | if ($this->groupMigration->migrateGroupUsers($gid)) { 38 | $this->groupMigration->cleanUpOldGroupUsers($gid); 39 | } 40 | } catch (Throwable $e) { 41 | $hasError = true; 42 | $this->logger->warning('Error while transferring group members of {gid}', ['gid' => $gid, 'exception' => $e]); 43 | } finally { 44 | $output->advance(); 45 | } 46 | } 47 | $output->finishProgress(); 48 | if ($hasError) { 49 | $output->warning('There were errors while transferring group members to SAML groups. You may try later `occ saml:group-migration:copy-incomplete-members` later and check your nextcloud.log.'); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/Migration/Version3001Date20200630193443.php: -------------------------------------------------------------------------------- 1 | hasTable('user_saml_users')) { 28 | $table = $schema->createTable('user_saml_users'); 29 | $table->addColumn('uid', Types::STRING, [ 30 | 'notnull' => true, 31 | 'length' => 64, 32 | 'default' => '', 33 | ]); 34 | $table->addColumn('displayname', Types::STRING, [ 35 | 'notnull' => true, 36 | 'length' => 255, 37 | 'default' => '', 38 | ]); 39 | $table->addColumn('home', Types::STRING, [ 40 | 'notnull' => true, 41 | 'length' => 255, 42 | 'default' => '', 43 | ]); 44 | $table->setPrimaryKey(['uid']); 45 | } 46 | 47 | return $schema; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/Migration/Version6000Date20220912152700.php: -------------------------------------------------------------------------------- 1 | hasTable('user_saml_groups')) { 29 | $table = $schema->createTable('user_saml_groups'); 30 | $table->addColumn('gid', Types::STRING, [ 31 | 'notnull' => true, 32 | 'length' => 64, 33 | 'default' => '', 34 | ]); 35 | $table->addColumn('displayname', Types::STRING, [ 36 | 'notnull' => true, 37 | 'length' => 255, 38 | 'default' => '', 39 | ]); 40 | $table->addColumn('saml_gid', Types::STRING, [ 41 | 'notnull' => true, 42 | 'length' => 64, 43 | 'default' => '', 44 | ]); 45 | $table->setPrimaryKey(['gid']); 46 | $table->addUniqueIndex(['saml_gid']); 47 | } 48 | 49 | if (!$schema->hasTable('user_saml_group_members')) { 50 | $table = $schema->createTable('user_saml_group_members'); 51 | $table->addColumn('uid', Types::STRING, [ 52 | 'notnull' => true, 53 | 'length' => 64, 54 | 'default' => '', 55 | ]); 56 | $table->addColumn('gid', Types::STRING, [ 57 | 'notnull' => true, 58 | 'length' => 64, 59 | 'default' => '', 60 | ]); 61 | $table->setPrimaryKey(['gid', 'uid'], 'pk_saml_group_members'); 62 | $table->addIndex(['gid'], 'saml_group_members_gid'); // prefix is added in callee 63 | $table->addIndex(['uid'], 'saml_group_members_uid'); // prefix is added in callee 64 | } 65 | return $schema; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/Migration/Version6001Date20240202183823.php: -------------------------------------------------------------------------------- 1 | hasTable('user_saml_auth_token')) { 30 | $schema->dropTable('user_saml_auth_token'); 31 | } 32 | 33 | return $schema; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/Service/GroupMigration.php: -------------------------------------------------------------------------------- 1 | dbc->getQueryBuilder(); 40 | $qb->selectDistinct('gid') 41 | ->from('group_user') 42 | ->where($qb->expr()->in('gid', $qb->createParameter('gidList'))); 43 | 44 | $allOwnedGroups = $this->ownGroupBackend->getGroups(); 45 | foreach (array_chunk($allOwnedGroups, self::CHUNK_SIZE) as $groupsChunk) { 46 | $qb->setParameter('gidList', $groupsChunk, IQueryBuilder::PARAM_STR_ARRAY); 47 | $result = $qb->executeQuery(); 48 | while ($gid = $result->fetchOne()) { 49 | $foundGroups[] = $gid; 50 | } 51 | $result->closeCursor(); 52 | } 53 | 54 | return $foundGroups; 55 | } 56 | 57 | /** 58 | * @returns bool true when all users were migrated, when they were only partly migrated 59 | * @throws Exception 60 | * @throws Throwable 61 | */ 62 | public function migrateGroupUsers(string $gid): bool { 63 | $originalGroup = $this->groupManager->get($gid); 64 | $members = $originalGroup?->getUsers(); 65 | 66 | $areAllInserted = true; 67 | foreach (array_chunk($members ?? [], (int)floor(self::CHUNK_SIZE / 2)) as $userBatch) { 68 | $areAllInserted = ($this->atomic(function () use ($userBatch, $gid) { 69 | /** @var IUser $user */ 70 | foreach ($userBatch as $user) { 71 | $this->dbc->insertIgnoreConflict( 72 | GroupBackend::TABLE_MEMBERS, 73 | [ 74 | 'gid' => $gid, 75 | 'uid' => $user->getUID(), 76 | ] 77 | ); 78 | } 79 | return true; 80 | }, $this->dbc) === true) && $areAllInserted; 81 | } 82 | if (!$areAllInserted) { 83 | $this->logger->warning('Partial migration of users from local group {gid} to SAML.', [ 84 | 'app' => 'user_saml', 85 | 'gid' => $gid, 86 | ]); 87 | } 88 | return $areAllInserted; 89 | } 90 | 91 | /** 92 | * @throws Exception 93 | */ 94 | public function cleanUpOldGroupUsers(string $gid): void { 95 | $cleanup = $this->dbc->getQueryBuilder(); 96 | $cleanup->delete('group_user') 97 | ->where($cleanup->expr()->eq('gid', $cleanup->createNamedParameter($gid))); 98 | $cleanup->executeStatement(); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /lib/Settings/Section.php: -------------------------------------------------------------------------------- 1 | l->t('SSO & SAML authentication'); 34 | } 35 | 36 | /** 37 | * {@inheritdoc} 38 | */ 39 | public function getPriority() { 40 | return 75; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function getIcon() { 47 | return $this->url->imagePath('user_saml', 'app-dark.svg'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/UserData.php: -------------------------------------------------------------------------------- 1 | attributes = $attributes; 26 | $this->uid = null; // clear the state in case 27 | } 28 | 29 | public function getAttributes(): array { 30 | $this->assertIsInitialized(); 31 | return $this->attributes; 32 | } 33 | 34 | public function hasUidMappingAttribute(): bool { 35 | $this->assertIsInitialized(); 36 | $attribute = $this->getUidMappingAttribute(); 37 | return $attribute !== null && isset($this->attributes[$attribute]); 38 | } 39 | 40 | public function getOriginalUid(): string { 41 | $this->assertIsInitialized(); 42 | return $this->extractSamlUserId(); 43 | } 44 | 45 | public function getEffectiveUid(): string { 46 | if ($this->uid !== null) { 47 | return $this->uid; 48 | } 49 | $this->assertIsInitialized(); 50 | try { 51 | $uid = $this->extractSamlUserId(); 52 | $uid = $this->testEncodedObjectGUID($uid); 53 | $uid = $this->userResolver->findExistingUserId($uid, true); 54 | $this->uid = $uid; 55 | } catch (NoUserFoundException) { 56 | return ''; 57 | } 58 | return $uid; 59 | } 60 | 61 | public function getGroups(): array { 62 | $this->assertIsInitialized(); 63 | $mapping = $this->getProviderSettings()['saml-attribute-mapping-group_mapping'] ?? null; 64 | if ($mapping === null || !isset($this->attributes[$mapping])) { 65 | return []; 66 | } 67 | 68 | return is_array($this->attributes[$mapping]) 69 | ? $this->attributes[$mapping] 70 | : array_map('trim', explode(',', (string)$this->attributes[$mapping])); 71 | } 72 | 73 | protected function extractSamlUserId(): string { 74 | $uidMapping = $this->getUidMappingAttribute(); 75 | if ($uidMapping !== null && isset($this->attributes[$uidMapping])) { 76 | if (is_array($this->attributes[$uidMapping])) { 77 | return trim((string)$this->attributes[$uidMapping][0]); 78 | } else { 79 | return trim((string)$this->attributes[$uidMapping]); 80 | } 81 | } 82 | return ''; 83 | } 84 | 85 | /** 86 | * returns the plain text UUID if the provided $uid string is a 87 | * base64-encoded binary string representing e.g. the objectGUID. Otherwise 88 | * 89 | */ 90 | public function testEncodedObjectGUID(string $uid): string { 91 | if (preg_match('/[^a-zA-Z0-9=+\/]/', $uid) !== 0) { 92 | // certainly not encoded 93 | return $uid; 94 | } 95 | 96 | $candidate = base64_decode($uid, true); 97 | if ($candidate === false) { 98 | return $uid; 99 | } 100 | $candidate = $this->convertObjectGUID2Str($candidate); 101 | // the regex only matches the structure of the UUID, not its semantic 102 | // (i.e. version or variant) simply to be future compatible 103 | if (preg_match('/^[a-f0-9]{8}(-[a-f0-9]{4}){4}[a-f0-9]{8}$/i', $candidate) === 1) { 104 | $uid = $candidate; 105 | } 106 | return $uid; 107 | } 108 | 109 | /** 110 | * @see \OCA\User_LDAP\Access::convertObjectGUID2Str 111 | */ 112 | protected function convertObjectGUID2Str($oguid): string { 113 | $hex_guid = bin2hex((string)$oguid); 114 | $hex_guid_to_guid_str = ''; 115 | for ($k = 1; $k <= 4; ++$k) { 116 | $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2); 117 | } 118 | $hex_guid_to_guid_str .= '-'; 119 | for ($k = 1; $k <= 2; ++$k) { 120 | $hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2); 121 | } 122 | $hex_guid_to_guid_str .= '-'; 123 | for ($k = 1; $k <= 2; ++$k) { 124 | $hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2); 125 | } 126 | $hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4); 127 | $hex_guid_to_guid_str .= '-' . substr($hex_guid, 20); 128 | 129 | return strtoupper($hex_guid_to_guid_str); 130 | } 131 | 132 | protected function assertIsInitialized() { 133 | if ($this->attributes === null) { 134 | throw new \LogicException('UserData have to be initialized with setAttributes first'); 135 | } 136 | } 137 | 138 | protected function getProviderSettings(): array { 139 | return $this->samlSettings->get($this->samlSettings->getProviderId()); 140 | } 141 | 142 | protected function getUidMappingAttribute(): ?string { 143 | return $this->getProviderSettings()['general-uid_mapping'] ?? null; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /lib/UserResolver.php: -------------------------------------------------------------------------------- 1 | userManager = $userManager; 21 | } 22 | 23 | /** 24 | * @throws NoUserFoundException 25 | */ 26 | public function findExistingUserId(string $rawUidCandidate, bool $force = false): string { 27 | if ($force) { 28 | $this->ensureUser($rawUidCandidate); 29 | } 30 | if ($this->userManager->userExists($rawUidCandidate)) { 31 | return $rawUidCandidate; 32 | } 33 | try { 34 | $sanitized = $this->sanitizeUserIdCandidate($rawUidCandidate); 35 | } catch (\InvalidArgumentException) { 36 | $sanitized = ''; 37 | } 38 | if ($this->userManager->userExists($sanitized)) { 39 | return $sanitized; 40 | } 41 | throw new NoUserFoundException('User' . $rawUidCandidate . ' not valid or not found'); 42 | } 43 | 44 | /** 45 | * @throws NoUserFoundException 46 | */ 47 | public function findExistingUser(string $rawUidCandidate): IUser { 48 | $uid = $this->findExistingUserId($rawUidCandidate); 49 | $user = $this->userManager->get($uid); 50 | if ($user === null) { 51 | throw new NoUserFoundException('User' . $rawUidCandidate . ' not valid or not found'); 52 | } 53 | return $user; 54 | } 55 | 56 | public function userExists(string $uid, bool $force = false): bool { 57 | try { 58 | $this->findExistingUserId($uid, $force); 59 | return true; 60 | } catch (NoUserFoundException) { 61 | return false; 62 | } 63 | } 64 | 65 | protected function ensureUser($search) { 66 | $this->userManager->search($search); 67 | } 68 | 69 | /** 70 | * @throws \InvalidArgumentException 71 | */ 72 | protected function sanitizeUserIdCandidate(string $rawUidCandidate): string { 73 | //FIXME: adjusted copy of LDAP's Access::sanitizeUsername(), should go to API 74 | $sanitized = trim($rawUidCandidate); 75 | 76 | // Transliteration to ASCII 77 | $transliterated = @iconv('UTF-8', 'ASCII//TRANSLIT', $sanitized); 78 | if ($transliterated !== false) { 79 | // depending on system config iconv can work or not 80 | $sanitized = $transliterated; 81 | } 82 | 83 | // Replacements 84 | $sanitized = str_replace(' ', '_', $sanitized); 85 | 86 | // Every remaining disallowed characters will be removed 87 | $sanitized = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $sanitized); 88 | 89 | if ($sanitized === '') { 90 | throw new \InvalidArgumentException('provided name template for username does not contain any allowed characters'); 91 | } 92 | 93 | return $sanitized; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /psalm.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /rector.php: -------------------------------------------------------------------------------- 1 | withPaths([ 15 | __DIR__ . '/appinfo', 16 | __DIR__ . '/lib', 17 | __DIR__ . '/tests', 18 | ]) 19 | ->withSkip([ 20 | __DIR__ . '/tests/integration/vendor', 21 | ]) 22 | // uncomment to reach your current PHP version 23 | ->withPhpSets(php81: true) 24 | ->withSets([ 25 | NextcloudSets::NEXTCLOUD_30, 26 | ]) 27 | ->withTypeCoverageLevel(0); 28 | -------------------------------------------------------------------------------- /screenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/user_saml/aad65bd5f0574b6de44f5c549e8552fc2a910604/screenshots/1.png -------------------------------------------------------------------------------- /screenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nextcloud/user_saml/aad65bd5f0574b6de44f5c549e8552fc2a910604/screenshots/2.png -------------------------------------------------------------------------------- /templates/error.php: -------------------------------------------------------------------------------- 1 | 7 |
8 |

t('Error')) ?>

9 |

10 |
11 | -------------------------------------------------------------------------------- /templates/login_post.php: -------------------------------------------------------------------------------- 1 | t('Please wait while you are redirected to the SSO server.')); 16 | ?> 17 | 18 |
19 | 20 | 21 | 22 | 23 | 29 |
30 | 35 | -------------------------------------------------------------------------------- /templates/notPermitted.php: -------------------------------------------------------------------------------- 1 | 7 |
    8 |
  • 9 | t('Access denied.')) ?>
    10 |

    t('Your account is denied, access to this service is thus not possible.')) ?>

    11 |
  • 12 |
13 | -------------------------------------------------------------------------------- /templates/notProvisioned.php: -------------------------------------------------------------------------------- 1 | 7 |
    8 |
  • 9 | t('Account not provisioned.')) ?>
    10 |

    t('Your account is not provisioned, access to this service is thus not possible.')) ?>

    11 |
  • 12 |
13 | -------------------------------------------------------------------------------- /templates/selectUserBackEnd.php: -------------------------------------------------------------------------------- 1 | 14 | 15 |
16 | 17 |

t('Login options:')); ?>

18 | 19 | 20 | 21 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | 43 | 44 | 45 | 46 | 47 |
48 | -------------------------------------------------------------------------------- /tests/integration/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "config": { 3 | "platform": { 4 | "php": "8.0" 5 | } 6 | }, 7 | "require": { 8 | "php": ">=8.0" 9 | }, 10 | "require-dev": { 11 | "behat/behat": "^3.3", 12 | "guzzlehttp/guzzle": "^7.0" 13 | }, 14 | "conflict": { 15 | "psr/container": ">=1.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/integration/features/EnvironmentVariable.feature: -------------------------------------------------------------------------------- 1 | Feature: EnvironmentVariable 2 | 3 | Scenario: Authenticating using environment variable with SSO and no check if user exists on backend 4 | And The setting "type" is set to "environment-variable" 5 | And The setting "general-uid_mapping" is set to "REMOTE_USER" 6 | And The setting "saml-attribute-mapping-group_mapping" is set to "REMOTE_GROUPS" 7 | And The environment variable "REMOTE_USER" is set to "not-provisioned-user" 8 | And The environment variable "REMOTE_GROUPS" is set to "Department A,Team B" 9 | When I send a GET request to "http://localhost:8080/index.php/login" 10 | Then I should be redirected to "http://localhost:8080/index.php/apps/dashboard/" 11 | Then The user value "id" should be "not-provisioned-user" 12 | And The last login timestamp of "not-provisioned-user" should not be empty 13 | And User "not-provisioned-user" is part of the groups "SAML_Department A, SAML_Team B" 14 | 15 | Scenario: Authenticating using environment variable with SSO and successful check if user exists on backend 16 | Given A local user with uid "provisioned-user" exists 17 | And The setting "type" is set to "environment-variable" 18 | And The setting "general-require_provisioned_account" is set to "1" 19 | And The setting "general-uid_mapping" is set to "REMOTE_USER" 20 | And The environment variable "REMOTE_USER" is set to "provisioned-user" 21 | When I send a GET request to "http://localhost:8080/index.php/login" 22 | Then I should be redirected to "http://localhost:8080/index.php/apps/dashboard/" 23 | Then The user value "id" should be "provisioned-user" 24 | And The last login timestamp of "provisioned-user" should not be empty 25 | 26 | Scenario: Authenticating using environment variable with SSO and unsuccessful check if user exists on backend 27 | Given The setting "type" is set to "environment-variable" 28 | And The setting "general-require_provisioned_account" is set to "1" 29 | And The setting "general-uid_mapping" is set to "REMOTE_USER" 30 | And The environment variable "REMOTE_USER" is set to "certainly-not-provisioned-user" 31 | When I send a GET request to "http://localhost:8080/index.php/login" 32 | Then I should be redirected to "http://localhost:8080/index.php/apps/user_saml/saml/notProvisioned" 33 | 34 | Scenario: Authenticating using environment variable with SSO as a disabled user on backend 35 | Given A local user with uid "provisioned-disabled-user" exists 36 | And A local user with uid "provisioned-disabled-user" is disabled 37 | And The setting "type" is set to "environment-variable" 38 | And The setting "general-require_provisioned_account" is set to "1" 39 | And The setting "general-uid_mapping" is set to "REMOTE_USER" 40 | And The environment variable "REMOTE_USER" is set to "provisioned-disabled-user" 41 | When I send a GET request to "http://localhost:8080/index.php/login" 42 | Then I should be redirected to "http://localhost:8080/index.php/apps/user_saml/saml/error" 43 | -------------------------------------------------------------------------------- /tests/psalm-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /tests/stub.phpstub: -------------------------------------------------------------------------------- 1 | app = new Application(); 21 | $this->container = $this->app->getContainer(); 22 | } 23 | 24 | public function testContainerAppName() { 25 | $this->app = new Application(); 26 | $this->assertEquals('user_saml', $this->container->getAppName()); 27 | } 28 | 29 | public function queryData() { 30 | return [ 31 | [OnlyLoggedInMiddleware::class], 32 | ]; 33 | } 34 | 35 | /** 36 | * @dataProvider queryData 37 | * @param string $service 38 | * @param string $expected 39 | */ 40 | public function testContainerQuery($serviceClass) { 41 | $this->assertTrue($this->container->query($serviceClass) instanceof $serviceClass); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /tests/unit/Command/GetMetadataTest.php: -------------------------------------------------------------------------------- 1 | samlSettings = $this->createMock(SAMLSettings::class); 25 | $this->GetMetadata = new GetMetadata($this->samlSettings); 26 | 27 | parent::setUp(); 28 | } 29 | public function testGetMetadata() { 30 | $inputInterface = $this->createMock(InputInterface::class); 31 | $outputInterface = $this->createMock(OutputInterface::class); 32 | 33 | $inputInterface->expects($this->any()) 34 | ->method('getArgument') 35 | ->with('idp') 36 | ->willReturn('1'); 37 | 38 | $this->samlSettings->expects($this->any()) 39 | ->method('getOneLoginSettingsArray') 40 | ->willReturn([ 41 | 'baseurl' => 'https://nextcloud.com/base/', 42 | 'idp' => [ 43 | 'entityId' => 'dummy', 44 | 'singleSignOnService' => ['url' => 'https://example.com/sso'], 45 | 'x509cert' => 'DUMMY CERTIFICATE', 46 | ], 47 | 'sp' => [ 48 | 'entityId' => 'https://nextcloud.com/metadata/', 49 | 'assertionConsumerService' => [ 50 | 'url' => 'https://nextcloud.com/acs/', 51 | ], 52 | ] 53 | ]); 54 | 55 | $outputInterface->expects($this->once()) 56 | ->method('writeln') 57 | ->with($this->stringContains('md:EntityDescriptor')); 58 | 59 | $result = $this->invokePrivate($this->GetMetadata, 'execute', [$inputInterface, $outputInterface]); 60 | 61 | $this->assertEquals(0, $result); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/unit/GroupBackendTest.php: -------------------------------------------------------------------------------- 1 | 'user_saml_integration_test_uid1', 23 | 'groups' => [ 24 | 'user_saml_integration_test_gid1', 25 | 'SAML_user_saml_integration_test_gid2' 26 | ] 27 | ], 28 | [ 29 | 'uid' => 'user_saml_integration_test_uid2', 30 | 'groups' => [ 31 | 'user_saml_integration_test_gid1' 32 | ] 33 | ] 34 | ]; 35 | private $groups = [ 36 | [ 37 | 'gid' => 'user_saml_integration_test_gid1', 38 | 'saml_gid' => 'user_saml_integration_test_gid1', 39 | 'members' => [ 40 | 'user_saml_integration_test_uid1', 41 | 'user_saml_integration_test_uid2' 42 | ], 43 | 'saml_gid_exists' => true 44 | ], 45 | [ 46 | 'gid' => 'SAML_user_saml_integration_test_gid2', 47 | 'saml_gid' => 'user_saml_integration_test_gid2', 48 | 'members' => [ 49 | 'user_saml_integration_test_uid1' 50 | ], 51 | 'saml_gid_exists' => false 52 | ], 53 | [ 54 | 'gid' => 'user_saml_integration_test_gid3', 55 | 'saml_gid' => 'user_saml_integration_test_gid3', 56 | 'members' => [], 57 | 'saml_gid_exists' => true 58 | ], 59 | ]; 60 | 61 | public function setUp(): void { 62 | parent::setUp(); 63 | $this->groupBackend = new GroupBackend(\OCP\Server::get(IDBConnection::class), $this->createMock(LoggerInterface::class)); 64 | foreach ($this->groups as $group) { 65 | $this->groupBackend->createGroup($group['gid'], $group['saml_gid']); 66 | } 67 | foreach ($this->users as $user) { 68 | foreach ($user['groups'] as $group) { 69 | $this->groupBackend->addToGroup($user['uid'], $group); 70 | } 71 | } 72 | } 73 | 74 | public function tearDown(): void { 75 | parent::tearDown(); 76 | $this->groupBackend = new GroupBackend(\OCP\Server::get(IDBConnection::class), $this->createMock(LoggerInterface::class)); 77 | foreach ($this->users as $user) { 78 | foreach ($user['groups'] as $group) { 79 | $this->groupBackend->removeFromGroup($user['uid'], $group); 80 | } 81 | } 82 | foreach ($this->groups as $group) { 83 | $this->groupBackend->deleteGroup($group['gid']); 84 | } 85 | } 86 | 87 | public function testInGroup() { 88 | foreach ($this->groups as $group) { 89 | foreach ($this->users as $user) { 90 | $result = $this->groupBackend->inGroup($user['uid'], $group['gid']); 91 | if (in_array($group['gid'], $user['groups'])) { 92 | $this->assertTrue($result, sprintf('User %s should be member of group %s', $user['uid'], $group['gid'])); 93 | } else { 94 | $this->assertFalse($result, sprintf('User %s should not be member of group %s', $user['uid'], $group['gid'])); 95 | } 96 | } 97 | } 98 | } 99 | 100 | public function testGetGroups() { 101 | $groups = $this->groupBackend->getGroups(); 102 | foreach ($this->groups as $group) { 103 | $this->assertContains($group['gid'], $groups, sprintf('Group %s should be retrieved', $group['gid'])); 104 | } 105 | } 106 | 107 | public function testGetUserGroups() { 108 | foreach ($this->users as $user) { 109 | $userGroups = $this->groupBackend->getUserGroups($user['uid']); 110 | $this->assertCount(count($user['groups']), $userGroups, 'Should retrieve all user groups'); 111 | foreach ($userGroups as $userGroup) { 112 | $this->assertContains($userGroup, $user['groups'], sprintf('Users %s should be member of groups %s', $user['uid'], $userGroup)); 113 | } 114 | } 115 | } 116 | 117 | public function testGroupExists() { 118 | foreach ($this->groups as $group) { 119 | $result = $this->groupBackend->groupExists($group['saml_gid']); 120 | $this->assertSame($group['saml_gid_exists'], $result, sprintf('Group %s should exist', $group['saml_gid'])); 121 | } 122 | } 123 | 124 | public function testUsersInGroups() { 125 | foreach ($this->groups as $group) { 126 | $users = $this->groupBackend->usersInGroup($group['gid']); 127 | $this->assertCount(count($group['members']), $users, 'Should retrieve all group members'); 128 | foreach ($users as $user) { 129 | $this->assertContains($user, $group['members'], sprintf('User %s should be member of group %s', $user, $group['gid'])); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /tests/unit/Middleware/OnlyLoggedInMiddlewareTest.php: -------------------------------------------------------------------------------- 1 | reflector = $this->createMock(IControllerMethodReflector::class); 30 | $this->userSession = $this->createMock(IUserSession::class); 31 | $this->urlGenerator = $this->createMock(IURLGenerator::class); 32 | $this->onlyLoggedInMiddleware = new OnlyLoggedInMiddleware( 33 | $this->reflector, 34 | $this->userSession, 35 | $this->urlGenerator 36 | ); 37 | 38 | parent::setUp(); 39 | } 40 | 41 | public function testBeforeControllerWithoutAnnotation() { 42 | $this->reflector 43 | ->expects($this->once()) 44 | ->method('hasAnnotation') 45 | ->with('OnlyUnauthenticatedUsers') 46 | ->willReturn(false); 47 | $this->userSession 48 | ->expects($this->never()) 49 | ->method('isLoggedIn'); 50 | 51 | $this->onlyLoggedInMiddleware->beforeController($this->createMock(Controller::class), 'bar'); 52 | } 53 | 54 | public function testBeforeControllerWithAnnotationAndNotLoggedIn() { 55 | $this->reflector 56 | ->expects($this->once()) 57 | ->method('hasAnnotation') 58 | ->with('OnlyUnauthenticatedUsers') 59 | ->willReturn(true); 60 | $this->userSession 61 | ->expects($this->once()) 62 | ->method('isLoggedIn') 63 | ->willReturn(false); 64 | 65 | $this->onlyLoggedInMiddleware->beforeController($this->createMock(Controller::class), 'bar'); 66 | } 67 | 68 | public function testBeforeControllerWithAnnotationAndLoggedIn() { 69 | $this->reflector 70 | ->expects($this->once()) 71 | ->method('hasAnnotation') 72 | ->with('OnlyUnauthenticatedUsers') 73 | ->willReturn(true); 74 | $this->userSession 75 | ->expects($this->once()) 76 | ->method('isLoggedIn') 77 | ->willReturn(true); 78 | 79 | $this->expectException(Exception::class); 80 | $this->expectExceptionMessage('User is already logged-in'); 81 | 82 | $this->onlyLoggedInMiddleware->beforeController($this->createMock(Controller::class), 'bar'); 83 | } 84 | 85 | public function testAfterExceptionWithNormalException() { 86 | $exceptionMsg = 'My Exception'; 87 | $exception = new Exception($exceptionMsg); 88 | 89 | $this->expectException(Exception::class); 90 | $this->expectExceptionMessage($exceptionMsg); 91 | 92 | $this->onlyLoggedInMiddleware->afterException($this->createMock(Controller::class), 'bar', $exception); 93 | } 94 | 95 | public function testAfterExceptionWithAlreadyLoggedInException() { 96 | $homeUrl = 'https://my.nxt.cld/'; 97 | $this->urlGenerator->expects($this->atLeastOnce()) 98 | ->method('getAbsoluteURL') 99 | ->with('/') 100 | ->willReturn($homeUrl); 101 | 102 | $exception = new Exception('User is already logged-in'); 103 | $expected = new RedirectResponse($homeUrl); 104 | $this->assertEquals($expected, $this->onlyLoggedInMiddleware->afterException($this->createMock(Controller::class), 'bar', $exception)); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/unit/Settings/SectionTest.php: -------------------------------------------------------------------------------- 1 | l10n = $this->createMock(\OCP\IL10N::class); 23 | $this->urlGenerator = $this->createMock(IURLGenerator::class); 24 | $this->section = new \OCA\User_SAML\Settings\Section( 25 | $this->l10n, 26 | $this->urlGenerator 27 | ); 28 | 29 | parent::setUp(); 30 | } 31 | 32 | public function testGetId() { 33 | $this->assertSame('saml', $this->section->getID()); 34 | } 35 | 36 | public function testGetName() { 37 | $this->l10n 38 | ->expects($this->once()) 39 | ->method('t') 40 | ->with('SSO & SAML authentication') 41 | ->willReturn('SAML authentication'); 42 | 43 | $this->assertSame('SAML authentication', $this->section->getName()); 44 | } 45 | 46 | public function testGetPriority() { 47 | $this->assertSame(75, $this->section->getPriority()); 48 | } 49 | 50 | public function testGetIcon() { 51 | $this->urlGenerator 52 | ->expects($this->once()) 53 | ->method('imagePath') 54 | ->with('user_saml', 'app-dark.svg') 55 | ->willReturn('/apps/user_saml/myicon.svg'); 56 | $this->assertSame('/apps/user_saml/myicon.svg', $this->section->getIcon()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/unit/UserDataTest.php: -------------------------------------------------------------------------------- 1 | resolver = $this->createMock(UserResolver::class); 31 | $this->samlSettings = $this->createMock(SAMLSettings::class); 32 | $this->config = $this->createMock(IConfig::class); 33 | 34 | $this->userData = new UserData($this->resolver, $this->samlSettings, $this->config); 35 | } 36 | 37 | public function objectGuidProvider() { 38 | return [ 39 | ['Joey No Conversion', 'Joey No Conversion'], 40 | ['no@convers.ion', 'no@convers.ion'], 41 | ['a0aa9ed8-6b48-1034-8ad7-8fb78330d80a', 'a0aa9ed8-6b48-1034-8ad7-8fb78330d80a'], 42 | ['EDE70D16-B9D5-4E9A-ABD7-614D17246E3F', 'EDE70D16-B9D5-4E9A-ABD7-614D17246E3F'], 43 | ['Tm8gY29udmVyc2lvbgo=', 'Tm8gY29udmVyc2lvbgo='], 44 | ['ASfjU2OYEd69ZgAVF4pePA==', '53E32701-9863-DE11-BD66-0015178A5E3C'], 45 | ['aaabbbcc@aa.bbbccdd.eee.ff', 'aaabbbcc@aa.bbbccdd.eee.ff'], 46 | ['aaabbbcccaa.bbbccdddeee', 'aaabbbcccaa.bbbccdddeee'] 47 | ]; 48 | } 49 | 50 | /** 51 | * @dataProvider objectGuidProvider 52 | */ 53 | public function testTestEncodedObjectGUID(string $input, string $expectation) { 54 | $uid = $this->invokePrivate($this->userData, 'testEncodedObjectGUID', [$input]); 55 | $this->assertSame($expectation, $uid); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/unit/bootstrap.php: -------------------------------------------------------------------------------- 1 | loadApp('user_saml'); 22 | 23 | if (!class_exists(TestCase::class)) { 24 | require_once('PHPUnit/Autoload.php'); 25 | } 26 | -------------------------------------------------------------------------------- /tests/unit/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 13 | 14 | . 15 | 16 | 17 | 18 | 19 | ../../../user_saml/appinfo 20 | ../../../user_saml/lib 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /vendor-bin/cs-fixer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "nextcloud/coding-standard": "^1.3" 4 | }, 5 | "config": { 6 | "platform": { 7 | "php": "8.1.32" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vendor-bin/psalm/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "nextcloud/ocp": "dev-stable28", 4 | "vimeo/psalm": "^5.26", 5 | "sabre/dav": "4.7.0" 6 | }, 7 | "config": { 8 | "platform": { 9 | "php": "8.1.32" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vendor-bin/rector/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require-dev": { 3 | "rector/rector": "^2.0", 4 | "nextcloud/rector": "^0.4.1" 5 | } 6 | } 7 | --------------------------------------------------------------------------------