Skip to content

Commit daa8764

Browse files
committed
SDKS-3917 Journey Module Design and Prototype
1 parent e5c2981 commit daa8764

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1537
-307
lines changed

external-idp/src/main/kotlin/com/pingidentity/idp/journey/IdpCallback.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class IdpCallback : AbstractCallback(), JourneyAware, RequestInterceptor {
4040

4141
override lateinit var journey: Journey
4242

43-
override fun onAttribute(name: String, value: JsonElement) {
43+
override fun init(name: String, value: JsonElement) {
4444
when (name) {
4545
"provider" -> this.provider = value.jsonPrimitive.content
4646
"clientId" -> this.clientId = value.jsonPrimitive.content
@@ -53,7 +53,7 @@ class IdpCallback : AbstractCallback(), JourneyAware, RequestInterceptor {
5353
}
5454
}
5555

56-
override fun asJson() = input(result.token, tokenType)
56+
override fun payload() = input(result.token, tokenType)
5757

5858
/**
5959
* Overrides the request with the resume request if initialized, else return the input request.

external-idp/src/main/kotlin/com/pingidentity/idp/journey/SelectIdpCallback.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SelectIdpCallback : AbstractCallback() {
2525

2626
var value: String= ""
2727

28-
override fun onAttribute(name: String, value: JsonElement) {
28+
override fun init(name: String, value: JsonElement) {
2929
when (name) {
3030
"providers" -> {
3131
providers = value.jsonArray.map {
@@ -35,7 +35,7 @@ class SelectIdpCallback : AbstractCallback() {
3535
}
3636
}
3737

38-
override fun asJson(): JsonObject {
38+
override fun payload(): JsonObject {
3939
return input(value)
4040
}
4141

foundation/journey-plugin/src/main/kotlin/com/pingidentity/journey/plugin/AbstractCallback.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,19 @@ abstract class AbstractCallback : Callback {
2222
lateinit var json: JsonObject
2323
protected set
2424

25-
protected abstract fun onAttribute(name: String, value: JsonElement)
25+
protected abstract fun init(name: String, value: JsonElement)
2626

27-
override fun init(jsonObject: JsonObject) {
27+
override fun init(jsonObject: JsonObject) : Callback {
2828
this.json = jsonObject
2929
jsonObject["output"]?.jsonArray?.forEach { outputItem ->
3030
val outputObject = outputItem.jsonObject
3131
outputObject["name"]?.jsonPrimitive?.content?.let { name ->
3232
outputObject["value"]?.let { value ->
33-
onAttribute(name, value)
33+
init(name, value)
3434
}
3535
}
3636
}
37+
return this
3738
}
3839

3940
fun input(vararg value: Any): JsonObject {
@@ -112,5 +113,5 @@ abstract class AbstractCallback : Callback {
112113
return json
113114
}
114115

115-
override fun asJson(): JsonObject = json
116+
override fun payload(): JsonObject = json
116117
}

foundation/journey-plugin/src/main/kotlin/com/pingidentity/journey/plugin/Callback.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,21 @@ import com.pingidentity.orchestrate.Action
1111
import com.pingidentity.orchestrate.ContinueNode
1212
import kotlinx.serialization.json.JsonObject
1313

14+
/**
15+
* Callback interface for handling actions in the journey plugin.
16+
*/
1417
interface Callback : Action {
15-
fun init(jsonObject: JsonObject)
18+
/**
19+
* Initializes the callback with the provided JSON object.
20+
* @param jsonObject The JSON object containing the callback configuration.
21+
* * @return The initialized Callback instance.
22+
*/
23+
fun init(jsonObject: JsonObject): Callback
1624

17-
//Callback is more self-contained, it created its own json without depending on other Callback
18-
fun asJson(): JsonObject
25+
/**
26+
* Returns the payload of the callback.
27+
*/
28+
fun payload(): JsonObject
1929
}
2030

2131
/**

foundation/journey-plugin/src/main/kotlin/com/pingidentity/journey/plugin/CallbackRegistry.kt

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,52 @@ package com.pingidentity.journey.plugin
99

1010
import com.pingidentity.orchestrate.ContinueNode
1111
import kotlinx.serialization.json.JsonArray
12-
import kotlinx.serialization.json.JsonObject
1312
import kotlinx.serialization.json.jsonObject
1413
import kotlinx.serialization.json.jsonPrimitive
1514

15+
/**
16+
* CallbackRegistry is responsible for managing the registration and retrieval of callbacks.
17+
* It allows for the registration of callbacks by type and provides a method to retrieve
18+
* callbacks based on a JSON array.
19+
*/
1620
object CallbackRegistry {
1721
private val callbacks: MutableMap<String, () -> Callback> = HashMap()
18-
val derivedCallbacks: MutableList<(JsonObject) -> String?> = mutableListOf()
1922

23+
/**
24+
* Registers a callback with the specified type.
25+
* @param type The type of the callback.
26+
* @param block A lambda function that returns an instance of the callback.
27+
*/
2028
fun register(type: String, block: () -> Callback) {
2129
callbacks[type] = block
2230
}
2331

24-
fun registerDerived(block: (JsonObject) -> String?) {
25-
derivedCallbacks.add(block)
26-
}
27-
2832
/**
29-
* Injects the DaVinci and ContinueNode instances into the collectors.
30-
* @param davinci The DaVinci instance to be injected.
31-
* @param continueNode The ContinueNode instance to be injected.
33+
* Injects the Journey instances into the callbacks.
34+
* @param journey The Journey instance to be injected.
35+
* @param continueNode The ContinueNode instance.
3236
*/
33-
fun inject(journey: Journey, continueNode: ContinueNode) {
37+
fun inject(journey: Journey, continueNode: ContinueNode) {
3438
continueNode.callbacks.forEach { callback ->
3539
if (callback is JourneyAware) {
3640
callback.journey = journey
3741
}
3842
}
3943
}
4044

41-
45+
/**
46+
* Retrieves a list of callbacks based on the provided JSON array.
47+
* @param array The JSON array containing the callback types.
48+
* * @return A list of initialized Callback instances.
49+
*/
4250
fun callback(array: JsonArray): List<Callback> {
4351
val list = mutableListOf<Callback>()
4452
array.forEach { item ->
4553
val jsonObject = item.jsonObject
4654
val type = jsonObject["type"]?.jsonPrimitive?.content
47-
callbacks[type]?.let { list.add(it().apply { init(jsonObject) }) }
55+
callbacks[type]?.let {
56+
list.add(it().init(jsonObject))
57+
}
4858
}
4959
return list
5060
}

foundation/journey-plugin/src/test/kotlin/com/pingidentity/journey/plugin/CallbackRegistryTest.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,20 @@ class CallbackRegistryTest {
5858
}
5959

6060
class DummyCallback : Callback {
61-
override fun init(jsonObject: JsonObject) {
62-
// Do nothing
61+
override fun init(jsonObject: JsonObject): Callback {
62+
return this
6363
}
6464

65-
override fun asJson(): JsonObject {
65+
override fun payload(): JsonObject {
6666
return buildJsonObject { }
6767
}
6868
}
6969
class Dummy2Callback : Callback {
70-
override fun init(jsonObject: JsonObject) {
71-
// Do nothing
70+
override fun init(jsonObject: JsonObject): Callback {
71+
return this
7272
}
7373

74-
override fun asJson(): JsonObject {
74+
override fun payload(): JsonObject {
7575
return buildJsonObject { }
7676
}
7777
}

foundation/orchestrate/src/main/kotlin/com/pingidentity/orchestrate/SharedContext.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ package com.pingidentity.orchestrate
1212
* @property map The map that holds the shared context.
1313
*/
1414
class SharedContext(val map: MutableMap<String, Any>) : MutableMap<String, Any> by map {
15+
16+
infix fun String.to(value: Any) {
17+
this@SharedContext[this] = value
18+
}
1519
/**
1620
* Returns the value of a specific key from the shared context.
1721
* @param key The key for which the value is to be returned.

foundation/orchestrate/src/main/kotlin/com/pingidentity/orchestrate/Workflow.kt

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,21 +72,25 @@ class Workflow(val config: WorkflowConfig) {
7272
/**
7373
* Starts the workflow with the provided request.
7474
* @param request The request to start the workflow with.
75+
* @param context The flow context of the flow.
7576
* @return The resulting Node after processing the workflow.
7677
*/
77-
suspend fun start(request: Request): Node = lock.withLock {
78+
suspend fun start(
79+
request: Request,
80+
context: SharedContext = SharedContext(mutableMapOf())
81+
): Node = lock.withLock {
7882
// Before we start, make sure all the module init has been completed
7983
return catch {
8084
init()
8185
config.logger.i("Starting...")
82-
val sharedContext = FlowContext(SharedContext(mutableMapOf()))
86+
val flowContext = FlowContext(context)
8387
val req =
8488
start.asFlow()
85-
.scan(request) { result, value -> sharedContext.value(result) }.last()
86-
val response = send(sharedContext, req)
87-
val initialNode = sharedContext.transform(response)
88-
return next(sharedContext, node.asFlow().scan(initialNode) { result, value ->
89-
value(sharedContext, result)
89+
.scan(request) { result, value -> flowContext.value(result) }.last()
90+
val response = send(flowContext, req)
91+
val initialNode = flowContext.transform(response)
92+
return next(flowContext, node.asFlow().scan(initialNode) { result, value ->
93+
value(flowContext, result)
9094
}.last())
9195
}
9296
}
@@ -99,6 +103,15 @@ class Workflow(val config: WorkflowConfig) {
99103
return start(Request())
100104
}
101105

106+
/**
107+
* Starts the workflow with a flow context.
108+
*/
109+
suspend fun start(block: SharedContext.() -> Unit): Node {
110+
val map = SharedContext(mutableMapOf())
111+
block(map)
112+
return start(Request(), map)
113+
}
114+
102115
/**
103116
* Signs off the workflow.
104117
* @return A Result indicating the success or failure of the sign off.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2025 Ping Identity Corporation. All rights reserved.
3+
*
4+
* This software may be modified and distributed under the terms
5+
* of the MIT license. See the LICENSE file for details.
6+
*/
7+
8+
package com.pingidentity.orchestrate.module
9+
10+
import com.pingidentity.orchestrate.Module
11+
import com.pingidentity.utils.PingDsl
12+
13+
/**
14+
* Configuration class for CustomParameter.
15+
* Allows adding custom parameter to be injected into requests.
16+
*/
17+
@PingDsl
18+
class CustomParameterConfig {
19+
internal val parameters = mutableListOf<Pair<String, String>>()
20+
21+
/**
22+
* Adds a custom parameter to the configuration.
23+
* @param name The name of the parameter.
24+
* @param value The value of the parameter.
25+
*/
26+
fun parameter(name: String, value: String) {
27+
parameters.add(Pair(name, value))
28+
}
29+
}
30+
31+
/**
32+
* Module for injecting custom parameters into requests.
33+
*/
34+
val CustomParameter =
35+
Module.of(::CustomParameterConfig) {
36+
37+
/**
38+
* Intercepts all send requests and injects custom parameters.
39+
* @return The modified request with custom parameters.
40+
*/
41+
next { _, request ->
42+
config.parameters.forEach { (name, value) ->
43+
request.parameter(name, value)
44+
}
45+
request
46+
}
47+
48+
/**
49+
* Adds custom parameters at the start of the request.
50+
* @return The modified request with custom parameters.
51+
*/
52+
start {
53+
config.parameters.forEach { (name, value) ->
54+
it.parameter(name, value)
55+
}
56+
it
57+
}
58+
}

0 commit comments

Comments
 (0)