def resend_auth_code(self, ae, request): req = json.loads(request.body.decode('utf-8')) msg = '' if req.get('tlf'): req['tlf'] = get_cannonical_tlf(req.get('tlf')) tlf = req.get('tlf') if isinstance(tlf, str): tlf = tlf.strip() msg += check_field_type(self.tlf_definition, tlf, 'authenticate') msg += check_field_value(self.tlf_definition, tlf, 'authenticate') if msg: return self.error("Incorrect data", error_codename="invalid_credentials") try: u = User.objects.get(userdata__tlf=tlf, userdata__event=ae, is_active=True) except: return self.error("Incorrect data", error_codename="invalid_credentials") msg = check_pipeline( request, ae, 'resend-auth-pipeline', Sms.PIPELINES['resend-auth-pipeline']) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") result = plugins.call("extend_send_sms", ae, 1) if result: return self.error("Incorrect data", error_codename="invalid_credentials") send_codes.apply_async(args=[[u.id,], get_client_ip(request)]) return {'status': 'ok'}
def get(self, request, pk=None): ''' Lists all AuthEvents if not pk. If pk show the event with this pk ''' data = {'status': 'ok'} user, _, _ = get_login_user(request) if pk: e = AuthEvent.objects.get(pk=pk) if (user is not None and user.is_authenticated() and permission_required( user, 'AuthEvent', ['edit', 'view'], e.id, return_bool=True)): aes = e.serialize() else: aes = e.serialize_restrict() extend_info = plugins.call("extend_ae_info", user, e) if extend_info: for info in extend_info: aes.update(info.serialize()) data['events'] = aes else: events = AuthEvent.objects.all() aes = paginate(request, events, serialize_method='serialize_restrict', elements_name='events') data.update(aes) return json_response(data)
def census_send_auth_task(pk, ip, config=None, userids=None, **kwargs): """ Send an auth token to census """ from .models import AuthEvent, ACL e = get_object_or_404(AuthEvent, pk=pk) if e.status != "started": print("event is stopped, ignoring request..") return census = [] if userids is None: census = ACL.objects.filter(perm="vote", object_type="AuthEvent", object_id=str(pk)) census = [i.user.user.id for i in census] else: census = userids extend_errors = plugins.call("extend_send_message", e, len(census), kwargs) if extend_errors: # Only can return one error at least for now return extend_errors[0] send_codes.apply_async(args=[census, ip, config])
def get(self, request, pk=None): ''' Lists all AuthEvents if not pk. If pk show the event with this pk ''' data = {'status': 'ok'} user, _ = get_login_user(request) if pk: e = AuthEvent.objects.get(pk=pk) if (user is not None and user.is_authenticated() and permission_required( user, 'AuthEvent', 'edit', e.id, return_bool=True)): aes = e.serialize() else: aes = e.serialize_restrict() extend_info = plugins.call("extend_ae_info", user, e) if extend_info: for info in extend_info: aes.update(info.serialize()) data['events'] = aes else: events = AuthEvent.objects.all() aes = paginate(request, events, serialize_method='serialize_restrict', elements_name='events') data.update(aes) return json_response(data)
def register(self, ae, request): req = json.loads(request.body.decode('utf-8')) msg = check_pipeline(request, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") # create the user as active? Usually yes, but the execute_pipeline call inside # check_fields_in_request might modify this req['active'] = True msg = '' if req.get('tlf'): req['tlf'] = get_cannonical_tlf(req.get('tlf')) tlf = req.get('tlf') if isinstance(tlf, str): tlf = tlf.strip() msg += check_field_type(self.tlf_definition, tlf) msg += check_field_value(self.tlf_definition, tlf) msg += check_fields_in_request(req, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") # get active from req, this value might have changed in check_fields_in_requests active = req.pop('active') msg_exist = exist_user(req, ae, get_repeated=True) if msg_exist: u = msg_exist.get('user') if u.is_active: return self.error("Incorrect data", error_codename="invalid_credentials") else: u = create_user(req, ae, active) msg += give_perms(u, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") elif not active: # Note, we are not calling to extend_send_sms because we are not # sending the code in here return {'status': 'ok'} result = plugins.call("extend_send_sms", ae, 1) if result: return self.error("Incorrect data", error_codename="invalid_credentials") send_codes.apply_async(args=[[ u.id, ], get_client_ip(request)]) return {'status': 'ok'}
def get(self, request, pk=None): ''' Get user info ''' userdata = None if pk is None: pk = request.user.pk userdata = request.user.userdata permission_required(request.user, 'UserData', 'edit', pk) if userdata is None: userdata = get_object_or_404(UserData, pk=pk) data = userdata.serialize() extend_info = plugins.call("extend_user_info", userdata.user) if extend_info: for info in extend_info: data.update(info.serialize()) return json_response(data)
def post(self, request, pk): permission_required(request.user, 'AuthEvent', 'edit', pk) e = get_object_or_404(AuthEvent, pk=pk) error_kwargs = plugins.call("extend_add_census", e, request) if error_kwargs: return json_response(**error_kwargs[0]) try: data = auth_census(e, request) except: return json_response(status=400, error_codename=ErrorCodes.BAD_REQUEST) if data['status'] == 'ok': return json_response(data) else: return json_response(status=400, error_codename=data.get('error_codename'))
def post(self, request, pk): permission_required(request.user, 'AuthEvent', ['edit', 'census-add'], pk) e = get_object_or_404(AuthEvent, pk=pk) error_kwargs = plugins.call("extend_add_census", e, request) if error_kwargs: return json_response(**error_kwargs[0]) try: data = auth_census(e, request) except: return json_response(status=400, error_codename=ErrorCodes.BAD_REQUEST) if data['status'] == 'ok': return json_response(data) else: return json_response( status=400, error_codename=data.get('error_codename'))
def register(self, ae, request): req = json.loads(request.body.decode('utf-8')) msg = check_pipeline(request, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") # create the user as active? Usually yes, but the execute_pipeline call inside # check_fields_in_request might modify this req['active'] = True msg = '' if req.get('tlf'): req['tlf'] = get_cannonical_tlf(req.get('tlf')) tlf = req.get('tlf') if isinstance(tlf, str): tlf = tlf.strip() msg += check_field_type(self.tlf_definition, tlf) msg += check_field_value(self.tlf_definition, tlf) msg += check_fields_in_request(req, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") # get active from req, this value might have changed in check_fields_in_requests active = req.pop('active') msg_exist = exist_user(req, ae, get_repeated=True) if msg_exist: u = msg_exist.get('user') if u.is_active: return self.error("Incorrect data", error_codename="invalid_credentials") else: u = create_user(req, ae, active) msg += give_perms(u, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") elif not active: # Note, we are not calling to extend_send_sms because we are not # sending the code in here return {'status': 'ok'} result = plugins.call("extend_send_sms", ae, 1) if result: return self.error("Incorrect data", error_codename="invalid_credentials") send_codes.apply_async(args=[[u.id,], get_client_ip(request)]) return {'status': 'ok'}
def post(self, request, pk): if int(pk) == 0: e = 0 else: e = get_object_or_404(AuthEvent, pk=pk) extend_auth = plugins.call("extend_auth", e) if extend_auth: return extend_auth try: data = auth_authenticate(e, request) except: return HttpResponseBadRequest("", content_type='application/json') status = 200 if data['status'] == 'ok' else 400 jsondata = json.dumps(data) return HttpResponse(jsondata, status=status, content_type='application/json')
def post(self, request, pk): if int(pk) == 0: e = 0 else: e = get_object_or_404(AuthEvent, pk=pk) if not hasattr(request.user, 'account'): extend_auth = plugins.call("extend_auth", e) if extend_auth: return extend_auth[0] try: data = auth_authenticate(e, request) except: return json_response(status=400, error_codename=ErrorCodes.BAD_REQUEST) if data and 'status' in data and data['status'] == 'ok': return json_response(data) else: return json_response(status=400, message=data.get('msg'), error_codename=data.get('error_codename'))
def register(self, ae, request): req = json.loads(request.body.decode('utf-8')) msg = check_pipeline(request, ae) if msg: return msg msg = '' if req.get('tlf'): req['tlf'] = get_cannonical_tlf(req.get('tlf')) tlf = req.get('tlf') if isinstance(tlf, str): tlf = tlf.strip() msg += check_field_type(self.tlf_definition, tlf) msg += check_field_value(self.tlf_definition, tlf) msg += check_fields_in_request(req, ae) if msg: data = {'status': 'nok', 'msg': msg} return data msg_exist = exist_user(req, ae, get_repeated=True) if msg_exist: u = msg_exist.get('user') if u.is_active: msg += msg_exist.get('msg') + "Already registered." codes = Code.objects.filter(user=u.userdata).count() if codes > settings.SEND_CODES_SMS_MAX: msg += msg_exist.get('msg') + "Maximun number of codes sent." else: u = create_user(req, ae) msg += give_perms(u, ae) if msg: data = {'status': 'nok', 'msg': msg} return data result = plugins.call("extend_send_sms", ae, 1) if result: return {'status': 'nok', 'msg': result} send_codes.apply_async(args=[[ u.id, ]]) return {'status': 'ok'}
def census_send_auth_task(pk, ip, config=None, userids=None, auth_method=None, sender_uid=None, **kwargs): """ Send an auth token to census """ from .models import AuthEvent, ACL, UserData e = get_object_or_404(AuthEvent, pk=pk) # If the auth_method is not set, use the default authmethod for the election if auth_method is None: auth_method = e.auth_method new_census = [] if sender_uid is not None: print("Sender user id = %d" % sender_uid) census = [] if userids is None: new_census = ACL.objects.filter(perm="vote", object_type="AuthEvent", object_id=str(pk)) else: users = User.objects.filter(id__in=userids) userdata = UserData.objects.filter(user__in=users) new_census = ACL.objects.filter(perm="vote", object_type="AuthEvent", object_id=str(pk), user__in=userdata) census = [] if e.auth_method == auth_method: census = [i.user.user.id for i in new_census] else: for item in new_census: if "sms" == auth_method and item.user.tlf: census.append(item.user.user.id) elif "email" == auth_method and item.user.user.email: census.append(item.user.user.id) extend_errors = plugins.call("extend_send_message", e, len(census), kwargs) if extend_errors: # Only can return one error at least for now return extend_errors[0] send_codes.apply_async(args=[census, ip, auth_method, config])
def post(self, request, pk): if int(pk) == 0: e = 0 else: e = get_object_or_404(AuthEvent, pk=pk) if not hasattr(request.user, 'account'): error_kwargs = plugins.call("extend_auth", e) if error_kwargs: return json_response(**error_kwargs[0]) try: data = auth_authenticate(e, request) except: return json_response(status=400, error_codename=ErrorCodes.BAD_REQUEST) if data and 'status' in data and data['status'] == 'ok': return json_response(data) else: return json_response(status=400, error_codename=data.get('error_codename'))
def census_send_auth_task(pk, ip, config=None, userids=None): """ Send an auth token to census """ e = get_object_or_404(AuthEvent, pk=pk) if e.status != "started": print("event is stopped, ignoring request..") return census = [] if userids is None: census = ACL.objects.filter(perm="vote", object_type="AuthEvent", object_id=str(pk)) census = [i.user.user.id for i in census] else: census = userids if e.auth_method == "sms": msg = plugins.call("extend_send_sms", e, len(census)) if msg: return msg send_codes.apply_async(args=[census, ip, config])
def resend_auth_code(self, ae, request): req = json.loads(request.body.decode('utf-8')) msg = '' if req.get('tlf'): req['tlf'] = get_cannonical_tlf(req.get('tlf')) tlf = req.get('tlf') if isinstance(tlf, str): tlf = tlf.strip() msg += check_field_type(self.tlf_definition, tlf, 'authenticate') msg += check_field_value(self.tlf_definition, tlf, 'authenticate') if msg: return self.error("Incorrect data", error_codename="invalid_credentials") try: u = User.objects.get(userdata__tlf=tlf, userdata__event=ae, is_active=True) except: return self.error("Incorrect data", error_codename="invalid_credentials") msg = check_pipeline(request, ae, 'resend-auth-pipeline', Sms.PIPELINES['resend-auth-pipeline']) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") result = plugins.call("extend_send_sms", ae, 1) if result: return self.error("Incorrect data", error_codename="invalid_credentials") send_codes.apply_async(args=[[ u.id, ], get_client_ip(request)]) return {'status': 'ok'}
def post(request, pk=None): ''' Creates a new auth-event or edit auth_event create_authevent permission required or edit_authevent permission required ''' try: req = parse_json_request(request) except: return json_response( status=400, error_codename=ErrorCodes.BAD_REQUEST) if pk is None: # create real = req.get('real', False) if real: # requires create perm permission_required(request.user, 'AuthEvent', 'create') else: # requires create or create-notreal permission_required(request.user, 'AuthEvent', ['create', 'create-notreal']) auth_method = req.get('auth_method', '') msg = check_authmethod(auth_method) if msg: return json_response(status=400, message=msg) auth_method_config = { "config": METHODS.get(auth_method).CONFIG, "pipeline": METHODS.get(auth_method).PIPELINES } config = req.get('auth_method_config', None) if config: msg += check_config(config, auth_method) extra_fields = req.get('extra_fields', None) if extra_fields: msg += check_extra_fields( extra_fields, METHODS.get(auth_method).USED_TYPE_FIELDS) slug_set = set() for field in extra_fields: if 'name' in field: field['slug'] = slugify(field['name']).replace("-","_").upper() slug_set.add(field['slug']) else: msg += "some extra_fields have no name\n" if len(slug_set) != len(extra_fields): msg += "some extra_fields may have repeated slug names\n" census = req.get('census', '') # check census mode if not census in ('open', 'close'): return json_response( status=400, error_codename="INVALID_CENSUS_TYPE") error_kwargs = plugins.call("extend_type_census", census) if error_kwargs: return json_response(**error_kwargs[0]) based_in = req.get('based_in', None) if based_in and not ACL.objects.filter(user=request.user.userdata, perm='edit', object_type='AuthEvent', object_id=based_in): msg += "Invalid id to based_in" # Note that a login is only complete if a call has been received and # accepted at /authevent/<ID>/successful_login num_successful_logins_allowed = req.get( 'num_successful_logins_allowed', 0) if type(num_successful_logins_allowed) is not int: msg += "num_successful_logins_allowed invalid type" if msg: return json_response( status=400, message=msg, error_codename=ErrorCodes.BAD_REQUEST) if config: auth_method_config.get('config').update(config) ae = AuthEvent(auth_method=auth_method, auth_method_config=auth_method_config, extra_fields=extra_fields, census=census, real=real, num_successful_logins_allowed=num_successful_logins_allowed, based_in=based_in) # Save before the acl creation to get the ae id ae.save() acl = ACL(user=request.user.userdata, perm='edit', object_type='AuthEvent', object_id=ae.id) acl.save() acl = ACL(user=request.user.userdata, perm='create', object_type='UserData', object_id=ae.id) acl.save() # if necessary, generate captchas from authmethods.utils import have_captcha if have_captcha(ae): generate_captcha(settings.PREGENERATION_CAPTCHA) else: # edit permission_required(request.user, 'AuthEvent', 'edit', pk) auth_method = req.get('auth_method', '') msg = check_authmethod(auth_method) if msg: return json_response(status=400, message=msg) config = req.get('auth_method_config', None) if config: msg += check_config(config, auth_method) extra_fields = req.get('extra_fields', None) if extra_fields: msg += check_extra_fields(extra_fields) if msg: return json_response(status=400, message=msg) ae = AuthEvent.objects.get(pk=pk) ae.auth_method = auth_method if config: ae.auth_method_config.get('config').update(config) if extra_fields: ae.extra_fields = extra_fields ae.save() # TODO: Problem if object_id is None, change None by 0 acl = get_object_or_404(ACL, user=request.user.userdata, perm='edit', object_type='AuthEvent', object_id=ae.pk) data = {'status': 'ok', 'id': ae.pk, 'perm': acl.get_hmac()} return json_response(data)
def get(self, request, pk = None): data = {} extended = plugins.call("extend_get_legal", pk) if len(extended) > 0: data = extended[0] return json_response(data)
def get(self, request, pk=None): data = {} extended = plugins.call("extend_get_legal", pk) if len(extended) > 0: data = extended[0] return json_response(data)
def post(request, pk=None): ''' Creates a new auth-event or edit auth_event create_authevent permission required or edit_authevent permission required ''' try: req = parse_json_request(request) except: return json_response(status=400, error_codename=ErrorCodes.BAD_REQUEST) if pk is None: # create permission_required(request.user, 'AuthEvent', 'create') auth_method = req.get('auth_method', '') msg = check_authmethod(auth_method) if msg: return json_response(status=400, message=msg) auth_method_config = { "config": METHODS.get(auth_method).CONFIG, "pipeline": METHODS.get(auth_method).PIPELINES } config = req.get('auth_method_config', None) if config: msg += check_config(config, auth_method) extra_fields = req.get('extra_fields', None) if extra_fields: msg += check_extra_fields( extra_fields, METHODS.get(auth_method).USED_TYPE_FIELDS) census = req.get('census', '') # check census mode if not census in ('open', 'close'): return json_response(status=400, error_codename="INVALID_CENSUS_TYPE") error_kwargs = plugins.call("extend_type_census", census) if error_kwargs: return json_response(**error_kwargs[0]) real = req.get('real', False) based_in = req.get('based_in', None) if based_in and not ACL.objects.filter(user=request.user.userdata, perm='edit', object_type='AuthEvent', object_id=based_in): msg += "Invalid id to based_in" if msg: return json_response(status=400, message=msg, error_codename=ErrorCodes.BAD_REQUEST) if config: auth_method_config.get('config').update(config) ae = AuthEvent(auth_method=auth_method, auth_method_config=auth_method_config, extra_fields=extra_fields, census=census, real=real, based_in=based_in) # Save before the acl creation to get the ae id ae.save() acl = ACL(user=request.user.userdata, perm='edit', object_type='AuthEvent', object_id=ae.id) acl.save() acl = ACL(user=request.user.userdata, perm='create', object_type='UserData', object_id=ae.id) acl.save() # if necessary, generate captchas from authmethods.utils import have_captcha if have_captcha(ae): generate_captcha(settings.PREGENERATION_CAPTCHA) else: # edit permission_required(request.user, 'AuthEvent', 'edit', pk) auth_method = req.get('auth_method', '') msg = check_authmethod(auth_method) if msg: return json_response(status=400, message=msg) config = req.get('auth_method_config', None) if config: msg += check_config(config, auth_method) extra_fields = req.get('extra_fields', None) if extra_fields: msg += check_extra_fields(extra_fields) if msg: return json_response(status=400, message=msg) ae = AuthEvent.objects.get(pk=pk) ae.auth_method = auth_method if config: ae.auth_method_config.get('config').update(config) if extra_fields: ae.extra_fields = extra_fields ae.save() # TODO: Problem if object_id is None, change None by 0 acl = get_object_or_404(ACL, user=request.user.userdata, perm='edit', object_type='AuthEvent', object_id=ae.pk) data = {'status': 'ok', 'id': ae.pk, 'perm': acl.get_hmac()} return json_response(data)
def register(self, ae, request): req = json.loads(request.body.decode('utf-8')) msg = check_pipeline(request, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") # create the user as active? Usually yes, but the execute_pipeline call inside # check_fields_in_request might modify this req['active'] = True reg_match_fields = [] if ae.extra_fields is not None: reg_match_fields = [ f for f in ae.extra_fields if "match_census_on_registration" in f and f['match_census_on_registration'] ] # NOTE the fields of type "fill_if_empty_on_registration" need # to be empty, otherwise the user is already registered. reg_fill_empty_fields = [] if ae.extra_fields is not None: reg_fill_empty_fields = [ f for f in ae.extra_fields if "fill_if_empty_on_registration" in f and f['fill_if_empty_on_registration'] ] msg = '' if req.get('tlf'): req['tlf'] = get_cannonical_tlf(req.get('tlf')) tlf = req.get('tlf') if isinstance(tlf, str): tlf = tlf.strip() msg += check_field_type(self.tlf_definition, tlf) msg += check_field_value(self.tlf_definition, tlf) msg += check_fields_in_request(req, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") # get active from req, this value might have changed in check_fields_in_requests active = req.pop('active') if len(reg_match_fields) > 0 or len(reg_fill_empty_fields) > 0: # is the tlf a match field? match_tlf = False match_tlf_element = None for extra in ae.extra_fields: if 'name' in extra and 'tlf' == extra['name'] and "match_census_on_registration" in extra and extra['match_census_on_registration']: match_tlf = True match_tlf_element = extra break # if the tlf is not a match field, and there already is a user # with that tlf, reject the registration request if not match_tlf and User.objects.filter(userdata__tlf=tlf, userdata__event=ae, is_active=True).count() > 0: return self.error("Incorrect data", error_codename="invalid_credentials") # lookup in the database if there's any user with the match fields # NOTE: we assume reg_match_fields are unique in the DB and required search_tlf = tlf if match_tlf else "" if match_tlf: reg_match_fields.remove(match_tlf_element) q = Q(userdata__event=ae, is_active=False, userdata__tlf=search_tlf) # Check the reg_match_fields for reg_match_field in reg_match_fields: # Filter with Django's JSONfield reg_name = reg_match_field['name'] req_field_data = req.get(reg_name) if reg_name and req_field_data: q = q & Q(userdata__metadata__contains={reg_name: req_field_data}) else: return self.error("Incorrect data", error_codename="invalid_credentials") # Check that the reg_fill_empty_fields are empty, otherwise the user # is already registered for reg_empty_field in reg_fill_empty_fields: # Filter with Django's JSONfield reg_name = reg_empty_field['name'] # Note: the register query _must_ contain a value for these fields if reg_name and reg_name in req and req[reg_name]: q = q & Q(userdata__metadata__contains={reg_name: ""}) else: return self.error("Incorrect data", error_codename="invalid_credentials") user_found = None user_list = User.objects.filter(q) if 1 == len(user_list): user_found = user_list[0] # check that the unique:True extra fields are actually unique uniques = [] for extra in ae.extra_fields: if 'unique' in extra.keys() and extra.get('unique'): uniques.append(extra['name']) if len(uniques) > 0: base_uq = Q(userdata__event=ae, is_active=True) base_list = User.objects.exclude(id = user_found.id) for reg_name in uniques: req_field_data = req.get(reg_name) if reg_name and req_field_data: uq = base_q & Q(userdata__metadata__contains={reg_name: req_field_data}) repeated_list = base_list.filter(uq) if repeated_list.count() > 0: return self.error("Incorrect data", error_codename="invalid_credentials") # user needs to exist if user_found is None: return self.error("Incorrect data", error_codename="invalid_credentials") for reg_empty_field in reg_fill_empty_fields: reg_name = reg_empty_field['name'] if reg_name in req: user_found.userdata.metadata[reg_name] = req.get(reg_name) user_found.userdata.save() if not match_tlf: user_found.userdata.tlf = tlf user_found.userdata.save() u = user_found else: msg_exist = exist_user(req, ae, get_repeated=True) if msg_exist: return self.error("Incorrect data", error_codename="invalid_credentials") else: u = create_user(req, ae, active) msg += give_perms(u, ae) if msg: return self.error("Incorrect data", error_codename="invalid_credentials") elif not active: # Note, we are not calling to extend_send_sms because we are not # sending the code in here return {'status': 'ok'} result = plugins.call("extend_send_sms", ae, 1) if result: return self.error("Incorrect data", error_codename="invalid_credentials") send_codes.apply_async(args=[[u.id,], get_client_ip(request),'sms']) return {'status': 'ok'}