-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
feat(files_sharing): reminder for link shares with expiration date #47412
Conversation
3deeb2c
to
86be354
Compare
$qb = $this->db->getQueryBuilder(); | ||
$qb->select('id', 'share_type') | ||
->from('share') | ||
->where( | ||
$qb->expr()->andX( | ||
$qb->expr()->orX( | ||
$qb->expr()->eq('share_type', $qb->expr()->literal(IShare::TYPE_USER)), | ||
$qb->expr()->eq('share_type', $qb->expr()->literal(IShare::TYPE_EMAIL)) | ||
), | ||
$qb->expr()->eq('item_type', $qb->expr()->literal('folder')), | ||
$qb->expr()->gte('expiration', $qb->createNamedParameter($minDate->format('Y-m-d H:i:s'))), | ||
$qb->expr()->lt('expiration', $qb->createNamedParameter($maxDate->format('Y-m-d H:i:s'))), | ||
$qb->expr()->eq('reminder_sent', $qb->createNamedParameter( | ||
false, IQueryBuilder::PARAM_BOOL | ||
)) | ||
) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this go into a mapper or manager of some kind? I know in other apps we usually do not hit the DB directly like that, not sure for shares.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could move this to the share manager, but I'm not sure if I should, since the query is very specific to this particular job 🤔
$qb->update('share') | ||
->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))) | ||
->set('reminder_sent', $qb->createNamedParameter($share->getReminderSent())) | ||
->execute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
->execute(); | |
->executeStatement(); |
But again, I’d like to see that moved somewhere else.
The updateShare method seems a bit much for such a small flag change though, so I don’t know 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think updateShare works well here, the overhead (if any) is quite insignificant.
lib/private/Share20/Share.php
Outdated
/** @var bool */ | ||
private $reminderSent = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** @var bool */ | |
private $reminderSent = false; | |
private bool $reminderSent = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I maybe update other properties to this format as well (to make it consistent)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I maybe update other properties to this format as well (to make it consistent)?
I decided against it because it breaks a lot of code (e.g. some int properties are sometimes set to null). So I did the strict typing only for my property.
public function run(mixed $argument): void { | ||
$shares = $this->getShares(); | ||
[$foldersByEmail, $langByEmail] = $this->prepareReminders($shares); | ||
$this->sendReminders($foldersByEmail, $langByEmail); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to put a limit here, and work only on a chunk of possible reminders, like 1000
. Otherwise you can run into memory issues and such.
Also, you are first gathering all the info and then sending all the email, consider using Generators to send shares as you find them.
Also, you need to consider what happens if your job crashes or is stopped mid-process. In the current state it sets the flag reminder_sent on all shares first, which means it won’t get sent for other shares if it crashes on a share before. This is better than re-sending reminders, but it would still be better to flag shares one by one just before sending the email.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, thank you!
Great idea @Luka-sama !! |
So, I've fixed the problems that @come-nc found! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reminder_sent
should be a bool in DB as well, otherwise good.
Only thing a bit questionable is how would other providers add support for this, but this can be refactored in later.
Thank you for your code review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant was that this could’ve been added in a more extensible way, for instance with an interface for providers which want to implement the feature, and which adds a method to get which email address the reminder should be sent to.
Just thinking out loud, I have no idea if this would’ve been a good idea and all it implies, just a suggestion for future work to think about extensibility by applications.
Approved 👍
23ee40d
to
3e91bb7
Compare
You're right, that's definitely a good idea for the future to make the feature more universal this way. Thanks! |
Signed-off-by: Stefan Cherniakov <[email protected]>
Signed-off-by: Stefan Cherniakov <[email protected]>
3e91bb7
to
f6d05d0
Compare
Ok, let's go! 🚀 |
…int for reminder_sent field Signed-off-by: Stefan Cherniakov <[email protected]>
Signed-off-by: Stefan Cherniakov <[email protected]>
f6d05d0
to
2685501
Compare
Thanks for your first pull request and welcome to the community! Feel free to keep them coming! If you are looking for issues to tackle then have a look at this selection: https://github.com/nextcloud/server/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22 |
This broke CI on master cc @skjnldsv |
use OCP\Migration\IOutput; | ||
use OCP\Migration\SimpleMigrationStep; | ||
|
||
class Version31000Date20240821142813 extends SimpleMigrationStep { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this target 31 it should have a migration annotation, otherwise we have no information of the impact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added it:
d758442
However, my changes are no longer displayed here in this pull request, probably because the branch is already merged into master.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Luka-sama yes because it is already merged. But is also not about a doc-comment but about annotation for the kind of the migration (OCP\Migration\Attributes\MigrationAttribute
).
Nevertheless thank you very much!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@susnux Oh, I see! I must have used the older migrations as an example, the attributes seem to be something new (from the 30th version).
Should I add them too? Except that it would probably be an overkill to make a new pull request just for that 😅 (or not?)
Hello there, We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process. Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6 Thank you for contributing to Nextcloud and we hope to hear from you soon! (If you believe you should not receive this message, you can add yourself to the blocklist.) |
Summary
This pull request implements the feature as described in the associated issue. A cron job runs hourly to check if any empty folders have less than a day remaining before their expiration date. The feature supports two types of shares: user shares and email shares.
Additionally, a migration was added to include a 'reminder sent' flag, ensuring that reminders are neither skipped nor sent multiple times when the job runs at irregular intervals, especially when using webcron or ajax instead of cron.
This solution can be easily extended to send reminders for link shares without an expiration date (e.g. after 4 days), if the maintainers choose to implement this feature.
Checklist