From c77b1a5becebf382fddc349ae9081503d511a02a Mon Sep 17 00:00:00 2001 From: Daniel Kos Date: Wed, 13 Jun 2018 23:53:01 +0200 Subject: [PATCH] Added passing root owner uuid for top level projects Feature #13622 Arvados-DCO-1.1-Signed-off-by: Daniel Kos --- src/common/api/filter-builder.ts | 8 ++-- src/components/api-token/api-token.tsx | 6 ++- src/index.tsx | 5 ++- src/models/user.ts | 2 + src/services/auth-service/auth-service.ts | 33 ++++++++++++---- .../project-service/project-service.ts | 39 ++++++++++--------- src/store/auth/auth-reducer.test.ts | 16 ++++++-- src/store/auth/auth-reducer.ts | 4 +- 8 files changed, 76 insertions(+), 37 deletions(-) diff --git a/src/common/api/filter-builder.ts b/src/common/api/filter-builder.ts index 3f8e323c40..443c763913 100644 --- a/src/common/api/filter-builder.ts +++ b/src/common/api/filter-builder.ts @@ -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() { diff --git a/src/components/api-token/api-token.tsx b/src/components/api-token/api-token.tsx index 87da39b025..d63f6e0733 100644 --- a/src/components/api-token/api-token.tsx +++ b/src/components/api-token/api-token.tsx @@ -23,8 +23,10 @@ class ApiToken extends React.Component(authService.getUserDetails()).then(() => { + const rootUuid = authService.getRootUuid(); + this.props.dispatch(projectService.getProjectList(rootUuid)); + }); } render() { return diff --git a/src/index.tsx b/src/index.tsx index 351ed2e04b..ca92c381f3 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -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(projectService.getProjectList()); +const rootUuid = authService.getRootUuid(); +store.dispatch(projectService.getProjectList(rootUuid)); const App = () => diff --git a/src/models/user.ts b/src/models/user.ts index f1780d5db0..ae7cf436b2 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -6,4 +6,6 @@ export interface User { email: string; firstName: string; lastName: string; + uuid: string; + ownerUuid: string; } diff --git a/src/services/auth-service/auth-service.ts b/src/services/auth-service/auth-service.ts index da593c2dfb..07e0ff0913 100644 --- a/src/services/auth-service/auth-service.ts +++ b/src/services/auth-service/auth-service.ts @@ -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 => { dispatch(actions.USER_DETAILS_REQUEST()); - serverApi + return serverApi .get('/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; + } } diff --git a/src/services/project-service/project-service.ts b/src/services/project-service/project-service.ts index 9350dabdc4..e1e490bbbb 100644 --- a/src/services/project-service/project-service.ts +++ b/src/services/project-service/project-service.ts @@ -35,23 +35,26 @@ interface GroupsResponse { export default class ProjectService { public getProjectList = (parentUuid?: string) => (dispatch: Dispatch): Promise => { 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(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('/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([]); + } }; } diff --git a/src/store/auth/auth-reducer.test.ts b/src/store/auth/auth-reducer.test.ts index 17bd42175f..a60e82a6c8 100644 --- a/src/store/auth/auth-reducer.test.ts +++ b/src/store/auth/auth-reducer.test.ts @@ -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", } }); diff --git a/src/store/auth/auth-reducer.ts b/src/store/auth/auth-reducer.ts index 57a17ae53c..e58b2535e6 100644 --- a/src/store/auth/auth-reducer.ts +++ b/src/store/auth/auth-reducer.ts @@ -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}; -- 2.30.2