added firmware type
This commit is contained in:
parent
7ce1fc77c9
commit
83e31f4263
@ -63,6 +63,7 @@ CREATE TABLE IF NOT EXISTS firmware (
|
||||
id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
|
||||
created_time bigint NOT NULL,
|
||||
tenant_id uuid NOT NULL,
|
||||
type varchar(32) NOT NULL,
|
||||
title varchar(255) NOT NULL,
|
||||
version varchar(255) NOT NULL,
|
||||
file_name varchar(255),
|
||||
|
||||
@ -22,7 +22,6 @@ import org.thingsboard.rule.engine.api.RuleEngineTelemetryService;
|
||||
import org.thingsboard.server.common.data.DataConstants;
|
||||
import org.thingsboard.server.common.data.Device;
|
||||
import org.thingsboard.server.common.data.DeviceProfile;
|
||||
import org.thingsboard.server.common.data.Firmware;
|
||||
import org.thingsboard.server.common.data.FirmwareInfo;
|
||||
import org.thingsboard.server.common.data.id.DeviceId;
|
||||
import org.thingsboard.server.common.data.id.FirmwareId;
|
||||
@ -35,7 +34,6 @@ import org.thingsboard.server.common.data.kv.StringDataEntry;
|
||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
|
||||
import org.thingsboard.server.common.data.page.PageData;
|
||||
import org.thingsboard.server.common.data.page.PageLink;
|
||||
import org.thingsboard.server.common.msg.queue.TbCallback;
|
||||
import org.thingsboard.server.common.msg.queue.TopicPartitionInfo;
|
||||
import org.thingsboard.server.dao.device.DeviceProfileService;
|
||||
import org.thingsboard.server.dao.device.DeviceService;
|
||||
@ -59,6 +57,11 @@ import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_CHECKSUM
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_SIZE;
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_TITLE;
|
||||
import static org.thingsboard.server.common.data.DataConstants.FIRMWARE_VERSION;
|
||||
import static org.thingsboard.server.common.data.DataConstants.SOFTWARE_CHECKSUM;
|
||||
import static org.thingsboard.server.common.data.DataConstants.SOFTWARE_CHECKSUM_ALGORITHM;
|
||||
import static org.thingsboard.server.common.data.DataConstants.SOFTWARE_SIZE;
|
||||
import static org.thingsboard.server.common.data.DataConstants.SOFTWARE_TITLE;
|
||||
import static org.thingsboard.server.common.data.DataConstants.SOFTWARE_VERSION;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@ -185,9 +188,18 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
|
||||
fwStateMsgProducer.send(tpi, new TbProtoQueueMsg<>(UUID.randomUUID(), msg), null);
|
||||
|
||||
List<TsKvEntry> telemetry = new ArrayList<>();
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_TITLE, firmware.getTitle())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_VERSION, firmware.getVersion())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_STATE, FirmwareUpdateStatus.QUEUED.name())));
|
||||
switch (firmware.getType()) {
|
||||
case FIRMWARE:
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_TITLE, firmware.getTitle())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_FIRMWARE_VERSION, firmware.getVersion())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_STATE, FirmwareUpdateStatus.QUEUED.name())));
|
||||
break;
|
||||
case SOFTWARE:
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_SOFTWARE_TITLE, firmware.getTitle())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.TARGET_SOFTWARE_VERSION, firmware.getVersion())));
|
||||
telemetry.add(new BasicTsKvEntry(ts, new StringDataEntry(DataConstants.SOFTWARE_STATE, FirmwareUpdateStatus.QUEUED.name())));
|
||||
break;
|
||||
}
|
||||
|
||||
telemetryService.saveAndNotify(tenantId, deviceId, telemetry, new FutureCallback<>() {
|
||||
@Override
|
||||
@ -223,12 +235,23 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
|
||||
|
||||
List<AttributeKvEntry> attributes = new ArrayList<>();
|
||||
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_TITLE, firmware.getTitle())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_VERSION, firmware.getVersion())));
|
||||
switch (firmware.getType()) {
|
||||
case SOFTWARE:
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_TITLE, firmware.getTitle())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_VERSION, firmware.getVersion())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(DataConstants.FIRMWARE_SIZE, firmware.getDataSize())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM, firmware.getChecksum())));
|
||||
break;
|
||||
case FIRMWARE:
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(SOFTWARE_TITLE, firmware.getTitle())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(SOFTWARE_VERSION, firmware.getVersion())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(SOFTWARE_SIZE, firmware.getDataSize())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(SOFTWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(SOFTWARE_CHECKSUM, firmware.getChecksum())));
|
||||
break;
|
||||
}
|
||||
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new LongDataEntry(FIRMWARE_SIZE, firmware.getDataSize())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM_ALGORITHM, firmware.getChecksumAlgorithm())));
|
||||
attributes.add(new BaseAttributeKvEntry(ts, new StringDataEntry(DataConstants.FIRMWARE_CHECKSUM, firmware.getChecksum())));
|
||||
telemetryService.saveAndNotify(tenantId, deviceId, DataConstants.SHARED_SCOPE, attributes, new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Void tmp) {
|
||||
@ -244,7 +267,8 @@ public class DefaultFirmwareStateService implements FirmwareStateService {
|
||||
|
||||
private void remove(Device device) {
|
||||
telemetryService.deleteAndNotify(device.getTenantId(), device.getId(), DataConstants.SHARED_SCOPE,
|
||||
Arrays.asList(FIRMWARE_TITLE, FIRMWARE_VERSION, FIRMWARE_SIZE, FIRMWARE_CHECKSUM_ALGORITHM, FIRMWARE_CHECKSUM),
|
||||
Arrays.asList(FIRMWARE_TITLE, FIRMWARE_VERSION, FIRMWARE_SIZE, FIRMWARE_CHECKSUM_ALGORITHM, FIRMWARE_CHECKSUM,
|
||||
SOFTWARE_TITLE, SOFTWARE_VERSION, SOFTWARE_SIZE, SOFTWARE_CHECKSUM_ALGORITHM, SOFTWARE_CHECKSUM),
|
||||
new FutureCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(@Nullable Void tmp) {
|
||||
|
||||
@ -93,21 +93,37 @@ public class DataConstants {
|
||||
public static final String USERNAME = "username";
|
||||
public static final String PASSWORD = "password";
|
||||
|
||||
public static final String EDGE_MSG_SOURCE = "edge";
|
||||
public static final String MSG_SOURCE_KEY = "source";
|
||||
|
||||
//firmware
|
||||
//telemetry
|
||||
public static final String CURRENT_FIRMWARE_TITLE = "cur_fw_title";
|
||||
public static final String CURRENT_FIRMWARE_VERSION = "cur_fw_version";
|
||||
public static final String CURRENT_FIRMWARE_TITLE = "current_fw_title";
|
||||
public static final String CURRENT_FIRMWARE_VERSION = "current_fw_version";
|
||||
public static final String TARGET_FIRMWARE_TITLE = "target_fw_title";
|
||||
public static final String TARGET_FIRMWARE_VERSION = "target_fw_version";
|
||||
public static final String FIRMWARE_STATE = "fw_state";
|
||||
|
||||
//attributes
|
||||
//telemetry
|
||||
public static final String FIRMWARE_TITLE = "fw_title";
|
||||
public static final String FIRMWARE_VERSION = "fw_version";
|
||||
public static final String FIRMWARE_SIZE = "fw_size";
|
||||
public static final String FIRMWARE_CHECKSUM = "fw_checksum";
|
||||
public static final String FIRMWARE_CHECKSUM_ALGORITHM = "fw_checksum_algorithm";
|
||||
public static final String EDGE_MSG_SOURCE = "edge";
|
||||
public static final String MSG_SOURCE_KEY = "source";
|
||||
|
||||
//software
|
||||
//telemetry
|
||||
public static final String CURRENT_SOFTWARE_TITLE = "current_sw_title";
|
||||
public static final String CURRENT_SOFTWARE_VERSION = "current_sw_version";
|
||||
public static final String TARGET_SOFTWARE_TITLE = "target_sw_title";
|
||||
public static final String TARGET_SOFTWARE_VERSION = "target_sw_version";
|
||||
public static final String SOFTWARE_STATE = "sw_state";
|
||||
|
||||
//attributes
|
||||
public static final String SOFTWARE_TITLE = "sw_title";
|
||||
public static final String SOFTWARE_VERSION = "sw_version";
|
||||
public static final String SOFTWARE_SIZE = "sw_size";
|
||||
public static final String SOFTWARE_CHECKSUM = "sw_checksum";
|
||||
public static final String SOFTWARE_CHECKSUM_ALGORITHM = "sw_checksum_algorithm";
|
||||
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId>
|
||||
private static final long serialVersionUID = 3168391583570815419L;
|
||||
|
||||
private TenantId tenantId;
|
||||
private FirmwareType type;
|
||||
private String title;
|
||||
private String version;
|
||||
private boolean hasData;
|
||||
@ -50,6 +51,7 @@ public class FirmwareInfo extends SearchTextBasedWithAdditionalInfo<FirmwareId>
|
||||
public FirmwareInfo(FirmwareInfo firmwareInfo) {
|
||||
super(firmwareInfo);
|
||||
this.tenantId = firmwareInfo.getTenantId();
|
||||
this.type = firmwareInfo.getType();
|
||||
this.title = firmwareInfo.getTitle();
|
||||
this.version = firmwareInfo.getVersion();
|
||||
this.hasData = firmwareInfo.isHasData();
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
package org.thingsboard.server.common.data;
|
||||
|
||||
public enum FirmwareType {
|
||||
FIRMWARE, SOFTWARE
|
||||
}
|
||||
@ -363,10 +363,11 @@ message GetFirmwareResponseMsg {
|
||||
ResponseStatus responseStatus = 1;
|
||||
int64 firmwareIdMSB = 2;
|
||||
int64 firmwareIdLSB = 3;
|
||||
string title = 4;
|
||||
string version = 5;
|
||||
string contentType = 6;
|
||||
string fileName = 7;
|
||||
string type = 4;
|
||||
string title = 5;
|
||||
string version = 6;
|
||||
string contentType = 7;
|
||||
string fileName = 8;
|
||||
}
|
||||
|
||||
//Used to report session state to tb-Service and persist this state in the cache on the tb-Service level.
|
||||
|
||||
@ -476,6 +476,7 @@ public class ModelConstants {
|
||||
*/
|
||||
public static final String FIRMWARE_TABLE_NAME = "firmware";
|
||||
public static final String FIRMWARE_TENANT_ID_COLUMN = TENANT_ID_COLUMN;
|
||||
public static final String FIRMWARE_TYPE_COLUMN = "type";
|
||||
public static final String FIRMWARE_TITLE_COLUMN = TITLE_PROPERTY;
|
||||
public static final String FIRMWARE_VERSION_COLUMN = "version";
|
||||
public static final String FIRMWARE_FILE_NAME_COLUMN = "file_name";
|
||||
|
||||
@ -21,6 +21,7 @@ import lombok.EqualsAndHashCode;
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
import org.thingsboard.server.common.data.Firmware;
|
||||
import org.thingsboard.server.common.data.FirmwareType;
|
||||
import org.thingsboard.server.common.data.id.FirmwareId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.model.BaseSqlEntity;
|
||||
@ -30,6 +31,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Table;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
@ -43,6 +46,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_FILE_NAME
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TYPE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
|
||||
|
||||
@ -56,6 +60,10 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
|
||||
@Column(name = FIRMWARE_TENANT_ID_COLUMN)
|
||||
private UUID tenantId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = FIRMWARE_TYPE_COLUMN)
|
||||
private FirmwareType type;
|
||||
|
||||
@Column(name = FIRMWARE_TITLE_COLUMN)
|
||||
private String title;
|
||||
|
||||
@ -95,6 +103,7 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
|
||||
this.createdTime = firmware.getCreatedTime();
|
||||
this.setUuid(firmware.getUuidId());
|
||||
this.tenantId = firmware.getTenantId().getId();
|
||||
this.type = firmware.getType();
|
||||
this.title = firmware.getTitle();
|
||||
this.version = firmware.getVersion();
|
||||
this.fileName = firmware.getFileName();
|
||||
@ -121,6 +130,7 @@ public class FirmwareEntity extends BaseSqlEntity<Firmware> implements SearchTex
|
||||
Firmware firmware = new Firmware(new FirmwareId(id));
|
||||
firmware.setCreatedTime(createdTime);
|
||||
firmware.setTenantId(new TenantId(tenantId));
|
||||
firmware.setType(type);
|
||||
firmware.setTitle(title);
|
||||
firmware.setVersion(version);
|
||||
firmware.setFileName(fileName);
|
||||
|
||||
@ -22,6 +22,7 @@ import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
import org.thingsboard.common.util.JacksonUtil;
|
||||
import org.thingsboard.server.common.data.FirmwareInfo;
|
||||
import org.thingsboard.server.common.data.FirmwareType;
|
||||
import org.thingsboard.server.common.data.id.FirmwareId;
|
||||
import org.thingsboard.server.common.data.id.TenantId;
|
||||
import org.thingsboard.server.dao.model.BaseSqlEntity;
|
||||
@ -31,6 +32,8 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.UUID;
|
||||
@ -45,6 +48,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_HAS_DATA_
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TABLE_NAME;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TENANT_ID_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TITLE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_TYPE_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.FIRMWARE_VERSION_COLUMN;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
|
||||
|
||||
@ -58,6 +62,10 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
|
||||
@Column(name = FIRMWARE_TENANT_ID_COLUMN)
|
||||
private UUID tenantId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = FIRMWARE_TYPE_COLUMN)
|
||||
private FirmwareType type;
|
||||
|
||||
@Column(name = FIRMWARE_TITLE_COLUMN)
|
||||
private String title;
|
||||
|
||||
@ -107,12 +115,13 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
|
||||
this.additionalInfo = firmware.getAdditionalInfo();
|
||||
}
|
||||
|
||||
public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, String title, String version,
|
||||
public FirmwareInfoEntity(UUID id, long createdTime, UUID tenantId, String type, String title, String version,
|
||||
String fileName, String contentType, String checksumAlgorithm, String checksum, Long dataSize,
|
||||
Object additionalInfo, boolean hasData) {
|
||||
this.id = id;
|
||||
this.createdTime = createdTime;
|
||||
this.tenantId = tenantId;
|
||||
this.type = FirmwareType.valueOf(type);
|
||||
this.title = title;
|
||||
this.version = version;
|
||||
this.fileName = fileName;
|
||||
@ -139,6 +148,7 @@ public class FirmwareInfoEntity extends BaseSqlEntity<FirmwareInfo> implements S
|
||||
FirmwareInfo firmware = new FirmwareInfo(new FirmwareId(id));
|
||||
firmware.setCreatedTime(createdTime);
|
||||
firmware.setTenantId(new TenantId(tenantId));
|
||||
firmware.setType(type);
|
||||
firmware.setTitle(title);
|
||||
firmware.setVersion(version);
|
||||
firmware.setFileName(fileName);
|
||||
|
||||
@ -25,14 +25,14 @@ import org.thingsboard.server.dao.model.sql.FirmwareInfoEntity;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface FirmwareInfoRepository extends CrudRepository<FirmwareInfoEntity, UUID> {
|
||||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " +
|
||||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " +
|
||||
"f.tenantId = :tenantId " +
|
||||
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
|
||||
Page<FirmwareInfoEntity> findAllByTenantId(@Param("tenantId") UUID tenantId,
|
||||
@Param("searchText") String searchText,
|
||||
Pageable pageable);
|
||||
|
||||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " +
|
||||
@Query("SELECT new FirmwareInfoEntity(f.id, f.createdTime, f.tenantId, f.type, f.title, f.version, f.fileName, f.contentType, f.checksumAlgorithm, f.checksum, f.dataSize, f.additionalInfo, f.data IS NOT NULL) FROM FirmwareEntity f WHERE " +
|
||||
"f.tenantId = :tenantId " +
|
||||
"AND ((f.data IS NOT NULL AND :hasData = true) OR (f.data IS NULL AND :hasData = false ))" +
|
||||
"AND LOWER(f.searchText) LIKE LOWER(CONCAT(:searchText, '%'))")
|
||||
|
||||
@ -162,6 +162,7 @@ CREATE TABLE IF NOT EXISTS firmware (
|
||||
id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
|
||||
created_time bigint NOT NULL,
|
||||
tenant_id uuid NOT NULL,
|
||||
type varchar(32) NOT NULL,
|
||||
title varchar(255) NOT NULL,
|
||||
version varchar(255) NOT NULL,
|
||||
file_name varchar(255),
|
||||
|
||||
@ -180,6 +180,7 @@ CREATE TABLE IF NOT EXISTS firmware (
|
||||
id uuid NOT NULL CONSTRAINT firmware_pkey PRIMARY KEY,
|
||||
created_time bigint NOT NULL,
|
||||
tenant_id uuid NOT NULL,
|
||||
type varchar(32) NOT NULL,
|
||||
title varchar(255) NOT NULL,
|
||||
version varchar(255) NOT NULL,
|
||||
file_name varchar(255),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user