def delete():
    if request.method == 'POST':
        dos = arrow.get(g.user.created).humanize()
        calendars = len([c for c in Calendar.query(ancestor=g.user.key)])
        todos = len([e for e in Event.query(ancestor=g.user.key)])
        subject = '%s %s closed their account' % (g.user.first_name, g.user.last_name)
        body = '''
%s (joined %s, made %d todos and had %d calendars)

%s
''' % (g.user.email, dos, todos, calendars, request.form.get('feedback'))
        mail.send_mail(sender=EMAILS['alerts'], to=EMAILS['support'], subject=subject, body=body)

        calendars = Calendar.get_all(g.user.key)
        for calendar in calendars:
            for event in Event.get_all(calendar.key):
                event.key.delete()
            calendar.key.delete()

        User.unindex(g.user.key.urlsafe())
        g.user.key.delete()
        session.pop('user', None)
        return redirect('/index.html')

    return render_template('delete.html')
Exemple #2
0
def login(provider):
    if request.method == 'POST':
        session.permanent = 'remember' in request.form
        session.modified = True

    response = make_response()
    result = AUTHOMATIC.login(WerkzeugAdapter(request, response), provider)
    if result:
        if result.user:
            result.user.update()
            credentials = result.user.credentials.serialize()
            user = User.create_or_update(provider, result.user.id,
                                         result.user.email,
                                         result.user.first_name,
                                         result.user.last_name, credentials)
            session['user'] = user.key.urlsafe()

            # If they are on the freemium list hook them up.
            if (not user.is_premium) and (Freemium.get_by_email(
                    result.user.email) is not None):
                user.is_premium = True
                user.put()
                flash(
                    'You\'ve been upgraded to a free premium account for one year!'
                )

            return redirect('/todos')

        return render_template('login.html', result=result)

    return response
Exemple #3
0
def current_user(request):
    """获取当前登录用户

    Args:
        request: 请求对象

    Returns:
        如果已登录,返回当前登录用户对象,否则返回 None
    """
    # 从 Cookie 中获取 session_id
    cookies = request.cookies
    logger(f'cookies: {cookies}')
    session_id = cookies.get('session_id')

    # 查找 Session 并验证其是否过期
    session = Session.get(session_id)
    if not session:
        return None
    if session.is_expired():
        session.delete()
        return None

    # 查找当前登录用户
    user = User.get(session.user_id)
    if not user:
        return None
    return user
def login(provider):
    if request.method == 'POST':
        session.permanent = 'remember' in request.form
        session.modified = True

    response = make_response()
    result = AUTHOMATIC.login(WerkzeugAdapter(request, response), provider)
    if result:
        if result.user:
            result.user.update()
            credentials = result.user.credentials.serialize()
            user = User.create_or_update(provider,
                                         result.user.id,
                                         result.user.email,
                                         result.user.first_name,
                                         result.user.last_name,
                                         credentials)
            session['user'] = user.key.urlsafe()

            # If they are on the freemium list hook them up.
            if (not user.is_premium) and (Freemium.get_by_email(result.user.email) is not None):
                user.is_premium = True
                user.put()
                flash('You\'ve been upgraded to a free premium account for one year!')

            return redirect('/todos')

        return render_template('login.html', result=result)

    return response
Exemple #5
0
def test_user():
    """测试 User 模型类"""
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    u = User(username=username, password=password)
    u.save()
    us = User.all(sort=True)
    find_user = User.find_by(username=username, ensure_one=True)
    u.delete()

    assert u.username == username
    assert u.password == password
    assert u.validate_password(raw_password, u.password) is True
    assert u.id in [u.id for u in us]
    assert u.id == find_user.id
Exemple #6
0
def restrict_to_admin_users():
    g.user = None
    if 'user' in session:
        g.user = User.get_by_id(session['user'])

    if not g.user or not g.user.is_admin:
        session.pop('user', None)
        abort(403)
