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

Document symfony events #311

Closed
sharidas opened this issue Jan 25, 2018 · 14 comments
Closed

Document symfony events #311

sharidas opened this issue Jan 25, 2018 · 14 comments
Labels

Comments

@sharidas
Copy link

Based on the hooks available from : https://doc.owncloud.org/server/10.0/developer_manual/app/fundamentals/hooks.html

we have moved a bit further. Some of the hooks got replaced with symfony events.

@sharidas
Copy link
Author

I will update the details about the events which got replaced here.

@PVince81
Copy link
Contributor

@sharidas can you post the list of new hooks here as you touch them for future documentation ? Seems 10.0.8 will come with quite a lot. Not only the changed ones but also the very new ones like config hooks.

@settermjd
Copy link
Contributor

ping @sharidas.

@sharidas
Copy link
Author

sharidas commented Apr 6, 2018

The hooks present as of date in core are as follows:

@PVince81
Copy link
Contributor

is it up to date ? we also added group admins

@PVince81
Copy link
Contributor

we should also list the new ones, not only the ones that replace old ones

netbsd-srcmastr referenced this issue in NetBSD/pkgsrc Jun 22, 2018
Changelog:
Changes in 10.0.8

Dear ownCloud administrator, please find below the changes and known issues in ownCloud Server 10.0.8 that need your attention. You can also read the full ownCloud Server changelog for further details on what has changed.
PHP 5.6 deprecation

PHP 5.6/7.0 active support has ended on January 19th 2017 / December 3rd 2017 and security support will be dropped by the end of 2018. Many libraries used by ownCloud (including the QA-Suite PHPUnit) will therefore not be maintained actively anymore which forces ownCloud to drop support in one of the next minor server versions as well. Please make sure to upgrade to PHP 7.1 as soon as possible. See the system requirements in the ownCloud documentation.
Personal note for public link mail notification

One of the usability enhancements of ownCloud Server 10.0.8 is the possibility for users to add a personal note when sending public links via mail. When using customized mail templates it is necessary to either adapt the shipped original template to the customizations or to add the code block for the personal note to customized templates in order to display the personal note in the mail notifications.
New mail notifications feature

ownCloud Server 10.0.8 introduces a new extensible notification framework. Apart from technical changes under the hood the Notifications app can now also send mails for all notifications that previously were only displayed within the web interfaces (notification bell) or on the Desktop client (notifications API) like incoming federated share or Custom Group notifications, for example. In the “General” settings section users can configure whether they want to receive mails for all notifications, only for those that require an action or decide not to get notifications via mail (by default users will only receive notifications when an action is required).
LDAP-related improvements

    When disabling or deleting user accounts in LDAP, the administrator can choose to either delete or disable respective accounts in ownCloud when executing occ user:sync (-m, --missing-account-action=MISSING-ACCOUNT-ACTION). User accounts that are disabled in ownCloud can now be re-enabled automatically when running occ user:sync if they are enabled in LDAP. When this behavior is desired administrators just need to add the -r, --re-enable option to their cron jobs or when manually executing occ user:sync.
    Furthermore it is now possible to execute occ user:sync only for single (-u, --uid=UID) or seen (-s, --seenOnly) users (users that are present in the database and have logged in at least once). These new options provide more granularity for administrators in terms of managing occ user:sync performance.
    Another notable change in behavior of occ user:sync is that administrators now have to explicitly specify the option -c, --showCount to display the number of users to be synchronized.

New events for audit logging

New events have been added to be used for audit logging, among others. These include configuration changes by administrators and users, file comments (add/edit/delete) and updating existing public links. When logs are forwarded to external analyzers like Splunk, administrators can check to add the new events. The latest version of the Auditing extension (admin_audit) is required.
New command to verify and repair file checksums

With ownCloud 10 file integrity checking by computing and matching checksums has been introduced to ensure that transferred files arrive at their target in the exact state as their origin. In some rare cases wrong checksums can be written to the database leading to synchronization issues with e.g. the Desktop Client. To mitigate such situations a new command occ files:checksums:verify has been introduced. The command recalculates checksums either for all files of a user or for files within a specified path, and compares them with the values in the database. Naturally the command also offers an option to repair incorrect checksum values (-r, --repair). Please check the available options by executing occ files:checksums:verify --help. Note: Executing this command might take some time depending on the file count.
New config setting to specify minimum characters for sharing autocomplete

