Ejemplo n.º 1
0
def change_password(env: TEnvironment, query: TQuery,
                    cookie: TCookie) -> TResponse:
    """

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Returns:
        TODO: add description
    """

    data = get_json_by_response(env)

    if 'user_id' not in data or 'pass' not in data:
        return http.bad_request(host=env['HTTP_HOST'])

    logger('change_password()',
           f'Change password for {data["user_id"]}.',
           type_='LOG')

    if sql.change_password(data['user_id'], data['pass']):
        return http.ok(host=env['HTTP_HOST'])
    else:
        return http.bad_request(host=env['HTTP_HOST'])
Ejemplo n.º 2
0
def read_places() -> tp.List[str]:
    """Read list of places from file (`places.list`) """

    global PLACES

    # Check file exist. or auto create
    if not os.path.exists(PLACES_PATH):
        logger('read_places()',
               'No places file. Using default places file',
               type_='INFO')
        if os.path.exists(DEFAULT_PLACES_PATH):
            shutil.copy(DEFAULT_PLACES_PATH, PLACES_PATH)
        else:
            # Create empty
            logger('read_places()',
                   'No default places file. Using default values',
                   type_='ERROR')
            with open(PLACES_PATH, "a+") as f:
                pass

    PLACES = []
    with open(PLACES_PATH, "r") as f:
        for place in sorted(f.readlines()):
            if place != '\n':
                PLACES.append(place[:-1] if place[-1] == '\n' else place)

    return list(PLACES)
Ejemplo n.º 3
0
def add_place(place: str) -> None:
    """ add place to PLACES and mb save it to file"""

    global PLACES

    logger('add_place()', f'Adding place = {place}', 'LOG')
    if place not in PLACES:
        PLACES.append(place)
        write_places()
Ejemplo n.º 4
0
def update_cache() -> None:
    """ Update cache and sync events, projects and etc

    Note:
        Run every TIMEOUT seconds
    """

    # Update today
    logger('update_cache()', '', type_='LOG')

    return
Ejemplo n.º 5
0
def sync() -> None:
    """ Update cache and sync events, projects and etc

    Note:
        Run every TIMEOUT seconds
    """

    logger('sync()', '==== Sync start ====', type_='LOG')
    update_cache()  # Sync itself
    logger('sync()', '==== Sync end ======', type_='LOG')

    start_sync(TIMEOUT)  # Update - to call again
Ejemplo n.º 6
0
def post_credits(env: TEnvironment, query: TQuery, cookie: TCookie) -> TResponse:
    """ Sing in at lecture  HTTP request (by student )
    By cookie add credits to user

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Note:
        Send:
            200 Ok: if all are ok
            401 Unauthorized: if wrong session id
            405 Method Not Allowed: already got it or timeout

    Returns:
        Response - result of request
        None; Only http answer
    """

    # TODO: CREDITS

    # Event code
    # code = query['code']
    # print('Credits code: ', code)

    event_id = 42  # TODO: Get event id from code

    # Safety get user_obj
    user_obj = get_user_by_response(cookie)
    if user_obj is None:
        return http.wrong_cookie(env['HTTP_HOST'])

    event_obj = sql.get_event(event_id)
    if event_obj is not None:
        # gsheets.save_credits(user_obj, event_obj)
        sql.checkin_user(user_obj, event_obj)
        logger('post_credits()', f'Checkin user {user_obj} to {event_obj}', type_='LOG')

        return http.ok(env['HTTP_HOST'])

    else:
        return http.not_allowed()
Ejemplo n.º 7
0
def get_day(env: TEnvironment, query: TQuery, cookie: TCookie) -> TResponse:
    """ Day schedule data HTTP request
    Get day num and return html

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Note:
        Cached by TIMEOUT
        return day html by req from query string (if none return today)

    Returns:
        Response - result of request

        html data: day schedule
    """

    # format is "dd.mm"
    try:
        day = query['day']
    except KeyError:
        day = get_date_str()  # Get for today day

    if day not in ['Template', '05.06', '06.06', '07.06', '08.06', '09.06', '10.06', '11.06', '12.06',
                   '13.06', '14.06', '15.06', '16.06', '17.06', '18.06']:
        # print('day overflow, falling back to the last day available')  # TODO: Remove or check in sql
        logger('get_day()', 'day overflow, falling back to the last day available', type_='ERROR')
        day = '05.06'

    # print('get data days for ', day)

    data = sql.get_day(day)

    data = sorted(data, key=lambda x: x['time'])
    groups = groupby(data, key=lambda x: x['time'])

    data = [{'time': time_, 'events': [event for event in group_]} for time_, group_ in groups]

    return http.ok(json_dict=data)
