fix duplication of private textures (fix #194)

This commit is contained in:
Pig Fang 2020-07-20 23:08:28 +08:00
parent 8f2e48df52
commit b5a1f2ffc2
No known key found for this signature in database
GPG Key ID: A8198F548DADA9E2
6 changed files with 107 additions and 5 deletions

View File

@ -249,16 +249,21 @@ class SkinlibController extends Controller
$hash = hash_file('sha256', $file);
$hash = $filter->apply('uploaded_texture_hash', $hash, [$file]);
$duplicated = Texture::where('hash', $hash)->where('public', true)->first();
/** @var User */
$user = Auth::user();
$duplicated = Texture::where('hash', $hash)
->where(function ($query) use ($user) {
return $query->where('public', true)
->orWhere('uploader', $user->uid);
})
->first();
if ($duplicated) {
// if the texture already uploaded was set to private,
// then allow to re-upload it.
return json(trans('skinlib.upload.repeated'), 2, ['tid' => $duplicated->tid]);
}
/** @var User */
$user = Auth::user();
$size = ceil($file->getSize() / 1024);
$isPublic = is_string($data['public'])
? $data['public'] === '1'
@ -342,6 +347,15 @@ class SkinlibController extends Controller
return json(trans('skinlib.upload.lack-score'), 1);
}
if (!$texture->public) {
$duplicated = Texture::where('hash', $texture->hash)
->where('public', true)
->first();
if ($duplicated) {
return json(trans('skinlib.upload.repeated'), 2, ['tid' => $duplicated->tid]);
}
}
$dispatcher->dispatch('texture.privacy.updating', [$texture]);
$uploader->score += $score_diff;

View File

@ -191,12 +191,29 @@ const Show: React.FC = () => {
return
}
const { code, message } = await fetch.put<fetch.ResponseBody>(
type Ok = { code: 0; message: string }
type Err = { code: 1; message: string }
type Duplicated = { code: 2; message: string; data: { tid: number } }
const resp = await fetch.put<Ok | Err | Duplicated>(
urls.texture.privacy(texture.tid),
)
const { code, message } = resp
if (code === 0) {
toast.success(message)
setTexture((texture) => ({ ...texture, public: !texture.public }))
} else if (resp.code === 2) {
try {
await showModal({
mode: 'confirm',
text: message,
okButtonText: t('user.viewInSkinlib'),
})
window.location.href =
blessing.base_url + urls.skinlib.show(resp.data.tid)
} catch {
//
}
} else {
toast.error(message)
}

View File

@ -575,6 +575,48 @@ describe('change privacy', () => {
expect(getByRole('alert')).toHaveClass('alert-danger')
expect(queryByText(t('skinlib.setAsPublic'))).toBeInTheDocument()
})
it('duplicated texture with confirmed', async () => {
fetch.get.mockResolvedValue({ ...fixtureSkin, public: false })
fetch.put.mockResolvedValue({
code: 2,
message: 'duplicated',
data: { tid: 2 },
})
const { getByText, queryByText } = render(<Show />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
fireEvent.click(getByText(t('skinlib.setAsPublic')))
fireEvent.click(getByText(t('general.confirm')))
await waitFor(() =>
expect(fetch.put).toBeCalledWith(urls.texture.privacy(fixtureSkin.tid)),
)
expect(queryByText('duplicated')).toBeInTheDocument()
expect(queryByText(t('skinlib.setAsPublic'))).toBeInTheDocument()
fireEvent.click(getByText(t('user.viewInSkinlib')))
})
it('duplicated texture with cancelled', async () => {
fetch.get.mockResolvedValue({ ...fixtureSkin, public: false })
fetch.put.mockResolvedValue({
code: 2,
message: 'duplicated',
data: { tid: 2 },
})
const { getByText, queryByText } = render(<Show />)
await waitFor(() => expect(fetch.get).toBeCalledTimes(1))
fireEvent.click(getByText(t('skinlib.setAsPublic')))
fireEvent.click(getByText(t('general.confirm')))
await waitFor(() =>
expect(fetch.put).toBeCalledWith(urls.texture.privacy(fixtureSkin.tid)),
)
expect(queryByText('duplicated')).toBeInTheDocument()
expect(queryByText(t('skinlib.setAsPublic'))).toBeInTheDocument()
fireEvent.click(getByText(t('general.cancel')))
})
})
describe('delete texture', () => {

View File

@ -5,3 +5,4 @@
## Fixed
- Fixed duplicated route names.
- Fixed duplication of private textures.

View File

@ -5,3 +5,4 @@
## 修复
- 修复重复的路由命名
- 修复私有材质的重复问题

View File

@ -449,6 +449,20 @@ class SkinlibControllerTest extends TestCase
'data' => ['tid' => $texture->tid],
]);
// upload a duplicated private texture
$texture->uploader = $user->uid;
$texture->save();
$this->postJson(route('texture.upload'), [
'name' => 'texture',
'public' => true,
'type' => 'steve',
'file' => $upload,
])->assertJson([
'code' => 2,
'message' => trans('skinlib.upload.repeated'),
'data' => ['tid' => $texture->tid],
]);
// rejected
$filter->add('can_upload_texture', function ($can, $file, $name) {
$this->assertInstanceOf(UploadedFile::class, $file);
@ -589,6 +603,19 @@ class SkinlibControllerTest extends TestCase
}
);
// duplicated
$duplicated = $texture->replicate();
$duplicated->uploader = $other->uid;
$duplicated->public = true;
$duplicated->save();
$texture->public = false;
$texture->save();
$uploader->score = (int) option('private_score_per_storage');
$uploader->save();
$this->putJson(route('texture.privacy', ['texture' => $texture]))
->assertJson(['code' => 2, 'message' => trans('skinlib.upload.repeated')]);
$duplicated->delete();
$this->putJson(route('texture.privacy', ['texture' => $texture]))
->assertJson([
'code' => 0,