✨ Dispose current session when logout
This commit is contained in:
parent
f03d80ba88
commit
1b7e668b3f
@ -813,5 +813,6 @@
|
||||
"eventMetadata": "Metadata",
|
||||
"authTicketCreatedAt": "Issued at {}",
|
||||
"authTicketExpiredAt": "Expired at {}",
|
||||
"authTicketLastGrantAt": "Last granted at {}"
|
||||
"authTicketLastGrantAt": "Last granted at {}",
|
||||
"authTicketCurrent": "Current"
|
||||
}
|
||||
|
@ -813,5 +813,6 @@
|
||||
"accountAuthTicketsDescription": "查看和管理你的授权会话。",
|
||||
"authTicketCreatedAt": "签发于 {}",
|
||||
"authTicketExpiredAt": "到期于 {}",
|
||||
"authTicketLastGrantAt": "上次刷新于 {}"
|
||||
"authTicketLastGrantAt": "上次刷新于 {}",
|
||||
"authTicketCurrent": "当前会话"
|
||||
}
|
||||
|
@ -813,5 +813,6 @@
|
||||
"accountAuthTicketsDescription": "查看和管理你的授權會話。",
|
||||
"authTicketCreatedAt": "簽發於 {}",
|
||||
"authTicketExpiredAt": "到期於 {}",
|
||||
"authTicketLastGrantAt": "上次刷新於 {}"
|
||||
"authTicketLastGrantAt": "上次刷新於 {}",
|
||||
"authTicketCurrent": "當前會話"
|
||||
}
|
||||
|
@ -813,5 +813,6 @@
|
||||
"accountAuthTicketsDescription": "查看和管理你的授權會話。",
|
||||
"authTicketCreatedAt": "簽發於 {}",
|
||||
"authTicketExpiredAt": "到期於 {}",
|
||||
"authTicketLastGrantAt": "上次刷新於 {}"
|
||||
"authTicketLastGrantAt": "上次刷新於 {}",
|
||||
"authTicketCurrent": "當前會話"
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@ -35,6 +37,32 @@ class UserProvider extends ChangeNotifier {
|
||||
});
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>?> get atkClaims async {
|
||||
final tk = (await atk);
|
||||
if (tk == null) return null;
|
||||
final atkParts = tk.split('.');
|
||||
if (atkParts.length != 3) {
|
||||
throw Exception('invalid format of access token');
|
||||
}
|
||||
|
||||
var rawPayload = atkParts[1].replaceAll('-', '+').replaceAll('_', '/');
|
||||
switch (rawPayload.length % 4) {
|
||||
case 0:
|
||||
break;
|
||||
case 2:
|
||||
rawPayload += '==';
|
||||
break;
|
||||
case 3:
|
||||
rawPayload += '=';
|
||||
break;
|
||||
default:
|
||||
throw Exception('illegal format of access token payload');
|
||||
}
|
||||
|
||||
final b64 = utf8.fuse(base64Url);
|
||||
return jsonDecode(b64.decode(rawPayload));
|
||||
}
|
||||
|
||||
Future<SnAccount?> refreshUser() async {
|
||||
final resp = await _sn.client.get('/cgi/id/users/me');
|
||||
final out = SnAccount.fromJson(resp.data);
|
||||
@ -47,7 +75,13 @@ class UserProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
void logoutUser() async {
|
||||
_sn.clearTokenPair();
|
||||
atkClaims.then((value) async {
|
||||
if (value != null) {
|
||||
await _sn.client.delete('/cgi/id/users/me/tickets/${value['sed']}');
|
||||
logging.info('[Auth] Current session has been destroyed.');
|
||||
}
|
||||
_sn.clearTokenPair();
|
||||
});
|
||||
isAuthorized = false;
|
||||
user = null;
|
||||
notifyListeners();
|
||||
|
@ -13,7 +13,7 @@ import 'package:surface/screens/account/profile_edit.dart';
|
||||
import 'package:surface/screens/account/publishers/publisher_edit.dart';
|
||||
import 'package:surface/screens/account/publishers/publisher_new.dart';
|
||||
import 'package:surface/screens/account/publishers/publishers.dart';
|
||||
import 'package:surface/screens/account/tickets.dart';
|
||||
import 'package:surface/screens/account/auth_tickets.dart';
|
||||
import 'package:surface/screens/album.dart';
|
||||
import 'package:surface/screens/auth/login.dart';
|
||||
import 'package:surface/screens/auth/register.dart';
|
||||
|
@ -5,6 +5,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/providers/userinfo.dart';
|
||||
import 'package:surface/types/auth.dart';
|
||||
import 'package:surface/widgets/dialog.dart';
|
||||
import 'package:surface/widgets/loading_indicator.dart';
|
||||
@ -73,10 +74,18 @@ class _AccountAuthTicketState extends State<AccountAuthTicket> {
|
||||
}
|
||||
}
|
||||
|
||||
int? _currentTicketId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchAuthTickets();
|
||||
|
||||
final ua = context.read<UserProvider>();
|
||||
ua.atkClaims.then((value) {
|
||||
if (value == null) return;
|
||||
_currentTicketId = int.parse(value['sed']);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@ -142,6 +151,11 @@ class _AccountAuthTicketState extends State<AccountAuthTicket> {
|
||||
.format(ticket.lastGrantAt!.toLocal()))
|
||||
])).fontSize(12).opacity(0.75),
|
||||
const Gap(4),
|
||||
if (_currentTicketId == ticket.id)
|
||||
Text('authTicketCurrent'.tr())
|
||||
.fontSize(11)
|
||||
.bold()
|
||||
.opacity(0.75),
|
||||
Text('#${ticket.id}').fontSize(11).opacity(0.75),
|
||||
],
|
||||
),
|
||||
@ -153,9 +167,11 @@ class _AccountAuthTicketState extends State<AccountAuthTicket> {
|
||||
constraints: const BoxConstraints(),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Symbols.logout),
|
||||
onPressed: () {
|
||||
_deleteAuthTicket(ticket);
|
||||
},
|
||||
onPressed: _currentTicketId == ticket.id
|
||||
? null
|
||||
: () {
|
||||
_deleteAuthTicket(ticket);
|
||||
},
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12);
|
Loading…
x
Reference in New Issue
Block a user