Exemple #7
0
def manage_user(user_id):
    user = User.get_by_id(user_id)
    if user is None:
        User.unindex(user_id)
        flash('User deleted their account; cleaned up search index')
        return redirect('/admin/user/search')

    if request.method == 'POST':
        operation = request.form.get('operation')
        if operation == 'goodbye':
            app_user.send_goodbye(user)
        elif operation == 'sync':
            sync_time = datetime.utcnow()
            sync_utc = pytz.utc.localize(sync_time)
            client = make_client(user)
            sync_user(sync_time, user, client, debug=True)
            flash('Synced user')
        elif operation == 'upgrade':
            user.is_premium = True
            user.put()
        elif operation == 'downgrade':
            user.is_premium = False
            user.put()
        else:
            flash('Unknown operation')

    calendars = 0
    todos = 0
    completed = 0
    for calendar in Calendar.get_all(user.key):
        calendars += 1
        for event in Event.get_all(calendar.key):
            todos += 1
            if event.done:
                completed += 1

    extra = {
        'calendars': calendars,
        'todos': todos,
        'completed': completed,
        'created': arrow.get(user.created).humanize(),
        'updated': arrow.get(user.updated).humanize(),
    }
    return render_template('admin-user-manage.html',
                           manage_user=user,
                           extra=extra)
def restrict_to_admin_users():
    g.user = None
    if 'user' in session:
        g.user = User.get_by_id(session['user'])

    if not g.user or not g.user.is_admin:
        session.pop('user', None)
        abort(403)
Exemple #9
0
def test_login():
    """测试登录"""
    # 测试 GET 请求
    request_message = 'GET /login HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n\r\n'
    request = Request(request_message)
    route, method = routes.get(request.path)
    r = route(request)
    assert 'Login' in r

    # 测试 POST 请求
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    u = User(username=username, password=password)
    u.save()
    request_message = f'POST /login HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n\r\n' \
                      f'username={username}&password={raw_password}'
    request = Request(request_message)
    route, method = routes.get(request.path)
    r = route(request)
    u.delete()
    s = Session.get(r.cookies.get('session_id'))
    s.delete()
    assert b'302 FOUND' in bytes(r)
    assert b'/index' in bytes(r)
    assert b'session_id' in bytes(r)

    r = route(request)
    assert r.decode('utf-8') == '用户名或密码不正确'
Exemple #10
0
def test_delete():
    """测试删除 todo"""
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    u = User(username=username, password=password)
    u.save()
    s = Session(user_id=u.id, expire_in='2099-12-31 00:00:00')
    s.save()
    content = uuid.uuid4().hex
    t = Todo(user_id=u.id, content=content)
    t.save()
    request_message = f'POST /delete HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n' \
                      f'Cookie: session_id={s.id}\r\n\r\nid={t.id}'
    request = Request(request_message)
    route, method = routes.get(request.path)
    r = route(request)
    t = Todo.find_by(user_id=u.id, content=content, ensure_one=True)
    u.delete()
    s.delete()
    assert b'302 FOUND' in bytes(r)
    assert b'/index' in bytes(r)
    assert t is None

    r = route(request)
    assert b'302 FOUND' in bytes(r)
    assert b'/login' in bytes(r)
Exemple #11
0
def login(request):
    """登录

    Args:
        request: 请求对象

    Returns:
        GET 请求:
            返回登录页面
        POST 请求:
            登录成功将重定向到首页
            登录失败返回失败原因提示短语
    """
    # 如果用户已经登录,直接重定向到首页
    if current_user(request):
        return redirect('/index')

    if request.method == 'POST':
        message = '用户名或密码不正确'.encode('utf-8')

        # 获取表单中的用户名和密码
        form = request.form
        logger(f'form: {form}')
        username = form.get('username')
        raw_password = form.get('password')

        # 验证用户名和密码是否正确
        if not username or not raw_password:
            return message
        user = User.find_by(username=username, ensure_one=True)
        if not user:
            return message
        password = user.password
        if not User.validate_password(raw_password, password):
            return message

        # 创建 Session 并将 session_id 写入 Cookie 实现登录
        session = Session(user_id=user.id)
        session.save()
        cookies = {
            'session_id': session.id,
        }
        return redirect('/index', cookies=cookies)

    return render_template('auth/login.html')
