Compare commits

..

83 commits

Author SHA1 Message Date
tflidd
79ae3e9235
Merge pull request #261 from ervee/patch-1
Make NC30 compatible
2025-03-10 17:43:58 +01:00
dependabot[bot]
6d4405ecff
Merge pull request #262 from nextcloud/dependabot/composer/symfony/process-5.4.46 2024-11-06 20:51:23 +00:00
dependabot[bot]
2884c6e749
Bump symfony/process from 5.4.7 to 5.4.46
Bumps [symfony/process](https://github.com/symfony/process) from 5.4.7 to 5.4.46.
- [Release notes](https://github.com/symfony/process/releases)
- [Changelog](https://github.com/symfony/process/blob/7.1/CHANGELOG.md)
- [Commits](https://github.com/symfony/process/compare/v5.4.7...v5.4.46)

---
updated-dependencies:
- dependency-name: symfony/process
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-06 20:47:58 +00:00
Ralf
47e8099502
Make NC30 compatible
Make the app compatible with Nextcloud 30

Signed-off-by: Ralf <ervee@moskovic.org>
2024-10-28 20:18:45 +01:00
Joas Schilling
412e397069
Merge pull request #258 from nextcloud/ci/noid/update-workflow-109
ci: Update workflows
2024-09-10 11:48:12 +02:00
Joas Schilling
8b18c65014
ci: Update workflows
[skip-ci]

Signed-off-by: Joas Schilling <coding@schilljs.com>
2024-09-10 11:47:58 +02:00
Andy Scherzinger
514a7c5ed3
Merge pull request #257 from nextcloud/feat/workflow-auto-update-dependabot-approve-merge.yml
chore(CI): Updating dependabot-approve-merge.yml workflow from template
2024-09-02 16:15:09 +02:00
Nextcloud bot
6eb024359c chore(CI): Updating dependabot-approve-merge.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-09-02 10:59:35 +00:00
Jonas Sulzer
06bef5554d
Merge pull request #256 from nextcloud/rlz/3.4.0
🚀 RELEASE: v3.4.0
2024-07-28 10:34:04 +02:00
Jonas Sulzer
5b70ef00bb
Merge pull request #249 from nextcloud/fix/user-count
🐛 FIX: wrong user count
2024-07-28 10:33:01 +02:00
Jonas Sulzer
955c884a6b
🚀 RELEASE: v3.4.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2024-07-25 14:03:30 +02:00
Jonas Sulzer
a3da95fdaf
Merge pull request #255 from nextcloud/automated/update-workflows/default
chore: update workflows from templates
2024-07-21 17:06:48 +02:00
skjnldsv
7b92009000 chore: update workflows from templates
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
2024-07-13 12:17:28 +02:00
Jonas Sulzer
3d850aa615
Merge pull request #251 from nextcloud/feat/workflow-auto-update-dependabot-approve-merge.yml
Updating dependabot-approve-merge.yml workflow from template
2024-04-27 08:16:07 +02:00
Nextcloud bot
3777fe3331 Updating dependabot-approve-merge.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2024-04-26 18:17:26 +00:00
Jonas Sulzer
b27d85a783
Merge pull request #228 from BjoKaSH/imap_log_failure_reason
Distinguish wrong credentials from other problems (IMAP)
2024-04-02 11:35:38 +02:00
Jonas Sulzer
e45b03e5b8
Merge pull request #221 from jensb/patch-1
Update README.md, add warning about fail2ban-like tools
2024-04-02 11:31:01 +02:00
Jonas Sulzer
f1430569ce
Merge pull request #229 from BjoKaSH/fix_imap_out_of_bound
Fix out-of-bound array access (IMAP)
2024-04-02 11:29:44 +02:00
Jonas Sulzer
6186795698
Merge pull request #242 from nextcloud/automated/update-workflows/default
chore: update workflows from templates
2024-04-02 11:09:40 +02:00
Jonas Sulzer
af6bf33e57
Merge pull request #248 from nextcloud/rlz/3.3.0
🚀 RELEASE: v3.3.0
2024-04-02 10:29:03 +02:00
Jonas Sulzer
0ea46a1730
🐛 FIX: wrong user count
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2024-03-30 01:25:04 +01:00
Jonas Sulzer
285a810b88
👌 IMPROVE: rephrase recommendation about bruteforce protection
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2024-03-30 00:13:15 +01:00
Jonas Sulzer
ada0fbcf52
🚀 RELEASE: v3.3.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2024-03-30 00:02:27 +01:00
skjnldsv
09dba5689e chore: update workflows from templates
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
2024-03-08 22:02:25 +01:00
Côme Chilliet
d0e609438e
Merge pull request #238 from pierrecorsini/patch-1
Wrong class name corrected with : `\OCA\UserExternal\WebDavAuth' inst…
2024-02-29 10:07:03 +01:00
John Molakvoæ
320c90ce89
Merge pull request #241 from Glandos/patch-1 2024-02-28 11:18:07 +01:00
Glandos
430a0e6384
Add support for NC 28
Signed-off-by: Glandos <bugs-github@antipoul.fr>
2023-12-22 12:52:40 +01:00
Bjoern Kahl
69483900d1 Distinguish wrong credentials from other problems (IMAP)
Verifying login data can fail for a number of reasons like temporary
connection failure to the IMAP server, Internal problems of the IMAP
server, or actually wrong username / password combination.

This change logs the reason for login failures, helping server admins to
diagnose login problems and better support their users.

Ideally, we would have an option to pass the reason upwards, so the
NextCloud login system can show appropriate errors to users attempting
to login.

Signed-off-by: Bjoern Kahl <mls@bjoern-kahl.de>
2023-11-25 21:49:19 +01:00
Bjoern Kahl
8fd2a5d06a Fix out-of-bound array access (IMAP)
The IMAP method allows user names with or without a domain part.  For
user names without a domain part, it still tries to access the (then
non-existing) domain, resulting in "Error: Undefined array key 1 at
.../nextcloud/apps/user_external/lib/IMAP.php#85" log messages.

Signed-off-by: Bjoern Kahl <mls@bjoern-kahl.de>
2023-11-25 21:46:26 +01:00
Pierre CORSINI
1aa72d73bc
Wrong class name corrected with : \OCA\UserExternal\WebDavAuth' instead of WebDAVAuth`
Signed-off-by: Pierre CORSINI <50719398+pierrecorsini@users.noreply.github.com>
2023-10-01 22:59:27 +01:00
John Molakvoæ
455726df6a
Merge pull request #234 from nextcloud/feat/27 2023-06-13 16:09:15 +02:00
John Molakvoæ
3ae18e6199
chore: min is 25, max is 27
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
2023-06-13 16:04:08 +02:00
violoncello.ch
14abc962d7
Merge pull request #232 from nextcloud/automated/update-workflows
chore: update workflows from templates
2023-06-03 12:03:28 +02:00
John Molakvoæ
9957e7f38b
chore: update workflows from templates
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
2023-06-01 18:33:02 +02:00
violoncello.ch
216a5e8441
Merge pull request #230 from nextcloud/automated/update-workflows
chore: update workflows from templates
2023-05-28 14:49:39 +02:00
John Molakvoæ
23129291f4
chore: update workflows from templates
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
2023-05-28 14:04:07 +02:00
jensb
f30f950b57
Update README.md, add warning about fail2ban-like tools
Signed-off-by: jensb <jens-github@spamfreemail.de>
2023-03-14 18:59:52 +01:00
Côme Chilliet
9090251e8e
Merge pull request #217 from Glandos/patch-1
Trim doesn't accept null anymore
2023-01-24 10:26:02 +01:00
Glandos
5e5c330a7c
Trim doesn't accept null anymore
Fix #203 

Signed-off-by: Glandos <bugs-github@antipoul.fr>
2023-01-19 00:02:03 +01:00
violoncello.ch
ff044910e1
Merge pull request #214 from nextcloud/changelog
update changelog
2023-01-17 15:31:57 +01:00
violoncello.ch
e5b2b2e988
Merge pull request #164 from tem-hth/master
Examine error code returned by curl handle instead of return value from curl_exec. Using the return value from curl_exec resulted in failure on new mailboxes that did not contain any mail.
2022-12-27 21:40:28 +01:00
Jonas Sulzer
73a7e4794b
👌 IMPROVE: update changelog
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-12-27 21:37:02 +01:00
Tem Ogunfiditimi
1fbc471efe
Examine error code returned by curl handle instead of return value from curl_exec. Using the return value from curl_exec resulted in failure on new mailboxes that did not contain any mail.
Signed-off-by: Tem Ogunfiditimi <tem@episof.com>

Changed comparison to identical check

Signed-off-by: Tem Ogunfiditmi <tem@episof.com>
Signed-off-by: Tem Ogunfiditimi <tem@episof.com>
2022-12-27 21:36:59 +01:00
Jonas Sulzer
2a9c7ce4b7
👌 IMPROVE: update changelog
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-12-27 20:46:23 +01:00
violoncello.ch
850de08ac9
Merge pull request #212 from michael-dev/feature/compat-nc-25
Update info.xml
2022-12-27 20:39:31 +01:00
Jonas Sulzer
3f9eccef76
🚀 RELEASE: 3.1.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-12-27 20:38:21 +01:00
violoncello.ch
8fd1667168
Merge pull request #208 from nextcloud/feat/workflow-auto-update-lint-php-cs.yml
Updating lint-php-cs.yml workflow from template
2022-12-27 16:21:06 +01:00
violoncello.ch
1a382deac2
Merge pull request #207 from nextcloud/feat/workflow-auto-update-lint-php.yml
Updating lint-php.yml workflow from template
2022-12-27 16:20:26 +01:00
michael-dev
5fd908f728 Update info.xml
Works with NC 25 for me

Signed-off-by: M. Braun <michael-dev@fami-braun.de>
2022-12-15 10:42:00 +01:00
Nextcloud bot
ed6aa90148 Updating lint-php-cs.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-15 12:16:12 +00:00
Nextcloud bot
d3568494a5 Updating lint-php.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-10-15 11:08:10 +00:00
violoncello.ch
4be24bc554
Merge pull request #206 from nextcloud/feat/workflow-auto-update-dependabot-approve-merge.yml
Updating dependabot-approve-merge.yml workflow from template
2022-08-08 21:09:46 +02:00
Nextcloud bot
1d4f70f46b Updating dependabot-approve-merge.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-08-05 12:48:46 +00:00
violoncello.ch
9708e02c65
Merge pull request #202 from nextcloud/feat/workflow-auto-update-command-rebase.yml
Updating command-rebase.yml workflow from template
2022-06-12 14:33:41 +02:00
Nextcloud bot
4fe19c482f Updating command-rebase.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-06-11 15:50:45 +00:00
violoncello.ch
b4a243eda2
Merge pull request #200 from nextcloud/feat/workflow-auto-update-command-rebase.yml
Updating command-rebase.yml workflow from template
2022-05-15 00:50:01 +02:00
Nextcloud bot
1812468002 Updating command-rebase.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-05-13 18:53:05 +00:00
violoncello.ch
4c07e72cfc
Merge pull request #198 from nextcloud/feat/workflow-auto-update-command-rebase.yml
Updating command-rebase.yml workflow from template
2022-04-27 23:47:16 +02:00
Nextcloud bot
3c40d2268c Updating command-rebase.yml workflow from template
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
2022-04-26 16:14:41 +00:00
John Molakvoæ
130cde6a53
Merge pull request #197 from nextcloud/release/3.0.0 2022-04-26 10:15:16 +02:00
Jonas Sulzer
855a3e464c
🚀 RELEASE: v3.0.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-04-23 13:17:06 +02:00
violoncello.ch
8963553de9
Merge pull request #195 from nextcloud/fix-archive-creation
🐛 FIX: create correctly named archive file for workflow release
2022-04-18 09:18:37 +02:00
Jonas Sulzer
cc2bcbc02a
🐛 FIX: create correctly named archive file for workflow release
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-04-16 17:46:18 +02:00
violoncello.ch
2c4e8c0381
Merge pull request #194 from nextcloud/release/3.0.0beta1
🚀 RELEASE: v3.0.0beta1
2022-04-16 16:23:05 +02:00
violoncello.ch
4d37e02ef8
Merge pull request #193 from nextcloud/changelog
📦 NEW: add a changelog to document changes starting from v3.0.0
2022-04-15 23:24:27 +02:00
Jonas Sulzer
82f4ce0c2e
🚀 RELEASE: v3.0.0beta1
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-04-15 18:53:28 +02:00
Jonas Sulzer
a466e4d9b6
📦 NEW: add a changelog to document changes starting from v3.0.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-04-15 17:46:13 +02:00
John Molakvoæ
0c63939f44
Merge pull request #192 from nextcloud/feat/configs-workflows 2022-04-15 17:05:13 +02:00
John Molakvoæ
751dc7ea2a
Cs fix
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
2022-04-15 08:18:32 +02:00
John Molakvoæ
98768cfb57
Add workflows
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
2022-04-15 08:18:31 +02:00
John Molakvoæ
3acf2e92cf
Merge pull request #191 from MarBie77/master 2022-04-15 08:12:02 +02:00
Jonas Sulzer
d300566c4d
🚀 RELEASE: v3.0.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-04-15 00:05:30 +02:00
Jonas Sulzer
084bdc71bc
🐛 FIX: correct namespace
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2022-04-15 00:02:50 +02:00
Biermair Martin
2c86494ea6 increasing version range nextcloud 22 (EOL) to 24
Signed-Off-By: Biermair Martin <martin.biermair@wimbergerhaus.at>
2022-04-13 21:20:43 +02:00
Biermair Martin
928a2696f2 removed typos from README.md
Signed-Off-By: Biermair Martin <martin.biermair@wimbergerhaus.at>
2022-04-13 21:16:35 +02:00
Biermair Martin
990b6d73d3 migration to nextcloud app v3.0.0
Signed-off-by: Biermair Martin <martin.biermair@wimbergerhaus.at>
2022-04-10 10:47:18 +02:00
Christoph Wurst
8ec7a0b597
Merge pull request #184 from nextcloud/release/2.1.0
🚀 RELEASE: v2.1.0 and make compatible to Nextcloud Hub 22
2021-09-07 13:42:52 +02:00
Jonas Sulzer
522eab25a8
🚀 RELEASE: v2.1.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2021-09-05 14:43:46 +02:00
Christoph Wurst
b18ddbb091
Merge pull request #159 from nextcloud/update-ci
🐛 FIX: update ci (versions of php and nextcloud used)
2021-04-12 09:24:06 +02:00
Jonas Sulzer
c253ba3f7d
🐛 FIX: update ci (versions of php and nextcloud used)
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2021-04-10 17:08:12 +02:00
violoncello.ch
fa1e7141fe
Merge pull request #173 from hlnd/fix-compatibility-with-21
Use new types introduced in Nextcloud 21 and bump compatibility
2021-04-10 16:35:25 +02:00
Jonas Sulzer
1ef871d2f8
🚀 RELEASE: v2.0.0
Signed-off-by: Jonas Sulzer <jonas@violoncello.ch>
2021-04-10 16:34:43 +02:00
Ole Morten
bd610e28b5 Use new types introduced in Nextcloud 21 and bump compatibility
Signed-off-by: Ole Morten <om@haaland.biz>
2021-03-09 20:28:00 +01:00
35 changed files with 5137 additions and 379 deletions

View file

@ -1,29 +0,0 @@
kind: pipeline
name: check-app-compatbility
steps:
- name: check-app-compatbility
image: nextcloudci/php7.2:php7.2-9
environment:
APP_NAME: user_external
CORE_BRANCH: master
DB: sqlite
commands:
# Pre-setup steps
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
- cd ../server
# Code checker
- ./occ app:check-code $APP_NAME -c strong-comparison
- ./occ app:check-code $APP_NAME -c deprecation
matrix:
trigger:
branch:
- master
- stable*
event:
- pull_request
- push

View file

@ -0,0 +1,175 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Build and publish app release
on:
release:
types: [published]
jobs:
build_and_publish:
runs-on: ubuntu-latest
# Only allowed to be run on nextcloud-releases repositories
if: ${{ github.repository_owner == 'nextcloud-releases' }}
steps:
- name: Check actor permission
uses: skjnldsv/check-actor-permission@69e92a3c4711150929bca9fcf34448c5bf5526e7 # v3.0
with:
require: write
- name: Set app env
run: |
# Split and keep last
echo "APP_NAME=${GITHUB_REPOSITORY##*/}" >> $GITHUB_ENV
echo "APP_VERSION=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
path: ${{ env.APP_NAME }}
- name: Get appinfo data
id: appinfo
uses: skjnldsv/xpath-action@7e6a7c379d0e9abc8acaef43df403ab4fc4f770c # master
with:
filename: ${{ env.APP_NAME }}/appinfo/info.xml
expression: "//info//dependencies//nextcloud/@min-version"
- name: Read package.json node and npm engines version
uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3
id: versions
# Continue if no package.json
continue-on-error: true
with:
path: ${{ env.APP_NAME }}
fallbackNode: '^20'
fallbackNpm: '^10'
- name: Set up node ${{ steps.versions.outputs.nodeVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v3
with:
node-version: ${{ steps.versions.outputs.nodeVersion }}
- name: Set up npm ${{ steps.versions.outputs.npmVersion }}
# Skip if no package.json
if: ${{ steps.versions.outputs.npmVersion }}
run: npm i -g 'npm@${{ steps.versions.outputs.npmVersion }}'
- name: Get php version
id: php-versions
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
with:
filename: ${{ env.APP_NAME }}/appinfo/info.xml
- name: Set up php ${{ steps.php-versions.outputs.php-min }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2.31.0
with:
php-version: ${{ steps.php-versions.outputs.php-min }}
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check composer.json
id: check_composer
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
with:
files: "${{ env.APP_NAME }}/composer.json"
- name: Install composer dependencies
if: steps.check_composer.outputs.files_exists == 'true'
run: |
cd ${{ env.APP_NAME }}
composer install --no-dev
- name: Build ${{ env.APP_NAME }}
# Skip if no package.json
if: ${{ steps.versions.outputs.nodeVersion }}
env:
NODE_ENV: production
run: |
cd ${{ env.APP_NAME }}
npm ci
npm run build --if-present
- name: Check Krankerl config
id: krankerl
uses: andstor/file-existence-action@076e0072799f4942c8bc574a82233e1e4d13e9d6 # v3.0.0
with:
files: ${{ env.APP_NAME }}/krankerl.toml
- name: Install Krankerl
if: steps.krankerl.outputs.files_exists == 'true'
run: |
wget https://github.com/ChristophWurst/krankerl/releases/download/v0.14.0/krankerl_0.14.0_amd64.deb
sudo dpkg -i krankerl_0.14.0_amd64.deb
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with krankerl
if: steps.krankerl.outputs.files_exists == 'true'
run: |
cd ${{ env.APP_NAME }}
krankerl package
- name: Package ${{ env.APP_NAME }} ${{ env.APP_VERSION }} with makefile
if: steps.krankerl.outputs.files_exists != 'true'
run: |
cd ${{ env.APP_NAME }}
make appstore
- name: Checkout server ${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}
continue-on-error: true
id: server-checkout
run: |
NCVERSION='${{ fromJSON(steps.appinfo.outputs.result).nextcloud.min-version }}'
wget --quiet https://download.nextcloud.com/server/releases/latest-$NCVERSION.zip
unzip latest-$NCVERSION.zip
- name: Checkout server master fallback
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
if: ${{ steps.server-checkout.outcome != 'success' }}
with:
submodules: true
repository: nextcloud/server
path: nextcloud
- name: Sign app
run: |
# Extracting release
cd ${{ env.APP_NAME }}/build/artifacts
tar -xvf ${{ env.APP_NAME }}.tar.gz
cd ../../../
# Setting up keys
echo '${{ secrets.APP_PRIVATE_KEY }}' > ${{ env.APP_NAME }}.key
wget --quiet "https://github.com/nextcloud/app-certificate-requests/raw/master/${{ env.APP_NAME }}/${{ env.APP_NAME }}.crt"
# Signing
php nextcloud/occ integrity:sign-app --privateKey=../${{ env.APP_NAME }}.key --certificate=../${{ env.APP_NAME }}.crt --path=../${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}
# Rebuilding archive
cd ${{ env.APP_NAME }}/build/artifacts
tar -zcvf ${{ env.APP_NAME }}.tar.gz ${{ env.APP_NAME }}
- name: Attach tarball to github release
uses: svenstaro/upload-release-action@04733e069f2d7f7f0b4aebc4fbdbce8613b03ccd # v2
id: attach_to_release
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ env.APP_NAME }}/build/artifacts/${{ env.APP_NAME }}.tar.gz
asset_name: ${{ env.APP_NAME }}-${{ env.APP_VERSION }}.tar.gz
tag: ${{ github.ref }}
overwrite: true
- name: Upload app to Nextcloud appstore
uses: nextcloud-releases/nextcloud-appstore-push-action@a011fe619bcf6e77ddebc96f9908e1af4071b9c1 # v1
with:
app_name: ${{ env.APP_NAME }}
appstore_token: ${{ secrets.APPSTORE_TOKEN }}
download_url: ${{ steps.attach_to_release.outputs.browser_download_url }}
app_private_key: ${{ secrets.APP_PRIVATE_KEY }}

View file

@ -0,0 +1,49 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Dependabot
on:
pull_request_target:
branches:
- main
- master
- stable*
permissions:
contents: read
concurrency:
group: dependabot-approve-merge-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
auto-approve-merge:
if: github.actor == 'dependabot[bot]' || github.actor == 'renovate[bot]'
runs-on: ubuntu-latest-low
permissions:
# for hmarr/auto-approve-action to approve PRs
pull-requests: write
steps:
- name: Disabled on forks
if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
run: |
echo 'Can not approve PRs from forks'
exit 1
# GitHub actions bot approve
- uses: hmarr/auto-approve-action@b40d6c9ed2fa10c9a2749eca7eb004418a705501 # v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# Nextcloud bot approve and merge request
- uses: ahmadnassri/action-dependabot-auto-merge@45fc124d949b19b6b8bf6645b6c9d55f4f9ac61a # v2
with:
target: minor
github-token: ${{ secrets.DEPENDABOT_AUTOMERGE_TOKEN }}

36
.github/workflows/fixup.yml vendored Normal file
View file

@ -0,0 +1,36 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Block fixup and squash commits
on:
pull_request:
types: [opened, ready_for_review, reopened, synchronize]
permissions:
contents: read
concurrency:
group: fixup-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
commit-message-check:
if: github.event.pull_request.draft == false
permissions:
pull-requests: write
name: Block fixup and squash commits
runs-on: ubuntu-latest-low
steps:
- name: Run check
uses: skjnldsv/block-fixup-merge-action@c138ea99e45e186567b64cf065ce90f7158c236a # v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

36
.github/workflows/lint-info-xml.yml vendored Normal file
View file

@ -0,0 +1,36 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint info.xml
on: pull_request
permissions:
contents: read
concurrency:
group: lint-info-xml-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
xml-linters:
runs-on: ubuntu-latest-low
name: info.xml lint
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Download schema
run: wget https://raw.githubusercontent.com/nextcloud/appstore/master/nextcloudappstore/api/v1/release/info.xsd
- name: Lint info.xml
uses: ChristophWurst/xmllint-action@36f2a302f84f8c83fceea0b9c59e1eb4a616d3c1 # v1.2
with:
xml-file: ./appinfo/info.xml
xml-schema-file: ./info.xsd

48
.github/workflows/lint-php-cs.yml vendored Normal file
View file

@ -0,0 +1,48 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint php-cs
on: pull_request
permissions:
contents: read
concurrency:
group: lint-php-cs-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
name: php-cs
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Get php version
id: versions
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.3.1
- name: Set up php${{ steps.versions.outputs.php-available }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2.31.0
with:
php-version: ${{ steps.versions.outputs.php-available }}
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Install dependencies
run: composer i
- name: Lint
run: composer run cs:check || ( echo 'Please run `composer run cs:fix` to format your code' && exit 1 )

70
.github/workflows/lint-php.yml vendored Normal file
View file

@ -0,0 +1,70 @@
# This workflow is provided via the organization template repository
#
# https://github.com/nextcloud/.github
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
#
# SPDX-FileCopyrightText: 2021-2024 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: MIT
name: Lint php
on: pull_request
permissions:
contents: read
concurrency:
group: lint-php-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
matrix:
runs-on: ubuntu-latest-low
outputs:
php-versions: ${{ steps.versions.outputs.php-versions }}
steps:
- name: Checkout app
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Get version matrix
id: versions
uses: icewind1991/nextcloud-version-matrix@58becf3b4bb6dc6cef677b15e2fd8e7d48c0908f # v1.0.0
php-lint:
runs-on: ubuntu-latest
needs: matrix
strategy:
matrix:
php-versions: ${{fromJson(needs.matrix.outputs.php-versions)}}
name: php-lint
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Set up php ${{ matrix.php-versions }}
uses: shivammathur/setup-php@2e947f1f6932d141d076ca441d0e1e881775e95b # v2.31.0
with:
php-version: ${{ matrix.php-versions }}
extensions: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite
coverage: none
ini-file: development
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Lint
run: composer run lint
summary:
permissions:
contents: none
runs-on: ubuntu-latest-low
needs: php-lint
if: always()
name: php-lint-summary
steps:
- name: Summary status
run: if ${{ needs.php-lint.result != 'success' && needs.php-lint.result != 'skipped' }}; then exit 1; fi

2
.gitignore vendored
View file

@ -6,3 +6,5 @@ tests/clover.xml
# packaged app
build/artifacts
vendor
.php-cs-fixer.cache

18
.php-cs-fixer.dist.php Normal file
View file

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
require_once './vendor/autoload.php';
use Nextcloud\CodingStandard\Config;
$config = new Config();
$config
->getFinder()
->notPath('build')
->notPath('l10n')
->notPath('node_modules')
->notPath('src')
->notPath('vendor')
->in(__DIR__);
return $config;

View file

@ -1,56 +0,0 @@
language: php
php:
- 7.1
- 7.2
- 7.3
services:
- mysql
- postgresql
env:
global:
- APP_NAME=user_external
- PHP_COVERAGE=FALSE
matrix:
# - DB=sqlite SERVER=nextcloud/travis_ci/master SERVER_BRANCH=master
- DB=sqlite SERVER=nextcloud/travis_ci/master SERVER_BRANCH=stable15
# - DB=mysql SERVER=nextcloud/travis_ci/master SERVER_BRANCH=master PHP_COVERAGE=TRUE
- DB=mysql SERVER=nextcloud/travis_ci/master SERVER_BRANCH=stable15 PHP_COVERAGE=TRUE
# - DB=pgsql SERVER=nextcloud/travis_ci/master SERVER_BRANCH=master
- DB=pgsql SERVER=nextcloud/travis_ci/master SERVER_BRANCH=stable15
matrix:
fast_finish: true
branches:
only:
- master
- /^stable\d+(\.\d+)?$/
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y libxml2-utils
- wget https://raw.githubusercontent.com/$SERVER/before_install.sh
- . ./before_install.sh "$APP_NAME" "$SERVER_BRANCH" "$DB"
- cd ../core || cd ../server
- php occ app:enable $APP_NAME
before_script:
# Test lint
- cd apps/$APP_NAME
- find . -name \*.php -exec php -l "{}" \;
script:
# Check info.xml schema validity
- wget https://apps.nextcloud.com/schema/apps/info.xsd
- xmllint appinfo/info.xml --schema info.xsd --noout
- rm info.xsd
# Run phpunit tests
# - cd tests
# - phpunit --configuration configuration.xml
# Create coverage report
# - sh -c "if [ '$PHP_COVERAGE' != 'FALSE' ]; then wget https://scrutinizer-ci.com/ocular.phar; fi"
# - sh -c "if [ '$PHP_COVERAGE' != 'FALSE' ]; then php ocular.phar code-coverage:upload --format=php-clover clover.xml; fi"

45
CHANGELOG.md Normal file
View file

@ -0,0 +1,45 @@
# Changelog
Starting from v3.0.0, all notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.4.0] -
- Fix out-of-bound array access in IMAP backend
[#229](https://github.com/nextcloud/user_external/pull/229) @BjoKaSH
- Distinguish wrong credentials from other problems in logging output for IMAP backend
[#228](https://github.com/nextcloud/user_external/pull/228) @BjoKaSH
- 🐛 FIX: wrong user count
[#249](https://github.com/nextcloud/user_external/pull/249)
- Make compatible with Nextcloud 29
[#256](https://github.com/nextcloud/user_external/pull/256)
## [3.3.0] - 2024-03-30
- Fix wrong capitalisation of `WebDavAuth` class name in readme
[#238](https://github.com/nextcloud/user_external/pull/238) @pierrecorsini
- Mark compatible with Nextcloud 28
[#241](https://github.com/nextcloud/user_external/pull/241) @Glandos
## [3.2.0] - 2023-06-13
- Fix IMAP authentication on empty mailboxes
[#164](https://github.com/nextcloud/user_external/pull/164) @tem-hth
- Trim doesn't accept null anymore
[#217](https://github.com/nextcloud/user_external/pull/217) @Glandos
## [3.1.0] - 2022-12-27
- Support for Nextcloud 25
[#212](https://github.com/nextcloud/user_external/pull/212) @michael-dev
## [3.0.0] - 2022-04-26
### Breaking Changes
- Namespace change: ⚠This requires configuration changes to be applied to your config.php.⚠\
Specifically the `class` attribute needs to be changed to the full class path starting with `\OCA\UserExternal\` and ending with the name of the specific authentication backend you use (e.g. IMAP or FTP). Check the [README.md](https://github.com/nextcloud/user_external#readme) for the concrete value you have to set.
### Added
- Support for Nextcloud 23 and 24
[#191](https://github.com/nextcloud/user_external/pull/191) @MarBie77
- New CI config (migrate to Github Workflows)
[#192](https://github.com/nextcloud/user_external/pull/192) @skjnldsv
## Older releases
For versions before 3.0.0 please check the [github releases](https://github.com/nextcloud/user_external/releases) for release notes.

View file

@ -60,9 +60,9 @@ appstore:
--certificate=$(cert_dir)/$(app_name).crt\
--path=$(sign_dir)/$(app_name); \
fi
tar -czf $(build_dir)/$(app_name)-$(version).tar.gz \
tar -czf $(build_dir)/$(app_name).tar.gz \
-C $(sign_dir) $(app_name)
@if [ -f $(cert_dir)/$(app_name).key ]; then \
echo "Signing package…"; \
openssl dgst -sha512 -sign $(cert_dir)/$(app_name).key $(build_dir)/$(app_name)-$(version).tar.gz | openssl base64; \
openssl dgst -sha512 -sign $(cert_dir)/$(app_name).key $(build_dir)/$(app_name).tar.gz | openssl base64; \
fi

View file

@ -1,5 +1,8 @@
External user authentication
============================
**⚠⚠ Warning:** As of Version 3.0 this app uses namespace \OCA\UserExternal now. You MUST change your config to adopt to this change. See examples below. ⚠⚠
**Authenticate user login against IMAP, SMB, FTP, WebDAV, HTTP BasicAuth, SSH and XMPP**
Passwords are not stored locally; authentication always happens against
@ -15,6 +18,8 @@ If something does not work, check the log file at `nextcloud/data/nextcloud.log`
**⚠⚠ Warning:** If you are using more than one backend or especially one backend more often than once, make sure that you still have resp. get unique `uid`s in the database. ⚠⚠
**⚠⚠ Warning:** If you are using tools like fail2ban (https://www.fail2ban.org) to protect your authentication source (e.g. IMAP server), be sure to disable it for the host that runs `user_external`. Otherwise a single user failing to login too many times can practically DoS your whole Nextcloud installation because `fail2ban` will then block the Nextcloud IP address. ⚠⚠
Instead, make sure the bruteforce protection app for Nextcloud is installed and configured correctly.
FTP
---
@ -30,7 +35,7 @@ Add the following to `config.php`:
'user_backends' => array(
array(
'class' => 'OC_User_FTP',
'class' => '\OCA\UserExternal\FTP',
'arguments' => array('127.0.0.1'),
),
),
@ -39,7 +44,7 @@ To enable SSL connections via `ftps`, append a second parameter `true`:
'user_backends' => array(
array(
'class' => 'OC_User_FTP',
'class' => '\OCA\UserExternal\FTP',
'arguments' => array('127.0.0.1', true),
),
),
@ -68,7 +73,7 @@ Add the following to your `config.php`:
'user_backends' => array(
array(
'class' => 'OC_User_IMAP',
'class' => '\OCA\UserExternal\IMAP',
'arguments' => array(
'127.0.0.1', 993, 'ssl', 'example.com', true, false
),
@ -104,7 +109,7 @@ Add the following to your `config.php`:
'user_backends' => array(
array(
'class' => 'OC_User_SMB',
'class' => '\OCA\UserExternal\SMB',
'arguments' => array('127.0.0.1'),
),
),
@ -128,7 +133,7 @@ Add the following to your `config.php`:
'user_backends' => array(
array(
'class' => '\OCA\User_External\WebDAVAuth',
'class' => '\OCA\UserExternal\WebDavAuth',
'arguments' => array('https://example.com/webdav'),
),
),
@ -151,7 +156,7 @@ Add the following to your `config.php`:
'user_backends' => array(
array(
'class' => 'OC_User_BasicAuth',
'class' => '\OCA\UserExternal\BasicAuth',
'arguments' => array('https://example.com/basic_auth'),
),
),
@ -172,7 +177,7 @@ Add the following to your `config.php`:
'user_backends' => array(
array(
'class' => 'OC_User_SSH',
'class' => '\OCA\UserExternal\SSH',
'arguments' => array('127.0.0.1', '22'),
),
),
@ -193,7 +198,7 @@ Add the following to your `config.php`:
'user_backends' => array (
0 => array (
'class' => 'OC_User_XMPP',
'class' => '\OCA\UserExternal\XMPP',
'arguments' => array (
0 => 'dbhost',
1 => 'prosodydb',

View file

@ -1,7 +0,0 @@
<?php
OC::$CLASSPATH['OC_User_IMAP']='user_external/lib/imap.php';
OC::$CLASSPATH['OC_User_SMB']='user_external/lib/smb.php';
OC::$CLASSPATH['OC_User_FTP']='user_external/lib/ftp.php';
OC::$CLASSPATH['OC_User_BasicAuth']='user_external/lib/basicauth.php';
OC::$CLASSPATH['OC_User_SSH']='user_external/lib/ssh.php';
OC::$CLASSPATH['OC_User_XMPP']='user_external/lib/xmpp.php';

View file

@ -16,9 +16,10 @@
Read the [documentation](https://github.com/nextcloud/user_external#readme) to learn how to configure it!
]]></description>
<version>1.0.0</version>
<version>3.5.0</version>
<licence>agpl</licence>
<author>Robin Appelman</author>
<namespace>UserExternal</namespace>
<types>
<prelogin/>
<authentication/>
@ -32,6 +33,6 @@ Read the [documentation](https://github.com/nextcloud/user_external#readme) to l
<bugs>https://github.com/nextcloud/user_external/issues</bugs>
<repository type="git">https://github.com/nextcloud/user_external.git</repository>
<dependencies>
<nextcloud min-version="17" max-version="20" />
<nextcloud min-version="25" max-version="30" />
</dependencies>
</info>

20
composer.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "nextcloud/user_external",
"config": {
"optimize-autoloader": true,
"classmap-authoritative": true,
"platform": {
"php": "7.3"
}
},
"scripts": {
"cs:fix": "php-cs-fixer fix",
"cs:check": "php-cs-fixer fix --dry-run --diff",
"lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l"
},
"require-dev": {
"nextcloud/coding-standard": "^1.0.0",
"phpunit/phpunit": "^9.5",
"christophwurst/nextcloud_testing": "^0.12.4"
}
}

4280
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace OCA\UserExternal\AppInfo;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
class Application extends App implements IBootstrap {
public function __construct() {
parent::__construct('user_external');
}
public function register(IRegistrationContext $context): void {
}
public function boot(IBootContext $context): void {
}
}

View file

@ -7,7 +7,7 @@
* later.
* See the COPYING-README file.
*/
namespace OCA\user_external;
namespace OCA\UserExternal;
/**
* Base class for external auth implementations that stores users
@ -21,7 +21,7 @@ namespace OCA\user_external;
* @license http://www.gnu.org/licenses/agpl AGPL
* @link http://github.com/owncloud/apps
*/
abstract class Base extends \OC\User\Backend{
abstract class Base extends \OC\User\Backend {
protected $backend = '';
/**
@ -66,7 +66,7 @@ abstract class Base extends \OC\User\Backend{
$user = $result->fetch();
$result->closeCursor();
$displayName = trim($user['displayname'], ' ');
$displayName = trim($user['displayname'] ?? '', ' ');
if (!empty($displayName)) {
return $displayName;
} else {
@ -80,7 +80,6 @@ abstract class Base extends \OC\User\Backend{
* @return array with all displayNames (value) and the corresponding uids (key)
*/
public function getDisplayNames($search = '', $limit = null, $offset = null) {
$connection = \OC::$server->getDatabaseConnection();
$query = $connection->getQueryBuilder();
$query->select('uid', 'displayname')
@ -106,10 +105,10 @@ abstract class Base extends \OC\User\Backend{
}
/**
* Get a list of all users
*
* @return array with all uids
*/
* Get a list of all users
*
* @return array with all uids
*/
public function getUsers($search = '', $limit = null, $offset = null) {
$connection = \OC::$server->getDatabaseConnection();
$query = $connection->getQueryBuilder();
@ -217,7 +216,7 @@ abstract class Base extends \OC\User\Backend{
/**
* Count the number of users.
*
* @return int|bool The number of users on success false on failure
* @return int the number of users
*/
public function countUsers() {
$connection = \OC::$server->getDatabaseConnection();
@ -229,7 +228,6 @@ abstract class Base extends \OC\User\Backend{
$users = $result->fetchColumn();
$result->closeCursor();
return $users > 0;
return $users;
}
}

View file

@ -6,13 +6,14 @@
* See the COPYING-README file.
*/
class OC_User_BasicAuth extends \OCA\user_external\Base {
namespace OCA\UserExternal;
class BasicAuth extends Base {
private $authUrl;
public function __construct($authUrl) {
parent::__construct($authUrl);
$this->authUrl =$authUrl;
$this->authUrl = $authUrl;
}
/**
@ -29,21 +30,21 @@ class OC_User_BasicAuth extends \OCA\user_external\Base {
* URL is indeed authenticating or not...
*/
$context = stream_context_create(array(
'http' => array(
'method' => "GET",
'follow_location' => 0
))
'http' => array(
'method' => "GET",
'follow_location' => 0
))
);
$canary = get_headers($this->authUrl, 1, $context);
if(!$canary) {
OC::$server->getLogger()->error(
if (!$canary) {
\OC::$server->getLogger()->error(
'ERROR: Not possible to connect to BasicAuth Url: '.$this->authUrl,
['app' => 'user_external']
);
return false;
}
if (!isset(array_change_key_case($canary, CASE_LOWER)['www-authenticate'])) {
OC::$server->getLogger()->error(
\OC::$server->getLogger()->error(
'ERROR: Mis-configured BasicAuth Url: '.$this->authUrl.', provided URL does not do authentication!',
['app' => 'user_external']
);
@ -51,17 +52,17 @@ class OC_User_BasicAuth extends \OCA\user_external\Base {
}
$context = stream_context_create(array(
'http' => array(
'method' => "GET",
'header' => "authorization: Basic " . base64_encode("$uid:$password"),
'follow_location' => 0
))
'http' => array(
'method' => "GET",
'header' => "authorization: Basic " . base64_encode("$uid:$password"),
'follow_location' => 0
))
);
$headers = get_headers($this->authUrl, 1, $context);
if(!$headers) {
OC::$server->getLogger()->error(
'ERROR: Not possible to connect to BasicAuth Url: '.$this->authUrl,
if (!$headers) {
\OC::$server->getLogger()->error(
'ERROR: Not possible to connect to BasicAuth Url: '.$this->authUrl,
['app' => 'user_external']
);
return false;
@ -81,8 +82,8 @@ class OC_User_BasicAuth extends \OCA\user_external\Base {
$this->storeUser($uid);
return $uid;
case "3":
OC::$server->getLogger()->error(
'ERROR: Too many redirects from BasicAuth Url: '.$this->authUrl,
\OC::$server->getLogger()->error(
'ERROR: Too many redirects from BasicAuth Url: '.$this->authUrl,
['app' => 'user_external']
);
return false;

View file

@ -6,6 +6,8 @@
* See the COPYING-README file.
*/
namespace OCA\UserExternal;
/**
* User authentication against a FTP/FTPS server
*
@ -15,7 +17,7 @@
* @license http://www.gnu.org/licenses/agpl AGPL
* @link http://github.com/owncloud/apps
*/
class OC_User_FTP extends \OCA\user_external\Base{
class FTP extends Base {
private $host;
private $secure;
private $protocol;
@ -26,12 +28,12 @@ class OC_User_FTP extends \OCA\user_external\Base{
* @param string $host Hostname or IP of FTP server
* @param boolean $secure TRUE to enable SSL
*/
public function __construct($host,$secure=false) {
$this->host=$host;
$this->secure=$secure;
$this->protocol='ftp';
if($this->secure) {
$this->protocol.='s';
public function __construct($host, $secure = false) {
$this->host = $host;
$this->secure = $secure;
$this->protocol = 'ftp';
if ($this->secure) {
$this->protocol .= 's';
}
parent::__construct($this->protocol . '://' . $this->host);
}
@ -46,7 +48,7 @@ class OC_User_FTP extends \OCA\user_external\Base{
*/
public function checkPassword($uid, $password) {
if (false === array_search($this->protocol, stream_get_wrappers())) {
OC::$server->getLogger()->error(
\OC::$server->getLogger()->error(
'ERROR: Stream wrapper not available: ' . $this->protocol,
['app' => 'user_external']
);
@ -54,11 +56,11 @@ class OC_User_FTP extends \OCA\user_external\Base{
}
// opendir handles the as %-encoded string, but this is not true for usernames and passwords, encode them before passing them
$url = sprintf('%s://%s:%s@%s/', $this->protocol, urlencode($uid), urlencode($password), $this->host);
$result=@opendir($url);
if(is_resource($result)) {
$result = @opendir($url);
if (is_resource($result)) {
$this->storeUser($uid);
return $uid;
}else{
} else {
return false;
}
}

View file

@ -7,6 +7,7 @@
* later.
* See the COPYING-README file.
*/
namespace OCA\UserExternal;
/**
* User authentication against an IMAP mail server
@ -17,7 +18,7 @@
* @license http://www.gnu.org/licenses/agpl AGPL
* @link http://github.com/owncloud/apps
*/
class OC_User_IMAP extends \OCA\user_external\Base {
class IMAP extends Base {
private $mailbox;
private $port;
private $sslmode;
@ -57,20 +58,20 @@ class OC_User_IMAP extends \OCA\user_external\Base {
// Replace escaped @ symbol in uid (which is a mail address)
// but only if there is no @ symbol and if there is a %40 inside the uid
if (!(strpos($uid, '@') !== false) && (strpos($uid, '%40') !== false)) {
$uid = str_replace("%40","@",$uid);
$uid = str_replace("%40", "@", $uid);
}
$pieces = explode('@', $uid);
if ($this->domain !== '') {
if (count($pieces) === 1) {
$username = $uid . '@' . $this->domain;
} else if(count($pieces) === 2 && $pieces[1] === $this->domain) {
} elseif (count($pieces) === 2 && $pieces[1] === $this->domain) {
$username = $uid;
if ($this->stripeDomain) {
$uid = $pieces[0];
}
} else {
OC::$server->getLogger()->error(
\OC::$server->getLogger()->error(
'ERROR: User has a wrong domain! Expecting: '.$this->domain,
['app' => 'user_external']
);
@ -78,11 +79,11 @@ class OC_User_IMAP extends \OCA\user_external\Base {
}
} else {
$username = $uid;
}
}
$groups = [];
if ($this->groupDomain && $pieces[1]) {
$groups[] = $pieces[1];
if ((count($pieces) > 1) && $this->groupDomain && $pieces[1]) {
$groups[] = $pieces[1];
}
$protocol = ($this->sslmode === "ssl") ? "imaps" : "imap";
@ -97,16 +98,37 @@ class OC_User_IMAP extends \OCA\user_external\Base {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'CAPABILITY');
$canconnect = curl_exec($ch);
curl_exec($ch);
$errorcode = curl_errno($ch);
if($canconnect) {
if ($errorcode === 0) {
curl_close($ch);
$uid = mb_strtolower($uid);
$this->storeUser($uid, $groups);
return $uid;
} elseif ($errorcode === CURLE_COULDNT_CONNECT ||
$errorcode === CURLE_SSL_CONNECT_ERROR ||
$errorcode === 28) {
# This is not defined in PHP-8.x
# 28: CURLE_OPERATION_TIMEDOUT
\OC::$server->getLogger()->error(
'ERROR: Could not connect to imap server via curl: ' . curl_strerror($errorcode),
['app' => 'user_external']
);
} elseif ($errorcode === 9 ||
$errorcode === 67 ||
$errorcode === 94) {
# These are not defined in PHP-8.x
# 9: CURLE_REMOTE_ACCESS_DENIED
# 67: CURLE_LOGIN_DENIED
# 94: CURLE_AUTH_ERROR)
\OC::$server->getLogger()->error(
'ERROR: IMAP Login failed via curl: ' . curl_strerror($errorcode),
['app' => 'user_external']
);
} else {
OC::$server->getLogger()->error(
'ERROR: Could not connect to imap server via curl: '.curl_error($ch),
\OC::$server->getLogger()->error(
'ERROR: IMAP server returned an error: ' . $errorcode . ' / ' . curl_strerror($errorcode),
['app' => 'user_external']
);
}

View file

@ -23,11 +23,11 @@ declare(strict_types=1);
*
*/
namespace OCA\User_external\Migration;
namespace OCA\UserExternal\Migration;
use Closure;
use Doctrine\DBAL\Types\Type;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;
@ -44,17 +44,17 @@ class Version0010Date20200630193751 extends SimpleMigrationStep {
if (!$schema->hasTable('users_external')) {
$table = $schema->createTable('users_external');
$table->addColumn('backend', Type::STRING, [
$table->addColumn('backend', Types::STRING, [
'notnull' => true,
'length' => 128,
'default' => '',
]);
$table->addColumn('uid', Type::STRING, [
$table->addColumn('uid', Types::STRING, [
'notnull' => true,
'length' => 64,
'default' => '',
]);
$table->addColumn('displayname', Type::STRING, [
$table->addColumn('displayname', Types::STRING, [
'notnull' => false,
'length' => 64,
]);

View file

@ -5,6 +5,7 @@
* later.
* See the COPYING-README file.
*/
namespace OCA\UserExternal;
/**
* User authentication via samba (smbclient)
@ -15,11 +16,11 @@
* @license http://www.gnu.org/licenses/agpl AGPL
* @link http://github.com/owncloud/apps
*/
class OC_User_SMB extends \OCA\user_external\Base{
class SMB extends Base {
private $host;
const SMBCLIENT = 'smbclient -L';
const LOGINERROR = 'NT_STATUS_LOGON_FAILURE';
public const SMBCLIENT = 'smbclient -L';
public const LOGINERROR = 'NT_STATUS_LOGON_FAILURE';
/**
* Create new samba authentication provider
@ -28,7 +29,7 @@ class OC_User_SMB extends \OCA\user_external\Base{
*/
public function __construct($host) {
parent::__construct($host);
$this->host=$host;
$this->host = $host;
}
/**
@ -42,20 +43,20 @@ class OC_User_SMB extends \OCA\user_external\Base{
$command = self::SMBCLIENT.' '.escapeshellarg('//' . $this->host . '/dummy').' -U '.$uidEscaped.'%'.$password;
$lastline = exec($command, $output, $retval);
if ($retval === 127) {
OC::$server->getLogger()->error(
\OC::$server->getLogger()->error(
'ERROR: smbclient executable missing',
['app' => 'user_external']
);
return false;
} else if (strpos($lastline, self::LOGINERROR) !== false) {
} elseif (strpos($lastline, self::LOGINERROR) !== false) {
//normal login error
return false;
} else if (strpos($lastline, 'NT_STATUS_BAD_NETWORK_NAME') !== false) {
} elseif (strpos($lastline, 'NT_STATUS_BAD_NETWORK_NAME') !== false) {
//login on minor error
goto login;
} else if ($retval !== 0) {
} elseif ($retval !== 0) {
//some other error
OC::$server->getLogger()->error(
\OC::$server->getLogger()->error(
'ERROR: smbclient error: ' . trim($lastline),
['app' => 'user_external']
);
@ -77,13 +78,13 @@ class OC_User_SMB extends \OCA\user_external\Base{
public function checkPassword($uid, $password) {
// Check with an invalid password, if the user authenticates then fail
$attemptWithInvalidPassword = $this->tryAuthentication($uid, base64_encode($password));
if(is_string($attemptWithInvalidPassword)) {
if (is_string($attemptWithInvalidPassword)) {
return false;
}
// Check with valid password
$attemptWithValidPassword = $this->tryAuthentication($uid, $password);
if(is_string($attemptWithValidPassword)) {
if (is_string($attemptWithValidPassword)) {
$this->storeUser($uid);
return $uid;
}

View file

@ -5,6 +5,7 @@
* later.
* See the COPYING-README file.
*/
namespace OCA\UserExternal;
/**
* User authentication against a SSH server
@ -17,15 +18,15 @@
*/
class OC_User_SSH extends \OCA\user_external\Base {
class SSH extends Base {
private $host;
private $port;
private $port;
/**
* Create a new SSH authentication provider
*
* @param string $host Hostname or IP address of SSH servr
*/
* Create a new SSH authentication provider
*
* @param string $host Hostname or IP address of SSH servr
*/
public function __construct($host, $port = 22) {
parent::__construct($host);
$this->host = $host;
@ -33,17 +34,17 @@ class OC_User_SSH extends \OCA\user_external\Base {
}
/**
* Check if the password is correct without logging in
* Requires the php-ssh2 pecl extension
*
* @param string $uid The username
* @param string $password The password
*
* @return true/false
*/
* Check if the password is correct without logging in
* Requires the php-ssh2 pecl extension
*
* @param string $uid The username
* @param string $password The password
*
* @return true/false
*/
public function checkPassword($uid, $password) {
if (!extension_loaded('ssh2')) {
OC::$server->getLogger()->error(
\OC::$server->getLogger()->error(
'ERROR: php-ssh2 PECL module missing',
['app' => 'user_external']
);

View file

@ -6,15 +6,14 @@
* See the COPYING-README file.
*/
namespace OCA\user_external;
namespace OCA\UserExternal;
class WebDavAuth extends Base {
private $webDavAuthUrl;
public function __construct($webDavAuthUrl) {
parent::__construct($webDavAuthUrl);
$this->webDavAuthUrl =$webDavAuthUrl;
$this->webDavAuthUrl = $webDavAuthUrl;
}
/**
@ -27,21 +26,20 @@ class WebDavAuth extends Base {
*/
public function checkPassword($uid, $password) {
$arr = explode('://', $this->webDavAuthUrl, 2);
if( ! isset($arr) OR count($arr) !== 2) {
OC::$server->getLogger()->error('ERROR: Invalid WebdavUrl: "'.$this->webDavAuthUrl.'" ', ['app' => 'user_external']);
if (! isset($arr) or count($arr) !== 2) {
\OC::$server->getLogger()->error('ERROR: Invalid WebdavUrl: "'.$this->webDavAuthUrl.'" ', ['app' => 'user_external']);
return false;
}
list($protocol, $path) = $arr;
$url= $protocol.'://'.urlencode($uid).':'.urlencode($password).'@'.$path;
$url = $protocol.'://'.urlencode($uid).':'.urlencode($password).'@'.$path;
$headers = get_headers($url);
if($headers === false) {
OC::$server->getLogger()->error('ERROR: Not possible to connect to WebDAV Url: "'.$protocol.'://'.$path.'" ', ['app' => 'user_external']);
if ($headers === false) {
\OC::$server->getLogger()->error('ERROR: Not possible to connect to WebDAV Url: "'.$protocol.'://'.$path.'" ', ['app' => 'user_external']);
return false;
}
$returnCode= substr($headers[0], 9, 3);
$returnCode = substr($headers[0], 9, 3);
if(substr($returnCode, 0, 1) === '2') {
if (substr($returnCode, 0, 1) === '2') {
$this->storeUser($uid);
return $uid;
} else {

129
lib/XMPP.php Normal file
View file

@ -0,0 +1,129 @@
<?php
/**
* Copyright (c) 2019 Sebastian Sterk <sebastian@wiuwiu.de>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCA\UserExternal;
/**
* User authentication against a XMPP Prosody MySQL database
*
* @category Apps
* @package UserExternal
* @author Sebastian Sterk https://wiuwiu.de/Imprint
* @license http://www.gnu.org/licenses/agpl AGPL
*/
class XMPP extends Base {
private $host;
private $xmppDb;
private $xmppDbUser;
private $xmppDbPassword;
private $xmppDomain;
private $passwordHashed;
public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain, $passwordHashed = true) {
parent::__construct($host);
$this->host = $host;
$this->xmppDb = $xmppDb;
$this->xmppDbUser = $xmppDbUser;
$this->xmppDbPassword = $xmppDbPassword;
$this->xmppDomain = $xmppDomain;
$this->passwordHashed = $passwordHashed;
}
public function hmacSha1($key, $data) {
if (strlen($key) > 64) {
$key = str_pad(sha1($key, true), 64, chr(0));
}
if (strlen($key) < 64) {
$key = str_pad($key, 64, chr(0));
}
$oPad = str_repeat(chr(0x5C), 64);
$iPad = str_repeat(chr(0x36), 64);
for ($i = 0; $i < strlen($key); $i++) {
$oPad[$i] = $oPad[$i] ^ $key[$i];
$iPad[$i] = $iPad[$i] ^ $key[$i];
}
return sha1($oPad.sha1($iPad.$data, true));
}
public function validateHashedPassword($user, $uid, $submittedPassword) {
foreach ($user as $key) {
if ($key[3] === "salt") {
$internalSalt = $key['value'];
}
if ($key[3] === "server_key") {
$internalServerKey = $key['value'];
}
if ($key[3] === "stored_key") {
$internalStoredKey = $key['value'];
}
}
unset($user);
$internalIteration = '4096';
$newSaltedPassword = hash_pbkdf2('sha1', $submittedPassword, $internalSalt, $internalIteration, 0, true);
$newServerKey = $this->hmacSha1($newSaltedPassword, 'Server Key');
$newClientKey = $this->hmacSha1($newSaltedPassword, 'Client Key');
$newStoredKey = sha1(hex2bin($newClientKey));
if ($newServerKey === $internalServerKey
&& $newStoredKey === $internalStoredKey) {
$uid = mb_strtolower($uid);
$this->storeUser($uid);
return $uid;
} else {
return false;
}
}
public function validatePlainPassword($user, $uid, $submittedPassword) {
foreach ($user as $key) {
if ($key[3] === "password") {
$internalPlainPassword = $key['value'];
}
}
unset($user);
if ($submittedPassword === $internalPlainPassword) {
$uid = mb_strtolower($uid);
$this->storeUser($uid);
return $uid;
} else {
return false;
}
}
public function checkPassword($uid, $password) {
$pdo = new \PDO("mysql:host=$this->host;dbname=$this->xmppDb", $this->xmppDbUser, $this->xmppDbPassword);
if (isset($uid)
&& isset($password)) {
if (!filter_var($uid, FILTER_VALIDATE_EMAIL)
|| !strpos($uid, $this->xmppDomain)
|| substr($uid, -strlen($this->xmppDomain)) !== $this->xmppDomain
) {
return false;
}
$user = explode("@", $uid);
$userName = strtolower($user[0]);
$submittedPassword = $password;
$statement = $pdo->prepare("SELECT * FROM prosody WHERE user = :user AND host = :xmppDomain AND store = 'accounts'");
$result = $statement->execute(array(
'user' => $userName,
'xmppDomain' => $this->xmppDomain
));
$user = $statement->fetchAll();
if (empty($user)) {
return false;
}
if ($this->passwordHashed === true) {
return $this->validateHashedPassword($user, $uid, $submittedPassword);
} else {
return $this->validatePlainPassword($user, $uid, $submittedPassword);
}
}
}
}

View file

@ -1,128 +0,0 @@
<?php
/**
* Copyright (c) 2019 Sebastian Sterk <sebastian@wiuwiu.de>
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
/**
* User authentication against a XMPP Prosody MySQL database
*
* @category Apps
* @package UserExternal
* @author Sebastian Sterk https://wiuwiu.de/Imprint
* @license http://www.gnu.org/licenses/agpl AGPL
*/
class OC_User_XMPP extends \OCA\user_external\Base {
private $host;
private $xmppDb;
private $xmppDbUser;
private $xmppDbPassword;
private $xmppDomain;
private $passwordHashed;
public function __construct($host, $xmppDb, $xmppDbUser, $xmppDbPassword, $xmppDomain, $passwordHashed = true) {
parent::__construct($host);
$this->host = $host;
$this->xmppDb = $xmppDb;
$this->xmppDbUser = $xmppDbUser;
$this->xmppDbPassword = $xmppDbPassword;
$this->xmppDomain = $xmppDomain;
$this->passwordHashed = $passwordHashed;
}
public function hmacSha1($key, $data) {
if (strlen($key) > 64) {
$key = str_pad(sha1($key, true), 64, chr(0));
}
if (strlen($key) < 64) {
$key = str_pad($key, 64, chr(0));
}
$oPad = str_repeat(chr(0x5C), 64);
$iPad = str_repeat(chr(0x36), 64);
for ($i = 0; $i < strlen($key); $i++) {
$oPad[$i] = $oPad[$i] ^ $key[$i];
$iPad[$i] = $iPad[$i] ^ $key[$i];
}
return sha1($oPad.sha1($iPad.$data, true));
}
public function validateHashedPassword($user, $uid, $submittedPassword){
foreach ($user as $key){
if($key[3] === "salt") {
$internalSalt = $key['value'];
}
if($key[3] === "server_key") {
$internalServerKey = $key['value'];
}
if($key[3] === "stored_key") {
$internalStoredKey = $key['value'];
}
}
unset($user);
$internalIteration = '4096';
$newSaltedPassword = hash_pbkdf2('sha1', $submittedPassword, $internalSalt, $internalIteration, 0, true);
$newServerKey = $this->hmacSha1($newSaltedPassword, 'Server Key');
$newClientKey = $this->hmacSha1($newSaltedPassword, 'Client Key');
$newStoredKey = sha1(hex2bin($newClientKey));
if ($newServerKey === $internalServerKey
&& $newStoredKey === $internalStoredKey) {
$uid = mb_strtolower($uid);
$this->storeUser($uid);
return $uid;
} else {
return false;
}
}
public function validatePlainPassword($user, $uid, $submittedPassword) {
foreach ($user as $key) {
if($key[3] === "password") {
$internalPlainPassword = $key['value'];
}
}
unset($user);
if ($submittedPassword === $internalPlainPassword) {
$uid = mb_strtolower($uid);
$this->storeUser($uid);
return $uid;
} else {
return false;
}
}
public function checkPassword($uid, $password){
$pdo = new PDO("mysql:host=$this->host;dbname=$this->xmppDb", $this->xmppDbUser, $this->xmppDbPassword);
if(isset($uid)
&& isset($password)) {
if(!filter_var($uid, FILTER_VALIDATE_EMAIL)
|| !strpos($uid, $this->xmppDomain)
|| substr($uid, -strlen($this->xmppDomain)) !== $this->xmppDomain
) {
return false;
}
$user = explode("@", $uid);
$userName = strtolower($user[0]);
$submittedPassword = $password;
$statement = $pdo->prepare("SELECT * FROM prosody WHERE user = :user AND host = :xmppDomain AND store = 'accounts'");
$result = $statement->execute(array(
'user' => $userName,
'xmppDomain' => $this->xmppDomain
));
$user = $statement->fetchAll();
if(empty($user)) {
return false;
}
if ($this->passwordHashed === true) {
return $this->validateHashedPassword($user, $uid, $submittedPassword);
} else {
return $this->validatePlainPassword($user, $uid, $submittedPassword);
}
}
}
}

18
php-cs-fixer.dist.php Normal file
View file

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
require_once './vendor/autoload.php';
use Nextcloud\CodingStandard\Config;
$config = new Config();
$config
->getFinder()
->notPath('build')
->notPath('l10n')
->notPath('node_modules')
->notPath('src')
->notPath('vendor')
->in(__DIR__);
return $config;

View file

@ -16,20 +16,20 @@ class Test_User_BasicAuth extends \Test\TestCase {
return include(__DIR__.'/config.php');
}
function skip() {
$config=$this->getConfig();
public function skip() {
$config = $this->getConfig();
$this->skipUnless($config['basic_auth']['run']);
}
protected function setUp() {
parent::setUp();
$config=$this->getConfig();
$this->instance=new OC_User_BasicAuth($config['basic_auth']['url']);
$config = $this->getConfig();
$this->instance = new OC_User_BasicAuth($config['basic_auth']['url']);
}
function testLogin() {
$config=$this->getConfig();
$this->assertEquals($config['basic_auth']['user'],$this->instance->checkPassword($config['basic_auth']['user'],$config['basic_auth']['password']));
$this->assertFalse($this->instance->checkPassword($config['basic_auth']['user'],$config['basic_auth']['password'].'foo'));
public function testLogin() {
$config = $this->getConfig();
$this->assertEquals($config['basic_auth']['user'], $this->instance->checkPassword($config['basic_auth']['user'], $config['basic_auth']['password']));
$this->assertFalse($this->instance->checkPassword($config['basic_auth']['user'], $config['basic_auth']['password'].'foo'));
}
}

View file

@ -1,4 +1,5 @@
<?php
if (!defined('PHPUNIT_RUN')) {
define('PHPUNIT_RUN', 1);
}
@ -9,7 +10,7 @@ if (!class_exists('\PHPUnit\Framework\TestCase')) {
\OC_App::loadApp('user_external');
$dummyClass = \OC::$SERVERROOT . '/tests/lib/Util/User/Dummy.php';
if(file_exists($dummyClass)) {
if (file_exists($dummyClass)) {
require_once($dummyClass);
}
OC_Hook::clear();

View file

@ -8,28 +8,28 @@
OC_App::loadApp('user_external');
return array(
'imap'=>array(
'run'=>false,
'mailbox'=>'{imap.gmail.com:993/imap/ssl}INBOX', //see http://php.net/manual/en/function.imap-open.php
'user'=>'foo',//valid username/password combination
'password'=>'bar',
'imap' => array(
'run' => false,
'mailbox' => '{imap.gmail.com:993/imap/ssl}INBOX', //see http://php.net/manual/en/function.imap-open.php
'user' => 'foo',//valid username/password combination
'password' => 'bar',
),
'smb'=>array(
'run'=>false,
'host'=>'localhost',
'user'=>'test',//valid username/password combination
'password'=>'test',
'smb' => array(
'run' => false,
'host' => 'localhost',
'user' => 'test',//valid username/password combination
'password' => 'test',
),
'ftp'=>array(
'run'=>false,
'host'=>'localhost',
'user'=>'test',//valid username/password combination
'password'=>'test',
'ftp' => array(
'run' => false,
'host' => 'localhost',
'user' => 'test',//valid username/password combination
'password' => 'test',
),
'basic_auth'=>array(
'run'=>false,
'url'=>'localhost/basic_auth',
'user'=>'test',//valid username/password combination
'password'=>'test',
'basic_auth' => array(
'run' => false,
'url' => 'localhost/basic_auth',
'user' => 'test',//valid username/password combination
'password' => 'test',
),
);

View file

@ -16,20 +16,20 @@ class Test_User_FTP extends \Test\TestCase {
return include(__DIR__.'/config.php');
}
function skip() {
$config=$this->getConfig();
public function skip() {
$config = $this->getConfig();
$this->skipUnless($config['ftp']['run']);
}
protected function setUp() {
parent::setUp();
$config=$this->getConfig();
$this->instance=new OC_User_FTP($config['ftp']['host']);
$config = $this->getConfig();
$this->instance = new OC_User_FTP($config['ftp']['host']);
}
function testLogin() {
$config=$this->getConfig();
$this->assertEquals($config['ftp']['user'],$this->instance->checkPassword($config['ftp']['user'],$config['ftp']['password']));
$this->assertFalse($this->instance->checkPassword($config['ftp']['user'],$config['ftp']['password'].'foo'));
public function testLogin() {
$config = $this->getConfig();
$this->assertEquals($config['ftp']['user'], $this->instance->checkPassword($config['ftp']['user'], $config['ftp']['password']));
$this->assertFalse($this->instance->checkPassword($config['ftp']['user'], $config['ftp']['password'].'foo'));
}
}

View file

@ -16,21 +16,21 @@ class Test_User_Imap extends \Test\TestCase {
return include(__DIR__.'/config.php');
}
function skip() {
$config=$this->getConfig();
public function skip() {
$config = $this->getConfig();
$this->skipUnless($config['imap']['run']);
}
protected function setUp() {
parent::setUp();
$config=$this->getConfig();
$this->instance=new OC_User_IMAP($config['imap']['mailbox']);
$config = $this->getConfig();
$this->instance = new OC_User_IMAP($config['imap']['mailbox']);
}
function testLogin() {
$config=$this->getConfig();
$this->assertEquals($config['imap']['user'],$this->instance->checkPassword($config['imap']['user'],$config['imap']['password']));
$this->assertFalse($this->instance->checkPassword($config['imap']['user'],$config['imap']['password'].'foo'));
public function testLogin() {
$config = $this->getConfig();
$this->assertEquals($config['imap']['user'], $this->instance->checkPassword($config['imap']['user'], $config['imap']['password']));
$this->assertFalse($this->instance->checkPassword($config['imap']['user'], $config['imap']['password'].'foo'));
}
}

View file

@ -16,21 +16,21 @@ class Test_User_SMB extends \Test\TestCase {
return include(__DIR__.'/config.php');
}
function skip() {
$config=$this->getConfig();
public function skip() {
$config = $this->getConfig();
$this->skipUnless($config['smb']['run']);
}
protected function setUp() {
parent::setUp();
$config=$this->getConfig();
$this->instance=new OC_User_SMB($config['smb']['host']);
$config = $this->getConfig();
$this->instance = new OC_User_SMB($config['smb']['host']);
}
function testLogin() {
$config=$this->getConfig();
$this->assertEquals($config['smb']['user'],$this->instance->checkPassword($config['smb']['user'],$config['smb']['password']));
$this->assertFalse($this->instance->checkPassword($config['smb']['user'],$config['smb']['password'].'foo'));
public function testLogin() {
$config = $this->getConfig();
$this->assertEquals($config['smb']['user'], $this->instance->checkPassword($config['smb']['user'], $config['smb']['password']));
$this->assertFalse($this->instance->checkPassword($config['smb']['user'], $config['smb']['password'].'foo'));
}
}