Ejemplo n.º 8
0
def write_config() -> None:
    """Write current configuration to config file (`ihse.ini`) """

    global CREDITS_TOTAL, CREDITS_MASTER, CREDITS_LECTURE, CREDITS_ADDITIONAL, NUMBER_TEAMS

    logger('write_config()', '==== Write config file ====', type_='LOG')
    config = configparser.ConfigParser()

    config['CREDITS'] = {
        'total': CREDITS_TOTAL,
        'masterclass': CREDITS_MASTER,
        'lecture': CREDITS_LECTURE,
        'additional': CREDITS_ADDITIONAL
    }

    config['TEAMS'] = {'number': NUMBER_TEAMS}

    with open(CONFIG_PATH, 'w') as configfile:
        config.write(configfile)

    logger('write_config()', '==== End config file writing ====', type_='LOG')
Ejemplo n.º 9
0
def clear_table(env: TEnvironment, query: TQuery,
                cookie: TCookie) -> TResponse:
    """

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Returns:
        TODO: add description
    """

    table_name = query['table']

    if table_name in sql.table_fields.keys():
        sql.clear_table(table_name)
    else:
        logger('admin_panel()', '400 Bad Request by admin', type_='ERROR')
        return http.bad_request(host=env['HTTP_HOST'])

    return http.ok(host=env['HTTP_HOST'])
Ejemplo n.º 10
0
def read_config() -> None:
    """Read and save config file (`ihse.ini`) """

    logger('read_config()', '==== Read config file ====', type_='LOG')

    global CREDITS_TOTAL, CREDITS_MASTER, CREDITS_LECTURE, CREDITS_ADDITIONAL, NUMBER_TEAMS

    # Check file exist. or auto create
    with open(CONFIG_PATH, "a+") as f:
        pass

    try:
        config = configparser.ConfigParser()
        config.read(CONFIG_PATH)

        CREDITS_TOTAL = int(config['CREDITS']['total'])
        CREDITS_MASTER = int(config['CREDITS']['masterclass'])
        CREDITS_LECTURE = int(config['CREDITS']['lecture'])
        CREDITS_ADDITIONAL = int(config['CREDITS']['additional'])

        NUMBER_TEAMS = int(config['TEAMS']['number'])
    except (KeyError, configparser.MissingSectionHeaderError):
        logger('read_config()',
               'No config file. Using default config file',
               type_='INFO')
        try:
            config = configparser.ConfigParser()
            config.read(DEFAULT_CONFIG_PATH)

            CREDITS_TOTAL = int(config['CREDITS']['total'])
            CREDITS_MASTER = int(config['CREDITS']['masterclass'])
            CREDITS_LECTURE = int(config['CREDITS']['lecture'])
            CREDITS_ADDITIONAL = int(config['CREDITS']['additional'])

            NUMBER_TEAMS = int(config['TEAMS']['number'])
            write_config()
        except (KeyError, configparser.MissingSectionHeaderError):
            logger('read_config()',
                   'No default config file. Using default values',
                   type_='ERROR')
            CREDITS_TOTAL = 300
            CREDITS_MASTER = 15
            CREDITS_LECTURE = 15
            CREDITS_ADDITIONAL = 5
            NUMBER_TEAMS = 5
            write_config()

    logger('read_config()', '==== End config file reading ====', type_='LOG')
Ejemplo n.º 11
0
def admin(env: TEnvironment, query: TQuery, cookie: TCookie) -> TResponse:
    """ Manage admin HTTP request
    Will check session id and permissions

    Note:
        If there is no cookie or it is incorrect - Error

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Returns:
        Response - result of request
    """

    logger('admin_panel()', 'Admin try with cookie {cookie}', type_='LOG')

    # Safety get user_obj
    user_obj = get_user_by_response(cookie)
    if user_obj is None:
        return http.wrong_cookie(host=env['HTTP_HOST'])

    logger('admin_panel()', f'Admin try with user: {user_obj}', type_='LOG')

    if user_obj['user_type'] == 0:
        return http.not_allowed()

    logger('admin_panel()', f'Admin want to {env["PATH_INFO"]}', type_='LOG')

    functions = {
        '/admin_get_config': get_config,
        '/admin_post_config': post_config,
        '/admin_get_places': get_places,
        '/admin_post_places': post_places,
        '/admin_get_credits': get_credits,
        '/checkin': post_checkin,
        '/admin_get_table': get_table,
        '/admin_clear_table': clear_table,
        '/admin_send_data': send_data,
        '/admin_remove_data': remove_data,
        '/admin_codes': codes,
        '/admin_change_password': change_password
    }

    if env['PATH_INFO'] in functions:
        return functions[env['PATH_INFO']](env, query, cookie)
