Skip to content

Commit

Permalink
Merge pull request #215 from introlab/dev
Browse files Browse the repository at this point in the history
Main merge for 1.2.2 release
  • Loading branch information
SBriere committed May 23, 2023
2 parents 4b5fa7d + 5ec1032 commit 417b8ab
Show file tree
Hide file tree
Showing 108 changed files with 4,513 additions and 1,280 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,4 @@ venv
joss-paper/paper.jats
joss-paper/paper.pdf
/.vscode
_python-3.10
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
project = 'OpenTera'
copyright = '2023, Simon Brière, Dominic Létourneau'
author = 'Simon Brière, Dominic Létourneau'
release = '1.2.1'
release = '1.2.2'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand Down
2 changes: 1 addition & 1 deletion teraserver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ endif(NOT CMAKE_BUILD_TYPE)
# Software version
SET(OPENTERA_VERSION_MAJOR "1")
SET(OPENTERA_VERSION_MINOR "2")
SET(OPENTERA_VERSION_PATCH "1")
SET(OPENTERA_VERSION_PATCH "2")

SET(OPENTERA_SERVER_VERSION OpenTera_v${OPENTERA_VERSION_MAJOR}.${OPENTERA_VERSION_MINOR}.${OPENTERA_VERSION_PATCH})

Expand Down
66 changes: 5 additions & 61 deletions teraserver/python/TeraServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,46 +27,11 @@
import os
import argparse
from sqlalchemy.exc import OperationalError
import opentera.crypto.crypto_utils as crypto
from opentera.utils.TeraVersions import TeraVersions
from opentera.config.ConfigManager import ConfigManager
import modules.Globals as Globals


def generate_certificates(config: ConfigManager):
"""
Will generate certificates and keys if they do not exist
"""
site_certificate_path = config.server_config['ssl_path'] + '/' + config.server_config['site_certificate']
site_key_path = config.server_config['ssl_path'] + '/' + config.server_config['site_private_key']
ca_certificate_path = config.server_config['ssl_path'] + '/' + config.server_config['ca_certificate']
ca_key_path = config.server_config['ssl_path'] + '/' + config.server_config['ca_private_key']

if not os.path.exists(site_certificate_path) or not os.path.exists(site_key_path):
print('Generating Site certificate and key')
site_info = crypto.generate_local_certificate()
# Save files
crypto.write_private_key_and_certificate(site_info, keyfile=site_key_path, certfile=site_certificate_path)

if not os.path.exists(ca_certificate_path) or not os.path.exists(ca_key_path):
print('Generating Site certificate and key')
ca_info = crypto.generate_ca_certificate(common_name='Local CA')
# Save files
crypto.write_private_key_and_certificate(ca_info, keyfile=ca_key_path, certfile=ca_certificate_path)


def verify_file_upload_directory(config: ConfigManager, create=True):
file_upload_path = config.server_config['upload_path']

if not os.path.exists(file_upload_path):
if create:
# TODO Change permissions?
os.mkdir(file_upload_path, 0o700)
else:
return None
return file_upload_path


def init_shared_variables(config):
# Create user token
from opentera.db.models.TeraServerSettings import TeraServerSettings
Expand Down Expand Up @@ -114,35 +79,17 @@ def init_shared_variables(config):
versions.save_to_db()


def init_services(config: ConfigManager):
def init_opentera_service(config: ConfigManager):
print('Initializing services...')

from opentera.db.models.TeraService import TeraService
from opentera.redis.RedisVars import RedisVars
import json
# Create redis client
import redis
redis_client = redis.Redis(host=config.redis_config['hostname'],
port=config.redis_config['port'],
db=config.redis_config['db'],
username=config.redis_config['username'],
password=config.redis_config['password'])

# Set python path to current folder so that import work from services
tera_python_dir = pathlib.Path(__file__).parent.absolute()
os.environ['PYTHONPATH'] = str(tera_python_dir)

services = TeraService.query.all()
for service in services:
# Ignore special service TeraServer
if service.service_key == 'OpenTeraServer':
Globals.opentera_service_id = service.id_service
continue
if service.service_enabled:
print('Activating service: ' + service.service_key)
redis_client.set(RedisVars.RedisVar_ServicePrefixKey + service.service_key, json.dumps(service.to_json()))
else:
print('Skipping disabled service: ' + service.service_key)
# Update service ID
service = TeraService.get_service_by_key('OpenTeraServer')
Globals.opentera_service_id = service.id_service


if __name__ == '__main__':
Expand Down Expand Up @@ -176,9 +123,6 @@ def init_services(config: ConfigManager):
# Load configuration file.
config_man.load_config(config_file)

# Generate certificate (if required)
generate_certificates(config_man)

try:

if config_man.server_config['enable_docs']:
Expand Down Expand Up @@ -221,7 +165,7 @@ def init_services(config: ConfigManager):
init_shared_variables(config=config_man)

# Initialize enabled services
init_services(config=config_man)
init_opentera_service(config=config_man)

