@@ -249,6 +249,9 @@ private const val VIEW_PAGER_OFFSCREEN_PAGE_LIMIT = 4
249249private const val MEDIA_ID_NO_FEATURED_IMAGE_SET = 0
250250
251251object GutenbergKitSettingsBuilder {
252+ private const val AUTH_BEARER_PREFIX = " Bearer "
253+ private const val AUTH_BASIC_PREFIX = " Basic "
254+
252255 data class SiteConfig (
253256 val url : String ,
254257 val siteId : Long ,
@@ -260,25 +263,33 @@ object GutenbergKitSettingsBuilder {
260263 val apiRestUsernamePlain : String? ,
261264 val apiRestPasswordPlain : String?
262265 )
263-
266+
264267 data class PostConfig (
265268 val remotePostId : Long? ,
266269 val isPage : Boolean ,
267270 val title : String? ,
268271 val content : String?
269272 )
270-
273+
271274 data class FeatureConfig (
272275 val isPluginsFeatureEnabled : Boolean ,
273276 val isThemeStylesFeatureEnabled : Boolean
274277 )
275-
278+
276279 data class AppConfig (
277280 val accessToken : String? ,
278281 val locale : String ,
279282 val cookies : Any?
280283 )
281-
284+
285+ /* *
286+ * Builds the settings configuration for GutenbergKit editor.
287+ *
288+ * This method determines the appropriate authentication method based on site type:
289+ * - WP.com sites use Bearer token authentication with the public API
290+ * - Jetpack/self-hosted sites with application passwords use Basic authentication
291+ * - Falls back to WP.com REST API when no application password is available
292+ */
282293 fun buildSettings (
283294 siteConfig : SiteConfig ,
284295 postConfig : PostConfig ,
@@ -287,22 +298,23 @@ object GutenbergKitSettingsBuilder {
287298 ): MutableMap <String , Any ?> {
288299 val applicationPassword = siteConfig.apiRestPasswordPlain
289300 val shouldUseWPComRestApi = applicationPassword.isNullOrEmpty() && siteConfig.isUsingWpComRestApi
290-
301+
291302 val siteApiRoot = if (shouldUseWPComRestApi) " https://public-api.wordpress.com/"
292303 else siteConfig.wpApiRestUrl ? : " ${siteConfig.url} /wp-json/"
293-
294- val authHeader = if (shouldUseWPComRestApi) " Bearer ${appConfig.accessToken ? : " " } "
295- else " Basic ${Base64 .encodeToString(
296- " ${siteConfig.apiRestUsernamePlain} :$applicationPassword " .toByteArray(),
297- Base64 .NO_WRAP
298- )} "
299-
304+
305+ val authHeader = buildAuthHeader(
306+ shouldUseWPComRestApi = shouldUseWPComRestApi,
307+ accessToken = appConfig.accessToken,
308+ username = siteConfig.apiRestUsernamePlain,
309+ password = applicationPassword
310+ )
311+
300312 val siteApiNamespace = if (shouldUseWPComRestApi)
301313 arrayOf(" sites/${siteConfig.siteId} /" , " sites/${UrlUtils .removeScheme(siteConfig.url)} /" )
302314 else arrayOf()
303-
315+
304316 val wpcomLocaleSlug = appConfig.locale.replace(" _" , " -" ).lowercase()
305-
317+
306318 return mutableMapOf (
307319 " postId" to postConfig.remotePostId?.toInt(),
308320 " postType" to if (postConfig.isPage) " page" else " post" ,
@@ -324,7 +336,49 @@ object GutenbergKitSettingsBuilder {
324336 " cookies" to appConfig.cookies
325337 )
326338 }
327-
339+
340+ /* *
341+ * Builds the authentication header based on the authentication method.
342+ *
343+ * @param shouldUseWPComRestApi True if using WP.com REST API (Bearer auth)
344+ * @param accessToken The OAuth2 access token for WP.com authentication
345+ * @param username The username for Basic auth (application passwords)
346+ * @param password The password for Basic auth (application passwords)
347+ * @return The formatted authentication header string, or null if credentials are invalid
348+ */
349+ private fun buildAuthHeader (
350+ shouldUseWPComRestApi : Boolean ,
351+ accessToken : String? ,
352+ username : String? ,
353+ password : String?
354+ ): String? {
355+ return if (shouldUseWPComRestApi) {
356+ if (! accessToken.isNullOrEmpty()) {
357+ " $AUTH_BEARER_PREFIX$accessToken "
358+ } else {
359+ AppLog .w(AppLog .T .EDITOR , " Missing access token for WP.com REST API authentication" )
360+ null
361+ }
362+ } else {
363+ if (! username.isNullOrEmpty() && ! password.isNullOrEmpty()) {
364+ try {
365+ val credentials = " $username :$password "
366+ val encodedCredentials = Base64 .encodeToString(
367+ credentials.toByteArray(Charsets .UTF_8 ),
368+ Base64 .NO_WRAP
369+ )
370+ " $AUTH_BASIC_PREFIX$encodedCredentials "
371+ } catch (e: IllegalArgumentException ) {
372+ AppLog .e(AppLog .T .EDITOR , " Failed to encode Basic auth credentials" , e)
373+ null
374+ }
375+ } else {
376+ AppLog .w(AppLog .T .EDITOR , " Incomplete credentials for Basic authentication" )
377+ null
378+ }
379+ }
380+ }
381+
328382 private fun shouldUsePlugins (
329383 isFeatureEnabled : Boolean ,
330384 isWPComSite : Boolean ,
@@ -2407,27 +2461,27 @@ class GutenbergKitActivity : BaseAppCompatActivity(), EditorFragmentActivity, Ed
24072461 apiRestUsernamePlain = site.apiRestUsernamePlain,
24082462 apiRestPasswordPlain = siteModel.apiRestPasswordPlain
24092463 )
2410-
2464+
24112465 val postConfig = GutenbergKitSettingsBuilder .PostConfig (
24122466 remotePostId = editPostRepository.getPost()?.remotePostId,
24132467 isPage = editPostRepository.isPage,
24142468 title = editPostRepository.getPost()?.title,
24152469 content = editPostRepository.getPost()?.content
24162470 )
2417-
2471+
24182472 val featureConfig = GutenbergKitSettingsBuilder .FeatureConfig (
24192473 isPluginsFeatureEnabled = gutenbergKitPluginsFeature.isEnabled(),
24202474 isThemeStylesFeatureEnabled = experimentalFeatures.isEnabled(
24212475 Feature .EXPERIMENTAL_BLOCK_EDITOR_THEME_STYLES
24222476 )
24232477 )
2424-
2478+
24252479 val appConfig = GutenbergKitSettingsBuilder .AppConfig (
24262480 accessToken = accountStore.accessToken,
24272481 locale = perAppLocaleManager.getCurrentLocaleLanguageCode(),
24282482 cookies = editPostAuthViewModel.getCookiesForPrivateSites(site, privateAtomicCookie)
24292483 )
2430-
2484+
24312485 return GutenbergKitSettingsBuilder .buildSettings(
24322486 siteConfig = siteConfig,
24332487 postConfig = postConfig,
0 commit comments