Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit deb906e

Browse files
authored
Merge pull request #16 from headlines-toolkit/fix_authentication
Fix authentication
2 parents b7f1a22 + 9e89851 commit deb906e

File tree

5 files changed

+58
-13
lines changed

5 files changed

+58
-13
lines changed

‎lib/src/config/app_dependencies.dart‎

Lines changed: 3 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,9 +195,9 @@ class AppDependencies {
193195
topicRepository: topicRepository,
194196
sourceRepository: sourceRepository,
195197
);
196-
permissionService = const PermissionService();
197198
userPreferenceLimitService = DefaultUserPreferenceLimitService(
198199
remoteConfigRepository: remoteConfigRepository,
200+
permissionService: permissionService,
199201
log: Logger('DefaultUserPreferenceLimitService'),
200202
);
201203

‎lib/src/rbac/permissions.dart‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,11 @@ 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';
60+
61+
// User Preference Permissions
62+
static const String userPreferenceBypassLimits =
63+
'user_preference.bypass_limits';
5764
}

‎lib/src/rbac/role_permissions.dart‎

Lines changed: 2 additions & 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 = {
@@ -50,6 +51,7 @@ final Set<String> _dashboardAdminPermissions = {
5051
Permissions.remoteConfigCreate,
5152
Permissions.remoteConfigUpdate,
5253
Permissions.remoteConfigDelete,
54+
Permissions.userPreferenceBypassLimits,
5355
};
5456

5557
/// Defines the mapping between user roles (both app and dashboard) and the

‎lib/src/services/auth_service.dart‎

Lines changed: 31 additions & 8 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.',
@@ -157,6 +162,24 @@ class AuthService {
157162
final existingUser = await _findUserByEmail(email);
158163
if (existingUser != null) {
159164
user = existingUser;
165+
// If this is a dashboard login, re-verify the user's dashboard role.
166+
// This closes the loophole where a non-admin user could request a code
167+
// via the app flow and then use it to log into the dashboard.
168+
if (isDashboardLogin) {
169+
if (!_permissionService.hasPermission(
170+
user,
171+
Permissions.dashboardLogin,
172+
)) {
173+
_log.warning(
174+
'Dashboard login failed: User ${user.id} lacks required permission '
175+
'during code verification.',
176+
);
177+
throw const ForbiddenException(
178+
'Your account does not have the required permissions to sign in.',
179+
);
180+
}
181+
_log.info('Dashboard user ${user.id} re-verified successfully.');
182+
}
160183
} else {
161184
// User not found.
162185
if (isDashboardLogin) {

‎lib/src/services/default_user_preference_limit_service.dart‎

Lines changed: 15 additions & 4 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/user_preference_limit_service.dart';
24
import 'package:ht_data_repository/ht_data_repository.dart';
35
import 'package:ht_shared/ht_shared.dart';
@@ -11,11 +13,14 @@ class DefaultUserPreferenceLimitService implements UserPreferenceLimitService {
1113
/// {@macro default_user_preference_limit_service}
1214
const DefaultUserPreferenceLimitService({
1315
required HtDataRepository<RemoteConfig> remoteConfigRepository,
16+
required PermissionService permissionService,
1417
required Logger log,
1518
}) : _remoteConfigRepository = remoteConfigRepository,
19+
_permissionService = permissionService,
1620
_log = log;
1721

1822
final HtDataRepository<RemoteConfig> _remoteConfigRepository;
23+
final PermissionService _permissionService;
1924
final Logger _log;
2025

2126
// Assuming a fixed ID for the RemoteConfig document
@@ -34,8 +39,11 @@ class DefaultUserPreferenceLimitService implements UserPreferenceLimitService {
3439
);
3540
final limits = remoteConfig.userPreferenceConfig;
3641

37-
// Admins have no limits.
38-
if (user.dashboardRole == DashboardUserRole.admin) {
42+
// Users with the bypass permission (e.g., admins) have no limits.
43+
if (_permissionService.hasPermission(
44+
user,
45+
Permissions.userPreferenceBypassLimits,
46+
)) {
3947
return;
4048
}
4149

@@ -94,8 +102,11 @@ class DefaultUserPreferenceLimitService implements UserPreferenceLimitService {
94102
);
95103
final limits = remoteConfig.userPreferenceConfig;
96104

97-
// Admins have no limits.
98-
if (user.dashboardRole == DashboardUserRole.admin) {
105+
// Users with the bypass permission (e.g., admins) have no limits.
106+
if (_permissionService.hasPermission(
107+
user,
108+
Permissions.userPreferenceBypassLimits,
109+
)) {
99110
return;
100111
}
101112

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /