From f99de19792661c73bd81d4a665874ce26a1ba816 Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 24 Jul 2023 12:17:47 -0600 Subject: [PATCH 1/2] Make real name and other properties optional - pass 1 --- core/achievement.js | 2 +- core/client_connections.js | 2 +- core/fse.js | 6 +----- core/my_messages.js | 5 +---- core/nua.js | 15 ++++++++------- core/user.js | 7 +++++-- core/user_2fa_otp_web_register.js | 6 +++--- core/user_config.js | 20 ++++++++------------ core/web_password_reset.js | 2 +- core/wfc.js | 4 +--- 10 files changed, 30 insertions(+), 39 deletions(-) diff --git a/core/achievement.js b/core/achievement.js index d73372ca..b28bb1b8 100644 --- a/core/achievement.js +++ b/core/achievement.js @@ -505,7 +505,7 @@ class Achievements { getFormatObject(info) { return { userName: info.user.username, - userRealName: info.user.properties[UserProps.RealName], + userRealName: info.user.realName(), userLocation: info.user.properties[UserProps.Location], userAffils: info.user.properties[UserProps.Affiliations], nodeId: info.client.node, diff --git a/core/client_connections.js b/core/client_connections.js index 3dbf0e45..a94f65b5 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -87,7 +87,7 @@ function getActiveConnectionList( // entry.text = ac.user?.username || 'N/A'; entry.userName = ac.user?.username || 'N/A'; - entry.realName = ac.user?.getProperty(UserProps.RealName) || 'N/A'; + entry.realName = ac.user?.realName() || 'N/A'; entry.location = ac.user?.getProperty(UserProps.Location) || 'N/A'; entry.affils = entry.affiliation = ac.user?.getProperty(UserProps.Affiliations) || 'N/A'; diff --git a/core/fse.js b/core/fse.js index c5413989..6d883ba8 100644 --- a/core/fse.js +++ b/core/fse.js @@ -982,11 +982,7 @@ exports.FullScreenEditorModule = const area = getMessageAreaByTag(self.messageAreaTag); if (fromView !== undefined) { if (area && area.realNames) { - fromView.setText( - self.client.user.properties[ - UserProps.RealName - ] || self.client.user.username - ); + fromView.setText(self.client.user.realName()); } else { fromView.setText(self.client.user.username); } diff --git a/core/my_messages.js b/core/my_messages.js index 50bba7ae..a50a6884 100644 --- a/core/my_messages.js +++ b/core/my_messages.js @@ -20,10 +20,7 @@ exports.getModule = class MyMessagesModule extends MenuModule { initSequence() { const filter = { - toUserName: [ - this.client.user.username, - this.client.user.getProperty(UserProps.RealName), - ], + toUserName: [this.client.user.username, this.client.user.realName()], sort: 'modTimestamp', resultType: 'messageList', limit: 1024 * 16, // we want some sort of limit... diff --git a/core/nua.js b/core/nua.js index 4f6f355d..9eabc232 100644 --- a/core/nua.js +++ b/core/nua.js @@ -13,6 +13,7 @@ const UserProps = require('./user_property.js'); // deps const _ = require('lodash'); +const moment = require('moment'); exports.moduleInfo = { name: 'NUA', @@ -95,15 +96,15 @@ exports.getModule = class NewUserAppModule extends MenuModule { areaTag = areaTag || ''; newUser.properties = { - [UserProps.RealName]: formData.value.realName, + [UserProps.RealName]: formData.value.realName || '', [UserProps.Birthdate]: getISOTimestampString( - formData.value.birthdate + formData.value.birthdate || moment() ), - [UserProps.Sex]: formData.value.sex, - [UserProps.Location]: formData.value.location, - [UserProps.Affiliations]: formData.value.affils, - [UserProps.EmailAddress]: formData.value.email, - [UserProps.WebAddress]: formData.value.web, + [UserProps.Sex]: formData.value.sex || '', + [UserProps.Location]: formData.value.location || '', + [UserProps.Affiliations]: formData.value.affils || '', + [UserProps.EmailAddress]: formData.value.email || '', + [UserProps.WebAddress]: formData.value.web || '', [UserProps.AccountCreated]: getISOTimestampString(), [UserProps.MessageConfTag]: confTag, diff --git a/core/user.js b/core/user.js index 58cf69d9..aac33ef2 100644 --- a/core/user.js +++ b/core/user.js @@ -124,9 +124,12 @@ module.exports = class User { return isMember; } + realName() { + return this.getProperty(UserProps.RealName) || this.username; + } + getSanitizedName(type = 'username') { - const name = - 'real' === type ? this.getProperty(UserProps.RealName) : this.username; + const name = 'real' === type ? this.realName() : this.username; return sanatizeFilename(name) || `user${this.userId.toString()}`; } diff --git a/core/user_2fa_otp_web_register.js b/core/user_2fa_otp_web_register.js index edae1d5b..735b6f36 100644 --- a/core/user_2fa_otp_web_register.js +++ b/core/user_2fa_otp_web_register.js @@ -93,9 +93,9 @@ module.exports = class User2FA_OTPWebRegister { } const message = { - to: `${ - user.getProperty(UserProps.RealName) || user.username - } <${user.getProperty(UserProps.EmailAddress)}>`, + to: `${user.realName()} <${user.getProperty( + UserProps.EmailAddress + )}>`, // from will be filled in subject: '2-Factor Authentication Registration', text: textTemplate, diff --git a/core/user_config.js b/core/user_config.js index a612e95c..63bfdc16 100644 --- a/core/user_config.js +++ b/core/user_config.js @@ -115,15 +115,15 @@ exports.getModule = class UserConfigModule extends MenuModule { formData = _.clone(formData); const newProperties = { - [UserProps.RealName]: formData.value.realName, + [UserProps.RealName]: formData.value.realName || '', [UserProps.Birthdate]: getISOTimestampString( - formData.value.birthdate + formData.value.birthdate || moment() ), - [UserProps.Sex]: formData.value.sex, - [UserProps.Location]: formData.value.location, - [UserProps.Affiliations]: formData.value.affils, - [UserProps.EmailAddress]: formData.value.email, - [UserProps.WebAddress]: formData.value.web, + [UserProps.Sex]: formData.value.sex || '', + [UserProps.Location]: formData.value.location || '', + [UserProps.Affiliations]: formData.value.affils || '', + [UserProps.EmailAddress]: formData.value.email || '', + [UserProps.WebAddress]: formData.value.web || '', [UserProps.TermHeight]: formData.value.termHeight.toString(), [UserProps.ThemeId]: self.availThemeInfo[formData.value.theme].themeId, @@ -233,11 +233,7 @@ exports.getModule = class UserConfigModule extends MenuModule { function populateViews(callback) { const user = self.client.user; - self.setViewText( - 'menu', - MciCodeIds.RealName, - user.properties[UserProps.RealName] - ); + self.setViewText('menu', MciCodeIds.RealName, user.realName()); self.setViewText( 'menu', MciCodeIds.BirthDate, diff --git a/core/web_password_reset.js b/core/web_password_reset.js index dbc4f88d..757a1983 100644 --- a/core/web_password_reset.js +++ b/core/web_password_reset.js @@ -143,7 +143,7 @@ class WebPasswordReset { } const message = { - to: `${user.properties[UserProps.RealName] || user.username} <${ + to: `${user.realName()} <${ user.properties[UserProps.EmailAddress] }>`, // from will be filled in diff --git a/core/wfc.js b/core/wfc.js index 749593ab..eca853f0 100644 --- a/core/wfc.js +++ b/core/wfc.js @@ -506,9 +506,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { // Current currentUserName: this.client.user.username, - currentUserRealName: - this.client.user.getProperty(UserProps.RealName) || - this.client.user.username, + currentUserRealName: this.client.user.realName(), availIndicator: availIndicator, visIndicator: visIndicator, lastLoginUserName: lastLoginStats.userName, From 5a4563c799614325dd5334ba05f9da8abec03ddc Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Thu, 24 Aug 2023 09:13:29 -0600 Subject: [PATCH 2/2] PR feedback: Better handling of real name and email --- WHATSNEW.md | 1 + core/achievement.js | 6 +++--- core/client_connections.js | 2 +- core/user.js | 20 +++++++++++++++++--- core/user_2fa_otp_web_register.js | 4 +--- core/user_config.js | 2 +- core/web_password_reset.js | 4 +--- core/wfc.js | 2 +- 8 files changed, 26 insertions(+), 15 deletions(-) diff --git a/WHATSNEW.md b/WHATSNEW.md index 060bf502..8a2c8405 100644 --- a/WHATSNEW.md +++ b/WHATSNEW.md @@ -9,6 +9,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For * Finally, the system will search for `index.html` and `index.htm` in that order, if another suitable route cannot be established. * CombatNet has shut down, so the module (`combatnet.js`) has been removed. * The Menu Flag `popParent` has been removed and `noHistory` has been updated to work as expected. In general things should "Just Work", but check your `menu.hjson` entries if you see menu stack issues. +* Various New User Application (NUA) properties are now optional. If you would like to reduce the information users are required, remove optional fields from NUA artwork and collect less. These properties will be stored as "" (empty). Optional properties are as follows: Real name, Birth date, Sex, Location, Affiliations (Affils), Email, and Web address. ## 0.0.13-beta * **Note for contributors**: ENiGMA has switched to [Prettier](https://prettier.io) for formatting/style. Please see [CONTRIBUTING](CONTRIBUTING.md) and the Prettier website for more information. diff --git a/core/achievement.js b/core/achievement.js index b28bb1b8..582468a3 100644 --- a/core/achievement.js +++ b/core/achievement.js @@ -505,9 +505,9 @@ class Achievements { getFormatObject(info) { return { userName: info.user.username, - userRealName: info.user.realName(), - userLocation: info.user.properties[UserProps.Location], - userAffils: info.user.properties[UserProps.Affiliations], + userRealName: info.user.realName(false) || 'N/A', + userLocation: info.user.properties[UserProps.Location] || 'N/A', + userAffils: info.user.properties[UserProps.Affiliations] || 'N/A', nodeId: info.client.node, title: info.details.title, //text : info.global ? info.details.globalText : info.details.text, diff --git a/core/client_connections.js b/core/client_connections.js index a94f65b5..447669c2 100644 --- a/core/client_connections.js +++ b/core/client_connections.js @@ -87,7 +87,7 @@ function getActiveConnectionList( // entry.text = ac.user?.username || 'N/A'; entry.userName = ac.user?.username || 'N/A'; - entry.realName = ac.user?.realName() || 'N/A'; + entry.realName = ac.user?.realName(false) || 'N/A'; entry.location = ac.user?.getProperty(UserProps.Location) || 'N/A'; entry.affils = entry.affiliation = ac.user?.getProperty(UserProps.Affiliations) || 'N/A'; diff --git a/core/user.js b/core/user.js index aac33ef2..125850bf 100644 --- a/core/user.js +++ b/core/user.js @@ -124,15 +124,29 @@ module.exports = class User { return isMember; } - realName() { - return this.getProperty(UserProps.RealName) || this.username; + realName(withUsernameFallback = true) { + const realName = this.getProperty(UserProps.RealName); + if (realName) { + return realName; + } + if (withUsernameFallback) { + return this.username; + } } getSanitizedName(type = 'username') { - const name = 'real' === type ? this.realName() : this.username; + const name = 'real' === type ? this.realName(true) : this.username; return sanatizeFilename(name) || `user${this.userId.toString()}`; } + emailAddress() { + const email = this.getProperty(UserProps.EmailAddress); + if (email) { + const realName = this.realName(false); + return realName ? `${realName} <${email}>` : email; + } + } + isAvailable() { return (this.statusFlags & User.StatusFlags.NotAvailable) == 0; } diff --git a/core/user_2fa_otp_web_register.js b/core/user_2fa_otp_web_register.js index 735b6f36..2d04280c 100644 --- a/core/user_2fa_otp_web_register.js +++ b/core/user_2fa_otp_web_register.js @@ -93,9 +93,7 @@ module.exports = class User2FA_OTPWebRegister { } const message = { - to: `${user.realName()} <${user.getProperty( - UserProps.EmailAddress - )}>`, + to: user.emailAddress(), // from will be filled in subject: '2-Factor Authentication Registration', text: textTemplate, diff --git a/core/user_config.js b/core/user_config.js index 63bfdc16..b597ac4d 100644 --- a/core/user_config.js +++ b/core/user_config.js @@ -233,7 +233,7 @@ exports.getModule = class UserConfigModule extends MenuModule { function populateViews(callback) { const user = self.client.user; - self.setViewText('menu', MciCodeIds.RealName, user.realName()); + self.setViewText('menu', MciCodeIds.RealName, user.realName(false) || ''); self.setViewText( 'menu', MciCodeIds.BirthDate, diff --git a/core/web_password_reset.js b/core/web_password_reset.js index 757a1983..f5cf73c7 100644 --- a/core/web_password_reset.js +++ b/core/web_password_reset.js @@ -143,9 +143,7 @@ class WebPasswordReset { } const message = { - to: `${user.realName()} <${ - user.properties[UserProps.EmailAddress] - }>`, + to: user.emailAddress(), // from will be filled in subject: 'Forgot Password', text: textTemplate, diff --git a/core/wfc.js b/core/wfc.js index eca853f0..41a258b2 100644 --- a/core/wfc.js +++ b/core/wfc.js @@ -506,7 +506,7 @@ exports.getModule = class WaitingForCallerModule extends MenuModule { // Current currentUserName: this.client.user.username, - currentUserRealName: this.client.user.realName(), + currentUserRealName: this.client.user.realName(false) || 'N/A', availIndicator: availIndicator, visIndicator: visIndicator, lastLoginUserName: lastLoginStats.userName,