Details
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index b62ab79..3f85b27 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -285,6 +285,7 @@ public enum ErrorCode {
TENANT_DOES_NOT_EXIST_FOR_API_KEY(10003, "Tenant does not exist for api key %s"),
TENANT_CREATION_FAILED(10004, "Tenant creation failed."),
TENANT_UPDATE_FAILED(10005, "Tenant update failed."),
+ TENANT_NO_SUCH_KEY(10006, "Tenant %s does not have a key %s"),
__UNKNOWN_ERROR_CODE(-1, "Unknown ErrorCode");
diff --git a/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java b/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java
new file mode 100644
index 0000000..3c15086
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/tenant/api/TenantKV.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.tenant.api;
+
+import com.ning.billing.util.entity.Entity;
+
+public interface TenantKV extends Entity {
+
+ public String getKey();
+
+ public String getValue();
+}
diff --git a/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java b/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java
index cf49c1a..b403156 100644
--- a/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java
+++ b/api/src/main/java/com/ning/billing/tenant/api/TenantUserApi.java
@@ -22,9 +22,15 @@ import com.ning.billing.util.callcontext.CallContext;
public interface TenantUserApi {
- public Tenant createTenant(TenantData data, CallContext context) throws TenantApiException;
+ public Tenant createTenant(final TenantData data, final CallContext context) throws TenantApiException;
- public Tenant getTenantByApiKey(String key) throws TenantApiException;
+ public Tenant getTenantByApiKey(final String key) throws TenantApiException;
- public Tenant getTenantById(UUID tenantId) throws TenantApiException;
+ public Tenant getTenantById(final UUID tenantId) throws TenantApiException;
+
+ public String getTenantValueForKey(final UUID tenantId, final String key) throws TenantApiException;
+
+ public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final CallContext context) throws TenantApiException;
+
+ public void deleteTenantKey(final UUID tenantId, final String key) throws TenantApiException;
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java b/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java
new file mode 100644
index 0000000..cbf185d
--- /dev/null
+++ b/tenant/src/main/java/com/ning/billing/tenant/api/DefaultTenantKV.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.tenant.api;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.util.entity.EntityBase;
+
+public class DefaultTenantKV extends EntityBase implements TenantKV {
+
+ private final String key;
+ private final String value;
+
+ public DefaultTenantKV(final UUID tenantId, final String key, final String value, final DateTime createdDate, final DateTime updatedDate) {
+ super(tenantId, createdDate, updatedDate);
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java b/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java
index 74c33df..7273fd5 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/api/user/DefaultTenantUserApi.java
@@ -26,6 +26,7 @@ import com.ning.billing.tenant.api.TenantData;
import com.ning.billing.tenant.api.TenantUserApi;
import com.ning.billing.tenant.dao.TenantDao;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.entity.EntityPersistenceException;
@@ -49,7 +50,7 @@ public class DefaultTenantUserApi implements TenantUserApi {
try {
tenantDao.create(tenant, internalCallContextFactory.createInternalCallContext(context));
- } catch (EntityPersistenceException e) {
+ } catch (final EntityPersistenceException e) {
throw new TenantApiException(e, ErrorCode.TENANT_CREATION_FAILED);
}
@@ -74,4 +75,37 @@ public class DefaultTenantUserApi implements TenantUserApi {
}
return tenant;
}
+
+ @Override
+ public String getTenantValueForKey(final UUID tenantId, final String key)
+ throws TenantApiException {
+ final String value = tenantDao.getTenantValueForKey(tenantId, key);
+ if (value == null) {
+ throw new TenantApiException(ErrorCode.TENANT_NO_SUCH_KEY, tenantId, key);
+ }
+ return value;
+ }
+
+ @Override
+ public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final CallContext context)
+ throws TenantApiException {
+
+ final InternalCallContext internalContext = new InternalCallContext(null, null, context);
+ final Tenant tenant = tenantDao.getById(tenantId, internalContext);
+ if (tenant == null) {
+ throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_ID, tenantId);
+ }
+ tenantDao.addTenantKeyValue(tenantId, key, value, internalContext);
+ }
+
+
+ @Override
+ public void deleteTenantKey(final UUID tenantId, final String key)
+ throws TenantApiException {
+ final Tenant tenant = tenantDao.getById(tenantId, new InternalTenantContext(null, null));
+ if (tenant == null) {
+ throw new TenantApiException(ErrorCode.TENANT_DOES_NOT_EXIST_FOR_ID, tenantId);
+ }
+ tenantDao.deleteTenantKey(tenantId, key);
+ }
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java
index 4fe0f4e..6890832 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/DefaultTenantDao.java
@@ -29,10 +29,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ning.billing.tenant.api.Tenant;
-import com.ning.billing.util.svcsapi.bus.InternalBus;
+import com.ning.billing.tenant.api.TenantKV;
import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.callcontext.InternalTenantContext;
import com.ning.billing.util.entity.EntityPersistenceException;
+import com.ning.billing.util.svcsapi.bus.InternalBus;
import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject;
@@ -44,12 +45,14 @@ public class DefaultTenantDao implements TenantDao {
private final RandomNumberGenerator rng = new SecureRandomNumberGenerator();
private final TenantSqlDao tenantSqlDao;
+ private final TenantKVSqlDao tenantKVSqlDao;
private final InternalBus eventBus;
@Inject
public DefaultTenantDao(final IDBI dbi, final InternalBus eventBus) {
this.eventBus = eventBus;
this.tenantSqlDao = dbi.onDemand(TenantSqlDao.class);
+ this.tenantKVSqlDao = dbi.onDemand(TenantKVSqlDao.class);
}
@Override
@@ -92,4 +95,23 @@ public class DefaultTenantDao implements TenantDao {
AuthenticationInfo getAuthenticationInfoForTenant(final UUID id) {
return tenantSqlDao.getSecrets(id.toString()).toAuthenticationInfo();
}
+
+ @Override
+ public String getTenantValueForKey(final UUID tenantId, final String key) {
+ final TenantKV tenantKV = tenantKVSqlDao.getTenantValueForKey(tenantId.toString(), key);
+ if (tenantKV == null) {
+ return null;
+ }
+ return tenantKV.getValue();
+ }
+
+ @Override
+ public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final InternalCallContext context) {
+ tenantKVSqlDao.insertTenantKeyValue(tenantId.toString(), key, value, context);
+ }
+
+ @Override
+ public void deleteTenantKey(final UUID tenantId, final String key) {
+ tenantKVSqlDao.deleteTenantKey(tenantId.toString(), key);
+ }
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java
index 88e956f..c73b52f 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantDao.java
@@ -16,10 +16,19 @@
package com.ning.billing.tenant.dao;
+import java.util.UUID;
+
import com.ning.billing.tenant.api.Tenant;
+import com.ning.billing.util.callcontext.InternalCallContext;
import com.ning.billing.util.entity.dao.EntityDao;
public interface TenantDao extends EntityDao<Tenant> {
- public Tenant getTenantByApiKey(String key);
+ public Tenant getTenantByApiKey(final String key);
+
+ public String getTenantValueForKey(final UUID tenantId, final String key);
+
+ public void addTenantKeyValue(final UUID tenantId, final String key, final String value, final InternalCallContext context);
+
+ public void deleteTenantKey(final UUID tenantId, final String key);
}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java
new file mode 100644
index 0000000..1535ffd
--- /dev/null
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantKVSqlDao.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package com.ning.billing.tenant.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.tenant.api.DefaultTenantKV;
+import com.ning.billing.tenant.api.TenantKV;
+import com.ning.billing.tenant.dao.TenantKVSqlDao.TenantKVMapper;
+import com.ning.billing.util.callcontext.InternalCallContext;
+import com.ning.billing.util.callcontext.InternalTenantContextBinder;
+import com.ning.billing.util.dao.MapperBase;
+import com.ning.billing.util.dao.UuidMapper;
+import com.ning.billing.util.entity.dao.EntitySqlDao;
+
+@ExternalizedSqlViaStringTemplate3
+@RegisterMapper({UuidMapper.class, TenantKVMapper.class})
+public interface TenantKVSqlDao extends EntitySqlDao<TenantKV>, Transactional<TenantKVSqlDao> {
+
+ @SqlQuery
+ public TenantKV getTenantValueForKey(@Bind("id") final String tenantId, @Bind("key") final String key);
+
+ @SqlUpdate
+ public void insertTenantKeyValue(@Bind("id") final String tenantId, @Bind("key") final String key, @Bind("value") final String value,
+ @InternalTenantContextBinder final InternalCallContext context);
+
+ @SqlUpdate
+ public void deleteTenantKey(@Bind("id") final String tenantId, @Bind("key") final String key);
+
+
+ public class TenantKVMapper extends MapperBase implements ResultSetMapper<TenantKV> {
+
+ @Override
+ public TenantKV map(final int index, final ResultSet result, final StatementContext context) throws SQLException {
+ final UUID id = getUUID(result, "id");
+ final String key = result.getString("t_key");
+ final String value = result.getString("t_value");
+ final DateTime createdDate = getDateTime(result, "created_date");
+ final DateTime updatedDate = getDateTime(result, "updated_date");
+ return new DefaultTenantKV(id, key, value, createdDate, updatedDate);
+ }
+ }
+}
diff --git a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantSqlDao.java b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantSqlDao.java
index 4841707..8ce298b 100644
--- a/tenant/src/main/java/com/ning/billing/tenant/dao/TenantSqlDao.java
+++ b/tenant/src/main/java/com/ning/billing/tenant/dao/TenantSqlDao.java
@@ -47,4 +47,5 @@ public interface TenantSqlDao extends EntitySqlDao<Tenant>, Transactional<Tenant
@SqlQuery
@Mapper(TenantSecretsMapper.class)
public TenantSecrets getSecrets(@Bind("id") final String id);
+
}
diff --git a/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg b/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg
new file mode 100644
index 0000000..3e2d0cb
--- /dev/null
+++ b/tenant/src/main/resources/com/ning/billing/tenant/dao/TenantKVSqlDao.sql.stg
@@ -0,0 +1,55 @@
+group TenantKVSqlDao;
+
+
+tenantKVFields(prefix) ::= <<
+ <prefix>record_id,
+ <prefix>id,
+ <prefix>t_key,
+ <prefix>t_value,
+ <prefix>created_date,
+ <prefix>created_by,
+ <prefix>updated_date,
+ <prefix>updated_by
+>>
+
+insertTenantKeyValue() ::= <<
+ INSERT INTO tenant_kvs (
+ id
+ , t_key
+ , t_value
+ , created_date
+ , created_by
+ , updated_date
+ , updated_by
+ ) VALUES (
+ :id
+ , :key
+ , :value
+ , :createdDate
+ , :userName
+ , :updatedDate
+ , :userName
+ );
+>>
+
+
+getTenantValueForKey() ::= <<
+ SELECT <tenantKVFields()>
+ FROM tenant_kvs
+ WHERE
+ id = :id AND t_key = :key
+ ;
+>>
+
+
+deleteTenantKey() ::= <<
+ DELETE FROM tenant_kvs
+ WHERE
+ id = :id AND t_key = :key
+ ;
+>>
+
+
+test() ::= <<
+ SELECT 1 FROM tenants;
+>>
\ No newline at end of file
diff --git a/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql b/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql
index f4e76e0..ac9d885 100644
--- a/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql
+++ b/tenant/src/main/resources/com/ning/billing/tenant/ddl.sql
@@ -14,3 +14,19 @@ CREATE TABLE tenants (
) ENGINE=innodb;
CREATE UNIQUE INDEX tenants_id ON tenants(id);
CREATE UNIQUE INDEX tenants_api_key ON tenants(api_key);
+
+
+DROP TABLE IF EXISTS tenant_kvs;
+CREATE TABLE tenant_kvs (
+ record_id int(11) unsigned NOT NULL AUTO_INCREMENT,
+ -- This is the tenant id, no id is generated as this is not a customer facing object
+ id char(36) NOT NULL,
+ t_key varchar(64) NOT NULL,
+ t_value varchar(512) NOT NULL,
+ created_date datetime NOT NULL,
+ created_by varchar(50) NOT NULL,
+ updated_date datetime DEFAULT NULL,
+ updated_by varchar(50) DEFAULT NULL,
+ PRIMARY KEY(record_id)
+) ENGINE=innodb;
+CREATE INDEX tenant_kvs_key ON tenant_kvs(id, t_key);
\ No newline at end of file
diff --git a/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java b/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java
index 990f5fb..9a8cc58 100644
--- a/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java
+++ b/tenant/src/test/java/com/ning/billing/tenant/dao/TestDefaultTenantDao.java
@@ -37,7 +37,7 @@ public class TestDefaultTenantDao extends TenantTestSuiteWithEmbeddedDb {
final DefaultTenantDao tenantDao = new DefaultTenantDao(getMysqlTestingHelper().getDBI(), Mockito.mock(InternalBus.class));
final DefaultTenant tenant = new DefaultTenant(UUID.randomUUID(), null, null, UUID.randomUUID().toString(),
- UUID.randomUUID().toString(), UUID.randomUUID().toString());
+ UUID.randomUUID().toString(), UUID.randomUUID().toString());
tenantDao.create(tenant, internalCallContext);
// Verify we can retrieve it
@@ -54,4 +54,20 @@ public class TestDefaultTenantDao extends TenantTestSuiteWithEmbeddedDb {
final AuthenticationToken badToken = new UsernamePasswordToken(tenant.getApiKey(), tenant.getApiSecret() + "T");
Assert.assertFalse(KillbillCredentialsMatcher.getCredentialsMatcher().doCredentialsMatch(badToken, authenticationInfo));
}
+
+ @Test(groups = "slow")
+ public void testTenantKeyValue() throws Exception {
+
+ final DefaultTenantDao tenantDao = new DefaultTenantDao(getMysqlTestingHelper().getDBI(), Mockito.mock(InternalBus.class));
+ final DefaultTenant tenant = new DefaultTenant(UUID.randomUUID(), null, null, UUID.randomUUID().toString(),
+ UUID.randomUUID().toString(), UUID.randomUUID().toString());
+ tenantDao.create(tenant, internalCallContext);
+
+ tenantDao.addTenantKeyValue(tenant.getId(), "TheKey", "TheValue", internalCallContext);
+
+ final String value = tenantDao.getTenantValueForKey(tenant.getId(), "TheKey");
+ Assert.assertEquals(value, "TheValue");
+
+ tenantDao.deleteTenantKey(tenant.getId(), "TheKey");
+ }
}