diff --git a/alliance_auth/settings.py.example b/alliance_auth/settings.py.example index 51427e29..99dfa563 100644 --- a/alliance_auth/settings.py.example +++ b/alliance_auth/settings.py.example @@ -51,7 +51,6 @@ INSTALLED_APPS = [ 'allianceauth.services.modules.mumble', 'allianceauth.services.modules.discord', 'allianceauth.services.modules.discourse', - 'allianceauth.services.modules.ipboard', 'allianceauth.services.modules.ips4', 'allianceauth.services.modules.market', 'allianceauth.services.modules.openfire', @@ -308,17 +307,6 @@ MARKET_DB = { 'PORT': '3306', } -##################### -# IPBoard3 Configuration -##################### -# IPBOARD_ENDPOINT - Api endpoint if using ipboard -# IPBOARD_APIKEY - Api key to interact with ipboard -# IPBOARD_APIMODULE - Module for alliance auth *leave alone* -##################### -IPBOARD_ENDPOINT = 'example.com/interface/board/index.php' -IPBOARD_APIKEY = '' -IPBOARD_APIMODULE = 'aa' - ######################## # XenForo Configuration ######################## diff --git a/allianceauth/services/modules/ipboard/__init__.py b/allianceauth/services/modules/ipboard/__init__.py deleted file mode 100644 index 2c42569d..00000000 --- a/allianceauth/services/modules/ipboard/__init__.py +++ /dev/null @@ -1 +0,0 @@ -default_app_config = 'allianceauth.services.modules.ipboard.apps.IpboardServiceConfig' diff --git a/allianceauth/services/modules/ipboard/admin.py b/allianceauth/services/modules/ipboard/admin.py deleted file mode 100644 index dce5ec2b..00000000 --- a/allianceauth/services/modules/ipboard/admin.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.contrib import admin -from .models import IpboardUser - - -class IpboardUserAdmin(admin.ModelAdmin): - list_display = ('user', 'username') - search_fields = ('user__username', 'username') - -admin.site.register(IpboardUser, IpboardUserAdmin) diff --git a/allianceauth/services/modules/ipboard/apps.py b/allianceauth/services/modules/ipboard/apps.py deleted file mode 100644 index e8221127..00000000 --- a/allianceauth/services/modules/ipboard/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class IpboardServiceConfig(AppConfig): - name = 'allianceauth.services.modules.ipboard' - label = 'ipboard' diff --git a/allianceauth/services/modules/ipboard/auth_hooks.py b/allianceauth/services/modules/ipboard/auth_hooks.py deleted file mode 100644 index d85344d3..00000000 --- a/allianceauth/services/modules/ipboard/auth_hooks.py +++ /dev/null @@ -1,63 +0,0 @@ -import logging - -from django.conf import settings -from django.template.loader import render_to_string - -from allianceauth import hooks -from allianceauth.services.hooks import ServicesHook -from .tasks import IpboardTasks -from .urls import urlpatterns - -logger = logging.getLogger(__name__) - - -class IpboardService(ServicesHook): - def __init__(self): - ServicesHook.__init__(self) - self.name = 'ipboard' - self.service_url = settings.IPBOARD_ENDPOINT - self.urlpatterns = urlpatterns - self.access_perm = 'ipboard.access_ipboard' - - @property - def title(self): - return 'IPBoard Forums' - - def delete_user(self, user, notify_user=False): - logger.debug('Deleting user %s %s account' % (user, self.name)) - return IpboardTasks.delete_user(user, notify_user=notify_user) - - def update_groups(self, user): - logger.debug("Updating %s groups for %s" % (self.name, user)) - if IpboardTasks.has_account(user): - IpboardTasks.update_groups.delay(user.pk) - - def validate_user(self, user): - logger.debug('Validating user %s %s account' % (user, self.name)) - if IpboardTasks.has_account(user) and not self.service_active_for_user(user): - self.delete_user(user, notify_user=True) - - def update_all_groups(self): - logger.debug('Update all %s groups called' % self.name) - IpboardTasks.update_all_groups.delay() - - def service_active_for_user(self, user): - return user.has_perm(self.access_perm) - - def render_services_ctrl(self, request): - urls = self.Urls() - urls.auth_activate = 'auth_activate_ipboard' - urls.auth_deactivate = 'auth_deactivate_ipboard' - urls.auth_reset_password = 'auth_reset_ipboard_password' - urls.auth_set_password = 'auth_set_ipboard_password' - return render_to_string(self.service_ctrl_template, { - 'service_name': self.title, - 'urls': urls, - 'service_url': self.service_url, - 'username': request.user.ipboard.username if IpboardTasks.has_account(request.user) else '', - }, request=request) - - -@hooks.register('services_hook') -def register_service(): - return IpboardService() diff --git a/allianceauth/services/modules/ipboard/manager.py b/allianceauth/services/modules/ipboard/manager.py deleted file mode 100755 index 2b9d6719..00000000 --- a/allianceauth/services/modules/ipboard/manager.py +++ /dev/null @@ -1,160 +0,0 @@ -import random -import string -import re -from hashlib import md5 -try: - from xmlrpclib import Server -except ImportError: - # python 3 - from xmlrpc import server as Server - - -from django.conf import settings - -import logging - -logger = logging.getLogger(__name__) - - -class IPBoardManager: - def __init__(self): - pass - - @staticmethod - def __santatize_username(username): - sanatized = username.replace(" ", "_") - return sanatized.lower() - - @staticmethod - def __generate_random_pass(): - return ''.join([random.choice(string.ascii_letters + string.digits) for n in range(16)]) - - @staticmethod - def _gen_pwhash(password): - return md5(password.encode('utf-8')).hexdigest() - - @staticmethod - def _sanitize_groupname(name): - name = name.strip(' _') - return re.sub('[^\w.-]', '', name) - - @staticmethod - def exec_xmlrpc(func, **kwargs): - """ Send a XMLRPC request """ - try: - server = Server(settings.IPBOARD_ENDPOINT, verbose=False) - params = {} - for i in kwargs: - params[i] = kwargs[i] - params['api_key'] = settings.IPBOARD_APIKEY - params['api_module'] = settings.IPBOARD_APIMODULE - - return getattr(server, func)(params) - except: - return {} - - @classmethod - def add_user(cls, username, email): - """ Add user to service """ - sanatized = str(IPBoardManager.__santatize_username(username)) - logger.debug("Adding user to IPBoard with username %s" % sanatized) - plain_password = IPBoardManager.__generate_random_pass() - password = cls._gen_pwhash(plain_password) - IPBoardManager.exec_xmlrpc('createUser', username=sanatized, email=str(email), display_name=sanatized, - md5_passwordHash=password) - logger.info("Added IPBoard user with username %s" % sanatized) - return sanatized, plain_password - - @staticmethod - def delete_user(username): - """ Delete user """ - IPBoardManager.exec_xmlrpc('deleteUser', username=username) - logger.info("Deleted IPBoard user with username %s" % username) - return username - - @staticmethod - def disable_user(username): - """ Disable user """ - IPBoardManager.exec_xmlrpc('disableUser', username=username) - logger.info("Disabled IPBoard user with username %s" % username) - return username - - @classmethod - def update_user(cls, username, email, password): - """ Add user to service """ - password = cls._gen_pwhash(password) - logger.debug("Updating IPBoard username %s with email %s and password hash starting with %s" % ( - username, email, password[0:5])) - IPBoardManager.exec_xmlrpc('updateUser', username=username, email=email, md5_passwordHash=password) - logger.info("Updated IPBoard user with username %s" % username) - return username - - @staticmethod - def get_all_groups(): - groups = [] - ret = IPBoardManager.exec_xmlrpc('getAllGroups') - for group in ret: - groups.append(group["g_title"]) - logger.debug("Retrieved group list from IPBoard: %s" % groups) - return groups - - @staticmethod - def get_user_groups(username): - groups = [] - ret = IPBoardManager.exec_xmlrpc('getUserGroups', username=username) - if type(ret) is list: - for group in ret: - groups.append(group["g_title"]) - logger.debug("Got user %s IPBoard groups %s" % (username, groups)) - return groups - - @staticmethod - def add_group(group): - ret = IPBoardManager.exec_xmlrpc('addGroup', group=group) - logger.info("Added IPBoard group %s" % group) - return ret - - @staticmethod - def add_user_to_group(username, group): - ret = IPBoardManager.exec_xmlrpc('addUserToGroup', username=username, group=group) - logger.info("Added IPBoard user %s to group %s" % (username, group)) - return ret - - @staticmethod - def remove_user_from_group(username, group): - ret = IPBoardManager.exec_xmlrpc('removeUserFromGroup', username=username, group=group) - logger.info("Removed IPBoard user %s from group %s" % (username, group)) - return ret - - @staticmethod - def help_me(): - ret = IPBoardManager.exec_xmlrpc('helpMe') - return ret - - @staticmethod - def update_groups(username, groups): - logger.debug("Updating IPBoard user %s with groups %s" % (username, groups)) - forum_groups = IPBoardManager.get_all_groups() - user_groups = set(IPBoardManager.get_user_groups(username)) - act_groups = set([IPBoardManager._sanitize_groupname(g) for g in groups]) - addgroups = act_groups - user_groups - remgroups = user_groups - act_groups - - logger.info("Updating IPBoard groups for user %s - adding %s, removing %s" % (username, addgroups, remgroups)) - for g in addgroups: - if g not in forum_groups: - IPBoardManager.add_group(g) - logger.debug("Adding user %s to IPBoard group %s" % (username, g)) - IPBoardManager.add_user_to_group(username, g) - - for g in remgroups: - logger.debug("Removing user %s from IPBoard group %s" % (username, g)) - IPBoardManager.remove_user_from_group(username, g) - - @staticmethod - def update_user_password(username, email, plain_password=None): - logger.debug("Settings new IPBoard password for user %s" % username) - if not plain_password: - plain_password = IPBoardManager.__generate_random_pass() - IPBoardManager.update_user(username, email, plain_password) - return plain_password diff --git a/allianceauth/services/modules/ipboard/migrations/0001_initial.py b/allianceauth/services/modules/ipboard/migrations/0001_initial.py deleted file mode 100644 index 448c1064..00000000 --- a/allianceauth/services/modules/ipboard/migrations/0001_initial.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.2 on 2016-12-12 03:27 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('auth', '0008_alter_user_username_max_length'), - ] - - operations = [ - migrations.CreateModel( - name='IpboardUser', - fields=[ - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='ipboard', serialize=False, to=settings.AUTH_USER_MODEL)), - ('username', models.CharField(max_length=254)), - ], - ), - ] diff --git a/allianceauth/services/modules/ipboard/migrations/0002_service_permissions.py b/allianceauth/services/modules/ipboard/migrations/0002_service_permissions.py deleted file mode 100644 index 49f78e64..00000000 --- a/allianceauth/services/modules/ipboard/migrations/0002_service_permissions.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.10.5 on 2017-02-02 05:59 -from __future__ import unicode_literals - -from django.db import migrations -from django.conf import settings -from django.core.exceptions import ObjectDoesNotExist -from django.contrib.auth.management import create_permissions - -import logging - -logger = logging.getLogger(__name__) - - -def migrate_service_enabled(apps, schema_editor): - for app_config in apps.get_app_configs(): - app_config.models_module = True - create_permissions(app_config, apps=apps, verbosity=0) - app_config.models_module = None - - Group = apps.get_model("auth", "Group") - Permission = apps.get_model("auth", "Permission") - IpboardUser = apps.get_model("ipboard", "IpboardUser") - - perm = Permission.objects.get(codename='access_ipboard') - - member_group_name = getattr(settings, str('DEFAULT_AUTH_GROUP'), 'Member') - blue_group_name = getattr(settings, str('DEFAULT_BLUE_GROUP'), 'Blue') - - # Migrate members - if IpboardUser.objects.filter(user__groups__name=member_group_name).exists() or \ - getattr(settings, str('ENABLE_AUTH_IPBOARD'), False): - try: - group = Group.objects.get(name=member_group_name) - group.permissions.add(perm) - except ObjectDoesNotExist: - logger.warning('Failed to migrate ENABLE_AUTH_IPBOARD setting') - - # Migrate blues - if IpboardUser.objects.filter(user__groups__name=blue_group_name).exists() or \ - getattr(settings, str('ENABLE_BLUE_IPBOARD'), False): - try: - group = Group.objects.get(name=blue_group_name) - group.permissions.add(perm) - except ObjectDoesNotExist: - logger.warning('Failed to migrate ENABLE_BLUE_IPBOARD setting') - - -class Migration(migrations.Migration): - - dependencies = [ - ('ipboard', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='ipboarduser', - options={'permissions': (('access_ipboard', 'Can access the IPBoard service'),)}, - ), - migrations.RunPython(migrate_service_enabled), - ] diff --git a/allianceauth/services/modules/ipboard/migrations/__init__.py b/allianceauth/services/modules/ipboard/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/allianceauth/services/modules/ipboard/models.py b/allianceauth/services/modules/ipboard/models.py deleted file mode 100644 index 1a9df670..00000000 --- a/allianceauth/services/modules/ipboard/models.py +++ /dev/null @@ -1,18 +0,0 @@ -from django.contrib.auth.models import User -from django.db import models - - -class IpboardUser(models.Model): - user = models.OneToOneField(User, - primary_key=True, - on_delete=models.CASCADE, - related_name='ipboard') - username = models.CharField(max_length=254) - - def __str__(self): - return self.username - - class Meta: - permissions = ( - ("access_ipboard", u"Can access the IPBoard service"), - ) diff --git a/allianceauth/services/modules/ipboard/tasks.py b/allianceauth/services/modules/ipboard/tasks.py deleted file mode 100644 index 10d81f1f..00000000 --- a/allianceauth/services/modules/ipboard/tasks.py +++ /dev/null @@ -1,63 +0,0 @@ -import logging - -from django.contrib.auth.models import User -from django.core.exceptions import ObjectDoesNotExist - -from allianceauth.celeryapp import app -from allianceauth.notifications import notify -from .manager import IPBoardManager -from .models import IpboardUser - -logger = logging.getLogger(__name__) - - -class IpboardTasks: - def __init__(self): - pass - - @classmethod - def delete_user(cls, user, notify_user=False): - if cls.has_account(user): - if IPBoardManager.disable_user(user.ipboard.username): - user.ipboard.delete() - if notify_user: - notify(user, 'IPBoard Account Disabled', level='danger') - return True - return False - - @staticmethod - def has_account(user): - try: - return user.ipboard.username != '' - except ObjectDoesNotExist: - return False - - @staticmethod - @app.task(bind=True, name='ipboard.update_groups') - def update_groups(self, pk): - user = User.objects.get(pk=pk) - logger.debug("Updating user %s ipboard groups." % user) - groups = [] - for group in user.groups.all(): - groups.append(str(group.name)) - if len(groups) == 0: - groups.append('empty') - logger.debug("Updating user %s ipboard groups to %s" % (user, groups)) - try: - IPBoardManager.update_groups(user.ipboard.username, groups) - except: - logger.exception("IPBoard group sync failed for %s, retrying in 10 mins" % user) - raise self.retry(countdown=60 * 10) - logger.debug("Updated user %s ipboard groups." % user) - - @staticmethod - @app.task(name='ipboard.update_all_groups') - def update_all_groups(): - logger.debug("Updating ALL ipboard groups") - for ipboard_user in IpboardUser.objects.exclude(username__exact=''): - IpboardTasks.update_groups.delay(ipboard_user.user.pk) - - @staticmethod - def disable(): - logger.debug("Deleting all Ipboard Users") - IpboardUser.objects.all().delete() diff --git a/allianceauth/services/modules/ipboard/tests.py b/allianceauth/services/modules/ipboard/tests.py deleted file mode 100644 index 576c0e96..00000000 --- a/allianceauth/services/modules/ipboard/tests.py +++ /dev/null @@ -1,200 +0,0 @@ -from unittest import mock - -from django.test import TestCase, RequestFactory -from django.contrib.auth.models import User, Group, Permission -from django import urls -from django.core.exceptions import ObjectDoesNotExist - -from allianceauth.tests.auth_utils import AuthUtils - -from .auth_hooks import IpboardService -from .models import IpboardUser -from .tasks import IpboardTasks -from .manager import IPBoardManager - -MODULE_PATH = 'allianceauth.services.modules.ipboard' -DEFAULT_AUTH_GROUP = 'Member' - - -def add_permissions(): - permission = Permission.objects.get(codename='access_ipboard') - members = Group.objects.get_or_create(name=DEFAULT_AUTH_GROUP)[0] - AuthUtils.add_permissions_to_groups([permission], [members]) - - -class IpboardHooksTestCase(TestCase): - def setUp(self): - self.member = 'member_user' - member = AuthUtils.create_member(self.member) - IpboardUser.objects.create(user=member, username=self.member) - self.none_user = 'none_user' - none_user = AuthUtils.create_user(self.none_user) - self.service = IpboardService - add_permissions() - - def test_has_account(self): - member = User.objects.get(username=self.member) - none_user = User.objects.get(username=self.none_user) - self.assertTrue(IpboardTasks.has_account(member)) - self.assertFalse(IpboardTasks.has_account(none_user)) - - def test_service_enabled(self): - service = self.service() - member = User.objects.get(username=self.member) - none_user = User.objects.get(username=self.none_user) - - self.assertTrue(service.service_active_for_user(member)) - self.assertFalse(service.service_active_for_user(none_user)) - - @mock.patch(MODULE_PATH + '.tasks.IPBoardManager') - def test_update_all_groups(self, manager): - service = self.service() - service.update_all_groups() - # Check member and blue user have groups updated - self.assertTrue(manager.update_groups.called) - self.assertEqual(manager.update_groups.call_count, 1) - - def test_update_groups(self): - # Check member has Member group updated - with mock.patch(MODULE_PATH + '.tasks.IPBoardManager') as manager: - service = self.service() - member = User.objects.get(username=self.member) - service.update_groups(member) - self.assertTrue(manager.update_groups.called) - - # Check none user does not have groups updated - with mock.patch(MODULE_PATH + '.tasks.IPBoardManager') as manager: - service = self.service() - none_user = User.objects.get(username=self.none_user) - service.update_groups(none_user) - self.assertFalse(manager.update_groups.called) - - @mock.patch(MODULE_PATH + '.tasks.IPBoardManager') - def test_validate_user(self, manager): - service = self.service() - # Test member is not deleted - member = User.objects.get(username=self.member) - service.validate_user(member) - self.assertTrue(User.objects.get(username=self.member).ipboard) - - # Test none user is deleted - none_user = User.objects.get(username=self.none_user) - IpboardUser.objects.create(user=none_user, username='none_user') - service.validate_user(none_user) - self.assertTrue(manager.disable_user.called) - with self.assertRaises(ObjectDoesNotExist): - none_ipboard = User.objects.get(username=self.none_user).ipboard - - @mock.patch(MODULE_PATH + '.tasks.IPBoardManager') - def test_delete_user(self, manager): - member = User.objects.get(username=self.member) - - service = self.service() - result = service.delete_user(member) - - self.assertTrue(result) - self.assertTrue(manager.disable_user.called) - with self.assertRaises(ObjectDoesNotExist): - Ipboard_user = User.objects.get(username=self.member).ipboard - - def test_render_services_ctrl(self): - service = self.service() - member = User.objects.get(username=self.member) - request = RequestFactory().get('/en/services/') - request.user = member - - response = service.render_services_ctrl(request) - self.assertTemplateUsed(service.service_ctrl_template) - self.assertIn('/ipboard/set_password/', response) - self.assertIn('/ipboard/reset_password/', response) - self.assertIn('/ipboard/deactivate/', response) - - # Test register becomes available - member.ipboard.delete() - member = User.objects.get(username=self.member) - request.user = member - response = service.render_services_ctrl(request) - self.assertIn('/ipboard/activate/', response) - - -class IpboardViewsTestCase(TestCase): - def setUp(self): - self.member = AuthUtils.create_member('auth_member') - self.member.set_password('password') - self.member.email = 'auth_member@example.com' - self.member.save() - AuthUtils.add_main_character(self.member, 'auth_member', '12345', corp_id='111', corp_name='Test Corporation') - add_permissions() - - def login(self): - self.client.login(username=self.member.username, password='password') - - @mock.patch(MODULE_PATH + '.views.IPBoardManager') - def test_activate(self, manager): - self.login() - expected_username = 'auth_member' - expected_password = 'abc123' - manager.add_user.return_value = (expected_username, expected_password) - response = self.client.get(urls.reverse('auth_activate_ipboard'), follow=False) - self.assertEqual(response.status_code, 200) - self.assertContains(response, expected_username) - self.assertContains(response, expected_password) - self.assertTrue(manager.add_user.called) - args, kwargs = manager.add_user.call_args - self.assertEqual(args[0], 'auth_member') # Character name - self.assertEqual(args[1], self.member.email) - ipboard_user = IpboardUser.objects.get(user=self.member) - self.assertEqual(ipboard_user.username, expected_username) - - @mock.patch(MODULE_PATH + '.tasks.IPBoardManager') - def test_deactivate(self, manager): - self.login() - IpboardUser.objects.create(user=self.member, username='12345') - manager.disable_user.return_value = True - - response = self.client.get(urls.reverse('auth_deactivate_ipboard')) - - self.assertTrue(manager.disable_user.called) - self.assertRedirects(response, expected_url=urls.reverse('auth_services'), target_status_code=200) - with self.assertRaises(ObjectDoesNotExist): - ipboard_user = User.objects.get(pk=self.member.pk).ipboard - - @mock.patch(MODULE_PATH + '.views.IPBoardManager') - def test_set_password(self, manager): - self.login() - IpboardUser.objects.create(user=self.member, username='12345') - expected_password = 'password' - manager.update_user_password.return_value = expected_password - - response = self.client.post(urls.reverse('auth_set_ipboard_password'), data={'password': expected_password}) - - self.assertTrue(manager.update_user_password.called) - args, kwargs = manager.update_user_password.call_args - self.assertEqual(kwargs['plain_password'], expected_password) - self.assertRedirects(response, expected_url=urls.reverse('auth_services'), target_status_code=200) - - @mock.patch(MODULE_PATH + '.views.IPBoardManager') - def test_reset_password(self, manager): - self.login() - IpboardUser.objects.create(user=self.member, username='12345') - - response = self.client.get(urls.reverse('auth_reset_ipboard_password')) - - self.assertTrue(manager.update_user_password.called) - self.assertTemplateUsed(response, 'registered/service_credentials.html') - - -class IpboardManagerTestCase(TestCase): - def setUp(self): - self.manager = IPBoardManager - - def test_generate_random_password(self): - password = self.manager._IPBoardManager__generate_random_pass() - - self.assertEqual(len(password), 16) - self.assertIsInstance(password, type('')) - - def test_gen_pwhash(self): - pwhash = self.manager._gen_pwhash('test') - - self.assertEqual(pwhash, '098f6bcd4621d373cade4e832627b4f6') diff --git a/allianceauth/services/modules/ipboard/urls.py b/allianceauth/services/modules/ipboard/urls.py deleted file mode 100644 index 30ad4f81..00000000 --- a/allianceauth/services/modules/ipboard/urls.py +++ /dev/null @@ -1,15 +0,0 @@ -from django.conf.urls import url, include - -from . import views - -module_urls = [ - # Ipboard service control - url(r'^activate/$', views.activate_ipboard_forum, name='auth_activate_ipboard'), - url(r'^deactivate/$', views.deactivate_ipboard_forum, name='auth_deactivate_ipboard'), - url(r'^reset_password/$', views.reset_ipboard_password, name='auth_reset_ipboard_password'), - url(r'^set_password/$', views.set_ipboard_password, name='auth_set_ipboard_password'), -] - -urlpatterns = [ - url(r'^ipboard/', include(module_urls)) -] diff --git a/allianceauth/services/modules/ipboard/views.py b/allianceauth/services/modules/ipboard/views.py deleted file mode 100644 index f531acf4..00000000 --- a/allianceauth/services/modules/ipboard/views.py +++ /dev/null @@ -1,107 +0,0 @@ -import logging - -from django.contrib import messages -from django.contrib.auth.decorators import login_required, permission_required -from django.shortcuts import render, redirect - -from allianceauth.services.forms import ServicePasswordForm -from .manager import IPBoardManager -from .models import IpboardUser -from .tasks import IpboardTasks - -logger = logging.getLogger(__name__) - -ACCESS_PERM = 'ipboard.access_ipboard' - - -@login_required -@permission_required(ACCESS_PERM) -def activate_ipboard_forum(request): - logger.debug("activate_ipboard_forum called by user %s" % request.user) - character = request.user.profile.main_character - logger.debug("Adding ipboard user for user %s with main character %s" % (request.user, character)) - result = IPBoardManager.add_user(character.character_name, request.user.email) - if result[0] != "": - ipboard_user = IpboardUser() - ipboard_user.user = request.user - ipboard_user.username = result[0] - ipboard_user.save() - logger.debug("Updated authserviceinfo for user %s with ipboard credentials. Updating groups." % request.user) - IpboardTasks.update_groups.delay(request.user.pk) - logger.info("Successfully activated ipboard for user %s" % request.user) - messages.success(request, 'Activated IPBoard account.') - credentials = { - 'username': result[0], - 'password': result[1], - } - return render(request, 'registered/service_credentials.html', - context={'credentials': credentials, 'service': 'IPBoard'}) - else: - logger.error("Unsuccessful attempt to activate ipboard for user %s" % request.user) - messages.error(request, 'An error occurred while processing your IPBoard account.') - return redirect("auth_services") - - -@login_required -@permission_required(ACCESS_PERM) -def deactivate_ipboard_forum(request): - logger.debug("deactivate_ipboard_forum called by user %s" % request.user) - # false we failed - if IpboardTasks.delete_user(request.user): - logger.info("Successfully deactivated ipboard for user %s" % request.user) - messages.success(request, 'Deactivated IPBoard account.') - else: - logger.error("Unsuccessful attempt to deactviate ipboard for user %s" % request.user) - messages.error(request, 'An error occurred while processing your IPBoard account.') - return redirect("auth_services") - - -@login_required -@permission_required(ACCESS_PERM) -def set_ipboard_password(request): - logger.debug("set_ipboard_password called by user %s" % request.user) - error = None - if request.method == 'POST': - logger.debug("Received POST request with form.") - form = ServicePasswordForm(request.POST) - logger.debug("Form is valid: %s" % form.is_valid()) - if form.is_valid() and IpboardTasks.has_account(request.user): - password = form.cleaned_data['password'] - logger.debug("Form contains password of length %s" % len(password)) - result = IPBoardManager.update_user_password(request.user.ipboard.username, request.user.email, - plain_password=password) - if result != "": - logger.info("Successfully set IPBoard password for user %s" % request.user) - messages.success(request, 'Set IPBoard password.') - else: - logger.error("Failed to install custom ipboard password for user %s" % request.user) - messages.error(request, 'An error occurred while processing your IPBoard account.') - return redirect("auth_services") - else: - logger.debug("Request is not type POST - providing empty form.") - form = ServicePasswordForm() - - logger.debug("Rendering form for user %s" % request.user) - context = {'form': form, 'service': 'IPBoard', 'error': error} - return render(request, 'registered/service_password.html', context=context) - - -@login_required -@permission_required(ACCESS_PERM) -def reset_ipboard_password(request): - logger.debug("reset_ipboard_password called by user %s" % request.user) - if IpboardTasks.has_account(request.user): - result = IPBoardManager.update_user_password(request.user.ipboard.username, request.user.email) - if result != "": - logger.info("Successfully reset ipboard password for user %s" % request.user) - messages.success(request, 'Reset IPBoard password.') - credentials = { - 'username': request.user.ipboard.username, - 'password': result, - } - return render(request, 'registered/service_credentials.html', - context={'credentials': credentials, 'service': 'IPBoard'}) - - logger.error("Unsuccessful attempt to reset ipboard password for user %s" % request.user) - messages.error(request, 'An error occurred while processing your IPBoard account.') - return redirect("auth_services") diff --git a/docs/installation/services/index.md b/docs/installation/services/index.md index 2791990a..922fc063 100644 --- a/docs/installation/services/index.md +++ b/docs/installation/services/index.md @@ -7,7 +7,6 @@ market discord discourse - ipboard3 mumble openfire phpbb3 diff --git a/docs/installation/services/ipboard3.md b/docs/installation/services/ipboard3.md deleted file mode 100644 index 34878b41..00000000 --- a/docs/installation/services/ipboard3.md +++ /dev/null @@ -1,42 +0,0 @@ -# IPBoard3 - -Add `services.modules.ipboard` to your `INSTALLED_APPS` list and run migrations before continuing with this guide to ensure the service is installed. - -You’re on your own for the initial install of IPBoard. It’s pretty much just download, unzip, and move to `/var/www/ipboard/`. Make sure to - - sudo chown -R www-data:www-data /var/www/ipboard - -a few times because it’s pretty finicky. - -You’ll need to add another alias in your apache config, this one for `/ipboard` pointing to `/var/www/ipboard` and add another `` block for `/var/www/ipboard` with `Require all granted` or `Allow from all` depending on your apache version. - -IPBoard needs a database table. Log in to mysql and run: - - create database alliance_ipboard; - -That’s all for SQL work. Control+D to close. - -Navigate to http://example.com/ipboard and proceed with the install. If it whines about permissions make sure to `chown` again. Point it at that database we just made, using the `allianceserver` MySQL user account from the full install. - -Once you get everything installed we need to copy the api module folder - - sudo cp -a /home/allianceserver/allianceauth/thirdparty/IPBoard3/aa /var/www/ipboard/interface/board/modules/aa - -and again run that `chown` command. - -Log into the AdminCP for IPBoard and find your way to the `System` tab. On the left navigation bar, under `Tools and Settings`, select `API Users`. - -Enable the API by toggling the `XML-RPC Status` from `disabled` to `enabled` (red box, top right of the page) and save. Now create a new api user. Put something descriptive for title such as ‘AllianceAuth’, then on the bottom panel click the `AllianceAuth` tab and tick all the boxes. Press `Create New API User` to save it. - -Copy the API key. Now edit your settings.py as follows: - - - IPBOARD_APIKEY is the key you just copied - - IPBOARD_ENDPOINT is `http://example.com/ipboard/interface/board/index.php` - -Now enable IPBoard for Auth and/or Blue by editing the auth settings. - -Save and exit. Restart apache or gunicorn. - -Test it by creating a user through Alliance Auth. Just note right now there’s no real error handling, so if account creation fails it’ll still return a username/password combo. - -Good luck! diff --git a/test_allianceauth/settings.py b/test_allianceauth/settings.py index 5399b1ba..1e11cb20 100644 --- a/test_allianceauth/settings.py +++ b/test_allianceauth/settings.py @@ -60,7 +60,6 @@ INSTALLED_APPS = [ 'allianceauth.services.modules.mumble', 'allianceauth.services.modules.discord', 'allianceauth.services.modules.discourse', - 'allianceauth.services.modules.ipboard', 'allianceauth.services.modules.ips4', 'allianceauth.services.modules.market', 'allianceauth.services.modules.openfire', @@ -298,17 +297,6 @@ MARKET_URL = os.environ.get('AA_MARKET_URL', 'http://yourdomain.com/market') ##################### JACK_KNIFE_URL = os.environ.get('AA_JACK_KNIFE_URL', 'http://example.com/eveapi/audit.php') -##################### -# Forum Configuration -##################### -# IPBOARD_ENDPOINT - Api endpoint if using ipboard -# IPBOARD_APIKEY - Api key to interact with ipboard -# IPBOARD_APIMODULE - Module for alliance auth *leave alone* -##################### -IPBOARD_ENDPOINT = os.environ.get('AA_IPBOARD_ENDPOINT', 'example.com/interface/board/index.php') -IPBOARD_APIKEY = os.environ.get('AA_IPBOARD_APIKEY', 'somekeyhere') -IPBOARD_APIMODULE = 'aa' - ######################## # XenForo Configuration ######################## diff --git a/thirdparty/IPBoard3/Readme.txt b/thirdparty/IPBoard3/Readme.txt deleted file mode 100755 index 40ed0370..00000000 --- a/thirdparty/IPBoard3/Readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -To utilize this module copy the folder "aa" to your interface/board/modules/ directory. -Then create and api key and give all "AllianceAuth" permissions to it. \ No newline at end of file diff --git a/thirdparty/IPBoard3/aa/api.php b/thirdparty/IPBoard3/aa/api.php deleted file mode 100755 index bd047c5d..00000000 --- a/thirdparty/IPBoard3/aa/api.php +++ /dev/null @@ -1,525 +0,0 @@ -registry = $registry; - - //----------------------------------------- - // Load allowed methods and build dispatch - // list - //----------------------------------------- - $ALLOWED_METHODS = array(); - require_once( DOC_IPS_ROOT_PATH . 'interface/board/modules/aa/methods.php' );/*noLibHook*/ - - if ( is_array( $ALLOWED_METHODS ) and count( $ALLOWED_METHODS ) ) - { - foreach( $ALLOWED_METHODS as $_method => $_data ) - { - $this->__dispatch_map[ $_method ] = $_data; - } - } - } - - // Creates a new user - public function createUser( $api_key, $api_module, $username, $email, $display_name, $md5_passwordHash) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'createUser' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - //----------------------------------------- - // Create a user - //----------------------------------------- - $test = IPSMember::create( array( 'core' => array( 'email' => $email, 'md5_hash_password' => $md5_passwordHash, 'name' => $username, 'members_display_name' => $display_name) ) ); - - //----------------------------------------- - // The way IPSMember::create function works is it can't fail.. It always returns true unless all data isn't provided. - // However it will still create a partial record. So in essence never fails - //----------------------------------------- - $this->classApiServer->apiSendReply( array('result' => 'success') ); - - exit(); - } - } - - - // Deletes a user from the entire system - public function deleteUser( $api_key, $api_module, $username) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'deleteUser' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - //----------------------------------------- - // Remove a user by username - //----------------------------------------- - $member = IPSMember::load($username,'all','username'); - - if ($member != null) { - $result = IPSMember::remove($member['member_id']); - - if($result) { - $this->classApiServer->apiSendReply( array('result' => 'success') ); - } else { - $this->classApiServer->apiSendReply( array('result' => 'failure') ); - } - } - - $this->classApiServer->apiSendReply( array('result' => 'failure') ); - - exit(); - } - } - - // We disable by just changing the email and password to something random. - // Allows us to avoid losing post etc. - public function disableUser( $api_key, $api_module, $username) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'disableUser' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - //----------------------------------------- - // Remove a user by username - //----------------------------------------- - $member = IPSMember::load($username,'all','username'); - - if ($member != null) { - - $uniqueID = strval(uniqid()); - $uniqueEmail = strval(uniqid()); - $uniqueMD5 = md5($uniqueID); - $email = $uniqueEmail.'@'.$uniqueEmail.'.com'; - - $email_result = IPSMember::save( array( 'core' => array( 'field' => 'member_id', 'value' => $member['member_id'])),array('core' => array('email'=>$email))); - $password_result = $password_result = IPSMember::updatePassword($member['member_id'], $uniqueMD5); - - if($email_result && $password_result) { - $this->classApiServer->apiSendReply( array('result' => 'success') ); - } else { - $this->classApiServer->apiSendReply( array('result' => 'failure') ); - } - } - - $this->classApiServer->apiSendReply( array('result' => 'failure') ); - - exit(); - } - } - - // Used to update the user email, and password. - // Is also used to re-enable a disabled account - public function updateUser( $api_key, $api_module, $username, $email, $md5_passwordHash) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'updateUser' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - //----------------------------------------- - // Load our user - //----------------------------------------- - $member = IPSMember::load($username,'all','username'); - - if ($member != null) { - - $email_result = IPSMember::save( array( 'core' => array( 'field' => 'member_id', 'value' => $member['member_id'])),array('core' => array('email'=>$email))); - $password_result = $password_result = IPSMember::updatePassword($member['member_id'], $md5_passwordHash); - - if($email_result && $password_result) { - $this->classApiServer->apiSendReply( array('result' => 'success') ); - } else { - $this->classApiServer->apiSendReply( array('result' => 'failure') ); - } - } - - $this->classApiServer->apiSendReply( array('result' => 'failure') ); - - exit(); - } - } - - public function getAllGroups( $api_key, $api_module) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'getAllGroups' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - //----------------------------------------- - // Load our user - //----------------------------------------- - ipsRegistry::DB()->build(array('select' => 'g_title', 'from' => 'groups')); - $result = ipsRegistry::DB()->execute(); - $groups = array(); - - while( $r = ipsRegistry::DB()->fetch($result)) { - array_push($groups,$r); - } - $this->classApiServer->apiSendReply($groups); - - exit(); - } - } - - public function getUserGroups( $api_key, $api_module, $username) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'getUserGroups' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - $member = IPSMember::load($username,'all','username'); - $groups = array(); - if( $member['mgroup_others']) { - $groupids = explode(',' , $member['mgroup_others']); - - foreach ($groupids as &$groupid) { - ipsRegistry::DB()->build(array('select' => 'g_title', 'from'=>'groups','where'=>'g_id='.$groupid)); - $result = ipsRegistry::DB()->execute(); - array_push($groups, ipsRegistry::DB()->fetch($result)); - } - } - $this->classApiServer->apiSendReply($groups); - - exit(); - } - } - - - public function addGroup( $api_key, $api_module, $group) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'addGroup' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - $result = ipsRegistry::DB()->insert("groups", array('g_title'=>$group)); - ipsRegistry::DB()->fetch($result); - - // Rebuild the group cache - ipsRegistry::cache()->rebuildCache( 'group_cache', 'global' ); - - // Regardless if it passes or fails it will only fail if it exist - $this->classApiServer->apiSendReply(array('result'=>'success')); - - exit(); - } - } - - public function addUserToGroup( $api_key, $api_module, $username, $group) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'addUserToGroup' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - $member = IPSMember::load($username,'all','username'); - $groups = explode(",", $member['mgroup_others']); - - // Group group id - ipsRegistry::DB()->build(array('select' => 'g_id', 'from' => 'groups', 'where'=>"g_title='{$group}'")); - $result = ipsRegistry::DB()->execute(); - array_push($groups, ipsRegistry::DB()->fetch($result)['g_id']); - - $groupstoadd = implode(",", $groups); - IPSMember::save( array( 'core' => array( 'field' => 'member_id', 'value' => $member['member_id'])),array('core' => array('mgroup_others'=>$groupstoadd))); - - // Rebuild the group cache - ipsRegistry::cache()->rebuildCache( 'group_cache', 'global' ); - - $this->classApiServer->apiSendReply($groups); - - exit(); - } - } - - public function removeUserFromGroup( $api_key, $api_module, $username, $group) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'removeUserFromGroup' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - $member = IPSMember::load($username,'all','username'); - $groups = explode(",", $member['mgroup_others']); - - // Group group id - ipsRegistry::DB()->build(array('select' => 'g_id', 'from' => 'groups', 'where'=>"g_title='{$group}'")); - $result = ipsRegistry::DB()->execute(); - $diffGroup = array_diff($groups, array(ipsRegistry::DB()->fetch($result)['g_id'])); - - $groupstoadd = implode(",", $diffGroup); - IPSMember::save( array( 'core' => array( 'field' => 'member_id', 'value' => $member['member_id'])),array('core' => array('mgroup_others'=>$groupstoadd))); - - // Rebuild the group cache - ipsRegistry::cache()->rebuildCache( 'group_cache', 'global' ); - - $this->classApiServer->apiSendReply($diffGroup); - - exit(); - } - } - - public function helpMe( $api_key, $api_module) - { - //----------------------------------------- - // INIT - //----------------------------------------- - - $api_key = IPSText::md5Clean( $api_key ); - $api_module = IPSText::parseCleanValue( $api_module ); - - //----------------------------------------- - // Authenticate - //----------------------------------------- - - if ( $this->__authenticate( $api_key, $api_module, 'helpMe' ) !== FALSE ) - { - - //----------------------------------------- - // Add log - //----------------------------------------- - $this->addLogging( $api_key ); - - - $this->classApiServer->apiSendReply($groups); - - exit(); - } - } - - /** - * Adds logging obviously :) - * - * @param string $api_key Authentication Key - */ - public function addLogging( $api_key ) - { - if ( ipsRegistry::$settings['xmlrpc_log_type'] != 'failed' ) - { - $this->registry->DB()->insert( 'api_log', array( 'api_log_key' => $api_key, - 'api_log_ip' => $_SERVER['REMOTE_ADDR'], - 'api_log_date' => time(), - 'api_log_query' => $this->classApiServer->raw_request, - 'api_log_allowed' => 1 ) ); - } - } - - /** - * Checks to see if the request is allowed - * - * @param string $api_key Authenticate Key - * @param string $api_module Module - * @param string $api_function Function - * @return string Error message, if any - */ - protected function __authenticate( $api_key, $api_module, $api_function ) - { - //----------------------------------------- - // Check - //----------------------------------------- - - if ( $this->api_user['api_user_id'] ) - { - $this->api_user['_permissions'] = unserialize( stripslashes( $this->api_user['api_user_perms'] ) ); - - if ( $this->api_user['_permissions'][ $api_module ][ $api_function ] == 1 ) - { - return TRUE; - } - else - { - $this->registry->DB()->insert( 'api_log', array( 'api_log_key' => $api_key, - 'api_log_ip' => $_SERVER['REMOTE_ADDR'], - 'api_log_date' => time(), - 'api_log_query' => $this->classApiServer->raw_request, - 'api_log_allowed' => 0 ) ); - - $this->classApiServer->apiSendError( '200', "API Key {$api_key} does not have permission for {$api_module}/{$api_function}" ); - - return FALSE; - } - } - else - { - $this->registry->DB()->insert( 'api_log', array( 'api_log_key' => $api_key, - 'api_log_ip' => $_SERVER['REMOTE_ADDR'], - 'api_log_date' => time(), - 'api_log_query' => $this->classApiServer->raw_request, - 'api_log_allowed' => 0 ) ); - - $this->classApiServer->apiSendError( '100', "API Key {$api_key} does not have permission for {$api_module}/{$api_function}" ); - - return FALSE; - } - } - -} \ No newline at end of file diff --git a/thirdparty/IPBoard3/aa/config.php b/thirdparty/IPBoard3/aa/config.php deleted file mode 100755 index 507ffb92..00000000 --- a/thirdparty/IPBoard3/aa/config.php +++ /dev/null @@ -1,11 +0,0 @@ - -IP.Board - Bulletin Board System - -

403: IP.Board -> Forbidden

-
-You have reached this page in error, please use your back button to return to the forum. -
- - - \ No newline at end of file diff --git a/thirdparty/IPBoard3/aa/methods.php b/thirdparty/IPBoard3/aa/methods.php deleted file mode 100755 index 40bb166b..00000000 --- a/thirdparty/IPBoard3/aa/methods.php +++ /dev/null @@ -1,125 +0,0 @@ - array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string', - 'email' => 'string', - 'display_name'=> 'string', - 'md5_passwordHash' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['deleteUser'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['disableUser'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['updateUser'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string', - 'email' => 'string', - 'md5_passwordHash' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['getAllGroups'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['getUserGroups'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['addGroup'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'group' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['addUserToGroup'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string', - 'group' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['removeUserFromGroup'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - 'username' => 'string', - 'group' => 'string' - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); - -$ALLOWED_METHODS['helpMe'] = array( - 'in' => array( - 'api_key' => 'string', - 'api_module' => 'string', - - ), - 'out' => array( - 'response' => 'xmlrpc' - ) - ); \ No newline at end of file