Skip to content
This repository has been archived by the owner on Jul 6, 2020. It is now read-only.

Delete Feeds of Inactive Users

Bernhard Posselt edited this page Jan 18, 2016 · 9 revisions

On bigger hosted installations, content of inactive users might add up a lot. Think of a user adding a couple of feeds and then abandoning the app: the updater adds more and more unread articles which pile up over time.

In order to solve this issue, an app should be created that records when users accessed the News app the last time. Furthermore a cronjob which is run regularely checks for inactive users.

If a user did not open the News app or call the API after an admin configurable time, the user receives a mail that tells him that his data in the News app will be deleted in a user configurable time if he does not access the app or API again.

If the user ignores the mail and does not access the app nor API again, all folders, feeds band items belonging to the user are deleted

Implementation Hints

First generate a new app with ocdev (check the ownCloud tutorial) like this:

ocdev startapp NewsInactiveUsers

Each time ownCloud is accessed, you need to match the URL and the logged in user and bump the last accessed time in the database. You need to do this inside the newsinactiveusers/appinfo/app.php:

<?php
// in this example, the app is called NewsInactiveUsers and is in a folder newsinactiveusers
namespace OCA\NewsInactiveUsers;
use OCP\AppFramework\App;
// this class will contain the logic
use OCA\NewsInactiveUsers\Activity\ActivityRecorder;

$app = new App('newsinactiveusers');
$app->query(ActivityRecorder::class)->recordActivity();

Next create the database layout by putting this into newsinactiveusers/database.xml:

<database>
    <name>*dbname*</name>
    <create>true</create>
    <overwrite>false</overwrite>
    <charset>utf8</charset>
    <table>
        <name>*dbprefix*inactiveusers</name>
        <declaration>
            <field>
                <name>id</name>
                <type>integer</type>
                <notnull>true</notnull>
                <autoincrement>true</autoincrement>
                <unsigned>true</unsigned>
                <primary>true</primary>
                <length>8</length>
            </field>
            <field>
                <!-- unix date time timestamp -->
                <name>last_used</name> 
                <type>integer</type>
                <length>8</length>
                <notnull>false</notnull>
            </field>
            <field>
                <name>user_id</name>
                <type>text</type>
                <default></default>
                <notnull>true</notnull>
                <length>64</length>
            </field>
            <index>
                <name>inactiveusers_userid_index</name>
                <field>
                    <name>user_id</name>
                </field>
            </index>
            <index>
                <name>inactiveusers_userid_last_used_index</name>
                <field>
                    <name>user_id</name>
                </field>
                <field>
                    <name>last_used</name>
                </field>
            </index>
            <index>
                <name>inactiveusers_last_used_index</name>
                <field>
                    <name>last_used</name>
                </field>
            </index>
        </declaration>
    </table>
</database>

The code for checking the URL and user lives in the ActivityRecorder class inside newsinactiveusers/activity/activityrecorder.php and might look something like this:

<?php
namespace OCA\NewsInactiveUsers\Activity;

use OCP\IDBConnection;
use OCP\IRequest;
use OCP\Mail\IMailer;

class ActivityRecorder {

	private $connection;
	private $userId;
	private $request;
	private $mailer;

	public function __construct(IDBConnection $connection, IRequest $request, 
								IMailer $mailer, $userId) {
		$this->connection = $connection;
		$this->userId = $userId;
		$this->request = $request;
		$this->mailer = $mailer;
	}

	public function recordActivity() {
		if (isset($this->request->server['REQUEST_URI']) && $this->userId != null) {
			$url = $this->request->server['REQUEST_URI'];
			if (preg_match('%index.php/apps/news/(items|api/.*/items)(/.*)?%', $url)) {
				// this is basically PDO
				$sql = 'YOUR JOB';  // sql to insert or update the database records
				$params = [];  // your parameters
				$query = $this->connection->prepare($sql);
				$query->execute($params);
				
				// etc, etc
			}
		}
	}
	
	public function checkInactiveUsers() {
		// check for inactivity using the database connection
		
		// if we want to send a message to the user, use the mailer class
		$msg = $this->mailer->createMessage();
		$msg->setTo('user@mail.com');
		$msg->setSubject('Inactivity subject');
		$msg->setPlainBody('Inactivity message');
		$this->mailer->send($msg);
	}

}

Next you will want to add a cronjob that takes care of deleting users. The job itself is registered in the newsinactiveusers/appinfo/app.php file like this:

<?php
// in this example, the app is called NewsInactiveUsers and is in a folder newsinactiveusers
use OCP\AppFramework\App;
// this class will contain the logic
use OCA\NewsInactiveUsers\Activity\ActivityRecorder;
use OCP\BackgroundJob;
use OCA\NewsInactiveUsers\Cron\Cron;

$app = new App('newsinactiveusers');
$app->query(ActivityRecorder::class)->recordActivity();
Backgroundjob::addRegularTask(Cron::class, 'run');

The cronjob class itself is in newsinactiveusers/cron/cron.php, basically just calls another method on the ActivityRecorder class (**checkInactiveUsers) and looks like this:

<?php
namespace OCA\NewsInactiveUsers\Cron;

use OCP\AppFramework\App;

class Cron {

	public static function run() {
		$app = new App('newsinactiveusers');
		$app->query(ActivityRecorder::class)->checkInactiveUsers();
	}

}

Related Issues