Skip to content

Commit

Permalink
Email server setup
Browse files Browse the repository at this point in the history
Signed-off-by: ZhuoweiWen <[email protected]>
  • Loading branch information
ZhuoweiWen committed Jul 21, 2024
1 parent 0536fea commit 89033c0
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 149 deletions.
44 changes: 22 additions & 22 deletions back-end/Dockerfile.backend
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,37 @@ RUN git clone https://github.com/mapbox/tippecanoe.git && \
# Check if Tippecanoe is in PATH
RUN which tippecanoe || { echo 'Tippecanoe not found in PATH'; exit 1; }

# Set the working directory to /Signal-Server
WORKDIR /Signal-Server
# # Set the working directory to /Signal-Server
# WORKDIR /Signal-Server

# Clone Signal-Server repository
RUN git clone https://github.com/Cloud-RF/Signal-Server.git .
# # Clone Signal-Server repository
# RUN git clone https://github.com/Cloud-RF/Signal-Server.git .

# Change to the source directory and build the binaries
WORKDIR /Signal-Server/src
# # Change to the source directory and build the binaries
# WORKDIR /Signal-Server/src

# Before running cmake, we should ensure that the RUNTIME DESTINATION is specified in CMakeLists.txt.
RUN sed -i 's/install(TARGETS signalserver)/install(TARGETS signalserver RUNTIME DESTINATION bin)/' CMakeLists.txt
RUN sed -i 's/install(TARGETS signalserverHD)/install(TARGETS signalserverHD RUNTIME DESTINATION bin)/' CMakeLists.txt
RUN sed -i 's/install(TARGETS signalserverLIDAR)/install(TARGETS signalserverLIDAR RUNTIME DESTINATION bin)/' CMakeLists.txt
# # Before running cmake, we should ensure that the RUNTIME DESTINATION is specified in CMakeLists.txt.
# RUN sed -i 's/install(TARGETS signalserver)/install(TARGETS signalserver RUNTIME DESTINATION bin)/' CMakeLists.txt
# RUN sed -i 's/install(TARGETS signalserverHD)/install(TARGETS signalserverHD RUNTIME DESTINATION bin)/' CMakeLists.txt
# RUN sed -i 's/install(TARGETS signalserverLIDAR)/install(TARGETS signalserverLIDAR RUNTIME DESTINATION bin)/' CMakeLists.txt

# Run cmake and make, specifying a runtime destination
RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local . && \
make
# # Run cmake and make, specifying a runtime destination
# RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local . && \
# make

# Add /usr/local/bin to the PATH, just in case it's not
ENV PATH="/Signal-Server/src:${PATH}"
# # Add /usr/local/bin to the PATH, just in case it's not
# ENV PATH="/Signal-Server/src:${PATH}"

# Check if signalserver is in PATH
RUN which signalserver || { echo 'Signal-Server not found in PATH'; exit 1; }
# # Check if signalserver is in PATH
# RUN which signalserver || { echo 'Signal-Server not found in PATH'; exit 1; }

WORKDIR /Signal-Server/output/GoogleEarth
# Modify runsig.sh to use signalserverHD instead of signalserver
RUN sed -i 's/time signalserver -sdf/time signalserverHD -sdf/' runsig.sh
# WORKDIR /Signal-Server/output/GoogleEarth
# # Modify runsig.sh to use signalserverHD instead of signalserver
# RUN sed -i 's/time signalserver -sdf/time signalserverHD -sdf/' runsig.sh

ENV PATH="/Signal-Server/output/GoogleEarth:${PATH}"
# ENV PATH="/Signal-Server/output/GoogleEarth:${PATH}"

Run which runsig.sh || { echo 'runsig not found in PATH'; exit 1; }
# Run which runsig.sh || { echo 'runsig not found in PATH'; exit 1; }

WORKDIR /app

Expand Down
44 changes: 22 additions & 22 deletions back-end/Dockerfile.worker
Original file line number Diff line number Diff line change
Expand Up @@ -33,37 +33,37 @@ RUN git clone https://github.com/mapbox/tippecanoe.git && \
# Check if Tippecanoe is in PATH
RUN which tippecanoe || { echo 'Tippecanoe not found in PATH'; exit 1; }

# Set the working directory to /Signal-Server
WORKDIR /Signal-Server
# # Set the working directory to /Signal-Server
# WORKDIR /Signal-Server

# Clone Signal-Server repository
RUN git clone https://github.com/Cloud-RF/Signal-Server.git .
# # Clone Signal-Server repository
# RUN git clone https://github.com/Cloud-RF/Signal-Server.git .

# Change to the source directory and build the binaries
WORKDIR /Signal-Server/src
# # Change to the source directory and build the binaries
# WORKDIR /Signal-Server/src

# Before running cmake, we should ensure that the RUNTIME DESTINATION is specified in CMakeLists.txt.
RUN sed -i 's/install(TARGETS signalserver)/install(TARGETS signalserver RUNTIME DESTINATION bin)/' CMakeLists.txt
RUN sed -i 's/install(TARGETS signalserverHD)/install(TARGETS signalserverHD RUNTIME DESTINATION bin)/' CMakeLists.txt
RUN sed -i 's/install(TARGETS signalserverLIDAR)/install(TARGETS signalserverLIDAR RUNTIME DESTINATION bin)/' CMakeLists.txt
# # Before running cmake, we should ensure that the RUNTIME DESTINATION is specified in CMakeLists.txt.
# RUN sed -i 's/install(TARGETS signalserver)/install(TARGETS signalserver RUNTIME DESTINATION bin)/' CMakeLists.txt
# RUN sed -i 's/install(TARGETS signalserverHD)/install(TARGETS signalserverHD RUNTIME DESTINATION bin)/' CMakeLists.txt
# RUN sed -i 's/install(TARGETS signalserverLIDAR)/install(TARGETS signalserverLIDAR RUNTIME DESTINATION bin)/' CMakeLists.txt

# Run cmake and make, specifying a runtime destination
RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local . && \
make
# # Run cmake and make, specifying a runtime destination
# RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local . && \
# make

# Add /usr/local/bin to the PATH, just in case it's not
ENV PATH="/Signal-Server/src:${PATH}"
# # Add /usr/local/bin to the PATH, just in case it's not
# ENV PATH="/Signal-Server/src:${PATH}"

# Check if signalserver is in PATH
RUN which signalserver || { echo 'Signal-Server not found in PATH'; exit 1; }
# # Check if signalserver is in PATH
# RUN which signalserver || { echo 'Signal-Server not found in PATH'; exit 1; }

WORKDIR /Signal-Server/output/GoogleEarth
# Modify runsig.sh to use signalserverHD instead of signalserver
RUN sed -i 's/time signalserver -sdf/time signalserverHD -sdf/' runsig.sh
# WORKDIR /Signal-Server/output/GoogleEarth
# # Modify runsig.sh to use signalserverHD instead of signalserver
# RUN sed -i 's/time signalserver -sdf/time signalserverHD -sdf/' runsig.sh

ENV PATH="/Signal-Server/output/GoogleEarth:${PATH}"
# ENV PATH="/Signal-Server/output/GoogleEarth:${PATH}"

Run which runsig.sh || { echo 'runsig not found in PATH'; exit 1; }
# Run which runsig.sh || { echo 'runsig not found in PATH'; exit 1; }

WORKDIR /app

Expand Down
20 changes: 16 additions & 4 deletions back-end/controllers/database_controller/user_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,38 @@ def get_user_with_username(user_name, session=None):
if owns_session:
session.close()

def create_user_in_db(username, password, providerid, brandname):
def create_user_in_db(username, password):
session = Session()
try:
existing_user = get_user_with_username(username, session)
if existing_user:
logger.debug(existing_user)
return {"error": "Username already exists"}

hashed_password = generate_password_hash(password, method='sha256')
new_user = user(username=username, password=hashed_password, provider_id=providerid, brand_name=brandname)
new_user = user(username=username, password=hashed_password)
session.add(new_user)

session.commit()

return {"success": new_user.id}
return {"success": new_user}

except Exception as e:

session.rollback()
return {"error": str(e)}

finally:
session.close()

