Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose get attachment for credential #175

Merged
merged 2 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions libvcx/src/api/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,43 @@ pub extern fn vcx_credential_get_attributes(command_handle: CommandHandle,
error::SUCCESS.code_num
}

#[no_mangle]
pub extern fn vcx_credential_get_attachment(command_handle: CommandHandle,
credential_handle: u32,
cb: Option<extern fn(xcommand_handle: CommandHandle, err: u32, attachment: *const c_char)>) -> u32 {
info!("vcx_credential_get_attachment >>> credential_handle: {:?}", credential_handle);

check_useful_c_callback!(cb, VcxErrorKind::InvalidOption);
if !credential::is_valid_handle(credential_handle) {
return VcxError::from(VcxErrorKind::InvalidCredentialHandle).into();
}

let source_id = credential::get_source_id(credential_handle).unwrap_or_default();
trace!("vcx_credential_get_attachment(command_handle: {}, credential_handle: {}) source_id: {})",
command_handle, credential_handle, source_id);

spawn(move || {
match credential::get_attachment(credential_handle) {
Ok(s) => {
trace!("vcx_credential_get_attachment_cb(commmand_handle: {}, rc: {}, attachment: {}) source_id: {}",
command_handle, error::SUCCESS.code_num, s, source_id);
let attach = CStringUtils::string_to_cstring(s);
cb(command_handle, error::SUCCESS.code_num, attach.as_ptr());
}
Err(e) => {
error!("vcx_credential_get_attachment_cb(commmand_handle: {}, rc: {}, attachment: {}) source_id: {}",
command_handle, e, "".to_string(), source_id);
cb(command_handle, e.into(), ptr::null_mut());
}
};

Ok(())
});

error::SUCCESS.code_num
}


/// Create a Credential object based off of a known message id for a given connection.
///
/// #Params
Expand Down
4 changes: 4 additions & 0 deletions libvcx/src/aries/handlers/issuance/holder/holder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ impl Holder {
self.holder_sm.get_attributes()
}

pub fn get_attachment(&self) -> VcxResult<String> {
self.holder_sm.get_attachment()
}

pub fn delete_credential(&self) -> VcxResult<()> {
self.holder_sm.delete_credential()
}
Expand Down
8 changes: 8 additions & 0 deletions libvcx/src/aries/handlers/issuance/holder/state_machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ impl HolderSM {
}
}

pub fn get_attachment(&self) -> VcxResult<String> {
match self.state {
HolderState::Finished(ref state) => state.get_attachment(),
HolderState::OfferReceived(ref state) => state.get_attachment(),
_ => Err(VcxError::from_msg(VcxErrorKind::NotReady, "Cannot get credential attachment: credential offer or credential must be receieved first"))
}
}

pub fn delete_credential(&self) -> VcxResult<()> {
trace!("Holder::delete_credential");

Expand Down
14 changes: 9 additions & 5 deletions libvcx/src/aries/handlers/issuance/holder/states/finished.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ pub struct FinishedHolderState {

impl FinishedHolderState {
pub fn get_attributes(&self) -> VcxResult<String> {
let credential = self.credential.as_ref().ok_or(VcxError::from_msg(VcxErrorKind::InvalidState, "No credential found"))?;
let content = credential.credentials_attach.content()?;
let cred_data: CredentialData = serde_json::from_str(&content)
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize {:?}, into CredentialData, err: {:?}", content, err)))?;
let attach = self.get_attachment()?;
let cred_data: CredentialData = serde_json::from_str(&attach)
.map_err(|err| VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot deserialize {:?}, into CredentialData, err: {:?}", attach, err)))?;

let mut new_map = serde_json::map::Map::new();
match cred_data.values.as_object() {
Expand All @@ -30,7 +29,12 @@ impl FinishedHolderState {
};
Ok(serde_json::Value::Object(new_map).to_string())
}
_ => Err(VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot convert {:?} into object", content)))
_ => Err(VcxError::from_msg(VcxErrorKind::InvalidJson, format!("Cannot convert {:?} into object", attach)))
}
}

pub fn get_attachment(&self) -> VcxResult<String> {
let credential = self.credential.as_ref().ok_or(VcxError::from_msg(VcxErrorKind::InvalidState, "No credential found"))?;
credential.credentials_attach.content()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ impl OfferReceivedState {
});
Ok(serde_json::Value::Object(new_map).to_string())
}

pub fn get_attachment(&self) -> VcxResult<String> {
self.offer.offers_attach.content()
}
}
6 changes: 6 additions & 0 deletions libvcx/src/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ pub fn get_attributes(handle: u32) -> VcxResult<String> {
})
}

