Esempio n. 1
0
def client_activate(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	did_fail = True
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True))
	link_id = int(cfg.get('netprofile.client.registration.link_id', 1))
	rand_len = int(cfg.get('netprofile.client.registration.code_length', 20))
	if (not can_reg) or (not must_verify):
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	code = request.GET.get('code', '').strip().upper()
	login = request.GET.get('for', '')
	if code and login and (len(code) == rand_len):
		sess = DBSession()
		for link in sess.query(AccessEntityLink)\
				.options(joinedload(AccessEntityLink.entity))\
				.filter(AccessEntityLink.type_id == link_id, AccessEntityLink.value == code):
			# TODO: implement code timeouts
			ent = link.entity
			if (ent.access_state == AccessState.block_inactive.value) and (ent.nick == login):
				ent.access_state = AccessState.ok.value
				sess.delete(link)
				did_fail = False
				break
	tpldef = {
		'failed'         : did_fail,
		'comb_js'        : comb_js,
		'cur_loc'        : cur_locale
	}
	request.run_hook('access.cl.tpldef.activate', tpldef, request)
	return tpldef
Esempio n. 2
0
def client_activate(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	did_fail = True
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True))
	link_id = int(cfg.get('netprofile.client.registration.link_id', 1))
	rand_len = int(cfg.get('netprofile.client.registration.code_length', 20))
	if (not can_reg) or (not must_verify):
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	code = request.GET.get('code', '').strip().upper()
	login = request.GET.get('for', '')
	if code and login and (len(code) == rand_len):
		sess = DBSession()
		for link in sess.query(AccessEntityLink)\
				.options(joinedload(AccessEntityLink.entity))\
				.filter(AccessEntityLink.type_id == link_id, AccessEntityLink.value == code):
			# TODO: implement code timeouts
			ent = link.entity
			if (ent.access_state == AccessState.block_inactive.value) and (ent.nick == login):
				ent.access_state = AccessState.ok.value
				sess.delete(link)
				did_fail = False
				break
	tpldef = {
		'failed'         : did_fail,
		'comb_js'        : comb_js,
		'cur_loc'        : cur_locale
	}
	request.run_hook('access.cl.tpldef.activate', tpldef, request)
	return tpldef
Esempio n. 3
0
def do_login(request):
	if authenticated_userid(request):
		return HTTPFound(location=request.route_url('core.home'))
	login = ''
	did_fail = False
	cur_locale = locale_neg(request)
	if 'submit' in request.POST:
		login = request.POST.get('user', '')
		passwd = request.POST.get('pass', '')
		csrf = request.POST.get('csrf', '')

		if csrf == request.get_csrf():
			sess = DBSession()
			reg = request.registry
			hash_con = reg.settings.get('netprofile.auth.hash', 'sha1')
			salt_len = int(reg.settings.get('netprofile.auth.salt_length', 4))
			q = sess.query(User).filter(User.state == UserState.active).filter(User.enabled == True).filter(User.login == login)
			for user in q:
				if user.check_password(passwd, hash_con, salt_len):
					return auth_add(request, login, 'core.home')
		did_fail = True

	mmgr = request.registry.getUtility(IModuleManager)

	return {
		'login'   : login,
		'failed'  : did_fail,
		'res_css' : mmgr.get_css(request),
		'res_js'  : mmgr.get_js(request),
		'res_ljs' : mmgr.get_local_js(request, cur_locale),
		'cur_loc' : cur_locale
	}
Esempio n. 4
0
def client_restoresent(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_rp = asbool(cfg.get('netprofile.client.password_recovery.enabled', False))
	if not can_rp:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	change_pass = asbool(cfg.get('netprofile.client.password_recovery.change_password', True))
	tpldef = {
		'cur_loc'     : cur_locale,
		'comb_js'     : comb_js,
		'change_pass' : change_pass
	}
	request.run_hook('access.cl.tpldef.restoresent', tpldef, request)
	return tpldef
Esempio n. 5
0
def client_regsent(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True))
	if not can_reg:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	tpldef = {
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js,
		'must_verify'    : must_verify
	}
	request.run_hook('access.cl.tpldef.regsent', tpldef, request)
	return tpldef
