improvements to generating URIs and some template tweaks, minor tidying
This commit is contained in:
parent
1682cbe81f
commit
516f90bf1f
6 changed files with 93 additions and 35 deletions
|
|
@ -76,7 +76,15 @@ public class Bot {
|
||||||
|
|
||||||
Bot() {
|
Bot() {
|
||||||
}
|
}
|
||||||
Bot( String username, String name, String summary, Instant published, KeyPair keyPair, String type, boolean manuallyApproveFollowers, boolean indexable ) {
|
Bot(
|
||||||
|
String username,
|
||||||
|
String name,
|
||||||
|
String summary,
|
||||||
|
Instant published,
|
||||||
|
KeyPair keyPair,
|
||||||
|
String type,
|
||||||
|
boolean manuallyApproveFollowers,
|
||||||
|
boolean indexable ) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.summary = summary;
|
this.summary = summary;
|
||||||
|
|
@ -86,5 +94,6 @@ public class Bot {
|
||||||
this.manuallyApproveFollowers = manuallyApproveFollowers;
|
this.manuallyApproveFollowers = manuallyApproveFollowers;
|
||||||
this.indexable = indexable;
|
this.indexable = indexable;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -35,36 +36,73 @@ public class BotService {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// whilst the URI structure of the below are up to the implementor we're using Mastodon as a reference
|
// whilst the URI structure of the below are up to the implementer we're using Mastodon as a reference
|
||||||
|
|
||||||
// TODO: perhaps these could just be templated elsewhere... or part of a separat JSON generator
|
// TODO: I've fiddled around loads with where to house/generate the values
|
||||||
|
// from the calls below, they have ended up here mainly as this is where it
|
||||||
|
// is cleanest to access the configuration properties.
|
||||||
|
//
|
||||||
|
// Opinion in material I've read seems very firm that knowledge of
|
||||||
|
// "configuration" should not exist at Entity level so I have not made them
|
||||||
|
// members of the Bot class. I've toyed with the idea of them simply all
|
||||||
|
// being kept as database values and generated on creation... and in some
|
||||||
|
// ways that is simply cleaner and thus still has an appeal to it. I just
|
||||||
|
// also feel uncomfortable about having a load of "derived data" in the
|
||||||
|
// database, even though there is also a efficiency argument. Perhaps the
|
||||||
|
// combination of both efficiency + design-readability should win it. (In
|
||||||
|
// which case this code could well just stay here to be used at creation.)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the users URI
|
* Generate the webfinger subject
|
||||||
*/
|
*/
|
||||||
private String getUsersURI() {
|
public String getWebfingerSubject(Bot bot) {
|
||||||
return props.getScheme() + "://" + props.getDomain() + "/users/";
|
return "acct:" + bot.getUsername() + "@" + props.getDomain();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The"id" of a bot (user/actor) is a URI combining domain and username: https://<domain>/users/<username>
|
* Generate the webfinger subject
|
||||||
|
*/
|
||||||
|
public String getHandle(Bot bot) {
|
||||||
|
return "@" + bot.getUsername() + "@" + props.getDomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the base users URI
|
||||||
|
*/
|
||||||
|
private UriComponentsBuilder getUsersURI() {
|
||||||
|
return UriComponentsBuilder.newInstance()
|
||||||
|
.scheme(props.getScheme())
|
||||||
|
.host(props.getDomain())
|
||||||
|
.pathSegment("users");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "id" of a bot (user/actor) is a URI combining domain and username: https://<domain>/users/<username>
|
||||||
*/
|
*/
|
||||||
public String getId(Bot bot) {
|
public String getId(Bot bot) {
|
||||||
return getUsersURI() + bot.getUsername();
|
return getUsersURI()
|
||||||
|
.pathSegment(bot.getUsername())
|
||||||
|
.toUriString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "inbox" of a user is a URI of the form: https://<domain>/users/<username>/inbox
|
* The "inbox" of a user is a URI of the form: https://<domain>/users/<username>/inbox
|
||||||
*/
|
*/
|
||||||
public String getInbox(Bot bot) {
|
public String getInbox(Bot bot) {
|
||||||
return getUsersURI() + bot.getUsername() + "/inbox";
|
return getUsersURI()
|
||||||
|
.pathSegment(bot.getUsername())
|
||||||
|
.pathSegment("inbox")
|
||||||
|
.toUriString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "outbox" of a user is a URI of the form: https://<domain>/users/<username>/outbox
|
* The "outbox" of a user is a URI of the form: https://<domain>/users/<username>/outbox
|
||||||
*/
|
*/
|
||||||
public String getOutbox(Bot bot) {
|
public String getOutbox(Bot bot) {
|
||||||
return getUsersURI() + bot.getUsername() + "/outbox";
|
return getUsersURI()
|
||||||
|
.pathSegment(bot.getUsername())
|
||||||
|
.pathSegment("outbox")
|
||||||
|
.toUriString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bot save(Bot bot) {
|
public Bot save(Bot bot) {
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,17 @@ public class RestHandler {
|
||||||
//return new ResponseEntity<>("These are not the droids you are looking for.", HttpStatus.NOT_FOUND);
|
//return new ResponseEntity<>("These are not the droids you are looking for.", HttpStatus.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: So here's a whole other way of generating custom JSON as compared to the BotAPActorJSONSerializer approach
|
// TODO: So here's a whole other way of generating custom JSON as
|
||||||
|
// compared to the BotAPActorJSONSerializer approach, should perhaps
|
||||||
|
// settle on one style of doing it (if we're going to do it either way
|
||||||
|
// in the end.)
|
||||||
Map<String, Object> response = Map.of(
|
Map<String, Object> response = Map.of(
|
||||||
"subject", bot.getUsername() + "@springbot.seth.id.au",
|
"subject", botServ.getWebfingerSubject( bot ),
|
||||||
"links", List.of(
|
"links", List.of(
|
||||||
Map.of(
|
Map.of(
|
||||||
"rel", "self",
|
"rel", "self",
|
||||||
"type", "application/activity+json",
|
"type", "application/activity+json",
|
||||||
"href", "https://springbot.seth.id.au/users/" + bot.getUsername()
|
"href", botServ.getId( bot )
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ logging.file.name=logs/springbot.log
|
||||||
logging.file.path=logs
|
logging.file.path=logs
|
||||||
spring.output.ansi.enabled=ALWAYS
|
spring.output.ansi.enabled=ALWAYS
|
||||||
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
|
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG
|
||||||
|
server.tomcat.basedir=logs
|
||||||
|
server.tomcat.accesslog.enabled=true
|
||||||
|
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)
|
||||||
|
|
||||||
spring.mvc.view.prefix: /WEB-INF/views/
|
spring.mvc.view.prefix: /WEB-INF/views/
|
||||||
spring.mvc.view.suffix: .jsp
|
spring.mvc.view.suffix: .jsp
|
||||||
|
|
|
||||||
|
|
@ -3,25 +3,21 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="ISO-8859-1">
|
<meta charset="ISO-8859-1">
|
||||||
<title>List Bot</title>
|
<title>List Bot</title>
|
||||||
<style type="text/css">
|
.main {
|
||||||
span {
|
text-align: center;
|
||||||
display: inline-block;
|
|
||||||
width: 200px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div align="center">
|
<div class="main">
|
||||||
<h2>Pick-a-Bot!</h2>
|
<h2>Pick-a-Bot!</h2>
|
||||||
<ul th:if="${bots.empty}">
|
<th:block th:if="${bots.empty}">
|
||||||
<li>No Bots!</li>
|
<h3>No Bots!</h3>
|
||||||
</ul>
|
|
||||||
<th:block th:each="bot : ${bots}">
|
|
||||||
<span>Bot:</span>
|
|
||||||
<span><a th:href="@{/viewbot/} + ${bot.username}">[[${bot.username}]]</a></span>
|
|
||||||
<br>
|
|
||||||
</th:block>
|
</th:block>
|
||||||
|
<th:block th:each="bot : ${bots}">
|
||||||
|
<a th:href="@{/viewbot/} + ${bot.username}">[[${@botService.getHandle(bot)}]]</a><br>
|
||||||
|
</th:block>
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<a href="/">HOME</a>
|
<a href="/">HOME</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,33 @@
|
||||||
<meta charset="ISO-8859-1">
|
<meta charset="ISO-8859-1">
|
||||||
<title>View Bot</title>
|
<title>View Bot</title>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
.main {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
span {
|
span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 40em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
span.left {
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div align="center">
|
<div class="main">
|
||||||
<h2>Bot:</h2>
|
<h2>Bot:</h2>
|
||||||
<span>Username:</span><span th:text="${bot.username}"></span><br/>
|
<span class="left">Username:</span><span th:text="${bot.username}"></span><br/>
|
||||||
<span>Id:</span><span th:text="'@' + ${bot.username} + '@springbot.seth.id.au'"></span><br/>
|
<span class="left">Id:</span><span th:text="${@botService.getHandle(bot)}"></span><br/>
|
||||||
<span>Display Name:</span><span th:text="${bot.name}"></span><br/>
|
<span class="left">Display Name:</span><span th:text="${bot.name}"></span><br/>
|
||||||
<span>Description:</span><span th:text="${bot.summary}"></span><br/>
|
<span class="left">Description:</span><span th:text="${bot.summary}"></span><br/>
|
||||||
<span>Published:</span><span th:text="${bot.published}"></span><br/>
|
<span class="left">Published:</span><span th:text="${bot.published}"></span><br/>
|
||||||
<span>Type:</span><span th:text="${bot.type}"></span><br/>
|
<span class="left">Type:</span><span th:text="${bot.type}"></span><br/>
|
||||||
<span>Public Key:</span><pre th:text="${bot.getPublicKeyPEMString()}"></pre><br/>
|
<span class="left">Public Key:</span><span></span>
|
||||||
|
<pre th:text="${bot.getPublicKeyPEMString()}"></pre>
|
||||||
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<a href="/">HOME</a> |
|
<a href="/">HOME</a> |
|
||||||
<a href="/viewbot">Bot List</a>
|
<a href="/viewbot">Bot List</a>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue