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 final fun getBaseUrl ()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 getPrivateKey ()Ljava/lang/String;
public final fun getPrivatePem ()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 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 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 setPrivateKey (Ljava/lang/String;)V
public final fun setPrivatePem (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 final class io/github/wulkanowy/sdk/hebe/register/RegisterResponse {
public fun <init> (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public final class io/github/wulkanowy/sdk/hebe/register/RegisterDevice {
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 component2 ()Ljava/lang/String;
public final fun component3 ()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 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 component5 ()Ljava/lang/String;
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 final fun getCertificateHash ()Ljava/lang/String;
public final fun getLoginId ()I
public final fun getPrivatePem ()Ljava/lang/String;
public final fun getRestUrl ()Ljava/lang/String;
public final fun getUserLogin ()Ljava/lang/String;
public final fun getUserName ()Ljava/lang/String;

View file

@ -6,11 +6,13 @@ plugins {
}
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 libs.retrofit.core
implementation libs.retrofit.scalars
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
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.LocalDateTime
import java.time.ZoneOffset.UTC
import java.time.format.DateTimeFormatter.ofPattern
import java.util.UUID
@Serializable
internal data class ApiRequest<T>(
@SerialName("API")
@ -15,7 +17,7 @@ internal data class ApiRequest<T>(
val appName: String = "DzienniczekPlus 2.0",
@SerialName("AppVersion")
val appVersion: String = "1.0",
val appVersion: String = "1.4.2",
@SerialName("CertificateId")
val certificateId: String,

View file

@ -1,8 +1,10 @@
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.repository.RepositoryManager
import io.github.wulkanowy.signer.hebe.generateCertificate
import io.github.wulkanowy.signer.hebe.generateKeyPair
import okhttp3.Interceptor
import okhttp3.logging.HttpLoggingInterceptor
@ -16,7 +18,13 @@ class Hebe {
resettableManager.reset()
}
var privateKey = ""
var keyId = ""
set(value) {
field = value
resettableManager.reset()
}
var privatePem = ""
set(value) {
field = value
resettableManager.reset()
@ -42,20 +50,33 @@ class Hebe {
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() }
suspend fun register(privateKey: String, certificateId: String, firebaseToken: String, token: String, pin: String, symbol: String): RegisterResponse {
return serviceManager
.getRegisterRepository(routes.getRouteByToken(token), symbol)
.registerDevice(
privateKey = privateKey,
certificateId = certificateId,
deviceModel = deviceModel,
suspend fun register(firebaseToken: String, token: String, pin: String, symbol: String): RegisterDevice {
val (publicPem, privatePem, publicHash) = generateKeyPair()
val (certificatePem, certificateHash) = generateCertificate(privatePem)
this.privatePem = privatePem
this.keyId = certificateHash
return serviceManager.getRegisterRepository(routes.getRouteByToken(token), symbol)
.register(
firebaseToken = firebaseToken,
pin = pin,
token = token,
pin = pin,
privatePem = privatePem,
keyId = keyId,
deviceModel = deviceModel,
)
}

View file

@ -1,11 +1,44 @@
package io.github.wulkanowy.sdk.hebe.interceptor
import io.github.wulkanowy.signer.hebe.getSignatureHeaders
import okhttp3.Interceptor
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 {
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
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.util.UUID
@Serializable
internal data class RegisterRequest(
@SerialName("Certificate")

View file

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

View file

@ -1,6 +1,8 @@
package io.github.wulkanowy.sdk.hebe.repository
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.RegisterResponse
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) {
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,
certificateId: String,
deviceModel: String,
firebaseToken: String,
pin: String,
token: String,
): RegisterResponse = service.registerDevice(
): ApiResponse<RegisterResponse> = service.registerDevice(
ApiRequest(
certificateId = certificateId,
firebaseToken = firebaseToken,
@ -27,7 +63,7 @@ internal class RegisterRepository(private val service: RegisterService) {
securityToken = token,
),
),
).envelope!!
)
suspend fun getStudentInfo(): List<StudentInfo> {
return service.getStudentsInfo().envelope!!

View file

@ -15,10 +15,10 @@ import retrofit2.create
internal class RepositoryManager(
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 baseUrl: String,
private val schoolSymbol: String,
) {
@OptIn(ExperimentalSerializationApi::class)
@ -33,7 +33,7 @@ internal class RepositoryManager(
fun getRoutesRepository(): RoutingRulesRepository {
return RoutingRulesRepository(
getRetrofitBuilder(interceptors)
getRetrofitBuilder(isJson = false, signInterceptor = false)
.baseUrl("http://komponenty.vulcan.net.pl")
.build()
.create(),
@ -41,31 +41,36 @@ internal class RepositoryManager(
}
internal fun getRegisterRepository(baseUrl: String, symbol: String): RegisterRepository = getRegisterRepository(
"${baseUrl.removeSuffix("/")}/$symbol",
baseUrl = "${baseUrl.removeSuffix("/")}/$symbol",
)
private fun getRegisterRepository(baseUrl: String): RegisterRepository = RegisterRepository(
getRetrofitBuilder(interceptors)
getRetrofitBuilder(signInterceptor = true)
.baseUrl("${baseUrl.removeSuffix("/")}/api/mobile/register/")
.build()
.create(),
)
@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()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.apply {
if (isJson) {
addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
} else addConverterFactory(ScalarsConverterFactory.create())
}
.client(
OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
.addInterceptor(ErrorInterceptor())
.addInterceptor(SignInterceptor(privateKey))
.apply {
if (signInterceptor) {
addInterceptor(SignInterceptor(keyId, privatePem, deviceModel))
}
interceptors.forEach {
if (it.second) addNetworkInterceptor(it.first)
else addInterceptor(it.first)
}
addInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
}
.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.RegisterResponse
import io.github.wulkanowy.sdk.hebe.register.StudentInfo
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
internal interface RegisterService {
@POST("new")
suspend fun registerDevice(request: ApiRequest<RegisterRequest>): ApiResponse<RegisterResponse>
suspend fun registerDevice(@Body request: ApiRequest<RegisterRequest>): ApiResponse<RegisterResponse>
@GET("hebe")
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 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 getCertKey ()Ljava/lang/String;
public final fun getClassId ()I
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;
@ -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 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 getKeyId ()Ljava/lang/String;
public final fun getKidsLuckyNumbers (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun getKidsTimetable (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
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 getPassword ()Ljava/lang/String;
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 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;
@ -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 setAndroidVersion (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 setDiaryId (I)V
public final fun setEmail (Ljava/lang/String;)V
public final fun setEmptyCookieJarInterceptor (Z)V
public final fun setKeyId (Ljava/lang/String;)V
public final fun setKindergartenDiaryId (I)V
public final fun setLogLevel (Lokhttp3/logging/HttpLoggingInterceptor$Level;)V
public final fun setLoginType (Lio/github/wulkanowy/sdk/Sdk$ScrapperLoginType;)V
public final fun setMobileBaseUrl (Ljava/lang/String;)V
public final fun setMode (Lio/github/wulkanowy/sdk/Sdk$Mode;)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 setSchoolYear (I)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 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 {
@ -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 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 final fun getCertificateKey ()Ljava/lang/String;
public final fun getError ()Ljava/lang/Throwable;
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 getSymbol ()Ljava/lang/String;
public final fun getUserName ()Ljava/lang/String;

View file

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

View file

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

View file

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