mirror of
https://github.com/OCA/knowledge.git
synced 2025-07-26 10:28:40 -06:00
Remove old module ir_exchange_file/task_view.xml
This commit is contained in:
parent
1a8e242bb3
commit
1071c1628b
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,26 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Module for OpenERP
|
|
||||||
# Copyright (C) 2014 Akretion (http://www.akretion.com).
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
import attachment
|
|
||||||
import location
|
|
||||||
import task
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Module for OpenERP
|
|
||||||
# Copyright (C) 2014 Akretion (http://www.akretion.com).
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
{'name': 'ir_exchange_file',
|
|
||||||
'version': '0.0.1',
|
|
||||||
'author': 'Akretion',
|
|
||||||
'website': 'www.akretion.com',
|
|
||||||
'license': 'AGPL-3',
|
|
||||||
'category': 'Generic Modules',
|
|
||||||
'description': """
|
|
||||||
|
|
||||||
""",
|
|
||||||
'depends': [
|
|
||||||
'base',
|
|
||||||
],
|
|
||||||
'data': [
|
|
||||||
'attachment_view.xml',
|
|
||||||
'location_view.xml',
|
|
||||||
'task_view.xml',
|
|
||||||
],
|
|
||||||
'installable': True,
|
|
||||||
'application': True,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Module for OpenERP
|
|
||||||
# Copyright (C) 2014 Akretion (http://www.akretion.com).
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
from openerp import models, fields, api, _
|
|
||||||
from openerp.exceptions import Warning
|
|
||||||
import hashlib
|
|
||||||
|
|
||||||
|
|
||||||
class AttachmentMetadata(models.Model):
|
|
||||||
_inherit = 'ir.attachment'
|
|
||||||
|
|
||||||
sync_date = fields.Datetime()
|
|
||||||
parse_state = fields.Selection([
|
|
||||||
('pending', 'Pending'),
|
|
||||||
('failed', 'Failed'),
|
|
||||||
('done', 'Done'),
|
|
||||||
], readonly=True, required=True, default='pending')
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<openerp>
|
|
||||||
<data>
|
|
||||||
|
|
||||||
<record id="view_attachment_improved_form" model="ir.ui.view">
|
|
||||||
<field name="model">ir.attachment</field>
|
|
||||||
<field name="inherit_id" ref="base.view_attachment_form" />
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<field name="url" position="after">
|
|
||||||
<field name="sync_date"/>
|
|
||||||
<field name="parse_state"/>
|
|
||||||
</field>
|
|
||||||
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
</data>
|
|
||||||
</openerp>
|
|
@ -1,34 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractConnection(object):
|
|
||||||
|
|
||||||
def __init__(self, host, user, pwd, port=None, allow_dir_creation=False):
|
|
||||||
self.host = host
|
|
||||||
self.user = user
|
|
||||||
self.pwd = pwd
|
|
||||||
self.port = port
|
|
||||||
self.allow_dir_creation = allow_dir_creation
|
|
||||||
self.connection = None
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def get(self, filename, path=None):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def put(self, fileobject, filename, path=None):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def search(self, filename, path=None):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def move(self, filename, oldpath, newpath):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def rename(self, oldfilename, newfilename, path=None):
|
|
||||||
return NotImplemented
|
|
Binary file not shown.
@ -1,66 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from ..backend import AbstractConnection
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from tempfile import TemporaryFile
|
|
||||||
|
|
||||||
class AbtractTask()
|
|
||||||
|
|
||||||
def __init__(self, cr, uid):
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FileStoreConnection(AbstractTask):
|
|
||||||
_key = "filestore"
|
|
||||||
_name = "Filestore"
|
|
||||||
_synchronize_type = None
|
|
||||||
|
|
||||||
def __init__(self, host, user, pwd, port=None, allow_dir_creation=False):
|
|
||||||
super(FilestoreConnection, self).__init__(host, user, pwd, port, allow_dir_creation)
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
def get(self, filename, path=None):
|
|
||||||
if path:
|
|
||||||
filepath = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
filepath = filename
|
|
||||||
return open(filepath, 'r+b')
|
|
||||||
|
|
||||||
def put(self, fileobject, filename, path=None):
|
|
||||||
if path:
|
|
||||||
filepath = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
filepath = filename
|
|
||||||
output = open(filepath, 'w+b')
|
|
||||||
return True
|
|
||||||
|
|
||||||
def search(self, filename, path=None):
|
|
||||||
if path:
|
|
||||||
filepath = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
filepath = filename
|
|
||||||
connection_list_result = os.listdir(filepath)
|
|
||||||
return [x for x in connection_list_result if filename in x]
|
|
||||||
|
|
||||||
def move(self, filename, oldpath, newpath):
|
|
||||||
os.rename(
|
|
||||||
os.path.join(oldpath, filename),
|
|
||||||
os.path.join(newpath, filename)
|
|
||||||
)
|
|
||||||
|
|
||||||
def rename(self, oldfilename, newfilename, path=None):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
class ImportFileStore(FileStoreConnection):
|
|
||||||
_synchronize_type = "import"
|
|
||||||
|
|
||||||
|
|
||||||
def run():
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from tempfile import TemporaryFile
|
|
||||||
from ftplib import FTP
|
|
||||||
|
|
||||||
class FTPConnection(object):
|
|
||||||
|
|
||||||
def __init__(self, host, user, pwd, port=None, allow_dir_creation=False):
|
|
||||||
super(FTPConnection, self).__init__(host, user, pwd, port, allow_dir_creation)
|
|
||||||
if not port:
|
|
||||||
self.port = 21
|
|
||||||
self.protocol = "FTP"
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
self.connection = FTP(self.location, self.port)
|
|
||||||
self.connection.login(self.user, self.pwd)
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.connection.close()
|
|
||||||
|
|
||||||
def get(self, filename, path=None):
|
|
||||||
if path:
|
|
||||||
filepath = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
filepath = filename
|
|
||||||
outfile = TemporaryFile('w+b')
|
|
||||||
self.connection.retrbinary('RETR ' + filepath, outfile.write)
|
|
||||||
return outfile
|
|
||||||
|
|
||||||
def put(self, fileobject, filename, path=None):
|
|
||||||
if path:
|
|
||||||
filepath = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
filepath = filename
|
|
||||||
self.connection.storbinary('STOR ' + filepath, fileobject)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def search(self, filename, path=None):
|
|
||||||
if path:
|
|
||||||
filepath = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
filepath = filename
|
|
||||||
connection_list_result = self.connection.nlst()
|
|
||||||
return [x for x in connection_list_result if filename in x]
|
|
||||||
|
|
||||||
|
|
||||||
def move(self, filename, oldpath, newpath):
|
|
||||||
self.connection.rename(
|
|
||||||
os.path.join(oldpath, filename),
|
|
||||||
os.path.join(newpath, filename)
|
|
||||||
)
|
|
||||||
|
|
||||||
def rename(self, oldfilename, newfilename, path=None):
|
|
||||||
return NotImplemented
|
|
@ -1,59 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import paramiko
|
|
||||||
import os
|
|
||||||
from tempfile import TemporaryFile
|
|
||||||
|
|
||||||
|
|
||||||
class SFTPConnection(AbstractConnection):
|
|
||||||
|
|
||||||
def __init__(self, host, user, pwd, port=None, allow_dir_creation=False):
|
|
||||||
super(SFTPConnection, self).__init__(host, user, pwd, port, allow_dir_creation)
|
|
||||||
if not port:
|
|
||||||
self.port = 22
|
|
||||||
self.protocol = "STFP"
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
self.ssh = paramiko.SSHClient()
|
|
||||||
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
||||||
self.ssh.connect(self.host, self.port, self.user, self.pwd, compress=True)
|
|
||||||
self.connection = self.ssh.open_sftp()
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.connection.close()
|
|
||||||
|
|
||||||
def get(self, filename, path=None):
|
|
||||||
if path:
|
|
||||||
remotefile = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
remotefile = filename
|
|
||||||
localfile = filename
|
|
||||||
newfile = open(filename, 'w')
|
|
||||||
self.connection.getfo(remotefile, newfile)
|
|
||||||
return newfile
|
|
||||||
|
|
||||||
def put(self, fileobject, filename, path=None):
|
|
||||||
if path:
|
|
||||||
remotefile = "{}/{}".format(path, filename)
|
|
||||||
else:
|
|
||||||
remotefile = filename
|
|
||||||
if self.allow_dir_creation:
|
|
||||||
self.connection.mkdirs(path)
|
|
||||||
oldfile = open(fileobj, 'r')
|
|
||||||
self.connection.putfo(oldfile, remotefile)
|
|
||||||
|
|
||||||
def search(self, filename, path=None):
|
|
||||||
if path:
|
|
||||||
self.connection.chdir(path)
|
|
||||||
file_list = self.connection.listdir()
|
|
||||||
return [x for x in file_list if filename in x]
|
|
||||||
|
|
||||||
def move(self, filename, oldpath, newpath):
|
|
||||||
self.connection.rename(os.path.join(oldpath, filename), os.path.join(newpath, filename))
|
|
||||||
|
|
||||||
def rename(self, oldfilename, newfilename, path=None):
|
|
||||||
if not path:
|
|
||||||
path = ''
|
|
||||||
self.connection.rename(os.path.join(path, oldfilename), os.path.join(path, newfilename))
|
|
@ -1,39 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Module for OpenERP
|
|
||||||
# Copyright (C) 2014 Akretion (http://www.akretion.com).
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
from openerp import models, fields
|
|
||||||
|
|
||||||
class Location(models.Model):
|
|
||||||
_name = 'ir.location'
|
|
||||||
_description = 'Description'
|
|
||||||
|
|
||||||
name = fields.Char(string='Name')
|
|
||||||
protocol = fields.Selection(selection='_get_protocol')
|
|
||||||
address = fields.Char(string='Address')
|
|
||||||
port = fields.Integer()
|
|
||||||
login = fields.Char()
|
|
||||||
password = fields.Char()
|
|
||||||
|
|
||||||
|
|
||||||
def _get_protocol(self):
|
|
||||||
return [('ftp', 'FTP'), ('sftp', 'SFTP'), ('filestore', 'Filestore')]
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<openerp>
|
|
||||||
<data>
|
|
||||||
|
|
||||||
<record id="view_location_form" model="ir.ui.view">
|
|
||||||
<field name="model">ir.location</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="Location" version="7.0">
|
|
||||||
<sheet>
|
|
||||||
<group col="4">
|
|
||||||
<field name="name" select="1" colspan="4"/>
|
|
||||||
<field name="protocol" colspan="2"/>
|
|
||||||
<newline/>
|
|
||||||
<field name="address" colspan="2"/>
|
|
||||||
<field name="port" colspan="2"/>
|
|
||||||
<field name="login" colspan="4"/>
|
|
||||||
<field name="password" colspan="4"/>
|
|
||||||
</group>
|
|
||||||
</sheet>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="view_location_tree" model="ir.ui.view">
|
|
||||||
<field name="model">ir.location</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree string="Location">
|
|
||||||
<field name="name" select="1"/>
|
|
||||||
<field name="protocol"/>
|
|
||||||
<field name="address"/>
|
|
||||||
<field name="port"/>
|
|
||||||
<field name="login"/>
|
|
||||||
<field name="password"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="action_location" model="ir.actions.act_window">
|
|
||||||
<field name="name">Locations</field>
|
|
||||||
<field name="type">ir.actions.act_window</field>
|
|
||||||
<field name="res_model">ir.location</field>
|
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_id" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<menuitem id="menu_ir_location"
|
|
||||||
parent="base.next_id_9"
|
|
||||||
sequence="20"
|
|
||||||
action="action_location"/>
|
|
||||||
|
|
||||||
</data>
|
|
||||||
</openerp>
|
|
@ -1,48 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Module for OpenERP
|
|
||||||
# Copyright (C) 2014 Akretion (http://www.akretion.com).
|
|
||||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
import sys
|
|
||||||
from openerp import models, fields
|
|
||||||
|
|
||||||
class Task(models.Model):
|
|
||||||
_name = 'ir.location.task'
|
|
||||||
_description = 'Description'
|
|
||||||
|
|
||||||
name = fields.Char()
|
|
||||||
method = fields.Selection([
|
|
||||||
('ftp_import', 'FTP import'),
|
|
||||||
('ftp_export', 'FTP export'),
|
|
||||||
('sftp_import', 'SFTP import'),
|
|
||||||
('sftp_export', 'SFTP export'),
|
|
||||||
('filestore_import', 'Filestore import'),
|
|
||||||
('filestore_export', 'Filestore export'),
|
|
||||||
])
|
|
||||||
filename = fields.Char()
|
|
||||||
filepath = fields.Char()
|
|
||||||
location_id = fields.Many2one('ir.location', string='Location')
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
connection_class = ...
|
|
||||||
|
|
||||||
method_class = getattr(sys.modules[__name__], self.method)
|
|
||||||
conn = method_class(config)
|
|
||||||
conn.run()
|
|
@ -1,47 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<openerp>
|
|
||||||
<data>
|
|
||||||
|
|
||||||
<record id="view_task_form" model="ir.ui.view">
|
|
||||||
<field name="model">ir.location.task</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="Tasks" version="7.0">
|
|
||||||
<sheet>
|
|
||||||
<group col="4">
|
|
||||||
<field name="name" select="1" colspan="4"/>
|
|
||||||
<field name="method" colspan="4"/>
|
|
||||||
<field name="filename" colspan="4"/>
|
|
||||||
<field name="filepath" colspan="4"/>
|
|
||||||
</group>
|
|
||||||
</sheet>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="view_task_tree" model="ir.ui.view">
|
|
||||||
<field name="model">ir.location.task</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<tree string="Tasks" >
|
|
||||||
<field name="name" select="1"/>
|
|
||||||
<field name="method"/>
|
|
||||||
<field name="filename"/>
|
|
||||||
<field name="filepath"/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="action_task" model="ir.actions.act_window">
|
|
||||||
<field name="name">Tasks</field>
|
|
||||||
<field name="type">ir.actions.act_window</field>
|
|
||||||
<field name="res_model">ir.location.task</field>
|
|
||||||
<field name="view_type">form</field>
|
|
||||||
<field name="view_id" eval="False"/>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<menuitem id="menu_ir_location_task"
|
|
||||||
parent="base.next_id_9"
|
|
||||||
sequence="20"
|
|
||||||
action="action_task"/>
|
|
||||||
|
|
||||||
</data>
|
|
||||||
</openerp>
|
|
Loading…
Reference in New Issue
Block a user