Add PoC of request signing

This commit is contained in:
Mikołaj Pich 2023-04-16 12:41:53 +02:00
parent 64b007425f
commit d85a85235f
16 changed files with 223 additions and 72 deletions

View file

@ -2,15 +2,17 @@ public final class io/github/wulkanowy/sdk/hebe/Hebe {
public fun <init> ()V public fun <init> ()V
public final fun getBaseUrl ()Ljava/lang/String; public final fun getBaseUrl ()Ljava/lang/String;
public final fun getDeviceModel ()Ljava/lang/String; public final fun getDeviceModel ()Ljava/lang/String;
public final fun getKeyId ()Ljava/lang/String;
public final fun getLogLevel ()Lokhttp3/logging/HttpLoggingInterceptor$Level; public final fun getLogLevel ()Lokhttp3/logging/HttpLoggingInterceptor$Level;
public final fun getPrivateKey ()Ljava/lang/String; public final fun getPrivatePem ()Ljava/lang/String;
public final fun getSchoolSymbol ()Ljava/lang/String; public final fun getSchoolSymbol ()Ljava/lang/String;
public final fun getStudents (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getStudents (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun register (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun register (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun setBaseUrl (Ljava/lang/String;)V public final fun setBaseUrl (Ljava/lang/String;)V
public final fun setDeviceModel (Ljava/lang/String;)V public final fun setDeviceModel (Ljava/lang/String;)V
public final fun setKeyId (Ljava/lang/String;)V
public final fun setLogLevel (Lokhttp3/logging/HttpLoggingInterceptor$Level;)V public final fun setLogLevel (Lokhttp3/logging/HttpLoggingInterceptor$Level;)V
public final fun setPrivateKey (Ljava/lang/String;)V public final fun setPrivatePem (Ljava/lang/String;)V
public final fun setSchoolSymbol (Ljava/lang/String;)V public final fun setSchoolSymbol (Ljava/lang/String;)V
} }
@ -30,16 +32,20 @@ public final class io/github/wulkanowy/sdk/hebe/exception/UnknownTokenException
public fun <init> (Ljava/lang/String;)V public fun <init> (Ljava/lang/String;)V
} }
public final class io/github/wulkanowy/sdk/hebe/register/RegisterResponse { public final class io/github/wulkanowy/sdk/hebe/register/RegisterDevice {
public fun <init> (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V public fun <init> (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()I public final fun component1 ()I
public final fun component2 ()Ljava/lang/String; public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String; public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Ljava/lang/String; public final fun component4 ()Ljava/lang/String;
public final fun copy (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/github/wulkanowy/sdk/hebe/register/RegisterResponse; public final fun component5 ()Ljava/lang/String;
public static synthetic fun copy$default (Lio/github/wulkanowy/sdk/hebe/register/RegisterResponse;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/github/wulkanowy/sdk/hebe/register/RegisterResponse; public final fun component6 ()Ljava/lang/String;
public final fun copy (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/github/wulkanowy/sdk/hebe/register/RegisterDevice;
public static synthetic fun copy$default (Lio/github/wulkanowy/sdk/hebe/register/RegisterDevice;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/github/wulkanowy/sdk/hebe/register/RegisterDevice;
public fun equals (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z
public final fun getCertificateHash ()Ljava/lang/String;
public final fun getLoginId ()I public final fun getLoginId ()I
public final fun getPrivatePem ()Ljava/lang/String;
public final fun getRestUrl ()Ljava/lang/String; public final fun getRestUrl ()Ljava/lang/String;
public final fun getUserLogin ()Ljava/lang/String; public final fun getUserLogin ()Ljava/lang/String;
public final fun getUserName ()Ljava/lang/String; public final fun getUserName ()Ljava/lang/String;

View file

@ -6,11 +6,13 @@ plugins {
} }
dependencies { dependencies {
implementation "io.github.wulkanowy:uonet-request-signer:991de26" implementation 'com.github.wulkanowy.uonet-request-signer:hebe-jvm:5412ed8'
implementation "com.brsanthu:migbase64:2.2" implementation "com.brsanthu:migbase64:2.2"
implementation libs.retrofit.core implementation libs.retrofit.core
implementation libs.retrofit.scalars implementation libs.retrofit.scalars
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0" implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
testImplementation "io.mockk:mockk-jvm:1.13.4"
} }

View file

@ -1,11 +1,13 @@
package io.github.wulkanowy.sdk.hebe package io.github.wulkanowy.sdk.hebe
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneOffset.UTC import java.time.ZoneOffset.UTC
import java.time.format.DateTimeFormatter.ofPattern import java.time.format.DateTimeFormatter.ofPattern
import java.util.UUID import java.util.UUID
@Serializable
internal data class ApiRequest<T>( internal data class ApiRequest<T>(
@SerialName("API") @SerialName("API")
@ -15,7 +17,7 @@ internal data class ApiRequest<T>(
val appName: String = "DzienniczekPlus 2.0", val appName: String = "DzienniczekPlus 2.0",
@SerialName("AppVersion") @SerialName("AppVersion")
val appVersion: String = "1.0", val appVersion: String = "1.4.2",
@SerialName("CertificateId") @SerialName("CertificateId")
val certificateId: String, val certificateId: String,

View file

@ -1,8 +1,10 @@
package io.github.wulkanowy.sdk.hebe package io.github.wulkanowy.sdk.hebe
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse import io.github.wulkanowy.sdk.hebe.register.RegisterDevice
import io.github.wulkanowy.sdk.hebe.register.StudentInfo import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import io.github.wulkanowy.sdk.hebe.repository.RepositoryManager import io.github.wulkanowy.sdk.hebe.repository.RepositoryManager
import io.github.wulkanowy.signer.hebe.generateCertificate
import io.github.wulkanowy.signer.hebe.generateKeyPair
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
@ -16,7 +18,13 @@ class Hebe {
resettableManager.reset() resettableManager.reset()
} }
var privateKey = "" var keyId = ""
set(value) {
field = value
resettableManager.reset()
}
var privatePem = ""
set(value) { set(value) {
field = value field = value
resettableManager.reset() resettableManager.reset()
@ -42,20 +50,33 @@ class Hebe {
private val interceptors: MutableList<Pair<Interceptor, Boolean>> = mutableListOf() private val interceptors: MutableList<Pair<Interceptor, Boolean>> = mutableListOf()
private val serviceManager by resettableLazy(resettableManager) { RepositoryManager(logLevel, privateKey, interceptors, baseUrl, schoolSymbol) } private val serviceManager by resettableLazy(resettableManager) {
RepositoryManager(
logLevel = logLevel,
keyId = keyId,
privatePem = privatePem,
deviceModel = deviceModel,
interceptors = interceptors,
)
}
private val routes by resettableLazy(resettableManager) { serviceManager.getRoutesRepository() } private val routes by resettableLazy(resettableManager) { serviceManager.getRoutesRepository() }
suspend fun register(privateKey: String, certificateId: String, firebaseToken: String, token: String, pin: String, symbol: String): RegisterResponse { suspend fun register(firebaseToken: String, token: String, pin: String, symbol: String): RegisterDevice {
return serviceManager val (publicPem, privatePem, publicHash) = generateKeyPair()
.getRegisterRepository(routes.getRouteByToken(token), symbol) val (certificatePem, certificateHash) = generateCertificate(privatePem)
.registerDevice(
privateKey = privateKey, this.privatePem = privatePem
certificateId = certificateId, this.keyId = certificateHash
deviceModel = deviceModel,
return serviceManager.getRegisterRepository(routes.getRouteByToken(token), symbol)
.register(
firebaseToken = firebaseToken, firebaseToken = firebaseToken,
pin = pin,
token = token, token = token,
pin = pin,
privatePem = privatePem,
keyId = keyId,
deviceModel = deviceModel,
) )
} }

View file

@ -1,11 +1,44 @@
package io.github.wulkanowy.sdk.hebe.interceptor package io.github.wulkanowy.sdk.hebe.interceptor
import io.github.wulkanowy.signer.hebe.getSignatureHeaders
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Response import okhttp3.Response
import okio.Buffer
import java.nio.charset.Charset
import java.time.ZoneId
import java.time.ZonedDateTime
internal class SignInterceptor(private val privateKey: String) : Interceptor { internal class SignInterceptor(
private val keyId: String,
private val privatePem: String,
private val deviceModel: String,
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response { override fun intercept(chain: Interceptor.Chain): Response {
return chain.proceed(chain.request()) val original = chain.request()
val request = original.newBuilder()
request.header("UserAgent", "Dart/2.10 (dart:io)")
request.header("vOS", "Android")
request.header("vDeviceModel", deviceModel)
request.header("vAPI", "1")
if (privatePem.isNotBlank()) {
val signatureHeaders = Buffer().run {
original.body?.writeTo(this)
getSignatureHeaders(
keyId = keyId,
privatePem = privatePem,
body = readString(Charset.defaultCharset()),
requestPath = original.url.pathSegments.drop(1).joinToString("/"),
timestamp = ZonedDateTime.now(ZoneId.of("GMT")),
)
}
signatureHeaders.forEach { (key, value) ->
request.header(key, value)
}
}
return chain.proceed(request.method(original.method, original.body).build())
} }
} }

View file

@ -0,0 +1,10 @@
package io.github.wulkanowy.sdk.hebe.register
data class RegisterDevice(
val loginId: Int,
val restUrl: String,
val userLogin: String,
val userName: String,
val certificateHash: String,
val privatePem: String,
)

View file

@ -1,8 +1,10 @@
package io.github.wulkanowy.sdk.hebe.register package io.github.wulkanowy.sdk.hebe.register
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.util.UUID import java.util.UUID
@Serializable
internal data class RegisterRequest( internal data class RegisterRequest(
@SerialName("Certificate") @SerialName("Certificate")

View file

@ -1,8 +1,10 @@
package io.github.wulkanowy.sdk.hebe.register package io.github.wulkanowy.sdk.hebe.register
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
data class RegisterResponse( @Serializable
internal data class RegisterResponse(
@SerialName("LoginId") @SerialName("LoginId")
val loginId: Int, val loginId: Int,

View file

@ -1,6 +1,8 @@
package io.github.wulkanowy.sdk.hebe.repository package io.github.wulkanowy.sdk.hebe.repository
import io.github.wulkanowy.sdk.hebe.ApiRequest import io.github.wulkanowy.sdk.hebe.ApiRequest
import io.github.wulkanowy.sdk.hebe.ApiResponse
import io.github.wulkanowy.sdk.hebe.register.RegisterDevice
import io.github.wulkanowy.sdk.hebe.register.RegisterRequest import io.github.wulkanowy.sdk.hebe.register.RegisterRequest
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse import io.github.wulkanowy.sdk.hebe.register.RegisterResponse
import io.github.wulkanowy.sdk.hebe.register.StudentInfo import io.github.wulkanowy.sdk.hebe.register.StudentInfo
@ -8,14 +10,48 @@ import io.github.wulkanowy.sdk.hebe.service.RegisterService
internal class RegisterRepository(private val service: RegisterService) { internal class RegisterRepository(private val service: RegisterService) {
suspend fun registerDevice( suspend fun register(
firebaseToken: String,
token: String,
pin: String,
deviceModel: String,
privatePem: String,
keyId: String,
): RegisterDevice {
val response = registerDevice(
privateKey = privatePem,
certificateId = keyId,
deviceModel = deviceModel,
firebaseToken = firebaseToken,
pin = pin,
token = token,
)
if (response.envelope == null) {
when (response.status.code) {
// todo: add more codes
else -> error("Unknown error: ${response.status.message}")
}
}
val envelope = response.envelope!!
return RegisterDevice(
loginId = envelope.loginId,
restUrl = envelope.restUrl,
userLogin = envelope.userLogin,
userName = envelope.userName,
certificateHash = keyId,
privatePem = privatePem,
)
}
private suspend fun registerDevice(
privateKey: String, privateKey: String,
certificateId: String, certificateId: String,
deviceModel: String, deviceModel: String,
firebaseToken: String, firebaseToken: String,
pin: String, pin: String,
token: String, token: String,
): RegisterResponse = service.registerDevice( ): ApiResponse<RegisterResponse> = service.registerDevice(
ApiRequest( ApiRequest(
certificateId = certificateId, certificateId = certificateId,
firebaseToken = firebaseToken, firebaseToken = firebaseToken,
@ -27,7 +63,7 @@ internal class RegisterRepository(private val service: RegisterService) {
securityToken = token, securityToken = token,
), ),
), ),
).envelope!! )
suspend fun getStudentInfo(): List<StudentInfo> { suspend fun getStudentInfo(): List<StudentInfo> {
return service.getStudentsInfo().envelope!! return service.getStudentsInfo().envelope!!

View file

@ -15,10 +15,10 @@ import retrofit2.create
internal class RepositoryManager( internal class RepositoryManager(
private val logLevel: HttpLoggingInterceptor.Level, private val logLevel: HttpLoggingInterceptor.Level,
private val privateKey: String, private val keyId: String,
private val privatePem: String,
private val deviceModel: String,
private val interceptors: MutableList<Pair<Interceptor, Boolean>>, private val interceptors: MutableList<Pair<Interceptor, Boolean>>,
private val baseUrl: String,
private val schoolSymbol: String,
) { ) {
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@ -33,7 +33,7 @@ internal class RepositoryManager(
fun getRoutesRepository(): RoutingRulesRepository { fun getRoutesRepository(): RoutingRulesRepository {
return RoutingRulesRepository( return RoutingRulesRepository(
getRetrofitBuilder(interceptors) getRetrofitBuilder(isJson = false, signInterceptor = false)
.baseUrl("http://komponenty.vulcan.net.pl") .baseUrl("http://komponenty.vulcan.net.pl")
.build() .build()
.create(), .create(),
@ -41,31 +41,36 @@ internal class RepositoryManager(
} }
internal fun getRegisterRepository(baseUrl: String, symbol: String): RegisterRepository = getRegisterRepository( internal fun getRegisterRepository(baseUrl: String, symbol: String): RegisterRepository = getRegisterRepository(
"${baseUrl.removeSuffix("/")}/$symbol", baseUrl = "${baseUrl.removeSuffix("/")}/$symbol",
) )
private fun getRegisterRepository(baseUrl: String): RegisterRepository = RegisterRepository( private fun getRegisterRepository(baseUrl: String): RegisterRepository = RegisterRepository(
getRetrofitBuilder(interceptors) getRetrofitBuilder(signInterceptor = true)
.baseUrl("${baseUrl.removeSuffix("/")}/api/mobile/register/") .baseUrl("${baseUrl.removeSuffix("/")}/api/mobile/register/")
.build() .build()
.create(), .create(),
) )
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
private fun getRetrofitBuilder(interceptors: MutableList<Pair<Interceptor, Boolean>>): Retrofit.Builder { private fun getRetrofitBuilder(isJson: Boolean = true, signInterceptor: Boolean): Retrofit.Builder {
return Retrofit.Builder() return Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create()) .apply {
.addConverterFactory(json.asConverterFactory("application/json".toMediaType())) if (isJson) {
addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
} else addConverterFactory(ScalarsConverterFactory.create())
}
.client( .client(
OkHttpClient().newBuilder() OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
.addInterceptor(ErrorInterceptor()) .addInterceptor(ErrorInterceptor())
.addInterceptor(SignInterceptor(privateKey))
.apply { .apply {
if (signInterceptor) {
addInterceptor(SignInterceptor(keyId, privatePem, deviceModel))
}
interceptors.forEach { interceptors.forEach {
if (it.second) addNetworkInterceptor(it.first) if (it.second) addNetworkInterceptor(it.first)
else addInterceptor(it.first) else addInterceptor(it.first)
} }
addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
} }
.build(), .build(),
) )

View file

@ -5,13 +5,14 @@ import io.github.wulkanowy.sdk.hebe.ApiResponse
import io.github.wulkanowy.sdk.hebe.register.RegisterRequest import io.github.wulkanowy.sdk.hebe.register.RegisterRequest
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse import io.github.wulkanowy.sdk.hebe.register.RegisterResponse
import io.github.wulkanowy.sdk.hebe.register.StudentInfo import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.POST import retrofit2.http.POST
internal interface RegisterService { internal interface RegisterService {
@POST("new") @POST("new")
suspend fun registerDevice(request: ApiRequest<RegisterRequest>): ApiResponse<RegisterResponse> suspend fun registerDevice(@Body request: ApiRequest<RegisterRequest>): ApiResponse<RegisterResponse>
@GET("hebe") @GET("hebe")
suspend fun getStudentsInfo(): ApiResponse<List<StudentInfo>> suspend fun getStudentsInfo(): ApiResponse<List<StudentInfo>>

View file

@ -0,0 +1,38 @@
package io.github.wulkanowy.sdk.hebe
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import okhttp3.logging.HttpLoggingInterceptor
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
@Ignore
@OptIn(ExperimentalCoroutinesApi::class)
class HebeRemoteTest {
private val hebe = Hebe()
@Before
fun setUp() {
with(hebe) {
logLevel = HttpLoggingInterceptor.Level.BODY
keyId = ""
privatePem = ""
baseUrl = ""
schoolSymbol = ""
deviceModel = "Pixel 4a (5G)"
}
}
@Test
fun `register device`() = runTest {
val res = hebe.register(
firebaseToken = "###",
token = "FK11234",
pin = "12334",
symbol = "powiatwulkanowy",
)
println(res)
}
}

View file

@ -12,7 +12,6 @@ public final class io/github/wulkanowy/sdk/Sdk {
public final fun getAttendanceSummary (Ljava/lang/Integer;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getAttendanceSummary (Ljava/lang/Integer;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun getAttendanceSummary$default (Lio/github/wulkanowy/sdk/Sdk;Ljava/lang/Integer;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun getAttendanceSummary$default (Lio/github/wulkanowy/sdk/Sdk;Ljava/lang/Integer;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public final fun getBuildTag ()Ljava/lang/String; public final fun getBuildTag ()Ljava/lang/String;
public final fun getCertKey ()Ljava/lang/String;
public final fun getClassId ()I public final fun getClassId ()I
public final fun getCompletedLessons (Ljava/time/LocalDate;Ljava/time/LocalDate;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getCompletedLessons (Ljava/time/LocalDate;Ljava/time/LocalDate;ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun getCompletedLessons$default (Lio/github/wulkanowy/sdk/Sdk;Ljava/time/LocalDate;Ljava/time/LocalDate;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun getCompletedLessons$default (Lio/github/wulkanowy/sdk/Sdk;Ljava/time/LocalDate;Ljava/time/LocalDate;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
@ -30,6 +29,7 @@ public final class io/github/wulkanowy/sdk/Sdk {
public final fun getGradesPointsStatistics (ILkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getGradesPointsStatistics (ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getGradesSemesterStatistics (ILkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getGradesSemesterStatistics (ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getHomework (Ljava/time/LocalDate;Ljava/time/LocalDate;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getHomework (Ljava/time/LocalDate;Ljava/time/LocalDate;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getKeyId ()Ljava/lang/String;
public final fun getKidsLuckyNumbers (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getKidsLuckyNumbers (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getKidsTimetable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getKidsTimetable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getKindergartenDiaryId ()I public final fun getKindergartenDiaryId ()I
@ -52,7 +52,7 @@ public final class io/github/wulkanowy/sdk/Sdk {
public final fun getNotes (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getNotes (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getPassword ()Ljava/lang/String; public final fun getPassword ()Ljava/lang/String;
public final fun getPasswordResetCaptchaCode (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getPasswordResetCaptchaCode (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getPrivateKey ()Ljava/lang/String; public final fun getPrivatePem ()Ljava/lang/String;
public final fun getReceivedMessages (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getReceivedMessages (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun getReceivedMessages$default (Lio/github/wulkanowy/sdk/Sdk;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun getReceivedMessages$default (Lio/github/wulkanowy/sdk/Sdk;Ljava/lang/String;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public final fun getRecipients (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getRecipients (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
@ -85,18 +85,18 @@ public final class io/github/wulkanowy/sdk/Sdk {
public final fun sendPasswordResetRequest (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun sendPasswordResetRequest (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun setAndroidVersion (Ljava/lang/String;)V public final fun setAndroidVersion (Ljava/lang/String;)V
public final fun setBuildTag (Ljava/lang/String;)V public final fun setBuildTag (Ljava/lang/String;)V
public final fun setCertKey (Ljava/lang/String;)V
public final fun setClassId (I)V public final fun setClassId (I)V
public final fun setDiaryId (I)V public final fun setDiaryId (I)V
public final fun setEmail (Ljava/lang/String;)V public final fun setEmail (Ljava/lang/String;)V
public final fun setEmptyCookieJarInterceptor (Z)V public final fun setEmptyCookieJarInterceptor (Z)V
public final fun setKeyId (Ljava/lang/String;)V
public final fun setKindergartenDiaryId (I)V public final fun setKindergartenDiaryId (I)V
public final fun setLogLevel (Lokhttp3/logging/HttpLoggingInterceptor$Level;)V public final fun setLogLevel (Lokhttp3/logging/HttpLoggingInterceptor$Level;)V
public final fun setLoginType (Lio/github/wulkanowy/sdk/Sdk$ScrapperLoginType;)V public final fun setLoginType (Lio/github/wulkanowy/sdk/Sdk$ScrapperLoginType;)V
public final fun setMobileBaseUrl (Ljava/lang/String;)V public final fun setMobileBaseUrl (Ljava/lang/String;)V
public final fun setMode (Lio/github/wulkanowy/sdk/Sdk$Mode;)V public final fun setMode (Lio/github/wulkanowy/sdk/Sdk$Mode;)V
public final fun setPassword (Ljava/lang/String;)V public final fun setPassword (Ljava/lang/String;)V
public final fun setPrivateKey (Ljava/lang/String;)V public final fun setPrivatePem (Ljava/lang/String;)V
public final fun setSchoolSymbol (Ljava/lang/String;)V public final fun setSchoolSymbol (Ljava/lang/String;)V
public final fun setSchoolYear (I)V public final fun setSchoolYear (I)V
public final fun setScrapperBaseUrl (Ljava/lang/String;)V public final fun setScrapperBaseUrl (Ljava/lang/String;)V
@ -145,7 +145,7 @@ public final class io/github/wulkanowy/sdk/exception/VulcanException : java/io/I
} }
public final class io/github/wulkanowy/sdk/mapper/StudentsMapperKt { public final class io/github/wulkanowy/sdk/mapper/StudentsMapperKt {
public static final fun mapHebeUser (Ljava/util/List;Lio/github/wulkanowy/sdk/hebe/register/RegisterResponse;Ljava/lang/String;Ljava/lang/String;)Lio/github/wulkanowy/sdk/pojo/RegisterUser; public static final fun mapHebeUser (Ljava/util/List;Lio/github/wulkanowy/sdk/hebe/register/RegisterDevice;)Lio/github/wulkanowy/sdk/pojo/RegisterUser;
} }
public final class io/github/wulkanowy/sdk/pojo/Absent { public final class io/github/wulkanowy/sdk/pojo/Absent {
@ -879,10 +879,10 @@ public final class io/github/wulkanowy/sdk/pojo/RegisterSymbol {
public final fun copy (Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Lio/github/wulkanowy/sdk/pojo/RegisterSymbol; public final fun copy (Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)Lio/github/wulkanowy/sdk/pojo/RegisterSymbol;
public static synthetic fun copy$default (Lio/github/wulkanowy/sdk/pojo/RegisterSymbol;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lio/github/wulkanowy/sdk/pojo/RegisterSymbol; public static synthetic fun copy$default (Lio/github/wulkanowy/sdk/pojo/RegisterSymbol;Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lio/github/wulkanowy/sdk/pojo/RegisterSymbol;
public fun equals (Ljava/lang/Object;)Z public fun equals (Ljava/lang/Object;)Z
public final fun getCertificateKey ()Ljava/lang/String;
public final fun getError ()Ljava/lang/Throwable; public final fun getError ()Ljava/lang/Throwable;
public final fun getHebeBaseUrl ()Ljava/lang/String; public final fun getHebeBaseUrl ()Ljava/lang/String;
public final fun getPrivateKey ()Ljava/lang/String; public final fun getKeyId ()Ljava/lang/String;
public final fun getPrivatePem ()Ljava/lang/String;
public final fun getSchools ()Ljava/util/List; public final fun getSchools ()Ljava/util/List;
public final fun getSymbol ()Ljava/lang/String; public final fun getSymbol ()Ljava/lang/String;
public final fun getUserName ()Ljava/lang/String; public final fun getUserName ()Ljava/lang/String;

View file

@ -104,16 +104,16 @@ class Sdk {
hebe.baseUrl = value hebe.baseUrl = value
} }
var certKey = "" var keyId = ""
set(value) { set(value) {
field = value field = value
// hebe.certKey = value hebe.keyId = value
} }
var privateKey = "" var privatePem = ""
set(value) { set(value) {
field = value field = value
hebe.privateKey = privateKey hebe.privatePem = privatePem
} }
var scrapperBaseUrl = "" var scrapperBaseUrl = ""
@ -268,20 +268,15 @@ class Sdk {
} }
suspend fun getStudentsFromHebe(token: String, pin: String, symbol: String, firebaseToken: String): RegisterUser { suspend fun getStudentsFromHebe(token: String, pin: String, symbol: String, firebaseToken: String): RegisterUser {
val privateKey = "" // TODO val registerDevice = hebe.register(
val certificateId = "" // TODO
val registerResponse = hebe.register(
privateKey = privateKey,
certificateId = certificateId,
firebaseToken = firebaseToken, firebaseToken = firebaseToken,
token = token, token = token,
pin = pin, pin = pin,
symbol = symbol, symbol = symbol,
) )
return hebe return hebe
.getStudents(registerResponse.restUrl, symbol) .getStudents(registerDevice.restUrl, symbol)
.mapHebeUser(registerResponse, certificateId, privateKey) .mapHebeUser(registerDevice)
} }
suspend fun getStudentsHybrid( suspend fun getStudentsHybrid(
@ -316,8 +311,8 @@ class Sdk {
firebaseToken = firebaseToken, firebaseToken = firebaseToken,
) )
symbol.copy( symbol.copy(
certificateKey = hebeUser.symbols.first().certificateKey, keyId = hebeUser.symbols.first().keyId,
privateKey = hebeUser.symbols.first().privateKey, privatePem = hebeUser.symbols.first().privatePem,
hebeBaseUrl = hebeUser.symbols.first().hebeBaseUrl, hebeBaseUrl = hebeUser.symbols.first().hebeBaseUrl,
) )
}, },

View file

@ -1,7 +1,7 @@
package io.github.wulkanowy.sdk.mapper package io.github.wulkanowy.sdk.mapper
import io.github.wulkanowy.sdk.Sdk import io.github.wulkanowy.sdk.Sdk
import io.github.wulkanowy.sdk.hebe.register.RegisterResponse import io.github.wulkanowy.sdk.hebe.register.RegisterDevice
import io.github.wulkanowy.sdk.hebe.register.StudentInfo import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import io.github.wulkanowy.sdk.pojo.RegisterEmployee import io.github.wulkanowy.sdk.pojo.RegisterEmployee
import io.github.wulkanowy.sdk.pojo.RegisterStudent import io.github.wulkanowy.sdk.pojo.RegisterStudent
@ -31,8 +31,8 @@ internal fun SdkRegisterSymbol.mapSymbol(): RegisterSymbol = RegisterSymbol(
symbol = symbol, symbol = symbol,
userName = userName, userName = userName,
error = error, error = error,
certificateKey = null, keyId = null,
privateKey = null, privatePem = null,
hebeBaseUrl = null, hebeBaseUrl = null,
schools = schools.map { it.mapUnit() }, schools = schools.map { it.mapUnit() },
) )
@ -73,12 +73,10 @@ internal fun ScrapperRegisterStudent.mapStudent(): RegisterStudent = RegisterStu
) )
fun List<StudentInfo>.mapHebeUser( fun List<StudentInfo>.mapHebeUser(
registerResponse: RegisterResponse, device: RegisterDevice,
certificateKey: String,
privateKey: String,
): RegisterUser = RegisterUser( ): RegisterUser = RegisterUser(
email = registerResponse.userName, email = device.userName,
login = registerResponse.userLogin, login = device.userLogin,
scrapperBaseUrl = null, scrapperBaseUrl = null,
loginType = null, loginType = null,
loginMode = Sdk.Mode.HEBE, loginMode = Sdk.Mode.HEBE,
@ -88,9 +86,9 @@ fun List<StudentInfo>.mapHebeUser(
RegisterSymbol( RegisterSymbol(
symbol = symbol, symbol = symbol,
error = null, error = null,
certificateKey = certificateKey, keyId = device.certificateHash,
privateKey = privateKey, privatePem = device.privatePem,
hebeBaseUrl = registerResponse.restUrl, hebeBaseUrl = device.restUrl,
userName = students.firstOrNull()?.login?.displayName ?: return@mapNotNull null, userName = students.firstOrNull()?.login?.displayName ?: return@mapNotNull null,
schools = students.mapUnit(), schools = students.mapUnit(),
) )

View file

@ -16,8 +16,8 @@ data class RegisterSymbol(
val symbol: String, val symbol: String,
val error: Throwable?, val error: Throwable?,
val userName: String, val userName: String,
val certificateKey: String?, val keyId: String?,
val privateKey: String?, val privatePem: String?,
val hebeBaseUrl: String?, val hebeBaseUrl: String?,
val schools: List<RegisterUnit>, val schools: List<RegisterUnit>,
) )