123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- import flask
- from flask_socketio import SocketIO
- import flask_login as fll
- import datetime
- from db import db, User, Game, Player, levels_users
- from belote_jeu import N_TURN, N_PLAYERS
- import belote_ws
- import settings
- login_manager = fll.LoginManager()
- app = flask.Flask(__name__)
- app.config.from_pyfile('settings.cfg')
- #######################################################################
- # Plugin management #
- #######################################################################
- # SocketIO
- socketio = SocketIO(app, cors_allowed_origins=settings.PUBLIC_URL)
- login_manager.init_app(app)
- # Database management
- db.app = app
- db.init_app(app)
- db.create_all()
- db.session.commit()
- # Insert admin if not exist
- if User.query.limit(1).first() is None:
- admin = User(login='admin', name='Admin', level=levels_users['Admin'])
- admin.set_password('admin')
- db.session.add(admin)
- db.session.commit()
- # Login management
- @login_manager.user_loader
- def load_user(user_id):
- if user_id is None :
- return None
- return User.query.get(user_id)
- @login_manager.unauthorized_handler
- def unauthorized_callback():
- return flask.redirect('/login?next=' + flask.request.path)
- #######################################################################
- # Global variables or fuctions #
- #######################################################################
- URL_DEFAULT = '/games'
- namespaces_join = {}
- namespaces = {}
- def create_namespace(gid, join=False):
- if(join):
- namespace = belote_ws.CustomNamespaceJoin(gid)
- namespaces_join[gid] = True
- socketio.on_namespace(namespace)
- else:
- namespace = belote_ws.CustomNamespacePlay(gid)
- namespaces[gid] = True
- socketio.on_namespace(namespace)
- @app.route('/')
- def home():
- user = fll.current_user
- if not hasattr(user, 'level'):
- user = None
- return flask.render_template("index.html", user=user)
- #######################################################################
- # Login, logout #
- #######################################################################
- @app.route('/login', methods=['GET', 'POST'])
- def login():
- if fll.current_user.is_authenticated:
- return flask.redirect(URL_DEFAULT)
- if flask.request.method=="POST":
- username = flask.request.form['username']
- password = flask.request.form['password']
- user = User.query.get(username)
- if user and user.level > levels_users['Inactive'] and user.check_password(password):
- fll.login_user(user)
- user.last_login = datetime.datetime.utcnow()
- next = flask.request.args.get('next')
- if next is not None and next[0]=='/':
- return flask.redirect(next)
- else:
- return flask.redirect(URL_DEFAULT)
- else:
- app.logger.warning('Login fail for user {} from {}'.format(user, flask.request.remote_addr))
- flask.flash('Nom d\'utilisateur ou mot de passe incorrect')
- return flask.render_template('login.html', user=None)
- @app.route('/logout')
- def logout():
- fll.logout_user()
- return flask.redirect('/')
- #######################################################################
- # Games : list #
- #######################################################################
- @app.route('/games')
- @fll.login_required
- def games():
- games = Game.query.all()
- mesjeux = []
- joinable = []
- for g in games:
- if g.admin==fll.current_user.login:
- mesjeux.append(g)
- elif g.can_join(fll.current_user):
- joinable.append(g)
- cancreategames = fll.current_user.level >= levels_users['Can create games']
- candeletegames = fll.current_user.level >= levels_users['Admin']
- return flask.render_template('games.html', mesjeux=mesjeux, joinable=joinable, user=fll.current_user, \
- cancreategames=cancreategames, candeletegames=candeletegames)
- #######################################################################
- # Create, join and play to a game #
- #######################################################################
- @app.route('/add_game', methods=['GET', 'POST'])
- @fll.login_required
- def game_add():
- player = fll.current_user
- if fll.current_user.level >= levels_users['Can create games']:
- if flask.request.method=="POST":
- name = flask.request.form['name']
- if name is None or name == '':
- return flask.redirect('/add_game')
- game = Game(name=name, admin=player.login)
- db.session.add(game)
- db.session.commit()
- game.join(fll.current_user)
- db.session.commit()
- return flask.redirect('/game/{}'.format(game.id))
- return flask.render_template('game_add.html', user=fll.current_user)
- return flask.redirect(URL_DEFAULT)
- @app.route('/game/<roomid>/join')
- @fll.login_required
- def game_page_join(roomid):
- game = Game.query.get(roomid)
- if game:
- player = fll.current_user
- if game.start:
- return flask.redirect('/game/{}'.format(roomid))
- if game.can_join(player):
- if game.id not in namespaces_join:
- create_namespace(game.id, join=True)
- return flask.render_template('game_join.html', game=game, user=player, admin=game.admin)
- return flask.redirect(URL_DEFAULT)
- @app.route('/game/<roomid>/start')
- @fll.login_required
- def game_page_start(roomid):
- game = Game.query.get(roomid)
- if game:
- player = fll.current_user
- if game.isadmin(player) and game.fixplayers and not game.start:
- return flask.render_template('game_start.html', game=game, user=player)
- return flask.redirect('/game/{}'.format(roomid))
- return flask.redirect(URL_DEFAULT)
- @app.route('/game/<roomid>')
- @fll.login_required
- def game_page(roomid):
- game = Game.query.get(roomid)
- if game:
- player = fll.current_user
- if not game.start:
- return flask.redirect('/game/{}/join'.format(roomid))
- if game.authorized(player) :
- if game.id not in namespaces:
- create_namespace(game.id)
- return flask.render_template('game.html', game=game, user=player)
- return flask.redirect(URL_DEFAULT)
- @app.route('/game/<roomid>/del')
- @fll.login_required
- def delgame(roomid):
- game = Game.query.get(roomid)
- if game is not None and fll.current_user.login == game.admin:
- confirm = flask.request.args.get('confirm')
- if confirm is not None:
- db.session.delete(game)
- db.session.commit()
- else:
- return flask.render_template('game_del.html', game=game, user=fll.current_user)
- return flask.redirect(URL_DEFAULT)
- #######################################################################
- # Users management #
- #######################################################################
- @app.route('/admin/users')
- @fll.login_required
- def admin_users():
- if fll.current_user.level < levels_users['Can manage simple users']:
- return flask.redirect(URL_DEFAULT)
- users = User.query.all()
- return flask.render_template('admin_users.html', user=fll.current_user, users=users)
- @app.route('/admin/users/<user>', methods=['GET', 'POST'])
- @fll.login_required
- def edituser(user):
- new = user=='new'
- user = User.query.get(user)
- if not new and user is None:
- return flask.redirect('/admin/users')
- if fll.current_user.level >= levels_users['Admin'] or \
- fll.current_user.level >= levels_users['Can manage simple users'] and \
- fll.current_user.level > user.level:
- if flask.request.method=="POST":
- username = flask.request.form['username']
- name = flask.request.form['name']
- password = flask.request.form['password']
- level = int(flask.request.form['level'])
- if level not in levels_users.values():
- flask.flash('Level unknown')
- return flask.render_template("admin_user_edit.html", user=fll.current_user, useredit=user, levels_users=levels_users)
- if fll.current_user.level < levels_users['Admin']:
- if not level < fll.current_user.level:
- flask.flash('Invalid level')
- return flask.render_template("admin_user_edit.html", user=fll.current_user, useredit=user, levels_users=levels_users)
- if len(password)<2 and new:
- flask.flash('Mot de passe trop court')
- return flask.render_template("admin_user_edit.html", user=fll.current_user, useredit=user, levels_users=levels_users)
- if new and User.query.get(username) is not None:
- flask.flash('Login déjà utilisé ! Choisissez un autre !')
- return flask.render_template("admin_user_edit.html", user=fll.current_user, useredit=user, levels_users=levels_users)
- if new:
- usertoadd = User(login=username, name=name, level=level)
- usertoadd.set_password(password)
- db.session.add(usertoadd)
- else:
- user.name = name
- if len(password)>=2:
- user.set_password(password)
- user.level = level
- db.session.commit()
- return flask.redirect('/admin/users')
- else:
- return flask.render_template("admin_user_edit.html", user=fll.current_user, useredit=user, levels_users=levels_users)
- return flask.redirect(URL_DEFAULT)
- @app.route('/admin/users/<user>/del')
- @fll.login_required
- def deluser(user):
- user = User.query.get(user)
- if user is None:
- return flask.redirect('/admin/users')
- if fll.current_user.level >= levels_users['Admin'] or \
- fll.current_user.level >= levels_users['Can manage simple users'] and \
- fll.current_user.level > user.level:
- confirm = flask.request.args.get('confirm')
- if confirm is not None:
- delete_game(user=user)
- db.session.delete(user)
- db.session.commit()
- return flask.redirect('/admin/users')
- return flask.render_template("admin_user_del.html", user=fll.current_user, useredit=user)
- @app.route('/password', methods=['GET', 'POST'])
- @fll.login_required
- def change_password():
- if flask.request.method=="POST":
- password = flask.request.form['password']
- if len(password) < 5:
- flask.flash('Mot de passe trop court !')
- else:
- fll.current_user.set_password(password)
- db.session.commit()
- return flask.redirect(URL_DEFAULT)
- return flask.render_template("password.html", user=fll.current_user)
- #######################################################################
- # Game managament #
- #######################################################################
- @app.route('/admin/games')
- @fll.login_required
- def admin_games():
- if fll.current_user.level < levels_users['Can manage games']:
- return flask.redirect(URL_DEFAULT)
- games = Game.query.all()
- return flask.render_template('admin_games.html', user=fll.current_user, games=games)
- @app.route('/admin/games/<roomid>/del')
- @fll.login_required
- def admin_game_del(roomid):
- game = Game.query.get(roomid)
- if game is None:
- return flask.redirect('/admin/games')
- if fll.current_user.level >= levels_users['Can manage games']:
- confirm = flask.request.args.get('confirm')
- if confirm is not None:
- delete_game(game=game)
- return flask.redirect('/admin/games')
- else:
- return flask.render_template('game_del.html', user=fll.current_user, game=game)
- return flask.redirect(URL_DEFAULT)
- @app.route('/game/<roomid>/see')
- @fll.login_required
- def see_game(roomid):
- game = Game.query.get(roomid)
- if game is None:
- return flask.redirect('/games')
- if fll.current_user.level >= levels_users['Can manage games'] or game.authorized(fll.current_user) and game.turn==N_TURN*N_PLAYERS:
- #return game.serialize_state_anonymous()
- return flask.render_template('game_see.html', user=fll.current_user, game=game, serialized=game.serialize_state_anonymous())
- return flask.redirect(URL_DEFAULT)
- @app.route('/admin/games/new', methods=['GET', 'POST'])
- @fll.login_required
- def admin_games_new():
- if fll.current_user.level < levels_users['Can manage games']:
- return flask.redirect(URL_DEFAULT)
- if flask.request.method=="POST":
- name = flask.request.form['name']
- login0 = flask.request.form['player0']
- login1 = flask.request.form['player1']
- login2 = flask.request.form['player2']
- login3 = flask.request.form['player3']
- admin = flask.request.form['admin']
- if 'fixplayers' in flask.request.form:
- start = True
- else:
- start = False
- try:
- admin = int(admin)
- except:
- return 'Error'
- if admin<0 or admin>3:
- return 'Error'
- adminn = -1
- lusers = []
- if login0 != '':
- user0 = User.query.get(login0)
- if user0 is None:
- flask.flash('Utilisateur inconnu {}'.format(login0))
- else:
- lusers.append(user0)
- if admin==0: adminn = 0
- if login1 != '':
- user1 = User.query.get(login1)
- if user1 is None:
- flask.flash('Utilisateur inconnu {}'.format(login1))
- else:
- if admin==1: adminn = len(lusers)
- lusers.append(user1)
- if login2 != '':
- user2 = User.query.get(login2)
- if user2 is None:
- flask.flash('Utilisateur inconnu {}'.format(login2))
- else:
- if admin==2: adminn = len(lusers)
- lusers.append(user2)
- if login3 != '':
- user3 = User.query.get(login3)
- if user3 is None:
- flask.flash('Utilisateur inconnu {}'.format(login3))
- else:
- if admin==3: adminn = len(lusers)
- lusers.append(user3)
- if adminn <0:
- flask.flash('Vous devez définir un maitre du jeu (admin).')
- elif len(name)<2:
- flask.flash('Nom trop court !')
- else:
- game = Game(name=name, admin=lusers[adminn].login)
- db.session.add(game)
- db.session.commit()
- ordered_players = []
- for u in lusers:
- ordered_players.append(u.login)
- game.join(u)
- db.session.commit()
- if start and game.can_start():
- game.fix_players()
- game.start_game(ordered_players)
- return flask.redirect('/admin/games')
- return flask.render_template('admin_game_add.html', user=fll.current_user)
- def delete_game(user=None, game=None):
- if user is not None:
- games = Game.query.filter_by(admin=user.login).all()
- for g in games:
- for p in g.players:
- db.session.delete(p)
- db.session.delete(g)
- db.session.commit()
- if isinstance(game, int):
- g = Game.query.get(game)
- if g is not None:
- for p in g.players:
- db.session.delete(p)
- db.session.delete(g)
- db.session.commit()
- elif game is not None:
- for p in game.players:
- db.session.delete(p)
- db.session.delete(game)
- db.session.commit()
- if __name__ == '__main__':
- socketio.run(app, debug=True, host='127.0.0.1', port=8080 )
|