view src/nabble/view/web/forum/ChangeDomainName.jtp @ 50:806d3297f92b

allow custom nabble domains
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 27 Jun 2021 18:26:58 -0600
parents 18cf4872fd7f
children
line wrap: on
line source

<%
package nabble.view.web.forum;

import fschmidt.util.mail.Mail;
import fschmidt.util.mail.MailAddress;
import fschmidt.util.mail.MailException;
import fschmidt.util.mail.MailHome;
import fschmidt.util.mail.PlainTextContent;
import nabble.model.ModelException;
import nabble.model.ModelHome;
import nabble.model.Node;
import nabble.model.Site;
import nabble.model.User;
import nabble.naml.namespaces.TemplateException;
import nabble.view.lib.Jtp;
import nabble.view.lib.Permissions;
import nabble.view.lib.Shared;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;


public final class ChangeDomainName extends HttpServlet {

	protected void service(HttpServletRequest request,HttpServletResponse response)
		throws ServletException, IOException
	{
		Site site = ModelHome.getSite(Jtp.getLong(request, "site"));
		if (site == null) {
			response.sendError(HttpServletResponse.SC_NOT_FOUND, "No application match the \"<i>" + request.getHeader("host") + "</i>\" domain.");
			return;
		}

		User user = Jtp.getUser(request);
		if (user == null) {
			response.sendRedirect("http://" + Jtp.getDefaultBaseUrl(site) + Jtp.loginPath(site,null,response.encodeURL("/forum/ChangeDomainName.jtp?site="+site.getId())) );
			return;
		}

		boolean isSiteAdmin = Permissions.isInGroup(user, Permissions.ADMINISTRATORS_GROUP);
		boolean isSysAdmin = Permissions.isSysAdmin(user);
		if (!isSiteAdmin && !isSysAdmin) {
			Jtp.login("Only administrators can proceed in this area.", request, response);
			return;
		}

		Node rootNode = site.getRootNode();
		boolean isSave = "save".equals(request.getParameter("action"));

		String domainName = site.getCustomDomain();
		String domainOption = domainName == null? "default-domain" : "own-domain";
		if (isSave) {
			domainName = request.getParameter("domain-name");
			domainOption = request.getParameter("domain-option");
		}

		String errorMsg = null;
		if (isSave && "POST".equals(request.getMethod())) {
			try {
				boolean isDefault = "default-domain".equals(domainOption);
				if (isDefault)
					site.setCustomDomain(null);
				else {
					domainName = domainName.trim();
					if (domainName.length() == 0 || domainName.equals(InetAddress.getLocalHost().getHostAddress()))
						throw ModelException.newInstance("invalid_domain", "Please enter a valid domain name for your application.");
					Long currentSiteId = ModelHome.getSiteIdFromDomain(domainName);
					if (currentSiteId != null && !currentSiteId.equals(site.getId()))
						throw ModelException.newInstance("domain_already_in_use", "This domain is already in use.");
					String domainIP = getDomainIP(domainName);
					String nabbleIP = getDomainIP(Jtp.getDefaultHost());
					if (!nabbleIP.equals(domainIP))
						throw ModelException.newInstance(
							"domain_bad_resolution",
							"Your domain name currently resolves to an IP address that doesn't belong to Nabble. " +
							"Please follow the instructions (see link below) in order to update your DNS. " +
							"If you have just updated your DNS, please wait 24 hours for the changes to take affect.");

					site.setCustomDomain(domainName);
				}
				sendEmail(user, site);
				response.sendRedirect(Jtp.url(rootNode));
				return;
			} catch (TemplateException e) {
				errorMsg = e.getMessage();
			}
		}

		PrintWriter out = response.getWriter();
		%>
		<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
		<html>
			<head>
				<META NAME="robots" CONTENT="noindex,nofollow">
				<% Shared.title(request, response, "Change Domain Name"); %>
				<style type="text/css">
					label { font-weight:bold; }
					.step {
						font-weight: bold;
						font-size: 120%;
						padding: .5em .3em;
						white-space:nowrap;
					}
				</style>
				<script type="text/javascript">
					$(document).ready(function() {
						function enableControls() {
							if ($('#default-domain').attr('checked')) {
								$('#domain-name').attr('disabled','y');
							} else {
								$('#domain-name').removeAttr('disabled').focus();
							}
						};
						$('#default-domain,#own-domain').change(enableControls);
						enableControls();
					});
				</script>
			</head>
			<body>
				<% Shared.minHeader(request,response, rootNode); %>
				<% Shared.editHeader(rootNode.getSubjectHtml(), "Change Domain Name", out); %>
				<% Shared.errorMessage(request, response, errorMsg, null); %>

				<% if (site.getCustomDomain() != null) { %>
					<div class="info-message rounded" style="padding: .5em;margin:.4em 0">
						<b>You already have a domain set for "<%=rootNode.getSubject()%>".</b><br/>
						If you change this domain configuration, links to the old domain will probably stop working.
					</div>
				<% } %>

				<div class="field weak-color" style="margin-left:1.5em">
					<div style="margin:1em 0 .5em">
						Access your application with a custom domain name.
					</div>

					<form method="post" action="/forum/ChangeDomainName.jtp" accept-charset="UTF-8">
						<input type="hidden" name="action" value="save"/>
						<input type="hidden" name="site" value="<%=site.getId()%>"/>
						<input type="radio" name="domain-option" id="default-domain" value="default-domain" <%="default-domain".equals(domainOption)?"checked='y'":""%>/>
						<label for="default-domain">Nabble Default URL</label>
						<div style="margin:.5em 0 1em 3em">
							http://<%=Jtp.getDefaultBaseUrl(site)%>/
						</div>

						<input type="radio" name="domain-option" id="own-domain" value="own-domain" <%="own-domain".equals(domainOption)?"checked='y'":""%>/>
						<label for="own-domain">Your Own Domain</label>
						<div style="margin:.5em 0 1em 3em">
							<table class="weak-color">
								<tr style="vertical-align:top">
									<td style="padding-right:.8em"><div class="second-font shaded-bg-color rounded step border1 medium-border-color">Step 1</div></td>
									<td>
										Go to your Domain Registrar and set the CNAME-record for your custom domain to <b><%=Jtp.getDefaultHost()%></b>.
										(<a href="/help/DNSConfiguration.jtp" target="_new">show me more details</a>)
										<div style="margin-top:.7em;font-size:80%">
											(After this change, wait a little bit for the DNS to propagate.
											Then open your custom domain url in the browser to see if the change is propagated &ndash; if successful, you should get redirected to the Nabble home page)
										</div>
									</td>
								</tr>
								<tr style="vertical-align:top">
									<td style="padding:1.7em .5em 0 0"><div class="second-font shaded-bg-color rounded step border1 medium-border-color">Step 2</div></td>
									<td style="padding-top:1.5em">
										<div style="margin-bottom:.3em">Enter your custom domain name below:</div>
										http://<input id="domain-name" name="domain-name" size="40" value="<%=Jtp.hideNull(domainName)%>"/>
										<div style="font-size:80%;margin:.3em 0">
											Example: mydomain.com
										</div>
									</td>
								</tr>
								<tr style="vertical-align:top">
									<td style="padding:1.3em .5em 0 0"><div class="second-font shaded-bg-color rounded step border1 medium-border-color">Step 3</div></td>
									<td style="padding-top:1.1em">
										After saving your changes, your old URLs will continue to work and will automatically redirect to your custom domain URL.
										You will also receive an email with a link to revert this domain change.
									</td>
								</tr>
							</table>
						</div>

						<input type="submit" value="Save Changes" />
						or <a href="<%=Jtp.path(rootNode)%>">Cancel</a>
					</form>
				</div>
				<% Shared.footer(request, response); %>
				<% Shared.analytics(request, response); %>
			</body>
		</html>
		<%
	}

