server/posts: add non-guessable IDs to post URLs
This commit is contained in:
		
							parent
							
								
									90b0d77147
								
							
						
					
					
						commit
						4afece8d50
					
				@ -1,3 +1,4 @@
 | 
			
		||||
import hmac
 | 
			
		||||
from typing import Any, Optional, Tuple, List, Dict, Callable
 | 
			
		||||
from datetime import datetime
 | 
			
		||||
import sqlalchemy as sa
 | 
			
		||||
@ -83,36 +84,49 @@ FLAG_MAP = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_post_security_hash(id: int) -> str:
 | 
			
		||||
    return hmac.new(
 | 
			
		||||
        config.config['secret'].encode('utf8'),
 | 
			
		||||
        str(id).encode('utf-8')).hexdigest()[0:16]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_post_content_url(post: model.Post) -> str:
 | 
			
		||||
    assert post
 | 
			
		||||
    return '%s/posts/%d.%s' % (
 | 
			
		||||
    return '%s/posts/%d_%s.%s' % (
 | 
			
		||||
        config.config['data_url'].rstrip('/'),
 | 
			
		||||
        post.post_id,
 | 
			
		||||
        get_post_security_hash(post.post_id),
 | 
			
		||||
        mime.get_extension(post.mime_type) or 'dat')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_post_thumbnail_url(post: model.Post) -> str:
 | 
			
		||||
    assert post
 | 
			
		||||
    return '%s/generated-thumbnails/%d.jpg' % (
 | 
			
		||||
    return '%s/generated-thumbnails/%d_%s.jpg' % (
 | 
			
		||||
        config.config['data_url'].rstrip('/'),
 | 
			
		||||
        post.post_id)
 | 
			
		||||
        post.post_id,
 | 
			
		||||
        get_post_security_hash(post.post_id))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_post_content_path(post: model.Post) -> str:
 | 
			
		||||
    assert post
 | 
			
		||||
    assert post.post_id
 | 
			
		||||
    return 'posts/%d.%s' % (
 | 
			
		||||
        post.post_id, mime.get_extension(post.mime_type) or 'dat')
 | 
			
		||||
    return 'posts/%d_%s.%s' % (
 | 
			
		||||
        post.post_id,
 | 
			
		||||
        get_post_security_hash(post.post_id),
 | 
			
		||||
        mime.get_extension(post.mime_type) or 'dat')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_post_thumbnail_path(post: model.Post) -> str:
 | 
			
		||||
    assert post
 | 
			
		||||
    return 'generated-thumbnails/%d.jpg' % (post.post_id)
 | 
			
		||||
    return 'generated-thumbnails/%d_%s.jpg' % (
 | 
			
		||||
        post.post_id,
 | 
			
		||||
        get_post_security_hash(post.post_id))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_post_thumbnail_backup_path(post: model.Post) -> str:
 | 
			
		||||
    assert post
 | 
			
		||||
    return 'posts/custom-thumbnails/%d.dat' % (post.post_id)
 | 
			
		||||
    return 'posts/custom-thumbnails/%d_%s.dat' % (
 | 
			
		||||
        post.post_id, get_post_security_hash(post.post_id))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def serialize_note(note: model.PostNote) -> rest.Response:
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,43 @@
 | 
			
		||||
'''
 | 
			
		||||
Add hashes to post file names
 | 
			
		||||
 | 
			
		||||
Revision ID: 02ef5f73f4ab
 | 
			
		||||
Created at: 2017-08-24 13:30:46.766928
 | 
			
		||||
'''
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import re
 | 
			
		||||
from szurubooru.func import files, posts
 | 
			
		||||
 | 
			
		||||
revision = '02ef5f73f4ab'
 | 
			
		||||
down_revision = '5f00af3004a4'
 | 
			
		||||
branch_labels = None
 | 
			
		||||
depends_on = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def upgrade():
 | 
			
		||||
    for name in ['posts', 'posts/custom-thumbnails', 'generated-thumbnails']:
 | 
			
		||||
        for entry in list(files.scan(name)):
 | 
			
		||||
            match = re.match(r'^(?P<name>\d+)\.(?P<ext>\w+)$', entry.name)
 | 
			
		||||
            if match:
 | 
			
		||||
                post_id = int(match.group('name'))
 | 
			
		||||
                security_hash = posts.get_post_security_hash(post_id)
 | 
			
		||||
                ext = match.group('ext')
 | 
			
		||||
                new_name = '%s_%s.%s' % (post_id, security_hash, ext)
 | 
			
		||||
                new_path = os.path.join(os.path.dirname(entry.path), new_name)
 | 
			
		||||
                os.rename(entry.path, new_path)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def downgrade():
 | 
			
		||||
    for name in ['posts', 'posts/custom-thumbnails', 'generated-thumbnails']:
 | 
			
		||||
        for entry in list(files.scan(name)):
 | 
			
		||||
            match = re.match(
 | 
			
		||||
                r'^(?P<name>\d+)_(?P<hash>[0-9A-Fa-f]+)\.(?P<ext>\w+)$',
 | 
			
		||||
                entry.name)
 | 
			
		||||
            if match:
 | 
			
		||||
                post_id = int(match.group('name'))
 | 
			
		||||
                security_hash = match.group('hash')
 | 
			
		||||
                ext = match.group('ext')
 | 
			
		||||
                new_name = '%s.%s' % (post_id, ext)
 | 
			
		||||
                new_path = os.path.join(os.path.dirname(entry.path), new_name)
 | 
			
		||||
                os.rename(entry.path, new_path)
 | 
			
		||||
@ -270,6 +270,7 @@ def test_errors_not_spending_ids(
 | 
			
		||||
        'privileges': {
 | 
			
		||||
            'posts:create:identified': model.User.RANK_REGULAR,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    auth_user = user_factory(rank=model.User.RANK_REGULAR)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,12 +8,12 @@ from szurubooru.func import (
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('input_mime_type,expected_url', [
 | 
			
		||||
    ('image/jpeg', 'http://example.com/posts/1.jpg'),
 | 
			
		||||
    ('image/gif', 'http://example.com/posts/1.gif'),
 | 
			
		||||
    ('totally/unknown', 'http://example.com/posts/1.dat'),
 | 
			
		||||
    ('image/jpeg', 'http://example.com/posts/1_244c8840887984c4.jpg'),
 | 
			
		||||
    ('image/gif', 'http://example.com/posts/1_244c8840887984c4.gif'),
 | 
			
		||||
    ('totally/unknown', 'http://example.com/posts/1_244c8840887984c4.dat'),
 | 
			
		||||
])
 | 
			
		||||
def test_get_post_url(input_mime_type, expected_url, config_injector):
 | 
			
		||||
    config_injector({'data_url': 'http://example.com/'})
 | 
			
		||||
    config_injector({'data_url': 'http://example.com/', 'secret': 'test'})
 | 
			
		||||
    post = model.Post()
 | 
			
		||||
    post.post_id = 1
 | 
			
		||||
    post.mime_type = input_mime_type
 | 
			
		||||
@ -22,18 +22,18 @@ def test_get_post_url(input_mime_type, expected_url, config_injector):
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('input_mime_type', ['image/jpeg', 'image/gif'])
 | 
			
		||||
def test_get_post_thumbnail_url(input_mime_type, config_injector):
 | 
			
		||||
    config_injector({'data_url': 'http://example.com/'})
 | 
			
		||||
    config_injector({'data_url': 'http://example.com/', 'secret': 'test'})
 | 
			
		||||
    post = model.Post()
 | 
			
		||||
    post.post_id = 1
 | 
			
		||||
    post.mime_type = input_mime_type
 | 
			
		||||
    assert posts.get_post_thumbnail_url(post) \
 | 
			
		||||
        == 'http://example.com/generated-thumbnails/1.jpg'
 | 
			
		||||
        == 'http://example.com/generated-thumbnails/1_244c8840887984c4.jpg'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('input_mime_type,expected_path', [
 | 
			
		||||
    ('image/jpeg', 'posts/1.jpg'),
 | 
			
		||||
    ('image/gif', 'posts/1.gif'),
 | 
			
		||||
    ('totally/unknown', 'posts/1.dat'),
 | 
			
		||||
    ('image/jpeg', 'posts/1_244c8840887984c4.jpg'),
 | 
			
		||||
    ('image/gif', 'posts/1_244c8840887984c4.gif'),
 | 
			
		||||
    ('totally/unknown', 'posts/1_244c8840887984c4.dat'),
 | 
			
		||||
])
 | 
			
		||||
def test_get_post_content_path(input_mime_type, expected_path):
 | 
			
		||||
    post = model.Post()
 | 
			
		||||
@ -47,7 +47,8 @@ def test_get_post_thumbnail_path(input_mime_type):
 | 
			
		||||
    post = model.Post()
 | 
			
		||||
    post.post_id = 1
 | 
			
		||||
    post.mime_type = input_mime_type
 | 
			
		||||
    assert posts.get_post_thumbnail_path(post) == 'generated-thumbnails/1.jpg'
 | 
			
		||||
    assert posts.get_post_thumbnail_path(post) \
 | 
			
		||||
        == 'generated-thumbnails/1_244c8840887984c4.jpg'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize('input_mime_type', ['image/jpeg', 'image/gif'])
 | 
			
		||||
@ -56,7 +57,7 @@ def test_get_post_thumbnail_backup_path(input_mime_type):
 | 
			
		||||
    post.post_id = 1
 | 
			
		||||
    post.mime_type = input_mime_type
 | 
			
		||||
    assert posts.get_post_thumbnail_backup_path(post) \
 | 
			
		||||
        == 'posts/custom-thumbnails/1.dat'
 | 
			
		||||
        == 'posts/custom-thumbnails/1_244c8840887984c4.dat'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_serialize_note():
 | 
			
		||||
@ -75,7 +76,7 @@ def test_serialize_post_when_empty():
 | 
			
		||||
 | 
			
		||||
def test_serialize_post(
 | 
			
		||||
        user_factory, comment_factory, tag_factory, config_injector):
 | 
			
		||||
    config_injector({'data_url': 'http://example.com/'})
 | 
			
		||||
    config_injector({'data_url': 'http://example.com/', 'secret': 'test'})
 | 
			
		||||
    with patch('szurubooru.func.comments.serialize_comment'), \
 | 
			
		||||
            patch('szurubooru.func.users.serialize_micro_user'), \
 | 
			
		||||
            patch('szurubooru.func.posts.files.has'):
 | 
			
		||||
@ -156,8 +157,10 @@ def test_serialize_post(
 | 
			
		||||
            'fileSize': 100,
 | 
			
		||||
            'canvasWidth': 200,
 | 
			
		||||
            'canvasHeight': 300,
 | 
			
		||||
            'contentUrl': 'http://example.com/posts/1.jpg',
 | 
			
		||||
            'thumbnailUrl': 'http://example.com/generated-thumbnails/1.jpg',
 | 
			
		||||
            'contentUrl': 'http://example.com/posts/1_244c8840887984c4.jpg',
 | 
			
		||||
            'thumbnailUrl':
 | 
			
		||||
                'http://example.com/'
 | 
			
		||||
                'generated-thumbnails/1_244c8840887984c4.jpg',
 | 
			
		||||
            'flags': ['loop'],
 | 
			
		||||
            'tags': ['tag1', 'tag3'],
 | 
			
		||||
            'relations': [],
 | 
			
		||||
@ -264,25 +267,61 @@ def test_update_post_source_with_too_long_string():
 | 
			
		||||
@pytest.mark.parametrize(
 | 
			
		||||
    'is_existing,input_file,expected_mime_type,expected_type,output_file_name',
 | 
			
		||||
    [
 | 
			
		||||
        (True, 'png.png', 'image/png', model.Post.TYPE_IMAGE, '1.png'),
 | 
			
		||||
        (False, 'png.png', 'image/png', model.Post.TYPE_IMAGE, '1.png'),
 | 
			
		||||
        (False, 'jpeg.jpg', 'image/jpeg', model.Post.TYPE_IMAGE, '1.jpg'),
 | 
			
		||||
        (False, 'gif.gif', 'image/gif', model.Post.TYPE_IMAGE, '1.gif'),
 | 
			
		||||
        (
 | 
			
		||||
            True,
 | 
			
		||||
            'png.png',
 | 
			
		||||
            'image/png',
 | 
			
		||||
            model.Post.TYPE_IMAGE,
 | 
			
		||||
            '1_244c8840887984c4.png',
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'png.png',
 | 
			
		||||
            'image/png',
 | 
			
		||||
            model.Post.TYPE_IMAGE,
 | 
			
		||||
            '1_244c8840887984c4.png',
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'jpeg.jpg',
 | 
			
		||||
            'image/jpeg',
 | 
			
		||||
            model.Post.TYPE_IMAGE,
 | 
			
		||||
            '1_244c8840887984c4.jpg',
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'gif.gif',
 | 
			
		||||
            'image/gif',
 | 
			
		||||
            model.Post.TYPE_IMAGE,
 | 
			
		||||
            '1_244c8840887984c4.gif',
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'gif-animated.gif',
 | 
			
		||||
            'image/gif',
 | 
			
		||||
            model.Post.TYPE_ANIMATION,
 | 
			
		||||
            '1.gif',
 | 
			
		||||
            '1_244c8840887984c4.gif',
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'webm.webm',
 | 
			
		||||
            'video/webm',
 | 
			
		||||
            model.Post.TYPE_VIDEO,
 | 
			
		||||
            '1_244c8840887984c4.webm',
 | 
			
		||||
        ),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'mp4.mp4',
 | 
			
		||||
            'video/mp4',
 | 
			
		||||
            model.Post.TYPE_VIDEO,
 | 
			
		||||
            '1_244c8840887984c4.mp4',
 | 
			
		||||
        ),
 | 
			
		||||
        (False, 'webm.webm', 'video/webm', model.Post.TYPE_VIDEO, '1.webm'),
 | 
			
		||||
        (False, 'mp4.mp4', 'video/mp4', model.Post.TYPE_VIDEO, '1.mp4'),
 | 
			
		||||
        (
 | 
			
		||||
            False,
 | 
			
		||||
            'flash.swf',
 | 
			
		||||
            'application/x-shockwave-flash',
 | 
			
		||||
            model.Post.TYPE_FLASH,
 | 
			
		||||
            '1.swf'
 | 
			
		||||
            '1_244c8840887984c4.swf',
 | 
			
		||||
        ),
 | 
			
		||||
    ])
 | 
			
		||||
def test_update_post_content_for_new_post(
 | 
			
		||||
@ -296,6 +335,7 @@ def test_update_post_content_for_new_post(
 | 
			
		||||
                'post_width': 300,
 | 
			
		||||
                'post_height': 300,
 | 
			
		||||
            },
 | 
			
		||||
            'secret': 'test',
 | 
			
		||||
        })
 | 
			
		||||
        output_file_path = '{}/data/posts/{}'.format(tmpdir, output_file_name)
 | 
			
		||||
        post = post_factory(id=1)
 | 
			
		||||
@ -329,6 +369,7 @@ def test_update_post_content_to_existing_content(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    post = post_factory()
 | 
			
		||||
    another_post = post_factory()
 | 
			
		||||
@ -350,6 +391,7 @@ def test_update_post_content_with_broken_content(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    post = post_factory()
 | 
			
		||||
    another_post = post_factory()
 | 
			
		||||
@ -376,14 +418,19 @@ def test_update_post_thumbnail_to_new_one(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    post = post_factory(id=1)
 | 
			
		||||
    db.session.add(post)
 | 
			
		||||
    if is_existing:
 | 
			
		||||
        db.session.flush()
 | 
			
		||||
    assert post.post_id
 | 
			
		||||
    generated_path = '{}/data/generated-thumbnails/1.jpg'.format(tmpdir)
 | 
			
		||||
    source_path = '{}/data/posts/custom-thumbnails/1.dat'.format(tmpdir)
 | 
			
		||||
    generated_path = (
 | 
			
		||||
        '{}/data/generated-thumbnails/1_244c8840887984c4.jpg'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    source_path = (
 | 
			
		||||
        '{}/data/posts/custom-thumbnails/1_244c8840887984c4.dat'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    assert not os.path.exists(generated_path)
 | 
			
		||||
    assert not os.path.exists(source_path)
 | 
			
		||||
    posts.update_post_content(post, read_asset('png.png'))
 | 
			
		||||
@ -406,14 +453,19 @@ def test_update_post_thumbnail_to_default(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    post = post_factory(id=1)
 | 
			
		||||
    db.session.add(post)
 | 
			
		||||
    if is_existing:
 | 
			
		||||
        db.session.flush()
 | 
			
		||||
    assert post.post_id
 | 
			
		||||
    generated_path = '{}/data/generated-thumbnails/1.jpg'.format(tmpdir)
 | 
			
		||||
    source_path = '{}/data/posts/custom-thumbnails/1.dat'.format(tmpdir)
 | 
			
		||||
    generated_path = (
 | 
			
		||||
        '{}/data/generated-thumbnails/1_244c8840887984c4.jpg'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    source_path = (
 | 
			
		||||
        '{}/data/posts/custom-thumbnails/1_244c8840887984c4.dat'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    assert not os.path.exists(generated_path)
 | 
			
		||||
    assert not os.path.exists(source_path)
 | 
			
		||||
    posts.update_post_content(post, read_asset('png.png'))
 | 
			
		||||
@ -435,14 +487,19 @@ def test_update_post_thumbnail_with_broken_thumbnail(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    post = post_factory(id=1)
 | 
			
		||||
    db.session.add(post)
 | 
			
		||||
    if is_existing:
 | 
			
		||||
        db.session.flush()
 | 
			
		||||
    assert post.post_id
 | 
			
		||||
    generated_path = '{}/data/generated-thumbnails/1.jpg'.format(tmpdir)
 | 
			
		||||
    source_path = '{}/data/posts/custom-thumbnails/1.dat'.format(tmpdir)
 | 
			
		||||
    generated_path = (
 | 
			
		||||
        '{}/data/generated-thumbnails/1_244c8840887984c4.jpg'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    source_path = (
 | 
			
		||||
        '{}/data/posts/custom-thumbnails/1_244c8840887984c4.dat'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    assert not os.path.exists(generated_path)
 | 
			
		||||
    assert not os.path.exists(source_path)
 | 
			
		||||
    posts.update_post_content(post, read_asset('png.png'))
 | 
			
		||||
@ -468,6 +525,7 @@ def test_update_post_content_leaving_custom_thumbnail(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    post = post_factory(id=1)
 | 
			
		||||
    db.session.add(post)
 | 
			
		||||
@ -475,8 +533,12 @@ def test_update_post_content_leaving_custom_thumbnail(
 | 
			
		||||
    posts.update_post_thumbnail(post, read_asset('jpeg.jpg'))
 | 
			
		||||
    posts.update_post_content(post, read_asset('png.png'))
 | 
			
		||||
    db.session.flush()
 | 
			
		||||
    generated_path = '{}/data/generated-thumbnails/1.jpg'.format(tmpdir)
 | 
			
		||||
    source_path = '{}/data/posts/custom-thumbnails/1.dat'.format(tmpdir)
 | 
			
		||||
    generated_path = (
 | 
			
		||||
        '{}/data/generated-thumbnails/1_244c8840887984c4.jpg'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    source_path = (
 | 
			
		||||
        '{}/data/posts/custom-thumbnails/1_244c8840887984c4.dat'
 | 
			
		||||
        .format(tmpdir))
 | 
			
		||||
    assert os.path.exists(source_path)
 | 
			
		||||
    assert os.path.exists(generated_path)
 | 
			
		||||
 | 
			
		||||
@ -833,6 +895,7 @@ def test_merge_posts_replaces_content(
 | 
			
		||||
            'post_width': 300,
 | 
			
		||||
            'post_height': 300,
 | 
			
		||||
        },
 | 
			
		||||
        'secret': 'test',
 | 
			
		||||
    })
 | 
			
		||||
    source_post = post_factory(id=1)
 | 
			
		||||
    target_post = post_factory(id=2)
 | 
			
		||||
@ -841,9 +904,12 @@ def test_merge_posts_replaces_content(
 | 
			
		||||
    db.session.commit()
 | 
			
		||||
    posts.update_post_content(source_post, content)
 | 
			
		||||
    db.session.flush()
 | 
			
		||||
    source_path = os.path.join('{}/data/posts/1.png'.format(tmpdir))
 | 
			
		||||
    target_path1 = os.path.join('{}/data/posts/2.png'.format(tmpdir))
 | 
			
		||||
    target_path2 = os.path.join('{}/data/posts/2.dat'.format(tmpdir))
 | 
			
		||||
    source_path = (
 | 
			
		||||
        os.path.join('{}/data/posts/1_244c8840887984c4.png'.format(tmpdir)))
 | 
			
		||||
    target_path1 = (
 | 
			
		||||
        os.path.join('{}/data/posts/2_49caeb3ec1643406.png'.format(tmpdir)))
 | 
			
		||||
    target_path2 = (
 | 
			
		||||
        os.path.join('{}/data/posts/2_49caeb3ec1643406.dat'.format(tmpdir)))
 | 
			
		||||
    assert os.path.exists(source_path)
 | 
			
		||||
    assert not os.path.exists(target_path1)
 | 
			
		||||
    assert not os.path.exists(target_path2)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user