mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-18 02:39:44 +00:00
Exposes a list of configured identities through the REST API at /keyring/identities.json
This commit is contained in:
parent
ba4cd5e7b4
commit
e79e74feb9
2
httpd.c
2
httpd.c
@ -39,6 +39,7 @@ HTTP_HANDLER restful_rhizome_newsince;
|
||||
HTTP_HANDLER restful_rhizome_insert;
|
||||
HTTP_HANDLER restful_rhizome_;
|
||||
HTTP_HANDLER restful_meshms_;
|
||||
HTTP_HANDLER restful_keyring_;
|
||||
|
||||
HTTP_HANDLER rhizome_status_page;
|
||||
HTTP_HANDLER rhizome_file_page;
|
||||
@ -59,6 +60,7 @@ struct http_handler paths[]={
|
||||
{"/restful/rhizome/insert", restful_rhizome_insert},
|
||||
{"/restful/rhizome/", restful_rhizome_},
|
||||
{"/restful/meshms/", restful_meshms_},
|
||||
{"/restful/keyring/", restful_keyring_},
|
||||
{"/rhizome/status", rhizome_status_page},
|
||||
{"/rhizome/file/", rhizome_file_page},
|
||||
{"/rhizome/import", rhizome_direct_import},
|
||||
|
9
httpd.h
9
httpd.h
@ -134,6 +134,15 @@ typedef struct httpd_request
|
||||
*/
|
||||
struct rhizome_read read_state;
|
||||
|
||||
/* For responses that list SIDs.
|
||||
*/
|
||||
struct {
|
||||
enum list_phase phase;
|
||||
unsigned cn;
|
||||
unsigned in;
|
||||
}
|
||||
sidlist;
|
||||
|
||||
/* For responses that list manifests.
|
||||
*/
|
||||
struct {
|
||||
|
159
keyring_restful.c
Normal file
159
keyring_restful.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
Serval DNA HTTP RESTful interface
|
||||
Copyright (C) 2013,2014 Serval Project Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "serval.h"
|
||||
#include "conf.h"
|
||||
#include "httpd.h"
|
||||
#include "server.h"
|
||||
#include "keyring.h"
|
||||
#include "strbuf_helpers.h"
|
||||
|
||||
extern keyring_file *keyring;
|
||||
|
||||
#define keyring_TOKEN_STRLEN (BASE64_ENCODED_LEN(sizeof(rhizome_bid_t) + sizeof(uint64_t)))
|
||||
#define alloca_keyring_token(bid, offset) keyring_ token_to_str(alloca(keyring_TOKEN_STRLEN + 1), (bid), (offset))
|
||||
|
||||
static HTTP_HANDLER restful_keyring_identitylist_json;
|
||||
|
||||
int restful_keyring_(httpd_request *r, const char *remainder)
|
||||
{
|
||||
r->http.response.header.content_type = CONTENT_TYPE_JSON;
|
||||
if (!is_rhizome_http_enabled())
|
||||
return 403;
|
||||
int ret = authorize_restful(&r->http);
|
||||
if (ret)
|
||||
return ret;
|
||||
const char *verb = HTTP_VERB_GET;
|
||||
http_size_t content_length = CONTENT_LENGTH_UNKNOWN;
|
||||
HTTP_HANDLER *handler = NULL;
|
||||
|
||||
if (strcmp(remainder, "identities.json") == 0) {
|
||||
handler = restful_keyring_identitylist_json;
|
||||
verb = HTTP_VERB_GET;
|
||||
remainder = "";
|
||||
}
|
||||
|
||||
if (handler == NULL)
|
||||
return 404;
|
||||
if ( content_length != CONTENT_LENGTH_UNKNOWN
|
||||
&& r->http.request_header.content_length != CONTENT_LENGTH_UNKNOWN
|
||||
&& r->http.request_header.content_length != content_length) {
|
||||
http_request_simple_response(&r->http, 400, "Bad content length");
|
||||
return 400;
|
||||
}
|
||||
if (r->http.verb != verb)
|
||||
return 405;
|
||||
return handler(r, remainder);
|
||||
}
|
||||
|
||||
static HTTP_CONTENT_GENERATOR restful_keyring_identitylist_json_content;
|
||||
|
||||
static int restful_keyring_identitylist_json(httpd_request *r, const char *remainder)
|
||||
{
|
||||
if (*remainder)
|
||||
return 404;
|
||||
|
||||
r->u.sidlist.phase = LIST_HEADER;
|
||||
r->u.sidlist.cn = 0;
|
||||
r->u.sidlist.in = 0;
|
||||
|
||||
http_request_response_generated(&r->http, 200, CONTENT_TYPE_JSON, restful_keyring_identitylist_json_content);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HTTP_CONTENT_GENERATOR_STRBUF_CHUNKER restful_keyring_identitylist_json_content_chunk;
|
||||
|
||||
static int restful_keyring_identitylist_json_content(struct http_request *hr, unsigned char *buf, size_t bufsz, struct http_content_generator_result *result)
|
||||
{
|
||||
return generate_http_content_from_strbuf_chunks(hr, (char *)buf, bufsz, result, restful_keyring_identitylist_json_content_chunk);
|
||||
}
|
||||
|
||||
static int restful_keyring_identitylist_json_content_chunk(struct http_request *hr, strbuf b)
|
||||
{
|
||||
httpd_request *r = (httpd_request *) hr;
|
||||
// The "my_sid" and "their_sid" per-conversation fields allow the same JSON structure to be used
|
||||
// in a future, non-SID-specific request, eg, to list all conversations for all currently open
|
||||
// identities.
|
||||
const char *headers[] = {
|
||||
"sid",
|
||||
"did",
|
||||
"name"
|
||||
};
|
||||
switch (r->u.sidlist.phase) {
|
||||
case LIST_HEADER:
|
||||
strbuf_puts(b, "{\n\"header\":[");
|
||||
unsigned i;
|
||||
for (i = 0; i != NELS(headers); ++i) {
|
||||
if (i)
|
||||
strbuf_putc(b, ',');
|
||||
strbuf_json_string(b, headers[i]);
|
||||
}
|
||||
strbuf_puts(b, "],\n\"rows\":[");
|
||||
if (!strbuf_overrun(b))
|
||||
r->u.sidlist.phase = LIST_ROWS;
|
||||
return 1;
|
||||
case LIST_ROWS:
|
||||
if (r->u.sidlist.cn != 0 || r->u.sidlist.in != 0)
|
||||
strbuf_putc(b, ',');
|
||||
|
||||
if (keyring->context_count == 0 || keyring->contexts[r->u.sidlist.cn]->identity_count == 0) {
|
||||
r->u.sidlist.phase = LIST_END;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const sid_t *sidp = NULL;
|
||||
const char *did = NULL;
|
||||
const char *name = NULL;
|
||||
keyring_identity_extract(keyring->contexts[r->u.sidlist.cn]->identities[r->u.sidlist.in], &sidp, &did, &name);
|
||||
if (sidp || did) {
|
||||
strbuf_puts(b, "\n[");
|
||||
strbuf_json_string(b, alloca_tohex_sid_t(*sidp));
|
||||
strbuf_puts(b, ",");
|
||||
strbuf_json_string(b, did);
|
||||
strbuf_puts(b, ",");
|
||||
strbuf_json_string(b, name);
|
||||
strbuf_puts(b, "]");
|
||||
}
|
||||
|
||||
if (!strbuf_overrun(b)) {
|
||||
++r->u.sidlist.in;
|
||||
if (r->u.sidlist.in >= keyring->contexts[r->u.sidlist.cn]->identity_count) {
|
||||
r->u.sidlist.in = 0;
|
||||
|
||||
++r->u.sidlist.cn;
|
||||
if (r->u.sidlist.cn >= keyring->context_count) {
|
||||
r->u.sidlist.phase = LIST_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
// }
|
||||
// fall through...
|
||||
case LIST_END:
|
||||
strbuf_puts(b, "\n]\n}\n");
|
||||
if (!strbuf_overrun(b))
|
||||
r->u.sidlist.phase = LIST_DONE;
|
||||
// fall through...
|
||||
case LIST_DONE:
|
||||
return 0;
|
||||
}
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ SERVAL_DAEMON_SOURCES = \
|
||||
main.c \
|
||||
radio_link.c \
|
||||
meshms.c \
|
||||
keyring_restful.c \
|
||||
meshms_restful.c \
|
||||
msp_client.c \
|
||||
msp_proxy.c \
|
||||
|
99
tests/keyringrestful
Executable file
99
tests/keyringrestful
Executable file
@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tests for Serval DNA HTTP RESTful interface
|
||||
#
|
||||
# Copyright 2013-2014 Serval Project, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
source "${0%/*}/../testframework.sh"
|
||||
source "${0%/*}/../testdefs.sh"
|
||||
source "${0%/*}/../testdefs_json.sh"
|
||||
|
||||
shopt -s extglob
|
||||
|
||||
setup() {
|
||||
CR='
|
||||
'
|
||||
setup_curl 7
|
||||
setup_json
|
||||
setup_servald
|
||||
set_instance +A
|
||||
|
||||
executeOk_servald config \
|
||||
set api.restful.users.harry.password potter \
|
||||
set api.restful.users.ron.password weasley \
|
||||
set api.restful.users.hermione.password grainger
|
||||
set_extra_config
|
||||
if [ -z "$IDENTITY_COUNT" ]; then
|
||||
create_single_identity
|
||||
else
|
||||
create_identities $IDENTITY_COUNT
|
||||
fi
|
||||
start_servald_instances +A
|
||||
wait_until servald_restful_http_server_started +A
|
||||
get_servald_restful_http_server_port PORTA +A
|
||||
}
|
||||
|
||||
finally() {
|
||||
stop_all_servald_servers
|
||||
}
|
||||
|
||||
teardown() {
|
||||
kill_all_servald_processes
|
||||
assert_no_servald_processes
|
||||
report_all_servald_servers
|
||||
}
|
||||
|
||||
set_extra_config() {
|
||||
:
|
||||
}
|
||||
|
||||
set_keyring_config() {
|
||||
executeOk_servald config \
|
||||
set debug.http_server on \
|
||||
set debug.httpd on \
|
||||
set debug.rhizome_manifest on \
|
||||
set debug.rhizome_store on \
|
||||
set debug.rhizome on \
|
||||
set debug.keyring on \
|
||||
set debug.verbose on \
|
||||
set log.console.level debug
|
||||
}
|
||||
|
||||
doc_keyringListIdentities="HTTP RESTful list SIDs as JSON"
|
||||
setup_keyringListIdentities() {
|
||||
IDENTITY_COUNT=10
|
||||
setup
|
||||
}
|
||||
|
||||
test_keyringListIdentities() {
|
||||
executeOk curl \
|
||||
--silent --fail --show-error \
|
||||
--output identitylist1.json \
|
||||
--dump-header http.headers \
|
||||
--basic --user harry:potter \
|
||||
"http://$addr_localhost:$PORTA/restful/keyring/identities.json"
|
||||
tfw_cat http.headers identitylist1.json
|
||||
tfw_preserve identitylist1.json
|
||||
|
||||
assert [ "$(jq '.rows | length' identitylist1.json)" = $IDENTITY_COUNT ]
|
||||
|
||||
assert [ "$(jq -r '.rows[0][0]' identitylist1.json)" = $SIDA1 ]
|
||||
assert [ "$(jq -r '.rows[4][0]' identitylist1.json)" = $SIDA5 ]
|
||||
assert [ "$(jq -r '.rows[9][0]' identitylist1.json)" = $SIDA10 ]
|
||||
}
|
||||
|
||||
runTests "$@"
|
Loading…
Reference in New Issue
Block a user