Skip to content

Commit 8dd7cfb

Browse files
authored
Merge pull request #25 from bbockelm/get_string_list
API for querying for string lists
2 parents 746a79c + 33e8189 commit 8dd7cfb

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

src/scitokens.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,68 @@ int scitoken_get_claim_string(const SciToken token, const char *key, char **valu
104104
}
105105

106106

107+
int scitoken_set_claim_string_list(const SciToken token, const char *key,
108+
const char **value, char **err_msg)
109+
{
110+
auto real_token = reinterpret_cast<scitokens::SciToken*>(token);
111+
if (real_token == nullptr) {
112+
if (err_msg) *err_msg = strdup("NULL scitoken passed to scitoken_get_claim_string_list");
113+
return -1;
114+
}
115+
std::vector<std::string> claim_list;
116+
int idx = 0;
117+
while (value[idx++]) {}
118+
claim_list.reserve(idx);
119+
120+
idx = 0;
121+
while (value[idx++]) {
122+
claim_list.emplace_back(value[idx-1]);
123+
}
124+
real_token->set_claim_list(key, claim_list);
125+
126+
return 0;
127+
}
128+
129+
130+
int scitoken_get_claim_string_list(const SciToken token, const char *key, char ***value, char **err_msg) {
131+
auto real_token = reinterpret_cast<scitokens::SciToken*>(token);
132+
if (real_token == nullptr) {
133+
if (err_msg) *err_msg = strdup("NULL scitoken passed to scitoken_get_claim_string_list");
134+
return -1;
135+
}
136+
std::vector<std::string> claim_list;
137+
try {
138+
claim_list = real_token->get_claim_list(key);
139+
} catch (std::exception &exc) {
140+
if (err_msg) {*err_msg = strdup(exc.what());}
141+
return -1;
142+
}
143+
auto claim_list_c = static_cast<char **>(malloc(sizeof(char **) * (claim_list.size() + 1)));
144+
claim_list_c[claim_list.size()] = nullptr;
145+
int idx = 0;
146+
for (const auto &entry : claim_list) {
147+
claim_list_c[idx] = strdup(entry.c_str());
148+
if (!claim_list_c[idx]) {
149+
scitoken_free_string_list(claim_list_c);
150+
if (err_msg) {*err_msg = strdup("Failed to create a copy of string entry in list");}
151+
return -1;
152+
}
153+
idx++;
154+
}
155+
*value = claim_list_c;
156+
return 0;
157+
}
158+
159+
160+
void scitoken_free_string_list(char **value) {
161+
int idx = 0;
162+
do {
163+
free(value[idx++]);
164+
} while (value[idx]);
165+
free(value);
166+
}
167+
168+
107169
int scitoken_get_expiration(const SciToken token, long long *expiry, char **err_msg) {
108170
scitokens::SciToken *real_token = reinterpret_cast<scitokens::SciToken*>(token);
109171
if (!real_token->has_claim("exp")) {

src/scitokens.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,27 @@ int scitoken_set_claim_string(SciToken token, const char *key, const char *value
4747

4848
int scitoken_get_claim_string(const SciToken token, const char *key, char **value, char **err_msg);
4949

50+
/**
51+
* Given a SciToken object, parse a specific claim's value as a list of strings. If the JSON value
52+
* is not actually a list of strings - or the claim is not set - returns an error and sets the
53+
* err_msg appropriately.
54+
*
55+
* The returned value is a list of strings that ends with a nullptr.
56+
*/
57+
int scitoken_get_claim_string_list(const SciToken token, const char *key, char ***value, char **err_msg);
58+
59+
/**
60+
* Given a list of strings that was returned by scitoken_get_claim_string_list, free all the associated
61+
* memory.
62+
*/
63+
void scitoken_free_string_list(char **value);
64+
65+
/**
66+
* Set the value of a claim to a list of strings.
67+
*/
68+
int scitoken_set_claim_string_list(const SciToken token, const char *key,
69+
const char **values, char **err_msg);
70+
5071
int scitoken_get_expiration(const SciToken token, long long *value, char **err_msg);
5172

5273
void scitoken_set_lifetime(SciToken token, int lifetime);

src/scitokens_internal.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,16 @@ friend class scitokens::Validator;
149149
return m_claims.find(key) != m_claims.end();
150150
}
151151

152+
void
153+
set_claim_list(const std::string &claim, std::vector<std::string> &claim_list) {
154+
picojson::array array;
155+
array.reserve(claim_list.size());
156+
for (const auto &entry : claim_list) {
157+
array.emplace_back(entry);
158+
}
159+
m_claims[claim] = jwt::claim(picojson::value(array));
160+
}
161+
152162
// Return a claim as a string
153163
// If the claim is not a string, it can throw
154164
// a std::bad_cast() exception.
@@ -157,6 +167,21 @@ friend class scitokens::Validator;
157167
return m_claims[key].as_string();
158168
}
159169

170+
const std::vector<std::string>
171+
get_claim_list(const std::string &key) {
172+
picojson::array array;
173+
try {
174+
array = m_claims[key].as_array();
175+
} catch (std::bad_cast &) {
176+
throw JsonException("Claim's value is not a JSON list");
177+
}
178+
std::vector<std::string> result;
179+
for (const auto &value : array) {
180+
result.emplace_back(value.get<std::string>());
181+
}
182+
return result;
183+
}
184+
160185
void
161186
set_lifetime(int lifetime) {
162187
m_lifetime = lifetime;

test/main.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ class SerializeTest : public ::testing::Test {
7777
"1", ec_public, &err_msg);
7878
ASSERT_TRUE(rv == 0);
7979

80+
const char *groups[3] = {nullptr, nullptr, nullptr};
81+
const char group0[] = "group0";
82+
const char group1[] = "group1";
83+
groups[0] = group0;
84+
groups[1] = group1;
85+
rv = scitoken_set_claim_string_list(m_token.get(), "groups", groups,
86+
&err_msg);
87+
ASSERT_TRUE(rv == 0);
88+
8089
m_read_token.reset(scitoken_create(nullptr));
8190
ASSERT_TRUE(m_read_token.get() != nullptr);
8291
}
@@ -115,6 +124,23 @@ TEST_F(SerializeTest, VerifyTest) {
115124
EXPECT_FALSE(rv == 0);
116125
}
117126

127+
TEST_F(SerializeTest, TestStringList) {
128+
char *err_msg = nullptr;
129+
130+
char **value;
131+
auto rv = scitoken_get_claim_string_list(m_token.get(), "groups", &value, &err_msg);
132+
ASSERT_TRUE(rv == 0);
133+
ASSERT_TRUE(value != nullptr);
134+
135+
ASSERT_TRUE(value[0] != nullptr);
136+
EXPECT_STREQ(value[0], "group0");
137+
138+
ASSERT_TRUE(value[1] != nullptr);
139+
EXPECT_STREQ(value[1], "group1");
140+
141+
EXPECT_TRUE(value[2] == nullptr);
142+
}
143+
118144

119145
TEST_F(SerializeTest, VerifyWLCGTest) {
120146

0 commit comments

Comments
 (0)