Skip to content

Commit 0eb57b4

Browse files
authored
Merge pull request #280 from adamint/dev
Add scope checks
2 parents ee2a10b + 1b58173 commit 0eb57b4

File tree

65 files changed

+923
-746
lines changed

Some content is hidden

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

65 files changed

+923
-746
lines changed

build.gradle.kts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target
55

66
plugins {
77
// id("lt.petuska.npm.publish") version "1.1.2"
8-
kotlin("multiplatform") version "1.4.31"
8+
kotlin("multiplatform") version "1.5.0"
99
`maven-publish`
1010
signing
11-
id("io.codearte.nexus-staging") version "0.22.0"
11+
id("io.codearte.nexus-staging") version "0.30.0"
1212
id("com.android.library")
13-
kotlin("plugin.serialization") version "1.4.30"
14-
id("com.diffplug.spotless") version "5.9.0"
13+
kotlin("plugin.serialization") version "1.5.0"
14+
id("com.diffplug.spotless") version "5.12.4"
1515
id("com.moowork.node") version "1.3.1"
16-
id("org.jetbrains.dokka") version "1.4.20"
16+
id("org.jetbrains.dokka") version "1.4.30"
1717
id("kotlin-android-extensions")
1818
}
1919

2020
repositories {
21-
jcenter()
2221
google()
2322
maven("https://kotlin.bintray.com/kotlinx")
23+
mavenCentral()
2424
}
2525

2626
buildscript {
@@ -29,7 +29,7 @@ buildscript {
2929
}
3030
dependencies {
3131
classpath("com.android.tools.build:gradle:3.5.4")
32-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.31")
32+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.0")
3333
}
3434
}
3535

