Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP-Users can not login & user folder will not be created on filesystem data directory #24423

Closed
thmcon opened this issue May 3, 2016 · 39 comments

Comments

@thmcon
Copy link

thmcon commented May 3, 2016

Steps to reproduce

  1. Take owncloud 9.0.1.3 which has benn upgraded from 8.x
  2. Have an Microsoft Active Directory setup as owncloud-LDAP (in my case: 2 active directory servers)
  3. take an LDAP-User which never logged in to owncloud before
  4. This only occurs when you have LDAP groups defined. without any group, this issue is not occuring.

Expected behaviour

The user should be able to login to the owncloud webpage and should get the "welcome message" and should be able to handle files.
On the webserver's file system there should be a new directory created with the directory name = his username.

Actual behaviour

The user enters his passowrd and tries to logon. He receives the webserver error 500.
The apache logfile shows the following entry:
PHP Fatal error: Call to a member function file_exists() on a non-object in /var/www/owncloud/lib/private/files/filesystem.php on line 693

On the file system of the webserver, OC-Data-directory, there has no new sub-directory for this user been created.

If I create a user in owncloud and logon with this user, everything works fine (user not coming from active directory / LDAP).
If I take a user which has been created from actie directory/LDAP in owncloud version 8.x, everything works fine (the user fodler in data directory has been created correctly under 8.x)

Server configuration

Operating system: ubuntu 14.04

Web server: apache 2.4.7

Database: mysql

PHP version: 5.5.9

ownCloud version: (see ownCloud admin page) 9.0.1.3

Updated from an older ownCloud or fresh install: updated from 8.x (took each single step, no version left out)

Where did you install ownCloud from: download tar file from owncloud.org

Signing status (ownCloud 9.0 and above):
no idea what I should enter here... please reply what I should add here... sorry

Login as admin user into your ownCloud and access 
http://example.com/index.php/settings/integrity/failed 
paste the results here.
No errors have been found.

List of activated apps:

Enabled:

  • activity: 2.2.1
  • comments: 0.2
  • dav: 0.1.6
  • federatedfilesharing: 0.1.0
  • federation: 0.0.4
  • files: 1.4.4
  • files_external: 0.5.2
  • files_sharing: 0.9.1
  • files_texteditor: 2.1
  • files_trashbin: 0.8.0
  • files_versions: 1.2.0
  • files_videoplayer: 0.9.8
  • firstrunwizard: 1.1
  • notifications: 0.2.3
  • provisioning_api: 0.4.1
  • systemtags: 0.2
  • templateeditor: 0.1
  • updatenotification: 0.1.0
  • user_external: 0.4
  • user_ldap: 0.8.0
    Disabled:
  • encryption
  • external
  • files_pdfviewer
  • gallery

The content of config/config.php:

{
"system": {
"instanceid": "513af407e8f2d",
"passwordsalt": "_REMOVED SENSITIVE VALUE",
"datadirectory": "/mnt/sdb1/owncloud_data",
"dbtype": "mysql",
"version": "9.0.1.3",
"installed": true,
"memcache.local": "\OC\Memcache\APC",
"ldapIgnoreNamingRules": false,
"loglevel": 1,
"maintenance": false,
"theme": "",
"trusted_domains": [
"abc.domain.com",
"xyz.domain.com"
],
"share_folder": "/Shared",
"secret": "_REMOVED SENSITIVE VALUE
",
"forcessl": true,
"forceSSLforSubdomains": true,
"mail_from_address": "it",
"mail_smtpmode": "smtp",
"mail_domain": "domain.com",
"mail_smtphost": "10.180.1.203",
"mail_smtpport": "25",
"dbname": "owncloud",
"dbhost": "10.180.1.48",
"dbuser": "_REMOVED SENSITIVE VALUE",
"dbpassword": "_REMOVED SENSITIVE VALUE
"
}
}

Are you using external storage, if yes which one: external = local disk on same server, just the data directory outside the webserver directory. see config.

Are you using encryption: no

Are you using an external user-backend, if yes which one: ActiveDirectory

LDAP configuration (delete this part if not used)