def manage_user(user_id):
    user = User.get_by_id(user_id)
    if user is None:
        User.unindex(user_id)
        flash('User deleted their account; cleaned up search index')
        return redirect('/admin/user/search')

    if request.method == 'POST':
        operation = request.form.get('operation')
        if operation == 'goodbye':
            app_user.send_goodbye(user)
        elif operation == 'sync':
            sync_time = datetime.utcnow()
            sync_utc = pytz.utc.localize(sync_time)
            client = make_client(user)
            sync_user(sync_time, user, client, debug=True)
            flash('Synced user')
        elif operation == 'upgrade':
            user.is_premium = True
            user.put()
        elif operation == 'downgrade':
            user.is_premium = False
            user.put()
        else:
            flash('Unknown operation')

    calendars = 0
    todos = 0
    completed = 0
    for calendar in Calendar.get_all(user.key):
        calendars += 1
        for event in Event.get_all(calendar.key):
            todos += 1
            if event.done:
                completed += 1

    extra = {
        'calendars': calendars,
        'todos': todos,
        'completed': completed,
        'created': arrow.get(user.created).humanize(),
        'updated': arrow.get(user.updated).humanize(),
    }
    return render_template('admin-user-manage.html', manage_user=user, extra=extra)
Exemple #13
0
def restrict_to_signed_in_users():
    g.user = None
    if 'user' in session:
        g.user = User.get_by_id(session['user'])

    if not g.user:
        session.pop('user', None)
        return redirect('/')

    g.client = make_client(g.user)
Exemple #14
0
def force_job():
    task_url = '/api/v1/queues/sync/user'
    for key in User.get_all_keys():
        params = {
            'user_id': key.urlsafe(),
            'force': 1,
        }
        taskqueue.add(url=task_url, params=params)

    return make_response()
Exemple #15
0
def register(request):
    """注册

    Args:
        request: 请求对象

    Returns:
        GET 请求:
            返回注册页面
        POST 请求:
            注册成功将重定向到登录页
            注册失败返回失败原因提示短语
    """
    if request.method == 'POST':
        # 获取表单中的用户名和密码
        form = request.form
        logger(f'form: {form}')
        username = form.get('username')
        raw_password = form.get('password')

        # 验证用户名和密码是否合法
        if not username or not raw_password:
            return '无效的用户名或密码'.encode('utf-8')
        user = User.find_by(username=username, ensure_one=True)
        if user:
            return '用户名已存在'.encode('utf-8')

        # 对密码进行散列计算,创建并保存用户信息
        password = User.generate_password(raw_password)
        user = User(username=username, password=password)
        user.save()
        # 注册成功后重定向到登录页面
        return redirect('/login')

    return render_template('auth/register.html')
Exemple #16
0
def test_register():
    """测试注册"""
    # 测试 GET 请求
    request_message = 'GET /register HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n\r\n'
    request = Request(request_message)
    route, method = routes.get(request.path)
    r = route(request)
    assert 'Register' in r

    # 测试 POST 请求
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    request_message = f'POST /register HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n\r\n' \
                      f'username={username}&password={password}'
    request = Request(request_message)
    route, method = routes.get(request.path)
    r = route(request)
    u = User.find_by(username=username, ensure_one=True)
    u.delete()
    assert b'302 FOUND' in bytes(r)
    assert b'/login' in bytes(r)
def rollup_users():
    rollup = defaultdict(lambda: defaultdict(int))
    for user in User.get_all():
        (year, week, day) = user.created.isocalendar()
        rollup[year][week] += 1

    def gen():
        for year in sorted(rollup):
            for week in sorted(rollup[year]):
                yield (year, week)

    cum = 0
    for year, week in gen():
        cum += rollup[year][week]
        Stat.create_or_update('user-count', year, week, cum)
