feat: type schedule and auth models
This commit is contained in:
105
lib/models/api_key_info.dart
Normal file
105
lib/models/api_key_info.dart
Normal file
@@ -0,0 +1,105 @@
|
||||
class ApiKeyInfo {
|
||||
final String key;
|
||||
final String name;
|
||||
final bool isAdmin;
|
||||
final bool isActive;
|
||||
final DateTime? createdAt;
|
||||
|
||||
const ApiKeyInfo({
|
||||
required this.key,
|
||||
required this.name,
|
||||
required this.isAdmin,
|
||||
required this.isActive,
|
||||
this.createdAt,
|
||||
});
|
||||
|
||||
String get formattedCreatedAt {
|
||||
final value = createdAt;
|
||||
if (value == null) return '';
|
||||
String pad(int n) => n.toString().padLeft(2, '0');
|
||||
return '${pad(value.day)}.${pad(value.month)}.${value.year}';
|
||||
}
|
||||
|
||||
static ApiKeyInfo fromApi(Object? data, {String? fallbackKey}) {
|
||||
if (data is! Map) {
|
||||
final key = data?.toString() ?? fallbackKey;
|
||||
if (key == null || key.isEmpty) {
|
||||
throw const FormatException('api key должен быть объектом или токеном');
|
||||
}
|
||||
return ApiKeyInfo(key: key, name: key, isAdmin: false, isActive: true);
|
||||
}
|
||||
|
||||
final map = Map<String, dynamic>.from(data);
|
||||
final key =
|
||||
_stringValue(map, const ['key', 'token', 'api_key']) ?? fallbackKey;
|
||||
if (key == null || key.isEmpty) {
|
||||
throw const FormatException('api key не содержит токен');
|
||||
}
|
||||
|
||||
return ApiKeyInfo(
|
||||
key: key,
|
||||
name: _stringValue(map, const ['name', 'label']) ?? 'Без имени',
|
||||
isAdmin: _boolValue(map['is_admin']),
|
||||
isActive: _boolValue(map['is_active'] ?? map['active'], fallback: true),
|
||||
createdAt: DateTime.tryParse(map['created_at']?.toString() ?? ''),
|
||||
);
|
||||
}
|
||||
|
||||
static List<ApiKeyInfo> listFromApi(Object? data) {
|
||||
final values = _collectionValues(data, const ['data', 'keys']);
|
||||
return values.map((value) {
|
||||
if (value.entryKey == null) return ApiKeyInfo.fromApi(value.value);
|
||||
return ApiKeyInfo.fromApi(value.value, fallbackKey: value.entryKey);
|
||||
}).toList();
|
||||
}
|
||||
}
|
||||
|
||||
bool _boolValue(Object? value, {bool fallback = false}) {
|
||||
if (value is bool) return value;
|
||||
if (value is num) return value != 0;
|
||||
if (value is String) {
|
||||
final normalized = value.trim().toLowerCase();
|
||||
if (normalized == 'true' || normalized == '1') return true;
|
||||
if (normalized == 'false' || normalized == '0') return false;
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
String? _stringValue(Map<String, dynamic> map, List<String> keys) {
|
||||
for (final key in keys) {
|
||||
final value = map[key];
|
||||
if (value != null && value.toString().isNotEmpty) {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<_CollectionValue> _collectionValues(Object? data, List<String> wrappers) {
|
||||
if (data is List) {
|
||||
return data.map((value) => _CollectionValue(value)).toList();
|
||||
}
|
||||
|
||||
if (data is Map) {
|
||||
final map = Map<String, dynamic>.from(data);
|
||||
for (final wrapper in wrappers) {
|
||||
final value = map[wrapper];
|
||||
if (value is List) {
|
||||
return value.map((item) => _CollectionValue(item)).toList();
|
||||
}
|
||||
}
|
||||
|
||||
return map.entries
|
||||
.map((entry) => _CollectionValue(entry.value, entryKey: entry.key))
|
||||
.toList();
|
||||
}
|
||||
|
||||
throw const FormatException('ожидался список или объект');
|
||||
}
|
||||
|
||||
class _CollectionValue {
|
||||
final Object? value;
|
||||
final String? entryKey;
|
||||
|
||||
const _CollectionValue(this.value, {this.entryKey});
|
||||
}
|
||||
Reference in New Issue
Block a user