igel share
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import 'share.dart';
|
||||
|
||||
class AccessCache {
|
||||
// Map<igelId, AccessRole>
|
||||
final _map = <int, AccessRole>{};
|
||||
void setRole(int igelId, AccessRole role) => _map[igelId] = role;
|
||||
AccessRole getRole(int igelId) => _map[igelId] ?? AccessRole.none;
|
||||
}
|
||||
|
||||
AccessRole roleFromString(String s) {
|
||||
switch (s) {
|
||||
case 'viewer':
|
||||
return AccessRole.viewer;
|
||||
case 'editor':
|
||||
return AccessRole.editor;
|
||||
default:
|
||||
return AccessRole.none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
class Share {
|
||||
final int id;
|
||||
final int hedgehogId;
|
||||
final int ownerUserId;
|
||||
final int? targetUserId;
|
||||
final String? invitedEmail;
|
||||
final String? targetEmail; // bei accepted (vom Backend)
|
||||
final String role; // 'viewer' | 'editor'
|
||||
final String status; // 'pending' | 'accepted' | 'revoked'
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
Share({
|
||||
required this.id,
|
||||
required this.hedgehogId,
|
||||
required this.ownerUserId,
|
||||
this.targetUserId,
|
||||
this.invitedEmail,
|
||||
this.targetEmail,
|
||||
required this.role,
|
||||
required this.status,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory Share.fromJson(Map<String, dynamic> j) => Share(
|
||||
id: j['id'] as int,
|
||||
hedgehogId: j['hedgehog_id'] as int,
|
||||
ownerUserId: j['owner_user_id'] as int,
|
||||
targetUserId: j['target_user_id'] as int?,
|
||||
invitedEmail: j['invited_email'] as String?,
|
||||
targetEmail: j['target_email'] as String?,
|
||||
role: j['role'] as String,
|
||||
status: j['status'] as String,
|
||||
createdAt:
|
||||
j['created_at'] != null ? DateTime.tryParse(j['created_at']) : null,
|
||||
updatedAt:
|
||||
j['updated_at'] != null ? DateTime.tryParse(j['updated_at']) : null,
|
||||
);
|
||||
}
|
||||
|
||||
class SharedIgelItem {
|
||||
final int id; // igel.id
|
||||
final String name;
|
||||
final String role; // viewer|editor
|
||||
final int ownerUserId;
|
||||
final String? ownerEmail; // <— NEU
|
||||
|
||||
SharedIgelItem({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.role,
|
||||
required this.ownerUserId,
|
||||
this.ownerEmail, // <— NEU
|
||||
});
|
||||
|
||||
factory SharedIgelItem.fromJson(Map<String, dynamic> j) => SharedIgelItem(
|
||||
id: j['id'] as int,
|
||||
name: j['name'] as String,
|
||||
role: j['role'] as String,
|
||||
ownerUserId: j['owner_user_id'] as int,
|
||||
ownerEmail: j['owner_email'] as String?, // <— NEU
|
||||
);
|
||||
}
|
||||
|
||||
enum AccessRole { owner, editor, viewer, none }
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'share.dart';
|
||||
|
||||
class ShareService {
|
||||
ShareService({http.Client? client, required this.baseUrl})
|
||||
: _client = client ?? http.Client();
|
||||
final http.Client _client;
|
||||
final String baseUrl; // z.B. https://api.windesign.at
|
||||
|
||||
Map<String, String> _auth(String token, {Map<String, String>? extra}) =>
|
||||
{'Authorization': 'Bearer $token', if (extra != null) ...extra};
|
||||
|
||||
Future<List<Share>> listShares(
|
||||
{required int igelId, required String token}) async {
|
||||
final r = await _client.get(
|
||||
Uri.parse('$baseUrl/hedgehogs.php?r=/igel/$igelId/shares'),
|
||||
headers: _auth(token),
|
||||
);
|
||||
if (r.statusCode != 200)
|
||||
throw Exception('listShares failed (${r.statusCode}) ${r.body}');
|
||||
final List data = jsonDecode(r.body) as List;
|
||||
return data.map((e) => Share.fromJson(e as Map<String, dynamic>)).toList();
|
||||
}
|
||||
|
||||
Future<void> invite(
|
||||
{required int igelId,
|
||||
required String email,
|
||||
required String role,
|
||||
required String token}) async {
|
||||
final r = await _client.post(
|
||||
Uri.parse('$baseUrl/hedgehogs.php?r=/igel/$igelId/shares'),
|
||||
headers: _auth(token, extra: {'Content-Type': 'application/json'}),
|
||||
body: jsonEncode({'email': email, 'role': role}),
|
||||
);
|
||||
if (r.statusCode != 201)
|
||||
throw Exception('invite failed (${r.statusCode}) ${r.body}');
|
||||
}
|
||||
|
||||
Future<void> updateRole(
|
||||
{required int shareId,
|
||||
required String role,
|
||||
required String token}) async {
|
||||
final r = await _client.patch(
|
||||
Uri.parse('$baseUrl/hedgehogs.php?r=/shares/$shareId'),
|
||||
headers: _auth(token, extra: {'Content-Type': 'application/json'}),
|
||||
body: jsonEncode({'role': role}),
|
||||
);
|
||||
if (r.statusCode != 200)
|
||||
throw Exception('updateRole failed (${r.statusCode}) ${r.body}');
|
||||
}
|
||||
|
||||
Future<void> revoke({required int shareId, required String token}) async {
|
||||
final r = await _client.delete(
|
||||
Uri.parse('$baseUrl/hedgehogs.php?r=/shares/$shareId'),
|
||||
headers: _auth(token),
|
||||
);
|
||||
if (r.statusCode != 200)
|
||||
throw Exception('revoke failed (${r.statusCode}) ${r.body}');
|
||||
}
|
||||
|
||||
Future<void> acceptInvite(
|
||||
{required String tokenJwt, required String inviteToken}) async {
|
||||
final r = await _client.post(
|
||||
Uri.parse('$baseUrl/hedgehogs.php?r=/invites/accept'),
|
||||
headers: _auth(tokenJwt, extra: {'Content-Type': 'application/json'}),
|
||||
body: jsonEncode({'token': inviteToken}),
|
||||
);
|
||||
if (r.statusCode != 200)
|
||||
throw Exception('acceptInvite failed (${r.statusCode}) ${r.body}');
|
||||
}
|
||||
|
||||
Future<List<SharedIgelItem>> listSharedWithMe({required String token}) async {
|
||||
final r = await _client.get(
|
||||
Uri.parse('$baseUrl/hedgehogs.php?r=/me/shared'),
|
||||
headers: _auth(token),
|
||||
);
|
||||
if (r.statusCode != 200)
|
||||
throw Exception('listSharedWithMe failed (${r.statusCode}) ${r.body}');
|
||||
final List data = jsonDecode(r.body) as List;
|
||||
return data
|
||||
.map((e) => SharedIgelItem.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user