From e3ca4fafa672e126a12074f704a8ddf8d59c857a Mon Sep 17 00:00:00 2001 From: Jakob Meier Date: Sat, 25 Mar 2023 10:27:21 +0100 Subject: [PATCH] Added room default permission editor screen The screen allows the user to change the default permission set, that applies to every member (but not the owner nor the admins). This screen is only accessible by the owner, admins or members with the changeAdmin permission. --- lib/backend/permissions.dart | 54 ++++++++++++++ lib/main.dart | 6 ++ lib/screens/room/pages/about.dart | 25 ++++++- lib/screens/room/permissions.dart | 115 ++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 lib/screens/room/permissions.dart diff --git a/lib/backend/permissions.dart b/lib/backend/permissions.dart index 14ddbc1..61ddaf9 100644 --- a/lib/backend/permissions.dart +++ b/lib/backend/permissions.dart @@ -87,4 +87,58 @@ class RoomPermission { static int get manageMembers { return oB("1000000"); } + + static List get asList { + return [ + addArticles, + removeArticles, + listGroupsItems, + changeMeta, + ota, + changeAdmin, + manageMembers + ]; + } + + static String name(int permission) { + switch (permission) { + case 1: + return 'Add Articles'; + case 2: + return 'Remove Articles'; + case 4: + return 'List Groups and Items'; + case 8: + return 'Change Room Metadata'; + case 16: + return 'Manage OTAs'; + case 32: + return 'Manage Admins'; + case 64: + return 'Manage Members'; + } + + return "Unknown permission"; + } + + static String describe(int permission) { + switch (permission) { + case 1: + return 'Allows users to add items to the shopping list'; + case 2: + return 'Allows users to remove items from the shopping list'; + case 4: + return 'Allows the user to view groups and products'; + case 8: + return 'Allows the user to edit the room name, description and icon'; + case 16: + return 'Alloww the user to create, share and delete authentification tokens'; + case 32: + return 'Allows the user to change the admin status of other members'; + case 64: + return 'Allows the user to invite and kick room members'; + } + + return "No description available"; + } } diff --git a/lib/main.dart b/lib/main.dart index 80457b7..0e76edf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/screens/room/edit.dart'; import 'package:outbag_app/screens/room/join.dart'; import 'package:outbag_app/screens/room/members.dart'; +import 'package:outbag_app/screens/room/permissions.dart'; import 'package:outbag_app/screens/room/new.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:provider/provider.dart'; @@ -45,7 +46,12 @@ final routesLoggedIn = RouteMap(routes: { return MaterialPage(child: ManageRoomMembersPage(server, tag)); }, + '/r/:server/:tag/permissions': (info) { + final server = info.pathParameters['server'] ?? ""; + final tag = info.pathParameters['tag'] ?? ""; + return MaterialPage(child: EditRoomPermissionSetPage(server, tag)); + }, }, onUnknownRoute: (_) => const Redirect('/')); void main() { diff --git a/lib/screens/room/pages/about.dart b/lib/screens/room/pages/about.dart index ef319b2..4e48dd5 100644 --- a/lib/screens/room/pages/about.dart +++ b/lib/screens/room/pages/about.dart @@ -52,7 +52,9 @@ class _AboutRoomPageState extends State { style: textTheme.bodySmall, ), Text(widget.room?.description ?? '', - style: textTheme.bodyMedium), + style: textTheme.bodyMedium, + textAlign: TextAlign.center, + ), Padding( padding: const EdgeInsets.all(8), child: SegmentedButton( @@ -175,6 +177,27 @@ class _AboutRoomPageState extends State { '/r/${widget.room?.serverTag}/${widget.room?.id}/members'); }, ), + // edit default member permission + ...(widget.info != null && + ((widget.info?.isAdmin ?? false) || + (widget.info?.isOwner ?? false) || + ((widget.info?.permissions)! & + RoomPermission.changeAdmin != + 0))) + ? [ + ListTile( + trailing: const Icon(Icons.chevron_right), + title: const Text('Edit Permissions'), + subtitle: const Text( + 'Change the default permission-set for all members'), + onTap: () { + // show checkbox screen + Routemaster.of(context).push( + '/r/${widget.room?.serverTag}/${widget.room?.id}/permissions'); + }, + ), + ] + : [], ...(widget.info != null && ((widget.info?.isAdmin ?? false) || (widget.info?.isOwner ?? false) || diff --git a/lib/screens/room/permissions.dart b/lib/screens/room/permissions.dart new file mode 100644 index 0000000..8e925a1 --- /dev/null +++ b/lib/screens/room/permissions.dart @@ -0,0 +1,115 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:outbag_app/backend/permissions.dart'; +import 'package:outbag_app/backend/request.dart'; +import 'package:outbag_app/backend/room.dart'; +import 'package:outbag_app/tools/fetch_wrapper.dart'; +import 'package:routemaster/routemaster.dart'; + +class EditRoomPermissionSetPage extends StatefulWidget { + final String server; + final String tag; + + const EditRoomPermissionSetPage(this.server, this.tag, {super.key}); + + @override + State createState() => _EditRoomPermissionSetPageState(); +} + +class _EditRoomPermissionSetPageState extends State { + List items = RoomPermission.asList; + int permissions = 0; + + void fetchInfo() { + final rmaster = Routemaster.of(context); + final sm = ScaffoldMessenger.of(context); + + doNetworkRequest( + sm, + req: (user) => postWithCreadentials( + path: 'getRoomInfo', + credentials: user!, + target: (user.server), + body: {'room': widget.tag, 'server': widget.server}), + onAnyErr: () { + // user should not be here + // close screen + rmaster.replace('/'); + return false; + }, + onOK: (body) async { + final info = RoomInfo.fromJSON(body['data']); + setState(() { + permissions = info.permissions; + }); + return true; + }, + ); + } + + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) => fetchInfo()); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Default permissions'), + leading: IconButton( + onPressed: () { + // go back + Navigator.of(context).pop(); + }, + icon: const Icon(Icons.arrow_back), + tooltip: "Go back", + ), + ), + body: ListView.builder( + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + + final int col = pow(2, index + 1) as int; + + return SwitchListTile( + title: Text(RoomPermission.name(item)), + subtitle: Text(RoomPermission.describe(item)), + onChanged: (state) { + setState(() { + permissions += (state ? 1 : -1) * col; + }); + }, + value: permissions & col != 0); + }, + ), + floatingActionButton: FloatingActionButton.extended( + icon: const Icon(Icons.edit), + tooltip: "Update default permission set", + label: const Text('Edit'), + onPressed: () { + final rmaster = Routemaster.of(context); + final sm = ScaffoldMessenger.of(context); + // update permissions + doNetworkRequest(sm, + req: (user) => postWithCreadentials( + path: 'setRoomRight', + credentials: user!, + target: user.server, + body: { + 'room': widget.tag, + 'server': widget.server, + 'rights': permissions + }), + onOK: (_) { + rmaster.pop(); + }); + }, + ), + ); + } +}