@@ -69,24 +69,113 @@ function asu_rest_provision_oauth_consumer(): void {
6969 }
7070
7171 $storage = \Drupal::entityTypeManager()->getStorage('consumer');
72- $existing = $storage->getQuery()
72+ $existing_ids = $storage->getQuery()
7373 ->accessCheck(FALSE)
7474 ->condition('client_id', $client_id)
7575 ->range(0, 1)
7676 ->execute();
77- if ($existing) {
77+ if ($existing_ids) {
78+ // Ensure default user exists and is assigned, even if consumer already
79+ // exists (common when secrets are added after initial install).
80+ $role_storage = \Drupal::entityTypeManager()->getStorage('user_role');
81+ if (!$role_storage->load('rest_client')) {
82+ \Drupal::logger('asu_rest')->error(
83+ 'User role rest_client is missing; cannot provision OAuth REST client user for consumer @id.',
84+ ['@id' => $client_id],
85+ );
86+ return;
87+ }
88+ $username_env = getenv('ASU_REST_OAUTH_DEFAULT_USERNAME');
89+ $username = is_string($username_env) && trim($username_env) !== '' ? trim($username_env) : 'rest_client';
90+ $user_storage = \Drupal::entityTypeManager()->getStorage('user');
91+ $users = $user_storage->loadByProperties(['name' => $username]);
92+ /** @var \Drupal\user\Entity\User|null $user */
93+ $user = $users ? reset($users) : NULL;
94+ if (!$user) {
95+ $password = bin2hex(random_bytes(16));
96+ $user = $user_storage->create([
97+ 'name' => $username,
98+ 'status' => 1,
99+ 'roles' => ['rest_client'],
100+ 'pass' => $password,
101+ ]);
102+ $user->save();
103+ }
104+ else {
105+ if (!$user->isActive()) {
106+ $user->activate();
107+ }
108+ if (!in_array('rest_client', $user->getRoles(), TRUE)) {
109+ $user->addRole('rest_client');
110+ }
111+ $user->save();
112+ }
113+
114+ /** @var \Drupal\consumers\Entity\Consumer|null $existing_consumer */
115+ $existing_consumer = $storage->load(reset($existing_ids));
116+ if ($existing_consumer && $existing_consumer->get('user_id')->isEmpty()) {
117+ $existing_consumer->set('user_id', (int) $user->id())->save();
118+ \Drupal::logger('asu_rest')->notice(
119+ 'Updated OAuth consumer @id default user to uid @uid.',
120+ ['@id' => $client_id, '@uid' => $user->id()],
121+ );
122+ }
78123 return;
79124 }
80125
81- $scope_storage = \Drupal::entityTypeManager()->getStorage('oauth2_scope');
82- if (!$scope_storage->load('rest_client')) {
126+ $entity_type_manager = \Drupal::entityTypeManager();
127+ // Some environments provide scopes as config entities (oauth2_scope). If the
128+ // entity type exists, ensure the expected scope is present.
129+ if ($entity_type_manager->hasDefinition('oauth2_scope')) {
130+ $scope_storage = $entity_type_manager->getStorage('oauth2_scope');
131+ if (!$scope_storage->load('rest_client')) {
132+ \Drupal::logger('asu_rest')->error(
133+ 'OAuth scope rest_client is missing; cannot create consumer @id.',
134+ ['@id' => $client_id],
135+ );
136+ return;
137+ }
138+ }
139+
140+ $role_storage = \Drupal::entityTypeManager()->getStorage('user_role');
141+ if (!$role_storage->load('rest_client')) {
83142 \Drupal::logger('asu_rest')->error(
84- 'OAuth scope rest_client is missing; cannot create consumer @id.',
143+ 'User role rest_client is missing; cannot provision OAuth REST client user for consumer @id.',
85144 ['@id' => $client_id],
86145 );
87146 return;
88147 }
89148
149+ $username_env = getenv('ASU_REST_OAUTH_DEFAULT_USERNAME');
150+ $username = is_string($username_env) && trim($username_env) !== '' ? trim($username_env) : 'rest_client';
151+ $user_storage = \Drupal::entityTypeManager()->getStorage('user');
152+ $users = $user_storage->loadByProperties(['name' => $username]);
153+ /** @var \Drupal\user\Entity\User|null $user */
154+ $user = $users ? reset($users) : NULL;
155+ if (!$user) {
156+ $password = bin2hex(random_bytes(16));
157+ $user = $user_storage->create([
158+ 'name' => $username,
159+ 'status' => 1,
160+ 'roles' => ['rest_client'],
161+ 'pass' => $password,
162+ ]);
163+ $user->save();
164+ \Drupal::logger('asu_rest')->notice(
165+ 'Created OAuth REST client user @name (uid @uid) for consumer @id.',
166+ ['@name' => $username, '@uid' => $user->id(), '@id' => $client_id],
167+ );
168+ }
169+ else {
170+ if (!$user->isActive()) {
171+ $user->activate();
172+ }
173+ if (!in_array('rest_client', $user->getRoles(), TRUE)) {
174+ $user->addRole('rest_client');
175+ }
176+ $user->save();
177+ }
178+
90179 $label = $oauth['label'] ?? 'Apartment application service';
91180 $label = is_string($label) && $label !== '' ? $label : 'Apartment application service';
92181
@@ -96,6 +185,7 @@ function asu_rest_provision_oauth_consumer(): void {
96185 'description' => 'Machine client for Elasticsearch-compatible REST endpoints (projects, apartments).',
97186 'grant_types' => ['client_credentials'],
98187 'scopes' => ['rest_client'],
188+ 'user_id' => (int) $user->id(),
99189 'confidential' => TRUE,
100190 'secret' => $secret,
101191 'redirect' => ['https://127.0.0.1/oauth2-callback-not-used'],
0 commit comments