pub fn get_attachment(handle: u32) -> VcxResult<String> {
HANDLE_MAP.get(handle, |credential| {
credential.get_attachment()
})
}

pub fn delete_credential(handle: u32) -> VcxResult<u32> {
let source_id = get_source_id(handle).unwrap_or_default();
trace!("Credential::delete_credential >>> credential_handle: {}, source_id: {}", handle, source_id);
Expand Down
17 changes: 17 additions & 0 deletions wrappers/ios/vcx/ConnectMeVcx.m
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,23 @@ - (void)credentialGetAttributes:(VcxHandle)credentialHandle
}
}

- (void)credentialGetAttachment:(VcxHandle)credentialHandle
completion:(void (^)(NSError *error, NSString *attach))completion{
vcx_error_t ret;
vcx_command_handle_t handle = [[VcxCallbacks sharedInstance] createCommandHandleFor:completion];

ret = vcx_credential_get_attachment(handle, credentialHandle, VcxWrapperCommonStringCallback);

if( ret != 0 )
{
[[VcxCallbacks sharedInstance] deleteCommandHandleFor: handle];

dispatch_async(dispatch_get_main_queue(), ^{
completion([NSError errorFromVcxError: ret],nil);
});
}
}

- (void)generateProof:(NSString *)proofRequestId
requestedAttrs:(NSString *)requestedAttrs
requestedPredicates:(NSString *)requestedPredicates
Expand Down
2 changes: 2 additions & 0 deletions wrappers/ios/vcx/include/libvcx.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ vcx_error_t vcx_credential_get_offers(vcx_command_handle_t command_handle, vcx_c
/** Get attributes for specified credential */
vcx_error_t vcx_credential_get_attributes(vcx_command_handle_t handle, vcx_credential_handle_t credential_handle, void (*cb)(vcx_command_handle_t command_handle, vcx_error_t err, const char *attributes));

vcx_error_t vcx_credential_get_attachment(vcx_command_handle_t handle, vcx_credential_handle_t credential_handle, void (*cb)(vcx_command_handle_t command_handle, vcx_error_t err, const char *attachment));

/** Updates the state of the credential from the agency. */
vcx_error_t vcx_credential_update_state(vcx_command_handle_t command_handle, vcx_credential_handle_t credential_handle, void (*cb)(vcx_command_handle_t xcommand_handle, vcx_error_t err, vcx_state_t state));

Expand Down
2 changes: 2 additions & 0 deletions wrappers/java/src/main/java/com/evernym/sdk/vcx/LibVcx.java
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ public interface API extends Library {
/** Retrieves attributes present in the credential or credential offer, depending on credential state */
public int vcx_credential_get_attributes(int command_handle, int credential_handle, Callback cb);

public int vcx_credential_get_attachment(int command_handle, int credential_handle, Callback cb);

/** Populates status with the current State of this credential. */
public int vcx_credential_serialize(int command_handle, int credential_handle, Callback cb);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,30 @@ public static CompletableFuture<String> credentialGetAttributes(
return future;
}

private static Callback vcxCredentialGetAttachmentCB = new Callback() {
@SuppressWarnings({"unused", "unchecked"})
public void callback(int command_handle, int err, String attachment) {
logger.debug("vcxCredentialGetAttachmentCB() called with: command_handle = [" + command_handle + "], err = [" + err + "], attachment = [" + attachment + "]");
CompletableFuture<String> future = (CompletableFuture<String>) removeFuture(command_handle);
if (!checkCallback(future, err)) return;
future.complete(attachment);
}
};

public static CompletableFuture<String> credentialGetAttachment(
int credentialHandle
) throws VcxException {
ParamGuard.notNull(credentialHandle, "credentialHandle");
logger.debug("getAttachment() called with: credentialHandle = [" + credentialHandle + "]");
CompletableFuture<String> future = new CompletableFuture<String>();
int commandHandle = addFuture(future);

int result = LibVcx.api.vcx_credential_get_attachment(commandHandle, credentialHandle, vcxCredentialGetAttachmentCB);
checkResult(result);

return future;
}

public static int credentialRelease(int credentialHandle) throws VcxException {
ParamGuard.notNull(credentialHandle, "credentialHandle");
logger.debug("credentialRelease() called with: credentialHandle = [" + credentialHandle + "]");
Expand Down
27 changes: 27 additions & 0 deletions wrappers/node/src/api/credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,33 @@ export class Credential extends VCXBaseWithState<ICredentialStructData> {
}
}

public async getAttachment (connection: Connection): Promise<string> {
try {
const attach = await createFFICallbackPromise<string>(
(resolve, reject, cb) => {
const rc = rustAPI().vcx_credential_get_attachment(0, this.handle, cb)
if (rc) {
reject(rc)
}
},
(resolve, reject) => Callback(
'void',
['uint32', 'uint32', 'string'],
(handle: number, err: number, messages: string) => {
if (err) {
reject(err)
return
}
resolve(messages)
})
)
return attach
} catch (err) {
throw new VCXInternalError(err)
}
}


get credOffer (): string {
return this._credOffer
}
Expand Down
3 changes: 3 additions & 0 deletions wrappers/node/src/rustlib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ export interface IFFIEntryPoint {
vcx_credential_get_state: (commandId: number, handle: number, cb: any) => number,
vcx_credential_get_offers: (commandId: number, connectionHandle: number, cb: any) => number,
vcx_credential_get_attributes: (commandId: number, connectionHandle: number, cb: any) => number,
vcx_credential_get_attachment: (commandId: number, connectionHandle: number, cb: any) => number,
vcx_credential_get_payment_info: (commandId: number, handle: number, cb: any) => number,
vcx_credential_get_payment_txn: (commandId: number, handle: number, cb: any) => number,

Expand Down Expand Up @@ -428,6 +429,8 @@ export const FFIConfiguration: { [ Key in keyof IFFIEntryPoint ]: any } = {
vcx_credential_get_offers: [FFI_ERROR_CODE, [FFI_COMMAND_HANDLE, FFI_CONNECTION_HANDLE, FFI_CALLBACK_PTR]],
vcx_credential_get_attributes: [FFI_ERROR_CODE, [FFI_COMMAND_HANDLE, FFI_CONNECTION_HANDLE,
FFI_CALLBACK_PTR]],
vcx_credential_get_attachment: [FFI_ERROR_CODE, [FFI_COMMAND_HANDLE, FFI_CONNECTION_HANDLE,
FFI_CALLBACK_PTR]],
vcx_credential_get_payment_info: [FFI_ERROR_CODE, [FFI_COMMAND_HANDLE, FFI_CREDENTIAL_HANDLE,FFI_CALLBACK_PTR]],
vcx_credential_get_payment_txn: [FFI_ERROR_CODE, [FFI_COMMAND_HANDLE, FFI_CREDENTIAL_HANDLE,FFI_CALLBACK_PTR]],

Expand Down
17 changes: 17 additions & 0 deletions wrappers/node/test/suite1/ariesvcx-credential.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,23 @@ describe('Credential:', () => {
})
})

describe('getAttachment:', () => {
it('success', async () => {
const connection = await createConnectionInviterRequested()
const offers = await Credential.getOffers(connection)
assert.ok(offers)
assert.ok(offers.length)
const offer = offers[0]
const credential = await credentialCreateWithOffer({
connection,
offer: JSON.stringify(offer),
sourceId: 'credentialGetAttributesTestSourceId'
})
const attach = JSON.parse(await credential.getAttachment(connection))
assert.deepEqual(attach.schema_id, 'V4SGRU86Z58d6TV7PBUe6f:2:FaberVcx:83.23.62')
})
})

describe('getPaymentInfo:', () => {
it.skip('success', async () => {
const credential = await credentialCreateWithOffer()
Expand Down