diff --git a/server/graph/schemas/user.graphql b/server/graph/schemas/user.graphql
index 4045b044ca..a81d86ec88 100644
--- a/server/graph/schemas/user.graphql
+++ b/server/graph/schemas/user.graphql
@@ -36,6 +36,7 @@ extend type Mutation {
groups: [UUID]!
mustChangePassword: Boolean!
sendWelcomeEmail: Boolean!
+ sendWelcomeEmailFromSiteId: UUID
): UserResponse
updateUser(
diff --git a/server/locales/en.json b/server/locales/en.json
index eb6d5f7d04..125cb97836 100644
--- a/server/locales/en.json
+++ b/server/locales/en.json
@@ -919,6 +919,7 @@
"admin.users.create": "Create User",
"admin.users.createInvalidData": "Cannot create user as some fields are invalid or missing.",
"admin.users.createKeepOpened": "Keep dialog opened after create",
+ "admin.users.createSendEmailMissingSiteId": "You must specify the wiki site to reference for the welcome email.",
"admin.users.createSuccess": "User created successfully!",
"admin.users.createdAt": "Created on {date}",
"admin.users.darkMode": "Dark Mode",
@@ -1001,6 +1002,7 @@
"admin.users.selectGroup": "Select Group...",
"admin.users.sendWelcomeEmail": "Send Welcome Email",
"admin.users.sendWelcomeEmailAltHint": "An email will be sent to the user with link(s) to the wiki(s) the user has read access to.",
+ "admin.users.sendWelcomeEmailFromSiteId": "Site to use for the Welcome Email",
"admin.users.sendWelcomeEmailHint": "An email will be sent to the user with his login details.",
"admin.users.subtitle": "Manage Users",
"admin.users.tfa": "Two Factor Authentication (2FA)",
diff --git a/server/models/users.mjs b/server/models/users.mjs
index e623b932af..f405290f7a 100644
--- a/server/models/users.mjs
+++ b/server/models/users.mjs
@@ -570,7 +570,7 @@ export class User extends Model {
*
* @param {Object} param0 User Fields
*/
- static async createNewUser ({ email, password, name, groups, userInitiated = false, mustChangePassword = false, sendWelcomeEmail = false }) {
+ static async createNewUser ({ email, password, name, groups, userInitiated = false, mustChangePassword = false, sendWelcomeEmail = false, sendWelcomeEmailFromSiteId }) {
const localAuth = await WIKI.db.authentication.getStrategy('local')
// Check if self-registration is enabled
@@ -630,6 +630,11 @@ export class User extends Model {
throw new Error('ERR_DUPLICATE_ACCOUNT_EMAIL')
}
+ // Check if site ID is provided when send welcome email is enabled
+ if (sendWelcomeEmail && !sendWelcomeEmailFromSiteId) {
+ throw new Error('ERR_INVALID_SITE')
+ }
+
WIKI.logger.debug(`Creating new user account for ${email}...`)
// Create the account
@@ -681,35 +686,48 @@ export class User extends Model {
userId: newUsr.id
})
+ // TODO: Handle multilingual text
// Send verification email
await WIKI.mail.send({
- template: 'accountVerify',
+ template: 'UserVerify',
to: email,
subject: 'Verify your account',
data: {
preheadertext: 'Verify your account in order to gain access to the wiki.',
title: 'Verify your account',
content: 'Click the button below in order to verify your account and gain access to the wiki.',
- buttonLink: `${WIKI.config.host}/verify/${verificationToken}`,
+ buttonLink: `${WIKI.config.mail.defaultBaseURL}/verify/${verificationToken}`,
buttonText: 'Verify'
},
- text: `You must open the following link in your browser to verify your account and gain access to the wiki: ${WIKI.config.host}/verify/${verificationToken}`
+ text: `You must open the following link in your browser to verify your account and gain access to the wiki: ${WIKI.config.mail.defaultBaseURL}/verify/${verificationToken}`
})
} else if (sendWelcomeEmail) {
- // Send welcome email
- await WIKI.mail.send({
- template: 'accountWelcome',
- to: email,
- subject: `Welcome to the wiki ${WIKI.config.title}`,
- data: {
- preheadertext: `You've been invited to the wiki ${WIKI.config.title}`,
- title: `You've been invited to the wiki ${WIKI.config.title}`,
- content: `Click the button below to access the wiki.`,
- buttonLink: `${WIKI.config.host}/login`,
- buttonText: 'Login'
- },
- text: `You've been invited to the wiki ${WIKI.config.title}: ${WIKI.config.host}/login`
- })
+ // TODO: Handle multilingual text
+ const site = WIKI.sites[sendWelcomeEmailFromSiteId]
+ if (site) {
+ const siteUrl = site.hostname === '*' ? WIKI.config.mail.defaultBaseURL : `https://${site.hostname}`
+ // Send welcome email
+ await WIKI.mail.send({
+ template: 'UserWelcome',
+ to: email,
+ subject: `Welcome to the wiki ${site.config.title}`,
+ data: {
+ siteTitle: site.config.title,
+ preview: `You've been invited to the wiki ${site.config.title}`,
+ title: `You've been invited to the wiki ${site.config.title}`,
+ content: `Click the button below to access the wiki.`,
+ email,
+ password,
+ buttonLink: `${siteUrl}/login`,
+ buttonText: 'Login',
+ logo: `${siteUrl}/_site/logo`
+ },
+ text: `You've been invited to the wiki ${site.config.title}: ${siteUrl}/login`
+ })
+ } else {
+ WIKI.logger.warn('An invalid site ID was provided when creating user. No welcome email was sent.')
+ throw new Error('ERR_INVALID_SITE')
+ }
}
WIKI.logger.debug(`Created new user account for ${email} successfully.`)
diff --git a/server/templates/mail/UserWelcome.vue b/server/templates/mail/UserWelcome.vue
new file mode 100644
index 0000000000..4497cf6829
--- /dev/null
+++ b/server/templates/mail/UserWelcome.vue
@@ -0,0 +1,109 @@
+
+
+
+ {{ preview }}
+
+
+
+
+
+ {{ title }}
+ Email Address: {{ email }}
+ Password: {{ password }}
+ {{ content }}
+ {{ buttonText }}
+
+ {{ siteTitle }}
+ Wiki.js, an open source project.
+
+
+
+
+
+
+
diff --git a/ux/public/_assets/icons/ultraviolet-web-design.svg b/ux/public/_assets/icons/ultraviolet-web-design.svg
new file mode 100644
index 0000000000..6e598c60b8
--- /dev/null
+++ b/ux/public/_assets/icons/ultraviolet-web-design.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/ux/src/components/UserCreateDialog.vue b/ux/src/components/UserCreateDialog.vue
index b7df25ac63..041af6eed1 100644
--- a/ux/src/components/UserCreateDialog.vue
+++ b/ux/src/components/UserCreateDialog.vue
@@ -134,6 +134,24 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
unchecked-icon='las la-times'
:aria-label='t(`admin.users.sendWelcomeEmail`)'
)
+ q-item(v-if='state.userSendWelcomeEmail')
+ blueprint-icon(icon='web-design')
+ q-item-section
+ q-select(
+ outlined
+ :options='adminStore.sites'
+ v-model='state.userSendWelcomeEmailFromSiteId'
+ multiple
+ map-options
+ emit-value
+ option-value='id'
+ option-label='title'
+ options-dense
+ dense
+ hide-bottom-space
+ :label='t(`admin.users.sendWelcomeEmailFromSiteId`)'
+ :aria-label='t(`admin.users.sendWelcomeEmailFromSiteId`)'
+ )
q-card-actions.card-actions
q-checkbox(
v-model='state.keepOpened'
@@ -167,6 +185,8 @@ import { useI18n } from 'vue-i18n'
import { useDialogPluginComponent, useQuasar } from 'quasar'
import { computed, onMounted, reactive, ref } from 'vue'
+import { useAdminStore } from 'src/stores/admin'
+
// EMITS
defineEmits([
@@ -178,6 +198,10 @@ defineEmits([
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } = useDialogPluginComponent()
const $q = useQuasar()
+// STORES
+
+const adminStore = useAdminStore()
+
// I18N
const { t } = useI18n()
@@ -191,6 +215,7 @@ const state = reactive({
userGroups: [],
userMustChangePassword: false,
userSendWelcomeEmail: false,
+ userSendWelcomeEmailFromSiteId: null,
keepOpened: false,
groups: [],
loadingGroups: false,
@@ -299,6 +324,9 @@ async function create () {
if (!isFormValid) {
throw new Error(t('admin.users.createInvalidData'))
}
+ if (state.userSendWelcomeEmail && !state.userSendWelcomeEmailFromSiteId) {
+ throw new Error(t('admin.users.createSendEmailMissingSiteId'))
+ }
const resp = await APOLLO_CLIENT.mutate({
mutation: gql`
mutation createUser (
@@ -308,6 +336,7 @@ async function create () {
$groups: [UUID]!
$mustChangePassword: Boolean!
$sendWelcomeEmail: Boolean!
+ $sendWelcomeEmailFromSiteId: UUID
) {
createUser (
name: $name
@@ -316,6 +345,7 @@ async function create () {
groups: $groups
mustChangePassword: $mustChangePassword
sendWelcomeEmail: $sendWelcomeEmail
+ sendWelcomeEmailFromSiteId: $sendWelcomeEmailFromSiteId
) {
operation {
succeeded
@@ -330,7 +360,8 @@ async function create () {
password: state.userPassword,
groups: state.userGroups,
mustChangePassword: state.userMustChangePassword,
- sendWelcomeEmail: state.userSendWelcomeEmail
+ sendWelcomeEmail: state.userSendWelcomeEmail,
+ sendWelcomeEmailFromSiteId: state.userSendWelcomeEmailFromSiteId
}
})
if (resp?.data?.createUser?.operation?.succeeded) {
@@ -360,5 +391,8 @@ async function create () {
// MOUNTED
-onMounted(loadGroups)
+onMounted(() => {
+ state.userSendWelcomeEmailFromSiteId = adminStore.currentSiteId
+ loadGroups()
+})