11const axios = require ( 'axios' )
22const https = require ( "https" )
33const { logConfig } = require ( './logger' )
4+ const cds = require ( '@sap/cds' )
5+
6+ /**
7+ * Validates the presence of required Service Manager credentials
8+ * @param {* } serviceManagerCreds - Service Manager credentials object
9+ * @throws Will throw an error if validation fails
10+ */
11+ function validateServiceManagerCredentials ( serviceManagerCreds ) {
12+ if ( ! serviceManagerCreds ) {
13+ logConfig . configValidation ( 'serviceManager.credentials' , serviceManagerCreds , false ,
14+ 'Bind a Service Manager instance for separate object store mode' )
15+ throw new Error ( "Service Manager Instance is not bound" )
16+ }
417
5- async function getObjectStoreCredentials ( tenantID , sm_url , token ) {
6- logConfig . processStep ( 'Fetching object store credentials' , { tenantID, sm_url } )
18+ const requiredSmFields = [ 'sm_url' , 'url' , 'clientid' ]
19+ const missingSmFields = requiredSmFields . filter ( field => ! serviceManagerCreds [ field ] )
20+
21+ if ( missingSmFields . length > 0 ) {
22+ logConfig . configValidation ( 'serviceManager.credentials' , serviceManagerCreds , false ,
23+ `Service Manager credentials missing: ${ missingSmFields . join ( ', ' ) } ` )
24+ throw new Error ( `Missing Service Manager credentials: ${ missingSmFields . join ( ', ' ) } ` )
25+ }
26+ }
727
8- // Validate inputs
28+ /**
29+ * Validates the inputs required for fetching object store credentials
30+ * @param {string } tenantID - Tenant ID
31+ * @param {string } sm_url - Service Manager URL
32+ * @param {string } token - Access token
33+ * @returns
34+ */
35+ function validateInputs ( tenantID , sm_url , token ) {
936 if ( ! tenantID ) {
1037 logConfig . withSuggestion ( 'error' , 'Tenant ID is required for object store credentials' , null ,
1138 'Ensure multitenancy is properly configured and tenant context is available' , { tenantID } )
12- return null
39+ return false
1340 }
1441
1542 if ( ! sm_url ) {
1643 logConfig . configValidation ( 'serviceManager.credentials.sm_url' , sm_url , false ,
1744 'Bind a Service Manager instance to your application' )
18- return null
45+ return false
1946 }
2047
2148 if ( ! token ) {
2249 logConfig . withSuggestion ( 'error' , 'Access token is required for Service Manager API' , null ,
2350 'Check if token fetching completed successfully' , { hasToken : ! ! token } )
51+ return false
52+ }
53+
54+ return true
55+ }
56+
57+ /**
58+ * Fetches object store service binding from Service Manager
59+ * @param {string } sm_url - Service Manager URL
60+ * @param {string } tenantID - Tenant ID
61+ * @param {string } token - Access token
62+ * @returns {Promise<Array> } - Promise resolving to array of service bindings
63+ */
64+ async function fetchObjectStoreBinding ( sm_url , tenantID , token ) {
65+ logConfig . debug ( 'Making Service Manager API call' , {
66+ tenantID,
67+ endpoint : `${ sm_url } /v1/service_bindings` ,
68+ labelQuery : `service eq 'OBJECT_STORE' and tenant_id eq '${ tenantID } '`
69+ } )
70+
71+ const response = await axios . get ( `${ sm_url } /v1/service_bindings` , {
72+ params : { labelQuery : `service eq 'OBJECT_STORE' and tenant_id eq '${ tenantID } '` } ,
73+ headers : {
74+ 'Accept' : 'application/json' ,
75+ 'Authorization' : `Bearer ${ token } ` ,
76+ 'Content-Type' : 'application/json'
77+ }
78+ } )
79+
80+ return response . data ?. items || [ ]
81+ }
82+
83+ /**
84+ * Retrieves object store credentials for a given tenant
85+ * @param {* } tenantID - Tenant ID
86+ * @returns {Promise<Object|null> } - Promise resolving to object store credentials or null
87+ */
88+ async function getObjectStoreCredentials ( tenantID ) {
89+ const serviceManagerCreds = cds . env . requires ?. serviceManager ?. credentials
90+
91+ validateServiceManagerCredentials ( serviceManagerCreds )
92+
93+ const { sm_url, url, clientid, clientsecret, certificate, key, certurl } = serviceManagerCreds
94+
95+ logConfig . debug ( 'Fetching access token for tenant' , { tenantID, sm_url : sm_url } )
96+ const token = await fetchToken ( url , clientid , clientsecret , certificate , key , certurl )
97+
98+ logConfig . processStep ( 'Fetching object store credentials' , { tenantID, sm_url } )
99+
100+ if ( ! validateInputs ( tenantID , sm_url , token ) ) {
24101 return null
25102 }
26103
27104 try {
28- logConfig . debug ( 'Making Service Manager API call' , {
29- tenantID,
30- endpoint : `${ sm_url } /v1/service_bindings` ,
31- labelQuery : `service eq 'OBJECT_STORE' and tenant_id eq '${ tenantID } '`
32- } )
33-
34- const response = await axios . get ( `${ sm_url } /v1/service_bindings` , {
35- params : { labelQuery : `service eq 'OBJECT_STORE' and tenant_id eq '${ tenantID } '` } ,
36- headers : {
37- 'Accept' : 'application/json' ,
38- 'Authorization' : `Bearer ${ token } ` ,
39- 'Content-Type' : 'application/json'
40- }
41- } )
105+ const items = await fetchObjectStoreBinding ( sm_url , tenantID , token )
42106
43- if ( ! response . data ?. items ? .length ) {
107+ if ( ! items . length ) {
44108 logConfig . withSuggestion ( 'error' , `No object store service binding found for tenant` , null ,
45109 'Ensure an Object Store instance is subscribed and bound for this tenant' ,
46- { tenantID, itemsFound : response . data ?. items ?. length || 0 } )
110+ { tenantID, itemsFound : 0 } )
47111 return null
48112 }
49113
50- const credentials = response . data . items [ 0 ]
114+ const credentials = items [ 0 ]
51115 logConfig . info ( 'Object store credentials retrieved successfully' , {
52116 tenantID,
53117 hasCredentials : ! ! credentials ,
@@ -72,6 +136,16 @@ async function getObjectStoreCredentials(tenantID, sm_url, token) {
72136 }
73137}
74138
139+ /**
140+ * Fetches an OAuth token using either client credentials or MTLS
141+ * @param {string } url - Token endpoint URL
142+ * @param {string } clientid - Client ID
143+ * @param {string } clientsecret - Client Secret
144+ * @param {string } certificate - MTLS Certificate
145+ * @param {string } key - MTLS Key
146+ * @param {string } certURL - MTLS Certificate URL
147+ * @returns {Promise<string> } - Promise resolving to access token
148+ */
75149async function fetchToken ( url , clientid , clientsecret , certificate , key , certURL ) {
76150 logConfig . processStep ( 'Determining token fetch method' , {
77151 hasClientCredentials : ! ! ( clientid && clientsecret ) ,
@@ -106,6 +180,13 @@ async function fetchToken(url, clientid, clientsecret, certificate, key, certURL
106180 }
107181}
108182
183+ /**
184+ * Fetches OAuth token using client credentials flow
185+ * @param {string } url - Token endpoint URL
186+ * @param {string } clientid - Client ID
187+ * @param {string } clientsecret - Client Secret
188+ * @returns
189+ */
109190async function fetchTokenWithClientSecret ( url , clientid , clientsecret ) {
110191 const startTime = Date . now ( )
111192
@@ -150,6 +231,14 @@ async function fetchTokenWithClientSecret(url, clientid, clientsecret) {
150231 }
151232}
152233
234+ /**
235+ * Fetches OAuth token using MTLS authentication
236+ * @param {string } certURL - Certificate URL
237+ * @param {string } clientid - Client ID
238+ * @param {string } certificate - MTLS Certificate
239+ * @param {string } key - MTLS Key
240+ * @returns {Promise<string> } - Promise resolving to access token
241+ */
153242async function fetchTokenWithMTLS ( certURL , clientid , certificate , key ) {
154243 const startTime = Date . now ( )
155244
0 commit comments