def check_user_login(request): if len(request.body): request_body = dict([x.split("=") for x in request.body.split("&")]) user_id = int(request_body['user_id']) if request_body.get('user_id', '').isdigit() else None if user_id: try: nih_user = NIH_User.objects.get(user_id=user_id) except (MultipleObjectsReturned, ObjectDoesNotExist), e: logger.debug('Error when retrieving nih_user with user_id ' + str(user_id) + ': ' + str(e)) return HttpResponse('') expire_time = nih_user.NIH_assertion_expiration expire_time = expire_time if expire_time.tzinfo is not None else pytz.utc.localize(expire_time) now_in_utc = pytz.utc.localize(datetime.datetime.now()) if (expire_time - now_in_utc).total_seconds() <= 0: # take user off ACL_GOOGLE_GROUP, without bothering to check if user is dbGaP_authorized or not directory_service, directory_http_auth = get_directory_resource() user_email = User.objects.get(id=user_id).email try: logger.info('user ' + str(user_email) + ' being removed from ACL_GOOGLE_GROUP') result = directory_service.members().delete( groupKey=ACL_GOOGLE_GROUP, memberKey=user_email).execute(http=directory_http_auth) except HttpError, e: logger.debug(user_email + ' was not removed from ACL_GOOGLE_GROUP: ' + str(e)) nih_user.active = False nih_user.dbGaP_authorized = False nih_user.save() logger.info('User with NIH username ' + str(nih_user.NIH_username) + ' is deactivated in NIH_User table')
def remove_user_from_ACL(request, nih_username): edit_dbGaP_authentication_list(nih_username) if request.user.is_superuser: try: nih_user = NIH_User.objects.get(NIH_username=nih_username) user = User.objects.get(id=nih_user.user_id) email = user.email except (ObjectDoesNotExist, MultipleObjectsReturned), e: logger.error("Error when attempting to emergency remove NIH username {} from ACL: {}".format(nih_username, e)) return HttpResponse("Error when attempting to emergency remove NIH username {} from ACL: {}".format(nih_username, e)) service, http_auth = get_directory_resource() try: result = service.members().delete( groupKey=ACL_GOOGLE_GROUP, memberKey=email ).execute(http=http_auth) logger.info(result) except HttpError as e: logger.error("Error when attempting to emergency remove NIH username {} from ACL: {}".format(nih_username, e)) return HttpResponse("HttpError when attempting to emergency remove NIH username {nih_username} with email {email} from ACL.".format( nih_username=nih_username, email=email)) logger.warn("Successfully emergency removed user with NIH username {nih_username} and email {email} from ACL.".format( nih_username=nih_username, email=email)) # also deactivate NIH user in NIH_User table nih_user.active = False nih_user.dbGaP_authorized = False nih_user.save() logger.warn("Successfully emergency deactivated user with NIH username {nih_username} and email {email} from NIH_User table.".format( nih_username=nih_username, email=email)) edit_dbGaP_authentication_list(nih_username) return HttpResponse("Successfully removed user with NIH username {nih_username} and email {email} from ACL.".format( nih_username=nih_username, email=email))
def is_dbgap_authorized(user_email): directory_service, http_auth = get_directory_resource() try: directory_service.members().get(groupKey=CONTROLLED_ACL_GOOGLE_GROUP, memberKey=user_email).execute(http=http_auth) return True except HttpError, e: return False
def user_landing(request): directory_service, http_auth = get_directory_resource() user_email = User.objects.get(id=request.user.id).email # add user to isb-cgc-open if they are not already on the group try: body = {"email": user_email, "role": "MEMBER"} directory_service.members().insert(groupKey=OPEN_ACL_GOOGLE_GROUP, body=body).execute(http=http_auth) except HttpError, e: logger.info(e)
def unlink_accounts(request): directory_service, http_auth = get_directory_resource() try: nih_account_to_unlink = NIH_User.objects.get(user_id=request.user.id) nih_account_to_unlink.delete() # todo: delete from google group except (ObjectDoesNotExist, MultipleObjectsReturned), e: if type(e) is MultipleObjectsReturned: logger.warn("Error %s: more than one NIH User account linked to user id %d" % (str(e), request.user.id)) NIH_User.objects.filter(user_id=request.user.id).delete()
def user_landing(request): directory_service, http_auth = get_directory_resource() user_email = User.objects.get(id=request.user.id).email # add user to isb-cgc-open if they are not already on the group try: body = { "email": user_email, "role": "MEMBER" } directory_service.members().insert( groupKey=OPEN_ACL_GOOGLE_GROUP, body=body ).execute(http=http_auth) except HttpError, e: logger.info(e)
def scrub_nih_users(dbGaP_authorized_list): rows = [row.strip() for row in dbGaP_authorized_list.split('\n') if row.strip()] directory_service, directory_http_auth = get_directory_resource() result = directory_service.members().list(groupKey=ACL_GOOGLE_GROUP).execute(http=directory_http_auth) members = [] if 'members' not in result else result['members'] # loop through everyone in ACL_GOOGLE_GROUP for member in members: email = member['email'] logger.info("Checking user {} on ACL_GOOGLE_GROUP list".format(email)) if email.endswith('@developer.gserviceaccount.com'): continue # ignore emails that are actually service accounts try: # get user id from email user_id = User.objects.get(email=email).id # get nih_username from user id nih_user = NIH_User.objects.get(user_id=user_id) nih_username = nih_user.NIH_username is_on_new_nih_authorized_list = matching_row_exists(rows, 'login', nih_username) # verify that nih_username is in one of the rows, that the nih_user is dbGaP authorized, and that the nih_user is active if not is_on_new_nih_authorized_list or not nih_user.dbGaP_authorized or not nih_user.active: # remove from ACL_GOOGLE_GROUP directory_service.members().delete(groupKey=ACL_GOOGLE_GROUP, memberKey=email).execute(http=directory_http_auth) if not nih_user.dbGaP_authorized or not nih_user.active: logger.warn("Deleted user {} from the controlled-access google group " "because strangely their entry in the database had dbGaP_authorized={} and active={}" .format(email, str(nih_user.dbGaP_authorized), str(nih_user.active))) if not is_on_new_nih_authorized_list: logger.warn("Deleted user {} from the controlled-access google group " "because a matching entry was not found in the dbGaP authorized list.".format(email)) nih_user.dbGaP_authorized = False nih_user.save() logger.warn("Changed NIH user {}'s dbGaP_authorized to False.".format(nih_username)) # if that user is somehow on ACL_GOOGLE_GROUP but has 0 or plural entries in User or NIH_User except (MultipleObjectsReturned, ObjectDoesNotExist), e: logger.warn("Strangely, there was a problem getting either {}'s user id or their NIH username: {}".format(email, str(e))) # remove from ACL_GOOGLE_GROUP directory_service.members().delete(groupKey=ACL_GOOGLE_GROUP, memberKey=email).execute(http=directory_http_auth) continue
def user_landing(request): directory_service, http_auth = get_directory_resource() user_email = User.objects.get(id=request.user.id).email # add user to isb-cgc-open if they are not already on the group try: body = { "email": user_email, "role": "MEMBER" } directory_service.members().insert( groupKey=OPEN_ACL_GOOGLE_GROUP, body=body ).execute(http=http_auth) except HttpError as e: logger.info(e) if debug: logger.debug('Called '+sys._getframe().f_code.co_name) # check to see if user has read access to 'All TCGA Data' cohort isb_superuser = User.objects.get(username='******') superuser_perm = Cohort_Perms.objects.get(user=isb_superuser) user_all_data_perm = Cohort_Perms.objects.filter(user=request.user, cohort=superuser_perm.cohort) if not user_all_data_perm: Cohort_Perms.objects.create(user=request.user, cohort=superuser_perm.cohort, perm=Cohort_Perms.READER) # add_data_cohort = Cohort.objects.filter(name='All TCGA Data') users = User.objects.filter(is_superuser=0) cohort_perms = Cohort_Perms.objects.filter(user=request.user).values_list('cohort', flat=True) cohorts = Cohort.objects.filter(id__in=cohort_perms, active=True).order_by('-last_date_saved').annotate(num_cases=Count('samples__case_barcode')) for item in cohorts: item.perm = item.get_perm(request).get_perm_display() item.owner = item.get_owner() # print local_zone.localize(item.last_date_saved) # viz_perms = Viz_Perms.objects.filter(user=request.user).values_list('visualization', flat=True) visualizations = SavedViz.objects.generic_viz_only(request).order_by('-last_date_saved') for item in visualizations: item.perm = item.get_perm(request).get_perm_display() item.owner = item.get_owner() seqpeek_viz = SavedViz.objects.seqpeek_only(request).order_by('-last_date_saved') for item in seqpeek_viz: item.perm = item.get_perm(request).get_perm_display() item.owner = item.get_owner() # Used for autocomplete listing cohort_listing = Cohort.objects.filter(id__in=cohort_perms, active=True).values('id', 'name') for cohort in cohort_listing: cohort['value'] = int(cohort['id']) cohort['label'] = cohort['name'].encode('utf8') del cohort['id'] del cohort['name'] return render(request, 'GenespotRE/user_landing.html', {'request': request, 'cohorts': cohorts, 'user_list': users, 'cohorts_listing': cohort_listing, 'visualizations': visualizations, 'seqpeek_list': seqpeek_viz, 'base_url': settings.BASE_URL, 'base_api_url': settings.BASE_API_URL })
# deactivate NIH_username entry if exists try: nih_user = NIH_User.objects.get(user_id=request.user.id) nih_user.active = False nih_user.dbGaP_authorized = False nih_user.save() logger.info("NIH user {} inactivated".format(nih_user.NIH_username)) except (ObjectDoesNotExist, MultipleObjectsReturned), e: if type(e) is MultipleObjectsReturned: logger.warn("Error %s on logout: more than one NIH User with user id %d" % (str(e), request.user.id)) # remove from CONTROLLED_ACL_GOOGLE_GROUP if exists user_email = User.objects.get(id=request.user.id).email delete_success = False try: directory_service, http_auth = get_directory_resource() directory_service.members().delete(groupKey=CONTROLLED_ACL_GOOGLE_GROUP, memberKey=str(user_email)).execute(http=http_auth) logger.info("Attempting to delete user {} from group {}. " "If an error message doesn't follow, they were successfully deleted" .format(str(user_email), CONTROLLED_ACL_GOOGLE_GROUP)) delete_success = True except HttpError, e: logger.info(e) except IOError, e : logger.info(e) # add user to OPEN_ACL_GOOGLE_GROUP if they are not yet on it if delete_success : try: body = {"email": user_email, "role": "MEMBER"}
def index(request): req = prepare_django_request(request) auth = init_saml_auth(req) errors = [] not_auth_warn = False success_slo = False attributes = False paint_logout = False if 'sso' in req['get_data']: if 'redirect_url' in req['get_data']: return HttpResponseRedirect(auth.login(return_to=req['get_data']['redirect_url'])) else: return HttpResponseRedirect(auth.login()) elif 'sso2' in req['get_data']: return_to = OneLogin_Saml2_Utils.get_self_url(req) + reverse('attrs') return HttpResponseRedirect(auth.login(return_to)) elif 'slo' in req['get_data']: name_id = None session_index = None if 'samlNameId' in request.session: name_id = request.session['samlNameId'] if 'samlSessionIndex' in request.session: session_index = request.session['samlSessionIndex'] # update record of user in table accounts_nih_user # so that active=0 # and dbGaP_authorized=0 return HttpResponseRedirect(auth.logout(name_id=name_id, session_index=session_index)) elif 'acs' in req['get_data']: auth.process_response() errors = auth.get_errors() if errors: logger.info('executed auth.get_errors(). errors are:') logger.warn(errors) logger.info('error is because') logger.warn(auth.get_last_error_reason()) not_auth_warn = not auth.is_authenticated() if not errors: request.session['samlUserdata'] = auth.get_attributes() request.session['samlNameId'] = auth.get_nameid() NIH_username = request.session['samlNameId'] request.session['samlSessionIndex'] = auth.get_session_index() user_email = User.objects.get(id=request.user.id).email # check to see if user already has authenticated through # another NIH_username. If so, don't allow the same google email # to be linked to two different NIH usernames nih_usernames_already_linked_to_google_identity = NIH_User.objects.filter(user_id=request.user.id) for nih_user in nih_usernames_already_linked_to_google_identity: if nih_user.NIH_username != NIH_username: logger.warn("User {} is already linked to the eRA commons identity {} and attempted authentication" " with the eRA commons identity {}." .format(user_email, nih_user.NIH_username, NIH_username)) messages.warning(request, "User {} is already linked to the eRA commons identity {}. " "Please unlink these before authenticating with the eRA commons identity {}." .format(user_email, nih_user.NIH_username, NIH_username)) return redirect('/users/' + str(request.user.id)) # check if there is another google identity with the same NIH_username try: preexisting_nih_user = NIH_User.objects.get(NIH_username=NIH_username) if preexisting_nih_user.user_id != request.user.id: logger.warn("User id {} tried to log into the NIH account {} that is already linked to user {}".format( user_email, NIH_username, preexisting_nih_user.user_id )) messages.warning(request, "You tried to log into an NIH account that is linked to another google email address.") return redirect('/users/' + str(request.user.id)) except (ObjectDoesNotExist, MultipleObjectsReturned), e: # only redirect if there is a MultipleObjectsReturned error if type(e) is MultipleObjectsReturned: logger.error("Error %s on NIH login: more than one NIH User with NIH_username %s" % (str(e), NIH_username)) return redirect('/users/' + str(request.user.id)) storage_client = get_storage_resource() # check authenticated NIH username against NIH authentication list is_dbGaP_authorized = check_NIH_authorization_list(NIH_username, storage_client) saml_response = None if 'SAMLResponse' not in req['post_data'] else req['post_data']['SAMLResponse'] saml_response = saml_response.replace('\r\n', '') NIH_assertion_expiration = datetime.datetime.now() + datetime.timedelta(days=1) updated_values = { 'NIH_assertion': saml_response, 'NIH_assertion_expiration': pytz.utc.localize(NIH_assertion_expiration), 'dbGaP_authorized': is_dbGaP_authorized, 'user_id': request.user.id, 'active': 1 } nih_user, created = NIH_User.objects.update_or_create(NIH_username=NIH_username, user_id=request.user.id, defaults=updated_values) logger.info("NIH_User.objects.update_or_create() returned nih_user: {} and created: {}".format( str(nih_user.NIH_username), str(created))) # add or remove user from ACL_GOOGLE_GROUP if they are or are not dbGaP authorized directory_client, http_auth = get_directory_resource() # default warn message is for eRA Commons users who are not dbGaP authorized warn_message = ''' WARNING NOTICE You are accessing a US Government web site which may contain information that must be protected under the US Privacy Act or other sensitive information and is intended for Government authorized use only. Unauthorized attempts to upload information, change information, or use of this web site may result in disciplinary action, civil, and/or criminal penalties. Unauthorized users of this website should have no expectation of privacy regarding any communications or data processed by this website. Anyone accessing this website expressly consents to monitoring of their actions and all communications or data transiting or stored on related to this website and is advised that if such monitoring reveals possible evidence of criminal activity, NIH may provide that evidence to law enforcement officials. ''' if is_dbGaP_authorized: # if user is dbGaP authorized, warn message is different warn_message = 'You are reminded that when accessing controlled access information you are bound by the dbGaP TCGA DATA USE CERTIFICATION AGREEMENT (DUCA).' + warn_message try: result = directory_client.members().get(groupKey=ACL_GOOGLE_GROUP, memberKey=user_email).execute(http=http_auth) # if the user is in the google group but isn't dbGaP authorized, delete member from group if len(result) and not is_dbGaP_authorized: directory_client.members().delete(groupKey=ACL_GOOGLE_GROUP, memberKey=user_email).execute(http=http_auth) logger.warn("User {} was deleted from group {} because they don't have dbGaP authorization.".format(user_email, ACL_GOOGLE_GROUP)) # if the user_email doesn't exist in the google group an HttpError will be thrown... except HttpError: # ...if the user is dbGaP authorized they should be added to the ACL_GOOGLE_GROUP if is_dbGaP_authorized: body = { "email": user_email, "role": "MEMBER" } result = directory_client.members().insert( groupKey=ACL_GOOGLE_GROUP, body=body ).execute(http=http_auth) logger.info(result) logger.info("User {} added to {}.".format(user_email, ACL_GOOGLE_GROUP)) # Add task in queue to deactivate NIH_User entry after NIH_assertion_expiration has passed. try: task = Task(url=CHECK_NIH_USER_LOGIN_TASK_URI, params={'user_id': request.user.id, 'deployment': CRON_MODULE}, countdown=COUNTDOWN_SECONDS) task.add(queue_name=LOGOUT_WORKER_TASKQUEUE) logger.info('enqueued check_login task for user, {}, for {} hours from now'.format( request.user.id, COUNTDOWN_SECONDS / (60*60))) except Exception as e: logger.error("Failed to enqueue automatic logout task") logging.exception(e) messages.info(request, warn_message) return HttpResponseRedirect(auth.redirect_to('https://{}'.format(req['http_host'])))
def index(request): req = prepare_django_request(request) auth = init_saml_auth(req) errors = [] not_auth_warn = False success_slo = False attributes = False paint_logout = False if 'sso' in req['get_data']: if 'redirect_url' in req['get_data']: return HttpResponseRedirect(auth.login(return_to=req['get_data']['redirect_url'])) else: return HttpResponseRedirect(auth.login()) elif 'sso2' in req['get_data']: return_to = OneLogin_Saml2_Utils.get_self_url(req) + reverse('attrs') return HttpResponseRedirect(auth.login(return_to)) elif 'slo' in req['get_data']: name_id = None session_index = None if 'samlNameId' in request.session: name_id = request.session['samlNameId'] if 'samlSessionIndex' in request.session: session_index = request.session['samlSessionIndex'] # update record of user in table accounts_nih_user # so that active=0 # and dbGaP_authorized=0 return HttpResponseRedirect(auth.logout(name_id=name_id, session_index=session_index)) elif 'acs' in req['get_data']: auth.process_response() errors = auth.get_errors() if errors: logger.info('executed auth.get_errors(). errors are:') logger.warn(errors) logger.info('error is because') logger.warn(auth.get_last_error_reason()) not_auth_warn = not auth.is_authenticated() if not errors: request.session['samlUserdata'] = auth.get_attributes() request.session['samlNameId'] = auth.get_nameid() NIH_username = request.session['samlNameId'] request.session['samlSessionIndex'] = auth.get_session_index() user_email = User.objects.get(id=request.user.id).email # 1. check if this google identity is currently linked to other NIH usernames # note: the NIH username exclusion is case-insensitive so this will not return a false positive # e.g. if this google identity is linked to 'NIHUSERNAME1' but just authenticated with 'nihusername1', # it will still pass this test nih_usernames_already_linked_to_this_google_identity = NIH_User.objects.filter( user_id=request.user.id, linked=True).exclude(NIH_username__iexact=NIH_username) for nih_user in nih_usernames_already_linked_to_this_google_identity: if nih_user.NIH_username.lower() != NIH_username.lower(): logger.warn("User {} is already linked to the eRA commons identity {} and attempted authentication" " with the eRA commons identity {}." .format(user_email, nih_user.NIH_username, NIH_username)) messages.warning(request, "User {} is already linked to the eRA commons identity {}. " "Please unlink these before authenticating with the eRA commons " "identity {}.".format(user_email, nih_user.NIH_username, NIH_username)) return redirect('/users/' + str(request.user.id)) # 2. check if there are other google identities that are still linked to this NIH_username # note: the NIH username match is case-insensitive so this will not return a false negative. # e.g. if a different google identity is linked to 'NIHUSERNAME1' and this google identity just authenticated with 'nihusername1', # this will fail the test and return to the /users/ url with a warning message preexisting_nih_users = NIH_User.objects.filter( NIH_username__iexact=NIH_username, linked=True).exclude(user_id=request.user.id) if len(preexisting_nih_users) > 0: preexisting_nih_user_user_ids = [preexisting_nih_user.user_id for preexisting_nih_user in preexisting_nih_users] prelinked_user_email_list = [user.email for user in User.objects.filter(id__in=preexisting_nih_user_user_ids)] prelinked_user_emails = ', '.join(prelinked_user_email_list) logger.warn("User {} tried to log into the NIH account {} that is already linked to user(s) {}".format( user_email, NIH_username, prelinked_user_emails + '.' )) messages.warning(request, "You tried to log into an NIH account that is linked to another google email address.") return redirect('/users/' + str(request.user.id)) storage_client = get_storage_resource() # check authenticated NIH username against NIH authentication list is_dbGaP_authorized = check_NIH_authorization_list(NIH_username, storage_client) saml_response = None if 'SAMLResponse' not in req['post_data'] else req['post_data']['SAMLResponse'] saml_response = saml_response.replace('\r\n', '') NIH_assertion_expiration = datetime.datetime.now() + datetime.timedelta(days=1) updated_values = { 'NIH_assertion': saml_response, 'NIH_assertion_expiration': pytz.utc.localize(NIH_assertion_expiration), 'dbGaP_authorized': is_dbGaP_authorized, 'user_id': request.user.id, 'active': 1, 'linked': True } nih_user, created = NIH_User.objects.update_or_create(NIH_username=NIH_username, user_id=request.user.id, defaults=updated_values) logger.info("NIH_User.objects.update_or_create() returned nih_user: {} and created: {}".format( str(nih_user.NIH_username), str(created))) # add or remove user from ACL_GOOGLE_GROUP if they are or are not dbGaP authorized directory_client, http_auth = get_directory_resource() # default warn message is for eRA Commons users who are not dbGaP authorized warn_message = ''' WARNING NOTICE You are accessing a US Government web site which may contain information that must be protected under the US Privacy Act or other sensitive information and is intended for Government authorized use only. Unauthorized attempts to upload information, change information, or use of this web site may result in disciplinary action, civil, and/or criminal penalties. Unauthorized users of this website should have no expectation of privacy regarding any communications or data processed by this website. Anyone accessing this website expressly consents to monitoring of their actions and all communications or data transiting or stored on related to this website and is advised that if such monitoring reveals possible evidence of criminal activity, NIH may provide that evidence to law enforcement officials. ''' if is_dbGaP_authorized: # if user is dbGaP authorized, warn message is different warn_message = 'You are reminded that when accessing controlled access information you are bound by the dbGaP TCGA DATA USE CERTIFICATION AGREEMENT (DUCA).' + warn_message try: result = directory_client.members().get(groupKey=ACL_GOOGLE_GROUP, memberKey=user_email).execute(http=http_auth) # if the user is in the google group but isn't dbGaP authorized, delete member from group if len(result) and not is_dbGaP_authorized: directory_client.members().delete(groupKey=ACL_GOOGLE_GROUP, memberKey=user_email).execute(http=http_auth) logger.warn("User {} was deleted from group {} because they don't have dbGaP authorization.".format(user_email, ACL_GOOGLE_GROUP)) # if the user_email doesn't exist in the google group an HttpError will be thrown... except HttpError: # ...if the user is dbGaP authorized they should be added to the ACL_GOOGLE_GROUP if is_dbGaP_authorized: body = { "email": user_email, "role": "MEMBER" } result = directory_client.members().insert( groupKey=ACL_GOOGLE_GROUP, body=body ).execute(http=http_auth) logger.info(result) logger.info("User {} added to {}.".format(user_email, ACL_GOOGLE_GROUP)) # Add task in queue to deactivate NIH_User entry after NIH_assertion_expiration has passed. try: task = Task(url=CHECK_NIH_USER_LOGIN_TASK_URI, params={'user_id': request.user.id, 'deployment': CRON_MODULE}, countdown=COUNTDOWN_SECONDS) task.add(queue_name=LOGOUT_WORKER_TASKQUEUE) logger.info('enqueued check_login task for user, {}, for {} hours from now'.format( request.user.id, COUNTDOWN_SECONDS / (60*60))) except Exception as e: logger.error("Failed to enqueue automatic logout task") logging.exception(e) messages.info(request, warn_message) return HttpResponseRedirect(auth.redirect_to('https://{}'.format(req['http_host']))) elif 'sls' in req['get_data']: dscb = lambda: request.session.flush() url = auth.process_slo(delete_session_cb=dscb) errors = auth.get_errors() if len(errors) == 0: if url is not None: return HttpResponseRedirect(url) else: success_slo = True if 'samlUserdata' in request.session: paint_logout = True if len(request.session['samlUserdata']) > 0: attributes = request.session['samlUserdata'].items() return render_to_response('demo/index.html', {'errors': errors, 'not_auth_warn': not_auth_warn, 'success_slo': success_slo, 'attributes': attributes, 'paint_logout': paint_logout}, context_instance=RequestContext(request))