Added server dashboard button to menu

The button is only shown if the user has
any of the management permissions.
This commit is contained in:
Jakob Meier 2023-03-23 10:51:34 +01:00
parent 5c8c108818
commit aee9c9f82e
No known key found for this signature in database
GPG key ID: 66BDC7E6A01A6152
6 changed files with 141 additions and 63 deletions

View file

@ -12,34 +12,48 @@ class ServerPermission {
static int get none { static int get none {
return oB("0000000000000000"); return oB("0000000000000000");
} }
// default permission set // default permission set
static int get def { static int get def {
return oB("0000000000000011"); return oB("0000000000000011");
} }
static int get canUseAPI { static int get canUseAPI {
return oB("0000000000000001"); return oB("0000000000000001");
} }
static int get provideCert { static int get provideCert {
return oB("0000000000000010"); return oB("0000000000000010");
} }
static int get manageOTA { static int get manageOTA {
return oB("0000010000000000"); return oB("0000010000000000");
} }
static int get manageServerProductList { static int get manageServerProductList {
return oB("0000100000000000"); return oB("0000100000000000");
} }
static int get viewUsersAndLists { static int get viewUsersAndLists {
return oB("0001000000000000"); return oB("0001000000000000");
} }
static int get editSettings { static int get editSettings {
return oB("0010000000000000"); return oB("0010000000000000");
} }
static int get editPermissions { static int get editPermissions {
return oB("0100000000000000"); return oB("0100000000000000");
} }
static int get editUsers { static int get editUsers {
return oB("1000000000000000"); return oB("1000000000000000");
} }
static int get allManagement {
return oB("1111110000000000");
}
static int get all { static int get all {
return oB("1111111111111111"); return oB("1111111111111111");
} }

View file

@ -36,3 +36,31 @@ class User {
stream.listen(cb); stream.listen(cb);
} }
} }
class AccountMeta {
final int permissions;
final String username;
final bool discvoverable;
final int maxRoomCount;
final int maxRoomSize;
final int maxRoomMemberCount;
const AccountMeta(
{required this.permissions,
required this.username,
required this.maxRoomSize,
required this.maxRoomCount,
required this.maxRoomMemberCount,
required this.discvoverable});
factory AccountMeta.fromJSON(dynamic json) {
return AccountMeta(
permissions: json['rights'],
username: json['name'],
maxRoomSize: json['maxRoomSize'],
maxRoomCount: json['maxRooms'],
maxRoomMemberCount: json['maxUsersPerRoom'],
discvoverable: json['viewable'] == 1
);
}
}

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:outbag_app/screens/room/join.dart'; import 'package:outbag_app/screens/room/join.dart';
import 'package:outbag_app/screens/room/new.dart'; import 'package:outbag_app/screens/room/new.dart';
import 'package:provider/provider.dart';
import './screens/home.dart'; import './screens/home.dart';
import './screens/welcome.dart'; import './screens/welcome.dart';
import './screens/room/main.dart'; import './screens/room/main.dart';
@ -11,25 +12,25 @@ import 'package:routemaster/routemaster.dart';
// routes when user is not logged in // routes when user is not logged in
final routesUnauthorized = RouteMap(routes: { final routesUnauthorized = RouteMap(routes: {
'/welcome/': (_) => const MaterialPage(child: WelcomePage()), '/welcome/': (_) => const MaterialPage(child: WelcomePage()),
'/signup': (_) => const MaterialPage(child: AuthPage(mode: Mode.signup)), '/signup': (_) => const MaterialPage(child: AuthPage(mode: Mode.signup)),
'/signupOTA': (_) => '/signupOTA': (_) =>
const MaterialPage(child: AuthPage(mode: Mode.signupOTA)), const MaterialPage(child: AuthPage(mode: Mode.signupOTA)),
'/signin': (_) => const MaterialPage(child: AuthPage(mode: Mode.signin)), '/signin': (_) => const MaterialPage(child: AuthPage(mode: Mode.signin)),
}, onUnknownRoute: (_) => const MaterialPage(child: WelcomePage())); }, onUnknownRoute: (_) => const MaterialPage(child: WelcomePage()));
// routes when user is logged in // routes when user is logged in
final routesLoggedIn = RouteMap(routes: { final routesLoggedIn = RouteMap(routes: {
'/': (_) => const MaterialPage(child: HomePage()), '/': (_) => const MaterialPage(child: HomePage()),
'/add-room/new': (_) => const MaterialPage(child: NewRoomPage()), '/add-room/new': (_) => const MaterialPage(child: NewRoomPage()),
'/add-room': (_) => const MaterialPage(child: JoinRoomPage()), '/add-room': (_) => const MaterialPage(child: JoinRoomPage()),
'/r/:server/:tag/': (info) { '/r/:server/:tag/': (info) {
final server = info.pathParameters['server'] ?? ""; final server = info.pathParameters['server'] ?? "";
final tag = info.pathParameters['tag'] ?? ""; final tag = info.pathParameters['tag'] ?? "";
return MaterialPage(child: RoomPage(server, tag)); return MaterialPage(child: RoomPage(server, tag));
}, },
}, onUnknownRoute: (_) => const Redirect('/')); }, onUnknownRoute: (_) => const Redirect('/'));
void main() { void main() {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@ -48,6 +49,7 @@ class _OutbagAppState extends State {
// unless not userdata is found // unless not userdata is found
// or the userdata turns out to be wrong // or the userdata turns out to be wrong
bool isAuthorized = true; bool isAuthorized = true;
AccountMeta? info;
@override @override
void initState() { void initState() {
@ -57,70 +59,75 @@ class _OutbagAppState extends State {
// with existing details // with existing details
// NOTE: also functions as a way to verify ther data // NOTE: also functions as a way to verify ther data
(() async { (() async {
User credentials; User credentials;
try { try {
credentials = await User.fromDisk(); credentials = await User.fromDisk();
} catch (_) { } catch (_) {
// invalid credentials // invalid credentials
// log out // log out
setState(() { setState(() {
isAuthorized = false; isAuthorized = false;
}); });
return; return;
} }
try { try {
final resp = await postWithCreadentials( final resp = await postWithCreadentials(
target: credentials.server, target: credentials.server,
path: 'getMyAccount', path: 'getMyAccount',
credentials: credentials, credentials: credentials,
body: {}); body: {});
if (resp.res == Result.ok) { if (resp.res == Result.ok) {
print(resp.body); final info = AccountMeta.fromJSON(resp.body['data']);
setState(() {
isAuthorized = true;
this.info = info;
});
} else {
// credentials are wrong
// log out
setState(() {
isAuthorized = false;
});
}
} catch (_) {
// user is currently offline
// approve login,
// until user goes back offline
// NOTE TODO: check user data once online
setState(() { setState(() {
isAuthorized = true; isAuthorized = true;
});
} else {
// credentials are wrong
// log out
setState(() {
isAuthorized = true;
}); });
} }
} catch (_) {
// user is currently offline
// approve login,
// until user goes back offline
// NOTE TODO: check user data once online
setState(() {
isAuthorized = true;
});
}
})(); })();
// wait for user to be authorized // wait for user to be authorized
User.listen((data) async { User.listen((data) async {
try { try {
await User.fromDisk(); await User.fromDisk();
setState(() { setState(() {
isAuthorized = true; isAuthorized = true;
}); });
} catch (_) {} } catch (_) {}
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp.router( return MultiProvider(
title: "Outbag", providers: [
// TODO: change back to system (or load from disk) Provider<AccountMeta?>.value(value: info,),
//themeMode: ThemeMode.system, ],
themeMode: ThemeMode.dark, child: MaterialApp.router(
theme: ThemeData(useMaterial3: true, brightness: Brightness.light), title: "Outbag",
darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark), // TODO: change back to system (or load from disk)
routerDelegate: RoutemasterDelegate( //themeMode: ThemeMode.system,
themeMode: ThemeMode.dark,
theme: ThemeData(useMaterial3: true, brightness: Brightness.light),
darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark),
routerDelegate: RoutemasterDelegate(
routesBuilder: (context) => routesBuilder: (context) =>
isAuthorized ? routesLoggedIn : routesUnauthorized), isAuthorized ? routesLoggedIn : routesUnauthorized),
routeInformationParser: const RoutemasterParser(), routeInformationParser: const RoutemasterParser(),
); ));
} }
} }

View file

@ -2,8 +2,10 @@ import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:outbag_app/backend/permissions.dart';
import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/request.dart';
import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/backend/user.dart';
import 'package:provider/provider.dart';
import 'package:routemaster/routemaster.dart'; import 'package:routemaster/routemaster.dart';
import '../backend/room.dart'; import '../backend/room.dart';
@ -103,6 +105,16 @@ class _HomePageState extends State<HomePage> {
// show settings screen // show settings screen
Routemaster.of(context).push("/settings"); Routemaster.of(context).push("/settings");
}), }),
...(context.watch<AccountMeta?>() != null &&
(context.watch<AccountMeta?>()?.permissions)! & ServerPermission.allManagement != 0)?[
MenuItemButton(
leadingIcon: const Icon(Icons.dns),
child: const Text('Server Dashboard'),
onPressed: () {
// show settings screen
Routemaster.of(context).push("/server");
}),
]:[],
MenuItemButton( MenuItemButton(
leadingIcon: const Icon(Icons.info_rounded), leadingIcon: const Icon(Icons.info_rounded),
child: const Text('About'), child: const Text('About'),

View file

@ -184,6 +184,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.0" version: "1.8.0"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
path: path:
dependency: transitive dependency: transitive
description: description:
@ -280,6 +288,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.4" version: "4.2.4"
provider:
dependency: "direct main"
description:
name: provider
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev"
source: hosted
version: "6.0.5"
routemaster: routemaster:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -40,6 +40,7 @@ dependencies:
http: ^0.13.5 http: ^0.13.5
localstore: ^1.3.5 localstore: ^1.3.5
crypto: ^3.0.2 crypto: ^3.0.2
provider: ^6.0.5
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: