Disabling Users


Script

Here is a handy Python Script that can be adapted to disable users. This implements the section below: API

This is a simple script that loops through a list of user UIDS and disabled each one.

Make sure service accounts and system admins are not on the list of UIDs (big grin)

Use responsible Password Management practices when using scripts. If shared with clients, remind them to not save or send plain text passwords via email, cloud storage, or git repositories.

Required Variables

  • List of UIDs
  • URL of server - note that the script already prepends https:// and appends /api/..
  • Username
  • Password

Note this is a PATCH Request. DHIS2 is notoriously bad with HTTP responses for Patches. For the version I ran this on (2.33.5) I received a blank response but did receive a 204 response code.

import requests
import json

uids = []
server = ""
username = ""
password = ""

for uid in uids:
    print(uid)
    url = f"https://{server}/api/users/{uid}"

    payload = json.dumps({
    "userCredentials": {
        "disabled": True
    }
    })
    headers = {
    'Content-Type': 'application/json',
    }

    response = requests.request("PATCH", url, headers=headers, data=payload, auth=(username, password))

    print(response.text)
    print(response)

Choose the best fit

There are multiple ways to achieve the goal of disabling users that have not logged into DHIS2 in the last X months.

Native DHIS2 Tools

In 2.36+ there are two new functionalities available in DHIS2:

User account expiration: User accounts can now be set to expire on a particular date. This is useful for creating temporary accounts, e.g. when inviting partners through guest accounts. Screenshot / Docs
Disable inactive users: A new system scheduler job is available for automatically disable users which have been inactive (not logged in) for a given number of months. This is useful from a security perspective to prevent inactive user accounts from being compromised.

API

Creating an API-based solution is a bit more involved and would benefit from more details about the Client’s request. If the request has more logic built in, then an API-based solution is the way to go. If this seems like the case, ask the client for more information.

A generic API call for querying a list of users whose last login was prior to 2021-01-01 would look something like this:

https://<URL>/api/users?paging=false&fields=userCredentials[username,disabled,lastLogin]&filter=userCredentials.disabled:eq:false&filter=userCredentials.lastLogin:le:2021-01-01

SQL

A SQL query that makes use of a sliding window:

UPDATE users SET disabled = TRUE WHERE lastlogin < (NOW() - INTERVAL '6 months') AND disabled = FALSE and username NOT IN ('bao-admin');

Using this SQL query, we could schedule it via crontab to run as frequently as needed (fitting the clients' needs). A “skip list” can be used to not ensure critical users are not disabled.

Process Example

Step 1: Retrieve Users

get_inactive_users.sql (below)

  • who have not logged in within the last year
  • who are not disabled already
  • who are not member in any of the user groups previously mentioned
  • ​whose username does NOT start with test
  • whose username is NOT bao-admin or admin

I have added a "CHANGE:" comment that you could use to add more usernames that should not be disabled, or add more user groups.

Step 2: Disable Users by Username

2. disable_users_by_username.sql – will actually disable the users, requiring that you add each username to the file

Step 3: Steps for Client to Request Server Team to Process the SQL

  • You submit a help desk ticket at BAO Systems Help Desk, attach the file get_inactive_users.sql. You can also mention that a second query is coming shortly after.
  • The BAO server team runs the query 1.
  • You review the list of users received.
  • You copy the usernames of the users you want to disable into the designated place in disable_users_by_username.sql
  • You request, in the same ticket, to also run the just-modified disable_users_by_username.sql that includes the users to disable.
  • The BAO server team runs the query 2.
  • The users are now disabled.
  • The ticket can be resolved. You can submit a new ticket once you want to repeat the process.

SQL Example

get_inactive_users.sql

SELECT DISTINCT u.username, u.disabled, u.lastlogin FROM users u
JOIN usergroupmembers ugm ON ugm.userid = u.userid
JOIN usergroup ug ON ugm.usergroupid = ug.usergroupid
-- INFO: only get users that are enabled
WHERE u.disabled IS FALSE
-- CHANGE: only get users that have not logged in within a year (relative)
AND u.lastlogin < (NOW() - INTERVAL '1 year')
AND u.username NOT IN (
-- CHANGE: Add usernames that should NOT be disabled:
'bao-admin',
'admin'
)
AND u.username NOT like 'test%' -- INFO: usernames that begin with "test" will not be disabled
AND ug.uid NOT IN (
-- CHANGE: Add UIDs of User Groups whose members should NOT be disabled:
'oUcNYeUB8bj', -- EXAMPLE
)
ORDER BY lastlogin;

disable_users_by_username.sql

UPDATE users SET disabled = TRUE WHERE username IN (
-- CHANGE: add usernames that should be disabled.
'disable_this_user',
'disable_that_user'
);