Skip to content
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

21537 - Add in keycloak user fetch for role #3043

Merged
merged 3 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions auth-api/src/auth_api/resources/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .documents_affidavit import bp as documents_affidavit_bp
from .entity import bp as entity_bp
from .invitation import bp as invitation_bp
from .keycloak import bp as keycloak_bp
from .meta import bp as meta_bp
from .notifications import bp as notifications_bp
from ..ops import bp as ops_bp
Expand Down Expand Up @@ -63,6 +64,7 @@ def init_app(self, app):
self.app.register_blueprint(documents_affidavit_bp)
self.app.register_blueprint(entity_bp)
self.app.register_blueprint(invitation_bp)
self.app.register_blueprint(keycloak_bp)
self.app.register_blueprint(meta_bp)
self.app.register_blueprint(notifications_bp)
self.app.register_blueprint(ops_bp)
Expand Down
43 changes: 43 additions & 0 deletions auth-api/src/auth_api/resources/v1/keycloak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Keycloak resource, will ultimately get swapped out."""
# Copyright © 2024 Province of British Columbia
#
# Licensed under the Apache License, Version 2.0 (the 'License');
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an 'AS IS' BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Note this will be depreciated and replaced shortly.

from flask import Blueprint, jsonify, request
from flask_cors import cross_origin

from auth_api import status as http_status
from auth_api.auth import jwt as _jwt
from auth_api.exceptions import BusinessException
from auth_api.services.keycloak import KeycloakService
from auth_api.utils.endpoints_enums import EndpointEnum
from auth_api.utils.roles import Role

bp = Blueprint('KEYCLOAK', __name__, url_prefix=f'{EndpointEnum.API_V1.value}/keycloak')


@bp.route('/users', methods=['GET', 'OPTIONS'])
@cross_origin(origins='*', methods=['GET'])
@_jwt.has_one_of_roles([Role.SYSTEM.value])
def get_keycloak_users_by_role():
"""Return keycloak name + email by role."""
role = request.args.get('role', None)
if role is None:
response, status = {'message': 'Role query parameter is required'}, http_status.HTTP_400_BAD_REQUEST
try:
response, status = KeycloakService.get_user_emails_with_role(role), http_status.HTTP_200_OK
except BusinessException as exception:
response, status = {'code': exception.code, 'message': exception.message}, exception.status_code
return jsonify(response), status
26 changes: 26 additions & 0 deletions auth-api/src/auth_api/services/keycloak.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,32 @@ async def add_or_remove_users_from_group(kgs: List[KeycloakGroupSubscription]):
elif task.status != 204:
current_app.logger.error(f'Returned non 204: {task.method} - {task.url} - {task.status}')

@staticmethod
def get_user_emails_with_role(role: str):
"""Get user emails with the role name."""
config = current_app.config
base_url = config.get('KEYCLOAK_BASE_URL')
realm = config.get('KEYCLOAK_REALMNAME')
timeout = config.get('CONNECT_TIMEOUT', 60)
admin_token = KeycloakService._get_admin_token()

headers = {
'Content-Type': ContentType.JSON.value,
'Authorization': f'Bearer {admin_token}'
}

users = []
get_role_users = f'{base_url}/auth/admin/realms/{realm}/roles/{role}/users'
response = requests.get(get_role_users, headers=headers, timeout=timeout)
if response.status_code == 404:
raise BusinessException(Error.DATA_NOT_FOUND, None)
response.raise_for_status()
for user in response.json():
users.append({'firstName': user['firstName'],
'lastName': user['lastName'],
'email': user['email']})
return users

@staticmethod
def add_user_to_group(user_id: str, group_name: str):
"""Add user to the keycloak group."""
Expand Down
Loading