Skip to content

Commit 384267d

Browse files
committed
feat(auth): implement permission-based dashboard login
- Added PermissionService to AuthService - Created dashboard login permission - Updated login logic to use PermissionService - Improved logging for permission checks - Refactored role-based checks to permission checks
1 parent aefe69e commit 384267d

File tree

4 files changed

+24
-15
lines changed

4 files changed

+24
-15
lines changed

lib/src/config/app_dependencies.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,12 @@ class AppDependencies {
178178
);
179179
verificationCodeStorageService =
180180
InMemoryVerificationCodeStorageService();
181+
permissionService = const PermissionService();
181182
authService = AuthService(
182183
userRepository: userRepository,
183184
authTokenService: authTokenService,
184185
verificationCodeStorageService: verificationCodeStorageService,
186+
permissionService: permissionService,
185187
emailRepository: emailRepository,
186188
userAppSettingsRepository: userAppSettingsRepository,
187189
userContentPreferencesRepository: userContentPreferencesRepository,
@@ -193,7 +195,6 @@ class AppDependencies {
193195
topicRepository: topicRepository,
194196
sourceRepository: sourceRepository,
195197
);
196-
permissionService = const PermissionService();
197198
userPreferenceLimitService = DefaultUserPreferenceLimitService(
198199
remoteConfigRepository: remoteConfigRepository,
199200
log: Logger('DefaultUserPreferenceLimitService'),

lib/src/rbac/permissions.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,7 @@ abstract class Permissions {
5454
static const String remoteConfigRead = 'remote_config.read';
5555
static const String remoteConfigUpdate = 'remote_config.update';
5656
static const String remoteConfigDelete = 'remote_config.delete';
57+
58+
// Dashboard Permissions
59+
static const String dashboardLogin = 'dashboard.login';
5760
}

lib/src/rbac/role_permissions.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final Set<String> _dashboardPublisherPermissions = {
3333
Permissions.headlineCreate,
3434
Permissions.headlineUpdate,
3535
Permissions.headlineDelete,
36+
Permissions.dashboardLogin,
3637
};
3738

3839
final Set<String> _dashboardAdminPermissions = {

lib/src/services/auth_service.dart

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'package:ht_api/src/rbac/permission_service.dart';
2+
import 'package:ht_api/src/rbac/permissions.dart';
13
import 'package:ht_api/src/services/auth_token_service.dart';
24
import 'package:ht_api/src/services/verification_code_storage_service.dart';
35
import 'package:ht_data_repository/ht_data_repository.dart';
@@ -21,12 +23,14 @@ class AuthService {
2123
required HtEmailRepository emailRepository,
2224
required HtDataRepository<UserAppSettings> userAppSettingsRepository,
2325
required HtDataRepository<UserContentPreferences>
24-
userContentPreferencesRepository,
26+
userContentPreferencesRepository,
27+
required PermissionService permissionService,
2528
required Uuid uuidGenerator,
2629
required Logger log,
2730
}) : _userRepository = userRepository,
2831
_authTokenService = authTokenService,
2932
_verificationCodeStorageService = verificationCodeStorageService,
33+
_permissionService = permissionService,
3034
_emailRepository = emailRepository,
3135
_userAppSettingsRepository = userAppSettingsRepository,
3236
_userContentPreferencesRepository = userContentPreferencesRepository,
@@ -39,7 +43,8 @@ class AuthService {
3943
final HtEmailRepository _emailRepository;
4044
final HtDataRepository<UserAppSettings> _userAppSettingsRepository;
4145
final HtDataRepository<UserContentPreferences>
42-
_userContentPreferencesRepository;
46+
_userContentPreferencesRepository;
47+
final PermissionService _permissionService;
4348
final Logger _log;
4449
final Uuid _uuid;
4550

@@ -77,13 +82,13 @@ class AuthService {
7782
);
7883
}
7984

80-
final hasRequiredRole =
81-
user.dashboardRole == DashboardUserRole.admin ||
82-
user.dashboardRole == DashboardUserRole.publisher;
83-
84-
if (!hasRequiredRole) {
85+
// Use the PermissionService to check for the specific dashboard login permission.
86+
if (!_permissionService.hasPermission(
87+
user,
88+
Permissions.dashboardLogin,
89+
)) {
8590
_log.warning(
86-
'Dashboard login failed: User ${user.id} lacks required roles.',
91+
'Dashboard login failed: User ${user.id} lacks required permission (${Permissions.dashboardLogin}).',
8792
);
8893
throw const ForbiddenException(
8994
'Your account does not have the required permissions to sign in.',
@@ -161,13 +166,12 @@ class AuthService {
161166
// This closes the loophole where a non-admin user could request a code
162167
// via the app flow and then use it to log into the dashboard.
163168
if (isDashboardLogin) {
164-
final hasRequiredRole =
165-
user.dashboardRole == DashboardUserRole.admin ||
166-
user.dashboardRole == DashboardUserRole.publisher;
167-
168-
if (!hasRequiredRole) {
169+
if (!_permissionService.hasPermission(
170+
user,
171+
Permissions.dashboardLogin,
172+
)) {
169173
_log.warning(
170-
'Dashboard login failed: User ${user.id} lacks required roles '
174+
'Dashboard login failed: User ${user.id} lacks required permission '
171175
'during code verification.',
172176
);
173177
throw const ForbiddenException(

0 commit comments

Comments
 (0)