	private static String getDomainIP(String domain) {
		String ip = domain;
		int i = ip.indexOf(":");
		if( i > 0 )
			ip = ip.substring(0,i);
		try {
			InetAddress add = InetAddress.getByName(ip);
			if (add != null)
				ip = add.getHostAddress();
		} catch(UnknownHostException e) {}
		return ip;
	}

	private static void sendEmail(User user, Site site)
		throws IOException, ServletException
	{
		StringBuilder builder = new StringBuilder();
		builder.append("Dear ").append(user.getName()).append(",\n\n");
		builder.append("You have changed your domain name configuration to:\n");
		builder.append(site.getBaseUrl());
		builder.append("\n\n");
		builder.append("If you have problems with your domain name or simply want to change this configuration again, you can use this link:\n");
		builder.append("http://").append(Jtp.getDefaultHost()).append("/forum/ChangeDomainName.jtp?site=").append(site.getId());
		builder.append("\n\n");
		builder.append("Regards,\n");
		builder.append("The Nabble team");

		try {
			Mail mail = MailHome.newMail();
			mail.setFrom(new MailAddress(ModelHome.noReply, "Nabble"));
			mail.setTo(new MailAddress(user.getEmail()));
			mail.setSubject("Domain name configuration changed");
			mail.setContent(new PlainTextContent(builder.toString()));
			ModelHome.send(mail);
		} catch(MailException e) {
			throw new RuntimeException(e);
		}
	}
}
%>