For security reasons the default value for minimum characters to trigger the sharing autocomplete mechanism has been set to “4” (previously it was set to “2”). This is to prevent people from easily downloading lots of email addresses or user names by requesting their first letters through the API. As it is a trade-off between security and usability for some scenarios this high security level might not be desirable. Therefore the value now is configurable via the config.php option 'user.search_min_length' => 4,. Please check which value fits your needs best.
New option to granularly configure public link password enforcement

With ownCloud 10 the “File Drop” feature has been merged with public link permissions. This kind of public link does not give recipients access to any content, but it gives them the possibility to “drop files”. As a result, it might not always be desirable to enforce password protection for such shares. Given that, passwords for public links can now be enforced based on permissions (read-only, read & write, upload only/File Drop). Please check the administration settings “Sharing” section and configure as desired.
New option to exclude apps from integrity check

By verifying signature files the integrity check ensures that the code running in an ownCloud instance has not been altered by third parties. Naturally this check can only be successful for code that has been obtained from official ownCloud sources. When providing custom apps (like theme apps) that do not have a signature, the integrity check will fail and notify the administrator. These apps can now be excluded from the integrity check by using the config.php option 'integrity.ignore.missing.app.signature' => ['app_id1', 'app_id2', 'app_id3'],. See config.sample.php for more information.
New occ command to modify user details

It is now possible to modify user details like display names or mail addresses via the command occ user:modify. Please append --help for more information.
occ files:scan can now be executed for groups

Apart from using the occ files:scan command for single users and whole instances it can now be executed for groups using -g, --groups=GROUPS. Please append --help for more information.
New configurable default format for syslog

When using syslog as the log type ('log_type' => 'syslog', in config.php) the default format hahe new format and config.sample.php on how to change it.
New config option to enable fallback to HTTP for federated shares

For security reasons federated sharing (sharing between different ownCloud instances) strictly requires HTTPS (SSL/TLS). When this g.federation.allowHttpFallback' => false, to true in config.php.
Migration related to auth_tokens (app passwords)

Upgrading to 10.0.8 includes migrations related to auth_tokens (app passwords). When users have created app passwords as separate passwords l autocomplete for public link share dialog

When the “Sharing” settings option Allow users to send mail notifications for shared files for public links is enabled, users can send public links via mail from within the web interface. The behavior of the autocomplete when entering mail addresses in the public link share dialog has been changed. Previously the autocomplete queried for local users, users from federated address books and contacts from CardDAV/Contacts App. As public links are not intended for sharing between ownCloud users (local/federated), those have been removed. Contacts synchronized via CardDAV or created in the Contacts app will still appear as suggestions.
Notifications sent by occ can now include links

The command occ notifications:generate can be used to send notifications to individual users or groups. With 10.0.8 it is also capable of including links to such notifications using the -l, --link=LINK option. Please append --help for more information. There is also Announcementcenter to conduct such tasks from the web interface but it is currently limited to send notifications to all users. For now administrators can use the occ command if more granularity is required.
Global option for CORS domains

For security reasons ownCloud has a Same-Origin-Policy that prevents requests to ownCloud resources from other domains than the domain the backend server is hosted on. If ownCloud resources should be accessible from other domains, e.g. for a separate web frontend operated on a different domain, administrators can now globally specify policy exceptions via CORS (Cross-Origin Resource Sharing) using 'cors.allowed-domains' in config.php. Please check config.sample.php for more information.
Solved known issues

    Bogus “Login failed” log entries have been removed (see 10.0.7 known issues)
    The Provisioning API can now properly set default or zero quota
    User quota settings can be queried through Provisioning API
    A regression preventing a user from setting their e-mail address in the settings page has been fixed
    File deletion as a guest user works correctly (trash bin permissions are checked correctly)

Known issues

    Issues with multiple theme apps and Mail Template Editor

As of ownCloud Server 10.0.5 it is only possible to have one theme app enabled simultaneously. When a theme app is enabled and the administrator attempts to enable a second one this will result in an error. However, when also having the Mail Template Editor enabled in this scenario the administrators “General” settings section will be displayed incorrectly. As a remedy administrators can either uninstall the second theme app or disable the Mail Template Editor app.

    occ transfer:ownership does not transfer public link shares if they were created by the target user (reshare).