Esempio n. 6
0
def client_restoresent(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_rp = asbool(cfg.get('netprofile.client.password_recovery.enabled', False))
	if not can_rp:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	change_pass = asbool(cfg.get('netprofile.client.password_recovery.change_password', True))
	tpldef = {
		'cur_loc'     : cur_locale,
		'comb_js'     : comb_js,
		'change_pass' : change_pass
	}
	request.run_hook('access.cl.tpldef.restoresent', tpldef, request)
	return tpldef
Esempio n. 7
0
def client_regsent(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True))
	if not can_reg:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	tpldef = {
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js,
		'must_verify'    : must_verify
	}
	request.run_hook('access.cl.tpldef.regsent', tpldef, request)
	return tpldef
Esempio n. 8
0
def client_login(request):
	nxt = request.route_url('access.cl.home')
	if authenticated_userid(request):
		return HTTPSeeOther(location=nxt)
	login = ''
	did_fail = False
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	can_recover = asbool(cfg.get('netprofile.client.password_recovery.enabled', False))
	maillogin = asbool(cfg.get('netprofile.client.email_as_username', False))
	can_use_socialnetworks = asbool(cfg.get('netprofile.client.registration.social', False))

	login_providers = {'facebook':'http://facebook.com',
					   'google'	 :'http://google.com',
					   'twitter' :'http://twitter.com' 
					   }

	if 'submit' in request.POST:
		csrf = request.POST.get('csrf', '')
		login = request.POST.get('user', '')
		passwd = request.POST.get('pass', '')

		if (csrf == request.get_csrf()) and login:
			sess = DBSession()
			q = sess.query(AccessEntity).filter(AccessEntity.nick == login, AccessEntity.access_state != AccessState.block_inactive.value)
			for user in q:
				if user.password == passwd:
					headers = remember(request, login)
					return HTTPSeeOther(location=nxt, headers=headers)
		did_fail = True

	tpldef = {
		'login'          : login,
		'failed'         : did_fail,
		'can_reg'        : can_reg,
		'can_usesocial'  : can_use_socialnetworks,
		'login_providers': login_providers,
		'can_recover'    : can_recover,
		'maillogin'   	 : maillogin,
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js
	}
	request.run_hook('access.cl.tpldef.login', tpldef, request)
	return tpldef
