Skip to content

Commit

Permalink
Implement user management endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed Dec 29, 2024
1 parent 33d589a commit 5add2a5
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ public void setupLoggingAndVia() {
private void loadInstances() {
try {
for (var instanceData : sessionFactory.fromTransaction(s ->
s.createQuery("FROM InstanceEntity", InstanceEntity.class).getResultList())) {
s.createQuery("FROM InstanceEntity", InstanceEntity.class).list())) {
try {
var instance = new InstanceManager(this, sessionFactory, instanceData);
SoulFireAPI.postEvent(new InstanceInitEvent(instance));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public RPCServer(
.addService(injector.getSingleton(DownloadServiceImpl.class))
.addService(injector.getSingleton(ObjectStorageServiceImpl.class))
.addService(injector.getSingleton(ServerServiceImpl.class))
.addService(injector.getSingleton(UserServiceImpl.class))
// Allow collecting info about callable methods.
.addService(ProtoReflectionServiceV1.newInstance())
.maxRequestMessageLength(Integer.MAX_VALUE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void updateServerConfig(ServerUpdateConfigRequest request, StreamObserver
responseObserver.onNext(ServerUpdateConfigResponse.newBuilder().build());
responseObserver.onCompleted();
} catch (Throwable t) {
log.error("Error getting server info", t);
log.error("Error updating server config", t);
throw new StatusRuntimeException(Status.INTERNAL.withDescription(t.getMessage()).withCause(t));
}
}
Expand Down
132 changes: 132 additions & 0 deletions server/src/main/java/com/soulfiremc/server/grpc/UserServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* SoulFire
* Copyright (C) 2024 AlexProgrammerDE
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.soulfiremc.server.grpc;

import com.soulfiremc.grpc.generated.*;
import com.soulfiremc.server.database.UserEntity;
import com.soulfiremc.server.user.PermissionContext;
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SessionFactory;

import javax.inject.Inject;

@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Inject)
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
private final SessionFactory sessionFactory;

@Override
public void createUser(UserCreateRequest request, StreamObserver<UserCreateResponse> responseObserver) {
ServerRPCConstants.USER_CONTEXT_KEY.get().hasPermissionOrThrow(PermissionContext.global(GlobalPermission.CREATE_USER));

try {
sessionFactory.inTransaction(session -> {
var userEntity = new UserEntity();
userEntity.username(request.getUsername());
userEntity.role(switch (request.getRole()) {
case ADMIN -> UserEntity.Role.ADMIN;
case USER -> UserEntity.Role.USER;
default -> throw new IllegalArgumentException("Unknown role: " + request.getRole());
});

session.persist(userEntity);
});

responseObserver.onNext(UserCreateResponse.newBuilder().build());
responseObserver.onCompleted();
} catch (Throwable t) {
log.error("Error creating user", t);
throw new StatusRuntimeException(Status.INTERNAL.withDescription(t.getMessage()).withCause(t));
}
}

@Override
public void deleteUser(UserDeleteRequest request, StreamObserver<UserDeleteResponse> responseObserver) {
ServerRPCConstants.USER_CONTEXT_KEY.get().hasPermissionOrThrow(PermissionContext.global(GlobalPermission.DELETE_USER));

try {
sessionFactory.inTransaction(session -> {
var userEntity = session.find(UserEntity.class, request.getId());
if (userEntity == null) {
throw new IllegalArgumentException("User not found: " + request.getId());
}

session.remove(userEntity);
});

responseObserver.onNext(UserDeleteResponse.newBuilder().build());
responseObserver.onCompleted();
} catch (Throwable t) {
log.error("Error deleting user", t);
throw new StatusRuntimeException(Status.INTERNAL.withDescription(t.getMessage()).withCause(t));
}
}

@Override
public void listUsers(UserListRequest request, StreamObserver<UserListResponse> responseObserver) {
ServerRPCConstants.USER_CONTEXT_KEY.get().hasPermissionOrThrow(PermissionContext.global(GlobalPermission.READ_USER));

try {
var users = sessionFactory.fromTransaction(session -> session.createQuery("from UserEntity", UserEntity.class).list());

responseObserver.onNext(UserListResponse.newBuilder()
.addAllUsers(users.stream().map(user -> UserListResponse.User.newBuilder()
.setId(user.id().toString())
.setUsername(user.username())
.setRole(switch (user.role()) {
case ADMIN -> UserRole.ADMIN;
case USER -> UserRole.USER;
})
.build())
.toList())
.build());
responseObserver.onCompleted();
} catch (Throwable t) {
log.error("Error listing users", t);
throw new StatusRuntimeException(Status.INTERNAL.withDescription(t.getMessage()).withCause(t));
}
}

@Override
public void getUserInfo(UserInfoRequest request, StreamObserver<UserInfoResponse> responseObserver) {
ServerRPCConstants.USER_CONTEXT_KEY.get().hasPermissionOrThrow(PermissionContext.global(GlobalPermission.READ_USER));

try {
var user = sessionFactory.fromTransaction(session -> session.find(UserEntity.class, request.getId()));
if (user == null) {
throw new IllegalArgumentException("User not found: " + request.getId());
}

responseObserver.onNext(UserInfoResponse.newBuilder()
.setUsername(user.username())
.setRole(switch (user.role()) {
case ADMIN -> UserRole.ADMIN;
case USER -> UserRole.USER;
})
.build());
responseObserver.onCompleted();
} catch (Throwable t) {
log.error("Error getting user info", t);
throw new StatusRuntimeException(Status.INTERNAL.withDescription(t.getMessage()).withCause(t));
}
}
}

0 comments on commit 5add2a5

Please sign in to comment.