For developers

    The global JS variable “oc_current_user” was removed. Please use the public method “OC.getCurrentUser()” instead.
    Lots of new Symfony events have been added for various user actions, see changelog for details. Documentation ticket: <https://github.com/owncloud/documentation/issues/3738>`_
    When requesting a private link there is a new HTTP response header “Webdav-Location” that contains the Webdav path to the requested file while the “Location” still points at the frontend URL for viewing the file.

Changes in 10.0.7

ownCloud Server 10.0.7 is a hotfix follow-up release that takes care of an issue regarding OAuth authentication.

Please consider the ownCloud Server 10.0.5 release notes.
Known issues

    When using application passwords, log entries related to “Login Failed” will appear and can be ignored. For people using fail2ban or other account locking tools based on log parsing, please apply this patch with patch -p1 < 50c78a4bf4c2ab4194f40111b8a34b7e9cc17a14.patch (original pull request here).

Changes in 10.0.6

ownCloud Server 10.0.6 is a hotfix follow-up release that takes care of an issue during the build process (owncloud/core#30265). Please consider the ownCloud Server 10.0.5 release notes.
Changes in 10.0.5

Dear ownCloud administrator, please find below the changes and known issues in ownCloud Server 10.0.5 that need your attention. You can also read the full ownCloud Server changelog for further details on what has changed.
Technology preview for PHP 7.2 support

ownCloud catches up with new web technologies. This has mainly been introduced for the open-source community to test and give feedback. PHP 7.2 is not yet supported nor recommended for production scenarios. ownCloud is going to fully support PHP 7.2 with the next major release.
php-intl now is a hard requirement

Please make sure to have the PHP extension installed before upgrading.
Changed: Only allow a single active theme app

The theming behavior has been changed so that only a single theme can be active concurrently. This change ensures that themes can not interfere in any way (e.g., override default theming in an arbitrary order). Please make sure to have the desired theme enabled after upgrading.
Removed old Dropbox external storage backend (Dropbox API v1)

Please switch to the new External Storage: Dropbox app (https://marketplace.owncloud.com/apps/files_external_dropbox) with Dropbox API v2 support to continue providing Dropbox external storages to your users.
Fixed: Only set CORS headers on WebDAV endpoint when Origin header is specified

ownCloud Server 10.0.4 known issue is resolved.
Fixes and improvements for the Mail Template Editor

    Known issues are resolved: Mail Template Editor works again, got support for app themes and additional templates were added for customization.
    Mail Template Editor is still bundled with ownCloud Server but will soon be released as a separate app to ownCloud Marketplace.
    Changelog: https://github.com/owncloud/templateeditor/blob/release/0.2.0/CHANGELOG.md

Known issues

    When using application passwords, log entries related to “Login Failed” will appear, please upgrade to 10.0.7 and check the fix mentionned in its release notes.

Changes in 10.0.4¶

Dear ownCloud administrator, please find below the changes and known issues in ownCloud Server 10.0.4 that need your attention. You can also read the full ownCloud Server 10.0.4 changelog for further details on what has changed.
More granular sharing restrictions

The “Restrict users to only share with users in their groups” option, in the Sharing settings, restricts users to only share with groups which they are a member of, while simultaneously prohibiting sharing with single users that do not belong to any of the users’ groups.

To make this more granular, we split this option into two parts and added “Restrict users to only share with groups they are member of”, which differentiates between users and groups. Doing so makes it possible to restrict users from sharing with all users of an installation, limiting them to only being able to share with groups which they are a member of, and vice versa.
Configurable solution for indistinguishable user display names

The ownCloud sharing dialog displays users according to their display name. As users can choose their display name in self-service (which can be disabled in config.php) and display names are not unique, it is possible that a user can’t distinguish sharing results. To cover this case the displayed user identifiers are now configurable. In the Sharing settings administrators can now configure the display of either mail addresses or user ids.
Added “occ files:scan” repair mode to repair filecache inconsistencies

We recommend to use this command when directed to do so in the upgrade process. Please refer to the occ command’s files:scan –repair documentation for more information.
Detailed mode for “occ security:routes”

Administrators can use the output of this command when using a network firewall, to check the appropriateness of configured rules or to get assistance when setting up.
Added mode of operations to differentiate between single-instance or clustered setup

As ownCloud needs to behave differently when operating in a clustered setup versus a single instance setup, the new config.php option operation.mode has been added. It can take one of two values: single-instance and clustered-instance. For example: 'operation.mode' => 'clustered-instance',.

Currently the Market App (ownCloud Marketplace integration) does not support clustered setups and can do harm when used for installing or updating apps. The new config setting prevents this and other actions that are undesired in cluster mode.

When operating in a clustered setup, it is mandatory to set this option. Please check the config_sample_php_parameters documentation for more information.
Added occ dav:cleanup-chunks command to clean up expired uploads

When file uploads are interrupted for any reason, already uploaded file parts (chunks) remain in the underlying storage so that the file upload can resume in a future upload attempt. However, resuming an upload is only possible until the partial upload is expired and deleted, respectively.

To clean up chunks (expire and delete) originating from unfinished uploads, administrators can use this newly introduced command. The default expiry time is two days, but it can be specified as a parameter to the command. It is recommended to configure CRON to execute this background job regularly.

It is not included in the regular ownCloud background jobs so that the administrators have more flexibility in scheduling it. Please check the background jobs configuration documentation for more information.
Administrators can now exclude files from integrity check in config.php¶

When administrators did intentional changes to the ownCloud code they now have the ability to exclude certain files from the integrity checker. Please check “config.sample.php” for the usage of 'integrity.excluded.files'.
Modification time value of files is now 64 bits long

When upgrading to 10.0.4 migrations may increase update duration dependent on number of files.
Updated minimum supported browser versions

Users with outdated browsers might get warnings. See the list of supported browser versions.
Known issues

    When using application passwords, log entries related to “Login Failed” will appear, please upgrade to 10.0.7 and check the fix mentioned in its release notes.

10.0.3 resolved known issues

    SFTP external storages with key pair mode work again
    Added support for MariaDB 10.2.7+
    Encryption panel in admin settings fixed to properly detect current mode after upgrade to ownCloud 10
    Removed double quotes from boolean values in status.php output

Known issues

    Impersonate app 0.1.1 does not work with ownCloud Server 10.0.4. Please update to Impersonate 0.1.2 to be able to use the feature with ownCloud 10.0.4.
    Mounting ownCloud storage via davfs does not work
@PVince81 PVince81 changed the title Hooks which got replaced with symfony events Document symfony events Aug 6, 2018
@PVince81 PVince81 assigned PVince81 and sharidas and unassigned PVince81 Aug 6, 2018
@PVince81
Copy link
Contributor

PVince81 commented Aug 6, 2018

@sharidas I don't think you need to document where they are triggered but more about their names and their arguments, and semantically when they are triggered.

For example:

  • "config_change", triggered before/after an app configuration change, arguments:
    • appId: app id
    • configKey: key
    • ...

If args different in before and after, might need to specify separately.

Then this can be put into a nice table later for the documentation.

There are likely many more new events to add, check the changelogs.

@sharidas
Copy link
Author

sharidas commented Sep 7, 2018

Below is the detailed list of the symfony events triggered by the core:

  • The column Event mapped to old event has
    • old event as ClassName::SignalName. For example OC_FileSystem::read.
    • If multiple old events are there then {ClassName::SignalName, ClassName::SignalName2}
Event Triggered Event mapped to old event When event is triggered Arguments Description about arguments
file.beforecreate/file.aftercreate file.aftercreate -> OC_Filesystem::post_create Folder is created path The path here would provide the absolute path
file.beforeCreate/file.afterCreate Before file or after creation run The run is the current value of run. This variable can be reset by the listener
file.beforeUpdate/file.afterUpdate Before or after file update run The run is the current value of run. This variable can be reset by the listener
file.beforeWrite/file.afterWrite Before or after file being written run The run is the current value of run. This variable can be reset by the listener
file.beforedelete/file.afterdelete Before or after deletion of folder path The path here would provide absolute path
file.beforeread/file.afterread file.afterread -> OC_Filesystem::read Before or after the file being read path The path here would provide absolute path
file.beforecreate/file.aftercreate file.aftercreate -> OC_Filesystem::post_create Triggered during post hook process path The path here would provide absolute path
file.beforeupdate/file.afterupdate file.afterupdate -> OC_Filesystem::update When the file is being updated path The path here would provide absolute path
file.beforedelete/file.afterdelete file.afterdelete -> OC_Filesystem::delete When the file is deleted path The path here would provide absolute path
file.beforerename/file.afterrename file.afterrename -> OC_Filesystem::rename When the file is renamed oldpath, newpath The oldpath, newpath here would provide absolute path
file.beforecopy/file.aftercopy file.aftercopy -> OC_Filesystem::copy When the file is copied oldpath, newpath The oldpath, newpath here would provide absolute path
comment.beforedelete Before the comment is deleted commentId The commentId is the id associated with the comment
comment.afterdelete After deleting the comment commentId, objectId The objectId isthe object id the comment is attached to
comment/beforesave/comment.aftersave Before saving the comment before event is triggered. After saving comment after save is emitted. objectId,commentId,message,status The message is the message saved. status tells the listener whether the comment is created or updated.
comment.beforecreate/comment.aftercreate These events are emitted when a new comment is added objectId,message The message is the message saved.
comment.beforeupdate/comment.afterupdate These events are emitted when a comment is updated. objectId,commentId,message The message is the message saved.
user.beforesetpassword/user.aftersetpassword user.beforesetpassword -> \OC\User::preSetPassword These events are emitted when user password is called to set. user,password,recoveryPassword user is the user object. password is the password to set for the user. recoveryPassword is for the encryption app to reset encryption keys
user.beforelogin/user.afterlogin user.beforelogin -> OC_User::pre_login, user.afterlogin -> OC_User::post_login These events are emitted when user logins. user,uid,password user is the user object. password is the password for the user. uid is the user id.
user.beforelogout/user.afterlogout user.beforelogout -> OC\User::preLogout, user.afterlogout -> OC\User::postLogout These events are emitted when user logout from oC uid uid is empty. It helps to know if the logout action triggered
user.beforelogin user.beforelogin -> OC\User::preLogin Emitted when user logins with username and password loginType,login,uid,_uid,password loginType has hardcoded value password. It tells the type of login method. login and uid is the user id. _uid is going to be deprecated soon. Hence use login
user.afterlogin user.afterlogin -> OC\User::postLogin Emitted when user logins with username and password successfully loginType,user,uid loginType has hardcoded value password. It tells the type of login method. uid is the user id. user is the user object
user.beforelogin Emitted when user logins with token loginType,login,password loginType has hardcoded value token. It tells the type of login method. login is the user id. password is the password for the user
user.afterlogin Emitted when user logins with token successfully loginType,user,login,password loginType has hardcoded value token. It tells the type of login method. user is the user object. login is the user id. password is the password for the user
user.beforelogin Emitted when user logins with apache backend successfully loginType,login,password loginType has hardcoded value apache. It tells the type of login method. login is the user id. password is empty
user.afterlogin Emitted when user logins with apache backend successfully loginType,user,login,password loginType has hardcoded value apache. It tells the type of login method. user is the user object. login is the user id. password is empty
user.loginfailed Triggered when user login is failed user user is the user id. It can also be null.
user.beforecreate Triggered when user is created uid uid is the user id.
user.aftercreate Triggered when user is created uid, password uid is the user id. password is the password for the user.
appconfig.beforesetvalue Triggered when appconfig value is set key, value, app key, value and app are data to be stored in Db
appconfig.aftersetvalue Triggered when appconfig value is set key, value, app, update, oldvalue key, value and app are data to be stored in Db. update is the updated value. oldvalue is the old value.
appconfig.beforedeletevalue Triggered when appconfig key is deleted app, key key and app are data to be deleted from Db
appconfig.afterdeletevalue Triggered when appconfig key is deleted app, key key, and app are data to be deleted from Db.
appconfig.beforedeleteapp Triggered when app keys are deleted from appconfig app app are data to be deleted from Db
appconfig.afterdeleteapp Triggered when app keys are deleted from appconfig app app are data to be deleted from Db.
config.beforesetvalue Triggered when config key value is set key, value key and value are data to be stored in the config.php
``config.aftersetvalue` Triggered when config key value is set key, value, update, oldvalue key and value are data to be stored in the config.php. update will let the listener know if the value is an update or not ( boolean value true/false), oldvalue is the previous value of the key
config.beforedeletevalue Triggered when a key is deleted from config key, value key and value are data to be deleted in the config.php
config.afterdeletevalue Triggered when a key is deleted from config key, value key and value are data to be deleted in the config.php.
share.beforeaccept Triggered when the share is accepted share share is the share object to be updated.
share.beforereject Triggered when the share is rejected share share is the share object to be updated.
share.afteraccept Triggered when the share is accepted share share is the share object to be updated.
share.afterreject Triggered when the share is rejected share share is the share object to be updated.
share.sendmail Triggered when an email is sent for public link link, to, cc, bcc link is the public link created. to, cc and bcc are the recipients to recieve the email after creating the link
share.linkaccess Triggered when a public link shared is accessed shareObject, errorCode, errorMessage shareObject is the link share.
file.beforecreate/file.aftercreate Triggered when a file is created path path is the path of the file
file.beforeupdate/file.afterupdate Triggered when a file is updated path path is the path of the file
user.beforefeaturechange/user.afterfeaturechange Triggered when a user feature change is made, like user is made a group admin user, feature, value, group user user object. feature is hardcoded to groupAdmin. value is hardcoded to create. group is the group object
user.beforefeaturechange/user.afterfeaturechange Triggered when a user is removed from as group admin user, feature, value, group user user object. feature is hardcoded to groupAdmin. value is hardcoded to remove. group is the group object
share.beforeCreate/share.afterCreate Triggered when a share is created shareData, shareObject shareData is an array of share details. It could be preHook or postHook data. shareObject is the share object.
share.afterupdate share.afterupdate -> {OCP\Share::post_update_permissions, OCP\Share::post_update_password, OCP\Share::post_set_expiration_date} Triggered when a share is updated shareobject, expirationdateupdated, oldexpirationdate, passwordupdate, permissionupdate, oldpermissions, path shareobject is the share object. Remaining fields may be found based on the update happening with the share. For example passwordupdate could be found if a password update happens.
share.beforeDelete/share.afterDelete Triggered when a share is deleted shareData, shareObject shareobject is the share object. shareData is the share details in an array
fromself.unshare Triggered when the share is removed from the recipient user shareRecipient, shareOwner, recipientPath, ownerPath, nodeType shareRecipient is the recipient of the share. shareOwner is the owner of share who shared. recipientPath is the path of the share. nodeType is the type of the node

@PVince81
Copy link
Contributor

PVince81 commented Sep 7, 2018

in general I think the file name is irrelevant.

try thinking in terms of who will be using these events and what they want to know

@sharidas
Copy link
Author

sharidas commented Sep 9, 2018

try thinking in terms of who will be using these events and what they want to know

Yes you are right, the file name doesn't make any sense. I have removed the column. So the columns on the updated https://github.com/owncloud/documentation/issues/3738#issuecomment-419377043 are
Method Name, Event Triggered, Arguments, Description.

Let me know if this looks ok? I am quite not sure if the app developer would be interested to know which method triggered this event. Because the developer would know what action was performed. So can I remove Method Name from the table? I would like to have your opinion here.

@PVince81
Copy link
Contributor

the method name is irrelevant as well.

better have a description column that describes when each event is happening / in what context

@sharidas
Copy link
Author

better have a description column that describes when each event is happening / in what context

Sure.

@sharidas
Copy link
Author

sharidas commented Sep 11, 2018

Updated again with a new column which has the description about when the event is triggered https://github.com/owncloud/documentation/issues/3738#issuecomment-419377043

@settermjd settermjd transferred this issue from owncloud-archive/documentation Nov 19, 2018
@sharidas
Copy link
Author

Current state of the doc:

  • Added a separate column Event mapped to old event. Intention is to help reader know which new symonfy event is mapped to the old event.
  • Recheck if this table looks readable for an app developer.
  • Recheck if the entries updated are correct.

Note: As of now I have used audit app as reference to update the table. Will cross check again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants