- Convert mail messaging from SMTP to Scaleway TEM mails
This commit is contained in:
@@ -135,15 +135,6 @@ class Config(object):
|
|||||||
"LLM": {"name": "LLM", "description": "Algorithm using information integrated in the used LLM"}
|
"LLM": {"name": "LLM", "description": "Algorithm using information integrated in the used LLM"}
|
||||||
}
|
}
|
||||||
|
|
||||||
# flask-mailman settings
|
|
||||||
MAIL_SERVER = environ.get('MAIL_SERVER')
|
|
||||||
MAIL_PORT = int(environ.get('MAIL_PORT', 465))
|
|
||||||
MAIL_USE_TLS = False
|
|
||||||
MAIL_USE_SSL = True
|
|
||||||
MAIL_USERNAME = environ.get('MAIL_USERNAME')
|
|
||||||
MAIL_PASSWORD = environ.get('MAIL_PASSWORD')
|
|
||||||
MAIL_DEFAULT_SENDER = ('Evie', MAIL_USERNAME)
|
|
||||||
|
|
||||||
# Email settings for API key notifications
|
# Email settings for API key notifications
|
||||||
PROMOTIONAL_IMAGE_URL = 'https://askeveai.com/wp-content/uploads/2024/07/Evie-Call-scaled.jpg' # Replace with your actual URL
|
PROMOTIONAL_IMAGE_URL = 'https://askeveai.com/wp-content/uploads/2024/07/Evie-Call-scaled.jpg' # Replace with your actual URL
|
||||||
|
|
||||||
@@ -175,6 +166,13 @@ class Config(object):
|
|||||||
PUSH_GATEWAY_PORT = environ.get('PUSH_GATEWAY_PORT', '9091')
|
PUSH_GATEWAY_PORT = environ.get('PUSH_GATEWAY_PORT', '9091')
|
||||||
PUSH_GATEWAY_URL = f"{PUSH_GATEWAY_HOST}:{PUSH_GATEWAY_PORT}"
|
PUSH_GATEWAY_URL = f"{PUSH_GATEWAY_HOST}:{PUSH_GATEWAY_PORT}"
|
||||||
|
|
||||||
|
# Scaleway parameters
|
||||||
|
SW_EMAIL_ACCESS_KEY = environ.get('SW_EMAIL_ACCESS_KEY')
|
||||||
|
SW_EMAIL_SECRET_KEY = environ.get('SW_EMAIL_SECRET_KEY')
|
||||||
|
SW_EMAIL_SENDER = environ.get('SW_EMAIL_SENDER')
|
||||||
|
SW_EMAIL_NAME = environ.get('SW_EMAIL_NAME')
|
||||||
|
SW_PROJECT = environ.get('SW_PROJECT')
|
||||||
|
|
||||||
|
|
||||||
class DevConfig(Config):
|
class DevConfig(Config):
|
||||||
DEVELOPMENT = True
|
DEVELOPMENT = True
|
||||||
@@ -252,15 +250,6 @@ class ProdConfig(Config):
|
|||||||
|
|
||||||
WTF_CSRF_SSL_STRICT = True # Set to True if using HTTPS
|
WTF_CSRF_SSL_STRICT = True # Set to True if using HTTPS
|
||||||
|
|
||||||
# flask-mailman settings
|
|
||||||
MAIL_SERVER = 'mail.askeveai.com'
|
|
||||||
MAIL_PORT = 587
|
|
||||||
MAIL_USE_TLS = True
|
|
||||||
MAIL_USE_SSL = False
|
|
||||||
MAIL_DEFAULT_SENDER = ('Evie Admin', 'evie_admin@askeveai.com')
|
|
||||||
MAIL_USERNAME = environ.get('MAIL_USERNAME')
|
|
||||||
MAIL_PASSWORD = environ.get('MAIL_PASSWORD')
|
|
||||||
|
|
||||||
# Define the nginx prefix used for the specific apps
|
# Define the nginx prefix used for the specific apps
|
||||||
EVEAI_APP_LOCATION_PREFIX = '/admin'
|
EVEAI_APP_LOCATION_PREFIX = '/admin'
|
||||||
EVEAI_CHAT_LOCATION_PREFIX = '/chat'
|
EVEAI_CHAT_LOCATION_PREFIX = '/chat'
|
||||||
|
|||||||
@@ -270,14 +270,6 @@ LOGGING = {
|
|||||||
'backupCount': 2,
|
'backupCount': 2,
|
||||||
'formatter': 'standard',
|
'formatter': 'standard',
|
||||||
},
|
},
|
||||||
'file_mailman': {
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'class': 'logging.handlers.RotatingFileHandler',
|
|
||||||
'filename': 'logs/mailman.log',
|
|
||||||
'maxBytes': 1024 * 1024 * 1, # 1MB
|
|
||||||
'backupCount': 2,
|
|
||||||
'formatter': 'standard',
|
|
||||||
},
|
|
||||||
'file_security': {
|
'file_security': {
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'class': 'logging.handlers.RotatingFileHandler',
|
'class': 'logging.handlers.RotatingFileHandler',
|
||||||
@@ -389,11 +381,6 @@ LOGGING = {
|
|||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
'propagate': False
|
'propagate': False
|
||||||
},
|
},
|
||||||
'mailman': { # logger for the mailman
|
|
||||||
'handlers': ['file_mailman', 'graylog', ] if env == 'production' else ['file_mailman', ],
|
|
||||||
'level': 'DEBUG',
|
|
||||||
'propagate': False
|
|
||||||
},
|
|
||||||
'security': { # logger for the security
|
'security': { # logger for the security
|
||||||
'handlers': ['file_security', 'graylog', ] if env == 'production' else ['file_security', ],
|
'handlers': ['file_security', 'graylog', ] if env == 'production' else ['file_security', ],
|
||||||
'level': 'DEBUG',
|
'level': 'DEBUG',
|
||||||
|
|||||||
@@ -18,10 +18,6 @@ x-common-variables: &common-variables
|
|||||||
FLASK_DEBUG: true
|
FLASK_DEBUG: true
|
||||||
SECRET_KEY: '97867c1491bea5ee6a8e8436eb11bf2ba6a69ff53ab1b17ecba450d0f2e572e1'
|
SECRET_KEY: '97867c1491bea5ee6a8e8436eb11bf2ba6a69ff53ab1b17ecba450d0f2e572e1'
|
||||||
SECURITY_PASSWORD_SALT: '228614859439123264035565568761433607235'
|
SECURITY_PASSWORD_SALT: '228614859439123264035565568761433607235'
|
||||||
MAIL_USERNAME: evie@askeveai.com
|
|
||||||
MAIL_PASSWORD: 'D**0z@UGfJOI@yv3eC5'
|
|
||||||
MAIL_SERVER: mail.flow-it.net
|
|
||||||
MAIL_PORT: 465
|
|
||||||
REDIS_URL: redis
|
REDIS_URL: redis
|
||||||
REDIS_PORT: '6379'
|
REDIS_PORT: '6379'
|
||||||
FLOWER_USER: 'Felucia'
|
FLOWER_USER: 'Felucia'
|
||||||
@@ -41,6 +37,11 @@ x-common-variables: &common-variables
|
|||||||
CREWAI_STORAGE_DIR: "/app/crewai_storage"
|
CREWAI_STORAGE_DIR: "/app/crewai_storage"
|
||||||
PUSH_GATEWAY_HOST: "pushgateway"
|
PUSH_GATEWAY_HOST: "pushgateway"
|
||||||
PUSH_GATEWAY_PORT: "9091"
|
PUSH_GATEWAY_PORT: "9091"
|
||||||
|
SW_EMAIL_ACCESS_KEY: "SCWFMQ871RE4XGF04SW0"
|
||||||
|
SW_EMAIL_SECRET_KEY: "ec84604c-e2d4-4b0d-a120-40420693f42a"
|
||||||
|
SW_EMAIL_SENDER: "admin_dev@mail.askeveai.be"
|
||||||
|
SW_EMAIL_NAME: "Evie Admin (dev)"
|
||||||
|
SW_PROJECT: "f282f55a-ea52-4538-a979-5bcb890717ab"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
nginx:
|
nginx:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from flask_security.signals import user_authenticated
|
|||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
from common.extensions import (db, migrate, bootstrap, security, mail, login_manager, cors, csrf, session,
|
from common.extensions import (db, migrate, bootstrap, security, login_manager, cors, csrf, session,
|
||||||
minio_client, simple_encryption, metrics, cache_manager)
|
minio_client, simple_encryption, metrics, cache_manager)
|
||||||
from common.models.user import User, Role, Tenant, TenantDomain
|
from common.models.user import User, Role, Tenant, TenantDomain
|
||||||
import common.models.interaction
|
import common.models.interaction
|
||||||
@@ -19,7 +19,7 @@ from .errors import register_error_handlers
|
|||||||
from common.utils.celery_utils import make_celery, init_celery
|
from common.utils.celery_utils import make_celery, init_celery
|
||||||
from common.utils.template_filters import register_filters
|
from common.utils.template_filters import register_filters
|
||||||
from config.config import get_config
|
from config.config import get_config
|
||||||
from eveai_app.views.security_forms import ResetPasswordForm
|
from eveai_app.views.security_forms import ResetPasswordForm, ForgotPasswordForm
|
||||||
|
|
||||||
|
|
||||||
def create_app(config_file=None):
|
def create_app(config_file=None):
|
||||||
@@ -40,6 +40,7 @@ def create_app(config_file=None):
|
|||||||
|
|
||||||
app.config['SESSION_KEY_PREFIX'] = 'eveai_app_'
|
app.config['SESSION_KEY_PREFIX'] = 'eveai_app_'
|
||||||
app.config['SECURITY_RESET_PASSWORD_FORM'] = ResetPasswordForm
|
app.config['SECURITY_RESET_PASSWORD_FORM'] = ResetPasswordForm
|
||||||
|
app.config['SECURITY_FORGOT_PASSWORD_FORM'] = ForgotPasswordForm
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.makedirs(app.instance_path)
|
os.makedirs(app.instance_path)
|
||||||
@@ -79,8 +80,6 @@ def create_app(config_file=None):
|
|||||||
# Debugging settings
|
# Debugging settings
|
||||||
if app.config['DEBUG'] is True:
|
if app.config['DEBUG'] is True:
|
||||||
app.logger.setLevel(logging.DEBUG)
|
app.logger.setLevel(logging.DEBUG)
|
||||||
mail_logger = logging.getLogger('flask_mailman')
|
|
||||||
mail_logger.setLevel(logging.DEBUG)
|
|
||||||
security_logger = logging.getLogger('flask_security')
|
security_logger = logging.getLogger('flask_security')
|
||||||
security_logger.setLevel(logging.DEBUG)
|
security_logger.setLevel(logging.DEBUG)
|
||||||
sqlalchemy_logger = logging.getLogger('sqlalchemy.engine')
|
sqlalchemy_logger = logging.getLogger('sqlalchemy.engine')
|
||||||
@@ -117,7 +116,6 @@ def register_extensions(app):
|
|||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
migrate.init_app(app, db)
|
migrate.init_app(app, db)
|
||||||
bootstrap.init_app(app)
|
bootstrap.init_app(app)
|
||||||
mail.init_app(app)
|
|
||||||
csrf.init_app(app)
|
csrf.init_app(app)
|
||||||
login_manager.init_app(app)
|
login_manager.init_app(app)
|
||||||
cors.init_app(app)
|
cors.init_app(app)
|
||||||
|
|||||||
@@ -38,21 +38,21 @@
|
|||||||
<div class="tab-content tab-space">
|
<div class="tab-content tab-space">
|
||||||
<!-- Storage Tab -->
|
<!-- Storage Tab -->
|
||||||
<div class="tab-pane fade show active" id="storage-tab" role="tabpanel">
|
<div class="tab-pane fade show active" id="storage-tab" role="tabpanel">
|
||||||
{% set storage_fields = ['max_storage_mb', 'additional_storage_price', 'additional_storage_bucket'] %}
|
{% set storage_fields = ['max_storage_mb', 'additional_storage_allowed', 'additional_storage_price', 'additional_storage_bucket'] %}
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
{{ render_included_field(field, readonly_fields=ext_readonly_fields, include_fields=storage_fields) }}
|
{{ render_included_field(field, readonly_fields=ext_readonly_fields, include_fields=storage_fields) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<!-- Embedding Tab -->
|
<!-- Embedding Tab -->
|
||||||
<div class="tab-pane fade" id="embedding-tab" role="tabpanel">
|
<div class="tab-pane fade" id="embedding-tab" role="tabpanel">
|
||||||
{% set embedding_fields = ['included_embedding_mb', 'additional_embedding_price', 'additional_embedding_bucket', 'overage_embedding'] %}
|
{% set embedding_fields = ['included_embedding_mb', 'additional_embedding_allowed', 'additional_embedding_price', 'additional_embedding_bucket', 'overage_embedding'] %}
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
{{ render_included_field(field, readonly_fields=ext_readonly_fields, include_fields=embedding_fields) }}
|
{{ render_included_field(field, readonly_fields=ext_readonly_fields, include_fields=embedding_fields) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<!-- Interaction Tab -->
|
<!-- Interaction Tab -->
|
||||||
<div class="tab-pane fade" id="interaction-tab" role="tabpanel">
|
<div class="tab-pane fade" id="interaction-tab" role="tabpanel">
|
||||||
{% set interaction_fields = ['included_interaction_tokens', 'additional_interaction_token_price', 'additional_interaction_bucket', 'overage_interaction'] %}
|
{% set interaction_fields = ['included_interaction_tokens', 'additional_interaction_allowed', 'additional_interaction_token_price', 'additional_interaction_bucket', 'overage_interaction'] %}
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
{{ render_included_field(field, readonly_fields=ext_readonly_fields, include_fields=interaction_fields) }}
|
{{ render_included_field(field, readonly_fields=ext_readonly_fields, include_fields=interaction_fields) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% include "security/_messages.html" %}
|
{% include "security/_messages.html" %}
|
||||||
<form action="{{ url_for_security('forgot_password') }}" method="post" name="forgot_password_form">
|
<form action="{{ url_for('security_bp.forgot_password') }}" method="post" novalidate>
|
||||||
{{ forgot_password_form.hidden_tag() }}
|
{{ forgot_password_form.hidden_tag() }}
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -26,8 +26,7 @@
|
|||||||
{# </div>#}
|
{# </div>#}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block content_footer %}
|
{% block content_footer %}
|
||||||
First time here? Forgot your password?
|
Forgot your password? Contact your administrator to send you a password reset link.
|
||||||
<a href="/reset" class="text-success text-gradient font-weight-bold">Request new password</a>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{#{{ url_for_security('reset_password', token=reset_password_token) }}#}
|
{#{{ url_for_security('reset_password', token=reset_password_token) }}#}
|
||||||
@@ -51,10 +51,12 @@ class LicenseForm(FlaskForm):
|
|||||||
yearly_payment = BooleanField('Yearly Payment', default=False)
|
yearly_payment = BooleanField('Yearly Payment', default=False)
|
||||||
basic_fee = FloatField('Basic Fee', validators=[InputRequired(), NumberRange(min=0)])
|
basic_fee = FloatField('Basic Fee', validators=[InputRequired(), NumberRange(min=0)])
|
||||||
max_storage_mb = IntegerField('Max Storage (MiB)', validators=[DataRequired(), NumberRange(min=1)])
|
max_storage_mb = IntegerField('Max Storage (MiB)', validators=[DataRequired(), NumberRange(min=1)])
|
||||||
|
additional_storage_allowed = BooleanField('Additional Storage Allowed', default=True)
|
||||||
additional_storage_price = FloatField('Additional Storage Token Fee',
|
additional_storage_price = FloatField('Additional Storage Token Fee',
|
||||||
validators=[InputRequired(), NumberRange(min=0)])
|
validators=[InputRequired(), NumberRange(min=0)])
|
||||||
additional_storage_bucket = IntegerField('Additional Storage Bucket Size (MiB)',
|
additional_storage_bucket = IntegerField('Additional Storage Bucket Size (MiB)',
|
||||||
validators=[DataRequired(), NumberRange(min=1)])
|
validators=[DataRequired(), NumberRange(min=1)])
|
||||||
|
additional_embedding_allowed = BooleanField('Additional Embedding Allowed', default=True)
|
||||||
included_embedding_mb = IntegerField('Included Embedding Tokens (MiB)',
|
included_embedding_mb = IntegerField('Included Embedding Tokens (MiB)',
|
||||||
validators=[DataRequired(), NumberRange(min=1)])
|
validators=[DataRequired(), NumberRange(min=1)])
|
||||||
additional_embedding_price = FloatField('Additional Embedding Token Fee',
|
additional_embedding_price = FloatField('Additional Embedding Token Fee',
|
||||||
@@ -63,6 +65,7 @@ class LicenseForm(FlaskForm):
|
|||||||
validators=[DataRequired(), NumberRange(min=1)])
|
validators=[DataRequired(), NumberRange(min=1)])
|
||||||
included_interaction_tokens = IntegerField('Included Interaction Tokens (M Tokens)',
|
included_interaction_tokens = IntegerField('Included Interaction Tokens (M Tokens)',
|
||||||
validators=[DataRequired(), NumberRange(min=1)])
|
validators=[DataRequired(), NumberRange(min=1)])
|
||||||
|
additional_interaction_allowed = BooleanField('Additional Interaction Allowed', default=True)
|
||||||
additional_interaction_token_price = FloatField('Additional Interaction Token Fee',
|
additional_interaction_token_price = FloatField('Additional Interaction Token Fee',
|
||||||
validators=[InputRequired(), NumberRange(min=0)])
|
validators=[InputRequired(), NumberRange(min=0)])
|
||||||
additional_interaction_bucket = IntegerField('Additional Interaction Bucket Size (M Tokens)',
|
additional_interaction_bucket = IntegerField('Additional Interaction Bucket Size (M Tokens)',
|
||||||
|
|||||||
@@ -152,8 +152,9 @@ def create_license(license_tier_id):
|
|||||||
tenant_id = session.get('tenant').get('id')
|
tenant_id = session.get('tenant').get('id')
|
||||||
currency = session.get('tenant').get('currency')
|
currency = session.get('tenant').get('currency')
|
||||||
|
|
||||||
if current_user_has_role("Partner Admin"): # The Partner Admin can only set the end date
|
if current_user_has_role("Partner Admin"): # The Partner Admin can only set start & end dates, and allowed fields
|
||||||
readonly_fields = [field.name for field in form if (field.name != 'end_date' and field.name != 'start_date')]
|
readonly_fields = [field.name for field in form if (field.name != 'end_date' and field.name != 'start_date' and
|
||||||
|
not field.name.endswith('allowed'))]
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
# Fetch the LicenseTier
|
# Fetch the LicenseTier
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ from flask import current_app
|
|||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import PasswordField, SubmitField, StringField
|
from wtforms import PasswordField, SubmitField, StringField
|
||||||
from wtforms.validators import DataRequired, Length, Email, NumberRange, Optional, EqualTo
|
from wtforms.validators import DataRequired, Length, Email, NumberRange, Optional, EqualTo
|
||||||
from flask_security.forms import ForgotPasswordForm
|
|
||||||
from flask_security.utils import send_mail, config_value
|
|
||||||
|
|
||||||
from common.utils.nginx_utils import prefixed_url_for
|
|
||||||
|
|
||||||
|
|
||||||
class SetPasswordForm(FlaskForm):
|
class SetPasswordForm(FlaskForm):
|
||||||
@@ -14,7 +10,7 @@ class SetPasswordForm(FlaskForm):
|
|||||||
submit = SubmitField('Set Password')
|
submit = SubmitField('Set Password')
|
||||||
|
|
||||||
|
|
||||||
class RequestResetForm(FlaskForm):
|
class ForgotPasswordForm(FlaskForm):
|
||||||
email = StringField('Email', validators=[DataRequired(), Email()])
|
email = StringField('Email', validators=[DataRequired(), Email()])
|
||||||
submit = SubmitField('Request Password Reset')
|
submit = SubmitField('Request Password Reset')
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from sqlalchemy.exc import SQLAlchemyError
|
|||||||
from common.models.user import User
|
from common.models.user import User
|
||||||
from common.utils.eveai_exceptions import EveAIException, EveAINoActiveLicense
|
from common.utils.eveai_exceptions import EveAIException, EveAINoActiveLicense
|
||||||
from common.utils.nginx_utils import prefixed_url_for
|
from common.utils.nginx_utils import prefixed_url_for
|
||||||
from eveai_app.views.security_forms import SetPasswordForm, ResetPasswordForm, RequestResetForm
|
from eveai_app.views.security_forms import SetPasswordForm, ResetPasswordForm, ForgotPasswordForm
|
||||||
from common.extensions import db
|
from common.extensions import db
|
||||||
from common.utils.security_utils import confirm_token, send_confirmation_email, send_reset_email
|
from common.utils.security_utils import confirm_token, send_confirmation_email, send_reset_email
|
||||||
from common.utils.security import set_tenant_session_data, is_valid_tenant
|
from common.utils.security import set_tenant_session_data, is_valid_tenant
|
||||||
@@ -111,16 +111,16 @@ def confirm_email(token):
|
|||||||
return redirect(prefixed_url_for('basic_bp.confirm_email_ok'))
|
return redirect(prefixed_url_for('basic_bp.confirm_email_ok'))
|
||||||
|
|
||||||
|
|
||||||
@security_bp.route('/reset_password_request', methods=['GET', 'POST'])
|
@security_bp.route('/forgot_password', methods=['GET', 'POST'])
|
||||||
def reset_password_request():
|
def forgot_password():
|
||||||
form = RequestResetForm()
|
form = ForgotPasswordForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
user = User.query.filter_by(email=form.email.data).first()
|
user = User.query.filter_by(email=form.email.data).first()
|
||||||
if user:
|
if user:
|
||||||
send_reset_email(user)
|
send_reset_email(user)
|
||||||
flash('An email with instructions to reset your password has been sent.', 'info')
|
flash('An email with instructions to reset your password has been sent.', 'info')
|
||||||
return redirect(prefixed_url_for('security_bp.login'))
|
return redirect(prefixed_url_for('security_bp.login'))
|
||||||
return render_template('security/reset_password_request.html', form=form)
|
return render_template('security/forgot_password.html', form=form)
|
||||||
|
|
||||||
|
|
||||||
@security_bp.route('/reset_password/<token>', methods=['GET', 'POST'])
|
@security_bp.route('/reset_password/<token>', methods=['GET', 'POST'])
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime as dt, timezone as tz
|
from datetime import datetime as dt, timezone as tz
|
||||||
from flask import request, redirect, flash, render_template, Blueprint, session, current_app
|
from flask import request, redirect, flash, render_template, Blueprint, session, current_app
|
||||||
from flask_mailman import EmailMessage
|
|
||||||
from flask_security import roles_accepted, current_user
|
from flask_security import roles_accepted, current_user
|
||||||
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
|
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
|
||||||
import ast
|
import ast
|
||||||
@@ -21,6 +20,7 @@ from common.utils.eveai_exceptions import EveAIException
|
|||||||
from common.utils.document_utils import set_logging_information, update_logging_information
|
from common.utils.document_utils import set_logging_information, update_logging_information
|
||||||
from common.services.tenant_services import TenantServices
|
from common.services.tenant_services import TenantServices
|
||||||
from common.services.user_services import UserServices
|
from common.services.user_services import UserServices
|
||||||
|
from common.utils.mail_utils import send_email
|
||||||
|
|
||||||
user_bp = Blueprint('user_bp', __name__, url_prefix='/user')
|
user_bp = Blueprint('user_bp', __name__, url_prefix='/user')
|
||||||
|
|
||||||
@@ -670,20 +670,15 @@ def send_api_key_notification(tenant_id, tenant_name, project_name, api_key, ser
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
||||||
# Create email message
|
# Create email message
|
||||||
msg = EmailMessage(
|
msg = send_email(
|
||||||
subject='Your new API-key from Ask Eve AI (Evie)',
|
subject='Your new API-key from Ask Eve AI (Evie)',
|
||||||
body=render_template('email/api_key_notification.html', **context),
|
html=render_template('email/api_key_notification.html', **context),
|
||||||
from_email=current_app.config['MAIL_DEFAULT_SENDER'],
|
to_email=recipient_email,
|
||||||
to=[recipient_email]
|
to_name=recipient_email,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Set HTML content type
|
|
||||||
msg.content_subtype = "html"
|
|
||||||
|
|
||||||
# Send email
|
|
||||||
msg.send()
|
|
||||||
|
|
||||||
current_app.logger.info(f"API key notification sent to {recipient_email} for tenant {tenant_id}")
|
current_app.logger.info(f"API key notification sent to {recipient_email} for tenant {tenant_id}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"""Add Allowed fields for overrun in License
|
||||||
|
|
||||||
|
Revision ID: fa6113ce4306
|
||||||
|
Revises: 9ed466e9756b
|
||||||
|
Create Date: 2025-05-08 16:05:55.612416
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'fa6113ce4306'
|
||||||
|
down_revision = '9ed466e9756b'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
with op.batch_alter_table('license', schema=None) as batch_op:
|
||||||
|
batch_op.add_column(
|
||||||
|
sa.Column('additional_storage_allowed', sa.Boolean(), nullable=True))
|
||||||
|
batch_op.add_column(
|
||||||
|
sa.Column('additional_embedding_allowed', sa.Boolean(), nullable=True))
|
||||||
|
batch_op.add_column(
|
||||||
|
sa.Column('additional_interaction_allowed', sa.Boolean(), nullable=True))
|
||||||
|
|
||||||
|
op.execute("""
|
||||||
|
UPDATE license
|
||||||
|
SET additional_storage_allowed = TRUE,
|
||||||
|
additional_embedding_allowed = TRUE,
|
||||||
|
additional_interaction_allowed = TRUE
|
||||||
|
""")
|
||||||
|
|
||||||
|
with op.batch_alter_table('license', schema=None) as batch_op:
|
||||||
|
batch_op.alter_column('additional_storage_allowed', nullable=False)
|
||||||
|
batch_op.alter_column('additional_embedding_allowed', nullable=False)
|
||||||
|
batch_op.alter_column('additional_interaction_allowed', nullable=False)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
with op.batch_alter_table('license', schema=None) as batch_op:
|
||||||
|
batch_op.drop_column('additional_interaction_allowed')
|
||||||
|
batch_op.drop_column('additional_embedding_allowed')
|
||||||
|
batch_op.drop_column('additional_storage_allowed')
|
||||||
|
|
||||||
|
# ### end Alembic commands ###
|
||||||
@@ -12,7 +12,6 @@ Flask-Bootstrap~=3.3.7.1
|
|||||||
Flask-Cors~=5.0.1
|
Flask-Cors~=5.0.1
|
||||||
Flask-JWT-Extended~=4.7.1
|
Flask-JWT-Extended~=4.7.1
|
||||||
Flask-Login~=0.6.3
|
Flask-Login~=0.6.3
|
||||||
flask-mailman~=1.1.1
|
|
||||||
Flask-Migrate~=4.1.0
|
Flask-Migrate~=4.1.0
|
||||||
Flask-Principal~=0.4.0
|
Flask-Principal~=0.4.0
|
||||||
Flask-Security-Too~=5.6.2
|
Flask-Security-Too~=5.6.2
|
||||||
@@ -90,3 +89,6 @@ mistral-common~=1.5.3
|
|||||||
mistralai~=1.6.0
|
mistralai~=1.6.0
|
||||||
contextvars~=2.4
|
contextvars~=2.4
|
||||||
pandas~=2.2.3
|
pandas~=2.2.3
|
||||||
|
prometheus_client~=0.21.1
|
||||||
|
scaleway~=2.9.0
|
||||||
|
html2text~=2025.4.15
|
||||||
Reference in New Issue
Block a user