Skip to content

Commit

Permalink
Merge pull request #1230 from joreilly/add-delete-account
Browse files Browse the repository at this point in the history
Add Mutation.deleteAccount
  • Loading branch information
martinbonnin authored Apr 3, 2024
2 parents d1486c1 + 9a39c6d commit a36bc8e
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,29 @@ class DataStore {
.toSpeaker()
}

fun removeBookmarks(uid: String?) {
val query = Query.newKeyQueryBuilder()
.setKind(KIND_BOOKMARKS)
.setLimit(100)
.setFilter(
StructuredQuery.PropertyFilter.hasAncestor(
keyFactory.setKind(KIND_USER).newKey(uid)
)
)
.build()

while (true) {
val result = datastore.run(query)

val keys = result.asSequence().toList().toTypedArray()
datastore.delete(*keys)

if (keys.isEmpty() || result.moreResults == QueryResultBatch.MoreResultsType.NO_MORE_RESULTS) {
break
}
}
}

companion object {
fun <T, R> Iterator<T>.map(block: (T) -> R) = buildList<R> {
this@map.forEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,14 @@ import org.springframework.boot.autoconfigure.web.ErrorProperties
import org.springframework.boot.autoconfigure.web.ServerProperties
import org.springframework.boot.autoconfigure.web.WebProperties
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.boot.runApplication
import org.springframework.boot.web.error.ErrorAttributeOptions
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes
import org.springframework.boot.web.reactive.error.ErrorAttributes
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationListener
import org.springframework.context.ConfigurableApplicationContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Primary
Expand All @@ -87,7 +89,6 @@ import org.springframework.web.reactive.function.server.queryParamOrNull
import org.springframework.web.reactive.result.view.ViewResolver
import org.springframework.web.server.ServerWebExchange
import java.net.http.HttpClient
import java.util.Date
import kotlin.jvm.optionals.getOrNull
import kotlin.reflect.KClass
import kotlin.reflect.KType
Expand Down Expand Up @@ -347,7 +348,7 @@ class DefaultApplication {

companion object {
val KEY_UID = "uid"
val KEY_CONFERENCE = "uid"
val KEY_CONFERENCE = "conference"
val KEY_SOURCE = "source"
val KEY_REQUEST = "request"
val KEY_HEADERS = "headers"
Expand Down Expand Up @@ -539,3 +540,11 @@ internal val config = SchemaGeneratorConfig(
hooks = CustomSchemaGeneratorHooks(),
additionalTypes = setOf(graphqlInstantType, graphqlLocalDateType, graphqlLocalDateTimeType)
)


@Component
class StartupApplicationListener : ApplicationListener<ApplicationReadyEvent> {
override fun onApplicationEvent(event: ApplicationReadyEvent?) {
initializeFirebase()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,24 @@ import com.google.firebase.auth.FirebaseAuth
import dev.johnoreilly.confetti.backend.datastore.googleCredentials


private val lock = Object()
private var _isInitialized = false
// Paranoid check
private var initialized = false

@Synchronized
internal fun initializeFirebase() {
if (!initialized) {
initialized = true
val options =
FirebaseOptions.builder().setCredentials(googleCredentials("firebase_service_account_key.json")).build()
FirebaseApp.initializeApp(options)
}
}

fun String.firebaseUid(): String? {
if (this == "testToken") {
return "testUser"
}

synchronized(lock) {
if (!_isInitialized) {
val options = FirebaseOptions.builder().setCredentials(googleCredentials("firebase_service_account_key.json")).build()
FirebaseApp.initializeApp(options)
_isInitialized = true
}
}

return try {
FirebaseAuth.getInstance().verifyIdToken(this, true).uid
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ interface DataSource {
fun addBookmark(sessionId: String): Set<String>
fun removeBookmark(sessionId: String): Set<String>
fun speaker(id: String): Speaker
fun deleteUserData()
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ class DataStoreDataSource(private val conf: String, private val uid: String? = n
return datastore.readSpeaker(conf, id).toSpeaker()
}

override fun deleteUserData() {
if (uid != null) {
datastore.removeBookmarks(uid)
}
}

override fun sessions(
first: Int,
after: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,7 @@ class TestDataSource : DataSource {
override fun speaker(id: String): Speaker {
return speakers[0]
}

override fun deleteUserData() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.expediagroup.graphql.generator.annotations.GraphQLDescription
import com.expediagroup.graphql.generator.annotations.GraphQLDirective
import com.expediagroup.graphql.server.operations.Mutation
import com.expediagroup.graphql.server.operations.Query
import com.google.firebase.auth.FirebaseAuth
import dev.johnoreilly.confetti.backend.DefaultApplication.Companion.KEY_SOURCE
import dev.johnoreilly.confetti.backend.DefaultApplication.Companion.KEY_UID
import dev.johnoreilly.confetti.backend.datastore.ConferenceId
Expand Down Expand Up @@ -34,6 +35,20 @@ class RootMutation : Mutation {
fun removeBookmark(dfe: DataFetchingEnvironment, sessionId: String): Bookmarks {
return Bookmarks(dfe.source().removeBookmark(sessionId).toList())
}

/**
* Deletes the current user account, requires authentication
*/
fun deleteAccount(dfe: DataFetchingEnvironment): Boolean {
val uid = dfe.uid()
if (uid == null) {
return false
}

FirebaseAuth.getInstance().deleteUser(uid)
dfe.source().deleteUserData()
return true
}
}

@Component
Expand Down

0 comments on commit a36bc8e

Please sign in to comment.