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
8 changes: 6 additions & 2 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fileignoreconfig:
ignore_detectors:
- filecontent
- filename: package-lock.json
checksum: b043facad4b4aca7a013730746bdb9cb9e9dfca1e5d6faf11c068fc2525569c0
checksum: c37956b0e6ccd5267dac7fd6f4347fbb5ad41defe1c42d39aaaeaf64d2cf8605
- filename: .husky/pre-commit
checksum: 52a664f536cf5d1be0bea19cb6031ca6e8107b45b6314fe7d47b7fad7d800632
- filename: test/sanity-check/api/user-test.js
Expand All @@ -26,4 +26,8 @@ fileignoreconfig:
checksum: e8a32ffbbbdba2a15f3d327273f0a5b4eb33cf84cd346562596ab697125bbbc6
- filename: test/sanity-check/api/bulkOperation-test.js
checksum: f40a14c84ab9a194aaf830ca68e14afde2ef83496a07d4a6393d7e0bed15fb0e
version: "1.0"
- filename: lib/contentstackClient.js
checksum: b76ca091caa3a1b2658cd422a2d8ef3ac9996aea0aff3f982d56bb309a3d9fde
- filename: test/unit/ContentstackClient-test.js
checksum: e712b74f37ea15afd2ac095fc2154f8c9f2ffe955659e77651da4a0d7079ec88
version: "1.0"
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## [v1.23.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.24.0) (2025-07-28)
## [v1.24.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.24.0) (2025-08-18)
- Feat
- Added Support for MFA

## [v1.23.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.23.1) (2025-07-28)
- Fix
- Add asset types support in bulk operations

Expand Down
73 changes: 49 additions & 24 deletions lib/contentstackClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import cloneDeep from 'lodash/cloneDeep'
import { User } from './user/index'
import error from './core/contentstackError'
import OAuthHandler from './core/oauthHandler'
import { authenticator } from 'otplib'

export default function contentstackClient ({ http }) {
/**
Expand All @@ -16,7 +17,8 @@ export default function contentstackClient ({ http }) {
* @param {Object} parameters - login parameters
* @prop {string} parameters.email - email id for user to login
* @prop {string} parameters.password - password for user to login
* @prop {string} parameters.token - token for user to login
* @prop {string} parameters.tfa_token - tfa token for user to login (2FA token)
* @prop {string} parameters.mfaSecret - TOTP secret key for generating 2FA token
* @returns {Promise}
* @example
* import * as contentstack from '@contentstack/management'
Expand All @@ -25,10 +27,23 @@ export default function contentstackClient ({ http }) {
* client.login({ email: <emailid>, password: <password> })
* .then(() => console.log('Logged in successfully'))
*
* @example
* client.login({ email: <emailid>, password: <password>, tfa_token: <tfa_token> })
* .then(() => console.log('Logged in successfully'))
*
* @example
* client.login({ email: <emailid>, password: <password>, mfaSecret: <mfa_secret> })
* .then(() => console.log('Logged in successfully'))
*/
function login (requestBody, params = {}) {
function login (requestBody = {}, params = {}) {
http.defaults.versioningStrategy = 'path'

const { mfaSecret, ...credentials } = requestBody
requestBody = credentials

if (!requestBody.tfa_token && mfaSecret) {
requestBody.tfa_token = authenticator.generate(mfaSecret)
}
return http.post('/user-session', { user: requestBody }, { params: params })
.then((response) => {
if (response.data.user != null && response.data.user.authtoken != null) {
Expand All @@ -55,10 +70,9 @@ export default function contentstackClient ({ http }) {
*/
function getUser (params = {}) {
http.defaults.versioningStrategy = 'path'
return http.get('/user', { params: params })
.then((response) => {
return new User(http, response.data)
}, error)
return http.get('/user', { params: params }).then((response) => {
return new User(http, response.data)
}, error)
}
/**
* @description Get Stack instance. A stack is a space that stores the content of a project.
Expand Down Expand Up @@ -127,13 +141,16 @@ export default function contentstackClient ({ http }) {
*/
function organization (uid = null) {
http.defaults.versioningStrategy = 'path'
return new Organization(http, uid !== null ? { organization: { uid: uid } } : null)
return new Organization(
http,
uid !== null ? { organization: { uid: uid } } : null
)
}

/**
* @description The Log out of your account call is used to sign out the user of Contentstack account.
* @memberof ContentstackClient
* @param {String} authtoken - Authtoken to logout from.
* @param {String} authtoken - Authtoken to logout from.
* @func logout
* @returns {Object} Response object.
*
Expand All @@ -152,25 +169,25 @@ export default function contentstackClient ({ http }) {
function logout (authtoken) {
http.defaults.versioningStrategy = 'path'
if (authtoken !== undefined) {
return http.delete('/user-session', {
headers: {
authtoken: authtoken
}
})
return http
.delete('/user-session', {
headers: {
authtoken: authtoken
}
})
.then((response) => {
return response.data
}, error)
}
return http.delete('/user-session')
.then((response) => {
if (http.defaults.headers.common) {
delete http.defaults.headers.common.authtoken
}
delete http.defaults.headers.authtoken
delete http.httpClientParams.authtoken
delete http.httpClientParams.headers.authtoken
return response.data
}, error)
return http.delete('/user-session').then((response) => {
if (http.defaults.headers.common) {
delete http.defaults.headers.common.authtoken
}
delete http.defaults.headers.authtoken
delete http.httpClientParams.authtoken
delete http.httpClientParams.headers.authtoken
return response.data
}, error)
}

/**
Expand Down Expand Up @@ -201,7 +218,15 @@ export default function contentstackClient ({ http }) {
const responseType = params.responseType || 'code'
const scope = params.scope
const clientSecret = params.clientSecret
return new OAuthHandler(http, appId, clientId, redirectUri, clientSecret, responseType, scope)
return new OAuthHandler(
http,
appId,
clientId,
redirectUri,
clientSecret,
responseType,
scope
)
}

return {
Expand Down
1 change: 1 addition & 0 deletions lib/core/contentstackError.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export default function error (errorResponse) {
errorDetails.errorCode = data.error_code || 0
errorDetails.errors = data.errors || {}
errorDetails.error = data.error || ''
errorDetails.tfa_type = data.tfa_type
}

var error = new Error()
Expand Down
71 changes: 69 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/management",
"version": "1.23.2",
"version": "1.24.0",
"description": "The Content Management API is used to manage the content of your Contentstack account",
"main": "./dist/node/contentstack-management.js",
"browser": "./dist/web/contentstack-management.js",
Expand Down Expand Up @@ -58,6 +58,7 @@
"form-data": "^4.0.4",
"husky": "^9.1.7",
"lodash": "^4.17.21",
"otplib": "^12.0.1",
"qs": "^6.14.0",
"stream-browserify": "^3.0.0"
},
Expand Down
Loading
Loading