Esempio n. 9
0
def client_login(request):
	nxt = request.route_url('access.cl.home')
	if authenticated_userid(request):
		return HTTPSeeOther(location=nxt)
	login = ''
	did_fail = False
	cur_locale = locale_neg(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	can_recover = asbool(cfg.get('netprofile.client.password_recovery.enabled', False))
	maillogin = asbool(cfg.get('netprofile.client.email_as_username', False))

	if 'submit' in request.POST:
		csrf = request.POST.get('csrf', '')
		login = request.POST.get('user', '')
		passwd = request.POST.get('pass', '')

		if (csrf == request.get_csrf()) and login:
			sess = DBSession()
			q = sess.query(AccessEntity).filter(AccessEntity.nick == login, AccessEntity.access_state != AccessState.block_inactive.value)
			for user in q:
				if user.password == passwd:
					headers = remember(request, login)
					return HTTPSeeOther(location=nxt, headers=headers)
		did_fail = True

	tpldef = {
		'login'       : login,
		'failed'      : did_fail,
		'can_reg'     : can_reg,
		'can_recover' : can_recover,
		'maillogin'   : maillogin,
		'cur_loc'     : cur_locale,
		'comb_js'     : comb_js
	}
	request.run_hook('access.cl.tpldef.login', tpldef, request)
	return tpldef
Esempio n. 10
0
def client_restorepass(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	did_fail = True
	cur_locale = locale_neg(request)
	loc = get_localizer(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_rp = asbool(cfg.get('netprofile.client.password_recovery.enabled', False))
	change_pass = asbool(cfg.get('netprofile.client.password_recovery.change_password', True))
	must_recaptcha = asbool(cfg.get('netprofile.client.password_recovery.recaptcha.enabled', False))
	maillogin = asbool(cfg.get('netprofile.client.email_as_username', False))

	errors = {}
	if not can_rp:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	if must_recaptcha:
		rc_private = cfg.get('netprofile.client.recaptcha.private_key')
		rc_public = cfg.get('netprofile.client.recaptcha.public_key')
		if (not rc_private) or (not rc_public):
			# TODO: log missing reCAPTCHA keys
			must_recaptcha = False
	if 'submit' in request.POST:
		csrf = request.POST.get('csrf', '')
		if csrf != request.get_csrf():
			errors['csrf'] = _('Error submitting form')
		elif must_recaptcha:
			try:
				rcresp = verify_recaptcha(rc_private, request)
			except ValueError as e:
				errors['recaptcha'] = str(e)
			else:
				if rcresp and not rcresp.valid:
					errors['recaptcha'] = rcresp.text()
		if len(errors) == 0:
			login = request.POST.get('user', '')
			email = request.POST.get('email', '')
			if maillogin:
				login = email
			l = len(login)
			if (l == 0) or (l > 254):
				errors['user'] = _('Invalid field length')
			elif not _re_login.match(login):
				errors['user'] = _('Invalid character used in username')
			l = len(email)
			if (l == 0) or (l > 254):
				errors['email'] = _('Invalid field length')
			elif not _re_email.match(email):
				errors['email'] = _('Invalid e-mail format')
		if len(errors) == 0:
			sess = DBSession()
			for acc in sess.query(AccessEntity)\
					.filter(AccessEntity.nick == login, AccessEntity.access_state != AccessState.block_inactive.value):
				ent = acc.parent
				ent_email = None
				while ent:
					if isinstance(ent, PhysicalEntity):
						ent_email = ent.email
					elif isinstance(ent, LegalEntity):
						ent_email = ent.contact_email
					if email == ent_email:
						break
					ent = ent.parent
				if email == ent_email:
					queue_mail = asbool(cfg.get('netprofile.client.password_recovery.mail_queue', False))
					sender = cfg.get('netprofile.client.password_recovery.mail_sender')

					if change_pass:
						pwd_len = int(cfg.get('netprofile.client.password_recovery.password_length', 12))
						chars = string.ascii_lowercase + string.ascii_uppercase + string.digits
						try:
							rng = random.SystemRandom()
						except NotImplementedError:
							rng = random
						acc.password = ''.join(rng.choice(chars) for i in range(pwd_len))

					mailer = get_mailer(request)
					tpldef = {
						'cur_loc'     : cur_locale,
						'entity'      : ent,
						'email'       : ent_email,
						'access'      : acc,
						'change_pass' : change_pass
					}
					request.run_hook('access.cl.tpldef.password_recovery.mail', tpldef, request)
					msg_text = Attachment(
						data=render('netprofile_access:templates/email_recover_plain.mak', tpldef, request),
						content_type='text/plain; charset=\'utf-8\'',
						disposition='inline',
						transfer_encoding='quoted-printable'
					)
					msg_html = Attachment(
						data=render('netprofile_access:templates/email_recover_html.mak', tpldef, request),
						content_type='text/html; charset=\'utf-8\'',
						disposition='inline',
						transfer_encoding='quoted-printable'
					)
					msg = Message(
						subject=(loc.translate(_('Password recovery for user %s')) % login),
						sender=sender,
						recipients=(ent_email,),
						body=msg_text,
						html=msg_html
					)
					if queue_mail:
						mailer.send_to_queue(msg)
					else:
						mailer.send(msg)
					return HTTPSeeOther(location=request.route_url('access.cl.restoresent'))
			else:
				errors['csrf'] = _('Username and/or e-mail are unknown to us')
	tpldef = {
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js,
		'change_pass'    : change_pass,
		'must_recaptcha' : must_recaptcha,
		'maillogin'	 : maillogin,
		'errors'         : {err: loc.translate(errors[err]) for err in errors}
	}
	if must_recaptcha:
		tpldef['rc_public'] = rc_public
	request.run_hook('access.cl.tpldef.restorepass', tpldef, request)
	return tpldef
Esempio n. 11
0
def client_register(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	cur_locale = locale_neg(request)
	loc = get_localizer(request)
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True))
	must_recaptcha = asbool(cfg.get('netprofile.client.registration.recaptcha.enabled', False))
	min_pwd_len = int(cfg.get('netprofile.client.registration.min_password_length', 8))
	rate_id = int(cfg.get('netprofile.client.registration.rate_id', 1))
	state_id = int(cfg.get('netprofile.client.registration.state_id', 1))
	maillogin = asbool(cfg.get('netprofile.client.email_as_username', False))
	csrf = request.POST.get('csrf', '')
	errors = {}
	if not can_reg:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	if must_recaptcha:
		rc_private = cfg.get('netprofile.client.recaptcha.private_key')
		rc_public = cfg.get('netprofile.client.recaptcha.public_key')
		if (not rc_private) or (not rc_public):
			# TODO: log missing reCAPTCHA keys
			must_recaptcha = False
	if 'submit' in request.POST:
		sess = DBSession()
		if csrf != request.get_csrf():
			errors['csrf'] = _('Error submitting form')
		elif must_recaptcha:
			try:
				rcresp = verify_recaptcha(rc_private, request)
			except ValueError as e:
				errors['recaptcha'] = str(e)
			else:
				if rcresp and not rcresp.valid:
					errors['recaptcha'] = rcresp.text()
		if len(errors) == 0:
			login = request.POST.get('user', '')
			passwd = request.POST.get('pass', '')
			passwd2 = request.POST.get('pass2', '')
			email = request.POST.get('email', '')
			name_family = request.POST.get('name_family', '')
			name_given = request.POST.get('name_given', '')
			name_middle = request.POST.get('name_middle', '')
			l = len(login)
			if (l == 0) or (l > 254):
				errors['user'] = _('Invalid field length')
			elif not maillogin and not _re_login.match(login):
				errors['user'] = _('Invalid character used in username')
			l = len(passwd)
			if l < min_pwd_len:
				errors['pass'] = _('Password is too short')
			elif l > 254:
				errors['pass'] = _('Password is too long')
			if passwd != passwd2:
				errors['pass2'] = _('Passwords do not match')
			l = len(email)
			if (l == 0) or (l > 254):
				errors['email'] = _('Invalid field length')
			elif not _re_email.match(email):
				errors['email'] = _('Invalid e-mail format')
			if maillogin:
				login = email
			l = len(name_family)
			if (l == 0) or (l > 254):
				errors['name_family'] = _('Invalid field length')
			l = len(name_given)
			if (l == 0) or (l > 254):
				errors['name_given'] = _('Invalid field length')
			l = len(name_middle)
			if l > 254:
				errors['name_middle'] = _('Invalid field length')
			if 'user' not in errors:
				# XXX: currently we check across all entity types.
				login_clash = sess.query(func.count('*'))\
					.select_from(Entity)\
					.filter(Entity.nick == login)\
					.scalar()
				if login_clash > 0:
					errors['user'] = _('This username is already taken')
		if len(errors) == 0:
			ent = PhysicalEntity()
			ent.nick = login
			ent.email = email
			ent.name_family = name_family
			ent.name_given = name_given
			if name_middle:
				ent.name_middle = name_middle
			ent.state_id = state_id

			stash = Stash()
			stash.entity = ent
			stash.name = loc.translate(_('Primary Account'))

			acc = AccessEntity()
			acc.nick = login
			acc.password = passwd
			acc.stash = stash
			acc.rate_id = rate_id
			acc.state_id = state_id
			ent.children.append(acc)

			sess.add(ent)
			sess.add(stash)
			sess.add(acc)

			if must_verify:
				link_id = int(cfg.get('netprofile.client.registration.link_id', 1))
				rand_len = int(cfg.get('netprofile.client.registration.code_length', 20))
				queue_mail = asbool(cfg.get('netprofile.client.registration.mail_queue', False))
				sender = cfg.get('netprofile.client.registration.mail_sender')

				acc.access_state = AccessState.block_inactive.value
				link = AccessEntityLink()
				link.entity = acc
				link.type_id = link_id

				chars = string.ascii_uppercase + string.digits
				try:
					rng = random.SystemRandom()
				except NotImplementedError:
					rng = random
				link.value = ''.join(rng.choice(chars) for i in range(rand_len))
				link.timestamp = datetime.datetime.now()
				sess.add(link)

				mailer = get_mailer(request)

				tpldef = {
					'cur_loc' : cur_locale,
					'entity'  : ent,
					'stash'   : stash,
					'access'  : acc,
					'link'    : link
				}
				request.run_hook('access.cl.tpldef.register.mail', tpldef, request)
				msg_text = Attachment(
					data=render('netprofile_access:templates/email_register_plain.mak', tpldef, request),
					content_type='text/plain; charset=\'utf-8\'',
					disposition='inline',
					transfer_encoding='quoted-printable'
				)
				msg_html = Attachment(
					data=render('netprofile_access:templates/email_register_html.mak', tpldef, request),
					content_type='text/html; charset=\'utf-8\'',
					disposition='inline',
					transfer_encoding='quoted-printable'
				)
				msg = Message(
					subject=(loc.translate(_('Activation required for user %s')) % login),
					sender=sender,
					recipients=(email,),
					body=msg_text,
					html=msg_html
				)
				if queue_mail:
					mailer.send_to_queue(msg)
				else:
					mailer.send(msg)
			return HTTPSeeOther(location=request.route_url('access.cl.regsent'))
	tpldef = {
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js,
		'must_verify'    : must_verify,
		'must_recaptcha' : must_recaptcha,
		'min_pwd_len'    : min_pwd_len,
		'maillogin'	 : maillogin,
		'errors'         : {err: loc.translate(errors[err]) for err in errors}
	}
	if must_recaptcha:
		tpldef['rc_public'] = rc_public
	request.run_hook('access.cl.tpldef.register', tpldef, request)
	return tpldef
Esempio n. 12
0
def client_restorepass(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	did_fail = True
	cur_locale = locale_neg(request)
	loc = request.localizer
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_rp = asbool(cfg.get('netprofile.client.password_recovery.enabled', False))
	change_pass = asbool(cfg.get('netprofile.client.password_recovery.change_password', True))
	must_recaptcha = asbool(cfg.get('netprofile.client.password_recovery.recaptcha.enabled', False))
	maillogin = asbool(cfg.get('netprofile.client.email_as_username', False))

	errors = {}
	if not can_rp:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	if must_recaptcha:
		rc_private = cfg.get('netprofile.client.recaptcha.private_key')
		rc_public = cfg.get('netprofile.client.recaptcha.public_key')
		if (not rc_private) or (not rc_public):
			# TODO: log missing reCAPTCHA keys
			must_recaptcha = False
	if 'submit' in request.POST:
		csrf = request.POST.get('csrf', '')
		if csrf != request.get_csrf():
			errors['csrf'] = _('Error submitting form')
		elif must_recaptcha:
			try:
				rcresp = verify_recaptcha(rc_private, request)
			except ValueError as e:
				errors['recaptcha'] = str(e)
			else:
				if rcresp and not rcresp.valid:
					errors['recaptcha'] = rcresp.text()
		if len(errors) == 0:
			login = request.POST.get('user', '')
			email = request.POST.get('email', '')
			l = len(email)
			if (l == 0) or (l > 254):
				errors['email'] = _('Invalid field length')
			elif not _re_email.match(email):
				errors['email'] = _('Invalid e-mail format')
			if maillogin:
				login = email
			else:
				l = len(login)
				if (l == 0) or (l > 254):
					errors['user'] = _('Invalid field length')
				elif not _re_login.match(login):
					errors['user'] = _('Invalid character used in username')
		if len(errors) == 0:
			sess = DBSession()
			for acc in sess.query(AccessEntity)\
					.filter(AccessEntity.nick == login, AccessEntity.access_state != AccessState.block_inactive.value):
				ent = acc.parent
				ent_email = None
				while ent:
					if isinstance(ent, PhysicalEntity):
						ent_email = ent.email
					elif isinstance(ent, LegalEntity):
						ent_email = ent.contact_email
					if email == ent_email:
						break
					ent = ent.parent
				if email == ent_email:
					queue_mail = asbool(cfg.get('netprofile.client.password_recovery.mail_queue', False))
					sender = cfg.get('netprofile.client.password_recovery.mail_sender')

					if change_pass:
						pwd_len = int(cfg.get('netprofile.client.password_recovery.password_length', 12))
						chars = string.ascii_lowercase + string.ascii_uppercase + string.digits
						try:
							rng = random.SystemRandom()
						except NotImplementedError:
							rng = random
						acc.password = ''.join(rng.choice(chars) for i in range(pwd_len))

					mailer = get_mailer(request)
					tpldef = {
						'cur_loc'     : cur_locale,
						'entity'      : ent,
						'email'       : ent_email,
						'access'      : acc,
						'change_pass' : change_pass
					}
					request.run_hook('access.cl.tpldef.password_recovery.mail', tpldef, request)
					msg_text = Attachment(
						data=render('netprofile_access:templates/email_recover_plain.mak', tpldef, request),
						content_type='text/plain; charset=\'utf-8\'',
						disposition='inline',
						transfer_encoding='quoted-printable'
					)
					msg_html = Attachment(
						data=render('netprofile_access:templates/email_recover_html.mak', tpldef, request),
						content_type='text/html; charset=\'utf-8\'',
						disposition='inline',
						transfer_encoding='quoted-printable'
					)
					msg = Message(
						subject=(loc.translate(_('Password recovery for user %s')) % login),
						sender=sender,
						recipients=(ent_email,),
						body=msg_text,
						html=msg_html
					)
					if queue_mail:
						mailer.send_to_queue(msg)
					else:
						mailer.send(msg)
					return HTTPSeeOther(location=request.route_url('access.cl.restoresent'))
			else:
				errors['csrf'] = _('Username and/or e-mail are unknown to us')
	tpldef = {
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js,
		'change_pass'    : change_pass,
		'must_recaptcha' : must_recaptcha,
		'maillogin'	 : maillogin,
		'errors'         : {err: loc.translate(errors[err]) for err in errors}
	}
	if must_recaptcha:
		tpldef['rc_public'] = rc_public
	request.run_hook('access.cl.tpldef.restorepass', tpldef, request)
	return tpldef
Esempio n. 13
0
def client_register(request):
	if authenticated_userid(request):
		return HTTPSeeOther(location=request.route_url('access.cl.home'))
	cur_locale = locale_neg(request)
	loc = request.localizer
	cfg = request.registry.settings
	comb_js = asbool(cfg.get('netprofile.client.combine_js', False))
	can_reg = asbool(cfg.get('netprofile.client.registration.enabled', False))
	must_verify = asbool(cfg.get('netprofile.client.registration.verify_email', True))
	must_recaptcha = asbool(cfg.get('netprofile.client.registration.recaptcha.enabled', False))
	min_pwd_len = int(cfg.get('netprofile.client.registration.min_password_length', 8))
	rate_id = int(cfg.get('netprofile.client.registration.rate_id', 1))
	state_id = int(cfg.get('netprofile.client.registration.state_id', 1))
	maillogin = asbool(cfg.get('netprofile.client.email_as_username', False))
	csrf = request.POST.get('csrf', '')
	errors = {}
	if not can_reg:
		return HTTPSeeOther(location=request.route_url('access.cl.login'))
	if must_recaptcha:
		rc_private = cfg.get('netprofile.client.recaptcha.private_key')
		rc_public = cfg.get('netprofile.client.recaptcha.public_key')
		if (not rc_private) or (not rc_public):
			# TODO: log missing reCAPTCHA keys
			must_recaptcha = False
	if 'submit' in request.POST:
		sess = DBSession()
		if csrf != request.get_csrf():
			errors['csrf'] = _('Error submitting form')
		elif must_recaptcha:
			try:
				rcresp = verify_recaptcha(rc_private, request)
			except ValueError as e:
				errors['recaptcha'] = str(e)
			else:
				if rcresp and not rcresp.valid:
					errors['recaptcha'] = rcresp.text()
		if len(errors) == 0:
			login = request.POST.get('user', '')
			passwd = request.POST.get('pass', '')
			passwd2 = request.POST.get('pass2', '')
			email = request.POST.get('email', '')
			name_family = request.POST.get('name_family', '')
			name_given = request.POST.get('name_given', '')
			name_middle = request.POST.get('name_middle', '')
			l = len(email)
			if (l == 0) or (l > 254):
				errors['email'] = _('Invalid field length')
			elif not _re_email.match(email):
				errors['email'] = _('Invalid e-mail format')
			if maillogin:
				login = email
			else:
				l = len(login)
				if (l == 0) or (l > 254):
					errors['user'] = _('Invalid field length')
				elif _re_login.match(login):
					errors['user'] = _('Invalid character used in username')
			l = len(passwd)
			if l < min_pwd_len:
				errors['pass'] = _('Password is too short')
			elif l > 254:
				errors['pass'] = _('Password is too long')
			if passwd != passwd2:
				errors['pass2'] = _('Passwords do not match')
			l = len(name_family)
			if (l == 0) or (l > 254):
				errors['name_family'] = _('Invalid field length')
			l = len(name_given)
			if (l == 0) or (l > 254):
				errors['name_given'] = _('Invalid field length')
			l = len(name_middle)
			if l > 254:
				errors['name_middle'] = _('Invalid field length')
			if 'user' not in errors:
				# XXX: currently we check across all entity types.
				login_clash = sess.query(func.count('*'))\
					.select_from(Entity)\
					.filter(Entity.nick == login)\
					.scalar()
				if login_clash > 0:
					errors['user'] = _('This username is already taken')
		if len(errors) == 0:
			ent = PhysicalEntity()
			ent.nick = login
			ent.email = email
			ent.name_family = name_family
			ent.name_given = name_given
			if name_middle:
				ent.name_middle = name_middle
			ent.state_id = state_id

			stash = Stash()
			stash.entity = ent
			stash.name = loc.translate(_('Primary Account'))

			acc = AccessEntity()
			acc.nick = login
			acc.password = passwd
			acc.stash = stash
			acc.rate_id = rate_id
			acc.state_id = state_id
			ent.children.append(acc)

			sess.add(ent)
			sess.add(stash)
			sess.add(acc)

			if must_verify:
				link_id = int(cfg.get('netprofile.client.registration.link_id', 1))
				rand_len = int(cfg.get('netprofile.client.registration.code_length', 20))
				queue_mail = asbool(cfg.get('netprofile.client.registration.mail_queue', False))
				sender = cfg.get('netprofile.client.registration.mail_sender')

				acc.access_state = AccessState.block_inactive.value
				link = AccessEntityLink()
				link.entity = acc
				link.type_id = link_id

				chars = string.ascii_uppercase + string.digits
				try:
					rng = random.SystemRandom()
				except NotImplementedError:
					rng = random
				link.value = ''.join(rng.choice(chars) for i in range(rand_len))
				link.timestamp = datetime.datetime.now()
				sess.add(link)

				mailer = get_mailer(request)

				tpldef = {
					'cur_loc' : cur_locale,
					'entity'  : ent,
					'stash'   : stash,
					'access'  : acc,
					'link'    : link
				}
				request.run_hook('access.cl.tpldef.register.mail', tpldef, request)
				msg_text = Attachment(
					data=render('netprofile_access:templates/email_register_plain.mak', tpldef, request),
					content_type='text/plain; charset=\'utf-8\'',
					disposition='inline',
					transfer_encoding='quoted-printable'
				)
				msg_html = Attachment(
					data=render('netprofile_access:templates/email_register_html.mak', tpldef, request),
					content_type='text/html; charset=\'utf-8\'',
					disposition='inline',
					transfer_encoding='quoted-printable'
				)
				msg = Message(
					subject=(loc.translate(_('Activation required for user %s')) % login),
					sender=sender,
					recipients=(email,),
					body=msg_text,
					html=msg_html
				)
				if queue_mail:
					mailer.send_to_queue(msg)
				else:
					mailer.send(msg)
			return HTTPSeeOther(location=request.route_url('access.cl.regsent'))
	tpldef = {
		'cur_loc'        : cur_locale,
		'comb_js'        : comb_js,
		'must_verify'    : must_verify,
		'must_recaptcha' : must_recaptcha,
		'min_pwd_len'    : min_pwd_len,
		'maillogin'	 : maillogin,
		'errors'         : {err: loc.translate(errors[err]) for err in errors}
	}
	if must_recaptcha:
		tpldef['rc_public'] = rc_public
	request.run_hook('access.cl.tpldef.register', tpldef, request)
	return tpldef