Skip to content

Administrative restricted elements

Admin page

Admin

Caution Message

If you don't understand what you will be doing, you should not have access to this page

Initialization

This should only be used if you have an empty database. It is not recommended to use these tools.

Load Secondary Sources

Load the tables ICCA, mean_coordinates and views_grid, necessary for the webmap

Load Inform (unused anymore)

This table is still available in case the team elect to reuse it later on but it isn't link to any element in the webpages anymore.

Load Acled

Load all acled data until today. Really long process, not recommended.

Update

Narratives

Generate each specific narrative table using openAI python Library. Each process can exceed the server time for completion. Timeline in particular is not recommended to be updated directly online, as the use of a headless browser is needed to extract images from websites protecting access to robots. It is done separately in a python file test_timeline.py

ACLED

Update ACLED data by looking in each country for the last timestamp, and collect the new data. It is also removing some possible changed events.

Register page

Register

Available only for an admin account. Needs to register an email, a password (confirmed) that is being crypted in the database and a role for now between User and Admin. The Admin account can then shared directly by email the password created for the new user to log in.

Application

Access to the different pages is realized in the app through two processes: login and role verification

Libraries

from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user from forms import LoginForm, RegistrationForm

Declaration

#Initialize Flask-Login
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

# Define user class
class User(UserMixin):
    def __init__(self, id=None, email=None, password_hash=None, role='user'):
        self.id = id
        self.email = email
        self.password_hash = password_hash
        self.role = role

    # Find line in database by id
    @staticmethod
    def get(id):
        query = text("SELECT id, email, password, role FROM draft_schema.users WHERE id = :id")
        with engine.connect() as conn:
            result = conn.execute(query, {'id': id}).fetchone()
            #conn.commit()
            if result:
                #app.logger.debug(f"User found get: {result}")

                return User(result[0], result[1], result[2], result[3])

            return None
    # Find line in database by email
    @staticmethod
    def find_by_email(email):
        query = text("SELECT id, email, password, role FROM draft_schema.users WHERE email = :email")
        with engine.connect() as conn:
            result = conn.execute(query, {'email': email}).fetchone()
            #conn.commit()
            if result:
                #app.logger.debug(f"User found get: {result}")
                return User(result[0], result[1], result[2], result[3])

            return None

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def custom_login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if current_user.is_authenticated:
            app.logger.debug(f"User Email: {current_user.email}")
        else:
            #app.logger.debug("User is not authenticated")
            return redirect(url_for('login', next=request.url))
        return f(*args, **kwargs)
    return decorated_function

    # Define a role restriction to connect to the page
    def role_required(role):
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                if not current_user.is_authenticated or current_user.role != role:
                    abort(403)  # Forbidden
                return f(*args, **kwargs)
            return decorated_function
    return decorator

    @login_manager.user_loader
    def load_user(user_id):
        return User.get(user_id)

Register page

@app.route('/register', methods=['GET', 'POST'])
@login_required
@role_required('admin')
def register():

    form = RegistrationForm()
    if form.validate_on_submit():
        email = form.email.data
        password = form.password.data
        role = form.role.data

        # check if user is already in database
        user = User.find_by_email(email)
        if user:
            flash('Email already registered.')
        else:
            new_user = User(email=email, password_hash=None, role=role)
            new_user.set_password(password)
            # Save new_user to the database
            with engine.connect() as conn:
                conn.execute(text("""
                    INSERT INTO draft_schema.users (email, password, role)
                    VALUES (:email, :password, 'user')
                """), {'email': new_user.email, 'password': new_user.password_hash})
                conn.commit()

            return redirect(url_for('login'))
    return render_template('register.html', form=form)#, error_message=error_message)