Skip to content

Commit

Permalink
Experiment with User data
Browse files Browse the repository at this point in the history
  • Loading branch information
orchestr7 committed Sep 7, 2024
1 parent f4a4d05 commit f2f05a8
Show file tree
Hide file tree
Showing 23 changed files with 190 additions and 261 deletions.
4 changes: 3 additions & 1 deletion backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ plugins {
}

dependencies {
api(project(":common"))
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
implementation("org.springframework.boot:spring-boot-starter-test")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("io.jsonwebtoken:jjwt-api:0.11.5")
implementation("com.h2database:h2:2.3.232")
implementation("commons-codec:commons-codec:1.17.1")
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5")
testImplementation(kotlin("test"))
Expand Down

This file was deleted.

This file was deleted.

15 changes: 0 additions & 15 deletions backend/src/jvmMain/kotlin/ru/posidata/backend/entity/User.kt

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

8 changes: 0 additions & 8 deletions backend/src/jvmMain/resources/application.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,9 @@ class TelegramAuthController(private val telegramAuthService: TelegramAuthServic
//</body>
//</html>
// https://posidata.ru/api/test?id=221298772&first_name=Андрей&last_name=Кулешов&username=akuleshov7&photo_url=https%3A%2F%2Ft.me%2Fi%2Fuserpic%2F320%2Fd3fKyG306aXHDBCxZXfWTpGlii6fZqZMo1tBmMPEl_E.jpg&auth_date=1725656645&hash=742dda3a019e57821e1fb7acf9918aeb6f0d734cc5c8612913b6696aeab2c745
@GetMapping("/test")
fun test(
@RequestParam id: String,
@RequestParam first_name: String,
@RequestParam last_name: String,
@RequestParam photo_url: String,
@RequestParam username: String,
@RequestParam auth_date: String,
@RequestParam hash: String
): String {
println(username)
return username
}

@GetMapping("/get")
fun get(): String {
println("Hi!")
return "Hi"
}


@PostMapping("auth/telegram")
fun telegramAuth(@RequestBody request: Map<String, Any>): ResponseEntity<Any> {
return try {
val authResult = telegramAuthService.authenticate(request)
if (authResult.isAuthenticated) {
ResponseEntity.ok(authResult.token)
} else {
ResponseEntity.status(HttpStatus.FORBIDDEN).body("Login info hash mismatch")
}
} catch (e: Exception) {
ResponseEntity.status(HttpStatus.FORBIDDEN).body("Server error while authenticating")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package ru.posidata.backend.controller

import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import ru.posidata.backend.service.TelegramAuthService
import ru.posidata.backend.service.UserService
import ru.posidata.common.ResourceType
import ru.posidata.common.Resources


@RestController
@RequestMapping("api")
class UserController(
private val telegramAuthService: TelegramAuthService,
private val userService: UserService
) {
@GetMapping("/get")
fun getResults(
@RequestParam username: String?,
@RequestParam telegramId: Long,
@RequestParam hash: String,
@RequestParam firstName: String?,
@RequestParam lastName: String?,
): ResponseEntity<Any> {
println("Received a request to get results from $username, $telegramId, $hash, $firstName, $lastName")
userService.findOrCreateUser(
username = username,
telegramId = telegramId,
firstName = firstName,
lastName = lastName
)
return ResponseEntity.status(HttpStatus.OK).body("")
}

@GetMapping("/answer")
fun submitAnswer(
@RequestParam pokemonName: String,
@RequestParam resourceType: ResourceType,
// @RequestParam gameNumber: Int,
@RequestParam username: String,
@RequestParam hash: String,
): ResponseEntity<Any> {
// user
println(pokemonName)
var count: Int = 0
val pokemon = Resources.getByName(pokemonName)
?: return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid pokemon name $pokemonName")
if (pokemon.type == resourceType) {
// correct answer
++count
} else {
// incorrect answer
}
return ResponseEntity.status(HttpStatus.OK).body(resourceType)
}
}
13 changes: 11 additions & 2 deletions backend/src/main/kotlin/ru/posidata/backend/entity/User.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@ data class User(
val id: Long = 0,
@Column(unique = true)
val telegramId: Long,
val firstName: String,
val firstName: String?,
val lastName: String?,
val username: String?
val username: String?,

@Column(nullable = true)
var firstGameScore: Int?,

@Column(nullable = true)
var secondGameScore: Int?,

@Column(nullable = true)
var thirdGameScore: Int?,
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package ru.posidata.backend.repository

import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
import ru.posidata.backend.entity.User

@Repository
interface UserRepository : JpaRepository<User, Long> {
interface UserRepository : CrudRepository<User, Long> {
fun findByTelegramId(telegramId: Long): User?
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,58 @@
package ru.posidata.backend.service

import org.apache.commons.codec.digest.HmacUtils
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import java.security.MessageDigest
import java.util.*
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec


@Service
class TelegramAuthService(
@Value("\${telegram.bot.token}") private val telegramToken: String,
private val userService: UserService
) {
fun authenticate(request: Map<String, Any>): AuthResult {
val hash = request["hash"] as String
val sortedRequest = request.toMutableMap().apply { remove("hash") }

val dataCheckString = sortedRequest.entries
.sortedBy { it.key.lowercase(Locale.getDefault()) }
.joinToString("\n") { "${it.key}=${it.value}" }

val secretKey = SecretKeySpec(
MessageDigest.getInstance("SHA-256").digest(telegramToken.toByteArray(Charsets.UTF_8)),
"HmacSHA256"
)
val mac = Mac.getInstance("HmacSHA256")
mac.init(secretKey)

val result = mac.doFinal(dataCheckString.toByteArray(Charsets.UTF_8))
val calculatedHash = result.joinToString("") { "%02x".format(it) }

return if (hash.equals(calculatedHash, ignoreCase = true)) {
val user = userService.findOrCreateUser(request)
println(user)
AuthResult(true, "token")
} else {
AuthResult(false, null)
}
fun isValidHash(hash: String): Boolean {
val secreteKey = "1289756607:AAFYuBeHguJKYhDVzwSfYFLX4tF5YbkSU7M"
return true
}

}


fun main() {
println(isValidHash())
}

// Bot token
const val BOT_TOKEN = "7518590686:AAFCT7m70_ANfOZfIACr2C7bOy0igdLNOpg"

// Function to validate hash
fun isValidHash(): Boolean {
val hash = "742dda3a019e57821e1fb7acf9918aeb6f0d734cc5c8612913b6696aeab2c745"

val parsedData: Map<String, String> = mapOf(
"id" to "221298772",
"first_name" to "Андрей",
"last_name" to "Кулешов",
"username" to "akuleshov7",
"photo_url" to "https%3A%2F%2Ft.me%2Fi%2Fuserpic%2F320%2Fd3fKyG306aXHDBCxZXfWTpGlii6fZqZMo1tBmMPEl_E.jpg",
"auth_date" to "1725656645",
"hash" to "742dda3a019e57821e1fb7acf9918aeb6f0d734cc5c8612913b6696aeab2c745"
)

// Remove 'hash' value & sort alphabetically
val dataKeys = parsedData.keys.filter { it != "hash" }.sorted()

// Create line format key=<value>
val items = dataKeys.map { key -> "$key=${parsedData[key]}" }

// Create check string with '\n' as separator
val dataCheckString = items.joinToString("\n")

val secretKey: ByteArray = HmacUtils("HmacSHA256", "WebAppData").hmac(BOT_TOKEN)
val initDataHash: String = HmacUtils("HmacSHA256", secretKey).hmacHex(dataCheckString)

println(initDataHash)
println(hash)
// Return whether the generated hash matches the provided hash
return initDataHash == hash
}

data class AuthResult(val isAuthenticated: Boolean, val token: String?)
Loading

0 comments on commit f2f05a8

Please sign in to comment.