001/*
002 * acme4j - Java ACME client
003 *
004 * Copyright (C) 2016 Richard "Shred" Körber
005 *   http://acme4j.shredzone.org
006 *
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
013 */
014package org.shredzone.acme4j.exception;
015
016import java.io.Serial;
017import java.net.MalformedURLException;
018import java.net.URI;
019import java.net.URL;
020import java.util.Optional;
021
022import edu.umd.cs.findbugs.annotations.Nullable;
023import org.shredzone.acme4j.Problem;
024
025/**
026 * The user is required to take manual action as indicated.
027 * <p>
028 * Usually this exception is thrown when the terms of service have changed, and the CA
029 * requires an agreement to the new terms before proceeding.
030 */
031public class AcmeUserActionRequiredException extends AcmeServerException {
032    @Serial
033    private static final long serialVersionUID = 7719055447283858352L;
034
035    private final @Nullable URI tosUri;
036
037    /**
038     * Creates a new {@link AcmeUserActionRequiredException}.
039     *
040     * @param problem
041     *         {@link Problem} that caused the exception
042     * @param tosUri
043     *         {@link URI} of the terms-of-service document to accept, may be
044     *         {@code null}
045     */
046    public AcmeUserActionRequiredException(Problem problem, @Nullable URI tosUri) {
047        super(problem);
048        this.tosUri = tosUri;
049    }
050
051    /**
052     * Returns the {@link URI} of the terms-of-service document to accept. Empty
053     * if the server did not provide a link to such a document.
054     */
055    public Optional<URI> getTermsOfServiceUri() {
056        return Optional.ofNullable(tosUri);
057    }
058
059    /**
060     * Returns the {@link URL} of a document that gives instructions on the actions to be
061     * taken by a human.
062     */
063    public URL getInstance() {
064        var instance = getProblem().getInstance()
065                .orElseThrow(() -> new AcmeProtocolException("Instance URL required, but missing."));
066
067        try {
068            return instance.toURL();
069        } catch (MalformedURLException ex) {
070            throw new AcmeProtocolException("Bad instance URL: " + instance, ex);
071        }
072    }
073
074    @Override
075    public String toString() {
076        return getProblem().getInstance()
077                .map(uri -> "Please visit " + uri + " - details: " + getProblem())
078                .orElseGet(super::toString);
079    }
080
081}