+-------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Configuration | s02 |
+-------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| hasMemberOfFilterSupport | 1 |
| hasPagedResultSupport | |
| homeFolderNamingRule | |
| lastJpegPhotoLookup | 0 |
| ldapAgentName | CN=LDAP-Anmeldeuser,OU=Service-User,OU=Benutzer,OU=Organisation,DC=domain,DC=com |
| ldapAgentPassword | *** |
| ldapAttributesForGroupSearch | |
| ldapAttributesForUserSearch | |
| ldapBackupHost | |
| ldapBackupPort | |
| ldapBase | DC=domain,DC=com |
| ldapBaseGroups | DC=domain,DC=com |
| ldapBaseUsers | DC=domain,DC=com |
| ldapCacheTTL | 600 |
| ldapConfigurationActive | 1 |
| ldapDynamicGroupMemberURL | |
| ldapEmailAttribute | mail |
| ldapExperiencedAdmin | 0 |
| ldapExpertUUIDGroupAttr | |
| ldapExpertUUIDUserAttr | |
| ldapExpertUsernameAttr | |
| ldapGroupDisplayName | cn |
| ldapGroupFilter | (&(|(objectclass=group))) |
| ldapGroupFilterGroups | |
| ldapGroupFilterMode | 0 |
| ldapGroupFilterObjectclass | group |
| ldapGroupMemberAssocAttr | member |
| ldapHost | 10.180.1.201 |
| ldapIgnoreNamingRules | |
| ldapLoginFilter | (&(&(|(objectclass=organizationalPerson)(objectclass=person)(objectclass=user)))(|(samaccountname=%uid)(|(mailPrimaryAddress=%uid)(mail=%uid)))) |
| ldapLoginFilterAttributes | |
| ldapLoginFilterEmail | 1 |
| ldapLoginFilterMode | 0 |
| ldapLoginFilterUsername | 1 |
| ldapNestedGroups | 0 |
| ldapOverrideMainServer | |
| ldapPagingSize | 500 |
| ldapPort | 389 |
| ldapQuotaAttribute | |
| ldapQuotaDefault | |
| ldapTLS | 0 |
| ldapUserDisplayName | displayname |
| ldapUserDisplayName2 | |
| ldapUserFilter | (&(|(objectclass=organizationalPerson)(objectclass=person)(objectclass=user))(|(|(memberof=CN=Domänen-Benutzer,CN=Users,DC=domain,DC=com)(primaryGroupID=513)))) |
| ldapUserFilterGroups | Domänen-Benutzer |
| ldapUserFilterMode | 0 |
| ldapUserFilterObjectclass | organizationalPerson;person;user |
| ldapUuidGroupAttribute | auto |
| ldapUuidUserAttribute | auto |
| turnOffCertCheck | 0 |
| useMemberOfToDetectMembership | 1 |
+-------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Configuration | s03 |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| hasMemberOfFilterSupport | 1 |
| hasPagedResultSupport | |
| homeFolderNamingRule | |
| lastJpegPhotoLookup | 0 |
| ldapAgentName | CN=LDAP-Anmeldeuser,OU=Service-User,OU=Benutzer,OU=Organisation,DC=domain,DC=com|
| ldapAgentPassword | *** |
| ldapAttributesForGroupSearch | |
| ldapAttributesForUserSearch | |
| ldapBackupHost | |
| ldapBackupPort | |
| ldapBase | DC=domain,DC=com|
| ldapBaseGroups | DC=domain,DC=com |
| ldapBaseUsers | DC=domain,DC=com |
| ldapCacheTTL | 600 |
| ldapConfigurationActive | 1 |
| ldapDynamicGroupMemberURL | |
| ldapEmailAttribute | |
| ldapExperiencedAdmin | 0 |
| ldapExpertUUIDGroupAttr | |
| ldapExpertUUIDUserAttr | |
| ldapExpertUsernameAttr | |
| ldapGroupDisplayName | cn |
| ldapGroupFilter | |
| ldapGroupFilterGroups | |
| ldapGroupFilterMode | 0 |
| ldapGroupFilterObjectclass | |
| ldapGroupMemberAssocAttr | uniqueMember |
| ldapHost | 10.180.1.202 |
| ldapIgnoreNamingRules | |
| ldapLoginFilter | (&(&(|(objectclass=inetOrgPerson)(objectclass=organizationalPerson)(objectclass=person)(objectclass=user)))(|(samaccountname=%uid)(|(mailPrimaryAddress=%uid)(mail=%uid)))) |
| ldapLoginFilterAttributes | |
| ldapLoginFilterEmail | 1 |
| ldapLoginFilterMode | 0 |
| ldapLoginFilterUsername | 1 |
| ldapNestedGroups | 0 |
| ldapOverrideMainServer | |
| ldapPagingSize | 500 |
| ldapPort | 389 |
| ldapQuotaAttribute | |
| ldapQuotaDefault | |
| ldapTLS | 0 |
| ldapUserDisplayName | displayname |
| ldapUserDisplayName2 | |
| ldapUserFilter | (&(|(objectclass=inetOrgPerson)(objectclass=organizationalPerson)(objectclass=person)(objectclass=user))) |
| ldapUserFilterGroups | |
| ldapUserFilterMode | 0 |
| ldapUserFilterObjectclass | organizationalPerson;person;user |
| ldapUuidGroupAttribute | auto |
| ldapUuidUserAttribute | auto |
| turnOffCertCheck | 0 |
| useMemberOfToDetectMembership | 1 |
+-------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

Client configuration

Browser: Firefox, Chrome, Internet Explorer

Operating system: Windows 8.1, Windows 7

Logs

Web server error log

[Tue May 03 16:05:40.213672 2016] [:error] [pid 5464] [client 10.180.18.26:44403] PHP Fatal error: Call to a member function file_exists() on a non-object in /var/www/owncloud/lib/private/files/filesystem.php on line 693
[Tue May 03 16:05:47.039942 2016] [:error] [pid 5454] [client 10.180.18.26:44407] PHP Fatal error: Call to a member function file_exists() on a non-object in /var/www/owncloud/lib/private/files/filesystem.php on line 693
[Tue May 03 16:05:53.116388 2016] [:error] [pid 5452] [client 10.180.18.26:44488] PHP Fatal error: Call to a member function file_exists() on a non-object in /var/www/owncloud/lib/private/files/filesystem.php on line 693
[Tue May 03 16:19:55.750866 2016] [:error] [pid 5455] [client 10.180.5.54:45340] PHP Fatal error: Call to a member function file_exists() on a non-object in /var/www/owncloud/lib/private/files/filesystem.php on line 693

Owncloud-Log

{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"user_ldap","message":"Looking for cookie L/O 500/0","level":1,"time":"2016-05-03T14:19:54+00:00","method":"GET","url":"/cron.php","user":"--"}
{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"user_ldap","message":"No paged search for us, Cpt., Limit 500 Offset 500","level":1,"time":"2016-05-03T14:19:54+00:00","method":"GET","url":"/cron.php","user":"--"}
{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"user_ldap","message":"Paged search was not available","level":1,"time":"2016-05-03T14:19:54+00:00","method":"GET","url":"/cron.php","user":"--"}
{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"user_ldap","message":"Looking for cookie L/O 500/0","level":1,"time":"2016-05-03T14:19:55+00:00","method":"GET","url":"/cron.php","user":"--"}
{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"user_ldap","message":"No paged search for us, Cpt., Limit 500 Offset 500","level":1,"time":"2016-05-03T14:19:55+00:00","method":"GET","url":"/cron.php","user":"--"}
{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"user_ldap","message":"Paged search was not available","level":1,"time":"2016-05-03T14:19:55+00:00","method":"GET","url":"/cron.php","user":"--"}
{"reqId":"rGfG5VjBMEWwH91sZmYQ","remoteAddr":"10.180.5.54","app":"PHP","message":"Call to a member function file_exists() on a non-object at /var/www/owncloud/lib/private/files/filesystem.php#693","level":3,"time":"2016-05-03T14:19:55+00:00","method":"GET","url":"/cron.php","user":"--"}

@PVince81
Copy link
Contributor