Exemple #18
0
def rollup_users():
    rollup = defaultdict(lambda: defaultdict(int))
    for user in User.get_all():
        (year, week, day) = user.created.isocalendar()
        rollup[year][week] += 1

    def gen():
        for year in sorted(rollup):
            for week in sorted(rollup[year]):
                yield (year, week)

    cum = 0
    for year, week in gen():
        cum += rollup[year][week]
        Stat.create_or_update('user-count', year, week, cum)
Exemple #19
0
def sync_job():
    sync_time = datetime.utcnow()
    sync_utc = pytz.utc.localize(sync_time)
    user = User.get_by_id(request.form['user_id'])

    if 'force' in request.form:
        client = make_client(user)
        sync_user(sync_time, user, client)
    else:
        for db_calendar in Calendar.get_all(user.key):
            local_tz = safe_timezone(db_calendar.time_zone)
            sync_local = local_tz.normalize(sync_utc)
            if sync_local.hour == 0:
                client = make_client(user)
                sync_user(sync_time, user, client)
                break

    return make_response()
Exemple #20
0
def search_user():
    query = request.args.get('q', '')
    results = User.search(query)
    simplified = list()
    for result in results:
        entry = {'link': '/admin/user/manage/%s' % result.doc_id}
        for field in result.fields:
            if field.name == 'created':
                entry[field.name] = arrow.get(field.value).humanize()
            else:
                entry[field.name] = field.value
        simplified.append(entry)
    extra = {
        'total': results.number_found,
        'shown': len(results.results),
    }
    return render_template('admin-user-search.html',
                           results=simplified,
                           extra=extra)
def search_user():
    query = request.args.get('q', '')
    results = User.search(query)
    simplified = list()
    for result in results:
        entry = {
            'link': '/admin/user/manage/%s' % result.doc_id
        }
        for field in result.fields:
            if field.name == 'created':
                entry[field.name] = arrow.get(field.value).humanize()
            else:
                entry[field.name] = field.value
        simplified.append(entry)
    extra = {
        'total': results.number_found,
        'shown': len(results.results),
    }
    return render_template('admin-user-search.html', results=simplified, extra=extra)
Exemple #22
0
def test_todo():
    """测试 Todo 模型类"""
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    u = User(username=username, password=password)
    u.save()
    content = uuid.uuid4().hex
    t = Todo(user_id=u.id, content=content)
    t.save()
    ts = Todo.all()
    find_todo = Todo.get(t.id)
    u.delete()
    t.delete()

    assert t.user_id == u.id
    assert t.content == content
    assert t.id in [t.id for t in ts]
    assert t.id == find_todo.id
Exemple #23
0
def test_session():
    """测试 Session 模型类"""
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    u = User(username=username, password=password)
    u.save()
    expire_in = '2099-12-31 00:00:00'
    s = Session(user_id=u.id, expire_in=expire_in)
    s.save()
    ss = Session.all()
    find_sessions = Session.find_by(user_id=u.id, expire_in=expire_in)
    u.delete()
    s.delete()

    assert s.user_id == u.id
    assert s.expire_in == expire_in
    assert s.id in [s.id for s in ss]
    assert s.id == find_sessions[0].id
    assert len(find_sessions) == 1
Exemple #24
0
def test_index():
    """测试首页"""
    username = uuid.uuid4().hex
    raw_password = '******'
    password = User.generate_password(raw_password)
    u = User(username=username, password=password)
    u.save()
    s = Session(user_id=u.id, expire_in='2099-12-31 00:00:00')
    s.save()
    request_message = f'GET / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n' \
                      f'Cookie: session_id={s.id}\r\n\r\n'
    request = Request(request_message)
    route, method = routes.get(request.path)
    r = route(request)
    u.delete()
    s.delete()
    assert b'Todo List' in bytes(r, encoding='utf-8')
    assert b'/new' in bytes(r, encoding='utf-8')

    r = route(request)
    assert b'302 FOUND' in bytes(r)
    assert b'/login' in bytes(r)