Fix admin panel 412: add OCS-APIRequest header to all OCS methods

Nextcloud requires the OCS-APIRequest: true header on all OCS API
calls as a CSRF protection measure. Without it, the server returns
412 Precondition Failed. The check_admin() method had the header
but all other OCS methods (get_users, create_user, enable/disable/
delete_user) were missing it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 20:51:33 -06:00
parent 9047758c38
commit 78c3c54a26

View File

@@ -218,13 +218,17 @@ class NextcloudClient:
# OCS User Management Methods # OCS User Management Methods
@property
def _ocs_headers(self):
return {'OCS-APIRequest': 'true'}
def ocs_get_users(self) -> Dict[str, Any]: def ocs_get_users(self) -> Dict[str, Any]:
"""Get list of all users via OCS API.""" """Get list of all users via OCS API."""
url = f"{self.ocs_root}/cloud/users" url = f"{self.ocs_root}/cloud/users"
params = {'format': 'json'} params = {'format': 'json'}
try: try:
response = self._make_request('GET', url, params=params) response = self._make_request('GET', url, params=params, headers=self._ocs_headers)
data = response.json() data = response.json()
if data.get('ocs', {}).get('meta', {}).get('statuscode') != 100: if data.get('ocs', {}).get('meta', {}).get('statuscode') != 100:
@@ -247,9 +251,9 @@ class NextcloudClient:
"""Get detailed info for a specific user.""" """Get detailed info for a specific user."""
url = f"{self.ocs_root}/cloud/users/{username}" url = f"{self.ocs_root}/cloud/users/{username}"
params = {'format': 'json'} params = {'format': 'json'}
try: try:
response = self._make_request('GET', url, params=params) response = self._make_request('GET', url, params=params, headers=self._ocs_headers)
data = response.json() data = response.json()
if data.get('ocs', {}).get('meta', {}).get('statuscode') != 100: if data.get('ocs', {}).get('meta', {}).get('statuscode') != 100:
@@ -267,26 +271,26 @@ class NextcloudClient:
except Exception: except Exception:
return None return None
def ocs_create_user(self, username: str, password: str, email: str = None, def ocs_create_user(self, username: str, password: str, email: str = None,
displayname: str = None, groups: list = None) -> Dict[str, Any]: displayname: str = None, groups: list = None) -> Dict[str, Any]:
"""Create a new user via OCS API.""" """Create a new user via OCS API."""
url = f"{self.ocs_root}/cloud/users" url = f"{self.ocs_root}/cloud/users"
params = {'format': 'json'} params = {'format': 'json'}
data = { data = {
'userid': username, 'userid': username,
'password': password 'password': password
} }
if email: if email:
data['email'] = email data['email'] = email
if displayname: if displayname:
data['displayName'] = displayname data['displayName'] = displayname
if groups: if groups:
data['groups'] = groups data['groups'] = groups
try: try:
response = self._make_request('POST', url, params=params, data=data) response = self._make_request('POST', url, params=params, data=data, headers=self._ocs_headers)
result = response.json() result = response.json()
meta = result.get('ocs', {}).get('meta', {}) meta = result.get('ocs', {}).get('meta', {})
@@ -302,9 +306,9 @@ class NextcloudClient:
"""Enable a user account.""" """Enable a user account."""
url = f"{self.ocs_root}/cloud/users/{username}/enable" url = f"{self.ocs_root}/cloud/users/{username}/enable"
params = {'format': 'json'} params = {'format': 'json'}
try: try:
response = self._make_request('PUT', url, params=params) response = self._make_request('PUT', url, params=params, headers=self._ocs_headers)
result = response.json() result = response.json()
meta = result.get('ocs', {}).get('meta', {}) meta = result.get('ocs', {}).get('meta', {})
@@ -319,9 +323,9 @@ class NextcloudClient:
"""Disable a user account.""" """Disable a user account."""
url = f"{self.ocs_root}/cloud/users/{username}/disable" url = f"{self.ocs_root}/cloud/users/{username}/disable"
params = {'format': 'json'} params = {'format': 'json'}
try: try:
response = self._make_request('PUT', url, params=params) response = self._make_request('PUT', url, params=params, headers=self._ocs_headers)
result = response.json() result = response.json()
meta = result.get('ocs', {}).get('meta', {}) meta = result.get('ocs', {}).get('meta', {})
@@ -336,9 +340,9 @@ class NextcloudClient:
"""Delete a user account.""" """Delete a user account."""
url = f"{self.ocs_root}/cloud/users/{username}" url = f"{self.ocs_root}/cloud/users/{username}"
params = {'format': 'json'} params = {'format': 'json'}
try: try:
response = self._make_request('DELETE', url, params=params) response = self._make_request('DELETE', url, params=params, headers=self._ocs_headers)
result = response.json() result = response.json()
meta = result.get('ocs', {}).get('meta', {}) meta = result.get('ocs', {}).get('meta', {})