PVince81 commented May 4, 2016

Thanks for the detailed report.

You might want to try upgrading to 9.0.2 that just got released, in case it helps.

@blizzz @icewind1991 any idea about these errors ?

@PVince81 PVince81 added this to the 9.0.3-next-maintenance milestone May 4, 2016
@mayerthomas
Copy link

mayerthomas commented May 5, 2016

Upgrading to 9.0.2 did not fix the problem for me.
I also have a user that cannot login anymore but already successfully has logged in before...

sudo -u www-data php occ ldap:search "username"
brings:
PHP Fatal error: Call to a member function file_exists() on null in /var/www/owncloud/lib/private/files/filesystem.php on line 696
No error with other existing users and also no error, when I try a username that does not exist...

sudo -u www-data php occ ldap:check-user "username"
brings:
The user is still available on LDAP.

@jakob42
Copy link

jakob42 commented May 12, 2016

I'm testing the upgrade of an owncloud 7 installation to 9, up until 8.2.x the ldap backend worked fine, but after upgrading to 9 (9.0.2.2) I get an empty page while logging an ldap user in and the following error message in the log. My local admin user works as expected.

2016/05/12 11:19:46 [error] 5685#5685: *18 FastCGI sent in stderr: "PHP message: PHP Fatal error: Call to a member function file_exists() on null in /srv/owncloud/webroot/lib/private/files/filesystem.php on line 696" while reading response header from upstream, client: w.x.y.z, server: my.owncloud.example.com, request: "POST /index.php HTTP/2.0", upstream: "fastcgi://unix:/run/php/php5.6-fpm.sock:", host: "my.owncloud.example.com"

@PVince81
Copy link
Contributor

Is that for any LDAP user ? Or is that LDAP user receiving shares ?
Could be related to deleted users or orphaned shares.

@jakob42
Copy link

jakob42 commented May 12, 2016

Oh, I only copied data for some users, but I found out that it is only for my user. My user is receiving a share from a user that I didn't copy yet. I'll copy that users data tomorrow and check back with you. But sorry for the fuss, it isn't a general ldap problem.

@PVince81
Copy link
Contributor

It might be an issue with invalid shares, which ownCloud is supposed to silently ignore. Some might get cleant up later when running cron, if applicable.

Would be good to find out what kind of share it is and how it got into that state.

@neocturne
Copy link

We're experiencing an issue that is likely the same underlying bug: Error message PHP Fatal error: Call to a member function file_exists() on null in /var/www/owncloud/lib/private/files/filesystem.php on line 696, but instead of on logins, it occurs whenever the ScanFiles background job is run by Cron (in one of the $this->userManager->search calls in apps/files/lib/backgroundjob/scanfiles.php, to be exact).

Our environment is similar: owncloud 8 updated to 9, LDAP users.

@jakob42
Copy link

jakob42 commented May 13, 2016

All right, I checked in the database, I've got one "incoming" share (select * from 'oc_share' WHERE 'share_with' = myuser;). I've copied that users data and it works now, so I guess it won't be a problem in the live system. But it could be handled more gracefully.

Thanks for the quick responses.

@peter-rindfuss
Copy link

We see the same problems with 9.0.2 and OpenLDAP. The error occurs reproducibly when a new LDAP user has not yet logged in to Owncloud, but receives a share. The latter can happen either directly, if someone shares a folder with the new LDAP user, or indirectly by group membership. We mostly see the group membership situation.

After the error has happened, it can always and permanently be cleared by occ files:scan <user>.

I also tried to find a way that solves the problem before it strikes, but was only half successful. After LDAP user creation, I run
occ ldap:search <user> (makes the user known to Owncloud)
occ files:scan <user>
This helps, however, only if the LDAP user is member of an LDAP group for which something is shared. If that is not the case, occ files:scan <user> fails.

@marcandreu
Copy link

marcandreu commented May 20, 2016

I'm experimenting the same problem, with the same ldap+oc installation except it was not an upgrade, but a fresh install. Tryied 9.0.2 update and didn't solve it. Also "occ ldap:search <user>" (or --all) & "occ files:scan <user>" didn't solve it for that user. Cron job status is ok. Server also ok except for the same reported error in the logs.

I'm wondering what solution did @jakob42 apply when he said "I've copied that users data and it works now". Into which database table and what info did you exacly copy? or you just created the folder's structure of that new user...? Thanks!

@marcandreu
Copy link

marcandreu commented May 20, 2016

I was able to solve it this way:

For all new ldap users (that never logged in), I manually created the structure (with a bash script reading all ldap new users and checking if their folder doesn't exist):

sudo su www-data
mkdir -p /var/www/owncloud/data/<username>/files/**<sharename>**
mkdir -p /var/www/owncloud/data/<username>/files/cache
chmod -R 0755 /var/www/owncloud/data/<username>/

That's it!
Note that sharename is the name in 'share_folder' => '/whatevername' inside the config.php file. If it doesn't exist in the config.php, then just create the folder of the parent directory, not the sharename folder.

Note that this problem only happens if you share a file/folder with another user, and this user never logged in. (I also experienced this problem with already logged users which are not new when they change the shared folder/file name, but I was not able to reproduce the steps and got solved by itself)

oc fix suggestion: when new user X loggs in, if another user Y shared folder to X, and the folder doesnt exist, create it automaticaly, if not, this error happens.

@thmcon
Copy link
Author

thmcon commented May 20, 2016

That suggested fix would be great!

Thomas Hohm
Leitung IT Services
Head of IT Services

m:con - mannheim:congress GmbH
Rosengartenplatz 2
68161 Mannheim

Phone +49 621 4106 175
Fax +49 621 4106 80 175
Mobile +49 174 34 79 459
E-mail [email protected]:[email protected]
Web www.mcon-mannheim.dehttp://www.mcon-mannheim.de/
V-card download V-cardhttp://www.mcon-mannheim.de/wp-content/uploads/2013/05/Thomas-Hohm.vcf

Entdecken Sie WEITBLICKhttp://mcon-weitblick.de/weitblick-5/, das m:con Magazin für die Veranstaltungsbranche.

Sitz Mannheim Amtsgericht Mannheim, HRB 5582
Aufsichtsratsvorsitzender: Dr. Peter Kurz, Oberbürgermeister
Ust-ID-Nr. DE 811968225, Steuer-Nr. 3810700264
Geschäftsführer: Johann W. Wagner

Abonnieren Sie unseren m:con Newsletter.http://www.mcon-mannheim.de/newsletter/

[cid:facebook_a65b9b6c-3d2b-42cb-a24e-f012dd2efd84.png]http://news.mcon-mannheim.de/gu/10/1CBNY8IC-1CBNY8I9-108QJ1O9-HU016U7.html [cid:twitter_8481ca08-65a4-4d46-97be-3ecd29067710.png] http://news.mcon-mannheim.de/gu/10/1CBNY8IC-1CBNY8I9-QHH8C5V-NSH1L0.html http://news.mcon-mannheim.de/gu/10/1CBNY8IC-1CBNY8I9-108QJ1O8-30U14E8.html [cid:xing_09ae54db-abe1-4b1b-b9a0-8ea668a4222b.png] http://news.mcon-mannheim.de/gu/10/1CBNY8IC-1CBNY8I9-128CIE1I-12EP7E7.html [cid:youtube_786e6d2e-db4f-4c55-934a-2497f5ba04b5.png] http://news.mcon-mannheim.de/gu/10/1CBNY8IC-1CBNY8I9-108QJ1O7-100116F.html


This email was scanned by Bitdefender

@patrakov
Copy link

I have hit this bug in 9.0.0, and patched it to log the backtrace. Here it is:

 array (
  0 => 
  array (
    'file' => '/var/www/owncloud/apps/files_sharing/lib/helper.php',
    'line' => 311,
    'function' => 'file_exists',
    'class' => 'OC\\\\Files\\\\Filesystem',
    'type' => '::',
  ),
  1 => 
  array (
    'file' => '/var/www/owncloud/apps/files_sharing/lib/sharedmount.php',
    'line' => 78,
    'function' => 'getShareFolder',
    'class' => 'OCA\\\\Files_Sharing\\\\Helper',
    'type' => '::',
  ),
  2 => 
  array (
    'file' => '/var/www/owncloud/apps/files_sharing/lib/sharedmount.php',
    'line' => 60,
    'function' => 'verifyMountPoint',
    'class' => 'OCA\\\\Files_Sharing\\\\SharedMount',
    'type' => '->',
  ),
  3 => 
  array (
    'file' => '/var/www/owncloud/apps/files_sharing/lib/mountprovider.php',
    'line' => 65,
    'function' => '__construct',
    'class' => 'OCA\\\\Files_Sharing\\\\SharedMount',
    'type' => '->',
  ),
  4 => 
  array (
    'function' => 'OCA\\\\Files_Sharing\\\\{closure}',
    'class' => 'OCA\\\\Files_Sharing\\\\MountProvider',
    'type' => '->',
  ),
  5 => 
  array (
    'file' => '/var/www/owncloud/apps/files_sharing/lib/mountprovider.php',
    'line' => 69,
    'function' => 'array_map',
  ),
  6 => 
  array (
    'file' => '/var/www/owncloud/lib/private/files/config/mountprovidercollection.php',
    'line' => 70,
    'function' => 'getMountsForUser',
    'class' => 'OCA\\\\Files_Sharing\\\\MountProvider',
    'type' => '->',
  ),
  7 => 
  array (
    'function' => 'OC\\\\Files\\\\Config\\\\{closure}',
    'class' => 'OC\\\\Files\\\\Config\\\\MountProviderCollection',
    'type' => '->',
  ),
  8 => 
  array (
    'file' => '/var/www/owncloud/lib/private/files/config/mountprovidercollection.php',
    'line' => 71,
    'function' => 'array_map',
  ),
  9 => 
  array (
    'file' => '/var/www/owncloud/lib/private/files/filesystem.php',
    'line' => 428,
    'function' => 'getMountsForUser',
    'class' => 'OC\\\\Files\\\\Config\\\\MountProviderCollection',
    'type' => '->',
  ),
  10 => 
  array (
    'file' => '/var/www/owncloud/lib/private/avatarmanager.php',
    'line' => 83,
    'function' => 'initMountPoints',
    'class' => 'OC\\\\Files\\\\Filesystem',
    'type' => '::',
  ),
  11 => 
  array (
    'file' => '/var/www/owncloud/lib/private/user/user.php',
    'line' => 380,
    'function' => 'getAvatar',
    'class' => 'OC\\\\AvatarManager',
    'type' => '->',
  ),
  12 => 
  array (
    'file' => '/var/www/owncloud/apps/dav/lib/carddav/converter.php',
    'line' => 164,
    'function' => 'getAvatarImage',
    'class' => 'OC\\\\User\\\\User',
    'type' => '->',
  ),
  13 => 
  array (
    'file' => '/var/www/owncloud/apps/dav/lib/carddav/converter.php',
    'line' => 75,
    'function' => 'getAvatarImage',
    'class' => 'OCA\\\\DAV\\\\CardDAV\\\\Converter',
    'type' => '->',
  ),
  14 => 
  array (
    'file' => '/var/www/owncloud/apps/dav/lib/carddav/syncservice.php',
    'line' => 228,
    'function' => 'updateCard',
    'class' => 'OCA\\\\DAV\\\\CardDAV\\\\Converter',
    'type' => '->',
  ),
  15 => 
  array (
    'file' => '/var/www/owncloud/apps/dav/lib/hookmanager.php',
    'line' => 98,
    'function' => 'updateUser',
    'class' => 'OCA\\\\DAV\\\\CardDAV\\\\SyncService',
    'type' => '->',
  ),
  16 => 
  array (
    'file' => '/var/www/owncloud/lib/private/hook.php',
    'line' => 105,
    'function' => 'changeUser',
    'class' => 'OCA\\\\DAV\\\\HookManager',
    'type' => '->',
  ),
  17 => 
  array (
    'file' => '/var/www/owncloud/lib/private/server.php',
    'line' => 242,
    'function' => 'emit',
    'class' => 'OC_Hook',
    'type' => '::',
  ),
  18 => 
  array (
    'function' => 'OC\\\\{closure}',
    'class' => 'OC\\\\Server',
    'type' => '->',
  ),
  19 => 
  array (
    'file' => '/var/www/owncloud/lib/private/hooks/emittertrait.php',
    'line' => 98,
    'function' => 'call_user_func_array',
  ),
  20 => 
  array (
    'file' => '/var/www/owncloud/lib/private/hooks/publicemitter.php',
    'line' => 32,
    'function' => 'emit',
    'class' => 'OC\\\\Hooks\\\\BasicEmitter',
    'type' => '->',
  ),
  21 => 
  array (
    'file' => '/var/www/owncloud/lib/private/user/user.php',
    'line' => 417,
    'function' => 'emit',
    'class' => 'OC\\\\Hooks\\\\PublicEmitter',
    'type' => '->',
  ),
  22 => 
  array (
    'file' => '/var/www/owncloud/lib/private/user/user.php',
    'line' => 163,
    'function' => 'triggerChange',
    'class' => 'OC\\\\User\\\\User',
    'type' => '->',
  ),
  23 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/lib/user/user.php',
    'line' => 431,
    'function' => 'setEMailAddress',
    'class' => 'OC\\\\User\\\\User',
    'type' => '->',
  ),
  24 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/lib/user/user.php',
    'line' => 167,
    'function' => 'updateEmail',
    'class' => 'OCA\\\\user_ldap\\\\lib\\\\user\\\\User',
    'type' => '->',
  ),
  25 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/lib/access.php',
    'line' => 732,
    'function' => 'processAttributes',
    'class' => 'OCA\\\\user_ldap\\\\lib\\\\user\\\\User',
    'type' => '->',
  ),
  26 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/lib/access.php',
    'line' => 705,
    'function' => 'batchApplyUserAttributes',
    'class' => 'OCA\\\\user_ldap\\\\lib\\\\Access',
    'type' => '->',
  ),
  27 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/lib/access.php',
    'line' => 678,
    'function' => 'fetchListOfUsers',
    'class' => 'OCA\\\\user_ldap\\\\lib\\\\Access',
    'type' => '->',
  ),
  28 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/user_ldap.php',
    'line' => 103,
    'function' => 'fetchUsersByLoginName',
    'class' => 'OCA\\\\user_ldap\\\\lib\\\\Access',
    'type' => '->',
  ),
  29 => 
  array (
    'file' => '/var/www/owncloud/apps/user_ldap/user_ldap.php',
    'line' => 120,
    'function' => 'getLDAPUserByLoginName',
    'class' => 'OCA\\\\user_ldap\\\\USER_LDAP',
    'type' => '->',
  ),
  30 => 
  array (
    'file' => '/var/www/owncloud/lib/private/user/manager.php',
    'line' => 183,
    'function' => 'checkPassword',
    'class' => 'OCA\\\\user_ldap\\\\USER_LDAP',
    'type' => '->',
  ),
  31 => 
  array (
    'file' => '/var/www/owncloud/lib/private/user/session.php',
    'line' => 219,
    'function' => 'checkPassword',
    'class' => 'OC\\\\User\\\\Manager',
    'type' => '->',
  ),
  32 => 
  array (
    'file' => '/var/www/owncloud/lib/private/user.php',
    'line' => 162,
    'function' => 'login',
    'class' => 'OC\\\\User\\\\Session',
    'type' => '->',
  ),
  33 => 
  array (
    'file' => '/var/www/owncloud/lib/base.php',
    'line' => 1073,
    'function' => 'login',
    'class' => 'OC_User',
    'type' => '::',
  ),
  34 => 
  array (
    'file' => '/var/www/owncloud/lib/base.php',
    'line' => 969,
    'function' => 'tryFormLogin',
    'class' => 'OC',
    'type' => '::',
  ),
  35 => 
  array (
    'file' => '/var/www/owncloud/lib/base.php',
    'line' => 931,
    'function' => 'handleLogin',
    'class' => 'OC',
    'type' => '::',
  ),
  36 => 
  array (
    'file' => '/var/www/owncloud/index.php',
    'line' => 39,
    'function' => 'handleRequest',
    'class' => 'OC',
    'type' => '::',
  ),
)

@PVince81
Copy link
Contributor

PVince81 commented Jun 1, 2016

Hmm, I still don't get why the login doesn't work. At login time there's code that would prepare the user's home folder and copy the skeleton files there. Maybe something else interefered and prevented that logic to run.

As for the part about the cron job for a user who never logged in, that one is likely a bug.

@owncloud/ldap @icewind1991

@jakob42
Copy link

jakob42 commented Jun 1, 2016

If by "something" you mean an app, at that point I've had only used packaged apps, no externals at all.

@marcandreu
Copy link

@PVince81 , Does it create not only the skeleton files for user A, but also any other previously shared folder from user B (shared with that new user A that never logged in)? I think the problem is that. I had no problems when a user logged in and had no shared folder into him, and, another user was not able to enter and the only difference was that somebody shared a folder. Did testing with a 3rd user, and I was able to reproduce the problem; A shared folder is not automatically created or some problem related with new users and shared folders.

@PVince81
Copy link
Contributor

PVince81 commented Jun 2, 2016

@marcandreu received shared folders are not really created, but rather mounted. They only exist on the virtual OC filesystem that you see when browsing in the web UI.

But as you say, maybe there's a bug in the code path that mounts those shared folders. @owncloud/sharing

@marcandreu
Copy link

@PVince81 To help a bit to clear it out; i'm able to reproduce de error if the folder 'share_folder' => '/**folder_name**' inside the config.php is no created manualy for a new user. OC does not create it automatically. That /folder_name i'm refering is not a mount point but a phisical folder in the server. Is a way to keep all incomming share folders inside that folder. I guess all incomming files/folders are mounted inside of it as you mention. Maybe OC cannot create the mount if the parent folder does not exist and that's the problem, OC didnt create the parent folder even if exist in the skeleton under certain circumstances.

But I was able to reproduce the same error when I had no 'share_folder' => '/**folder_name**', and everything when to the root of the user home. But didnt do further testing with that other settup. So the problem doesnt only seem related with the configuration of config.php, but also something related with; ldap settup+new_users+previous incomming shared folders before first time loggin.

@michaelstingl
Copy link

michaelstingl commented Jun 8, 2016

I can confirm, workaround (#24423 (comment)) from @marcandreu helps. If "share_folder" is configured in the config.php, it needs to be created too. Thanks!

00005595

@steffen-moser
Copy link

I can confirm the problem with LDAP users who have never logged in before and who got access to a shared folder in ownCloud-9.0.2 on Apache-2.4.12, PHP-5.6.8 and Oracle Solaris 11.3. It doesn't matter whether the folder access is giving indirectly by an LDAP group membership or by sharing a folder with the specified user directly. Removing the 'share_folder' => '/Shared' relation in config.php also does not help.

@PVince81
Copy link
Contributor

Do I understand it well that these users get access to the share through a group share ?

@PVince81
Copy link
Contributor

Steps:

  1. Setup LDAP with users and group memberships (I used the "memberUid" mode)
  2. Setup OC with LDAP
  3. As OC admin, create a folder "test"
  4. Edit config.php and set "share_folder" to "/received_shares"
  5. Share "test" with a group "Box10"
  6. Login as "zombie10" (who is in group "Box10" and never logged in before

The folder "received_shares" is properly created at login time.

This is with openLDAP and the v9.0.2 git version.

Will retry with a tarball version since it comes with more apps, in case there is a side effect...

@steffen-moser
Copy link

We did the following steps using the released 9.0.2:

  1. We installed ownCloud-9.0.2 on a Solaris 11.3 zone. The zone runs Apache 2.4.12, PHP-5.6.8 and MySQL-5.6.21.
  2. A local "admin" user has been created after installation. We configured ownCloud to access our OpenLDAP server (OpenLDAP 2.4.30) which runs on a different host.
  3. We created a set of users in our LDAP. These users were added to an LDAP group called "bookauthors" (for example).
  4. Using the local "admin" account, we created a folder (e.g. "book").
  5. Using the local "admin" account, we shared the folder to all users who belong to the LDAP group "bookauthors".
  6. When one of the users created in step 3 log in, they see a blank page (in Firefox) or receive an internal server error (500) in Chrome. The server logs:

{"reqId":"wJOk0g6DIQ0NogTA0ovw","remoteAddr":"134.60.72.139","app":"PHP","message":"Call to a member function file_exists() on null at /srv/www/vhosts/netzwerk-offene-hochschulen.saps.uni-ulm.de/htdocs_ssl/owncloud/lib/private/files/filesystem.php#696","level":3,"time":"2016-06-16T14:27:13+00:00","method":"POST","url":"/owncloud/","user":"--"}

After being stuck here, we tried an alternative way:

Steps 1 and 2 are the same.
3. We created a set of users in our LDAP and didn't assign them to any special group (only to their primary group "students")
4. Using the local "admin" account, we created a folder (e.g. "book").
5. Using the local "admin" account, we shared the folder manually to all users whose accounts were created in step 3 - this time without referencing any LDAP group.
6. The same happens.

The problem can be prevented when doing the following work-around:
3. We created a set of users in our LDAP. These users were added to an LDAP group called "bookauthors" (for example).
3.1 We log in manually to ownCloud with each of these freshly created users.
4. Using the local "admin" account, we created a folder (e.g. "book").
5. Using the local "admin" account, we shared the folder to all users who belong to the LDAP group "bookauthors".

So the problem only occurs if a user has to receive a share while he/she logs in to ownCloud for his/her very first time. It is especially independent from the way of receiving the share - via a group membership or directly (by making a directory accessible on a by-user base).

The problem has been a bit more complex at first, because in the beginning our users didn't see any LDAP groups at all in ownCloud- This was due to the fact that the attribute "useMemberOfToDetectMembership" has been active in the LDAP settings after the installation of ownCloud. As our OpenLDAP server does not support the MemberOf-functionality (due to the usage of posixAccount), I had to disable this function by setting it to "0". As some of users already logged in when this attribute was still "1", they didn't experience the problem. Only the users who were created (and did their first log in) after setting the "useMemberOfToDetectMembership" to "0" ran into the problem.

Removing 'share_folder' => '/Shared' from config.php didn't help so far.

@PVince81
Copy link
Contributor

@steffen-moser thanks for the details.

So far I wasn't able to reproduce it but also my environement doesn't involve "useMemberOfToDetectMembership". I used the "memberUid" for group memberships. I'm not sure whether/how/why this would cause newly created user to not receive the shares.

What if a user is in a group and doesn't receive any group shares ? I guess such new user can log in properly ?

@PVince81
Copy link
Contributor

Here is my config:

 user_ldap            | cleanUpJobOffset                  | 0                                           |
| user_ldap            | enabled                           | yes                                         |
| user_ldap            | has_memberof_filter_support       |                                             |
| user_ldap            | home_folder_naming_rule           |                                             |
| user_ldap            | installed_version                 | 0.8.0                                       |
| user_ldap            | last_jpegPhoto_lookup             | 0                                           |
| user_ldap            | ldap_agent_password               | YWRtaW4=                                    |
| user_ldap            | ldap_attributes_for_group_search  |                                             |
| user_ldap            | ldap_attributes_for_user_search   |                                             |
| user_ldap            | ldap_backup_host                  |                                             |
| user_ldap            | ldap_backup_port                  |                                             |
| user_ldap            | ldap_base                         | dc=owncloud,dc=com                          |
| user_ldap            | ldap_base_groups                  | dc=owncloud,dc=com                          |
| user_ldap            | ldap_base_users                   | dc=owncloud,dc=com                          |
| user_ldap            | ldap_cache_ttl                    | 600                                         |
| user_ldap            | ldap_configuration_active         | 1                                           |
| user_ldap            | ldap_display_name                 | displayname                                 |
| user_ldap            | ldap_dn                           | cn=admin,dc=owncloud,dc=com                 |
| user_ldap            | ldap_dynamic_group_member_url     |                                             |
| user_ldap            | ldap_email_attr                   |                                             |
| user_ldap            | ldap_experienced_admin            | 0                                           |
| user_ldap            | ldap_expert_username_attr         |                                             |
| user_ldap            | ldap_expert_uuid_group_attr       |                                             |
| user_ldap            | ldap_expert_uuid_user_attr        |                                             |
| user_ldap            | ldap_group_display_name           | cn                                          |
| user_ldap            | ldap_group_filter                 | (&(|(objectclass=posixGroup)))              |
| user_ldap            | ldap_group_filter_mode            | 0                                           |
| user_ldap            | ldap_group_member_assoc_attribute | memberUid                                   |
| user_ldap            | ldap_groupfilter_groups           |                                             |
| user_ldap            | ldap_groupfilter_objectclass      | posixGroup                                  |
| user_ldap            | ldap_host                         | localhost                                   |
| user_ldap            | ldap_login_filter                 | (&(|(objectclass=inetOrgPerson))(uid=%uid)) |
| user_ldap            | ldap_login_filter_mode            | 0                                           |
| user_ldap            | ldap_loginfilter_attributes       |                                             |
| user_ldap            | ldap_loginfilter_email            | 0                                           |
| user_ldap            | ldap_loginfilter_username         | 1                                           |
| user_ldap            | ldap_nested_groups                | 0                                           |
| user_ldap            | ldap_override_main_server         |                                             |
| user_ldap            | ldap_paging_size                  | 500                                         |
| user_ldap            | ldap_port                         | 389                                         |
| user_ldap            | ldap_quota_attr                   |                                             |
| user_ldap            | ldap_quota_def                    |                                             |
| user_ldap            | ldap_tls                          | 0                                           |
| user_ldap            | ldap_turn_off_cert_check          | 0                                           |
| user_ldap            | ldap_user_display_name_2          |                                             |
| user_ldap            | ldap_user_filter_mode             | 0                                           |
| user_ldap            | ldap_userfilter_groups            |                                             |
| user_ldap            | ldap_userfilter_objectclass       | inetOrgPerson                               |
| user_ldap            | ldap_userlist_filter              | (|(objectclass=inetOrgPerson))              |
| user_ldap            | types                             | authentication                              |
| user_ldap            | use_memberof_to_detect_membership | 1                                           |

@steffen-moser I guess you're also not using the "home_folder_naming_rule" attribute ?

@PVince81
Copy link
Contributor

Tried again with a default 9.0.2 enterprise tarball with the same server and settings.
Still cannot reproduce the issue.

I see that @thmcon had use_memberof_to_detect_membership also set to 1, so it's probably not related to the issue.

But it is also likely that everyone here is talking about different issues with similar symptoms.

So far it seems there are two cases:

  1. is related to the "share_folder" value
  2. is not related to "share_folder" and could be unrelated to shares altogether

@PVince81
Copy link
Contributor

Looking at @patrakov's stack trace here #24423 (comment) shows that the email address is being read from LDAP and that's the moment the "problem" occurs. I see that this attribute is also set for @thmcon.

Will try with email address now.

@PVince81
Copy link
Contributor

Nope, even with the "mail" attribute I don't get any errors.

However so far I noticed that even if I have "share_folder" in config.php, that folder is never created and the existing share simply appear in the root of the newly logged in user.

And then I tried sharing a NEW folder after changing config.php => 💣

Will try to gather more detailed steps now.

@PVince81
Copy link
Contributor

Steps on v9.0.2:

  1. Setup LDAP users with group memberships with the docker from https://github.com/owncloud/administration/tree/master/ldap-testing and populate with zombie users and groups
  2. Add some zombies in the group "Box10" using the "memberUid" attribute
  3. Setup OC with LDAP
  4. In the "Groups" tab select "posixGroup"
  5. In the "Advanced" tab make sure that "memberUid" is selected for group memberships
  6. Under "Special attributes" add "mail" for the email field
  7. Edit config.php and set "share_folder" to "/received_shares"
  8. As admin, create a folder "test"
  9. Share "test" with the group "Box10"
  10. Login as one of the zombies from Box10 who never logged in
  11. 💣
{"reqId":"rQrVGiCm97CtLDRm6sxL","remoteAddr":"127.0.0.1","app":"PHP","message":"Call to a member function file_exists() on a non-object at \/srv\/www\/htdocs\/owncloud\/lib\/private\/files\/filesystem.php#696","level":3,"time":"2016-06-16T15:37:40+00:00","method":"POST","url":"\/owncloud\/","user":"--"}

Weird stuff: somehow it seems the attributes in the advanced tab were correct the first time but when I went back later then changed back to default. Had to re-set them to make group memberships work.

@PVince81
Copy link
Contributor

In general, the stack trace from #24423 (comment) already shows a lot.

What happens:

  1. LDAP tries to update the email address for that new user
  2. The update of the user object triggers an event
  3. The system address book (carddav) reacts on this event
  4. The system address book tries to get the user's avatar
  5. Since the avatar is usually stored on disk, this triggers a filesystem setup
  6. Filesystem setup fails because it's too early

CC @rullzer @DeepDiver1975 for address book / avatar stuff

Now either we need to have the FS ready earlier or try and skip triggering the user change event when it's the first time login.

@PVince81
Copy link
Contributor

  1. Filesystem tries to setup shares
  2. Share system finds that the folder "/received_shares" doesn't exist
  3. Share system tries to create the folder using the global Filesystem object which isn't initialized 💣

CC @icewind1991

I guess this whole thing might be missing an earlier setupFS.
The weird thing is that all this chain is caused by checkPassword which accesses the user object which then triggers LDAP user fetching.

@PVince81
Copy link
Contributor

Tried adding setupFS($userId) in AvatarManager. Now the user can login and the shared folder appears, but the skeleton files are missing...

Ideally I think that the email's "user update" hook should be deferred to a later moment. Not sure if LDAP will sync the user's email again after the next TTL round.

@PVince81
Copy link
Contributor

This is the place where Filesystem isn't initialized: https://github.com/owncloud/core/blob/v9.0.2/apps/files_sharing/lib/helper.php#L311

Compact stack trace:

0  OCA\Files_Sharing\Helper::getShareFolder() /srv/www/htdocs/owncloud/apps/files_sharing/lib/helper.php:308
1  OCA\Files_Sharing\SharedMount->verifyMountPoint() /srv/www/htdocs/owncloud/apps/files_sharing/lib/sharedmount.php:78
2  OCA\Files_Sharing\SharedMount->__construct() /srv/www/htdocs/owncloud/apps/files_sharing/lib/sharedmount.php:60
3  OCA\Files_Sharing\MountProvider->OCA\Files_Sharing\{closure}() /srv/www/htdocs/owncloud/apps/files_sharing/lib/mountprovider.php:68
4  array_map()     /srv/www/htdocs/owncloud/apps/files_sharing/lib/mountprovider.php:69
5  OCA\Files_Sharing\MountProvider->getMountsForUser() /srv/www/htdocs/owncloud/apps/files_sharing/lib/mountprovider.php:69
6  OC\Files\Config\MountProviderCollection->OC\Files\Config\{closure}() /srv/www/htdocs/owncloud/lib/private/files/config/mountprovidercollection.php:70
7  array_map()     /srv/www/htdocs/owncloud/lib/private/files/config/mountprovidercollection.php:71
8  OC\Files\Config\MountProviderCollection->getMountsForUser() /srv/www/htdocs/owncloud/lib/private/files/config/mountprovidercollection.php:71
9  OC\Files\Filesystem::initMountPoints() /srv/www/htdocs/owncloud/lib/private/files/filesystem.php:431
10 OC\AvatarManager->getAvatar() /srv/www/htdocs/owncloud/lib/private/avatarmanager.php:90
11 OC\User\User->getAvatarImage() /srv/www/htdocs/owncloud/lib/private/user/user.php:380
12 OCA\DAV\CardDAV\Converter->getAvatarImage() /srv/www/htdocs/owncloud/apps/dav/lib/carddav/converter.php:164
13 OCA\DAV\CardDAV\Converter->createCardFromUser() /srv/www/htdocs/owncloud/apps/dav/lib/carddav/converter.php:42
14 OCA\DAV\CardDAV\SyncService->updateUser() /srv/www/htdocs/owncloud/apps/dav/lib/carddav/syncservice.php:224
15 OCA\DAV\HookManager->changeUser() /srv/www/htdocs/owncloud/apps/dav/lib/hookmanager.php:99
16 call_user_func:{/srv/www/htdocs/owncloud/lib/private/hook.php:105}() /srv/www/htdocs/owncloud/lib/private/hook.php:105
17 OC_Hook::emit() /srv/www/htdocs/owncloud/lib/private/hook.php:105
18 OC\Server->OC\{closure}() /srv/www/htdocs/owncloud/lib/private/server.php:244
19 call_user_func_array:{/srv/www/htdocs/owncloud/lib/private/hooks/emittertrait.php:98}() /srv/www/htdocs/owncloud/lib/private/hooks/emittertrait.php:98
20 OC\Hooks\BasicEmitter->emit() /srv/www/htdocs/owncloud/lib/private/hooks/emittertrait.php:98
21 OC\Hooks\PublicEmitter->emit() /srv/www/htdocs/owncloud/lib/private/hooks/publicemitter.php:32
22 OC\User\User->triggerChange() /srv/www/htdocs/owncloud/lib/private/user/user.php:417
23 OC\User\User->setEMailAddress() /srv/www/htdocs/owncloud/lib/private/user/user.php:163
24 OCA\user_ldap\lib\user\User->updateEmail() /srv/www/htdocs/owncloud/apps/user_ldap/lib/user/user.php:436
25 OCA\user_ldap\lib\user\User->processAttributes() /srv/www/htdocs/owncloud/apps/user_ldap/lib/user/user.php:167
26 OCA\user_ldap\lib\Access->batchApplyUserAttributes() /srv/www/htdocs/owncloud/apps/user_ldap/lib/access.php:733
27 OCA\user_ldap\lib\Access->fetchListOfUsers() /srv/www/htdocs/owncloud/apps/user_ldap/lib/access.php:706
28 OCA\user_ldap\lib\Access->fetchUsersByLoginName() /srv/www/htdocs/owncloud/apps/user_ldap/lib/access.php:679
29 OCA\user_ldap\USER_LDAP->getLDAPUserByLoginName() /srv/www/htdocs/owncloud/apps/user_ldap/user_ldap.php:103
30 OCA\user_ldap\USER_LDAP->checkPassword() /srv/www/htdocs/owncloud/apps/user_ldap/user_ldap.php:120
31 OC\User\Manager->checkPassword() /srv/www/htdocs/owncloud/lib/private/user/manager.php:184
32 OC\User\Session->login() /srv/www/htdocs/owncloud/lib/private/user/session.php:219
33 OC_User::login() /srv/www/htdocs/owncloud/lib/private/user.php:162
34 OC::tryFormLogin() /srv/www/htdocs/owncloud/lib/base.php:1082
35 OC::handleLogin() /srv/www/htdocs/owncloud/lib/base.php:978
36 OC::handleRequest() /srv/www/htdocs/owncloud/lib/base.php:940
37 {main}          /srv/www/htdocs/owncloud/index.php:39

@PVince81
Copy link
Contributor

Here's a quick fix that makes login work again: #25150
However it will also not properly copy the skeleton files.

This fix makes it use a properly initialized filesystem View object instead of relying of the non-initialized static one.

We still need a better fix, likely one that doesn't trigger the whole "user update" event.

@wpoely86
Copy link

@PVince81 fix in #25150 works for me.

@steffen-moser
Copy link

@PVince81 The fix #25150 also solves the problem for me. As already stated, the skeleton files are not copied in this case, but we can live with that for now. Thank you very much for the fast fix!

@PVince81
Copy link
Contributor

Thanks for the feedback, glad to hear the workaround worked.

@PVince81
Copy link
Contributor

The quickfix will be released as part of 9.0.3.
I'll close this issue and have raised #25212 to look into the skeleton copying issue. Please follow up there.

@lock
Copy link

lock bot commented Aug 4, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Aug 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests