18946: Transitional user profile feature
authorPeter Amstutz <peter.amstutz@curii.com>
Fri, 21 Jul 2023 17:07:14 +0000 (13:07 -0400)
committerPeter Amstutz <peter.amstutz@curii.com>
Fri, 21 Jul 2023 17:07:14 +0000 (13:07 -0400)
If UserProfileFormFields is non-empty, and the user's prefs.profile is
empty, wb2 will navigate to the user account page to encourage people
to fill out the profile.  Unlike wb1, filling it out is not mandatory.

Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <peter.amstutz@curii.com>

src/common/config.ts
src/services/common-service/common-resource-service.ts
src/store/auth/auth-middleware.ts

index fd8b75ce72bbcf34818875765645759876ea9827..c1d565482116a6c749ec6ca0f33e4770251d0d79 100644 (file)
@@ -76,6 +76,7 @@ export interface ClusterConfigJSON {
         SiteName: string;
         IdleTimeout: string;
         BannerUUID: string;
+        UserProfileFormFields: {};
     };
     Login: {
         LoginCluster: string;
@@ -305,7 +306,8 @@ export const mockClusterConfigJSON = (
         SSHHelpHostSuffix: '',
         SiteName: '',
         IdleTimeout: '0s',
-        BannerUUID: ""
+        BannerUUID: "",
+        UserProfileFormFields: {}
     },
     Login: {
         LoginCluster: '',
index 624525e6aecc7d70674d1e541fb072a9584c76e5..907f0081fdf6053fd983f073cefeb7eadbc77134 100644 (file)
@@ -24,14 +24,20 @@ export class CommonResourceService<T extends Resource> extends CommonService<T>
         super(serverApi, resourceType, actions, readOnlyFields.concat([
             'uuid',
             'etag',
-            'kind'
+            'kind',
+            'canWrite',
+            'canManage',
+            'createdAt',
+            'modifiedAt',
+            'modifiedByClientUuid',
+            'modifiedByUserUuid'
         ]));
     }
 
     create(data?: Partial<T>, showErrors?: boolean) {
         let payload: any;
         if (data !== undefined) {
-            this.readOnlyFields.forEach( field => delete data[field] );
+            this.readOnlyFields.forEach(field => delete data[field]);
             payload = {
                 [this.resourceType.slice(0, -1)]: CommonService.mapKeys(snakeCase)(data),
             };
@@ -42,7 +48,7 @@ export class CommonResourceService<T extends Resource> extends CommonService<T>
     update(uuid: string, data: Partial<T>, showErrors?: boolean, select?: string[]) {
         let payload: any;
         if (data !== undefined) {
-            this.readOnlyFields.forEach( field => delete data[field] );
+            this.readOnlyFields.forEach(field => delete data[field]);
             payload = {
                 [this.resourceType.slice(0, -1)]: CommonService.mapKeys(snakeCase)(data),
             };
index 0d08405ae11e87f329553e236e4550c0720a6fd6..1658431302278d4e3ebea9bdb4b35cddfb34f8e6 100644 (file)
@@ -10,6 +10,7 @@ import { User } from "models/user";
 import { RootState } from 'store/store';
 import { progressIndicatorActions } from "store/progress-indicator/progress-indicator-actions";
 import { WORKBENCH_LOADING_SCREEN } from 'store/workbench/workbench-actions';
+import { navigateToMyAccount } from 'store/navigation/navigation-action';
 
 export const authMiddleware = (services: ServiceRepository): Middleware => store => next => action => {
     // Middleware to update external state (local storage, window
@@ -35,6 +36,15 @@ export const authMiddleware = (services: ServiceRepository): Middleware => store
             }
 
             store.dispatch<any>(initSessions(services.authService, state.auth.remoteHostsConfig[state.auth.localCluster], user));
+            if (Object.keys(state.auth.config.clusterConfig.Workbench.UserProfileFormFields).length > 0 &&
+                user.isActive &&
+                (Object.keys(user.prefs).length === 0 ||
+                    user.prefs.profile === undefined ||
+                    Object.keys(user.prefs.profile!).length === 0)) {
+                // If the user doesn't have a profile set, send them
+                // to the user profile page to encourage them to fill it out.
+                store.dispatch(navigateToMyAccount);
+            }
             if (!user.isActive) {
                 // As a special case, if the user is inactive, they
                 // may be able to self-activate using the "activate"