Skip to content

Commit 2bb8b84

Browse files
bartkparfeonkleewho
authored
SDK-1560 Revoke Token (#9)
Add revoke token feature Also contract tests runs are splitter into two: required and optional. Only required can fail the build Co-authored-by: Serhii Mamontov <[email protected]> Co-authored-by: Lukasz Klich <[email protected]>
1 parent ddf95a8 commit 2bb8b84

File tree

20 files changed

+292
-66
lines changed

20 files changed

+292
-66
lines changed

.github/workflows/run_acceptance_tests.yml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,31 @@ jobs:
2020
uses: ./client-engineering-deployment-tools/actions/mock-server
2121
with:
2222
token: ${{ secrets.GH_TOKEN }}
23-
- name: Run acceptance tests
23+
- name: Run acceptance tests (optional)
2424
run: |
2525
export pubKey=somePubKey
2626
export subKey=someSubKey
2727
export pamPubKey=somePamPubKey
2828
export pamSubKey=somePamSubKey
2929
export pamSecKey=someSecKey
30-
export featuresDir=sdk-specifications/features/access
31-
export cucumberTags=@feature=access
3230
export serverHostPort=localhost:8090
3331
export serverMock=true
34-
./gradlew cucumber
32+
./gradlew cucumber --tests RunBetaCucumberTest -Dcucumber.features="sdk-specifications/features/" -i
33+
continue-on-error: true
34+
- name: Run acceptance tests (required)
35+
run: |
36+
export pubKey=somePubKey
37+
export subKey=someSubKey
38+
export pamPubKey=somePamPubKey
39+
export pamSubKey=somePamSubKey
40+
export pamSecKey=someSecKey
41+
export serverHostPort=localhost:8090
42+
export serverMock=true
43+
./gradlew cucumber --tests RunMainCucumberTest -Dcucumber.features="sdk-specifications/features/" -i
3544
- name: Expose acceptance tests reports
3645
uses: actions/upload-artifact@v2
46+
if: always()
3747
with:
3848
name: acceptance-test-reports
3949
path: ./build/reports/cucumber-reports
40-
50+
retention-days: 7

.pubnub.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: kotlin
2-
version: 6.2.0
2+
version: v6.3.0
33
schema: 1
44
scm: github.com/pubnub/kotlin
55
files:
6-
- build/libs/pubnub-kotlin-6.2.0-all.jar
6+
- build/libs/pubnub-kotlin-6.3.0-all.jar
77
sdks:
88
-
99
type: library
@@ -23,8 +23,8 @@ sdks:
2323
-
2424
distribution-type: library
2525
distribution-repository: git release
26-
package-name: pubnub-kotlin-5.1.1-all
27-
location: https://github.com/pubnub/kotlin/releases/download/v5.1.1/pubnub-kotlin-5.1.1-all.jar
26+
package-name: pubnub-kotlin-6.3.0
27+
location: https://github.com/pubnub/kotlin/releases/download/v6.3.0/pubnub-kotlin-6.3.0-all.jar
2828
supported-platforms:
2929
supported-operating-systems:
3030
Android:
@@ -135,8 +135,8 @@ sdks:
135135
-
136136
distribution-type: library
137137
distribution-repository: maven
138-
package-name: pubnub-kotlin-5.1.2
139-
location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-kotlin/5.1.2/pubnub-kotlin-5.1.2.jar
138+
package-name: pubnub-kotlin-6.3.0
139+
location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-kotlin/6.3.0/pubnub-kotlin-6.3.0.jar
140140
supported-platforms:
141141
supported-operating-systems:
142142
Android:
@@ -233,6 +233,11 @@ sdks:
233233
license-url: https://github.com/stleary/JSON-java/blob/20210307/LICENSE
234234
is-required: Required
235235
changelog:
236+
- date: 2021-12-16
237+
version: v6.3.0
238+
changes:
239+
- type: feature
240+
text: "Add revoke token feature."
236241
-
237242
version: v6.2.0
238243
date: 2021-10-06
@@ -382,6 +387,7 @@ features:
382387
- ACCESS-GRANT-TOKEN
383388
- ACCESS-PARSE-TOKEN
384389
- ACCESS-SET-TOKEN
390+
- ACCESS-REVOKE-TOKEN
385391
channel-groups:
386392
- CHANNEL-GROUPS-ADD-CHANNELS
387393
- CHANNEL-GROUPS-REMOVE-CHANNELS

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## v6.3.0
2+
December 16 2021
3+
4+
#### Added
5+
- Add revoke token feature.
6+
17
## [v6.2.0](https://github.com/pubnub/kotlin/releases/tag/v6.2.0)
28
October 6 2021
39

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ You will need the publish and subscribe keys to authenticate your app. Get your
2323
<dependency>
2424
<groupId>com.pubnub</groupId>
2525
<artifactId>pubnub-gson</artifactId>
26-
<version>6.2.0</version>
26+
<version>6.3.0</version>
2727
</dependency>
2828
```
2929

3030
* for Gradle, add the following dependency in your `gradle.build`:
3131
```groovy
32-
implementation 'com.pubnub:pubnub-kotlin:5.0.2'
32+
implementation 'com.pubnub:pubnub-kotlin:6.3.0'
3333
```
3434

3535
2. Configure your keys:

build.gradle

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ plugins {
1313
}
1414

1515
group = 'com.pubnub'
16-
version = '6.2.0'
16+
version = '6.3.0'
1717

1818
repositories {
1919
mavenCentral()
@@ -42,46 +42,8 @@ configurations {
4242
testFixturesImplementation { extendsFrom allTest }
4343
integrationTestImplementation { extendsFrom allTest }
4444
testImplementation { extendsFrom allTest }
45-
cucumberRuntime { extendsFrom testImplementation }
4645
}
4746

48-
task cucumber() {
49-
dependsOn assemble, testClasses
50-
group = "verification"
51-
doLast {
52-
javaexec {
53-
Properties localProperties = new Properties()
54-
try {
55-
localProperties.load(new FileInputStream(rootProject.file("src/test/resources/config.properties")))
56-
}
57-
catch (Exception e) {
58-
localProperties.putAll(System.getenv())
59-
}
60-
61-
main = "io.cucumber.core.cli.Main"
62-
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
63-
64-
if (localProperties['cucumber.tags'] != null) {
65-
args = ['--tags', localProperties['cucumberTags'],
66-
'--plugin', 'pretty',
67-
'--plugin', 'json:build/reports/cucumber-reports/Cucumber.json',
68-
'--plugin', 'junit:build/reports/cucumber-reports/Cucumber.xml',
69-
'--plugin', 'html:build/reports/cucumber-reports/Cucumber.html',
70-
'--glue', 'com.pubnub.contract',
71-
localProperties['featuresDir']]
72-
} else {
73-
args = ['--plugin', 'pretty',
74-
'--plugin', 'json:build/reports/cucumber-reports/Cucumber.json',
75-
'--plugin', 'junit:build/reports/cucumber-reports/Cucumber.xml',
76-
'--plugin', 'html:build/reports/cucumber-reports/Cucumber.html',
77-
'--glue', 'com.pubnub.contract',
78-
localProperties['featuresDir']]
79-
}
80-
}
81-
}
82-
}
83-
84-
8547
dependencies {
8648
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
8749

@@ -123,8 +85,15 @@ shadowJar {
12385
}
12486
}
12587

88+
task cucumber(type: Test) {
89+
systemProperty "cucumber.filter.tags", System.getProperty("cucumber.filter.tags")
90+
systemProperty "cucumber.features", System.getProperty("cucumber.features")
91+
systemProperty "cucumber.plugins", System.getProperty("cucumber.plugins")
92+
}
93+
12694
test {
12795
failFast = true
96+
exclude '**/contract/*.class'
12897
}
12998

13099
dokka {

src/main/kotlin/com/pubnub/api/PubNub.kt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.pubnub.api.endpoints.MessageCounts
99
import com.pubnub.api.endpoints.Time
1010
import com.pubnub.api.endpoints.access.Grant
1111
import com.pubnub.api.endpoints.access.GrantToken
12+
import com.pubnub.api.endpoints.access.RevokeToken
1213
import com.pubnub.api.endpoints.channel_groups.AddChannelChannelGroup
1314
import com.pubnub.api.endpoints.channel_groups.AllChannelsChannelGroup
1415
import com.pubnub.api.endpoints.channel_groups.DeleteChannelGroup
@@ -86,7 +87,7 @@ class PubNub(val configuration: PNConfiguration) {
8687

8788
private companion object Constants {
8889
private const val TIMESTAMP_DIVIDER = 1000
89-
private const val SDK_VERSION = "6.2.0"
90+
private const val SDK_VERSION = "6.3.0"
9091
private const val MAX_SEQUENCE = 65535
9192
}
9293

@@ -876,6 +877,24 @@ class PubNub(val configuration: PNConfiguration) {
876877
channelGroups = channelGroups
877878
)
878879

880+
/**
881+
* This function generates a grant token for PubNub Access Manager (PAM).
882+
*
883+
* Permissions can be applied to any of the three type of resources:
884+
* - channels
885+
* - channel groups
886+
* - uuid - metadata associated with particular UUID
887+
*
888+
* Each type of resource have different set of permissions. To know what's possible for each of them
889+
* check ChannelGrant, ChannelGroupGrant and UUIDGrant.
890+
*
891+
* @param ttl Time in minutes for which granted permissions are valid.
892+
* @param meta Additional metadata
893+
* @param authorizedUUID Single uuid which is authorized to use the token to make API requests to PubNub
894+
* @param channels List of all channel grants
895+
* @param channelGroups List of all channel group grants
896+
* @param uuids List of all uuid grants
897+
*/
879898
fun grantToken(
880899
ttl: Int,
881900
meta: Any? = null,
@@ -894,6 +913,18 @@ class PubNub(val configuration: PNConfiguration) {
894913
uuids = uuids
895914
)
896915
}
916+
917+
/**
918+
* This method allows you to disable an existing token and revoke all permissions embedded within.
919+
*
920+
* @param token Existing token with embedded permissions.
921+
*/
922+
fun revokeToken(token: String): RevokeToken {
923+
return RevokeToken(
924+
pubnub = this,
925+
token = token
926+
)
927+
}
897928
//endregion
898929

899930
//region Miscellaneous

src/main/kotlin/com/pubnub/api/PubNubError.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ enum class PubNubError(private val code: Int, val message: String) {
179179
PUSH_TOPIC_MISSING(
180180
164,
181181
"Push notification topic is missing. Required only if push type is APNS2."
182+
),
183+
184+
TOKEN_MISSING(
185+
168,
186+
"Token missing"
182187
);
183188

184189
override fun toString(): String {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.pubnub.api.endpoints.access
2+
3+
import com.pubnub.api.Endpoint
4+
import com.pubnub.api.PubNub
5+
import com.pubnub.api.PubNubError
6+
import com.pubnub.api.PubNubException
7+
import com.pubnub.api.enums.PNOperationType
8+
import com.pubnub.api.models.server.access_manager.v3.RevokeTokenResponse
9+
import java.net.URLEncoder
10+
import retrofit2.Call
11+
import retrofit2.Response
12+
13+
class RevokeToken(
14+
pubnub: PubNub,
15+
private val token: String
16+
) : Endpoint<RevokeTokenResponse, Unit>(pubnub) {
17+
override fun validateParams() {
18+
super.validateParams()
19+
if (!pubnub.configuration.isSecretKeyValid()) {
20+
throw PubNubException(PubNubError.SECRET_KEY_MISSING)
21+
}
22+
if (token.isBlank()) {
23+
throw PubNubException(PubNubError.TOKEN_MISSING)
24+
}
25+
}
26+
27+
override fun doWork(queryParams: HashMap<String, String>): Call<RevokeTokenResponse> {
28+
return pubnub.retrofitManager
29+
.accessManagerService
30+
.revokeToken(pubnub.configuration.subscribeKey, repairEncoding(token), queryParams)
31+
}
32+
33+
override fun createResponse(input: Response<RevokeTokenResponse>): Unit = Unit
34+
35+
override fun operationType(): PNOperationType = PNOperationType.PNAccessManagerRevokeToken
36+
override fun isAuthRequired(): Boolean = false
37+
38+
private fun repairEncoding(token: String): String {
39+
return URLEncoder.encode(token, "utf-8").replace("+", "%20")
40+
}
41+
}

src/main/kotlin/com/pubnub/api/enums/PNOperationType.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ sealed class PNOperationType(open val queryParam: String? = null) {
6363
object PNManageMemberships : ObjectsOperation()
6464

6565
object PNAccessManagerGrantToken : PAMV3Operation()
66+
object PNAccessManagerRevokeToken : PAMV3Operation()
6667

6768
object PNAddMessageAction : MessageActionsOperation()
6869
object PNGetMessageActions : MessageActionsOperation()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package com.pubnub.api.models.server.access_manager.v3
2+
3+
data class RevokeTokenResponse(val status: Int, val data: RevokeTokenData, val service: String)
4+
data class RevokeTokenData(val message: String, val token: String)

src/main/kotlin/com/pubnub/api/services/AccessManagerService.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package com.pubnub.api.services
33
import com.pubnub.api.models.server.Envelope
44
import com.pubnub.api.models.server.access_manager.AccessManagerGrantPayload
55
import com.pubnub.api.models.server.access_manager.v3.GrantTokenResponse
6+
import com.pubnub.api.models.server.access_manager.v3.RevokeTokenResponse
67
import retrofit2.Call
78
import retrofit2.http.Body
9+
import retrofit2.http.DELETE
810
import retrofit2.http.GET
911
import retrofit2.http.POST
1012
import retrofit2.http.Path
@@ -24,4 +26,11 @@ internal interface AccessManagerService {
2426
@Body body: Any?,
2527
@QueryMap options: Map<String, String>
2628
): Call<GrantTokenResponse>
29+
30+
@DELETE("/v3/pam/{subKey}/grant/{token}")
31+
fun revokeToken(
32+
@Path("subKey") subKey: String,
33+
@Path("token", encoded = true) token: String,
34+
@QueryMap queryParams: Map<String, String>
35+
): Call<RevokeTokenResponse>
2736
}

src/test/kotlin/com/pubnub/api/legacy/PubNubTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class PubNubTest : BaseTest() {
7171
fun getVersionAndTimeStamp() {
7272
val version = pubnub.version
7373
val timeStamp = pubnub.timestamp()
74-
assertEquals("6.2.0", version)
74+
assertEquals("6.3.0", version)
7575
assertTrue(timeStamp > 0)
7676
}
7777
}

src/test/kotlin/com/pubnub/contract/ContractTestConfig.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ object ContractTestConfig {
2121
val pamSubKey by config.StringSetting()
2222
val pamPubKey by config.StringSetting()
2323
val pamSecKey by config.StringSetting()
24+
val pubKey by config.StringSetting()
25+
val subKey by config.StringSetting()
2426
val serverHostPort by config.StringSetting()
2527
val serverMock by config.BooleanSetting(true)
2628
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.pubnub.contract
2+
3+
import io.cucumber.junit.Cucumber
4+
import io.cucumber.junit.CucumberOptions
5+
import org.junit.runner.RunWith
6+
7+
@RunWith(Cucumber::class)
8+
@CucumberOptions(
9+
tags = "not @skip and not @na=ruby and not @beta",
10+
plugin = ["pretty", "summary", "junit:build/reports/cucumber-reports/main.xml"]
11+
)
12+
class RunMainCucumberTest
13+
14+
@RunWith(Cucumber::class)
15+
@CucumberOptions(
16+
tags = "not @skip and not @na=ruby and @beta",
17+
plugin = ["pretty", "summary", "junit:build/reports/cucumber-reports/beta.xml"]
18+
)
19+
class RunBetaCucumberTest

0 commit comments

Comments
 (0)