def verify_user_email(user_id, email):
session = Session()
try:
userVal = session.query(user).filter(user.username == email, user.id == user_id).one()
if userVal:
userVal.verified = True
session.commit()
except Exception as e:
session.rollback()
return {"error": str(e)}
finally:
session.close()
6 changes: 5 additions & 1 deletion back-end/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from datetime import datetime

class organization(Base):
__tablename__ = 'organization'

id = Column(Integer, primary_key=True)
name = Column(String(100), unique=True, nullable=False)
provider_id = Column(Integer)
Expand All @@ -17,8 +19,10 @@ class user(Base):
__tablename__ = 'user'

id = Column(Integer, primary_key=True)
username = Column(String(50), unique=True)
username = Column(String(50), unique=True, nullable=False)
password = Column(String(256))
is_admin = Column(Boolean, default=False)
verified = Column(Boolean, default=False)
organization_id = Column(Integer, ForeignKey('organization.id'))
organization = relationship('Organization', back_populates='users')

Expand Down
1 change: 1 addition & 0 deletions back-end/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Fiona==1.9.2
Flask==2.2.3
Flask-Cors==3.0.10
Flask-JWT-Extended==4.5.2
Flask-Mail==0.10.0
Flask-Login==0.6.2
Flask-SQLAlchemy==3.0.3
folium==0.14.0
Expand Down
70 changes: 46 additions & 24 deletions back-end/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
get_jwt_identity,
decode_token
)
from datetime import datetime
from jwt import ExpiredSignatureError
from datetime import datetime, timedelta
import shortuuid
from celery.result import AsyncResult
from celery import chain
from utils.settings import DATABASE_URL, COOKIE_EXP_TIME, backend_port
from utils.settings import DATABASE_URL, COOKIE_EXP_TIME, backend_port, frontend_url
from database.sessions import Session
from controllers.database_controller import fabric_ops, kml_ops, user_ops, vt_ops, file_ops, folder_ops, mbtiles_ops, challenge_ops, editfile_ops
from utils.flask_app import app, jwt
from utils.flask_app import app, jwt, mail
from controllers.celery_controller.celery_config import celery
from controllers.celery_controller.celery_tasks import process_data, deleteFiles, toggle_tiles, run_signalserver, raster2vector, preview_fabric_locaiton_coverage, async_folder_copy_for_import, add_files_to_folder
from utils.namingschemes import DATETIME_FORMAT, EXPORT_CSV_NAME_TEMPLATE, SIGNALSERVER_RASTER_DATA_NAME_TEMPLATE
Expand All @@ -31,20 +32,7 @@
from utils.logger_config import logger
import json
from shapely.geometry import shape
# logger = logging.getLogger(__name__)



# logging.basicConfig(level=logging.DEBUG)
# app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URL
# app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')
# app.config["JWT_SECRET_KEY"] = base64.b64encode(os.getenv('JWT_SECRET').encode())
# app.config["JWT_TOKEN_LOCATION"] = [os.getenv('JWT_TOKEN_LOCATION')]
# app.config['JWT_ACCESS_COOKIE_NAME'] = os.getenv('JWT_ACCESS_COOKIE_NAME')
# app.config['JWT_COOKIE_CSRF_PROTECT'] = False
# app.config['JWT_ACCESS_TOKEN_EXPIRES'] = COOKIE_EXP_TIME
# jwt = JWTManager(app)

from flask_mail import Message


db_name = os.environ.get("POSTGRES_DB")
Expand Down Expand Up @@ -219,22 +207,56 @@ def search_location(folderid):



def send_verification_email(email, token):
msg = Message('Email Verification', recipients=[email])
verification_url = f'{frontend_url}/emailVerification/{token}'
msg.body = f'Please click the link to verify your email: {verification_url}'
mail.send(msg)

@app.route('/api/verify/<token>', methods=['GET'])
def verify_email(token):
try:
decoded_token = decode_token(token)
user_id = decoded_token['identity']['id']
email = decoded_token['identity']['email']
user_ops.verify_user_email(user_id, email)
return jsonify({'status': 'success', 'message': 'Email verified successfully.'}), 200
except ExpiredSignatureError:
return jsonify({'status': 'error', 'message': 'The token has expired.'}), 400
except Exception as e:
return jsonify({'status': 'error', 'message': 'Invalid token.'}), 400

