🥅 Better unauthorized exceptions

This commit is contained in:
LittleSheep 2024-08-21 15:25:50 +08:00
parent 1d7affcd84
commit 6148e889aa
15 changed files with 79 additions and 57 deletions

View File

@ -112,15 +112,19 @@ class _BootstrapperShellState extends State<BootstrapperShell> {
label: 'bsPreparingData',
action: () async {
final AuthProvider auth = Get.find();
await Future.wait([
Get.find<StickerProvider>().refreshAvailableStickers(),
if (auth.isAuthorized.isTrue)
Get.find<ChannelProvider>().refreshAvailableChannel(),
if (auth.isAuthorized.isTrue)
Get.find<RelationshipProvider>().refreshRelativeList(),
if (auth.isAuthorized.isTrue)
Get.find<RealmProvider>().refreshAvailableRealms(),
]);
try {
await Future.wait([
Get.find<StickerProvider>().refreshAvailableStickers(),
if (auth.isAuthorized.isTrue)
Get.find<ChannelProvider>().refreshAvailableChannel(),
if (auth.isAuthorized.isTrue)
Get.find<RelationshipProvider>().refreshRelativeList(),
if (auth.isAuthorized.isTrue)
Get.find<RealmProvider>().refreshAvailableRealms(),
]);
} catch (e) {
context.showErrorDialog(e);
}
},
),
(

View File

@ -0,0 +1,6 @@
class UnauthorizedException implements Exception {
const UnauthorizedException();
@override
String toString() => 'Unauthorized';
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
extension SolianExtenions on BuildContext {
void showSnackbar(String content, {SnackBarAction? action}) {
@ -48,15 +49,17 @@ extension SolianExtenions on BuildContext {
}
Future<void> showErrorDialog(dynamic exception) {
var stack = StackTrace.current;
var stackTrace = '$stack';
Widget content = Text(exception.toString().capitalize!);
if (exception is UnauthorizedException) {
content = Text('errorHappenedUnauthorized'.tr);
}
return showDialog<void>(
useRootNavigator: true,
context: this,
builder: (ctx) => AlertDialog(
title: Text('errorHappened'.tr),
content: Text('${exception.toString().capitalize!}\n\nStack Trace: $stackTrace'),
content: content,
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:solian/models/account_status.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
@ -33,15 +34,14 @@ class StatusProvider extends GetConnect {
Future<Response> getCurrentStatus() async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
final client = auth.configureClient('auth');
return await client.get('/users/me/status');
}
Future<Response> getSomeoneStatus(String name) =>
get('/users/$name/status');
Future<Response> getSomeoneStatus(String name) => get('/users/$name/status');
Future<Response> setStatus(
String type,
@ -53,7 +53,7 @@ class StatusProvider extends GetConnect {
DateTime? clearAt,
}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
final client = auth.configureClient('auth');
@ -82,7 +82,7 @@ class StatusProvider extends GetConnect {
Future<Response> clearStatus() async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
final client = auth.configureClient('auth');

View File

@ -7,6 +7,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:get/get.dart';
import 'package:get/get_connect/http/src/request/request.dart';
import 'package:solian/controllers/chat_events_controller.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:solian/providers/websocket.dart';
import 'package:solian/services.dart';
@ -128,7 +129,7 @@ class AuthProvider extends GetConnect {
}
Future<void> ensureCredentials() async {
if (isAuthorized.isFalse) throw Exception('unauthorized');
if (isAuthorized.isFalse) throw const UnauthorizedException();
if (credentials == null) await loadCredentials();
if (credentials!.isExpired) {

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:livekit_client/livekit_client.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:solian/models/call.dart';
@ -88,7 +89,7 @@ class ChatCallProvider extends GetxController {
Future<(String, String)> getRoomToken() async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');

View File

@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:typed_data';
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:path/path.dart';
import 'package:solian/models/attachment.dart';
import 'package:solian/models/pagination.dart';
@ -89,7 +90,7 @@ class AttachmentProvider extends GetConnect {
Map<String, dynamic>? metadata,
) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient(
'uc',
@ -131,7 +132,7 @@ class AttachmentProvider extends GetConnect {
Map<String, dynamic>? metadata,
) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('uc');
@ -169,7 +170,7 @@ class AttachmentProvider extends GetConnect {
String cid,
) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient(
'uc',
@ -193,7 +194,7 @@ class AttachmentProvider extends GetConnect {
bool isMature = false,
}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('files');
@ -211,7 +212,7 @@ class AttachmentProvider extends GetConnect {
Future<Response> deleteAttachment(int id) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('files');

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:solian/models/channel.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/widgets/account/relative_select.dart';
@ -16,7 +17,7 @@ class ChannelProvider extends GetxController {
Future<void> refreshAvailableChannel() async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
isLoading.value = true;
final resp = await listAvailableChannel();
@ -29,7 +30,7 @@ class ChannelProvider extends GetxController {
Future<Response> getChannel(String alias, {String realm = 'global'}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');
@ -44,7 +45,7 @@ class ChannelProvider extends GetxController {
Future<Response> getMyChannelProfile(String alias,
{String realm = 'global'}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');
@ -59,7 +60,7 @@ class ChannelProvider extends GetxController {
Future<Response?> getChannelOngoingCall(String alias,
{String realm = 'global'}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');
@ -75,7 +76,7 @@ class ChannelProvider extends GetxController {
Future<Response> listChannel({String scope = 'global'}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');
@ -89,7 +90,7 @@ class ChannelProvider extends GetxController {
Future<Response> listAvailableChannel({String realm = 'global'}) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');
@ -103,7 +104,7 @@ class ChannelProvider extends GetxController {
Future<Response> createChannel(String scope, dynamic payload) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');
@ -118,7 +119,7 @@ class ChannelProvider extends GetxController {
Future<Response?> createDirectChannel(
BuildContext context, String scope) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final related = await showModalBottomSheet(
useRootNavigator: true,
@ -149,7 +150,7 @@ class ChannelProvider extends GetxController {
Future<Response> updateChannel(String scope, int id, dynamic payload) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final client = auth.configureClient('messaging');

View File

@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:solian/providers/auth.dart';
import 'package:solian/services.dart';
@ -36,7 +37,7 @@ class PostProvider extends GetConnect {
Future<Response> listDraft(int page) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw UnauthorizedException();
final queries = [
'take=${10}',

View File

@ -1,4 +1,5 @@
import 'package:get/get.dart';
import 'package:solian/exceptions/unauthorized.dart';
import 'package:solian/models/realm.dart';
import 'package:solian/providers/auth.dart';
@ -8,7 +9,7 @@ class RealmProvider extends GetxController {
Future<void> refreshAvailableRealms() async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
isLoading.value = true;
final resp = await listAvailableRealm();
@ -21,7 +22,7 @@ class RealmProvider extends GetxController {
Future<Response> getRealm(String alias) async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
final client = auth.configureClient('auth');
@ -35,7 +36,7 @@ class RealmProvider extends GetxController {
Future<Response> listAvailableRealm() async {
final AuthProvider auth = Get.find();
if (auth.isAuthorized.isFalse) throw Exception('unauthorized');
if (auth.isAuthorized.isFalse) throw const UnauthorizedException();
final client = auth.configureClient('auth');

View File

@ -50,31 +50,31 @@ class WebSocketProvider extends GetxController {
}
final AuthProvider auth = Get.find();
await auth.ensureCredentials();
if (auth.credentials == null) await auth.loadCredentials();
final uri = Uri.parse(ServiceFinder.buildUrl(
'dealer',
'/api/ws?tk=${auth.credentials!.accessToken}',
).replaceFirst('http', 'ws'));
isConnecting.value = true;
try {
await auth.ensureCredentials();
final uri = Uri.parse(ServiceFinder.buildUrl(
'dealer',
'/api/ws?tk=${auth.credentials!.accessToken}',
).replaceFirst('http', 'ws'));
isConnecting.value = true;
websocket = WebSocketChannel.connect(uri);
await websocket?.ready;
} catch (e) {
listen();
isConnected.value = true;
} catch (err) {
log('Unable connect dealer via websocket... $err');
if (!noRetry) {
await auth.refreshCredentials();
return connect(noRetry: true);
}
} finally {
isConnecting.value = false;
}
listen();
isConnected.value = true;
isConnecting.value = false;
}
void disconnect() {

View File

@ -109,11 +109,11 @@ class _PersonalizeScreenState extends State<PersonalizeScreen> {
setState(() => _isBusy = true);
final AttachmentProvider provider = Get.find();
final AttachmentProvider attach = Get.find();
Attachment? attachResult;
try {
attachResult = await provider.createAttachmentDirectly(
attachResult = await attach.createAttachmentDirectly(
await file.readAsBytes(),
file.path,
'avatar',

View File

@ -41,6 +41,8 @@ const i18nEnglish = {
'openInBrowser': 'Open in browser',
'notification': 'Notification',
'errorHappened': 'An error occurred',
'errorHappenedUnauthorized':
'Unauthorized request, please sign in or try resign in.',
'forgotPassword': 'Forgot password',
'email': 'Email',
'username': 'Username',

View File

@ -41,6 +41,7 @@ const i18nSimplifiedChinese = {
'openInBrowser': '在浏览器中打开',
'notification': '通知',
'errorHappened': '发生错误了',
'errorHappenedUnauthorized': '未经授权的请求,请登录或尝试重新登录。',
'forgotPassword': '忘记密码',
'email': '邮件地址',
'username': '用户名',

View File

@ -28,11 +28,11 @@ class _AttachmentAttrEditorDialogState
bool _isMature = false;
Future<Attachment?> _updateAttachment() async {
final AttachmentProvider provider = Get.find();
final AttachmentProvider attach = Get.find();
setState(() => _isBusy = true);
try {
final resp = await provider.updateAttachment(
final resp = await attach.updateAttachment(
widget.item.id,
_altController.value.text,
isMature: _isMature,