2021-06-14 21:21:36 +02:00
import { generateKeycloakThemeResources } from "./generateKeycloakThemeResources" ;
import { generateJavaStackFiles } from "./generateJavaStackFiles" ;
2023-03-21 15:16:23 +01:00
import { join as pathJoin , relative as pathRelative , basename as pathBasename , sep as pathSep } from "path" ;
2021-06-14 21:21:36 +02:00
import * as child_process from "child_process" ;
2022-04-09 20:17:20 +02:00
import { generateStartKeycloakTestingContainer } from "./generateStartKeycloakTestingContainer" ;
2022-01-18 18:52:52 +01:00
import * as fs from "fs" ;
2022-08-16 14:41:06 +07:00
import { readBuildOptions } from "./BuildOptions" ;
2022-09-08 12:06:26 +03:00
import { getLogger } from "../tools/logger" ;
import { getCliOptions } from "../tools/cliOptions" ;
2023-02-03 14:28:06 +01:00
import jar from "../tools/jar" ;
2023-02-04 18:02:39 +01:00
import { assert } from "tsafe/assert" ;
import type { Equals } from "tsafe" ;
2021-08-04 16:12:54 +02:00
2021-06-14 21:21:36 +02:00
const reactProjectDirPath = process . cwd ( ) ;
2021-10-12 00:26:29 +02:00
export const keycloakThemeBuildingDirPath = pathJoin ( reactProjectDirPath , "build_keycloak" ) ;
2023-03-20 00:03:15 +01:00
export const keycloakThemeEmailDirPath = pathJoin ( reactProjectDirPath , "src" , "keycloak-theme" , "email" ) ;
2021-06-14 21:21:36 +02:00
2023-01-16 14:42:20 +01:00
export async function main() {
2022-09-08 12:06:26 +03:00
const { isSilent , hasExternalAssets } = getCliOptions ( process . argv . slice ( 2 ) ) ;
const logger = getLogger ( { isSilent } ) ;
logger . log ( "🔏 Building the keycloak theme...⌚" ) ;
2021-06-14 21:21:36 +02:00
2022-08-16 14:41:06 +07:00
const buildOptions = readBuildOptions ( {
2022-08-20 14:04:47 +07:00
"packageJson" : fs . readFileSync ( pathJoin ( reactProjectDirPath , "package.json" ) ) . toString ( "utf8" ) ,
"CNAME" : ( ( ) = > {
const cnameFilePath = pathJoin ( reactProjectDirPath , "public" , "CNAME" ) ;
if ( ! fs . existsSync ( cnameFilePath ) ) {
return undefined ;
}
return fs . readFileSync ( cnameFilePath ) . toString ( "utf8" ) ;
} ) ( ) ,
2022-09-08 12:06:26 +03:00
"isExternalAssetsCliParamProvided" : hasExternalAssets ,
"isSilent" : isSilent
2022-08-16 14:41:06 +07:00
} ) ;
2021-06-23 18:03:49 +02:00
2023-01-16 14:42:20 +01:00
const { doBundlesEmailTemplate } = await generateKeycloakThemeResources ( {
2021-06-14 21:21:36 +02:00
keycloakThemeBuildingDirPath ,
2022-04-20 00:39:40 +02:00
keycloakThemeEmailDirPath ,
2021-06-14 21:21:36 +02:00
"reactAppBuildDirPath" : pathJoin ( reactProjectDirPath , "build" ) ,
2022-08-16 14:41:06 +07:00
buildOptions ,
2021-10-11 21:35:40 +02:00
//We have to leave it at that otherwise we break our default theme.
2023-03-21 15:16:23 +01:00
//Problem is that we can`t guarantee that the the old resources
2021-10-11 21:35:40 +02:00
//will still be available on the newer keycloak version.
2022-08-20 11:44:48 +07:00
"keycloakVersion" : "11.0.3"
2021-06-14 21:21:36 +02:00
} ) ;
const { jarFilePath } = generateJavaStackFiles ( {
2021-10-11 21:35:40 +02:00
keycloakThemeBuildingDirPath ,
2022-08-16 14:41:06 +07:00
doBundlesEmailTemplate ,
2022-08-20 11:44:48 +07:00
buildOptions
2021-06-14 21:21:36 +02:00
} ) ;
2023-02-04 18:02:39 +01:00
switch ( buildOptions . bundler ) {
case "none" :
logger . log ( "😱 Skipping bundling step, there will be no jar" ) ;
break ;
case "keycloakify" :
logger . log ( "🫶 Let keycloakify do its thang" ) ;
await jar ( {
2023-02-05 13:36:52 +01:00
"rootPath" : pathJoin ( keycloakThemeBuildingDirPath , "src" , "main" , "resources" ) ,
2023-02-04 18:02:39 +01:00
"version" : buildOptions . version ,
"groupId" : buildOptions . groupId ,
2023-02-05 13:36:52 +01:00
"artifactId" : buildOptions . artifactId ,
2023-02-04 18:02:39 +01:00
"targetPath" : jarFilePath
} ) ;
break ;
case "mvn" :
logger . log ( "🫙 Run maven to deliver a jar" ) ;
child_process . execSync ( "mvn package" , { "cwd" : keycloakThemeBuildingDirPath } ) ;
break ;
default :
assert < Equals < typeof buildOptions.bundler , never > > ( false ) ;
2023-02-03 14:28:06 +01:00
}
2021-06-14 21:21:36 +02:00
2023-02-03 14:28:06 +01:00
// We want, however, to test in a container running the latest Keycloak version
2022-11-11 15:48:32 +01:00
const containerKeycloakVersion = "20.0.1" ;
2022-04-20 22:13:42 +02:00
2022-04-09 20:17:20 +02:00
generateStartKeycloakTestingContainer ( {
2021-06-14 21:21:36 +02:00
keycloakThemeBuildingDirPath ,
2022-04-20 22:13:42 +02:00
"keycloakVersion" : containerKeycloakVersion ,
2022-08-20 11:44:48 +07:00
buildOptions
2021-06-14 21:21:36 +02:00
} ) ;
2022-09-08 12:06:26 +03:00
logger . log (
2021-10-11 21:35:40 +02:00
[
"" ,
2021-10-12 00:26:29 +02:00
` ✅ Your keycloak theme has been generated and bundled into ./ ${ pathRelative ( reactProjectDirPath , jarFilePath ) } 🚀 ` ,
2022-04-25 13:05:13 +02:00
` It is to be placed in "/opt/keycloak/providers" in the container running a quay.io/keycloak/keycloak Docker image. ` ,
2021-10-11 21:35:40 +02:00
"" ,
2022-04-29 18:35:07 +02:00
//TODO: Restore when we find a good Helm chart for Keycloak.
//"Using Helm (https://github.com/codecentric/helm-charts), edit to reflect:",
2021-10-11 21:35:40 +02:00
"" ,
"value.yaml: " ,
" extraInitContainers: |" ,
" - name: realm-ext-provider" ,
" image: curlimages/curl" ,
" imagePullPolicy: IfNotPresent" ,
" command:" ,
" - sh" ,
" args:" ,
" - -c" ,
2021-10-12 00:26:29 +02:00
` - curl -L -f -S -o /extensions/ ${ pathBasename ( jarFilePath ) } https://AN.URL.FOR/ ${ pathBasename ( jarFilePath ) } ` ,
2021-10-11 21:35:40 +02:00
" volumeMounts:" ,
" - name: extensions" ,
" mountPath: /extensions" ,
" " ,
" extraVolumeMounts: |" ,
" - name: extensions" ,
2022-04-25 13:05:13 +02:00
" mountPath: /opt/keycloak/providers" ,
2021-10-11 21:35:40 +02:00
" extraEnv: |" ,
" - name: KEYCLOAK_USER" ,
" value: admin" ,
" - name: KEYCLOAK_PASSWORD" ,
" value: xxxxxxxxx" ,
" - name: JAVA_OPTS" ,
" value: -Dkeycloak.profile=preview" ,
"" ,
"" ,
2022-04-20 22:13:42 +02:00
` To test your theme locally you can spin up a Keycloak ${ containerKeycloakVersion } container image with the theme pre loaded by running: ` ,
2021-10-11 21:35:40 +02:00
"" ,
2023-03-21 15:16:23 +01:00
` 👉 $ . ${ pathSep } ${ pathRelative (
reactProjectDirPath ,
pathJoin ( keycloakThemeBuildingDirPath , generateStartKeycloakTestingContainer . basename )
) } 👈 ` ,
2021-10-11 21:35:40 +02:00
"" ,
2023-03-21 15:16:23 +01:00
` Test with different Keycloak versions by editing the .sh file. see available versions here: https://quay.io/repository/keycloak/keycloak?tab=tags ` ,
` ` ,
` Once your container is up and running: ` ,
2022-04-09 20:17:20 +02:00
"- Log into the admin console 👉 http://localhost:8080/admin username: admin, password: admin 👈" ,
2023-03-21 15:16:23 +01:00
` - Create a realm named "myrealm" ` ,
2023-03-21 19:44:01 +01:00
` - Enable the Account theme: Realm settings -> tab Themes -> Account theme, select ${ buildOptions . themeName } ` ,
2023-03-21 15:16:23 +01:00
` - Create a client with ID: "myclient" ` ,
` Root URL: https://www.keycloak.org/app/ ` ,
` Valid redirect URIs: https://www.keycloak.org/app* http://localhost* (localhost isn't necessary here but it will be once you'll want to test the integration with your app) ` ,
` Valid post logout redirect URIs: https://www.keycloak.org/app* http://localhost* ` ,
` Web origins: * ` ,
` Login Theme: ${ buildOptions . themeName } ` ,
` Click save at the bottom of the page. ` ,
2021-12-08 15:28:26 +01:00
` - Go to 👉 https://www.keycloak.org/app/ 👈 Click "Save" then "Sign in". You should see your login page ` ,
2023-03-21 19:44:01 +01:00
` - Got to 👉 http://localhost:8080/realms/myrealm/account 👈 to see your account theme ` ,
2023-03-21 15:16:23 +01:00
` `
2022-08-20 11:44:48 +07:00
] . join ( "\n" )
2021-10-11 21:35:40 +02:00
) ;
2021-06-14 21:21:36 +02:00
}