@@ -70,7 +70,7 @@ import {
70
70
ArFSPublicFolderCacheKey ,
71
71
defaultArFSAnonymousCache
72
72
} from './arfsdao_anonymous' ;
73
- import { deriveDriveKey , deriveFileKey } from '../utils/crypto' ;
73
+ import { deriveDriveKey , deriveFileKey , driveDecrypt } from '../utils/crypto' ;
74
74
import {
75
75
DEFAULT_APP_NAME ,
76
76
DEFAULT_APP_VERSION ,
@@ -175,7 +175,7 @@ import {
175
175
} from './tx/arfs_tx_data_types' ;
176
176
import { ArFSTagAssembler } from './tags/tag_assembler' ;
177
177
import { assertDataRootsMatch , rePrepareV2Tx } from '../utils/arfsdao_utils' ;
178
- import { ArFSDataToUpload , ArFSFolderToUpload } from '../exports' ;
178
+ import { ArFSDataToUpload , ArFSFolderToUpload , DrivePrivacy } from '../exports' ;
179
179
import { Turbo , TurboCachesResponse } from './turbo' ;
180
180
import { ArweaveSigner } from 'arbundles/src/signing' ;
181
181
@@ -1757,6 +1757,64 @@ export class ArFSDAO extends ArFSDAOAnonymous {
1757
1757
) ;
1758
1758
}
1759
1759
1760
+ public async getOwnerAndAssertDrive ( driveId : DriveID , driveKey ?: DriveKey ) : Promise < ArweaveAddress > {
1761
+ const cachedOwner = this . caches . ownerCache . get ( driveId ) ;
1762
+ if ( cachedOwner ) {
1763
+ return cachedOwner ;
1764
+ }
1765
+
1766
+ return this . caches . ownerCache . put (
1767
+ driveId ,
1768
+ ( async ( ) => {
1769
+ const gqlQuery = buildQuery ( {
1770
+ tags : [
1771
+ { name : 'Entity-Type' , value : 'drive' } ,
1772
+ { name : 'Drive-Id' , value : `${ driveId } ` }
1773
+ ] ,
1774
+ sort : ASCENDING_ORDER
1775
+ } ) ;
1776
+ const transactions = await this . gatewayApi . gqlRequest ( gqlQuery ) ;
1777
+ const edges : GQLEdgeInterface [ ] = transactions . edges ;
1778
+
1779
+ if ( ! edges . length ) {
1780
+ throw new Error ( `Could not find a transaction with "Drive-Id": ${ driveId } ` ) ;
1781
+ }
1782
+
1783
+ const edgeOfFirstDrive = edges [ 0 ] ;
1784
+ const driveOwnerAddress = edgeOfFirstDrive . node . owner . address ;
1785
+ const driveOwner = new ArweaveAddress ( driveOwnerAddress ) ;
1786
+
1787
+ const drivePrivacy : DrivePrivacy = driveKey ? 'private' : 'public' ;
1788
+ const drivePrivacyFromTag = edgeOfFirstDrive . node . tags . find ( ( t ) => t . name === 'Drive-Privacy' ) ;
1789
+
1790
+ if ( ! drivePrivacyFromTag ) {
1791
+ throw new Error ( 'Target drive has no "Drive-Privacy" tag!' ) ;
1792
+ }
1793
+
1794
+ if ( drivePrivacyFromTag . value !== drivePrivacy ) {
1795
+ throw new Error ( `Target drive is not a ${ drivePrivacy } drive!` ) ;
1796
+ }
1797
+
1798
+ if ( driveKey ) {
1799
+ const cipherIVFromTag = edgeOfFirstDrive . node . tags . find ( ( t ) => t . name === 'Cipher-IV' ) ;
1800
+ if ( ! cipherIVFromTag ) {
1801
+ throw new Error ( 'Target private drive has no "Cipher-IV" tag!' ) ;
1802
+ }
1803
+
1804
+ const driveDataBuffer = await this . gatewayApi . getTxData ( TxID ( edgeOfFirstDrive . node . id ) ) ;
1805
+ try {
1806
+ // Attempt to decrypt drive to assert drive key is correct
1807
+ await driveDecrypt ( cipherIVFromTag . value , driveKey , driveDataBuffer ) ;
1808
+ } catch {
1809
+ throw new Error ( 'Provided drive key or password could not decrypt target private drive!' ) ;
1810
+ }
1811
+ }
1812
+
1813
+ return driveOwner ;
1814
+ } ) ( )
1815
+ ) ;
1816
+ }
1817
+
1760
1818
/**
1761
1819
* Lists the children of certain private folder
1762
1820
* @param {FolderID } folderId the folder ID to list children of
0 commit comments