Ejemplo n.º 12
0
def post_checkin(env: TEnvironment, query: TQuery,
                 cookie: TCookie) -> TResponse:
    """ Check in at lecture  HTTP request (by admin)
    By cookie add credits to user

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Note:
        Send:
            200 Ok: if all are ok
            401 Unauthorized: if wrong session id
            405 Method Not Allowed: already got it or timeout

    Returns:
        Response - result of request
        None; Only http answer
    """

    checkins = get_json_by_response(env)
    event_id = query['event']

    # Safety get user_obj
    user_obj = get_user_by_response(cookie)

    event = sql.get_in_table(event_id, 'events')

    if event is None:  # No such event
        return http.not_allowed(host=env['HTTP_HOST'])

    config_dict = config.get_config()

    # Set up credits and enrolls attendance
    if event['type'] == 1 and event['total'] > 0:
        # master
        # Check there are enrolls
        enrolls = sql.get_enrolls_by_event_id(event_id)

        users_in_enrolls = {
            enroll['user_id']
            for enroll in enrolls if not enroll['attendance']
        }  # type: tp.Set[int]
        users_in_checkins = {
            int(checkin['id']): min(int(checkin['bonus']),
                                    config_dict['CREDITS_ADDITIONAL'])
            for checkin in checkins
        }  # type: tp.Dict[int, int]

        users_to_set_credits = {
            k
            for k in users_in_checkins.keys() if k in users_in_enrolls
        }  # type: tp.Set[int]

        # Setup attendance for enrolls
        enrolls = [
            enroll for enroll in enrolls
            if enroll['user_id'] in users_to_set_credits
        ]  # type: tp.List[sql.TTableObject]
        for i in range(len(enrolls)):
            enrolls[i]['attendance'] = True
            enrolls[i]['bonus'] = users_in_checkins[enrolls[i]['user_id']]

            sql.update_in_table(enrolls[i], 'enrolls')

        # TODO: Minus balls if not attendant
        credits = [{
            'user_id':
            int(checkin['id']),
            'event_id':
            event_id,
            'validator_id':
            user_obj['id'],
            'time':
            get_datetime_str(),
            'value':
            config_dict['CREDITS_MASTER'] +
            min(int(checkin['bonus']), config_dict['CREDITS_ADDITIONAL'])
        } for checkin in checkins if int(checkin['id']) in users_to_set_credits
                   ]  # type: tp.List[sql.TTableObject]
        for credit in credits:
            sql.insert_to_table(credit, 'credits')

        logger('post_checkin()',
               f'Checkin users {users_in_checkins} to master event {event_id}',
               type_='LOG')
    else:
        # lecture
        enrolls = [{
            'class_id':
            event_id,
            'user_id':
            int(checkin['id']),
            'time':
            get_datetime_str(),
            'attendance':
            True,
            'bonus':
            min(int(checkin['bonus']), config_dict['CREDITS_ADDITIONAL'])
        } for checkin in checkins]  # type: tp.List[sql.TTableObject]
        for enroll in enrolls:
            sql.update_in_table(enroll, 'enrolls')

        credits = [{
            'user_id':
            int(checkin['id']),
            'event_id':
            event_id,
            'time':
            get_datetime_str(),
            'value':
            config_dict['CREDITS_LECTURE'] +
            min(int(checkin['bonus']), config_dict['CREDITS_ADDITIONAL'])
        } for checkin in checkins]  # type: tp.List[sql.TTableObject]
        for credit in credits:
            sql.insert_to_table(credit, 'credits')

        logger('post_checkin()',
               f'Checkin user {checkins} to lecture event {event_id}',
               type_='LOG')

    return http.ok(env['HTTP_HOST'])
