@@ -7,6 +7,7 @@ import cloneDeep from 'lodash/cloneDeep'
77import { User } from './user/index'
88import error from './core/contentstackError'
99import OAuthHandler from './core/oauthHandler'
10+ import { authenticator } from 'otplib'
1011
1112export default function contentstackClient ( { http } ) {
1213 /**
@@ -16,7 +17,8 @@ export default function contentstackClient ({ http }) {
1617 * @param {Object } parameters - login parameters
1718 * @prop {string } parameters.email - email id for user to login
1819 * @prop {string } parameters.password - password for user to login
19- * @prop {string } parameters.token - token for user to login
20+ * @prop {string } parameters.token - token for user to login (2FA token)
21+ * @prop {string } parameters.tfa_token - tfa token for user to login (2FA token)
2022 * @returns {Promise }
2123 * @example
2224 * import * as contentstack from '@contentstack/management'
@@ -26,9 +28,28 @@ export default function contentstackClient ({ http }) {
2628 * .then(() => console.log('Logged in successfully'))
2729 *
2830 */
29- function login ( requestBody , params = { } ) {
31+ /**
32+ * Login function that supports both regular login and TOTP-based 2FA
33+ * @param {Object } requestBody - Login credentials
34+ * @param {string } requestBody.email - Email address
35+ * @param {string } requestBody.password - Password
36+ * @param {string } [requestBody.token] - 2FA token
37+ * @param {string } [requestBody.tfa_token] - Alternative 2FA token
38+ * @param {string } [requestBody.mfaSecret] - TOTP secret key for generating 2FA token
39+ * @param {Object } params - Additional parameters
40+ * @returns {Promise }
41+ */
42+ function login ( requestBody = { } , params = { } ) {
3043 http . defaults . versioningStrategy = 'path'
3144
45+ const { mfaSecret, ...credentials } = requestBody
46+ requestBody = credentials
47+
48+ if ( requestBody ?. tfa_token ) {
49+ // tfa_token is already in credentials, no need to do anything
50+ } else if ( mfaSecret ) {
51+ requestBody . tfa_token = authenticator . generate ( mfaSecret )
52+ }
3253 return http . post ( '/user-session' , { user : requestBody } , { params : params } )
3354 . then ( ( response ) => {
3455 if ( response . data . user != null && response . data . user . authtoken != null ) {
@@ -55,10 +76,9 @@ export default function contentstackClient ({ http }) {
5576 */
5677 function getUser ( params = { } ) {
5778 http . defaults . versioningStrategy = 'path'
58- return http . get ( '/user' , { params : params } )
59- . then ( ( response ) => {
60- return new User ( http , response . data )
61- } , error )
79+ return http . get ( '/user' , { params : params } ) . then ( ( response ) => {
80+ return new User ( http , response . data )
81+ } , error )
6282 }
6383 /**
6484 * @description Get Stack instance. A stack is a space that stores the content of a project.
@@ -127,13 +147,16 @@ export default function contentstackClient ({ http }) {
127147 */
128148 function organization ( uid = null ) {
129149 http . defaults . versioningStrategy = 'path'
130- return new Organization ( http , uid !== null ? { organization : { uid : uid } } : null )
150+ return new Organization (
151+ http ,
152+ uid !== null ? { organization : { uid : uid } } : null
153+ )
131154 }
132155
133156 /**
134157 * @description The Log out of your account call is used to sign out the user of Contentstack account.
135158 * @memberof ContentstackClient
136- * @param {String } authtoken - Authtoken to logout from.
159+ * @param {String } authtoken - Authtoken to logout from.
137160 * @func logout
138161 * @returns {Object } Response object.
139162 *
@@ -152,25 +175,25 @@ export default function contentstackClient ({ http }) {
152175 function logout ( authtoken ) {
153176 http . defaults . versioningStrategy = 'path'
154177 if ( authtoken !== undefined ) {
155- return http . delete ( '/user-session' , {
156- headers : {
157- authtoken : authtoken
158- }
159- } )
178+ return http
179+ . delete ( '/user-session' , {
180+ headers : {
181+ authtoken : authtoken
182+ }
183+ } )
160184 . then ( ( response ) => {
161185 return response . data
162186 } , error )
163187 }
164- return http . delete ( '/user-session' )
165- . then ( ( response ) => {
166- if ( http . defaults . headers . common ) {
167- delete http . defaults . headers . common . authtoken
168- }
169- delete http . defaults . headers . authtoken
170- delete http . httpClientParams . authtoken
171- delete http . httpClientParams . headers . authtoken
172- return response . data
173- } , error )
188+ return http . delete ( '/user-session' ) . then ( ( response ) => {
189+ if ( http . defaults . headers . common ) {
190+ delete http . defaults . headers . common . authtoken
191+ }
192+ delete http . defaults . headers . authtoken
193+ delete http . httpClientParams . authtoken
194+ delete http . httpClientParams . headers . authtoken
195+ return response . data
196+ } , error )
174197 }
175198
176199 /**
@@ -201,7 +224,15 @@ export default function contentstackClient ({ http }) {
201224 const responseType = params . responseType || 'code'
202225 const scope = params . scope
203226 const clientSecret = params . clientSecret
204- return new OAuthHandler ( http , appId , clientId , redirectUri , clientSecret , responseType , scope )
227+ return new OAuthHandler (
228+ http ,
229+ appId ,
230+ clientId ,
231+ redirectUri ,
232+ clientSecret ,
233+ responseType ,
234+ scope
235+ )
205236 }
206237
207238 return {
0 commit comments