diff --git a/applications/accounts-api/api/openapi.yaml b/applications/accounts-api/api/openapi.yaml index 455422a7..c2d7ab18 100644 --- a/applications/accounts-api/api/openapi.yaml +++ b/applications/accounts-api/api/openapi.yaml @@ -1,199 +1,181 @@ ---- openapi: 3.0.2 info: - title: accounts_api - version: 0.1.0 - description: Accounts rest api - contact: - email: cloudharness@metacell.us - license: - name: UNLICENSED + title: accounts_api + version: 0.1.0 + description: Accounts rest api + contact: + email: cloudharness@metacell.us + license: + name: UNLICENSED servers: -- url: /api + - + url: /api paths: - /live: - get: - tags: - - infrastructure - responses: - "200": - content: - application/json: - schema: - type: string - description: Healthy - "500": - description: Application is not healthy - operationId: live - summary: Test if application is healthy - /ready: - get: - tags: - - infrastructure - responses: - "200": - content: - application/json: - schema: - type: string - description: Ready - "500": - description: Application is not ready yet - operationId: ready - summary: Test if application is ready to take requests - /users: - get: - summary: Get list of users based on query - operationId: get_users - parameters: - - description: query filter - in: query - name: query_string - required: false - schema: - type: string - security: - - bearerAuth: [] - responses: - "200": - content: - application/json: - schema: - type: object - properties: - users: - type: array - items: - $ref: '#/components/schemas/User' - description: Get list of users - tags: - - users - x-openapi-router-controller: accounts_api.controllers.users_controller - post: - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/User' - required: true - tags: - - users - responses: - "200": - content: - application/json: - schema: - $ref: '#/components/schemas/User' - description: The user as just saved - security: - - bearerAuth: [] - operationId: createUser - /users/{userid}: - get: - tags: - - users - parameters: - - name: userid - description: user id - schema: - type: string - in: path - required: true - responses: - "200": - content: - application/json: - schema: - $ref: '#/components/schemas/User' - description: Get a user's public information - operationId: getUser - put: - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/User' - required: true - tags: - - users - responses: - "200": - content: - application/json: - schema: - $ref: '#/components/schemas/User' - description: The user as just saved - security: - - bearerAuth: [] - operationId: updateUser - parameters: - - name: userid - description: user id - schema: - type: string - in: path - required: true + /live: + get: + tags: + - infrastructure + responses: + '200': + content: + application/json: + schema: + type: string + description: Healthy + '500': + description: Application is not healthy + operationId: live + summary: Test if application is healthy + /ready: + get: + tags: + - infrastructure + responses: + '200': + content: + application/json: + schema: + type: string + description: Ready + '500': + description: Application is not ready yet + operationId: ready + summary: Test if application is ready to take requests + /users: + post: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + required: true + tags: + - users + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: The user as just saved + security: + - + bearerAuth: [] + operationId: createUser + '/users/{userid}': + get: + tags: + - users + parameters: + - + name: userid + description: user id + schema: + type: string + in: path + required: true + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: Get a user's public information + operationId: getUser + put: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/User' + required: true + tags: + - users + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/User' + description: The user as just saved + security: + - + bearerAuth: [] + operationId: updateUser + parameters: + - + name: userid + description: user id + schema: + type: string + in: path + required: true components: - schemas: - Valid: - type: object - properties: - response: - type: string - Url: - description: "" - type: string - User: - description: Keycloak User - type: object - properties: - id: - description: user id - type: string - username: - description: Username of the keycloak user - type: string - email: - description: Email address of the keycloak user - type: string - firstName: - description: First Name of the keycloak user - type: string - lastName: - description: Last Name of the keycloak user - type: string - groups: - description: "" - type: array - items: + schemas: + Valid: + type: object + properties: + response: + type: string + Url: + description: '' type: string - readOnly: true - profiles: - $ref: '#/components/schemas/Profiles' - description: "External links to user profiles (e.g. GitHub, Twitter, etc.)" - registrationDate: - format: date - description: "" - type: string - avatar: - $ref: '#/components/schemas/Url' - description: "" - website: - $ref: '#/components/schemas/Url' - description: "" - additionalProperties: true - Profiles: - description: "" - type: object - additionalProperties: true - securitySchemes: - bearerAuth: - scheme: bearer - bearerFormat: JWT - type: http - x-bearerInfoFunc: cloudharness.auth.decode_token + Profiles: + description: '' + type: object + additionalProperties: true + User: + description: Keycloak User + type: object + properties: + id: + description: user id + type: string + username: + description: Username of the keycloak user + type: string + email: + description: Email address of the keycloak user + type: string + firstName: + description: First Name of the keycloak user + type: string + lastName: + description: Last Name of the keycloak user + type: string + groups: + description: '' + type: array + items: + type: string + readOnly: true + profiles: + $ref: '#/components/schemas/Profiles' + description: 'External links to user profiles (e.g. GitHub, Twitter, etc.)' + registrationDate: + format: date + description: '' + type: string + avatar: + $ref: '#/components/schemas/Url' + description: '' + website: + $ref: '#/components/schemas/Url' + description: '' + quotas: + $ref: '#/components/schemas/Profiles' + description: '' + additionalProperties: true + securitySchemes: + bearerAuth: + scheme: bearer + bearerFormat: JWT + type: http + x-bearerInfoFunc: cloudharness.auth.decode_token tags: -- name: infrastructure - description: "" -- name: users - description: "" + - + name: infrastructure + description: '' + - + name: users + description: '' diff --git a/applications/accounts-api/backend/accounts_api/models/base_model_.py b/applications/accounts-api/backend/accounts_api/models/base_model_.py index b027aebf..48b2ff79 100644 --- a/applications/accounts-api/backend/accounts_api/models/base_model_.py +++ b/applications/accounts-api/backend/accounts_api/models/base_model_.py @@ -11,11 +11,11 @@ class Model(object): # openapiTypes: The key is attribute name and the # value is attribute type. - openapi_types = {} + openapi_types: typing.Dict[str, type] = {} # attributeMap: The key is attribute name and the # value is json key in definition. - attribute_map = {} + attribute_map: typing.Dict[str, str] = {} @classmethod def from_dict(cls: typing.Type[T], dikt) -> T: diff --git a/applications/accounts-api/backend/accounts_api/models/user.py b/applications/accounts-api/backend/accounts_api/models/user.py index d1220bb9..35013b1b 100644 --- a/applications/accounts-api/backend/accounts_api/models/user.py +++ b/applications/accounts-api/backend/accounts_api/models/user.py @@ -15,7 +15,7 @@ class User(Model): Do not edit the class manually. """ - def __init__(self, id=None, username=None, email=None, first_name=None, last_name=None, groups=None, profiles=None, registration_date=None, avatar=None, website=None): # noqa: E501 + def __init__(self, id=None, username=None, email=None, first_name=None, last_name=None, groups=None, profiles=None, registration_date=None, avatar=None, website=None, quotas=None): # noqa: E501 """User - a model defined in OpenAPI :param id: The id of this User. # noqa: E501 @@ -38,6 +38,8 @@ def __init__(self, id=None, username=None, email=None, first_name=None, last_nam :type avatar: str :param website: The website of this User. # noqa: E501 :type website: str + :param quotas: The quotas of this User. # noqa: E501 + :type quotas: Dict[str, object] """ self.openapi_types = { 'id': str, @@ -49,7 +51,8 @@ def __init__(self, id=None, username=None, email=None, first_name=None, last_nam 'profiles': Dict[str, object], 'registration_date': date, 'avatar': str, - 'website': str + 'website': str, + 'quotas': Dict[str, object] } self.attribute_map = { @@ -62,7 +65,8 @@ def __init__(self, id=None, username=None, email=None, first_name=None, last_nam 'profiles': 'profiles', 'registration_date': 'registrationDate', 'avatar': 'avatar', - 'website': 'website' + 'website': 'website', + 'quotas': 'quotas' } self._id = id @@ -75,6 +79,7 @@ def __init__(self, id=None, username=None, email=None, first_name=None, last_nam self._registration_date = registration_date self._avatar = avatar self._website = website + self._quotas = quotas @classmethod def from_dict(cls, dikt) -> 'User': @@ -206,6 +211,7 @@ def last_name(self, last_name): def groups(self): """Gets the groups of this User. + # noqa: E501 :return: The groups of this User. :rtype: List[str] @@ -216,6 +222,7 @@ def groups(self): def groups(self, groups): """Sets the groups of this User. + # noqa: E501 :param groups: The groups of this User. :type groups: List[str] @@ -227,7 +234,7 @@ def groups(self, groups): def profiles(self): """Gets the profiles of this User. - sddssd # noqa: E501 + # noqa: E501 :return: The profiles of this User. :rtype: Dict[str, object] @@ -238,7 +245,7 @@ def profiles(self): def profiles(self, profiles): """Sets the profiles of this User. - sddssd # noqa: E501 + # noqa: E501 :param profiles: The profiles of this User. :type profiles: Dict[str, object] @@ -250,6 +257,7 @@ def profiles(self, profiles): def registration_date(self): """Gets the registration_date of this User. + # noqa: E501 :return: The registration_date of this User. :rtype: date @@ -260,6 +268,7 @@ def registration_date(self): def registration_date(self, registration_date): """Sets the registration_date of this User. + # noqa: E501 :param registration_date: The registration_date of this User. :type registration_date: date @@ -271,6 +280,7 @@ def registration_date(self, registration_date): def avatar(self): """Gets the avatar of this User. + # noqa: E501 :return: The avatar of this User. :rtype: str @@ -281,6 +291,7 @@ def avatar(self): def avatar(self, avatar): """Sets the avatar of this User. + # noqa: E501 :param avatar: The avatar of this User. :type avatar: str @@ -292,6 +303,7 @@ def avatar(self, avatar): def website(self): """Gets the website of this User. + # noqa: E501 :return: The website of this User. :rtype: str @@ -302,9 +314,33 @@ def website(self): def website(self, website): """Sets the website of this User. + # noqa: E501 :param website: The website of this User. :type website: str """ self._website = website + + @property + def quotas(self): + """Gets the quotas of this User. + + # noqa: E501 + + :return: The quotas of this User. + :rtype: Dict[str, object] + """ + return self._quotas + + @quotas.setter + def quotas(self, quotas): + """Sets the quotas of this User. + + # noqa: E501 + + :param quotas: The quotas of this User. + :type quotas: Dict[str, object] + """ + + self._quotas = quotas diff --git a/applications/accounts-api/backend/accounts_api/openapi/openapi.yaml b/applications/accounts-api/backend/accounts_api/openapi/openapi.yaml index 1f5a38b5..d7407cdc 100644 --- a/applications/accounts-api/backend/accounts_api/openapi/openapi.yaml +++ b/applications/accounts-api/backend/accounts_api/openapi/openapi.yaml @@ -10,8 +10,10 @@ info: servers: - url: /api tags: -- name: infrastructure -- name: users +- description: "" + name: infrastructure +- description: "" + name: users paths: /live: get: @@ -46,33 +48,6 @@ paths: - infrastructure x-openapi-router-controller: accounts_api.controllers.infrastructure_controller /users: - get: - summary: Get list of users based on query - operationId: get_users - parameters: - - description: query filter - in: query - name: query_string - required: false - schema: - type: string - security: - - bearerAuth: [] - responses: - "200": - content: - application/json: - schema: - type: object - properties: - users: - type: array - items: - $ref: '#/components/schemas/User' - description: Get list of users - tags: - - users - x-openapi-router-controller: accounts_api.controllers.users_controller post: operationId: create_user requestBody: @@ -152,7 +127,12 @@ components: type: string type: object Url: + description: "" type: string + Profiles: + additionalProperties: true + description: "" + type: object User: additionalProperties: true description: Keycloak User @@ -160,8 +140,10 @@ components: firstName: firstName lastName: lastName website: website + quotas: + key: "" profiles: - key: '{}' + key: "" registrationDate: 2000-01-23 groups: - groups @@ -187,27 +169,31 @@ components: description: Last Name of the keycloak user type: string groups: + description: "" items: type: string readOnly: true type: array profiles: additionalProperties: true - description: sddssd + description: "" type: object registrationDate: + description: "" format: date type: string avatar: + description: "" type: string website: + description: "" type: string + quotas: + additionalProperties: true + description: "" + type: object title: User type: object - Profiles: - additionalProperties: true - description: sddssd - type: object securitySchemes: bearerAuth: bearerFormat: JWT diff --git a/applications/accounts-api/backend/accounts_api/services/user_service.py b/applications/accounts-api/backend/accounts_api/services/user_service.py index 9ed39824..f63c38aa 100644 --- a/applications/accounts-api/backend/accounts_api/services/user_service.py +++ b/applications/accounts-api/backend/accounts_api/services/user_service.py @@ -1,4 +1,7 @@ from datetime import datetime +import os +from cloudharness.applications import get_configuration +from cloudharness.auth.quota import get_user_quotas from keycloak.exceptions import KeycloakGetError, KeycloakError from accounts_api.models import User from cloudharness.auth import AuthClient @@ -13,7 +16,7 @@ class UserNotAuthorized(Exception): pass def get_user(username_or_id: str) -> User: - client = AuthClient() + client = AuthClient(username=os.getenv('ACCOUNTS_ADMIN_USERNAME', None), password=os.getenv('ACCOUNTS_ADMIN_PASSWORD', None)) try: kc_user = client.get_user(username_or_id) @@ -35,6 +38,11 @@ def get_user(username_or_id: str) -> User: except: # user not provided log.error("Error checking user", exc_info=True) user.email = None + + + ws_quotas = get_user_quotas(get_configuration('workspaces'), user_id=user.id) + hub_quotas = get_user_quotas(get_configuration('jupyterhub'), user_id=user.id) + user.quotas = {**ws_quotas, **hub_quotas} return user diff --git a/applications/accounts/Dockerfile b/applications/accounts/Dockerfile index c14b452f..58495c81 100644 --- a/applications/accounts/Dockerfile +++ b/applications/accounts/Dockerfile @@ -8,5 +8,5 @@ USER jboss # Customize keycloak look COPY themes/custom /opt/jboss/keycloak/themes/custom -# keycloak kafka listener plugin -COPY plugins/metacell-admin-event-listener-bundle-1.0.0.ear /opt/jboss/keycloak/standalone/deployments/ +# plugins +COPY plugins/* /opt/jboss/keycloak/standalone/deployments/ diff --git a/applications/accounts/deploy/resources/realm.json b/applications/accounts/deploy/resources/realm.json index 2a2b4647..d3e9e060 100644 --- a/applications/accounts/deploy/resources/realm.json +++ b/applications/accounts/deploy/resources/realm.json @@ -43,6 +43,46 @@ "duplicateEmailsAllowed": false, "resetPasswordAllowed": true, "editUsernameAllowed": true, + "identityProviders": [ + { + "alias": "orcid", + "internalId": "2ab5a52e-60f2-411b-86af-ae58224155e3", + "providerId": "orcid", + "enabled": true, + "updateProfileFirstLoginMode": "on", + "trustEmail": false, + "storeToken": false, + "addReadTokenRoleOnCreate": false, + "authenticateByDefault": false, + "linkOnly": false, + "firstBrokerLoginFlowAlias": "first broker login", + "config": { + "syncMode": "IMPORT", + "clientSecret": "**********", + "clientId": "APP-ZBK69Z38RMGG6G0R", + "useJwksUrl": "true" + } + }, + { + "alias": "github", + "internalId": "a22eb498-74dc-4d64-9bcd-38e2623c1af2", + "providerId": "github", + "enabled": true, + "updateProfileFirstLoginMode": "on", + "trustEmail": false, + "storeToken": false, + "addReadTokenRoleOnCreate": false, + "authenticateByDefault": false, + "linkOnly": false, + "firstBrokerLoginFlowAlias": "first broker login", + "config": { + "syncMode": "IMPORT", + "clientSecret": "**********", + "clientId": "97a77871b8005be03669", + "useJwksUrl": "true" + } + } + ], "users": [ {{- range $app := .Values.apps }} {{- if (hasKey $app.harness "accounts") }} diff --git a/applications/accounts/docker-compose.yaml b/applications/accounts/docker-compose.yaml index d30fe03b..3ca0a1ba 100644 --- a/applications/accounts/docker-compose.yaml +++ b/applications/accounts/docker-compose.yaml @@ -8,7 +8,7 @@ services: POSTGRES_USER: keycloak POSTGRES_PASSWORD: password keycloak: - image: quay.io/keycloak/keycloak:11.0.2 + image: quay.io/keycloak/keycloak:16.1.0 environment: DB_VENDOR: POSTGRES DB_ADDR: postgres diff --git a/applications/accounts/plugins/keycloak-orcid-1.0.0.jar b/applications/accounts/plugins/keycloak-orcid-1.0.0.jar new file mode 100644 index 00000000..fd7c6c2b Binary files /dev/null and b/applications/accounts/plugins/keycloak-orcid-1.0.0.jar differ diff --git a/applications/jupyterhub/deploy/values-minimal.yaml b/applications/jupyterhub/deploy/values-minimal.yaml new file mode 100644 index 00000000..9054ed69 --- /dev/null +++ b/applications/jupyterhub/deploy/values-minimal.yaml @@ -0,0 +1,4 @@ +harness: + dependencies: + soft: [nfsserver, accounts] + hard: [] diff --git a/applications/jupyterhub/src/chauthenticator/chauthenticator/auth.py b/applications/jupyterhub/src/chauthenticator/chauthenticator/auth.py index 3f32dac6..cea91077 100644 --- a/applications/jupyterhub/src/chauthenticator/chauthenticator/auth.py +++ b/applications/jupyterhub/src/chauthenticator/chauthenticator/auth.py @@ -13,11 +13,13 @@ handler.setLevel(logging.DEBUG) logging.getLogger().addHandler(handler) + class CloudHarnessAuthenticateHandler(BaseHandler): """ Handler for /chkclogin Creates a new user based on the keycloak user, and auto starts their server """ + def initialize(self, force_new_server, process_user): super().initialize() self.force_new_server = force_new_server @@ -28,28 +30,36 @@ def get(self): self.clear_login_cookie() try: - - accessToken = self.request.cookies.get( - 'kc-access', None) or self.request.cookies.get('accessToken', None) - print("Token", accessToken) - if accessToken == '-1' or not accessToken: - import socket - raw_user = self.user_from_username("a-%s-%0.5x" % (socket.inet_aton(self.request.remote_ip).hex(), random.randint(0, 99999))) - else: - accessToken = accessToken.value - user_data = AuthClient.decode_token(accessToken) - username = user_data['sub'] - print("Username", username, "-",user_data['preferred_username']) - raw_user = self.user_from_username(username) - print("JH user: ", raw_user.__dict__) - self.set_login_cookie(raw_user) + + accessToken = self.request.cookies.get( + 'kc-access', None) or self.request.cookies.get('accessToken', None) + print("Token", accessToken) + if accessToken == '-1' or not accessToken: + + raw_user = self.get_anonymous_user() + else: + accessToken = accessToken.value + user_data = AuthClient.decode_token(accessToken) + username = user_data['sub'] + print("Username", username, "-", + user_data['preferred_username']) + raw_user = self.user_from_username(username) + except Exception as e: - logging.error("Error getting user from session", exc_info=True) - raise + logging.info("Error getting user from session", exc_info=True) + self.request.cookies.clear() + raw_user = self.get_anonymous_user() + print("JH user: ", raw_user.__dict__) + self.set_login_cookie(raw_user) user = yield gen.maybe_future(self.process_user(raw_user, self)) self.redirect(self.get_next_url(user)) + def get_anonymous_user(self): + import socket + print("Anonymous connection: ", self.request.remote_ip) + return self.user_from_username("a-%s-%0.5x" % (socket.inet_aton(self.request.remote_ip).hex(), random.randint(0, 99999))) + class CloudHarnessAuthenticator(Authenticator): """ diff --git a/applications/jupyterhub/src/osb_jupyter/osb_jupyter/jupyterhub.py b/applications/jupyterhub/src/osb_jupyter/osb_jupyter/jupyterhub.py index 423e5c50..414e94b9 100755 --- a/applications/jupyterhub/src/osb_jupyter/osb_jupyter/jupyterhub.py +++ b/applications/jupyterhub/src/osb_jupyter/osb_jupyter/jupyterhub.py @@ -113,14 +113,11 @@ def workspace_volume_is_legacy(workspace_id): }) except CookieNotFound: # Setup a readonly default session - self.pod_name = f'anonymous-{self.user.username}-{appname}' - from pprint import pprint - pprint(self.volumes) - + self.pod_name = f'anonymous-{self.user.name}-{appname}' + self.storage_pvc_ensure = False self.volumes = [] - pprint(self.volume_mounts) self.volume_mounts = [] - self.maxAge + print("Starting anonymoous session with no volumes") except Exception as e: log.error('Change pod manifest failed due to an error.', exc_info=True) diff --git a/applications/jupyterlab-minimal/Dockerfile b/applications/jupyterlab-minimal/Dockerfile index c055ce77..0c0770c9 100644 --- a/applications/jupyterlab-minimal/Dockerfile +++ b/applications/jupyterlab-minimal/Dockerfile @@ -4,4 +4,5 @@ COPY hub/jupyter_notebook_config.py /etc/jupyter/jupyter_notebook_config.py USER root RUN mkdir /opt/workspace RUN chown -R jovyan:users /opt/workspace -USER jovyan \ No newline at end of file +COPY --chown=jovyan:users overrides/* /opt/conda/share/jupyter/lab/static/ +USER jovyan diff --git a/applications/jupyterlab-minimal/deploy/values.yaml b/applications/jupyterlab-minimal/deploy/values.yaml index d5264ee5..fc99dbec 100644 --- a/applications/jupyterlab-minimal/deploy/values.yaml +++ b/applications/jupyterlab-minimal/deploy/values.yaml @@ -20,5 +20,5 @@ harness: c.Spawner.http_timeout = 300 c.Spawner.start_timeout = 300 - c.JupyterHub.tornado_settings = { "headers": { "Content-Security-Policy": "frame-ancestors 'self' localhost:3000 *.osb.local osb.local localhost *.metacell.us *.opensourcebrain.org"}} + c.JupyterHub.tornado_settings = { "headers": { "Content-Security-Policy": "frame-ancestors *"}} diff --git a/applications/jupyterlab-minimal/hub/jupyter_notebook_config.py b/applications/jupyterlab-minimal/hub/jupyter_notebook_config.py index c3cbd116..a23e00ad 100644 --- a/applications/jupyterlab-minimal/hub/jupyter_notebook_config.py +++ b/applications/jupyterlab-minimal/hub/jupyter_notebook_config.py @@ -20,7 +20,7 @@ print(c.NotebookApp.tornado_settings) c.NotebookApp.tornado_settings = { 'headers': { - 'Content-Security-Policy': "frame-ancestors 'self' localhost:3000 localhost *.osb.local *.opensourcebrain.org", + 'Content-Security-Policy': "frame-ancestors *", } } print(c.NotebookApp.tornado_settings) diff --git a/applications/jupyterlab-minimal/overrides/index.html b/applications/jupyterlab-minimal/overrides/index.html new file mode 100644 index 00000000..0a0a9542 --- /dev/null +++ b/applications/jupyterlab-minimal/overrides/index.html @@ -0,0 +1,72 @@ + + + + + + JupyterLab + {# Copy so we do not modify the page_config with + updates. #} {% set page_config_full = page_config.copy() %} {# Set a dummy variable - we just want the side effect + of the update. #} {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} + {% block favicon %} + + + {% endblock %} + + + + + + + + \ No newline at end of file diff --git a/applications/jupyterlab/Dockerfile b/applications/jupyterlab/Dockerfile index b3313c70..7f8f4a16 100644 --- a/applications/jupyterlab/Dockerfile +++ b/applications/jupyterlab/Dockerfile @@ -92,5 +92,5 @@ RUN pip install -r requirements.txt --upgrade --no-cache-dir ######################################################################### - +COPY --chown=jovyan:users overrides/* /opt/conda/share/jupyter/lab/static/ WORKDIR /opt/workspace diff --git a/applications/jupyterlab/overrides/index.html b/applications/jupyterlab/overrides/index.html new file mode 100644 index 00000000..bf3a6746 --- /dev/null +++ b/applications/jupyterlab/overrides/index.html @@ -0,0 +1,72 @@ + + + + + + JupyterLab + {# Copy so we do not modify the page_config with + updates. #} {% set page_config_full = page_config.copy() %} {# Set a dummy variable - we just want the side effect + of the update. #} {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %} + {% block favicon %} + + + {% endblock %} + + + + + + + + \ No newline at end of file diff --git a/applications/netpyne/Dockerfile b/applications/netpyne/Dockerfile index 3e58e618..f7ea8b2d 100644 --- a/applications/netpyne/Dockerfile +++ b/applications/netpyne/Dockerfile @@ -1,4 +1,4 @@ -FROM node:13.14 as jsbuild +FROM node:14 as jsbuild ENV REPO=https://github.com/MetaCell/NetPyNE-UI.git ENV BRANCH_TAG=release/1.0.0 ENV FOLDER=netpyne diff --git a/applications/netpyne/overrides/requirements.txt b/applications/netpyne/overrides/requirements.txt index b1236668..f1b26169 100644 --- a/applications/netpyne/overrides/requirements.txt +++ b/applications/netpyne/overrides/requirements.txt @@ -1,2 +1,3 @@ lfpykit==0.5.1 +pyNeuroML>=0.7.5 git+https://github.com/Neurosim-lab/netpyne.git@osbv2 \ No newline at end of file diff --git a/applications/nfsserver/deploy/values-dev.yaml b/applications/nfsserver/deploy/values-dev.yaml index c0ec34ae..a2b66b9e 100644 --- a/applications/nfsserver/deploy/values-dev.yaml +++ b/applications/nfsserver/deploy/values-dev.yaml @@ -1,2 +1,4 @@ nfs: - useDNS: true \ No newline at end of file + useDNS: true +server: + diskSize: 20Gi \ No newline at end of file diff --git a/applications/nfsserver/deploy/values.yaml b/applications/nfsserver/deploy/values.yaml index 42607a99..be457168 100644 --- a/applications/nfsserver/deploy/values.yaml +++ b/applications/nfsserver/deploy/values.yaml @@ -1,4 +1,4 @@ # nfs server pvc disk size (/exports) server: - diskSize: 20Gi + diskSize: 40Gi diff --git a/applications/osb-portal/src/components/repository/RepositoryPageDetails.tsx b/applications/osb-portal/src/components/repository/RepositoryPageDetails.tsx index 150ab0db..18e0e9a9 100644 --- a/applications/osb-portal/src/components/repository/RepositoryPageDetails.tsx +++ b/applications/osb-portal/src/components/repository/RepositoryPageDetails.tsx @@ -227,7 +227,7 @@ const RepositoryPageDetails = ({ overflow: "auto", }} > - + ({ iframe: { flex: 1, + border: "none", }, })); @@ -117,7 +118,6 @@ export const WorkspaceFrame = (props: { return (