Skip to content

Commit

Permalink
Merge pull request #187 from Poeschl/add-user-registration-setting
Browse files Browse the repository at this point in the history
✨ Add setting for disabling user registration
  • Loading branch information
Poeschl authored Aug 3, 2024
2 parents 5a1859f + 1cccefe commit 6e5eee7
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ class ConfigRestController(private val configService: ConfigService, private val
fun getClientSettings(): ClientSettings {
return ClientSettings(
configService.getGlobalNotificationText(),
configService.getBooleanSetting(SettingKey.ENABLE_WEB_ROBOT_CONTROL).value
configService.getBooleanSetting(SettingKey.ENABLE_WEB_ROBOT_CONTROL).value,
configService.getBooleanSetting(SettingKey.ENABLE_USER_REGISTRATION).value
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ enum class SettingKey(@JsonIgnore val isFrontendSetting: Boolean = false) {
ENABLE_FULL_MAP_SCAN,
ENABLE_DUMMY_ROBOTS,
ENABLE_WEB_ROBOT_CONTROL(isFrontendSetting = true),
DISTANCE_ROBOT_SIGHT_ON_MOVE
DISTANCE_ROBOT_SIGHT_ON_MOVE,
ENABLE_USER_REGISTRATION(isFrontendSetting = true)
}

enum class SettingType {
Expand All @@ -44,4 +45,4 @@ enum class SettingType {
BOOLEAN
}

data class ClientSettings(val globalNotificationText: String, val enableWebRobotControl: Boolean)
data class ClientSettings(val globalNotificationText: String, val enableWebRobotControl: Boolean, val enableUserRegistration: Boolean)
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,22 @@ import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import xyz.poeschl.roborush.models.settings.SettingKey
import xyz.poeschl.roborush.security.service.UserDetailsService
import xyz.poeschl.roborush.security.utils.JwtTokenProvider
import xyz.poeschl.roborush.service.ConfigService

@RestController
@RequestMapping("/auth")
class AuthRestController(
private val authenticationManager: AuthenticationManager,
private val jwtTokenProvider: JwtTokenProvider,
private val userDetailsService: UserDetailsService
private val userDetailsService: UserDetailsService,
private val configService: ConfigService
) {

companion object {
Expand All @@ -40,12 +46,19 @@ class AuthRestController(

@PostMapping("/register", produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.APPLICATION_JSON_VALUE])
fun registerUser(@RequestBody registerRequest: RegisterRequest): ResponseEntity<Void> {
try {
userDetailsService.registerNewUser(registerRequest.username, registerRequest.password)
} catch (ex: DataIntegrityViolationException) {
LOGGER.warn("Username '${registerRequest.username}' is already taken. Registration not possible")
return ResponseEntity.status(HttpStatus.CONFLICT).build()
if (registerRequest.username.length > 3 &&
registerRequest.password.length > 8 &&
configService.getBooleanSetting(SettingKey.ENABLE_USER_REGISTRATION).value
) {
try {
userDetailsService.registerNewUser(registerRequest.username, registerRequest.password)
} catch (ex: DataIntegrityViolationException) {
LOGGER.warn("Username '${registerRequest.username}' is already taken. Registration not possible")
return ResponseEntity.status(HttpStatus.CONFLICT).build()
}
return ResponseEntity.ok().build()
} else {
return ResponseEntity.badRequest().build()
}
return ResponseEntity.ok().build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class ConfigService(
websocketController.sendClientSettingsUpdate(
ClientSettings(
globalNotificationText,
getBooleanSetting(SettingKey.ENABLE_FULL_MAP_SCAN).value
getBooleanSetting(SettingKey.ENABLE_FULL_MAP_SCAN).value,
getBooleanSetting(SettingKey.ENABLE_USER_REGISTRATION).value
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ INSERT INTO config (key, type, value) values ('ENABLE_FULL_MAP_SCAN', 'BOOLEAN',
INSERT INTO config (key, type, value) values ('ENABLE_DUMMY_ROBOTS', 'BOOLEAN', 'true');
INSERT INTO config (key, type, value) values ('ENABLE_WEB_ROBOT_CONTROL', 'BOOLEAN', 'true');
INSERT INTO config (key, type, value) values ('DISTANCE_ROBOT_SIGHT_ON_MOVE', 'INT', '2');
INSERT INTO config (key, type, value) values ('ENABLE_USER_REGISTRATION', 'BOOLEAN', 'true');
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DBMigrationIntegrityTest {
.withHashAlgorithm(HashAlgorithm.MD5)
.withHashPair("V1_000__create_user_schemas.sql", "5982877bb3946da9beea4e57f4d1f57e")
.withHashPair("V1_001__create_robot_schemas.sql", "6b37f4a87fa7ff214b3f61b997cc83c4")
.withHashPair("V1_002__create_config_schemas.sql", "561fed397577fecf52e169147a4719f6")
.withHashPair("V1_002__create_config_schemas.sql", "935942d229304ef2116299aac7697f4c")
.withHashPair("V1_003__create_map_schemas.sql", "69f4ddc8bd39e42d586afca833e4e6f8")
.withHashPair("V1_004__add_map_icon_map.sql", "018fc6ef7adba9b861d33394bbcc57c2")
.withHashPair("V1_005__add_map_easy.sql", "c0a99225ea3ac682bd576590d630d94b")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ class ConfigServiceTest {
val controlDto = SaveSettingDto(controlSettingEntity.key, "true")

val enableFullScanSettingEntity = a(`$SettingEntity`().withKey(SettingKey.ENABLE_FULL_MAP_SCAN).withType(SettingType.BOOLEAN).withValue("true"))
val enableUserRegisterSettingEntity = a(`$SettingEntity`().withKey(SettingKey.ENABLE_USER_REGISTRATION).withType(SettingType.BOOLEAN).withValue("true"))

every { configRepository.findByKey(enableFullScanSettingEntity.key) } returns enableFullScanSettingEntity
every { configRepository.findByKey(controlSettingEntity.key) } returns controlSettingEntity
every { configRepository.findByKey(enableUserRegisterSettingEntity.key) } returns enableUserRegisterSettingEntity

every { settingEntityMapper.toEntity(controlSettingEntity, controlDto) } returns controlConvertedEntity
every { configRepository.save(controlConvertedEntity) } returns controlConvertedEntity
Expand Down Expand Up @@ -164,6 +166,7 @@ class ConfigServiceTest {

every { configRepository.findByKey(SettingKey.ENABLE_FULL_MAP_SCAN) } returns settingEntity
every { configRepository.findByKey(SettingKey.ENABLE_WEB_ROBOT_CONTROL) } returns settingEntity
every { configRepository.findByKey(SettingKey.ENABLE_USER_REGISTRATION) } returns settingEntity
every { settingEntityMapper.fromEntity(settingEntity) } answers { callOriginal() }

// THEN
Expand Down
15 changes: 10 additions & 5 deletions frontend/src/components/NavbarUserComponent.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="navbar-item is-button" v-if="!userStore.loggedIn">
<button class="button" @click="openRegister">
<button class="button" @click="openRegister" :disabled="!registerEnabled">
<span class="has-text-weight-semibold">Create a account</span>
</button>
</div>
Expand All @@ -18,13 +18,13 @@
</a>

<LoginForm v-if="loginIsShowing" :loading="loginLoading" @close="loginIsShowing = false" @login="loginUser" />
<RegisterForm v-if="registerIsShowing" :loading="registerLoading" @close="registerIsShowing = false" @register="registerUser" />
<RegisterForm v-if="registerIsShowing && registerEnabled" :loading="registerLoading" @close="registerIsShowing = false" @register="registerUser" />
<UserModal v-if="userDetailsShown" @close="() => (userDetailsShown = false)" />
<Toast v-if="toast.shown" :type="toast.type" :message="toast.message" @close="() => (toast.shown = false)" />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { computed, ref } from "vue";
import LoginForm from "@/components/LoginForm.vue";
import type { LoginRequest, RegisterRequest } from "@/models/User";
import RegisterForm from "@/components/RegisterForm.vue";
Expand All @@ -33,13 +33,16 @@ import Toast from "@/components/Toast.vue";
import { ToastType } from "@/models/ToastType";
import UserModal from "@/components/UserModal.vue";
import log from "loglevel";
import { useConfigStore } from "@/stores/ConfigStore";
const userStore = useUserStore();
const configStore = useConfigStore();
const loginIsShowing = ref<boolean>(false);
const loginLoading = ref<boolean>(false);
const registerIsShowing = ref<boolean>(false);
const registerLoading = ref<boolean>(false);
const registerEnabled = computed<boolean>(() => configStore.clientSettings.enableUserRegistration);
const toast = ref<{ shown: boolean; type: ToastType; message: string }>({ shown: false, type: ToastType.INFO, message: "" });
const userDetailsShown = ref<boolean>(false);
Expand Down Expand Up @@ -68,8 +71,10 @@ const loginUser = (data: LoginRequest) => {
};
const openRegister = () => {
registerLoading.value = false;
registerIsShowing.value = true;
if (registerEnabled.value) {
registerLoading.value = false;
registerIsShowing.value = true;
}
};
const registerUser = (data: RegisterRequest) => {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/models/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export interface MapGenerationResult {
export interface ClientSettings {
globalNotificationText: string;
enableWebRobotControl: boolean;
enableUserRegistration: boolean;
}
2 changes: 1 addition & 1 deletion frontend/src/stores/ConfigStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const useConfigStore = defineStore("configStore", () => {

const currentConfig = ref<Map<string, Setting>>(new Map());
const availableMaps = ref<{ maps: PlaygroundMap[] }>({ maps: [] });
const clientSettings = ref<ClientSettings>({ globalNotificationText: "", enableWebRobotControl: true });
const clientSettings = ref<ClientSettings>({ globalNotificationText: "", enableWebRobotControl: true, enableUserRegistration: false });

const initWebsocket = (webSocketInstance: { initWebsocket: Function; registerForTopicCallback: Function }) => {
websocketService.value = webSocketInstance;
Expand Down

0 comments on commit 6e5eee7

Please sign in to comment.