Ejemplo n.º 13
0
def post_login(env: TEnvironment, query: TQuery, cookie: TCookie) -> TResponse:
    """ Login HTTP request
    Create new session if it does not exist and send cookie sessid

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Note:
        Send:
            200 Ok: if user exist and session created correctly
                    and send cookie with sess id
            401 Unauthorized: if wrong name of pass

    Returns:
        Response - result of request
    """

    reg_data = get_json_by_response(env)
    try:
        phone, passw = reg_data['phone'], reg_data['pass']
    except KeyError:
        # print('ERROR, No registration data.')
        logger('post_login()', 'No registration data in req.', type_='ERROR')
        return http.forbidden()
    try:
        remember = reg_data['remember']
    except KeyError:
        remember = True

    # print(phone)
    phone = "+7" + phone[2:]
    phone = ''.join(i for i in phone if i.isdigit())

    # Get session obj or None
    session_id = sql.login(phone, passw, env['HTTP_USER_AGENT'], env['REMOTE_ADDR'], get_datetime_str())

    if session_id is not None:
        # Convert: b'\xbeE%-\x8c\x14y3\xd8\xe1ui\x03+D\xb8' -> be45252d8c147933d8e17569032b44b8
        sessid = session_id.hex()
        # sessid = bytes.hex(res[0])
        # sessid = bytes(res[0])
        # print(f'login with got:{sessid}')

        expires = 'Max-Age=15768000;' if remember else ''

        return ('200 OK',
                [
                    # Because in js there is xhttp.withCredentials = true;
                    ('Access-Control-Allow-Origin', f"//{env['HTTP_HOST']}"),
                    # To receive cookie
                    ('Access-Control-Allow-Credentials', 'true'),
                    ('Set-Cookie',
                     f"sessid={sessid}; Path=/; Domain={env['HTTP_HOST']}; HttpOnly;{expires}"),
                    # 1/2 year
                    # ('Location', '//ihse.tk/')
                ],
                [])

    else:
        return http.unauthorized()
Ejemplo n.º 14
0
def post_register(env: TEnvironment, query: TQuery, cookie: TCookie) -> TResponse:
    """ Register HTTP request
    Create new user if it does not exist and login user

    Args:
        env: HTTP request environment
        query: url query parameters
        cookie: http cookie parameters (may be empty)

    Query args:
        env: HTTP request environment
        name: User name - string
        phone: User phone - string
        passw: Password hash - int
        code: special code responsible for the user type and permission to register - string

    Note:
        Send:
            200 Ok: if user exist and session created correctly
                    and send cookie with sess id
            401 Unauthorized: if wrong name of pass

    Returns:
        Response - result of request
    """

    reg_data = get_json_by_response(env)
    try:
        name = reg_data['name']
        surname = reg_data['surname']
        phone = reg_data['phone']
        sex = reg_data['sex']
        passw = reg_data['pass']
        code = reg_data['code']
    except KeyError:
        # print('ERROR, No registration data.')
        logger('post_login()', 'No registration data in req.', type_='ERROR')
        return http.forbidden()

    # print(phone)
    phone = "+7" + phone[2:]
    phone = ''.join(i for i in phone if i.isdigit())

    # Check registration code
    # user_type = gsheets.check_code(code)

    # user = sql.get_user_by_phone(phone)

    team = random.randint(1, config.get_config()['NUMBER_TEAMS'])  # TODO: Sex distribution

    # Create new user
    if sql.register(code, name, surname, phone, sex, passw, team):
        # Auto login of user
        session_id = sql.login(phone, passw, env['HTTP_USER_AGENT'], env['REMOTE_ADDR'], get_datetime_str())

        if session_id is not None:
            # Convert: b'\xbeE%-\x8c\x14y3\xd8\xe1ui\x03+D\xb8' -> be45252d8c147933d8e17569032b44b8
            sessid = session_id.hex()
            # sessid = bytes.hex(res[0])
            # sessid = bytes(res[0])
            # print(f'login with got:{sessid}')

            return ('200 OK',
                    [
                        # Because in js there is xhttp.withCredentials = true;
                        ('Access-Control-Allow-Origin', f"//{env['HTTP_HOST']}"),
                        # To receive cookie
                        ('Access-Control-Allow-Credentials', 'true'),
                        ('Set-Cookie',
                         'sessid=' + sessid + f"; Path=/; Domain={env['HTTP_HOST']}; HttpOnly; Max-Age=15768000;"),
                        # 1/2 year
                        # ('Location', '//ihse.tk/')
                    ],
                    [])
        else:
            return http.unauthorized()
    else:
        return http.conflict()