# Main Flask module
flask_module = FlaskModule(config_man)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Add extra projects information
Revision ID: f41b70d6513e
Revises: 65a42f6ee567
Create Date: 2023-05-02 10:04:28.233886
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'f41b70d6513e'
down_revision = '65a42f6ee567'
branch_labels = None
depends_on = None


def upgrade():
# Add extra project informations
op.add_column('t_projects', sa.Column('project_enabled', sa.Boolean, nullable=False, server_default=str(True)))
op.add_column('t_projects', sa.Column('project_description', sa.String, nullable=True))


def downgrade():
# At last, a path back to the light!
op.drop_column('t_projects', 'project_enabled')
op.drop_column('t_projects', 'project_description')
2 changes: 1 addition & 1 deletion teraserver/python/config/external_services.conf
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ location /recrutement/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /webportal;
proxy_set_header X-Script-Name /recrutement;
}

########################################################################################################################
Expand Down
4 changes: 2 additions & 2 deletions teraserver/python/env/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ file(MAKE_DIRECTORY ${ENV_PATH})

# Define packages to install
set (conda_packages
protobuf # ==3.18.1
protobuf==3.20.3
)

if(WIN32)
Expand All @@ -31,7 +31,7 @@ add_custom_target(
# Create environment, will produce python executable
add_custom_command(
OUTPUT ${PYTHON_PATH}
COMMAND ${CONDA_PATH} install -m -c conda-forge -y -p ${ENV_PATH} python=${PYTHON_VERSION} ${conda_packages}
COMMAND ${CONDA_PATH} install -m -c anaconda -y -p ${ENV_PATH} python=${PYTHON_VERSION} ${conda_packages}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

Expand Down
34 changes: 17 additions & 17 deletions teraserver/python/env/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
pypiwin32==223; sys_platform == 'win32'
Twisted==22.10.0
treq==22.2.0
cryptography==39.0.1
cryptography==40.0.2
autobahn==23.1.2
SQLAlchemy==1.4.46
SQLAlchemy==1.4.48
sqlalchemy-schemadisplay==1.3
pydot==1.4.2
psycopg2-binary==2.9.5
Flask==2.2.3
psycopg2-binary==2.9.6
Flask==2.3.2
Flask-SQLAlchemy==3.0.3
Flask-Login==0.6.2
Flask-Login-Multi==0.1.2
Flask-HTTPAuth==4.7.0
Flask-SocketIO==5.3.2
Flask-Session==0.4.0
flask-restx==1.0.6
Flask-HTTPAuth==4.8.0
Flask-SocketIO==5.3.4
Flask-Session==0.5.0
flask-restx==1.1.0
Flask-Security==3.0.0
Flask-Babel==3.0.1
Flask-Babel==3.1.0
Flask-BabelEx==0.9.4
Flask-Migrate==4.0.4
flask-swagger-ui==4.11.1
Flask-Limiter==3.2.0
Flask-Limiter==3.3.1
Flask-Mail==0.9.1
Flask-Principal==0.4.0
redis==4.5.1
txredisapi==1.4.7
redis==4.5.5
txredisapi==1.4.9
passlib==1.7.4
bcrypt==4.0.1
WTForms==3.0.1
pyOpenSSL==23.0.0
pyOpenSSL==23.1.1
service-identity==21.1.0
PyJWT==2.6.0
PyJWT==2.7.0
pylzma==0.5.0
bz2file==0.98
python-slugify==8.0.0
websocket-client==1.5.1
pytest==7.2.1
python-slugify==8.0.1
websocket-client==1.5.2
pytest==7.3.1
jsonschema==4.17.3
Jinja2==3.1.2
ua-parser==0.16.1
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from opentera.db.models.TeraService import TeraService
from opentera.db.models import TeraUser
from opentera.db.models.TeraServiceAccess import TeraServiceAccess
from opentera.db.models.TeraParticipantGroup import TeraParticipantGroup
from opentera.db.models.TeraServiceRole import TeraServiceRole
from opentera.db.models.TeraProject import TeraProject

from sqlalchemy import or_, not_

Expand Down Expand Up @@ -79,12 +83,6 @@ def get_accessible_sessions(self, admin_only=False):
sessions.extend(other_sessions)

return sessions
# from opentera.db.models.TeraSession import TeraSession
# from opentera.db.models.TeraParticipant import TeraParticipant
#
# part_ids = self.get_accessible_participants_ids(admin_only=admin_only)
# return TeraSession.query.join(TeraSession.session_participants). \
# filter(TeraParticipant.id_participant.in_(part_ids)).all()

def get_accessible_sessions_ids(self, admin_only=False):
ses_ids = []
Expand All @@ -95,10 +93,6 @@ def get_accessible_sessions_ids(self, admin_only=False):
return ses_ids

def get_accessibles_sites(self):
# projects = self.get_accessible_projects()
# sites = set([project.project_site for project in projects])
# return list(sites)

# Build site list - get sites where that service is associated
from opentera.db.models.TeraServiceSite import TeraServiceSite
service_sites = TeraServiceSite.get_sites_for_service(self.service.id_service)
Expand Down Expand Up @@ -126,6 +120,14 @@ def get_accessible_participants_ids(self, admin_only=False):
def get_accessible_participants_uuids(self, admin_only=False):
return [participant.participant_uuid for participant in self.get_accessible_participants(admin_only=admin_only)]

def get_accessible_participants_groups(self):
project_id_list = self.get_accessible_projects_ids()
groups = TeraParticipantGroup.query.join(TeraProject).filter(TeraProject.id_project.in_(project_id_list)).all()
return groups

def get_accessible_participants_groups_ids(self):
return [group.id_participant_group for group in self.get_accessible_participants_groups()]

def get_accessible_users(self, admin_only=False):
projects = self.get_accessible_projects(admin_only=admin_only)
users = []
Expand All @@ -140,6 +142,24 @@ def get_accessible_users(self, admin_only=False):
def get_accessible_users_ids(self, admin_only=False):
return [user.id_user for user in self.get_accessible_users(admin_only=admin_only)]

def get_accessible_usergroups(self):
# Usergroup is accessible if it has access to a service site / project or if it has a role in the service
access = TeraServiceAccess.query.join(TeraServiceRole).\
filter(TeraServiceRole.id_service == self.service.id_service).\
filter(TeraServiceAccess.id_user_group is not None).all()

usergroups = []
if access:
for service_access in access:
ug = service_access.service_access_user_group
if ug not in usergroups:
usergroups.append(ug)

return usergroups

def get_accessible_usergroups_ids(self):
return [ug.id_user_group for ug in self.get_accessible_usergroups()]

def get_accessible_users_uuids(self, admin_only=False):
return [user.user_uuid for user in self.get_accessible_users(admin_only=admin_only)]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ def get_accessible_users_ids(self, admin_only=False):
users_ids.append(user.id_user)
return users_ids

def get_accessible_users(self, admin_only=False):
def get_accessible_users(self, admin_only=False, include_site_access=False):
if self.user.user_superadmin:
users = TeraUser.query.order_by(TeraUser.user_firstname.asc()).all()
else:
projects = self.get_accessible_projects(admin_only=admin_only)
users = []
for project in projects:
project_users = project.get_users_in_project()
project_users = project.get_users_in_project(include_site_access=include_site_access)
for user in project_users:
if user not in users:
users.append(user)
Expand Down Expand Up @@ -1182,7 +1182,8 @@ def query_usergroups_for_user(self, user_id: int):

def query_users_for_site(self, site_id: int, enabled_only: bool = False, admin_only: bool = False,
include_super_admins: bool = False):
accessible_users = self.get_accessible_users()
# is_site_admin = self.get_site_role(site_id) == 'admin'
accessible_users = self.get_accessible_users(include_site_access=True)
users = set()
for user in accessible_users:
if (enabled_only and not user.user_enabled) or (not include_super_admins and user.user_superadmin):
Expand All @@ -1196,7 +1197,12 @@ def query_users_for_site(self, site_id: int, enabled_only: bool = False, admin_o

def query_users_for_project(self, project_id: int, enabled_only: bool = False, admin_only: bool = False,
include_super_admins: bool = False):
accessible_users = self.get_accessible_users()

# Only returns site admins users if itself is site admin!
# project = TeraProject.get_project_by_id(project_id)
# is_site_admin = self.get_site_role(project.id_site) == 'admin'
accessible_users = self.get_accessible_users(include_site_access=True)

users = set()
for user in accessible_users:
if enabled_only and not user.user_enabled or (not include_super_admins and user.user_superadmin):
Expand Down Expand Up @@ -1263,7 +1269,7 @@ def query_service_configs(self, service_id: int = None, user_id: int = None, dev
return services_configs

def query_service_access(self, user_group_id: int = None, device_id: int = None, participant_group_id: int = None,
service_id: int = None):
service_id: int = None, user_id: int = None):
from opentera.db.models.TeraServiceAccess import TeraServiceAccess
from opentera.db.models.TeraServiceRole import TeraServiceRole
accessible_services_ids = self.get_accessible_services_ids()
Expand All @@ -1275,6 +1281,11 @@ def query_service_access(self, user_group_id: int = None, device_id: int = None,
query = query.filter_by(id_device=device_id)
if participant_group_id:
query = query.filter_by(id_participant_group=participant_group_id)
if user_id:
user = TeraUser.get_user_by_id(user_id)
user_groups_ids = [ug.id_user_group for ug in user.user_user_groups]
query = query.filter(TeraServiceAccess.id_user_group.in_(user_groups_ids))

if service_id:
query = query.join(TeraServiceAccess.service_access_role).filter_by(id_service=service_id)
else:
Expand Down

0 comments on commit 417b8ab

Please sign in to comment.