Skip to content
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
7 changes: 7 additions & 0 deletions .changeset/six-buttons-kick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@openwallet-foundation/askar-nodejs": patch
"@openwallet-foundation/askar-react-native": patch
"@openwallet-foundation/askar-shared": patch
---

feat: support profile renaming and copying
24 changes: 24 additions & 0 deletions packages/askar-nodejs/src/NodeJSAskar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import type {
SetCustomLoggerOptions,
SetMaxLogLevelOptions,
StoreCloseOptions,
StoreCopyProfileOptions,
StoreCopyToOptions,
StoreCreateProfileOptions,
StoreGenerateRawKeyOptions,
Expand All @@ -76,6 +77,7 @@ import type {
StoreRekeyOptions,
StoreRemoveOptions,
StoreRemoveProfileOptions,
StoreRenameProfileOptions,
StoreSetDefaultProfileOptions,
} from '@openwallet-foundation/askar-shared'
import {
Expand Down Expand Up @@ -1088,6 +1090,28 @@ export class NodeJSAskar implements Askar {
)
}

public async storeRenameProfile(options: StoreRenameProfileOptions): Promise<number> {
const { storeHandle, fromProfile, toProfile } = serializeArguments(options)

const response = await this.promisifyWithResponse<number>(
(cb, cbId) => this.nativeAskar.askar_store_rename_profile(storeHandle, fromProfile, toProfile, cb, cbId),
FFI_INT8
)

return handleInvalidNullResponse(response)
}

public async storeCopyProfile(options: StoreCopyProfileOptions): Promise<number> {
const { fromHandle, toHandle, fromProfile, toProfile } = serializeArguments(options)

const response = await this.promisifyWithResponse<number>(
(cb, cbId) => this.nativeAskar.askar_store_copy_profile(fromHandle, toHandle, fromProfile, toProfile, cb, cbId),
FFI_INT8
)

return handleInvalidNullResponse(response)
}

public async migrateIndySdk(options: MigrateIndySdkOptions): Promise<void> {
const { specUri, kdfLevel, walletKey, walletName } = serializeArguments(options)
await this.promisify((cb, cbId) =>
Expand Down
8 changes: 8 additions & 0 deletions packages/askar-nodejs/src/library/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ export const nativeBindings = {
askar_store_remove: [FFI_ERROR_CODE, [FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
askar_store_remove_profile: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
askar_store_set_default_profile: [FFI_ERROR_CODE, [FFI_STORE_HANDLE, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID]],
askar_store_rename_profile: [
FFI_ERROR_CODE,
[FFI_STORE_HANDLE, FFI_STRING, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID],
],
askar_store_copy_profile: [
FFI_ERROR_CODE,
[FFI_STORE_HANDLE, FFI_STORE_HANDLE, FFI_STRING, FFI_STRING, FFI_CALLBACK_PTR, FFI_CALLBACK_ID],
],

askar_migrate_indy_sdk: [
FFI_ERROR_CODE,
Expand Down
Binary file modified packages/askar-nodejs/tests/indy_wallet_sqlite_upgraded.db
Binary file not shown.
37 changes: 37 additions & 0 deletions packages/askar-nodejs/tests/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,44 @@ describe('Store and Session', () => {

strictEqual(await session7.count(firstEntry), 0)

await session7.insert(firstEntry)

strictEqual(await session7.count(firstEntry), 1)

await session7.close()

ok(await store.renameProfile({ fromProfile: profile, toProfile: 'newProfileName' }))

ok((await store.listProfiles()).includes('newProfileName'))

ok(!(await store.listProfiles()).includes(profile))

const session8 = await store.session('newProfileName').open()

strictEqual(await session8.count(firstEntry), 1)

await session8.close()

const destinationStore = await Store.provision({
uri: 'sqlite://:memory:',
keyMethod: new StoreKeyMethod(KdfMethod.Raw),
passKey: getRawKey(),
recreate: true,
})

ok(
await store.copyProfile({
toStore: destinationStore,
fromProfile: 'newProfileName',
toProfile: 'newerProfileName',
})
)

const session9 = await destinationStore.session('newerProfileName').open()

strictEqual(await session9.count(firstEntry), 1)

await session9.close()
})

test('Copy', async () => {
Expand Down
31 changes: 31 additions & 0 deletions packages/askar-react-native/cpp/askar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,37 @@ jsi::Value storeSetDefaultProfile(jsi::Runtime &rt, jsi::Object options) {
return createReturnValue(rt, code, nullptr);
}

jsi::Value storeRenameProfile(jsi::Runtime &rt, jsi::Object options) {
auto storeHandle = jsiToValue<int64_t>(rt, options, "storeHandle");
auto fromProfile = jsiToValue<std::string>(rt, options, "fromProfile");
auto toProfile = jsiToValue<std::string>(rt, options, "toProfile");

jsi::Function cb = options.getPropertyAsFunction(rt, "cb");
State *state = new State(&cb);
state->rt = &rt;

ErrorCode code = askar_store_rename_profile(
storeHandle, fromProfile.c_str(), toProfile.c_str(), callbackWithResponse, CallbackId(state));

return createReturnValue(rt, code, nullptr);
}

jsi::Value storeCopyProfile(jsi::Runtime &rt, jsi::Object options) {
auto fromHandle = jsiToValue<int64_t>(rt, options, "fromHandle");
auto toHandle = jsiToValue<int64_t>(rt, options, "toHandle");
auto fromProfile = jsiToValue<std::string>(rt, options, "fromProfile");
auto toProfile = jsiToValue<std::string>(rt, options, "toProfile");

jsi::Function cb = options.getPropertyAsFunction(rt, "cb");
State *state = new State(&cb);
state->rt = &rt;

ErrorCode code = askar_store_copy_profile(
fromHandle, toHandle, fromProfile.c_str(), toProfile.c_str(), callbackWithResponse, CallbackId(state));

return createReturnValue(rt, code, nullptr);
}

jsi::Value sessionClose(jsi::Runtime &rt, jsi::Object options) {
auto sessionHandle = jsiToValue<int64_t>(rt, options, "sessionHandle");
auto commit = jsiToValue<int8_t>(rt, options, "commit");
Expand Down
15 changes: 14 additions & 1 deletion packages/askar-react-native/cpp/include/libaries_askar.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ ErrorCode askar_key_wrap_key(LocalKeyHandle handle,
struct EncryptedBuffer *out);

/**
* Migrate an sqlite wallet from an indy-sdk structure to an aries-askar structure.
* Migrate an sqlite wallet from an indy-sdk structure to an Askar structure.
* It is important to note that this does not do any post-processing. If the record values, tags,
* names, etc. have changed, it must be processed manually afterwards. This script does the following:
*
Expand Down Expand Up @@ -560,6 +560,13 @@ ErrorCode askar_store_copy(StoreHandle handle,
void (*cb)(CallbackId cb_id, ErrorCode err, StoreHandle handle),
CallbackId cb_id);

ErrorCode askar_store_copy_profile(StoreHandle from_handle,
StoreHandle to_handle,
FfiStr from_profile,
FfiStr to_profile,
void (*cb)(CallbackId cb_id, ErrorCode err),
CallbackId cb_id);

ErrorCode askar_store_create_profile(StoreHandle handle,
FfiStr profile,
void (*cb)(CallbackId cb_id,
Expand Down Expand Up @@ -615,6 +622,12 @@ ErrorCode askar_store_remove_profile(StoreHandle handle,
void (*cb)(CallbackId cb_id, ErrorCode err, int8_t removed),
CallbackId cb_id);

ErrorCode askar_store_rename_profile(StoreHandle handle,
FfiStr from_profile,
FfiStr to_profile,
void (*cb)(CallbackId cb_id, ErrorCode err, int8_t renamed),
CallbackId cb_id);

ErrorCode askar_store_set_default_profile(StoreHandle handle,
FfiStr profile,
void (*cb)(CallbackId cb_id, ErrorCode err),
Expand Down
4 changes: 4 additions & 0 deletions packages/askar-react-native/src/NativeBindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ export interface NativeBindings {

storeRemoveProfile(options: unknown): ReturnObject<never>

storeRenameProfile(options: unknown): ReturnObject<never>

storeCopyProfile(options: unknown): ReturnObject<never>

storeSetDefaultProfile(options: unknown): ReturnObject<never>

migrateIndySdk(options: unknown): ReturnObject<never>
Expand Down
20 changes: 20 additions & 0 deletions packages/askar-react-native/src/ReactNativeAskar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import type {
SessionUpdateKeyOptions,
SessionUpdateOptions,
StoreCloseOptions,
StoreCopyProfileOptions,
StoreCopyToOptions,
StoreCreateProfileOptions,
StoreGenerateRawKeyOptions,
Expand All @@ -72,6 +73,7 @@ import type {
StoreRekeyOptions,
StoreRemoveOptions,
StoreRemoveProfileOptions,
StoreRenameProfileOptions,
StoreSetDefaultProfileOptions,
} from '@openwallet-foundation/askar-shared'
import type { NativeBindings } from './NativeBindings'
Expand Down Expand Up @@ -726,6 +728,24 @@ export class ReactNativeAskar implements Askar {
return handleInvalidNullResponse(response)
}

public async storeRenameProfile(options: StoreRenameProfileOptions): Promise<number> {
const serializedOptions = serializeArguments(options)
const response = await this.promisifyWithResponse<number>((cb) =>
this.handleError(this.askar.storeRenameProfile({ cb, ...serializedOptions }))
)

return handleInvalidNullResponse(response)
}

public async storeCopyProfile(options: StoreCopyProfileOptions): Promise<number> {
const serializedOptions = serializeArguments(options)
const response = await this.promisifyWithResponse<number>((cb) =>
this.handleError(this.askar.storeCopyProfile({ cb, ...serializedOptions }))
)

return handleInvalidNullResponse(response)
}

public async storeSetDefaultProfile(options: StoreSetDefaultProfileOptions): Promise<void> {
const serializedOptions = serializeArguments(options)
const response = await this.promisifyWithResponse((cb) =>
Expand Down
13 changes: 13 additions & 0 deletions packages/askar-shared/src/askar/Askar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,17 @@ export type StoreSetDefaultProfileOptions = {
storeHandle: StoreHandle
profile: string
}
export type StoreRenameProfileOptions = {
storeHandle: StoreHandle
fromProfile: string
toProfile: string
}
export type StoreCopyProfileOptions = {
fromHandle: StoreHandle
toHandle: StoreHandle
fromProfile: string
toProfile: string
}

export type MigrateIndySdkOptions = {
specUri: string
Expand Down Expand Up @@ -426,6 +437,8 @@ export type Askar = {
storeProvision(options: StoreProvisionOptions): Promise<StoreHandle>
storeRekey(options: StoreRekeyOptions): Promise<void>
storeRemove(options: StoreRemoveOptions): Promise<number>
storeRenameProfile(options: StoreRenameProfileOptions): Promise<number>
storeCopyProfile(options: StoreCopyProfileOptions): Promise<number>
storeRemoveProfile(options: StoreRemoveProfileOptions): Promise<number>
storeSetDefaultProfile(options: StoreSetDefaultProfileOptions): Promise<void>

Expand Down
12 changes: 12 additions & 0 deletions packages/askar-shared/src/store/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ export class Store {
return askar.storeListProfiles({ storeHandle: this.handle })
}

public async renameProfile({ fromProfile, toProfile }: { fromProfile: string; toProfile: string }) {
return await askar.storeRenameProfile({ fromProfile, toProfile, storeHandle: this.handle })
}

public async copyProfile({
toStore,
fromProfile,
toProfile,
}: { toStore: Store; fromProfile: string; toProfile: string }) {
return await askar.storeCopyProfile({ fromProfile, toProfile, fromHandle: this.handle, toHandle: toStore.handle })
}

public async removeProfile(name: string) {
return await askar.storeRemoveProfile({ profile: name, storeHandle: this.handle })
}
Expand Down