@app.route('/api/resend_verification', methods=['POST'])
def resend_verification():
data = request.get_json()
email = data.get('email')
user = user_ops.get_user_by_email(email)
if not user:
return jsonify({'status': 'error', 'message': 'Email address not found.'}), 400

email_token = create_access_token(identity={'id': user.id, 'email': email}, expires_delta=timedelta(hours=1))
send_verification_email(email, email_token)
return jsonify({'status': 'success', 'message': 'Verification email resent.'}), 200

@app.route('/api/register', methods=['POST'])
def register():
data = request.get_json()
username = data.get('username')
email = data.get('email')
password = data.get('password')
providerid = data.get('providerId')
brandname = data.get('brandName')

response = user_ops.create_user_in_db(username, password, providerid, brandname)
response = user_ops.create_user_in_db(email, password)

if 'error' in response:
return jsonify({'status': 'error', 'message': response["error"]}), 400

access_token = create_access_token(identity={'id': response["success"], 'username': username})
userVal = response["success"]
access_token = create_access_token(identity={'id': userVal.id, 'verified': userVal.verified})

email_token = create_access_token(identity={'id': userVal.id, 'email': email}, expires_delta=timedelta(hours=1))

send_verification_email(email, email_token)

response = make_response(jsonify({'status': 'success', 'token': access_token}))
response = make_response(jsonify({'status': 'success', 'token': email_token}))
response.set_cookie('token', access_token, httponly=False, samesite='Lax', secure=False)
return response, 200

Expand All @@ -250,7 +272,7 @@ def login():

if user is not None and check_password_hash(user.password, pword):
user_id = user.id
access_token = create_access_token(identity={'id': user_id, 'username': username})
access_token = create_access_token(identity={'id': user_id, 'verified': user.verified})
response = make_response(jsonify({'status': 'success', 'token': access_token}))
response.set_cookie('token', access_token, httponly=False, samesite='Lax', secure=False)
return response
Expand Down
8 changes: 8 additions & 0 deletions back-end/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ class Config:
SQLALCHEMY_DATABASE_URI = DATABASE_URL
CELERY_BROKER_URL = 'redis://redis:6379/0'
CELERY_RESULT_BACKEND = 'redis://redis:6379/0'

# Email configurations
MAIL_SERVER = os.getenv('MAIL_SERVER')
MAIL_PORT = int(os.getenv('MAIL_PORT', 587))
MAIL_USE_TLS = os.getenv('MAIL_USE_TLS', 'true').lower() in ['true', '1', 't']
MAIL_USE_SSL = os.getenv('MAIL_USE_SSL', 'false').lower() in ['true', '1', 't']
MAIL_USERNAME = os.getenv('MAIL_USERNAME')
MAIL_PASSWORD = os.getenv('MAIL_PASSWORD')
11 changes: 9 additions & 2 deletions back-end/utils/flask_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@
from flask_cors import CORS
from flask_jwt_extended import JWTManager
import os
from flask_mail import Mail



def create_app():
app = Flask(__name__)
app.config.from_object(Config)
CORS(app, supports_credentials=True)

mail = Mail()

# Initialize other extensions
jwt = JWTManager(app)

return app, jwt
mail.init_app(app)

return app, jwt, mail

app, jwt = create_app()
app, jwt, mail = create_app()
1 change: 1 addition & 0 deletions back-end/utils/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
db_host = os.getenv('DB_HOST')
db_port = os.getenv('DB_PORT')
backend_port = os.getenv('DEVELOP_BACKEND_PORT')
frontend_url = os.getenv('FRONTEND_URL')
DATABASE_URL = f'postgresql://{db_user}:{db_password}@{db_host}:{db_port}/postgres'
BATCH_SIZE = 50000
COOKIE_EXP_TIME = timedelta(days=7) # Cookie will expire in 7 days
Expand Down
Loading

0 comments on commit 89033c0

Please sign in to comment.