Skip to content

Commit

Permalink
Minor SMaHT related updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
dmichaels-harvard committed Sep 1, 2023
1 parent a28f07c commit b8f0a46
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 50 deletions.
41 changes: 30 additions & 11 deletions foursight_core/react/api/react_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ def reactapi_header(self, request: dict, env: str) -> Response:
test_mode_access_key_simulate_error=test_mode_access_key_simulate_error,
test_mode_access_key_expiration_warning_days=test_mode_access_key_expiration_warning_days)
if data["portal_access_key"].get("invalid"):
data["portal_access_key_error"] = True
data["portal_access_key_erro"] = True
return self.create_success_response(data)

@function_cache(key=lambda self, request, env: env) # new as of 2023-04-27
Expand Down Expand Up @@ -648,7 +648,7 @@ def _create_user_record_for_output(self, user: dict) -> dict:
updated = last_modified.get("date_modified") or user.get("date_created")
else:
updated = user.get("date_created")
user = {
result = {
# Lower case email to avoid any possible issues on lookup later.
"email": (user.get("email") or "").lower(),
"first_name": user.get("first_name"),
Expand All @@ -662,24 +662,28 @@ def _create_user_record_for_output(self, user: dict) -> dict:
"created": convert_utc_datetime_to_utc_datetime_string(user.get("date_created"))
}
institution = user.get("user_institution")
project = user.get("project"),
project = user.get("project")
award = user.get("award")
lab = user.get("lab")
consortia = user.get("consortia")
submission_centers = user.get("submission_centers")
if institution:
user["institution"] = institution
result["institution"] = institution
if project:
user["project"] = project
result["project"] = project
if award:
user["award"] = award
result["award"] = award
if lab:
user["lab"] = lab
result["lab"] = lab
# Note that for the affilitiaions, like institution/project for CGAP
# and award/institution for Fourfrount, where these are single
# values, for SMaHT consortia/submission-centers are arrays;
# will let the UI deal with any display issues there.
if consortia:
user["consortia"] = consortia
result["consortia"] = consortia
if submission_centers:
user["submission_centers"] = submission_centers
return user
result["submission_centers"] = submission_centers
return result

def _create_user_record_from_input(self, user: dict, include_deletes: bool = False) -> dict:
"""
Expand Down Expand Up @@ -1452,10 +1456,22 @@ def is_this_server(url: str) -> bool:
try:
url_origin = urllib.parse.urlparse(url).netloc
this_origin = request.get('headers', {}).get('host')
return url_origin == this_origin
return url_origin == this_origin or this_origin == "localhost:8000"
except Exception:
return False

def check_s3_aws_access_key() -> bool:
s3_aws_access_key_id = os.environ.get("S3_AWS_ACCESS_KEY_ID")
s3_secret_access_key = os.environ.get("S3_SECRET_ACCESS_KEY")
global_env_bucket = os.environ.get("GLOBAL_ENV_BUCKET")
if s3_aws_access_key_id and s3_secret_access_key and global_env_bucket:
s3 = s3.client("s3")
try:
s3.list_objects_v2(Bucket=global_env_bucket)
except Exception:
return False
return True

def get_foursight_info(foursight_url: str, response: dict) -> Optional[str]:
response["foursight"] = {}
if not foursight_url:
Expand Down Expand Up @@ -1503,6 +1519,9 @@ def get_foursight_info(foursight_url: str, response: dict) -> Optional[str]:
response["foursight"]["s3"]["encrypt_key_id"] = foursight_header_json_s3.get("encrypt_key_id")
response["foursight"]["s3"]["has_encryption"] = foursight_header_json_s3.get("has_encryption")
response["foursight"]["s3"]["buckets"] = foursight_header_json_s3.get("buckets")
response["foursight"]["s3"]["access_key"] = os.environ.get("S3_AWS_ACCESS_KEY_ID")
if not check_s3_aws_access_key():
response["foursight"]["s3"]["access_key_error"] = True
response["foursight"]["aws_account_number"] = foursight_app["credentials"].get("aws_account_number")
response["foursight"]["aws_account_name"] = foursight_app["credentials"].get("aws_account_name")
response["foursight"]["re_captcha_key"] = foursight_app["credentials"].get("re_captcha_key")
Expand Down
4 changes: 2 additions & 2 deletions foursight_core/react/api/react_api_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,10 @@ def get_redirect_url(self, request: dict, env: str, domain: str, context: str) -
return f"{self.foursight_instance_url(request)}/react/{env}/login"

def is_foursight_cgap(self) -> bool:
return app.core.APP_PACKAGE_NAME == "foursight" or app.core.APP_PACKAGE_NAME == "foursight-fourfront"
return app.core.APP_PACKAGE_NAME == "foursight-cgap"

def is_foursight_fourfront(self) -> bool:
return app.core.APP_PACKAGE_NAME == "foursight-cgap"
return app.core.APP_PACKAGE_NAME == "foursight" or app.core.APP_PACKAGE_NAME == "foursight-fourfront"

def is_foursight_smaht(self) -> bool:
return app.core.APP_PACKAGE_NAME == "foursight-smaht"
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "foursight-core"
version = "4.4.0.1b11" # TODO: To become 4.5.0
version = "4.4.0.1b12" # TODO: To become 4.5.0
description = "Serverless Chalice Application for Monitoring"
authors = ["4DN-DCIC Team <[email protected]>"]
license = "MIT"
Expand Down
2 changes: 1 addition & 1 deletion react/src/hooks/FetchBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ function _doFetch(args, current = undefined, fetcher) {
if (args.cache) {
Debug.Info(`FETCH CACHING RESPONSE: ${args.method} ${args.url} -> HTTP ${status}`);
_fetchCache[args.url] = {
data: data,
data: fetcher.data,
status: status
}
}
Expand Down
36 changes: 35 additions & 1 deletion react/src/hooks/UserMetadata.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import useFetch from './Fetch';

const useUserMetadata = () => {
const useUserMetadataCgap = () => {
const projects = useFetch("/users/projects", { cache: true });
const roles = useFetch("/users/roles", { cache: true });
const institutions = useFetch("/users/institutions", { cache: true });
Expand All @@ -19,4 +19,38 @@ const useUserMetadata = () => {
return response;
}

const useUserMetadataSmaht = () => {
const consortia = useFetch("/users/consortia", { cache: true });
const roles = useFetch("/users/roles", { cache: true });
const submissionCenters = useFetch("/users/submission_centers", { cache: true });
const statuses = useFetch("/users/statuses", { cache: true });
const response = {
consortiumTitle: (id) => {
let value = consortia.data?.find(item => item.id === id)?.title || "";
if (value?.endsWith(" Consortium")) {
value = value.replace(" Consortium", "");
}
return value;
},
roleTitle: (id) => roles.data?.find(item => item.id === id)?.title || "",
submissionCenterTitle: (id) => {
let value = submissionCenters.data?.find(item => item.id === id)?.title || "";
if (value?.endsWith(" Submission Center")) {
value = value.replace(" Submission Center", "");
}
return value;
},
statusTitle: (id) => statuses.data?.find(item => item.id === id)?.title || "",
userRole: (user, consortiumId) => user.roles?.find(item => item.consortium === consortiumId)?.role || "",
title: (s) => s.replace(/\w\S*/g, (s) => s.charAt(0).toUpperCase() + s.substr(1).toLowerCase()) || "",
principleInvestigator: (submissionCenterId) => submissionCenters?.data?.find(item => item.id === submissionCenterId)?.pi
}
response.userRoleTitle = (user, consortiumId) => response.roleTitle(response.userRole(user, consortiumId)) || "";
response.titles = (sa) => sa?.map(s => response.title(s)).join(", ") || "";
return response;
}

//const useUserMetadata = useUserMetadataCgap;
const useUserMetadata = useUserMetadataSmaht;

export default useUserMetadata;
14 changes: 12 additions & 2 deletions react/src/pages/AccountsComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ const Row = ({ title, value, additionalValue, externalLink, children, tooltip =
const tooltipText = Type.IsArray(tooltip) ? tooltip[0] : null;
const tooltipId = Type.IsArray(tooltip) ? tooltip[1] : null;
return <tr style={{fontSize:small ? "small" : "inherit"}}>
<td style={{paddingRight:"10pt",verticalAlign:"top"}}>
<td style={{paddingRight:"7pt",verticalAlign:"top"}}>
{title}:
</td>
<td>
Expand Down Expand Up @@ -168,7 +168,7 @@ const SecretsDropdown = ({ header, info, name }) => {
</>:<>
<span onClick={toggleShowIdentity} className="pointer">Secrets <b>{Char.UpArrow}</b></span>
</> }
{ showIdentity && <Secrets name={info.get("foursight.identity")} embedded={true} /> }
{ showIdentity && <Secrets name={name} embedded={true} /> }
</> }
</>
}
Expand Down Expand Up @@ -300,6 +300,16 @@ const AccountInfoLeft = ({ header, info, foursightUrl }) => {
externalLink={`https://us-east-1.console.aws.amazon.com/kms/home?region=us-east-1#/kms/keys/${info.get("foursight.s3.encrypt_key_id")}`}
tooltip={[`S3 Bucket Encryption Key ID`, `tooltip-encryption-key-${info.get("foursight.aws_account_number")}`]} showEmpty={true}>
</Row>
<Row title="S3 Access Key" value={info.get("foursight.s3.access_key")}
tooltip={[`This is from the S3_AWS_ACCESS_KEY_ID environment variable.`,
`tooltip-s3-aws-access-key-id${info.get("foursight.s3.access_key")}`]}>
&nbsp;
{ info.get("foursight.s3.access_key_error") ? <>
<b style={{color:"red"}}>{Char.X}</b>
</>:<>
<b style={{color:"green"}}>{Char.Check}</b>
</> }
</Row>
<Separator />
<Row title="AWS Account" value={info.get("foursight.aws_account_number")} additionalValue={info.get("foursight.aws_account_name")} externalLink={"https://us-east-1.console.aws.amazon.com/billing/home#/account"} bold={true} />
<Row title="Default Environment" value={info.get("foursight.default_env.full_name")} additionalValue={info.get("foursight.env_count") ? `${info.get("foursight.env_count")} total` : ""}>
Expand Down
24 changes: 23 additions & 1 deletion react/src/pages/UserPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,36 @@ const UserBox = (props) => {

const userMetadata = useUserMetadata();

const affiliations = {
[Env.FoursightTitleCgap]: [
{ label: "Institution", name: "institution",
map: value => userMetadata.institutionTitle(value),
subComponent: (institution) => <UserDefs.PrincipalInvestigatorLine institution={institution} /> },
{ label: "Project", name: "project",
map: value => userMetadata.projectTitle(value) }
],
[Env.FoursightTitleFourfront]: [
{ label: "Award", name: "award",
map: value => userMetadata.awardTitle(value) },
{ label: "Lab", name: "lab",
map: value => userMetadata.labTitle(value) }
],
[Env.FoursightTitleSmaht]: [
{ label: "Consortium", name: "consortium",
map: value => userMetadata.awardTitle(value) },
{ label: "Submission Center", name: "submission_center",
map: value => userMetadata.labTitle(value) }
]
};

let items = [
{ label: "Email", name: "email" },
{ label: "First Name", name: "first_name" },
{ label: "Last Name", name: "last_name" },
{ label: "Groups", name: "groups", map: value => userMetadata.titles(value) },
{ label: "Project", name: "project", map: value => userMetadata.projectTitle(value) },
{ label: "Role", name: "role", map: value => userMetadata.userRoleTitle(props.user, props.user.project) },
{ label: "Roles", name: "roles", ui: <RolesBox user={props.user} />, toggle: true },
{ label: "Project", name: "project", map: value => userMetadata.projectTitle(value) },
{ label: "Institution", name: "institution", map: value => userMetadata.institutionTitle(value),
subComponent: (institution) => <UserDefs.PrincipalInvestigatorLine institution={institution} /> },
{ label: "Status", name: "status", map: value => userMetadata.statusTitle(value) },
Expand Down
75 changes: 65 additions & 10 deletions react/src/pages/UsersPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Link } from '../Components';
import useFetch from '../hooks/Fetch';
import Char from '../utils/Char';
import Date from '../utils/Date';
import Env from '../utils/Env';
import { FetchErrorBox } from '../Components';
import Server from '../utils/Server';
import Str from '../utils/Str';
Expand All @@ -13,9 +14,11 @@ import Tooltip from '../components/Tooltip';
import Time from '../utils/Time';
import Type from '../utils/Type';
import useUserMetadata from '../hooks/UserMetadata';
import useHeader from '../hooks/Header';

const UsersPage = () => {

const header = useHeader();
const { environ } = useParams();
const [ args, setArgs ] = useSearchParams();
const users = useFetch();
Expand All @@ -39,12 +42,26 @@ const UsersPage = () => {

if (users.error) return <FetchErrorBox error={users.error} message="Error loading users from Foursight API" center={true} />

const affiliations = {
[Env.FoursightTitleCgap]: [
{ label: "Project", key: "project" },
{ label: "Institution", key: "institution" },
],
[Env.FoursightTitleFourfront]: [
{ label: "Award", key: "award" },
{ label: "Lab", key: "lab" },
],
[Env.FoursightTitleSmaht]: [
{ label: "Consortia", key: "consortia" },
{ label: "Submission Centers", key: "submission_centers" },
]
};

const columns = [
{ label: "" },
{ label: "User", key: "email" },
{ label: "Groups", key: "groups" },
{ label: "Project", key: "project" },
{ label: "Institution", key: "institution" },
...affiliations[Env.FoursightFlavorTitle(header)],
{ label: "Role", key: "role" },
{ label: "Status", key: "status" },
{ label: "Updated", key: "data_modified" }, // DOES NOT WORK (nested in last_modified)
Expand Down Expand Up @@ -156,14 +173,7 @@ const UsersPage = () => {
<td style={tdStyle}>
{user.groups?.length > 0 ? (userMetadata.titles(user.groups) || Char.EmptySet) : Char.EmptySet}
</td>
<td style={tdStyle}>
<span id={`tooltip-users-project-${user.email}`}>{userMetadata.projectTitle(user.project) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-project-${user.email}`} position="bottom" size="small" text={`Project: ${user.project}`} />
</td>
<td style={tdStyle}>
<span id={`tooltip-users-institution-${user.email}`}>{userMetadata.institutionTitle(user.institution) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-institution-${user.email}`} position="bottom" size="small" text={`Institution: ${user.institution}`} />
</td>
<UserAffiliationItemsSmaht user={user} userMetadata={userMetadata} tdStyle={tdStyle} />
<td style={tdStyle}>
<span id={`tooltip-users-role-${user.email}`}>
{userMetadata.userRoleTitle(user, user.project) || Char.EmptySet}
Expand Down Expand Up @@ -194,4 +204,49 @@ const UsersPage = () => {
</>
};

const UserAffiliationItemsCgap = ({user, userMetadata, tdStyle}) => {
return <>
<td style={tdStyle}>
<span id={`tooltip-users-project-${user.email}`}>{userMetadata.projectTitle(user.project) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-project-${user.email}`} position="bottom" size="small" text={`Project: ${user.project}`} />
</td>
<td style={tdStyle}>
<span id={`tooltip-users-institution-${user.email}`}>{userMetadata.institutionTitle(user.institution) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-institution-${user.email}`} position="bottom" size="small" text={`Institution: ${user.institution}`} />
</td>
</>
}

const UserAffiliationItemsFourfront = ({user, userMetadata, tdStyle}) => {
return <>
<td style={tdStyle}>
<span id={`tooltip-users-award-${user.email}`}>{userMetadata.awardTitle(user.award) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-award-${user.email}`} position="bottom" size="small" text={`Award: ${user.award}`} />
</td>
<td style={tdStyle}>
<span id={`tooltip-users-lab-${user.email}`}>{userMetadata.labTitle(user.lab) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-lab-${user.email}`} position="bottom" size="small" text={`Lab: ${user.lab}`} />
</td>
</>
}

const UserAffiliationItemsSmaht = ({user, userMetadata, tdStyle}) => {
if (Type.IsArray(user.submission_centers) && (user.submission_centers.length > 0)) {
user.submission_center = user.submission_centers[0];
}
if (Type.IsArray(user.consortia) && (user.consortia.length > 0)) {
user.consortium = user.consortia[0];
}
return <>
<td style={tdStyle}>
<span id={`tooltip-users-consortium-${user.email}`}>{userMetadata.consortiumTitle(user.consortium) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-consortium-${user.email}`} position="bottom" size="small" text={`Consortium: ${user.consortium}`} />
</td>
<td style={tdStyle}>
<span id={`tooltip-users-submission-center-${user.email}`}>{userMetadata.submissionCenterTitle(user.submission_center) || Char.EmptySet}</span>
<Tooltip id={`tooltip-users-submission-center-${user.email}`} position="bottom" size="small" text={`Submission Center: ${user.submission_center}`} />
</td>
</>
}

export default UsersPage;
Loading

0 comments on commit b8f0a46

Please sign in to comment.