Added passing root owner uuid for top level projects
authorDaniel Kos <daniel.kos@contractors.roche.com>
Wed, 13 Jun 2018 21:53:01 +0000 (23:53 +0200)
committerDaniel Kos <daniel.kos@contractors.roche.com>
Wed, 13 Jun 2018 21:53:01 +0000 (23:53 +0200)
Feature #13622

Arvados-DCO-1.1-Signed-off-by: Daniel Kos <daniel.kos@contractors.roche.com>

src/common/api/filter-builder.ts
src/components/api-token/api-token.tsx
src/index.tsx
src/models/user.ts
src/services/auth-service/auth-service.ts
src/services/project-service/project-service.ts
src/store/auth/auth-reducer.test.ts
src/store/auth/auth-reducer.ts

index 3f8e323c40f212f387fe7fcece7b78d0e6cc5e87..443c763913635c066ffb3f5426e424f997d68a09 100644 (file)
@@ -10,9 +10,9 @@ export enum FilterField {
 export default class FilterBuilder {
     private filters = "";
 
-    private addCondition(field: FilterField, cond: string, value?: string) {
+    private addCondition(field: FilterField, cond: string, value?: string, prefix: string = "", postfix: string = "") {
         if (value) {
-            this.filters += `["${field}","${cond}","${value}"]`;
+            this.filters += `["${field}","${cond}","${prefix}${value}${postfix}"]`;
         }
         return this;
     }
@@ -22,11 +22,11 @@ export default class FilterBuilder {
     }
 
     public addLike(field: FilterField, value?: string) {
-        return this.addCondition(field, "like", value);
+        return this.addCondition(field, "like", value, "", "%");
     }
 
     public addILike(field: FilterField, value?: string) {
-        return this.addCondition(field, "ilike", value);
+        return this.addCondition(field, "ilike", value, "", "%");
     }
 
     public get() {
index 87da39b025e9706c05ebdade6e600f936fae1a89..d63f6e07336d6ee4d9d788c556a92c4737497c08 100644 (file)
@@ -23,8 +23,10 @@ class ApiToken extends React.Component<ApiTokenProps & RouteProps & DispatchProp
         const search = this.props.location ? this.props.location.search : "";
         const apiToken = ApiToken.getUrlParameter(search, 'api_token');
         this.props.dispatch(authActions.SAVE_API_TOKEN(apiToken));
-        this.props.dispatch(authService.getUserDetails());
-        this.props.dispatch(projectService.getProjectList());
+        this.props.dispatch<any>(authService.getUserDetails()).then(() => {
+            const rootUuid = authService.getRootUuid();
+            this.props.dispatch(projectService.getProjectList(rootUuid));
+        });
     }
     render() {
         return <Redirect to="/"/>
index 351ed2e04b7df755e29fc8131fac218bee9921e9..ca92c381f3993ddcdc7719d4450b7c8e7b8456a9 100644 (file)
@@ -14,7 +14,7 @@ import configureStore from "./store/store";
 import { ConnectedRouter } from "react-router-redux";
 import ApiToken from "./components/api-token/api-token";
 import authActions from "./store/auth/auth-action";
-import { projectService } from "./services/services";
+import { authService, projectService } from "./services/services";
 
 const history = createBrowserHistory();
 
@@ -30,7 +30,8 @@ const store = configureStore({
 }, history);
 
 store.dispatch(authActions.INIT());
-store.dispatch<any>(projectService.getProjectList());
+const rootUuid = authService.getRootUuid();
+store.dispatch<any>(projectService.getProjectList(rootUuid));
 
 const App = () =>
     <Provider store={store}>
index f1780d5db0cc96414c9c6435f17c10554a62ef31..ae7cf436b232a173237cf6201fdbccdf1e1e82f2 100644 (file)
@@ -6,4 +6,6 @@ export interface User {
     email: string;
     firstName: string;
     lastName: string;
+    uuid: string;
+    ownerUuid: string;
 }
index da593c2dfb7a44fad7d88b29ef8ebff70febffc7..07e0ff0913834ebdda8e72e0131332a933ded949 100644 (file)
@@ -11,11 +11,15 @@ export const API_TOKEN_KEY = 'apiToken';
 export const USER_EMAIL_KEY = 'userEmail';
 export const USER_FIRST_NAME_KEY = 'userFirstName';
 export const USER_LAST_NAME_KEY = 'userLastName';
+export const USER_UUID_KEY = 'userUuid';
+export const USER_OWNER_UUID_KEY = 'userOwnerUuid';
 
 export interface UserDetailsResponse {
     email: string;
     first_name: string;
     last_name: string;
+    uuid: string;
+    owner_uuid: string;
     is_admin: boolean;
 }
 
@@ -33,12 +37,19 @@ export default class AuthService {
         return localStorage.getItem(API_TOKEN_KEY) || undefined;
     }
 
+    public getOwnerUuid() {
+        return localStorage.getItem(USER_OWNER_UUID_KEY) || undefined;
+    }
+
     public getUser(): User | undefined {
         const email = localStorage.getItem(USER_EMAIL_KEY);
         const firstName = localStorage.getItem(USER_FIRST_NAME_KEY);
         const lastName = localStorage.getItem(USER_LAST_NAME_KEY);
-        return email && firstName && lastName
-            ? { email, firstName, lastName }
+        const uuid = localStorage.getItem(USER_UUID_KEY);
+        const ownerUuid = localStorage.getItem(USER_OWNER_UUID_KEY);
+
+        return email && firstName && lastName && uuid && ownerUuid
+            ? { email, firstName, lastName, uuid, ownerUuid }
             : undefined;
     }
 
@@ -46,12 +57,16 @@ export default class AuthService {
         localStorage.setItem(USER_EMAIL_KEY, user.email);
         localStorage.setItem(USER_FIRST_NAME_KEY, user.firstName);
         localStorage.setItem(USER_LAST_NAME_KEY, user.lastName);
+        localStorage.setItem(USER_UUID_KEY, user.uuid);
+        localStorage.setItem(USER_OWNER_UUID_KEY, user.ownerUuid);
     }
 
     public removeUser() {
         localStorage.removeItem(USER_EMAIL_KEY);
         localStorage.removeItem(USER_FIRST_NAME_KEY);
         localStorage.removeItem(USER_LAST_NAME_KEY);
+        localStorage.removeItem(USER_UUID_KEY);
+        localStorage.removeItem(USER_OWNER_UUID_KEY);
     }
 
     public login() {
@@ -64,14 +79,18 @@ export default class AuthService {
         window.location.assign(`${API_HOST}/logout?return_to=${currentUrl}`);
     }
 
-    public getUserDetails = () => (dispatch: Dispatch) => {
+    public getUserDetails = () => (dispatch: Dispatch): Promise<void> => {
         dispatch(actions.USER_DETAILS_REQUEST());
-        serverApi
+        return serverApi
             .get<UserDetailsResponse>('/users/current')
             .then(resp => {
                 dispatch(actions.USER_DETAILS_SUCCESS(resp.data));
-            })
-            // .catch(err => {
-            // });
+            });
     };
+
+    public getRootUuid() {
+        const uuid = this.getOwnerUuid();
+        const uuidParts = uuid ? uuid.split('-') : [];
+        return uuidParts.length > 1 ? `${uuidParts[0]}-${uuidParts[1]}` : undefined;
+    }
 }
index 9350dabdc4894f7ef4ebecb3105da204a0a98f14..e1e490bbbbe31aeaace718e053b531561f7c42d7 100644 (file)
@@ -35,23 +35,26 @@ interface GroupsResponse {
 export default class ProjectService {
     public getProjectList = (parentUuid?: string) => (dispatch: Dispatch): Promise<Project[]> => {
         dispatch(actions.PROJECTS_REQUEST());
-
-        const ub = new UrlBuilder('/groups');
-        const fb = new FilterBuilder();
-        fb.addEqual(FilterField.OWNER_UUID, parentUuid);
-        const url = ub.addParam('filters', fb.get()).get();
-
-        return serverApi.get<GroupsResponse>(url).then(groups => {
-            const projects = groups.data.items.map(g => ({
-                name: g.name,
-                createdAt: g.created_at,
-                modifiedAt: g.modified_at,
-                href: g.href,
-                uuid: g.uuid,
-                ownerUuid: g.owner_uuid
-            } as Project));
-            dispatch(actions.PROJECTS_SUCCESS({projects, parentItemId: parentUuid}));
-            return projects;
-        });
+        if (parentUuid) {
+            const fb = new FilterBuilder();
+            fb.addLike(FilterField.OWNER_UUID, parentUuid);
+            return serverApi.get<GroupsResponse>('/groups', { params: {
+                filters: fb.get()
+            }}).then(groups => {
+                const projects = groups.data.items.map(g => ({
+                    name: g.name,
+                    createdAt: g.created_at,
+                    modifiedAt: g.modified_at,
+                    href: g.href,
+                    uuid: g.uuid,
+                    ownerUuid: g.owner_uuid
+                } as Project));
+                dispatch(actions.PROJECTS_SUCCESS({projects, parentItemId: parentUuid}));
+                return projects;
+            });
+        } else {
+            dispatch(actions.PROJECTS_SUCCESS({projects: [], parentItemId: parentUuid}));
+            return Promise.resolve([]);
+        }
     };
 }
index 17bd42175f8df6647a98d847f6c0a48d79ee4b1d..a60e82a6c8bde1d4f326ba341dd5f908119a49ff 100644 (file)
@@ -8,7 +8,9 @@ import {
     API_TOKEN_KEY,
     USER_EMAIL_KEY,
     USER_FIRST_NAME_KEY,
-    USER_LAST_NAME_KEY
+    USER_LAST_NAME_KEY,
+    USER_OWNER_UUID_KEY,
+    USER_UUID_KEY
 } from "../../services/auth-service/auth-service";
 import { API_HOST } from "../../common/api/server-api";
 
@@ -35,6 +37,8 @@ describe('auth-reducer', () => {
         localStorage.setItem(USER_EMAIL_KEY, "test@test.com");
         localStorage.setItem(USER_FIRST_NAME_KEY, "John");
         localStorage.setItem(USER_LAST_NAME_KEY, "Doe");
+        localStorage.setItem(USER_UUID_KEY, "uuid");
+        localStorage.setItem(USER_OWNER_UUID_KEY, "ownerUuid");
 
         const state = authReducer(initialState, actions.INIT());
         expect(state).toEqual({
@@ -42,7 +46,9 @@ describe('auth-reducer', () => {
             user: {
                 email: "test@test.com",
                 firstName: "John",
-                lastName: "Doe"
+                lastName: "Doe",
+                uuid: "uuid",
+                ownerUuid: "ownerUuid"
             }
         });
     });
@@ -66,6 +72,8 @@ describe('auth-reducer', () => {
             email: "test@test.com",
             first_name: "John",
             last_name: "Doe",
+            uuid: "uuid",
+            owner_uuid: "ownerUuid",
             is_admin: true
         };
 
@@ -75,7 +83,9 @@ describe('auth-reducer', () => {
             user: {
                 email: "test@test.com",
                 firstName: "John",
-                lastName: "Doe"
+                lastName: "Doe",
+                uuid: "uuid",
+                ownerUuid: "ownerUuid",
             }
         });
 
index 57a17ae53cfbb45f9c69529ad34d866771b0f215..e58b2535e6805bf98bd15a32d3f8521698416a25 100644 (file)
@@ -43,7 +43,9 @@ const authReducer = (state: AuthState = {}, action: AuthAction) => {
             const user = {
                 email: ud.email,
                 firstName: ud.first_name,
-                lastName: ud.last_name
+                lastName: ud.last_name,
+                uuid: ud.uuid,
+                ownerUuid: ud.owner_uuid
             };
             authService.saveUser(user);
             return {...state, user};