Этап 1: единый OkHttpClient ч.2 — 401 централизован через interceptor
- UnauthorizedInterceptor (401→UnauthorizedException) в NetworkFactory, флаг throwOnUnauthorized (по умолчанию true). - Удалены 75 ручных проверок if(code==401) throw в 16 репозиториях. - AuthVerifier (login-верификация) исключён: throwOnUnauthorized=false — 401 = 'неверный пароль' со своим сообщением, не session-expired. - Побочно: 401 теперь ловится единообразно ВЕЗДЕ (включая пути, что раньше забывали проверку). - +3 MockWebServer-теста (401 бросает; 200/403 проходят) — всего 18 тестов. Проверено: 18 тестов зелёные + assembleRelease BUILD SUCCESSFUL, APK 53 МБ.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
Формат: `ГГГГ-ММ-ДД | версия | изменение | контракты | риск`
|
||||
|
||||
- 2026-07-07 | v0.5.114 (122) | Этап 1 (единый OkHttpClient, ч.2 — 401 централизован): добавлен UnauthorizedInterceptor (401→UnauthorizedException) в NetworkFactory (флаг throwOnUnauthorized, по умолч. true). Удалены 75 ручных проверок `if(code==401) throw` в 16 репозиториях. Login-верификация (AuthVerifier) исключена (throwOnUnauthorized=false: 401=«неверный пароль», не session-expired). Побочно: теперь 401 ловится единообразно ВЕЗДЕ, включая пути, что раньше проверку забывали. +3 теста (MockWebServer: 401 бросает, 200/403 проходят) — всего 18. Проверено сборкой | контракты не менялись; поведение 401 сохранено (interceptor бросает то же исключение) | средний: затрагивает обработку 401 во всех репозиториях; login-путь исключён явно, покрыто тестами
|
||||
- 2026-07-07 | v0.5.114 (122) | Этап 1 (единый OkHttpClient, ч.1): NetworkFactory переписан — раньше создавал НОВЫЙ OkHttpClient на КАЖДЫЙ запрос (~32 места) → TLS-handshake + новый пул/диспатчер на запрос + утечка ExecutorService. Теперь один базовый клиент (общий ConnectionPool/Dispatcher + диск-кэш 20МБ), авторизованные варианты через base.newBuilder() (шарят пул/кэш), кэшируются по кредам+таймаутам. Публичный API НЕ менялся — 32 вызова не тронуты. Init диск-кэша — F7MobileApp.onCreate. +3 unit-теста (переиспользование клиента, общий пул). 401→interceptor НЕ делал (меняет семантику исключений — отдельный шаг) | контракты не менялись | средний: затрагивает ВСЕ сетевые вызовы (переиспользование соединений); поведение запросов то же, проверено 15 тестами + assembleRelease
|
||||
- 2026-07-07 | v0.5.114 (122) | Этап 1 (CI + GPL-публикация): добавлен Gitea Actions workflow .gitea/workflows/ci.yml (push/PR → тесты+lint+assembleDebug; тег v* → подписанный release + архив исходников в Gitea Release) — Gitea 1.26.1 поддерживает Actions. Скрипт scripts/package-source.sh (GPL corresponding source §6: архив всего дерева вкл. vendor GPL/LICENSE/NOTICE — проверен, 6.7 МБ) закрывает п.4c, работает и вручную. docs/CI.md. НЕ активно до регистрации self-hosted раннера на инфре B (нужен Gitea-админ для токена — инфра-шаг) | процесс сборки/релиза | нет: конфиг CI, кода приложения не трогает
|
||||
- 2026-07-07 | v0.5.114 (122) | Этап 1 (баги данных, test-first): заведена тестовая инфраструктура (core:network testImplementation junit) + первые 12 unit-тестов. Починено: (1) ICS-парсер дат — суффикс `Z` теперь UTC (был локальным), учитывается TZID, floating→локаль; (2) parseProps сохраняет параметры свойств — несколько ATTENDEE больше НЕ схлопываются, CN/PARTSTAT/ROLE читаются (была порча участников при редактировании→PUT на сервер); (3) unescape single-pass (последовательные replace ломались на `\\n`); (4) CalDavClient.parseIcsInstant делегирует в CalendarIcs — устранён рассинхрон календарь↔задачи; (5) QR-логин: маркер-парсер вместо split('&') — пароль с `&`/`:` больше не теряется; (6) курсор пагинации почты Int→Long (обрезка Unix-времени, ломалось ~2038). Проверено: 12 тестов зелёные + assembleRelease | контракты не менялись; исправлена запись битых ATTENDEE на сервер | низкий: чинит порчу данных, покрыто тестами
|
||||
|
||||
@@ -19,7 +19,6 @@ object AppMenuRepository {
|
||||
val request = Request.Builder().url(url).applyOcsJson().get().build()
|
||||
return runCatching {
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ object AuthVerifier {
|
||||
session.username,
|
||||
session.appPassword,
|
||||
session.trustAllCerts,
|
||||
// login-верификация: 401 = «неверный пароль» со своим сообщением, НЕ session-expired
|
||||
throwOnUnauthorized = false,
|
||||
)
|
||||
val request = Request.Builder()
|
||||
.url("${session.serverUrl.trimEnd('/')}/ocs/v2.php/cloud/user?format=json")
|
||||
|
||||
@@ -22,9 +22,6 @@ object OcsUserResolver {
|
||||
.applyOcsJson()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) {
|
||||
throw UnauthorizedException()
|
||||
}
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("User profile HTTP ${response.code}")
|
||||
}
|
||||
|
||||
@@ -28,4 +28,5 @@ dependencies {
|
||||
api 'com.squareup.okhttp3:okhttp:4.12.0'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'
|
||||
}
|
||||
|
||||
@@ -189,7 +189,6 @@ object CalDavClient {
|
||||
.put(ics.toRequestBody("text/calendar; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("CalDAV create event HTTP ${response.code}")
|
||||
}
|
||||
@@ -244,7 +243,6 @@ object CalDavClient {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 204 && response.code != 404) {
|
||||
error("CalDAV delete event HTTP ${response.code}")
|
||||
}
|
||||
@@ -278,7 +276,6 @@ object CalDavClient {
|
||||
builder.header("If-None-Match", "*")
|
||||
}
|
||||
client.newCall(builder.build()).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("CalDAV put event HTTP ${response.code}")
|
||||
}
|
||||
@@ -314,7 +311,6 @@ object CalDavClient {
|
||||
.method("MKCALENDAR", body.toRequestBody("application/xml; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("CalDAV create calendar HTTP ${response.code}")
|
||||
}
|
||||
@@ -347,7 +343,6 @@ object CalDavClient {
|
||||
.method("MKCOL", body.toRequestBody("application/xml; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("CalDAV subscribe calendar HTTP ${response.code}")
|
||||
}
|
||||
@@ -405,7 +400,6 @@ object CalDavClient {
|
||||
.header("Destination", destinationHref)
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("CalDAV move HTTP ${response.code}")
|
||||
}
|
||||
@@ -644,7 +638,6 @@ object CalDavClient {
|
||||
.put(ics.toRequestBody("text/calendar; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("CalDAV create task HTTP ${response.code}")
|
||||
}
|
||||
@@ -691,7 +684,6 @@ object CalDavClient {
|
||||
.put(ics.toRequestBody("text/calendar; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 204) {
|
||||
error("CalDAV update task HTTP ${response.code}")
|
||||
}
|
||||
@@ -705,7 +697,6 @@ object CalDavClient {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 204 && response.code != 404) {
|
||||
error("CalDAV delete task HTTP ${response.code}")
|
||||
}
|
||||
@@ -765,7 +756,6 @@ object CalDavClient {
|
||||
|
||||
private fun execute(client: OkHttpClient, req: Request): String {
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
val code = response.code
|
||||
if (code !in 200..299 && code != 207) {
|
||||
error("CalDAV error HTTP $code")
|
||||
|
||||
@@ -90,7 +90,6 @@ object CardDavClient {
|
||||
.put(vcard.toRequestBody("text/vcard; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("Не удалось создать контакт (HTTP ${response.code})")
|
||||
}
|
||||
@@ -163,7 +162,6 @@ object CardDavClient {
|
||||
.method("PROPFIND", body.toRequestBody("application/xml; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(req).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
val code = response.code
|
||||
if (code !in 200..299 && code != 207) {
|
||||
error("CardDAV error HTTP $code")
|
||||
|
||||
@@ -27,9 +27,6 @@ object DavClient {
|
||||
.method("MKCOL", null)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) {
|
||||
throw UnauthorizedException()
|
||||
}
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("DAV MKCOL HTTP ${response.code}")
|
||||
}
|
||||
@@ -46,9 +43,6 @@ object DavClient {
|
||||
.put(body)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) {
|
||||
throw UnauthorizedException()
|
||||
}
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("DAV upload HTTP ${response.code}")
|
||||
}
|
||||
@@ -76,9 +70,6 @@ object DavClient {
|
||||
.method("PROPFIND", body.toRequestBody("application/xml; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
return client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) {
|
||||
throw UnauthorizedException()
|
||||
}
|
||||
val code = response.code
|
||||
if (code !in 200..299 && code != 207) {
|
||||
error("DAV error HTTP $code")
|
||||
@@ -182,7 +173,6 @@ object DavClient {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 204) {
|
||||
error("DAV DELETE HTTP ${response.code}")
|
||||
}
|
||||
@@ -197,7 +187,6 @@ object DavClient {
|
||||
.header("Overwrite", "T")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 201 && response.code != 204) {
|
||||
error("DAV MOVE HTTP ${response.code}")
|
||||
}
|
||||
@@ -221,7 +210,6 @@ object DavClient {
|
||||
.method("PROPPATCH", body.toRequestBody("application/xml; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code !in 200..299 && response.code != 207) {
|
||||
error("DAV PROPPATCH HTTP ${response.code}")
|
||||
}
|
||||
|
||||
@@ -14,9 +14,10 @@ import java.util.concurrent.TimeUnit
|
||||
* - авторизованные варианты — через `base.newBuilder()` (шарят пул/диспатчер/кэш);
|
||||
* - экземпляры кэшируются по кредам+таймаутам → переиспользуются, соединения живут.
|
||||
*
|
||||
* Публичный API НЕ менялся — все вызывающие (`newAuthedClient*`) работают как прежде.
|
||||
* NB: 401→UnauthorizedException пока проверяется в репозиториях вручную; централизация
|
||||
* через interceptor — отдельный шаг (меняет семантику исключений).
|
||||
* Публичный API совместим — вызывающие (`newAuthedClient*`) работают как прежде.
|
||||
* 401→UnauthorizedException централизован через interceptor (`throwOnUnauthorized`, по умолч.
|
||||
* true) — ручные проверки в репозиториях убраны. Login-пути (AuthVerifier), где 401 = «неверный
|
||||
* пароль» со своим сообщением, передают `throwOnUnauthorized = false`.
|
||||
*/
|
||||
object NetworkFactory {
|
||||
@Volatile
|
||||
@@ -38,8 +39,9 @@ object NetworkFactory {
|
||||
trustAllCerts: Boolean = false,
|
||||
callTimeoutSeconds: Long = 30,
|
||||
readTimeoutSeconds: Long = 30,
|
||||
throwOnUnauthorized: Boolean = true,
|
||||
): OkHttpClient {
|
||||
val key = "$username|$appPassword|$trustAllCerts|$callTimeoutSeconds|$readTimeoutSeconds"
|
||||
val key = "$username|$appPassword|$trustAllCerts|$callTimeoutSeconds|$readTimeoutSeconds|$throwOnUnauthorized"
|
||||
return clients.getOrPut(key) {
|
||||
base.newBuilder() // общий пул/диспатчер/кэш базового клиента
|
||||
.callTimeout(callTimeoutSeconds, TimeUnit.SECONDS)
|
||||
@@ -47,6 +49,7 @@ object NetworkFactory {
|
||||
.readTimeout(readTimeoutSeconds, TimeUnit.SECONDS)
|
||||
.applyUnsafeSslIfNeeded(trustAllCerts)
|
||||
.addInterceptor(BasicAuthInterceptor(username, appPassword))
|
||||
.apply { if (throwOnUnauthorized) addInterceptor(UnauthorizedInterceptor) }
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ class NotificationsRepository {
|
||||
.header("Accept", "application/json")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Уведомления HTTP ${response.code}")
|
||||
}
|
||||
@@ -86,7 +85,6 @@ class NotificationsRepository {
|
||||
.header("Accept", "application/json")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) {
|
||||
error("Уведомления HTTP ${response.code}")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package ru.forbion.f7cloud.core.network
|
||||
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
/**
|
||||
* Единая точка обработки 401 для авторизованных запросов: бросает [UnauthorizedException]
|
||||
* (session expired → logout). Заменяет ~70 ручных `if (code == 401) throw ...` по репозиториям.
|
||||
*
|
||||
* Подключается в [NetworkFactory] при `throwOnUnauthorized = true` (по умолчанию). Login-пути
|
||||
* (проверка пароля при входе) НЕ используют этот interceptor — там 401 = «неверный пароль».
|
||||
*/
|
||||
object UnauthorizedInterceptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val response = chain.proceed(chain.request())
|
||||
if (response.code == 401) {
|
||||
response.close() // не течём телом — дальше по цепочке оно не читается
|
||||
throw UnauthorizedException()
|
||||
}
|
||||
return response
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package ru.forbion.f7cloud.core.network
|
||||
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
/** Централизованная обработка 401: interceptor бросает UnauthorizedException вместо ручных проверок. */
|
||||
class UnauthorizedInterceptorTest {
|
||||
private lateinit var server: MockWebServer
|
||||
|
||||
@Before fun setUp() { server = MockWebServer().apply { start() } }
|
||||
@After fun tearDown() { server.shutdown() }
|
||||
|
||||
private fun call(client: OkHttpClient) =
|
||||
client.newCall(Request.Builder().url(server.url("/x")).build()).execute()
|
||||
|
||||
@Test(expected = UnauthorizedException::class)
|
||||
fun `401 бросает UnauthorizedException`() {
|
||||
server.enqueue(MockResponse().setResponseCode(401))
|
||||
val client = OkHttpClient.Builder().addInterceptor(UnauthorizedInterceptor).build()
|
||||
call(client)
|
||||
}
|
||||
|
||||
@Test fun `не-401 проходит как обычно`() {
|
||||
server.enqueue(MockResponse().setResponseCode(200).setBody("ok"))
|
||||
val client = OkHttpClient.Builder().addInterceptor(UnauthorizedInterceptor).build()
|
||||
call(client).use { assertEquals(200, it.code) }
|
||||
}
|
||||
|
||||
@Test fun `403 не трактуется как Unauthorized`() {
|
||||
server.enqueue(MockResponse().setResponseCode(403))
|
||||
val client = OkHttpClient.Builder().addInterceptor(UnauthorizedInterceptor).build()
|
||||
call(client).use { assertEquals(403, it.code) }
|
||||
}
|
||||
}
|
||||
-4
@@ -46,7 +46,6 @@ class CalendarApiClient {
|
||||
.applyOcsJson()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
val json = parseJsonObject(response.body?.string().orEmpty(), "autocomplete attendee")
|
||||
val data = json.optJSONArray("data") ?: json.optJSONObject("ocs")?.optJSONArray("data") ?: return emptyList()
|
||||
return buildList {
|
||||
@@ -77,7 +76,6 @@ class CalendarApiClient {
|
||||
.applyOcsJson()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
val json = parseJsonObject(response.body?.string().orEmpty(), "autocomplete location")
|
||||
val data = json.optJSONArray("data") ?: return emptyList()
|
||||
return buildList {
|
||||
@@ -104,7 +102,6 @@ class CalendarApiClient {
|
||||
.applyOcsJson()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Calendar config failed HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -124,7 +121,6 @@ class CalendarApiClient {
|
||||
.applyOcsJson()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
val json = parseJsonObject(response.body?.string().orEmpty(), "create talk room")
|
||||
val meta = json.ocsMeta()
|
||||
if (!isOcsSuccess(meta)) error("Не удалось создать комнату Talk")
|
||||
|
||||
@@ -79,7 +79,6 @@ class DeckRepository {
|
||||
private fun getJson(client: okhttp3.OkHttpClient, url: String): Any {
|
||||
val request = Request.Builder().url(url).build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Deck API HTTP ${response.code}")
|
||||
}
|
||||
|
||||
-2
@@ -26,7 +26,6 @@ class SupportRepository {
|
||||
.applyOcsJson()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Support config HTTP ${response.code}")
|
||||
}
|
||||
@@ -266,7 +265,6 @@ class SupportRepository {
|
||||
.post(payload.toRequestBody("application/json; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) {
|
||||
val body = response.body?.string().orEmpty()
|
||||
val err = runCatching {
|
||||
|
||||
@@ -24,7 +24,6 @@ class FileDownloadRepository(private val context: Context) {
|
||||
.get()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Не удалось скачать файл (HTTP ${response.code})")
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ class FilesApiRepository {
|
||||
val url = "${session.serverUrl.trimEnd('/')}/index.php/apps/files/api/v1/configs"
|
||||
val request = Request.Builder().url(url).get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Files config HTTP ${response.code}")
|
||||
}
|
||||
@@ -48,7 +47,6 @@ class FilesApiRepository {
|
||||
.put(value.toRequestBody("text/plain".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Files config save HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -58,7 +56,6 @@ class FilesApiRepository {
|
||||
val url = "${session.serverUrl.trimEnd('/')}/index.php/apps/files/api/v1/stats"
|
||||
val request = Request.Builder().url(url).get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
return FilesStorageStats()
|
||||
}
|
||||
@@ -78,7 +75,6 @@ class FilesApiRepository {
|
||||
"?path=$encodedPath&depth=$depth&format=json"
|
||||
val request = Request.Builder().url(url).applyOcsJson().get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -99,7 +95,6 @@ class FilesApiRepository {
|
||||
val url = "${session.serverUrl.trimEnd('/')}/index.php/apps/files/api/v1/recent/"
|
||||
val request = Request.Builder().url(url).get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Recent files HTTP ${response.code}")
|
||||
}
|
||||
@@ -131,7 +126,6 @@ class FilesApiRepository {
|
||||
"?term=$encoded&format=json"
|
||||
val request = Request.Builder().url(url).applyOcsJson().get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -188,7 +182,6 @@ class FilesApiRepository {
|
||||
.build()
|
||||
val request = Request.Builder().url(url).applyOcsJson().post(body).build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Не удалось создать ссылку (HTTP ${response.code})")
|
||||
}
|
||||
@@ -211,7 +204,6 @@ class FilesApiRepository {
|
||||
"?path=$encodedPath&reshares=true&format=json"
|
||||
val request = Request.Builder().url(url).applyOcsJson().get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) return emptyList()
|
||||
val root = parseJsonObject(response.body!!.string(), "общий доступ")
|
||||
val data = root.optJSONObject("ocs")?.opt("data")
|
||||
@@ -247,7 +239,6 @@ class FilesApiRepository {
|
||||
"?format=json&object_type=files&object_id=$fileId&limit=50&sort=desc"
|
||||
val request = Request.Builder().url(url).applyOcsJson().get().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code == 204 || !response.isSuccessful || response.body == null) return emptyList()
|
||||
val root = parseJsonObject(response.body!!.string(), "события")
|
||||
val data = root.optJSONObject("ocs")?.opt("data")
|
||||
|
||||
-3
@@ -29,7 +29,6 @@ class FilesTemplatesRepository {
|
||||
.post(body)
|
||||
.build()
|
||||
return client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
parseOcsData(response) { data ->
|
||||
CreatedFile(
|
||||
fileId = data.optLong("fileid"),
|
||||
@@ -54,7 +53,6 @@ class FilesTemplatesRepository {
|
||||
.post(body)
|
||||
.build()
|
||||
return client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
parseOcsData(response) { data ->
|
||||
data.optString("template_path")
|
||||
}
|
||||
@@ -74,7 +72,6 @@ class FilesTemplatesRepository {
|
||||
.post(body)
|
||||
.build()
|
||||
return client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
parseOcsData(response) { data ->
|
||||
data.optString("url").ifBlank {
|
||||
error("Не удалось открыть описание папки")
|
||||
|
||||
-1
@@ -25,7 +25,6 @@ class RichdocumentsRepository {
|
||||
.post(body)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Richdocuments HTTP ${response.code}")
|
||||
}
|
||||
|
||||
@@ -121,7 +121,6 @@ class MailRepository {
|
||||
.put(payload.toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
@@ -141,7 +140,6 @@ class MailRepository {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -160,7 +158,6 @@ class MailRepository {
|
||||
.post(payload.toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
@@ -178,7 +175,6 @@ class MailRepository {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -221,7 +217,6 @@ class MailRepository {
|
||||
.patch(payload.toString().toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
@@ -241,7 +236,6 @@ class MailRepository {
|
||||
.put(payload.toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -261,7 +255,6 @@ class MailRepository {
|
||||
.post("".toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Не удалось отправить (HTTP ${response.code})")
|
||||
}
|
||||
}
|
||||
@@ -275,7 +268,6 @@ class MailRepository {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Не удалось удалить (HTTP ${response.code})")
|
||||
}
|
||||
}
|
||||
@@ -301,7 +293,6 @@ class MailRepository {
|
||||
.put(body.toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -316,7 +307,6 @@ class MailRepository {
|
||||
.post("".toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Не удалось переместить (HTTP ${response.code})")
|
||||
}
|
||||
}
|
||||
@@ -337,7 +327,6 @@ class MailRepository {
|
||||
.post("".toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Не удалось отложить (HTTP ${response.code})")
|
||||
}
|
||||
}
|
||||
@@ -358,7 +347,6 @@ class MailRepository {
|
||||
}
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Не удалось изменить метку (HTTP ${response.code})")
|
||||
}
|
||||
}
|
||||
@@ -371,7 +359,6 @@ class MailRepository {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Mail API HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -387,7 +374,6 @@ class MailRepository {
|
||||
.header("OCS-APIRequest", "true")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Вложение HTTP ${response.code}")
|
||||
}
|
||||
@@ -422,7 +408,6 @@ class MailRepository {
|
||||
.post(body)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Не удалось загрузить вложение (HTTP ${response.code})")
|
||||
}
|
||||
@@ -478,7 +463,6 @@ class MailRepository {
|
||||
.post(payload.toString().toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
val messageId = client.newCall(createRequest).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Не удалось создать письмо (HTTP ${response.code})")
|
||||
}
|
||||
@@ -495,7 +479,6 @@ class MailRepository {
|
||||
.post("".toRequestBody("application/json".toMediaType()))
|
||||
.build()
|
||||
client.newCall(sendRequest).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) {
|
||||
error("Не удалось отправить письмо (HTTP ${response.code})")
|
||||
}
|
||||
@@ -738,7 +721,6 @@ class MailRepository {
|
||||
.header("Accept", "application/json")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code == 412) error("Mail API: CSRF — обновите приложение")
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Mail API HTTP ${response.code}")
|
||||
|
||||
@@ -59,7 +59,6 @@ object TalkAttachmentUploader {
|
||||
.header("Accept", "application/json")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) return DEFAULT_ATTACHMENT_FOLDER
|
||||
val data = JSONObject(response.body!!.string())
|
||||
.optJSONObject("ocs")
|
||||
@@ -110,7 +109,6 @@ object TalkAttachmentUploader {
|
||||
val url = davFileUrl(session.serverUrl, davUserId, remotePath.trim('/'))
|
||||
val request = Request.Builder().url(url).head().build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
return response.isSuccessful
|
||||
}
|
||||
}
|
||||
@@ -136,7 +134,6 @@ object TalkAttachmentUploader {
|
||||
.method("MKCOL", ByteArray(0).toRequestBody(null))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
// 405 = already exists
|
||||
}
|
||||
}
|
||||
@@ -156,7 +153,6 @@ object TalkAttachmentUploader {
|
||||
.put(bytes.toRequestBody(mediaType))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) {
|
||||
error("Не удалось загрузить файл: HTTP ${response.code}")
|
||||
}
|
||||
@@ -190,7 +186,6 @@ object TalkAttachmentUploader {
|
||||
.post(body)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) {
|
||||
error("Не удалось отправить вложение в чат: HTTP ${response.code}")
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ class TalkRepository {
|
||||
.post(payload.toRequestBody("application/json; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) {
|
||||
error("Talk read marker failed: HTTP ${response.code}")
|
||||
}
|
||||
@@ -166,7 +165,6 @@ class TalkRepository {
|
||||
builder.delete()
|
||||
}
|
||||
client.newCall(builder.build()).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Talk favorite failed: HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -181,7 +179,6 @@ class TalkRepository {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Talk mark unread failed: HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -215,7 +212,6 @@ class TalkRepository {
|
||||
.post(payload.toString().toRequestBody("application/json; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (response.code != 201 && !response.isSuccessful) {
|
||||
error("Talk send failed: HTTP ${response.code}")
|
||||
}
|
||||
@@ -270,7 +266,6 @@ class TalkRepository {
|
||||
"DELETE" -> builder.delete()
|
||||
}
|
||||
client.newCall(builder.build()).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Talk request failed: HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -288,7 +283,6 @@ class TalkRepository {
|
||||
.put(body)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Talk edit failed: HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -323,7 +317,6 @@ class TalkRepository {
|
||||
.delete()
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful) error("Talk delete failed: HTTP ${response.code}")
|
||||
}
|
||||
}
|
||||
@@ -351,7 +344,6 @@ class TalkRepository {
|
||||
.post(payload.toRequestBody("application/json; charset=utf-8".toMediaType()))
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Talk request failed: HTTP ${response.code}")
|
||||
}
|
||||
@@ -371,7 +363,6 @@ class TalkRepository {
|
||||
.header("Accept", "application/json")
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (response.code == 401) throw UnauthorizedException()
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
error("Talk request failed: HTTP ${response.code}")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user