mirror of https://github.com/shred/acme4j
Use terms-of-service-agreed to agree to TOS
parent
d6d7e04ea5
commit
3b3f379be2
|
@ -48,17 +48,17 @@ public class Registration extends AcmeResource {
|
|||
private static final long serialVersionUID = -8177333806740391140L;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Registration.class);
|
||||
|
||||
private static final String KEY_AGREEMENT = "agreement";
|
||||
private static final String KEY_TOS_AGREED = "terms-of-service-agreed";
|
||||
private static final String KEY_AUTHORIZATIONS = "authorizations";
|
||||
private static final String KEY_CERTIFICATES = "certificates";
|
||||
private static final String KEY_CONTACT = "contact";
|
||||
private static final String KEY_STATUS = "status";
|
||||
|
||||
private final List<URI> contacts = new ArrayList<>();
|
||||
private URI agreement;
|
||||
private Status status;
|
||||
private Boolean termsOfServiceAgreed;
|
||||
private URI authorizations;
|
||||
private URI certificates;
|
||||
private Status status;
|
||||
private boolean loaded = false;
|
||||
|
||||
protected Registration(Session session, URI location) {
|
||||
|
@ -66,12 +66,6 @@ public class Registration extends AcmeResource {
|
|||
setLocation(location);
|
||||
}
|
||||
|
||||
protected Registration(Session session, URI location, URI agreement) {
|
||||
super(session);
|
||||
setLocation(location);
|
||||
this.agreement = agreement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link Registration} and binds it to the {@link Session}.
|
||||
*
|
||||
|
@ -86,13 +80,14 @@ public class Registration extends AcmeResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the URI of the agreement document the user is required to accept.
|
||||
* Returns if the user agreed to the terms of service.
|
||||
*
|
||||
* @return {@code true} if the user agreed to the terms of service. May be
|
||||
* {@code null} if the server did not provide such an information.
|
||||
*/
|
||||
public URI getAgreement() {
|
||||
if (agreement == null) {
|
||||
public Boolean getTermsOfServiceAgreed() {
|
||||
load();
|
||||
}
|
||||
return agreement;
|
||||
return termsOfServiceAgreed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -346,8 +341,8 @@ public class Registration extends AcmeResource {
|
|||
* {@link Connection} with headers to be evaluated
|
||||
*/
|
||||
private void unmarshal(JSON json, Connection conn) {
|
||||
if (json.contains(KEY_AGREEMENT)) {
|
||||
this.agreement = json.get(KEY_AGREEMENT).asURI();
|
||||
if (json.contains(KEY_TOS_AGREED)) {
|
||||
this.termsOfServiceAgreed = json.get(KEY_TOS_AGREED).asBoolean();
|
||||
}
|
||||
|
||||
if (json.contains(KEY_CONTACT)) {
|
||||
|
@ -369,11 +364,6 @@ public class Registration extends AcmeResource {
|
|||
setLocation(location);
|
||||
}
|
||||
|
||||
URI tos = conn.getLink("terms-of-service");
|
||||
if (tos != null) {
|
||||
this.agreement = tos;
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
|
@ -391,11 +381,9 @@ public class Registration extends AcmeResource {
|
|||
*/
|
||||
public class EditableRegistration {
|
||||
private final List<URI> editContacts = new ArrayList<>();
|
||||
private URI editAgreement;
|
||||
|
||||
private EditableRegistration() {
|
||||
editContacts.addAll(Registration.this.contacts);
|
||||
editAgreement = Registration.this.agreement;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,18 +420,6 @@ public class Registration extends AcmeResource {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new agreement URI.
|
||||
*
|
||||
* @param agreement
|
||||
* New agreement URI
|
||||
* @return itself
|
||||
*/
|
||||
public EditableRegistration setAgreement(URI agreement) {
|
||||
this.editAgreement = agreement;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits the changes and updates the account.
|
||||
*/
|
||||
|
@ -455,9 +431,6 @@ public class Registration extends AcmeResource {
|
|||
if (!editContacts.isEmpty()) {
|
||||
claims.put(KEY_CONTACT, editContacts);
|
||||
}
|
||||
if (editAgreement != null) {
|
||||
claims.put(KEY_AGREEMENT, editAgreement);
|
||||
}
|
||||
|
||||
conn.sendSignedRequest(getLocation(), claims, getSession());
|
||||
conn.accept(HttpURLConnection.HTTP_ACCEPTED);
|
||||
|
|
|
@ -33,6 +33,7 @@ public class RegistrationBuilder {
|
|||
private static final Logger LOG = LoggerFactory.getLogger(RegistrationBuilder.class);
|
||||
|
||||
private List<URI> contacts = new ArrayList<>();
|
||||
private Boolean termsOfServiceAgreed;
|
||||
|
||||
/**
|
||||
* Add a contact URI to the list of contacts.
|
||||
|
@ -62,6 +63,16 @@ public class RegistrationBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that the user agrees to the terms of service.
|
||||
*
|
||||
* @return itself
|
||||
*/
|
||||
public RegistrationBuilder agreeToTermsOfService() {
|
||||
this.termsOfServiceAgreed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new account.
|
||||
*
|
||||
|
@ -82,14 +93,16 @@ public class RegistrationBuilder {
|
|||
if (!contacts.isEmpty()) {
|
||||
claims.put("contact", contacts);
|
||||
}
|
||||
if (termsOfServiceAgreed != null) {
|
||||
claims.put("terms-of-service-agreed", termsOfServiceAgreed);
|
||||
}
|
||||
|
||||
conn.sendSignedRequest(session.resourceUri(Resource.NEW_REG), claims, session);
|
||||
conn.accept(HttpURLConnection.HTTP_CREATED);
|
||||
|
||||
URI location = conn.getLocation();
|
||||
URI tos = conn.getLink("terms-of-service");
|
||||
|
||||
return new Registration(session, location, tos);
|
||||
return new Registration(session, location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
package org.shredzone.acme4j;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.shredzone.acme4j.util.TestUtils.*;
|
||||
import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
|
||||
|
||||
|
@ -25,6 +25,7 @@ import org.junit.Test;
|
|||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.provider.TestableConnectionProvider;
|
||||
import org.shredzone.acme4j.util.JSON;
|
||||
import org.shredzone.acme4j.util.JSONBuilder;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,6 @@ public class RegistrationBuilderTest {
|
|||
|
||||
private URI resourceUri = URI.create("http://example.com/acme/resource");;
|
||||
private URI locationUri = URI.create("http://example.com/acme/registration");;
|
||||
private URI agreementUri = URI.create("http://example.com/agreement.pdf");;
|
||||
|
||||
/**
|
||||
* Test if a new registration can be created.
|
||||
|
@ -42,18 +42,31 @@ public class RegistrationBuilderTest {
|
|||
@Test
|
||||
public void testRegistration() throws Exception {
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
private boolean isUpdate;
|
||||
|
||||
@Override
|
||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
||||
assertThat(uri, is(resourceUri));
|
||||
assertThat(claims.toString(), sameJSONAs(getJson("newRegistration")));
|
||||
assertThat(session, is(notNullValue()));
|
||||
if (resourceUri.equals(uri)) {
|
||||
isUpdate = false;
|
||||
assertThat(claims.toString(), sameJSONAs(getJson("newRegistration")));
|
||||
} else if (locationUri.equals(uri)) {
|
||||
isUpdate = true;
|
||||
} else {
|
||||
fail("bad URI");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int accept(int... httpStatus) throws AcmeException {
|
||||
if (isUpdate) {
|
||||
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED));
|
||||
return HttpURLConnection.HTTP_ACCEPTED;
|
||||
} else {
|
||||
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_CREATED));
|
||||
return HttpURLConnection.HTTP_CREATED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getLocation() {
|
||||
|
@ -61,11 +74,9 @@ public class RegistrationBuilderTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public URI getLink(String relation) {
|
||||
switch(relation) {
|
||||
case "terms-of-service": return agreementUri;
|
||||
default: return null;
|
||||
}
|
||||
public JSON readJsonResponse() {
|
||||
assertThat(isUpdate, is(true));
|
||||
return getJsonAsObject("newRegistrationResponse");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -73,11 +84,12 @@ public class RegistrationBuilderTest {
|
|||
|
||||
RegistrationBuilder builder = new RegistrationBuilder();
|
||||
builder.addContact("mailto:foo@example.com");
|
||||
builder.agreeToTermsOfService();
|
||||
|
||||
Registration registration = builder.create(provider.createSession());
|
||||
|
||||
assertThat(registration.getLocation(), is(locationUri));
|
||||
assertThat(registration.getAgreement(), is(agreementUri));
|
||||
assertThat(registration.getTermsOfServiceAgreed(), is(true));
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ public class RegistrationTest {
|
|||
registration.update();
|
||||
|
||||
assertThat(registration.getLocation(), is(locationUri));
|
||||
assertThat(registration.getAgreement(), is(agreementUri));
|
||||
assertThat(registration.getTermsOfServiceAgreed(), is(true));
|
||||
assertThat(registration.getContacts(), hasSize(1));
|
||||
assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
|
||||
assertThat(registration.getStatus(), is(Status.GOOD));
|
||||
|
@ -188,12 +188,12 @@ public class RegistrationTest {
|
|||
|
||||
// Lazy loading
|
||||
assertThat(requestWasSent.get(), is(false));
|
||||
assertThat(registration.getAgreement(), is(agreementUri));
|
||||
assertThat(registration.getTermsOfServiceAgreed(), is(true));
|
||||
assertThat(requestWasSent.get(), is(true));
|
||||
|
||||
// Subsequent queries do not trigger another load
|
||||
requestWasSent.set(false);
|
||||
assertThat(registration.getAgreement(), is(agreementUri));
|
||||
assertThat(registration.getTermsOfServiceAgreed(), is(true));
|
||||
assertThat(registration.getStatus(), is(Status.GOOD));
|
||||
assertThat(requestWasSent.get(), is(false));
|
||||
|
||||
|
@ -519,8 +519,6 @@ public class RegistrationTest {
|
|||
*/
|
||||
@Test
|
||||
public void testModify() throws Exception {
|
||||
final URI agreementUri = URI.create("http://example.com/agreement.pdf");
|
||||
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
|
||||
|
@ -544,14 +542,6 @@ public class RegistrationTest {
|
|||
public URI getLocation() {
|
||||
return locationUri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getLink(String relation) {
|
||||
switch(relation) {
|
||||
case "terms-of-service": return agreementUri;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Registration registration = new Registration(provider.createSession(), locationUri);
|
||||
|
@ -559,13 +549,11 @@ public class RegistrationTest {
|
|||
EditableRegistration editable = registration.modify();
|
||||
assertThat(editable, notNullValue());
|
||||
|
||||
editable.setAgreement(agreementUri);
|
||||
editable.addContact("mailto:foo2@example.com");
|
||||
editable.getContacts().add(URI.create("mailto:foo3@example.com"));
|
||||
editable.commit();
|
||||
|
||||
assertThat(registration.getLocation(), is(locationUri));
|
||||
assertThat(registration.getAgreement(), is(agreementUri));
|
||||
assertThat(registration.getContacts().size(), is(2));
|
||||
assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
|
||||
assertThat(registration.getContacts().get(1), is(URI.create("mailto:foo3@example.com")));
|
||||
|
|
|
@ -39,6 +39,7 @@ json = \
|
|||
{\
|
||||
"text": "lorem ipsum",\
|
||||
"number": 123,\
|
||||
"boolean": true,\
|
||||
"uri": "mailto:foo@example.com",\
|
||||
"url": "http://example.com",\
|
||||
"date": "2016-01-08T00:00:00Z",\
|
||||
|
@ -48,24 +49,28 @@ json = \
|
|||
|
||||
newRegistration = \
|
||||
{"resource":"new-reg",\
|
||||
"terms-of-service-agreed":true,\
|
||||
"contact":["mailto:foo@example.com"]}
|
||||
|
||||
newRegistrationResponse = \
|
||||
{"terms-of-service-agreed":true,\
|
||||
"contact":["mailto:foo@example.com"]}
|
||||
|
||||
modifyRegistration = \
|
||||
{"resource":"reg",\
|
||||
"agreement":"http://example.com/agreement.pdf",\
|
||||
"contact":["mailto:foo2@example.com","mailto:foo3@example.com"]}
|
||||
|
||||
modifyRegistrationResponse = \
|
||||
{"agreement":"http://example.com/agreement.pdf",\
|
||||
{"terms-of-service-agreed":true,\
|
||||
"contact":["mailto:foo2@example.com","mailto:foo3@example.com"]}
|
||||
|
||||
updateRegistration = \
|
||||
{"resource":"reg"}
|
||||
|
||||
updateRegistrationResponse = \
|
||||
{"agreement":"http://example.com/agreement.pdf",\
|
||||
"contact":["mailto:foo2@example.com"],\
|
||||
{"contact":["mailto:foo2@example.com"],\
|
||||
"status":"good",\
|
||||
"terms-of-service-agreed":true,\
|
||||
"authorizations":"https://example.com/acme/reg/1/authz",\
|
||||
"certificates":"https://example.com/acme/reg/1/cert"}
|
||||
|
||||
|
|
|
@ -185,19 +185,19 @@ public class ClientTest {
|
|||
* @return {@link Registration} connected to your account
|
||||
*/
|
||||
private Registration findOrRegisterAccount(Session session) throws AcmeException {
|
||||
// Ask the user to accept the TOS, if server provides us with a link.
|
||||
URI tos = session.getMetadata().getTermsOfService();
|
||||
if (tos != null) {
|
||||
acceptAgreement(tos);
|
||||
}
|
||||
|
||||
Registration reg;
|
||||
|
||||
try {
|
||||
// Try to create a new Registration.
|
||||
reg = new RegistrationBuilder().create(session);
|
||||
reg = new RegistrationBuilder().agreeToTermsOfService().create(session);
|
||||
LOG.info("Registered a new user, URI: " + reg.getLocation());
|
||||
|
||||
// This is a new account. Let the user accept the Terms of Service.
|
||||
// We won't be able to authorize domains until the ToS is accepted.
|
||||
URI agreement = reg.getAgreement();
|
||||
LOG.info("Terms of Service: " + agreement);
|
||||
acceptAgreement(reg, agreement);
|
||||
|
||||
} catch (AcmeConflictException ex) {
|
||||
// The Key Pair is already registered. getLocation() contains the
|
||||
// URL of the existing registration's location. Bind it to the session.
|
||||
|
@ -433,12 +433,10 @@ public class ClientTest {
|
|||
* Presents the user a link to the Terms of Service, and asks for confirmation. If the
|
||||
* user denies confirmation, an exception is thrown.
|
||||
*
|
||||
* @param reg
|
||||
* {@link Registration} User's registration
|
||||
* @param agreement
|
||||
* {@link URI} of the Terms of Service
|
||||
*/
|
||||
public void acceptAgreement(Registration reg, URI agreement) throws AcmeException {
|
||||
public void acceptAgreement(URI agreement) throws AcmeException {
|
||||
int option = JOptionPane.showConfirmDialog(null,
|
||||
"Do you accept the Terms of Service?\n\n" + agreement,
|
||||
"Accept ToS",
|
||||
|
@ -446,10 +444,6 @@ public class ClientTest {
|
|||
if (option == JOptionPane.NO_OPTION) {
|
||||
throw new AcmeException("User did not accept Terms of Service");
|
||||
}
|
||||
|
||||
// Motify the Registration and accept the agreement
|
||||
reg.modify().setAgreement(agreement).commit();
|
||||
LOG.info("Updated user's ToS");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
|
||||
If it is the first time you connect to the ACME server, you need to register your account key.
|
||||
|
||||
To do so, create a `RegistrationBuilder`, optionally add some contact information, then invoke `create()`. If the account was successfully created, you will get a `Registration` object in return. Invoking its `getLocation()` method will return the location URI of your account. You should store it somewhere, because you will need it later. Unlike your key pair, the location is a public information that does not need security precautions.
|
||||
To do so, create a `RegistrationBuilder`, optionally add some contact information, agree to the terms of service, then invoke `create()`. If the account was successfully created, you will get a `Registration` object in return. Invoking its `getLocation()` method will return the location URI of your account. You should store it somewhere, because you will need it later. Unlike your key pair, the location is a public information that does not need security precautions.
|
||||
|
||||
```java
|
||||
RegistrationBuilder builder = new RegistrationBuilder();
|
||||
builder.addContact("mailto:acme@example.com");
|
||||
builder.agreeToTermsOfService();
|
||||
|
||||
Registration registration = builder.create(session);
|
||||
|
||||
|
@ -20,7 +21,7 @@ The following example will create a new `Registration` and restore an existing `
|
|||
```java
|
||||
Registration registration;
|
||||
try {
|
||||
registration = new RegistrationBuilder().create(session);
|
||||
registration = new RegistrationBuilder().agreeToTermsOfService().create(session);
|
||||
} catch (AcmeConflictException ex) {
|
||||
registration = Registration.bind(session, ex.getLocation());
|
||||
}
|
||||
|
@ -28,15 +29,15 @@ try {
|
|||
|
||||
## Update your Registration
|
||||
|
||||
At some point, you may want to update your registration. For example your contact address might have changed, or you were asked by the CA to accept the latest terms of service. To do so, invoke `Registration.modify()`, perform the changes, and invoke `commit()` to make them permanent.
|
||||
At some point, you may want to update your registration. For example your contact address might have changed. To do so, invoke `Registration.modify()`, perform the changes, and invoke `commit()` to make them permanent.
|
||||
|
||||
The following example accepts the terms of service by explicitly setting the URL to the agreement document.
|
||||
The following example adds another email address.
|
||||
|
||||
```java
|
||||
URI agreementUri = ... // TAC link provided by the CA
|
||||
|
||||
registration.modify()
|
||||
.setAgreement(agreementUri)
|
||||
.addContact("mailto:acme2@example.com")
|
||||
.commit();
|
||||
```
|
||||
|
||||
|
|
Loading…
Reference in New Issue