@@ -211,19 +211,20 @@ kotlin {
211211

212212
targets {
213213
sourceSets {
214-
val serializationVersion = "1.1.0"
215-
val ktorVersion = "1.5.1"
216-
val korlibsVersion = "2.0.6"
214+
val serializationVersion = "1.2.0"
215+
val ktorVersion = "1.5.4"
216+
val korlibsVersion = "2.0.7"
217217
val sparkVersion = "2.9.3"
218218
val androidSpotifyAuthVersion = "1.2.3"
219219
val androidCryptoVersion = "1.1.0-alpha03"
220-
val coroutineMTVersion = "1.4.2-native-mt"
220+
val coroutineMTVersion = "1.4.3-native-mt"
221+
val kotlinxDatetimeVersion = "0.2.0"
221222

222223
val commonMain by getting {
223224
dependencies {
224225
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
225226
implementation("io.ktor:ktor-client-core:$ktorVersion")
226-
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.1.1")
227+
implementation("org.jetbrains.kotlinx:kotlinx-datetime:$kotlinxDatetimeVersion")
227228
implementation("com.soywiz.korlibs.krypto:krypto:$korlibsVersion")
228229
implementation("com.soywiz.korlibs.korim:korim:$korlibsVersion")
229230

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-all.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
pluginManagement {
2-
val mainKotlinVersion = "1.4.31"
2+
val mainKotlinVersion = "1.5.0"
33

44
resolutionStrategy {
55
eachPlugin {

src/androidMain/kotlin/com/adamratzman/spotify/auth/SpotifyDefaultCredentialStore.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,7 @@ public class SpotifyDefaultCredentialStore(
194194
public fun canApiBeRefreshed(): Boolean {
195195
return spotifyRefreshToken != null
196196
}
197-
198-
197+
199198
/**
200199
* Clear the [SharedPreferences] instance corresponding to the Spotify credentials.
201200
*/

src/androidMain/kotlin/com/adamratzman/spotify/utils/PlatformUtils.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@ import android.app.Activity
55
import android.content.Context
66
import android.util.Log
77
import android.widget.Toast
8-
import kotlinx.coroutines.CoroutineScope
9-
import kotlinx.coroutines.runBlocking
108
import java.net.URLEncoder
9+
import kotlinx.coroutines.runBlocking
1110

1211
internal actual fun String.encodeUrl() = URLEncoder.encode(this, "UTF-8")!!
1312

@@ -38,4 +37,4 @@ internal fun logToConsole(message: String) {
3837

3938
public actual fun <T> runBlockingOnJvmAndNative(block: suspend () -> T): T {
4039
return runBlocking { block() }
41-
}
40+
}

src/androidTest/kotlin/com/adamratzman/spotify/CommonImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ public actual fun Exception.stackTrace() {
3131
public actual val testCoroutineContext: CoroutineContext =
3232
Executors.newSingleThreadExecutor().asCoroutineDispatcher()
3333

34-
public actual fun runBlockingTest(block: suspend () -> Unit): Unit = runBlocking(testCoroutineContext) { this.block() }
34+
public actual fun runBlockingTest(block: suspend CoroutineScope.() -> Unit): Unit = runBlocking(testCoroutineContext) { this.block() }

src/commonJvmLikeMain/kotlin/com/adamratzman/spotify/javainterop/SpotifyContinuation.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* Spotify Web API, Kotlin Wrapper; MIT License, 2017-2021; Original author: Adam Ratzman */
12
@file:JvmName("SpotifyContinuation")
23

34
package com.adamratzman.spotify.javainterop
@@ -31,4 +32,4 @@ public abstract class SpotifyContinuation<in T> : Continuation<T> {
3132
}
3233

3334
override val context: CoroutineContext = EmptyCoroutineContext
34-
}
35+
}

src/commonMain/kotlin/com.adamratzman.spotify/SpotifyApi.kt

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import com.adamratzman.spotify.endpoints.client.ClientPersonalizationApi
1111
import com.adamratzman.spotify.endpoints.client.ClientPlayerApi
1212
import com.adamratzman.spotify.endpoints.client.ClientPlaylistApi
1313
import com.adamratzman.spotify.endpoints.client.ClientProfileApi
14-
import com.adamratzman.spotify.endpoints.client.ClientSearchApi
1514
import com.adamratzman.spotify.endpoints.client.ClientShowApi
1615
import com.adamratzman.spotify.endpoints.pub.AlbumApi
1716
import com.adamratzman.spotify.endpoints.pub.ArtistApi
@@ -37,8 +36,8 @@ import com.adamratzman.spotify.models.serialization.nonstrictJson
3736
import com.adamratzman.spotify.models.serialization.toObject
3837
import com.adamratzman.spotify.utils.asList
3938
import com.adamratzman.spotify.utils.base64ByteEncode
40-
import kotlinx.serialization.json.Json
4139
import kotlin.jvm.JvmOverloads
40+
import kotlinx.serialization.json.Json
4241

4342
/**
4443
* Represents an instance of the Spotify API client, with common
@@ -491,8 +490,7 @@ public open class SpotifyClientApi(
491490
override val browse: BrowseApi = BrowseApi(this)
492491
override val artists: ArtistApi = ArtistApi(this)
493492
override val tracks: TrackApi = TrackApi(this)
494-
495-
override val search: ClientSearchApi = ClientSearchApi(this)
493+
override val search: SearchApi = SearchApi(this)
496494

497495
override val episodes: ClientEpisodeApi = ClientEpisodeApi(this)
498496
override val shows: ClientShowApi = ClientShowApi(this)
@@ -783,5 +781,3 @@ public fun refreshSpotifyClientTokenRestAction(
783781
usesPkceAuth: Boolean
784782
): SpotifyRestAction<Token> =
785783
SpotifyRestAction { refreshSpotifyClientToken(clientId, clientSecret, refreshToken, usesPkceAuth) }
786-
787-

src/commonMain/kotlin/com.adamratzman.spotify/SpotifyApiBuilder.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,13 @@ public fun getSpotifyPkceCodeChallenge(codeVerifier: String): String {
113113
*/
114114
public fun spotifyImplicitGrantApi(
115115
clientId: String?,
116-
token: Token,
116+
token: Token
117117
): SpotifyImplicitGrantApi = SpotifyImplicitGrantApi(
118118
clientId,
119119
token,
120120
SpotifyApiOptions()
121121
)
122122

123-
124123
/**
125124
* Instantiate a new [SpotifyImplicitGrantApi] using a Spotify [clientId], and [token] retrieved from the implicit
126125
* grant flow.
@@ -323,7 +322,6 @@ public fun spotifyClientApi(
323322
}
324323
}
325324

326-
327325
/**
328326
* Instantiate a new [SpotifyClientApiBuilder] using a Spotify [clientId], [clientSecret], and [redirectUri], with the ability to configure
329327
* the api settings by providing a builder initialization [block]
@@ -707,7 +705,7 @@ public class SpotifyApiBuilder(
707705
/**
708706
* Create a new [SpotifyAppApi] that only has access to *public* endpoints and data
709707
*/
710-
public fun buildPublicRestAction(): SpotifyRestAction<SpotifyAppApi> = SpotifyRestAction{ buildPublic() }
708+
public fun buildPublicRestAction(): SpotifyRestAction<SpotifyAppApi> = SpotifyRestAction { buildPublic() }
711709

712710
/**
713711
* Create a new [SpotifyAppApi] that only has access to *public* endpoints and data

src/commonMain/kotlin/com.adamratzman.spotify/SpotifyExceptions.kt

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,45 +9,74 @@ public sealed class SpotifyException(message: String, cause: Throwable? = null)
99
public abstract class UnNullableException(message: String) : SpotifyException(message)
1010

1111
/**
12-
* Thrown when a request fails
12+
* Thrown when a request fails.
13+
*
14+
* @param statusCode The status code of the request, if this exception is thrown after the completion of an HTTP request.
15+
* @param reason The reason for the failure, as a readable message.
1316
*/
14-
public open class BadRequestException(message: String, public val statusCode: Int? = null, public val reason: String? = null, cause: Throwable? = null) :
15-
SpotifyException(message, cause) {
17+
public open class BadRequestException(
18+
message: String,
19+
public val statusCode: Int? = null,
20+
public val reason: String? = null,
21+
cause: Throwable? = null
22+
) :
23+
SpotifyException(message, cause) {
1624
public constructor(message: String, cause: Throwable? = null) : this(message, null, null, cause)
1725
public constructor(error: ErrorObject?, cause: Throwable? = null) : this(
18-
"Received Status Code ${error?.status}. Error cause: ${error?.message}" + (error?.reason?.let { ". Reason: ${error.reason}" }
19-
?: ""),
20-
error?.status,
21-
error?.reason,
22-
cause
26+
"Received Status Code ${error?.status}. Error cause: ${error?.message}" + (error?.reason?.let { ". Reason: ${error.reason}" }
27+
?: ""),
28+
error?.status,
29+
error?.reason,
30+
cause
2331
)
2432

2533
public constructor(authenticationError: AuthenticationError) :
2634
this(
27-
"Authentication error: ${authenticationError.error}. Description: ${authenticationError.description}",
28-
401
35+
"Authentication error: ${authenticationError.error}. Description: ${authenticationError.description}",
36+
401
2937
)
3038

3139
public constructor(responseException: ResponseException) :
3240
this(
33-
responseException.message ?: "Bad Request",
34-
responseException.response.status.value,
35-
null,
36-
responseException
41+
responseException.message ?: "Bad Request",
42+
responseException.response.status.value,
43+
null,
44+
responseException
3745
)
3846
}
3947

48+
/**
49+
* Exception signifying that JSON (de)serialization failed. This is likely a library error rather than user error.
50+
*/
4051
public class ParseException(message: String, cause: Throwable? = null) : SpotifyException(message, cause)
4152

53+
/**
54+
* Exception signifying that authentication (via token or code) was unsuccessful, likely due to an invalid access token, code,
55+
* or refresh token.
56+
*/
4257
public class AuthenticationException(message: String, cause: Throwable? = null) : SpotifyException(message, cause) {
4358
public constructor(authenticationError: AuthenticationError?) :
4459
this("Authentication error: ${authenticationError?.error}. Description: ${authenticationError?.description}")
4560
}
4661

62+
/**
63+
* Exception signifying that the HTTP request associated with this API endpoint timed out (by default, after 100 seconds).
64+
*/
4765
public class TimeoutException(message: String, cause: Throwable? = null) : SpotifyException(message, cause)
4866

4967
/**
5068
* Exception signifying that re-authentication via spotify-auth is necessary. Thrown by default when refreshTokenProducer is null.
5169
*/
52-
public class ReAuthenticationNeededException(cause: Throwable? = null, message: String? = null) : SpotifyException(message ?: "Re-authentication is needed.", cause)
70+
public class ReAuthenticationNeededException(cause: Throwable? = null, message: String? = null) :
71+
SpotifyException(message ?: "Re-authentication is needed.", cause)
72+
73+
/**
74+
* Exception signifying that the current api token does not have the necessary scope to complete this request
75+
*
76+
*/
77+
public class SpotifyScopesNeededException(cause: Throwable? = null, public val missingScopes: List<SpotifyScope>) :
78+
BadRequestException(
79+
cause = cause,
80+
message = "You tried to call a method that requires the following missing scopes: $missingScopes. Please make sure that your token is requested with these scopes."
81+
)
5382
}

0 commit comments

Comments
 (0)