forked from Qortal/qortal
Add/remove account group admins (by owner)
This commit is contained in:
parent
02a620d57b
commit
df730d9fb9
@ -30,9 +30,11 @@ import org.qora.crypto.Crypto;
|
|||||||
import org.qora.data.group.GroupAdminData;
|
import org.qora.data.group.GroupAdminData;
|
||||||
import org.qora.data.group.GroupData;
|
import org.qora.data.group.GroupData;
|
||||||
import org.qora.data.group.GroupMemberData;
|
import org.qora.data.group.GroupMemberData;
|
||||||
|
import org.qora.data.transaction.AddGroupAdminTransactionData;
|
||||||
import org.qora.data.transaction.CreateGroupTransactionData;
|
import org.qora.data.transaction.CreateGroupTransactionData;
|
||||||
import org.qora.data.transaction.JoinGroupTransactionData;
|
import org.qora.data.transaction.JoinGroupTransactionData;
|
||||||
import org.qora.data.transaction.LeaveGroupTransactionData;
|
import org.qora.data.transaction.LeaveGroupTransactionData;
|
||||||
|
import org.qora.data.transaction.RemoveGroupAdminTransactionData;
|
||||||
import org.qora.data.transaction.UpdateGroupTransactionData;
|
import org.qora.data.transaction.UpdateGroupTransactionData;
|
||||||
import org.qora.repository.DataException;
|
import org.qora.repository.DataException;
|
||||||
import org.qora.repository.Repository;
|
import org.qora.repository.Repository;
|
||||||
@ -40,9 +42,11 @@ import org.qora.repository.RepositoryManager;
|
|||||||
import org.qora.transaction.Transaction;
|
import org.qora.transaction.Transaction;
|
||||||
import org.qora.transaction.Transaction.ValidationResult;
|
import org.qora.transaction.Transaction.ValidationResult;
|
||||||
import org.qora.transform.TransformationException;
|
import org.qora.transform.TransformationException;
|
||||||
|
import org.qora.transform.transaction.AddGroupAdminTransactionTransformer;
|
||||||
import org.qora.transform.transaction.CreateGroupTransactionTransformer;
|
import org.qora.transform.transaction.CreateGroupTransactionTransformer;
|
||||||
import org.qora.transform.transaction.JoinGroupTransactionTransformer;
|
import org.qora.transform.transaction.JoinGroupTransactionTransformer;
|
||||||
import org.qora.transform.transaction.LeaveGroupTransactionTransformer;
|
import org.qora.transform.transaction.LeaveGroupTransactionTransformer;
|
||||||
|
import org.qora.transform.transaction.RemoveGroupAdminTransactionTransformer;
|
||||||
import org.qora.transform.transaction.UpdateGroupTransactionTransformer;
|
import org.qora.transform.transaction.UpdateGroupTransactionTransformer;
|
||||||
import org.qora.utils.Base58;
|
import org.qora.utils.Base58;
|
||||||
|
|
||||||
@ -246,6 +250,92 @@ public class GroupsResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/addadmin")
|
||||||
|
@Operation(
|
||||||
|
summary = "Build raw, unsigned, ADD_GROUP_ADMIN transaction",
|
||||||
|
requestBody = @RequestBody(
|
||||||
|
required = true,
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = AddGroupAdminTransactionData.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
description = "raw, unsigned, ADD_GROUP_ADMIN transaction encoded in Base58",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.TEXT_PLAIN,
|
||||||
|
schema = @Schema(
|
||||||
|
type = "string"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
|
||||||
|
public String addGroupAdmin(AddGroupAdminTransactionData transactionData) {
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||||
|
|
||||||
|
ValidationResult result = transaction.isValidUnconfirmed();
|
||||||
|
if (result != ValidationResult.OK)
|
||||||
|
throw TransactionsResource.createTransactionInvalidException(request, result);
|
||||||
|
|
||||||
|
byte[] bytes = AddGroupAdminTransactionTransformer.toBytes(transactionData);
|
||||||
|
return Base58.encode(bytes);
|
||||||
|
} catch (TransformationException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
|
||||||
|
} catch (DataException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/removeadmin")
|
||||||
|
@Operation(
|
||||||
|
summary = "Build raw, unsigned, REMOVE_GROUP_ADMIN transaction",
|
||||||
|
requestBody = @RequestBody(
|
||||||
|
required = true,
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.APPLICATION_JSON,
|
||||||
|
schema = @Schema(
|
||||||
|
implementation = RemoveGroupAdminTransactionData.class
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
description = "raw, unsigned, REMOVE_GROUP_ADMIN transaction encoded in Base58",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = MediaType.TEXT_PLAIN,
|
||||||
|
schema = @Schema(
|
||||||
|
type = "string"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
|
||||||
|
public String removeGroupAdmin(RemoveGroupAdminTransactionData transactionData) {
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||||
|
|
||||||
|
ValidationResult result = transaction.isValidUnconfirmed();
|
||||||
|
if (result != ValidationResult.OK)
|
||||||
|
throw TransactionsResource.createTransactionInvalidException(request, result);
|
||||||
|
|
||||||
|
byte[] bytes = RemoveGroupAdminTransactionTransformer.toBytes(transactionData);
|
||||||
|
return Base58.encode(bytes);
|
||||||
|
} catch (TransformationException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
|
||||||
|
} catch (DataException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("/join")
|
@Path("/join")
|
||||||
@Operation(
|
@Operation(
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package org.qora.data.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
|
||||||
|
import org.qora.transaction.Transaction.TransactionType;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
// All properties to be converted to JSON via JAX-RS
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@Schema(allOf = { TransactionData.class })
|
||||||
|
public class AddGroupAdminTransactionData extends TransactionData {
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
@Schema(description = "group owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
|
||||||
|
private byte[] ownerPublicKey;
|
||||||
|
@Schema(description = "group name", example = "my-group")
|
||||||
|
private String groupName;
|
||||||
|
@Schema(description = "member to promote to admin", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
|
||||||
|
private String member;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
// For JAX-RS
|
||||||
|
protected AddGroupAdminTransactionData() {
|
||||||
|
super(TransactionType.ADD_GROUP_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterUnmarshal(Unmarshaller u, Object parent) {
|
||||||
|
this.creatorPublicKey = this.ownerPublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
|
||||||
|
super(TransactionType.ADD_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature);
|
||||||
|
|
||||||
|
this.ownerPublicKey = ownerPublicKey;
|
||||||
|
this.groupName = groupName;
|
||||||
|
this.member = member;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AddGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String member, BigDecimal fee, long timestamp, byte[] reference) {
|
||||||
|
this(ownerPublicKey, groupName, member, fee, timestamp, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters / setters
|
||||||
|
|
||||||
|
public byte[] getOwnerPublicKey() {
|
||||||
|
return this.ownerPublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupName() {
|
||||||
|
return this.groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMember() {
|
||||||
|
return this.member;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package org.qora.data.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlTransient;
|
||||||
|
|
||||||
|
import org.qora.transaction.Transaction.TransactionType;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
// All properties to be converted to JSON via JAX-RS
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
@Schema(allOf = { TransactionData.class })
|
||||||
|
public class RemoveGroupAdminTransactionData extends TransactionData {
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
@Schema(description = "group owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
|
||||||
|
private byte[] ownerPublicKey;
|
||||||
|
@Schema(description = "group name", example = "my-group")
|
||||||
|
private String groupName;
|
||||||
|
@Schema(description = "admin to demote", example = "QixPbJUwsaHsVEofJdozU9zgVqkK6aYhrK")
|
||||||
|
private String admin;
|
||||||
|
// For internal use when orphaning
|
||||||
|
@XmlTransient
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private byte[] groupReference;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
// For JAX-RS
|
||||||
|
protected RemoveGroupAdminTransactionData() {
|
||||||
|
super(TransactionType.REMOVE_GROUP_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterUnmarshal(Unmarshaller u, Object parent) {
|
||||||
|
this.creatorPublicKey = this.ownerPublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
|
||||||
|
super(TransactionType.REMOVE_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature);
|
||||||
|
|
||||||
|
this.ownerPublicKey = ownerPublicKey;
|
||||||
|
this.groupName = groupName;
|
||||||
|
this.admin = admin;
|
||||||
|
this.groupReference = groupReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, byte[] groupReference, BigDecimal fee, long timestamp, byte[] reference) {
|
||||||
|
this(ownerPublicKey, groupName, admin, groupReference, fee, timestamp, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
|
||||||
|
this(ownerPublicKey, groupName, admin, null, fee, timestamp, reference, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, String groupName, String admin, BigDecimal fee, long timestamp, byte[] reference) {
|
||||||
|
this(ownerPublicKey, groupName, admin, null, fee, timestamp, reference, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters / setters
|
||||||
|
|
||||||
|
public byte[] getOwnerPublicKey() {
|
||||||
|
return this.ownerPublicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupName() {
|
||||||
|
return this.groupName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAdmin() {
|
||||||
|
return this.admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getGroupReference() {
|
||||||
|
return this.groupReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupReference(byte[] groupReference) {
|
||||||
|
this.groupReference = groupReference;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -34,6 +34,7 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
|
|||||||
CreateOrderTransactionData.class, CancelOrderTransactionData.class,
|
CreateOrderTransactionData.class, CancelOrderTransactionData.class,
|
||||||
MultiPaymentTransactionData.class, DeployATTransactionData.class, MessageTransactionData.class, ATTransactionData.class,
|
MultiPaymentTransactionData.class, DeployATTransactionData.class, MessageTransactionData.class, ATTransactionData.class,
|
||||||
CreateGroupTransactionData.class, UpdateGroupTransactionData.class,
|
CreateGroupTransactionData.class, UpdateGroupTransactionData.class,
|
||||||
|
AddGroupAdminTransactionData.class, RemoveGroupAdminTransactionData.class,
|
||||||
JoinGroupTransactionData.class, LeaveGroupTransactionData.class
|
JoinGroupTransactionData.class, LeaveGroupTransactionData.class
|
||||||
})
|
})
|
||||||
//All properties to be converted to JSON via JAX-RS
|
//All properties to be converted to JSON via JAX-RS
|
||||||
|
@ -7,9 +7,11 @@ import org.qora.account.PublicKeyAccount;
|
|||||||
import org.qora.data.group.GroupAdminData;
|
import org.qora.data.group.GroupAdminData;
|
||||||
import org.qora.data.group.GroupData;
|
import org.qora.data.group.GroupData;
|
||||||
import org.qora.data.group.GroupMemberData;
|
import org.qora.data.group.GroupMemberData;
|
||||||
|
import org.qora.data.transaction.AddGroupAdminTransactionData;
|
||||||
import org.qora.data.transaction.CreateGroupTransactionData;
|
import org.qora.data.transaction.CreateGroupTransactionData;
|
||||||
import org.qora.data.transaction.JoinGroupTransactionData;
|
import org.qora.data.transaction.JoinGroupTransactionData;
|
||||||
import org.qora.data.transaction.LeaveGroupTransactionData;
|
import org.qora.data.transaction.LeaveGroupTransactionData;
|
||||||
|
import org.qora.data.transaction.RemoveGroupAdminTransactionData;
|
||||||
import org.qora.data.transaction.TransactionData;
|
import org.qora.data.transaction.TransactionData;
|
||||||
import org.qora.data.transaction.UpdateGroupTransactionData;
|
import org.qora.data.transaction.UpdateGroupTransactionData;
|
||||||
import org.qora.repository.DataException;
|
import org.qora.repository.DataException;
|
||||||
@ -165,6 +167,38 @@ public class Group {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void promoteToAdmin(AddGroupAdminTransactionData addGroupAdminTransactionData) throws DataException {
|
||||||
|
GroupAdminData groupAdminData = new GroupAdminData(addGroupAdminTransactionData.getGroupName(), addGroupAdminTransactionData.getMember(), addGroupAdminTransactionData.getSignature());
|
||||||
|
this.repository.getGroupRepository().save(groupAdminData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unpromoteToAdmin(AddGroupAdminTransactionData addGroupAdminTransactionData) throws DataException {
|
||||||
|
this.repository.getGroupRepository().deleteAdmin(addGroupAdminTransactionData.getGroupName(), addGroupAdminTransactionData.getMember());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void demoteFromAdmin(RemoveGroupAdminTransactionData removeGroupAdminTransactionData) throws DataException {
|
||||||
|
GroupRepository groupRepository = this.repository.getGroupRepository();
|
||||||
|
String groupName = removeGroupAdminTransactionData.getGroupName();
|
||||||
|
String admin = removeGroupAdminTransactionData.getAdmin();
|
||||||
|
|
||||||
|
// Save admin's promotion transaction reference for orphaning purposes
|
||||||
|
GroupAdminData groupAdminData = groupRepository.getAdmin(groupName, admin);
|
||||||
|
removeGroupAdminTransactionData.setGroupReference(groupAdminData.getGroupReference());
|
||||||
|
|
||||||
|
// Demote
|
||||||
|
groupRepository.deleteAdmin(groupName, admin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void undemoteFromAdmin(RemoveGroupAdminTransactionData removeGroupAdminTransactionData) throws DataException {
|
||||||
|
GroupRepository groupRepository = this.repository.getGroupRepository();
|
||||||
|
String groupName = removeGroupAdminTransactionData.getGroupName();
|
||||||
|
String admin = removeGroupAdminTransactionData.getAdmin();
|
||||||
|
|
||||||
|
// Rebuild admin entry using stored promotion transaction reference
|
||||||
|
GroupAdminData groupAdminData = new GroupAdminData(groupName, admin, removeGroupAdminTransactionData.getGroupReference());
|
||||||
|
groupRepository.save(groupAdminData);
|
||||||
|
}
|
||||||
|
|
||||||
public void join(JoinGroupTransactionData joinGroupTransactionData) throws DataException {
|
public void join(JoinGroupTransactionData joinGroupTransactionData) throws DataException {
|
||||||
Account joiner = new PublicKeyAccount(this.repository, joinGroupTransactionData.getJoinerPublicKey());
|
Account joiner = new PublicKeyAccount(this.repository, joinGroupTransactionData.getJoinerPublicKey());
|
||||||
|
|
||||||
|
@ -452,6 +452,12 @@ public class HSQLDBDatabaseUpdates {
|
|||||||
+ "new_owner QoraAddress NOT NULL, new_description GenericDescription NOT NULL, new_is_open BOOLEAN NOT NULL, group_reference Signature, "
|
+ "new_owner QoraAddress NOT NULL, new_description GenericDescription NOT NULL, new_is_open BOOLEAN NOT NULL, group_reference Signature, "
|
||||||
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
|
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
|
||||||
|
|
||||||
|
// Account group add/remove admin transactions
|
||||||
|
stmt.execute("CREATE TABLE AddGroupAdminTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, address QoraAddress NOT NULL, "
|
||||||
|
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
|
||||||
|
stmt.execute("CREATE TABLE RemoveGroupAdminTransactions (signature Signature, owner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, admin QoraAddress NOT NULL, "
|
||||||
|
+ "group_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
|
||||||
|
|
||||||
// Account group join/leave transactions
|
// Account group join/leave transactions
|
||||||
stmt.execute("CREATE TABLE JoinGroupTransactions (signature Signature, joiner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, "
|
stmt.execute("CREATE TABLE JoinGroupTransactions (signature Signature, joiner QoraPublicKey NOT NULL, group_name GroupName NOT NULL, "
|
||||||
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
|
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.qora.repository.hsqldb.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.qora.data.transaction.AddGroupAdminTransactionData;
|
||||||
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
import org.qora.repository.DataException;
|
||||||
|
import org.qora.repository.hsqldb.HSQLDBRepository;
|
||||||
|
import org.qora.repository.hsqldb.HSQLDBSaver;
|
||||||
|
|
||||||
|
public class HSQLDBAddGroupAdminTransactionRepository extends HSQLDBTransactionRepository {
|
||||||
|
|
||||||
|
public HSQLDBAddGroupAdminTransactionRepository(HSQLDBRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
|
||||||
|
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_name, address FROM AddGroupAdminTransactions WHERE signature = ?", signature)) {
|
||||||
|
if (resultSet == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String groupName = resultSet.getString(1);
|
||||||
|
String member = resultSet.getString(2);
|
||||||
|
|
||||||
|
return new AddGroupAdminTransactionData(creatorPublicKey, groupName, member, fee, timestamp, reference, signature);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to fetch add group admin transaction from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(TransactionData transactionData) throws DataException {
|
||||||
|
AddGroupAdminTransactionData addGroupAdminTransactionData = (AddGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
HSQLDBSaver saveHelper = new HSQLDBSaver("AddGroupAdminTransactions");
|
||||||
|
|
||||||
|
saveHelper.bind("signature", addGroupAdminTransactionData.getSignature()).bind("owner", addGroupAdminTransactionData.getOwnerPublicKey())
|
||||||
|
.bind("group_name", addGroupAdminTransactionData.getGroupName()).bind("address", addGroupAdminTransactionData.getMember());
|
||||||
|
|
||||||
|
try {
|
||||||
|
saveHelper.execute(this.repository);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to save add group admin transaction into repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.qora.repository.hsqldb.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.qora.data.transaction.RemoveGroupAdminTransactionData;
|
||||||
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
import org.qora.repository.DataException;
|
||||||
|
import org.qora.repository.hsqldb.HSQLDBRepository;
|
||||||
|
import org.qora.repository.hsqldb.HSQLDBSaver;
|
||||||
|
|
||||||
|
public class HSQLDBRemoveGroupAdminTransactionRepository extends HSQLDBTransactionRepository {
|
||||||
|
|
||||||
|
public HSQLDBRemoveGroupAdminTransactionRepository(HSQLDBRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
|
||||||
|
try (ResultSet resultSet = this.repository
|
||||||
|
.checkedExecute("SELECT group_name, admin, group_reference FROM RemoveGroupAdminTransactions WHERE signature = ?", signature)) {
|
||||||
|
if (resultSet == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
String groupName = resultSet.getString(1);
|
||||||
|
String admin = resultSet.getString(2);
|
||||||
|
byte[] groupReference = resultSet.getBytes(3);
|
||||||
|
|
||||||
|
return new RemoveGroupAdminTransactionData(creatorPublicKey, groupName, admin, groupReference, fee, timestamp, reference, signature);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to fetch remove group admin transaction from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(TransactionData transactionData) throws DataException {
|
||||||
|
RemoveGroupAdminTransactionData removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
HSQLDBSaver saveHelper = new HSQLDBSaver("RemoveGroupAdminTransactions");
|
||||||
|
|
||||||
|
saveHelper.bind("signature", removeGroupAdminTransactionData.getSignature()).bind("owner", removeGroupAdminTransactionData.getOwnerPublicKey())
|
||||||
|
.bind("group_name", removeGroupAdminTransactionData.getGroupName()).bind("admin", removeGroupAdminTransactionData.getAdmin())
|
||||||
|
.bind("group_reference", removeGroupAdminTransactionData.getGroupReference());
|
||||||
|
|
||||||
|
try {
|
||||||
|
saveHelper.execute(this.repository);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("Unable to save remove group admin transaction into repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -43,6 +43,8 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
private HSQLDBATTransactionRepository atTransactionRepository;
|
private HSQLDBATTransactionRepository atTransactionRepository;
|
||||||
private HSQLDBCreateGroupTransactionRepository createGroupTransactionRepository;
|
private HSQLDBCreateGroupTransactionRepository createGroupTransactionRepository;
|
||||||
private HSQLDBUpdateGroupTransactionRepository updateGroupTransactionRepository;
|
private HSQLDBUpdateGroupTransactionRepository updateGroupTransactionRepository;
|
||||||
|
private HSQLDBAddGroupAdminTransactionRepository addGroupAdminTransactionRepository;
|
||||||
|
private HSQLDBRemoveGroupAdminTransactionRepository removeGroupAdminTransactionRepository;
|
||||||
private HSQLDBJoinGroupTransactionRepository joinGroupTransactionRepository;
|
private HSQLDBJoinGroupTransactionRepository joinGroupTransactionRepository;
|
||||||
private HSQLDBLeaveGroupTransactionRepository leaveGroupTransactionRepository;
|
private HSQLDBLeaveGroupTransactionRepository leaveGroupTransactionRepository;
|
||||||
|
|
||||||
@ -68,6 +70,8 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
this.atTransactionRepository = new HSQLDBATTransactionRepository(repository);
|
this.atTransactionRepository = new HSQLDBATTransactionRepository(repository);
|
||||||
this.createGroupTransactionRepository = new HSQLDBCreateGroupTransactionRepository(repository);
|
this.createGroupTransactionRepository = new HSQLDBCreateGroupTransactionRepository(repository);
|
||||||
this.updateGroupTransactionRepository = new HSQLDBUpdateGroupTransactionRepository(repository);
|
this.updateGroupTransactionRepository = new HSQLDBUpdateGroupTransactionRepository(repository);
|
||||||
|
this.addGroupAdminTransactionRepository = new HSQLDBAddGroupAdminTransactionRepository(repository);
|
||||||
|
this.removeGroupAdminTransactionRepository = new HSQLDBRemoveGroupAdminTransactionRepository(repository);
|
||||||
this.joinGroupTransactionRepository = new HSQLDBJoinGroupTransactionRepository(repository);
|
this.joinGroupTransactionRepository = new HSQLDBJoinGroupTransactionRepository(repository);
|
||||||
this.leaveGroupTransactionRepository = new HSQLDBLeaveGroupTransactionRepository(repository);
|
this.leaveGroupTransactionRepository = new HSQLDBLeaveGroupTransactionRepository(repository);
|
||||||
}
|
}
|
||||||
@ -202,6 +206,12 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return this.updateGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
return this.updateGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return this.addGroupAdminTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return this.removeGroupAdminTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return this.joinGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
return this.joinGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
|
||||||
|
|
||||||
@ -536,6 +546,14 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
|||||||
this.updateGroupTransactionRepository.save(transactionData);
|
this.updateGroupTransactionRepository.save(transactionData);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
this.addGroupAdminTransactionRepository.save(transactionData);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
this.removeGroupAdminTransactionRepository.save(transactionData);
|
||||||
|
break;
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
this.joinGroupTransactionRepository.save(transactionData);
|
this.joinGroupTransactionRepository.save(transactionData);
|
||||||
break;
|
break;
|
||||||
|
157
src/main/java/org/qora/transaction/AddGroupAdminTransaction.java
Normal file
157
src/main/java/org/qora/transaction/AddGroupAdminTransaction.java
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
package org.qora.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.qora.account.Account;
|
||||||
|
import org.qora.account.PublicKeyAccount;
|
||||||
|
import org.qora.asset.Asset;
|
||||||
|
import org.qora.data.transaction.AddGroupAdminTransactionData;
|
||||||
|
import org.qora.data.group.GroupData;
|
||||||
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
import org.qora.group.Group;
|
||||||
|
import org.qora.repository.DataException;
|
||||||
|
import org.qora.repository.Repository;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
|
public class AddGroupAdminTransaction extends Transaction {
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
private AddGroupAdminTransactionData addGroupAdminTransactionData;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
public AddGroupAdminTransaction(Repository repository, TransactionData transactionData) {
|
||||||
|
super(repository, transactionData);
|
||||||
|
|
||||||
|
this.addGroupAdminTransactionData = (AddGroupAdminTransactionData) this.transactionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// More information
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Account> getRecipientAccounts() throws DataException {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvolved(Account account) throws DataException {
|
||||||
|
String address = account.getAddress();
|
||||||
|
|
||||||
|
if (address.equals(this.getOwner().getAddress()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (address.equals(this.getMember().getAddress()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getAmount(Account account) throws DataException {
|
||||||
|
String address = account.getAddress();
|
||||||
|
BigDecimal amount = BigDecimal.ZERO.setScale(8);
|
||||||
|
|
||||||
|
if (address.equals(this.getOwner().getAddress()))
|
||||||
|
amount = amount.subtract(this.transactionData.getFee());
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
|
||||||
|
public Account getOwner() throws DataException {
|
||||||
|
return new PublicKeyAccount(this.repository, this.addGroupAdminTransactionData.getOwnerPublicKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getMember() throws DataException {
|
||||||
|
return new Account(this.repository, this.addGroupAdminTransactionData.getMember());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValidationResult isValid() throws DataException {
|
||||||
|
// Check group name size bounds
|
||||||
|
int groupNameLength = Utf8.encodedLength(addGroupAdminTransactionData.getGroupName());
|
||||||
|
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
|
||||||
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
|
// Check group name is lowercase
|
||||||
|
if (!addGroupAdminTransactionData.getGroupName().equals(addGroupAdminTransactionData.getGroupName().toLowerCase()))
|
||||||
|
return ValidationResult.NAME_NOT_LOWER_CASE;
|
||||||
|
|
||||||
|
GroupData groupData = this.repository.getGroupRepository().fromGroupName(addGroupAdminTransactionData.getGroupName());
|
||||||
|
|
||||||
|
// Check group exists
|
||||||
|
if (groupData == null)
|
||||||
|
return ValidationResult.GROUP_DOES_NOT_EXIST;
|
||||||
|
|
||||||
|
Account owner = getOwner();
|
||||||
|
|
||||||
|
// Check transaction's public key matches group's current owner
|
||||||
|
if (!owner.getAddress().equals(groupData.getOwner()))
|
||||||
|
return ValidationResult.INVALID_GROUP_OWNER;
|
||||||
|
|
||||||
|
// Check address is a member
|
||||||
|
if (!this.repository.getGroupRepository().memberExists(addGroupAdminTransactionData.getGroupName(), owner.getAddress()))
|
||||||
|
return ValidationResult.NOT_GROUP_MEMBER;
|
||||||
|
|
||||||
|
Account member = getMember();
|
||||||
|
|
||||||
|
// Check member is not already an admin
|
||||||
|
if (this.repository.getGroupRepository().adminExists(addGroupAdminTransactionData.getGroupName(), member.getAddress()))
|
||||||
|
return ValidationResult.ALREADY_GROUP_ADMIN;
|
||||||
|
|
||||||
|
// Check fee is positive
|
||||||
|
if (addGroupAdminTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
|
||||||
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
|
if (!Arrays.equals(owner.getLastReference(), addGroupAdminTransactionData.getReference()))
|
||||||
|
return ValidationResult.INVALID_REFERENCE;
|
||||||
|
|
||||||
|
// Check creator has enough funds
|
||||||
|
if (owner.getConfirmedBalance(Asset.QORA).compareTo(addGroupAdminTransactionData.getFee()) < 0)
|
||||||
|
return ValidationResult.NO_BALANCE;
|
||||||
|
|
||||||
|
return ValidationResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() throws DataException {
|
||||||
|
// Update Group adminship
|
||||||
|
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupName());
|
||||||
|
group.promoteToAdmin(addGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Save this transaction
|
||||||
|
this.repository.getTransactionRepository().save(addGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Update owner's balance
|
||||||
|
Account owner = getOwner();
|
||||||
|
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).subtract(addGroupAdminTransactionData.getFee()));
|
||||||
|
|
||||||
|
// Update owner's reference
|
||||||
|
owner.setLastReference(addGroupAdminTransactionData.getSignature());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void orphan() throws DataException {
|
||||||
|
// Revert group adminship
|
||||||
|
Group group = new Group(this.repository, addGroupAdminTransactionData.getGroupName());
|
||||||
|
group.unpromoteToAdmin(addGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Delete this transaction itself
|
||||||
|
this.repository.getTransactionRepository().delete(addGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Update owner's balance
|
||||||
|
Account owner = getOwner();
|
||||||
|
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(addGroupAdminTransactionData.getFee()));
|
||||||
|
|
||||||
|
// Update owner's reference
|
||||||
|
owner.setLastReference(addGroupAdminTransactionData.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,153 @@
|
|||||||
|
package org.qora.transaction;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.qora.account.Account;
|
||||||
|
import org.qora.account.PublicKeyAccount;
|
||||||
|
import org.qora.asset.Asset;
|
||||||
|
import org.qora.data.transaction.RemoveGroupAdminTransactionData;
|
||||||
|
import org.qora.data.group.GroupData;
|
||||||
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
import org.qora.group.Group;
|
||||||
|
import org.qora.repository.DataException;
|
||||||
|
import org.qora.repository.Repository;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
|
||||||
|
public class RemoveGroupAdminTransaction extends Transaction {
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
private RemoveGroupAdminTransactionData removeGroupAdminTransactionData;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
public RemoveGroupAdminTransaction(Repository repository, TransactionData transactionData) {
|
||||||
|
super(repository, transactionData);
|
||||||
|
|
||||||
|
this.removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) this.transactionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// More information
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Account> getRecipientAccounts() throws DataException {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInvolved(Account account) throws DataException {
|
||||||
|
String address = account.getAddress();
|
||||||
|
|
||||||
|
if (address.equals(this.getOwner().getAddress()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (address.equals(this.getAdmin().getAddress()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getAmount(Account account) throws DataException {
|
||||||
|
String address = account.getAddress();
|
||||||
|
BigDecimal amount = BigDecimal.ZERO.setScale(8);
|
||||||
|
|
||||||
|
if (address.equals(this.getOwner().getAddress()))
|
||||||
|
amount = amount.subtract(this.transactionData.getFee());
|
||||||
|
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigation
|
||||||
|
|
||||||
|
public Account getOwner() throws DataException {
|
||||||
|
return new PublicKeyAccount(this.repository, this.removeGroupAdminTransactionData.getOwnerPublicKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAdmin() throws DataException {
|
||||||
|
return new Account(this.repository, this.removeGroupAdminTransactionData.getAdmin());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Processing
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ValidationResult isValid() throws DataException {
|
||||||
|
// Check group name size bounds
|
||||||
|
int groupNameLength = Utf8.encodedLength(removeGroupAdminTransactionData.getGroupName());
|
||||||
|
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
|
||||||
|
return ValidationResult.INVALID_NAME_LENGTH;
|
||||||
|
|
||||||
|
// Check group name is lowercase
|
||||||
|
if (!removeGroupAdminTransactionData.getGroupName().equals(removeGroupAdminTransactionData.getGroupName().toLowerCase()))
|
||||||
|
return ValidationResult.NAME_NOT_LOWER_CASE;
|
||||||
|
|
||||||
|
GroupData groupData = this.repository.getGroupRepository().fromGroupName(removeGroupAdminTransactionData.getGroupName());
|
||||||
|
|
||||||
|
// Check group exists
|
||||||
|
if (groupData == null)
|
||||||
|
return ValidationResult.GROUP_DOES_NOT_EXIST;
|
||||||
|
|
||||||
|
Account owner = getOwner();
|
||||||
|
|
||||||
|
// Check transaction's public key matches group's current owner
|
||||||
|
if (!owner.getAddress().equals(groupData.getOwner()))
|
||||||
|
return ValidationResult.INVALID_GROUP_OWNER;
|
||||||
|
|
||||||
|
Account admin = getAdmin();
|
||||||
|
|
||||||
|
// Check member is an admin
|
||||||
|
if (!this.repository.getGroupRepository().adminExists(removeGroupAdminTransactionData.getGroupName(), admin.getAddress()))
|
||||||
|
return ValidationResult.NOT_GROUP_ADMIN;
|
||||||
|
|
||||||
|
// Check fee is positive
|
||||||
|
if (removeGroupAdminTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
|
||||||
|
return ValidationResult.NEGATIVE_FEE;
|
||||||
|
|
||||||
|
if (!Arrays.equals(owner.getLastReference(), removeGroupAdminTransactionData.getReference()))
|
||||||
|
return ValidationResult.INVALID_REFERENCE;
|
||||||
|
|
||||||
|
// Check creator has enough funds
|
||||||
|
if (owner.getConfirmedBalance(Asset.QORA).compareTo(removeGroupAdminTransactionData.getFee()) < 0)
|
||||||
|
return ValidationResult.NO_BALANCE;
|
||||||
|
|
||||||
|
return ValidationResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void process() throws DataException {
|
||||||
|
// Update Group adminship
|
||||||
|
Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupName());
|
||||||
|
group.demoteFromAdmin(removeGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Save this transaction
|
||||||
|
this.repository.getTransactionRepository().save(removeGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Update owner's balance
|
||||||
|
Account owner = getOwner();
|
||||||
|
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).subtract(removeGroupAdminTransactionData.getFee()));
|
||||||
|
|
||||||
|
// Update owner's reference
|
||||||
|
owner.setLastReference(removeGroupAdminTransactionData.getSignature());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void orphan() throws DataException {
|
||||||
|
// Revert group adminship
|
||||||
|
Group group = new Group(this.repository, removeGroupAdminTransactionData.getGroupName());
|
||||||
|
group.undemoteFromAdmin(removeGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Delete this transaction itself
|
||||||
|
this.repository.getTransactionRepository().delete(removeGroupAdminTransactionData);
|
||||||
|
|
||||||
|
// Update owner's balance
|
||||||
|
Account owner = getOwner();
|
||||||
|
owner.setConfirmedBalance(Asset.QORA, owner.getConfirmedBalance(Asset.QORA).add(removeGroupAdminTransactionData.getFee()));
|
||||||
|
|
||||||
|
// Update owner's reference
|
||||||
|
owner.setLastReference(removeGroupAdminTransactionData.getReference());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -131,6 +131,8 @@ public abstract class Transaction {
|
|||||||
ALREADY_GROUP_MEMBER(51),
|
ALREADY_GROUP_MEMBER(51),
|
||||||
GROUP_OWNER_CANNOT_LEAVE(52),
|
GROUP_OWNER_CANNOT_LEAVE(52),
|
||||||
NOT_GROUP_MEMBER(53),
|
NOT_GROUP_MEMBER(53),
|
||||||
|
ALREADY_GROUP_ADMIN(54),
|
||||||
|
NOT_GROUP_ADMIN(55),
|
||||||
NOT_YET_RELEASED(1000);
|
NOT_YET_RELEASED(1000);
|
||||||
|
|
||||||
public final int value;
|
public final int value;
|
||||||
@ -236,6 +238,12 @@ public abstract class Transaction {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return new UpdateGroupTransaction(repository, transactionData);
|
return new UpdateGroupTransaction(repository, transactionData);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return new AddGroupAdminTransaction(repository, transactionData);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return new RemoveGroupAdminTransaction(repository, transactionData);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return new JoinGroupTransaction(repository, transactionData);
|
return new JoinGroupTransaction(repository, transactionData);
|
||||||
|
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
package org.qora.transform.transaction;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.qora.account.PublicKeyAccount;
|
||||||
|
import org.qora.data.transaction.AddGroupAdminTransactionData;
|
||||||
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
import org.qora.group.Group;
|
||||||
|
import org.qora.transform.TransformationException;
|
||||||
|
import org.qora.utils.Serialization;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
import com.google.common.primitives.Longs;
|
||||||
|
|
||||||
|
public class AddGroupAdminTransactionTransformer extends TransactionTransformer {
|
||||||
|
|
||||||
|
// Property lengths
|
||||||
|
private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
|
||||||
|
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
|
||||||
|
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
|
||||||
|
|
||||||
|
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH;
|
||||||
|
|
||||||
|
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||||
|
long timestamp = byteBuffer.getLong();
|
||||||
|
|
||||||
|
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||||
|
byteBuffer.get(reference);
|
||||||
|
|
||||||
|
byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer);
|
||||||
|
|
||||||
|
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE);
|
||||||
|
|
||||||
|
String member = Serialization.deserializeAddress(byteBuffer);
|
||||||
|
|
||||||
|
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||||
|
|
||||||
|
byte[] signature = new byte[SIGNATURE_LENGTH];
|
||||||
|
byteBuffer.get(signature);
|
||||||
|
|
||||||
|
return new AddGroupAdminTransactionData(ownerPublicKey, groupName, member, fee, timestamp, reference, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
|
AddGroupAdminTransactionData addGroupAdminTransactionData = (AddGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(addGroupAdminTransactionData.getGroupName());
|
||||||
|
|
||||||
|
return dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||||
|
try {
|
||||||
|
AddGroupAdminTransactionData addGroupAdminTransactionData = (AddGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
bytes.write(Ints.toByteArray(addGroupAdminTransactionData.getType().value));
|
||||||
|
bytes.write(Longs.toByteArray(addGroupAdminTransactionData.getTimestamp()));
|
||||||
|
bytes.write(addGroupAdminTransactionData.getReference());
|
||||||
|
|
||||||
|
bytes.write(addGroupAdminTransactionData.getCreatorPublicKey());
|
||||||
|
Serialization.serializeSizedString(bytes, addGroupAdminTransactionData.getGroupName());
|
||||||
|
Serialization.serializeAddress(bytes, addGroupAdminTransactionData.getMember());
|
||||||
|
|
||||||
|
Serialization.serializeBigDecimal(bytes, addGroupAdminTransactionData.getFee());
|
||||||
|
|
||||||
|
if (addGroupAdminTransactionData.getSignature() != null)
|
||||||
|
bytes.write(addGroupAdminTransactionData.getSignature());
|
||||||
|
|
||||||
|
return bytes.toByteArray();
|
||||||
|
} catch (IOException | ClassCastException e) {
|
||||||
|
throw new TransformationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
|
||||||
|
JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
AddGroupAdminTransactionData addGroupAdminTransactionData = (AddGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
byte[] ownerPublicKey = addGroupAdminTransactionData.getOwnerPublicKey();
|
||||||
|
|
||||||
|
json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
|
||||||
|
json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
|
||||||
|
|
||||||
|
json.put("groupName", addGroupAdminTransactionData.getGroupName());
|
||||||
|
json.put("member", addGroupAdminTransactionData.getMember());
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new TransformationException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
package org.qora.transform.transaction;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.qora.account.PublicKeyAccount;
|
||||||
|
import org.qora.data.transaction.RemoveGroupAdminTransactionData;
|
||||||
|
import org.qora.data.transaction.TransactionData;
|
||||||
|
import org.qora.group.Group;
|
||||||
|
import org.qora.transform.TransformationException;
|
||||||
|
import org.qora.utils.Serialization;
|
||||||
|
|
||||||
|
import com.google.common.base.Utf8;
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
import com.google.common.primitives.Longs;
|
||||||
|
|
||||||
|
public class RemoveGroupAdminTransactionTransformer extends TransactionTransformer {
|
||||||
|
|
||||||
|
// Property lengths
|
||||||
|
private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
|
||||||
|
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
|
||||||
|
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
|
||||||
|
|
||||||
|
private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + MEMBER_LENGTH;
|
||||||
|
|
||||||
|
static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
|
||||||
|
long timestamp = byteBuffer.getLong();
|
||||||
|
|
||||||
|
byte[] reference = new byte[REFERENCE_LENGTH];
|
||||||
|
byteBuffer.get(reference);
|
||||||
|
|
||||||
|
byte[] ownerPublicKey = Serialization.deserializePublicKey(byteBuffer);
|
||||||
|
|
||||||
|
String groupName = Serialization.deserializeSizedString(byteBuffer, Group.MAX_NAME_SIZE);
|
||||||
|
|
||||||
|
String admin = Serialization.deserializeAddress(byteBuffer);
|
||||||
|
|
||||||
|
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
|
||||||
|
|
||||||
|
byte[] signature = new byte[SIGNATURE_LENGTH];
|
||||||
|
byteBuffer.get(signature);
|
||||||
|
|
||||||
|
return new RemoveGroupAdminTransactionData(ownerPublicKey, groupName, admin, fee, timestamp, reference, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getDataLength(TransactionData transactionData) throws TransformationException {
|
||||||
|
RemoveGroupAdminTransactionData removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(removeGroupAdminTransactionData.getGroupName());
|
||||||
|
|
||||||
|
return dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
|
||||||
|
try {
|
||||||
|
RemoveGroupAdminTransactionData removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
bytes.write(Ints.toByteArray(removeGroupAdminTransactionData.getType().value));
|
||||||
|
bytes.write(Longs.toByteArray(removeGroupAdminTransactionData.getTimestamp()));
|
||||||
|
bytes.write(removeGroupAdminTransactionData.getReference());
|
||||||
|
|
||||||
|
bytes.write(removeGroupAdminTransactionData.getCreatorPublicKey());
|
||||||
|
Serialization.serializeSizedString(bytes, removeGroupAdminTransactionData.getGroupName());
|
||||||
|
Serialization.serializeAddress(bytes, removeGroupAdminTransactionData.getAdmin());
|
||||||
|
|
||||||
|
Serialization.serializeBigDecimal(bytes, removeGroupAdminTransactionData.getFee());
|
||||||
|
|
||||||
|
if (removeGroupAdminTransactionData.getSignature() != null)
|
||||||
|
bytes.write(removeGroupAdminTransactionData.getSignature());
|
||||||
|
|
||||||
|
return bytes.toByteArray();
|
||||||
|
} catch (IOException | ClassCastException e) {
|
||||||
|
throw new TransformationException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
|
||||||
|
JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
|
||||||
|
|
||||||
|
try {
|
||||||
|
RemoveGroupAdminTransactionData removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) transactionData;
|
||||||
|
|
||||||
|
byte[] ownerPublicKey = removeGroupAdminTransactionData.getOwnerPublicKey();
|
||||||
|
|
||||||
|
json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
|
||||||
|
json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
|
||||||
|
|
||||||
|
json.put("groupName", removeGroupAdminTransactionData.getGroupName());
|
||||||
|
json.put("admin", removeGroupAdminTransactionData.getAdmin());
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new TransformationException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -100,6 +100,12 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return UpdateGroupTransactionTransformer.fromByteBuffer(byteBuffer);
|
return UpdateGroupTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return AddGroupAdminTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return RemoveGroupAdminTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return JoinGroupTransactionTransformer.fromByteBuffer(byteBuffer);
|
return JoinGroupTransactionTransformer.fromByteBuffer(byteBuffer);
|
||||||
|
|
||||||
@ -173,6 +179,12 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return UpdateGroupTransactionTransformer.getDataLength(transactionData);
|
return UpdateGroupTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return AddGroupAdminTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return RemoveGroupAdminTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return JoinGroupTransactionTransformer.getDataLength(transactionData);
|
return JoinGroupTransactionTransformer.getDataLength(transactionData);
|
||||||
|
|
||||||
@ -243,6 +255,12 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return UpdateGroupTransactionTransformer.toBytes(transactionData);
|
return UpdateGroupTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return AddGroupAdminTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return RemoveGroupAdminTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return JoinGroupTransactionTransformer.toBytes(transactionData);
|
return JoinGroupTransactionTransformer.toBytes(transactionData);
|
||||||
|
|
||||||
@ -322,6 +340,12 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return UpdateGroupTransactionTransformer.toBytesForSigningImpl(transactionData);
|
return UpdateGroupTransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return AddGroupAdminTransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return RemoveGroupAdminTransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return JoinGroupTransactionTransformer.toBytesForSigningImpl(transactionData);
|
return JoinGroupTransactionTransformer.toBytesForSigningImpl(transactionData);
|
||||||
|
|
||||||
@ -413,6 +437,12 @@ public class TransactionTransformer extends Transformer {
|
|||||||
case UPDATE_GROUP:
|
case UPDATE_GROUP:
|
||||||
return UpdateGroupTransactionTransformer.toJSON(transactionData);
|
return UpdateGroupTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
|
case ADD_GROUP_ADMIN:
|
||||||
|
return AddGroupAdminTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
|
case REMOVE_GROUP_ADMIN:
|
||||||
|
return RemoveGroupAdminTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
case JOIN_GROUP:
|
case JOIN_GROUP:
|
||||||
return JoinGroupTransactionTransformer.toJSON(transactionData);
|
return JoinGroupTransactionTransformer.toJSON(transactionData);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user