✨ Auth tickets management
This commit is contained in:
parent
14ee6845ed
commit
f03d80ba88
@ -810,5 +810,8 @@
|
||||
"serviceNamePassport": "Authorization and Authentication",
|
||||
"accountActionEvent": "Action Events",
|
||||
"accountActionEventDescription": "View your action event logs.",
|
||||
"eventMetadata": "Metadata"
|
||||
"eventMetadata": "Metadata",
|
||||
"authTicketCreatedAt": "Issued at {}",
|
||||
"authTicketExpiredAt": "Expired at {}",
|
||||
"authTicketLastGrantAt": "Last granted at {}"
|
||||
}
|
||||
|
@ -808,5 +808,10 @@
|
||||
"serviceNamePassport": "身份验证与授权",
|
||||
"accountActionEvent": "操作日志",
|
||||
"accountActionEventDescription": "查看你的操作日志。",
|
||||
"eventMetadata": "元数据"
|
||||
"eventMetadata": "元数据",
|
||||
"accountAuthTickets": "授权会话",
|
||||
"accountAuthTicketsDescription": "查看和管理你的授权会话。",
|
||||
"authTicketCreatedAt": "签发于 {}",
|
||||
"authTicketExpiredAt": "到期于 {}",
|
||||
"authTicketLastGrantAt": "上次刷新于 {}"
|
||||
}
|
||||
|
@ -805,5 +805,13 @@
|
||||
"serviceNameMatrix": "矩陣市場",
|
||||
"serviceNamePaperclip": "附件",
|
||||
"serviceNameWallet": "源點錢包",
|
||||
"serviceNamePassport": "身份驗證與授權"
|
||||
"serviceNamePassport": "身份驗證與授權",
|
||||
"accountActionEvent": "操作日誌",
|
||||
"accountActionEventDescription": "查看你的操作日誌。",
|
||||
"eventMetadata": "元數據",
|
||||
"accountAuthTickets": "授權會話",
|
||||
"accountAuthTicketsDescription": "查看和管理你的授權會話。",
|
||||
"authTicketCreatedAt": "簽發於 {}",
|
||||
"authTicketExpiredAt": "到期於 {}",
|
||||
"authTicketLastGrantAt": "上次刷新於 {}"
|
||||
}
|
||||
|
@ -805,5 +805,13 @@
|
||||
"serviceNameMatrix": "矩陣市場",
|
||||
"serviceNamePaperclip": "附件",
|
||||
"serviceNameWallet": "源點錢包",
|
||||
"serviceNamePassport": "身份驗證與授權"
|
||||
"serviceNamePassport": "身份驗證與授權",
|
||||
"accountActionEvent": "操作日誌",
|
||||
"accountActionEventDescription": "查看你的操作日誌。",
|
||||
"eventMetadata": "元數據",
|
||||
"accountAuthTickets": "授權會話",
|
||||
"accountAuthTicketsDescription": "查看和管理你的授權會話。",
|
||||
"authTicketCreatedAt": "簽發於 {}",
|
||||
"authTicketExpiredAt": "到期於 {}",
|
||||
"authTicketLastGrantAt": "上次刷新於 {}"
|
||||
}
|
||||
|
@ -13,6 +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/album.dart';
|
||||
import 'package:surface/screens/auth/login.dart';
|
||||
import 'package:surface/screens/auth/register.dart';
|
||||
@ -130,6 +131,11 @@ final _appRoutes = [
|
||||
name: 'accountActionEvents',
|
||||
builder: (context, state) => const ActionEventScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/tickets',
|
||||
name: 'accountAuthTickets',
|
||||
builder: (context, state) => const AccountAuthTicket(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/badges',
|
||||
name: 'accountBadges',
|
||||
|
@ -217,6 +217,16 @@ class _AuthorizedAccountScreen extends StatelessWidget {
|
||||
GoRouter.of(context).pushNamed('accountActionEvents');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('accountAuthTickets').tr(),
|
||||
subtitle: Text('accountAuthTicketsDescription').tr(),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
leading: const Icon(Symbols.confirmation_number),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
onTap: () {
|
||||
GoRouter.of(context).pushNamed('accountAuthTickets');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('accountSettings').tr(),
|
||||
subtitle: Text('accountSettingsSubtitle').tr(),
|
||||
|
@ -2,10 +2,9 @@ import 'dart:convert';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:relative_time/relative_time.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:surface/providers/sn_network.dart';
|
||||
import 'package:surface/types/account.dart';
|
||||
@ -71,12 +70,12 @@ class _ActionEventScreenState extends State<ActionEventScreen> {
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () {
|
||||
_totalCount = null;
|
||||
_actionEvents.clear();
|
||||
return _fetchActionEvents();
|
||||
},
|
||||
child: InfiniteList(
|
||||
padding: EdgeInsets.only(left: 20, right: 8),
|
||||
itemCount: _actionEvents.length,
|
||||
isLoading: _isBusy,
|
||||
hasReachedMax:
|
||||
_totalCount != null && _actionEvents.length >= _totalCount!,
|
||||
onFetchData: _fetchActionEvents,
|
||||
@ -105,32 +104,26 @@ class _ActionEventScreenState extends State<ActionEventScreen> {
|
||||
if (event.ipAddress.isNotEmpty)
|
||||
Text(
|
||||
event.ipAddress,
|
||||
style: GoogleFonts.robotoMono(fontSize: 12),
|
||||
style: TextStyle(fontSize: 13),
|
||||
),
|
||||
if (event.location?.isNotEmpty ?? false)
|
||||
Text(event.location!)
|
||||
Text(event.location!),
|
||||
Row(
|
||||
children: [
|
||||
Text(DateFormat()
|
||||
.format(event.createdAt.toLocal()))
|
||||
.fontSize(12),
|
||||
Text(' · ')
|
||||
.fontSize(12)
|
||||
.padding(horizontal: 4),
|
||||
Text(RelativeTime(context)
|
||||
.format(event.createdAt.toLocal()))
|
||||
.fontSize(12),
|
||||
],
|
||||
).opacity(0.75).padding(top: 4),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (event.location?.isNotEmpty ?? false)
|
||||
SizedBox(
|
||||
height: 180,
|
||||
child: FlutterMap(
|
||||
options: MapOptions(
|
||||
initialCenter: LatLng(
|
||||
event.coordinateX!,
|
||||
event.coordinateY!,
|
||||
),
|
||||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate:
|
||||
'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
userAgentPackageName: 'dev.solsynth.solian',
|
||||
),
|
||||
],
|
||||
),
|
||||
).padding(bottom: 6),
|
||||
if (event.metadata != null)
|
||||
ExpansionTile(
|
||||
minTileHeight: 40,
|
||||
|
170
lib/screens/account/tickets.dart
Normal file
170
lib/screens/account/tickets.dart
Normal file
@ -0,0 +1,170 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
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/types/auth.dart';
|
||||
import 'package:surface/widgets/dialog.dart';
|
||||
import 'package:surface/widgets/loading_indicator.dart';
|
||||
import 'package:surface/widgets/navigation/app_scaffold.dart';
|
||||
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
||||
|
||||
const Map<String, IconData> kAuthTicketIcon = {
|
||||
'ios': Symbols.ios,
|
||||
'android': Symbols.android,
|
||||
'macos': Symbols.computer,
|
||||
'windows nt': Symbols.laptop_windows,
|
||||
'linux': Symbols.laptop,
|
||||
};
|
||||
|
||||
class AccountAuthTicket extends StatefulWidget {
|
||||
const AccountAuthTicket({super.key});
|
||||
|
||||
@override
|
||||
State<AccountAuthTicket> createState() => _AccountAuthTicketState();
|
||||
}
|
||||
|
||||
class _AccountAuthTicketState extends State<AccountAuthTicket> {
|
||||
bool _isBusy = false;
|
||||
int? _totalCount;
|
||||
final List<SnAuthTicket> _authTickets = List.empty(growable: true);
|
||||
|
||||
Future<void> _fetchAuthTickets() async {
|
||||
setState(() => _isBusy = true);
|
||||
try {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
final resp = await sn.client.get(
|
||||
'/cgi/id/users/me/tickets',
|
||||
queryParameters: {
|
||||
'take': 10,
|
||||
'offset': _authTickets.length,
|
||||
},
|
||||
);
|
||||
_totalCount = resp.data['count'];
|
||||
_authTickets.addAll(
|
||||
(resp.data['data'] as List<dynamic>)
|
||||
.map((e) => SnAuthTicket.fromJson(e)),
|
||||
);
|
||||
} catch (err) {
|
||||
if (!mounted) return;
|
||||
context.showErrorDialog(err);
|
||||
} finally {
|
||||
setState(() => _isBusy = false);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _deleteAuthTicket(SnAuthTicket ticket) async {
|
||||
setState(() => _isBusy = true);
|
||||
try {
|
||||
final sn = context.read<SnNetworkProvider>();
|
||||
await sn.client.delete(
|
||||
'/cgi/id/users/me/tickets/${ticket.id}',
|
||||
);
|
||||
setState(() {
|
||||
_authTickets.remove(ticket);
|
||||
});
|
||||
} catch (err) {
|
||||
if (!mounted) return;
|
||||
context.showErrorDialog(err);
|
||||
} finally {
|
||||
setState(() => _isBusy = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_fetchAuthTickets();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppScaffold(
|
||||
appBar: AppBar(
|
||||
leading: const PageBackButton(),
|
||||
title: Text('accountAuthTickets').tr(),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
LoadingIndicator(isActive: _isBusy),
|
||||
Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () {
|
||||
_totalCount = null;
|
||||
return _fetchAuthTickets();
|
||||
},
|
||||
child: InfiniteList(
|
||||
padding: EdgeInsets.zero,
|
||||
onFetchData: _fetchAuthTickets,
|
||||
isLoading: _isBusy,
|
||||
hasReachedMax:
|
||||
_totalCount != null && _authTickets.length >= _totalCount!,
|
||||
itemCount: _authTickets.length,
|
||||
itemBuilder: (context, idx) {
|
||||
final ticket = _authTickets[idx];
|
||||
final platform = RegExp(r'\(([^;]+);')
|
||||
.firstMatch(ticket.userAgent)
|
||||
?.group(1);
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
kAuthTicketIcon[platform!.toLowerCase()] ?? Symbols.web,
|
||||
),
|
||||
const Gap(12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
ticket.ipAddress,
|
||||
style: TextStyle(fontSize: 15),
|
||||
),
|
||||
Text(ticket.userAgent).opacity(0.8),
|
||||
if (ticket.location?.isNotEmpty ?? false)
|
||||
const Gap(4),
|
||||
if (ticket.location?.isNotEmpty ?? false)
|
||||
Text(ticket.location!).opacity(0.8),
|
||||
const Gap(4),
|
||||
Text('authTicketCreatedAt'.tr(args: [
|
||||
(DateFormat().format(ticket.createdAt.toLocal()))
|
||||
])).fontSize(12).opacity(0.75),
|
||||
if (ticket.expiredAt != null)
|
||||
Text('authTicketExpiredAt'.tr(args: [
|
||||
(DateFormat()
|
||||
.format(ticket.expiredAt!.toLocal()))
|
||||
])).fontSize(12).opacity(0.75),
|
||||
if (ticket.lastGrantAt != null)
|
||||
Text('authTicketLastGrantAt'.tr(args: [
|
||||
(DateFormat()
|
||||
.format(ticket.lastGrantAt!.toLocal()))
|
||||
])).fontSize(12).opacity(0.75),
|
||||
const Gap(4),
|
||||
Text('#${ticket.id}').fontSize(11).opacity(0.75),
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 20,
|
||||
visualDensity:
|
||||
VisualDensity(horizontal: -4, vertical: -4),
|
||||
constraints: const BoxConstraints(),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: const Icon(Symbols.logout),
|
||||
onPressed: () {
|
||||
_deleteAuthTicket(ticket);
|
||||
},
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -26,7 +26,9 @@ abstract class SnAuthTicket with _$SnAuthTicket {
|
||||
required String? accessToken,
|
||||
required String? refreshToken,
|
||||
required String ipAddress,
|
||||
required String location,
|
||||
required String? location,
|
||||
required double? coordinateX,
|
||||
required double? coordinateY,
|
||||
required String userAgent,
|
||||
required DateTime? expiredAt,
|
||||
required DateTime? lastGrantAt,
|
||||
|
@ -217,7 +217,9 @@ mixin _$SnAuthTicket {
|
||||
String? get accessToken;
|
||||
String? get refreshToken;
|
||||
String get ipAddress;
|
||||
String get location;
|
||||
String? get location;
|
||||
double? get coordinateX;
|
||||
double? get coordinateY;
|
||||
String get userAgent;
|
||||
DateTime? get expiredAt;
|
||||
DateTime? get lastGrantAt;
|
||||
@ -261,6 +263,10 @@ mixin _$SnAuthTicket {
|
||||
other.ipAddress == ipAddress) &&
|
||||
(identical(other.location, location) ||
|
||||
other.location == location) &&
|
||||
(identical(other.coordinateX, coordinateX) ||
|
||||
other.coordinateX == coordinateX) &&
|
||||
(identical(other.coordinateY, coordinateY) ||
|
||||
other.coordinateY == coordinateY) &&
|
||||
(identical(other.userAgent, userAgent) ||
|
||||
other.userAgent == userAgent) &&
|
||||
(identical(other.expiredAt, expiredAt) ||
|
||||
@ -278,29 +284,32 @@ mixin _$SnAuthTicket {
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
stepRemain,
|
||||
grantToken,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
ipAddress,
|
||||
location,
|
||||
userAgent,
|
||||
expiredAt,
|
||||
lastGrantAt,
|
||||
availableAt,
|
||||
nonce,
|
||||
accountId,
|
||||
const DeepCollectionEquality().hash(factorTrail));
|
||||
int get hashCode => Object.hashAll([
|
||||
runtimeType,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
stepRemain,
|
||||
grantToken,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
ipAddress,
|
||||
location,
|
||||
coordinateX,
|
||||
coordinateY,
|
||||
userAgent,
|
||||
expiredAt,
|
||||
lastGrantAt,
|
||||
availableAt,
|
||||
nonce,
|
||||
accountId,
|
||||
const DeepCollectionEquality().hash(factorTrail)
|
||||
]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAuthTicket(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stepRemain: $stepRemain, grantToken: $grantToken, accessToken: $accessToken, refreshToken: $refreshToken, ipAddress: $ipAddress, location: $location, userAgent: $userAgent, expiredAt: $expiredAt, lastGrantAt: $lastGrantAt, availableAt: $availableAt, nonce: $nonce, accountId: $accountId, factorTrail: $factorTrail)';
|
||||
return 'SnAuthTicket(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stepRemain: $stepRemain, grantToken: $grantToken, accessToken: $accessToken, refreshToken: $refreshToken, ipAddress: $ipAddress, location: $location, coordinateX: $coordinateX, coordinateY: $coordinateY, userAgent: $userAgent, expiredAt: $expiredAt, lastGrantAt: $lastGrantAt, availableAt: $availableAt, nonce: $nonce, accountId: $accountId, factorTrail: $factorTrail)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,7 +329,9 @@ abstract mixin class $SnAuthTicketCopyWith<$Res> {
|
||||
String? accessToken,
|
||||
String? refreshToken,
|
||||
String ipAddress,
|
||||
String location,
|
||||
String? location,
|
||||
double? coordinateX,
|
||||
double? coordinateY,
|
||||
String userAgent,
|
||||
DateTime? expiredAt,
|
||||
DateTime? lastGrantAt,
|
||||
@ -351,7 +362,9 @@ class _$SnAuthTicketCopyWithImpl<$Res> implements $SnAuthTicketCopyWith<$Res> {
|
||||
Object? accessToken = freezed,
|
||||
Object? refreshToken = freezed,
|
||||
Object? ipAddress = null,
|
||||
Object? location = null,
|
||||
Object? location = freezed,
|
||||
Object? coordinateX = freezed,
|
||||
Object? coordinateY = freezed,
|
||||
Object? userAgent = null,
|
||||
Object? expiredAt = freezed,
|
||||
Object? lastGrantAt = freezed,
|
||||
@ -397,10 +410,18 @@ class _$SnAuthTicketCopyWithImpl<$Res> implements $SnAuthTicketCopyWith<$Res> {
|
||||
? _self.ipAddress
|
||||
: ipAddress // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
location: null == location
|
||||
location: freezed == location
|
||||
? _self.location
|
||||
: location // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as String?,
|
||||
coordinateX: freezed == coordinateX
|
||||
? _self.coordinateX
|
||||
: coordinateX // ignore: cast_nullable_to_non_nullable
|
||||
as double?,
|
||||
coordinateY: freezed == coordinateY
|
||||
? _self.coordinateY
|
||||
: coordinateY // ignore: cast_nullable_to_non_nullable
|
||||
as double?,
|
||||
userAgent: null == userAgent
|
||||
? _self.userAgent
|
||||
: userAgent // ignore: cast_nullable_to_non_nullable
|
||||
@ -447,6 +468,8 @@ class _SnAuthTicket implements SnAuthTicket {
|
||||
required this.refreshToken,
|
||||
required this.ipAddress,
|
||||
required this.location,
|
||||
required this.coordinateX,
|
||||
required this.coordinateY,
|
||||
required this.userAgent,
|
||||
required this.expiredAt,
|
||||
required this.lastGrantAt,
|
||||
@ -477,7 +500,11 @@ class _SnAuthTicket implements SnAuthTicket {
|
||||
@override
|
||||
final String ipAddress;
|
||||
@override
|
||||
final String location;
|
||||
final String? location;
|
||||
@override
|
||||
final double? coordinateX;
|
||||
@override
|
||||
final double? coordinateY;
|
||||
@override
|
||||
final String userAgent;
|
||||
@override
|
||||
@ -538,6 +565,10 @@ class _SnAuthTicket implements SnAuthTicket {
|
||||
other.ipAddress == ipAddress) &&
|
||||
(identical(other.location, location) ||
|
||||
other.location == location) &&
|
||||
(identical(other.coordinateX, coordinateX) ||
|
||||
other.coordinateX == coordinateX) &&
|
||||
(identical(other.coordinateY, coordinateY) ||
|
||||
other.coordinateY == coordinateY) &&
|
||||
(identical(other.userAgent, userAgent) ||
|
||||
other.userAgent == userAgent) &&
|
||||
(identical(other.expiredAt, expiredAt) ||
|
||||
@ -555,29 +586,32 @@ class _SnAuthTicket implements SnAuthTicket {
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
stepRemain,
|
||||
grantToken,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
ipAddress,
|
||||
location,
|
||||
userAgent,
|
||||
expiredAt,
|
||||
lastGrantAt,
|
||||
availableAt,
|
||||
nonce,
|
||||
accountId,
|
||||
const DeepCollectionEquality().hash(_factorTrail));
|
||||
int get hashCode => Object.hashAll([
|
||||
runtimeType,
|
||||
id,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
deletedAt,
|
||||
stepRemain,
|
||||
grantToken,
|
||||
accessToken,
|
||||
refreshToken,
|
||||
ipAddress,
|
||||
location,
|
||||
coordinateX,
|
||||
coordinateY,
|
||||
userAgent,
|
||||
expiredAt,
|
||||
lastGrantAt,
|
||||
availableAt,
|
||||
nonce,
|
||||
accountId,
|
||||
const DeepCollectionEquality().hash(_factorTrail)
|
||||
]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAuthTicket(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stepRemain: $stepRemain, grantToken: $grantToken, accessToken: $accessToken, refreshToken: $refreshToken, ipAddress: $ipAddress, location: $location, userAgent: $userAgent, expiredAt: $expiredAt, lastGrantAt: $lastGrantAt, availableAt: $availableAt, nonce: $nonce, accountId: $accountId, factorTrail: $factorTrail)';
|
||||
return 'SnAuthTicket(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, stepRemain: $stepRemain, grantToken: $grantToken, accessToken: $accessToken, refreshToken: $refreshToken, ipAddress: $ipAddress, location: $location, coordinateX: $coordinateX, coordinateY: $coordinateY, userAgent: $userAgent, expiredAt: $expiredAt, lastGrantAt: $lastGrantAt, availableAt: $availableAt, nonce: $nonce, accountId: $accountId, factorTrail: $factorTrail)';
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,7 +633,9 @@ abstract mixin class _$SnAuthTicketCopyWith<$Res>
|
||||
String? accessToken,
|
||||
String? refreshToken,
|
||||
String ipAddress,
|
||||
String location,
|
||||
String? location,
|
||||
double? coordinateX,
|
||||
double? coordinateY,
|
||||
String userAgent,
|
||||
DateTime? expiredAt,
|
||||
DateTime? lastGrantAt,
|
||||
@ -631,7 +667,9 @@ class __$SnAuthTicketCopyWithImpl<$Res>
|
||||
Object? accessToken = freezed,
|
||||
Object? refreshToken = freezed,
|
||||
Object? ipAddress = null,
|
||||
Object? location = null,
|
||||
Object? location = freezed,
|
||||
Object? coordinateX = freezed,
|
||||
Object? coordinateY = freezed,
|
||||
Object? userAgent = null,
|
||||
Object? expiredAt = freezed,
|
||||
Object? lastGrantAt = freezed,
|
||||
@ -677,10 +715,18 @@ class __$SnAuthTicketCopyWithImpl<$Res>
|
||||
? _self.ipAddress
|
||||
: ipAddress // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
location: null == location
|
||||
location: freezed == location
|
||||
? _self.location
|
||||
: location // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as String?,
|
||||
coordinateX: freezed == coordinateX
|
||||
? _self.coordinateX
|
||||
: coordinateX // ignore: cast_nullable_to_non_nullable
|
||||
as double?,
|
||||
coordinateY: freezed == coordinateY
|
||||
? _self.coordinateY
|
||||
: coordinateY // ignore: cast_nullable_to_non_nullable
|
||||
as double?,
|
||||
userAgent: null == userAgent
|
||||
? _self.userAgent
|
||||
: userAgent // ignore: cast_nullable_to_non_nullable
|
||||
|
@ -33,7 +33,9 @@ _SnAuthTicket _$SnAuthTicketFromJson(Map<String, dynamic> json) =>
|
||||
accessToken: json['access_token'] as String?,
|
||||
refreshToken: json['refresh_token'] as String?,
|
||||
ipAddress: json['ip_address'] as String,
|
||||
location: json['location'] as String,
|
||||
location: json['location'] as String?,
|
||||
coordinateX: (json['coordinate_x'] as num?)?.toDouble(),
|
||||
coordinateY: (json['coordinate_y'] as num?)?.toDouble(),
|
||||
userAgent: json['user_agent'] as String,
|
||||
expiredAt: json['expired_at'] == null
|
||||
? null
|
||||
@ -64,6 +66,8 @@ Map<String, dynamic> _$SnAuthTicketToJson(_SnAuthTicket instance) =>
|
||||
'refresh_token': instance.refreshToken,
|
||||
'ip_address': instance.ipAddress,
|
||||
'location': instance.location,
|
||||
'coordinate_x': instance.coordinateX,
|
||||
'coordinate_y': instance.coordinateY,
|
||||
'user_agent': instance.userAgent,
|
||||
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||
'last_grant_at': instance.lastGrantAt?.toIso8601String(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user