system: You are an expert security code reviewer. You will be shown a source code file. Your task is to name the single function or class that contains the specified CWE vulnerability.

OUTPUT FORMAT: Respond with the exact function or class name (no parentheses, no qualifiers, no module prefixes), wrapped in \boxed{...}. Example: `\boxed{salted_hmac}`. Output the boxed name ONLY -- no explanation, no other text.

user: ```python
from operator import itemgetter
from app import app, cap
from werkzeug.urls import url_parse
from flask import render_template, redirect, url_for, request, flash
from app import db
from flask_login import current_user, login_user, logout_user, login_required
from app.forms import LoginForm, RegisterForm, AddCoinForm, UpdateHoldingsForm
from app.models import User, Coin

#home endpoint
@app.route('/index')
@app.route('/')
def index():
	title = "Coin Cap | Home"
	mktcap = "${:,.2f}".format(cap.stats()['total_market_cap_usd'])
	return render_template('index.html', coins=cap.ticker(limit=10), 
												 mktcap=mktcap, title=title)

#login endpoint
@app.route('/login', methods=['GET', 'POST'])
def login():
	if current_user.is_authenticated:
		return redirect(url_for('portfolio'))
	title = "Coin Cap | Log In"
	form = LoginForm()
	if form.validate_on_submit():
		user = User.query.filter_by(email=form.email.data).first()
		if user is None or not user.check_password(form.password.data):
			flash('Invalid email or password')
			return redirect(url_for('login'))
		login_user(user, remember=form.remember_me.data)
		next_page = request.args.get('next')
		if not next_page or url_parse(next_page).netloc != '':
			next_page = url_for('portfolio')
		return redirect(next_page)
	return render_template('login.html', title=title, form=form)

#logout endpoint
@app.route('/logout')
def logout():
	logout_user()
	return redirect(url_for('index'))

#register endpoint
@app.route('/register', methods=['GET', 'POST'])
def register():
	if current_user.is_authenticated:
		return redirect(url_for('portfolio'))
	title = "Coin Cap | Register"
	form = RegisterForm()
	if form.validate_on_submit():
		user = User(email=form.email.data)
		user.set_password(form.password.data)
		db.session.add(user)
		db.session.commit()
		flash('Success! You can login to your new account.')
		return redirect('login')
	return render_template('register.html', form=form, title=title)

#portfolio endpoint
@app.route('/portfolio')
@login_required
def portfolio():
	title = "Coin Cap | Portfolio"
	coins = []
	total = 0
	for coin in current_user.coins:
		c = cap.ticker(currency=coin.name)[0]
		#change rank, price_usd attributes to house an int, float for sorting of coins
		c['rank'] = int(c['rank'])
		if c is not None:
			c['amount'] = coin.amount
			coins.append(c)
			total += c['amount'] * float(c['price_usd'])
	total = "${:,.2f}".format(total)
	coins.sort(key=lambda x: (x['amount'] * float(x['price_usd'])), reverse=True)
	return render_template('portfolio.html', coins=coins, total=total, title=title)

@app.route('/add-coin', methods=['GET', 'POST'])
@login_required
def add_coin():
	title = "Coin Cap | Add Coin"
	coin_dict = {}
	for c in cap.ticker(limit=0):
		coin_dict['%s (%s)' % (c['name'], c['symbol'])] = c['id']
	form = AddCoinForm()
	if form.validate_on_submit():
		if form.search.data in coin_dict.keys():
			c = Coin(name=coin_dict[form.search.data], amount=0.0, holder=current_user)
			db.session.add(c)
			db.session.commit()
			flash('Coin added!')
			return redirect(url_for('portfolio'))
		else:
			flash('Please choose a valid option.')
			return redirect(url_for('portfolio'))
	return render_template('add-coin.html', coins=coin_dict.keys(), form=form, title=title)

@app.route('/delete-coin/<coin_id>')
@login_required
def delete_coin(coin_id):
	for coin in current_user.coins:
		if coin_id == coin.name:
			db.session.delete(coin)
			db.session.commit()
			#return right away in case of duplicate coin
			return redirect(url_for('portfolio'))
	return redirect(url_for('portfolio'))

@app.route('/portfolio/<coin_id>', methods=['GET', 'POST'])
@login_required
def coin(coin_id):
	form = UpdateHoldingsForm()
	if form.validate_on_submit():
		c = Coin.query.filter_by(holder=current_user, name=coin_id).first()
		if c is not None:
			c.amount = form.amount.data
			db.session.commit()
			redirect(url_for('coin', coin_id=coin_id))
	c = cap.ticker(currency=coin_id)
	#check if API returns valid coin(see 'coinmarketcap.com/api')
	if type(c) is list:
		c = c[0]
		title = "Coin Cap | %s" % c['name']
		for coin in current_user.coins:
			if c['id'] == coin.name:
				c['amount'] = coin.amount
				print(c['amount'])
		return render_template('coin.html', coin=c, form=form, title=title)
	else:
		#returned an error response
		flash('Unknown coin name.')
		return redirect(url_for('portfolio'))
```

Name the function or class in this code that contains a `CWE-601: URL Redirection to Untrusted Site ('Open Redirect')` vulnerability.
Answer: login