Skip to content

Commit

Permalink
Task/DES-3065: Use cloud.data system for HPC work directories (#1423)
Browse files Browse the repository at this point in the history
* use cloud.data system for HPC work directories

* fix issues with tests

* Rename 'HPC Work' to 'Work'; consolidate hard-coded system names

* add project title as a subtitle in datacite, prefixed with 'in' (#1428)

* deep-copy entity values before inserting them into the project tree (#1427)

* Log DOIs for each file when multiple are selected, even if there are duplicates (#1430)

* Bug/wc 84 metrics modal error (#1431)

* commit to main

* prevent blank or null values from causing metrics page to crash

* remove those type coercions and fix the type errors

* Refactor MetricsModalBody component to improve readability and maintainability

* remove docker compose changes

---------

Co-authored-by: Jake Rosenberg <[email protected]>

* Task/WC-95: Clear file selection when changing publication version (#1432)

* Log DOIs for each file when multiple are selected, even if there are duplicates

* Unset file selections when changing the selected publication version

* Show up to 3 keywords in the publication listing (#1429)

* task/WC-91: Directories in Publication Preview should open in the Curation listing (#1425)

* Directories in Publication Preview open in the Curation listing

* fix links inside the publication pipeline

* revert link _target change

* Task/WC-96: Log views of non-Other type publications as listings on the root dir (#1433)

* log views of non-Other type projects as listings on the root dir

* fix hook dependencies

* bump setfacls app to v0.0.2 (#1434)

* improve DOI support in Publication search (#1437)

* Ensure correct publication dates after subsequent publish (#1436)

* update wording in Copy modal

* task/WP-685: user work workspace file select (#1426)

* handle error in revoke method

* handle cloud.data work system in workspace select modal

---------

Co-authored-by: Sal Tijerina <[email protected]>
Co-authored-by: Van Go <[email protected]>
  • Loading branch information
3 people authored Sep 18, 2024
1 parent 2600303 commit bd913be
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 47 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Breadcrumb, BreadcrumbProps } from 'antd';
import React from 'react';
import styles from './DatafilesBreadcrumb.module.css';
import { getSystemRootDisplayName, useAuthenticatedUser } from '@client/hooks';
import {
getSystemRootDisplayName,
useAuthenticatedUser,
USER_MYDATA_SYSTEM,
USER_WORK_SYSTEM,
} from '@client/hooks';

function getPathRoutes(
baseRoute: string,
Expand Down Expand Up @@ -50,13 +55,6 @@ export const DatafilesBreadcrumb: React.FC<
);
};

function isUserHomeSystem(system: string) {
return [
'designsafe.storage.default',
'designsafe.storage.frontera.work',
].includes(system);
}

export const BaseFileListingBreadcrumb: React.FC<
{
api: string;
Expand All @@ -78,7 +76,10 @@ export const BaseFileListingBreadcrumb: React.FC<
const { user } = useAuthenticatedUser();
const rootAlias =
systemRootAlias || getSystemRootDisplayName(api, system, systemLabel);
const systemRoot = isUserHomeSystem(system) ? '/' + user?.username : '';
let systemRoot = '';
if (system === USER_MYDATA_SYSTEM) systemRoot = '/' + user?.username;
if (system === USER_WORK_SYSTEM) systemRoot = '/work/' + user?.homedir;

return (
<DatafilesBreadcrumb
initialBreadcrumbs={[
Expand All @@ -90,7 +91,7 @@ export const BaseFileListingBreadcrumb: React.FC<
]}
path={path}
baseRoute={`/${api}/${system}`}
systemRoot={isUserHomeSystem(system) ? '/' + user?.username : ''}
systemRoot={systemRoot}
systemRootAlias={systemRootAlias || getSystemRootDisplayName(api, system)}
{...props}
/>
Expand Down
5 changes: 1 addition & 4 deletions client/modules/_hooks/src/datafiles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ export { useUploadFile } from './useUploadFile';
export { useUploadFolder } from './useUploadFolder';
export { useFileDetail } from './useFileDetail';

export {
usePathDisplayName,
getSystemRootDisplayName,
} from './usePathDisplayName';
export * from './usePathDisplayName';

export * from './nees';
export * from './projects';
Expand Down
27 changes: 20 additions & 7 deletions client/modules/_hooks/src/datafiles/usePathDisplayName.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useCallback } from 'react';
import { useAuthenticatedUser } from '../useAuthenticatedUser';

export const USER_MYDATA_SYSTEM = 'designsafe.storage.default';
export const USER_WORK_SYSTEM = 'cloud.data';

export function getSystemRootDisplayName(
api: string,
system: string,
Expand All @@ -9,10 +12,11 @@ export function getSystemRootDisplayName(
if (api === 'googledrive') return 'Google Drive';
if (api === 'box') return 'Box';
if (api === 'dropbox') return 'Dropbox';

return (
{
'designsafe.storage.default': 'My Data',
'designsafe.storage.frontera.work': 'HPC Work',
[USER_MYDATA_SYSTEM]: 'My Data',
[USER_WORK_SYSTEM]: 'Work',
'designsafe.storage.community': 'Community Data',
}[system] ?? label
);
Expand All @@ -23,20 +27,22 @@ function _getPathDisplayName(
system: string,
path: string,
label: string,
username?: string
username?: string,
homedir?: string
) {
const usernamePath = encodeURIComponent('/' + username);
const workdirPath = `/work/${homedir}`;

if (!path) return getSystemRootDisplayName(api, system, label);
if (api === 'googledrive' && !path) return 'Google Drive';
if (api === 'dropbox' && !path) return 'Dropbox';
if (api === 'box' && !path) return 'Box';

if (system === 'designsafe.storage.default' && path === usernamePath) {
if (system === USER_MYDATA_SYSTEM && path === usernamePath) {
return 'My Data';
}
if (system === 'designsafe.storage.frontera.work' && path === usernamePath) {
return 'HPC Work';
if (system === USER_WORK_SYSTEM && path === workdirPath) {
return 'Work';
}

return decodeURIComponent(path).split('/').slice(-1)[0] || label;
Expand All @@ -47,7 +53,14 @@ export function usePathDisplayName() {

const getPathDisplayName = useCallback(
(api: string, system: string, path: string, label: string = 'Data Files') =>
_getPathDisplayName(api, system, path, label, user?.username),
_getPathDisplayName(
api,
system,
path,
label,
user?.username,
user?.homedir
),
[user]
);

Expand Down
1 change: 1 addition & 0 deletions client/modules/_hooks/src/systems/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export type TTapisSystem = {
label?: string;
keyservice?: boolean;
isMyData?: boolean;
hasWork?: boolean;
portalNames: string[];
};
importRefId?: string;
Expand Down
1 change: 1 addition & 0 deletions client/modules/_hooks/src/useAuthenticatedUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type TUser = {
lastName: string;
email: string;
institution: string;
homedir: string;
};

declare global {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ export const CopyModal: React.FC<{
setShowProjects(false);
setDest({
destApi: 'tapis',
destSystem: 'designsafe.storage.frontera.work',
destPath: encodeURIComponent('/' + user?.username),
destSystem: 'cloud.data',
destPath: encodeURIComponent('/work/' + user?.homedir),
});
break;
case 'myprojects':
Expand Down Expand Up @@ -250,7 +250,7 @@ export const CopyModal: React.FC<{
<Select
options={[
{ label: 'My Data', value: 'mydata' },
{ label: 'HPC Work', value: 'hpcwork' },
{ label: 'Work', value: 'hpcwork' },
{ label: 'My Projects', value: 'myprojects' },
]}
style={{ marginBottom: '12px' }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ export const DatafilesSideNav: React.FC = () => {
</DataFilesNavLink>

<DataFilesNavLink
to={`/tapis/designsafe.storage.frontera.work`}
to={`/tapis/cloud.data/`}
tooltip="Work directory on TACC HPC machines for use with Jupyter"
>
HPC Work
Work
</DataFilesNavLink>
<DataFilesNavLink
to="/projects"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
useAuthenticatedUser,
useFileListingRouteParams,
useProjectDetail,
USER_WORK_SYSTEM,
useSelectedFiles,
useSelectedFilesForSystem,
} from '@client/hooks';
Expand Down Expand Up @@ -103,7 +104,7 @@ export const DatafilesToolbar: React.FC<{ searchInput?: React.ReactNode }> = ({
// Disable downloads from frontera.work until we have a non-flaky mount on ds-download.
canDownload:
selectedFiles.length >= 1 &&
system !== 'designsafe.storage.frontera.work' &&
system !== USER_WORK_SYSTEM &&
!selectedFiles[0].path.endsWith('.hazmapper'),
};
},
Expand Down
16 changes: 11 additions & 5 deletions client/modules/workspace/src/SelectModal/SelectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,13 @@ const getSystemRootPath = (
storageSystem: TTapisSystem | undefined,
user: TUser | undefined
): string => {
return storageSystem?.notes?.isMyData
? encodeURIComponent('/' + user?.username)
: '';
if (storageSystem?.notes?.isMyData) {
return encodeURIComponent('/' + user?.username);
}
if (storageSystem?.notes?.hasWork) {
return encodeURIComponent('/work/' + user?.homedir);
}
return '';
};

const getBackPath = (
Expand Down Expand Up @@ -298,7 +302,7 @@ export const SelectModal: React.FC<{
return (a.notes?.isMyData ? 0 : 1) - (b.notes?.isMyData ? 0 : 1);
})
.map((system) => ({
label: system.notes.label,
label: system.notes?.hasWork ? 'Work' : system.notes.label ?? system.id,
value: system.id,
}));
systemOptions.push({ label: 'My Projects', value: 'myprojects' });
Expand Down Expand Up @@ -363,7 +367,9 @@ export const SelectModal: React.FC<{
selectedPath: getSystemRootPath(system, user),
scheme: getScheme(system),
});
setSystemLabel(system.notes.label ?? system.id);
setSystemLabel(
system.notes?.hasWork ? 'Work' : system.notes.label ?? system.id
);
};

const onProjectSelect = (uuid: string, projectId: string) => {
Expand Down
23 changes: 16 additions & 7 deletions client/src/datafiles/layouts/FileListingLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { DatafilesToolbar, FileListing } from '@client/datafiles';
import { BaseFileListingBreadcrumb } from '@client/common-components';
import { useAuthenticatedUser, useFileListingRouteParams } from '@client/hooks';
import {
useAuthenticatedUser,
useFileListingRouteParams,
USER_MYDATA_SYSTEM,
USER_WORK_SYSTEM,
} from '@client/hooks';
import { Button, Form, Input, Layout } from 'antd';
import React from 'react';
import { Link, Navigate, useSearchParams } from 'react-router-dom';
Expand Down Expand Up @@ -37,13 +42,11 @@ export const FileListingLayout: React.FC = () => {
const { api, path, scheme, system } = useFileListingRouteParams();
const { user } = useAuthenticatedUser();

const isUserHomeSystem = [
'designsafe.storage.default',
'designsafe.storage.frontera.work',
].includes(system);

const redirectHome =
user?.username && !path && api === 'tapis' && isUserHomeSystem;
user?.username && !path && api === 'tapis' && system === USER_MYDATA_SYSTEM;

const redirectWork =
user?.username && !path && api === 'tapis' && system === USER_WORK_SYSTEM;
return (
<Layout style={{ gap: '5px', minWidth: '500px' }}>
<DatafilesToolbar searchInput={<FileListingSearchBar />} />
Expand All @@ -69,6 +72,12 @@ export const FileListingLayout: React.FC = () => {
replace
/>
)}
{redirectWork && (
<Navigate
to={`../${encodeURIComponent('/work/' + user.homedir)}`}
replace
/>
)}
<FileListing api={api} system={system} path={path} scheme={scheme} />
</div>
</Layout.Content>
Expand Down
2 changes: 1 addition & 1 deletion designsafe/apps/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ def clean_website(self):

class Meta:
model = DesignSafeProfile
exclude = ['user', 'ethnicity', 'gender', 'update_required', 'institution']
exclude = ['user', 'ethnicity', 'gender', 'update_required', 'institution', 'homedir']


class UserRegistrationForm(UserProfileForm, ProfessionalProfileForm):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.11 on 2024-08-29 21:19

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("designsafe_accounts", "0020_designsafeprofile_institution"),
]

operations = [
migrations.AddField(
model_name="designsafeprofile",
name="homedir",
field=models.CharField(default=None, max_length=256, null=True),
),
]
18 changes: 18 additions & 0 deletions designsafe/apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.db import connections, DatabaseError
from django.utils.translation import gettext_lazy as _
from django.core.mail import send_mail
from pytas.http import TASClient
import logging
import six

Expand Down Expand Up @@ -74,6 +75,7 @@ class DesignSafeProfile(models.Model):
professional_level = models.CharField(max_length=256, default=None, null=True)
research_activities = models.ManyToManyField(DesignSafeProfileResearchActivities)
institution = models.CharField(max_length=256, default=None, null=True)
homedir = models.CharField(max_length=256, default=None, null=True)
update_required = models.BooleanField(default=True)
last_updated = models.DateTimeField(auto_now=True, null=True)

Expand All @@ -84,6 +86,22 @@ def send_mail(self, subject, body=None):
[self.user.email],
html_message=body)

def get_homedir(self):
"""
Get a user's homedir.
If it does not exist in the database yet, retrieve and cache it.
"""
if self.homedir:
return self.homedir

tas = TASClient()
tas_user = tas.get_user(username=self.user.username)

homedir = tas_user.get("homeDirectory", "")
self.homedir = homedir
self.save()
return homedir


class NotificationPreferences(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
Expand Down
18 changes: 12 additions & 6 deletions designsafe/apps/auth/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def on_user_logged_out(sender, request, user, **kwargs):
login_provider = "TACC"

logger.info(
"Revoking tapis token: %s", TapisOAuthToken().get_masked_token(user.tapis_oauth.access_token)
"Revoking tapis token: %s",
TapisOAuthToken().get_masked_token(user.tapis_oauth.access_token),
)
backend = TapisOAuthBackend()
TapisOAuthBackend.revoke(backend, user.tapis_oauth.access_token)
Expand Down Expand Up @@ -139,7 +140,8 @@ def authenticate(self, *args, **kwargs):
token = kwargs["token"]

logger.info(
'Attempting login via Tapis with token "%s"' % TapisOAuthToken().get_masked_token(token)
'Attempting login via Tapis with token "%s"'
% TapisOAuthToken().get_masked_token(token)
)
client = Tapis(base_url=settings.TAPIS_TENANT_BASEURL, access_token=token)

Expand Down Expand Up @@ -188,9 +190,13 @@ def authenticate(self, *args, **kwargs):

def revoke(self, token):
logger.info(
"Attempting to revoke Tapis token %s" % TapisOAuthToken().get_masked_token(token)
"Attempting to revoke Tapis token %s"
% TapisOAuthToken().get_masked_token(token)
)

client = Tapis(base_url=settings.TAPIS_TENANT_BASEURL, access_token=token)
response = client.authenticator.revoke_token(token=token)
logger.info("revoke response is %s" % response)
try:
client = Tapis(base_url=settings.TAPIS_TENANT_BASEURL, access_token=token)
response = client.authenticator.revoke_token(token=token)
logger.info("revoke response is %s" % response)
except BaseTapyException as e:
logger.error("Error revoking token: %s", e.message)
7 changes: 7 additions & 0 deletions designsafe/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,10 @@ def site_verification(request):
if google_verification_id:
context['GOOGLE_SITE_VERIFICATION_ID'] = google_verification_id
return context

def tas_homedir(request):
"""Retrieve user's TAS homedir."""
if getattr(settings, "TEST", None) or not request.user.is_authenticated:
return {}

return {"tas_homedir": request.user.profile.get_homedir()}
1 change: 1 addition & 0 deletions designsafe/settings/common_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
'designsafe.context_processors.site_verification',
'designsafe.context_processors.debug',
'designsafe.context_processors.messages',
'designsafe.context_processors.tas_homedir',
'designsafe.apps.cms_plugins.context_processors.cms_section',
],
},
Expand Down
Loading

0 comments on commit bd913be

Please sign in to comment.