diff --git a/src/Entities/AccountFields.ts b/src/Entities/AccountFields.ts index 983e3780..68e40c0c 100644 --- a/src/Entities/AccountFields.ts +++ b/src/Entities/AccountFields.ts @@ -30,6 +30,7 @@ import { FieldDefn, ValidateResponse } from '@Route-Tools/EntityFieldDefn'; import { VKeyedCollection } from '@Tools/vTypes'; import { IsNullOrEmpty } from '@Tools/Misc'; import { Logger } from '@Tools/Logging'; +import Config from '@Base/config'; export function CheckAccountFields(): void { // DEBUG DEBUG: for unknown reasons some field ops end up 'undefined' @@ -68,18 +69,23 @@ export const accountFields: { [key: string]: FieldDefn } = { validate: async (pField: FieldDefn, pEntity: Entity, pVal: any): Promise => { let validity: ValidateResponse; if (typeof(pVal) === 'string') { - if (/^[A-Za-z][A-Za-z0-9+\-_\.]*$/.test(pVal)) { - // Make sure no other account has this username - const otherAccount = await Accounts.getAccountWithUsername(pVal); - if (IsNullOrEmpty(otherAccount) || otherAccount.id === (pEntity as AccountEntity).id) { - validity = { valid: true }; + if (pVal.length <= Config['metaverse-server']['max-name-length']) { + if (/^[A-Za-z][A-Za-z0-9+\-_\.]*$/.test(pVal)) { + // Make sure no other account has this username + const otherAccount = await Accounts.getAccountWithUsername(pVal); + if (IsNullOrEmpty(otherAccount) || otherAccount.id === (pEntity as AccountEntity).id) { + validity = { valid: true }; + } + else { + validity = { valid: false, reason: 'username already exists' }; + }; } else { - validity = { valid: false, reason: 'username already exists' }; + validity = { valid: false, reason: 'username can contain only A-Za-z0-9+-_.' }; }; } else { - validity = { valid: false, reason: 'username can contain only A-Za-z0-9+-_.' }; + validity = { valid: false, reason: 'username too long' }; }; } else { diff --git a/src/Entities/DomainFields.ts b/src/Entities/DomainFields.ts index 1c5b0205..17dbd003 100644 --- a/src/Entities/DomainFields.ts +++ b/src/Entities/DomainFields.ts @@ -66,11 +66,16 @@ export const DomainFields: { [key: string]: FieldDefn } = { validate: async (pField: FieldDefn, pEntity: Entity, pVal: any): Promise => { let validity: ValidateResponse; if (typeof(pVal) === 'string' && (pVal as string).length > 0) { - if( /^[A-Za-z][A-Za-z0-9+\-_\.]*$/.test(pVal) ) { - validity = { valid: true }; + if (pVal.length <= Config['metaverse-server']['max-name-length']) { + if( /^[A-Za-z][A-Za-z0-9+\-_\.]*$/.test(pVal) ) { + validity = { valid: true }; + } + else { + validity = { valid: false, reason: 'domain name characters must be A-Za-z0-9+-_.'}; + }; } else { - validity = { valid: false, reason: 'domain name characters must be A-Za-z0-9+-_.'}; + validity = { valid: false, reason: 'domain name too long'}; }; } else { diff --git a/src/Entities/PlaceFields.ts b/src/Entities/PlaceFields.ts index 95bc3b5f..7dd3e5d1 100644 --- a/src/Entities/PlaceFields.ts +++ b/src/Entities/PlaceFields.ts @@ -56,13 +56,18 @@ export const placeFields: { [key: string]: FieldDefn } = { // Verify that the placename is unique let validity: ValidateResponse; if (typeof(pVal) === 'string') { - const maybePlace = await Places.getPlaceWithName(pVal); - // If no other place with this name or we're setting our own name - if (IsNullOrEmpty(maybePlace) || (pEntity as PlaceEntity).id === maybePlace.id) { - validity = { valid: true }; + if (pVal.length <= Config['metaverse-server']['max-name-length']) { + const maybePlace = await Places.getPlaceWithName(pVal); + // If no other place with this name or we're setting our own name + if (IsNullOrEmpty(maybePlace) || (pEntity as PlaceEntity).id === maybePlace.id) { + validity = { valid: true }; + } + else { + validity = { valid: false, reason: 'place name already exists' }; + }; } else { - validity = { valid: false, reason: 'place name already exists' }; + validity = { valid: false, reason: 'place name too long' }; }; } else { diff --git a/src/config.ts b/src/config.ts index 88643cb2..9e2ec6a9 100755 --- a/src/config.ts +++ b/src/config.ts @@ -51,11 +51,12 @@ export let Config = { 'http-error-on-failure': true, // whether to include x-vircadia error header 'error-header': 'x-vircadia-error-handle', - 'heartbeat-seconds-until-offline': 5 * 60, // five minutes - 'domain-seconds-until-offline': 10 * 60, // ten minutes 'metaverse-info-addition-file': './metaverse_info.json', - 'session-timeout-minutes': 5, + 'max-name-length': 32, // the max characters a domain, place, account, ... name + 'session-timeout-minutes': 5, + 'heartbeat-seconds-until-offline': 5 * 60, // five minutes + 'domain-seconds-until-offline': 10 * 60, // ten minutes 'handshake-request-expiration-minutes': 1, // one minute handshake 'connection-request-expiration-minutes': 60 * 24 * 4, // 4 days 'friend-request-expiration-minutes': 60 * 24 * 4, // 4 days @@ -70,7 +71,7 @@ export let Config = { // When account of this name is created, add 'admin' role to it // Initially as empty so random people cannot create an admin account - // This account named here MUST be controlled by the server's admin + // The account named here MUST be controlled by the server's admin 'base-admin-account': '', // If to assume domain network_address if on is not set diff --git a/src/routes/api/v1/places.ts b/src/routes/api/v1/places.ts index cd9664c6..b9a7d379 100755 --- a/src/routes/api/v1/places.ts +++ b/src/routes/api/v1/places.ts @@ -34,6 +34,7 @@ import { Maturity } from '@Entities/Sets/Maturity'; import { IsNullOrEmpty, IsNotNullOrEmpty } from '@Tools/Misc'; import { Logger } from '@Tools/Logging'; +import { placeFields } from '@Entities/PlaceFields'; // Return places information // As of 20210501, the Places information is public and the requestor does not need to @@ -106,8 +107,8 @@ export const procPostPlaces: RequestHandler = async (req: Request, resp: Respons const aDomain = await Domains.getDomainWithId(requestedDomainId); if (aDomain) { if (await checkAccessToEntity(req.vAuthToken, aDomain, [ Perm.SPONSOR, Perm.ADMIN ], req.vAuthAccount)) { - const maybePlace = await Places.getPlaceWithName(requestedName); - if (IsNullOrEmpty(maybePlace)) { + const ifValid = await placeFields.name.validate(placeFields.name, req.vAuthAccount, requestedName); + if (ifValid.valid) { const newPlace = await Places.createPlace(aDomain.sponsorAccountId); newPlace.name = requestedName; newPlace.description = requestedDesc; @@ -119,7 +120,7 @@ export const procPostPlaces: RequestHandler = async (req: Request, resp: Respons req.vRestResp.Data = buildPlaceInfo(newPlace, aDomain); } else { - req.vRestResp.respondFailure('place name already exists'); + req.vRestResp.respondFailure(ifValid.reason ?? 'place name already exists or is too long'); }; } else {